add option to expand & collapse

This commit is contained in:
Aykut Saraç 2022-02-14 14:36:16 +03:00
parent da5ae26949
commit 4b53b08868
5 changed files with 71 additions and 56 deletions

View File

@ -3,7 +3,7 @@ import Link from "next/link";
import styled from "styled-components";
import { useLocalStorage } from "usehooks-ts";
import { FaFileImport, FaMap } from "react-icons/fa";
import { MdAutoGraph } from "react-icons/md";
import { MdAutoGraph, MdFormatLineSpacing } from "react-icons/md";
import {
AiFillHome,
AiOutlineClear,
@ -96,7 +96,7 @@ export const Sidebar: React.FC<{
const [jsonFile, setJsonFile] = React.useState<File | null>(null);
const [config, setConfig] = useLocalStorage<StorageConfig>("config", {
layout: "LEFT",
minimap: true,
expand: true,
controls: true,
});
@ -104,7 +104,7 @@ export const Sidebar: React.FC<{
if (e.target.files) setJsonFile(e.target.files?.item(0));
};
const toggle = (setting: "minimap" | "controls") => {
const toggle = (setting: "expand" | "controls") => {
setConfig((c) => ({
...c,
[setting]: !c[setting],
@ -125,16 +125,14 @@ export const Sidebar: React.FC<{
return (
<StyledSidebar>
<StyledTopWrapper>
<StyledElement>
<Link href="/">
<a>
<StyledLogo>
<StyledText>J</StyledText>
<StyledText secondary>V</StyledText>
</StyledLogo>
</a>
</Link>
</StyledElement>
<Link href="/">
<StyledElement as="a">
<StyledLogo>
<StyledText>J</StyledText>
<StyledText secondary>V</StyledText>
</StyledLogo>
</StyledElement>
</Link>
<StyledElement title="Home">
<Link href="/">
<a>
@ -164,14 +162,6 @@ export const Sidebar: React.FC<{
>
<MdAutoGraph />
</StyledElement>
<StyledElement
title="Toggle Minimap"
as="a"
onClick={() => toggle("minimap")}
disabled
>
<FaMap />
</StyledElement>
<StyledElement
title="Toggle Controls"
as="a"
@ -179,18 +169,24 @@ export const Sidebar: React.FC<{
>
<AiFillControl />
</StyledElement>
<StyledElement title="Import JSON File">
<a>
<StyledImportFile>
<input
key={jsonFile?.name}
onChange={handleFileChange}
type="file"
accept="application/JSON"
/>
<FaFileImport />
</StyledImportFile>
</a>
<StyledElement
as="a"
title="Toggle Expand/Collapse"
onClick={() => toggle("expand")}
>
<MdFormatLineSpacing />
</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>

View File

@ -1,11 +1,8 @@
import React, { memo } from "react";
import { Label, Node, Port, NodeChildProps, NodeProps } from "reaflow";
import React from "react";
import { Label, Node, Port, NodeProps } from "reaflow";
import styled from "styled-components";
const StyledNode = styled(Node)`
stroke: black;
stroke-width: 1;
`;
const StyledNode = styled(Node)``;
const StyledTextWrapper = styled.div`
position: absolute;
@ -15,9 +12,18 @@ const StyledTextWrapper = styled.div`
font-size: 12px;
width: 100%;
height: 100%;
overflow: hidden;
&:hover {
cursor: pointer;
stroke: white !important;
}
`;
const StyledText = styled.pre<{ width: number; height: number }>`
display: flex;
justify-content: center;
flex-direction: column;
width: ${({ width }) => width};
height: ${({ height }) => height};
color: ${({ theme }) => theme.SILVER};
@ -33,7 +39,10 @@ const StyledForeignObject = styled.foreignObject<{
height: ${({ height }) => height + "px"};
`;
const StyledKey = styled.span<{ bond?: boolean; arrayValue?: boolean }>`
const StyledKey = styled.span<{
bond?: boolean;
arrayValue?: boolean;
}>`
color: ${({ theme, bond, arrayValue }) =>
bond ? theme.SEAGREEN : arrayValue ? theme.ORANGE : theme.BLURPLE};
`;
@ -64,13 +73,13 @@ const CustomNode = ({ nodeProps }) => {
const entries = Object.entries(data.text);
if (Object.keys(data.text).every((val) => !isNaN(+val))) {
const text = Object.values(data.text).join("");
return (
<StyledForeignObject width={width} height={height} x={0} y={0}>
<StyledTextWrapper>
<StyledText width={width} height={height}>
<StyledKey arrayValue>
{Object.values(data.text).join("")}
</StyledKey>
<StyledKey arrayValue>{text}</StyledKey>
</StyledText>
</StyledTextWrapper>
</StyledForeignObject>
@ -84,7 +93,14 @@ const CustomNode = ({ nodeProps }) => {
{entries.map((val) => (
<div
key={nodeProps.id}
style={{ height: "fit-content" }}
style={{
height: "fit-content",
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
padding: '0 auto',
width: width - 20
}}
>
<StyledKey>{val[0]}: </StyledKey>
{val[1]}

View File

@ -1,7 +1,7 @@
import { CanvasDirection, NodeData, EdgeData } from "reaflow";
import { parser } from "src/utils/json-editor-parser";
export function getEdgeNodes(graph: any): any {
export function getEdgeNodes(graph: any, isExpanded: boolean = true): any {
graph = JSON.parse(graph);
const elements = parser(graph);
@ -22,8 +22,8 @@ export function getEdgeNodes(graph: any): any {
nodes.push({
id: el.id,
text: el.text,
width: 35 + longestLine * 8,
height: 30 + lines.length * 10,
width: isExpanded ? (35 + longestLine * 8) : 180,
height: isExpanded ? (30 + lines.length * 10) : 50,
data: { type: "special" },
});
} else {

View File

@ -9,7 +9,6 @@ import { useLocalStorage } from "usehooks-ts";
import { Canvas, CanvasRef } from "reaflow";
import { StorageConfig } from "src/typings/global";
import { defaultValue } from "../JsonEditor";
import { getEdgeNodes } from "./helpers";
import { NodeWrapper } from "./CustomNode";
import { Button } from "src/components/Button";
@ -37,7 +36,11 @@ const StyledControls = styled.div`
gap: 8px;
bottom: 8px;
right: 8px;
opacity: 0.8;
opacity: 0.9;
button:hover {
opacity: 0.5;
}
`;
export const LiveEditor: React.FC<{
@ -48,7 +51,7 @@ export const LiveEditor: React.FC<{
const wrapperRef = React.useRef<ReactZoomPanPinchRef | null>(null);
const [config] = useLocalStorage<StorageConfig>("config", {
layout: "LEFT",
minimap: true,
expand: true,
controls: true,
});
@ -56,7 +59,7 @@ export const LiveEditor: React.FC<{
if (wrapperRef.current) wrapperRef.current?.resetTransform();
}, [json, wrapperRef]);
const { nodes, edges } = getEdgeNodes(json);
const { nodes, edges } = getEdgeNodes(json, config.expand);
const zoomIn = (scale: number) => {
if (
@ -120,16 +123,16 @@ export const LiveEditor: React.FC<{
{config.controls && (
<StyledControls>
<Button onClick={() => zoomIn(0.5)}>
<AiOutlineZoomIn size={20} />
<AiOutlineZoomIn size={24} />
</Button>
<Button onClick={() => zoomOut(0.4)}>
<AiOutlineZoomOut size={20} />
<AiOutlineZoomOut size={24} />
</Button>
<Button onClick={() => wrapperRef.current?.resetTransform()}>
<AiOutlineFullscreen size={20} />
<AiOutlineFullscreen size={24} />
</Button>
<Button onClick={() => localStorage.setItem("json", json)}>
<AiFillSave size={20} />
<AiFillSave size={24} />
</Button>
</StyledControls>
)}

View File

@ -2,6 +2,6 @@ import { CanvasDirection } from "reaflow";
export interface StorageConfig {
layout: CanvasDirection;
minimap: boolean;
expand: boolean;
controls: boolean;
}