Browse Source

add option to expand & collapse

Aykut Saraç 3 năm trước cách đây
mục cha
commit
4b53b08868

+ 28 - 32
src/components/Sidebar/index.tsx

@@ -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>
@@ -165,32 +163,30 @@ export const Sidebar: React.FC<{
           <MdAutoGraph />
         </StyledElement>
         <StyledElement
-          title="Toggle Minimap"
+          title="Toggle Controls"
           as="a"
-          onClick={() => toggle("minimap")}
-          disabled
+          onClick={() => toggle("controls")}
         >
-          <FaMap />
+          <AiFillControl />
         </StyledElement>
+
         <StyledElement
-          title="Toggle Controls"
           as="a"
-          onClick={() => toggle("controls")}
+          title="Toggle Expand/Collapse"
+          onClick={() => toggle("expand")}
         >
-          <AiFillControl />
+          <MdFormatLineSpacing />
         </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="Import JSON File">
+          <StyledImportFile>
+            <input
+              key={jsonFile?.name}
+              onChange={handleFileChange}
+              type="file"
+              accept="application/JSON"
+            />
+            <FaFileImport />
+          </StyledImportFile>
         </StyledElement>
       </StyledTopWrapper>
       <StyledBottomWrapper>

+ 27 - 11
src/containers/LiveEditor/CustomNode.tsx

@@ -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]}

+ 3 - 3
src/containers/LiveEditor/helpers.ts

@@ -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 {

+ 11 - 8
src/containers/LiveEditor/index.tsx

@@ -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>
       )}

+ 1 - 1
src/typings/global.ts

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