@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
|
@@ -9,6 +9,13 @@
|
|
|
9
9
|
* editor's `border-left` nesting idiom) with their own add-statement pickers. Cards drag-reorder
|
|
10
10
|
* within their lane via the pragmatic-drag-and-drop tree-item pattern (see panels/dnd.ts). All
|
|
11
11
|
* edits flow through `onChange(next)` immutably — no statement object is mutated in place.
|
|
12
|
+
*
|
|
13
|
+
* **The layout is CSS, in `styles/inspector.css` (§ "The statement editor").** Every frame, indent
|
|
14
|
+
* and connector here used to be an inline `style=` attribute, so nothing in the chain could set
|
|
15
|
+
* `min-width: 0` and the operand controls refused to shrink: in a 280px Inspector an If/Else card
|
|
16
|
+
* pushed Operator, Target and Value past the right edge of the window. This editor has two hosts of
|
|
17
|
+
* very different widths — the Navigator's State panel and the Inspector's Events tab — plus the
|
|
18
|
+
* Bottom dock, so a fixed pixel layout is wrong by construction and only a stylesheet can say so.
|
|
12
19
|
*/
|
|
13
20
|
|
|
14
21
|
import { html, nothing } from "lit-html";
|
|
@@ -42,6 +49,24 @@ export interface StatementEditorOpts {
|
|
|
42
49
|
allowEventRef: boolean;
|
|
43
50
|
/** The entry's declared CEM events — offered as dispatchEvent name completions. */
|
|
44
51
|
emits?: CemEvent[];
|
|
52
|
+
/**
|
|
53
|
+
* The region id of THIS editor, supplied by the surface that is drawing it.
|
|
54
|
+
*
|
|
55
|
+
* Required, and required of every host, which is the point. The editor used to hard-stamp
|
|
56
|
+
* `navigator/statements` on itself, and it has two hosts that can be open at the same time — the
|
|
57
|
+
* Navigator's State panel (`signals-panel.ts`) and the INSPECTOR's Events tab
|
|
58
|
+
* (`events-panel.ts`). `resolveRegion` takes the last match in document order and `#right-panel`
|
|
59
|
+
* follows `#left-panel`, so the id resolved to the Inspector's editor while saying Navigator, and
|
|
60
|
+
* the shot that crops it cropped the wrong control.
|
|
61
|
+
*
|
|
62
|
+
* A shared control cannot know where it is, so it may not claim to. This is the same verdict
|
|
63
|
+
* `ui/regions.ts`'s `DERIVED_RESOLVERS` records for the media picker's Browse button — _an
|
|
64
|
+
* `inspector/…` id on an element outside the Inspector is not a pane-scoping problem, it is a
|
|
65
|
+
* wrong id_ — reached the other way round: the picker's id is derived from the Inspector because
|
|
66
|
+
* nothing addresses the card's copies, whereas both statement editors are real surfaces that
|
|
67
|
+
* deserve names, so the HOST names them.
|
|
68
|
+
*/
|
|
69
|
+
region: string;
|
|
45
70
|
}
|
|
46
71
|
|
|
47
72
|
/**
|
|
@@ -120,7 +145,13 @@ export function laneListAt(list: JxStatement[], path: LanePath): JxStatement[] |
|
|
|
120
145
|
return list;
|
|
121
146
|
}
|
|
122
147
|
const [idx, key] = path;
|
|
123
|
-
|
|
148
|
+
/*
|
|
149
|
+
* `unknown`, not a cast to `Record<string, unknown>`. A `JxStatement` is a union of interfaces
|
|
150
|
+
* with no index signature, so asserting one into an open bag is a lie TypeScript rightly refuses
|
|
151
|
+
* — and it was buying nothing, because `isJsonObject` takes `unknown` and narrows to exactly the
|
|
152
|
+
* open bag this wants. The guard on the next line is the real check either way.
|
|
153
|
+
*/
|
|
154
|
+
const stmt: unknown = typeof idx === "number" ? list[idx] : null;
|
|
124
155
|
if (!isJsonObject(stmt) || typeof key !== "string") {
|
|
125
156
|
return null;
|
|
126
157
|
}
|
|
@@ -292,9 +323,6 @@ function registerStatementsDnD(
|
|
|
292
323
|
|
|
293
324
|
// ─── Small shared widgets ────────────────────────────────────────────────────
|
|
294
325
|
|
|
295
|
-
const laneLabelStyle =
|
|
296
|
-
"font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:0.04em;color:var(--spectrum-gray-600, #808080)";
|
|
297
|
-
|
|
298
326
|
function operandOpts(opts: StatementEditorOpts) {
|
|
299
327
|
return {
|
|
300
328
|
allowEventRef: opts.allowEventRef,
|
|
@@ -346,9 +374,9 @@ function renderLane(
|
|
|
346
374
|
extras: { onRemove?: () => void } = {},
|
|
347
375
|
): TemplateResult {
|
|
348
376
|
return html`
|
|
349
|
-
<div class="statement-lane"
|
|
350
|
-
<div class="statement-lane-header"
|
|
351
|
-
<span
|
|
377
|
+
<div class="statement-lane">
|
|
378
|
+
<div class="statement-lane-header">
|
|
379
|
+
<span class="statement-lane-label">${label}</span>
|
|
352
380
|
${
|
|
353
381
|
extras.onRemove
|
|
354
382
|
? html`
|
|
@@ -453,7 +481,6 @@ function renderSwitchBody(
|
|
|
453
481
|
<sp-textfield
|
|
454
482
|
size="s"
|
|
455
483
|
class="statement-case-key"
|
|
456
|
-
style="width:96px"
|
|
457
484
|
placeholder="value"
|
|
458
485
|
.value=${live(key)}
|
|
459
486
|
@change=${(e: Event) => {
|
|
@@ -543,7 +570,6 @@ function renderDispatchBody(
|
|
|
543
570
|
size="s"
|
|
544
571
|
allows-custom-value
|
|
545
572
|
class="statement-dispatch-name"
|
|
546
|
-
style="flex:1"
|
|
547
573
|
.value=${live(stmt.dispatchEvent ?? "")}
|
|
548
574
|
@change=${commitName}
|
|
549
575
|
>
|
|
@@ -554,7 +580,6 @@ function renderDispatchBody(
|
|
|
554
580
|
<sp-textfield
|
|
555
581
|
size="s"
|
|
556
582
|
class="statement-dispatch-name"
|
|
557
|
-
style="flex:1"
|
|
558
583
|
placeholder="event-name"
|
|
559
584
|
.value=${live(stmt.dispatchEvent ?? "")}
|
|
560
585
|
@input=${commitName}
|
|
@@ -576,7 +601,7 @@ function renderDispatchBody(
|
|
|
576
601
|
label: "Options",
|
|
577
602
|
prop: "eventInit",
|
|
578
603
|
widget: html`
|
|
579
|
-
<div
|
|
604
|
+
<div class="statement-dispatch-options">
|
|
580
605
|
<sp-checkbox
|
|
581
606
|
size="s"
|
|
582
607
|
class="statement-dispatch-bubbles"
|
|
@@ -641,17 +666,10 @@ function renderStatementCard(
|
|
|
641
666
|
data-stmt-kind=${kind}
|
|
642
667
|
data-stmt-lane=${JSON.stringify(lanePath)}
|
|
643
668
|
data-stmt-index=${index}
|
|
644
|
-
style="border:1px solid var(--spectrum-gray-300, #3c3c3c);border-radius:4px;padding:4px 6px;margin:0 0 6px;background:var(--spectrum-gray-75, #1e1e1e)"
|
|
645
669
|
>
|
|
646
|
-
<div class="statement-card-header"
|
|
647
|
-
<span
|
|
648
|
-
|
|
649
|
-
title="Drag to reorder"
|
|
650
|
-
style="cursor:grab;color:var(--spectrum-gray-500, #6e6e6e);font-size:11px;line-height:1;user-select:none"
|
|
651
|
-
>⠿</span
|
|
652
|
-
>
|
|
653
|
-
<span class="statement-kind-label" style=${laneLabelStyle}>${kindLabel(stmt)}</span>
|
|
654
|
-
<span style="flex:1"></span>
|
|
670
|
+
<div class="statement-card-header">
|
|
671
|
+
<span class="statement-drag-handle" title="Drag to reorder">⠿</span>
|
|
672
|
+
<span class="statement-kind-label">${kindLabel(stmt)}</span>
|
|
655
673
|
<sp-action-button
|
|
656
674
|
quiet
|
|
657
675
|
size="xs"
|
|
@@ -675,10 +693,7 @@ function renderStatementList(
|
|
|
675
693
|
lanePath: LanePath,
|
|
676
694
|
): TemplateResult {
|
|
677
695
|
return html`
|
|
678
|
-
<div
|
|
679
|
-
class="statement-list"
|
|
680
|
-
style="margin-left:4px;border-left:2px solid var(--spectrum-gray-300, #3c3c3c);padding:2px 0 0 8px"
|
|
681
|
-
>
|
|
696
|
+
<div class="statement-list">
|
|
682
697
|
${list.map((stmt, index) =>
|
|
683
698
|
renderStatementCard(stmt, index, list, commitList, opts, lanePath),
|
|
684
699
|
)}
|
|
@@ -702,6 +717,7 @@ export function renderStatementEditor(
|
|
|
702
717
|
return html`
|
|
703
718
|
<div
|
|
704
719
|
class="statement-editor"
|
|
720
|
+
data-jx-region=${opts.region}
|
|
705
721
|
${ref((el) => {
|
|
706
722
|
if (el) {
|
|
707
723
|
registerStatementsDnD(el as HTMLElement, safe, onChange);
|
package/src/panels/statusbar.ts
CHANGED
|
@@ -1,140 +1,376 @@
|
|
|
1
1
|
/// <reference lib="dom" />
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* ⑫ The status bar — ambient state, in scope order, and nothing else.
|
|
4
|
+
*
|
|
5
|
+
* What this replaces: a bar built by `innerHTML` string concatenation with a three-character
|
|
6
|
+
* escaper, carrying whatever the last of 78 `statusMessage()` calls had said, for three seconds.
|
|
7
|
+
* Transient messages have left entirely for the toast host (`ui/layers.ts`) and the Problems list
|
|
8
|
+
* (`services/notify.ts`); what remains here is state that is TRUE for as long as it is shown.
|
|
9
|
+
*
|
|
10
|
+
* **Three fixed fields, in the shell's own left-to-right level order** (plan §3.2 ⑫), so the bar
|
|
11
|
+
* restates the containment model on every glance:
|
|
12
|
+
*
|
|
13
|
+
* ```text
|
|
14
|
+
* PROJECT ‖ DOCUMENT ‖ SELECTION
|
|
15
|
+
* name · branch ↑n↓n · problems ‖ path · view · save state ‖ count · style rule
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* The SELECTION field held an ancestor breadcrumb until region ⑥ landed. The trail is an ADDRESS,
|
|
19
|
+
* not ambient state, and it now lives once — in the jump bar (`panels/jump-bar.ts`), which merged
|
|
20
|
+
* it with the pane context bar's document-stack chain. What is left here is the count and the
|
|
21
|
+
* Stylebook's rule, neither of which is a path.
|
|
22
|
+
*
|
|
23
|
+
* `statusbar/project`, `statusbar/document` and `statusbar/selection` are three placements the
|
|
24
|
+
* level × placement matrix already declares, each admitting exactly one level — so the bar's
|
|
25
|
+
* mixedness is structural rather than an exemption.
|
|
26
|
+
*
|
|
27
|
+
* **The effective view, not a mode string.** The bar used to print "Content Mode" from
|
|
28
|
+
* `tab.doc.mode` while the Command Bar printed "Design" from `canvasMode` — two surfaces reading
|
|
29
|
+
* two fields to answer one question. Both now read `registry.context()`, which is the same record
|
|
30
|
+
* every `when` predicate reads, so they cannot disagree again.
|
|
31
|
+
*
|
|
32
|
+
* **Every interactive item is a command.** There are no click handlers in this file: an item names
|
|
33
|
+
* a command id, and renders as a button only when the registry has that command and its `when`
|
|
34
|
+
* holds. That is what lets an item that has no command yet — the peers count, whose `Collaborate:`
|
|
35
|
+
* family lands with P4.8 — sit in the template today and start rendering the day it is registered,
|
|
36
|
+
* with no edit here. The three readouts that are NOT buttons are marked: the view name (its control
|
|
37
|
+
* is the pane context bar ⑦; a second mode picker in 24px would be the chrome duplication §2
|
|
38
|
+
* principle 9 exists to prevent), the save wording once a document IS saved, and the stylebook
|
|
39
|
+
* selector.
|
|
40
|
+
*/
|
|
3
41
|
|
|
4
|
-
import {
|
|
42
|
+
import { html, render as litRender, nothing } from "lit-html";
|
|
43
|
+
import { projectState, statusbarEl } from "../store";
|
|
44
|
+
import { documentLabel } from "./jump-bar";
|
|
45
|
+
import { shell } from "../shell";
|
|
5
46
|
import { effect, effectScope } from "../reactivity";
|
|
6
47
|
import { activeTab } from "../workspace/workspace";
|
|
7
|
-
import
|
|
48
|
+
import { EDITOR_KIND_LABELS } from "../commands/context";
|
|
49
|
+
import { activeRegistry } from "../commands/active-registry";
|
|
50
|
+
import { deployStatusItem } from "../publish/deploy-checklist";
|
|
51
|
+
import { collabState } from "../collab/collab-state";
|
|
52
|
+
import { problemCount, problems } from "../services/notify";
|
|
53
|
+
import { now } from "../services/clock";
|
|
54
|
+
import { relativeTime } from "./ai-chat/sessions-view";
|
|
55
|
+
import type { CommandRegistry } from "../commands/registry";
|
|
56
|
+
import type { EditorKind } from "../commands/context";
|
|
8
57
|
import type { EffectScope } from "@vue/reactivity";
|
|
58
|
+
import type { TemplateResult } from "lit-html";
|
|
9
59
|
|
|
10
|
-
// ─── Module state ────────────────────────────────────────────────────────────
|
|
11
|
-
|
|
12
|
-
let statusMsg = "";
|
|
13
|
-
/** @type {ReturnType<typeof setTimeout> | undefined} */
|
|
14
|
-
let statusTimeout: ReturnType<typeof setTimeout> | undefined;
|
|
15
|
-
let _rerender: (() => void) | null = null;
|
|
16
60
|
let _scope: EffectScope | null = null;
|
|
17
61
|
|
|
18
62
|
/**
|
|
19
|
-
*
|
|
63
|
+
* Document path → when it was last written, from the {@link now} seam.
|
|
20
64
|
*
|
|
21
|
-
*
|
|
65
|
+
* Kept here rather than on the `Tab` record for one reason: a save time is something the STATUS BAR
|
|
66
|
+
* observes, not something a document is. `files/file-ops.ts` reports it after a successful write —
|
|
67
|
+
* the same place the old `statusMessage("Saved …")` was raised from, so the fact has not moved, it
|
|
68
|
+
* has only stopped being a message that erases itself.
|
|
22
69
|
*/
|
|
23
|
-
|
|
24
|
-
|
|
70
|
+
const _savedAt = new Map<string, number>();
|
|
71
|
+
|
|
72
|
+
/** Record a successful write. Called by the save path; keyed by document path. */
|
|
73
|
+
export function noteDocumentSaved(path: string | null | undefined): void {
|
|
74
|
+
if (path) {
|
|
75
|
+
_savedAt.set(path, now());
|
|
76
|
+
}
|
|
25
77
|
}
|
|
26
78
|
|
|
27
|
-
/**
|
|
28
|
-
export function
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
effect(() => {
|
|
32
|
-
const tab = activeTab.value;
|
|
33
|
-
if (!tab) {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
// Track relevant reactive properties
|
|
37
|
-
void tab.doc.document;
|
|
38
|
-
void tab.doc.mode;
|
|
39
|
-
void tab.session.selection;
|
|
40
|
-
void tab.session.ui.stylebookSelection;
|
|
41
|
-
renderStatusbar();
|
|
42
|
-
});
|
|
43
|
-
});
|
|
79
|
+
/** Forget every recorded save. Project close and the tests both want a clean slate. */
|
|
80
|
+
export function forgetSavedTimes(): void {
|
|
81
|
+
_savedAt.clear();
|
|
82
|
+
}
|
|
44
83
|
|
|
45
|
-
|
|
84
|
+
// ─── Items ───────────────────────────────────────────────────────────────────
|
|
85
|
+
|
|
86
|
+
/** One thing the bar can show. A `command` makes it a button; without one it is a readout. */
|
|
87
|
+
interface StatusItem {
|
|
88
|
+
/** Command id, or `null` for a pure readout. */
|
|
89
|
+
command: string | null;
|
|
90
|
+
label: string;
|
|
91
|
+
/** Extra context for the tooltip. The command's own title and chord are added to it. */
|
|
92
|
+
title?: string;
|
|
93
|
+
args?: Record<string, unknown>;
|
|
46
94
|
}
|
|
47
95
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
96
|
+
/**
|
|
97
|
+
* Render one item.
|
|
98
|
+
*
|
|
99
|
+
* A named command that the registry does not have, or whose `when` is false, renders NOTHING — the
|
|
100
|
+
* item disappears rather than becoming a dead label. That is the whole mechanism by which the bar
|
|
101
|
+
* stays a rendering of the registry instead of a second place capabilities are decided.
|
|
102
|
+
*/
|
|
103
|
+
function itemTpl(registry: CommandRegistry | null, item: StatusItem) {
|
|
104
|
+
if (item.command === null) {
|
|
105
|
+
return html`<span class="sb-item sb-state" title=${item.title ?? item.label}
|
|
106
|
+
>${item.label}</span
|
|
107
|
+
>`;
|
|
108
|
+
}
|
|
109
|
+
const id = item.command;
|
|
110
|
+
if (!registry?.get(id) || !registry.isVisible(id)) {
|
|
111
|
+
return nothing;
|
|
112
|
+
}
|
|
113
|
+
const command = registry.get(id)!;
|
|
114
|
+
const reason = registry.disabledReason(id);
|
|
115
|
+
const chord = registry.keymap.formatBinding(id);
|
|
116
|
+
const suffix = reason
|
|
117
|
+
? `${command.title} — requires ${reason}`
|
|
118
|
+
: chord
|
|
119
|
+
? `${command.title} (${chord})`
|
|
120
|
+
: command.title;
|
|
121
|
+
return html`<button
|
|
122
|
+
class="sb-item"
|
|
123
|
+
?disabled=${reason !== undefined}
|
|
124
|
+
title=${item.title ? `${item.title} · ${suffix}` : suffix}
|
|
125
|
+
@click=${() => {
|
|
126
|
+
void registry.run(id, item.args);
|
|
127
|
+
}}
|
|
128
|
+
>
|
|
129
|
+
${item.label}
|
|
130
|
+
</button>`;
|
|
52
131
|
}
|
|
53
132
|
|
|
54
|
-
|
|
133
|
+
/** What {@link itemTpl} returns: a rendered item, or the absence of one. */
|
|
134
|
+
type ItemResult = TemplateResult | typeof nothing;
|
|
55
135
|
|
|
56
|
-
/**
|
|
57
|
-
function
|
|
58
|
-
|
|
136
|
+
/** A field, with its region stamp. Renders nothing at all when it has no items. */
|
|
137
|
+
function fieldTpl(region: string, items: readonly ItemResult[]) {
|
|
138
|
+
const live = items.filter((item): item is TemplateResult => item !== nothing);
|
|
139
|
+
if (live.length === 0) {
|
|
140
|
+
return nothing;
|
|
141
|
+
}
|
|
142
|
+
return html`<div class="sb-field" data-jx-region=${region}>${live}</div>`;
|
|
59
143
|
}
|
|
60
144
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
145
|
+
// ─── ⑫a PROJECT ──────────────────────────────────────────────────────────────
|
|
146
|
+
|
|
147
|
+
/** `↑2↓1`, or "" when the branch is level with its upstream. */
|
|
148
|
+
export function aheadBehindLabel(ahead: number, behind: number): string {
|
|
149
|
+
return `${ahead > 0 ? ` ↑${ahead}` : ""}${behind > 0 ? ` ↓${behind}` : ""}`;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function projectFieldTpl(registry: CommandRegistry | null) {
|
|
153
|
+
const project = projectState;
|
|
154
|
+
const { status } = shell.git;
|
|
155
|
+
const count = problemCount();
|
|
156
|
+
const deploy = deployStatusItem();
|
|
157
|
+
const peers = activeTab.value ? collabState(activeTab.value).peers.length : 0;
|
|
158
|
+
return fieldTpl("statusbar/project", [
|
|
159
|
+
project
|
|
160
|
+
? itemTpl(registry, { command: "project.openRecent", label: project.name })
|
|
161
|
+
: itemTpl(registry, { command: "project.open", label: "No project" }),
|
|
162
|
+
/* WHICH branch, when there is one — and deliberately no "not tracked" twin, though plan §12 P1
|
|
163
|
+
workstream 9's "repo state becomes a persistent status-bar field" reads like a request for
|
|
164
|
+
one. An untracked project already states itself in this field, one item along:
|
|
165
|
+
`deployStatusItem()`'s first link is `repo`, whose label is "Track this project with git" and
|
|
166
|
+
whose command is `git.init`. A second item beside it would carry no fact the first does not
|
|
167
|
+
— "Not tracked" and "Track this project with git" answer the same question with the same verb
|
|
168
|
+
— and adjacent duplicate chrome is what §2 principle 9 forbids. `tests/statusbar.test.ts`
|
|
169
|
+
pins the pairing from both ends, so deleting the checklist's repo step fails there rather
|
|
170
|
+
than quietly taking the state off the bar. */
|
|
171
|
+
status?.isRepo === true && status.branch
|
|
172
|
+
? itemTpl(registry, {
|
|
173
|
+
command: "panel.focus.git",
|
|
174
|
+
label: `⑂ ${status.branch}${aheadBehindLabel(status.ahead, status.behind)}`,
|
|
175
|
+
title: `${status.files.length} changed file(s)`,
|
|
176
|
+
})
|
|
177
|
+
: nothing,
|
|
178
|
+
// Where the project stands with shipping — ambient state, so it belongs beside the branch and
|
|
179
|
+
// The problem count rather than in a toast. `deployStatusItem` names the NEXT missing step
|
|
180
|
+
// While anything is missing, and the deployment itself once nothing is.
|
|
181
|
+
deploy
|
|
182
|
+
? itemTpl(registry, {
|
|
183
|
+
command: deploy.command,
|
|
184
|
+
label: deploy.label,
|
|
185
|
+
title: deploy.title,
|
|
186
|
+
})
|
|
187
|
+
: nothing,
|
|
188
|
+
// `view.setBottomTab`, not `panel.focus.problems`: the latter is generated from the rail
|
|
189
|
+
// Roster, and Problems left the rail. That is the same verb Diff, Logic and Activity are
|
|
190
|
+
// Addressed by — one door per bottom tab — and it is what keeps this readout the ONLY standing
|
|
191
|
+
// Mention of problems in the chrome, which is the point of taking the rail button away.
|
|
192
|
+
count > 0
|
|
193
|
+
? itemTpl(registry, {
|
|
194
|
+
args: { tab: "problems" },
|
|
195
|
+
command: "view.setBottomTab",
|
|
196
|
+
label: `⚠ ${count}`,
|
|
197
|
+
title: `${count} problem(s)`,
|
|
198
|
+
})
|
|
199
|
+
: nothing,
|
|
200
|
+
/* `collab.showStatus` — "what is happening in this document?" — because that is the question a
|
|
201
|
+
peer count raises.
|
|
202
|
+
|
|
203
|
+
This said `collab.share` and carried a comment promising the item would "appear the day the
|
|
204
|
+
`Collaborate:` family lands, with no edit to this file". The family landed, under five ids,
|
|
205
|
+
and `share` was renamed `collab.setEnabled` on the way (the set*-not-toggle* rule). `itemTpl`
|
|
206
|
+
renders `nothing` for an id the registry does not have, so the readout was permanently blank
|
|
207
|
+
and the comment said it was fine. An id is not a stable interface between two files unless
|
|
208
|
+
something checks it, which is what `tests/statusbar.test.ts` now does. */
|
|
209
|
+
peers > 0
|
|
210
|
+
? itemTpl(registry, {
|
|
211
|
+
command: "collab.showStatus",
|
|
212
|
+
label: `${peers} peer${peers === 1 ? "" : "s"}`,
|
|
213
|
+
title: `${peers} peer${peers === 1 ? "" : "s"} in this document`,
|
|
214
|
+
})
|
|
215
|
+
: nothing,
|
|
216
|
+
]);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// ─── ⑫b DOCUMENT ─────────────────────────────────────────────────────────────
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* What the pane is showing, in the words the pane context bar uses.
|
|
223
|
+
*
|
|
224
|
+
* Derived from the command context — `editor.kind` and `canvas.view` — so it is the SAME two facts
|
|
225
|
+
* the Command Bar, the keyboard scope stack and every `when` predicate read.
|
|
226
|
+
*/
|
|
227
|
+
export function viewLabel(kind: EditorKind, view: string): string {
|
|
228
|
+
if (kind === "none") {
|
|
229
|
+
return "";
|
|
100
230
|
}
|
|
101
|
-
if (
|
|
102
|
-
|
|
231
|
+
if (kind !== "canvas") {
|
|
232
|
+
return EDITOR_KIND_LABELS[kind];
|
|
103
233
|
}
|
|
104
|
-
|
|
234
|
+
return view.charAt(0).toUpperCase() + view.slice(1);
|
|
105
235
|
}
|
|
106
236
|
|
|
107
|
-
/**
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
237
|
+
/**
|
|
238
|
+
* The save state, in words.
|
|
239
|
+
*
|
|
240
|
+
* A dot glyph said one bit and required a legend nobody has. These four sentences say which of the
|
|
241
|
+
* four states the document is in, and the one that needs an action IS the action: "Unsaved changes"
|
|
242
|
+
* renders as the `file.save` button.
|
|
243
|
+
*/
|
|
244
|
+
function saveItem(dirty: boolean, readOnly: boolean, savedAt: number | undefined): StatusItem {
|
|
245
|
+
if (readOnly) {
|
|
246
|
+
return { command: null, label: "Read-only", title: "A collaborator owns this session's file" };
|
|
112
247
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
return;
|
|
248
|
+
if (dirty) {
|
|
249
|
+
return { command: "file.save", label: "Unsaved changes" };
|
|
116
250
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
251
|
+
return savedAt === undefined
|
|
252
|
+
? { command: null, label: "Saved" }
|
|
253
|
+
: { command: null, label: `Saved ${relativeTime(savedAt)}` };
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function documentFieldTpl(registry: CommandRegistry | null) {
|
|
257
|
+
const tab = activeTab.value;
|
|
258
|
+
if (!tab) {
|
|
259
|
+
return nothing;
|
|
123
260
|
}
|
|
261
|
+
const ctx = registry?.context() ?? null;
|
|
262
|
+
const view = ctx ? viewLabel(ctx.editor.kind, ctx.canvas.view) : "";
|
|
263
|
+
const collab = collabState(tab);
|
|
264
|
+
const savedAt = tab.documentPath === null ? undefined : _savedAt.get(tab.documentPath);
|
|
265
|
+
return fieldTpl("statusbar/document", [
|
|
266
|
+
itemTpl(registry, {
|
|
267
|
+
command: "palette.openFiles",
|
|
268
|
+
label: documentLabel(tab.documentPath),
|
|
269
|
+
title: tab.documentPath ?? "Not saved to disk yet",
|
|
270
|
+
}),
|
|
271
|
+
view
|
|
272
|
+
? itemTpl(registry, {
|
|
273
|
+
command: null,
|
|
274
|
+
label: view,
|
|
275
|
+
title: "The pane's view — change it on the pane context bar",
|
|
276
|
+
})
|
|
277
|
+
: nothing,
|
|
278
|
+
itemTpl(registry, saveItem(tab.doc.dirty, collab.readOnly, savedAt)),
|
|
279
|
+
]);
|
|
124
280
|
}
|
|
125
281
|
|
|
282
|
+
// ─── ⑫c SELECTION ────────────────────────────────────────────────────────────
|
|
283
|
+
|
|
126
284
|
/**
|
|
127
|
-
*
|
|
285
|
+
* What is selected — the COUNT, and nothing that is an address.
|
|
286
|
+
*
|
|
287
|
+
* This field used to carry a clickable ancestor trail, one `selection.set` per crumb. That trail
|
|
288
|
+
* has moved whole to the jump bar (⑥, `panels/jump-bar.ts`), which is region ⑥'s entire reason to
|
|
289
|
+
* exist: Studio had two half-breadcrumbs — that one, and the pane context bar's document-stack
|
|
290
|
+
* chain — and neither ever rendered the whole address. Leaving a copy here would have made three.
|
|
128
291
|
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
292
|
+
* What is left is what the jump bar CANNOT say, and both are ambient state in the §16.2 sense: how
|
|
293
|
+
* many things are selected (a count is not a path, and the jump bar names only the primary), and
|
|
294
|
+
* which style rule the Stylebook is editing (a CSS selector is not a node in this document).
|
|
295
|
+
*
|
|
296
|
+
* A single selection therefore leaves this field empty. That is deliberate — the jump bar's leaf
|
|
297
|
+
* segment states it permanently, with its ancestors, and a second copy at 11px says nothing new.
|
|
131
298
|
*/
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
299
|
+
function selectionFieldTpl(registry: CommandRegistry | null) {
|
|
300
|
+
const paths = activeTab.value?.session.selection ?? [];
|
|
301
|
+
if (paths.length > 0) {
|
|
302
|
+
// A document selection owns the field even when it prints nothing: the Stylebook's selector
|
|
303
|
+
// Below would otherwise appear while an element is picked, which is two answers to one question.
|
|
304
|
+
return paths.length > 1
|
|
305
|
+
? fieldTpl("statusbar/selection", [
|
|
306
|
+
itemTpl(registry, {
|
|
307
|
+
command: null,
|
|
308
|
+
label: `${paths.length} selected`,
|
|
309
|
+
title: `${paths.length} elements are selected; the jump bar names the primary`,
|
|
310
|
+
}),
|
|
311
|
+
])
|
|
312
|
+
: nothing;
|
|
313
|
+
}
|
|
314
|
+
// The stylebook's own selection is a selection: it is what the Style panel is editing, and it is
|
|
315
|
+
// The only thing in this field when no document node is picked.
|
|
316
|
+
return shell.stylebook.selection
|
|
317
|
+
? fieldTpl("statusbar/selection", [
|
|
318
|
+
itemTpl(registry, {
|
|
319
|
+
command: null,
|
|
320
|
+
label: shell.stylebook.selection.replaceAll(" ", " › "),
|
|
321
|
+
title: "The style rule being edited",
|
|
322
|
+
}),
|
|
323
|
+
])
|
|
324
|
+
: nothing;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// ─── The bar ─────────────────────────────────────────────────────────────────
|
|
328
|
+
|
|
329
|
+
/** The whole bar, as one template. There is no second variant for the empty states. */
|
|
330
|
+
export function statusbarTemplate() {
|
|
331
|
+
const registry = activeRegistry();
|
|
332
|
+
return html`${projectFieldTpl(registry)}${documentFieldTpl(registry)}${selectionFieldTpl(
|
|
333
|
+
registry,
|
|
334
|
+
)}`;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/** Paint the bar. Exported because the bootstrap paints once before mounting the effect. */
|
|
338
|
+
export function renderStatusbar(): void {
|
|
339
|
+
if (statusbarEl) {
|
|
340
|
+
litRender(statusbarTemplate(), statusbarEl);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/** Subscribe the bar to the state it renders. Idempotent. */
|
|
345
|
+
export function mountStatusbar(): void {
|
|
346
|
+
unmountStatusbar();
|
|
347
|
+
_scope = effectScope();
|
|
348
|
+
_scope.run(() => {
|
|
349
|
+
effect(() => {
|
|
350
|
+
// The registry is composed AFTER the bootstrap mounts this, and it is a reactive holder —
|
|
351
|
+
// Reading it here is what repaints the bar from a skeleton into the real thing.
|
|
352
|
+
void activeRegistry();
|
|
353
|
+
void shell.stylebook.selection;
|
|
354
|
+
void shell.git.status;
|
|
355
|
+
void problems.length;
|
|
356
|
+
const tab = activeTab.value;
|
|
357
|
+
if (tab) {
|
|
358
|
+
void tab.doc.document;
|
|
359
|
+
void tab.doc.dirty;
|
|
360
|
+
void tab.doc.mode;
|
|
361
|
+
void tab.documentPath;
|
|
362
|
+
void tab.session.selection.map((path) => path.join("/")).join("|");
|
|
363
|
+
void tab.session.ui.canvasMode;
|
|
364
|
+
void tab.session.ui.preview;
|
|
365
|
+
void collabState(tab).peers.length;
|
|
366
|
+
void collabState(tab).readOnly;
|
|
367
|
+
}
|
|
368
|
+
renderStatusbar();
|
|
369
|
+
});
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
export function unmountStatusbar(): void {
|
|
374
|
+
_scope?.stop();
|
|
375
|
+
_scope = null;
|
|
140
376
|
}
|