mirror of
https://github.com/AykutSarac/jsoncrack.com.git
synced 2025-01-20 05:12:54 +08:00
add option to expand & collapse
This commit is contained in:
parent
da5ae26949
commit
4b53b08868
@ -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>
|
||||
|
@ -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]}
|
||||
|
@ -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 {
|
||||
|
@ -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>
|
||||
)}
|
||||
|
@ -2,6 +2,6 @@ import { CanvasDirection } from "reaflow";
|
||||
|
||||
export interface StorageConfig {
|
||||
layout: CanvasDirection;
|
||||
minimap: boolean;
|
||||
expand: boolean;
|
||||
controls: boolean;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user