From 07d539fe449b099ca1c4a2ec7fb6a0b5f57f3f4c Mon Sep 17 00:00:00 2001 From: Visal In Date: Wed, 24 Jul 2024 21:43:21 +0900 Subject: [PATCH] feat: add json and multi-line editor --- package-lock.json | 276 +----------------- package.json | 5 +- src/app/testing/page.tsx | 26 +- src/components/gui/json-editor/index.tsx | 102 +++++++ .../gui/providers/full-editor-provider.tsx | 70 +++-- src/components/gui/query-result-table.tsx | 58 +++- ...{BigNumberCell.tsx => big-number-cell.tsx} | 2 +- ...tableCell.tsx => create-editable-cell.tsx} | 25 +- .../{GenericCell.tsx => generic-cell.tsx} | 0 .../{NumberCell.tsx => number-cell.tsx} | 2 +- .../{TextCell.tsx => text-cell.tsx} | 2 +- .../table-optimized/OptimizeTableState.tsx | 7 +- src/components/markdown-editor/index.tsx | 107 ------- 13 files changed, 264 insertions(+), 418 deletions(-) create mode 100644 src/components/gui/json-editor/index.tsx rename src/components/gui/table-cell/{BigNumberCell.tsx => big-number-cell.tsx} (88%) rename src/components/gui/table-cell/{createEditableCell.tsx => create-editable-cell.tsx} (84%) rename src/components/gui/table-cell/{GenericCell.tsx => generic-cell.tsx} (100%) rename src/components/gui/table-cell/{NumberCell.tsx => number-cell.tsx} (89%) rename src/components/gui/table-cell/{TextCell.tsx => text-cell.tsx} (67%) delete mode 100644 src/components/markdown-editor/index.tsx diff --git a/package-lock.json b/package-lock.json index 95d4c984..90c9a02e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,12 +11,11 @@ "@aws-sdk/client-s3": "^3.540.0", "@blocknote/core": "^0.12.1", "@blocknote/react": "^0.12.2", + "@codemirror/lang-json": "^6.0.1", "@codemirror/lang-sql": "^6.5.5", "@dnd-kit/core": "^6.1.0", "@dnd-kit/sortable": "^8.0.0", "@justmiracle/result": "^1.2.0", - "@lexical/markdown": "^0.16.1", - "@lexical/react": "^0.16.1", "@lezer/common": "^1.2.1", "@lezer/lr": "^1.4.0", "@libsql/client": "^0.5.3", @@ -44,6 +43,7 @@ "@radix-ui/react-toggle": "^1.0.3", "@radix-ui/react-toggle-group": "^1.0.4", "@radix-ui/react-tooltip": "^1.0.7", + "@replit/codemirror-indentation-markers": "^6.5.3", "@silevis/reactgrid": "^4.1.3", "@t3-oss/env-nextjs": "^0.9.2", "@tiptap/core": "^2.3.0", @@ -64,7 +64,6 @@ "drizzle-orm": "^0.30.1", "eslint-plugin-jest": "^27.6.3", "file-saver": "^2.0.5", - "lexical": "^0.16.1", "libsql-stateless-easy": "^1.6.11", "lucia": "^3.2.0", "lucide-react": "^0.309.0", @@ -3805,239 +3804,6 @@ "resolved": "https://registry.npmjs.org/@justmiracle/result/-/result-1.2.0.tgz", "integrity": "sha512-MyyfTSloRNvdB1EnzSDiOeyPtdXeK+gp1d2zxqcjq/XHoagsIzo7ImEJCKIUkOTlmuEInPfYZrcAU7sdeCWqkg==" }, - "node_modules/@lexical/clipboard": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@lexical/clipboard/-/clipboard-0.16.1.tgz", - "integrity": "sha512-0dWs/SwKS5KPpuf6fUVVt9vSCl6HAqcDGhSITw/okv0rrIlXTUT6WhVsMJtXfFxTyVvwMeOecJHvQH3i/jRQtA==", - "dependencies": { - "@lexical/html": "0.16.1", - "@lexical/list": "0.16.1", - "@lexical/selection": "0.16.1", - "@lexical/utils": "0.16.1", - "lexical": "0.16.1" - } - }, - "node_modules/@lexical/code": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@lexical/code/-/code-0.16.1.tgz", - "integrity": "sha512-pOC28rRZ2XkmI2nIJm50DbKaCJtk5D0o7r6nORYp4i0z+lxt5Sf2m82DL9ksUHJRqKy87pwJDpoWvJ2SAI0ohw==", - "dependencies": { - "@lexical/utils": "0.16.1", - "lexical": "0.16.1", - "prismjs": "^1.27.0" - } - }, - "node_modules/@lexical/devtools-core": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@lexical/devtools-core/-/devtools-core-0.16.1.tgz", - "integrity": "sha512-8CvGERGL7ySDVGLU+YPeq+JupIXsOFlXa3EuJ88koLKqXxYenwMleZgGqayFp6lCP78xqPKnATVeoOZUt/NabQ==", - "dependencies": { - "@lexical/html": "0.16.1", - "@lexical/link": "0.16.1", - "@lexical/mark": "0.16.1", - "@lexical/table": "0.16.1", - "@lexical/utils": "0.16.1", - "lexical": "0.16.1" - }, - "peerDependencies": { - "react": ">=17.x", - "react-dom": ">=17.x" - } - }, - "node_modules/@lexical/dragon": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@lexical/dragon/-/dragon-0.16.1.tgz", - "integrity": "sha512-Rvd60GIYN5kpjjBumS34EnNbBaNsoseI0AlzOdtIV302jiHPCLH0noe9kxzu9nZy+MZmjZy8Dx2zTbQT2mueRw==", - "dependencies": { - "lexical": "0.16.1" - } - }, - "node_modules/@lexical/hashtag": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@lexical/hashtag/-/hashtag-0.16.1.tgz", - "integrity": "sha512-G+YOxStAKs3q1utqm9KR4D4lCkwIH52Rctm4RgaVTI+4lvTaybeDRGFV75P/pI/qlF7/FvAYHTYEzCjtC3GNMQ==", - "dependencies": { - "@lexical/utils": "0.16.1", - "lexical": "0.16.1" - } - }, - "node_modules/@lexical/history": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@lexical/history/-/history-0.16.1.tgz", - "integrity": "sha512-WQhScx0TJeKSQAnEkRpIaWdUXqirrNrom2MxbBUc/32zEUMm9FzV7nRGknvUabEFUo7vZq6xTZpOExQJqHInQA==", - "dependencies": { - "@lexical/utils": "0.16.1", - "lexical": "0.16.1" - } - }, - "node_modules/@lexical/html": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@lexical/html/-/html-0.16.1.tgz", - "integrity": "sha512-vbtAdCvQ3PaAqa5mFmtmrvbiAvjCu1iXBAJ0bsHqFXCF2Sba5LwHVe8dUAOTpfEZEMbiHfjul6b5fj4vNPGF2A==", - "dependencies": { - "@lexical/selection": "0.16.1", - "@lexical/utils": "0.16.1", - "lexical": "0.16.1" - } - }, - "node_modules/@lexical/link": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@lexical/link/-/link-0.16.1.tgz", - "integrity": "sha512-zG36gEnEqbIe6tK/MhXi7wn/XMY/zdivnPcOY5WyC3derkEezeLSSIFsC1u5UNeK5pbpNMSy4LDpLhi1Ww4Y5w==", - "dependencies": { - "@lexical/utils": "0.16.1", - "lexical": "0.16.1" - } - }, - "node_modules/@lexical/list": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@lexical/list/-/list-0.16.1.tgz", - "integrity": "sha512-i9YhLAh5N6YO9dP+R1SIL9WEdCKeTiQQYVUzj84vDvX5DIBxMPUjTmMn3LXu9T+QO3h1s2L/vJusZASrl45eAw==", - "dependencies": { - "@lexical/utils": "0.16.1", - "lexical": "0.16.1" - } - }, - "node_modules/@lexical/mark": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@lexical/mark/-/mark-0.16.1.tgz", - "integrity": "sha512-CZRGMLcxn5D+jzf1XnH+Z+uUugmpg1mBwTbGybCPm8UWpBrKDHkrscfMgWz62iRWz0cdVjM5+0zWpNElxFTRjQ==", - "dependencies": { - "@lexical/utils": "0.16.1", - "lexical": "0.16.1" - } - }, - "node_modules/@lexical/markdown": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@lexical/markdown/-/markdown-0.16.1.tgz", - "integrity": "sha512-0sBLttMvfQO/hVaIqpHdvDowpgV2CoRuWo2CNwvRLZPPWvPVjL4Nkb73wmi8zAZsAOTbX2aw+g4m/+k5oJqNig==", - "dependencies": { - "@lexical/code": "0.16.1", - "@lexical/link": "0.16.1", - "@lexical/list": "0.16.1", - "@lexical/rich-text": "0.16.1", - "@lexical/text": "0.16.1", - "@lexical/utils": "0.16.1", - "lexical": "0.16.1" - } - }, - "node_modules/@lexical/offset": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@lexical/offset/-/offset-0.16.1.tgz", - "integrity": "sha512-/i2J04lQmFeydUZIF8tKXLQTXiJDTQ6GRnkfv1OpxU4amc0rwGa7+qAz/PuF1n58rP6InpLmSHxgY5JztXa2jw==", - "dependencies": { - "lexical": "0.16.1" - } - }, - "node_modules/@lexical/overflow": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@lexical/overflow/-/overflow-0.16.1.tgz", - "integrity": "sha512-xh5YpoxwA7K4wgMQF/Sjl8sdjaxqesLCtH5ZrcMsaPlmucDIEEs+i8xxk+kDUTEY7y+3FvRxs4lGNgX8RVWkvQ==", - "dependencies": { - "lexical": "0.16.1" - } - }, - "node_modules/@lexical/plain-text": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@lexical/plain-text/-/plain-text-0.16.1.tgz", - "integrity": "sha512-GjY4ylrBZIaAVIF8IFnmW0XGyHAuRmWA6gKB8iTTlsjgFrCHFIYC74EeJSp309O0Hflg9rRBnKoX1TYruFHVwA==", - "dependencies": { - "@lexical/clipboard": "0.16.1", - "@lexical/selection": "0.16.1", - "@lexical/utils": "0.16.1", - "lexical": "0.16.1" - } - }, - "node_modules/@lexical/react": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@lexical/react/-/react-0.16.1.tgz", - "integrity": "sha512-SsGgLt9iKfrrMRy9lFb6ROVPUYOgv6b+mCn9Al+TLqs/gBReDBi3msA7m526nrtBUKYUnjHdQ1QXIJzuKgOxcg==", - "dependencies": { - "@lexical/clipboard": "0.16.1", - "@lexical/code": "0.16.1", - "@lexical/devtools-core": "0.16.1", - "@lexical/dragon": "0.16.1", - "@lexical/hashtag": "0.16.1", - "@lexical/history": "0.16.1", - "@lexical/link": "0.16.1", - "@lexical/list": "0.16.1", - "@lexical/mark": "0.16.1", - "@lexical/markdown": "0.16.1", - "@lexical/overflow": "0.16.1", - "@lexical/plain-text": "0.16.1", - "@lexical/rich-text": "0.16.1", - "@lexical/selection": "0.16.1", - "@lexical/table": "0.16.1", - "@lexical/text": "0.16.1", - "@lexical/utils": "0.16.1", - "@lexical/yjs": "0.16.1", - "lexical": "0.16.1", - "react-error-boundary": "^3.1.4" - }, - "peerDependencies": { - "react": ">=17.x", - "react-dom": ">=17.x" - } - }, - "node_modules/@lexical/rich-text": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@lexical/rich-text/-/rich-text-0.16.1.tgz", - "integrity": "sha512-4uEVXJur7tdSbqbmsToCW4YVm0AMh4y9LK077Yq2O9hSuA5dqpI8UbTDnxZN2D7RfahNvwlqp8eZKFB1yeiJGQ==", - "dependencies": { - "@lexical/clipboard": "0.16.1", - "@lexical/selection": "0.16.1", - "@lexical/utils": "0.16.1", - "lexical": "0.16.1" - } - }, - "node_modules/@lexical/selection": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@lexical/selection/-/selection-0.16.1.tgz", - "integrity": "sha512-+nK3RvXtyQvQDq7AZ46JpphmM33pwuulwiRfeXR5T9iFQTtgWOEjsAi/KKX7vGm70BxACfiSxy5QCOgBWFwVJg==", - "dependencies": { - "lexical": "0.16.1" - } - }, - "node_modules/@lexical/table": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@lexical/table/-/table-0.16.1.tgz", - "integrity": "sha512-GWb0/MM1sVXpi1p2HWWOBldZXASMQ4c6WRNYnRmq7J/aB5N66HqQgJGKp3m66Kz4k1JjhmZfPs7F018qIBhnFQ==", - "dependencies": { - "@lexical/utils": "0.16.1", - "lexical": "0.16.1" - } - }, - "node_modules/@lexical/text": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@lexical/text/-/text-0.16.1.tgz", - "integrity": "sha512-Os/nKQegORTrKKN6vL3/FMVszyzyqaotlisPynvTaHTUC+yY4uyjM2hlF93i5a2ixxyiPLF9bDroxUP96TMPXg==", - "dependencies": { - "lexical": "0.16.1" - } - }, - "node_modules/@lexical/utils": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@lexical/utils/-/utils-0.16.1.tgz", - "integrity": "sha512-BVyJxDQi/rIxFTDjf2zE7rMDKSuEaeJ4dybHRa/hRERt85gavGByQawSLeQlTjLaYLVsy+x7wCcqh2fNhlLf0g==", - "dependencies": { - "@lexical/list": "0.16.1", - "@lexical/selection": "0.16.1", - "@lexical/table": "0.16.1", - "lexical": "0.16.1" - } - }, - "node_modules/@lexical/yjs": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@lexical/yjs/-/yjs-0.16.1.tgz", - "integrity": "sha512-QHw1bmzB/IypIV1tRWMH4hhwE1xX7wV+HxbzBS8oJAkoU5AYXM/kyp/sQicgqiwVfpai1Px7zatOoUDFgbyzHQ==", - "dependencies": { - "@lexical/offset": "0.16.1", - "lexical": "0.16.1" - }, - "peerDependencies": { - "yjs": ">=13.5.22" - } - }, "node_modules/@lezer/common": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz", @@ -7037,6 +6803,16 @@ "resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-2.0.2.tgz", "integrity": "sha512-dyHY+sMF0ihPus3O27ODd4+agdHMEmuRdyiZJ2CCWjPV5UFmn17ZbElvk6WOGVE4rdCJKZQCrPV2BcikOMLUGQ==" }, + "node_modules/@replit/codemirror-indentation-markers": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/@replit/codemirror-indentation-markers/-/codemirror-indentation-markers-6.5.3.tgz", + "integrity": "sha512-hL5Sfvw3C1vgg7GolLe/uxX5T3tmgOA3ZzqlMv47zjU1ON51pzNWiVbS22oh6crYhtVhv8b3gdXwoYp++2ilHw==", + "peerDependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0" + } + }, "node_modules/@replit/codemirror-lang-csharp": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/@replit/codemirror-lang-csharp/-/codemirror-lang-csharp-6.2.0.tgz", @@ -15740,11 +15516,6 @@ "node": ">= 0.8.0" } }, - "node_modules/lexical": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/lexical/-/lexical-0.16.1.tgz", - "integrity": "sha512-+R05d3+N945OY8pTUjTqQrWoApjC+ctzvjnmNETtx9WmVAaiW0tQVG+AYLt5pDGY8dQXtd4RPorvnxBTECt9SA==" - }, "node_modules/lib0": { "version": "0.2.94", "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.94.tgz", @@ -20886,14 +20657,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/prismjs": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", - "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", - "engines": { - "node": ">=6" - } - }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -21202,21 +20965,6 @@ "react": "^18.3.1" } }, - "node_modules/react-error-boundary": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-3.1.4.tgz", - "integrity": "sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==", - "dependencies": { - "@babel/runtime": "^7.12.5" - }, - "engines": { - "node": ">=10", - "npm": ">=6" - }, - "peerDependencies": { - "react": ">=16.13.1" - } - }, "node_modules/react-icons": { "version": "4.12.0", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.12.0.tgz", diff --git a/package.json b/package.json index 6f22eca6..3300f563 100644 --- a/package.json +++ b/package.json @@ -30,12 +30,11 @@ "@aws-sdk/client-s3": "^3.540.0", "@blocknote/core": "^0.12.1", "@blocknote/react": "^0.12.2", + "@codemirror/lang-json": "^6.0.1", "@codemirror/lang-sql": "^6.5.5", "@dnd-kit/core": "^6.1.0", "@dnd-kit/sortable": "^8.0.0", "@justmiracle/result": "^1.2.0", - "@lexical/markdown": "^0.16.1", - "@lexical/react": "^0.16.1", "@lezer/common": "^1.2.1", "@lezer/lr": "^1.4.0", "@libsql/client": "^0.5.3", @@ -63,6 +62,7 @@ "@radix-ui/react-toggle": "^1.0.3", "@radix-ui/react-toggle-group": "^1.0.4", "@radix-ui/react-tooltip": "^1.0.7", + "@replit/codemirror-indentation-markers": "^6.5.3", "@silevis/reactgrid": "^4.1.3", "@t3-oss/env-nextjs": "^0.9.2", "@tiptap/core": "^2.3.0", @@ -83,7 +83,6 @@ "drizzle-orm": "^0.30.1", "eslint-plugin-jest": "^27.6.3", "file-saver": "^2.0.5", - "lexical": "^0.16.1", "libsql-stateless-easy": "^1.6.11", "lucia": "^3.2.0", "lucide-react": "^0.309.0", diff --git a/src/app/testing/page.tsx b/src/app/testing/page.tsx index d8172b17..6a2973a1 100644 --- a/src/app/testing/page.tsx +++ b/src/app/testing/page.tsx @@ -1,9 +1,27 @@ -import MarkdownEditor from "@/components/markdown-editor"; +"use client"; +import JsonEditor from "@/components/gui/json-editor"; +import ThemeProvider from "@/context/theme-provider"; +import { useState } from "react"; export default function TestingPage() { + const [code, setCode] = useState( + JSON.stringify( + { + name: "Visal", + country: { + id: 1, + verified: true, + name: "Cambodia", + }, + }, + undefined, + 2 + ) + ); + return ( -
- -
+ + + ); } diff --git a/src/components/gui/json-editor/index.tsx b/src/components/gui/json-editor/index.tsx new file mode 100644 index 00000000..60d87391 --- /dev/null +++ b/src/components/gui/json-editor/index.tsx @@ -0,0 +1,102 @@ +import CodeMirror, { ReactCodeMirrorRef } from "@uiw/react-codemirror"; +import { json } from "@codemirror/lang-json"; +import { forwardRef, useMemo } from "react"; +import { tags as t } from "@lezer/highlight"; +import createTheme from "@uiw/codemirror-themes"; +import { useTheme } from "@/context/theme-provider"; +import { indentationMarkers } from "@replit/codemirror-indentation-markers"; + +interface JsonEditorProps { + value: string; + readOnly?: boolean; + onChange?: (value: string) => void; +} + +function useJsonTheme() { + const { theme } = useTheme(); + + return useMemo(() => { + if (theme === "light") { + return createTheme({ + theme: "light", + settings: { + background: "#FFFFFF", + foreground: "#000000", + caret: "#FBAC52", + selection: "#FFD420", + selectionMatch: "#FFD420", + gutterBackground: "#fff", + gutterForeground: "#4D4D4C", + gutterBorder: "transparent", + lineHighlight: "#00000012", + fontFamily: + 'Consolas, "Andale Mono", "Ubuntu Mono", "Courier New", monospace', + }, + styles: [ + { tag: [t.propertyName], color: "#4078F2" }, + { tag: [t.bool, t.null], color: "#696C77" }, + { tag: [t.number], color: "#FF0080" }, + { tag: [t.string], color: "#50A14F" }, + { tag: [t.separator], color: "#383A42" }, + { tag: [t.squareBracket], color: "#383A42" }, + { tag: [t.brace], color: "#A626A4" }, + ], + }); + } else { + return createTheme({ + theme: "dark", + settings: { + background: "var(--background)", + foreground: "#9cdcfe", + caret: "#c6c6c6", + selection: "#6199ff2f", + selectionMatch: "#72a1ff59", + lineHighlight: "#ffffff0f", + gutterBackground: "var(--background)", + gutterForeground: "#838383", + gutterActiveForeground: "#fff", + fontFamily: + 'Consolas, "Andale Mono", "Ubuntu Mono", "Courier New", monospace', + }, + styles: [ + { tag: [t.propertyName], color: "#4078F2" }, + { tag: [t.bool, t.null], color: "#696C77" }, + { tag: [t.number], color: "#f39c12" }, + { tag: [t.string], color: "#50A14F" }, + { tag: [t.separator], color: "#383A42" }, + { tag: [t.squareBracket], color: "#383A42" }, + { tag: [t.brace], color: "#A626A4" }, + ], + }); + } + }, [theme]); +} + +const JsonEditor = forwardRef( + function SqlEditor({ value, onChange, readOnly }: JsonEditorProps, ref) { + const theme = useJsonTheme(); + + return ( + + ); + } +); + +export default JsonEditor; diff --git a/src/components/gui/providers/full-editor-provider.tsx b/src/components/gui/providers/full-editor-provider.tsx index 27777678..4b331724 100644 --- a/src/components/gui/providers/full-editor-provider.tsx +++ b/src/components/gui/providers/full-editor-provider.tsx @@ -17,6 +17,7 @@ import { useMemo, useState, } from "react"; +import JsonEditor from "../json-editor"; interface FullEditorContextValue { openEditor: (option: FullEditorOption) => void; @@ -25,6 +26,8 @@ interface FullEditorContextValue { interface FullEditorOption { initialValue: string; + format: string; + readOnly?: boolean; onSave: (value: string) => void; onCancel: () => void; } @@ -35,47 +38,67 @@ const FullEditorContext = createContext({ }); function FullEditorSheet({ option }: { option: FullEditorOption }) { - const [value, setValue] = useState(option.initialValue); + const [value, setValue] = useState(() => { + if (option.format === "json") { + try { + return JSON.stringify(JSON.parse(option.initialValue), undefined, 2); + } catch { + return option.initialValue; + } + } + + return option.initialValue; + }); return ( -
+
-
- -
-