@jxsuite/studio 2.0.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/canvas.html +21 -0
- package/dist/chunks/Overlay.dev-qfjzkms8.js +23 -0
- package/dist/chunks/{Overlay.dev-cszx7yn5.js.map → Overlay.dev-qfjzkms8.js.map} +1 -1
- package/dist/chunks/{adapter-z8fkmbmv.js → adapter-qfnesn5v.js} +2 -2
- package/dist/chunks/{cf-settings-mmyv436d.js → cf-settings-73sh5z4p.js} +3 -3
- package/dist/chunks/{components-799jpvhm.js → components-2bpqp4mq.js} +5 -7
- package/dist/chunks/{components-799jpvhm.js.map → components-2bpqp4mq.js.map} +1 -1
- package/dist/chunks/content-source-34gnkbnn.js +38 -0
- package/dist/chunks/content-source-34gnkbnn.js.map +9 -0
- package/dist/chunks/convert-to-repeater-t8kxre5s.js +258 -0
- package/dist/chunks/convert-to-repeater-t8kxre5s.js.map +10 -0
- package/dist/chunks/extension-sections-6mqydz35.js +301 -0
- package/dist/chunks/extension-sections-6mqydz35.js.map +11 -0
- package/dist/chunks/files-8kn321h1.js +70 -0
- package/dist/chunks/files-8kn321h1.js.map +9 -0
- package/dist/chunks/{format-host-8jxwts2p.js → format-host-mkwsmt8d.js} +3 -3
- package/dist/chunks/git-panel-tjbr191d.js +51 -0
- package/dist/chunks/git-panel-tjbr191d.js.map +9 -0
- package/dist/chunks/{index-baeg2x3y.js → index-7pxchcce.js} +4 -3
- package/dist/chunks/{index-baeg2x3y.js.map → index-7pxchcce.js.map} +3 -3
- package/dist/chunks/{jx-validate-qx8degj7.js → jx-validate-v6qgknrs.js} +3 -3
- package/dist/chunks/layers-panel-87pb25km.js +58 -0
- package/dist/chunks/layers-panel-87pb25km.js.map +9 -0
- package/dist/chunks/{monaco-setup-zjdp9zdw.js → monaco-setup-e0yh25j4.js} +4 -75
- package/dist/chunks/{monaco-setup-zjdp9zdw.js.map → monaco-setup-e0yh25j4.js.map} +3 -4
- package/dist/chunks/publish-panel-m0fcgdrt.js +21 -0
- package/dist/chunks/publish-panel-m0fcgdrt.js.map +9 -0
- package/dist/chunks/quick-search-rhs6cbsb.js +53 -0
- package/dist/chunks/quick-search-rhs6cbsb.js.map +9 -0
- package/dist/chunks/right-panel-zpdxd98t.js +37 -0
- package/dist/chunks/right-panel-zpdxd98t.js.map +9 -0
- package/dist/chunks/section-registry-zmckaxf4.js +30 -0
- package/dist/chunks/section-registry-zmckaxf4.js.map +9 -0
- package/dist/chunks/sp-overlay.dev-9ran0sfq.js +18 -0
- package/dist/chunks/sp-overlay.dev-9ran0sfq.js.map +9 -0
- package/dist/chunks/sp-popover.dev-rebmdncr.js +9 -0
- package/dist/chunks/sp-popover.dev-rebmdncr.js.map +9 -0
- package/dist/chunks/sp-progress-circle.dev-5vkppfkt.js +15 -0
- package/dist/chunks/sp-progress-circle.dev-5vkppfkt.js.map +9 -0
- package/dist/chunks/sp-tooltip.dev-ykqrg8h5.js +15 -0
- package/dist/chunks/sp-tooltip.dev-ykqrg8h5.js.map +9 -0
- package/dist/chunks/{sp-tray.dev-pb2fsd65.js → sp-tray.dev-ey59vfh7.js} +10 -8
- package/dist/chunks/{sp-tray.dev-pb2fsd65.js.map → sp-tray.dev-ey59vfh7.js.map} +2 -2
- package/dist/chunks/{studio-9qr6fq7p.js → studio-0rqqhrdy.js} +10 -378
- package/dist/chunks/{studio-9qr6fq7p.js.map → studio-0rqqhrdy.js.map} +4 -14
- package/dist/chunks/{studio-5x6tqqec.js → studio-2sj1jj3v.js} +10 -8
- package/dist/chunks/{studio-5x6tqqec.js.map → studio-2sj1jj3v.js.map} +2 -2
- package/dist/chunks/{studio-h3fw0wn8.js → studio-3fk1ac9z.js} +6 -4
- package/dist/chunks/{studio-h3fw0wn8.js.map → studio-3fk1ac9z.js.map} +2 -2
- package/dist/chunks/studio-41exgzhq.js +6690 -0
- package/dist/chunks/studio-41exgzhq.js.map +38 -0
- package/dist/chunks/{studio-7v2bpweq.js → studio-4mqb9a0j.js} +6 -4
- package/dist/chunks/{studio-7v2bpweq.js.map → studio-4mqb9a0j.js.map} +2 -2
- package/dist/chunks/studio-50k77cca.js +1787 -0
- package/dist/chunks/studio-50k77cca.js.map +18 -0
- package/dist/chunks/{studio-56v3zwk6.js → studio-6a0h7sne.js} +10 -8
- package/dist/chunks/{studio-56v3zwk6.js.map → studio-6a0h7sne.js.map} +2 -2
- package/dist/chunks/studio-6f0am8f2.js +53 -0
- package/dist/chunks/studio-6f0am8f2.js.map +10 -0
- package/dist/chunks/studio-6nmjc5qk.js +7002 -0
- package/dist/chunks/studio-6nmjc5qk.js.map +32 -0
- package/dist/chunks/studio-7afd21nw.js +67 -0
- package/dist/chunks/studio-7afd21nw.js.map +10 -0
- package/dist/chunks/{studio-xze4zrs1.js → studio-7bmdvzne.js} +2 -2
- package/dist/chunks/studio-7bmdvzne.js.map +10 -0
- package/dist/chunks/studio-8jpzqk5s.js +128 -0
- package/dist/chunks/studio-8jpzqk5s.js.map +10 -0
- package/dist/chunks/studio-94m77tgk.js +1482 -0
- package/dist/chunks/studio-94m77tgk.js.map +13 -0
- package/dist/chunks/studio-9je6w5sq.js +1000 -0
- package/dist/chunks/studio-9je6w5sq.js.map +16 -0
- package/dist/chunks/{studio-w7c6kvk7.js → studio-a7pzveq1.js} +2 -2
- package/dist/chunks/{studio-gs6kqdt1.js → studio-adn0z1k3.js} +14 -8
- package/dist/chunks/{studio-gs6kqdt1.js.map → studio-adn0z1k3.js.map} +3 -3
- package/dist/chunks/{studio-kr88ryr7.js → studio-bsxxx3x2.js} +17 -15
- package/dist/chunks/{studio-kr88ryr7.js.map → studio-bsxxx3x2.js.map} +7 -6
- package/dist/chunks/studio-bw5dz6km.js +608 -0
- package/dist/chunks/studio-bw5dz6km.js.map +21 -0
- package/dist/chunks/studio-c6s5getc.js +4232 -0
- package/dist/chunks/studio-c6s5getc.js.map +39 -0
- package/dist/chunks/studio-cjm7fdjf.js +451 -0
- package/dist/chunks/studio-cjm7fdjf.js.map +14 -0
- package/dist/chunks/{studio-cx91mnh8.js → studio-ckwz4d3x.js} +53 -53
- package/dist/chunks/{studio-cx91mnh8.js.map → studio-ckwz4d3x.js.map} +5 -5
- package/dist/chunks/studio-dg7zyt5x.js +28 -0
- package/dist/chunks/studio-dg7zyt5x.js.map +10 -0
- package/dist/chunks/studio-dzcyvvvz.js +166 -0
- package/dist/chunks/studio-dzcyvvvz.js.map +10 -0
- package/dist/chunks/{studio-7kqe41sa.js → studio-evkr5d3b.js} +15 -7
- package/dist/chunks/{studio-7kqe41sa.js.map → studio-evkr5d3b.js.map} +5 -4
- package/dist/chunks/studio-f12h6177.js +411 -0
- package/dist/chunks/studio-f12h6177.js.map +13 -0
- package/dist/chunks/studio-hbp1s8m9.js +1817 -0
- package/dist/chunks/studio-hbp1s8m9.js.map +14 -0
- package/dist/chunks/studio-k2sxjph5.js +15295 -0
- package/dist/chunks/studio-k2sxjph5.js.map +235 -0
- package/dist/chunks/studio-myje51t3.js +385 -0
- package/dist/chunks/studio-myje51t3.js.map +12 -0
- package/dist/chunks/studio-na6rwzhw.js +353 -0
- package/dist/chunks/studio-na6rwzhw.js.map +11 -0
- package/dist/chunks/{studio-4k0m4fmp.js → studio-p471gg5n.js} +126 -3
- package/dist/chunks/studio-p471gg5n.js.map +14 -0
- package/dist/chunks/{studio-9bjwf0d4.js → studio-rgwcpast.js} +5 -46
- package/dist/chunks/{studio-9bjwf0d4.js.map → studio-rgwcpast.js.map} +4 -5
- package/dist/chunks/{studio-esrewxap.js → studio-s519zc99.js} +3 -3
- package/dist/chunks/studio-sas7mt3k.js +75 -0
- package/dist/chunks/studio-sas7mt3k.js.map +10 -0
- package/dist/chunks/studio-t5wqwzdh.js +74 -0
- package/dist/chunks/studio-t5wqwzdh.js.map +10 -0
- package/dist/chunks/{studio-9qpspwfn.js → studio-temv5bw4.js} +5 -5
- package/dist/chunks/{studio-9qpspwfn.js.map → studio-temv5bw4.js.map} +1 -1
- package/dist/chunks/{studio-qkvt37c0.js → studio-tr20m8g8.js} +669 -18
- package/dist/chunks/studio-tr20m8g8.js.map +9 -0
- package/dist/chunks/{studio-v7jkjqng.js → studio-v96qfnww.js} +5514 -4291
- package/dist/chunks/studio-v96qfnww.js.map +54 -0
- package/dist/chunks/studio-vcetc91k.js +659 -0
- package/dist/chunks/studio-vcetc91k.js.map +10 -0
- package/dist/chunks/{studio-jm0z592w.js → studio-vmymjefp.js} +2972 -4937
- package/dist/chunks/studio-vmymjefp.js.map +98 -0
- package/dist/chunks/{studio-bghqfmea.js → studio-wwseqyw0.js} +2 -2
- package/dist/chunks/studio-x9hmy5kr.js +390 -0
- package/dist/chunks/studio-x9hmy5kr.js.map +10 -0
- package/dist/chunks/studio-xa0ce0n7.js +335 -0
- package/dist/chunks/studio-xa0ce0n7.js.map +10 -0
- package/dist/chunks/studio-xm3dbxvn.js +378 -0
- package/dist/chunks/studio-xm3dbxvn.js.map +19 -0
- package/dist/chunks/{studio-nqw433kv.js → studio-xmvbhg31.js} +2 -2
- package/dist/chunks/studio-zv37yrfa.js +1054 -0
- package/dist/chunks/studio-zv37yrfa.js.map +13 -0
- package/dist/chunks/{ws-client-q7hkz3j9.js → ws-client-654ts66j.js} +6 -4
- package/dist/chunks/ws-client-654ts66j.js.map +11 -0
- package/dist/iframe-entry.js +668 -230
- package/dist/studio.js +21080 -32585
- package/index.html +35 -4685
- package/package.json +17 -15
- package/src/about/about-modal.ts +42 -11
- package/src/browse/library-commands.ts +240 -0
- package/src/browse/library-layouts.ts +369 -0
- package/src/browse/library-model.ts +396 -0
- package/src/browse/library-pane.ts +1049 -0
- package/src/browse/library-preview.ts +252 -0
- package/src/browse/library-source.ts +150 -0
- package/src/canvas/canvas-helpers.ts +33 -9
- package/src/canvas/canvas-live-render.ts +45 -29
- package/src/canvas/canvas-patcher.ts +151 -31
- package/src/canvas/canvas-perf.ts +46 -7
- package/src/canvas/canvas-render.ts +1092 -220
- package/src/canvas/canvas-surface.ts +240 -0
- package/src/canvas/canvas-utils.ts +1166 -124
- package/src/canvas/iframe-drop.ts +2 -1
- package/src/canvas/iframe-entry.ts +241 -4
- package/src/canvas/iframe-host.ts +1226 -143
- package/src/canvas/iframe-inline-edit.ts +31 -0
- package/src/canvas/iframe-interaction.ts +76 -16
- package/src/canvas/iframe-keys.ts +107 -45
- package/src/canvas/iframe-overlay.ts +38 -1
- package/src/canvas/iframe-protocol.ts +137 -2
- package/src/canvas/iframe-render.ts +70 -2
- package/src/canvas/iframe-slash.ts +6 -0
- package/src/canvas/path-mapping.ts +56 -6
- package/src/canvas/surface-registry.ts +292 -0
- package/src/collab/collab-commands.ts +244 -0
- package/src/collab/collab-session.ts +198 -32
- package/src/collab/collab-state.ts +28 -2
- package/src/collab/presence-chips.ts +100 -9
- package/src/commands/active-registry.ts +42 -0
- package/src/commands/app-commands.ts +176 -0
- package/src/commands/budget.ts +158 -0
- package/src/commands/command-args.ts +253 -0
- package/src/commands/context.ts +387 -0
- package/src/commands/defaults.ts +580 -0
- package/src/commands/keymap.ts +571 -0
- package/src/commands/levels.ts +345 -0
- package/src/commands/live-context.ts +193 -0
- package/src/commands/reference.ts +227 -0
- package/src/commands/registry.ts +293 -0
- package/src/component-props.ts +3 -2
- package/src/content/draft-state.ts +106 -0
- package/src/content/entry-commands.ts +282 -0
- package/src/content/entry-editor.ts +327 -0
- package/src/content/entry-fields.ts +116 -0
- package/src/content/entry-model.ts +175 -0
- package/src/editor/canvas-context-menu.ts +17 -11
- package/src/editor/canvas-slash-bridge.ts +11 -4
- package/src/editor/context-menu.ts +804 -204
- package/src/editor/convert-to-component.ts +31 -10
- package/src/editor/convert-to-repeater.ts +3 -2
- package/src/editor/inline-edit-apply.ts +5 -5
- package/src/editor/inline-edit.ts +86 -50
- package/src/editor/insert-zone-action.ts +1 -1
- package/src/editor/shortcuts.ts +1043 -329
- package/src/editor/slash-menu.ts +1 -0
- package/src/files/elements.ts +166 -0
- package/src/files/file-ops.ts +178 -31
- package/src/files/files.ts +898 -268
- package/src/files/fs-events.ts +21 -0
- package/src/files/media-meta.ts +203 -0
- package/src/files/media-paths.ts +141 -0
- package/src/files/media-upload.ts +7 -3
- package/src/files/media-usage.ts +189 -0
- package/src/github/github-auth.ts +235 -33
- package/src/github/github-publish.ts +80 -21
- package/src/grid/grid-controller.ts +152 -12
- package/src/grid/grid-layout.ts +225 -20
- package/src/grid/grid-open.ts +120 -0
- package/src/grid/grid-panel.ts +554 -39
- package/src/grid/grid-source.ts +27 -1
- package/src/grid/redirects-grid.ts +599 -0
- package/src/grid/redirects.ts +398 -0
- package/src/grid/sources/content-source.ts +108 -2
- package/src/i18n/i18n-commands.ts +322 -0
- package/src/new-project/add-repo-modal.ts +8 -10
- package/src/new-project/import-tab.ts +7 -0
- package/src/new-project/location-fields.ts +9 -1
- package/src/new-project/new-project-modal.ts +221 -245
- package/src/packages/jxsuite-update.ts +97 -48
- package/src/packages/pull-package-sync.ts +18 -9
- package/src/page-params.ts +2 -1
- package/src/panels/activity-bar.ts +152 -91
- package/src/panels/activity-panel.ts +481 -0
- package/src/panels/ai-chat/chat-markdown.ts +8 -3
- package/src/panels/ai-chat/chat-view.ts +245 -18
- package/src/panels/ai-chat/composer.ts +31 -5
- package/src/panels/ai-chat/sessions-view.ts +17 -10
- package/src/panels/ai-panel.ts +279 -53
- package/src/panels/block-action-bar.ts +1115 -224
- package/src/panels/bottom-dock.ts +337 -0
- package/src/panels/canvas-dnd-bridge.ts +37 -8
- package/src/panels/chat-panel.ts +29 -12
- package/src/panels/data-explorer.ts +254 -112
- package/src/panels/data-grid.ts +10 -4
- package/src/panels/dnd.ts +28 -51
- package/src/panels/editors.ts +434 -107
- package/src/panels/elements-panel.ts +66 -2
- package/src/panels/empty-state.ts +112 -0
- package/src/panels/events-panel.ts +596 -82
- package/src/panels/formula-workspace.ts +408 -218
- package/src/panels/frontmatter-fields.ts +51 -10
- package/src/panels/frontmatter-panel.ts +357 -79
- package/src/panels/git-panel.ts +375 -164
- package/src/panels/head-panel.ts +791 -85
- package/src/panels/i18n-panel.ts +592 -0
- package/src/panels/imports-panel.ts +95 -85
- package/src/panels/jump-bar.ts +584 -0
- package/src/panels/layers-panel.ts +1106 -328
- package/src/panels/left-panel.ts +109 -204
- package/src/panels/navigator-panels.ts +131 -0
- package/src/panels/overlays.ts +7 -2
- package/src/panels/pane-context.ts +1477 -0
- package/src/panels/pane-grid.ts +406 -0
- package/src/panels/panel-registry.ts +340 -0
- package/src/panels/panel-scheduler.ts +75 -0
- package/src/panels/problems-panel.ts +234 -0
- package/src/panels/properties-panel.ts +946 -1139
- package/src/panels/provenance.ts +258 -0
- package/src/panels/quick-search.ts +791 -122
- package/src/panels/right-panel.ts +228 -102
- package/src/panels/seo-modal.ts +395 -0
- package/src/panels/settings-pane.ts +203 -0
- package/src/panels/signals-panel.ts +354 -137
- package/src/panels/statement-editor.ts +41 -25
- package/src/panels/statusbar.ts +342 -106
- package/src/panels/style-panel.ts +974 -463
- package/src/panels/style-utils.ts +3 -3
- package/src/panels/stylebook-doc.ts +4 -2
- package/src/panels/stylebook-layers-panel.ts +3 -2
- package/src/panels/stylebook-panel.ts +51 -26
- package/src/panels/tab-strip.ts +1058 -78
- package/src/panels/target-line.ts +274 -0
- package/src/panels/toolbar.ts +631 -484
- package/src/panels/welcome-screen.ts +301 -198
- package/src/platform-errors.ts +26 -3
- package/src/platform.ts +96 -2
- package/src/platforms/cloud.ts +71 -8
- package/src/platforms/devserver.ts +92 -29
- package/src/publish/deploy-checklist.ts +383 -0
- package/src/publish/pages-service.ts +10 -1
- package/src/publish/publish-commands.ts +218 -0
- package/src/publish/publish-panel.ts +110 -16
- package/src/recent-projects.ts +3 -2
- package/src/services/a11y-report.ts +505 -0
- package/src/services/ai-models.ts +30 -1
- package/src/services/ai-project-tools.ts +29 -10
- package/src/services/ai-system-prompt.ts +53 -14
- package/src/services/ai-tools.ts +39 -3
- package/src/services/ai-writes.ts +154 -0
- package/src/services/announce.ts +97 -0
- package/src/services/automation.ts +424 -175
- package/src/services/cem-export.ts +9 -4
- package/src/services/clock.ts +61 -0
- package/src/services/document-assistant.ts +36 -8
- package/src/services/idle.ts +179 -0
- package/src/services/import-client.ts +26 -0
- package/src/services/monaco-buffer.ts +627 -0
- package/src/services/monaco-lazy.ts +36 -0
- package/src/services/notify.ts +271 -0
- package/src/services/profile.ts +155 -0
- package/src/services/references.ts +0 -0
- package/src/services/token-lint.ts +3 -2
- package/src/services/tool-executor.ts +53 -7
- package/src/services/trusted-types.ts +123 -0
- package/src/settings/contexts-section.ts +427 -0
- package/src/settings/contributed-section.ts +149 -11
- package/src/settings/css-vars-editor.ts +306 -349
- package/src/settings/defs-editor.ts +93 -34
- package/src/settings/dependencies-editor.ts +7 -7
- package/src/settings/extension-sections.ts +37 -5
- package/src/settings/general-settings.ts +204 -121
- package/src/settings/locales-section.ts +347 -0
- package/src/settings/preferences-accounts.ts +140 -0
- package/src/settings/preferences-dialog.ts +620 -0
- package/src/settings/preferences-keymap.ts +270 -0
- package/src/settings/project-sections.ts +260 -0
- package/src/settings/section-registry.ts +169 -0
- package/src/settings/settings-document.ts +385 -0
- package/src/shell.ts +1549 -0
- package/src/site-context.ts +45 -20
- package/src/state.ts +14 -275
- package/src/store.ts +88 -43
- package/src/studio.ts +790 -346
- package/src/style/live-preview.ts +36 -0
- package/src/style/project-styles.ts +349 -0
- package/src/style/token-ref.ts +123 -0
- package/src/tabs/patch-ops.ts +16 -4
- package/src/tabs/project-config.ts +416 -0
- package/src/tabs/selection.ts +323 -0
- package/src/tabs/tab.ts +182 -47
- package/src/tabs/transact.ts +209 -28
- package/src/types.ts +68 -13
- package/src/ui/ai-credentials-form.ts +39 -35
- package/src/ui/ai-managed-connect.ts +7 -1
- package/src/ui/dynamic-slot.ts +224 -81
- package/src/ui/expression-editor.ts +71 -63
- package/src/ui/field-input.ts +4 -6
- package/src/ui/field-row.ts +215 -38
- package/src/ui/form-controls.ts +194 -7
- package/src/ui/layers.ts +492 -69
- package/src/ui/media-picker.ts +115 -25
- package/src/ui/panel-resize.ts +109 -91
- package/src/ui/progress-modal.ts +131 -50
- package/src/ui/regions.ts +462 -0
- package/src/ui/schema-form.ts +229 -45
- package/src/ui/spectrum.ts +24 -8
- package/src/ui/timing.ts +49 -0
- package/src/ui/value-selector.ts +20 -0
- package/src/ui/value-source.ts +348 -0
- package/src/ui/virtual-window.ts +400 -0
- package/src/utils/edit-display.ts +3 -2
- package/src/utils/inherited-style.ts +67 -37
- package/src/view.ts +64 -78
- package/src/workspace/pane-derive.ts +1258 -0
- package/src/workspace/session.ts +317 -0
- package/src/workspace/workspace.ts +1345 -23
- package/styles/canvas.css +653 -0
- package/styles/forced-colors.css +106 -0
- package/styles/inspector.css +1454 -0
- package/styles/overlays.css +2704 -0
- package/styles/panels.css +1701 -0
- package/styles/shell.css +1423 -0
- package/styles/tokens.css +151 -0
- package/dist/chunks/Overlay.dev-cszx7yn5.js +0 -22
- package/dist/chunks/extension-sections-qr3drkkw.js +0 -531
- package/dist/chunks/extension-sections-qr3drkkw.js.map +0 -12
- package/dist/chunks/files-j8a1t06k.js +0 -50
- package/dist/chunks/files-j8a1t06k.js.map +0 -9
- package/dist/chunks/git-panel-xtq5z81x.js +0 -28
- package/dist/chunks/git-panel-xtq5z81x.js.map +0 -9
- package/dist/chunks/layers-panel-ancn2wpq.js +0 -26
- package/dist/chunks/layers-panel-ancn2wpq.js.map +0 -9
- package/dist/chunks/settings-modal-17ttr96g.js +0 -29
- package/dist/chunks/settings-modal-17ttr96g.js.map +0 -9
- package/dist/chunks/sp-overlay.dev-earn5as8.js +0 -17
- package/dist/chunks/sp-overlay.dev-earn5as8.js.map +0 -9
- package/dist/chunks/sp-popover.dev-frxtfejn.js +0 -8
- package/dist/chunks/sp-popover.dev-frxtfejn.js.map +0 -9
- package/dist/chunks/sp-progress-circle.dev-7tvw34h8.js +0 -14
- package/dist/chunks/sp-progress-circle.dev-7tvw34h8.js.map +0 -9
- package/dist/chunks/sp-tooltip.dev-a9fywesm.js +0 -21
- package/dist/chunks/sp-tooltip.dev-a9fywesm.js.map +0 -10
- package/dist/chunks/studio-0xgs7xrs.js +0 -429
- package/dist/chunks/studio-0xgs7xrs.js.map +0 -13
- package/dist/chunks/studio-4d8hzcz5.js +0 -3427
- package/dist/chunks/studio-4d8hzcz5.js.map +0 -26
- package/dist/chunks/studio-4k0m4fmp.js.map +0 -13
- package/dist/chunks/studio-9smfzqhc.js +0 -19
- package/dist/chunks/studio-9smfzqhc.js.map +0 -10
- package/dist/chunks/studio-jm0z592w.js.map +0 -115
- package/dist/chunks/studio-m2t4mdg5.js +0 -1854
- package/dist/chunks/studio-m2t4mdg5.js.map +0 -18
- package/dist/chunks/studio-n4p11dfy.js +0 -853
- package/dist/chunks/studio-n4p11dfy.js.map +0 -12
- package/dist/chunks/studio-qkvt37c0.js.map +0 -9
- package/dist/chunks/studio-sjh1wt1a.js +0 -3744
- package/dist/chunks/studio-sjh1wt1a.js.map +0 -22
- package/dist/chunks/studio-v7jkjqng.js.map +0 -46
- package/dist/chunks/studio-xq0t7n5t.js +0 -140
- package/dist/chunks/studio-xq0t7n5t.js.map +0 -10
- package/dist/chunks/studio-xze4zrs1.js.map +0 -10
- package/dist/chunks/studio-yfcstdzy.js +0 -399
- package/dist/chunks/studio-yfcstdzy.js.map +0 -12
- package/dist/chunks/studio-zp7jncs8.js +0 -469
- package/dist/chunks/studio-zp7jncs8.js.map +0 -14
- package/dist/chunks/ws-client-q7hkz3j9.js.map +0 -11
- package/src/browse/browse-modal.ts +0 -69
- package/src/browse/browse.ts +0 -904
- package/src/canvas/canvas-diff.ts +0 -216
- package/src/canvas/nested-site-style.ts +0 -58
- package/src/new-project/design-fields.ts +0 -264
- package/src/new-project/templates.ts +0 -61
- package/src/panels/tab-bar.ts +0 -548
- package/src/settings/settings-modal.ts +0 -203
- /package/dist/chunks/{adapter-z8fkmbmv.js.map → adapter-qfnesn5v.js.map} +0 -0
- /package/dist/chunks/{cf-settings-mmyv436d.js.map → cf-settings-73sh5z4p.js.map} +0 -0
- /package/dist/chunks/{format-host-8jxwts2p.js.map → format-host-mkwsmt8d.js.map} +0 -0
- /package/dist/chunks/{jx-validate-qx8degj7.js.map → jx-validate-v6qgknrs.js.map} +0 -0
- /package/dist/chunks/{studio-w7c6kvk7.js.map → studio-a7pzveq1.js.map} +0 -0
- /package/dist/chunks/{studio-esrewxap.js.map → studio-s519zc99.js.map} +0 -0
- /package/dist/chunks/{studio-bghqfmea.js.map → studio-wwseqyw0.js.map} +0 -0
- /package/dist/chunks/{studio-nqw433kv.js.map → studio-xmvbhg31.js.map} +0 -0
package/src/site-context.ts
CHANGED
|
@@ -4,12 +4,16 @@
|
|
|
4
4
|
*
|
|
5
5
|
* When a project has a project.json, its $media and style cascade into every file. File-level
|
|
6
6
|
* definitions merge on top (file wins on conflict).
|
|
7
|
+
*
|
|
8
|
+
* @docs framework/site/i18n
|
|
7
9
|
*/
|
|
8
10
|
|
|
9
|
-
import { projectState
|
|
11
|
+
import { projectState } from "./store";
|
|
10
12
|
import { getPlatform } from "./platform";
|
|
11
|
-
import {
|
|
13
|
+
import { commitProjectConfig } from "./tabs/project-config";
|
|
12
14
|
|
|
15
|
+
import { resolveI18n } from "@jxsuite/schema/locale";
|
|
16
|
+
import type { ResolvedI18n } from "@jxsuite/schema/locale";
|
|
13
17
|
import type {
|
|
14
18
|
JxElement,
|
|
15
19
|
JxHeadEntry,
|
|
@@ -133,6 +137,27 @@ export function getEffectiveHead(docHead?: JxHeadEntry[]) {
|
|
|
133
137
|
return merged;
|
|
134
138
|
}
|
|
135
139
|
|
|
140
|
+
/**
|
|
141
|
+
* The project's resolved locales, or null when it declares none.
|
|
142
|
+
*
|
|
143
|
+
* The resolution is `@jxsuite/schema/locale`'s own — literally the function the compiler runs — so
|
|
144
|
+
* a tag Studio offers is a tag the build accepts, and the two cannot drift into disagreeing about
|
|
145
|
+
* what `EN-us` means or which locales exist.
|
|
146
|
+
*
|
|
147
|
+
* Errors are dropped here on purpose. Every helper in this file answers a render, and a render has
|
|
148
|
+
* nowhere to put a sentence; `settings/locales-section.ts` is where a malformed tag is refused with
|
|
149
|
+
* words, before it can reach the file.
|
|
150
|
+
*
|
|
151
|
+
* Called at render time rather than cached: `projectState` is a plain module-level binding replaced
|
|
152
|
+
* wholesale on a project switch, so a cached answer would outlive the project it described.
|
|
153
|
+
*
|
|
154
|
+
* @returns {ResolvedI18n | null}
|
|
155
|
+
*/
|
|
156
|
+
export function getEffectiveLocales(): ResolvedI18n | null {
|
|
157
|
+
const config = projectState?.projectConfig;
|
|
158
|
+
return config ? resolveI18n(config).i18n : null;
|
|
159
|
+
}
|
|
160
|
+
|
|
136
161
|
// ─── Layout resolution ──────────────────────────────────────────────────────
|
|
137
162
|
|
|
138
163
|
const layoutCache = new Map<string, JxMutableNode>();
|
|
@@ -259,26 +284,26 @@ function fillSlots(
|
|
|
259
284
|
}
|
|
260
285
|
|
|
261
286
|
/**
|
|
262
|
-
*
|
|
263
|
-
*
|
|
264
|
-
*
|
|
287
|
+
* Merge a partial patch into the project's configuration and persist it.
|
|
288
|
+
*
|
|
289
|
+
* The patch-shaped door onto `tabs/project-config.ts` — the single chokepoint every configuration
|
|
290
|
+
* write goes through. It used to serialize and write `project.json` itself, which is how this file
|
|
291
|
+
* came to hold one of the two serializations in play, and how ten call sites came to change the
|
|
292
|
+
* file that defines the project with no history behind them.
|
|
293
|
+
*
|
|
294
|
+
* **It still rejects.** `settings/general-settings.ts` and `settings/contexts-section.ts` catch the
|
|
295
|
+
* rejection and park it on the control that caused it (§7.1's inline tier), and that is the right
|
|
296
|
+
* treatment for a field the author is looking at. The chokepoint ALSO files the failure as a
|
|
297
|
+
* Problem, because the eight other sites reach this through `void updateSiteConfig(...)` and used
|
|
298
|
+
* to drop it on the floor.
|
|
265
299
|
*
|
|
266
|
-
* @param {Partial<ProjectConfig>} patch - Fields to merge into the current projectConfig
|
|
300
|
+
* @param {Partial<ProjectConfig>} patch - Fields to merge into the current projectConfig; a value
|
|
301
|
+
* of `undefined` clears the key.
|
|
302
|
+
* @throws {unknown} The platform's rejection, when the write fails.
|
|
267
303
|
*/
|
|
268
304
|
export async function updateSiteConfig(patch: Partial<ProjectConfig>) {
|
|
269
|
-
const
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
...patch,
|
|
273
|
-
} as ProjectConfig;
|
|
274
|
-
await platform.writeFile("project.json", JSON.stringify(config, null, 2));
|
|
275
|
-
setProjectState({ ...requireProjectState(), projectConfig: config });
|
|
276
|
-
setWorkspaceProject(workspace.projectRoot, config);
|
|
277
|
-
if ("extensions" in patch) {
|
|
278
|
-
const { loadFormats, refreshExtensionUi, refreshFormats } =
|
|
279
|
-
await import("./format/format-host");
|
|
280
|
-
refreshFormats();
|
|
281
|
-
void loadFormats();
|
|
282
|
-
refreshExtensionUi(platform);
|
|
305
|
+
const result = await commitProjectConfig(patch);
|
|
306
|
+
if (!result.ok) {
|
|
307
|
+
throw result.error;
|
|
283
308
|
}
|
|
284
309
|
}
|
package/src/state.ts
CHANGED
|
@@ -1,57 +1,22 @@
|
|
|
1
|
-
/// <reference lib="dom" />
|
|
2
1
|
/**
|
|
3
|
-
*
|
|
2
|
+
* Document paths, the tree walk over them, and the project record.
|
|
4
3
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* A `JxPath` addresses one node from the document root: `[]` is the root itself, `["children", 0]`
|
|
5
|
+
* its first child, `["children", 0, "children", 2]` that child's third. Every module that points at
|
|
6
|
+
* a node — selection, hover, the layers tree, a patch — spells it this way, which is why the
|
|
7
|
+
* comparison and ancestry predicates live here rather than beside any one of them.
|
|
7
8
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
9
|
+
* The editable document and its history belong to a TAB (`tabs/tab.ts`) and its session lives on
|
|
10
|
+
* the workspace; nothing here holds mutable document state. The one exception is `projectState`,
|
|
11
|
+
* which outlives every document because it describes the folder they all come from.
|
|
10
12
|
*/
|
|
11
13
|
|
|
12
14
|
import type { ProjectState } from "./types";
|
|
13
|
-
import { isRef } from "@jxsuite/schema/guards";
|
|
15
|
+
import { displayTagName, isRef } from "@jxsuite/schema/guards";
|
|
14
16
|
import type { JxMutableNode } from "@jxsuite/schema/types";
|
|
15
17
|
|
|
16
18
|
export type JxPath = (string | number)[];
|
|
17
19
|
|
|
18
|
-
interface HistorySnapshot {
|
|
19
|
-
document: JxMutableNode;
|
|
20
|
-
selection: JxPath | null;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface StudioState {
|
|
24
|
-
document: JxMutableNode;
|
|
25
|
-
selection: JxPath | null;
|
|
26
|
-
hover: JxPath | null;
|
|
27
|
-
history: HistorySnapshot[];
|
|
28
|
-
historyIndex: number;
|
|
29
|
-
dirty: boolean;
|
|
30
|
-
fileHandle: FileSystemFileHandle | null;
|
|
31
|
-
documentPath: string | null;
|
|
32
|
-
documentStack: StudioStackFrame[];
|
|
33
|
-
handlersSource: string | null;
|
|
34
|
-
mode: string;
|
|
35
|
-
content: { frontmatter: Record<string, unknown> };
|
|
36
|
-
ui: Record<string, unknown>;
|
|
37
|
-
canvas: {
|
|
38
|
-
status: string;
|
|
39
|
-
scope: Record<string, unknown> | null;
|
|
40
|
-
error: string | null;
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
interface StudioStackFrame {
|
|
45
|
-
document: JxMutableNode;
|
|
46
|
-
selection: JxPath | null;
|
|
47
|
-
fileHandle: FileSystemFileHandle | null;
|
|
48
|
-
documentPath: string | null;
|
|
49
|
-
dirty: boolean;
|
|
50
|
-
history: HistorySnapshot[];
|
|
51
|
-
historyIndex: number;
|
|
52
|
-
mode: string;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
20
|
// ─── Path utilities ───────────────────────────────────────────────────────────
|
|
56
21
|
|
|
57
22
|
/**
|
|
@@ -73,35 +38,6 @@ export function getNodeAtPath(doc: JxMutableNode, path: JxPath) {
|
|
|
73
38
|
return node;
|
|
74
39
|
}
|
|
75
40
|
|
|
76
|
-
/**
|
|
77
|
-
* Shallow-clone every node along `path` from root to target, leaving non-path subtrees as shared
|
|
78
|
-
* references. Returns the new root and the mutable target node at the end of the path.
|
|
79
|
-
*
|
|
80
|
-
* Used by mutation functions for structural-sharing history: the old root becomes an immutable
|
|
81
|
-
* snapshot (shared subtrees are never mutated), and the new root is the live document.
|
|
82
|
-
*/
|
|
83
|
-
export function cloneAlongPath(
|
|
84
|
-
doc: JxMutableNode,
|
|
85
|
-
path: JxPath,
|
|
86
|
-
): { root: JxMutableNode; target: JxMutableNode } {
|
|
87
|
-
const root = Array.isArray(doc) ? [...doc] : { ...doc };
|
|
88
|
-
let node: Record<string | number, unknown> = root as Record<string | number, unknown>;
|
|
89
|
-
|
|
90
|
-
for (const key of path) {
|
|
91
|
-
const child = node[key];
|
|
92
|
-
if (child == null) {
|
|
93
|
-
return { root: root as JxMutableNode, target: node as JxMutableNode };
|
|
94
|
-
}
|
|
95
|
-
const cloned = Array.isArray(child)
|
|
96
|
-
? [...(child as unknown[])]
|
|
97
|
-
: { ...(child as Record<string, unknown>) };
|
|
98
|
-
node[key] = cloned;
|
|
99
|
-
node = cloned as Record<string | number, unknown>;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return { root: root as JxMutableNode, target: node as JxMutableNode };
|
|
103
|
-
}
|
|
104
|
-
|
|
105
41
|
/**
|
|
106
42
|
* The node's children when they are a static array (the edit-mode invariant); an empty array for
|
|
107
43
|
* mapped-array or absent children.
|
|
@@ -300,7 +236,7 @@ function collectRows(
|
|
|
300
236
|
}
|
|
301
237
|
|
|
302
238
|
// Custom component instances without user-authored children are atomic in the layer tree
|
|
303
|
-
if (doc.$props && (doc.tagName
|
|
239
|
+
if (doc.$props && displayTagName(doc.tagName).includes("-") && !Array.isArray(doc.children)) {
|
|
304
240
|
return;
|
|
305
241
|
}
|
|
306
242
|
|
|
@@ -372,7 +308,10 @@ export function nodeLabel(node: JxMutableNode | null) {
|
|
|
372
308
|
const name = node.attributes?.name;
|
|
373
309
|
return typeof name === "string" && name.trim() ? `slot: ${name.trim()}` : "slot";
|
|
374
310
|
}
|
|
375
|
-
|
|
311
|
+
/* `displayTagName`, because a tag may be CHOSEN rather than written: this label reached the
|
|
312
|
+
Outline row, the Inspector's header and the jump bar, and a raw read rendered `[object Object]`
|
|
313
|
+
in all three. `a|div` is the honest answer — one element, tag decided at creation. */
|
|
314
|
+
const tag = displayTagName(node.tagName) || "div";
|
|
376
315
|
const suffix = node.$switch ? " ⇆" : "";
|
|
377
316
|
if (typeof node.textContent === "string" && node.textContent.length > 0) {
|
|
378
317
|
return `${tag} — ${node.textContent.slice(0, 24)}${suffix}`;
|
|
@@ -380,113 +319,6 @@ export function nodeLabel(node: JxMutableNode | null) {
|
|
|
380
319
|
return tag + suffix;
|
|
381
320
|
}
|
|
382
321
|
|
|
383
|
-
// ─── State factory ────────────────────────────────────────────────────────────
|
|
384
|
-
|
|
385
|
-
/**
|
|
386
|
-
* @param {JxMutableNode} doc
|
|
387
|
-
* @returns {StudioState}
|
|
388
|
-
*/
|
|
389
|
-
export function createState(doc: JxMutableNode): StudioState {
|
|
390
|
-
const initial = { document: doc, selection: null };
|
|
391
|
-
return {
|
|
392
|
-
canvas: {
|
|
393
|
-
error: null, // Error message on failure
|
|
394
|
-
scope: null, // $defs scope from runtime buildScope
|
|
395
|
-
status: "idle", // "idle" | "loading" | "ready" | "error"
|
|
396
|
-
},
|
|
397
|
-
content: { frontmatter: {} }, // Frontmatter metadata for .md files
|
|
398
|
-
dirty: false,
|
|
399
|
-
document: doc,
|
|
400
|
-
documentPath: null, // Root-relative path, e.g. "examples/markdown/blog.json"
|
|
401
|
-
documentStack: [], // Frames for component navigation
|
|
402
|
-
fileHandle: null,
|
|
403
|
-
handlersSource: null,
|
|
404
|
-
history: [initial],
|
|
405
|
-
historyIndex: 0,
|
|
406
|
-
hover: null,
|
|
407
|
-
mode: "component", // 'component' | 'content'
|
|
408
|
-
selection: null,
|
|
409
|
-
ui: {
|
|
410
|
-
activeMedia: null, // '--md' | null (base) — focused canvas/breakpoint
|
|
411
|
-
activeSelector: null, // ':hover' | '.child' | null (base) — nested selector context
|
|
412
|
-
editingFunction: null, // Null | { type: 'def', defName } | { type: 'event', path, eventKey }
|
|
413
|
-
featureToggles: {}, // { '--dark': true } — non-size media toggles
|
|
414
|
-
gitBranches: null, // { current, branches: [] }
|
|
415
|
-
gitCommitMessage: "", // Commit message input
|
|
416
|
-
gitDiffState: null,
|
|
417
|
-
gitError: null, // Error message string
|
|
418
|
-
gitLoading: false, // Loading indicator during async ops
|
|
419
|
-
gitStatus: null, // { branch, ahead, behind, files: [] }
|
|
420
|
-
inspectorSections: {}, // { identity: true, ... } — properties panel section open/closed state
|
|
421
|
-
pendingInlineEdit: null, // Null | { path, mediaName } — deferred inline edit awaiting canvas readiness
|
|
422
|
-
rightTab: "properties", // 'properties' | 'events' | 'style'
|
|
423
|
-
settingsTab: "stylebook", // "stylebook" | "definitions" | "contentTypes"
|
|
424
|
-
styleFilter: "", // Free-text filter for CSS property names
|
|
425
|
-
styleFilterActive: false, // True = show only props with values set
|
|
426
|
-
styleSections: {}, // { layout: true, ... } — section open/closed state
|
|
427
|
-
styleShorthands: {}, // { padding: true, ... } — shorthand expand/collapse state
|
|
428
|
-
stylebookCustomizedOnly: false, // Show only customized elements
|
|
429
|
-
stylebookFilter: "", // Search filter text
|
|
430
|
-
stylebookSelection: null, // Tag name string, e.g. "h1"
|
|
431
|
-
stylebookTab: "elements", // "elements" | "variables"
|
|
432
|
-
zoom: 1,
|
|
433
|
-
},
|
|
434
|
-
};
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
// ─── Doc/Session slice helpers ───────────────────────────────────────────────
|
|
438
|
-
|
|
439
|
-
/**
|
|
440
|
-
* Compose a flat StudioState from separate doc and session slices.
|
|
441
|
-
*
|
|
442
|
-
* @param {Partial<StudioState>} doc
|
|
443
|
-
* @param {Partial<StudioState>} session
|
|
444
|
-
* @returns {StudioState}
|
|
445
|
-
*/
|
|
446
|
-
export function toFlat(doc: Partial<StudioState>, session: Partial<StudioState>) {
|
|
447
|
-
return { ...doc, ...session } as StudioState;
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
/**
|
|
451
|
-
* Decompose a flat StudioState into doc and session slices.
|
|
452
|
-
*
|
|
453
|
-
* @param {StudioState} S
|
|
454
|
-
* @returns {{ doc: Partial<StudioState>; session: Partial<StudioState> }}
|
|
455
|
-
*/
|
|
456
|
-
export function fromFlat(S: StudioState) {
|
|
457
|
-
const {
|
|
458
|
-
document,
|
|
459
|
-
dirty,
|
|
460
|
-
fileHandle,
|
|
461
|
-
documentPath,
|
|
462
|
-
documentStack,
|
|
463
|
-
handlersSource,
|
|
464
|
-
mode,
|
|
465
|
-
content,
|
|
466
|
-
history,
|
|
467
|
-
historyIndex,
|
|
468
|
-
selection,
|
|
469
|
-
hover,
|
|
470
|
-
ui,
|
|
471
|
-
canvas,
|
|
472
|
-
} = S;
|
|
473
|
-
return {
|
|
474
|
-
doc: {
|
|
475
|
-
content,
|
|
476
|
-
dirty,
|
|
477
|
-
document,
|
|
478
|
-
documentPath,
|
|
479
|
-
documentStack,
|
|
480
|
-
fileHandle,
|
|
481
|
-
handlersSource,
|
|
482
|
-
history,
|
|
483
|
-
historyIndex,
|
|
484
|
-
mode,
|
|
485
|
-
},
|
|
486
|
-
session: { canvas, hover, selection, ui },
|
|
487
|
-
};
|
|
488
|
-
}
|
|
489
|
-
|
|
490
322
|
// ─── Project state (persists across document switches) ────────────────────────
|
|
491
323
|
//
|
|
492
324
|
// Shape: { root, name, projectRoot, isSiteProject, projectConfig,
|
|
@@ -510,96 +342,3 @@ export function setProjectState(ps: ProjectState | null) {
|
|
|
510
342
|
export function requireProjectState() {
|
|
511
343
|
return projectState as ProjectState;
|
|
512
344
|
}
|
|
513
|
-
|
|
514
|
-
// ─── Frontmatter mutation ───────────────────────────────────────────────────
|
|
515
|
-
|
|
516
|
-
/**
|
|
517
|
-
* Update a frontmatter field. Does not use applyMutation because frontmatter lives in S.content,
|
|
518
|
-
* not S.document.
|
|
519
|
-
*
|
|
520
|
-
* @param {StudioState} state
|
|
521
|
-
* @param {string} field
|
|
522
|
-
* @param {unknown} value
|
|
523
|
-
* @returns {StudioState}
|
|
524
|
-
*/
|
|
525
|
-
export function updateFrontmatter(state: StudioState, field: string, value: unknown) {
|
|
526
|
-
const fm = { ...state.content?.frontmatter };
|
|
527
|
-
if (value === undefined || value === null || value === "") {
|
|
528
|
-
delete fm[field];
|
|
529
|
-
} else {
|
|
530
|
-
fm[field] = value;
|
|
531
|
-
}
|
|
532
|
-
return {
|
|
533
|
-
...state,
|
|
534
|
-
content: { ...state.content, frontmatter: fm },
|
|
535
|
-
dirty: true,
|
|
536
|
-
};
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
// ─── Selection / hover ────────────────────────────────────────────────────────
|
|
540
|
-
|
|
541
|
-
/**
|
|
542
|
-
* @param {StudioState} state
|
|
543
|
-
* @param {JxPath | null} path
|
|
544
|
-
* @returns {StudioState}
|
|
545
|
-
*/
|
|
546
|
-
export function selectNode(state: StudioState, path: JxPath | null) {
|
|
547
|
-
return { ...state, selection: path };
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
/**
|
|
551
|
-
* @param {StudioState} state
|
|
552
|
-
* @param {JxPath | null} path
|
|
553
|
-
* @returns {StudioState}
|
|
554
|
-
*/
|
|
555
|
-
export function hoverNode(state: StudioState, path: JxPath | null) {
|
|
556
|
-
return { ...state, hover: path };
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
// ─── Document stack (component navigation) ──────────────────────────────────
|
|
560
|
-
|
|
561
|
-
/**
|
|
562
|
-
* Push current document onto the stack and switch to editing a new document.
|
|
563
|
-
*
|
|
564
|
-
* @param {StudioState} state
|
|
565
|
-
* @param {JxMutableNode} doc
|
|
566
|
-
* @param {string | null} documentPath
|
|
567
|
-
* @returns {StudioState}
|
|
568
|
-
*/
|
|
569
|
-
export function pushDocument(state: StudioState, doc: JxMutableNode, documentPath: string | null) {
|
|
570
|
-
const frame = {
|
|
571
|
-
dirty: state.dirty,
|
|
572
|
-
document: state.document,
|
|
573
|
-
documentPath: state.documentPath,
|
|
574
|
-
fileHandle: state.fileHandle,
|
|
575
|
-
history: state.history,
|
|
576
|
-
historyIndex: state.historyIndex,
|
|
577
|
-
mode: state.mode,
|
|
578
|
-
selection: state.selection,
|
|
579
|
-
};
|
|
580
|
-
const newState = createState(doc);
|
|
581
|
-
newState.documentStack = [...(state.documentStack || []), frame];
|
|
582
|
-
newState.documentPath = documentPath;
|
|
583
|
-
newState.ui = { ...state.ui, activeMedia: null, activeSelector: null };
|
|
584
|
-
return newState;
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
/**
|
|
588
|
-
* Pop the document stack and return to the previous document.
|
|
589
|
-
*
|
|
590
|
-
* @param {StudioState} state
|
|
591
|
-
* @returns {StudioState}
|
|
592
|
-
*/
|
|
593
|
-
export function popDocument(state: StudioState) {
|
|
594
|
-
if (!state.documentStack || state.documentStack.length === 0) {
|
|
595
|
-
return state;
|
|
596
|
-
}
|
|
597
|
-
const stack = [...state.documentStack];
|
|
598
|
-
const frame = stack.pop();
|
|
599
|
-
return {
|
|
600
|
-
...state,
|
|
601
|
-
...frame,
|
|
602
|
-
documentStack: stack,
|
|
603
|
-
ui: { ...state.ui },
|
|
604
|
-
};
|
|
605
|
-
}
|
package/src/store.ts
CHANGED
|
@@ -9,13 +9,12 @@
|
|
|
9
9
|
|
|
10
10
|
// ─── Re-exports from state.js ────────────────────────────────────────────────
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import { INPUT_DEBOUNCE } from "./ui/timing";
|
|
13
13
|
import type { JxPath } from "./state";
|
|
14
|
+
import type { Tab } from "./tabs/tab";
|
|
14
15
|
import type { JxMutableNode } from "@jxsuite/schema/types";
|
|
15
|
-
import type { CanvasPanel } from "./types";
|
|
16
16
|
|
|
17
17
|
export {
|
|
18
|
-
createState,
|
|
19
18
|
getNodeAtPath,
|
|
20
19
|
childList,
|
|
21
20
|
flattenTree,
|
|
@@ -28,35 +27,29 @@ export {
|
|
|
28
27
|
projectState,
|
|
29
28
|
setProjectState,
|
|
30
29
|
requireProjectState,
|
|
31
|
-
updateFrontmatter,
|
|
32
30
|
} from "./state";
|
|
33
31
|
|
|
34
32
|
// ─── Shell element refs (populated by initShellRefs) ─────────────────────────
|
|
35
33
|
|
|
36
|
-
|
|
34
|
+
/* There is no `canvasWrap` here, and there cannot be one.
|
|
35
|
+
It was `#canvas-wrap`, the shell's single stage, imported by six modules and read at ~30 sites —
|
|
36
|
+
each of which meant "the pane I am acting on" and got "the pane that happens to be focused". A
|
|
37
|
+
stage belongs to a pane (`canvas/canvas-surface.ts`), a pane's cell is built by
|
|
38
|
+
`panels/pane-grid.ts`, and every one of those readers now takes its surface. */
|
|
37
39
|
export let activityBar = null as unknown as HTMLElement;
|
|
38
40
|
export let leftPanel = null as unknown as HTMLElement;
|
|
39
41
|
export let rightPanel = null as unknown as HTMLElement;
|
|
40
|
-
export let chatPanelEl = null as unknown as HTMLElement;
|
|
41
42
|
export let toolbarEl = null as unknown as HTMLElement;
|
|
42
43
|
export let statusbarEl = null as unknown as HTMLElement;
|
|
43
|
-
export let frontmatterPanelEl = null as unknown as HTMLElement;
|
|
44
44
|
|
|
45
45
|
export function initShellRefs() {
|
|
46
|
-
canvasWrap = document.querySelector("#canvas-wrap") as HTMLElement;
|
|
47
46
|
activityBar = document.querySelector("#activity-bar") as HTMLElement;
|
|
48
47
|
leftPanel = document.querySelector("#left-panel") as HTMLElement;
|
|
49
48
|
rightPanel = document.querySelector("#right-panel") as HTMLElement;
|
|
50
|
-
chatPanelEl = document.querySelector("#chat-panel") as HTMLElement;
|
|
51
49
|
toolbarEl = document.querySelector("#toolbar") as HTMLElement;
|
|
52
50
|
statusbarEl = document.querySelector("#statusbar") as HTMLElement;
|
|
53
|
-
frontmatterPanelEl = document.querySelector("#frontmatter-panel") as HTMLElement;
|
|
54
51
|
}
|
|
55
52
|
|
|
56
|
-
// ─── Shared containers (mutated in place by owner modules) ───────────────────
|
|
57
|
-
|
|
58
|
-
export const canvasPanels: CanvasPanel[] = [];
|
|
59
|
-
|
|
60
53
|
// ─── Shared constants ────────────────────────────────────────────────────────
|
|
61
54
|
|
|
62
55
|
/** Void elements that cannot accept children */
|
|
@@ -102,14 +95,15 @@ const _styleDebounceTimers = new Map<string, ReturnType<typeof setTimeout>>();
|
|
|
102
95
|
|
|
103
96
|
/**
|
|
104
97
|
* @param {string} prop
|
|
105
|
-
* @param {number} ms
|
|
98
|
+
* @param {number | undefined} ms Debounce delay; `undefined` takes the standard input debounce.
|
|
106
99
|
* @param {(...args: unknown[]) => void} fn
|
|
107
100
|
*/
|
|
108
101
|
export function debouncedStyleCommit<A extends unknown[]>(
|
|
109
102
|
prop: string,
|
|
110
|
-
ms: number,
|
|
103
|
+
ms: number | undefined,
|
|
111
104
|
fn: (...args: A) => void,
|
|
112
105
|
) {
|
|
106
|
+
const delay = ms ?? INPUT_DEBOUNCE;
|
|
113
107
|
return (...args: A) => {
|
|
114
108
|
clearTimeout(_styleDebounceTimers.get(prop));
|
|
115
109
|
_styleDebounceTimers.set(
|
|
@@ -117,7 +111,7 @@ export function debouncedStyleCommit<A extends unknown[]>(
|
|
|
117
111
|
setTimeout(() => {
|
|
118
112
|
_styleDebounceTimers.delete(prop);
|
|
119
113
|
fn(...args);
|
|
120
|
-
},
|
|
114
|
+
}, delay),
|
|
121
115
|
);
|
|
122
116
|
};
|
|
123
117
|
}
|
|
@@ -136,6 +130,47 @@ export { stripEventHandlers } from "./utils/strip-events";
|
|
|
136
130
|
|
|
137
131
|
const _renderers = new Map<string, () => void>();
|
|
138
132
|
|
|
133
|
+
/**
|
|
134
|
+
* How many registered renderers are mid-paint right now.
|
|
135
|
+
*
|
|
136
|
+
* Condition 1 of the `probe.idle()` predicate (`services/idle.ts`, spec §13.5). A renderer is
|
|
137
|
+
* declared `() => void`, but TypeScript happily assigns an `async` function to that type, so a
|
|
138
|
+
* renderer that awaits keeps repainting long after `render()` returned. Counting the returned
|
|
139
|
+
* thenable is what makes "no queued lit render" an answerable question instead of an assumption —
|
|
140
|
+
* the alternative is a sleep, and a sleep cannot name what it is waiting for.
|
|
141
|
+
*/
|
|
142
|
+
let _rendersInFlight = 0;
|
|
143
|
+
|
|
144
|
+
/** Renderers currently mid-paint — zero when the shell's DOM has caught up with its state. */
|
|
145
|
+
export function rendersInFlight(): number {
|
|
146
|
+
return _rendersInFlight;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** Run one renderer, counting it as in-flight until it returns (or its promise settles). */
|
|
150
|
+
function runRenderer(name: string, fn: () => void) {
|
|
151
|
+
_rendersInFlight += 1;
|
|
152
|
+
const done = () => {
|
|
153
|
+
_rendersInFlight -= 1;
|
|
154
|
+
};
|
|
155
|
+
let pending: PromiseLike<unknown> | null = null;
|
|
156
|
+
try {
|
|
157
|
+
const result = fn() as unknown;
|
|
158
|
+
if (typeof (result as PromiseLike<unknown> | null)?.then === "function") {
|
|
159
|
+
pending = result as PromiseLike<unknown>;
|
|
160
|
+
}
|
|
161
|
+
} catch (error) {
|
|
162
|
+
console.error(`Renderer "${name}" failed:`, error);
|
|
163
|
+
}
|
|
164
|
+
if (!pending) {
|
|
165
|
+
done();
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
pending.then(done, (error: unknown) => {
|
|
169
|
+
console.error(`Renderer "${name}" failed:`, error);
|
|
170
|
+
done();
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
139
174
|
/**
|
|
140
175
|
* Register a named renderer. Called at module import time by each module.
|
|
141
176
|
*
|
|
@@ -149,11 +184,7 @@ export function registerRenderer(name: string, fn: () => void) {
|
|
|
149
184
|
/** Call all registered renderers (full repaint). */
|
|
150
185
|
export function render() {
|
|
151
186
|
for (const [name, fn] of _renderers.entries()) {
|
|
152
|
-
|
|
153
|
-
fn();
|
|
154
|
-
} catch (error) {
|
|
155
|
-
console.error(`Renderer "${name}" failed:`, error);
|
|
156
|
-
}
|
|
187
|
+
runRenderer(name, fn);
|
|
157
188
|
}
|
|
158
189
|
}
|
|
159
190
|
|
|
@@ -168,32 +199,46 @@ export function renderOnly(...names: string[]) {
|
|
|
168
199
|
if (!fn) {
|
|
169
200
|
continue;
|
|
170
201
|
}
|
|
171
|
-
|
|
172
|
-
fn();
|
|
173
|
-
} catch (error) {
|
|
174
|
-
console.error(`Renderer "${name}" failed:`, error);
|
|
175
|
-
}
|
|
202
|
+
runRenderer(name, fn);
|
|
176
203
|
}
|
|
177
204
|
}
|
|
178
205
|
|
|
179
206
|
// ─── Session dispatch ──────────────────────────────────────────────────────
|
|
180
207
|
|
|
208
|
+
/* **Every dispatcher below takes the tab it writes, and none of them can find one on its own.**
|
|
209
|
+
All three used to open with `const tab = activeTab.value`, which made "the document this
|
|
210
|
+
control is about" and "the document the keyboard happens to be in" the same expression — the
|
|
211
|
+
defect that produced the Document Header card writing through focus, the zoom axis writing
|
|
212
|
+
through focus, the debounced Monaco commit writing through focus, and the whole pane context
|
|
213
|
+
bar writing through focus. Four instances, four audits, no gate: while the shell had one stage
|
|
214
|
+
the two readings could not disagree, so nothing could observe the difference.
|
|
215
|
+
|
|
216
|
+
`store.ts` is where they could not disagree, so `store.ts` is where the shape is fixed. There is
|
|
217
|
+
no `activeTab` import in this file and no zero-argument variant of any of these: a caller that
|
|
218
|
+
means the focused pane spells `activeTab.value` at its own call site, where a reviewer and
|
|
219
|
+
`scripts/check-pane-singletons.ts` can both see it, and a caller drawn FOR a pane passes the tab
|
|
220
|
+
it was drawn for. */
|
|
221
|
+
|
|
181
222
|
/**
|
|
182
|
-
* Dispatch a session-only state update (selection, hover, ui)
|
|
223
|
+
* Dispatch a session-only state update (selection, hover, ui) into `tab`.
|
|
183
224
|
*
|
|
225
|
+
* @param {Tab | null} tab — the tab this update is about. `null` is a no-op.
|
|
184
226
|
* @param {object} patch — partial session object, e.g. { ui: { zoom: 2 } }
|
|
185
227
|
*/
|
|
186
|
-
export function updateSession(
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
228
|
+
export function updateSession(
|
|
229
|
+
tab: Tab | null,
|
|
230
|
+
patch: {
|
|
231
|
+
/** The whole selection SET — `[]` clears it. Widened with `session.selection` itself (§6.5). */
|
|
232
|
+
selection?: JxPath[];
|
|
233
|
+
hover?: JxPath | null;
|
|
234
|
+
clipboard?: JxMutableNode | null;
|
|
235
|
+
ui?: Record<string, unknown>;
|
|
236
|
+
canvas?: Record<string, unknown>;
|
|
237
|
+
},
|
|
238
|
+
) {
|
|
194
239
|
if (tab) {
|
|
195
240
|
if (patch.selection !== undefined) {
|
|
196
|
-
tab.session.selection = patch.selection
|
|
241
|
+
tab.session.selection = patch.selection;
|
|
197
242
|
}
|
|
198
243
|
if (patch.hover !== undefined) {
|
|
199
244
|
tab.session.hover = patch.hover as JxPath | null;
|
|
@@ -215,25 +260,25 @@ export function updateSession(patch: {
|
|
|
215
260
|
}
|
|
216
261
|
|
|
217
262
|
/**
|
|
218
|
-
* Update a single UI field
|
|
263
|
+
* Update a single UI field on `tab`.
|
|
219
264
|
*
|
|
265
|
+
* @param {Tab | null} tab — the tab this field belongs to. `null` is a no-op.
|
|
220
266
|
* @param {string} field
|
|
221
267
|
* @param {unknown} value
|
|
222
268
|
*/
|
|
223
|
-
export function updateUi(field: string, value: unknown) {
|
|
224
|
-
const tab = activeTab.value;
|
|
269
|
+
export function updateUi(tab: Tab | null, field: string, value: unknown) {
|
|
225
270
|
if (tab) {
|
|
226
271
|
(tab.session.ui as unknown as Record<string, unknown>)[field] = value;
|
|
227
272
|
}
|
|
228
273
|
}
|
|
229
274
|
|
|
230
275
|
/**
|
|
231
|
-
* Update
|
|
276
|
+
* Update `tab`'s canvas async state (status, scope, error).
|
|
232
277
|
*
|
|
278
|
+
* @param {Tab | null} tab — the tab whose stage produced this state. `null` is a no-op.
|
|
233
279
|
* @param {object} patch
|
|
234
280
|
*/
|
|
235
|
-
export function updateCanvas(patch: Record<string, unknown>) {
|
|
236
|
-
const tab = activeTab.value;
|
|
281
|
+
export function updateCanvas(tab: Tab | null, patch: Record<string, unknown>) {
|
|
237
282
|
if (tab) {
|
|
238
283
|
for (const [k, v] of Object.entries(patch)) {
|
|
239
284
|
(tab.session.canvas as Record<string, unknown>)[k] = v;
|