@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
|
@@ -8,7 +8,22 @@ import { reactive, toRaw } from "../reactivity";
|
|
|
8
8
|
import type { Tab } from "../tabs/tab";
|
|
9
9
|
import type { CollabAwarenessState } from "@jxsuite/collab/awareness-types";
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* What co-editing is doing for this tab.
|
|
13
|
+
*
|
|
14
|
+
* `"detached"` used to mean three different things at once and say none of them: this build has no
|
|
15
|
+
* collaboration at all, this project has collaboration but this tab is solo, and the attach was
|
|
16
|
+
* tried and it FAILED. §7.4: a freeze is currently indistinguishable from a bug, and so was a
|
|
17
|
+
* broken connection. `"unavailable"` and `"failed"` split the third and first cases out, so the
|
|
18
|
+
* chip can say which one it is.
|
|
19
|
+
*/
|
|
20
|
+
export type CollabTabStatus =
|
|
21
|
+
| "unavailable"
|
|
22
|
+
| "detached"
|
|
23
|
+
| "connecting"
|
|
24
|
+
| "synced"
|
|
25
|
+
| "offline"
|
|
26
|
+
| "failed";
|
|
12
27
|
|
|
13
28
|
export interface PeerPresence {
|
|
14
29
|
clientId: number;
|
|
@@ -25,8 +40,18 @@ export interface TabCollabState {
|
|
|
25
40
|
/**
|
|
26
41
|
* True while source holds the canonical lock (someone is co-editing the code view): structural
|
|
27
42
|
* surfaces soft-freeze and the canvas previews the source reconciler's parses.
|
|
43
|
+
*
|
|
44
|
+
* The freeze is real and it is brief, and until now its only rendering was a grey line for three
|
|
45
|
+
* seconds — which is exactly what a bug looks like. It gets an indicator (§7.4).
|
|
28
46
|
*/
|
|
29
47
|
sourceCanonical: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Why the last attach failed, when it did. Empty while `status` is anything but `"failed"`.
|
|
50
|
+
*
|
|
51
|
+
* The attach used to swallow its own exception into `status = "detached"`, so a dead relay, an
|
|
52
|
+
* expired token and a project that simply is not shared all produced the same silence.
|
|
53
|
+
*/
|
|
54
|
+
attachError: string;
|
|
30
55
|
}
|
|
31
56
|
|
|
32
57
|
const states = new WeakMap<Tab, TabCollabState>();
|
|
@@ -40,10 +65,11 @@ export function collabState(tab: Tab): TabCollabState {
|
|
|
40
65
|
if (!state) {
|
|
41
66
|
state = reactive({
|
|
42
67
|
active: false,
|
|
68
|
+
attachError: "",
|
|
43
69
|
peers: [],
|
|
44
70
|
readOnly: false,
|
|
45
71
|
sourceCanonical: false,
|
|
46
|
-
status: "
|
|
72
|
+
status: "unavailable",
|
|
47
73
|
}) as TabCollabState;
|
|
48
74
|
states.set(key, state);
|
|
49
75
|
}
|
|
@@ -1,13 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Presence chips — who else is in this co-editing session,
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Presence chips — who else is in this co-editing session, the sync-status pill that replaces the
|
|
3
|
+
* dirty dot for collab tabs, and the two states co-editing had no way to announce (§7.4).
|
|
4
|
+
*
|
|
5
|
+
* Pure lit templates over `collabState(tab)`; the toolbar includes them and its render effect
|
|
6
|
+
* tracks the underlying reactive state.
|
|
7
|
+
*
|
|
8
|
+
* **What was invisible.** Three things:
|
|
9
|
+
*
|
|
10
|
+
* - **The source-canonical freeze.** While a peer holds the code view, structural edits are refused.
|
|
11
|
+
* The whole rendering of that was a three-second grey status line the moment you tried — which is
|
|
12
|
+
* precisely what a bug looks like. It gets a persistent indicator, so the refusal has a visible
|
|
13
|
+
* cause standing beside it for as long as it is true.
|
|
14
|
+
* - **Read-only guests.** Their edits applied locally and were dropped at the publish gate. They now
|
|
15
|
+
* get a banner that says so before they type, not a silence after.
|
|
16
|
+
* - **A failed attach.** It set `status = "detached"` — the same value a solo document carries — so a
|
|
17
|
+
* dead relay was indistinguishable from nobody having shared the file. `"failed"` and
|
|
18
|
+
* `"unavailable"` are now separate states with separate sentences.
|
|
19
|
+
*
|
|
20
|
+
* **Undo says what it does.** The Y.UndoManager is constructed with `trackedOrigins:
|
|
21
|
+
* {LOCAL_ORIGIN}`, so ⌘Z reaches your own actions and never a peer's. That is the correct behaviour
|
|
22
|
+
* and it is also surprising, so the status pill's title states it — §13 lists this as adopted
|
|
23
|
+
* precisely because silently undoing someone else's work is worse than not undoing.
|
|
5
24
|
*/
|
|
6
25
|
|
|
7
26
|
import { html, nothing } from "lit-html";
|
|
8
27
|
import type { TemplateResult } from "lit-html";
|
|
9
28
|
import { collabState } from "./collab-state";
|
|
10
|
-
import type { PeerPresence } from "./collab-state";
|
|
29
|
+
import type { CollabTabStatus, PeerPresence } from "./collab-state";
|
|
11
30
|
import type { Tab } from "../tabs/tab";
|
|
12
31
|
|
|
13
32
|
function initialOf(peer: PeerPresence): string {
|
|
@@ -22,25 +41,71 @@ function titleOf(peer: PeerPresence, docPath: string | null): string {
|
|
|
22
41
|
return here ? who : `${who} — ${peer.state.focusedPath ?? "browsing"}`;
|
|
23
42
|
}
|
|
24
43
|
|
|
25
|
-
|
|
44
|
+
/** One line per status. Every state says what it is; none of them say nothing. */
|
|
45
|
+
const STATUS_LABEL: Readonly<Record<CollabTabStatus, string>> = {
|
|
26
46
|
connecting: "Connecting…",
|
|
47
|
+
detached: "Solo",
|
|
48
|
+
failed: "Not connected",
|
|
27
49
|
offline: "Offline — changes sync on reconnect",
|
|
28
50
|
synced: "Live",
|
|
51
|
+
unavailable: "",
|
|
29
52
|
};
|
|
30
53
|
|
|
31
|
-
/**
|
|
54
|
+
/**
|
|
55
|
+
* The sentence behind the pill — including the one undo fact nobody would guess.
|
|
56
|
+
*
|
|
57
|
+
* @param {CollabTabStatus} status
|
|
58
|
+
* @param {string} attachError
|
|
59
|
+
* @returns {string}
|
|
60
|
+
*/
|
|
61
|
+
export function statusTitle(status: CollabTabStatus, attachError: string): string {
|
|
62
|
+
if (status === "failed") {
|
|
63
|
+
return (
|
|
64
|
+
`Live collaboration could not start${attachError ? ` — ${attachError}` : ""}. ` +
|
|
65
|
+
"Your edits are saved to this machine as usual."
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
if (status === "synced" || status === "offline") {
|
|
69
|
+
return `${STATUS_LABEL[status]}. Undo only takes back your own edits, never a collaborator's.`;
|
|
70
|
+
}
|
|
71
|
+
return STATUS_LABEL[status];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Chips + status pill for the toolbar; `nothing` while the tab has no collaboration to report. */
|
|
32
75
|
export function presenceChipsTemplate(tab: Tab | null): TemplateResult | typeof nothing {
|
|
33
76
|
if (!tab) {
|
|
34
77
|
return nothing;
|
|
35
78
|
}
|
|
36
79
|
const state = collabState(tab);
|
|
37
|
-
|
|
80
|
+
/* "unavailable" is the only silent state: this build has no collaboration, so there is nothing to
|
|
81
|
+
be honest ABOUT. Every other state — including solo and failed — says which one it is. */
|
|
82
|
+
if (state.status === "unavailable") {
|
|
38
83
|
return nothing;
|
|
39
84
|
}
|
|
40
|
-
const label = STATUS_LABEL[state.status]
|
|
85
|
+
const label = STATUS_LABEL[state.status] || state.status;
|
|
41
86
|
return html`
|
|
42
|
-
<div class="jx-presence" title=${
|
|
87
|
+
<div class="jx-presence" title=${statusTitle(state.status, state.attachError)}>
|
|
43
88
|
<span class="jx-presence-status" data-status=${state.status}>${label}</span>
|
|
89
|
+
${
|
|
90
|
+
state.readOnly
|
|
91
|
+
? html`<span
|
|
92
|
+
class="jx-presence-flag"
|
|
93
|
+
data-flag="read-only"
|
|
94
|
+
title="You have read access to this session. Your edits show here but are not published to the others."
|
|
95
|
+
>Read-only</span
|
|
96
|
+
>`
|
|
97
|
+
: nothing
|
|
98
|
+
}
|
|
99
|
+
${
|
|
100
|
+
state.sourceCanonical
|
|
101
|
+
? html`<span
|
|
102
|
+
class="jx-presence-flag"
|
|
103
|
+
data-flag="frozen"
|
|
104
|
+
title="Someone is editing the code view. Structural edits are paused until they stop — this is not an error."
|
|
105
|
+
>Code view held</span
|
|
106
|
+
>`
|
|
107
|
+
: nothing
|
|
108
|
+
}
|
|
44
109
|
${state.peers.map(
|
|
45
110
|
(peer) => html`
|
|
46
111
|
<span
|
|
@@ -58,3 +123,29 @@ export function presenceChipsTemplate(tab: Tab | null): TemplateResult | typeof
|
|
|
58
123
|
</div>
|
|
59
124
|
`;
|
|
60
125
|
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* The read-only banner — a standing statement, not an after-the-fact refusal.
|
|
129
|
+
*
|
|
130
|
+
* A guest without write access used to watch their edits apply locally and be dropped silently at
|
|
131
|
+
* the publish gate, which reads as the app losing work. The sentence has to be there before the
|
|
132
|
+
* first keystroke, so it is rendered by the PANE CHROME (`panels/pane-context.ts`) rather than by
|
|
133
|
+
* the toolbar the chips ride in: the chrome is per-pane and per-document, it sits directly above
|
|
134
|
+
* the editing surface, and the stage is offset by the band it lives in — so the banner pushes the
|
|
135
|
+
* document down instead of covering it.
|
|
136
|
+
*/
|
|
137
|
+
export function readOnlyBannerTemplate(tab: Tab | null): TemplateResult | typeof nothing {
|
|
138
|
+
if (!tab) {
|
|
139
|
+
return nothing;
|
|
140
|
+
}
|
|
141
|
+
const state = collabState(tab);
|
|
142
|
+
if (!state.active || !state.readOnly) {
|
|
143
|
+
return nothing;
|
|
144
|
+
}
|
|
145
|
+
return html`
|
|
146
|
+
<div class="jx-collab-banner" role="status" data-kind="read-only">
|
|
147
|
+
You have read access to this session. You can explore and edit locally, but your changes are
|
|
148
|
+
not published to the other people in it.
|
|
149
|
+
</div>
|
|
150
|
+
`;
|
|
151
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Active-registry.ts — the one registry this window's chrome renders from.
|
|
3
|
+
*
|
|
4
|
+
* `registry.ts` deliberately has no module-level singleton: the context a registry closes over is
|
|
5
|
+
* one window's, the CI checks build their own, and every test wants a registry it can state
|
|
6
|
+
* exactly. That is right, and it leaves one gap — the Command Bar and the Palette are mounted by
|
|
7
|
+
* `studio.ts` BEFORE the bootstrap composes the registry (`toolbar.mount` runs at the top of the
|
|
8
|
+
* file, `createCommandRegistry` near the bottom), so neither surface can be handed one at mount.
|
|
9
|
+
*
|
|
10
|
+
* This is the seam, in the same idiom as `platform.ts`'s `registerPlatform` / `getPlatform` and
|
|
11
|
+
* `canvas/preview-navigate.ts`'s handler slot: the bootstrap sets it once, and the surfaces ask.
|
|
12
|
+
*
|
|
13
|
+
* The holder is a `shallowRef`, which is the load-bearing part. A surface that reads
|
|
14
|
+
* {@link activeRegistry} inside its render effect TRACKS the holder, so the effect re-runs the
|
|
15
|
+
* moment the bootstrap sets it — which is what lets the Command Bar paint an honest empty band at
|
|
16
|
+
* mount and fill in without anyone remembering to call `render()` afterwards.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { shallowRef } from "../reactivity";
|
|
20
|
+
import type { CommandRegistry } from "./registry";
|
|
21
|
+
|
|
22
|
+
const _registry = shallowRef<CommandRegistry | null>(null);
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Publish this window's registry. Called once by the bootstrap, and by tests with their own.
|
|
26
|
+
*
|
|
27
|
+
* Passing `null` clears it, which is what an unmounting test does so the next one starts cold.
|
|
28
|
+
*/
|
|
29
|
+
export function setActiveRegistry(registry: CommandRegistry | null): void {
|
|
30
|
+
_registry.value = registry;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* This window's registry, or `null` before the bootstrap has composed it.
|
|
35
|
+
*
|
|
36
|
+
* Returning `null` rather than throwing is deliberate: the surfaces render a skeleton in that
|
|
37
|
+
* window, and a chrome that crashes because it painted one frame early would be a worse bug than
|
|
38
|
+
* the one this seam exists to solve.
|
|
39
|
+
*/
|
|
40
|
+
export function activeRegistry(): CommandRegistry | null {
|
|
41
|
+
return _registry.value;
|
|
42
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App-commands.ts — the whole app's command set, in one bare-Bun-importable place.
|
|
3
|
+
*
|
|
4
|
+
* `src/studio.ts` composes the registry a RUNNING window uses, by calling each module's
|
|
5
|
+
* `registerXCommands(registry, deps)` beside the state it writes. That is the right shape for the
|
|
6
|
+
* app and the wrong shape for CI: `scripts/check-command-levels.ts`,
|
|
7
|
+
* `scripts/check-chrome-budget.ts` and `scripts/check-shot-contract.ts` all run in a bare Bun
|
|
8
|
+
* process with no DOM and no bootstrap, and each looks for one export — `defaultCommandSet()`.
|
|
9
|
+
*
|
|
10
|
+
* Without this module those three checks see only `commands/defaults.ts`'s sixteen records, which
|
|
11
|
+
* is why plan §13.5's headline promise was not yet true: a manifest step naming `view.setActivity`
|
|
12
|
+
* with a panel id the registry does not declare sailed through Lane 1, because Lane 1 could not
|
|
13
|
+
* load the record that declares the enum. Every module gathered below imports cleanly with no
|
|
14
|
+
* `document` and no `localStorage` write, which is the ONLY property this file requires of them —
|
|
15
|
+
* and the test beside it asserts exactly that, so a future DOM read at module scope fails here
|
|
16
|
+
* rather than in CI.
|
|
17
|
+
*
|
|
18
|
+
* **Deps are the no-op set.** Nothing here runs a command; the checks read `id`, `level`, `menus`
|
|
19
|
+
* and `args`. Passing real implementations would mean importing the app.
|
|
20
|
+
*
|
|
21
|
+
* **The canvas keyboard is here now.** This note used to say `editor/shortcuts.ts`'s records were
|
|
22
|
+
* deliberately absent because `edit.copy` / `edit.cut` were declared in two places, and that they
|
|
23
|
+
* would join "when that reconciliation lands — one line each, and no script changes". The
|
|
24
|
+
* reconciliation had already landed (`shortcuts.ts`'s handoff table records it as PAID: the
|
|
25
|
+
* clipboard pair is defined once, in `editor/context-menu.ts`, and spread from there), so the
|
|
26
|
+
* deferral outlived its reason by two phases while ten records the app runs stayed invisible to
|
|
27
|
+
* every check and to the generated keyboard sheet. It was one line. `tests/
|
|
28
|
+
* app-commands-composition.test.ts` now asserts the projection from BOTH directions, because a
|
|
29
|
+
* record the app registers and the projection omits is exactly as invisible as the reverse, and
|
|
30
|
+
* only one of the two had a guard.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import { defaultCommands, noopCommandDeps } from "./defaults";
|
|
34
|
+
import { panelFocusRoster } from "../panels/navigator-panels";
|
|
35
|
+
import { createCommandRegistry } from "./registry";
|
|
36
|
+
import { emptyContext } from "./context";
|
|
37
|
+
import { DEFAULT_INSPECTOR_TAB, shellViewCommands } from "../shell";
|
|
38
|
+
import { canvasViewCommands } from "../canvas/canvas-utils";
|
|
39
|
+
import { selectionCommands } from "../canvas/canvas-render";
|
|
40
|
+
import { inspectorCommands } from "../panels/properties-panel";
|
|
41
|
+
import { dataExplorerCommands } from "../panels/data-explorer";
|
|
42
|
+
import { seoCommands } from "../panels/seo-modal";
|
|
43
|
+
import { a11yCommands } from "../services/a11y-report";
|
|
44
|
+
import { liveElementCommands } from "../editor/context-menu";
|
|
45
|
+
import { signalsCommands } from "../panels/signals-panel";
|
|
46
|
+
import { formulaEditorCommands } from "../panels/formula-workspace";
|
|
47
|
+
import { styleCommands } from "../panels/style-panel";
|
|
48
|
+
import { gridCommands } from "../grid/grid-open";
|
|
49
|
+
import { settingsCommands } from "../settings/settings-document";
|
|
50
|
+
import { collabCommands } from "../collab/collab-commands";
|
|
51
|
+
import { assistantCommands } from "../panels/ai-panel";
|
|
52
|
+
import { preferencesCommands } from "../settings/preferences-dialog";
|
|
53
|
+
import { aboutCommands } from "../about/about-modal";
|
|
54
|
+
import { libraryCommands } from "../browse/library-commands";
|
|
55
|
+
import { sourceControlCommands } from "../panels/git-panel";
|
|
56
|
+
import { publishCommands } from "../publish/publish-commands";
|
|
57
|
+
import { gridViewCommands } from "../grid/grid-panel";
|
|
58
|
+
import { redirectsCommands } from "../grid/redirects-grid";
|
|
59
|
+
import { contentCommands } from "../content/entry-commands";
|
|
60
|
+
import { i18nCommands } from "../i18n/i18n-commands";
|
|
61
|
+
import { newProjectCommands } from "../new-project/new-project-modal";
|
|
62
|
+
import { canvasCommands } from "../editor/shortcuts";
|
|
63
|
+
import { formatCommands, registerSelectionCommands } from "../panels/block-action-bar";
|
|
64
|
+
import { registerTabCommands } from "../workspace/workspace";
|
|
65
|
+
import { derivationCommands, noopDerivationDeps } from "../workspace/pane-derive";
|
|
66
|
+
import type { AnyCommand } from "./registry";
|
|
67
|
+
|
|
68
|
+
/** A verb set that does nothing — the checks read declarations, never behaviour. */
|
|
69
|
+
const NO_OP = () => {};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* A stage the zoom verbs can be DECLARED against. Reading it is a no-op; running one is not the
|
|
73
|
+
* point here — the checks read `id`, `level`, `menus` and `args`.
|
|
74
|
+
*
|
|
75
|
+
* Exported so its own test can call it. The zoom records only reach a stage when they RUN with a
|
|
76
|
+
* document open, which no check does, so the accessor would otherwise be a function nothing in the
|
|
77
|
+
* suite ever enters — and "nothing calls it" is the shape this repository treats as a defect
|
|
78
|
+
* everywhere else.
|
|
79
|
+
*/
|
|
80
|
+
export const noopStage = () => ({
|
|
81
|
+
applyTransform: NO_OP,
|
|
82
|
+
canvasMode: "design",
|
|
83
|
+
panX: 0,
|
|
84
|
+
panY: 0,
|
|
85
|
+
setPan: NO_OP,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Records that are only reachable through a `registerX(registry, deps)` entry point.
|
|
90
|
+
*
|
|
91
|
+
* Collected by registering them into a throwaway registry and reading it back, rather than by
|
|
92
|
+
* asking those modules to grow a second export. That also means these records go through
|
|
93
|
+
* `register()`'s own duplicate-id, chord-conflict and placement checks on the way in, so this
|
|
94
|
+
* function throws for the same reasons the app's bootstrap would.
|
|
95
|
+
*/
|
|
96
|
+
function viaRegistration(): AnyCommand[] {
|
|
97
|
+
const registry = createCommandRegistry({ getContext: emptyContext });
|
|
98
|
+
registerTabCommands(registry, { openFile: NO_OP, openFileInPane: NO_OP });
|
|
99
|
+
registerSelectionCommands(registry, { convertToComponent: NO_OP, navigateToComponent: NO_OP });
|
|
100
|
+
return [...registry.list()];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Every command the app's registry holds, in bootstrap order.
|
|
105
|
+
*
|
|
106
|
+
* Order matches `studio.ts` so a reader comparing the two files can do it line by line.
|
|
107
|
+
*/
|
|
108
|
+
export function appCommandSet(): AnyCommand[] {
|
|
109
|
+
return [
|
|
110
|
+
// The panel roster is the one dependency the checks must supply for real: the ⌘1–8 records are
|
|
111
|
+
// Generated from it, so an empty one would hide eight commands (and their chords) from the
|
|
112
|
+
// Level check, the chrome budget and the generated keyboard sheet alike.
|
|
113
|
+
...defaultCommands({ ...noopCommandDeps(), panelRoster: panelFocusRoster() }),
|
|
114
|
+
...viaRegistration(),
|
|
115
|
+
...derivationCommands(noopDerivationDeps()),
|
|
116
|
+
...shellViewCommands({ inspectorTab: () => DEFAULT_INSPECTOR_TAB, setInspectorTab: NO_OP }),
|
|
117
|
+
...canvasViewCommands({
|
|
118
|
+
getCanvasMode: () => "design",
|
|
119
|
+
renderPane: NO_OP,
|
|
120
|
+
setCanvasMode: NO_OP,
|
|
121
|
+
setResolvingOpen: NO_OP,
|
|
122
|
+
}),
|
|
123
|
+
...selectionCommands(),
|
|
124
|
+
...inspectorCommands(),
|
|
125
|
+
...seoCommands(),
|
|
126
|
+
...a11yCommands(),
|
|
127
|
+
// The element menu's eight verbs. Every one declares `menus: ["context/element", "palette"]`
|
|
128
|
+
// And none reached the palette, because they were registered ONLY into the private registry
|
|
129
|
+
// `editor/context-menu.ts` builds for its popover — a registry whose own docstring said it
|
|
130
|
+
// Existed "until a bootstrap composes every contribution point into a single app-wide
|
|
131
|
+
// Registry". This is that bootstrap; it has existed since P2.
|
|
132
|
+
...liveElementCommands(),
|
|
133
|
+
...dataExplorerCommands({ renderLeftPanel: NO_OP }),
|
|
134
|
+
...signalsCommands(),
|
|
135
|
+
...formulaEditorCommands(),
|
|
136
|
+
...gridCommands(),
|
|
137
|
+
...settingsCommands(),
|
|
138
|
+
...collabCommands(),
|
|
139
|
+
...assistantCommands(),
|
|
140
|
+
...preferencesCommands(),
|
|
141
|
+
...aboutCommands(),
|
|
142
|
+
...libraryCommands(),
|
|
143
|
+
...contentCommands(),
|
|
144
|
+
// The four translation verbs. `i18n.switchLocale` is deliberately not among them: it is a
|
|
145
|
+
// Rendering context, defined in `canvas/canvas-utils.ts` beside the per-tab UI state it writes.
|
|
146
|
+
...i18nCommands(),
|
|
147
|
+
...sourceControlCommands(),
|
|
148
|
+
...publishCommands(),
|
|
149
|
+
...gridViewCommands(),
|
|
150
|
+
...redirectsCommands(),
|
|
151
|
+
...newProjectCommands(),
|
|
152
|
+
...styleCommands(),
|
|
153
|
+
// Inline formatting — the eight `format.*` records. Registered in the bootstrap beside the bar
|
|
154
|
+
// That renders them, and projected here so the palette, the level check and the generated
|
|
155
|
+
// Keyboard sheet all see the first `caret`-scoped chords the app has ever had.
|
|
156
|
+
...formatCommands(),
|
|
157
|
+
/* The canvas keyboard's own nine, plus the clipboard pair they spread.
|
|
158
|
+
These were the last records the app registered and this projection did not contain, so ⌘C,
|
|
159
|
+
⌘X, ⌘V, Enter, the three structural arrows and all three zoom chords were absent from
|
|
160
|
+
`check-command-levels`, from the chrome budget and from the GENERATED keyboard sheet — a
|
|
161
|
+
reader of `docs/studio/interface/shortcuts.md` could not find Copy. The docstring above used
|
|
162
|
+
to defer this on the grounds that `edit.copy` was declared twice; it is not, and has not been
|
|
163
|
+
since the four literal duplicates were paid off (`shortcuts.ts`'s handoff table). It is one
|
|
164
|
+
line, exactly as that note promised. */
|
|
165
|
+
...canvasCommands(noopStage),
|
|
166
|
+
];
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* The name the three CI checks import by.
|
|
171
|
+
*
|
|
172
|
+
* Kept as an alias rather than renaming the scripts' contract: `commands/defaults.ts` exports the
|
|
173
|
+
* same symbol, so pointing a check at either module is a `--source` flag, and a check written
|
|
174
|
+
* before this file existed keeps working unchanged.
|
|
175
|
+
*/
|
|
176
|
+
export const defaultCommandSet = appCommandSet;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Budget.ts — chrome is earned by frequency and capped by a build check.
|
|
3
|
+
*
|
|
4
|
+
* Plan §2, principle 9: at most five commands may declare `menus: ["commandbar/primary"]`, and at
|
|
5
|
+
* most four tabs per dock. `scripts/check-chrome-budget.ts` fails CI otherwise, which is what turns
|
|
6
|
+
* "we should keep the toolbar small" from a code-review opinion into a build error.
|
|
7
|
+
*
|
|
8
|
+
* The cap is not arbitrary. The toolbar's own CSS already admits it is over budget — a container
|
|
9
|
+
* query at 1140px strips every `.tb-label` rather than conceding there are too many controls — and
|
|
10
|
+
* an unlabelled icon is a control the user has to hover to identify. A hard number is what makes
|
|
11
|
+
* "retire this control, keep its name and its chord" the cheap option.
|
|
12
|
+
*
|
|
13
|
+
* The dock/tab sets used to be a flat declaration — written out from §3.2 because `registerPanel()`
|
|
14
|
+
* did not exist. It does now, so the two `rail/*` rows are a QUERY over `railDeclarations()`
|
|
15
|
+
* ({@link dockTabs}) and adding a ninth rail panel fails this check without anyone remembering to
|
|
16
|
+
* update a list. The two rows that remain declared are the two docks whose tab sets this module
|
|
17
|
+
* cannot see from a bare Bun process: the Inspector's four come from `commands/defaults.ts`'s
|
|
18
|
+
* `INSPECTOR_TABS` (a query in all but name), and the Bottom dock's four are records in
|
|
19
|
+
* `panels/bottom-dock.ts`, which renders lit templates and therefore cannot be imported here.
|
|
20
|
+
* `tests/bottom-dock.test.ts` asserts the declared row and the registered set are the same four
|
|
21
|
+
* titles, so the copy cannot drift — the same bargain `tests/right-panel.test.ts` strikes for the
|
|
22
|
+
* Inspector. Both become real queries the day `scripts/check-chrome-budget.ts` joins them the way
|
|
23
|
+
* it already joins the rail.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { INSPECTOR_TABS } from "./defaults";
|
|
27
|
+
|
|
28
|
+
/** The caps. Raising either one is a design decision, so it happens here, in one place. */
|
|
29
|
+
export const CHROME_BUDGET = {
|
|
30
|
+
/** Commands allowed in the Command Bar's primary verb cluster. */
|
|
31
|
+
commandbarPrimary: 5,
|
|
32
|
+
/** Tabs allowed in any one dock (or rail group). */
|
|
33
|
+
dockTabs: 4,
|
|
34
|
+
/**
|
|
35
|
+
* Verbs allowed in the block action bar's inline-format cluster.
|
|
36
|
+
*
|
|
37
|
+
* Eight, which is the whole vocabulary `data/elements-meta.json` declares — bold, italic,
|
|
38
|
+
* underline, strikethrough, superscript, subscript, code, link. It is a cap and not a count: an
|
|
39
|
+
* element offers the SUBSET its `$inlineActions` names, so the bar never draws eight, and a ninth
|
|
40
|
+
* verb is a design decision that has to be made here rather than by appending to a data file.
|
|
41
|
+
*/
|
|
42
|
+
blockbarFormat: 8,
|
|
43
|
+
} as const;
|
|
44
|
+
|
|
45
|
+
/** One tabbed region and what it currently hosts. */
|
|
46
|
+
export interface DockDeclaration {
|
|
47
|
+
/** Region key as §3.2 names it. Rail groups count separately — they are separate placements. */
|
|
48
|
+
dock: string;
|
|
49
|
+
tabs: readonly string[];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The tabbed regions that are still WRITTEN DOWN rather than observed.
|
|
54
|
+
*
|
|
55
|
+
* The Inspector's row is a query in all but name — `INSPECTOR_TABS` is the list `right-panel.ts`
|
|
56
|
+
* renders and `⌘⇧1–4` address, so a fifth inspector tab fails this check in the commit that adds
|
|
57
|
+
* it. The Bottom dock's row is the same shape: the four ids live in `shell.ts`'s `BOTTOM_TAB_IDS`
|
|
58
|
+
* (so `view.setBottomTab`'s enum can be read in a bare Bun process) and the four RECORDS live in
|
|
59
|
+
* `panels/bottom-dock.ts`. It inherited this cap before it existed, which is why Deploy folded into
|
|
60
|
+
* Activity rather than becoming a fifth tab.
|
|
61
|
+
*
|
|
62
|
+
* The rail's two groups are NOT here. They come from `panels/panel-registry.ts`'s
|
|
63
|
+
* `railDeclarations()` and are joined on by {@link dockTabs} — the registry is the single source of
|
|
64
|
+
* what a panel is called and which group it sits in, and a duplicate list here was the last place
|
|
65
|
+
* those could disagree.
|
|
66
|
+
*/
|
|
67
|
+
export const DECLARED_DOCK_TABS: readonly DockDeclaration[] = [
|
|
68
|
+
{ dock: "inspector", tabs: INSPECTOR_TABS.map((tab) => tab.title) },
|
|
69
|
+
{ dock: "bottom", tabs: ["Problems", "Logic", "Activity"] },
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Every tabbed region: the declared ones plus the rail groups the panel registry observes.
|
|
74
|
+
*
|
|
75
|
+
* The rails arrive as an ARGUMENT rather than by import so this module keeps the property that lets
|
|
76
|
+
* three CI checks load it in a bare Bun process — `panel-registry.ts` reaches the DOM, the shell
|
|
77
|
+
* record and the workspace. `scripts/check-chrome-budget.ts` is the one place that joins them.
|
|
78
|
+
*
|
|
79
|
+
* @param rails `railDeclarations()`, or `[]` where no registry has been populated.
|
|
80
|
+
*/
|
|
81
|
+
export function dockTabs(rails: readonly DockDeclaration[] = []): DockDeclaration[] {
|
|
82
|
+
return [...DECLARED_DOCK_TABS, ...rails];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** The subset of a command record the budget check reads. */
|
|
86
|
+
export interface BudgetableRecord {
|
|
87
|
+
id: string;
|
|
88
|
+
menus?: readonly string[] | undefined;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** One exceeded cap. */
|
|
92
|
+
export interface BudgetViolation {
|
|
93
|
+
/** What was counted: a placement key, or a dock key. */
|
|
94
|
+
subject: string;
|
|
95
|
+
count: number;
|
|
96
|
+
limit: number;
|
|
97
|
+
message: string;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Commands declaring the primary Command Bar cluster. */
|
|
101
|
+
export function primaryCommandIds(commands: readonly BudgetableRecord[]): string[] {
|
|
102
|
+
return commands
|
|
103
|
+
.filter((command) => (command.menus ?? []).includes("commandbar/primary"))
|
|
104
|
+
.map((command) => command.id);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Check both caps.
|
|
109
|
+
*
|
|
110
|
+
* @param input.commands Every registered command record.
|
|
111
|
+
* @param input.docks The shell's tabbed regions. Defaults to {@link dockTabs} with no rails.
|
|
112
|
+
*/
|
|
113
|
+
export function checkChromeBudget(input: {
|
|
114
|
+
commands: readonly BudgetableRecord[];
|
|
115
|
+
docks?: readonly DockDeclaration[];
|
|
116
|
+
}): BudgetViolation[] {
|
|
117
|
+
const violations: BudgetViolation[] = [];
|
|
118
|
+
const primary = primaryCommandIds(input.commands);
|
|
119
|
+
if (primary.length > CHROME_BUDGET.commandbarPrimary) {
|
|
120
|
+
violations.push({
|
|
121
|
+
subject: "commandbar/primary",
|
|
122
|
+
count: primary.length,
|
|
123
|
+
limit: CHROME_BUDGET.commandbarPrimary,
|
|
124
|
+
message:
|
|
125
|
+
`${primary.length} commands declare menus:["commandbar/primary"], the cap is ` +
|
|
126
|
+
`${CHROME_BUDGET.commandbarPrimary} — ${primary.join(", ")}. Retire one to ` +
|
|
127
|
+
`"commandbar/overflow": it keeps its name, its chord and its palette row.`,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
const formatting = input.commands
|
|
131
|
+
.filter((command) => (command.menus ?? []).includes("blockbar/format"))
|
|
132
|
+
.map((command) => command.id);
|
|
133
|
+
if (formatting.length > CHROME_BUDGET.blockbarFormat) {
|
|
134
|
+
violations.push({
|
|
135
|
+
subject: "blockbar/format",
|
|
136
|
+
count: formatting.length,
|
|
137
|
+
limit: CHROME_BUDGET.blockbarFormat,
|
|
138
|
+
message:
|
|
139
|
+
`${formatting.length} commands declare menus:["blockbar/format"], the cap is ` +
|
|
140
|
+
`${CHROME_BUDGET.blockbarFormat} — ${formatting.join(", ")}. The cluster sits over a text ` +
|
|
141
|
+
`range in a floating bar; a ninth verb belongs in the palette.`,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
for (const dock of input.docks ?? dockTabs()) {
|
|
145
|
+
if (dock.tabs.length > CHROME_BUDGET.dockTabs) {
|
|
146
|
+
violations.push({
|
|
147
|
+
subject: dock.dock,
|
|
148
|
+
count: dock.tabs.length,
|
|
149
|
+
limit: CHROME_BUDGET.dockTabs,
|
|
150
|
+
message:
|
|
151
|
+
`dock "${dock.dock}" declares ${dock.tabs.length} tabs, the cap is ` +
|
|
152
|
+
`${CHROME_BUDGET.dockTabs} — ${dock.tabs.join(", ")}. Fold two together or move one ` +
|
|
153
|
+
`to another dock.`,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return violations;
|
|
158
|
+
}
|