replace useConfig with useGraph

This commit is contained in:
AykutSarac 2022-12-17 23:00:37 +03:00
parent a26b94f584
commit 20bcdfef10
11 changed files with 98 additions and 112 deletions

View File

@ -1,7 +1,7 @@
import React from "react";
// import { useInViewport } from "react-in-viewport";
import { CustomNodeProps } from "src/components/CustomNode";
import useConfig from "src/store/useConfig";
import useGraph from "src/store/useGraph";
import * as Styled from "./styles";
const inViewport = true;
@ -9,7 +9,7 @@ const inViewport = true;
const ObjectNode: React.FC<CustomNodeProps> = ({ node, x, y }) => {
const { text, width, height, data } = node;
const ref = React.useRef(null);
const performanceMode = useConfig(state => state.performanceMode);
const performanceMode = useGraph(state => state.performanceMode);
// const { inViewport } = useInViewport(ref);
if (data.isEmpty) return null;

View File

@ -2,7 +2,6 @@ import React from "react";
import { MdLink, MdLinkOff } from "react-icons/md";
// import { useInViewport } from "react-in-viewport";
import { CustomNodeProps } from "src/components/CustomNode";
import useConfig from "src/store/useConfig";
import useGraph from "src/store/useGraph";
import useStored from "src/store/useStored";
import styled from "styled-components";
@ -48,7 +47,7 @@ const TextNode: React.FC<CustomNodeProps> = ({
const expandNodes = useGraph(state => state.expandNodes);
const collapseNodes = useGraph(state => state.collapseNodes);
const isExpanded = useGraph(state => state.collapsedParents.includes(id));
const performanceMode = useConfig(state => state.performanceMode);
const performanceMode = useGraph(state => state.performanceMode);
// const { inViewport } = useInViewport(ref);
const handleExpand = (e: React.MouseEvent<HTMLButtonElement>) => {

View File

@ -6,7 +6,6 @@ import {
} from "react-zoom-pan-pinch";
import { Canvas, Edge, ElkRoot } from "reaflow";
import { CustomNode } from "src/components/CustomNode";
import useConfig from "src/store/useConfig";
import useGraph from "src/store/useGraph";
import styled from "styled-components";
import { Loading } from "../Loading";
@ -47,8 +46,8 @@ const GraphComponent = ({
setSelectedNode,
}: GraphProps) => {
const setLoading = useGraph(state => state.setLoading);
const setConfig = useConfig(state => state.setConfig);
const centerView = useConfig(state => state.centerView);
const setZoomPanPinch = useGraph(state => state.setZoomPanPinch);
const centerView = useGraph(state => state.centerView);
const loading = useGraph(state => state.loading);
const direction = useGraph(state => state.direction);
@ -70,9 +69,9 @@ const GraphComponent = ({
const onInit = React.useCallback(
(ref: ReactZoomPanPinchRef) => {
setConfig("zoomPanPinch", ref);
setZoomPanPinch(ref);
},
[setConfig]
[setZoomPanPinch]
);
const onLayoutChange = React.useCallback(

View File

@ -19,11 +19,11 @@ import {
VscSettingsGear,
} from "react-icons/vsc";
import { Tooltip } from "src/components/Tooltip";
import useConfig from "src/store/useConfig";
import useGraph from "src/store/useGraph";
import useModal from "src/store/useModal";
import { getNextDirection } from "src/utils/getNextDirection";
import styled from "styled-components";
import useJson from "src/store/useJson";
const StyledSidebar = styled.div`
display: flex;
@ -140,17 +140,19 @@ function rotateLayout(direction: "LEFT" | "RIGHT" | "DOWN" | "UP") {
export const Sidebar: React.FC = () => {
const setVisible = useModal(state => state.setVisible);
const getJson = useGraph(state => state.getJson);
const setDirection = useGraph(state => state.setDirection);
const setConfig = useConfig(state => state.setConfig);
const centerView = useConfig(state => state.centerView);
const getJson = useJson(state => state.getJson);
const collapseGraph = useGraph(state => state.collapseGraph);
const expandGraph = useGraph(state => state.expandGraph);
const centerView = useGraph(state => state.centerView);
const toggleFold = useGraph(state => state.toggleFold);
const toggleFullscreen = useGraph(state => state.toggleFullscreen);
const graphCollapsed = useGraph(state => state.graphCollapsed);
const direction = useGraph(state => state.direction);
const foldNodes = useConfig(state => state.foldNodes);
const fullscreen = useConfig(state => state.fullscreen);
const foldNodes = useGraph(state => state.foldNodes);
const fullscreen = useGraph(state => state.fullscreen);
const graphCollapsed = useGraph(state => state.graphCollapsed);
const handleSave = () => {
const a = document.createElement("a");
@ -162,7 +164,7 @@ export const Sidebar: React.FC = () => {
};
const toggleFoldNodes = () => {
setConfig("foldNodes", !foldNodes);
toggleFold(!foldNodes);
toast(`${foldNodes ? "Unfolded" : "Folded"} nodes`);
};
@ -189,7 +191,7 @@ export const Sidebar: React.FC = () => {
</Link>
<Tooltip className="mobile" title="Edit JSON">
<StyledElement onClick={() => setConfig("fullscreen", !fullscreen)}>
<StyledElement onClick={() => toggleFullscreen(!fullscreen)}>
<AiOutlineEdit />
</StyledElement>
</Tooltip>

View File

@ -3,8 +3,8 @@ import dynamic from "next/dynamic";
import { Allotment } from "allotment";
import "allotment/dist/style.css";
import { JsonEditor } from "src/containers/Editor/JsonEditor";
import useConfig from "src/store/useConfig";
import styled from "styled-components";
import useGraph from "src/store/useGraph";
export const StyledEditor = styled(Allotment)`
position: relative !important;
@ -17,13 +17,13 @@ const LiveEditor = dynamic(() => import("src/containers/Editor/LiveEditor"), {
});
const Panes: React.FC = () => {
const fullscreen = useConfig(state => state.fullscreen);
const setConfig = useConfig(state => state.setConfig);
const fullscreen = useGraph(state => state.fullscreen);
const toggleFullscreen = useGraph(state => state.toggleFullscreen);
const isMobile = React.useMemo(() => window.innerWidth <= 768, []);
React.useEffect(() => {
if (isMobile) setConfig("fullscreen", true);
}, [isMobile, setConfig]);
if (isMobile) toggleFullscreen(true);
}, [isMobile, toggleFullscreen]);
return (
<StyledEditor proportionalLayout={false} vertical={isMobile}>

View File

@ -3,7 +3,7 @@ import { AiOutlineFullscreen, AiOutlineMinus, AiOutlinePlus } from "react-icons/
import { FiDownload } from "react-icons/fi";
import { MdCenterFocusWeak } from "react-icons/md";
import { SearchInput } from "src/components/SearchInput";
import useConfig from "src/store/useConfig";
import useGraph from "src/store/useGraph";
import useModal from "src/store/useModal";
import styled from "styled-components";
@ -48,13 +48,13 @@ const StyledToolElement = styled.button`
export const Tools: React.FC = () => {
const setVisible = useModal(state => state.setVisible);
const fullscreen = useConfig(state => state.fullscreen);
const setConfig = useConfig(state => state.setConfig);
const fullscreen = useGraph(state => state.fullscreen);
const toggleFullscreen = useGraph(state => state.toggleFullscreen);
const zoomIn = useConfig(state => state.zoomIn);
const zoomOut = useConfig(state => state.zoomOut);
const centerView = useConfig(state => state.centerView);
const toggleEditor = () => setConfig("fullscreen", !fullscreen);
const zoomIn = useGraph(state => state.zoomIn);
const zoomOut = useGraph(state => state.zoomOut);
const centerView = useGraph(state => state.centerView);
const toggleEditor = () => toggleFullscreen(!fullscreen);
return (
<>

View File

@ -7,8 +7,8 @@ import { FiCopy, FiDownload } from "react-icons/fi";
import { Button } from "src/components/Button";
import { Input } from "src/components/Input";
import { Modal, ModalProps } from "src/components/Modal";
import useConfig from "src/store/useConfig";
import styled from "styled-components";
import useGraph from "src/store/useGraph";
const ColorPickerStyles: Partial<TwitterPickerStylesProps> = {
card: {
@ -93,7 +93,7 @@ const StyledColorIndicator = styled.div<{ color: string }>`
`;
export const DownloadModal: React.FC<ModalProps> = ({ visible, setVisible }) => {
const setConfig = useConfig(state => state.setConfig);
const togglePerfMode = useGraph(state => state.togglePerfMode);
const [fileDetails, setFileDetails] = React.useState({
filename: "jsoncrack.com",
backgroundColor: "transparent",
@ -103,7 +103,7 @@ export const DownloadModal: React.FC<ModalProps> = ({ visible, setVisible }) =>
const clipboardImage = async () => {
try {
toast.loading("Copying to clipboard...", { id: "toastClipboard" });
setConfig("performanceMode", false);
togglePerfMode(false);
const imageElement = document.querySelector("svg[id*='ref']") as HTMLElement;
@ -126,14 +126,14 @@ export const DownloadModal: React.FC<ModalProps> = ({ visible, setVisible }) =>
} finally {
toast.dismiss("toastClipboard");
setVisible(false);
setConfig("performanceMode", true);
togglePerfMode(true);
}
};
const exportAsImage = async () => {
try {
toast.loading("Downloading...", { id: "toastDownload" });
setConfig("performanceMode", false);
togglePerfMode(false);
const imageElement = document.querySelector("svg[id*='ref']") as HTMLElement;
@ -148,7 +148,7 @@ export const DownloadModal: React.FC<ModalProps> = ({ visible, setVisible }) =>
} finally {
toast.dismiss("toastDownload");
setVisible(false);
setConfig("performanceMode", true);
togglePerfMode(true);
}
};

View File

@ -1,14 +1,14 @@
import React from "react";
import useGraph from "src/store/useGraph";
import {
searchQuery,
cleanupHighlight,
highlightMatchedNodes,
} from "src/utils/search";
import useConfig from "../store/useConfig";
export const useFocusNode = () => {
const setConfig = useConfig(state => state.setConfig);
const zoomPanPinch = useConfig(state => state.zoomPanPinch);
const togglePerfMode = useGraph(state => state.togglePerfMode);
const zoomPanPinch = useGraph(state => state.zoomPanPinch);
const [selectedNode, setSelectedNode] = React.useState(0);
const [content, setContent] = React.useState({
value: "",
@ -18,14 +18,14 @@ export const useFocusNode = () => {
const skip = () => setSelectedNode(current => current + 1);
React.useEffect(() => {
setConfig("performanceMode", !content.value.length);
togglePerfMode(!content.value.length);
const debouncer = setTimeout(() => {
setContent(val => ({ ...val, debounced: content.value }));
}, 800);
return () => clearTimeout(debouncer);
}, [content.value, setConfig]);
}, [content.value, togglePerfMode]);
React.useEffect(() => {
if (!zoomPanPinch) return;

View File

@ -1,60 +0,0 @@
import { ReactZoomPanPinchRef } from "react-zoom-pan-pinch";
import create from "zustand";
type StateType = keyof typeof initialStates;
type StateKey<T extends StateType> = typeof initialStates[T];
interface ConfigActions {
setConfig: <T extends StateType, K extends StateKey<T>>(key: T, value: K) => void;
zoomIn: () => void;
zoomOut: () => void;
centerView: () => void;
}
const initialStates = {
foldNodes: false,
fullscreen: false,
performanceMode: true,
zoomPanPinch: undefined as ReactZoomPanPinchRef | undefined,
};
export type Config = typeof initialStates;
const useConfig = create<Config & ConfigActions>()((set, get) => ({
...initialStates,
zoomIn: () => {
const zoomPanPinch = get().zoomPanPinch;
if (zoomPanPinch) {
zoomPanPinch.setTransform(
zoomPanPinch?.state.positionX,
zoomPanPinch?.state.positionY,
zoomPanPinch?.state.scale + 0.4
);
}
},
zoomOut: () => {
const zoomPanPinch = get().zoomPanPinch;
if (zoomPanPinch) {
zoomPanPinch.setTransform(
zoomPanPinch?.state.positionX,
zoomPanPinch?.state.positionY,
zoomPanPinch?.state.scale - 0.4
);
}
},
centerView: () => {
const zoomPanPinch = get().zoomPanPinch;
const canvas = document.querySelector(".jsoncrack-canvas") as HTMLElement;
if (zoomPanPinch && canvas) zoomPanPinch.zoomToElement(canvas);
},
setConfig: (setting, value) => {
if (setting === "fullscreen" && value) {
set({ fullscreen: true });
return get().centerView();
}
set({ [setting]: value });
},
}));
export default useConfig;

View File

@ -1,17 +1,19 @@
import { parse } from "jsonc-parser";
import { ReactZoomPanPinchRef } from "react-zoom-pan-pinch";
import { CanvasDirection } from "reaflow";
import { Graph } from "src/components/Graph";
import { getChildrenEdges } from "src/utils/getChildrenEdges";
import { getOutgoers } from "src/utils/getOutgoers";
import { parser } from "src/utils/jsonParser";
import create from "zustand";
import useConfig from "./useConfig";
const initialStates = {
json: null as unknown as string,
loading: true,
zoomPanPinch: undefined as ReactZoomPanPinchRef | undefined,
direction: "RIGHT" as CanvasDirection,
loading: true,
graphCollapsed: false,
foldNodes: false,
fullscreen: false,
performanceMode: true,
nodes: [] as NodeData[],
edges: [] as EdgeData[],
collapsedNodes: [] as string[],
@ -23,25 +25,36 @@ export type Graph = typeof initialStates;
interface GraphActions {
setGraph: (json: string) => void;
getJson: () => string;
setNodeEdges: (nodes: NodeData[], edges: EdgeData[]) => void;
setLoading: (loading: boolean) => void;
setDirection: (direction: CanvasDirection) => void;
setZoomPanPinch: (ref: ReactZoomPanPinchRef) => void;
expandNodes: (nodeId: string) => void;
collapseNodes: (nodeId: string) => void;
collapseGraph: () => void;
expandGraph: () => void;
toggleFold: (value: boolean) => void;
toggleFullscreen: (value: boolean) => void;
togglePerfMode: (value: boolean) => void;
zoomIn: () => void;
zoomOut: () => void;
centerView: () => void;
}
const useGraph = create<Graph & GraphActions>((set, get) => ({
...initialStates,
getJson: () => get().json,
setGraph: (data: string) => {
const { nodes, edges } = parser(data, useConfig.getState().foldNodes);
const json = JSON.stringify(parse(data), null, 2);
const { nodes, edges } = parser(data, get().foldNodes);
set({ json, loading: true });
get().setNodeEdges(nodes, edges);
set({
nodes,
edges,
collapsedParents: [],
collapsedNodes: [],
collapsedEdges: [],
graphCollapsed: false,
loading: true
});
},
setDirection: direction => set({ direction }),
setNodeEdges: (nodes, edges) =>
@ -52,6 +65,7 @@ const useGraph = create<Graph & GraphActions>((set, get) => ({
collapsedNodes: [],
collapsedEdges: [],
graphCollapsed: false,
loading: true
}),
setLoading: loading => set({ loading }),
expandNodes: nodeId => {
@ -141,6 +155,36 @@ const useGraph = create<Graph & GraphActions>((set, get) => ({
graphCollapsed: false,
});
},
zoomIn: () => {
const zoomPanPinch = get().zoomPanPinch;
if (zoomPanPinch) {
zoomPanPinch.setTransform(
zoomPanPinch?.state.positionX,
zoomPanPinch?.state.positionY,
zoomPanPinch?.state.scale + 0.4
);
}
},
zoomOut: () => {
const zoomPanPinch = get().zoomPanPinch;
if (zoomPanPinch) {
zoomPanPinch.setTransform(
zoomPanPinch?.state.positionX,
zoomPanPinch?.state.positionY,
zoomPanPinch?.state.scale - 0.4
);
}
},
centerView: () => {
const zoomPanPinch = get().zoomPanPinch;
const canvas = document.querySelector(".jsoncrack-canvas") as HTMLElement;
if (zoomPanPinch && canvas) zoomPanPinch.zoomToElement(canvas);
},
toggleFold: foldNodes => set({ foldNodes }),
togglePerfMode: performanceMode => set({ performanceMode }),
toggleFullscreen: fullscreen => set({ fullscreen }),
setZoomPanPinch: zoomPanPinch => set({ zoomPanPinch }),
}));
export default useGraph;

View File

@ -15,6 +15,7 @@ interface Json {
interface JsonActions {
setJson: (json: string) => void;
getJson: () => string;
fetchJson: (jsonId: string | string[] | undefined) => void;
setError: (hasError: boolean) => void;
setHasChanges: (hasChanges: boolean) => void;
@ -30,8 +31,9 @@ const initialStates = {
export type JsonStates = typeof initialStates;
const useJson = create<JsonStates & JsonActions>()(set => ({
const useJson = create<JsonStates & JsonActions>()((set, get) => ({
...initialStates,
getJson: () => get().json,
fetchJson: async jsonId => {
if (jsonId) {
const { data } = await altogic.endpoint.get(`json/${jsonId}`);