@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,50 +1,146 @@
|
|
|
1
1
|
/// <reference lib="dom" />
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
* §19.9, milestone M4). Takes over the canvas area exactly like the Monaco function editor
|
|
5
|
-
* (renderFunctionEditor): `TabUi.editingFormula` identifies the document position being edited (a
|
|
6
|
-
* state entry's `$expression` via defName, or an element event binding's via path + eventKey).
|
|
3
|
+
* ⑪ · Logic — the formula workspace and the function editor, hosted by the Bottom dock.
|
|
7
4
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
5
|
+
* **What changed, and why it is the whole point.** Both of these surfaces used to TAKE OVER the
|
|
6
|
+
* canvas: `TabUi.editingFormula` (this file) and `TabUi.editingFunction` (`panels/editors.ts`) each
|
|
7
|
+
* cleared `canvasWrap`, dropped every canvas panel and drew themselves over the stage. So the one
|
|
8
|
+
* artefact whose values you are authoring — the page — was the one thing you could not see while
|
|
9
|
+
* authoring them, and the workspace's own data rail existed to paper over it: a frozen snapshot of
|
|
10
|
+
* a scope, shown because the live thing had just been unmounted. Plan §12 P8.5: "no editor hides
|
|
11
|
+
* the page it computes." They are a **tab of the Bottom dock** now (§3.2 ⑪), which sits under the
|
|
12
|
+
* pane grid, so the page renders beside the formula and keeps rendering while you edit it.
|
|
13
|
+
*
|
|
14
|
+
* **A dock tab is not a reparented takeover.** The surface has to work at dock height, so the
|
|
15
|
+
* header is one row, the chip pipeline and the result are single lines, the data rail is a narrow
|
|
16
|
+
* column that scrolls rather than a 280px slab, and every measurement lives in `styles/panels.css`
|
|
17
|
+
* instead of the inline `style=` attributes that kept seventeen `fw-*` classes on
|
|
18
|
+
* `scripts/check-styles.ts`'s orphan list.
|
|
19
|
+
*
|
|
20
|
+
* **One target, two surfaces, one tab.** {@link logicTarget} is the single reader of the two
|
|
21
|
+
* `TabUi` fields, and the function editor wins when both are set — the precedence `tabs/tab.ts` has
|
|
22
|
+
* always documented, now stated in exactly one place. The tab's `when` is that same predicate, so
|
|
23
|
+
* Logic exists only while something is open in it, and `panels/bottom-dock.ts` reveals the dock on
|
|
24
|
+
* that tab when a target appears.
|
|
25
|
+
*
|
|
26
|
+
* **The close is real.** Both surfaces carry one, and closing is the only thing that clears the
|
|
27
|
+
* target — leaving the dock, switching tabs and collapsing the dock all keep your place, because
|
|
28
|
+
* the editor no longer owns a screen it would otherwise be stranded on.
|
|
11
29
|
*
|
|
12
30
|
* Every edit immutably replaces the selected sub-node within the root and writes the WHOLE root
|
|
13
|
-
* node back through transactDoc — undo/redo and canvas
|
|
31
|
+
* node back through `transactDoc` — undo/redo and the canvas patch come free, and because the
|
|
32
|
+
* canvas is still mounted the patch lands in a page you can watch.
|
|
14
33
|
*/
|
|
15
34
|
|
|
16
|
-
import { html
|
|
35
|
+
import { html } from "lit-html";
|
|
17
36
|
import { getEventBinding, isExpressionDef, isJsonObject } from "@jxsuite/schema/guards";
|
|
18
37
|
|
|
19
|
-
import {
|
|
38
|
+
import { shallowRef } from "../reactivity";
|
|
39
|
+
import { getNodeAtPath, updateUi } from "../store";
|
|
20
40
|
import { activeTab } from "../workspace/workspace";
|
|
21
41
|
import { mutateAddDef, mutateUpdateDef, mutateUpdateProperty, transactDoc } from "../tabs/transact";
|
|
22
|
-
import {
|
|
42
|
+
import { setBottomTab } from "../shell";
|
|
23
43
|
import { chipSummary, renderFormulaChips } from "../ui/formula-chips";
|
|
24
44
|
import { renderExpressionEditor } from "../ui/expression-editor";
|
|
25
45
|
import { applyCatalogPick, formulaCatalog } from "../ui/formula-catalog";
|
|
26
46
|
import { openFormulaPalette } from "../ui/formula-palette";
|
|
27
47
|
import { livePreviewExpression } from "../services/live-preview";
|
|
48
|
+
import { closeFunctionEditor, functionEditorTemplate, syncFunctionEditor } from "./editors";
|
|
49
|
+
import { registerPanel } from "./panel-registry";
|
|
50
|
+
import { renderEmptyState } from "./empty-state";
|
|
28
51
|
import { dataTypeLabel, renderDataTreeTemplate, unwrapSignal } from "./data-explorer";
|
|
29
52
|
|
|
53
|
+
import {
|
|
54
|
+
argsSchema,
|
|
55
|
+
pathArg,
|
|
56
|
+
pathProperty,
|
|
57
|
+
stringArg,
|
|
58
|
+
stringProperty,
|
|
59
|
+
} from "../commands/command-args";
|
|
60
|
+
|
|
30
61
|
import type { JxNodeValue } from "../tabs/transact";
|
|
31
|
-
import type {
|
|
62
|
+
import type { AnyCommand, CommandRegistry } from "../commands/registry";
|
|
63
|
+
import type { PanelBody } from "./panel-registry";
|
|
64
|
+
import type { ExpressionPreview } from "../services/preview-eval";
|
|
65
|
+
import type { FormulaEditDef, FunctionEditDef, JsonValue } from "../types";
|
|
32
66
|
import type { Tab } from "../tabs/tab";
|
|
33
67
|
import type { JxStateDefinition } from "@jxsuite/schema/types";
|
|
34
68
|
import type { TemplateResult } from "lit-html";
|
|
35
69
|
|
|
36
70
|
type NodePath = (string | number)[];
|
|
37
71
|
|
|
38
|
-
|
|
72
|
+
/** What the Logic tab is showing: the Monaco function body, or the structured `$expression`. */
|
|
73
|
+
export type LogicTarget =
|
|
74
|
+
| { surface: "function"; editing: FunctionEditDef }
|
|
75
|
+
| { surface: "formula"; editing: FormulaEditDef };
|
|
39
76
|
|
|
40
|
-
/**
|
|
41
|
-
|
|
77
|
+
/**
|
|
78
|
+
* The Logic tab's target, or `null` when nothing is open in it.
|
|
79
|
+
*
|
|
80
|
+
* The ONE reader of `TabUi.editingFunction` / `TabUi.editingFormula`, and therefore the one place
|
|
81
|
+
* their precedence is decided. Two surfaces used to answer that question separately — the canvas
|
|
82
|
+
* render pipeline by branch order, the pane context bar by an `||` — which is two definition sites
|
|
83
|
+
* for a rule neither of them stated.
|
|
84
|
+
*
|
|
85
|
+
* @param {Tab | null} [tab] The tab to read; defaults to the focused one.
|
|
86
|
+
* @returns {LogicTarget | null}
|
|
87
|
+
*/
|
|
88
|
+
export function logicTarget(tab: Tab | null = activeTab.value): LogicTarget | null {
|
|
89
|
+
const ui = tab?.session.ui;
|
|
90
|
+
if (!ui) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
if (ui.editingFunction) {
|
|
94
|
+
return { editing: ui.editingFunction as FunctionEditDef, surface: "function" };
|
|
95
|
+
}
|
|
96
|
+
if (ui.editingFormula) {
|
|
97
|
+
return { editing: ui.editingFormula as FormulaEditDef, surface: "formula" };
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
42
101
|
|
|
43
|
-
/**
|
|
44
|
-
|
|
102
|
+
/**
|
|
103
|
+
* Put the Logic tab on screen. Idempotent.
|
|
104
|
+
*
|
|
105
|
+
* `setBottomTab` is the shell's own "reveal" — it selects the tab AND opens the dock, for the same
|
|
106
|
+
* reason `setActivityTab` does: "show me the formula" means the formula is on screen when the call
|
|
107
|
+
* returns, not that a tab is selected inside a closed dock.
|
|
108
|
+
*/
|
|
109
|
+
export function revealLogicPanel(): void {
|
|
110
|
+
setBottomTab("logic");
|
|
111
|
+
}
|
|
45
112
|
|
|
46
|
-
/**
|
|
47
|
-
|
|
113
|
+
/**
|
|
114
|
+
* Open something in the Logic tab and put it on screen. The one WRITER of the two `TabUi` fields
|
|
115
|
+
* {@link logicTarget} reads, as that is its one reader.
|
|
116
|
+
*
|
|
117
|
+
* **One tab holds one target, so opening either surface clears the other.** `logicTarget` gives the
|
|
118
|
+
* function editor precedence when both are set, which is the right tie-break for a state that
|
|
119
|
+
* should never occur — and every opener used to create it. Four buttons and two commands each set
|
|
120
|
+
* their own field and left the other alone, so "Open in formula workspace" on an `$expression`
|
|
121
|
+
* while a Function body was open was a dead click: the dock went on showing the function, and the
|
|
122
|
+
* target key had not changed so nothing revealed either. Writing both fields here means the fifth
|
|
123
|
+
* opener inherits the rule instead of re-deciding it.
|
|
124
|
+
*
|
|
125
|
+
* **The reveal is the OTHER half, and it is a different event from the dock's.**
|
|
126
|
+
* `panels/bottom-dock.ts` reveals when a target APPEARS or CHANGES, at most once per target — that
|
|
127
|
+
* is what lets you close the dock over an open formula and have it stay closed (§16.3). Neither
|
|
128
|
+
* half can do the other's job: an effect on the target cannot see "the user pressed the button
|
|
129
|
+
* again" (same target, no change, no reveal — the dock stayed shut and the button did nothing), and
|
|
130
|
+
* a gesture cannot cover a target that appears without one. So the gesture says so explicitly, and
|
|
131
|
+
* this is what makes a call to it a gesture.
|
|
132
|
+
*
|
|
133
|
+
* @param {LogicTarget} target The surface to show and what it should be pointed at.
|
|
134
|
+
*/
|
|
135
|
+
export function openLogicTarget(target: LogicTarget): void {
|
|
136
|
+
updateUi(
|
|
137
|
+
activeTab.value,
|
|
138
|
+
"editingFunction",
|
|
139
|
+
target.surface === "function" ? target.editing : null,
|
|
140
|
+
);
|
|
141
|
+
updateUi(activeTab.value, "editingFormula", target.surface === "formula" ? target.editing : null);
|
|
142
|
+
revealLogicPanel();
|
|
143
|
+
}
|
|
48
144
|
|
|
49
145
|
function isExprNode(value: unknown): value is Record<string, unknown> {
|
|
50
146
|
return isJsonObject(value) && typeof value.operator === "string";
|
|
@@ -119,215 +215,245 @@ function writeRoot(tab: Tab, editing: FormulaEditDef, newRoot: unknown) {
|
|
|
119
215
|
mutateUpdateProperty(t, path, eventKey, { $expression: newRoot } as JxNodeValue),
|
|
120
216
|
);
|
|
121
217
|
}
|
|
122
|
-
renderFormulaWorkspace();
|
|
123
218
|
}
|
|
124
219
|
|
|
125
|
-
/** Close the workspace — clears `editingFormula`; the
|
|
220
|
+
/** Close the workspace — clears `editingFormula`; the Logic tab leaves the strip with it. */
|
|
126
221
|
export function closeFormulaWorkspace() {
|
|
127
|
-
updateUi("editingFormula", null);
|
|
222
|
+
updateUi(activeTab.value, "editingFormula", null);
|
|
128
223
|
}
|
|
129
224
|
|
|
130
|
-
// ───
|
|
225
|
+
// ─── The Logic tab ───────────────────────────────────────────────────────────
|
|
131
226
|
|
|
132
|
-
|
|
227
|
+
/**
|
|
228
|
+
* The chip selection, keyed by the target it belongs to.
|
|
229
|
+
*
|
|
230
|
+
* Keyed rather than reset, because the reset used to happen INSIDE the render — and a render that
|
|
231
|
+
* writes the state it reads is a reactive loop the moment the surface becomes an effect, which is
|
|
232
|
+
* exactly what hosting it in the dock makes it. A selection whose key no longer matches simply does
|
|
233
|
+
* not apply, so retargeting starts at the root with nothing written.
|
|
234
|
+
*/
|
|
235
|
+
const _selection = shallowRef<{ tab: Tab | null; key: string; path: NodePath }>({
|
|
236
|
+
key: "",
|
|
237
|
+
path: [],
|
|
238
|
+
tab: null,
|
|
239
|
+
});
|
|
133
240
|
|
|
134
|
-
|
|
241
|
+
/**
|
|
242
|
+
* The document position a selection belongs to. Paired with the tab OBJECT, never its id: a tab
|
|
243
|
+
* that was closed and reopened at the same path is a different document, and inheriting a chip
|
|
244
|
+
* selection into it is how you edit the wrong sub-node of a formula that merely looks the same.
|
|
245
|
+
*/
|
|
246
|
+
function selectionKey(editing: FormulaEditDef): string {
|
|
247
|
+
return JSON.stringify(editing);
|
|
248
|
+
}
|
|
135
249
|
|
|
136
250
|
/**
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
251
|
+
* Register the Bottom dock's Logic tab.
|
|
252
|
+
*
|
|
253
|
+
* Defined here and registered from `panels/bottom-dock.ts`, the same way Problems is defined beside
|
|
254
|
+
* its notification store: the dock owns the strip, the surface owns the record.
|
|
140
255
|
*/
|
|
141
|
-
export function
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
256
|
+
export function registerLogicPanel(): void {
|
|
257
|
+
registerPanel({
|
|
258
|
+
id: "logic",
|
|
259
|
+
title: "Logic",
|
|
260
|
+
level: "document",
|
|
261
|
+
dock: "bottom",
|
|
262
|
+
icon: "sp-icon-event",
|
|
263
|
+
// No rail button: Logic has no steady state to badge. It exists while a formula or a function
|
|
264
|
+
// Is open and leaves the strip when you close it, which is what `when` says below.
|
|
265
|
+
rail: false,
|
|
266
|
+
when: () => logicTarget() !== null,
|
|
267
|
+
render: (ctx) => logicPanelBody(ctx.rerender),
|
|
268
|
+
afterRender: (_ctx, host) => syncFunctionEditor(host),
|
|
269
|
+
});
|
|
270
|
+
}
|
|
147
271
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
272
|
+
/**
|
|
273
|
+
* What the Logic tab draws.
|
|
274
|
+
*
|
|
275
|
+
* @param {() => void} rerender The dock's repaint, handed to the live-preview refresh.
|
|
276
|
+
* @returns {PanelBody}
|
|
277
|
+
*/
|
|
278
|
+
export function logicPanelBody(rerender: () => void): PanelBody {
|
|
279
|
+
const tab = activeTab.value;
|
|
280
|
+
const target = logicTarget(tab);
|
|
281
|
+
if (!tab || !target) {
|
|
282
|
+
return renderEmptyState({
|
|
283
|
+
message: "Open a formula or a function to edit it here, beside the page it computes.",
|
|
284
|
+
});
|
|
154
285
|
}
|
|
286
|
+
return target.surface === "function"
|
|
287
|
+
? functionPaneTemplate(target.editing)
|
|
288
|
+
: workspaceTemplate(tab, target.editing, rerender);
|
|
289
|
+
}
|
|
155
290
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
291
|
+
/** The one header both surfaces wear: what is open, what kind it is, its verbs, and the close. */
|
|
292
|
+
function logicHeaderTemplate(
|
|
293
|
+
glyph: string,
|
|
294
|
+
name: string,
|
|
295
|
+
kind: string,
|
|
296
|
+
title: string,
|
|
297
|
+
verbs: TemplateResult | null,
|
|
298
|
+
close: () => void,
|
|
299
|
+
): TemplateResult {
|
|
300
|
+
return html`
|
|
301
|
+
<div class="fw-header">
|
|
302
|
+
<span class="fw-title" title=${title}>${glyph} ${name}</span>
|
|
303
|
+
<span class="fw-kind">${kind}</span>
|
|
304
|
+
<div class="fw-header-gap"></div>
|
|
305
|
+
${verbs}
|
|
306
|
+
<sp-action-button
|
|
307
|
+
quiet
|
|
308
|
+
size="s"
|
|
309
|
+
class="fw-close"
|
|
310
|
+
title="Close"
|
|
311
|
+
@click=${() => {
|
|
312
|
+
close();
|
|
313
|
+
}}
|
|
314
|
+
>
|
|
315
|
+
<sp-icon-close slot="icon"></sp-icon-close>
|
|
316
|
+
Close
|
|
317
|
+
</sp-action-button>
|
|
318
|
+
</div>
|
|
319
|
+
`;
|
|
320
|
+
}
|
|
177
321
|
|
|
178
|
-
|
|
322
|
+
/** The Monaco function body, at dock height. The editor itself is mounted by `afterRender`. */
|
|
323
|
+
function functionPaneTemplate(editing: FunctionEditDef): TemplateResult {
|
|
324
|
+
const name = editing.defName ?? editing.eventKey ?? "?";
|
|
325
|
+
return html`
|
|
326
|
+
<div class="formula-workspace formula-workspace--code">
|
|
327
|
+
${logicHeaderTemplate(
|
|
328
|
+
"ƒ",
|
|
329
|
+
name,
|
|
330
|
+
editing.type === "def" ? "function body" : "event handler",
|
|
331
|
+
editing.type === "def" ? `state/${name}` : name,
|
|
332
|
+
null,
|
|
333
|
+
() => {
|
|
334
|
+
void closeFunctionEditor();
|
|
335
|
+
},
|
|
336
|
+
)}
|
|
337
|
+
${functionEditorTemplate()}
|
|
338
|
+
</div>
|
|
339
|
+
`;
|
|
179
340
|
}
|
|
180
341
|
|
|
181
|
-
function workspaceTemplate(
|
|
342
|
+
function workspaceTemplate(
|
|
343
|
+
tab: Tab,
|
|
344
|
+
editing: FormulaEditDef,
|
|
345
|
+
rerender: () => void,
|
|
346
|
+
): TemplateResult {
|
|
182
347
|
const stateEntries = (tab.doc.document?.state ?? {}) as Record<string, JxStateDefinition>;
|
|
183
|
-
const
|
|
348
|
+
const name = (editing.type === "def" ? editing.defName : editing.eventKey) ?? "?";
|
|
184
349
|
const root = formulaRoot(tab, editing);
|
|
185
|
-
|
|
186
|
-
const
|
|
187
|
-
<sp-action-button
|
|
188
|
-
quiet
|
|
189
|
-
size="s"
|
|
190
|
-
class="fw-close"
|
|
191
|
-
title="Close formula workspace"
|
|
192
|
-
@click=${closeFormulaWorkspace}
|
|
193
|
-
>
|
|
194
|
-
<sp-icon-close slot="icon"></sp-icon-close>
|
|
195
|
-
Close
|
|
196
|
-
</sp-action-button>
|
|
197
|
-
`;
|
|
350
|
+
const kind = editing.type === "def" ? "state expression" : "event expression";
|
|
351
|
+
const title = editing.type === "def" ? `state/${name}` : name;
|
|
198
352
|
|
|
199
353
|
if (!root) {
|
|
200
354
|
return html`
|
|
201
|
-
<div
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
<div class="fw-header" style="display:flex;align-items:center;gap:8px">
|
|
206
|
-
<span class="fw-title" style="${MONO};font-size:14px">fx ${title}</span>
|
|
207
|
-
<div style="flex:1"></div>
|
|
208
|
-
${closeButton}
|
|
355
|
+
<div class="formula-workspace">
|
|
356
|
+
${logicHeaderTemplate("fx", name, kind, title, null, closeFormulaWorkspace)}
|
|
357
|
+
<div class="fw-body">
|
|
358
|
+
${renderEmptyState({ message: "No expression found at this document position." })}
|
|
209
359
|
</div>
|
|
210
|
-
<div class="empty-state">No expression found at this document position.</div>
|
|
211
360
|
</div>
|
|
212
361
|
`;
|
|
213
362
|
}
|
|
214
363
|
|
|
215
364
|
const { scope } = tab.session.canvas;
|
|
216
|
-
// Live-context evaluation in the canvas iframe with snapshot fallback (M6).
|
|
217
|
-
//
|
|
218
|
-
//
|
|
365
|
+
// Live-context evaluation in the canvas iframe with snapshot fallback (M6). The canvas is no
|
|
366
|
+
// Longer unmounted while this surface is open — that is the entire point of the move — so the
|
|
367
|
+
// Live path is the ORDINARY case now rather than the one that never happened. An event target's
|
|
219
368
|
// Element path is the context, so repeater-template formulas bind the first item's $map scope.
|
|
220
369
|
const preview = livePreviewExpression(
|
|
221
370
|
tab,
|
|
222
371
|
`formula:${JSON.stringify(editing)}`,
|
|
223
372
|
root,
|
|
224
373
|
editing.type === "event" ? (editing.path ?? null) : null,
|
|
225
|
-
|
|
374
|
+
rerender,
|
|
375
|
+
);
|
|
376
|
+
const stored = _selection.value;
|
|
377
|
+
const key = selectionKey(editing);
|
|
378
|
+
const { node: selected, path: selectedPath } = resolveSelection(
|
|
379
|
+
root,
|
|
380
|
+
stored.tab === tab && stored.key === key ? stored.path : [],
|
|
226
381
|
);
|
|
227
|
-
const { node: selected, path: selectedPath } = resolveSelection(root, _selectedPath);
|
|
228
382
|
const write = (next: unknown) => writeRoot(tab, editing, next);
|
|
229
383
|
const writeSelected = (next: unknown) => write(replaceAtPath(root, selectedPath, next));
|
|
230
384
|
const onChipSelect = (path: NodePath) => {
|
|
231
|
-
|
|
232
|
-
renderFormulaWorkspace();
|
|
385
|
+
_selection.value = { key, path, tab };
|
|
233
386
|
};
|
|
234
387
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
applyCatalogPick(entry, writeSelected, {
|
|
259
|
-
onInsertDef: (name, def) =>
|
|
260
|
-
transactDoc(activeTab.value, (t) =>
|
|
261
|
-
mutateAddDef(t, name, def as Record<string, JsonValue>),
|
|
262
|
-
),
|
|
263
|
-
stateEntries,
|
|
264
|
-
}),
|
|
265
|
-
})}
|
|
266
|
-
>
|
|
267
|
-
<sp-icon-brackets slot="icon"></sp-icon-brackets>
|
|
268
|
-
Catalog
|
|
269
|
-
</sp-action-button>
|
|
270
|
-
${closeButton}
|
|
271
|
-
</div>
|
|
272
|
-
`;
|
|
273
|
-
|
|
274
|
-
// ── Chip strip: the whole tree as chips with live badges; clicking selects the sub-node ──
|
|
275
|
-
const chips = html`
|
|
276
|
-
<div class="fw-chips" style="padding:2px 20px 10px;border-bottom:${PANE_BORDER}">
|
|
277
|
-
${renderFormulaChips(root, onChipSelect, { preview })}
|
|
278
|
-
</div>
|
|
388
|
+
const catalogButton = html`
|
|
389
|
+
<sp-action-button
|
|
390
|
+
quiet
|
|
391
|
+
size="s"
|
|
392
|
+
class="fw-browse-catalog"
|
|
393
|
+
title="Browse catalog"
|
|
394
|
+
@click=${(e: Event) =>
|
|
395
|
+
openFormulaPalette({
|
|
396
|
+
anchor: e.currentTarget as HTMLElement,
|
|
397
|
+
entries: formulaCatalog(stateEntries),
|
|
398
|
+
onPick: (entry) =>
|
|
399
|
+
applyCatalogPick(entry, writeSelected, {
|
|
400
|
+
onInsertDef: (defName, def) =>
|
|
401
|
+
transactDoc(activeTab.value, (t) =>
|
|
402
|
+
mutateAddDef(t, defName, def as Record<string, JsonValue>),
|
|
403
|
+
),
|
|
404
|
+
stateEntries,
|
|
405
|
+
}),
|
|
406
|
+
})}
|
|
407
|
+
>
|
|
408
|
+
<sp-icon-brackets slot="icon"></sp-icon-brackets>
|
|
409
|
+
Catalog
|
|
410
|
+
</sp-action-button>
|
|
279
411
|
`;
|
|
280
412
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
<div
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
413
|
+
return html`
|
|
414
|
+
<div class="formula-workspace">
|
|
415
|
+
${logicHeaderTemplate("fx", name, kind, title, catalogButton, closeFormulaWorkspace)}
|
|
416
|
+
<div class="fw-chips">${renderFormulaChips(root, onChipSelect, { preview })}</div>
|
|
417
|
+
<div class="fw-body">
|
|
418
|
+
<div class="fw-editor">
|
|
419
|
+
<div class="fw-selected">
|
|
420
|
+
Selected:
|
|
421
|
+
<span class="fw-selected-node"
|
|
422
|
+
>${selectedPath.length === 0 ? "root" : chipSummary(selected)}</span
|
|
423
|
+
>
|
|
424
|
+
</div>
|
|
425
|
+
${renderExpressionEditor(selected, writeSelected, {
|
|
426
|
+
allowEventRef: editing.type === "event",
|
|
427
|
+
depth: 1,
|
|
428
|
+
path: selectedPath,
|
|
429
|
+
preview,
|
|
430
|
+
stateDefs: Object.keys(stateEntries),
|
|
431
|
+
stateEntries,
|
|
432
|
+
})}
|
|
433
|
+
</div>
|
|
434
|
+
${dataRailTemplate(scope)}
|
|
290
435
|
</div>
|
|
291
|
-
${
|
|
292
|
-
allowEventRef: editing.type === "event",
|
|
293
|
-
depth: 1,
|
|
294
|
-
path: selectedPath,
|
|
295
|
-
preview,
|
|
296
|
-
stateDefs: Object.keys(stateEntries),
|
|
297
|
-
stateEntries,
|
|
298
|
-
})}
|
|
436
|
+
${resultTemplate(preview)}
|
|
299
437
|
</div>
|
|
300
438
|
`;
|
|
439
|
+
}
|
|
301
440
|
|
|
302
|
-
|
|
441
|
+
/** The live data context — a SECOND opinion now that the page itself is on screen, not the only one. */
|
|
442
|
+
function dataRailTemplate(scope: Record<string, unknown> | null | undefined): TemplateResult {
|
|
303
443
|
const scopeEntries = scope ? Object.entries(scope) : [];
|
|
304
|
-
|
|
305
|
-
<div
|
|
306
|
-
class="fw-context"
|
|
307
|
-
style="width:280px;flex-shrink:0;overflow:auto;border-left:${PANE_BORDER};padding:16px"
|
|
308
|
-
>
|
|
309
|
-
<div
|
|
310
|
-
class="fw-context-title"
|
|
311
|
-
style="font-size:11px;text-transform:uppercase;letter-spacing:0.5px;color:var(--spectrum-gray-600, #808080);padding-bottom:8px"
|
|
312
|
-
>
|
|
313
|
-
Data
|
|
314
|
-
</div>
|
|
444
|
+
return html`
|
|
445
|
+
<div class="fw-context">
|
|
446
|
+
<div class="fw-context-title">Data</div>
|
|
315
447
|
${
|
|
316
448
|
scopeEntries.length === 0
|
|
317
449
|
? html`<div class="empty-state">No canvas data snapshot yet</div>`
|
|
318
450
|
: scopeEntries.map(([name, value]) => {
|
|
319
451
|
const unwrapped = unwrapSignal(value);
|
|
320
452
|
return html`
|
|
321
|
-
<div class="fw-context-entry"
|
|
322
|
-
<div
|
|
323
|
-
<span
|
|
324
|
-
|
|
325
|
-
style="${MONO};font-size:12px;color:var(--spectrum-gray-800, #d0d0d0)"
|
|
326
|
-
>${name}</span
|
|
327
|
-
>
|
|
328
|
-
<span style="font-size:10px;color:var(--spectrum-gray-600, #808080)"
|
|
329
|
-
>${dataTypeLabel(value)}</span
|
|
330
|
-
>
|
|
453
|
+
<div class="fw-context-entry">
|
|
454
|
+
<div class="fw-context-head">
|
|
455
|
+
<span class="fw-context-name">${name}</span>
|
|
456
|
+
<span class="fw-context-type">${dataTypeLabel(value)}</span>
|
|
331
457
|
</div>
|
|
332
458
|
<div class="data-tree">${renderDataTreeTemplate(unwrapped, 0, 4)}</div>
|
|
333
459
|
</div>
|
|
@@ -336,50 +462,114 @@ function workspaceTemplate(tab: Tab, editing: FormulaEditDef): TemplateResult {
|
|
|
336
462
|
}
|
|
337
463
|
</div>
|
|
338
464
|
`;
|
|
465
|
+
}
|
|
339
466
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
class="fw-result"
|
|
354
|
-
style="${MONO};font-size:12px;padding:10px 20px;border-top:${PANE_BORDER};color:var(--spectrum-seafoam-900, #35a690)"
|
|
355
|
-
>
|
|
356
|
-
= ${preview.values.get("") ?? "undefined"}
|
|
357
|
-
${
|
|
358
|
-
preview.mutating
|
|
359
|
-
? html`<span style="color:var(--spectrum-gray-600, #808080)"
|
|
360
|
-
>(mutates target)</span
|
|
361
|
-
>`
|
|
362
|
-
: ""
|
|
363
|
-
}
|
|
364
|
-
</div>
|
|
365
|
-
`
|
|
366
|
-
: html`
|
|
367
|
-
<div
|
|
368
|
-
class="fw-result fw-result--pending"
|
|
369
|
-
style="font-size:12px;padding:10px 20px;border-top:${PANE_BORDER};color:var(--spectrum-gray-600, #808080)"
|
|
370
|
-
>
|
|
371
|
-
Preview unavailable — the canvas has not posted a data snapshot yet
|
|
372
|
-
</div>
|
|
373
|
-
`;
|
|
374
|
-
|
|
467
|
+
/** The root result, the evaluation error, or the honest "nothing has evaluated this yet". */
|
|
468
|
+
function resultTemplate(preview: ExpressionPreview | null): TemplateResult {
|
|
469
|
+
if (preview?.error) {
|
|
470
|
+
return html`<div class="fw-result fw-result--error">${preview.error}</div>`;
|
|
471
|
+
}
|
|
472
|
+
if (preview) {
|
|
473
|
+
return html`
|
|
474
|
+
<div class="fw-result">
|
|
475
|
+
= ${preview.values.get("") ?? "undefined"}
|
|
476
|
+
${preview.mutating ? html`<span class="fw-result-note">(mutates target)</span>` : ""}
|
|
477
|
+
</div>
|
|
478
|
+
`;
|
|
479
|
+
}
|
|
375
480
|
return html`
|
|
376
|
-
<div
|
|
377
|
-
|
|
378
|
-
style="display:flex;flex-direction:column;flex:1;min-height:0;background:var(--spectrum-gray-75, #1d1d1d)"
|
|
379
|
-
>
|
|
380
|
-
${header} ${chips}
|
|
381
|
-
<div class="fw-body" style="display:flex;flex:1;min-height:0">${editor} ${rail}</div>
|
|
382
|
-
${footer}
|
|
481
|
+
<div class="fw-result fw-result--pending">
|
|
482
|
+
Preview unavailable — the canvas has not posted a data snapshot yet
|
|
383
483
|
</div>
|
|
384
484
|
`;
|
|
385
485
|
}
|
|
486
|
+
|
|
487
|
+
// ─── Commands ─────────────────────────────────────────────────────────────────
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* The formula/function EDITOR verbs — open a state entry's body or an event binding in Logic.
|
|
491
|
+
*
|
|
492
|
+
* They live here rather than beside `panels/editors.ts`'s renderer because this module already owns
|
|
493
|
+
* the other half of the same idea: `editingFormula` (the structured workspace) and
|
|
494
|
+
* `editingFunction` (the code editor) are two surfaces of ONE dock tab, addressing the same two
|
|
495
|
+
* document positions — a state entry by `defName`, or an element event binding by `path` +
|
|
496
|
+
* `eventKey`.
|
|
497
|
+
*
|
|
498
|
+
* Both REFUSE a target the document does not hold. The predecessors wrote `ui.editingFunction`
|
|
499
|
+
* straight from the automation hook with no check at all, so a renamed def opened an editor over
|
|
500
|
+
* nothing and the shot photographed an empty takeover.
|
|
501
|
+
*
|
|
502
|
+
* @returns {AnyCommand[]}
|
|
503
|
+
*/
|
|
504
|
+
export function formulaEditorCommands(): AnyCommand[] {
|
|
505
|
+
return [
|
|
506
|
+
{
|
|
507
|
+
args: argsSchema({
|
|
508
|
+
defName: stringProperty("The state entry whose body to open in the code editor."),
|
|
509
|
+
}),
|
|
510
|
+
category: "Document",
|
|
511
|
+
id: "formula.editDef",
|
|
512
|
+
level: "document",
|
|
513
|
+
menus: ["palette"],
|
|
514
|
+
group: "5_data",
|
|
515
|
+
requires: "an open document that defines state",
|
|
516
|
+
when: (ctx) => ctx.document.open,
|
|
517
|
+
run: (_commandCtx, args) => {
|
|
518
|
+
const defName = stringArg("formula.editDef", args, "defName");
|
|
519
|
+
const tab = activeTab.value;
|
|
520
|
+
if (!tab) {
|
|
521
|
+
throw new RangeError(`command "formula.editDef" needs an open document`);
|
|
522
|
+
}
|
|
523
|
+
const defs = tab.doc.document?.state ?? {};
|
|
524
|
+
if (!(defName in defs)) {
|
|
525
|
+
const defined = Object.keys(defs);
|
|
526
|
+
throw new RangeError(
|
|
527
|
+
`command "formula.editDef" argument "defName": "${defName}" is not a state entry ` +
|
|
528
|
+
`this document defines — it defines: ` +
|
|
529
|
+
`${defined.length > 0 ? defined.join(", ") : "nothing"}`,
|
|
530
|
+
);
|
|
531
|
+
}
|
|
532
|
+
openLogicTarget({ editing: { defName, type: "def" }, surface: "function" });
|
|
533
|
+
},
|
|
534
|
+
title: "Edit Function",
|
|
535
|
+
},
|
|
536
|
+
{
|
|
537
|
+
args: argsSchema({
|
|
538
|
+
eventKey: stringProperty('The event binding, e.g. "onclick".'),
|
|
539
|
+
path: pathProperty("The document path of the element that carries the binding."),
|
|
540
|
+
}),
|
|
541
|
+
category: "Document",
|
|
542
|
+
id: "formula.editEvent",
|
|
543
|
+
level: "document",
|
|
544
|
+
menus: ["palette"],
|
|
545
|
+
group: "5_data",
|
|
546
|
+
requires: "an open document",
|
|
547
|
+
when: (ctx) => ctx.document.open,
|
|
548
|
+
run: (_commandCtx, args) => {
|
|
549
|
+
const eventKey = stringArg("formula.editEvent", args, "eventKey");
|
|
550
|
+
const path = pathArg("formula.editEvent", args, "path");
|
|
551
|
+
const tab = activeTab.value;
|
|
552
|
+
if (!tab) {
|
|
553
|
+
throw new RangeError(`command "formula.editEvent" needs an open document`);
|
|
554
|
+
}
|
|
555
|
+
if (!getNodeAtPath(tab.doc.document, path)) {
|
|
556
|
+
throw new RangeError(
|
|
557
|
+
`command "formula.editEvent" argument "path": [${path.join(", ")}] addresses no ` +
|
|
558
|
+
`node in ${tab.documentPath ?? "the open document"}`,
|
|
559
|
+
);
|
|
560
|
+
}
|
|
561
|
+
openLogicTarget({ editing: { eventKey, path, type: "event" }, surface: "function" });
|
|
562
|
+
},
|
|
563
|
+
title: "Edit Event Handler",
|
|
564
|
+
},
|
|
565
|
+
];
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Register the formula/function editor verbs.
|
|
570
|
+
*
|
|
571
|
+
* @param {CommandRegistry} registry
|
|
572
|
+
*/
|
|
573
|
+
export function registerFormulaEditorCommands(registry: CommandRegistry): void {
|
|
574
|
+
registry.registerAll(formulaEditorCommands());
|
|
575
|
+
}
|