@jxsuite/studio 2.0.0 → 2.1.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/canvas.html +21 -0
- package/dist/chunks/Overlay.dev-qfjzkms8.js +23 -0
- package/dist/chunks/{Overlay.dev-cszx7yn5.js.map → Overlay.dev-qfjzkms8.js.map} +1 -1
- package/dist/chunks/{adapter-z8fkmbmv.js → adapter-qfnesn5v.js} +2 -2
- package/dist/chunks/{cf-settings-mmyv436d.js → cf-settings-73sh5z4p.js} +3 -3
- package/dist/chunks/{components-0hzentwq.js → components-2bpqp4mq.js} +5 -7
- package/dist/chunks/{components-0hzentwq.js.map → components-2bpqp4mq.js.map} +1 -1
- package/dist/chunks/content-source-34gnkbnn.js +38 -0
- package/dist/chunks/content-source-34gnkbnn.js.map +9 -0
- package/dist/chunks/convert-to-repeater-t8kxre5s.js +258 -0
- package/dist/chunks/convert-to-repeater-t8kxre5s.js.map +10 -0
- package/dist/chunks/extension-sections-6mqydz35.js +301 -0
- package/dist/chunks/extension-sections-6mqydz35.js.map +11 -0
- package/dist/chunks/files-8kn321h1.js +70 -0
- package/dist/chunks/files-8kn321h1.js.map +9 -0
- package/dist/chunks/{format-host-2c188n41.js → format-host-mkwsmt8d.js} +3 -3
- package/dist/chunks/git-panel-tjbr191d.js +51 -0
- package/dist/chunks/git-panel-tjbr191d.js.map +9 -0
- package/dist/chunks/{index-baeg2x3y.js → index-7pxchcce.js} +4 -3
- package/dist/chunks/{index-baeg2x3y.js.map → index-7pxchcce.js.map} +3 -3
- package/dist/chunks/{jx-validate-qx8degj7.js → jx-validate-v6qgknrs.js} +3 -3
- package/dist/chunks/layers-panel-87pb25km.js +58 -0
- package/dist/chunks/layers-panel-87pb25km.js.map +9 -0
- package/dist/chunks/{monaco-setup-zjdp9zdw.js → monaco-setup-e0yh25j4.js} +4 -75
- package/dist/chunks/{monaco-setup-zjdp9zdw.js.map → monaco-setup-e0yh25j4.js.map} +3 -4
- package/dist/chunks/publish-panel-m0fcgdrt.js +21 -0
- package/dist/chunks/publish-panel-m0fcgdrt.js.map +9 -0
- package/dist/chunks/quick-search-rhs6cbsb.js +53 -0
- package/dist/chunks/quick-search-rhs6cbsb.js.map +9 -0
- package/dist/chunks/right-panel-zpdxd98t.js +37 -0
- package/dist/chunks/right-panel-zpdxd98t.js.map +9 -0
- package/dist/chunks/section-registry-zmckaxf4.js +30 -0
- package/dist/chunks/section-registry-zmckaxf4.js.map +9 -0
- package/dist/chunks/sp-overlay.dev-9ran0sfq.js +18 -0
- package/dist/chunks/sp-overlay.dev-9ran0sfq.js.map +9 -0
- package/dist/chunks/sp-popover.dev-rebmdncr.js +9 -0
- package/dist/chunks/sp-popover.dev-rebmdncr.js.map +9 -0
- package/dist/chunks/sp-progress-circle.dev-5vkppfkt.js +15 -0
- package/dist/chunks/sp-progress-circle.dev-5vkppfkt.js.map +9 -0
- package/dist/chunks/sp-tooltip.dev-ykqrg8h5.js +15 -0
- package/dist/chunks/sp-tooltip.dev-ykqrg8h5.js.map +9 -0
- package/dist/chunks/{sp-tray.dev-pb2fsd65.js → sp-tray.dev-ey59vfh7.js} +10 -8
- package/dist/chunks/{sp-tray.dev-pb2fsd65.js.map → sp-tray.dev-ey59vfh7.js.map} +2 -2
- package/dist/chunks/{studio-9qr6fq7p.js → studio-0rqqhrdy.js} +10 -378
- package/dist/chunks/{studio-9qr6fq7p.js.map → studio-0rqqhrdy.js.map} +4 -14
- package/dist/chunks/{studio-5x6tqqec.js → studio-2sj1jj3v.js} +10 -8
- package/dist/chunks/{studio-5x6tqqec.js.map → studio-2sj1jj3v.js.map} +2 -2
- package/dist/chunks/{studio-h3fw0wn8.js → studio-3fk1ac9z.js} +6 -4
- package/dist/chunks/{studio-h3fw0wn8.js.map → studio-3fk1ac9z.js.map} +2 -2
- package/dist/chunks/studio-41exgzhq.js +6690 -0
- package/dist/chunks/studio-41exgzhq.js.map +38 -0
- package/dist/chunks/{studio-7v2bpweq.js → studio-4mqb9a0j.js} +6 -4
- package/dist/chunks/{studio-7v2bpweq.js.map → studio-4mqb9a0j.js.map} +2 -2
- package/dist/chunks/studio-50k77cca.js +1787 -0
- package/dist/chunks/studio-50k77cca.js.map +18 -0
- package/dist/chunks/{studio-56v3zwk6.js → studio-6a0h7sne.js} +10 -8
- package/dist/chunks/{studio-56v3zwk6.js.map → studio-6a0h7sne.js.map} +2 -2
- package/dist/chunks/studio-6f0am8f2.js +53 -0
- package/dist/chunks/studio-6f0am8f2.js.map +10 -0
- package/dist/chunks/studio-6nmjc5qk.js +7002 -0
- package/dist/chunks/studio-6nmjc5qk.js.map +32 -0
- package/dist/chunks/studio-7afd21nw.js +67 -0
- package/dist/chunks/studio-7afd21nw.js.map +10 -0
- package/dist/chunks/{studio-xze4zrs1.js → studio-7bmdvzne.js} +2 -2
- package/dist/chunks/studio-7bmdvzne.js.map +10 -0
- package/dist/chunks/studio-8jpzqk5s.js +128 -0
- package/dist/chunks/studio-8jpzqk5s.js.map +10 -0
- package/dist/chunks/studio-94m77tgk.js +1482 -0
- package/dist/chunks/studio-94m77tgk.js.map +13 -0
- package/dist/chunks/studio-9je6w5sq.js +1000 -0
- package/dist/chunks/studio-9je6w5sq.js.map +16 -0
- package/dist/chunks/{studio-w7c6kvk7.js → studio-a7pzveq1.js} +2 -2
- package/dist/chunks/{studio-97qcgvdn.js → studio-adn0z1k3.js} +14 -8
- package/dist/chunks/{studio-97qcgvdn.js.map → studio-adn0z1k3.js.map} +3 -3
- package/dist/chunks/{studio-kr88ryr7.js → studio-bsxxx3x2.js} +17 -15
- package/dist/chunks/{studio-kr88ryr7.js.map → studio-bsxxx3x2.js.map} +7 -6
- package/dist/chunks/studio-bw5dz6km.js +608 -0
- package/dist/chunks/studio-bw5dz6km.js.map +21 -0
- package/dist/chunks/studio-c6s5getc.js +4232 -0
- package/dist/chunks/studio-c6s5getc.js.map +39 -0
- package/dist/chunks/studio-cjm7fdjf.js +451 -0
- package/dist/chunks/studio-cjm7fdjf.js.map +14 -0
- package/dist/chunks/{studio-cx91mnh8.js → studio-ckwz4d3x.js} +53 -53
- package/dist/chunks/{studio-cx91mnh8.js.map → studio-ckwz4d3x.js.map} +5 -5
- package/dist/chunks/studio-dg7zyt5x.js +28 -0
- package/dist/chunks/studio-dg7zyt5x.js.map +10 -0
- package/dist/chunks/studio-dzcyvvvz.js +166 -0
- package/dist/chunks/studio-dzcyvvvz.js.map +10 -0
- package/dist/chunks/{studio-7kqe41sa.js → studio-evkr5d3b.js} +15 -7
- package/dist/chunks/{studio-7kqe41sa.js.map → studio-evkr5d3b.js.map} +5 -4
- package/dist/chunks/studio-f12h6177.js +411 -0
- package/dist/chunks/studio-f12h6177.js.map +13 -0
- package/dist/chunks/studio-hbp1s8m9.js +1817 -0
- package/dist/chunks/studio-hbp1s8m9.js.map +14 -0
- package/dist/chunks/studio-k2sxjph5.js +15295 -0
- package/dist/chunks/studio-k2sxjph5.js.map +235 -0
- package/dist/chunks/studio-myje51t3.js +385 -0
- package/dist/chunks/studio-myje51t3.js.map +12 -0
- package/dist/chunks/studio-na6rwzhw.js +353 -0
- package/dist/chunks/studio-na6rwzhw.js.map +11 -0
- package/dist/chunks/{studio-4k0m4fmp.js → studio-p471gg5n.js} +126 -3
- package/dist/chunks/studio-p471gg5n.js.map +14 -0
- package/dist/chunks/{studio-9bjwf0d4.js → studio-rgwcpast.js} +5 -46
- package/dist/chunks/{studio-9bjwf0d4.js.map → studio-rgwcpast.js.map} +4 -5
- package/dist/chunks/{studio-hhj92gcr.js → studio-s519zc99.js} +3 -3
- package/dist/chunks/studio-sas7mt3k.js +75 -0
- package/dist/chunks/studio-sas7mt3k.js.map +10 -0
- package/dist/chunks/studio-t5wqwzdh.js +74 -0
- package/dist/chunks/studio-t5wqwzdh.js.map +10 -0
- package/dist/chunks/{studio-9qpspwfn.js → studio-temv5bw4.js} +5 -5
- package/dist/chunks/{studio-9qpspwfn.js.map → studio-temv5bw4.js.map} +1 -1
- package/dist/chunks/{studio-qkvt37c0.js → studio-tr20m8g8.js} +669 -18
- package/dist/chunks/studio-tr20m8g8.js.map +9 -0
- package/dist/chunks/{studio-ygzav7z5.js → studio-v96qfnww.js} +5514 -4291
- package/dist/chunks/studio-v96qfnww.js.map +54 -0
- package/dist/chunks/studio-vcetc91k.js +659 -0
- package/dist/chunks/studio-vcetc91k.js.map +10 -0
- package/dist/chunks/{studio-n9zmpxjg.js → studio-vmymjefp.js} +2972 -4937
- package/dist/chunks/studio-vmymjefp.js.map +98 -0
- package/dist/chunks/{studio-bghqfmea.js → studio-wwseqyw0.js} +2 -2
- package/dist/chunks/studio-x9hmy5kr.js +390 -0
- package/dist/chunks/studio-x9hmy5kr.js.map +10 -0
- package/dist/chunks/studio-xa0ce0n7.js +335 -0
- package/dist/chunks/studio-xa0ce0n7.js.map +10 -0
- package/dist/chunks/studio-xm3dbxvn.js +378 -0
- package/dist/chunks/studio-xm3dbxvn.js.map +19 -0
- package/dist/chunks/{studio-nqw433kv.js → studio-xmvbhg31.js} +2 -2
- package/dist/chunks/studio-zv37yrfa.js +1054 -0
- package/dist/chunks/studio-zv37yrfa.js.map +13 -0
- package/dist/chunks/{ws-client-q7hkz3j9.js → ws-client-654ts66j.js} +6 -4
- package/dist/chunks/ws-client-654ts66j.js.map +11 -0
- package/dist/iframe-entry.js +668 -230
- package/dist/studio.js +23711 -35185
- package/index.html +35 -4685
- package/package.json +17 -15
- package/src/about/about-modal.ts +42 -11
- package/src/browse/library-commands.ts +240 -0
- package/src/browse/library-layouts.ts +369 -0
- package/src/browse/library-model.ts +396 -0
- package/src/browse/library-pane.ts +1049 -0
- package/src/browse/library-preview.ts +252 -0
- package/src/browse/library-source.ts +150 -0
- package/src/canvas/canvas-helpers.ts +33 -9
- package/src/canvas/canvas-live-render.ts +45 -29
- package/src/canvas/canvas-patcher.ts +151 -31
- package/src/canvas/canvas-perf.ts +46 -7
- package/src/canvas/canvas-render.ts +1092 -220
- package/src/canvas/canvas-surface.ts +240 -0
- package/src/canvas/canvas-utils.ts +1166 -124
- package/src/canvas/iframe-drop.ts +2 -1
- package/src/canvas/iframe-entry.ts +241 -4
- package/src/canvas/iframe-host.ts +1226 -143
- package/src/canvas/iframe-inline-edit.ts +31 -0
- package/src/canvas/iframe-interaction.ts +76 -16
- package/src/canvas/iframe-keys.ts +107 -45
- package/src/canvas/iframe-overlay.ts +38 -1
- package/src/canvas/iframe-protocol.ts +137 -2
- package/src/canvas/iframe-render.ts +70 -2
- package/src/canvas/iframe-slash.ts +6 -0
- package/src/canvas/path-mapping.ts +56 -6
- package/src/canvas/surface-registry.ts +292 -0
- package/src/collab/collab-commands.ts +244 -0
- package/src/collab/collab-session.ts +198 -32
- package/src/collab/collab-state.ts +28 -2
- package/src/collab/presence-chips.ts +100 -9
- package/src/commands/active-registry.ts +42 -0
- package/src/commands/app-commands.ts +176 -0
- package/src/commands/budget.ts +158 -0
- package/src/commands/command-args.ts +253 -0
- package/src/commands/context.ts +387 -0
- package/src/commands/defaults.ts +580 -0
- package/src/commands/keymap.ts +571 -0
- package/src/commands/levels.ts +345 -0
- package/src/commands/live-context.ts +193 -0
- package/src/commands/reference.ts +227 -0
- package/src/commands/registry.ts +293 -0
- package/src/component-props.ts +3 -2
- package/src/content/draft-state.ts +106 -0
- package/src/content/entry-commands.ts +282 -0
- package/src/content/entry-editor.ts +327 -0
- package/src/content/entry-fields.ts +116 -0
- package/src/content/entry-model.ts +175 -0
- package/src/editor/canvas-context-menu.ts +17 -11
- package/src/editor/canvas-slash-bridge.ts +11 -4
- package/src/editor/context-menu.ts +804 -204
- package/src/editor/convert-to-component.ts +31 -10
- package/src/editor/convert-to-repeater.ts +3 -2
- package/src/editor/inline-edit-apply.ts +5 -5
- package/src/editor/inline-edit.ts +86 -50
- package/src/editor/insert-zone-action.ts +1 -1
- package/src/editor/shortcuts.ts +1043 -329
- package/src/editor/slash-menu.ts +1 -0
- package/src/files/elements.ts +166 -0
- package/src/files/file-ops.ts +178 -31
- package/src/files/files.ts +898 -268
- package/src/files/fs-events.ts +21 -0
- package/src/files/media-meta.ts +203 -0
- package/src/files/media-paths.ts +141 -0
- package/src/files/media-upload.ts +7 -3
- package/src/files/media-usage.ts +189 -0
- package/src/github/github-auth.ts +235 -33
- package/src/github/github-publish.ts +80 -21
- package/src/grid/grid-controller.ts +152 -12
- package/src/grid/grid-layout.ts +225 -20
- package/src/grid/grid-open.ts +120 -0
- package/src/grid/grid-panel.ts +554 -39
- package/src/grid/grid-source.ts +27 -1
- package/src/grid/redirects-grid.ts +599 -0
- package/src/grid/redirects.ts +398 -0
- package/src/grid/sources/content-source.ts +108 -2
- package/src/i18n/i18n-commands.ts +322 -0
- package/src/new-project/add-repo-modal.ts +8 -10
- package/src/new-project/import-tab.ts +34 -9
- package/src/new-project/location-fields.ts +9 -1
- package/src/new-project/new-project-modal.ts +270 -262
- package/src/packages/jxsuite-update.ts +97 -48
- package/src/packages/pull-package-sync.ts +18 -9
- package/src/page-params.ts +2 -1
- package/src/panels/activity-bar.ts +152 -91
- package/src/panels/activity-panel.ts +481 -0
- package/src/panels/ai-chat/chat-markdown.ts +8 -3
- package/src/panels/ai-chat/chat-view.ts +245 -18
- package/src/panels/ai-chat/composer.ts +31 -5
- package/src/panels/ai-chat/sessions-view.ts +17 -10
- package/src/panels/ai-panel.ts +279 -120
- package/src/panels/block-action-bar.ts +1115 -224
- package/src/panels/bottom-dock.ts +337 -0
- package/src/panels/canvas-dnd-bridge.ts +37 -8
- package/src/panels/chat-panel.ts +29 -12
- package/src/panels/data-explorer.ts +254 -112
- package/src/panels/data-grid.ts +10 -4
- package/src/panels/dnd.ts +28 -51
- package/src/panels/editors.ts +434 -107
- package/src/panels/elements-panel.ts +66 -2
- package/src/panels/empty-state.ts +112 -0
- package/src/panels/events-panel.ts +596 -82
- package/src/panels/formula-workspace.ts +408 -218
- package/src/panels/frontmatter-fields.ts +51 -10
- package/src/panels/frontmatter-panel.ts +357 -79
- package/src/panels/git-panel.ts +375 -164
- package/src/panels/head-panel.ts +791 -85
- package/src/panels/i18n-panel.ts +592 -0
- package/src/panels/imports-panel.ts +95 -85
- package/src/panels/jump-bar.ts +584 -0
- package/src/panels/layers-panel.ts +1106 -328
- package/src/panels/left-panel.ts +109 -204
- package/src/panels/navigator-panels.ts +131 -0
- package/src/panels/overlays.ts +7 -2
- package/src/panels/pane-context.ts +1477 -0
- package/src/panels/pane-grid.ts +406 -0
- package/src/panels/panel-registry.ts +340 -0
- package/src/panels/panel-scheduler.ts +75 -0
- package/src/panels/problems-panel.ts +234 -0
- package/src/panels/properties-panel.ts +946 -1139
- package/src/panels/provenance.ts +258 -0
- package/src/panels/quick-search.ts +791 -122
- package/src/panels/right-panel.ts +228 -102
- package/src/panels/seo-modal.ts +395 -0
- package/src/panels/settings-pane.ts +203 -0
- package/src/panels/signals-panel.ts +354 -137
- package/src/panels/statement-editor.ts +41 -25
- package/src/panels/statusbar.ts +342 -106
- package/src/panels/style-panel.ts +974 -463
- package/src/panels/style-utils.ts +3 -3
- package/src/panels/stylebook-doc.ts +4 -2
- package/src/panels/stylebook-layers-panel.ts +3 -2
- package/src/panels/stylebook-panel.ts +51 -26
- package/src/panels/tab-strip.ts +1058 -78
- package/src/panels/target-line.ts +274 -0
- package/src/panels/toolbar.ts +631 -484
- package/src/panels/welcome-screen.ts +301 -198
- package/src/platform-errors.ts +26 -3
- package/src/platform.ts +96 -2
- package/src/platforms/cloud.ts +71 -8
- package/src/platforms/devserver.ts +92 -29
- package/src/publish/deploy-checklist.ts +383 -0
- package/src/publish/pages-service.ts +10 -1
- package/src/publish/publish-commands.ts +218 -0
- package/src/publish/publish-panel.ts +110 -16
- package/src/recent-projects.ts +3 -2
- package/src/services/a11y-report.ts +505 -0
- package/src/services/ai-models.ts +75 -2
- package/src/services/ai-project-tools.ts +29 -10
- package/src/services/ai-system-prompt.ts +53 -14
- package/src/services/ai-tools.ts +39 -3
- package/src/services/ai-writes.ts +154 -0
- package/src/services/announce.ts +97 -0
- package/src/services/automation.ts +424 -175
- package/src/services/cem-export.ts +9 -4
- package/src/services/clock.ts +61 -0
- package/src/services/document-assistant.ts +36 -8
- package/src/services/idle.ts +179 -0
- package/src/services/import-client.ts +26 -0
- package/src/services/monaco-buffer.ts +627 -0
- package/src/services/monaco-lazy.ts +36 -0
- package/src/services/notify.ts +271 -0
- package/src/services/profile.ts +155 -0
- package/src/services/references.ts +0 -0
- package/src/services/token-lint.ts +3 -2
- package/src/services/tool-executor.ts +53 -7
- package/src/services/trusted-types.ts +123 -0
- package/src/settings/contexts-section.ts +427 -0
- package/src/settings/contributed-section.ts +149 -11
- package/src/settings/css-vars-editor.ts +306 -349
- package/src/settings/defs-editor.ts +93 -34
- package/src/settings/dependencies-editor.ts +7 -7
- package/src/settings/extension-sections.ts +37 -5
- package/src/settings/general-settings.ts +204 -121
- package/src/settings/locales-section.ts +347 -0
- package/src/settings/preferences-accounts.ts +140 -0
- package/src/settings/preferences-dialog.ts +620 -0
- package/src/settings/preferences-keymap.ts +270 -0
- package/src/settings/project-sections.ts +260 -0
- package/src/settings/section-registry.ts +169 -0
- package/src/settings/settings-document.ts +385 -0
- package/src/shell.ts +1549 -0
- package/src/site-context.ts +45 -20
- package/src/state.ts +14 -275
- package/src/store.ts +88 -43
- package/src/studio.ts +790 -346
- package/src/style/live-preview.ts +36 -0
- package/src/style/project-styles.ts +349 -0
- package/src/style/token-ref.ts +123 -0
- package/src/tabs/patch-ops.ts +16 -4
- package/src/tabs/project-config.ts +416 -0
- package/src/tabs/selection.ts +323 -0
- package/src/tabs/tab.ts +182 -47
- package/src/tabs/transact.ts +209 -28
- package/src/types.ts +68 -13
- package/src/ui/ai-credentials-form.ts +39 -35
- package/src/ui/ai-managed-connect.ts +113 -0
- package/src/ui/dynamic-slot.ts +224 -81
- package/src/ui/expression-editor.ts +71 -63
- package/src/ui/field-input.ts +4 -6
- package/src/ui/field-row.ts +215 -38
- package/src/ui/form-controls.ts +194 -7
- package/src/ui/layers.ts +492 -69
- package/src/ui/media-picker.ts +115 -25
- package/src/ui/panel-resize.ts +109 -91
- package/src/ui/progress-modal.ts +131 -50
- package/src/ui/regions.ts +462 -0
- package/src/ui/schema-form.ts +229 -45
- package/src/ui/spectrum.ts +24 -8
- package/src/ui/timing.ts +49 -0
- package/src/ui/value-selector.ts +20 -0
- package/src/ui/value-source.ts +348 -0
- package/src/ui/virtual-window.ts +400 -0
- package/src/utils/edit-display.ts +3 -2
- package/src/utils/inherited-style.ts +67 -37
- package/src/view.ts +64 -78
- package/src/workspace/pane-derive.ts +1258 -0
- package/src/workspace/session.ts +317 -0
- package/src/workspace/workspace.ts +1345 -23
- package/styles/canvas.css +653 -0
- package/styles/forced-colors.css +106 -0
- package/styles/inspector.css +1454 -0
- package/styles/overlays.css +2704 -0
- package/styles/panels.css +1701 -0
- package/styles/shell.css +1423 -0
- package/styles/tokens.css +151 -0
- package/dist/chunks/Overlay.dev-cszx7yn5.js +0 -22
- package/dist/chunks/extension-sections-qct0gt8f.js +0 -531
- package/dist/chunks/extension-sections-qct0gt8f.js.map +0 -12
- package/dist/chunks/files-02zn5y24.js +0 -50
- package/dist/chunks/files-02zn5y24.js.map +0 -9
- package/dist/chunks/git-panel-mbb0y0hz.js +0 -28
- package/dist/chunks/git-panel-mbb0y0hz.js.map +0 -9
- package/dist/chunks/layers-panel-9qekmqk1.js +0 -26
- package/dist/chunks/layers-panel-9qekmqk1.js.map +0 -9
- package/dist/chunks/settings-modal-gj0hrah4.js +0 -29
- package/dist/chunks/settings-modal-gj0hrah4.js.map +0 -9
- package/dist/chunks/sp-overlay.dev-earn5as8.js +0 -17
- package/dist/chunks/sp-overlay.dev-earn5as8.js.map +0 -9
- package/dist/chunks/sp-popover.dev-frxtfejn.js +0 -8
- package/dist/chunks/sp-popover.dev-frxtfejn.js.map +0 -9
- package/dist/chunks/sp-progress-circle.dev-7tvw34h8.js +0 -14
- package/dist/chunks/sp-progress-circle.dev-7tvw34h8.js.map +0 -9
- package/dist/chunks/sp-tooltip.dev-a9fywesm.js +0 -21
- package/dist/chunks/sp-tooltip.dev-a9fywesm.js.map +0 -10
- package/dist/chunks/studio-4k0m4fmp.js.map +0 -13
- package/dist/chunks/studio-568nx4t5.js +0 -469
- package/dist/chunks/studio-568nx4t5.js.map +0 -14
- package/dist/chunks/studio-9smfzqhc.js +0 -19
- package/dist/chunks/studio-9smfzqhc.js.map +0 -10
- package/dist/chunks/studio-asvf0j9e.js +0 -429
- package/dist/chunks/studio-asvf0j9e.js.map +0 -13
- package/dist/chunks/studio-d77qm3pk.js +0 -3427
- package/dist/chunks/studio-d77qm3pk.js.map +0 -26
- package/dist/chunks/studio-j6gqyjf4.js +0 -1854
- package/dist/chunks/studio-j6gqyjf4.js.map +0 -18
- package/dist/chunks/studio-n9zmpxjg.js.map +0 -115
- package/dist/chunks/studio-qkvt37c0.js.map +0 -9
- package/dist/chunks/studio-rq0vxb19.js +0 -3744
- package/dist/chunks/studio-rq0vxb19.js.map +0 -22
- package/dist/chunks/studio-wd6ewdvd.js +0 -853
- package/dist/chunks/studio-wd6ewdvd.js.map +0 -12
- package/dist/chunks/studio-xq0t7n5t.js +0 -140
- package/dist/chunks/studio-xq0t7n5t.js.map +0 -10
- package/dist/chunks/studio-xze4zrs1.js.map +0 -10
- package/dist/chunks/studio-ygzav7z5.js.map +0 -46
- package/dist/chunks/studio-zmy7241e.js +0 -399
- package/dist/chunks/studio-zmy7241e.js.map +0 -12
- package/dist/chunks/ws-client-q7hkz3j9.js.map +0 -11
- package/src/browse/browse-modal.ts +0 -69
- package/src/browse/browse.ts +0 -904
- package/src/canvas/canvas-diff.ts +0 -216
- package/src/canvas/nested-site-style.ts +0 -58
- package/src/new-project/design-fields.ts +0 -264
- package/src/new-project/templates.ts +0 -61
- package/src/panels/tab-bar.ts +0 -548
- package/src/settings/settings-modal.ts +0 -203
- /package/dist/chunks/{adapter-z8fkmbmv.js.map → adapter-qfnesn5v.js.map} +0 -0
- /package/dist/chunks/{cf-settings-mmyv436d.js.map → cf-settings-73sh5z4p.js.map} +0 -0
- /package/dist/chunks/{format-host-2c188n41.js.map → format-host-mkwsmt8d.js.map} +0 -0
- /package/dist/chunks/{jx-validate-qx8degj7.js.map → jx-validate-v6qgknrs.js.map} +0 -0
- /package/dist/chunks/{studio-w7c6kvk7.js.map → studio-a7pzveq1.js.map} +0 -0
- /package/dist/chunks/{studio-hhj92gcr.js.map → studio-s519zc99.js.map} +0 -0
- /package/dist/chunks/{studio-bghqfmea.js.map → studio-wwseqyw0.js.map} +0 -0
- /package/dist/chunks/{studio-nqw433kv.js.map → studio-xmvbhg31.js.map} +0 -0
package/src/ui/schema-form.ts
CHANGED
|
@@ -5,9 +5,17 @@
|
|
|
5
5
|
* Maps schema property types to Spectrum controls (enum → picker, boolean → checkbox,
|
|
6
6
|
* number/integer → number-field, `json-schema` format → multiline JSON editor, array-of-objects →
|
|
7
7
|
* multi-row inline form, other array/object → JSON text field, default → textfield). Hosts commit
|
|
8
|
-
* edits through a single `onChange(patch)` callback; dynamic enum choices
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* edits through a single `onChange(patch)` callback; dynamic enum choices resolve through a
|
|
9
|
+
* {@link SchemaFormContext}. Custom controls register by name via {@link registerFormControl} and
|
|
10
|
+
* are consulted first for `ui` overrides.
|
|
11
|
+
*
|
|
12
|
+
* **Binding is the same ladder as everywhere else** (§6.6). A host that names somewhere a value can
|
|
13
|
+
* come from — route params, the document's signals — gets a Value Source chip on every scalar
|
|
14
|
+
* field, drawn by `ui/dynamic-slot.ts` and named by `ui/value-source.ts`. It replaces two things: a
|
|
15
|
+
* private `Static value / $params/… / Custom…` picker that mounted only when the field ALREADY held
|
|
16
|
+
* a `$ref` (so no form had a gesture for starting a binding at all), and a link button beside the
|
|
17
|
+
* textfield that silently committed the first route param. A host that names no source — the
|
|
18
|
+
* project settings forms — draws no chip and edits fixed values, exactly as before.
|
|
11
19
|
*/
|
|
12
20
|
|
|
13
21
|
import { html, nothing } from "lit-html";
|
|
@@ -16,7 +24,11 @@ import { live } from "lit-html/directives/live.js";
|
|
|
16
24
|
import { styleMap } from "lit-html/directives/style-map.js";
|
|
17
25
|
import { isRef } from "@jxsuite/schema/guards";
|
|
18
26
|
import { renderFieldRow } from "./field-row";
|
|
27
|
+
import { renderDynamicSlot } from "./dynamic-slot";
|
|
28
|
+
import { configFieldSchema } from "./value-source";
|
|
19
29
|
import type { TemplateResult } from "lit-html";
|
|
30
|
+
import type { SignalOption } from "./dynamic-slot";
|
|
31
|
+
import type { JsonValue } from "../types";
|
|
20
32
|
|
|
21
33
|
/** A (possibly nested) JSON Schema node, covering both object and property level keys. */
|
|
22
34
|
export interface JsonSchema {
|
|
@@ -32,6 +44,12 @@ export interface JsonSchema {
|
|
|
32
44
|
examples?: string[];
|
|
33
45
|
name?: string;
|
|
34
46
|
items?: JsonSchema;
|
|
47
|
+
/**
|
|
48
|
+
* A pointer to another schema. `#/content/<type>` is the one this engine acts on: it is how
|
|
49
|
+
* site-architecture.md §6.1 declares a relationship between collections, and it is what the
|
|
50
|
+
* schema-builder writes (`form-controls.ts`'s `onChangeRefTarget`).
|
|
51
|
+
*/
|
|
52
|
+
$ref?: string;
|
|
35
53
|
}
|
|
36
54
|
|
|
37
55
|
/** Host-provided context threaded to every control. */
|
|
@@ -40,7 +58,13 @@ export interface SchemaFormContext {
|
|
|
40
58
|
resolvePointer: (pointer: string, scope?: Record<string, unknown>) => unknown;
|
|
41
59
|
/** Route params available for `$ref` bindings (e.g. from the document path). */
|
|
42
60
|
params?: string[] | undefined;
|
|
43
|
-
/**
|
|
61
|
+
/**
|
|
62
|
+
* State keys a field may bind to. Together with {@link params} this is the whole answer to "where
|
|
63
|
+
* could this value come from" — and naming none of them is how a host says the form edits fixed
|
|
64
|
+
* values only, which is why the settings forms show no Value Source chip.
|
|
65
|
+
*/
|
|
66
|
+
signals?: string[] | undefined;
|
|
67
|
+
/** Unique prefix for the dynamic slot's per-field, per-rung value memory. */
|
|
44
68
|
fieldKeyPrefix?: string | undefined;
|
|
45
69
|
/**
|
|
46
70
|
* Commit hook for the "secret" control: stores the VALUE in the platform's secret store (never
|
|
@@ -73,6 +97,30 @@ export interface RenderFormOptions {
|
|
|
73
97
|
*/
|
|
74
98
|
ui?: Record<string, { control?: string; enum?: unknown }> | undefined;
|
|
75
99
|
rerender?: (() => void) | undefined;
|
|
100
|
+
/**
|
|
101
|
+
* Externally-produced diagnostics, keyed by property name — §7.1's inline tier, sourced.
|
|
102
|
+
*
|
|
103
|
+
* This is how a validator that runs over the WHOLE document reaches the one field it is about:
|
|
104
|
+
* `jx-validate`'s `project.json` errors (until now wired only to the AI's `write_project_config`,
|
|
105
|
+
* so a human editing the same file through Settings got no validation at all), Monaco's markers
|
|
106
|
+
* for the same file open in the code view, and a host's own commit-time rejection.
|
|
107
|
+
*
|
|
108
|
+
* A host message wins over {@link validateFieldValue}'s intrinsic check, because the host knows
|
|
109
|
+
* things the property schema alone does not — that this enum value names a connector that was
|
|
110
|
+
* just deleted, say. An empty string means "no error", so a host can pass a lookup result
|
|
111
|
+
* straight through.
|
|
112
|
+
*/
|
|
113
|
+
errors?: Record<string, string> | undefined;
|
|
114
|
+
/** How many times each field has been refused in a row; drives the row's repeat counter. */
|
|
115
|
+
errorCounts?: Record<string, number> | undefined;
|
|
116
|
+
/**
|
|
117
|
+
* Report required-but-empty fields inline. Off by default, and that default is §7.1's rule
|
|
118
|
+
* literally applied: a form the user has not touched yet has not committed anything, so painting
|
|
119
|
+
* every required field red the moment it renders is telling them they got something wrong before
|
|
120
|
+
* they did anything. Required-ness is already shown — the label carries a `*`. A host that
|
|
121
|
+
* validates on submit turns this on for the render that follows the rejected submit.
|
|
122
|
+
*/
|
|
123
|
+
showRequired?: boolean | undefined;
|
|
76
124
|
}
|
|
77
125
|
|
|
78
126
|
// ─── Control registry ────────────────────────────────────────────────────────
|
|
@@ -89,8 +137,30 @@ export function getFormControl(name: string): SchemaFormControl | undefined {
|
|
|
89
137
|
return controlRegistry.get(name);
|
|
90
138
|
}
|
|
91
139
|
|
|
92
|
-
|
|
93
|
-
|
|
140
|
+
// ─── References between collections ──────────────────────────────────────────
|
|
141
|
+
|
|
142
|
+
/** `#/content/<type>` — a property whose value is the id of an entry in another collection. */
|
|
143
|
+
const CONTENT_REF = /^#\/content\/([^/]+)$/;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* The collection a property references, or null when it references nothing.
|
|
147
|
+
*
|
|
148
|
+
* Exported because it is the ONE test for "is this field a relationship", and three surfaces have
|
|
149
|
+
* to agree on it: this engine, the frontmatter renderer, and the grid's relationship cell. A fourth
|
|
150
|
+
* reading of `$ref` is how the picker ends up existing three times with three behaviours.
|
|
151
|
+
*/
|
|
152
|
+
export function referenceTarget(schema: { $ref?: string } | undefined): string | null {
|
|
153
|
+
const match = typeof schema?.$ref === "string" ? CONTENT_REF.exec(schema.$ref) : null;
|
|
154
|
+
return match ? match[1]! : null;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Inert context used when a host renders a form without one.
|
|
159
|
+
*
|
|
160
|
+
* Exported because a host with genuinely nowhere to resolve from — the frontmatter renderer, whose
|
|
161
|
+
* one registered control reads FILES — should name this rather than write a second empty closure.
|
|
162
|
+
*/
|
|
163
|
+
export const NULL_FORM_CONTEXT: SchemaFormContext = {
|
|
94
164
|
resolvePointer: () => {
|
|
95
165
|
// Nothing to resolve against without a host context
|
|
96
166
|
},
|
|
@@ -173,6 +243,9 @@ function refTextField(key: string, refVal: string, onChange: (next: unknown) =>
|
|
|
173
243
|
* @param {(val: unknown) => void} onChange
|
|
174
244
|
* @param {SchemaFormContext | undefined} ctx
|
|
175
245
|
* @param {Record<string, unknown>} [scope] - Scope for dependent enum refs (the parent form value)
|
|
246
|
+
* @param {() => void} [rerender] - Repaint hook, threaded so an inline reference can show its
|
|
247
|
+
* choices once they load — an async control with no way to ask for a second frame renders its
|
|
248
|
+
* loading state forever.
|
|
176
249
|
*/
|
|
177
250
|
export function renderInlineField(
|
|
178
251
|
key: string,
|
|
@@ -181,10 +254,23 @@ export function renderInlineField(
|
|
|
181
254
|
onChange: (val: unknown) => void,
|
|
182
255
|
ctx?: SchemaFormContext,
|
|
183
256
|
scope?: Record<string, unknown>,
|
|
257
|
+
rerender?: () => void,
|
|
184
258
|
) {
|
|
185
259
|
if (isRef(value)) {
|
|
186
260
|
return refTextField(key, value.$ref, onChange);
|
|
187
261
|
}
|
|
262
|
+
const referenceControl =
|
|
263
|
+
referenceTarget(schema) === null ? undefined : controlRegistry.get("reference");
|
|
264
|
+
if (referenceControl) {
|
|
265
|
+
return referenceControl({
|
|
266
|
+
ctx: ctx ?? NULL_FORM_CONTEXT,
|
|
267
|
+
key,
|
|
268
|
+
onChange,
|
|
269
|
+
rerender,
|
|
270
|
+
schema,
|
|
271
|
+
value,
|
|
272
|
+
});
|
|
273
|
+
}
|
|
188
274
|
const enumValues = resolveFormEnum(schema.enum, ctx, scope);
|
|
189
275
|
|
|
190
276
|
if (enumValues) {
|
|
@@ -287,19 +373,26 @@ function renderPropertyControl(
|
|
|
287
373
|
}
|
|
288
374
|
}
|
|
289
375
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
ps.type !== "object" &&
|
|
294
|
-
ps.type !== "array"
|
|
295
|
-
) {
|
|
296
|
-
const binding = controlRegistry.get("binding");
|
|
297
|
-
if (binding) {
|
|
298
|
-
return binding(controlArgs);
|
|
299
|
-
}
|
|
376
|
+
/* A ref left in a form whose host named nowhere to bind: no ladder is drawn, so the pointer is
|
|
377
|
+
edited as the string it is rather than rendered as "[object Object]" in a typed widget. */
|
|
378
|
+
if (isRef(currentValue) && isBindableField(ps)) {
|
|
300
379
|
return refTextField(prop, currentValue.$ref, commit);
|
|
301
380
|
}
|
|
302
381
|
|
|
382
|
+
/* A relationship to another collection (`$ref: "#/content/<type>"`) is the registered `reference`
|
|
383
|
+
control, wherever the form is drawn — §9.2's "one picker" is this dispatch plus the single
|
|
384
|
+
`registerFormControl("reference", …)` in `ui/form-controls.ts`. It is deliberately NOT an enum:
|
|
385
|
+
the choices are entry files on disk, so they are read asynchronously and can be stale, and a
|
|
386
|
+
schema `enum` is a closed set the document itself declares. When the control is not registered
|
|
387
|
+
(a bare-Bun import of this engine), the field falls through to the plain textfield below rather
|
|
388
|
+
than rendering nothing. */
|
|
389
|
+
if (referenceTarget(ps) !== null) {
|
|
390
|
+
const referenceControl = controlRegistry.get("reference");
|
|
391
|
+
if (referenceControl) {
|
|
392
|
+
return referenceControl(controlArgs);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
303
396
|
const enumValues = resolveFormEnum(opts.ui?.[prop]?.enum ?? ps.enum, ctx, value);
|
|
304
397
|
if (enumValues) {
|
|
305
398
|
return html`
|
|
@@ -425,6 +518,7 @@ function renderPropertyControl(
|
|
|
425
518
|
},
|
|
426
519
|
ctx,
|
|
427
520
|
value,
|
|
521
|
+
opts.rerender,
|
|
428
522
|
),
|
|
429
523
|
)}
|
|
430
524
|
<sp-action-button
|
|
@@ -466,35 +560,99 @@ function renderPropertyControl(
|
|
|
466
560
|
|
|
467
561
|
/** @type {ReturnType<typeof setTimeout> | undefined} */
|
|
468
562
|
let debounce: ReturnType<typeof setTimeout> | undefined;
|
|
469
|
-
const params = ctx.params ?? [];
|
|
470
563
|
const ph = ps.default !== undefined ? String(ps.default) : (ps.examples?.[0] ?? "");
|
|
471
|
-
return html`<
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
564
|
+
return html`<sp-textfield
|
|
565
|
+
size="s"
|
|
566
|
+
style="flex:1"
|
|
567
|
+
.value=${currentValue ?? ""}
|
|
568
|
+
placeholder=${ph || nothing}
|
|
569
|
+
title=${ps.description || nothing}
|
|
570
|
+
@input=${(e: Event) => {
|
|
571
|
+
clearTimeout(debounce);
|
|
572
|
+
debounce = setTimeout(() => commit((e.target as HTMLInputElement).value || undefined), 400);
|
|
573
|
+
}}
|
|
574
|
+
></sp-textfield>`;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
// ─── The Value Source ladder (§6.6) ──────────────────────────────────────────
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* Whether a property is edited as a single value at all. The three that are not — a nested JSON
|
|
581
|
+
* Schema, an object and an array — are edited as raw JSON or as a multi-row sub-form, and a chip
|
|
582
|
+
* offering to replace that editor with a signal pointer would be offering to delete the user's
|
|
583
|
+
* work.
|
|
584
|
+
*/
|
|
585
|
+
function isBindableField(ps: JsonSchema): boolean {
|
|
586
|
+
return ps.format !== "json-schema" && ps.type !== "object" && ps.type !== "array";
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
/** Every pointer this form's host says a value may come from. */
|
|
590
|
+
function refSourcesFor(ctx: SchemaFormContext): SignalOption[] {
|
|
591
|
+
return [
|
|
592
|
+
...(ctx.signals ?? []).map((name) => ({ label: name, value: `#/state/${name}` })),
|
|
593
|
+
...(ctx.params ?? []).map((name) => ({ label: `$params/${name}`, value: `#/$params/${name}` })),
|
|
594
|
+
];
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// ─── Field validation (§7.1, inline tier) ────────────────────────────────────
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* Why this value is not acceptable for this property schema, or `""` when it is.
|
|
601
|
+
*
|
|
602
|
+
* Deliberately narrow: the checks a _property_ schema can make on its own, at the moment the value
|
|
603
|
+
* is committed. Anything cross-field, cross-document or extension-defined belongs to whoever ran
|
|
604
|
+
* the real validator and arrives through {@link RenderFormOptions.errors} — a form control is not a
|
|
605
|
+
* second implementation of JSON Schema, it is the place a verdict gets rendered.
|
|
606
|
+
*
|
|
607
|
+
* A `$ref` binding is never judged here. Its value is resolved at render time from state the form
|
|
608
|
+
* cannot see, so type-checking the reference itself would refuse every correct binding.
|
|
609
|
+
*
|
|
610
|
+
* @param {JsonSchema} schema
|
|
611
|
+
* @param {unknown} value
|
|
612
|
+
* @param {boolean} isRequired
|
|
613
|
+
* @returns {string}
|
|
614
|
+
*/
|
|
615
|
+
export function validateFieldValue(
|
|
616
|
+
schema: JsonSchema,
|
|
617
|
+
value: unknown,
|
|
618
|
+
isRequired: boolean,
|
|
619
|
+
): string {
|
|
620
|
+
if (isRef(value)) {
|
|
621
|
+
return "";
|
|
622
|
+
}
|
|
623
|
+
const empty = value === undefined || value === null || value === "";
|
|
624
|
+
if (empty) {
|
|
625
|
+
return isRequired ? "Required." : "";
|
|
626
|
+
}
|
|
627
|
+
if (Array.isArray(schema.enum) && !schema.enum.includes(value)) {
|
|
628
|
+
return `Choose one of: ${schema.enum.map(String).join(", ")}.`;
|
|
629
|
+
}
|
|
630
|
+
if (schema.type === "number" || schema.type === "integer") {
|
|
631
|
+
const n = typeof value === "number" ? value : Number(value);
|
|
632
|
+
if (!Number.isFinite(n)) {
|
|
633
|
+
return "Enter a number.";
|
|
634
|
+
}
|
|
635
|
+
if (schema.type === "integer" && !Number.isInteger(n)) {
|
|
636
|
+
return "Enter a whole number.";
|
|
637
|
+
}
|
|
638
|
+
if (schema.minimum !== undefined && n < schema.minimum) {
|
|
639
|
+
return `Must be ${schema.minimum} or more.`;
|
|
640
|
+
}
|
|
641
|
+
if (schema.maximum !== undefined && n > schema.maximum) {
|
|
642
|
+
return `Must be ${schema.maximum} or less.`;
|
|
496
643
|
}
|
|
497
|
-
|
|
644
|
+
return "";
|
|
645
|
+
}
|
|
646
|
+
if (schema.type === "boolean" && typeof value !== "boolean") {
|
|
647
|
+
return "Must be true or false.";
|
|
648
|
+
}
|
|
649
|
+
if (schema.type === "array" && !Array.isArray(value)) {
|
|
650
|
+
return "Must be a list.";
|
|
651
|
+
}
|
|
652
|
+
if (schema.type === "object" && (typeof value !== "object" || Array.isArray(value))) {
|
|
653
|
+
return "Must be an object.";
|
|
654
|
+
}
|
|
655
|
+
return "";
|
|
498
656
|
}
|
|
499
657
|
|
|
500
658
|
// ─── Form rendering ──────────────────────────────────────────────────────────
|
|
@@ -514,15 +672,41 @@ export function renderForm(
|
|
|
514
672
|
opts: RenderFormOptions,
|
|
515
673
|
): TemplateResult {
|
|
516
674
|
const required = new Set(schema.required);
|
|
517
|
-
const ctx = opts.context ??
|
|
675
|
+
const ctx = opts.context ?? NULL_FORM_CONTEXT;
|
|
676
|
+
const refSources = refSourcesFor(ctx);
|
|
518
677
|
|
|
519
678
|
const propertyFields = Object.entries(schema.properties ?? {}).map(([prop, ps]) => {
|
|
520
679
|
const labelText = prop + (required.has(prop) ? " *" : "");
|
|
680
|
+
// Host diagnostics win over the intrinsic check — see RenderFormOptions.errors.
|
|
681
|
+
const error =
|
|
682
|
+
opts.errors?.[prop] ||
|
|
683
|
+
validateFieldValue(ps, value[prop], Boolean(opts.showRequired) && required.has(prop));
|
|
684
|
+
const count = opts.errorCounts?.[prop];
|
|
685
|
+
const staticWidget = renderPropertyControl(prop, ps, value, required, opts, ctx);
|
|
686
|
+
/* A `ui.control` override owns its whole field — the secret control writes an env-var NAME
|
|
687
|
+
rather than the value it was handed, so a rung switch above it would be editing a different
|
|
688
|
+
thing than the one on screen. */
|
|
689
|
+
const laddered =
|
|
690
|
+
refSources.length > 0 && isBindableField(ps) && !opts.ui?.[prop]?.control
|
|
691
|
+
? renderDynamicSlot({
|
|
692
|
+
allowCustomRef: true,
|
|
693
|
+
caps: { schema: configFieldSchema(ps) },
|
|
694
|
+
extraSignals: refSources,
|
|
695
|
+
fieldKey: `${ctx.fieldKeyPrefix ?? ""}.${prop}`,
|
|
696
|
+
onChange: (v?: JsonValue) => opts.onChange({ [prop]: v }),
|
|
697
|
+
staticWidget,
|
|
698
|
+
stateDefs: [],
|
|
699
|
+
value: value[prop],
|
|
700
|
+
})
|
|
701
|
+
: null;
|
|
521
702
|
return renderFieldRow({
|
|
522
703
|
hasValue: false,
|
|
523
704
|
label: labelText,
|
|
524
705
|
prop: ps.name || prop,
|
|
525
|
-
widget:
|
|
706
|
+
widget: laddered ? laddered.widget : staticWidget,
|
|
707
|
+
...(laddered ? { labelExtra: laddered.modeButton } : {}),
|
|
708
|
+
...(error ? { error } : {}),
|
|
709
|
+
...(count === undefined ? {} : { errorCount: count }),
|
|
526
710
|
});
|
|
527
711
|
});
|
|
528
712
|
|
package/src/ui/spectrum.ts
CHANGED
|
@@ -36,7 +36,16 @@ import { FieldLabel } from "@spectrum-web-components/field-label/src/FieldLabel.
|
|
|
36
36
|
import { Checkbox } from "@spectrum-web-components/checkbox/src/Checkbox.js";
|
|
37
37
|
import { Switch as SpSwitch } from "@spectrum-web-components/switch/src/Switch.js";
|
|
38
38
|
import { Divider } from "@spectrum-web-components/divider/src/Divider.js";
|
|
39
|
-
|
|
39
|
+
/* SIDE-EFFECT IMPORT, deliberately unlike every other row in this file.
|
|
40
|
+
Registering `sp-tooltip` ourselves from the class-only module made Studio the first definer, and
|
|
41
|
+
the package's OWN registering entry is reached later by a dynamic import (the textfield's
|
|
42
|
+
truncated-value controller) — which then calls `customElements.define` for a name we already
|
|
43
|
+
took, and throws `NotSupportedError` in the console during ordinary panel use. Our loop's
|
|
44
|
+
`customElements.get` guard cannot help: the second define is Spectrum's own call inside
|
|
45
|
+
node_modules. The tooltip package declares `sideEffects: ["./sp-*.js", …]`, so this import
|
|
46
|
+
survives bundling, and putting Spectrum's module in the static graph makes it the single definer
|
|
47
|
+
while the later dynamic import hits the module cache. */
|
|
48
|
+
import "@spectrum-web-components/tooltip/sp-tooltip.js";
|
|
40
49
|
import { Overlay } from "@spectrum-web-components/overlay/src/Overlay.js";
|
|
41
50
|
import { OverlayTrigger } from "@spectrum-web-components/overlay/src/OverlayTrigger.js";
|
|
42
51
|
import { Dialog } from "@spectrum-web-components/dialog/src/Dialog.js";
|
|
@@ -58,6 +67,9 @@ import { TableRow } from "@spectrum-web-components/table/src/TableRow.js";
|
|
|
58
67
|
import { TableCell } from "@spectrum-web-components/table/src/TableCell.js";
|
|
59
68
|
|
|
60
69
|
// Icons
|
|
70
|
+
import { IconRailBottom } from "@spectrum-web-components/icons-workflow/src/elements/IconRailBottom.js";
|
|
71
|
+
import { IconRailLeft } from "@spectrum-web-components/icons-workflow/src/elements/IconRailLeft.js";
|
|
72
|
+
import { IconRailRight } from "@spectrum-web-components/icons-workflow/src/elements/IconRailRight.js";
|
|
61
73
|
import { IconFolder } from "@spectrum-web-components/icons-workflow/src/elements/IconFolder.js";
|
|
62
74
|
import { IconFolderOpen } from "@spectrum-web-components/icons-workflow/src/elements/IconFolderOpen.js";
|
|
63
75
|
import { IconDocument } from "@spectrum-web-components/icons-workflow/src/elements/IconDocument.js";
|
|
@@ -92,7 +104,6 @@ import { IconSettings } from "@spectrum-web-components/icons-workflow/src/elemen
|
|
|
92
104
|
import { IconInfo } from "@spectrum-web-components/icons-workflow/src/elements/IconInfo.js";
|
|
93
105
|
import { IconBack } from "@spectrum-web-components/icons-workflow/src/elements/IconBack.js";
|
|
94
106
|
import { IconProperties } from "@spectrum-web-components/icons-workflow/src/elements/IconProperties.js";
|
|
95
|
-
import { IconEvent } from "@spectrum-web-components/icons-workflow/src/elements/IconEvent.js";
|
|
96
107
|
import { IconMore } from "@spectrum-web-components/icons-workflow/src/elements/IconMore.js";
|
|
97
108
|
|
|
98
109
|
// Layout / alignment icons
|
|
@@ -106,6 +117,10 @@ import { IconTextAlignRight } from "@spectrum-web-components/icons-workflow/src/
|
|
|
106
117
|
import { IconTextAlignJustify } from "@spectrum-web-components/icons-workflow/src/elements/IconTextAlignJustify.js";
|
|
107
118
|
import { IconAlignTop } from "@spectrum-web-components/icons-workflow/src/elements/IconAlignTop.js";
|
|
108
119
|
import { IconAlignBottom } from "@spectrum-web-components/icons-workflow/src/elements/IconAlignBottom.js";
|
|
120
|
+
import { IconPlay } from "@spectrum-web-components/icons-workflow/src/elements/IconPlay.js";
|
|
121
|
+
import { IconSearch } from "@spectrum-web-components/icons-workflow/src/elements/IconSearch.js";
|
|
122
|
+
import { IconShare } from "@spectrum-web-components/icons-workflow/src/elements/IconShare.js";
|
|
123
|
+
import { IconShowMenu } from "@spectrum-web-components/icons-workflow/src/elements/IconShowMenu.js";
|
|
109
124
|
import { IconAlignMiddle } from "@spectrum-web-components/icons-workflow/src/elements/IconAlignMiddle.js";
|
|
110
125
|
import { IconAlignLeft } from "@spectrum-web-components/icons-workflow/src/elements/IconAlignLeft.js";
|
|
111
126
|
import { IconAlignRight } from "@spectrum-web-components/icons-workflow/src/elements/IconAlignRight.js";
|
|
@@ -132,8 +147,6 @@ import { IconStop } from "@spectrum-web-components/icons-workflow/src/elements/I
|
|
|
132
147
|
import { IconHistory } from "@spectrum-web-components/icons-workflow/src/elements/IconHistory.js";
|
|
133
148
|
import { IconAttach } from "@spectrum-web-components/icons-workflow/src/elements/IconAttach.js";
|
|
134
149
|
import { IconViewList } from "@spectrum-web-components/icons-workflow/src/elements/IconViewList.js";
|
|
135
|
-
import { IconRailRightClose } from "@spectrum-web-components/icons-workflow/src/elements/IconRailRightClose.js";
|
|
136
|
-
import { IconRailRightOpen } from "@spectrum-web-components/icons-workflow/src/elements/IconRailRightOpen.js";
|
|
137
150
|
import { IconRectangle } from "@spectrum-web-components/icons-workflow/src/elements/IconRectangle.js";
|
|
138
151
|
|
|
139
152
|
// Inline formatting icons
|
|
@@ -184,7 +197,6 @@ const components = [
|
|
|
184
197
|
["sp-checkbox", Checkbox],
|
|
185
198
|
["sp-switch", SpSwitch],
|
|
186
199
|
["sp-divider", Divider],
|
|
187
|
-
["sp-tooltip", Tooltip],
|
|
188
200
|
["sp-overlay", Overlay],
|
|
189
201
|
["overlay-trigger", OverlayTrigger],
|
|
190
202
|
["sp-dialog", Dialog],
|
|
@@ -204,6 +216,9 @@ const components = [
|
|
|
204
216
|
["sp-table-body", TableBody],
|
|
205
217
|
["sp-table-row", TableRow],
|
|
206
218
|
["sp-table-cell", TableCell],
|
|
219
|
+
["sp-icon-rail-bottom", IconRailBottom],
|
|
220
|
+
["sp-icon-rail-left", IconRailLeft],
|
|
221
|
+
["sp-icon-rail-right", IconRailRight],
|
|
207
222
|
["sp-icon-folder", IconFolder],
|
|
208
223
|
["sp-icon-folder-open", IconFolderOpen],
|
|
209
224
|
["sp-icon-document", IconDocument],
|
|
@@ -238,7 +253,6 @@ const components = [
|
|
|
238
253
|
["sp-icon-info", IconInfo],
|
|
239
254
|
["sp-icon-back", IconBack],
|
|
240
255
|
["sp-icon-properties", IconProperties],
|
|
241
|
-
["sp-icon-event", IconEvent],
|
|
242
256
|
["sp-icon-more", IconMore],
|
|
243
257
|
["sp-icon-arrow-right", IconArrowRight],
|
|
244
258
|
["sp-icon-arrow-left", IconArrowLeft],
|
|
@@ -250,6 +264,10 @@ const components = [
|
|
|
250
264
|
["sp-icon-text-align-justify", IconTextAlignJustify],
|
|
251
265
|
["sp-icon-align-top", IconAlignTop],
|
|
252
266
|
["sp-icon-align-bottom", IconAlignBottom],
|
|
267
|
+
["sp-icon-play", IconPlay],
|
|
268
|
+
["sp-icon-search", IconSearch],
|
|
269
|
+
["sp-icon-share", IconShare],
|
|
270
|
+
["sp-icon-show-menu", IconShowMenu],
|
|
253
271
|
["sp-icon-align-middle", IconAlignMiddle],
|
|
254
272
|
["sp-icon-align-left", IconAlignLeft],
|
|
255
273
|
["sp-icon-align-right", IconAlignRight],
|
|
@@ -268,8 +286,6 @@ const components = [
|
|
|
268
286
|
["sp-icon-download", IconDownload],
|
|
269
287
|
["sp-icon-checkmark", IconCheckmark],
|
|
270
288
|
["sp-icon-view-column", IconViewColumn],
|
|
271
|
-
["sp-icon-rail-right-close", IconRailRightClose],
|
|
272
|
-
["sp-icon-rail-right-open", IconRailRightOpen],
|
|
273
289
|
["sp-icon-rectangle", IconRectangle],
|
|
274
290
|
["sp-icon-box", IconBox],
|
|
275
291
|
["sp-icon-visibility", IconVisibility],
|
package/src/ui/timing.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Timing.ts — Studio's latency vocabulary.
|
|
3
|
+
*
|
|
4
|
+
* Every user-visible delay in Studio expresses one of a small number of intents: "wait until the
|
|
5
|
+
* user stops typing", "hold a message on screen long enough to read", "check the repo again". Each
|
|
6
|
+
* call site used to pick its own number for its intent, so the same intent shipped as 350, 400 and
|
|
7
|
+
* 600 ms in three different panels and a retune meant a grep. Name the intent once here, import the
|
|
8
|
+
* name, and the retune is a single edit.
|
|
9
|
+
*
|
|
10
|
+
* All values are milliseconds. The two input debounces are contractual:
|
|
11
|
+
* `specs/studio-ui-guidelines.md` §4.4 fixes 400 ms for text inputs and 500 ms for code/expression
|
|
12
|
+
* textareas. Do not change either without releasing that spec section.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Text/style input debounce — the §4.4 standard. Long enough that a normal typing cadence produces
|
|
17
|
+
* one commit per pause rather than one per keystroke, short enough that the canvas still feels
|
|
18
|
+
* live.
|
|
19
|
+
*/
|
|
20
|
+
export const INPUT_DEBOUNCE = 400;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Code and expression textareas — the §4.4 standard. Longer than {@link INPUT_DEBOUNCE} because
|
|
24
|
+
* each commit re-parses source (or re-lints), and because half-typed code is usually invalid, so
|
|
25
|
+
* committing eagerly just burns work on states the user is about to leave.
|
|
26
|
+
*/
|
|
27
|
+
export const CODE_DEBOUNCE = 500;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Draft-layer live preview (ui/field-input.ts) — how long after a keystroke the in-progress draft
|
|
31
|
+
* is pushed to the document so the canvas updates while the field stays focused. Deliberately below
|
|
32
|
+
* {@link INPUT_DEBOUNCE}: this commit is provisional (the draft survives it, and blur/Enter commits
|
|
33
|
+
* again), so it can afford to fire sooner than a committing input.
|
|
34
|
+
*/
|
|
35
|
+
export const LIVE_PREVIEW = 350;
|
|
36
|
+
|
|
37
|
+
/*
|
|
38
|
+
* `STATUS_MESSAGE = 3000` used to live here: how long a transient message stayed in the status bar
|
|
39
|
+
* before it erased itself. It had one reader, `statusMessage`, which is deleted — the bar carries
|
|
40
|
+
* ambient state now and outcomes go to `services/notify.ts`, whose `TOAST_LIFETIME_MS` is per
|
|
41
|
+
* SEVERITY (§7.1 caps the band at 4–8s) rather than one number for a failure and a save alike.
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Git status poll while the Git panel is open. Deliberately coarse: it exists to notice changes
|
|
46
|
+
* made outside Studio, and each tick shells out to git, so a faster cadence buys little and costs
|
|
47
|
+
* I/O.
|
|
48
|
+
*/
|
|
49
|
+
export const POLL_GIT = 30_000;
|
package/src/ui/value-selector.ts
CHANGED
|
@@ -6,6 +6,11 @@
|
|
|
6
6
|
* dropdown overlay (manual combobox) when it doesn't. Both modes share identical styled menu items,
|
|
7
7
|
* ensuring visual consistency.
|
|
8
8
|
*
|
|
9
|
+
* The option list is a set of SUGGESTIONS, never a whitelist: both modes emit `change` on commit
|
|
10
|
+
* (picker selection, menu selection, or blur/Enter in the textfield) and combobox mode also emits
|
|
11
|
+
* `input` while typing, so a caller can offer a short list of common values without forbidding the
|
|
12
|
+
* rest — which is what lets a control like the event-name field stop being a list of ten.
|
|
13
|
+
*
|
|
9
14
|
* Usage: html`<jx-value-selector size="s" .value=${"italic"} placeholder="normal" .options=${[{
|
|
10
15
|
* value: "italic", label: "Italic", style: "font-style: italic" }]} @change=${handler}
|
|
11
16
|
* @input=${handler}
|
|
@@ -101,6 +106,20 @@ export class JxValueSelector extends LitElement {
|
|
|
101
106
|
this.dispatchEvent(new Event("input", { bubbles: true, composed: true }));
|
|
102
107
|
}
|
|
103
108
|
|
|
109
|
+
/**
|
|
110
|
+
* Combobox mode: textfield @change handler (blur / Enter).
|
|
111
|
+
*
|
|
112
|
+
* Without this, a typed value only ever reached listeners as `input`. Every consumer that binds
|
|
113
|
+
* `@change` — the pattern for "commit this to the document" everywhere else in the app — saw
|
|
114
|
+
* nothing at all, so the free-form half of this dual-mode control was decorative: you could type
|
|
115
|
+
* a value the option list did not contain and it would never be written down.
|
|
116
|
+
*/
|
|
117
|
+
_handleTextChange(e: Event) {
|
|
118
|
+
e.stopPropagation();
|
|
119
|
+
this.value = (e.target as HTMLInputElement).value;
|
|
120
|
+
this.dispatchEvent(new Event("change", { bubbles: true, composed: true }));
|
|
121
|
+
}
|
|
122
|
+
|
|
104
123
|
/** Set popover min-width to match trigger width (replicates sp-picker behavior) */
|
|
105
124
|
_setPopoverWidth(e: Event) {
|
|
106
125
|
const group = this.querySelector(".jx-combobox-group");
|
|
@@ -133,6 +152,7 @@ export class JxValueSelector extends LitElement {
|
|
|
133
152
|
placeholder=${this.placeholder}
|
|
134
153
|
.value=${live(this.value || "")}
|
|
135
154
|
@input=${this._handleInput}
|
|
155
|
+
@change=${this._handleTextChange}
|
|
136
156
|
@click=${(e: Event) => e.stopPropagation()}
|
|
137
157
|
></sp-textfield>
|
|
138
158
|
<sp-picker-button size=${this.size}></sp-picker-button>
|