From a671267bd28ff072c48a3729e6386709bdece3c4 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 -> 217056 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/package.json | 2 +- nodepkg/vuekit/src/Provider.tsx | 100 +++---- .../vuekit/src/__tests__/Provider.spec.tsx | 79 +++-- nodepkg/vuekit/src/__tests__/Type.spec.tsx | 14 +- nodepkg/vuekit/src/component.ts | 22 +- 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/package.json | 2 +- nodepkg/vueuikit/src/GlobalStyle.tsx | 37 ++- nodepkg/vueuikit/src/Overlay.tsx | 78 +++-- nodepkg/vueuikit/src/Popper.tsx | 46 +-- 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 ++--- package.json | 2 + .../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 +++ 63 files changed, 2462 insertions(+), 718 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..203c8bb432a27b43a6e8230b0e4ff740eac6c8a7 100755 GIT binary patch delta 42049 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 TOsV(rsXn}qPk48CIP!l0T#%(@ delta 41803 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�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 { 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(); + }} + > +