@jxsuite/studio 2.0.1 → 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-799jpvhm.js → components-2bpqp4mq.js} +5 -7
- package/dist/chunks/{components-799jpvhm.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-8jxwts2p.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-gs6kqdt1.js → studio-adn0z1k3.js} +14 -8
- package/dist/chunks/{studio-gs6kqdt1.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-esrewxap.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-v7jkjqng.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-jm0z592w.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 +21080 -32585
- 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 +7 -0
- package/src/new-project/location-fields.ts +9 -1
- package/src/new-project/new-project-modal.ts +221 -245
- 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 -53
- 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 +30 -1
- 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 +7 -1
- 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-qr3drkkw.js +0 -531
- package/dist/chunks/extension-sections-qr3drkkw.js.map +0 -12
- package/dist/chunks/files-j8a1t06k.js +0 -50
- package/dist/chunks/files-j8a1t06k.js.map +0 -9
- package/dist/chunks/git-panel-xtq5z81x.js +0 -28
- package/dist/chunks/git-panel-xtq5z81x.js.map +0 -9
- package/dist/chunks/layers-panel-ancn2wpq.js +0 -26
- package/dist/chunks/layers-panel-ancn2wpq.js.map +0 -9
- package/dist/chunks/settings-modal-17ttr96g.js +0 -29
- package/dist/chunks/settings-modal-17ttr96g.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-0xgs7xrs.js +0 -429
- package/dist/chunks/studio-0xgs7xrs.js.map +0 -13
- package/dist/chunks/studio-4d8hzcz5.js +0 -3427
- package/dist/chunks/studio-4d8hzcz5.js.map +0 -26
- package/dist/chunks/studio-4k0m4fmp.js.map +0 -13
- package/dist/chunks/studio-9smfzqhc.js +0 -19
- package/dist/chunks/studio-9smfzqhc.js.map +0 -10
- package/dist/chunks/studio-jm0z592w.js.map +0 -115
- package/dist/chunks/studio-m2t4mdg5.js +0 -1854
- package/dist/chunks/studio-m2t4mdg5.js.map +0 -18
- package/dist/chunks/studio-n4p11dfy.js +0 -853
- package/dist/chunks/studio-n4p11dfy.js.map +0 -12
- package/dist/chunks/studio-qkvt37c0.js.map +0 -9
- package/dist/chunks/studio-sjh1wt1a.js +0 -3744
- package/dist/chunks/studio-sjh1wt1a.js.map +0 -22
- package/dist/chunks/studio-v7jkjqng.js.map +0 -46
- 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-yfcstdzy.js +0 -399
- package/dist/chunks/studio-yfcstdzy.js.map +0 -12
- package/dist/chunks/studio-zp7jncs8.js +0 -469
- package/dist/chunks/studio-zp7jncs8.js.map +0 -14
- 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-8jxwts2p.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-esrewxap.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
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
/// <reference lib="dom" />
|
|
2
|
+
/**
|
|
3
|
+
* The expression editor — one operator row plus an operand editor per slot, nested to any depth.
|
|
4
|
+
*
|
|
5
|
+
* **The layout is CSS, in `styles/inspector.css` (§ "The expression editor").** Every row here used
|
|
6
|
+
* to be an inline `display:flex;…` attribute with a hard `min-width` on the pickers, and no rung of
|
|
7
|
+
* that chain could set `min-width: 0` — so at Inspector width the operand controls refused to
|
|
8
|
+
* shrink and Operator, Target and Value were clipped by the edge of the window. The editor is drawn
|
|
9
|
+
* in the Inspector (~280px), in the Navigator, and in the Bottom dock's Logic tab (very wide), so
|
|
10
|
+
* every row wraps to a stack rather than sizing itself in pixels.
|
|
11
|
+
*/
|
|
2
12
|
import { html, nothing } from "lit-html";
|
|
3
13
|
import { live } from "lit-html/directives/live.js";
|
|
4
14
|
import { PURE_METHOD_OPS } from "@jxsuite/runtime/expression";
|
|
@@ -7,6 +17,8 @@ import { renderFieldRow } from "./field-row";
|
|
|
7
17
|
import { renderFormulaChips } from "./formula-chips";
|
|
8
18
|
import { applyCatalogPick, calleeEntry, formulaCatalog } from "./formula-catalog";
|
|
9
19
|
import { openFormulaPalette } from "./formula-palette";
|
|
20
|
+
import { VALUE_SOURCE_LABELS } from "./value-source";
|
|
21
|
+
import { renderEmptyState } from "../panels/empty-state";
|
|
10
22
|
|
|
11
23
|
import type {
|
|
12
24
|
JxExpressionNode,
|
|
@@ -35,6 +47,18 @@ const BINARY_OPS = new Set([
|
|
|
35
47
|
"??",
|
|
36
48
|
]);
|
|
37
49
|
const ASSIGN_OPS = new Set(["=", "+=", "-=", "*=", "/="]);
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Does this expression node DO something rather than compute something?
|
|
53
|
+
*
|
|
54
|
+
* An assignment writes a target and yields nothing worth reading; a `+` or a `filter` yields a
|
|
55
|
+
* value. The Data panel needs the distinction to know whether a row has a value column at all —
|
|
56
|
+
* labelling `setBeds0` "pending" reads as "still loading" for a thing that will never load.
|
|
57
|
+
*/
|
|
58
|
+
export function isActionExpression(node: unknown): boolean {
|
|
59
|
+
const op = (node as { operator?: unknown } | null | undefined)?.operator;
|
|
60
|
+
return typeof op === "string" && ASSIGN_OPS.has(op);
|
|
61
|
+
}
|
|
38
62
|
const NO_ARG_OPS = new Set(["pop", "shift"]);
|
|
39
63
|
const ONE_ARG_OPS = new Set(["push", "unshift"]);
|
|
40
64
|
|
|
@@ -180,6 +204,10 @@ function operatorInfo(op: string): OperatorInfo {
|
|
|
180
204
|
// ─── Operand Mode Detection ─────────────────────────────────────────────────
|
|
181
205
|
|
|
182
206
|
/**
|
|
207
|
+
* Which rung of the value ladder an operand occupies. The three answers are the same three the
|
|
208
|
+
* Properties, Style and Logic tabs give, and they are spelled the same way — `ui/value-source.ts`
|
|
209
|
+
* owns the words, so `lit / $ref / expr` is gone from the operand picker (plan §6.3).
|
|
210
|
+
*
|
|
183
211
|
* @param {unknown} operand
|
|
184
212
|
* @returns {"ref" | "expression" | "literal"}
|
|
185
213
|
*/
|
|
@@ -315,14 +343,7 @@ function renderValueBadge(preview: EditorPreview | null | undefined, pathKey: st
|
|
|
315
343
|
if (text === undefined) {
|
|
316
344
|
return nothing;
|
|
317
345
|
}
|
|
318
|
-
return html
|
|
319
|
-
<span
|
|
320
|
-
class="expr-live-badge"
|
|
321
|
-
title=${text}
|
|
322
|
-
style="font-family:var(--spectrum-code-font-family, monospace);font-size:10px;line-height:16px;padding:0 5px;border-radius:4px;background:var(--spectrum-gray-200, #323232);color:var(--spectrum-seafoam-900, #35a690);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:160px;flex-shrink:1"
|
|
323
|
-
>${text}</span
|
|
324
|
-
>
|
|
325
|
-
`;
|
|
346
|
+
return html`<span class="expr-live-badge" title=${text}>${text}</span>`;
|
|
326
347
|
}
|
|
327
348
|
|
|
328
349
|
// ─── Ref Picker ─────────────────────────────────────────────────────────────
|
|
@@ -343,10 +364,20 @@ function renderRefPicker(
|
|
|
343
364
|
const allRefs = [...stateRefs, ...eventRefs];
|
|
344
365
|
const isCustom = refVal && !allRefs.includes(refVal);
|
|
345
366
|
|
|
367
|
+
// Nothing to pick and nothing already picked: a picker whose only entry is a disabled "No state
|
|
368
|
+
// Defined" is a dead end. Say what a binding is instead, in the shell's one empty-state voice.
|
|
369
|
+
if (allRefs.length === 0 && !refVal) {
|
|
370
|
+
return renderEmptyState({
|
|
371
|
+
compact: true,
|
|
372
|
+
detail: "Add one in the State panel and it shows up here.",
|
|
373
|
+
message: "A binding points at a value this page holds.",
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
|
|
346
377
|
return html`
|
|
347
378
|
<sp-picker
|
|
348
379
|
size="s"
|
|
349
|
-
|
|
380
|
+
class="expr-ref"
|
|
350
381
|
placeholder="Select…"
|
|
351
382
|
.value=${live(isCustom ? "__custom__" : refVal || "")}
|
|
352
383
|
@change=${(e: Event) => {
|
|
@@ -357,13 +388,9 @@ function renderRefPicker(
|
|
|
357
388
|
onRefChange(val);
|
|
358
389
|
}}
|
|
359
390
|
>
|
|
360
|
-
${
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
(r) => html`<sp-menu-item value=${r}>${r.replace("#/state/", "")}</sp-menu-item>`,
|
|
364
|
-
)
|
|
365
|
-
: html`<sp-menu-item disabled>No state defined</sp-menu-item>`
|
|
366
|
-
}
|
|
391
|
+
${stateRefs.map(
|
|
392
|
+
(r) => html`<sp-menu-item value=${r}>${r.replace("#/state/", "")}</sp-menu-item>`,
|
|
393
|
+
)}
|
|
367
394
|
${
|
|
368
395
|
eventRefs.length > 0
|
|
369
396
|
? html`
|
|
@@ -386,10 +413,10 @@ function renderRefPicker(
|
|
|
386
413
|
function renderLiteralEditor(operand: unknown, onChange: (newVal: JxExpressionOperand) => void) {
|
|
387
414
|
const type = literalType(operand);
|
|
388
415
|
return html`
|
|
389
|
-
<div
|
|
416
|
+
<div class="expr-literal">
|
|
390
417
|
<sp-picker
|
|
391
418
|
size="s"
|
|
392
|
-
|
|
419
|
+
class="expr-literal-type"
|
|
393
420
|
.value=${live(type)}
|
|
394
421
|
@change=${(e: Event) => {
|
|
395
422
|
const newType = (e.target as HTMLInputElement).value;
|
|
@@ -405,28 +432,26 @@ function renderLiteralEditor(operand: unknown, onChange: (newVal: JxExpressionOp
|
|
|
405
432
|
type === "string"
|
|
406
433
|
? html`<sp-textfield
|
|
407
434
|
size="s"
|
|
408
|
-
|
|
435
|
+
class="expr-literal-value"
|
|
409
436
|
.value=${live(String(operand ?? ""))}
|
|
410
437
|
@input=${(e: Event) => onChange((e.target as HTMLInputElement).value)}
|
|
411
438
|
></sp-textfield>`
|
|
412
439
|
: type === "number"
|
|
413
440
|
? html`<sp-number-field
|
|
414
441
|
size="s"
|
|
415
|
-
|
|
442
|
+
class="expr-literal-value"
|
|
416
443
|
.value=${live(Number(operand ?? 0))}
|
|
417
444
|
@change=${(e: Event) => onChange(Number((e.target as HTMLInputElement).value))}
|
|
418
445
|
></sp-number-field>`
|
|
419
446
|
: type === "boolean"
|
|
420
447
|
? html`<sp-checkbox
|
|
421
448
|
size="s"
|
|
449
|
+
class="expr-literal-bool"
|
|
422
450
|
?checked=${Boolean(operand)}
|
|
423
451
|
@change=${(e: Event) => onChange((e.target as HTMLInputElement).checked)}
|
|
424
452
|
>true</sp-checkbox
|
|
425
453
|
>`
|
|
426
|
-
: html`<span
|
|
427
|
-
style="font-size:var(--spectrum-font-size-75, 12px);color:var(--spectrum-gray-600, #808080)"
|
|
428
|
-
>null</span
|
|
429
|
-
>`
|
|
454
|
+
: html`<span class="expr-literal-null">null</span>`
|
|
430
455
|
}
|
|
431
456
|
</div>
|
|
432
457
|
`;
|
|
@@ -465,25 +490,26 @@ export function renderOperandEditor(
|
|
|
465
490
|
if (opts.mustBeRef) {
|
|
466
491
|
const refVal = ((operand as Record<string, unknown> | null)?.$ref as string) ?? "";
|
|
467
492
|
return html`
|
|
468
|
-
<div
|
|
493
|
+
<div class="expr-operand">${renderRefPicker(refVal, (r) => onChange({ $ref: r }), opts)}</div>
|
|
469
494
|
`;
|
|
470
495
|
}
|
|
471
496
|
|
|
472
497
|
const mode = operandMode(operand);
|
|
473
498
|
return html`
|
|
474
|
-
<div
|
|
499
|
+
<div class="expr-operand">
|
|
475
500
|
<sp-picker
|
|
476
501
|
size="s"
|
|
477
|
-
|
|
502
|
+
class="expr-operand-mode"
|
|
503
|
+
label="Value source"
|
|
478
504
|
.value=${live(mode)}
|
|
479
505
|
@change=${(e: Event) => {
|
|
480
506
|
const newMode = (e.target as HTMLInputElement).value;
|
|
481
507
|
onChange(defaultForMode(newMode));
|
|
482
508
|
}}
|
|
483
509
|
>
|
|
484
|
-
<sp-menu-item value="literal"
|
|
485
|
-
<sp-menu-item value="ref">$ref</sp-menu-item>
|
|
486
|
-
<sp-menu-item value="expression"
|
|
510
|
+
<sp-menu-item value="literal">${VALUE_SOURCE_LABELS.literal}</sp-menu-item>
|
|
511
|
+
<sp-menu-item value="ref">${VALUE_SOURCE_LABELS.ref}</sp-menu-item>
|
|
512
|
+
<sp-menu-item value="expression">${VALUE_SOURCE_LABELS.expression}</sp-menu-item>
|
|
487
513
|
</sp-picker>
|
|
488
514
|
${
|
|
489
515
|
mode === "literal"
|
|
@@ -526,13 +552,8 @@ function renderSpliceArgsEditor(
|
|
|
526
552
|
<div class="array-object-field">
|
|
527
553
|
${safeArgs.map(
|
|
528
554
|
(arg, idx) => html`
|
|
529
|
-
<div
|
|
530
|
-
class="array-object-
|
|
531
|
-
style="display:flex;gap:4px;align-items:center;margin-bottom:4px"
|
|
532
|
-
>
|
|
533
|
-
<span style="font-size:10px;color:var(--spectrum-gray-600, #808080);min-width:30px">
|
|
534
|
-
${labels[idx] ?? fallbackLabel}
|
|
535
|
-
</span>
|
|
555
|
+
<div class="array-object-row">
|
|
556
|
+
<span class="array-object-label">${labels[idx] ?? fallbackLabel}</span>
|
|
536
557
|
${renderOperandEditor(
|
|
537
558
|
arg,
|
|
538
559
|
(newArg) => {
|
|
@@ -614,21 +635,14 @@ export function renderExpressionEditor(
|
|
|
614
635
|
const sub = (...segs: (string | number)[]) => [...path, ...segs].join("/");
|
|
615
636
|
/** Wrap an operand widget with its live value badge. */
|
|
616
637
|
const withBadge = (widget: unknown, key: string) =>
|
|
617
|
-
html`<div
|
|
618
|
-
${widget}${renderValueBadge(preview, key)}
|
|
619
|
-
</div>`;
|
|
620
|
-
|
|
621
|
-
const nestStyle =
|
|
622
|
-
depth > 0
|
|
623
|
-
? "border-left:2px solid var(--spectrum-gray-300, #3c3c3c);margin-left:8px;padding-left:8px;"
|
|
624
|
-
: "";
|
|
638
|
+
html`<div class="expr-widget">${widget}${renderValueBadge(preview, key)}</div>`;
|
|
625
639
|
|
|
626
640
|
// The root badge: pure roots show their result; mutating roots' effect shows on target/value.
|
|
627
641
|
const rootBadge =
|
|
628
642
|
depth === 0 && preview && !preview.mutating ? renderValueBadge(preview, pathKey) : nothing;
|
|
629
643
|
|
|
630
644
|
return html`
|
|
631
|
-
<div class
|
|
645
|
+
<div class=${depth > 0 ? "expression-editor expression-editor--nested" : "expression-editor"}>
|
|
632
646
|
${
|
|
633
647
|
depth === 0
|
|
634
648
|
? renderFormulaChips(safeNode, opts.onChipSelect ?? (() => {}), { path, preview })
|
|
@@ -636,11 +650,7 @@ export function renderExpressionEditor(
|
|
|
636
650
|
}
|
|
637
651
|
${
|
|
638
652
|
depth === 0 && preview?.error
|
|
639
|
-
? html`<div
|
|
640
|
-
style="font-size:10px;color:var(--spectrum-negative-content-color-default, #f76a63);padding:2px 0"
|
|
641
|
-
>
|
|
642
|
-
${preview.error}
|
|
643
|
-
</div>`
|
|
653
|
+
? html`<div class="expr-error">${preview.error}</div>`
|
|
644
654
|
: nothing
|
|
645
655
|
}
|
|
646
656
|
${renderFieldRow({
|
|
@@ -648,9 +658,10 @@ export function renderExpressionEditor(
|
|
|
648
658
|
label: "Operator",
|
|
649
659
|
prop: "operator",
|
|
650
660
|
widget: html`
|
|
651
|
-
<div
|
|
661
|
+
<div class="expr-widget">
|
|
652
662
|
<sp-picker
|
|
653
663
|
size="s"
|
|
664
|
+
class="expr-operator"
|
|
654
665
|
.value=${live(op)}
|
|
655
666
|
@change=${(e: Event) => {
|
|
656
667
|
const newOp = (e.target as HTMLInputElement).value;
|
|
@@ -748,7 +759,7 @@ export function renderExpressionEditor(
|
|
|
748
759
|
${
|
|
749
760
|
info.needsValue && info.valueIsNode
|
|
750
761
|
? html`
|
|
751
|
-
<div
|
|
762
|
+
<div class="expr-subsection">
|
|
752
763
|
${renderFieldRow({
|
|
753
764
|
hasValue: false,
|
|
754
765
|
label: "Per-item",
|
|
@@ -769,7 +780,7 @@ export function renderExpressionEditor(
|
|
|
769
780
|
${
|
|
770
781
|
info.spliceArray
|
|
771
782
|
? html`
|
|
772
|
-
<div
|
|
783
|
+
<div class="expr-subsection">
|
|
773
784
|
${renderFieldRow({
|
|
774
785
|
hasValue: false,
|
|
775
786
|
label: "Args",
|
|
@@ -791,7 +802,7 @@ export function renderExpressionEditor(
|
|
|
791
802
|
${
|
|
792
803
|
info.callArgs
|
|
793
804
|
? html`
|
|
794
|
-
<div
|
|
805
|
+
<div class="expr-subsection">
|
|
795
806
|
${renderFieldRow({
|
|
796
807
|
hasValue: false,
|
|
797
808
|
label: "Args",
|
|
@@ -867,13 +878,13 @@ function renderSwitchCasesEditor(
|
|
|
867
878
|
const setCases = (next: Record<string, unknown>) => onChange({ ...safeNode, cases: next });
|
|
868
879
|
|
|
869
880
|
return html`
|
|
870
|
-
<div class="switch-cases"
|
|
881
|
+
<div class="switch-cases">
|
|
871
882
|
${entries.map(
|
|
872
883
|
([key, operand]) => html`
|
|
873
|
-
<div
|
|
884
|
+
<div class="switch-case-row">
|
|
874
885
|
<sp-textfield
|
|
875
886
|
size="s"
|
|
876
|
-
|
|
887
|
+
class="switch-case-key"
|
|
877
888
|
placeholder="value"
|
|
878
889
|
.value=${live(key)}
|
|
879
890
|
@change=${(e: Event) => {
|
|
@@ -910,11 +921,8 @@ function renderSwitchCasesEditor(
|
|
|
910
921
|
</div>
|
|
911
922
|
`,
|
|
912
923
|
)}
|
|
913
|
-
<div
|
|
914
|
-
<span
|
|
915
|
-
style="width:80px;flex-shrink:0;font-size:10px;line-height:24px;color:var(--spectrum-gray-600, #808080)"
|
|
916
|
-
>default</span
|
|
917
|
-
>
|
|
924
|
+
<div class="switch-case-row">
|
|
925
|
+
<span class="switch-case-key switch-case-default">default</span>
|
|
918
926
|
${withBadge(
|
|
919
927
|
renderOperandEditor(safeNode.default, (v) => onChange({ ...safeNode, default: v }), {
|
|
920
928
|
...opts,
|
package/src/ui/field-input.ts
CHANGED
|
@@ -20,13 +20,11 @@ import { html } from "lit-html";
|
|
|
20
20
|
import type { TemplateResult } from "lit-html";
|
|
21
21
|
import { live } from "lit-html/directives/live.js";
|
|
22
22
|
import { keyed } from "lit-html/directives/keyed.js";
|
|
23
|
+
import { LIVE_PREVIEW } from "./timing";
|
|
23
24
|
|
|
24
25
|
/** A lit-renderable value (template or directive result). */
|
|
25
26
|
type Renderable = unknown;
|
|
26
27
|
|
|
27
|
-
/** Default debounce (ms) before an in-progress edit is committed to the document. */
|
|
28
|
-
export const DEFAULT_DEBOUNCE_MS = 350;
|
|
29
|
-
|
|
30
28
|
interface DraftEntry {
|
|
31
29
|
value: string;
|
|
32
30
|
timer?: ReturnType<typeof setTimeout>;
|
|
@@ -167,7 +165,7 @@ export function spTextField(
|
|
|
167
165
|
commit: (v: string) => void,
|
|
168
166
|
opts: FieldOpts = {},
|
|
169
167
|
): Renderable {
|
|
170
|
-
const ms = opts.debounceMs ??
|
|
168
|
+
const ms = opts.debounceMs ?? LIVE_PREVIEW;
|
|
171
169
|
const { onInput, onCommit, onKeydown } = makeHandlers(key, ms, commit, opts.commitMode);
|
|
172
170
|
return keyed(
|
|
173
171
|
key,
|
|
@@ -193,7 +191,7 @@ export function spTextArea(
|
|
|
193
191
|
commit: (v: string) => void,
|
|
194
192
|
opts: FieldOpts = {},
|
|
195
193
|
): Renderable {
|
|
196
|
-
const ms = opts.debounceMs ??
|
|
194
|
+
const ms = opts.debounceMs ?? LIVE_PREVIEW;
|
|
197
195
|
const { onInput, onCommit } = makeHandlers(key, ms, commit, opts.commitMode);
|
|
198
196
|
return keyed(
|
|
199
197
|
key,
|
|
@@ -219,7 +217,7 @@ export function rawTextArea(
|
|
|
219
217
|
commit: (v: string) => void,
|
|
220
218
|
opts: TextAreaOpts = {},
|
|
221
219
|
): Renderable {
|
|
222
|
-
const ms = opts.debounceMs ??
|
|
220
|
+
const ms = opts.debounceMs ?? LIVE_PREVIEW;
|
|
223
221
|
const { onInput, onCommit } = makeHandlers(key, ms, commit, opts.commitMode);
|
|
224
222
|
const style = [
|
|
225
223
|
`min-height:${opts.minHeight ?? "40px"}`,
|
package/src/ui/field-row.ts
CHANGED
|
@@ -1,27 +1,79 @@
|
|
|
1
1
|
/// <reference lib="dom" />
|
|
2
2
|
/**
|
|
3
|
-
* Field-row.js —
|
|
3
|
+
* Field-row.js — the inspector's row vocabulary, in one module.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Three rows, and every panel that draws one imports it from here:
|
|
6
|
+
*
|
|
7
|
+
* - {@link renderFieldRow} — label + widget, plus §7.1's **third notification tier** (an `error` line
|
|
8
|
+
* rendered at the control) and §6.2's **provenance chip** (where this value came from). The chip
|
|
9
|
+
* itself is `panels/provenance.ts`'s: one vocabulary, two cascades, one template.
|
|
10
|
+
* - {@link renderKvRow} — an editable key/value pair with a delete affordance. Custom attributes and
|
|
11
|
+
* custom CSS properties are the same row; they were two.
|
|
12
|
+
* - {@link renderStaticKvRow} — the read-only name/value line. Observed Attributes, CSS Properties
|
|
13
|
+
* and CSS Parts each hand-wrote it with the same inline style declarations.
|
|
14
|
+
*
|
|
15
|
+
* **The error line.** The other two notification tiers are hosted records in `services/notify.ts`:
|
|
16
|
+
* a toast is taken away on a timer, a problem is kept until somebody fixes it. An inline error is
|
|
17
|
+
* neither, because it is not a record at all — it is a property of the value currently in the
|
|
18
|
+
* field, and it lives exactly as long as that value does. Which is the point: a rejected value used
|
|
19
|
+
* to be announced in a three-second grey line at the bottom of the window, hundreds of pixels from
|
|
20
|
+
* the field that rejected it, and by the time you looked down the field had snapped back and the
|
|
21
|
+
* reason was gone.
|
|
22
|
+
*
|
|
23
|
+
* **Validated on commit, never on input** (§7.1). Producers decide a value is bad on `change` or
|
|
24
|
+
* blur, not on `input` — a field cannot spend the middle of every word telling you it is wrong.
|
|
7
25
|
*/
|
|
8
26
|
|
|
9
27
|
import { html, nothing } from "lit-html";
|
|
10
28
|
import { classMap } from "lit-html/directives/class-map.js";
|
|
29
|
+
import { renderProvenanceChip } from "../panels/provenance";
|
|
30
|
+
|
|
31
|
+
import type { FieldProvenance } from "../panels/provenance";
|
|
32
|
+
|
|
33
|
+
// ─── The field row ───────────────────────────────────────────────────────────
|
|
34
|
+
|
|
35
|
+
/** Options for {@link renderFieldRow}. */
|
|
36
|
+
export interface FieldRowOptions {
|
|
37
|
+
prop: string;
|
|
38
|
+
label: string;
|
|
39
|
+
hasValue: boolean;
|
|
40
|
+
onClear?: () => void;
|
|
41
|
+
widget: unknown;
|
|
42
|
+
/** Rendered after the label inside the label cell (e.g. the dynamic-slot mode button). */
|
|
43
|
+
labelExtra?: unknown;
|
|
44
|
+
span?: number;
|
|
45
|
+
warning?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Where this value came from (§6.2). When omitted the row derives the `set`/`default` pair from
|
|
48
|
+
* `hasValue` and `onClear`, which is what every caller meant by them all along; a caller that can
|
|
49
|
+
* answer the richer question passes the answer.
|
|
50
|
+
*/
|
|
51
|
+
provenance?: FieldProvenance | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* Why the value in this control is not acceptable — §7.1's inline tier.
|
|
54
|
+
*
|
|
55
|
+
* Rendered under the widget in danger colour with `role="alert"`, so a screen reader announces it
|
|
56
|
+
* when it appears. Presence also marks the row invalid, so the state is legible without reading:
|
|
57
|
+
* `warning` says "this is unusual", `error` says "this is refused".
|
|
58
|
+
*
|
|
59
|
+
* Empty string and `undefined` both mean "no error", so a producer can pass its validator's
|
|
60
|
+
* output straight through without a ternary.
|
|
61
|
+
*/
|
|
62
|
+
error?: string | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* How many times this value has been refused in a row — the "message + counter" §7.1 asks for.
|
|
65
|
+
*
|
|
66
|
+
* A repeat count is the difference between "the field is still red from last time" and "it just
|
|
67
|
+
* refused me again", which is otherwise invisible when the second attempt fails the same way.
|
|
68
|
+
* Rendered from 2 up.
|
|
69
|
+
*/
|
|
70
|
+
errorCount?: number | undefined;
|
|
71
|
+
}
|
|
11
72
|
|
|
12
73
|
/**
|
|
13
|
-
* Render a universal field row with
|
|
74
|
+
* Render a universal field row with a provenance chip, label, widget, and an optional inline error.
|
|
14
75
|
*
|
|
15
|
-
* @param {
|
|
16
|
-
* prop: string;
|
|
17
|
-
* label: string;
|
|
18
|
-
* hasValue: boolean;
|
|
19
|
-
* onClear?: () => void;
|
|
20
|
-
* widget: unknown;
|
|
21
|
-
* labelExtra?: unknown;
|
|
22
|
-
* span?: number;
|
|
23
|
-
* warning?: boolean;
|
|
24
|
-
* }} opts
|
|
76
|
+
* @param {FieldRowOptions} opts
|
|
25
77
|
* @returns {import("lit-html").TemplateResult}
|
|
26
78
|
*/
|
|
27
79
|
export function renderFieldRow({
|
|
@@ -33,40 +85,165 @@ export function renderFieldRow({
|
|
|
33
85
|
labelExtra,
|
|
34
86
|
span,
|
|
35
87
|
warning,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
span?: number;
|
|
45
|
-
warning?: boolean;
|
|
46
|
-
}) {
|
|
88
|
+
provenance,
|
|
89
|
+
error,
|
|
90
|
+
errorCount,
|
|
91
|
+
}: FieldRowOptions) {
|
|
92
|
+
const invalid = Boolean(error);
|
|
93
|
+
const chip: FieldProvenance | undefined =
|
|
94
|
+
provenance ??
|
|
95
|
+
(hasValue && onClear ? { onClick: onClear, state: "set", title: `Clear ${prop}` } : undefined);
|
|
47
96
|
return html`
|
|
48
97
|
<div
|
|
49
|
-
class=${classMap({
|
|
98
|
+
class=${classMap({
|
|
99
|
+
"style-row": true,
|
|
100
|
+
"style-row--invalid": invalid,
|
|
101
|
+
"style-row--warning": Boolean(warning) && !invalid,
|
|
102
|
+
})}
|
|
50
103
|
data-prop=${prop}
|
|
51
104
|
style=${span === 2 ? "grid-column: 1 / -1" : ""}
|
|
52
105
|
>
|
|
53
106
|
<div class="style-row-label">
|
|
54
|
-
${
|
|
55
|
-
hasValue && onClear
|
|
56
|
-
? html`<span
|
|
57
|
-
class="set-dot"
|
|
58
|
-
title="Clear ${prop}"
|
|
59
|
-
@click=${(e: Event) => {
|
|
60
|
-
e.stopPropagation();
|
|
61
|
-
onClear();
|
|
62
|
-
}}
|
|
63
|
-
></span>`
|
|
64
|
-
: nothing
|
|
65
|
-
}
|
|
107
|
+
${chip ? renderProvenanceChip(prop, chip) : nothing}
|
|
66
108
|
<sp-field-label size="s" title=${prop}>${label}</sp-field-label>
|
|
67
109
|
${labelExtra ?? nothing}
|
|
68
110
|
</div>
|
|
69
111
|
${widget}
|
|
112
|
+
${
|
|
113
|
+
invalid
|
|
114
|
+
? html`<p class="style-row-error" role="alert">
|
|
115
|
+
${error}${
|
|
116
|
+
errorCount !== undefined && errorCount > 1
|
|
117
|
+
? html`<span class="style-row-error-count">×${errorCount}</span>`
|
|
118
|
+
: nothing
|
|
119
|
+
}
|
|
120
|
+
</p>`
|
|
121
|
+
: nothing
|
|
122
|
+
}
|
|
123
|
+
</div>
|
|
124
|
+
`;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ─── The editable key/value row ──────────────────────────────────────────────
|
|
128
|
+
|
|
129
|
+
/** Options for {@link renderKvRow}. */
|
|
130
|
+
export interface KvRowOptions {
|
|
131
|
+
/** The pair's current key. */
|
|
132
|
+
name: string;
|
|
133
|
+
/** The pair's current value. */
|
|
134
|
+
value: string;
|
|
135
|
+
/** Commit both cells, debounced, with the current contents of each. */
|
|
136
|
+
onCommit: (name: string, value: string) => void;
|
|
137
|
+
/** Remove the pair outright. */
|
|
138
|
+
onDelete: () => void;
|
|
139
|
+
/**
|
|
140
|
+
* The value cell's placeholder, resolved from the key — a CSS property's initial value, say.
|
|
141
|
+
*
|
|
142
|
+
* A resolver rather than a string because the key is editable: typing `display` into the key cell
|
|
143
|
+
* should offer `inline` under it before anything is committed, and only the caller knows the
|
|
144
|
+
* map.
|
|
145
|
+
*/
|
|
146
|
+
placeholderFor?: ((name: string) => string) | undefined;
|
|
147
|
+
/** Debounce before {@link KvRowOptions.onCommit}, in ms. */
|
|
148
|
+
debounceMs?: number;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* An editable key/value pair with a delete affordance — the ONE implementation.
|
|
153
|
+
*
|
|
154
|
+
* Custom HTML attributes and custom CSS properties are the same row and were written twice, with
|
|
155
|
+
* different rename behaviour (one committed on `input`, the other on `change`) and different
|
|
156
|
+
* placeholder plumbing. They now differ only in what they pass in.
|
|
157
|
+
*
|
|
158
|
+
* @param {KvRowOptions} opts
|
|
159
|
+
*/
|
|
160
|
+
export function renderKvRow({
|
|
161
|
+
name,
|
|
162
|
+
value,
|
|
163
|
+
onCommit,
|
|
164
|
+
onDelete,
|
|
165
|
+
placeholderFor,
|
|
166
|
+
debounceMs = 400,
|
|
167
|
+
}: KvRowOptions) {
|
|
168
|
+
let debounce: ReturnType<typeof setTimeout> | undefined;
|
|
169
|
+
let currentName = name;
|
|
170
|
+
let currentValue = value;
|
|
171
|
+
const commit = () => {
|
|
172
|
+
clearTimeout(debounce);
|
|
173
|
+
debounce = setTimeout(() => onCommit(currentName, currentValue), debounceMs);
|
|
174
|
+
};
|
|
175
|
+
return html`
|
|
176
|
+
<div class="kv-row" data-prop=${name}>
|
|
177
|
+
<sp-textfield
|
|
178
|
+
size="s"
|
|
179
|
+
class="kv-key"
|
|
180
|
+
.value=${name}
|
|
181
|
+
@input=${(e: Event) => {
|
|
182
|
+
currentName = (e.target as HTMLInputElement).value;
|
|
183
|
+
commit();
|
|
184
|
+
}}
|
|
185
|
+
@change=${
|
|
186
|
+
placeholderFor
|
|
187
|
+
? (e: Event) => {
|
|
188
|
+
const cell = (e.target as HTMLInputElement)
|
|
189
|
+
.closest(".kv-row")
|
|
190
|
+
?.querySelector(".kv-val");
|
|
191
|
+
cell?.setAttribute(
|
|
192
|
+
"placeholder",
|
|
193
|
+
placeholderFor((e.target as HTMLInputElement).value),
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
: nothing
|
|
197
|
+
}
|
|
198
|
+
></sp-textfield>
|
|
199
|
+
<sp-textfield
|
|
200
|
+
size="s"
|
|
201
|
+
class="kv-val"
|
|
202
|
+
.value=${value}
|
|
203
|
+
placeholder=${placeholderFor ? placeholderFor(name) : ""}
|
|
204
|
+
@input=${(e: Event) => {
|
|
205
|
+
currentValue = (e.target as HTMLInputElement).value;
|
|
206
|
+
commit();
|
|
207
|
+
}}
|
|
208
|
+
></sp-textfield>
|
|
209
|
+
<sp-action-button size="xs" quiet title="Remove ${name}" @click=${onDelete}>
|
|
210
|
+
<sp-icon-close slot="icon"></sp-icon-close>
|
|
211
|
+
</sp-action-button>
|
|
212
|
+
</div>
|
|
213
|
+
`;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// ─── The read-only key/value row ─────────────────────────────────────────────
|
|
217
|
+
|
|
218
|
+
/** Options for {@link renderStaticKvRow}. */
|
|
219
|
+
export interface StaticKvRowOptions {
|
|
220
|
+
/** The thing being named — an attribute, a custom property, a part. Rendered as code. */
|
|
221
|
+
name: string;
|
|
222
|
+
/** What it maps to, rendered immediately after the name ("→ count", "<button>"). */
|
|
223
|
+
detail?: string | undefined;
|
|
224
|
+
/** Its value or type, rendered hard right. */
|
|
225
|
+
value?: string | undefined;
|
|
226
|
+
/** Flags, rendered hard right after the value ("reflects"). */
|
|
227
|
+
tags?: readonly string[] | undefined;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* A read-only name/value line.
|
|
232
|
+
*
|
|
233
|
+
* Observed Attributes, CSS Properties and CSS Parts each hand-wrote this with the same
|
|
234
|
+
* `display:flex;gap:6px;align-items:center;padding:2px 0;font-size:…` inline block — three copies
|
|
235
|
+
* of one row, none of them addressable by a stylesheet, and so none of them able to respond to the
|
|
236
|
+
* theme. They differ only in which of the three slots they fill.
|
|
237
|
+
*
|
|
238
|
+
* @param {StaticKvRowOptions} opts
|
|
239
|
+
*/
|
|
240
|
+
export function renderStaticKvRow({ name, detail, value, tags }: StaticKvRowOptions) {
|
|
241
|
+
return html`
|
|
242
|
+
<div class="kv-static-row" data-prop=${name}>
|
|
243
|
+
<code class="kv-static-name">${name}</code>
|
|
244
|
+
${detail ? html`<span class="kv-static-detail">${detail}</span>` : nothing}
|
|
245
|
+
${value ? html`<span class="kv-static-value">${value}</span>` : nothing}
|
|
246
|
+
${(tags ?? []).map((tag) => html`<span class="kv-static-tag">${tag}</span>`)}
|
|
70
247
|
</div>
|
|
71
248
|
`;
|
|
72
249
|
}
|