@jxsuite/studio 6.1.0 → 6.1.2
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/dist/chunks/2020-f2gkpy8d.js +4 -0
- package/dist/chunks/{action-group-2mqby73c.js → action-group-4aan7g6g.js} +3 -3
- package/dist/chunks/adapter-4912g339.js +4 -0
- package/dist/chunks/cf-account-picker-wccaenh6.js +4 -0
- package/dist/chunks/cf-settings-br6105tr.js +4 -0
- package/dist/chunks/color-28ksk2qm.js +4 -0
- package/dist/chunks/color-area-0fj8a4ga.js +4 -0
- package/dist/chunks/color-field-xch8kx2g.js +4 -0
- package/dist/chunks/color-slider-jxd8v350.js +4 -0
- package/dist/chunks/combobox-p0efwjke.js +4 -0
- package/dist/chunks/components-db68vsn7.js +4 -0
- package/dist/chunks/content-source-1449qesq.js +4 -0
- package/dist/chunks/convert-to-repeater-5h457egj.js +4 -0
- package/dist/chunks/dialog-c4x05vyx.js +4 -0
- package/dist/chunks/editor-x9jn86a7.js +4 -0
- package/dist/chunks/entry-commands-may24cpt.js +4 -0
- package/dist/chunks/extension-sections-pvr14vxr.js +4 -0
- package/dist/chunks/file-ops-x9v54pcj.js +4 -0
- package/dist/chunks/files-j3knqf0s.js +4 -0
- package/dist/chunks/format-host-tyre2trb.js +4 -0
- package/dist/chunks/fs-events-64ma9htc.js +4 -0
- package/dist/chunks/git-panel-84ps5dex.js +4 -0
- package/dist/chunks/grid-view-d2wq9ezg.js +51 -0
- package/dist/chunks/icons-pnfz478q.js +4 -0
- package/dist/chunks/iframe-entry-fvbk89gm.js +5 -0
- package/dist/chunks/iframe-entry-jdcktez8.js +5 -0
- package/dist/chunks/iframe-entry-x0ygf2yr.js +5 -0
- package/dist/chunks/iframe-entry-zap785cw.js +5 -0
- package/dist/chunks/iframe-host-ck6vejt5.js +4 -0
- package/dist/chunks/index-b8xw3vy9.js +4 -0
- package/dist/chunks/{index-gybvv7a6.js → index-zpjmzqfk.js} +3 -3
- package/dist/chunks/{javascript-rnvdp3k4.js → javascript-m54mnwp6.js} +3 -3
- package/dist/chunks/jsonMode-w15cmrcm.js +13 -0
- package/dist/chunks/jx-validate-at3zn8wa.js +4 -0
- package/dist/chunks/layers-h4xp1pss.js +4 -0
- package/dist/chunks/layers-panel-m5hw1d7g.js +4 -0
- package/dist/chunks/listbox-e74qjyq6.js +4 -0
- package/dist/chunks/lit-html-8t8t3dnr.js +4 -0
- package/dist/chunks/media-picker-2cweexc5.js +4 -0
- package/dist/chunks/menu-n6yzswmy.js +4 -0
- package/dist/chunks/menu-ynw13y0s.js +4 -0
- package/dist/chunks/monaco-binding-7gx83x3r.js +4 -0
- package/dist/chunks/monaco-buffer-qzxn567r.js +4 -0
- package/dist/chunks/monaco-setup-gxf6656g.js +4 -0
- package/dist/chunks/notify-cj5zbrs2.js +4 -0
- package/dist/chunks/number-field-y62xq0ty.js +4 -0
- package/dist/chunks/parse-b7ddhr8m.js +4 -0
- package/dist/chunks/platform-3dfws9js.js +4 -0
- package/dist/chunks/popover-jt2gxmzs.js +4 -0
- package/dist/chunks/publish-panel-1gvxbj21.js +4 -0
- package/dist/chunks/quick-search-0dajrwqg.js +4 -0
- package/dist/chunks/references-49qgt404.js +4 -0
- package/dist/chunks/right-panel-jm1bwe53.js +4 -0
- package/dist/chunks/section-registry-6kwc4fky.js +4 -0
- package/dist/chunks/select-rzds841e.js +4 -0
- package/dist/chunks/split-n2gfpm5m.js +4 -0
- package/dist/chunks/{studio-5g0ag7c0.js → studio-0q988f9w.js} +3 -3
- package/dist/chunks/studio-0rt52vpq.js +5 -0
- package/dist/chunks/studio-18vgbhs5.js +5 -0
- package/dist/chunks/{studio-pxg4ap1e.js → studio-1fxkaaea.js} +4 -4
- package/dist/chunks/studio-24mccdrj.js +5 -0
- package/dist/chunks/studio-2eh507zk.js +9 -0
- package/dist/chunks/studio-2hcbccfv.js +5 -0
- package/dist/chunks/studio-2j1cb95x.js +5 -0
- package/dist/chunks/studio-2jbs3rxv.js +5 -0
- package/dist/chunks/{studio-qbj760tx.js → studio-485046te.js} +7 -7
- package/dist/chunks/studio-4h8k4dw9.js +5 -0
- package/dist/chunks/studio-5f6n18kx.js +5 -0
- package/dist/chunks/studio-5gthpky6.js +5 -0
- package/dist/chunks/studio-5ve6bbep.js +5 -0
- package/dist/chunks/studio-6ep3js6b.js +9 -0
- package/dist/chunks/studio-6wkmf3wz.js +9 -0
- package/dist/chunks/studio-841rf3cg.js +5 -0
- package/dist/chunks/studio-8gmwgheg.js +5 -0
- package/dist/chunks/studio-8qm0ep50.js +5 -0
- package/dist/chunks/{studio-anyrgzvb.js → studio-90pq9km1.js} +4 -4
- package/dist/chunks/studio-924p1tm1.js +6 -0
- package/dist/chunks/{studio-v2bvmbjj.js → studio-a3g98wjr.js} +4 -4
- package/dist/chunks/studio-a3shpz9y.js +5 -0
- package/dist/chunks/studio-amsbaaar.js +6 -0
- package/dist/chunks/studio-at5spjbc.js +7 -0
- package/dist/chunks/studio-b2xv945e.js +5 -0
- package/dist/chunks/studio-bn5nkafw.js +5 -0
- package/dist/chunks/studio-bw6q5xjf.js +9 -0
- package/dist/chunks/studio-c7q0t9x1.js +5 -0
- package/dist/chunks/studio-camnhc96.js +6 -0
- package/dist/chunks/studio-cffqvnzd.js +5 -0
- package/dist/chunks/studio-d81xfh1g.js +5 -0
- package/dist/chunks/studio-dgz8d0c1.js +5 -0
- package/dist/chunks/studio-efvfrsf8.js +5 -0
- package/dist/chunks/studio-er30bpcx.js +5 -0
- package/dist/chunks/studio-ezscgr64.js +5 -0
- package/dist/chunks/studio-ffrrncvz.js +5 -0
- package/dist/chunks/studio-fpphgn8y.js +10 -0
- package/dist/chunks/studio-j1kvhdjk.js +4 -0
- package/dist/chunks/{studio-txjjzrsm.js → studio-j430n16g.js} +5 -5
- package/dist/chunks/studio-jjkg84nj.js +5 -0
- package/dist/chunks/studio-m0q32ars.js +4 -0
- package/dist/chunks/studio-m6bdst11.js +5 -0
- package/dist/chunks/studio-nv2cptd4.js +64 -0
- package/dist/chunks/studio-nwfrc98n.js +5 -0
- package/dist/chunks/studio-p1wgvp7r.js +5 -0
- package/dist/chunks/studio-pag2wncm.js +5 -0
- package/dist/chunks/studio-qvanvzfd.js +5 -0
- package/dist/chunks/studio-qwa64kt7.js +5 -0
- package/dist/chunks/studio-rk1zc4x3.js +928 -0
- package/dist/chunks/studio-se2r3ptc.js +5 -0
- package/dist/chunks/studio-sg2a0dh0.js +5 -0
- package/dist/chunks/studio-tjzjhe68.js +5 -0
- package/dist/chunks/{studio-0x3jyb8r.js → studio-tq0rtfwj.js} +4 -4
- package/dist/chunks/{studio-cpxkgjrj.js → studio-v0jzqdjm.js} +4 -4
- package/dist/chunks/studio-v2w7q8r1.js +7 -0
- package/dist/chunks/studio-v5vjq1h0.js +4 -0
- package/dist/chunks/studio-v8aga3vp.js +14 -0
- package/dist/chunks/studio-vfcdrfmv.js +5 -0
- package/dist/chunks/studio-vmfkgdjf.js +5 -0
- package/dist/chunks/studio-wt1816jj.js +5 -0
- package/dist/chunks/studio-wz73q5kq.js +4 -0
- package/dist/chunks/studio-y04qtxvp.js +7 -0
- package/dist/chunks/studio-y21g8zzg.js +5 -0
- package/dist/chunks/studio-y64hrt8p.js +12 -0
- package/dist/chunks/studio-ynn90f58.js +16 -0
- package/dist/chunks/studio-yxz682sx.js +5 -0
- package/dist/chunks/studio-zp7snvkq.js +5 -0
- package/dist/chunks/studio-zq4z6tm6.js +5 -0
- package/dist/chunks/swatch-group-ewh24n1f.js +4 -0
- package/dist/chunks/tabs-f5cw3tgp.js +4 -0
- package/dist/chunks/textfield-wewc8rq2.js +4 -0
- package/dist/chunks/toast-c9fn075p.js +4 -0
- package/dist/chunks/toast-host-ke5z4ng7.js +4 -0
- package/dist/chunks/{toolbar-2nnzqhrj.js → toolbar-44cm5cta.js} +3 -3
- package/dist/chunks/tooltip-5v8ngwj2.js +4 -0
- package/dist/chunks/tree-mdq3v5cw.js +4 -0
- package/dist/chunks/tsMode-sf49ee9x.js +14 -0
- package/dist/chunks/workspace-jtfahpee.js +4 -0
- package/dist/chunks/ws-client-nze0k6mv.js +4 -0
- package/dist/iframe-entry.js +16 -16
- package/dist/manifest.json +63 -63
- package/dist/studio.js +98 -98
- package/dist/workers/ts.worker.js +3 -3
- package/package.json +11 -11
- package/src/about/about-modal.ts +4 -3
- package/src/account/action-flow.ts +45 -38
- package/src/account-status.ts +7 -2
- package/src/browse/library-layouts.ts +8 -5
- package/src/browse/library-model.ts +18 -6
- package/src/browse/library-pane.ts +37 -21
- package/src/browse/library-preview.ts +14 -9
- package/src/browse/library-source.ts +1 -1
- package/src/canvas/asset-refs.ts +24 -9
- package/src/canvas/asset-resolve.ts +19 -23
- package/src/canvas/canvas-helpers.ts +7 -6
- package/src/canvas/canvas-live-render.ts +44 -53
- package/src/canvas/canvas-patcher.ts +30 -30
- package/src/canvas/canvas-perf.ts +11 -5
- package/src/canvas/canvas-render.ts +66 -42
- package/src/canvas/canvas-surface.ts +5 -3
- package/src/canvas/canvas-utils.ts +163 -64
- package/src/canvas/dialog-path.ts +9 -4
- package/src/canvas/dialog-state.ts +1 -2
- package/src/canvas/diff-marks.ts +9 -16
- package/src/canvas/diff-toolbar.ts +8 -7
- package/src/canvas/edit-width-drag.ts +4 -1
- package/src/canvas/edit-width.ts +1 -3
- package/src/canvas/iframe-channel.ts +27 -13
- package/src/canvas/iframe-drop.ts +13 -12
- package/src/canvas/iframe-editable-root.ts +29 -16
- package/src/canvas/iframe-entry.ts +80 -63
- package/src/canvas/iframe-eval.ts +73 -49
- package/src/canvas/iframe-host.ts +203 -118
- package/src/canvas/iframe-inline-edit.ts +69 -32
- package/src/canvas/iframe-insert.ts +5 -4
- package/src/canvas/iframe-interaction.ts +37 -26
- package/src/canvas/iframe-overlay.ts +1 -1
- package/src/canvas/iframe-patch.ts +18 -15
- package/src/canvas/iframe-position.ts +12 -6
- package/src/canvas/iframe-protocol.ts +15 -16
- package/src/canvas/iframe-render.ts +41 -36
- package/src/canvas/iframe-slash.ts +24 -11
- package/src/canvas/iframe-subtree.ts +6 -2
- package/src/canvas/path-mapping.ts +19 -12
- package/src/canvas/popover-path.ts +7 -3
- package/src/canvas/popover-state.ts +1 -2
- package/src/canvas/serialize-scope.ts +13 -5
- package/src/canvas/stage-scrollbar.ts +2 -1
- package/src/canvas/surface-registry.ts +21 -3
- package/src/collab/collab-commands.ts +7 -2
- package/src/collab/collab-session.ts +84 -45
- package/src/collab/collab-state.ts +4 -3
- package/src/collab/monaco-binding.ts +16 -13
- package/src/collab/monaco-cursors.ts +5 -2
- package/src/commands/budget.ts +3 -3
- package/src/commands/command-args.ts +103 -71
- package/src/commands/context.ts +22 -20
- package/src/commands/defaults.ts +4 -1
- package/src/commands/keymap.ts +47 -43
- package/src/commands/levels.ts +3 -3
- package/src/commands/live-context.ts +10 -8
- package/src/commands/reference.ts +2 -1
- package/src/commands/registry.ts +12 -10
- package/src/commands/run-reported.ts +15 -10
- package/src/component-props.ts +46 -30
- package/src/content/collection-match.ts +5 -4
- package/src/content/draft-state.ts +4 -3
- package/src/content/entry-commands.ts +3 -2
- package/src/content/entry-editor.ts +29 -17
- package/src/content/entry-fields.ts +12 -7
- package/src/content/entry-model.ts +21 -12
- package/src/editor/canvas-context-menu.ts +1 -2
- package/src/editor/canvas-slash-bridge.ts +3 -6
- package/src/editor/content-slice.ts +16 -14
- package/src/editor/context-menu.ts +35 -22
- package/src/editor/convert-targets.ts +30 -35
- package/src/editor/convert-to-component.ts +11 -5
- package/src/editor/convert-to-repeater.ts +34 -22
- package/src/editor/editable-tags.ts +17 -2
- package/src/editor/file-drop-action.ts +21 -22
- package/src/editor/inline-edit-apply.ts +35 -17
- package/src/editor/inline-edit.ts +66 -50
- package/src/editor/inline-format.ts +59 -56
- package/src/editor/inline-link.ts +40 -15
- package/src/editor/insert-zone-action.ts +1 -1
- package/src/editor/merge-tags.ts +58 -19
- package/src/editor/repeater-scope.ts +39 -28
- package/src/editor/shortcuts.ts +87 -47
- package/src/editor/slash-menu.ts +1 -6
- package/src/files/asset-versions.ts +4 -4
- package/src/files/components.ts +15 -10
- package/src/files/elements.ts +5 -6
- package/src/files/file-ops.ts +77 -36
- package/src/files/files.ts +90 -95
- package/src/files/media-meta.ts +2 -1
- package/src/files/media-paths.ts +6 -1
- package/src/files/serialize-document.ts +2 -2
- package/src/format/constraints.ts +1 -1
- package/src/format/convert-file.ts +27 -13
- package/src/format/format-choices.ts +2 -1
- package/src/format/format-host.ts +76 -50
- package/src/github/github-auth-status.ts +27 -3
- package/src/github/github-auth.ts +19 -9
- package/src/github/github-publish.ts +24 -20
- package/src/grid/cell-editors.ts +46 -31
- package/src/grid/cell-popovers.ts +5 -3
- package/src/grid/edit-buffer.ts +10 -9
- package/src/grid/grid-controller.ts +20 -22
- package/src/grid/grid-layout.ts +21 -5
- package/src/grid/grid-open.ts +3 -6
- package/src/grid/grid-panel.ts +11 -4
- package/src/grid/grid-source.ts +8 -8
- package/src/grid/grid-view.ts +14 -17
- package/src/grid/redirects-grid.ts +14 -5
- package/src/grid/redirects.ts +16 -14
- package/src/grid/schema-columns.ts +25 -19
- package/src/grid/sources/connector-source.ts +47 -20
- package/src/grid/sources/content-source.ts +25 -24
- package/src/grid/sources/csv-file-source.ts +2 -2
- package/src/grid/tabulator-tables.d.ts +55 -34
- package/src/hosting/stage.ts +7 -7
- package/src/i18n/i18n-commands.ts +1 -2
- package/src/media/media-pane.ts +4 -1
- package/src/new-project/add-repo-modal.ts +20 -19
- package/src/new-project/import-tab.ts +10 -14
- package/src/new-project/location-fields.ts +2 -1
- package/src/new-project/new-project-modal.ts +12 -9
- package/src/packages/jxsuite-update.ts +4 -3
- package/src/packages/pull-package-sync.ts +26 -25
- package/src/page-params.ts +97 -68
- package/src/panels/activity-panel.ts +17 -9
- package/src/panels/ai-chat/attached-context.ts +13 -7
- package/src/panels/ai-chat/chat-view.ts +80 -73
- package/src/panels/ai-chat/composer.ts +30 -33
- package/src/panels/ai-chat/sessions-view.ts +1 -2
- package/src/panels/ai-panel.ts +23 -20
- package/src/panels/block-action-bar.ts +46 -35
- package/src/panels/bottom-dock.ts +5 -3
- package/src/panels/canvas-dnd-bridge.ts +31 -24
- package/src/panels/data-explorer.ts +62 -25
- package/src/panels/data-grid.ts +14 -11
- package/src/panels/dnd.ts +108 -118
- package/src/panels/editors.ts +55 -22
- package/src/panels/elements-panel.ts +10 -3
- package/src/panels/events-panel.ts +84 -69
- package/src/panels/formula-workspace.ts +76 -51
- package/src/panels/frontmatter-fields.ts +24 -19
- package/src/panels/frontmatter-panel.ts +44 -34
- package/src/panels/git-diff-open.ts +4 -4
- package/src/panels/git-panel.ts +49 -61
- package/src/panels/head-panel.ts +131 -111
- package/src/panels/i18n-panel.ts +10 -3
- package/src/panels/imports-panel.ts +23 -47
- package/src/panels/jump-bar.ts +48 -29
- package/src/panels/layers-panel.ts +97 -74
- package/src/panels/left-panel.ts +3 -3
- package/src/panels/pane-context.ts +31 -22
- package/src/panels/pane-grid.ts +49 -20
- package/src/panels/panel-registry.ts +22 -37
- package/src/panels/properties-panel.ts +175 -121
- package/src/panels/quick-search.ts +53 -31
- package/src/panels/right-panel.ts +3 -3
- package/src/panels/seo-modal.ts +13 -17
- package/src/panels/settings-menu.ts +15 -15
- package/src/panels/signals-panel.ts +153 -131
- package/src/panels/statement-editor.ts +230 -140
- package/src/panels/style-panel.ts +254 -216
- package/src/panels/style-utils.ts +114 -51
- package/src/panels/stylebook-doc.ts +57 -54
- package/src/panels/stylebook-layers-panel.ts +9 -9
- package/src/panels/stylebook-panel.ts +13 -17
- package/src/panels/tab-drop.ts +27 -11
- package/src/panels/tab-strip.ts +36 -26
- package/src/platform-errors.ts +57 -43
- package/src/platform.ts +58 -30
- package/src/platforms/cloud.ts +345 -175
- package/src/platforms/default-platform.ts +10 -4
- package/src/platforms/devserver.ts +174 -127
- package/src/platforms/read-batcher.ts +16 -8
- package/src/project-list.ts +2 -1
- package/src/publish/deploy-checklist.ts +8 -2
- package/src/publish/pages-service.ts +28 -13
- package/src/publish/publish-commands.ts +5 -4
- package/src/publish/publish-panel.ts +10 -6
- package/src/recent-projects.ts +15 -8
- package/src/resize-edges.ts +26 -36
- package/src/services/a11y-report.ts +26 -19
- package/src/services/agent-seed.ts +23 -11
- package/src/services/ai-ask.ts +9 -12
- package/src/services/ai-command-tools.ts +68 -62
- package/src/services/ai-import-tools.ts +80 -67
- package/src/services/ai-models.ts +17 -13
- package/src/services/ai-project-tools.ts +68 -32
- package/src/services/ai-session-store.ts +19 -10
- package/src/services/ai-system-prompt.ts +46 -20
- package/src/services/ai-tools.ts +71 -27
- package/src/services/ai-write-report.ts +20 -12
- package/src/services/ai-writes.ts +4 -4
- package/src/services/automation.ts +58 -31
- package/src/services/cem-export.ts +149 -58
- package/src/services/clock.ts +6 -1
- package/src/services/code-services.ts +37 -31
- package/src/services/context-manager.ts +14 -10
- package/src/services/context-resolver.ts +20 -8
- package/src/services/data-service.ts +19 -15
- package/src/services/directory-picker.ts +18 -12
- package/src/services/document-assistant.ts +39 -19
- package/src/services/gated-registry.ts +10 -6
- package/src/services/harness/chat-reducer.ts +23 -1
- package/src/services/import-client.ts +91 -38
- package/src/services/import-seed.ts +8 -2
- package/src/services/jx-validate.ts +28 -31
- package/src/services/live-preview.ts +0 -0
- package/src/services/live-surfaces.ts +6 -3
- package/src/services/model-uri.ts +10 -2
- package/src/services/module-preloads.ts +12 -8
- package/src/services/monaco-buffer.ts +43 -24
- package/src/services/monaco-lazy.ts +7 -8
- package/src/services/monaco-setup.ts +23 -16
- package/src/services/notify.ts +44 -17
- package/src/services/popover-report.ts +25 -10
- package/src/services/preview-eval.ts +20 -8
- package/src/services/profile.ts +13 -6
- package/src/services/project-path.ts +13 -10
- package/src/services/references.ts +0 -0
- package/src/services/render-critic.ts +8 -7
- package/src/services/settings/kernel.ts +13 -4
- package/src/services/settings/write-queue.ts +9 -9
- package/src/services/token-lint.ts +12 -10
- package/src/services/tool-executor.ts +17 -5
- package/src/services/tool-outcomes.ts +44 -24
- package/src/services/trusted-types.ts +24 -7
- package/src/settings/contexts-section.ts +11 -8
- package/src/settings/contributed-section.ts +79 -60
- package/src/settings/css-vars-editor.ts +37 -16
- package/src/settings/defs-editor.ts +38 -35
- package/src/settings/extension-rows.ts +16 -8
- package/src/settings/extension-sections.ts +23 -13
- package/src/settings/extensions-section.ts +4 -1
- package/src/settings/general-settings.ts +11 -8
- package/src/settings/locales-section.ts +20 -12
- package/src/settings/preferences-dialog.ts +9 -6
- package/src/settings/preferences-keymap.ts +7 -5
- package/src/settings/preferences-sections.ts +11 -5
- package/src/settings/project-sections.ts +1 -1
- package/src/settings/schema-field-ui.ts +9 -0
- package/src/settings/settings-document.ts +5 -5
- package/src/shell/tree.ts +6 -5
- package/src/shell.ts +104 -81
- package/src/site-context.ts +37 -22
- package/src/state.ts +41 -49
- package/src/store.ts +54 -34
- package/src/studio.ts +39 -77
- package/src/style/live-preview.ts +1 -1
- package/src/style/project-styles.ts +6 -7
- package/src/style/token-ref.ts +5 -4
- package/src/surfaces/about.ts +18 -19
- package/src/surfaces/add-repo.ts +17 -19
- package/src/surfaces/ai-chat.ts +31 -36
- package/src/surfaces/ai-credentials-form.ts +6 -16
- package/src/surfaces/ai-managed-connect.ts +3 -4
- package/src/surfaces/ai-model-picker.ts +3 -5
- package/src/surfaces/block-action-bar.ts +22 -11
- package/src/surfaces/boot-failure.ts +4 -5
- package/src/surfaces/bottom-dock.ts +9 -18
- package/src/surfaces/canvas-stage.ts +12 -11
- package/src/surfaces/cf-account-picker.ts +17 -18
- package/src/surfaces/commandbar.ts +14 -9
- package/src/surfaces/convert-repeater.ts +17 -19
- package/src/surfaces/data-actions.ts +9 -7
- package/src/surfaces/dialog.ts +26 -28
- package/src/surfaces/diff-toolbar.ts +9 -7
- package/src/surfaces/doc-header.ts +10 -19
- package/src/surfaces/empty-state.ts +7 -10
- package/src/surfaces/entry-editor.ts +14 -11
- package/src/surfaces/expression-editor.ts +11 -25
- package/src/surfaces/files-panel.ts +27 -14
- package/src/surfaces/formula-palette.ts +4 -5
- package/src/surfaces/git-panel.ts +7 -15
- package/src/surfaces/github-auth.ts +16 -20
- package/src/surfaces/github-publish.ts +17 -22
- package/src/surfaces/grid-cell.ts +30 -31
- package/src/surfaces/grid-open.ts +10 -14
- package/src/surfaces/grid-panel.ts +13 -9
- package/src/surfaces/grid-replace.ts +13 -13
- package/src/surfaces/grid-views.ts +15 -18
- package/src/surfaces/inspector-dock.ts +13 -12
- package/src/surfaces/jump-bar.ts +5 -6
- package/src/surfaces/jxsuite-update.ts +16 -22
- package/src/surfaces/library-pane.ts +25 -20
- package/src/surfaces/logic-panel.ts +17 -30
- package/src/surfaces/logic-workspace.ts +13 -15
- package/src/surfaces/media-browser.ts +11 -10
- package/src/surfaces/media-field.ts +4 -5
- package/src/surfaces/media-pane.ts +8 -7
- package/src/surfaces/menu.ts +29 -23
- package/src/surfaces/navigator-dock.ts +11 -12
- package/src/surfaces/new-project.ts +27 -26
- package/src/surfaces/pane-context.ts +20 -25
- package/src/surfaces/pane-grid.ts +15 -10
- package/src/surfaces/panel-activity.ts +5 -6
- package/src/surfaces/panel-data.ts +3 -4
- package/src/surfaces/panel-deploy-checklist.ts +5 -6
- package/src/surfaces/panel-elements.ts +5 -7
- package/src/surfaces/panel-i18n.ts +5 -7
- package/src/surfaces/panel-imports.ts +6 -13
- package/src/surfaces/panel-outline.ts +25 -19
- package/src/surfaces/panel-page.ts +11 -18
- package/src/surfaces/panel-problems.ts +5 -7
- package/src/surfaces/panel-signals.ts +20 -34
- package/src/surfaces/panel-stylebook-layers.ts +5 -8
- package/src/surfaces/preferences.ts +21 -11
- package/src/surfaces/progress-modal.ts +15 -9
- package/src/surfaces/properties-panel.json +1 -1
- package/src/surfaces/properties-panel.ts +20 -42
- package/src/surfaces/publish.ts +18 -18
- package/src/surfaces/push-plan.ts +7 -8
- package/src/surfaces/rail.json +126 -73
- package/src/surfaces/rail.ts +38 -12
- package/src/surfaces/reference-field.ts +11 -15
- package/src/surfaces/schema-builder.ts +16 -22
- package/src/surfaces/schema-form.ts +15 -25
- package/src/surfaces/secret-field.ts +9 -6
- package/src/surfaces/seo.ts +21 -15
- package/src/surfaces/settings-contexts.ts +9 -7
- package/src/surfaces/settings-contributed.ts +14 -10
- package/src/surfaces/settings-css-vars.ts +5 -12
- package/src/surfaces/settings-defs.json +2 -2
- package/src/surfaces/settings-defs.ts +17 -21
- package/src/surfaces/settings-deploy.ts +8 -15
- package/src/surfaces/settings-extensions.ts +5 -6
- package/src/surfaces/settings-head.ts +33 -39
- package/src/surfaces/settings-locales.ts +8 -20
- package/src/surfaces/settings-overview.ts +5 -6
- package/src/surfaces/settings-packages.ts +8 -7
- package/src/surfaces/settings-pane.ts +9 -18
- package/src/surfaces/settings-rawjson.ts +5 -6
- package/src/surfaces/shell.ts +1 -2
- package/src/surfaces/slash-menu.ts +19 -9
- package/src/surfaces/statements.ts +13 -18
- package/src/surfaces/statusbar.ts +17 -14
- package/src/surfaces/style-panel.ts +18 -31
- package/src/surfaces/stylebook-chrome.ts +3 -5
- package/src/surfaces/tab-strip.ts +14 -13
- package/src/surfaces/target-line.ts +6 -7
- package/src/surfaces/welcome.ts +5 -7
- package/src/tabs/patch-ops.ts +4 -3
- package/src/tabs/project-config.ts +32 -21
- package/src/tabs/selection.ts +36 -8
- package/src/tabs/tab.ts +52 -41
- package/src/tabs/transact.ts +98 -53
- package/src/tabs/typing.ts +31 -0
- package/src/types.ts +32 -17
- package/src/ui/ai-credentials-form.ts +10 -13
- package/src/ui/ai-model-picker.ts +3 -3
- package/src/ui/cf-account-picker.ts +7 -9
- package/src/ui/color-selector.ts +9 -5
- package/src/ui/dynamic-slot.ts +7 -8
- package/src/ui/expression-editor.ts +112 -105
- package/src/ui/form-controls.ts +57 -48
- package/src/ui/formula-catalog.ts +239 -230
- package/src/ui/formula-chips.ts +33 -18
- package/src/ui/layers.ts +44 -31
- package/src/ui/media-picker.ts +18 -9
- package/src/ui/popover-surface.ts +20 -12
- package/src/ui/progress-modal.ts +13 -8
- package/src/ui/regions.ts +7 -6
- package/src/ui/schema-form.ts +113 -70
- package/src/ui/surface.ts +71 -8
- package/src/ui/timing.ts +9 -0
- package/src/ui/value-source.ts +44 -31
- package/src/ui/virtual-window.ts +3 -2
- package/src/utils/base64.ts +3 -1
- package/src/utils/edit-display.ts +103 -74
- package/src/utils/element-selectors.ts +3 -2
- package/src/utils/google-fonts.ts +15 -14
- package/src/utils/inherited-style.ts +18 -20
- package/src/utils/link-target.ts +1 -1
- package/src/utils/preview-format.ts +25 -3
- package/src/utils/strip-events.ts +49 -22
- package/src/utils/studio-utils.ts +29 -14
- package/src/view.ts +2 -3
- package/src/workspace/pane-derive.ts +10 -12
- package/src/workspace/session.ts +53 -43
- package/src/workspace/workspace.ts +47 -36
- package/dist/chunks/2020-nkxms0ay.js +0 -4
- package/dist/chunks/adapter-m948ab5f.js +0 -4
- package/dist/chunks/cf-account-picker-n8hr38v7.js +0 -4
- package/dist/chunks/cf-settings-356xdtne.js +0 -4
- package/dist/chunks/color-area-jqhna8zy.js +0 -4
- package/dist/chunks/color-field-embq5ctg.js +0 -4
- package/dist/chunks/color-fpezvnkt.js +0 -4
- package/dist/chunks/color-slider-1qmw7wqy.js +0 -4
- package/dist/chunks/combobox-773hdzyj.js +0 -4
- package/dist/chunks/components-yk3t844e.js +0 -4
- package/dist/chunks/content-source-bawmyc09.js +0 -4
- package/dist/chunks/convert-to-repeater-7wns8kf1.js +0 -4
- package/dist/chunks/dialog-mtm9fq5t.js +0 -4
- package/dist/chunks/editor-6sc8nacq.js +0 -4
- package/dist/chunks/entry-commands-8ay9fh81.js +0 -4
- package/dist/chunks/extension-sections-na7rj3nr.js +0 -4
- package/dist/chunks/file-ops-gye0qw56.js +0 -4
- package/dist/chunks/files-dmc2xvcq.js +0 -4
- package/dist/chunks/format-host-t76b53f8.js +0 -4
- package/dist/chunks/fs-events-cg4tpz06.js +0 -4
- package/dist/chunks/git-panel-yef7bshy.js +0 -4
- package/dist/chunks/grid-view-7tt4bxw1.js +0 -51
- package/dist/chunks/icons-qbh8akb1.js +0 -4
- package/dist/chunks/iframe-entry-f7mqjwpm.js +0 -5
- package/dist/chunks/iframe-entry-haw7jkvz.js +0 -5
- package/dist/chunks/iframe-entry-z6qrytv3.js +0 -5
- package/dist/chunks/iframe-host-tmz30gfp.js +0 -4
- package/dist/chunks/index-nag78a9h.js +0 -4
- package/dist/chunks/jsonMode-zhwsprqk.js +0 -13
- package/dist/chunks/jx-validate-3gbp5nkn.js +0 -4
- package/dist/chunks/layers-fvz99859.js +0 -4
- package/dist/chunks/layers-panel-gchmbf9p.js +0 -4
- package/dist/chunks/listbox-s8fkmnq8.js +0 -4
- package/dist/chunks/lit-html-9agdspkt.js +0 -4
- package/dist/chunks/media-picker-rhjvyy00.js +0 -4
- package/dist/chunks/menu-2e4y9j7b.js +0 -4
- package/dist/chunks/menu-37d07z9m.js +0 -4
- package/dist/chunks/monaco-binding-2jnhjjvr.js +0 -4
- package/dist/chunks/monaco-buffer-rp21359g.js +0 -4
- package/dist/chunks/monaco-setup-vhh7gayr.js +0 -4
- package/dist/chunks/notify-h3www560.js +0 -4
- package/dist/chunks/number-field-gw7sq8rn.js +0 -4
- package/dist/chunks/parse-897fvqah.js +0 -4
- package/dist/chunks/platform-hz34wcd7.js +0 -4
- package/dist/chunks/popover-8htra4er.js +0 -4
- package/dist/chunks/publish-panel-exsmjzyj.js +0 -4
- package/dist/chunks/quick-search-pgaqeh0m.js +0 -4
- package/dist/chunks/references-2cgdxnb8.js +0 -4
- package/dist/chunks/right-panel-jf856w5w.js +0 -4
- package/dist/chunks/section-registry-jnf8r5gy.js +0 -4
- package/dist/chunks/select-n3v7gwas.js +0 -4
- package/dist/chunks/split-pff8f3ze.js +0 -4
- package/dist/chunks/studio-0f55h9ye.js +0 -5
- package/dist/chunks/studio-0sqdhnew.js +0 -12
- package/dist/chunks/studio-19x1c75w.js +0 -5
- package/dist/chunks/studio-2sqcndak.js +0 -5
- package/dist/chunks/studio-3aey7dd3.js +0 -5
- package/dist/chunks/studio-3bpdkq2s.js +0 -5
- package/dist/chunks/studio-47y6fbpf.js +0 -5
- package/dist/chunks/studio-4m3826v2.js +0 -5
- package/dist/chunks/studio-4nx2dj1g.js +0 -4
- package/dist/chunks/studio-4xv5s47r.js +0 -9
- package/dist/chunks/studio-5g4t8v6w.js +0 -5
- package/dist/chunks/studio-5py436sf.js +0 -5
- package/dist/chunks/studio-77kt594t.js +0 -5
- package/dist/chunks/studio-8f87n763.js +0 -10
- package/dist/chunks/studio-8mb00b84.js +0 -5
- package/dist/chunks/studio-8p51gq2h.js +0 -6
- package/dist/chunks/studio-954ds834.js +0 -5
- package/dist/chunks/studio-9ft45c83.js +0 -9
- package/dist/chunks/studio-a2138x5k.js +0 -7
- package/dist/chunks/studio-a9yzstqj.js +0 -5
- package/dist/chunks/studio-acdksxx6.js +0 -5
- package/dist/chunks/studio-ar8jcf2y.js +0 -5
- package/dist/chunks/studio-bmn4mn9j.js +0 -7
- package/dist/chunks/studio-e7xxa0sj.js +0 -5
- package/dist/chunks/studio-ecaz25vk.js +0 -5
- package/dist/chunks/studio-ery42sqr.js +0 -4
- package/dist/chunks/studio-fzdywr6p.js +0 -9
- package/dist/chunks/studio-g5fmf0c1.js +0 -5
- package/dist/chunks/studio-g7nse7zb.js +0 -5
- package/dist/chunks/studio-geq1ea6k.js +0 -14
- package/dist/chunks/studio-ghkb32r8.js +0 -5
- package/dist/chunks/studio-ghrhy2y7.js +0 -5
- package/dist/chunks/studio-grawhey1.js +0 -5
- package/dist/chunks/studio-h0xgswew.js +0 -5
- package/dist/chunks/studio-h9c4p2tx.js +0 -5
- package/dist/chunks/studio-jyzj5cxs.js +0 -5
- package/dist/chunks/studio-mgx8yhnz.js +0 -64
- package/dist/chunks/studio-mpb04y1d.js +0 -6
- package/dist/chunks/studio-n17mty64.js +0 -5
- package/dist/chunks/studio-nwh2eqsk.js +0 -6
- package/dist/chunks/studio-q1h883bt.js +0 -16
- package/dist/chunks/studio-q4tv82h7.js +0 -9
- package/dist/chunks/studio-qpqa7vk3.js +0 -5
- package/dist/chunks/studio-qqz8e5gk.js +0 -5
- package/dist/chunks/studio-qvasen3f.js +0 -5
- package/dist/chunks/studio-rggdb3hm.js +0 -5
- package/dist/chunks/studio-sghy936h.js +0 -4
- package/dist/chunks/studio-skprc6ef.js +0 -5
- package/dist/chunks/studio-tt2nactf.js +0 -5
- package/dist/chunks/studio-tyasmc39.js +0 -5
- package/dist/chunks/studio-vk9ezads.js +0 -5
- package/dist/chunks/studio-vzacdfsc.js +0 -4
- package/dist/chunks/studio-w4c0xmrw.js +0 -5
- package/dist/chunks/studio-wfjqhhbk.js +0 -5
- package/dist/chunks/studio-wgh5kxpj.js +0 -5
- package/dist/chunks/studio-xasj0796.js +0 -5
- package/dist/chunks/studio-y78s8r2n.js +0 -5
- package/dist/chunks/studio-z8w183sh.js +0 -5
- package/dist/chunks/studio-zscd9ty4.js +0 -928
- package/dist/chunks/studio-zxp13sss.js +0 -7
- package/dist/chunks/studio-zygnmm01.js +0 -5
- package/dist/chunks/swatch-group-8qh9a3bm.js +0 -4
- package/dist/chunks/tabs-jwthg40w.js +0 -4
- package/dist/chunks/textfield-spy3hc77.js +0 -4
- package/dist/chunks/toast-4d35zd64.js +0 -4
- package/dist/chunks/toast-host-8sjmfed3.js +0 -4
- package/dist/chunks/tooltip-fd6g9xy3.js +0 -4
- package/dist/chunks/tree-h19v1jfz.js +0 -4
- package/dist/chunks/tsMode-gr0m4dzr.js +0 -14
- package/dist/chunks/workspace-m15qtcqp.js +0 -4
- package/dist/chunks/ws-client-nf61frr1.js +0 -4
|
@@ -46,6 +46,7 @@ import { formatEditableVerdicts } from "../format/constraints";
|
|
|
46
46
|
import { formatByName } from "../format/format-host";
|
|
47
47
|
import { collabState } from "../collab/collab-state";
|
|
48
48
|
import { DIALOG_COMMANDS, isDialog, POPOVER_COMMANDS } from "@jxsuite/schema/dialogs";
|
|
49
|
+
import { isNodeObject } from "@jxsuite/schema/guards";
|
|
49
50
|
import { isPopover } from "@jxsuite/schema/overlays";
|
|
50
51
|
import { localeDirection } from "@jxsuite/schema/locale";
|
|
51
52
|
import { getPlatform, hasPlatform } from "../platform";
|
|
@@ -66,19 +67,70 @@ import type {
|
|
|
66
67
|
SerializableRect,
|
|
67
68
|
SerializedKey,
|
|
68
69
|
SyncedChord,
|
|
69
|
-
WireDocOp,
|
|
70
70
|
} from "./iframe-protocol";
|
|
71
|
+
import type { JxDocOp } from "../tabs/patch-ops";
|
|
71
72
|
import type { IframeChannel } from "./iframe-channel";
|
|
72
73
|
import type { OverlayLayer, OverlayPlacement } from "./iframe-overlay";
|
|
73
74
|
import type { SlashCommand } from "../editor/inline-edit";
|
|
74
75
|
import type { Tab } from "../tabs/tab";
|
|
75
|
-
import type { JxExpressionNode, JxMutableNode } from "@jxsuite/schema/types";
|
|
76
|
+
import type { JxExpressionNode, JxMutableNode, JxStyle } from "@jxsuite/schema/types";
|
|
76
77
|
import { bundleUrl } from "../services/bundle-base";
|
|
77
78
|
|
|
78
|
-
/**
|
|
79
|
-
|
|
79
|
+
/**
|
|
80
|
+
* A plain-data copy of a value bound for `postMessage`.
|
|
81
|
+
*
|
|
82
|
+
* A JSON round trip rather than `structuredClone`, which throws on exactly what this exists to
|
|
83
|
+
* drop: reactive-proxy internals and stray functions riding on a value read off a live store.
|
|
84
|
+
*/
|
|
85
|
+
function plainCopy<T>(value: T): T {
|
|
86
|
+
/* SAFETY: Every value posted through here is document or config data, which is JSON by contract,
|
|
87
|
+
so the round trip returns the same shape minus only what the realm boundary cannot carry. */
|
|
88
|
+
// oxlint-disable-next-line unicorn/prefer-structured-clone
|
|
89
|
+
return JSON.parse(JSON.stringify(value)) as T;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** A deferred re-entry into inline editing, waiting for the host's DOM to reflect a split/insert. */
|
|
93
|
+
interface PendingEnterEdit {
|
|
94
|
+
path: (string | number)[];
|
|
95
|
+
minGen: number;
|
|
96
|
+
offset?: number;
|
|
97
|
+
/** Set when the deferred re-entry is a PROP host rather than a block (see deferEnterEdit). */
|
|
98
|
+
prop?: string;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** The `enterEdit` message a host posts to re-enter inline editing. */
|
|
102
|
+
type EnterEditMsg = Extract<ParentToIframe, { kind: "enterEdit" }>;
|
|
103
|
+
|
|
104
|
+
/** A full-render message, as one host receives it. */
|
|
105
|
+
type RenderMsg = Extract<ParentToIframe, { kind: "render" }>;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* The source data a drag session retains for its drop, exactly what {@link applyDropInstruction}
|
|
109
|
+
* consumes.
|
|
110
|
+
*/
|
|
111
|
+
type RetainedDragData = Parameters<typeof applyDropInstruction>[2];
|
|
80
112
|
|
|
81
|
-
|
|
113
|
+
/** The empirical zoom of a host's iframe and the iframe's parent-viewport offset. */
|
|
114
|
+
export interface DragGeometry {
|
|
115
|
+
scale: number;
|
|
116
|
+
rect: { left: number; top: number };
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** The current edit session's editing flag + latest selection snapshot, for the parent toolbar. */
|
|
120
|
+
export interface EditSnapshotState {
|
|
121
|
+
editing: boolean;
|
|
122
|
+
editingProp: string | null;
|
|
123
|
+
snapshot: SelectionSnapshot | null;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* One artboard's iframe, overlay, selection and edit session.
|
|
128
|
+
*
|
|
129
|
+
* Exported for the drag coordinator, which holds one as an opaque handle and passes it back to the
|
|
130
|
+
* session API ({@link beginDragSession}/{@link hostDragGeometry}/{@link postDragMessage}) without
|
|
131
|
+
* reading its fields.
|
|
132
|
+
*/
|
|
133
|
+
export interface HostState {
|
|
82
134
|
iframe: HTMLIFrameElement;
|
|
83
135
|
/** The `.canvas-panel-canvas` element hosting the iframe + overlay (the WeakMap key). */
|
|
84
136
|
canvasEl: HTMLElement;
|
|
@@ -101,7 +153,7 @@ interface HostState {
|
|
|
101
153
|
/** Primary selected path (mirrors `session.selection`'s last entry), for hover de-dupe. */
|
|
102
154
|
selectionPath: (string | number)[] | null;
|
|
103
155
|
/** The whole selection this host last measured, so a re-measure redraws every box. */
|
|
104
|
-
selectionPaths: JxPath[];
|
|
156
|
+
selectionPaths: readonly JxPath[];
|
|
105
157
|
/** Id of the most recent selection `measure` request, so stale `geometry` replies are dropped. */
|
|
106
158
|
selReqId: number;
|
|
107
159
|
/**
|
|
@@ -157,7 +209,9 @@ interface HostState {
|
|
|
157
209
|
/** Highest snapshot `seq` seen, so stale (re-ordered) snapshots are dropped. */
|
|
158
210
|
lastSnapshotSeq: number;
|
|
159
211
|
/** The last non-null selection rect drawn (parent/overlay coords) — toolbar position fallback. */
|
|
160
|
-
lastSelectionRect:
|
|
212
|
+
lastSelectionRect: OverlayPlacement | null;
|
|
213
|
+
/** The node the pointer last hovered (iframe-viewport rect), so a zoom can hold it still. */
|
|
214
|
+
lastHover: NodeHit | null;
|
|
161
215
|
/**
|
|
162
216
|
* The gen of the render/patch this iframe's DOM currently reflects (set from `renderComplete`/
|
|
163
217
|
* `patchComplete`). Cross-frame drag replies (`dragOver`/`dropResult`) are dropped unless their
|
|
@@ -226,13 +280,7 @@ interface HostState {
|
|
|
226
280
|
* render acks (`renderComplete`) at a bumped one — both satisfy `gen >= minGen`. An immediate
|
|
227
281
|
* `enterEdit` would race the escalated ASYNC render and silently fail to find the element.
|
|
228
282
|
*/
|
|
229
|
-
pendingEnterEdit:
|
|
230
|
-
path: (string | number)[];
|
|
231
|
-
minGen: number;
|
|
232
|
-
offset?: number;
|
|
233
|
-
/** Set when the deferred re-entry is a PROP host rather than a block (see deferEnterEdit). */
|
|
234
|
-
prop?: string;
|
|
235
|
-
} | null;
|
|
283
|
+
pendingEnterEdit: PendingEnterEdit | null;
|
|
236
284
|
/**
|
|
237
285
|
* Stylebook capability (set by {@link mountStylebookCanvas}, cleared by page mounts). The specimen
|
|
238
286
|
* doc's paths decode to TAGS, not tab-document paths: hits route to the injected stylebook
|
|
@@ -248,13 +296,6 @@ interface HostState {
|
|
|
248
296
|
panReqId: number;
|
|
249
297
|
}
|
|
250
298
|
|
|
251
|
-
/**
|
|
252
|
-
* Opaque drag-target host handle for the coordinator bridge. The bridge passes it back to the
|
|
253
|
-
* session API ({@link beginDragSession}/{@link hostDragGeometry}/{@link postDragMessage}) without
|
|
254
|
-
* reading its fields.
|
|
255
|
-
*/
|
|
256
|
-
export type DragHost = HostState;
|
|
257
|
-
|
|
258
299
|
const hosts = new WeakMap<HTMLElement, HostState>();
|
|
259
300
|
|
|
260
301
|
/** Every live host, so the selection watcher can re-measure each one when selection changes. */
|
|
@@ -269,7 +310,7 @@ const liveHosts = new Set<HostState>();
|
|
|
269
310
|
let currentDragSeq = 0;
|
|
270
311
|
|
|
271
312
|
/** Parent-retained source data keyed by `dragSeq` (the block fragment never crosses the boundary). */
|
|
272
|
-
const retainedSrcData = new Map<number,
|
|
313
|
+
const retainedSrcData = new Map<number, RetainedDragData>();
|
|
273
314
|
|
|
274
315
|
/**
|
|
275
316
|
* The last session whose cursor-carrying `dragOver` arrived FROM an iframe, and when. While a
|
|
@@ -419,9 +460,10 @@ export function requestCanvasEval(
|
|
|
419
460
|
}
|
|
420
461
|
evalReqId += 1;
|
|
421
462
|
const reqId = evalReqId;
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
463
|
+
/* Expression nodes come off the reactive document — only plain values may cross postMessage.
|
|
464
|
+
SAFETY: A request's nodes are expression nodes by the caller's contract, and the frame re-checks
|
|
465
|
+
`operator` before evaluating one (`iframe-eval.ts`), reporting anything else per expression. */
|
|
466
|
+
const wireExprs = plainCopy(exprs) as { id: string; node: JxExpressionNode }[];
|
|
425
467
|
target.channel.post({
|
|
426
468
|
contextPath: contextPath ? [...contextPath] : null,
|
|
427
469
|
exprs: wireExprs,
|
|
@@ -539,7 +581,7 @@ export function liveDragHostAt(cursor: { x: number; y: number }): HostState | nu
|
|
|
539
581
|
export function beginDragSession(
|
|
540
582
|
host: HostState,
|
|
541
583
|
src: DragSrcKind,
|
|
542
|
-
srcData:
|
|
584
|
+
srcData: RetainedDragData,
|
|
543
585
|
): number {
|
|
544
586
|
currentDragSeq += 1;
|
|
545
587
|
retainedSrcData.set(currentDragSeq, srcData);
|
|
@@ -567,7 +609,7 @@ export function beginDragSession(
|
|
|
567
609
|
export function adoptDragSession(
|
|
568
610
|
_host: HostState,
|
|
569
611
|
_src: DragSrcKind,
|
|
570
|
-
srcData:
|
|
612
|
+
srcData: RetainedDragData,
|
|
571
613
|
seq: number,
|
|
572
614
|
): number {
|
|
573
615
|
currentDragSeq = seq;
|
|
@@ -585,10 +627,7 @@ export function currentDragSession(): number {
|
|
|
585
627
|
* read FRESH so a pan/zoom mid-drag is reflected. NOT `effectiveZoom()` (a separate path that can
|
|
586
628
|
* desync). The matching iframe parent-viewport rect is returned so the cursor map cancels the pan.
|
|
587
629
|
*/
|
|
588
|
-
export function hostDragGeometry(host: HostState): {
|
|
589
|
-
scale: number;
|
|
590
|
-
rect: { left: number; top: number };
|
|
591
|
-
} {
|
|
630
|
+
export function hostDragGeometry(host: HostState): DragGeometry {
|
|
592
631
|
const rect = rectOf(host.iframe);
|
|
593
632
|
const scale = host.iframe.clientWidth > 0 ? rect.width / host.iframe.clientWidth : 1;
|
|
594
633
|
return { rect, scale };
|
|
@@ -749,6 +788,38 @@ function measureIn(
|
|
|
749
788
|
});
|
|
750
789
|
}
|
|
751
790
|
|
|
791
|
+
/** An element on screen that a zoom should hold still: where it is now, and where it went. */
|
|
792
|
+
export interface PointerAnchor {
|
|
793
|
+
/** The element's top-document `top` when the anchor was taken. */
|
|
794
|
+
top: number;
|
|
795
|
+
/** Measure it again, after the zoom has reflowed the frame; null when it is gone. */
|
|
796
|
+
settle: () => Promise<number | null>;
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
/**
|
|
800
|
+
* The node under the pointer in `canvasEl`'s frame, as a zoom anchor — or null when the pointer has
|
|
801
|
+
* hovered nothing there.
|
|
802
|
+
*
|
|
803
|
+
* Edit's zoom REFLOWS: the frame's layout width changes, text rewraps, and everything above the
|
|
804
|
+
* cursor changes height, so no arithmetic on the old geometry can say where the line under the
|
|
805
|
+
* cursor will land. The frame can: it reported that node on hover, and it measures it again once
|
|
806
|
+
* the new layout exists.
|
|
807
|
+
*/
|
|
808
|
+
export function pointerAnchor(canvasEl: HTMLElement): PointerAnchor | null {
|
|
809
|
+
const host = hostForCanvas(canvasEl);
|
|
810
|
+
const hover = host?.lastHover;
|
|
811
|
+
if (!host || !hover) {
|
|
812
|
+
return null;
|
|
813
|
+
}
|
|
814
|
+
return {
|
|
815
|
+
settle: async () => {
|
|
816
|
+
const point = await measureIn(host, hover.path);
|
|
817
|
+
return point?.top ?? null;
|
|
818
|
+
},
|
|
819
|
+
top: pointForRect(host, hover.rect).top,
|
|
820
|
+
};
|
|
821
|
+
}
|
|
822
|
+
|
|
752
823
|
/**
|
|
753
824
|
* Where the node at `path` is on screen right now, or null when no canvas can answer.
|
|
754
825
|
*
|
|
@@ -1283,7 +1354,7 @@ export function postDialogOpen(tab: { id: string }, path: JxPath | null): void {
|
|
|
1283
1354
|
* `host` is deliberately not a pane-scoped parameter name (see `PANE_PARAM_NAMES`), and the body
|
|
1284
1355
|
* reads no focus: `panelHostingCanvas` resolves the stage from the host's own element.
|
|
1285
1356
|
*/
|
|
1286
|
-
export function postPatchToHosts(forwardOps:
|
|
1357
|
+
export function postPatchToHosts(forwardOps: JxDocOp[], tabId: string | null): number {
|
|
1287
1358
|
let posted = 0;
|
|
1288
1359
|
for (const host of liveHosts) {
|
|
1289
1360
|
if (!host.iframe.isConnected) {
|
|
@@ -1423,14 +1494,14 @@ function hostTab(state: HostState): Tab | null {
|
|
|
1423
1494
|
}
|
|
1424
1495
|
|
|
1425
1496
|
/**
|
|
1426
|
-
* The tab a drag TARGET is showing — the one public reader on the opaque {@link
|
|
1497
|
+
* The tab a drag TARGET is showing — the one public reader on the opaque {@link HostState} handle.
|
|
1427
1498
|
*
|
|
1428
1499
|
* `panels/canvas-dnd-bridge.ts` binds a session to the host under the cursor and then had nothing
|
|
1429
1500
|
* to ask it, so the one fact it needed about the drag — what the dragged node is CALLED — came from
|
|
1430
1501
|
* `activeTab`. The bridge is not supposed to read the handle's fields (that is what "opaque"
|
|
1431
1502
|
* means), so the answer is a function rather than a widened type.
|
|
1432
1503
|
*/
|
|
1433
|
-
export function dragHostTab(host:
|
|
1504
|
+
export function dragHostTab(host: HostState): Tab | null {
|
|
1434
1505
|
return hostTab(host);
|
|
1435
1506
|
}
|
|
1436
1507
|
|
|
@@ -1465,7 +1536,7 @@ function shownSelections(): Map<string, readonly JxPath[]> {
|
|
|
1465
1536
|
if (!tab) {
|
|
1466
1537
|
continue;
|
|
1467
1538
|
}
|
|
1468
|
-
const sel =
|
|
1539
|
+
const sel: readonly JxPath[] = tab.session.selection;
|
|
1469
1540
|
// Track the selection deeply enough that a change WITHIN the set re-measures: the effect
|
|
1470
1541
|
// Reads every path, not just the array reference.
|
|
1471
1542
|
void sel.map((path) => path.join("/")).join("|");
|
|
@@ -1664,7 +1735,7 @@ function requestSelection(host: HostState, sel: readonly JxPath[]): void {
|
|
|
1664
1735
|
}
|
|
1665
1736
|
const primary = primarySelection(sel);
|
|
1666
1737
|
host.selectionPath = primary;
|
|
1667
|
-
host.selectionPaths = sel
|
|
1738
|
+
host.selectionPaths = sel;
|
|
1668
1739
|
if (!host.iframe.isConnected) {
|
|
1669
1740
|
liveHosts.delete(host);
|
|
1670
1741
|
return;
|
|
@@ -1913,6 +1984,7 @@ function ensureHost(canvasEl: HTMLElement): HostState {
|
|
|
1913
1984
|
coSelectionKeys: new Set<string>(),
|
|
1914
1985
|
insertZone: null,
|
|
1915
1986
|
lastRenderedGen: -1,
|
|
1987
|
+
lastHover: null,
|
|
1916
1988
|
lastSelectionRect: null,
|
|
1917
1989
|
lastSnapshotSeq: 0,
|
|
1918
1990
|
overlay,
|
|
@@ -1982,7 +2054,7 @@ function hideInsertZoneNow(state: HostState): void {
|
|
|
1982
2054
|
*/
|
|
1983
2055
|
function insertButtonHovered(state: HostState): boolean {
|
|
1984
2056
|
const btn = state.overlay.insertButton;
|
|
1985
|
-
return state.insertHover ||
|
|
2057
|
+
return state.insertHover || btn.matches(":hover");
|
|
1986
2058
|
}
|
|
1987
2059
|
|
|
1988
2060
|
/**
|
|
@@ -2039,6 +2111,7 @@ const PREVIEW_BLOCKED: ReadonlySet<IframeToParent["kind"]> = new Set([
|
|
|
2039
2111
|
"dropResult",
|
|
2040
2112
|
"editCommit",
|
|
2041
2113
|
"editCommitProp",
|
|
2114
|
+
"editInput",
|
|
2042
2115
|
"editInsert",
|
|
2043
2116
|
"editMerge",
|
|
2044
2117
|
"editRangeReplace",
|
|
@@ -2137,7 +2210,8 @@ function handleMessage(state: HostState, msg: IframeToParent): void {
|
|
|
2137
2210
|
behind that message with it. The null check is the same guard for a `targetPath` an edit
|
|
2138
2211
|
has since invalidated, which threw for the same reason. */
|
|
2139
2212
|
const target = getNodeAtPath(tab.doc.document, msg.targetPath);
|
|
2140
|
-
|
|
2213
|
+
// A path can resolve to a string child or to nothing at all, whatever the declared type says.
|
|
2214
|
+
if (!isNodeObject(target)) {
|
|
2141
2215
|
return;
|
|
2142
2216
|
}
|
|
2143
2217
|
if (POPOVER_COMMANDS.has(msg.command)) {
|
|
@@ -2272,6 +2346,7 @@ function handleMessage(state: HostState, msg: IframeToParent): void {
|
|
|
2272
2346
|
}
|
|
2273
2347
|
return;
|
|
2274
2348
|
}
|
|
2349
|
+
state.lastHover = msg.hit;
|
|
2275
2350
|
drawHover(state, msg.hit);
|
|
2276
2351
|
return;
|
|
2277
2352
|
}
|
|
@@ -2333,7 +2408,7 @@ function handleMessage(state: HostState, msg: IframeToParent): void {
|
|
|
2333
2408
|
// The iframe could not resolve is simply absent from `hits`.
|
|
2334
2409
|
const primaryKey = JSON.stringify(state.selectionPath);
|
|
2335
2410
|
const co: OverlayPlacement[] = [];
|
|
2336
|
-
let rect:
|
|
2411
|
+
let rect: OverlayPlacement | null = null;
|
|
2337
2412
|
if (state.stylebook) {
|
|
2338
2413
|
const [hit] = msg.hits;
|
|
2339
2414
|
rect = hit ? canvasRectToParent(hit.rect) : null;
|
|
@@ -2629,6 +2704,15 @@ function handleMessage(state: HostState, msg: IframeToParent): void {
|
|
|
2629
2704
|
}
|
|
2630
2705
|
return;
|
|
2631
2706
|
}
|
|
2707
|
+
case "editInput": {
|
|
2708
|
+
// The first keystroke of a burst: the text lands on the idle tick, but the tab has unsaved
|
|
2709
|
+
// Work from now, and Save's enablement reads exactly this flag.
|
|
2710
|
+
const tab = hostTab(state);
|
|
2711
|
+
if (tab) {
|
|
2712
|
+
tab.doc.dirty = true;
|
|
2713
|
+
}
|
|
2714
|
+
return;
|
|
2715
|
+
}
|
|
2632
2716
|
case "editCommit": {
|
|
2633
2717
|
// Route to the tab this host's iframe renders — NOT activeTab, which may have changed while
|
|
2634
2718
|
// The message was in flight (the cross-document bleed).
|
|
@@ -2716,9 +2800,8 @@ function handleMessage(state: HostState, msg: IframeToParent): void {
|
|
|
2716
2800
|
const { rect: ifr, scale } = hostDragGeometry(state);
|
|
2717
2801
|
const left = msg.rect.x * scale + ifr.left;
|
|
2718
2802
|
const top = msg.rect.y * scale + ifr.top;
|
|
2719
|
-
|
|
2803
|
+
const request: CanvasSlashRequest = {
|
|
2720
2804
|
filter: msg.filter,
|
|
2721
|
-
...(msg.showFilter === true ? { showFilter: true } : {}),
|
|
2722
2805
|
onDismiss: () => state.channel.post({ kind: "slashDismissed" }),
|
|
2723
2806
|
onSelect: (cmd) => state.channel.post({ cmd: { ...cmd }, kind: "slashSelect" }),
|
|
2724
2807
|
rect: {
|
|
@@ -2728,7 +2811,11 @@ function handleMessage(state: HostState, msg: IframeToParent): void {
|
|
|
2728
2811
|
top,
|
|
2729
2812
|
width: msg.rect.width * scale,
|
|
2730
2813
|
},
|
|
2731
|
-
}
|
|
2814
|
+
};
|
|
2815
|
+
if (msg.showFilter === true) {
|
|
2816
|
+
request.showFilter = true;
|
|
2817
|
+
}
|
|
2818
|
+
canvasSlashHandler?.show(request);
|
|
2732
2819
|
return;
|
|
2733
2820
|
}
|
|
2734
2821
|
case "slashNav": {
|
|
@@ -2825,12 +2912,14 @@ function deferEnterEdit(
|
|
|
2825
2912
|
offset?: number,
|
|
2826
2913
|
prop?: string,
|
|
2827
2914
|
): void {
|
|
2828
|
-
state.
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2915
|
+
const pending: PendingEnterEdit = { minGen: state.lastRenderedGen, path: [...path] };
|
|
2916
|
+
if (offset !== undefined) {
|
|
2917
|
+
pending.offset = offset;
|
|
2918
|
+
}
|
|
2919
|
+
if (prop !== undefined) {
|
|
2920
|
+
pending.prop = prop;
|
|
2921
|
+
}
|
|
2922
|
+
state.pendingEnterEdit = pending;
|
|
2834
2923
|
}
|
|
2835
2924
|
|
|
2836
2925
|
/** Ask the host's iframe to (re-)enter inline editing on `path` (a plain copy crosses the bridge). */
|
|
@@ -2840,12 +2929,14 @@ function reenterEdit(
|
|
|
2840
2929
|
offset?: number,
|
|
2841
2930
|
prop?: string,
|
|
2842
2931
|
): void {
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2932
|
+
const enter: EnterEditMsg = { kind: "enterEdit", path: [...path] };
|
|
2933
|
+
if (offset !== undefined) {
|
|
2934
|
+
enter.offset = offset;
|
|
2935
|
+
}
|
|
2936
|
+
if (prop !== undefined) {
|
|
2937
|
+
enter.prop = prop;
|
|
2938
|
+
}
|
|
2939
|
+
state.channel.post(enter);
|
|
2849
2940
|
}
|
|
2850
2941
|
|
|
2851
2942
|
/**
|
|
@@ -3041,11 +3132,9 @@ function preparePassRender(
|
|
|
3041
3132
|
// So a JSON round-trip (NOT structuredClone, which would throw) drops residual functions /
|
|
3042
3133
|
// Reactive proxy artifacts that would otherwise raise DataCloneError and silently drop the
|
|
3043
3134
|
// Entire message.
|
|
3044
|
-
|
|
3045
|
-
const cloneableDoc = JSON.parse(JSON.stringify(resolved.renderDoc)) as unknown;
|
|
3135
|
+
const cloneableDoc = plainCopy(resolved.renderDoc);
|
|
3046
3136
|
// The RAW page doc (forward-op + data-jx-path coordinate space) crosses as the shadow doc.
|
|
3047
|
-
|
|
3048
|
-
const cloneableShadow = JSON.parse(JSON.stringify(doc)) as unknown;
|
|
3137
|
+
const cloneableShadow = plainCopy(doc);
|
|
3049
3138
|
// Which tags can hold a caret depends on the document's vocabulary, so the format's verdicts
|
|
3050
3139
|
// Ride with the render rather than being baked into the frame. Absent for a native document,
|
|
3051
3140
|
// Where the studio's own element metadata answers on its own.
|
|
@@ -3055,21 +3144,27 @@ function preparePassRender(
|
|
|
3055
3144
|
const renderTab = tabId ? (workspace.tabs.get(tabId) ?? null) : null;
|
|
3056
3145
|
const formatElements = formatByName(renderTab?.doc.sourceFormat)?.studio?.elements;
|
|
3057
3146
|
const editableTags = formatElements ? formatEditableVerdicts(formatElements) : undefined;
|
|
3058
|
-
|
|
3147
|
+
const prepared: PreparedRender = {
|
|
3059
3148
|
assets: resolved.assets,
|
|
3060
3149
|
doc: cloneableDoc,
|
|
3061
3150
|
docBase: resolved.docBase ?? `${canvasBaseOrigin()}/`,
|
|
3062
3151
|
mapperCtx: resolved.mapperCtx,
|
|
3063
|
-
/*
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
`git-diff` while git-diff
|
|
3152
|
+
/* SAFETY: `WireMapperCtx.canvasMode` is typed `string` only because it mirrors `PathMapCtx`,
|
|
3153
|
+
which takes `CanvasMode | string`; `resolveCanvasDocument` fills it with the mode this host
|
|
3154
|
+
was asked to render (`modeOverride ?? canvasModeOfTab(tab)`), and only a canvas mode ever
|
|
3155
|
+
mounts a host. It used to narrow to a union that did not list `git-diff` while git-diff
|
|
3156
|
+
renders went through here every day. */
|
|
3067
3157
|
mode: resolved.mapperCtx.canvasMode as CanvasMode,
|
|
3068
3158
|
shadowDoc: cloneableShadow,
|
|
3069
3159
|
siteStyle: resolved.siteStyle,
|
|
3070
|
-
...(editableTags ? { editableTags } : {}),
|
|
3071
|
-
...(allowAutoRequests ? { allowAutoRequests: true } : {}),
|
|
3072
3160
|
};
|
|
3161
|
+
if (editableTags) {
|
|
3162
|
+
prepared.editableTags = editableTags;
|
|
3163
|
+
}
|
|
3164
|
+
if (allowAutoRequests) {
|
|
3165
|
+
prepared.allowAutoRequests = true;
|
|
3166
|
+
}
|
|
3167
|
+
return prepared;
|
|
3073
3168
|
});
|
|
3074
3169
|
byDoc.set(doc, { mode: modeOverride, payload, tabId, viewTabId });
|
|
3075
3170
|
return payload;
|
|
@@ -3134,18 +3229,12 @@ export async function mountIframeCanvas(
|
|
|
3134
3229
|
paneOfContainer(canvasEl),
|
|
3135
3230
|
modeOverride,
|
|
3136
3231
|
);
|
|
3137
|
-
const message:
|
|
3232
|
+
const message: RenderMsg = {
|
|
3138
3233
|
...prepared,
|
|
3139
3234
|
// Per-TAB, and read at POST time so a scheme flip that raced the shared resolution is not
|
|
3140
3235
|
// Baked into the payload every host shares. `viewTab` is this artboard's tab — defaulted from
|
|
3141
3236
|
// `tabOfContainer(canvasEl)`, the same route the rest of this mount takes.
|
|
3142
3237
|
colorScheme: schemeWireFor(viewTab),
|
|
3143
|
-
/* Per-ARTBOARD, and post-time for a sharper version of the same reason. `preparePassRender`
|
|
3144
|
-
memoizes on the document and hands the SAME payload object to every host in the pass, and a
|
|
3145
|
-
git-diff pass has two hosts holding two documents — but marks are a function of BOTH sides,
|
|
3146
|
-
not of the document this host draws, so they are not derivable from that cache key at all.
|
|
3147
|
-
Baking them in would make the two artboards race for whose marks the pass kept. */
|
|
3148
|
-
...(diffMarks ? { diffMarks } : {}),
|
|
3149
3238
|
gen,
|
|
3150
3239
|
kind: "render",
|
|
3151
3240
|
// Read at POST time for the same reason `colorScheme` is: a render replaces the DOM, so a panel
|
|
@@ -3153,6 +3242,15 @@ export async function mountIframeCanvas(
|
|
|
3153
3242
|
popoverOpen: viewTab?.session.ui.openPopover ?? null,
|
|
3154
3243
|
dialogOpen: viewTab?.session.ui.openDialog ?? null,
|
|
3155
3244
|
};
|
|
3245
|
+
/* Diff marks are per-ARTBOARD, and post-time for a sharper version of the colour scheme's
|
|
3246
|
+
reason. `preparePassRender` memoizes on the document and hands the SAME payload object to every
|
|
3247
|
+
host in the pass, and a git-diff pass has two hosts holding two documents — but marks are a
|
|
3248
|
+
function of BOTH sides, not of the document this host draws, so they are not derivable from
|
|
3249
|
+
that cache key at all. Baking them in would make the two artboards race for whose marks the
|
|
3250
|
+
pass kept. */
|
|
3251
|
+
if (diffMarks) {
|
|
3252
|
+
message.diffMarks = diffMarks;
|
|
3253
|
+
}
|
|
3156
3254
|
state.popoverOpen = message.popoverOpen ?? null;
|
|
3157
3255
|
state.dialogOpen = message.dialogOpen ?? null;
|
|
3158
3256
|
// Preview is the fidelity view: no editing messages are honoured from it, no overlay is painted
|
|
@@ -3204,10 +3302,8 @@ export function mountStylebookCanvas(
|
|
|
3204
3302
|
state.iframe.style.width = widthPx ? `${widthPx}px` : "100%";
|
|
3205
3303
|
// Two independent plain clones: the iframe renders `doc` and folds styleUpdates into `shadowDoc`
|
|
3206
3304
|
// (and fake test channels pass messages by reference, so sharing one object would alias them).
|
|
3207
|
-
|
|
3208
|
-
const
|
|
3209
|
-
// oxlint-disable-next-line unicorn/prefer-structured-clone
|
|
3210
|
-
const cloneableShadow = JSON.parse(JSON.stringify(generated.doc)) as unknown;
|
|
3305
|
+
const cloneableDoc = plainCopy(generated.doc);
|
|
3306
|
+
const cloneableShadow = plainCopy(generated.doc);
|
|
3211
3307
|
const message: ParentToIframe = {
|
|
3212
3308
|
// The specimen carries no tab identity, but the STAGE it is mounted into does: a stylebook is
|
|
3213
3309
|
// Opened as a tab like anything else, and its `previewColorScheme` is that tab's.
|
|
@@ -3325,8 +3421,7 @@ export function postLocaleToLiveHosts(locale: string | null, root?: HTMLElement
|
|
|
3325
3421
|
* off a tab's reactive record is a proxy, and a proxy cannot be structured-cloned.
|
|
3326
3422
|
*/
|
|
3327
3423
|
export function postRedefineElementToLiveHosts(doc: JxMutableNode, base: string): number {
|
|
3328
|
-
|
|
3329
|
-
const plain = JSON.parse(JSON.stringify(doc)) as JxMutableNode;
|
|
3424
|
+
const plain = plainCopy(doc);
|
|
3330
3425
|
let posted = 0;
|
|
3331
3426
|
for (const host of liveHosts) {
|
|
3332
3427
|
if (!host.iframe.isConnected) {
|
|
@@ -3352,13 +3447,8 @@ export function postSiteStyleToLiveHosts(): void {
|
|
|
3352
3447
|
return;
|
|
3353
3448
|
}
|
|
3354
3449
|
// Site config comes off a reactive store — only plain values may cross postMessage.
|
|
3355
|
-
|
|
3356
|
-
const
|
|
3357
|
-
string,
|
|
3358
|
-
unknown
|
|
3359
|
-
> | null;
|
|
3360
|
-
// oxlint-disable-next-line unicorn/prefer-structured-clone
|
|
3361
|
-
const media = JSON.parse(JSON.stringify(config.$media ?? {})) as Record<string, string>;
|
|
3450
|
+
const siteStyle = plainCopy(config.style ?? null);
|
|
3451
|
+
const media = plainCopy(config.$media ?? {});
|
|
3362
3452
|
for (const host of liveHosts) {
|
|
3363
3453
|
if (!host.iframe.isConnected) {
|
|
3364
3454
|
liveHosts.delete(host);
|
|
@@ -3376,11 +3466,10 @@ export function postSiteStyleToLiveHosts(): void {
|
|
|
3376
3466
|
* received it — zero means no stylebook iframe is live yet and the caller should fall through to a
|
|
3377
3467
|
* full render. Each post is followed by a selection re-measure so the box tracks the reflow.
|
|
3378
3468
|
*/
|
|
3379
|
-
export function postStyleUpdateToStylebookHosts(style:
|
|
3469
|
+
export function postStyleUpdateToStylebookHosts(style: JxStyle): number {
|
|
3380
3470
|
let posted = 0;
|
|
3381
3471
|
// Style objects come off the reactive doc — only plain values may cross postMessage.
|
|
3382
|
-
|
|
3383
|
-
const cloneable = JSON.parse(JSON.stringify(style)) as Record<string, unknown>;
|
|
3472
|
+
const cloneable = plainCopy(style);
|
|
3384
3473
|
for (const host of liveHosts) {
|
|
3385
3474
|
if (!host.iframe.isConnected) {
|
|
3386
3475
|
liveHosts.delete(host);
|
|
@@ -3416,12 +3505,8 @@ export function panToStylebookTag(tag: string): void {
|
|
|
3416
3505
|
|
|
3417
3506
|
// ─── Format-toolbar bridge (Phase 4b-2) ─────────────────────────────────────────
|
|
3418
3507
|
|
|
3419
|
-
/** The current edit session's
|
|
3420
|
-
export function getEditSnapshot(): {
|
|
3421
|
-
editing: boolean;
|
|
3422
|
-
editingProp: string | null;
|
|
3423
|
-
snapshot: SelectionSnapshot | null;
|
|
3424
|
-
} {
|
|
3508
|
+
/** The current edit session's state, for the parent toolbar. */
|
|
3509
|
+
export function getEditSnapshot(): EditSnapshotState {
|
|
3425
3510
|
/* The same connectivity guard {@link isCaretActive} has, and for the same reason: a session
|
|
3426
3511
|
belongs to a frame, and a frame that has left the document has no caret in it. `releaseHost`
|
|
3427
3512
|
clears `activeEditHost`, so this is the second line rather than the first — it covers the frame
|
|
@@ -3532,31 +3617,40 @@ export function commitActiveEditSession(): void {
|
|
|
3532
3617
|
/** The live host backing the active panel's canvas (for non-edit selection-bar positioning). */
|
|
3533
3618
|
function hostForActivePanel(): HostState | null {
|
|
3534
3619
|
const panel = getActivePanel();
|
|
3535
|
-
return panel ? hostForCanvas(panel.canvas
|
|
3620
|
+
return panel ? hostForCanvas(panel.canvas) : null;
|
|
3536
3621
|
}
|
|
3537
3622
|
|
|
3538
3623
|
/**
|
|
3539
3624
|
* The format toolbar's anchor rect, in PARENT-VIEWPORT space (the bar is `position:fixed`). Both
|
|
3540
|
-
* source rects — the
|
|
3541
|
-
* UNSCALED iframe-viewport px (D-2: the overlay draws them inside the scaled
|
|
3542
|
-
* browser applies the zoom there); the fixed bar gets no such free ride, so
|
|
3543
|
-
* empirical zoom ({@link hostDragGeometry}) and add the iframe's on-screen
|
|
3544
|
-
* already bakes in pan + zoom + ancestor scroll. The empirical ratio covers BOTH
|
|
3545
|
-
* design mode's panzoom-wrap transform and edit mode's content-zoom counter-scale
|
|
3546
|
-
* evaluates to exactly `editZoom` — the iframe's layout width is `renderWidth / editZoom`
|
|
3547
|
-
* rendered width is `renderWidth`).
|
|
3548
|
-
*/
|
|
3549
|
-
export function getEditBarAnchorRect():
|
|
3550
|
-
// The
|
|
3551
|
-
//
|
|
3552
|
-
//
|
|
3553
|
-
//
|
|
3625
|
+
* source rects — the selected element's `lastSelectionRect` and the edit session's caret-snapshot
|
|
3626
|
+
* fallback — are in UNSCALED iframe-viewport px (D-2: the overlay draws them inside the scaled
|
|
3627
|
+
* panzoom-wrap, so the browser applies the zoom there); the fixed bar gets no such free ride, so
|
|
3628
|
+
* scale by the live empirical zoom ({@link hostDragGeometry}) and add the iframe's on-screen
|
|
3629
|
+
* offset, whose GBCR already bakes in pan + zoom + ancestor scroll. The empirical ratio covers BOTH
|
|
3630
|
+
* scale sources: design mode's panzoom-wrap transform and edit mode's content-zoom counter-scale
|
|
3631
|
+
* (where it evaluates to exactly `editZoom` — the iframe's layout width is `renderWidth / editZoom`
|
|
3632
|
+
* while its rendered width is `renderWidth`).
|
|
3633
|
+
*/
|
|
3634
|
+
export function getEditBarAnchorRect(): OverlayPlacement | null {
|
|
3635
|
+
// The bar rests on the SELECTED ELEMENT's box, edit session or not. It used to prefer the caret's
|
|
3636
|
+
// Snapshot rect while editing, so it hopped line to line with the caret and sat over the text the
|
|
3637
|
+
// Author was typing; the snapshot still feeds the format state, never the position. Only an edit
|
|
3638
|
+
// Session with no measured element yet falls back to the caret rect.
|
|
3554
3639
|
const editHost = activeEditHost;
|
|
3555
3640
|
const host = editHost ?? hostForActivePanel();
|
|
3556
3641
|
if (!host) {
|
|
3557
3642
|
return null;
|
|
3558
3643
|
}
|
|
3559
3644
|
const { rect: ifr, scale } = hostDragGeometry(host);
|
|
3645
|
+
if (host.lastSelectionRect) {
|
|
3646
|
+
// Overlay-local (same top-left + coordinate space as the iframe viewport).
|
|
3647
|
+
return {
|
|
3648
|
+
height: host.lastSelectionRect.height * scale,
|
|
3649
|
+
left: host.lastSelectionRect.left * scale + ifr.left,
|
|
3650
|
+
top: host.lastSelectionRect.top * scale + ifr.top,
|
|
3651
|
+
width: host.lastSelectionRect.width * scale,
|
|
3652
|
+
};
|
|
3653
|
+
}
|
|
3560
3654
|
const snapRect = host === editHost ? host.snapshot?.rect : null;
|
|
3561
3655
|
if (snapRect) {
|
|
3562
3656
|
return {
|
|
@@ -3566,14 +3660,5 @@ export function getEditBarAnchorRect(): ParentRect | null {
|
|
|
3566
3660
|
width: snapRect.width * scale,
|
|
3567
3661
|
};
|
|
3568
3662
|
}
|
|
3569
|
-
if (host.lastSelectionRect) {
|
|
3570
|
-
// The fallback rect is overlay-local (same top-left + coordinate space as the iframe viewport).
|
|
3571
|
-
return {
|
|
3572
|
-
height: host.lastSelectionRect.height * scale,
|
|
3573
|
-
left: host.lastSelectionRect.left * scale + ifr.left,
|
|
3574
|
-
top: host.lastSelectionRect.top * scale + ifr.top,
|
|
3575
|
-
width: host.lastSelectionRect.width * scale,
|
|
3576
|
-
};
|
|
3577
|
-
}
|
|
3578
3663
|
return null;
|
|
3579
3664
|
}
|