This commit is contained in:
Aykut Saraç 2022-02-15 17:01:44 +03:00
parent c093575700
commit 1286dbba13
3 changed files with 147 additions and 142 deletions

View File

@ -3,10 +3,7 @@ import Link from "next/link";
import styled from "styled-components";
import { useLocalStorage } from "usehooks-ts";
import { FaFileImport } from "react-icons/fa";
import {
MdUnfoldMore,
MdUnfoldLess,
} from "react-icons/md";
import { MdUnfoldMore, MdUnfoldLess } from "react-icons/md";
import {
AiFillHome,
AiOutlineClear,
@ -25,6 +22,7 @@ import {
import { getNextLayout } from "src/containers/LiveEditor/helpers";
import { StorageConfig } from "src/typings/global";
import { CanvasDirection } from "reaflow";
import { useLoading } from "src/hooks/useLoading";
const StyledSidebar = styled.div`
display: flex;
@ -110,6 +108,8 @@ function getLayoutIcon(layout: CanvasDirection) {
export const Sidebar: React.FC<{
setJson: React.Dispatch<React.SetStateAction<string>>;
}> = ({ setJson }) => {
const pageLoaded = useLoading();
const [jsonFile, setJsonFile] = React.useState<File | null>(null);
const [config, setConfig] = useLocalStorage<StorageConfig>("config", {
layout: "LEFT",
@ -117,7 +117,6 @@ export const Sidebar: React.FC<{
controls: true,
});
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.files) setJsonFile(e.target.files?.item(0));
};
@ -140,89 +139,92 @@ export const Sidebar: React.FC<{
}
}, [jsonFile, setJson]);
return (
<StyledSidebar>
<StyledTopWrapper>
<Link passHref href="/">
<StyledElement as="a">
<StyledLogo>
<StyledText>J</StyledText>
<StyledText secondary>V</StyledText>
</StyledLogo>
if (pageLoaded)
return (
<StyledSidebar>
<StyledTopWrapper>
<Link passHref href="/">
<StyledElement as="a">
<StyledLogo>
<StyledText>J</StyledText>
<StyledText secondary>V</StyledText>
</StyledLogo>
</StyledElement>
</Link>
<StyledElement title="Home">
<Link href="/">
<a>
<AiFillHome />
</a>
</Link>
</StyledElement>
<StyledElement
as="a"
onClick={() => {
setJson("[]");
localStorage.removeItem("json");
}}
title="Clear JSON"
>
<AiOutlineClear />
</StyledElement>
<StyledElement
as="a"
onClick={() =>
setConfig((c) => ({
...c,
layout: getNextLayout(c.layout),
}))
}
title="Change Layout"
>
{getLayoutIcon(config.layout)}
</StyledElement>
<StyledElement
title="Toggle Controls"
as="a"
onClick={() => toggle("controls")}
>
{config.controls ? <AiFillControl /> : <AiOutlineControl />}
</StyledElement>
</Link>
<StyledElement title="Home">
<Link href="/">
<a>
<AiFillHome />
</a>
</Link>
</StyledElement>
<StyledElement
as="a"
onClick={() => {
setJson("[]");
localStorage.removeItem("json");
}}
title="Clear JSON"
>
<AiOutlineClear />
</StyledElement>
<StyledElement
as="a"
onClick={() =>
setConfig((c) => ({
...c,
layout: getNextLayout(c.layout),
}))
}
title="Change Layout"
>
{getLayoutIcon(config.layout)}
</StyledElement>
<StyledElement
title="Toggle Controls"
as="a"
onClick={() => toggle("controls")}
>
{config.controls ? <AiFillControl /> : <AiOutlineControl />}
</StyledElement>
<StyledElement
as="a"
title="Toggle Expand/Collapse"
onClick={() => toggle("expand")}
>
{config.expand ? <MdUnfoldMore /> : <MdUnfoldLess />}
</StyledElement>
<StyledElement as="a" title="Import JSON File">
<StyledImportFile>
<input
key={jsonFile?.name}
onChange={handleFileChange}
type="file"
accept="application/JSON"
/>
<FaFileImport />
</StyledImportFile>
</StyledElement>
</StyledTopWrapper>
<StyledBottomWrapper>
<StyledElement>
<Link href="https://twitter.com/aykutsarach">
<a rel="me" target="_blank">
<AiOutlineTwitter />
</a>
</Link>
</StyledElement>
<StyledElement>
<Link href="https://github.com/AykutSarac/jsonvisio.com">
<a rel="me" target="_blank">
<AiFillGithub />
</a>
</Link>
</StyledElement>
</StyledBottomWrapper>
</StyledSidebar>
);
<StyledElement
as="a"
title="Toggle Expand/Collapse"
onClick={() => toggle("expand")}
>
{config.expand ? <MdUnfoldMore /> : <MdUnfoldLess />}
</StyledElement>
<StyledElement as="a" title="Import JSON File">
<StyledImportFile>
<input
key={jsonFile?.name}
onChange={handleFileChange}
type="file"
accept="application/JSON"
/>
<FaFileImport />
</StyledImportFile>
</StyledElement>
</StyledTopWrapper>
<StyledBottomWrapper>
<StyledElement>
<Link href="https://twitter.com/aykutsarach">
<a rel="me" target="_blank">
<AiOutlineTwitter />
</a>
</Link>
</StyledElement>
<StyledElement>
<Link href="https://github.com/AykutSarac/jsonvisio.com">
<a rel="me" target="_blank">
<AiFillGithub />
</a>
</Link>
</StyledElement>
</StyledBottomWrapper>
</StyledSidebar>
);
return null;
};

View File

@ -18,6 +18,7 @@ import {
AiOutlineFullscreen,
AiFillSave,
} from "react-icons/ai";
import { useLoading } from "src/hooks/useLoading";
const StyledLiveEditor = styled.div`
position: relative;
@ -47,6 +48,8 @@ export const LiveEditor: React.FC<{
json: string;
setJson: React.Dispatch<React.SetStateAction<string>>;
}> = ({ json }) => {
const pageLoaded = useLoading();
const canvasRef = React.useRef<CanvasRef | null>(null);
const wrapperRef = React.useRef<ReactZoomPanPinchRef | null>(null);
const [config] = useLocalStorage<StorageConfig>("config", {
@ -87,55 +90,58 @@ export const LiveEditor: React.FC<{
}
};
return (
<StyledLiveEditor>
<StyledEditorWrapper>
<TransformWrapper
maxScale={2}
minScale={0.4}
initialScale={0.8}
ref={wrapperRef}
limitToBounds={false}
wheel={{
step: 0.4,
}}
>
<TransformComponent>
<Canvas
ref={canvasRef}
nodes={nodes}
edges={edges}
layoutOptions={{
"elk.direction": config.layout,
}}
maxWidth={20000}
maxHeight={20000}
center={false}
zoomable={false}
fit
readonly
animated
node={CustomNode}
/>
</TransformComponent>
</TransformWrapper>
</StyledEditorWrapper>
{config.controls && (
<StyledControls>
<Button onClick={() => zoomIn(0.5)}>
<AiOutlineZoomIn size={24} />
</Button>
<Button onClick={() => zoomOut(0.4)}>
<AiOutlineZoomOut size={24} />
</Button>
<Button onClick={() => wrapperRef.current?.resetTransform()}>
<AiOutlineFullscreen size={24} />
</Button>
<Button onClick={() => localStorage.setItem("json", json)}>
<AiFillSave size={24} />
</Button>
</StyledControls>
)}
</StyledLiveEditor>
);
if (pageLoaded)
return (
<StyledLiveEditor>
<StyledEditorWrapper>
<TransformWrapper
maxScale={2}
minScale={0.4}
initialScale={0.8}
ref={wrapperRef}
limitToBounds={false}
wheel={{
step: 0.4,
}}
>
<TransformComponent>
<Canvas
ref={canvasRef}
nodes={nodes}
edges={edges}
layoutOptions={{
"elk.direction": config.layout,
}}
maxWidth={20000}
maxHeight={20000}
center={false}
zoomable={false}
fit
readonly
animated
node={CustomNode}
/>
</TransformComponent>
</TransformWrapper>
</StyledEditorWrapper>
{config.controls && (
<StyledControls>
<Button onClick={() => zoomIn(0.5)}>
<AiOutlineZoomIn size={24} />
</Button>
<Button onClick={() => zoomOut(0.4)}>
<AiOutlineZoomOut size={24} />
</Button>
<Button onClick={() => wrapperRef.current?.resetTransform()}>
<AiOutlineFullscreen size={24} />
</Button>
<Button onClick={() => localStorage.setItem("json", json)}>
<AiFillSave size={24} />
</Button>
</StyledControls>
)}
</StyledLiveEditor>
);
return null;
};

View File

@ -11,7 +11,6 @@ import { useLoading } from "src/hooks/useLoading";
function AykutSarac({ Component, pageProps }: AppProps) {
const router = useRouter();
const data = useLoading();
const [pageLoading, setPageLoading] = React.useState<boolean>(false);
React.useEffect(() => {
@ -38,8 +37,6 @@ function AykutSarac({ Component, pageProps }: AppProps) {
</ThemeProvider>
);
if (!data) return null;
return (
<ThemeProvider theme={darkTheme}>
<GlobalStyle />