From 4cf5364443d7a1e776149cda5a9aea574fc3072e Mon Sep 17 00:00:00 2001 From: Morlay Date: Tue, 6 Aug 2024 18:54:16 +0800 Subject: [PATCH] feat: json editor --- bun.lockb | Bin 217318 -> 217892 bytes .../vue-vite-presets/src/chunkCleanup.ts | 14 +- nodedevpkg/vue-vite-presets/src/mdx/index.tsx | 50 ++-- nodedevpkg/vue-vite-presets/src/viteVue.ts | 14 +- .../src/vue/componentCompleter.ts | 17 +- .../vue-vite-presets/src/vue/componentHMR.ts | 19 +- nodepkg/csstype/package.json | 2 +- nodepkg/gents/src/__tests__/client/example.ts | 4 +- nodepkg/jsoneditor/package.json | 51 ++++ nodepkg/jsoneditor/src/JSONEditorView.tsx | 102 +++++++ nodepkg/jsoneditor/src/JSONPointer.ts | 26 ++ nodepkg/jsoneditor/src/index.ts | 3 + nodepkg/jsoneditor/src/models/JSONEditor.tsx | 46 +++ nodepkg/jsoneditor/src/models/index.ts | 1 + nodepkg/jsoneditor/src/views/Actions.tsx | 56 ++++ nodepkg/jsoneditor/src/views/ArrayInput.tsx | 126 ++++++++ nodepkg/jsoneditor/src/views/BooleanInput.tsx | 48 ++++ nodepkg/jsoneditor/src/views/EnumInput.tsx | 50 ++++ nodepkg/jsoneditor/src/views/Form.tsx | 45 +++ nodepkg/jsoneditor/src/views/JSONRaw.tsx | 116 ++++++++ nodepkg/jsoneditor/src/views/Menu.tsx | 147 ++++++++++ nodepkg/jsoneditor/src/views/NumberInput.tsx | 122 ++++++++ nodepkg/jsoneditor/src/views/ObjectInput.tsx | 185 ++++++++++++ nodepkg/jsoneditor/src/views/RecordInput.tsx | 224 +++++++++++++++ nodepkg/jsoneditor/src/views/StringInput.tsx | 111 ++++++++ nodepkg/jsoneditor/src/views/TokenView.tsx | 269 ++++++++++++++++++ nodepkg/jsoneditor/src/views/Tooltip.tsx | 71 +++++ nodepkg/jsoneditor/src/views/index.ts | 10 + nodepkg/jsoneditor/tsconfig.monobundle.json | 6 + nodepkg/typedef/package.json | 2 +- nodepkg/typedef/src/core/TypeBoolean.ts | 2 +- nodepkg/typedef/src/core/TypeInteger.ts | 2 +- nodepkg/typedef/src/core/TypeNumber.ts | 2 +- .../typedef/src/encoding/TypeScriptEncoder.ts | 12 +- .../__snapshots__/index.spec.ts.snap | 6 +- nodepkg/vuekit/src/component.ts | 41 +-- nodepkg/vuekit/src/reactive/RxSlot.tsx | 8 +- nodepkg/vuekit/src/reactive/component$.tsx | 38 +-- nodepkg/vuekit/src/vue.ts | 26 +- .../src/Buttons/ElevatedButton.tsx | 22 +- .../vuematerial/src/Buttons/FilledButton.tsx | 18 +- .../vuematerial/src/Buttons/IconButton.tsx | 2 +- nodepkg/vuematerial/src/Icons/Icon.tsx | 14 +- nodepkg/vuematerial/src/Overlays/Dialog.tsx | 28 +- nodepkg/vueuikit/example/color-palette.tsx | 15 +- nodepkg/vueuikit/src/Popper.tsx | 44 +-- nodepkg/vueuikit/src/styled.tsx | 154 +++++----- nodepkg/vueuikit/src/theming/m3/index.ts | 4 +- nodepkg/vueuikit/src/theming/m3/palette.ts | 130 +++++---- .../vueuikit/src/theming/token/DesignToken.ts | 66 ++--- .../common/manifest/index.ts | 6 +- .../mod/openapi/RequestBuilder.tsx | 6 +- .../mod/openapi/SchemaView.tsx | 117 ++++---- .../mod/openapi/components/JSONCueEditor.tsx | 138 --------- .../mod/openapi/components/JSONEditor.tsx | 45 +++ 55 files changed, 2315 insertions(+), 568 deletions(-) create mode 100644 nodepkg/jsoneditor/package.json create mode 100644 nodepkg/jsoneditor/src/JSONEditorView.tsx create mode 100644 nodepkg/jsoneditor/src/JSONPointer.ts create mode 100644 nodepkg/jsoneditor/src/index.ts create mode 100644 nodepkg/jsoneditor/src/models/JSONEditor.tsx create mode 100644 nodepkg/jsoneditor/src/models/index.ts create mode 100644 nodepkg/jsoneditor/src/views/Actions.tsx create mode 100644 nodepkg/jsoneditor/src/views/ArrayInput.tsx create mode 100644 nodepkg/jsoneditor/src/views/BooleanInput.tsx create mode 100644 nodepkg/jsoneditor/src/views/EnumInput.tsx create mode 100644 nodepkg/jsoneditor/src/views/Form.tsx create mode 100644 nodepkg/jsoneditor/src/views/JSONRaw.tsx create mode 100644 nodepkg/jsoneditor/src/views/Menu.tsx create mode 100644 nodepkg/jsoneditor/src/views/NumberInput.tsx create mode 100644 nodepkg/jsoneditor/src/views/ObjectInput.tsx create mode 100644 nodepkg/jsoneditor/src/views/RecordInput.tsx create mode 100644 nodepkg/jsoneditor/src/views/StringInput.tsx create mode 100644 nodepkg/jsoneditor/src/views/TokenView.tsx create mode 100644 nodepkg/jsoneditor/src/views/Tooltip.tsx create mode 100644 nodepkg/jsoneditor/src/views/index.ts create mode 100644 nodepkg/jsoneditor/tsconfig.monobundle.json delete mode 100644 webapp/openapi-playground/mod/openapi/components/JSONCueEditor.tsx create mode 100644 webapp/openapi-playground/mod/openapi/components/JSONEditor.tsx diff --git a/bun.lockb b/bun.lockb index 01bc7b98cf321da747376e28c6cb01b39ddae098..546559de728144a0fc6a60c5144b1b9965d74079 100755 GIT binary patch delta 34910 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

nRuW-;z-nlMW-N~!XU44qS)k!dGfscZ>U z9S8K6C}EWc^x{wm2lRF0weU`y@!_i+HkYCgM&-Q!lcJr1YcW+G+-os7xF0&}Q3v;$ zMhG3;)4|GKK-FjVnx1xMFD%htp4{*1t6S#(v)J2VNtI{$T6&!2htGc0S-z&Bo#lIp zQ#7`6Hm1Mz?7(aocZ|I=8~eng>^{M97BL6HWh@!s8yir?Njp|4d`&Na+2&v@YA5b> z12x%sX#bDHaV-Xi{_jKEM;2$`uAYfEHtwJFmUhIgX=q3GUU+uzGZ*Dnd1$Zc-S=m` z=i>1}m8a>NMwQ3tTFgAQ0h#-R2_tfbZ+&on`HMIO#xo2}L3aquO@%X?U zb)pmVN)ID6q>qypucADW_)JmJCVIi+6)~X9v9haANwA~$uBa~ ze6%oswjHDY+eF@)Gj1~%^kD9C@G8FW@pscow%0#NyjA?wbh_UZ=Xx2eWIi0Izi=?| z{OhIHUTtsy3OH`01IHrvDiq|otZcs0IpL|*d}7dFXt?c(NfW33KG;ti>iBL$E9qxw z(1FP8gIQ;qwN80avl%NjzWBA84OxKE-CBmat0X?FQ3fCO+Xlt9W zD@aPq`@fKraw(U!Sco30eO17d4OytvHASrD7K+W=3rt;z8LA&EC(urud*aTCRwsS# zV+R*u=qzKW@N}W-;h}v;;by?<636J!L{*LsEe4~b7qqJ$9h$~aR$KzVZe{BLRgVr$ z52NEOa;kcCXc|?H4lQOL^IQC=(V;1?b*_DEV+T*xd>q0aj2mG4f8{?_*L_4S&9_OM2KA0)ba z%+1wXr=9#fA2CQs7JtZ=AgPc30?DtQX>mnO+BZNbU?e2<-sJb2@&V@1C>yuF7_Sczsk!AbzW`s+ViF4%Qq{nPE3L+|z; zc6=p#U+J`=s{2uH8;?28maanPmG9?;@l^>aRlTat0EA~n-Z&|Umc!ZI)yP|%&G49* zozL*?z*AeE?SFs98F~&Q&cXil`HC=097(_%j;)p3 zC%b%mBI3v7CRo{Hv`0+hJ90jc{$|i%wy6|@SAS8e`9#U{t2>p`LL-iJ^mnUTcHFoZ z*)aEK#Ng|B^z85z_AQe7JVF7>Vt*F67S0^a;sJU!SngWIyZYB_U^6b`TDD@XGHJy7 z_+~4Vl`oyxSViI~h>;QPAZu_QX0R0f(}?*D3yO&fv+KJEGrS z^z6OYd#CRB6g(}+Ulh&Cb|2O4(hcym{n*RBE(SF6evHAu2O+H** zli8^rPL0_QJ)D}bfSyiWt1qMfgTU3Q*U^HWPLVSG!=@a7_hmId>YU>Aq+ESCeLWu6 z*<4^QZ$SSxfolOChom|sSoJT+>R*S|zvoMLYi_7fe_(B({*7Jj`?=tc zi}){q { const isJSOrLike = createFilter([ /\.vue$/, /\.mdx$/, /\.tsx?$/, /\.mjs$/, - /\.jsx?$/ + /\.jsx?$/, ]); return { @@ -50,13 +50,13 @@ export const chunkCleanup = ( const result = await transform(code, { filename: id, env: opt.env ?? { targets: "defaults" }, - minify: false + minify: false, }); return ( result.code && { code: result.code, - map: result.map || null + map: result.map || null, } ); }, @@ -65,11 +65,9 @@ export const chunkCleanup = ( return ( await transform(code, { minify: opt.minify ?? false, - plugins: [ - usePlugin({}) - ] + plugins: [usePlugin({})], }) ).code; - } + }, }; }; diff --git a/nodedevpkg/vue-vite-presets/src/mdx/index.tsx b/nodedevpkg/vue-vite-presets/src/mdx/index.tsx index 87d6e08b..fd03c213 100644 --- a/nodedevpkg/vue-vite-presets/src/mdx/index.tsx +++ b/nodedevpkg/vue-vite-presets/src/mdx/index.tsx @@ -43,31 +43,31 @@ export const mdx = (): PluginOption => { const rawCode = children[0].value; const exportName = `CodeBlock${getHash( - `${metadata["filename"] ?? pos}` + `${metadata["filename"] ?? pos}`, )}`; const id = vc.store(`${mdxFile}~${exportName}.tsx`, rawCode); additionalImports.set(mdxFile, { ...(additionalImports.get(mdxFile) ?? {}), - [id]: exportName + [id]: exportName, }); tree.children[pos] = h( "div", { - "data-example": "" + "data-example": "", }, [ h( "div", { - "data-example-container": "" + "data-example-container": "", }, - h(exportName) + h(exportName), ), - pre - ] + pre, + ], ); } } @@ -80,7 +80,7 @@ export const mdx = (): PluginOption => { include: [/\.mdx?$/], jsxRuntime: "automatic", jsxImportSource: "@innoai-tech/vuekit", - rehypePlugins: [rehypeRenderCodeBlock, rehypePrism] + rehypePlugins: [rehypeRenderCodeBlock, rehypePrism], }); return { @@ -114,36 +114,36 @@ export const mdx = (): PluginOption => { ...ret, code: ` ${Object.keys(codeBlockImports) - .map( - (importPath) => ` -import ${codeBlockImports[importPath]} from ${JSON.stringify(importPath)}` - ) - .join(";\n")} + .map( + (importPath) => ` +import ${codeBlockImports[importPath]} from ${JSON.stringify(importPath)}`, + ) + .join(";\n")} import { defineComponent, h } from "vue" ${ret.code.replace( - "export default function MDXContent(", - "function MDXContent(" - )} + "export default function MDXContent(", + "function MDXContent(", +)} export default defineComponent(() => { return () => h(MDXContent, { components: { ${Object.keys(codeBlockImports) - .map( - (importPath) => - `${codeBlockImports[importPath]?.toLowerCase()}: ${ - codeBlockImports[importPath] - }` - ) - .join(",\n")} + .map( + (importPath) => + `${codeBlockImports[importPath]?.toLowerCase()}: ${ + codeBlockImports[importPath] + }`, + ) + .join(",\n")} } }) }) -` +`, }; } - } + }, }; }; diff --git a/nodedevpkg/vue-vite-presets/src/viteVue.ts b/nodedevpkg/vue-vite-presets/src/viteVue.ts index b7c216b3..55d038cb 100644 --- a/nodedevpkg/vue-vite-presets/src/viteVue.ts +++ b/nodedevpkg/vue-vite-presets/src/viteVue.ts @@ -2,10 +2,14 @@ import vue from "@vitejs/plugin-vue"; import type { PluginOption } from "vite"; import vitePages, { type PageResolver, - type PageOptions + type PageOptions, } from "vite-plugin-pages"; import { mdx } from "./mdx"; -import { createPageMetaResolver, viteVueComponentCompleter, viteVueComponentHMR } from "./vue"; +import { + createPageMetaResolver, + viteVueComponentCompleter, + viteVueComponentHMR, +} from "./vue"; export interface ViteReactOptions { pagesDirs?: string | (string | PageOptions)[]; @@ -27,8 +31,8 @@ export const viteVue = (options: ViteReactOptions = {}): PluginOption[] => { onRoutesGenerated: r.onRoutesGenerated, resolver: { ...r.pagesResolver, - ...options.pagesResolver - } - }) as PluginOption + ...options.pagesResolver, + }, + }) as PluginOption, ]; }; diff --git a/nodedevpkg/vue-vite-presets/src/vue/componentCompleter.ts b/nodedevpkg/vue-vite-presets/src/vue/componentCompleter.ts index 0bd46d69..b9e1217f 100644 --- a/nodedevpkg/vue-vite-presets/src/vue/componentCompleter.ts +++ b/nodedevpkg/vue-vite-presets/src/vue/componentCompleter.ts @@ -2,18 +2,17 @@ import { type Plugin, createFilter } from "vite"; import { usePlugin } from "@innoai-tech/vuecomponentcompleter"; import { transform } from "@swc/core"; - export interface ComponentCompleterOptions { include?: string[]; exclude?: string[]; } export const viteVueComponentCompleter = ( - options: ComponentCompleterOptions = {} + options: ComponentCompleterOptions = {}, ): Plugin => { const filter = createFilter( options.include || [/\.tsx$/, /\.mdx?$/], - options.exclude + options.exclude, ); return { @@ -34,24 +33,24 @@ export const viteVueComponentCompleter = ( externalHelpers: false, parser: { syntax: "typescript", - tsx: true + tsx: true, }, experimental: { disableBuiltinTransformsForInternalTesting: true, - plugins: [usePlugin({})] - } - } + plugins: [usePlugin({})], + }, + }, }); return ( result.code && { code: result.code, - map: result.map || null + map: result.map || null, } ); } return null; - } + }, }; }; diff --git a/nodedevpkg/vue-vite-presets/src/vue/componentHMR.ts b/nodedevpkg/vue-vite-presets/src/vue/componentHMR.ts index 1772fce9..e9a5d0c0 100644 --- a/nodedevpkg/vue-vite-presets/src/vue/componentHMR.ts +++ b/nodedevpkg/vue-vite-presets/src/vue/componentHMR.ts @@ -18,12 +18,10 @@ export interface Module { exports: Map; } -export const viteVueComponentHMR = ( - options: VueJsxHmrOptions = {} -): Plugin => { +export const viteVueComponentHMR = (options: VueJsxHmrOptions = {}): Plugin => { const filter = createFilter( options.include || [/\.tsx$/, /\.mdx?$/], - options.exclude + options.exclude, ); let hmrEnabled = false; @@ -50,7 +48,7 @@ export const viteVueComponentHMR = ( } return null; - } + }, }; }; @@ -80,7 +78,6 @@ ${callbackBlock} return code; } - export const exportScanner = (id: string, filename = id) => { const re = /export (const (?\w+) =|default) (?(styled|component\$?)\()/; @@ -89,7 +86,7 @@ export const exportScanner = (id: string, filename = id) => { scan(code: string): Module { const ret = { code: "", - exports: new Map() + exports: new Map(), }; let src = code; let m: RegExpMatchArray | null = null; @@ -108,11 +105,13 @@ export const exportScanner = (id: string, filename = id) => { const local = exported !== "default" ? exported - : upperFirst(camelCase(`${basename(filename, extname(filename))}Default`)); + : upperFirst( + camelCase(`${basename(filename, extname(filename))}Default`), + ); const range = { start: m.index ?? 0, - length: m[0].length + length: m[0].length, }; ret.exports.set(local, { exported, id: getHash(`${id}#${exported}`) }); @@ -143,6 +142,6 @@ export { ${nonDefaultExports.join(", ")} } } return ret; - } + }, }; }; diff --git a/nodepkg/csstype/package.json b/nodepkg/csstype/package.json index e0ae17b3..d755e4e3 100644 --- a/nodepkg/csstype/package.json +++ b/nodepkg/csstype/package.json @@ -19,4 +19,4 @@ "sideEffects": false, "type": "module", "types": "index.d.ts" -} +} \ No newline at end of file diff --git a/nodepkg/gents/src/__tests__/client/example.ts b/nodepkg/gents/src/__tests__/client/example.ts index a0c540e5..07be5296 100644 --- a/nodepkg/gents/src/__tests__/client/example.ts +++ b/nodepkg/gents/src/__tests__/client/example.ts @@ -204,8 +204,8 @@ manifest = "manifest" export const displayKubepkgV1Alpha1DigestMetaType = (v: KubepkgV1Alpha1DigestMetaType) => { return ({ -blob: "Blob", -manifest: "Manifest" +"blob": "Blob", +"manifest": "Manifest" })[v] ?? v } diff --git a/nodepkg/jsoneditor/package.json b/nodepkg/jsoneditor/package.json new file mode 100644 index 00000000..3101ec15 --- /dev/null +++ b/nodepkg/jsoneditor/package.json @@ -0,0 +1,51 @@ +{ + "name": "@innoai-tech/jsoneditor", + "version": "0.1.4", + "monobundle": { + "build": { + "clean": true + }, + "exports": { + ".": "./src/index.ts" + } + }, + "dependencies": { + "@innoai-tech/vuekit": "workspace:^", + "@innoai-tech/vuemarkdown": "workspace:^", + "@innoai-tech/vuematerial": "workspace:^", + "@innoai-tech/vueuikit": "workspace:^", + "@mdi/js": "^7.4.47", + "copy-to-clipboard": "^3.3.3" + }, + "peerDependencies": {}, + "exports": { + ".": { + "bun": "./src/index.ts", + "import": { + "types": "./src/index.ts", + "default": "./dist/index.mjs" + } + } + }, + "files": [ + "dist/*", + "src/*", + "!/**/__tests__" + ], + "license": "MIT", + "publishConfig": { + "registry": "https://npm.pkg.github.com", + "access": "public" + }, + "repository": { + "type": "git", + "url": "ssh://git@github.com:innoai-tech/vuekit.git", + "directory": "nodepkg/jsoneditor" + }, + "scripts": { + "lint": "bunx --bun prettier --write . ", + "build": "bunx --bun monobundle", + "prepublishOnly": "bun run build" + }, + "type": "module" +} diff --git a/nodepkg/jsoneditor/src/JSONEditorView.tsx b/nodepkg/jsoneditor/src/JSONEditorView.tsx new file mode 100644 index 00000000..d7bf3bc9 --- /dev/null +++ b/nodepkg/jsoneditor/src/JSONEditorView.tsx @@ -0,0 +1,102 @@ +import { + type AnyType, + component$, + type Context, + EmptyContext, + rx, +} from "@innoai-tech/vuekit"; +import { JSONEditorProvider, JSONEditorSlotsProvider } from "./models"; +import { + ObjectInput, + ArrayInput, + RecordInput, + EnumInput, + NumberInput, + BooleanInput, + StringInput, + LayoutContextProvider, + Line, +} from "./views"; +import { styled } from "@innoai-tech/vueuikit"; +import { ref } from "vue"; + +export const JSONEditorView = component$(({}, { render }) => { + const editor$ = JSONEditorProvider.use(); + + const renderValues = (typedef: AnyType, value: any, ctx: Context) => { + if ( + typedef.type == "object" || + typedef.type == "intersection" || + typedef.type == "union" + ) { + return ; + } + + if (typedef.type == "record") { + return ; + } + + if (typedef.type == "array") { + return ; + } + + if (typedef.type == "enums") { + return ; + } + + if (typedef.type == "string") { + return ; + } + + if (typedef.type == "number" || typedef.type == "integer") { + return ; + } + + if (typedef.type == "boolean") { + return ; + } + + return null; + }; + + const $container = ref(null); + + return rx( + editor$, + render((root: any) => { + return ( + + +

+ {$container.value && ( + + {renderValues(editor$.typedef, root, EmptyContext)} + + )} + + + ); + }), + ); +}); + +const JSONEditorContainer = styled("div")({ + width: "100%", + height: "100%", + overflow: "auto", + + section: { + display: "flex", + flexDirection: "column", + minWidth: "max-content", + }, +}); diff --git a/nodepkg/jsoneditor/src/JSONPointer.ts b/nodepkg/jsoneditor/src/JSONPointer.ts new file mode 100644 index 00000000..2e7d0d57 --- /dev/null +++ b/nodepkg/jsoneditor/src/JSONPointer.ts @@ -0,0 +1,26 @@ +export class JSONPointer { + static parse(pointer: string): any[] { + if (pointer === "") { + return []; + } + if (pointer.charAt(0) !== "/") { + throw new Error("Invalid JSON pointer: " + pointer); + } + return pointer.substring(1).split(/\//).map(JSONPointer.unescape); + } + + static compile(keyPath: any[]) { + if (keyPath.length === 0) { + return ""; + } + return "/" + keyPath.map(JSONPointer.escape).join("/"); + } + + static unescape(str: string) { + return str.replace(/~1/g, "/").replace(/~0/g, "~"); + } + + static escape(str: string) { + return str.toString().replace(/~/g, "~0").replace(/\//g, "~1"); + } +} diff --git a/nodepkg/jsoneditor/src/index.ts b/nodepkg/jsoneditor/src/index.ts new file mode 100644 index 00000000..0aad583e --- /dev/null +++ b/nodepkg/jsoneditor/src/index.ts @@ -0,0 +1,3 @@ +export * from "./models"; +export * from "./JSONEditorView.tsx"; +export * from "./JSONPointer.ts"; diff --git a/nodepkg/jsoneditor/src/models/JSONEditor.tsx b/nodepkg/jsoneditor/src/models/JSONEditor.tsx new file mode 100644 index 00000000..512d6048 --- /dev/null +++ b/nodepkg/jsoneditor/src/models/JSONEditor.tsx @@ -0,0 +1,46 @@ +import { + type AnyType, + type Context, + createProvider, + ImmerBehaviorSubject, + type Infer, + t, + Type, +} from "@innoai-tech/vuekit"; +import { get, isPlainObject, isUndefined } from "@innoai-tech/lodash"; + +export class JSONEditor extends ImmerBehaviorSubject> { + static of(typedef: T, initials?: Partial>) { + return new JSONEditor( + typedef, + initials ?? (typedef.type == "array" ? [] : {}), + ); + } + + constructor( + public typedef: T, + protected initials: Infer, + ) { + super(initials); + } + + isDirty(value: any, path: any[]) { + if (!isPlainObject(value)) { + const v = get(this.initials, path); + + return isUndefined(v) || v !== value; + } + return false; + } +} + +export const JSONEditorProvider = createProvider( + () => new JSONEditor(t.object(), {}), +); + +export const JSONEditorSlotsProvider = createProvider(() => { + return { + render: (_t: AnyType, _value: any, _ctx: Context): JSX.Element | null => + null, + }; +}); diff --git a/nodepkg/jsoneditor/src/models/index.ts b/nodepkg/jsoneditor/src/models/index.ts new file mode 100644 index 00000000..8fbfc9bd --- /dev/null +++ b/nodepkg/jsoneditor/src/models/index.ts @@ -0,0 +1 @@ +export * from "./JSONEditor.tsx"; diff --git a/nodepkg/jsoneditor/src/views/Actions.tsx b/nodepkg/jsoneditor/src/views/Actions.tsx new file mode 100644 index 00000000..60d8ae19 --- /dev/null +++ b/nodepkg/jsoneditor/src/views/Actions.tsx @@ -0,0 +1,56 @@ +import { styled } from "@innoai-tech/vueuikit"; +import type { VNodeChild } from "@innoai-tech/vuekit"; + +const ActionToolbar = styled("span")({ + pos: "relative", + px: 8, + display: "flex", + alignItems: "center", + gap: 8 +}); + +export const Actions = styled< + { + $default?: VNodeChild; + }, + "span" +>("span", ({}, { slots }) => { + return (Root) => ( + + {slots.default?.()} + + ); +})({ + flex: 1, + lineHeight: 18, + + wordBreak: "keep-all", + whiteSpace: "nowrap", + display: "inline-flex", + alignItems: "center", + + [`& ${ActionToolbar}`]: { + visibility: "hidden" + }, + + _hover: { + [`& ${ActionToolbar}`]: { + visibility: "visible" + } + } +}); + +export const ActionBtn = styled("span")({ + display: "flex", + alignItems: "center", + justifyContent: "center", + height: 16, + width: 16, + opacity: 0.5, + cursor: "pointer", + textStyle: "sys.label-small", + + _hover: { + opacity: 0.8 + } +}); diff --git a/nodepkg/jsoneditor/src/views/ArrayInput.tsx b/nodepkg/jsoneditor/src/views/ArrayInput.tsx new file mode 100644 index 00000000..f20859f5 --- /dev/null +++ b/nodepkg/jsoneditor/src/views/ArrayInput.tsx @@ -0,0 +1,126 @@ +import { + type AnyType, + component$, + type Context, + rx, + type VNodeChild +} from "@innoai-tech/vuekit"; +import { get, set } from "@innoai-tech/lodash"; +import { Icon } from "@innoai-tech/vuematerial"; +import { mdiMinusBoxOutline, mdiPlusBoxOutline } from "@mdi/js"; +import { Block, Line, PropName } from "./TokenView.tsx"; +import { JSONEditorProvider, JSONEditorSlotsProvider } from "../models"; +import { ActionBtn, Actions } from "./Actions.tsx"; +import { CopyAsJSONIconBtn, InputFromJSONRawIconBtn } from "./JSONRaw.tsx"; +import { Tooltip } from "./Tooltip.tsx"; + + +export const ArrayInput = component$<{ + ctx: Context; + value: []; + typedef: AnyType; +}>((props, { render }) => { + const editor$ = JSONEditorProvider.use(); + const slots = JSONEditorSlotsProvider.use(); + + return rx( + props.value$, + render((obj) => { + return ( + + { + editor$.next((values: any) => { + const arr = get(values, props.ctx.path, []); + + set(values, props.ctx.path, [...arr, undefined]); + }); + }} + /> + + { + editor$.next((values: any) => { + if (props.ctx.path.length) { + set(values, props.ctx.path, updated); + } else { + Object.assign(values, updated); + } + }); + }} + /> + + } + > + {[...props.typedef.entries(obj, props.ctx)].map( + ([idx, itemValue, propSchema]) => { + const path = [...props.ctx.path, idx]; + + return ( + + { + editor$.next((values: any) => { + let arr = get(values, props.ctx.path, [] as any[]); + + set( + values, + props.ctx.path, + arr.filter((_: any, i: number) => i !== idx) + ); + }); + }} + /> + } + > + {String(idx)} + + {slots.render(propSchema, itemValue, { + ...props.ctx, + path: path, + branch: [...props.ctx.branch, itemValue] + })} + + ); + } + )} + + ); + }) + ); +}); + +const AddItemIconBtn = component$<{ + $default?: VNodeChild; + onAdd?: () => void; +}>(({}, { emit }) => { + return () => ( + + emit("add")}> + + + + ); +}); + +const RemoteItemIconBtn = component$<{ + $default?: VNodeChild; + onRemove?: () => void; +}>(({}, { emit }) => { + return () => ( + + emit("remove")}> + + + + ); +}); diff --git a/nodepkg/jsoneditor/src/views/BooleanInput.tsx b/nodepkg/jsoneditor/src/views/BooleanInput.tsx new file mode 100644 index 00000000..f333225a --- /dev/null +++ b/nodepkg/jsoneditor/src/views/BooleanInput.tsx @@ -0,0 +1,48 @@ +import { + type AnyType, + component$, + type Context, + rx, +} from "@innoai-tech/vuekit"; +import { JSONEditorProvider } from "../models"; +import { set } from "@innoai-tech/lodash"; +import { Menu, MenuItem, PopupStatus } from "./Menu.tsx"; +import { ValueView } from "./TokenView.tsx"; + +export const BooleanInput = component$<{ + ctx: Context; + value: any; + typedef: AnyType; +}>((props, { render }) => { + const editor$ = JSONEditorProvider.use(); + const open$ = new PopupStatus(false); + + return rx( + props.value$, + render((value) => { + const enumValues = [false, true]; + + return ( + { + editor$.next((values: any) => { + set(values, props.ctx.path, value === "true"); + }); + }} + $content={ + <> + {enumValues.map((v) => ( + +
{v}
+
+ ))} + + } + > + open$.show()} /> +
+ ); + }), + ); +}); diff --git a/nodepkg/jsoneditor/src/views/EnumInput.tsx b/nodepkg/jsoneditor/src/views/EnumInput.tsx new file mode 100644 index 00000000..a087dc20 --- /dev/null +++ b/nodepkg/jsoneditor/src/views/EnumInput.tsx @@ -0,0 +1,50 @@ +import { + type AnyType, + component$, + type Context, + rx, +} from "@innoai-tech/vuekit"; +import { JSONEditorProvider } from "../models"; +import { set } from "@innoai-tech/lodash"; +import { Menu, MenuItem, PopupStatus } from "./Menu.tsx"; +import { ValueView } from "./TokenView.tsx"; + +export const EnumInput = component$<{ + ctx: Context; + value: any; + typedef: AnyType; +}>((props, { render }) => { + const editor$ = JSONEditorProvider.use(); + const open$ = new PopupStatus(false); + + return rx( + props.value$, + render((value) => { + const enumValues = props.typedef.getSchema("enum") ?? []; + const enumLabels = props.typedef.getMeta("enumLabels") ?? []; + + return ( + { + editor$.next((values: any) => { + set(values, props.ctx.path, value); + }); + }} + $content={ + <> + {enumValues.map((v, i) => ( + +
{v}
+ {enumLabels[i] &&
{enumLabels[i]}
} +
+ ))} + + } + > + open$.show()} /> +
+ ); + }), + ); +}); diff --git a/nodepkg/jsoneditor/src/views/Form.tsx b/nodepkg/jsoneditor/src/views/Form.tsx new file mode 100644 index 00000000..7772c542 --- /dev/null +++ b/nodepkg/jsoneditor/src/views/Form.tsx @@ -0,0 +1,45 @@ +import { styled } from "@innoai-tech/vueuikit"; + +export const FormControls = styled("form")({ + display: "flex", + pos: "absolute", + right: 0, + bottom: 0, + px: 8, +}); + +export const FormContainer = styled("div")({ + display: "block", + pos: "relative", + + textarea: { + minW: "20vw", + outline: "none", + border: "none", + bg: "none", + py: 8, + px: 12, + }, +}); + +export const FormContainerAsRow = styled("div")({ + display: "flex", + alignItems: "center", + gap: 8, + pos: "relative", + px: 8, + + input: { + outline: "none", + border: "none", + bg: "none", + minWidth: "10vw", + py: 8, + px: 12, + }, + + [`& ${FormControls}`]: { + pos: "relative", + px: 0, + }, +}); diff --git a/nodepkg/jsoneditor/src/views/JSONRaw.tsx b/nodepkg/jsoneditor/src/views/JSONRaw.tsx new file mode 100644 index 00000000..6757a9a1 --- /dev/null +++ b/nodepkg/jsoneditor/src/views/JSONRaw.tsx @@ -0,0 +1,116 @@ +import { component$, ImmerBehaviorSubject, rx } from "@innoai-tech/vuekit"; +import { Icon, IconButton } from "@innoai-tech/vuematerial"; +import { ActionBtn } from "./Actions.tsx"; +import copyToClipboard from "copy-to-clipboard"; +import { mdiCancel, mdiCheck, mdiCodeJson, mdiContentCopy } from "@mdi/js"; +import { Popover, PopupStatus } from "./Menu.tsx"; +import { onMounted, ref } from "vue"; +import { FormContainer, FormControls } from "./Form.tsx"; +import { Tooltip } from "./Tooltip.tsx"; + +export const CopyAsJSONIconBtn = component$<{ + value?: any; +}>((props, {}) => { + return () => ( + + copyToClipboard(JSON.stringify(props.value, null, 2))}> + + + + ); +}); + +export const InputFromJSONRawIconBtn = component$<{ + onInput?: (prop: string) => void; +}>(({}, { emit }) => { + const open$ = new PopupStatus(false); + + return ( + { + if (v) { + emit("input", v); + } + open$.hide(); + }} + /> + } + > + + open$.show()}> + + + + + ); +}); + +const JSONRawForm = component$<{ + onSubmit: (value?: any) => void; +}>(({}, { emit, render }) => { + const input$ = new ImmerBehaviorSubject(""); + const $input = ref(null); + + const cancel = () => { + emit("submit", undefined); + }; + + const submit = () => { + try { + emit("submit", JSON.parse(input$.value!)); + } catch (e) { + } + }; + + const handleUserKeyPress = (e: KeyboardEvent) => { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + submit(); + } + }; + + onMounted(() => { + $input.value?.focus(); + }); + + return rx( + input$, + render((input) => { + return ( + { + evt.preventDefault(); + submit(); + }} + > +