@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
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
2
|
+
/**
|
|
3
|
+
* Panel-registry.ts — one definition site per panel.
|
|
4
|
+
*
|
|
5
|
+
* A {@link PanelRecord} is to a surface what a `Command` is to an action: its name, the containment
|
|
6
|
+
* level of the state it WRITES, the dock that hosts it, the predicate that decides whether it
|
|
7
|
+
* exists at all, and the function that draws it. The rail, the panel header and the dock budget
|
|
8
|
+
* become RENDERINGS of these records — plan §2 principle 1, applied to regions rather than verbs.
|
|
9
|
+
*
|
|
10
|
+
* It mirrors the shipped `settings/settings-modal.ts` contribution point
|
|
11
|
+
* (`registerSettingsSection`) deliberately: a module-level `Map`, keyed by id, written by the
|
|
12
|
+
* module that OWNS the surface. The one thing it adds is the field that makes the rail derivable —
|
|
13
|
+
*
|
|
14
|
+
* **`level` is required, and it is the level of the state the panel WRITES, not the state it
|
|
15
|
+
* reads** (plan §2 principle 3). Insert reads the project's component registry and writes the
|
|
16
|
+
* document tree, so it is `document`. Files reads documents and writes project files, so it is
|
|
17
|
+
* `project`. That rule, and not intuition, is what settles every contested placement and what stops
|
|
18
|
+
* the rail re-accreting: the two rail groups are two rows of
|
|
19
|
+
* {@link
|
|
20
|
+
* import("../commands/levels").PANEL_PLACEMENT_MATRIX}, checked at registration exactly the
|
|
21
|
+
* way a command's `menus` are.
|
|
22
|
+
*
|
|
23
|
+
* The predecessor was an eight-item array literal inside `panels/activity-bar.ts` — `{icon, label,
|
|
24
|
+
* value}` — beside an eight-branch `if` chain in `panels/left-panel.ts` and a third list in
|
|
25
|
+
* `shell.ts`. Three places to keep in step, none of which recorded what a panel was FOR.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
import { resolveI18n } from "@jxsuite/schema/locale";
|
|
29
|
+
import { checkPanelPlacement } from "../commands/levels";
|
|
30
|
+
import { emptyContext } from "../commands/context";
|
|
31
|
+
import { projectState } from "../store";
|
|
32
|
+
import { shell } from "../shell";
|
|
33
|
+
import { activeTab } from "../workspace/workspace";
|
|
34
|
+
import type { Level } from "../commands/levels";
|
|
35
|
+
import type { CommandContext } from "../commands/context";
|
|
36
|
+
import type { GitDiffState } from "../types";
|
|
37
|
+
import type { JxMutableNode } from "@jxsuite/schema/types";
|
|
38
|
+
import type { JxPath } from "../state";
|
|
39
|
+
import type { Tab, TabUi } from "../tabs/tab";
|
|
40
|
+
import type { nothing, TemplateResult } from "lit-html";
|
|
41
|
+
import type { renderGitPanel } from "./git-panel";
|
|
42
|
+
import type { renderHeadTemplate } from "./head-panel";
|
|
43
|
+
import type { renderImportsTemplate } from "./imports-panel";
|
|
44
|
+
import type { renderSignalsTemplate } from "./signals-panel";
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The three docks that host panels.
|
|
48
|
+
*
|
|
49
|
+
* A panel's dock is where its BODY is drawn. Every rail button opens the NAVIGATOR, so a record
|
|
50
|
+
* outside it is `rail: false` and is addressed by name instead — `view.setBottomTab` for the four
|
|
51
|
+
* Bottom-dock tabs. The two were briefly independent, for Problems alone, and the cost was a
|
|
52
|
+
* per-dock branch in three separate places plus a left-hand control that opened something along the
|
|
53
|
+
* bottom. The Inspector has no records yet.
|
|
54
|
+
*/
|
|
55
|
+
export type PanelDock = "navigator" | "inspector" | "bottom";
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* What a Navigator panel is handed that its own module cannot import.
|
|
59
|
+
*
|
|
60
|
+
* This is `left-panel.ts`'s old `LeftPanelCtx`, moved to the registry because it is now the panel
|
|
61
|
+
* CONTRACT rather than one orchestrator's private argument list. `studio.ts` still builds it: the
|
|
62
|
+
* renderers it injects (the file tree, the head panel, the git panel) close over bootstrap state,
|
|
63
|
+
* and injecting them is what keeps `panels/*` free of an import cycle back through `studio.ts`.
|
|
64
|
+
*/
|
|
65
|
+
export interface NavigatorPanelDeps {
|
|
66
|
+
getCanvasMode: () => string;
|
|
67
|
+
setCanvasMode: (tab: Tab | null, mode: string) => void;
|
|
68
|
+
// Typed against their implementations so every call site stays checked. These are type-only
|
|
69
|
+
// Imports, so they are erased — the modules themselves are never pulled in through this file.
|
|
70
|
+
renderImportsTemplate: typeof renderImportsTemplate;
|
|
71
|
+
renderFilesTemplate: () => TemplateResult;
|
|
72
|
+
renderSignalsTemplate: typeof renderSignalsTemplate;
|
|
73
|
+
renderHeadTemplate: typeof renderHeadTemplate;
|
|
74
|
+
renderGitPanel: typeof renderGitPanel;
|
|
75
|
+
renderCanvas: () => void;
|
|
76
|
+
/** Canvas re-render that also lets automatic `Request` entries fetch (Data panel Refresh). */
|
|
77
|
+
refreshData: () => void;
|
|
78
|
+
defCategory: (def: unknown) => string;
|
|
79
|
+
defBadgeLabel: (def: unknown) => string;
|
|
80
|
+
navigateToComponent: (path: string) => void;
|
|
81
|
+
webdata: Record<string, unknown>;
|
|
82
|
+
defaultDef: (tag: string) => Record<string, unknown>;
|
|
83
|
+
registerLayersDnD: () => void;
|
|
84
|
+
registerElementsDnD: () => void;
|
|
85
|
+
registerComponentsDnD: () => void;
|
|
86
|
+
setupTreeKeyboard: (tree: HTMLElement) => void;
|
|
87
|
+
registerFileTreeDnD: (ctx: { renderLeftPanel: () => void }) => void;
|
|
88
|
+
setGitDiffState: (state: GitDiffState | null) => void;
|
|
89
|
+
cloneRepository?: () => void;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* The focused document, as a document-level panel reads it. `null` when no tab is open.
|
|
94
|
+
*
|
|
95
|
+
* A `level: "project"` panel must not read this — that is principle 3's corollary, and the reason
|
|
96
|
+
* the Source Control badge used to vanish when the last tab closed. {@link registerPanel} cannot
|
|
97
|
+
* enforce it (a closure's imports are not inspectable), so the contract is stated here and asserted
|
|
98
|
+
* by `tests/panel-registry.test.ts`, which renders every project-level panel with `doc: null`.
|
|
99
|
+
*/
|
|
100
|
+
export interface NavigatorDocument {
|
|
101
|
+
document: JxMutableNode;
|
|
102
|
+
mode: string;
|
|
103
|
+
/** The whole selection SET the navigator/inspector panels render against (§6.5). */
|
|
104
|
+
selection: JxPath[];
|
|
105
|
+
canvas: Record<string, unknown> | null;
|
|
106
|
+
content?: { frontmatter?: Record<string, unknown> } | undefined;
|
|
107
|
+
documentPath?: string | null | undefined;
|
|
108
|
+
ui: TabUi;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** Everything a panel's `render` receives. One argument, so a record stays a one-liner. */
|
|
112
|
+
export interface NavigatorPanelContext {
|
|
113
|
+
deps: NavigatorPanelDeps;
|
|
114
|
+
/** The focused document, or `null`. Document-level panels render their empty state on `null`. */
|
|
115
|
+
doc: NavigatorDocument | null;
|
|
116
|
+
/** Repaint the Navigator — `left-panel.ts`'s scheduler, not a synchronous re-render. */
|
|
117
|
+
rerender: () => void;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** A panel's rendered body. `nothing` is legal — an empty panel is a state, not a bug. */
|
|
121
|
+
export type PanelBody = TemplateResult | typeof nothing;
|
|
122
|
+
|
|
123
|
+
/** One panel, defined once. */
|
|
124
|
+
export interface PanelRecord {
|
|
125
|
+
/** Lowercase, stable, and the value `view.setActivity` accepts — renaming one is a shot break. */
|
|
126
|
+
id: string;
|
|
127
|
+
/** The human name. The rail label AND the panel header, so there is one place it is spelled. */
|
|
128
|
+
title: string;
|
|
129
|
+
/** REQUIRED. The level of the state this panel WRITES. Checked against the panel matrix. */
|
|
130
|
+
level: Level;
|
|
131
|
+
dock: PanelDock;
|
|
132
|
+
/** Icon key, resolved through `activity-bar.ts`'s `tabIcon()` map. */
|
|
133
|
+
icon: string;
|
|
134
|
+
/**
|
|
135
|
+
* `false` for a panel with no rail button.
|
|
136
|
+
*
|
|
137
|
+
* Not a hiding mechanism — a rail-less panel is still reachable by `view.setActivity`, by the
|
|
138
|
+
* palette and by another surface linking to it. It is how a record survives the interval between
|
|
139
|
+
* losing its rail slot and gaining its real home (Insert becomes an overlay in P3.5; State folds
|
|
140
|
+
* into Data). Declaring it `false` also removes the panel's `rail/<level>` placement, which is
|
|
141
|
+
* what keeps the rail inside its four-per-group budget.
|
|
142
|
+
*/
|
|
143
|
+
rail?: boolean;
|
|
144
|
+
/**
|
|
145
|
+
* The sentence a document-level panel shows instead of its body when no document is open.
|
|
146
|
+
*
|
|
147
|
+
* Said in the words of the thing the panel needs ("Open a page to see the elements it is built
|
|
148
|
+
* from."), so the ring collapses to a sentence rather than to an empty box. Absent means the
|
|
149
|
+
* panel renders with `doc: null` — Insert does, because an element palette is meaningful before
|
|
150
|
+
* you have chosen where to put anything.
|
|
151
|
+
*/
|
|
152
|
+
requiresDocument?: string;
|
|
153
|
+
/** Hide entirely — for a surface that does not exist yet. Default: always present. */
|
|
154
|
+
when?: (ctx: CommandContext) => boolean;
|
|
155
|
+
/** The rail badge, e.g. Source Control's changed-file count. `null`/`0` renders nothing. */
|
|
156
|
+
badge?: (ctx: CommandContext) => number | string | null;
|
|
157
|
+
render: (ctx: NavigatorPanelContext) => PanelBody;
|
|
158
|
+
/**
|
|
159
|
+
* Imperative work that needs the painted DOM — drag registrations, tree keyboard wiring.
|
|
160
|
+
*
|
|
161
|
+
* The eight `if (tab === …)` post-render branches `left-panel.ts` carried, moved onto the records
|
|
162
|
+
* that caused them, so adding a panel cannot forget to drain the previous one's registrations.
|
|
163
|
+
*/
|
|
164
|
+
afterRender?: (ctx: NavigatorPanelContext, host: HTMLElement) => void;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* The context a panel's `when` and `badge` are evaluated against.
|
|
169
|
+
*
|
|
170
|
+
* A SUBSET of the command context, built from the two records a panel predicate has ever needed:
|
|
171
|
+
* the reactive `shell` (project-level source control, hoisted off `TabUi` for exactly this reason)
|
|
172
|
+
* and `projectState`. Reading it inside a rendering effect is what makes the rail repaint when the
|
|
173
|
+
* working tree changes, because both reads are tracked.
|
|
174
|
+
*
|
|
175
|
+
* **A key a panel gates on has to be here.** A subset is only safe while it covers every predicate
|
|
176
|
+
* actually written: `isMultilingual` was declared, computed in `live-context.ts`, and left out of
|
|
177
|
+
* this one — so the Languages panel's `when` read the `emptyContext()` default, and the Navigator
|
|
178
|
+
* answered "No Navigator panel is registered as i18n" on a project that declares three languages.
|
|
179
|
+
* Nothing failed; the panel was simply never visible.
|
|
180
|
+
*
|
|
181
|
+
* It is deliberately not `createLiveContext()`: that builder needs four facts only `studio.ts` can
|
|
182
|
+
* inject (the canvas mode, the caret, the modal flag, the platform), and a rail that imported the
|
|
183
|
+
* bootstrap to draw a badge would be the import cycle `live-context.ts` documents avoiding. When
|
|
184
|
+
* the bootstrap wires panels the same way it wires commands, this function is what it replaces.
|
|
185
|
+
*/
|
|
186
|
+
export function panelContext(): CommandContext {
|
|
187
|
+
const ctx = emptyContext();
|
|
188
|
+
ctx.project.open = projectState !== null;
|
|
189
|
+
ctx.project.isMultilingual =
|
|
190
|
+
(resolveI18n(projectState?.projectConfig ?? {}).i18n?.locales.length ?? 0) > 1;
|
|
191
|
+
ctx.git.dirtyCount = shell.git.status?.files?.length ?? 0;
|
|
192
|
+
ctx.document.open = activeTab.value !== null;
|
|
193
|
+
return ctx;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/** `[a-z]` then word characters — the same shape `navigator/panel:<id>` is matched by. */
|
|
197
|
+
const PANEL_ID_PATTERN = /^[a-z][\w-]*$/;
|
|
198
|
+
|
|
199
|
+
const panelRegistry = new Map<string, PanelRecord>();
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Define a panel. Throws on a duplicate id, a malformed id, or a matrix violation.
|
|
203
|
+
*
|
|
204
|
+
* Failing at registration is the same bet `createCommandRegistry.register` makes: a misplaced
|
|
205
|
+
* surface is a design error, and a design error that only shows up as a wrong-looking rail is a
|
|
206
|
+
* design error nobody fixes.
|
|
207
|
+
*
|
|
208
|
+
* @param {PanelRecord} panel
|
|
209
|
+
*/
|
|
210
|
+
export function registerPanel(panel: PanelRecord): void {
|
|
211
|
+
if (!PANEL_ID_PATTERN.test(panel.id)) {
|
|
212
|
+
throw new Error(
|
|
213
|
+
`Panel id "${panel.id}" is malformed — expected /^[a-z][\\w-]*$/, because the id is also ` +
|
|
214
|
+
`the region "navigator/panel:${panel.id}" and the value view.setActivity accepts.`,
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
if (panelRegistry.has(panel.id)) {
|
|
218
|
+
throw new Error(
|
|
219
|
+
`Panel "${panel.id}" is already registered — a second definition site is the defect this ` +
|
|
220
|
+
`registry exists to prevent.`,
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
const violations = checkPanelPlacement({
|
|
224
|
+
id: panel.id,
|
|
225
|
+
level: panel.level,
|
|
226
|
+
dock: panel.dock,
|
|
227
|
+
rail: panel.rail,
|
|
228
|
+
});
|
|
229
|
+
if (violations.length > 0) {
|
|
230
|
+
const detail = violations.map((violation) => ` ✗ ${panel.id} ${violation.message}`).join("\n");
|
|
231
|
+
throw new Error(`Panel "${panel.id}" violates the level × placement matrix:\n${detail}`);
|
|
232
|
+
}
|
|
233
|
+
panelRegistry.set(panel.id, panel);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/** Remove a panel — the contributed-extension path, and the reset every test needs. */
|
|
237
|
+
export function unregisterPanel(id: string): void {
|
|
238
|
+
panelRegistry.delete(id);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** Drop every registration. Tests only; the app registers once, at mount. */
|
|
242
|
+
export function resetPanels(): void {
|
|
243
|
+
panelRegistry.clear();
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/** One panel by id, or `undefined`. */
|
|
247
|
+
export function getPanel(id: string): PanelRecord | undefined {
|
|
248
|
+
return panelRegistry.get(id);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/** Every registered panel, in registration order — which is rail order. */
|
|
252
|
+
export function listPanels(dock?: PanelDock): readonly PanelRecord[] {
|
|
253
|
+
const all = [...panelRegistry.values()];
|
|
254
|
+
return dock ? all.filter((panel) => panel.dock === dock) : all;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/** Whether a panel's `when` admits it in this context. A record with no `when` always does. */
|
|
258
|
+
export function isPanelVisible(panel: PanelRecord, ctx: CommandContext): boolean {
|
|
259
|
+
return panel.when ? panel.when(ctx) : true;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/** One rail group: the level it hosts, its heading, and the panels in it. */
|
|
263
|
+
export interface RailGroup {
|
|
264
|
+
level: Level;
|
|
265
|
+
/** The group's accessible name — "Project" / "Document", the levels said out loud. */
|
|
266
|
+
label: string;
|
|
267
|
+
panels: readonly PanelRecord[];
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/** The rail's two groups, in shell order. `application` and `selection` have no group. */
|
|
271
|
+
const RAIL_GROUP_LEVELS: readonly { level: Level; label: string }[] = [
|
|
272
|
+
{ level: "project", label: "Project" },
|
|
273
|
+
{ level: "document", label: "Document" },
|
|
274
|
+
];
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Every panel that has a rail button, whatever dock draws its body.
|
|
278
|
+
*
|
|
279
|
+
* The rail is NOT the Navigator's tab strip. `panelPlacements()` has always awarded `rail/<level>`
|
|
280
|
+
* on `rail !== false` alone — the dock is a separate placement — and Problems is the panel that
|
|
281
|
+
* proves it: its body is the Bottom dock's first tab (plan §7.2), and it still owns a rail slot and
|
|
282
|
+
* a badge, because "how many things need fixing" is a question you ask without opening anything.
|
|
283
|
+
* Filtering this by `dock === "navigator"` is what would put the same list in two hosts at once.
|
|
284
|
+
*/
|
|
285
|
+
function railablePanels(): readonly PanelRecord[] {
|
|
286
|
+
return listPanels().filter((panel) => panel.rail !== false);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* The rail, as data: every rail-able panel, grouped by level, `when`-filtered.
|
|
291
|
+
*
|
|
292
|
+
* Empty groups are dropped, so the divider between them is never drawn against nothing.
|
|
293
|
+
*
|
|
294
|
+
* @param {CommandContext} ctx
|
|
295
|
+
*/
|
|
296
|
+
export function railGroups(ctx: CommandContext): RailGroup[] {
|
|
297
|
+
const railable = railablePanels();
|
|
298
|
+
return RAIL_GROUP_LEVELS.map(({ level, label }) => ({
|
|
299
|
+
level,
|
|
300
|
+
label,
|
|
301
|
+
panels: railable.filter((panel) => panel.level === level && isPanelVisible(panel, ctx)),
|
|
302
|
+
})).filter((group) => group.panels.length > 0);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* The rail's panels flattened into rail order — PROJECT group, then DOCUMENT group.
|
|
307
|
+
*
|
|
308
|
+
* This is the order ⌘1–8 follow, and it is derived from the same two rows the rail draws rather
|
|
309
|
+
* than from registration order, so a panel registered by its dock's module (Problems, from
|
|
310
|
+
* `panels/bottom-dock.ts`) still lands in the slot its LEVEL gives it. `when` is not applied: a
|
|
311
|
+
* chord roster that changed length with context would move every chord after the hidden panel.
|
|
312
|
+
*/
|
|
313
|
+
export function railPanelSet(): PanelRecord[] {
|
|
314
|
+
const railable = railablePanels();
|
|
315
|
+
return RAIL_GROUP_LEVELS.flatMap(({ level }) =>
|
|
316
|
+
railable.filter((panel) => panel.level === level),
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/** One tabbed region and what it declares, in `commands/budget.ts`'s shape. */
|
|
321
|
+
export interface PanelDockDeclaration {
|
|
322
|
+
dock: string;
|
|
323
|
+
tabs: readonly string[];
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* The rail's two groups as budget declarations — the `rail/*` rows `scripts/check-chrome-budget.ts`
|
|
328
|
+
* counts, observed rather than written down. `commands/budget.ts` no longer carries a copy.
|
|
329
|
+
*
|
|
330
|
+
* `when` is deliberately NOT applied: the budget caps what the shell may GROW to, not what happens
|
|
331
|
+
* to be visible in one context. Search is registered and hidden today, and it still spends its rail
|
|
332
|
+
* slot — which is the point, because its arrival must not silently push the rail to five.
|
|
333
|
+
*/
|
|
334
|
+
export function railDeclarations(): PanelDockDeclaration[] {
|
|
335
|
+
const railable = railablePanels();
|
|
336
|
+
return RAIL_GROUP_LEVELS.map(({ level }) => ({
|
|
337
|
+
dock: `rail/${level}`,
|
|
338
|
+
tabs: railable.filter((panel) => panel.level === level).map((panel) => panel.title),
|
|
339
|
+
})).filter((declaration) => declaration.tabs.length > 0);
|
|
340
|
+
}
|
|
@@ -33,6 +33,53 @@ export function isTextInput(el: Element | null): boolean {
|
|
|
33
33
|
return false;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Every bound scheduler, so "is any panel still owing a repaint?" has one answer.
|
|
38
|
+
*
|
|
39
|
+
* Condition 2 of the `probe.idle()` predicate (`services/idle.ts`, spec §13.5). Each scheduler
|
|
40
|
+
* already knew whether it had a frame queued or a render withheld; nothing could ask all of them at
|
|
41
|
+
* once. P4.4 makes the withheld case visible to the author too — a panel silently showing stale
|
|
42
|
+
* state is a bug whichever consumer notices it first.
|
|
43
|
+
*/
|
|
44
|
+
const boundSchedulers = new Set<TrackedScheduler>();
|
|
45
|
+
|
|
46
|
+
interface TrackedScheduler {
|
|
47
|
+
/** The panel root, for the human-readable blocker string. */
|
|
48
|
+
root: HTMLElement;
|
|
49
|
+
/** A coalescing frame is queued and will paint. */
|
|
50
|
+
hasFrame: () => boolean;
|
|
51
|
+
/** A render was requested and is being WITHHELD because a field in the panel has focus. */
|
|
52
|
+
isDeferring: () => boolean;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** `#right-panel`, `.frontmatter-panel`, `div` — the most specific handle the root offers. */
|
|
56
|
+
function describeRoot(root: HTMLElement): string {
|
|
57
|
+
if (root.id) {
|
|
58
|
+
return `#${root.id}`;
|
|
59
|
+
}
|
|
60
|
+
const first = root.className.split(/\s+/).find(Boolean);
|
|
61
|
+
return first ? `.${first}` : root.tagName.toLowerCase();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* One line per panel that still owes a repaint — empty when every panel's DOM matches its state.
|
|
66
|
+
*
|
|
67
|
+
* A withheld render is reported separately from a queued one because they end differently: a queued
|
|
68
|
+
* frame lands on its own, a withheld one waits for a focusout that may never come. A predicate that
|
|
69
|
+
* conflated them would either hang or lie.
|
|
70
|
+
*/
|
|
71
|
+
export function pendingSchedulers(): string[] {
|
|
72
|
+
const blockers: string[] = [];
|
|
73
|
+
for (const entry of boundSchedulers) {
|
|
74
|
+
if (entry.hasFrame()) {
|
|
75
|
+
blockers.push(`${describeRoot(entry.root)} has a frame queued`);
|
|
76
|
+
} else if (entry.isDeferring()) {
|
|
77
|
+
blockers.push(`${describeRoot(entry.root)} is withholding a render (a field has focus)`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return blockers;
|
|
81
|
+
}
|
|
82
|
+
|
|
36
83
|
export interface PanelScheduler {
|
|
37
84
|
/** Request a render. Coalesced; deferred while a text input in the panel is focused. */
|
|
38
85
|
schedule: () => void;
|
|
@@ -72,6 +119,23 @@ export function createPanelScheduler(opts: {
|
|
|
72
119
|
|
|
73
120
|
const blocked = () => editing || (blockWhile ? blockWhile() : false);
|
|
74
121
|
|
|
122
|
+
/**
|
|
123
|
+
* Publish the withheld render to the person looking at the panel.
|
|
124
|
+
*
|
|
125
|
+
* A deferred render is the panel deciding, correctly, that finishing your sentence matters more
|
|
126
|
+
* than being current — but until P4 it made that trade in silence, so a panel showing state from
|
|
127
|
+
* before your last edit was indistinguishable from a panel that had stopped working. The
|
|
128
|
+
* attribute is the whole mechanism: `styles/overlays.css` hangs the hint off it, so every panel
|
|
129
|
+
* that already routes through this scheduler inherits it without a line of its own.
|
|
130
|
+
*/
|
|
131
|
+
function markStale(stale: boolean) {
|
|
132
|
+
if (stale) {
|
|
133
|
+
root.dataset.jxStale = "";
|
|
134
|
+
} else {
|
|
135
|
+
delete root.dataset.jxStale;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
75
139
|
function flush() {
|
|
76
140
|
scheduled = false;
|
|
77
141
|
rafId = 0;
|
|
@@ -81,9 +145,11 @@ export function createPanelScheduler(opts: {
|
|
|
81
145
|
// Defer while a field is focused — flushed later by focusout (or the next schedule()).
|
|
82
146
|
if (blocked()) {
|
|
83
147
|
pending = true;
|
|
148
|
+
markStale(true);
|
|
84
149
|
return;
|
|
85
150
|
}
|
|
86
151
|
pending = false;
|
|
152
|
+
markStale(false);
|
|
87
153
|
rendering = true;
|
|
88
154
|
try {
|
|
89
155
|
render();
|
|
@@ -114,6 +180,13 @@ export function createPanelScheduler(opts: {
|
|
|
114
180
|
}
|
|
115
181
|
}
|
|
116
182
|
|
|
183
|
+
const tracked: TrackedScheduler = {
|
|
184
|
+
hasFrame: () => scheduled,
|
|
185
|
+
isDeferring: () => pending,
|
|
186
|
+
root,
|
|
187
|
+
};
|
|
188
|
+
boundSchedulers.add(tracked);
|
|
189
|
+
|
|
117
190
|
return {
|
|
118
191
|
bindFocus() {
|
|
119
192
|
root.addEventListener("focusin", onFocusIn);
|
|
@@ -130,6 +203,7 @@ export function createPanelScheduler(opts: {
|
|
|
130
203
|
isEditing: () => blocked(),
|
|
131
204
|
schedule,
|
|
132
205
|
unbind() {
|
|
206
|
+
boundSchedulers.delete(tracked);
|
|
133
207
|
root.removeEventListener("focusin", onFocusIn);
|
|
134
208
|
root.removeEventListener("focusout", onFocusOut);
|
|
135
209
|
if (rafId) {
|
|
@@ -138,6 +212,7 @@ export function createPanelScheduler(opts: {
|
|
|
138
212
|
scheduled = false;
|
|
139
213
|
pending = false;
|
|
140
214
|
editing = false;
|
|
215
|
+
markStale(false);
|
|
141
216
|
rendering = false;
|
|
142
217
|
},
|
|
143
218
|
};
|