@jxsuite/studio 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/canvas.html +21 -0
- package/dist/chunks/Overlay.dev-qfjzkms8.js +23 -0
- package/dist/chunks/{Overlay.dev-cszx7yn5.js.map → Overlay.dev-qfjzkms8.js.map} +1 -1
- package/dist/chunks/{adapter-z8fkmbmv.js → adapter-qfnesn5v.js} +2 -2
- package/dist/chunks/{cf-settings-mmyv436d.js → cf-settings-73sh5z4p.js} +3 -3
- package/dist/chunks/{components-0hzentwq.js → components-2bpqp4mq.js} +5 -7
- package/dist/chunks/{components-0hzentwq.js.map → components-2bpqp4mq.js.map} +1 -1
- package/dist/chunks/content-source-34gnkbnn.js +38 -0
- package/dist/chunks/content-source-34gnkbnn.js.map +9 -0
- package/dist/chunks/convert-to-repeater-t8kxre5s.js +258 -0
- package/dist/chunks/convert-to-repeater-t8kxre5s.js.map +10 -0
- package/dist/chunks/extension-sections-6mqydz35.js +301 -0
- package/dist/chunks/extension-sections-6mqydz35.js.map +11 -0
- package/dist/chunks/files-8kn321h1.js +70 -0
- package/dist/chunks/files-8kn321h1.js.map +9 -0
- package/dist/chunks/{format-host-2c188n41.js → format-host-mkwsmt8d.js} +3 -3
- package/dist/chunks/git-panel-tjbr191d.js +51 -0
- package/dist/chunks/git-panel-tjbr191d.js.map +9 -0
- package/dist/chunks/{index-baeg2x3y.js → index-7pxchcce.js} +4 -3
- package/dist/chunks/{index-baeg2x3y.js.map → index-7pxchcce.js.map} +3 -3
- package/dist/chunks/{jx-validate-qx8degj7.js → jx-validate-v6qgknrs.js} +3 -3
- package/dist/chunks/layers-panel-87pb25km.js +58 -0
- package/dist/chunks/layers-panel-87pb25km.js.map +9 -0
- package/dist/chunks/{monaco-setup-zjdp9zdw.js → monaco-setup-e0yh25j4.js} +4 -75
- package/dist/chunks/{monaco-setup-zjdp9zdw.js.map → monaco-setup-e0yh25j4.js.map} +3 -4
- package/dist/chunks/publish-panel-m0fcgdrt.js +21 -0
- package/dist/chunks/publish-panel-m0fcgdrt.js.map +9 -0
- package/dist/chunks/quick-search-rhs6cbsb.js +53 -0
- package/dist/chunks/quick-search-rhs6cbsb.js.map +9 -0
- package/dist/chunks/right-panel-zpdxd98t.js +37 -0
- package/dist/chunks/right-panel-zpdxd98t.js.map +9 -0
- package/dist/chunks/section-registry-zmckaxf4.js +30 -0
- package/dist/chunks/section-registry-zmckaxf4.js.map +9 -0
- package/dist/chunks/sp-overlay.dev-9ran0sfq.js +18 -0
- package/dist/chunks/sp-overlay.dev-9ran0sfq.js.map +9 -0
- package/dist/chunks/sp-popover.dev-rebmdncr.js +9 -0
- package/dist/chunks/sp-popover.dev-rebmdncr.js.map +9 -0
- package/dist/chunks/sp-progress-circle.dev-5vkppfkt.js +15 -0
- package/dist/chunks/sp-progress-circle.dev-5vkppfkt.js.map +9 -0
- package/dist/chunks/sp-tooltip.dev-ykqrg8h5.js +15 -0
- package/dist/chunks/sp-tooltip.dev-ykqrg8h5.js.map +9 -0
- package/dist/chunks/{sp-tray.dev-pb2fsd65.js → sp-tray.dev-ey59vfh7.js} +10 -8
- package/dist/chunks/{sp-tray.dev-pb2fsd65.js.map → sp-tray.dev-ey59vfh7.js.map} +2 -2
- package/dist/chunks/{studio-9qr6fq7p.js → studio-0rqqhrdy.js} +10 -378
- package/dist/chunks/{studio-9qr6fq7p.js.map → studio-0rqqhrdy.js.map} +4 -14
- package/dist/chunks/{studio-5x6tqqec.js → studio-2sj1jj3v.js} +10 -8
- package/dist/chunks/{studio-5x6tqqec.js.map → studio-2sj1jj3v.js.map} +2 -2
- package/dist/chunks/{studio-h3fw0wn8.js → studio-3fk1ac9z.js} +6 -4
- package/dist/chunks/{studio-h3fw0wn8.js.map → studio-3fk1ac9z.js.map} +2 -2
- package/dist/chunks/studio-41exgzhq.js +6690 -0
- package/dist/chunks/studio-41exgzhq.js.map +38 -0
- package/dist/chunks/{studio-7v2bpweq.js → studio-4mqb9a0j.js} +6 -4
- package/dist/chunks/{studio-7v2bpweq.js.map → studio-4mqb9a0j.js.map} +2 -2
- package/dist/chunks/studio-50k77cca.js +1787 -0
- package/dist/chunks/studio-50k77cca.js.map +18 -0
- package/dist/chunks/{studio-56v3zwk6.js → studio-6a0h7sne.js} +10 -8
- package/dist/chunks/{studio-56v3zwk6.js.map → studio-6a0h7sne.js.map} +2 -2
- package/dist/chunks/studio-6f0am8f2.js +53 -0
- package/dist/chunks/studio-6f0am8f2.js.map +10 -0
- package/dist/chunks/studio-6nmjc5qk.js +7002 -0
- package/dist/chunks/studio-6nmjc5qk.js.map +32 -0
- package/dist/chunks/studio-7afd21nw.js +67 -0
- package/dist/chunks/studio-7afd21nw.js.map +10 -0
- package/dist/chunks/{studio-xze4zrs1.js → studio-7bmdvzne.js} +2 -2
- package/dist/chunks/studio-7bmdvzne.js.map +10 -0
- package/dist/chunks/studio-8jpzqk5s.js +128 -0
- package/dist/chunks/studio-8jpzqk5s.js.map +10 -0
- package/dist/chunks/studio-94m77tgk.js +1482 -0
- package/dist/chunks/studio-94m77tgk.js.map +13 -0
- package/dist/chunks/studio-9je6w5sq.js +1000 -0
- package/dist/chunks/studio-9je6w5sq.js.map +16 -0
- package/dist/chunks/{studio-w7c6kvk7.js → studio-a7pzveq1.js} +2 -2
- package/dist/chunks/{studio-97qcgvdn.js → studio-adn0z1k3.js} +14 -8
- package/dist/chunks/{studio-97qcgvdn.js.map → studio-adn0z1k3.js.map} +3 -3
- package/dist/chunks/{studio-kr88ryr7.js → studio-bsxxx3x2.js} +17 -15
- package/dist/chunks/{studio-kr88ryr7.js.map → studio-bsxxx3x2.js.map} +7 -6
- package/dist/chunks/studio-bw5dz6km.js +608 -0
- package/dist/chunks/studio-bw5dz6km.js.map +21 -0
- package/dist/chunks/studio-c6s5getc.js +4232 -0
- package/dist/chunks/studio-c6s5getc.js.map +39 -0
- package/dist/chunks/studio-cjm7fdjf.js +451 -0
- package/dist/chunks/studio-cjm7fdjf.js.map +14 -0
- package/dist/chunks/{studio-cx91mnh8.js → studio-ckwz4d3x.js} +53 -53
- package/dist/chunks/{studio-cx91mnh8.js.map → studio-ckwz4d3x.js.map} +5 -5
- package/dist/chunks/studio-dg7zyt5x.js +28 -0
- package/dist/chunks/studio-dg7zyt5x.js.map +10 -0
- package/dist/chunks/studio-dzcyvvvz.js +166 -0
- package/dist/chunks/studio-dzcyvvvz.js.map +10 -0
- package/dist/chunks/{studio-7kqe41sa.js → studio-evkr5d3b.js} +15 -7
- package/dist/chunks/{studio-7kqe41sa.js.map → studio-evkr5d3b.js.map} +5 -4
- package/dist/chunks/studio-f12h6177.js +411 -0
- package/dist/chunks/studio-f12h6177.js.map +13 -0
- package/dist/chunks/studio-hbp1s8m9.js +1817 -0
- package/dist/chunks/studio-hbp1s8m9.js.map +14 -0
- package/dist/chunks/studio-k2sxjph5.js +15295 -0
- package/dist/chunks/studio-k2sxjph5.js.map +235 -0
- package/dist/chunks/studio-myje51t3.js +385 -0
- package/dist/chunks/studio-myje51t3.js.map +12 -0
- package/dist/chunks/studio-na6rwzhw.js +353 -0
- package/dist/chunks/studio-na6rwzhw.js.map +11 -0
- package/dist/chunks/{studio-4k0m4fmp.js → studio-p471gg5n.js} +126 -3
- package/dist/chunks/studio-p471gg5n.js.map +14 -0
- package/dist/chunks/{studio-9bjwf0d4.js → studio-rgwcpast.js} +5 -46
- package/dist/chunks/{studio-9bjwf0d4.js.map → studio-rgwcpast.js.map} +4 -5
- package/dist/chunks/{studio-hhj92gcr.js → studio-s519zc99.js} +3 -3
- package/dist/chunks/studio-sas7mt3k.js +75 -0
- package/dist/chunks/studio-sas7mt3k.js.map +10 -0
- package/dist/chunks/studio-t5wqwzdh.js +74 -0
- package/dist/chunks/studio-t5wqwzdh.js.map +10 -0
- package/dist/chunks/{studio-9qpspwfn.js → studio-temv5bw4.js} +5 -5
- package/dist/chunks/{studio-9qpspwfn.js.map → studio-temv5bw4.js.map} +1 -1
- package/dist/chunks/{studio-qkvt37c0.js → studio-tr20m8g8.js} +669 -18
- package/dist/chunks/studio-tr20m8g8.js.map +9 -0
- package/dist/chunks/{studio-ygzav7z5.js → studio-v96qfnww.js} +5514 -4291
- package/dist/chunks/studio-v96qfnww.js.map +54 -0
- package/dist/chunks/studio-vcetc91k.js +659 -0
- package/dist/chunks/studio-vcetc91k.js.map +10 -0
- package/dist/chunks/{studio-n9zmpxjg.js → studio-vmymjefp.js} +2972 -4937
- package/dist/chunks/studio-vmymjefp.js.map +98 -0
- package/dist/chunks/{studio-bghqfmea.js → studio-wwseqyw0.js} +2 -2
- package/dist/chunks/studio-x9hmy5kr.js +390 -0
- package/dist/chunks/studio-x9hmy5kr.js.map +10 -0
- package/dist/chunks/studio-xa0ce0n7.js +335 -0
- package/dist/chunks/studio-xa0ce0n7.js.map +10 -0
- package/dist/chunks/studio-xm3dbxvn.js +378 -0
- package/dist/chunks/studio-xm3dbxvn.js.map +19 -0
- package/dist/chunks/{studio-nqw433kv.js → studio-xmvbhg31.js} +2 -2
- package/dist/chunks/studio-zv37yrfa.js +1054 -0
- package/dist/chunks/studio-zv37yrfa.js.map +13 -0
- package/dist/chunks/{ws-client-q7hkz3j9.js → ws-client-654ts66j.js} +6 -4
- package/dist/chunks/ws-client-654ts66j.js.map +11 -0
- package/dist/iframe-entry.js +668 -230
- package/dist/studio.js +23711 -35185
- package/index.html +35 -4685
- package/package.json +17 -15
- package/src/about/about-modal.ts +42 -11
- package/src/browse/library-commands.ts +240 -0
- package/src/browse/library-layouts.ts +369 -0
- package/src/browse/library-model.ts +396 -0
- package/src/browse/library-pane.ts +1049 -0
- package/src/browse/library-preview.ts +252 -0
- package/src/browse/library-source.ts +150 -0
- package/src/canvas/canvas-helpers.ts +33 -9
- package/src/canvas/canvas-live-render.ts +45 -29
- package/src/canvas/canvas-patcher.ts +151 -31
- package/src/canvas/canvas-perf.ts +46 -7
- package/src/canvas/canvas-render.ts +1092 -220
- package/src/canvas/canvas-surface.ts +240 -0
- package/src/canvas/canvas-utils.ts +1166 -124
- package/src/canvas/iframe-drop.ts +2 -1
- package/src/canvas/iframe-entry.ts +241 -4
- package/src/canvas/iframe-host.ts +1226 -143
- package/src/canvas/iframe-inline-edit.ts +31 -0
- package/src/canvas/iframe-interaction.ts +76 -16
- package/src/canvas/iframe-keys.ts +107 -45
- package/src/canvas/iframe-overlay.ts +38 -1
- package/src/canvas/iframe-protocol.ts +137 -2
- package/src/canvas/iframe-render.ts +70 -2
- package/src/canvas/iframe-slash.ts +6 -0
- package/src/canvas/path-mapping.ts +56 -6
- package/src/canvas/surface-registry.ts +292 -0
- package/src/collab/collab-commands.ts +244 -0
- package/src/collab/collab-session.ts +198 -32
- package/src/collab/collab-state.ts +28 -2
- package/src/collab/presence-chips.ts +100 -9
- package/src/commands/active-registry.ts +42 -0
- package/src/commands/app-commands.ts +176 -0
- package/src/commands/budget.ts +158 -0
- package/src/commands/command-args.ts +253 -0
- package/src/commands/context.ts +387 -0
- package/src/commands/defaults.ts +580 -0
- package/src/commands/keymap.ts +571 -0
- package/src/commands/levels.ts +345 -0
- package/src/commands/live-context.ts +193 -0
- package/src/commands/reference.ts +227 -0
- package/src/commands/registry.ts +293 -0
- package/src/component-props.ts +3 -2
- package/src/content/draft-state.ts +106 -0
- package/src/content/entry-commands.ts +282 -0
- package/src/content/entry-editor.ts +327 -0
- package/src/content/entry-fields.ts +116 -0
- package/src/content/entry-model.ts +175 -0
- package/src/editor/canvas-context-menu.ts +17 -11
- package/src/editor/canvas-slash-bridge.ts +11 -4
- package/src/editor/context-menu.ts +804 -204
- package/src/editor/convert-to-component.ts +31 -10
- package/src/editor/convert-to-repeater.ts +3 -2
- package/src/editor/inline-edit-apply.ts +5 -5
- package/src/editor/inline-edit.ts +86 -50
- package/src/editor/insert-zone-action.ts +1 -1
- package/src/editor/shortcuts.ts +1043 -329
- package/src/editor/slash-menu.ts +1 -0
- package/src/files/elements.ts +166 -0
- package/src/files/file-ops.ts +178 -31
- package/src/files/files.ts +898 -268
- package/src/files/fs-events.ts +21 -0
- package/src/files/media-meta.ts +203 -0
- package/src/files/media-paths.ts +141 -0
- package/src/files/media-upload.ts +7 -3
- package/src/files/media-usage.ts +189 -0
- package/src/github/github-auth.ts +235 -33
- package/src/github/github-publish.ts +80 -21
- package/src/grid/grid-controller.ts +152 -12
- package/src/grid/grid-layout.ts +225 -20
- package/src/grid/grid-open.ts +120 -0
- package/src/grid/grid-panel.ts +554 -39
- package/src/grid/grid-source.ts +27 -1
- package/src/grid/redirects-grid.ts +599 -0
- package/src/grid/redirects.ts +398 -0
- package/src/grid/sources/content-source.ts +108 -2
- package/src/i18n/i18n-commands.ts +322 -0
- package/src/new-project/add-repo-modal.ts +8 -10
- package/src/new-project/import-tab.ts +34 -9
- package/src/new-project/location-fields.ts +9 -1
- package/src/new-project/new-project-modal.ts +270 -262
- package/src/packages/jxsuite-update.ts +97 -48
- package/src/packages/pull-package-sync.ts +18 -9
- package/src/page-params.ts +2 -1
- package/src/panels/activity-bar.ts +152 -91
- package/src/panels/activity-panel.ts +481 -0
- package/src/panels/ai-chat/chat-markdown.ts +8 -3
- package/src/panels/ai-chat/chat-view.ts +245 -18
- package/src/panels/ai-chat/composer.ts +31 -5
- package/src/panels/ai-chat/sessions-view.ts +17 -10
- package/src/panels/ai-panel.ts +279 -120
- package/src/panels/block-action-bar.ts +1115 -224
- package/src/panels/bottom-dock.ts +337 -0
- package/src/panels/canvas-dnd-bridge.ts +37 -8
- package/src/panels/chat-panel.ts +29 -12
- package/src/panels/data-explorer.ts +254 -112
- package/src/panels/data-grid.ts +10 -4
- package/src/panels/dnd.ts +28 -51
- package/src/panels/editors.ts +434 -107
- package/src/panels/elements-panel.ts +66 -2
- package/src/panels/empty-state.ts +112 -0
- package/src/panels/events-panel.ts +596 -82
- package/src/panels/formula-workspace.ts +408 -218
- package/src/panels/frontmatter-fields.ts +51 -10
- package/src/panels/frontmatter-panel.ts +357 -79
- package/src/panels/git-panel.ts +375 -164
- package/src/panels/head-panel.ts +791 -85
- package/src/panels/i18n-panel.ts +592 -0
- package/src/panels/imports-panel.ts +95 -85
- package/src/panels/jump-bar.ts +584 -0
- package/src/panels/layers-panel.ts +1106 -328
- package/src/panels/left-panel.ts +109 -204
- package/src/panels/navigator-panels.ts +131 -0
- package/src/panels/overlays.ts +7 -2
- package/src/panels/pane-context.ts +1477 -0
- package/src/panels/pane-grid.ts +406 -0
- package/src/panels/panel-registry.ts +340 -0
- package/src/panels/panel-scheduler.ts +75 -0
- package/src/panels/problems-panel.ts +234 -0
- package/src/panels/properties-panel.ts +946 -1139
- package/src/panels/provenance.ts +258 -0
- package/src/panels/quick-search.ts +791 -122
- package/src/panels/right-panel.ts +228 -102
- package/src/panels/seo-modal.ts +395 -0
- package/src/panels/settings-pane.ts +203 -0
- package/src/panels/signals-panel.ts +354 -137
- package/src/panels/statement-editor.ts +41 -25
- package/src/panels/statusbar.ts +342 -106
- package/src/panels/style-panel.ts +974 -463
- package/src/panels/style-utils.ts +3 -3
- package/src/panels/stylebook-doc.ts +4 -2
- package/src/panels/stylebook-layers-panel.ts +3 -2
- package/src/panels/stylebook-panel.ts +51 -26
- package/src/panels/tab-strip.ts +1058 -78
- package/src/panels/target-line.ts +274 -0
- package/src/panels/toolbar.ts +631 -484
- package/src/panels/welcome-screen.ts +301 -198
- package/src/platform-errors.ts +26 -3
- package/src/platform.ts +96 -2
- package/src/platforms/cloud.ts +71 -8
- package/src/platforms/devserver.ts +92 -29
- package/src/publish/deploy-checklist.ts +383 -0
- package/src/publish/pages-service.ts +10 -1
- package/src/publish/publish-commands.ts +218 -0
- package/src/publish/publish-panel.ts +110 -16
- package/src/recent-projects.ts +3 -2
- package/src/services/a11y-report.ts +505 -0
- package/src/services/ai-models.ts +75 -2
- package/src/services/ai-project-tools.ts +29 -10
- package/src/services/ai-system-prompt.ts +53 -14
- package/src/services/ai-tools.ts +39 -3
- package/src/services/ai-writes.ts +154 -0
- package/src/services/announce.ts +97 -0
- package/src/services/automation.ts +424 -175
- package/src/services/cem-export.ts +9 -4
- package/src/services/clock.ts +61 -0
- package/src/services/document-assistant.ts +36 -8
- package/src/services/idle.ts +179 -0
- package/src/services/import-client.ts +26 -0
- package/src/services/monaco-buffer.ts +627 -0
- package/src/services/monaco-lazy.ts +36 -0
- package/src/services/notify.ts +271 -0
- package/src/services/profile.ts +155 -0
- package/src/services/references.ts +0 -0
- package/src/services/token-lint.ts +3 -2
- package/src/services/tool-executor.ts +53 -7
- package/src/services/trusted-types.ts +123 -0
- package/src/settings/contexts-section.ts +427 -0
- package/src/settings/contributed-section.ts +149 -11
- package/src/settings/css-vars-editor.ts +306 -349
- package/src/settings/defs-editor.ts +93 -34
- package/src/settings/dependencies-editor.ts +7 -7
- package/src/settings/extension-sections.ts +37 -5
- package/src/settings/general-settings.ts +204 -121
- package/src/settings/locales-section.ts +347 -0
- package/src/settings/preferences-accounts.ts +140 -0
- package/src/settings/preferences-dialog.ts +620 -0
- package/src/settings/preferences-keymap.ts +270 -0
- package/src/settings/project-sections.ts +260 -0
- package/src/settings/section-registry.ts +169 -0
- package/src/settings/settings-document.ts +385 -0
- package/src/shell.ts +1549 -0
- package/src/site-context.ts +45 -20
- package/src/state.ts +14 -275
- package/src/store.ts +88 -43
- package/src/studio.ts +790 -346
- package/src/style/live-preview.ts +36 -0
- package/src/style/project-styles.ts +349 -0
- package/src/style/token-ref.ts +123 -0
- package/src/tabs/patch-ops.ts +16 -4
- package/src/tabs/project-config.ts +416 -0
- package/src/tabs/selection.ts +323 -0
- package/src/tabs/tab.ts +182 -47
- package/src/tabs/transact.ts +209 -28
- package/src/types.ts +68 -13
- package/src/ui/ai-credentials-form.ts +39 -35
- package/src/ui/ai-managed-connect.ts +113 -0
- package/src/ui/dynamic-slot.ts +224 -81
- package/src/ui/expression-editor.ts +71 -63
- package/src/ui/field-input.ts +4 -6
- package/src/ui/field-row.ts +215 -38
- package/src/ui/form-controls.ts +194 -7
- package/src/ui/layers.ts +492 -69
- package/src/ui/media-picker.ts +115 -25
- package/src/ui/panel-resize.ts +109 -91
- package/src/ui/progress-modal.ts +131 -50
- package/src/ui/regions.ts +462 -0
- package/src/ui/schema-form.ts +229 -45
- package/src/ui/spectrum.ts +24 -8
- package/src/ui/timing.ts +49 -0
- package/src/ui/value-selector.ts +20 -0
- package/src/ui/value-source.ts +348 -0
- package/src/ui/virtual-window.ts +400 -0
- package/src/utils/edit-display.ts +3 -2
- package/src/utils/inherited-style.ts +67 -37
- package/src/view.ts +64 -78
- package/src/workspace/pane-derive.ts +1258 -0
- package/src/workspace/session.ts +317 -0
- package/src/workspace/workspace.ts +1345 -23
- package/styles/canvas.css +653 -0
- package/styles/forced-colors.css +106 -0
- package/styles/inspector.css +1454 -0
- package/styles/overlays.css +2704 -0
- package/styles/panels.css +1701 -0
- package/styles/shell.css +1423 -0
- package/styles/tokens.css +151 -0
- package/dist/chunks/Overlay.dev-cszx7yn5.js +0 -22
- package/dist/chunks/extension-sections-qct0gt8f.js +0 -531
- package/dist/chunks/extension-sections-qct0gt8f.js.map +0 -12
- package/dist/chunks/files-02zn5y24.js +0 -50
- package/dist/chunks/files-02zn5y24.js.map +0 -9
- package/dist/chunks/git-panel-mbb0y0hz.js +0 -28
- package/dist/chunks/git-panel-mbb0y0hz.js.map +0 -9
- package/dist/chunks/layers-panel-9qekmqk1.js +0 -26
- package/dist/chunks/layers-panel-9qekmqk1.js.map +0 -9
- package/dist/chunks/settings-modal-gj0hrah4.js +0 -29
- package/dist/chunks/settings-modal-gj0hrah4.js.map +0 -9
- package/dist/chunks/sp-overlay.dev-earn5as8.js +0 -17
- package/dist/chunks/sp-overlay.dev-earn5as8.js.map +0 -9
- package/dist/chunks/sp-popover.dev-frxtfejn.js +0 -8
- package/dist/chunks/sp-popover.dev-frxtfejn.js.map +0 -9
- package/dist/chunks/sp-progress-circle.dev-7tvw34h8.js +0 -14
- package/dist/chunks/sp-progress-circle.dev-7tvw34h8.js.map +0 -9
- package/dist/chunks/sp-tooltip.dev-a9fywesm.js +0 -21
- package/dist/chunks/sp-tooltip.dev-a9fywesm.js.map +0 -10
- package/dist/chunks/studio-4k0m4fmp.js.map +0 -13
- package/dist/chunks/studio-568nx4t5.js +0 -469
- package/dist/chunks/studio-568nx4t5.js.map +0 -14
- package/dist/chunks/studio-9smfzqhc.js +0 -19
- package/dist/chunks/studio-9smfzqhc.js.map +0 -10
- package/dist/chunks/studio-asvf0j9e.js +0 -429
- package/dist/chunks/studio-asvf0j9e.js.map +0 -13
- package/dist/chunks/studio-d77qm3pk.js +0 -3427
- package/dist/chunks/studio-d77qm3pk.js.map +0 -26
- package/dist/chunks/studio-j6gqyjf4.js +0 -1854
- package/dist/chunks/studio-j6gqyjf4.js.map +0 -18
- package/dist/chunks/studio-n9zmpxjg.js.map +0 -115
- package/dist/chunks/studio-qkvt37c0.js.map +0 -9
- package/dist/chunks/studio-rq0vxb19.js +0 -3744
- package/dist/chunks/studio-rq0vxb19.js.map +0 -22
- package/dist/chunks/studio-wd6ewdvd.js +0 -853
- package/dist/chunks/studio-wd6ewdvd.js.map +0 -12
- package/dist/chunks/studio-xq0t7n5t.js +0 -140
- package/dist/chunks/studio-xq0t7n5t.js.map +0 -10
- package/dist/chunks/studio-xze4zrs1.js.map +0 -10
- package/dist/chunks/studio-ygzav7z5.js.map +0 -46
- package/dist/chunks/studio-zmy7241e.js +0 -399
- package/dist/chunks/studio-zmy7241e.js.map +0 -12
- package/dist/chunks/ws-client-q7hkz3j9.js.map +0 -11
- package/src/browse/browse-modal.ts +0 -69
- package/src/browse/browse.ts +0 -904
- package/src/canvas/canvas-diff.ts +0 -216
- package/src/canvas/nested-site-style.ts +0 -58
- package/src/new-project/design-fields.ts +0 -264
- package/src/new-project/templates.ts +0 -61
- package/src/panels/tab-bar.ts +0 -548
- package/src/settings/settings-modal.ts +0 -203
- /package/dist/chunks/{adapter-z8fkmbmv.js.map → adapter-qfnesn5v.js.map} +0 -0
- /package/dist/chunks/{cf-settings-mmyv436d.js.map → cf-settings-73sh5z4p.js.map} +0 -0
- /package/dist/chunks/{format-host-2c188n41.js.map → format-host-mkwsmt8d.js.map} +0 -0
- /package/dist/chunks/{jx-validate-qx8degj7.js.map → jx-validate-v6qgknrs.js.map} +0 -0
- /package/dist/chunks/{studio-w7c6kvk7.js.map → studio-a7pzveq1.js.map} +0 -0
- /package/dist/chunks/{studio-hhj92gcr.js.map → studio-s519zc99.js.map} +0 -0
- /package/dist/chunks/{studio-bghqfmea.js.map → studio-wwseqyw0.js.map} +0 -0
- /package/dist/chunks/{studio-nqw433kv.js.map → studio-xmvbhg31.js.map} +0 -0
|
@@ -1,214 +1,463 @@
|
|
|
1
1
|
/// <reference lib="dom" />
|
|
2
2
|
/**
|
|
3
|
-
* Automation
|
|
4
|
-
* runner (see scripts/screenshots/ at the repo root). Installed as `window.__jxAutomation` only
|
|
5
|
-
* when the page URL carries `?automation=1`; without the flag production behavior is untouched.
|
|
3
|
+
* Automation.ts — the scripting surface, as a PROJECTION of the app.
|
|
6
4
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* Installed as `window.__jxAutomation` only when the page URL carries `?automation=1`. It exposes
|
|
6
|
+
* exactly three members (spec studio.md §13.5):
|
|
7
|
+
*
|
|
8
|
+
* - `run(id, args)` — **is** `registry.run(id, args)`, behind {@link isScriptable}. There is no
|
|
9
|
+
* second action table. A hand-maintained parallel list of what the app can do is what plan §2
|
|
10
|
+
* principle 1 defines as a defect, and this module used to be 39 entries of exactly that, 16 of
|
|
11
|
+
* them holding raw XPath into the shell and three of them matching RENDERED TEXT.
|
|
12
|
+
* - `seed(id, args)` — the {@link SEEDS} registry, under the **Remote Rule**: a seed may only write
|
|
13
|
+
* state whose real writer is a network or IPC boundary. It stands in for a remote, never for a
|
|
14
|
+
* user. {@link REFUSED_SEEDS} names what that excludes and why.
|
|
15
|
+
* - `probe` — read-only. {@link AutomationProbe.idle} (the predicate that replaced 115 sleeps),
|
|
16
|
+
* `state()` (the full `CommandContext`), `commands()`, `seeds()`, and `pointAt`/`revealPath`,
|
|
17
|
+
* which compose the app's own transforms and answer in top-document coordinates.
|
|
18
|
+
*
|
|
19
|
+
* **What is deliberately absent**, each a normative refusal in spec §13.5:
|
|
20
|
+
*
|
|
21
|
+
* 1. No method that takes a selector. If a script cannot say it in command ids and `JxPath`s, it
|
|
22
|
+
* cannot say it here.
|
|
23
|
+
* 2. No `setStatus`. Staging the word "Ready" over the status bar is lying to the reader; if a capture
|
|
24
|
+
* needs a calm status bar, the app has to BE calm.
|
|
25
|
+
* 3. No `toggle*`. A delta against unstated state is what silently inverted 23 manifest steps when the
|
|
26
|
+
* assistant's default flipped, and an agent calling `view.toggleAssistant` is guessing at state
|
|
27
|
+
* it cannot observe. {@link TOGGLE_ID} refuses them at runtime.
|
|
28
|
+
* 4. No compatibility shim. The predecessor carried `setRightTab`'s `if (tab === "assistant")`
|
|
29
|
+
* redirect, whose own comment said it existed "to keep the Screenshot-manifest verb working" — a
|
|
30
|
+
* pipeline artefact living in production code.
|
|
31
|
+
* 5. No presentation-state pokes. Automation mutates documents by running the commands a user runs, so
|
|
32
|
+
* every write goes through the transaction log.
|
|
10
33
|
*/
|
|
11
34
|
|
|
12
|
-
import {
|
|
13
|
-
import { setProjectState } from "../state";
|
|
35
|
+
import { render } from "../store";
|
|
14
36
|
import { seedProjectList } from "../project-list";
|
|
15
|
-
import { activeTab
|
|
16
|
-
import
|
|
17
|
-
import { applyPanelCollapse, view } from "../view";
|
|
18
|
-
import { setEditZoom as applyEditZoomLevel } from "../canvas/canvas-utils";
|
|
37
|
+
import { activeTab } from "../workspace/workspace";
|
|
38
|
+
import { shell } from "../shell";
|
|
19
39
|
import { collabState } from "../collab/collab-state";
|
|
40
|
+
import { canvasPointAt, revealCanvasPath } from "../canvas/iframe-host";
|
|
41
|
+
import { probeIdle } from "./idle";
|
|
42
|
+
import type { CanvasPoint } from "../canvas/iframe-host";
|
|
43
|
+
import type { IdleOptions } from "./idle";
|
|
44
|
+
import type { CommandContext } from "../commands/context";
|
|
45
|
+
import type { AnyCommand, CommandRegistry } from "../commands/registry";
|
|
20
46
|
import type { PeerPresence } from "../collab/collab-state";
|
|
21
47
|
import type { SeededAssistantMessage } from "../panels/ai-panel";
|
|
22
48
|
import type { PagesDeploymentInfo } from "../publish/pages-service";
|
|
49
|
+
import type { GitBranchesResult, GitStatusResult, ProjectListEntry } from "../types";
|
|
50
|
+
import type { GitLogEntry } from "../shell";
|
|
23
51
|
import type { JxPath } from "../state";
|
|
24
52
|
|
|
25
|
-
/**
|
|
53
|
+
/** Loosely-typed arguments, as they arrive from a manifest step, a palette prompt or a tool call. */
|
|
54
|
+
export type AutomationArgs = Record<string, unknown>;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* What the hook needs that it cannot import.
|
|
58
|
+
*
|
|
59
|
+
* Three entries, and the shape is the point: everything the predecessor took by injection —
|
|
60
|
+
* `getCanvasMode`, `openBrowseModal`, `openSettingsModal`, `render`, `setCanvasMode`,
|
|
61
|
+
* `statusMessage` — was a capability being re-implemented here instead of being a command.
|
|
62
|
+
*/
|
|
26
63
|
export interface AutomationDeps {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
openNewProjectModal: () => void;
|
|
31
|
-
openQuickSearchPalette: () => void;
|
|
32
|
-
openSettingsModal: (section?: string) => void;
|
|
33
|
-
render: () => void;
|
|
34
|
-
renderActivityBar: () => void;
|
|
64
|
+
/** The registry `run()` projects. One per window, exactly as the bootstrap builds it. */
|
|
65
|
+
registry: CommandRegistry;
|
|
66
|
+
/** The assistant's transcript sink — stands in for the model stream. */
|
|
35
67
|
seedAssistantMessages: (messages: SeededAssistantMessage[]) => void;
|
|
68
|
+
/** The publish panel's connected state — stands in for the Cloudflare Pages API. */
|
|
36
69
|
seedPublishConnected: (options: { accountId?: string; deployment: PagesDeploymentInfo }) => void;
|
|
37
|
-
setCanvasMode: (mode: string) => void;
|
|
38
|
-
statusMessage: (text: string) => void;
|
|
39
70
|
}
|
|
40
71
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
seedAssistant: (options: { messages: SeededAssistantMessage[] }) => void;
|
|
50
|
-
seedCollab: (options: { peers: PeerPresence[] }) => void;
|
|
51
|
-
seedPublish: (options: { accountId?: string; deployment: PagesDeploymentInfo }) => void;
|
|
52
|
-
showWelcome: (options?: { projects?: ProjectListEntry[] }) => void;
|
|
53
|
-
getState: () => {
|
|
54
|
-
activeTabId: string | null;
|
|
55
|
-
canvasMode: string;
|
|
56
|
-
canvasStatus: string | null;
|
|
57
|
-
leftTab: string;
|
|
58
|
-
};
|
|
59
|
-
select: (path: JxPath | null) => void;
|
|
60
|
-
setActivity: (tab: string) => void;
|
|
61
|
-
setCanvasMode: (mode: string) => void;
|
|
62
|
-
setRightTab: (tab: string) => void;
|
|
63
|
-
setStatus: (text: string) => void;
|
|
64
|
-
setTheme: (color: string) => void;
|
|
65
|
-
setZoom: (zoom: number) => void;
|
|
66
|
-
setEditZoom: (zoom: number) => void;
|
|
67
|
-
waitForCanvasReady: (timeoutMs?: number) => Promise<void>;
|
|
72
|
+
// ─── The idempotence rule ─────────────────────────────────────────────────────
|
|
73
|
+
|
|
74
|
+
/** `view.toggleAssistant` names a delta; `view.setAssistant` names a state. Only one is runnable. */
|
|
75
|
+
export const TOGGLE_ID = /\.toggle[A-Z]/;
|
|
76
|
+
|
|
77
|
+
/** The idempotent id a toggle should have become — printed so the fix is inside the refusal. */
|
|
78
|
+
export function setterFor(id: string): string {
|
|
79
|
+
return id.replace(/\.toggle([A-Z])/, (_match, initial: string) => `.set${initial}`);
|
|
68
80
|
}
|
|
69
81
|
|
|
70
|
-
/**
|
|
71
|
-
|
|
72
|
-
|
|
82
|
+
/**
|
|
83
|
+
* Whether a command projects into `run()`.
|
|
84
|
+
*
|
|
85
|
+
* Derived, not declared: everything the registry holds is a capability with an id, a gate and a
|
|
86
|
+
* `run`, which is exactly what a script needs. The one exclusion is the idempotence rule, so the
|
|
87
|
+
* projection cannot drift from the registry the way a hand-kept allow-list would.
|
|
88
|
+
*/
|
|
89
|
+
export function isScriptable(command: AnyCommand): boolean {
|
|
90
|
+
return !TOGGLE_ID.test(command.id);
|
|
73
91
|
}
|
|
74
92
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
93
|
+
// ─── The registry-gap declaration ─────────────────────────────────────────────
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* How a manifest id the registry does not declare is going to stop existing.
|
|
97
|
+
*
|
|
98
|
+
* - `command` — a thing a user does, so it becomes a registry record. The value names who lands it.
|
|
99
|
+
* - `seed` — a remote's state, addressed through {@link AutomationApi.seed}.
|
|
100
|
+
* - `refused` — §13.3 says the app will never provide it; the manifest step is deleted.
|
|
101
|
+
*/
|
|
102
|
+
export type GapDisposition = "command" | "seed" | "refused";
|
|
103
|
+
|
|
104
|
+
export interface ManifestId {
|
|
105
|
+
disposition: GapDisposition;
|
|
106
|
+
/** The phase that lands the record, or the sentence that refuses it. One line, for the error. */
|
|
107
|
+
note: string;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Ids the screenshot manifest still depends on and no registry declares. **No handlers, no
|
|
112
|
+
* behaviour.**
|
|
113
|
+
*
|
|
114
|
+
* The export name is the contract `scripts/check-shot-contract.ts` reads (`loadCommandTable` looks
|
|
115
|
+
* for `defaultCommandSet()`, `seedIds()` or `AUTOMATION_COMMANDS`), and it is all that is left of
|
|
116
|
+
* the 39-entry action table this module used to be: every `press`, every XPath, every rendered-text
|
|
117
|
+
* matcher and both label mirrors are gone, and `run()` never consults this map to decide what to DO
|
|
118
|
+
* — only to explain, when the registry refuses an id, which of the three fates that id has.
|
|
119
|
+
*
|
|
120
|
+
* This is a countdown, in the idiom of the checker's own `TOGGLE_DEBT`: it may only shrink. It went
|
|
121
|
+
* 39 → 8 when the manifest converted (S2), and 8 → 7 when `element.insertData` became `insert.data`
|
|
122
|
+
* (P5, `canvas/canvas-render.ts`). What left: every `seed` entry, now read off {@link seedIds} and
|
|
123
|
+
* answered from the live registry rather than from a hand-kept list; every `toggle*` entry, which
|
|
124
|
+
* {@link TOGGLE_ID} refuses before this map is ever consulted; and every `command` entry whose
|
|
125
|
+
* record has since landed.
|
|
126
|
+
*
|
|
127
|
+
* What is left is two kinds. Two `command` entries are the manifest's real registry gaps — each
|
|
128
|
+
* reached today by an `input` step clicking a hand-stamped region, and each of those steps carries
|
|
129
|
+
* an `unstable` hatch naming the phase that lands the record, so this map and that hatch count are
|
|
130
|
+
* the same debt. Five `refused` entries are NOT a countdown: they are §13.3's normative refusals,
|
|
131
|
+
* and they stay so that a caller reaching for one gets the reason instead of "unknown command".
|
|
132
|
+
*/
|
|
133
|
+
export const AUTOMATION_COMMANDS: Readonly<Record<string, ManifestId>> = {
|
|
134
|
+
"file.contextMenu": {
|
|
135
|
+
disposition: "refused",
|
|
136
|
+
note: "opening a menu to press an item names a control; the ITEM is the command",
|
|
137
|
+
},
|
|
138
|
+
"layers.contextMenu": {
|
|
139
|
+
disposition: "refused",
|
|
140
|
+
note: "matched RENDERED TEXT, which §13's R1 forbids; P5.5 stamps data-jx-path on rows",
|
|
141
|
+
},
|
|
142
|
+
"media.browse": { disposition: "command", note: "P7.5 — media.browse" },
|
|
143
|
+
"project.showWelcome": {
|
|
144
|
+
disposition: "refused",
|
|
145
|
+
note: "cold start is a startup profile (?profile=fresh), not an action",
|
|
146
|
+
},
|
|
147
|
+
"settings.setSection": {
|
|
148
|
+
disposition: "refused",
|
|
149
|
+
note: 'mirrored the section registry\'s LABELS; say settings.open { section: "cssVars" }',
|
|
150
|
+
},
|
|
151
|
+
"view.setStatus": {
|
|
152
|
+
disposition: "refused",
|
|
153
|
+
note: "the status bar is not staged — if a capture needs a calm shell, the app must BE calm",
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
// ─── The seed registry, under the Remote Rule ─────────────────────────────────
|
|
158
|
+
|
|
159
|
+
/** One staged fixture, and the boundary whose job it is doing. */
|
|
160
|
+
export interface SeedDefinition {
|
|
161
|
+
id: string;
|
|
162
|
+
/** The network or IPC boundary this seed stands in for. The Remote Rule, written down per seed. */
|
|
163
|
+
boundary: string;
|
|
164
|
+
run: (args: AutomationArgs) => void | Promise<void>;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Writes a seed will not do, and the reason, quoted back at the caller.
|
|
169
|
+
*
|
|
170
|
+
* Every one of these was a method on the old surface. Each writes state a USER writes, so each is a
|
|
171
|
+
* COMMAND — and a fixture that stages it photographs a state no session could have reached.
|
|
172
|
+
*/
|
|
173
|
+
export const REFUSED_SEEDS: Readonly<Record<string, string>> = {
|
|
174
|
+
openSettings: 'a user opens Settings — run("settings.open")',
|
|
175
|
+
select: 'a user selects a node — run("selection.set", { path })',
|
|
176
|
+
setActivity: 'a user picks a Navigator panel — run("navigator.showPanel", { panel })',
|
|
177
|
+
setRightTab: 'a user picks an Inspector tab — run("inspector.setTab", { tab })',
|
|
178
|
+
setStatus:
|
|
179
|
+
"the status bar reports what the app just did; staging it is the one lie §13.3 names outright",
|
|
180
|
+
setZoom: 'a user zooms — run("canvas.setZoom", { zoom })',
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
function arrayArg<T>(args: AutomationArgs, key: string): T[] {
|
|
184
|
+
const value = args[key];
|
|
185
|
+
if (value === undefined) {
|
|
186
|
+
return [];
|
|
187
|
+
}
|
|
188
|
+
if (!Array.isArray(value)) {
|
|
189
|
+
throw new TypeError(`seed argument "${key}" must be an array`);
|
|
190
|
+
}
|
|
191
|
+
return value as T[];
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function requiredArg<T>(args: AutomationArgs, key: string): T {
|
|
195
|
+
const value = args[key];
|
|
196
|
+
if (value === null || typeof value !== "object") {
|
|
197
|
+
throw new TypeError(`seed argument "${key}" must be an object`);
|
|
198
|
+
}
|
|
199
|
+
return value as T;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function optionalString(args: AutomationArgs, key: string): string | undefined {
|
|
203
|
+
const value = args[key];
|
|
204
|
+
if (value === undefined) {
|
|
205
|
+
return undefined;
|
|
206
|
+
}
|
|
207
|
+
if (typeof value !== "string") {
|
|
208
|
+
throw new TypeError(`seed argument "${key}" must be a string`);
|
|
209
|
+
}
|
|
210
|
+
return value;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* The declared seeds.
|
|
215
|
+
*
|
|
216
|
+
* Each one writes exactly what its named boundary would have written, and nothing else — the git
|
|
217
|
+
* seed does not also open the Source Control panel, because a user does that.
|
|
218
|
+
*/
|
|
219
|
+
export function createSeeds(deps: AutomationDeps): SeedDefinition[] {
|
|
220
|
+
return [
|
|
221
|
+
{
|
|
222
|
+
boundary: "the assistant's model stream",
|
|
223
|
+
id: "seed.assistant",
|
|
224
|
+
run: (args) => {
|
|
225
|
+
deps.seedAssistantMessages(arrayArg<SeededAssistantMessage>(args, "messages"));
|
|
226
|
+
},
|
|
87
227
|
},
|
|
88
|
-
|
|
89
|
-
|
|
228
|
+
{
|
|
229
|
+
boundary: "the collaboration websocket (awareness + sync)",
|
|
230
|
+
id: "seed.collab",
|
|
231
|
+
run: (args) => {
|
|
232
|
+
const tab = activeTab.value;
|
|
233
|
+
if (!tab) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const state = collabState(tab);
|
|
237
|
+
state.status = "synced";
|
|
238
|
+
state.active = true;
|
|
239
|
+
const peers: PeerPresence[] = [];
|
|
240
|
+
for (const peer of arrayArg<PeerPresence>(args, "peers")) {
|
|
241
|
+
const peerState = { ...peer.state };
|
|
242
|
+
// A peer with no focused document is focused on THIS one — the presence overlay keys on it.
|
|
243
|
+
peerState.focusedPath ??= tab.documentPath;
|
|
244
|
+
peers.push({ ...peer, state: peerState });
|
|
245
|
+
}
|
|
246
|
+
state.peers = peers;
|
|
247
|
+
render();
|
|
248
|
+
},
|
|
90
249
|
},
|
|
91
|
-
|
|
92
|
-
|
|
250
|
+
{
|
|
251
|
+
boundary: "the Cloudflare Pages API",
|
|
252
|
+
id: "seed.publish",
|
|
253
|
+
run: (args) => {
|
|
254
|
+
const accountId = optionalString(args, "accountId");
|
|
255
|
+
deps.seedPublishConnected({
|
|
256
|
+
deployment: requiredArg<PagesDeploymentInfo>(args, "deployment"),
|
|
257
|
+
...(accountId ? { accountId } : {}),
|
|
258
|
+
});
|
|
259
|
+
},
|
|
93
260
|
},
|
|
94
|
-
|
|
95
|
-
|
|
261
|
+
{
|
|
262
|
+
boundary: "the platform's git routes (`gitStatus` / `gitBranches` / `gitLog`)",
|
|
263
|
+
id: "seed.git",
|
|
264
|
+
run: (args) => {
|
|
265
|
+
// The working tree really is a remote here: the git-panel shot photographs whatever the
|
|
266
|
+
// Author happened to have dirty, because its project lives inside this repository.
|
|
267
|
+
shell.git.status = (args.status as GitStatusResult | undefined) ?? null;
|
|
268
|
+
shell.git.branches = (args.branches as GitBranchesResult | undefined) ?? null;
|
|
269
|
+
shell.git.logEntries = (args.log as GitLogEntry[] | undefined) ?? null;
|
|
270
|
+
shell.git.loading = false;
|
|
271
|
+
shell.git.error = null;
|
|
272
|
+
render();
|
|
273
|
+
},
|
|
96
274
|
},
|
|
97
|
-
|
|
98
|
-
|
|
275
|
+
{
|
|
276
|
+
boundary: "the platform's recent-projects store (desktop IPC / cloud API)",
|
|
277
|
+
id: "seed.projectList",
|
|
278
|
+
run: (args) => {
|
|
279
|
+
seedProjectList(arrayArg<ProjectListEntry>(args, "projects"));
|
|
280
|
+
render();
|
|
281
|
+
},
|
|
99
282
|
},
|
|
100
|
-
|
|
101
|
-
|
|
283
|
+
];
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Every declared seed id, read off {@link createSeeds} itself.
|
|
288
|
+
*
|
|
289
|
+
* `scripts/check-shot-contract.ts` needs to answer "is `seed.projectList` a real seed?" in a bare
|
|
290
|
+
* Bun process with no app. It could have read a hand-kept list — and a hand-kept list is precisely
|
|
291
|
+
* how `seed.git` and `seed.projectList` came to be missing from {@link AUTOMATION_COMMANDS} while
|
|
292
|
+
* both were shipping. Constructing the definitions is free: every seed's dependency is used inside
|
|
293
|
+
* its `run`, never while building it, so the no-op deps below can never be called.
|
|
294
|
+
*/
|
|
295
|
+
export function seedIds(): string[] {
|
|
296
|
+
const inert = {
|
|
297
|
+
registry: undefined as unknown as CommandRegistry,
|
|
298
|
+
seedAssistantMessages: () => {},
|
|
299
|
+
seedPublishConnected: () => {},
|
|
300
|
+
} satisfies AutomationDeps;
|
|
301
|
+
return createSeeds(inert).map((seed) => seed.id);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// ─── The API ──────────────────────────────────────────────────────────────────
|
|
305
|
+
|
|
306
|
+
/** One command as a script sees it — the projection, not a second declaration. */
|
|
307
|
+
export interface ScriptableCommand {
|
|
308
|
+
id: string;
|
|
309
|
+
title: string;
|
|
310
|
+
/** Whether its own `enablement` predicate would let it run right now. */
|
|
311
|
+
enabled: boolean;
|
|
312
|
+
/** The `requires` sentence when it would not. */
|
|
313
|
+
requires?: string;
|
|
314
|
+
/** The command's own JSON Schema — the palette's prompt and the AI tool's parameters. */
|
|
315
|
+
args?: object;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/** What `pointAt` can address. Region ids join `path` when P3.8's region registry lands. */
|
|
319
|
+
export interface AutomationTarget {
|
|
320
|
+
path: JxPath;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/** Read-only questions. Nothing here writes document or presentation state. */
|
|
324
|
+
export interface AutomationProbe {
|
|
325
|
+
/**
|
|
326
|
+
* Resolve when Studio has settled; reject with `NotIdleError.blockedBy` naming what it is waiting
|
|
327
|
+
* on. See `services/idle.ts` — the rejection is the reason this exists.
|
|
328
|
+
*/
|
|
329
|
+
idle: (options?: Pick<IdleOptions, "frames" | "timeoutMs">) => Promise<void>;
|
|
330
|
+
/** The full `CommandContext` — the same record every `when` predicate and AI tool gate reads. */
|
|
331
|
+
state: () => CommandContext;
|
|
332
|
+
/** Every command a script may run right now, with its gate already evaluated. */
|
|
333
|
+
commands: () => ScriptableCommand[];
|
|
334
|
+
/** The declared seed ids, with the boundary each stands in for. */
|
|
335
|
+
seeds: () => { id: string; boundary: string }[];
|
|
336
|
+
/** Where a node is on screen, in TOP-DOCUMENT coordinates. Measures; moves nothing. */
|
|
337
|
+
pointAt: (target: AutomationTarget) => Promise<CanvasPoint | null>;
|
|
338
|
+
/** Bring a node into view and answer where it landed — the app's own jump-to-node. */
|
|
339
|
+
revealPath: (path: JxPath) => Promise<CanvasPoint | null>;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export interface AutomationApi {
|
|
343
|
+
run: (id: string, args?: AutomationArgs) => Promise<void>;
|
|
344
|
+
seed: (id: string, args?: AutomationArgs) => Promise<void>;
|
|
345
|
+
probe: AutomationProbe;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/** Thrown when the surface refuses an id on principle rather than because it is unknown. */
|
|
349
|
+
export class AutomationRefusedError extends Error {
|
|
350
|
+
readonly id: string;
|
|
351
|
+
|
|
352
|
+
constructor(id: string, reason: string) {
|
|
353
|
+
super(`automation refuses "${id}" — ${reason}`);
|
|
354
|
+
this.name = "AutomationRefusedError";
|
|
355
|
+
this.id = id;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/** The projection: every visible, scriptable command with its gate already evaluated. */
|
|
360
|
+
export function scriptableCommands(registry: CommandRegistry): ScriptableCommand[] {
|
|
361
|
+
const projected: ScriptableCommand[] = [];
|
|
362
|
+
for (const command of registry.visible()) {
|
|
363
|
+
if (!isScriptable(command)) {
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
const requires = registry.disabledReason(command.id);
|
|
367
|
+
const entry: ScriptableCommand = {
|
|
368
|
+
enabled: requires === undefined,
|
|
369
|
+
id: command.id,
|
|
370
|
+
title: command.title,
|
|
371
|
+
};
|
|
372
|
+
if (command.args) {
|
|
373
|
+
entry.args = command.args;
|
|
374
|
+
}
|
|
375
|
+
if (requires !== undefined) {
|
|
376
|
+
entry.requires = requires;
|
|
377
|
+
}
|
|
378
|
+
projected.push(entry);
|
|
379
|
+
}
|
|
380
|
+
return projected;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/** Why an id the registry does not declare is not runnable — the countdown, said out loud. */
|
|
384
|
+
function unknownCommandMessage(
|
|
385
|
+
id: string,
|
|
386
|
+
registry: CommandRegistry,
|
|
387
|
+
seeds: ReadonlySet<string>,
|
|
388
|
+
): string {
|
|
389
|
+
// Derived from the live seed registry, not from a hand-kept `disposition: "seed"` list: a seed
|
|
390
|
+
// Added next week answers this question without anyone remembering to write it down twice.
|
|
391
|
+
if (seeds.has(id)) {
|
|
392
|
+
return `"${id}" is a seed, not a command — call seed("${id}", …)`;
|
|
393
|
+
}
|
|
394
|
+
const gap = AUTOMATION_COMMANDS[id];
|
|
395
|
+
if (gap?.disposition === "refused") {
|
|
396
|
+
return `"${id}" is refused by spec §13.5: ${gap.note}`;
|
|
397
|
+
}
|
|
398
|
+
if (gap) {
|
|
399
|
+
return `"${id}" has no command record yet (${gap.note}) — __jxAutomation.run projects the registry and nothing else`;
|
|
400
|
+
}
|
|
401
|
+
const known = registry
|
|
402
|
+
.list()
|
|
403
|
+
.filter((command) => isScriptable(command))
|
|
404
|
+
.map((command) => command.id);
|
|
405
|
+
return `unknown command "${id}" — the registry declares ${known.length} scriptable id(s)`;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
export function createAutomationApi(deps: AutomationDeps): AutomationApi {
|
|
409
|
+
const seeds = new Map(createSeeds(deps).map((seed) => [seed.id, seed]));
|
|
410
|
+
const seedIdSet = new Set(seeds.keys());
|
|
411
|
+
|
|
412
|
+
return {
|
|
413
|
+
probe: {
|
|
414
|
+
commands: () => scriptableCommands(deps.registry),
|
|
415
|
+
idle: (options = {}) => probeIdle(options),
|
|
416
|
+
pointAt: (target) => canvasPointAt(target.path),
|
|
417
|
+
revealPath: (path) => revealCanvasPath(path),
|
|
418
|
+
seeds: () => [...seeds.values()].map((seed) => ({ boundary: seed.boundary, id: seed.id })),
|
|
419
|
+
state: () => deps.registry.context(),
|
|
102
420
|
},
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
421
|
+
async run(id, args = {}) {
|
|
422
|
+
if (TOGGLE_ID.test(id)) {
|
|
423
|
+
throw new AutomationRefusedError(
|
|
424
|
+
id,
|
|
425
|
+
`it names a delta against state the caller cannot observe; call "${setterFor(id)}"`,
|
|
426
|
+
);
|
|
109
427
|
}
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
state.peers = options.peers.map((peer) => ({
|
|
114
|
-
...peer,
|
|
115
|
-
state: {
|
|
116
|
-
...peer.state,
|
|
117
|
-
focusedPath: peer.state.focusedPath ?? tab.documentPath,
|
|
118
|
-
},
|
|
119
|
-
}));
|
|
120
|
-
deps.render();
|
|
121
|
-
},
|
|
122
|
-
seedPublish(options: { accountId?: string; deployment: PagesDeploymentInfo }) {
|
|
123
|
-
deps.seedPublishConnected(options);
|
|
124
|
-
},
|
|
125
|
-
showWelcome(options?: { projects?: ProjectListEntry[] }) {
|
|
126
|
-
// The devserver platform auto-opens the repo-root project on boot; the welcome
|
|
127
|
-
// Screen only renders with no project and no tabs, so stage that state directly.
|
|
128
|
-
// A staged catalogue replaces the real one (screenshots must not leak local paths).
|
|
129
|
-
closeAllTabs();
|
|
130
|
-
setProjectState(null);
|
|
131
|
-
if (options?.projects) {
|
|
132
|
-
seedProjectList(options.projects);
|
|
428
|
+
const { registry } = deps;
|
|
429
|
+
if (!registry.get(id)) {
|
|
430
|
+
throw new Error(unknownCommandMessage(id, registry, seedIdSet));
|
|
133
431
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
},
|
|
138
|
-
getState() {
|
|
139
|
-
return {
|
|
140
|
-
activeTabId: workspace.activeTabId,
|
|
141
|
-
canvasMode: deps.getCanvasMode(),
|
|
142
|
-
canvasStatus: activeTab.value?.session.canvas.status ?? null,
|
|
143
|
-
leftTab: view.leftTab,
|
|
144
|
-
};
|
|
432
|
+
// Refusal propagates as `CommandUnavailableError`: a step asking for a state the app refuses
|
|
433
|
+
// Must FAIL, because that step is lying about what the app can be.
|
|
434
|
+
await registry.run(id, args);
|
|
145
435
|
},
|
|
146
|
-
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
436
|
+
async seed(id, args = {}) {
|
|
437
|
+
const bare = id.startsWith("seed.") ? id.slice(5) : id;
|
|
438
|
+
const refusal = REFUSED_SEEDS[bare];
|
|
439
|
+
if (refusal) {
|
|
440
|
+
throw new AutomationRefusedError(
|
|
441
|
+
id,
|
|
442
|
+
`a seed stands in for a remote, never for a user: ${refusal}`,
|
|
443
|
+
);
|
|
150
444
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
applyPanelCollapse();
|
|
157
|
-
renderOnly("leftPanel");
|
|
158
|
-
deps.renderActivityBar();
|
|
159
|
-
},
|
|
160
|
-
setCanvasMode(mode: string) {
|
|
161
|
-
deps.setCanvasMode(mode);
|
|
162
|
-
deps.render();
|
|
163
|
-
},
|
|
164
|
-
setRightTab(tab: string) {
|
|
165
|
-
// "assistant" now lives in the persistent chat sidebar, not the right panel — keep the
|
|
166
|
-
// Screenshot-manifest verb working by opening that sidebar instead.
|
|
167
|
-
if (tab === "assistant") {
|
|
168
|
-
view.chatPanelCollapsed = false;
|
|
169
|
-
applyPanelCollapse();
|
|
170
|
-
renderOnly("chatPanel");
|
|
171
|
-
deps.render();
|
|
172
|
-
return;
|
|
445
|
+
const seed = seeds.get(id.startsWith("seed.") ? id : `seed.${id}`);
|
|
446
|
+
if (!seed) {
|
|
447
|
+
throw new Error(
|
|
448
|
+
`unknown seed "${id}" — declared seeds are ${[...seeds.keys()].join(", ")}`,
|
|
449
|
+
);
|
|
173
450
|
}
|
|
174
|
-
|
|
175
|
-
deps.render();
|
|
176
|
-
},
|
|
177
|
-
setStatus(text: string) {
|
|
178
|
-
deps.statusMessage(text);
|
|
179
|
-
},
|
|
180
|
-
setTheme(color: string) {
|
|
181
|
-
document.querySelector("sp-theme")?.setAttribute("color", color);
|
|
182
|
-
},
|
|
183
|
-
setZoom(zoom: number) {
|
|
184
|
-
updateUi("zoom", zoom);
|
|
185
|
-
deps.render();
|
|
186
|
-
},
|
|
187
|
-
setEditZoom(zoom: number) {
|
|
188
|
-
// Deliberately NOT deps.render(): live edit zoom must never re-render the canvas (it would
|
|
189
|
-
// Rebuild the iframe DOM) — setEditZoom applies bare style writes, matching production paths.
|
|
190
|
-
applyEditZoomLevel(zoom);
|
|
191
|
-
},
|
|
192
|
-
waitForCanvasReady(timeoutMs = 30_000) {
|
|
193
|
-
return new Promise((resolve, reject) => {
|
|
194
|
-
const started = Date.now();
|
|
195
|
-
const tick = () => {
|
|
196
|
-
if (activeTab.value?.session.canvas.status === "ready") {
|
|
197
|
-
resolve();
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
if (Date.now() - started > timeoutMs) {
|
|
201
|
-
reject(new Error(`canvas not ready after ${timeoutMs}ms`));
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
setTimeout(tick, 50);
|
|
205
|
-
};
|
|
206
|
-
tick();
|
|
207
|
-
});
|
|
451
|
+
await seed.run(args);
|
|
208
452
|
},
|
|
209
453
|
};
|
|
210
454
|
}
|
|
211
455
|
|
|
456
|
+
/** The hook is opt-in per page load: only `?automation=1` installs it. */
|
|
457
|
+
export function shouldInstallAutomation(search: string): boolean {
|
|
458
|
+
return new URLSearchParams(search).get("automation") === "1";
|
|
459
|
+
}
|
|
460
|
+
|
|
212
461
|
/**
|
|
213
462
|
* Install the hook on globalThis when the current URL opts in. Returns whether it installed, so
|
|
214
463
|
* callers (and tests) can assert the gate.
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
/// <reference lib="dom" />
|
|
2
2
|
import type { CemParameter, JxMutableNode, JxStateObject } from "@jxsuite/schema/types";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
displayTagName,
|
|
5
|
+
isFunctionDef,
|
|
6
|
+
isJsonObject,
|
|
7
|
+
isPrivateStateKey,
|
|
8
|
+
} from "@jxsuite/schema/guards";
|
|
4
9
|
|
|
5
10
|
/** Collect slot elements from the document tree. Whitespace-only names count as unnamed. */
|
|
6
11
|
export function collectSlots(node?: JxMutableNode | null, slots: string[] = []) {
|
|
@@ -58,7 +63,7 @@ export function exportCemManifest(
|
|
|
58
63
|
const { defCategory, normParam, collectCssParts } = helpers;
|
|
59
64
|
const doc = S.document;
|
|
60
65
|
const { tagName } = doc;
|
|
61
|
-
if (!tagName || !tagName.includes("-")) {
|
|
66
|
+
if (!tagName || !displayTagName(tagName).includes("-")) {
|
|
62
67
|
return;
|
|
63
68
|
}
|
|
64
69
|
|
|
@@ -69,9 +74,9 @@ export function exportCemManifest(
|
|
|
69
74
|
const seenEvents = new Set<string>();
|
|
70
75
|
|
|
71
76
|
for (const [key, d] of Object.entries(state)) {
|
|
72
|
-
if (key
|
|
77
|
+
if (isPrivateStateKey(key)) {
|
|
73
78
|
continue;
|
|
74
|
-
} // Private
|
|
79
|
+
} // Private (spec.md §5.6)
|
|
75
80
|
|
|
76
81
|
const cat = defCategory(d);
|
|
77
82
|
|