@jxsuite/studio 6.1.2 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/chunks/2020-5wtzce5g.js +4 -0
- package/dist/chunks/adapter-5tphg7xe.js +4 -0
- package/dist/chunks/add-new-flow-psym14sn.js +4 -0
- package/dist/chunks/cf-account-picker-haqazq5r.js +4 -0
- package/dist/chunks/cf-settings-h2wrh6hq.js +4 -0
- package/dist/chunks/{color-area-0fj8a4ga.js → color-area-6rbra5dy.js} +2 -2
- package/dist/chunks/{color-field-xch8kx2g.js → color-field-gy56c94g.js} +3 -3
- package/dist/chunks/color-m7r1vk54.js +4 -0
- package/dist/chunks/{color-slider-jxd8v350.js → color-slider-sqqdyf6c.js} +2 -2
- package/dist/chunks/{combobox-p0efwjke.js → combobox-72h32ejk.js} +3 -3
- package/dist/chunks/components-r22xca09.js +4 -0
- package/dist/chunks/content-source-mmppmcyg.js +4 -0
- package/dist/chunks/convert-to-repeater-he70fc2b.js +4 -0
- package/dist/chunks/editor-ccd9jwsa.js +4 -0
- package/dist/chunks/entry-commands-6qxz9e8p.js +4 -0
- package/dist/chunks/extension-sections-0egb88dm.js +4 -0
- package/dist/chunks/file-ops-qnab36ek.js +4 -0
- package/dist/chunks/files-rcn56qvm.js +4 -0
- package/dist/chunks/format-host-yxz0kjjs.js +4 -0
- package/dist/chunks/fs-events-d1qxq4z4.js +4 -0
- package/dist/chunks/grid-open-4z1g062t.js +4 -0
- package/dist/chunks/{grid-view-d2wq9ezg.js → grid-view-qg1b5eqx.js} +25 -25
- package/dist/chunks/{icons-pnfz478q.js → icons-63bjtbs7.js} +2 -2
- package/dist/chunks/{iframe-entry-jdcktez8.js → iframe-entry-2zggzajv.js} +4 -4
- package/dist/chunks/{iframe-entry-zap785cw.js → iframe-entry-76j8vwwx.js} +4 -4
- package/dist/chunks/iframe-entry-99nr5zfb.js +5 -0
- package/dist/chunks/{iframe-entry-x0ygf2yr.js → iframe-entry-pkgmcgp0.js} +4 -4
- package/dist/chunks/iframe-host-ssv7kyj0.js +4 -0
- package/dist/chunks/{index-zpjmzqfk.js → index-32eqzv1k.js} +3 -3
- package/dist/chunks/index-f0jn7nnp.js +4 -0
- package/dist/chunks/{javascript-m54mnwp6.js → javascript-pjp734q4.js} +3 -3
- package/dist/chunks/jsonMode-njkvsa02.js +13 -0
- package/dist/chunks/jx-validate-ttasrbh7.js +4 -0
- package/dist/chunks/layers-bgyr11tr.js +4 -0
- package/dist/chunks/layers-panel-7ez66zeq.js +4 -0
- package/dist/chunks/{listbox-e74qjyq6.js → listbox-c421cf8c.js} +2 -2
- package/dist/chunks/lit-html-v9gh687x.js +4 -0
- package/dist/chunks/media-library-sq468wts.js +4 -0
- package/dist/chunks/media-picker-shfe59pt.js +4 -0
- package/dist/chunks/{menu-n6yzswmy.js → menu-bdpzbfvs.js} +2 -2
- package/dist/chunks/{monaco-binding-7gx83x3r.js → monaco-binding-vq1hgnn0.js} +3 -3
- package/dist/chunks/monaco-buffer-3afgwvbp.js +4 -0
- package/dist/chunks/monaco-setup-xrd2cbkp.js +4 -0
- package/dist/chunks/notify-kzrjr3fv.js +4 -0
- package/dist/chunks/parse-v77xtwv7.js +4 -0
- package/dist/chunks/platform-7v4rtd7m.js +4 -0
- package/dist/chunks/popover-b89sfej7.js +4 -0
- package/dist/chunks/publish-panel-2z9gw8ee.js +4 -0
- package/dist/chunks/publish-quick-qx2455cj.js +4 -0
- package/dist/chunks/publish-workspace-wrc1dgwx.js +4 -0
- package/dist/chunks/quick-search-n0t0eqxb.js +4 -0
- package/dist/chunks/references-9547rg5s.js +4 -0
- package/dist/chunks/right-panel-wsgnr9pn.js +4 -0
- package/dist/chunks/source-control-kwktr9y6.js +4 -0
- package/dist/chunks/{split-n2gfpm5m.js → split-c9zfdgxf.js} +2 -2
- package/dist/chunks/studio-03ct6yfv.js +9 -0
- package/dist/chunks/studio-07rcfje3.js +5 -0
- package/dist/chunks/studio-3e54qh39.js +7 -0
- package/dist/chunks/studio-3exxhz5g.js +5 -0
- package/dist/chunks/studio-3q40e3rj.js +5 -0
- package/dist/chunks/studio-3qeh9t0h.js +6 -0
- package/dist/chunks/studio-3qqjeep5.js +6 -0
- package/dist/chunks/studio-43sd2mam.js +4 -0
- package/dist/chunks/studio-4hp8pkyt.js +5 -0
- package/dist/chunks/studio-58xg6j2q.js +9 -0
- package/dist/chunks/studio-5g0rprdt.js +7 -0
- package/dist/chunks/{studio-2j1cb95x.js → studio-6m380wp7.js} +4 -4
- package/dist/chunks/studio-80jyh1xh.js +4 -0
- package/dist/chunks/studio-83mk4bgg.js +9 -0
- package/dist/chunks/{studio-v0jzqdjm.js → studio-881z1xrx.js} +4 -4
- package/dist/chunks/studio-8m0y2qe7.js +5 -0
- package/dist/chunks/{studio-d81xfh1g.js → studio-8tr6cfrc.js} +4 -4
- package/dist/chunks/studio-8vcvfs7r.js +6 -0
- package/dist/chunks/studio-9tmebf0s.js +5 -0
- package/dist/chunks/studio-a2bvaptz.js +5 -0
- package/dist/chunks/studio-b7y5mr30.js +5 -0
- package/dist/chunks/studio-bavb31r0.js +5 -0
- package/dist/chunks/{studio-dgz8d0c1.js → studio-bbe4c90a.js} +4 -4
- package/dist/chunks/studio-c05wdnt3.js +5 -0
- package/dist/chunks/studio-ccv2svc6.js +5 -0
- package/dist/chunks/studio-d5grtb9e.js +16 -0
- package/dist/chunks/studio-df0baea9.js +5 -0
- package/dist/chunks/studio-dgk4dqtx.js +7 -0
- package/dist/chunks/studio-e1g64q43.js +5 -0
- package/dist/chunks/studio-ed1hp6zf.js +6 -0
- package/dist/chunks/studio-ed3xx40h.js +7 -0
- package/dist/chunks/studio-f14e1zdj.js +5 -0
- package/dist/chunks/studio-fbhxxc5f.js +5 -0
- package/dist/chunks/studio-fyh0jc96.js +5 -0
- package/dist/chunks/studio-gcxk20n7.js +5 -0
- package/dist/chunks/studio-jaaz8ce9.js +5 -0
- package/dist/chunks/{studio-90pq9km1.js → studio-jcnsdaep.js} +4 -4
- package/dist/chunks/studio-jsgf2q5k.js +7 -0
- package/dist/chunks/{studio-0q988f9w.js → studio-k3xxbagr.js} +3 -3
- package/dist/chunks/{studio-5ve6bbep.js → studio-k7evxqh4.js} +4 -4
- package/dist/chunks/studio-kt3pjkwd.js +5 -0
- package/dist/chunks/studio-m8g16bgz.js +5 -0
- package/dist/chunks/studio-mn0476ag.js +5 -0
- package/dist/chunks/studio-mx1smyq0.js +5 -0
- package/dist/chunks/studio-n0c5h6mf.js +5 -0
- package/dist/chunks/{studio-485046te.js → studio-nh6d342n.js} +7 -7
- package/dist/chunks/studio-nqxqf8p2.js +4 -0
- package/dist/chunks/studio-p4nrkvqr.js +5 -0
- package/dist/chunks/{studio-1fxkaaea.js → studio-pbxa5fpc.js} +4 -4
- package/dist/chunks/studio-pgmvdv7z.js +7 -0
- package/dist/chunks/studio-ph84avkf.js +5 -0
- package/dist/chunks/{studio-tq0rtfwj.js → studio-q0mvbaq6.js} +4 -4
- package/dist/chunks/studio-q0tccd43.js +5 -0
- package/dist/chunks/studio-q7rtx6zq.js +14 -0
- package/dist/chunks/{studio-a3g98wjr.js → studio-qgh13jtz.js} +4 -4
- package/dist/chunks/studio-qmn1xc24.js +5 -0
- package/dist/chunks/studio-qwdqwkj0.js +5 -0
- package/dist/chunks/studio-r5qy30vx.js +5 -0
- package/dist/chunks/studio-rj9eamf8.js +5 -0
- package/dist/chunks/studio-rptgsk96.js +5 -0
- package/dist/chunks/studio-rthyg42z.js +928 -0
- package/dist/chunks/studio-s19tp1xr.js +5 -0
- package/dist/chunks/studio-s32578pn.js +5 -0
- package/dist/chunks/studio-svb7yyve.js +5 -0
- package/dist/chunks/studio-syreb644.js +5 -0
- package/dist/chunks/studio-tf9jryb1.js +10 -0
- package/dist/chunks/studio-tfkznv39.js +5 -0
- package/dist/chunks/studio-tft6r105.js +5 -0
- package/dist/chunks/studio-txf2kysx.js +5 -0
- package/dist/chunks/studio-v8867ddv.js +12 -0
- package/dist/chunks/studio-vxq7fcvv.js +5 -0
- package/dist/chunks/studio-w4rz9hdk.js +5 -0
- package/dist/chunks/studio-wbcjbhy1.js +9 -0
- package/dist/chunks/studio-wc649wss.js +5 -0
- package/dist/chunks/studio-wys23mxz.js +5 -0
- package/dist/chunks/studio-x1x167jh.js +5 -0
- package/dist/chunks/studio-x9hsze61.js +5 -0
- package/dist/chunks/studio-y0n7yxea.js +9 -0
- package/dist/chunks/studio-y3ahhdpx.js +5 -0
- package/dist/chunks/studio-z97c48fk.js +5 -0
- package/dist/chunks/studio-zat62m0c.js +5 -0
- package/dist/chunks/studio-zcd2e7yz.js +5 -0
- package/dist/chunks/studio-zz9qe3rw.js +64 -0
- package/dist/chunks/toast-1gv0h53h.js +4 -0
- package/dist/chunks/{toast-host-ke5z4ng7.js → toast-host-1yg5ar8d.js} +3 -3
- package/dist/chunks/{tooltip-5v8ngwj2.js → tooltip-yypz28gq.js} +3 -3
- package/dist/chunks/{tree-mdq3v5cw.js → tree-9xa4hm7n.js} +2 -2
- package/dist/chunks/tsMode-epyfz1hv.js +14 -0
- package/dist/chunks/workspace-dz7nxfhv.js +4 -0
- package/dist/chunks/workspace-home-xsd7hkjw.js +4 -0
- package/dist/chunks/{ws-client-nze0k6mv.js → ws-client-bv552sfx.js} +3 -3
- package/dist/iframe-entry.js +20 -16
- package/dist/manifest.json +77 -63
- package/dist/studio.js +103 -104
- package/dist/workers/ts.worker.js +3 -3
- package/package.json +12 -11
- package/src/browse/component-examples.ts +272 -0
- package/src/browse/library-commands.ts +64 -104
- package/src/browse/library-layouts.ts +263 -49
- package/src/browse/library-model.ts +181 -133
- package/src/browse/library-pane.ts +738 -446
- package/src/browse/library-preview.ts +149 -19
- package/src/browse/library-source.ts +308 -41
- package/src/browse/preview-root.ts +78 -0
- package/src/browse/preview-style.ts +155 -0
- package/src/canvas/asset-refs.ts +16 -1
- package/src/canvas/canvas-live-render.ts +222 -30
- package/src/canvas/canvas-origin.ts +37 -12
- package/src/canvas/canvas-page-context.ts +112 -0
- package/src/canvas/canvas-render.ts +113 -107
- package/src/canvas/canvas-utils.ts +57 -12
- package/src/canvas/iframe-drop.ts +107 -0
- package/src/canvas/iframe-entry.ts +24 -12
- package/src/canvas/iframe-host.ts +134 -62
- package/src/canvas/iframe-keys.ts +11 -0
- package/src/canvas/iframe-patch.ts +8 -7
- package/src/canvas/iframe-protocol.ts +24 -5
- package/src/canvas/iframe-render.ts +48 -1
- package/src/canvas/iframe-subtree.ts +5 -2
- package/src/canvas/npm-modules.ts +22 -0
- package/src/canvas/preview-navigate.ts +16 -0
- package/src/canvas/repeater-sources.ts +200 -0
- package/src/canvas/stage-scrollbar.ts +5 -1
- package/src/canvas/surface-registry.ts +6 -0
- package/src/commands/app-commands.ts +16 -6
- package/src/commands/budget.ts +10 -8
- package/src/commands/context.ts +35 -10
- package/src/commands/defaults.ts +69 -45
- package/src/commands/keymap.ts +9 -0
- package/src/commands/levels.ts +11 -5
- package/src/commands/live-context.ts +2 -0
- package/src/commands/registry.ts +10 -1
- package/src/content/collection-match.ts +6 -5
- package/src/content/collection-pages.ts +412 -0
- package/src/content/content-collections.ts +270 -0
- package/src/content/entry-commands.ts +51 -60
- package/src/content/entry-editor.ts +111 -18
- package/src/content/entry-fields.ts +13 -1
- package/src/content/entry-inspector.ts +225 -0
- package/src/content/entry-model.ts +17 -3
- package/src/content/entry-open.ts +80 -0
- package/src/content/entry-summaries.ts +440 -0
- package/src/content/file-record-ids.ts +80 -0
- package/src/content/file-records.ts +125 -0
- package/src/content/page-summaries.ts +129 -0
- package/src/content/record-entry.ts +201 -0
- package/src/content/writing-banner.ts +177 -0
- package/src/create/add-new-commands.ts +185 -0
- package/src/create/add-new-flow.ts +1116 -0
- package/src/create/add-new.ts +1014 -0
- package/src/create/element-name.ts +121 -0
- package/src/editor/convert-to-component.ts +67 -43
- package/src/editor/file-drop-action.ts +9 -1
- package/src/editor/inline-edit-apply.ts +44 -0
- package/src/editor/inline-edit.ts +10 -0
- package/src/editor/insert-component.ts +91 -0
- package/src/editor/insert-zone-action.ts +13 -4
- package/src/editor/shortcuts.ts +44 -22
- package/src/editor/slash-menu.ts +51 -8
- package/src/files/components.ts +74 -10
- package/src/files/file-ops.ts +15 -5
- package/src/files/files.ts +164 -150
- package/src/files/fs-events.ts +18 -7
- package/src/files/media-meta.ts +95 -1
- package/src/files/media-types.ts +55 -0
- package/src/files/media-upload.ts +209 -52
- package/src/files/new-file-name.ts +156 -0
- package/src/files/serialize-document.ts +13 -3
- package/src/format/format-host.ts +15 -0
- package/src/github/github-auth.ts +2 -2
- package/src/github/github-publish.ts +4 -3
- package/src/grid/grid-controller.ts +5 -1
- package/src/grid/grid-open.ts +0 -27
- package/src/grid/grid-panel.ts +54 -2
- package/src/grid/grid-reveal.ts +34 -0
- package/src/grid/grid-source.ts +3 -25
- package/src/grid/grid-view.ts +31 -6
- package/src/grid/sources/content-source.ts +75 -7
- package/src/grid/tabulator-tables.d.ts +6 -0
- package/src/hosting/document.ts +2 -2
- package/src/i18n/i18n-commands.ts +2 -1
- package/src/media/media-commands.ts +181 -0
- package/src/media/media-library-model.ts +232 -0
- package/src/media/media-library.ts +1283 -0
- package/src/media/media-pane.ts +47 -19
- package/src/packages/pull-package-sync.ts +1 -1
- package/src/panels/activity-panel.ts +21 -5
- package/src/panels/ai-chat/chat-markdown.ts +8 -8
- package/src/panels/block-action-bar.ts +11 -11
- package/src/panels/canvas-dnd-bridge.ts +5 -2
- package/src/panels/chat-panel.ts +6 -6
- package/src/panels/collections-panel.ts +306 -0
- package/src/panels/component-preview.ts +35 -13
- package/src/panels/data-explorer.ts +1 -1
- package/src/panels/data-grid.ts +4 -0
- package/src/panels/dnd.ts +17 -30
- package/src/panels/elements-panel.ts +9 -2
- package/src/panels/empty-state.ts +2 -2
- package/src/panels/formula-workspace.ts +2 -3
- package/src/panels/frontmatter-fields.ts +9 -9
- package/src/panels/git-diff-open.ts +9 -5
- package/src/panels/head-panel.ts +369 -103
- package/src/panels/i18n-panel.ts +11 -10
- package/src/panels/imports-panel.ts +2 -0
- package/src/panels/jump-bar.ts +27 -2
- package/src/panels/layers-panel.ts +36 -30
- package/src/panels/left-panel.ts +22 -8
- package/src/panels/navigator-panels.ts +23 -11
- package/src/panels/pane-context.ts +111 -29
- package/src/panels/pane-grid.ts +6 -6
- package/src/panels/panel-registry.ts +14 -9
- package/src/panels/properties-panel.ts +7 -3
- package/src/panels/right-panel.ts +199 -43
- package/src/panels/seo-modal.ts +41 -108
- package/src/panels/settings-menu.ts +52 -50
- package/src/panels/settings-pane.ts +268 -162
- package/src/panels/signals-panel.ts +3 -4
- package/src/panels/site-model.ts +367 -0
- package/src/panels/site-panel.ts +638 -0
- package/src/panels/style-panel.ts +37 -3
- package/src/panels/stylebook-doc.ts +142 -10
- package/src/panels/stylebook-layers-panel.ts +39 -80
- package/src/panels/stylebook-panel.ts +47 -10
- package/src/panels/styles-panel.ts +327 -0
- package/src/panels/tab-strip.ts +109 -25
- package/src/platform.ts +1 -1
- package/src/platforms/cloud.ts +28 -1
- package/src/platforms/default-platform.ts +4 -4
- package/src/platforms/devserver.ts +51 -25
- package/src/publish/deploy-checklist.ts +12 -7
- package/src/publish/pages-service.ts +38 -14
- package/src/publish/publish-changes.ts +491 -0
- package/src/publish/publish-commands.ts +83 -18
- package/src/publish/publish-ids.ts +49 -0
- package/src/publish/publish-quick.ts +148 -0
- package/src/publish/publish-workspace.ts +926 -0
- package/src/publish/source-control.ts +907 -0
- package/src/services/automation.ts +16 -20
- package/src/services/cf-settings.ts +4 -4
- package/src/services/connection.ts +2 -2
- package/src/services/directory-picker.ts +2 -2
- package/src/services/references.ts +0 -0
- package/src/services/render-critic.ts +21 -2
- package/src/services/settings/definitions.ts +25 -14
- package/src/settings/contributed-section.ts +49 -10
- package/src/settings/css-vars-editor.ts +93 -27
- package/src/settings/developer-panels.ts +43 -0
- package/src/settings/extension-sections.ts +20 -2
- package/src/settings/general-settings.ts +91 -21
- package/src/settings/preferences-dialog.ts +8 -1
- package/src/settings/project-sections.ts +27 -10
- package/src/settings/schema-field-ui.ts +3 -1
- package/src/settings/section-registry.ts +116 -11
- package/src/settings/settings-dialog.ts +192 -0
- package/src/settings/settings-document.ts +182 -162
- package/src/shell.ts +467 -431
- package/src/site-context.ts +64 -10
- package/src/state.ts +28 -9
- package/src/studio.ts +194 -41
- package/src/style/project-styles.ts +34 -0
- package/src/style/stylebook-specimens.ts +89 -0
- package/src/style/stylebook-target.ts +26 -0
- package/src/style/tag-inheritance.ts +105 -0
- package/src/style/variables-focus.ts +61 -0
- package/src/style/variables-view.ts +235 -0
- package/src/surfaces/add-new.json +1482 -0
- package/src/surfaces/add-new.ts +325 -0
- package/src/surfaces/ai-chat.ts +2 -2
- package/src/surfaces/boot-failure.json +4 -3
- package/src/surfaces/bottom-dock.json +1 -1
- package/src/surfaces/canvas-stage.json +30 -19
- package/src/surfaces/canvas-stage.ts +5 -5
- package/src/surfaces/collections-panel.json +615 -0
- package/src/surfaces/collections-panel.ts +168 -0
- package/src/surfaces/commandbar.json +241 -96
- package/src/surfaces/commandbar.ts +134 -99
- package/src/surfaces/empty-state.json +1 -1
- package/src/surfaces/entry-editor.json +136 -0
- package/src/surfaces/entry-editor.ts +21 -0
- package/src/surfaces/entry-inspector.json +371 -0
- package/src/surfaces/entry-inspector.ts +143 -0
- package/src/surfaces/inspector-dock.json +162 -14
- package/src/surfaces/inspector-dock.ts +46 -19
- package/src/surfaces/library-pane.json +670 -437
- package/src/surfaces/library-pane.ts +94 -59
- package/src/surfaces/media-browser.json +62 -6
- package/src/surfaces/media-browser.ts +15 -1
- package/src/surfaces/media-field.json +1 -1
- package/src/surfaces/media-library.json +1586 -0
- package/src/surfaces/media-library.ts +282 -0
- package/src/surfaces/media-pick-dialog.json +71 -0
- package/src/surfaces/media-pick-dialog.ts +132 -0
- package/src/surfaces/menu.ts +18 -0
- package/src/surfaces/pane-context.json +144 -77
- package/src/surfaces/pane-context.ts +24 -0
- package/src/surfaces/panel-deploy-checklist.json +12 -6
- package/src/surfaces/panel-deploy-checklist.ts +3 -1
- package/src/surfaces/panel-page.json +72 -2
- package/src/surfaces/panel-page.ts +38 -7
- package/src/surfaces/panel-signals.json +1 -1
- package/src/surfaces/panel-signals.ts +5 -5
- package/src/surfaces/panel-stylebook-layers.json +71 -204
- package/src/surfaces/panel-stylebook-layers.ts +0 -21
- package/src/surfaces/preferences.json +120 -48
- package/src/surfaces/preferences.ts +8 -0
- package/src/surfaces/publish-quick.json +428 -0
- package/src/surfaces/publish-quick.ts +165 -0
- package/src/surfaces/publish-workspace.json +2892 -0
- package/src/surfaces/publish-workspace.ts +391 -0
- package/src/surfaces/rail.json +1 -159
- package/src/surfaces/rail.ts +18 -75
- package/src/surfaces/schema-form.json +10 -2
- package/src/surfaces/schema-form.ts +2 -0
- package/src/surfaces/seo.json +1 -1
- package/src/surfaces/settings-contributed.json +5 -5
- package/src/surfaces/settings-contributed.ts +18 -2
- package/src/surfaces/settings-css-vars.json +44 -36
- package/src/surfaces/settings-css-vars.ts +77 -4
- package/src/surfaces/settings-deploy.json +2 -15
- package/src/surfaces/settings-deploy.ts +1 -1
- package/src/surfaces/settings-dialog.json +51 -0
- package/src/surfaces/settings-dialog.ts +169 -0
- package/src/surfaces/settings-overview.json +3 -3
- package/src/surfaces/settings-overview.ts +9 -2
- package/src/surfaces/settings-pane.json +269 -46
- package/src/surfaces/settings-pane.ts +85 -24
- package/src/surfaces/shell.json +2 -1
- package/src/surfaces/site-panel.json +1029 -0
- package/src/surfaces/site-panel.ts +233 -0
- package/src/surfaces/slash-menu.json +63 -21
- package/src/surfaces/slash-menu.ts +23 -0
- package/src/surfaces/statusbar.ts +39 -15
- package/src/surfaces/styles-panel.json +735 -0
- package/src/surfaces/styles-panel.ts +195 -0
- package/src/surfaces/styles-variables.json +149 -0
- package/src/surfaces/styles-variables.ts +145 -0
- package/src/surfaces/tab-strip.json +4 -4
- package/src/surfaces/welcome.ts +1 -1
- package/src/surfaces/writing-banner.json +94 -0
- package/src/surfaces/writing-banner.ts +80 -0
- package/src/tabs/bare-repeaters.ts +101 -0
- package/src/tabs/tab.ts +47 -7
- package/src/types.ts +21 -26
- package/src/ui/form-controls.ts +47 -8
- package/src/ui/layers.ts +13 -0
- package/src/ui/media-picker.ts +284 -40
- package/src/ui/regions.ts +7 -6
- package/src/ui/schema-form.ts +259 -27
- package/src/ui/virtual-window.ts +26 -1
- package/src/utils/base64.ts +3 -3
- package/src/utils/edit-display.ts +322 -67
- package/src/utils/local-day.ts +18 -0
- package/src/workspace/pane-derive.ts +4 -4
- package/src/workspace/session.ts +28 -7
- package/src/workspace/tab-workspace.ts +137 -0
- package/src/workspace/workspace-back.ts +189 -0
- package/src/workspace/workspace-home.ts +133 -0
- package/src/workspace/workspace-ids.ts +129 -0
- package/src/workspace/workspace-switch.ts +372 -0
- package/src/workspace/workspace.ts +125 -11
- package/styles/shell-frame.css +30 -7
- package/styles/shell-frame.json +15 -3
- package/dist/chunks/2020-f2gkpy8d.js +0 -4
- package/dist/chunks/adapter-4912g339.js +0 -4
- package/dist/chunks/cf-account-picker-wccaenh6.js +0 -4
- package/dist/chunks/cf-settings-br6105tr.js +0 -4
- package/dist/chunks/color-28ksk2qm.js +0 -4
- package/dist/chunks/components-db68vsn7.js +0 -4
- package/dist/chunks/content-source-1449qesq.js +0 -4
- package/dist/chunks/convert-to-repeater-5h457egj.js +0 -4
- package/dist/chunks/editor-x9jn86a7.js +0 -4
- package/dist/chunks/entry-commands-may24cpt.js +0 -4
- package/dist/chunks/extension-sections-pvr14vxr.js +0 -4
- package/dist/chunks/file-ops-x9v54pcj.js +0 -4
- package/dist/chunks/files-j3knqf0s.js +0 -4
- package/dist/chunks/format-host-tyre2trb.js +0 -4
- package/dist/chunks/fs-events-64ma9htc.js +0 -4
- package/dist/chunks/git-panel-84ps5dex.js +0 -4
- package/dist/chunks/iframe-entry-fvbk89gm.js +0 -5
- package/dist/chunks/iframe-host-ck6vejt5.js +0 -4
- package/dist/chunks/index-b8xw3vy9.js +0 -4
- package/dist/chunks/jsonMode-w15cmrcm.js +0 -13
- package/dist/chunks/jx-validate-at3zn8wa.js +0 -4
- package/dist/chunks/layers-h4xp1pss.js +0 -4
- package/dist/chunks/layers-panel-m5hw1d7g.js +0 -4
- package/dist/chunks/lit-html-8t8t3dnr.js +0 -4
- package/dist/chunks/media-picker-2cweexc5.js +0 -4
- package/dist/chunks/menu-ynw13y0s.js +0 -4
- package/dist/chunks/monaco-buffer-qzxn567r.js +0 -4
- package/dist/chunks/monaco-setup-gxf6656g.js +0 -4
- package/dist/chunks/notify-cj5zbrs2.js +0 -4
- package/dist/chunks/parse-b7ddhr8m.js +0 -4
- package/dist/chunks/platform-3dfws9js.js +0 -4
- package/dist/chunks/popover-jt2gxmzs.js +0 -4
- package/dist/chunks/publish-panel-1gvxbj21.js +0 -4
- package/dist/chunks/quick-search-0dajrwqg.js +0 -4
- package/dist/chunks/references-49qgt404.js +0 -4
- package/dist/chunks/right-panel-jm1bwe53.js +0 -4
- package/dist/chunks/section-registry-6kwc4fky.js +0 -4
- package/dist/chunks/studio-0rt52vpq.js +0 -5
- package/dist/chunks/studio-18vgbhs5.js +0 -5
- package/dist/chunks/studio-24mccdrj.js +0 -5
- package/dist/chunks/studio-2eh507zk.js +0 -9
- package/dist/chunks/studio-2hcbccfv.js +0 -5
- package/dist/chunks/studio-2jbs3rxv.js +0 -5
- package/dist/chunks/studio-4h8k4dw9.js +0 -5
- package/dist/chunks/studio-5f6n18kx.js +0 -5
- package/dist/chunks/studio-5gthpky6.js +0 -5
- package/dist/chunks/studio-6ep3js6b.js +0 -9
- package/dist/chunks/studio-6wkmf3wz.js +0 -9
- package/dist/chunks/studio-841rf3cg.js +0 -5
- package/dist/chunks/studio-8gmwgheg.js +0 -5
- package/dist/chunks/studio-8qm0ep50.js +0 -5
- package/dist/chunks/studio-924p1tm1.js +0 -6
- package/dist/chunks/studio-a3shpz9y.js +0 -5
- package/dist/chunks/studio-amsbaaar.js +0 -6
- package/dist/chunks/studio-at5spjbc.js +0 -7
- package/dist/chunks/studio-b2xv945e.js +0 -5
- package/dist/chunks/studio-bn5nkafw.js +0 -5
- package/dist/chunks/studio-bw6q5xjf.js +0 -9
- package/dist/chunks/studio-c7q0t9x1.js +0 -5
- package/dist/chunks/studio-camnhc96.js +0 -6
- package/dist/chunks/studio-cffqvnzd.js +0 -5
- package/dist/chunks/studio-efvfrsf8.js +0 -5
- package/dist/chunks/studio-er30bpcx.js +0 -5
- package/dist/chunks/studio-ezscgr64.js +0 -5
- package/dist/chunks/studio-ffrrncvz.js +0 -5
- package/dist/chunks/studio-fpphgn8y.js +0 -10
- package/dist/chunks/studio-j1kvhdjk.js +0 -4
- package/dist/chunks/studio-j430n16g.js +0 -7
- package/dist/chunks/studio-jjkg84nj.js +0 -5
- package/dist/chunks/studio-m0q32ars.js +0 -4
- package/dist/chunks/studio-m6bdst11.js +0 -5
- package/dist/chunks/studio-nv2cptd4.js +0 -64
- package/dist/chunks/studio-nwfrc98n.js +0 -5
- package/dist/chunks/studio-p1wgvp7r.js +0 -5
- package/dist/chunks/studio-pag2wncm.js +0 -5
- package/dist/chunks/studio-qvanvzfd.js +0 -5
- package/dist/chunks/studio-qwa64kt7.js +0 -5
- package/dist/chunks/studio-rk1zc4x3.js +0 -928
- package/dist/chunks/studio-se2r3ptc.js +0 -5
- package/dist/chunks/studio-sg2a0dh0.js +0 -5
- package/dist/chunks/studio-tjzjhe68.js +0 -5
- package/dist/chunks/studio-v2w7q8r1.js +0 -7
- package/dist/chunks/studio-v5vjq1h0.js +0 -4
- package/dist/chunks/studio-v8aga3vp.js +0 -14
- package/dist/chunks/studio-vfcdrfmv.js +0 -5
- package/dist/chunks/studio-vmfkgdjf.js +0 -5
- package/dist/chunks/studio-wt1816jj.js +0 -5
- package/dist/chunks/studio-wz73q5kq.js +0 -4
- package/dist/chunks/studio-y04qtxvp.js +0 -7
- package/dist/chunks/studio-y21g8zzg.js +0 -5
- package/dist/chunks/studio-y64hrt8p.js +0 -12
- package/dist/chunks/studio-ynn90f58.js +0 -16
- package/dist/chunks/studio-yxz682sx.js +0 -5
- package/dist/chunks/studio-zp7snvkq.js +0 -5
- package/dist/chunks/studio-zq4z6tm6.js +0 -5
- package/dist/chunks/toast-c9fn075p.js +0 -4
- package/dist/chunks/tsMode-sf49ee9x.js +0 -14
- package/dist/chunks/workspace-jtfahpee.js +0 -4
- package/src/panels/frontmatter-panel.ts +0 -711
- package/src/panels/git-panel.ts +0 -1108
- package/src/surfaces/doc-header.json +0 -776
- package/src/surfaces/doc-header.ts +0 -222
- package/src/surfaces/git-panel.json +0 -1880
- package/src/surfaces/git-panel.ts +0 -264
package/src/ui/schema-form.ts
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
* Schema-form — the reusable JSON-Schema → form engine, and the FLOW half of it.
|
|
4
4
|
*
|
|
5
5
|
* Maps schema property types to controls (enum → select, boolean → checkbox, number/integer →
|
|
6
|
-
* number field, `json-schema` format → JSON editor, array-of-objects → a row per item,
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* overrides.
|
|
6
|
+
* number field, `json-schema` format → JSON editor, array-of-objects → a row per item, an array of
|
|
7
|
+
* single values (text, numbers, pictures, entries) → a row per item too, other array/object → JSON
|
|
8
|
+
* text, default → text field); hosts commit edits through a single `onChange(patch)` callback;
|
|
9
|
+
* dynamic enum choices resolve through a {@link SchemaFormContext}. Custom controls register by
|
|
10
|
+
* name via {@link registerFormControl} and are consulted first for `ui` overrides.
|
|
11
11
|
*
|
|
12
12
|
* **This module decides; `surfaces/schema-form.json` draws.** Every question with an answer — which
|
|
13
13
|
* control a property gets, what its choices are, which rungs of the value ladder the position
|
|
@@ -174,9 +174,10 @@ export interface RenderFormOptions {
|
|
|
174
174
|
/**
|
|
175
175
|
* Per-field overrides from `$studio.settings.entry.ui`: a registered control name, and/or an
|
|
176
176
|
* `enum` source (choice list or `{ "$ref": "#/$context/<pointer>" }`) layered over the field
|
|
177
|
-
* schema — fragments stay valid JSON Schema while descriptors add dynamic choices.
|
|
177
|
+
* schema — fragments stay valid JSON Schema while descriptors add dynamic choices. `label` is the
|
|
178
|
+
* words the row is titled with in place of the property's key.
|
|
178
179
|
*/
|
|
179
|
-
ui?: Record<string, { control?: string; enum?: unknown }> | undefined;
|
|
180
|
+
ui?: Record<string, { control?: string; enum?: unknown; label?: string }> | undefined;
|
|
180
181
|
rerender?: (() => void) | undefined;
|
|
181
182
|
/**
|
|
182
183
|
* Externally-produced diagnostics, keyed by property name — §16.1's inline tier, sourced.
|
|
@@ -416,16 +417,28 @@ interface FieldPlan {
|
|
|
416
417
|
itemProps?: Record<string, JsonSchema> | undefined;
|
|
417
418
|
/** The rows currently held, so a cell edit can rebuild the array. */
|
|
418
419
|
rows?: JsonObject[] | undefined;
|
|
420
|
+
/**
|
|
421
|
+
* The field is an array of single values (`string[]`, a gallery of pictures), drawn as rows of
|
|
422
|
+
* one cell each: every row is `{ [SCALAR_CELL]: item }` here, and a commit writes the bare items
|
|
423
|
+
* back. One row editor for both shapes, rather than a list control beside the row control.
|
|
424
|
+
*/
|
|
425
|
+
scalarItems?: boolean | undefined;
|
|
419
426
|
/** The ladder, when this position offers one. */
|
|
420
427
|
ladder?: { fieldKey: string; mode: SlotMode; offered: SlotMode[]; sources: SurfaceOption[] };
|
|
421
428
|
/** A registered control owns the whole field; args are rebuilt for it on every repaint. */
|
|
422
429
|
control?: SchemaFormMountedControl | undefined;
|
|
430
|
+
/**
|
|
431
|
+
* The member of the property's OBJECT this row edits, when the row is one part of an object
|
|
432
|
+
* field: an image object's `alt` is a text row of its own, and its commit writes the whole object
|
|
433
|
+
* back with that one member changed.
|
|
434
|
+
*/
|
|
435
|
+
member?: string | undefined;
|
|
423
436
|
/**
|
|
424
437
|
* Registered controls owning one cell, keyed by the cell's host id.
|
|
425
438
|
*
|
|
426
439
|
* The same kind of entry a field's own control is, and reached by the same dispatch: a cell host
|
|
427
|
-
* is a host like any other.
|
|
428
|
-
* {@link deriveCell}).
|
|
440
|
+
* is a host like any other. A cell is given `reference` for an entry of another collection and
|
|
441
|
+
* `media` for a picture (see {@link deriveCell}).
|
|
429
442
|
*/
|
|
430
443
|
cellControls?: Map<
|
|
431
444
|
string,
|
|
@@ -574,11 +587,37 @@ function createController(): FormController {
|
|
|
574
587
|
return;
|
|
575
588
|
}
|
|
576
589
|
default: {
|
|
590
|
+
if (plan.member !== undefined) {
|
|
591
|
+
// One member of an object: the object goes back whole, with that member set or removed.
|
|
592
|
+
const held = value[plan.prop];
|
|
593
|
+
const base: JsonObject = isJsonObject(held) ? { ...held } : {};
|
|
594
|
+
if (raw) {
|
|
595
|
+
base[plan.member] = raw;
|
|
596
|
+
} else {
|
|
597
|
+
delete base[plan.member];
|
|
598
|
+
}
|
|
599
|
+
patch(plan.prop, Object.keys(base).length > 0 ? base : undefined);
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
577
602
|
patch(plan.prop, raw || undefined);
|
|
578
603
|
}
|
|
579
604
|
}
|
|
580
605
|
};
|
|
581
606
|
|
|
607
|
+
/**
|
|
608
|
+
* Write a row field's rows back as the array the document holds: the rows themselves for an array
|
|
609
|
+
* of objects, each row's one value for an array of single values. A row whose value was cleared
|
|
610
|
+
* stays as an empty string, so clearing the text of an item does not delete its row under the
|
|
611
|
+
* caret; Remove is how an item goes.
|
|
612
|
+
*/
|
|
613
|
+
const patchRows = (plan: FieldPlan, rows: JsonObject[]): void => {
|
|
614
|
+
let next: JsonValue | undefined;
|
|
615
|
+
if (rows.length > 0) {
|
|
616
|
+
next = plan.scalarItems ? rows.map((row) => row[SCALAR_CELL] ?? "") : rows;
|
|
617
|
+
}
|
|
618
|
+
patch(plan.prop, next);
|
|
619
|
+
};
|
|
620
|
+
|
|
582
621
|
/** The field's items, each shallow-copied so a cell edit never writes through to the document. */
|
|
583
622
|
const cellRows = (plan: FieldPlan): JsonObject[] => {
|
|
584
623
|
const copies: JsonObject[] = [];
|
|
@@ -602,7 +641,7 @@ function createController(): FormController {
|
|
|
602
641
|
seed[k] = v.default as JsonValue;
|
|
603
642
|
}
|
|
604
643
|
}
|
|
605
|
-
|
|
644
|
+
patchRows(plan, [...cellRows(plan), seed]);
|
|
606
645
|
opts.rerender?.();
|
|
607
646
|
},
|
|
608
647
|
commit: (key: string, raw: string) => {
|
|
@@ -644,8 +683,10 @@ function createController(): FormController {
|
|
|
644
683
|
return;
|
|
645
684
|
}
|
|
646
685
|
const idx = Number(row);
|
|
647
|
-
|
|
648
|
-
|
|
686
|
+
patchRows(
|
|
687
|
+
plan,
|
|
688
|
+
cellRows(plan).filter((_, i) => i !== idx),
|
|
689
|
+
);
|
|
649
690
|
opts.rerender?.();
|
|
650
691
|
},
|
|
651
692
|
};
|
|
@@ -669,7 +710,7 @@ function createController(): FormController {
|
|
|
669
710
|
...target,
|
|
670
711
|
[cell]: coerceCell(cellSchema, next, plan.refCells?.has(`${field}/${row}/${cell}`) ?? false),
|
|
671
712
|
} as JsonObject;
|
|
672
|
-
|
|
713
|
+
patchRows(plan, rows);
|
|
673
714
|
}
|
|
674
715
|
|
|
675
716
|
/** A cell's committed string, as the item property's declared type. */
|
|
@@ -887,18 +928,93 @@ function deriveFields(
|
|
|
887
928
|
): SchemaFormFieldView[] {
|
|
888
929
|
const required = new Set(schema.required);
|
|
889
930
|
const sources = refSourcesFor(ctx);
|
|
890
|
-
return Object.entries(schema.properties ?? {}).
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
931
|
+
return Object.entries(schema.properties ?? {}).flatMap(([prop, ps]) => {
|
|
932
|
+
const args = { ctx, opts, plans, required: required.has(prop), sources, value };
|
|
933
|
+
const field = deriveField(prop, ps, args);
|
|
934
|
+
// An image object's alt text is a row of its own, under the picture it describes.
|
|
935
|
+
return field.kind === "control" && isImageObjectSchema(ps) && ps.properties?.["alt"]
|
|
936
|
+
? [field, imageAltRow(prop, args)]
|
|
937
|
+
: [field];
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
/** The members an image object may have beside its `src`: what an `<img>` says about itself. */
|
|
942
|
+
const IMAGE_OBJECT_MEMBERS: ReadonlySet<string> = new Set([
|
|
943
|
+
"src",
|
|
944
|
+
"alt",
|
|
945
|
+
"width",
|
|
946
|
+
"height",
|
|
947
|
+
"title",
|
|
948
|
+
]);
|
|
949
|
+
|
|
950
|
+
/**
|
|
951
|
+
* Whether a property is an image OBJECT: `{ src, alt?, width?, height?, title? }`, the shape a site
|
|
952
|
+
* imported from a CMS keeps a picture in (`featuredImage: { src, width, height, alt }`). Such a
|
|
953
|
+
* field is a picture to pick, not a record to type JSON into.
|
|
954
|
+
*/
|
|
955
|
+
export function isImageObjectSchema(ps: JsonSchema): boolean {
|
|
956
|
+
const properties = ps.properties ?? {};
|
|
957
|
+
return (
|
|
958
|
+
ps.type === "object" &&
|
|
959
|
+
properties["src"]?.type === "string" &&
|
|
960
|
+
Object.keys(properties).every((name) => IMAGE_OBJECT_MEMBERS.has(name))
|
|
899
961
|
);
|
|
900
962
|
}
|
|
901
963
|
|
|
964
|
+
/** The media control over an image object's `src`, writing the object back around it. */
|
|
965
|
+
function imageObjectControl(media: SchemaFormMountedControl): SchemaFormMountedControl {
|
|
966
|
+
/** The args the media control sees: the `src`, and a commit that rebuilds the object. */
|
|
967
|
+
const srcArgs = (args: SchemaFormControlArgs): SchemaFormControlArgs => {
|
|
968
|
+
const held = isJsonObject(args.value) ? args.value : {};
|
|
969
|
+
const { src } = held;
|
|
970
|
+
return {
|
|
971
|
+
...args,
|
|
972
|
+
onChange: (next) => {
|
|
973
|
+
if (next === src) {
|
|
974
|
+
return;
|
|
975
|
+
}
|
|
976
|
+
/* A different picture: its alt text and title still describe what the author meant, but the
|
|
977
|
+
old picture's width and height would be a lie about the new one, so they go. A cleared
|
|
978
|
+
field clears the whole object: an image with no picture is no image. */
|
|
979
|
+
const { height: _height, width: _width, ...kept } = held;
|
|
980
|
+
let rebuilt: JsonValue | undefined;
|
|
981
|
+
if (next !== undefined && next !== "") {
|
|
982
|
+
rebuilt = { ...kept, src: next };
|
|
983
|
+
}
|
|
984
|
+
args.onChange(rebuilt);
|
|
985
|
+
},
|
|
986
|
+
value: isString(src) ? src : undefined,
|
|
987
|
+
};
|
|
988
|
+
};
|
|
989
|
+
return {
|
|
990
|
+
mount(host, args) {
|
|
991
|
+
const handle = media.mount(host, srcArgs(args));
|
|
992
|
+
return {
|
|
993
|
+
dispose: () => handle.dispose(),
|
|
994
|
+
update: (next) => handle.update(srcArgs(next)),
|
|
995
|
+
};
|
|
996
|
+
},
|
|
997
|
+
};
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
/** The text row an image object's `alt` is edited in. */
|
|
1001
|
+
function imageAltRow(prop: string, args: DeriveArgs): SchemaFormFieldView {
|
|
1002
|
+
const key = `${prop}/alt`;
|
|
1003
|
+
const held = args.value[prop];
|
|
1004
|
+
const alt = isJsonObject(held) ? held["alt"] : undefined;
|
|
1005
|
+
const row = deriveField(key, { type: "string" }, { ...args, required: false });
|
|
1006
|
+
const plan = args.plans.get(key);
|
|
1007
|
+
if (plan) {
|
|
1008
|
+
plan.prop = prop;
|
|
1009
|
+
plan.member = "alt";
|
|
1010
|
+
}
|
|
1011
|
+
return {
|
|
1012
|
+
...row,
|
|
1013
|
+
label: `${args.opts.ui?.[prop]?.label ?? prop} alt text`,
|
|
1014
|
+
value: isString(alt) ? alt : "",
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
1017
|
+
|
|
902
1018
|
interface DeriveArgs {
|
|
903
1019
|
ctx: SchemaFormContext;
|
|
904
1020
|
opts: RenderFormOptions;
|
|
@@ -941,11 +1057,12 @@ function deriveField(prop: string, ps: JsonSchema, args: DeriveArgs): SchemaForm
|
|
|
941
1057
|
invalid: error !== "",
|
|
942
1058
|
key: prop,
|
|
943
1059
|
kind: "text",
|
|
944
|
-
label: prop,
|
|
1060
|
+
label: opts.ui?.[prop]?.label ?? prop,
|
|
945
1061
|
max: "",
|
|
946
1062
|
min: "",
|
|
947
1063
|
mono: false,
|
|
948
1064
|
multiline: false,
|
|
1065
|
+
inputType: "text",
|
|
949
1066
|
options: [],
|
|
950
1067
|
placeholder: "",
|
|
951
1068
|
prop: ps.name || prop,
|
|
@@ -1032,6 +1149,29 @@ function deriveField(prop: string, ps: JsonSchema, args: DeriveArgs): SchemaForm
|
|
|
1032
1149
|
}
|
|
1033
1150
|
}
|
|
1034
1151
|
|
|
1152
|
+
/* An image field (`format: "image"`) is the registered `media` control: the same field, Upload and
|
|
1153
|
+
Browse the page's Icon and OG Image rows draw (`surfaces/media-field.json`), so a collection
|
|
1154
|
+
entry's picture is picked from the project's media rather than typed as a path. Unregistered
|
|
1155
|
+
(a bare-Bun import of this engine), it falls through to the text control below. */
|
|
1156
|
+
if (ps.format === "image") {
|
|
1157
|
+
const media = controlRegistry.get("media");
|
|
1158
|
+
if (media) {
|
|
1159
|
+
plan.commit = "none";
|
|
1160
|
+
plan.control = media;
|
|
1161
|
+
row.kind = "control";
|
|
1162
|
+
return row;
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
/* An image OBJECT (`{ src, alt, width, height }`) is the same media field over its `src`; its
|
|
1166
|
+
`alt` is a text row of its own (`deriveFields`). Unregistered, it falls through to JSON. */
|
|
1167
|
+
const imageMedia = isImageObjectSchema(ps) ? controlRegistry.get("media") : undefined;
|
|
1168
|
+
if (imageMedia) {
|
|
1169
|
+
plan.commit = "none";
|
|
1170
|
+
plan.control = imageObjectControl(imageMedia);
|
|
1171
|
+
row.kind = "control";
|
|
1172
|
+
return row;
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1035
1175
|
/* SAFETY: both sources are read from JSON — the descriptor's `$studio.settings.entry.ui` and the
|
|
1036
1176
|
field schema — so whichever `enum` is present is a JSON value. */
|
|
1037
1177
|
const enumSource = (opts.ui?.[prop]?.enum ?? ps.enum) as JsonValue | undefined;
|
|
@@ -1081,6 +1221,9 @@ function deriveField(prop: string, ps: JsonSchema, args: DeriveArgs): SchemaForm
|
|
|
1081
1221
|
if (ps.type === "array" && ps.items?.type === "object" && ps.items.properties) {
|
|
1082
1222
|
return arrayOfObjects(prop, ps.items.properties, args, plan, row);
|
|
1083
1223
|
}
|
|
1224
|
+
if (ps.type === "array" && isSingleValueSchema(ps.items)) {
|
|
1225
|
+
return arrayOfSingleValues(prop, ps.items, args, plan, row);
|
|
1226
|
+
}
|
|
1084
1227
|
/* A union with an object or a list in it (`alerts` is an object of types or `false`) is JSON too:
|
|
1085
1228
|
a text box would store what is typed as a string, which is none of the members. */
|
|
1086
1229
|
const types = Array.isArray(ps.type) ? ps.type : [ps.type];
|
|
@@ -1095,9 +1238,27 @@ function deriveField(prop: string, ps: JsonSchema, args: DeriveArgs): SchemaForm
|
|
|
1095
1238
|
row.kind = "text";
|
|
1096
1239
|
row.value = asText(current);
|
|
1097
1240
|
row.placeholder = ps.default !== undefined ? String(ps.default) : (ps.examples?.[0] ?? "");
|
|
1241
|
+
row.inputType = TEXT_INPUT_TYPES.get(ps.format ?? "") ?? "text";
|
|
1242
|
+
/* A date input shows nothing for a value it cannot read, so a timestamp is shown as its day. YAML
|
|
1243
|
+
reads an unquoted date as a Date, which reaches here as its quoted JSON. */
|
|
1244
|
+
const day = /^"?(\d{4}-\d{2}-\d{2})/.exec(row.value);
|
|
1245
|
+
if (row.inputType === "date" && day) {
|
|
1246
|
+
row.value = day[1] ?? row.value;
|
|
1247
|
+
}
|
|
1098
1248
|
return row;
|
|
1099
1249
|
}
|
|
1100
1250
|
|
|
1251
|
+
/**
|
|
1252
|
+
* The native input a string format is typed in. `date` is the one that changes what can be typed: a
|
|
1253
|
+
* date picker, and a value that is always `YYYY-MM-DD`, the `full-date` JSON Schema's `date` names.
|
|
1254
|
+
* `email` and `uri` only change the keyboard a phone shows, and the value stays the text typed.
|
|
1255
|
+
*/
|
|
1256
|
+
const TEXT_INPUT_TYPES: ReadonlyMap<string, string> = new Map([
|
|
1257
|
+
["date", "date"],
|
|
1258
|
+
["email", "email"],
|
|
1259
|
+
["uri", "url"],
|
|
1260
|
+
]);
|
|
1261
|
+
|
|
1101
1262
|
/** The property chips above a JSON-Schema field: what shape is in there right now. */
|
|
1102
1263
|
function schemaPropertyChips(current: JsonValue | undefined): { key: string; label: string }[] {
|
|
1103
1264
|
// An array names no `properties`, so it has no chips either.
|
|
@@ -1137,6 +1298,69 @@ function arrayOfObjects(
|
|
|
1137
1298
|
return row;
|
|
1138
1299
|
}
|
|
1139
1300
|
|
|
1301
|
+
/** The one cell key a row of an array of single values is drawn under. */
|
|
1302
|
+
const SCALAR_CELL = "value";
|
|
1303
|
+
|
|
1304
|
+
/**
|
|
1305
|
+
* Whether an array's items are single values a cell can edit: text, a number, a yes/no, one of an
|
|
1306
|
+
* enum, or an entry of another collection. A picture is text with `format: "image"`, so it is one.
|
|
1307
|
+
*/
|
|
1308
|
+
function isSingleValueSchema(items: JsonSchema | undefined): items is JsonSchema {
|
|
1309
|
+
if (items === undefined || items.format === "json-schema") {
|
|
1310
|
+
return false;
|
|
1311
|
+
}
|
|
1312
|
+
if (referenceTarget(items) !== null || Array.isArray(items.enum)) {
|
|
1313
|
+
return true;
|
|
1314
|
+
}
|
|
1315
|
+
return (
|
|
1316
|
+
items.type === "string" ||
|
|
1317
|
+
items.type === "number" ||
|
|
1318
|
+
items.type === "integer" ||
|
|
1319
|
+
items.type === "boolean"
|
|
1320
|
+
);
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
/**
|
|
1324
|
+
* An array of single values (`categories: string[]`, a gallery's picture paths): one row per item,
|
|
1325
|
+
* each a single cell drawn by the item schema, with the same remove and add an array of objects
|
|
1326
|
+
* gets. A value that is not yet a list (a CSV cell holding one category) is shown as its one item,
|
|
1327
|
+
* and becomes a list the moment it is edited; the field's own check still says it is not one.
|
|
1328
|
+
*/
|
|
1329
|
+
function arrayOfSingleValues(
|
|
1330
|
+
prop: string,
|
|
1331
|
+
items: JsonSchema,
|
|
1332
|
+
args: DeriveArgs,
|
|
1333
|
+
plan: FieldPlan,
|
|
1334
|
+
row: SchemaFormFieldView,
|
|
1335
|
+
): SchemaFormFieldView {
|
|
1336
|
+
const held = args.value[prop];
|
|
1337
|
+
let list: JsonValue[] = [];
|
|
1338
|
+
if (Array.isArray(held)) {
|
|
1339
|
+
list = held;
|
|
1340
|
+
} else if (held !== undefined && held !== null && held !== "") {
|
|
1341
|
+
list = [held];
|
|
1342
|
+
}
|
|
1343
|
+
const rows: JsonObject[] = list.map((item) => ({ [SCALAR_CELL]: item }));
|
|
1344
|
+
const itemProps = { [SCALAR_CELL]: items };
|
|
1345
|
+
const label = args.opts.ui?.[prop]?.label ?? prop;
|
|
1346
|
+
plan.commit = "none";
|
|
1347
|
+
plan.itemProps = itemProps;
|
|
1348
|
+
plan.rows = rows;
|
|
1349
|
+
plan.scalarItems = true;
|
|
1350
|
+
plan.cellControls = new Map();
|
|
1351
|
+
plan.refCells = new Set();
|
|
1352
|
+
row.kind = "rows";
|
|
1353
|
+
row.rows = rows.map((item, idx) => {
|
|
1354
|
+
const drawn = deriveRow(prop, String(idx), item, itemProps, args, plan);
|
|
1355
|
+
// A row has one cell, so the cell is named by its place in the list rather than by `value`.
|
|
1356
|
+
for (const cell of drawn.cells) {
|
|
1357
|
+
cell.label = `${label} ${idx + 1}`;
|
|
1358
|
+
}
|
|
1359
|
+
return drawn;
|
|
1360
|
+
});
|
|
1361
|
+
return row;
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1140
1364
|
function deriveRow(
|
|
1141
1365
|
prop: string,
|
|
1142
1366
|
key: string,
|
|
@@ -1182,10 +1406,10 @@ function deriveCell(
|
|
|
1182
1406
|
return cell;
|
|
1183
1407
|
}
|
|
1184
1408
|
if (referenceTarget(cellSchema) !== null) {
|
|
1185
|
-
/* A CELL's control is mounted into a host of the cell's own, exactly as a field's is: the
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1409
|
+
/* A CELL's control is mounted into a host of the cell's own, exactly as a field's is: the
|
|
1410
|
+
reference picker is a document now (`surfaces/reference-field.json`), as the media field
|
|
1411
|
+
below is. What the cell host must never become is a second writer of a node the document
|
|
1412
|
+
already owns. */
|
|
1189
1413
|
const reference = controlRegistry.get("reference");
|
|
1190
1414
|
if (reference) {
|
|
1191
1415
|
cell.kind = "control";
|
|
@@ -1198,6 +1422,14 @@ function deriveCell(
|
|
|
1198
1422
|
return cell;
|
|
1199
1423
|
}
|
|
1200
1424
|
}
|
|
1425
|
+
/* A picture cell (`format: "image"`, a gallery's item) is the media control a picture FIELD
|
|
1426
|
+
gets, mounted into the cell's host by the same dispatch. */
|
|
1427
|
+
const media = cellSchema.format === "image" ? controlRegistry.get("media") : undefined;
|
|
1428
|
+
if (media) {
|
|
1429
|
+
cell.kind = "control";
|
|
1430
|
+
plan.cellControls?.set(id, { control: media, key: cellKey, row: rowKey, schema: cellSchema });
|
|
1431
|
+
return cell;
|
|
1432
|
+
}
|
|
1201
1433
|
// SAFETY: an item property's schema is read from JSON, so its `enum` is a JSON value.
|
|
1202
1434
|
const enumValues = resolveFormEnum(
|
|
1203
1435
|
cellSchema.enum as JsonValue | undefined,
|
package/src/ui/virtual-window.ts
CHANGED
|
@@ -330,7 +330,7 @@ export function scrollerFor(list: HTMLElement): HTMLElement | null {
|
|
|
330
330
|
if (cached && cached.isConnected && list.isConnected && cached.contains(list)) {
|
|
331
331
|
return cached;
|
|
332
332
|
}
|
|
333
|
-
const found = nearestScroller(list);
|
|
333
|
+
const found = declaredScroller(list) ?? nearestScroller(list);
|
|
334
334
|
if (found) {
|
|
335
335
|
scrollerCache.set(list, found);
|
|
336
336
|
} else {
|
|
@@ -339,6 +339,31 @@ export function scrollerFor(list: HTMLElement): HTMLElement | null {
|
|
|
339
339
|
return found;
|
|
340
340
|
}
|
|
341
341
|
|
|
342
|
+
/**
|
|
343
|
+
* The attribute a host stamps on the element it KNOWS scrolls the lists drawn inside it.
|
|
344
|
+
*
|
|
345
|
+
* `#left-panel` is the one scroller every Navigator panel draws in (its dock's root is `display:
|
|
346
|
+
* contents`), and the shell says so in `surfaces/shell.json`.
|
|
347
|
+
*/
|
|
348
|
+
export const SCROLLER_ATTR = "data-jx-scroller";
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* The scroller a host declared for `list`, found by a node walk that reads no layout, or null.
|
|
352
|
+
*
|
|
353
|
+
* {@link nearestScroller}'s walk reads `scrollHeight`, `clientHeight` and computed overflow on every
|
|
354
|
+
* ancestor, and the moment a list is bound is the moment its panel has just been drawn, so the
|
|
355
|
+
* first read pays a style recalculation of the whole half-written document. The cache cannot help
|
|
356
|
+
* there: the Files tree and the Outline are new elements each time their panel is shown again, so
|
|
357
|
+
* every show of either one walked (12 to 32 ms a show in the perf trace). A declared scroller
|
|
358
|
+
* answers by identity. It carries the memoized answer's one residue: it is the scroller whether or
|
|
359
|
+
* not its content overflows right now, and a list that fits is windowed to the whole list, which is
|
|
360
|
+
* what {@link computeWindow} answers for it anyway. Only a CONNECTED list asks: a list still being
|
|
361
|
+
* built is not inside its scroller yet.
|
|
362
|
+
*/
|
|
363
|
+
function declaredScroller(list: HTMLElement): HTMLElement | null {
|
|
364
|
+
return list.isConnected ? list.closest<HTMLElement>(`[${SCROLLER_ATTR}]`) : null;
|
|
365
|
+
}
|
|
366
|
+
|
|
342
367
|
/**
|
|
343
368
|
* How far `list`'s first row has scrolled above the top of `scroller`'s viewport.
|
|
344
369
|
*
|
package/src/utils/base64.ts
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* Base64 encoding for binary payloads that cross an RPC boundary.
|
|
4
4
|
*
|
|
5
5
|
* `StudioPlatform.uploadFile` accepts `string | File | Blob | ArrayBuffer`, but the RPC platforms
|
|
6
|
-
* (
|
|
7
|
-
* Those platforms encode here before the call; the HTTP platforms (dev server, cloud) post
|
|
8
|
-
* binary body directly and must NOT use this.
|
|
6
|
+
* (the chromium desktop shell) JSON-serialize their params — a `File`/`Blob` becomes `{}` on the
|
|
7
|
+
* wire. Those platforms encode here before the call; the HTTP platforms (dev server, cloud) post
|
|
8
|
+
* the binary body directly and must NOT use this.
|
|
9
9
|
*
|
|
10
10
|
* {@link base64ToBytes} is the same boundary in the other direction, for `readFileBytes`: the RPC
|
|
11
11
|
* backends answer a base64 string for the same reason they accept one, and the caller wants bytes.
|