@jxsuite/studio 6.1.1 → 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-va2wwra4.js → 2020-f2gkpy8d.js} +3 -3
- 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-2veqmnhr.js → index-zpjmzqfk.js} +3 -3
- package/dist/chunks/{javascript-8nbvs12s.js → javascript-m54mnwp6.js} +3 -3
- package/dist/chunks/{jsonMode-s8kt9dsj.js → jsonMode-w15cmrcm.js} +8 -8
- 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-1q1sh2ax.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-h46vtzk8.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-rv11kfwa.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-8grwxtqk.js → studio-90pq9km1.js} +4 -4
- package/dist/chunks/studio-924p1tm1.js +6 -0
- package/dist/chunks/{studio-pre0skq6.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-vrmcjf9g.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-wszjyh0j.js → studio-tq0rtfwj.js} +4 -4
- package/dist/chunks/{studio-kggey1jt.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-zey7zsdw.js → studio-y64hrt8p.js} +7 -7
- 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-2frah6h1.js → tsMode-sf49ee9x.js} +7 -7
- 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 +97 -97
- package/package.json +6 -6
- 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 +62 -41
- package/src/canvas/canvas-surface.ts +5 -3
- package/src/canvas/canvas-utils.ts +90 -49
- 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 +135 -96
- package/src/canvas/iframe-inline-edit.ts +49 -30
- package/src/canvas/iframe-insert.ts +5 -4
- package/src/canvas/iframe-interaction.ts +30 -25
- 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 +12 -16
- package/src/canvas/iframe-render.ts +36 -34
- 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/keymap.ts +47 -43
- package/src/commands/levels.ts +3 -3
- package/src/commands/live-context.ts +7 -7
- 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 +32 -20
- 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 +3 -0
- 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 +52 -21
- 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 +218 -205
- 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 +129 -117
- 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 +25 -75
- 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 +19 -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.ts +13 -13
- 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/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 +73 -73
- 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 +40 -36
- package/dist/chunks/adapter-f93pafd7.js +0 -4
- package/dist/chunks/cf-account-picker-af1h381v.js +0 -4
- package/dist/chunks/cf-settings-125tdm0w.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-ax2f1fnn.js +0 -4
- package/dist/chunks/content-source-108aqtk1.js +0 -4
- package/dist/chunks/convert-to-repeater-ry5rmppr.js +0 -4
- package/dist/chunks/dialog-mtm9fq5t.js +0 -4
- package/dist/chunks/editor-pfgdmkb0.js +0 -4
- package/dist/chunks/entry-commands-t0k1q0kx.js +0 -4
- package/dist/chunks/extension-sections-6mwh2hf8.js +0 -4
- package/dist/chunks/file-ops-meej5mqf.js +0 -4
- package/dist/chunks/files-44vp8a2s.js +0 -4
- package/dist/chunks/format-host-7q1petb9.js +0 -4
- package/dist/chunks/fs-events-h2mwnxaz.js +0 -4
- package/dist/chunks/git-panel-zngbymvd.js +0 -4
- package/dist/chunks/grid-view-sx9vynsp.js +0 -51
- package/dist/chunks/icons-p44xhjf0.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-qk3ycq87.js +0 -4
- package/dist/chunks/index-wkyfjeqz.js +0 -4
- package/dist/chunks/jx-validate-psgd7vsx.js +0 -4
- package/dist/chunks/layers-panel-1kq2jyfk.js +0 -4
- package/dist/chunks/layers-xd92fg8d.js +0 -4
- package/dist/chunks/listbox-s8fkmnq8.js +0 -4
- package/dist/chunks/lit-html-ac4cwwr4.js +0 -4
- package/dist/chunks/media-picker-0svzkdyb.js +0 -4
- package/dist/chunks/menu-37d07z9m.js +0 -4
- package/dist/chunks/menu-5c55ea3d.js +0 -4
- package/dist/chunks/monaco-binding-z6r70pdt.js +0 -4
- package/dist/chunks/monaco-buffer-fz6gq5y7.js +0 -4
- package/dist/chunks/monaco-setup-q4axkgj7.js +0 -4
- package/dist/chunks/notify-0xgtn8q1.js +0 -4
- package/dist/chunks/number-field-gw7sq8rn.js +0 -4
- package/dist/chunks/parse-897fvqah.js +0 -4
- package/dist/chunks/platform-v1qctbe6.js +0 -4
- package/dist/chunks/popover-8htra4er.js +0 -4
- package/dist/chunks/publish-panel-ym1fmgq5.js +0 -4
- package/dist/chunks/quick-search-a54e6t5n.js +0 -4
- package/dist/chunks/references-gmqp82fs.js +0 -4
- package/dist/chunks/right-panel-v7t9awbk.js +0 -4
- package/dist/chunks/section-registry-vhyf3zsr.js +0 -4
- package/dist/chunks/select-n3v7gwas.js +0 -4
- package/dist/chunks/split-pff8f3ze.js +0 -4
- package/dist/chunks/studio-0bhx5hz6.js +0 -5
- package/dist/chunks/studio-0k1ddnyy.js +0 -6
- package/dist/chunks/studio-1b04pd0j.js +0 -64
- package/dist/chunks/studio-4dwbj6gb.js +0 -5
- package/dist/chunks/studio-4tanh828.js +0 -5
- package/dist/chunks/studio-55h4mstj.js +0 -4
- package/dist/chunks/studio-5tnvjkz4.js +0 -5
- package/dist/chunks/studio-60dqgb0c.js +0 -5
- package/dist/chunks/studio-61dp09qg.js +0 -9
- package/dist/chunks/studio-63epcrj2.js +0 -5
- package/dist/chunks/studio-74k29dy9.js +0 -5
- package/dist/chunks/studio-7vg6jcd3.js +0 -5
- package/dist/chunks/studio-7zx31knw.js +0 -9
- package/dist/chunks/studio-8bxk97km.js +0 -5
- package/dist/chunks/studio-933e30n4.js +0 -5
- package/dist/chunks/studio-98wnwhbg.js +0 -5
- package/dist/chunks/studio-9mccjwjh.js +0 -14
- package/dist/chunks/studio-a2ke1e4t.js +0 -5
- package/dist/chunks/studio-e3a2a6v3.js +0 -4
- package/dist/chunks/studio-e81q1vb9.js +0 -5
- package/dist/chunks/studio-epgrmqqm.js +0 -5
- package/dist/chunks/studio-ery42sqr.js +0 -4
- package/dist/chunks/studio-g1shz58g.js +0 -5
- package/dist/chunks/studio-gf0fz03c.js +0 -5
- package/dist/chunks/studio-gjtpe62q.js +0 -6
- package/dist/chunks/studio-gkskhg7m.js +0 -5
- package/dist/chunks/studio-gx4dnjzd.js +0 -5
- package/dist/chunks/studio-j03zga3y.js +0 -9
- package/dist/chunks/studio-jhpxeckz.js +0 -5
- package/dist/chunks/studio-k01r7ykp.js +0 -5
- package/dist/chunks/studio-kk7h30ne.js +0 -7
- package/dist/chunks/studio-kt1zqney.js +0 -5
- package/dist/chunks/studio-m3cwhvye.js +0 -5
- package/dist/chunks/studio-mcayt6hz.js +0 -5
- package/dist/chunks/studio-myjcghv3.js +0 -5
- package/dist/chunks/studio-n8bxwc3y.js +0 -4
- package/dist/chunks/studio-ngm8gvpb.js +0 -5
- package/dist/chunks/studio-nj5a01jy.js +0 -928
- package/dist/chunks/studio-pcgz8heb.js +0 -5
- package/dist/chunks/studio-qcsq0t15.js +0 -5
- package/dist/chunks/studio-qkstvve9.js +0 -5
- package/dist/chunks/studio-qv1pwd3c.js +0 -5
- package/dist/chunks/studio-rc6dvxjb.js +0 -7
- package/dist/chunks/studio-s8dmmz66.js +0 -5
- package/dist/chunks/studio-sp5xzbj4.js +0 -6
- package/dist/chunks/studio-szsjbj0g.js +0 -5
- package/dist/chunks/studio-t1xzawhr.js +0 -16
- package/dist/chunks/studio-t6b6qe31.js +0 -5
- package/dist/chunks/studio-tdcprbqb.js +0 -5
- package/dist/chunks/studio-vyc0b4he.js +0 -10
- package/dist/chunks/studio-w0cgf6jg.js +0 -5
- package/dist/chunks/studio-w3hskzqk.js +0 -5
- package/dist/chunks/studio-xgrgcdyh.js +0 -9
- package/dist/chunks/studio-xz2yxfcb.js +0 -5
- package/dist/chunks/studio-y6n42tgs.js +0 -5
- package/dist/chunks/studio-yb560vxr.js +0 -5
- package/dist/chunks/studio-yn9f8vtx.js +0 -5
- package/dist/chunks/studio-yw05w8f0.js +0 -7
- package/dist/chunks/studio-z16sgavc.js +0 -5
- package/dist/chunks/studio-zyqn40w4.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/workspace-zt81g1ms.js +0 -4
- package/dist/chunks/ws-client-n2bh4hkf.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];
|
|
112
|
+
|
|
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
|
+
}
|
|
80
125
|
|
|
81
|
-
|
|
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,7 @@ 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;
|
|
161
213
|
/** The node the pointer last hovered (iframe-viewport rect), so a zoom can hold it still. */
|
|
162
214
|
lastHover: NodeHit | null;
|
|
163
215
|
/**
|
|
@@ -228,13 +280,7 @@ interface HostState {
|
|
|
228
280
|
* render acks (`renderComplete`) at a bumped one — both satisfy `gen >= minGen`. An immediate
|
|
229
281
|
* `enterEdit` would race the escalated ASYNC render and silently fail to find the element.
|
|
230
282
|
*/
|
|
231
|
-
pendingEnterEdit:
|
|
232
|
-
path: (string | number)[];
|
|
233
|
-
minGen: number;
|
|
234
|
-
offset?: number;
|
|
235
|
-
/** Set when the deferred re-entry is a PROP host rather than a block (see deferEnterEdit). */
|
|
236
|
-
prop?: string;
|
|
237
|
-
} | null;
|
|
283
|
+
pendingEnterEdit: PendingEnterEdit | null;
|
|
238
284
|
/**
|
|
239
285
|
* Stylebook capability (set by {@link mountStylebookCanvas}, cleared by page mounts). The specimen
|
|
240
286
|
* doc's paths decode to TAGS, not tab-document paths: hits route to the injected stylebook
|
|
@@ -250,13 +296,6 @@ interface HostState {
|
|
|
250
296
|
panReqId: number;
|
|
251
297
|
}
|
|
252
298
|
|
|
253
|
-
/**
|
|
254
|
-
* Opaque drag-target host handle for the coordinator bridge. The bridge passes it back to the
|
|
255
|
-
* session API ({@link beginDragSession}/{@link hostDragGeometry}/{@link postDragMessage}) without
|
|
256
|
-
* reading its fields.
|
|
257
|
-
*/
|
|
258
|
-
export type DragHost = HostState;
|
|
259
|
-
|
|
260
299
|
const hosts = new WeakMap<HTMLElement, HostState>();
|
|
261
300
|
|
|
262
301
|
/** Every live host, so the selection watcher can re-measure each one when selection changes. */
|
|
@@ -271,7 +310,7 @@ const liveHosts = new Set<HostState>();
|
|
|
271
310
|
let currentDragSeq = 0;
|
|
272
311
|
|
|
273
312
|
/** Parent-retained source data keyed by `dragSeq` (the block fragment never crosses the boundary). */
|
|
274
|
-
const retainedSrcData = new Map<number,
|
|
313
|
+
const retainedSrcData = new Map<number, RetainedDragData>();
|
|
275
314
|
|
|
276
315
|
/**
|
|
277
316
|
* The last session whose cursor-carrying `dragOver` arrived FROM an iframe, and when. While a
|
|
@@ -421,9 +460,10 @@ export function requestCanvasEval(
|
|
|
421
460
|
}
|
|
422
461
|
evalReqId += 1;
|
|
423
462
|
const reqId = evalReqId;
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
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 }[];
|
|
427
467
|
target.channel.post({
|
|
428
468
|
contextPath: contextPath ? [...contextPath] : null,
|
|
429
469
|
exprs: wireExprs,
|
|
@@ -541,7 +581,7 @@ export function liveDragHostAt(cursor: { x: number; y: number }): HostState | nu
|
|
|
541
581
|
export function beginDragSession(
|
|
542
582
|
host: HostState,
|
|
543
583
|
src: DragSrcKind,
|
|
544
|
-
srcData:
|
|
584
|
+
srcData: RetainedDragData,
|
|
545
585
|
): number {
|
|
546
586
|
currentDragSeq += 1;
|
|
547
587
|
retainedSrcData.set(currentDragSeq, srcData);
|
|
@@ -569,7 +609,7 @@ export function beginDragSession(
|
|
|
569
609
|
export function adoptDragSession(
|
|
570
610
|
_host: HostState,
|
|
571
611
|
_src: DragSrcKind,
|
|
572
|
-
srcData:
|
|
612
|
+
srcData: RetainedDragData,
|
|
573
613
|
seq: number,
|
|
574
614
|
): number {
|
|
575
615
|
currentDragSeq = seq;
|
|
@@ -587,10 +627,7 @@ export function currentDragSession(): number {
|
|
|
587
627
|
* read FRESH so a pan/zoom mid-drag is reflected. NOT `effectiveZoom()` (a separate path that can
|
|
588
628
|
* desync). The matching iframe parent-viewport rect is returned so the cursor map cancels the pan.
|
|
589
629
|
*/
|
|
590
|
-
export function hostDragGeometry(host: HostState): {
|
|
591
|
-
scale: number;
|
|
592
|
-
rect: { left: number; top: number };
|
|
593
|
-
} {
|
|
630
|
+
export function hostDragGeometry(host: HostState): DragGeometry {
|
|
594
631
|
const rect = rectOf(host.iframe);
|
|
595
632
|
const scale = host.iframe.clientWidth > 0 ? rect.width / host.iframe.clientWidth : 1;
|
|
596
633
|
return { rect, scale };
|
|
@@ -1317,7 +1354,7 @@ export function postDialogOpen(tab: { id: string }, path: JxPath | null): void {
|
|
|
1317
1354
|
* `host` is deliberately not a pane-scoped parameter name (see `PANE_PARAM_NAMES`), and the body
|
|
1318
1355
|
* reads no focus: `panelHostingCanvas` resolves the stage from the host's own element.
|
|
1319
1356
|
*/
|
|
1320
|
-
export function postPatchToHosts(forwardOps:
|
|
1357
|
+
export function postPatchToHosts(forwardOps: JxDocOp[], tabId: string | null): number {
|
|
1321
1358
|
let posted = 0;
|
|
1322
1359
|
for (const host of liveHosts) {
|
|
1323
1360
|
if (!host.iframe.isConnected) {
|
|
@@ -1457,14 +1494,14 @@ function hostTab(state: HostState): Tab | null {
|
|
|
1457
1494
|
}
|
|
1458
1495
|
|
|
1459
1496
|
/**
|
|
1460
|
-
* 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.
|
|
1461
1498
|
*
|
|
1462
1499
|
* `panels/canvas-dnd-bridge.ts` binds a session to the host under the cursor and then had nothing
|
|
1463
1500
|
* to ask it, so the one fact it needed about the drag — what the dragged node is CALLED — came from
|
|
1464
1501
|
* `activeTab`. The bridge is not supposed to read the handle's fields (that is what "opaque"
|
|
1465
1502
|
* means), so the answer is a function rather than a widened type.
|
|
1466
1503
|
*/
|
|
1467
|
-
export function dragHostTab(host:
|
|
1504
|
+
export function dragHostTab(host: HostState): Tab | null {
|
|
1468
1505
|
return hostTab(host);
|
|
1469
1506
|
}
|
|
1470
1507
|
|
|
@@ -1499,7 +1536,7 @@ function shownSelections(): Map<string, readonly JxPath[]> {
|
|
|
1499
1536
|
if (!tab) {
|
|
1500
1537
|
continue;
|
|
1501
1538
|
}
|
|
1502
|
-
const sel =
|
|
1539
|
+
const sel: readonly JxPath[] = tab.session.selection;
|
|
1503
1540
|
// Track the selection deeply enough that a change WITHIN the set re-measures: the effect
|
|
1504
1541
|
// Reads every path, not just the array reference.
|
|
1505
1542
|
void sel.map((path) => path.join("/")).join("|");
|
|
@@ -1698,7 +1735,7 @@ function requestSelection(host: HostState, sel: readonly JxPath[]): void {
|
|
|
1698
1735
|
}
|
|
1699
1736
|
const primary = primarySelection(sel);
|
|
1700
1737
|
host.selectionPath = primary;
|
|
1701
|
-
host.selectionPaths = sel
|
|
1738
|
+
host.selectionPaths = sel;
|
|
1702
1739
|
if (!host.iframe.isConnected) {
|
|
1703
1740
|
liveHosts.delete(host);
|
|
1704
1741
|
return;
|
|
@@ -2017,7 +2054,7 @@ function hideInsertZoneNow(state: HostState): void {
|
|
|
2017
2054
|
*/
|
|
2018
2055
|
function insertButtonHovered(state: HostState): boolean {
|
|
2019
2056
|
const btn = state.overlay.insertButton;
|
|
2020
|
-
return state.insertHover ||
|
|
2057
|
+
return state.insertHover || btn.matches(":hover");
|
|
2021
2058
|
}
|
|
2022
2059
|
|
|
2023
2060
|
/**
|
|
@@ -2173,7 +2210,8 @@ function handleMessage(state: HostState, msg: IframeToParent): void {
|
|
|
2173
2210
|
behind that message with it. The null check is the same guard for a `targetPath` an edit
|
|
2174
2211
|
has since invalidated, which threw for the same reason. */
|
|
2175
2212
|
const target = getNodeAtPath(tab.doc.document, msg.targetPath);
|
|
2176
|
-
|
|
2213
|
+
// A path can resolve to a string child or to nothing at all, whatever the declared type says.
|
|
2214
|
+
if (!isNodeObject(target)) {
|
|
2177
2215
|
return;
|
|
2178
2216
|
}
|
|
2179
2217
|
if (POPOVER_COMMANDS.has(msg.command)) {
|
|
@@ -2370,7 +2408,7 @@ function handleMessage(state: HostState, msg: IframeToParent): void {
|
|
|
2370
2408
|
// The iframe could not resolve is simply absent from `hits`.
|
|
2371
2409
|
const primaryKey = JSON.stringify(state.selectionPath);
|
|
2372
2410
|
const co: OverlayPlacement[] = [];
|
|
2373
|
-
let rect:
|
|
2411
|
+
let rect: OverlayPlacement | null = null;
|
|
2374
2412
|
if (state.stylebook) {
|
|
2375
2413
|
const [hit] = msg.hits;
|
|
2376
2414
|
rect = hit ? canvasRectToParent(hit.rect) : null;
|
|
@@ -2762,9 +2800,8 @@ function handleMessage(state: HostState, msg: IframeToParent): void {
|
|
|
2762
2800
|
const { rect: ifr, scale } = hostDragGeometry(state);
|
|
2763
2801
|
const left = msg.rect.x * scale + ifr.left;
|
|
2764
2802
|
const top = msg.rect.y * scale + ifr.top;
|
|
2765
|
-
|
|
2803
|
+
const request: CanvasSlashRequest = {
|
|
2766
2804
|
filter: msg.filter,
|
|
2767
|
-
...(msg.showFilter === true ? { showFilter: true } : {}),
|
|
2768
2805
|
onDismiss: () => state.channel.post({ kind: "slashDismissed" }),
|
|
2769
2806
|
onSelect: (cmd) => state.channel.post({ cmd: { ...cmd }, kind: "slashSelect" }),
|
|
2770
2807
|
rect: {
|
|
@@ -2774,7 +2811,11 @@ function handleMessage(state: HostState, msg: IframeToParent): void {
|
|
|
2774
2811
|
top,
|
|
2775
2812
|
width: msg.rect.width * scale,
|
|
2776
2813
|
},
|
|
2777
|
-
}
|
|
2814
|
+
};
|
|
2815
|
+
if (msg.showFilter === true) {
|
|
2816
|
+
request.showFilter = true;
|
|
2817
|
+
}
|
|
2818
|
+
canvasSlashHandler?.show(request);
|
|
2778
2819
|
return;
|
|
2779
2820
|
}
|
|
2780
2821
|
case "slashNav": {
|
|
@@ -2871,12 +2912,14 @@ function deferEnterEdit(
|
|
|
2871
2912
|
offset?: number,
|
|
2872
2913
|
prop?: string,
|
|
2873
2914
|
): void {
|
|
2874
|
-
state.
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
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;
|
|
2880
2923
|
}
|
|
2881
2924
|
|
|
2882
2925
|
/** Ask the host's iframe to (re-)enter inline editing on `path` (a plain copy crosses the bridge). */
|
|
@@ -2886,12 +2929,14 @@ function reenterEdit(
|
|
|
2886
2929
|
offset?: number,
|
|
2887
2930
|
prop?: string,
|
|
2888
2931
|
): void {
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
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);
|
|
2895
2940
|
}
|
|
2896
2941
|
|
|
2897
2942
|
/**
|
|
@@ -3087,11 +3132,9 @@ function preparePassRender(
|
|
|
3087
3132
|
// So a JSON round-trip (NOT structuredClone, which would throw) drops residual functions /
|
|
3088
3133
|
// Reactive proxy artifacts that would otherwise raise DataCloneError and silently drop the
|
|
3089
3134
|
// Entire message.
|
|
3090
|
-
|
|
3091
|
-
const cloneableDoc = JSON.parse(JSON.stringify(resolved.renderDoc)) as unknown;
|
|
3135
|
+
const cloneableDoc = plainCopy(resolved.renderDoc);
|
|
3092
3136
|
// The RAW page doc (forward-op + data-jx-path coordinate space) crosses as the shadow doc.
|
|
3093
|
-
|
|
3094
|
-
const cloneableShadow = JSON.parse(JSON.stringify(doc)) as unknown;
|
|
3137
|
+
const cloneableShadow = plainCopy(doc);
|
|
3095
3138
|
// Which tags can hold a caret depends on the document's vocabulary, so the format's verdicts
|
|
3096
3139
|
// Ride with the render rather than being baked into the frame. Absent for a native document,
|
|
3097
3140
|
// Where the studio's own element metadata answers on its own.
|
|
@@ -3101,21 +3144,27 @@ function preparePassRender(
|
|
|
3101
3144
|
const renderTab = tabId ? (workspace.tabs.get(tabId) ?? null) : null;
|
|
3102
3145
|
const formatElements = formatByName(renderTab?.doc.sourceFormat)?.studio?.elements;
|
|
3103
3146
|
const editableTags = formatElements ? formatEditableVerdicts(formatElements) : undefined;
|
|
3104
|
-
|
|
3147
|
+
const prepared: PreparedRender = {
|
|
3105
3148
|
assets: resolved.assets,
|
|
3106
3149
|
doc: cloneableDoc,
|
|
3107
3150
|
docBase: resolved.docBase ?? `${canvasBaseOrigin()}/`,
|
|
3108
3151
|
mapperCtx: resolved.mapperCtx,
|
|
3109
|
-
/*
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
`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. */
|
|
3113
3157
|
mode: resolved.mapperCtx.canvasMode as CanvasMode,
|
|
3114
3158
|
shadowDoc: cloneableShadow,
|
|
3115
3159
|
siteStyle: resolved.siteStyle,
|
|
3116
|
-
...(editableTags ? { editableTags } : {}),
|
|
3117
|
-
...(allowAutoRequests ? { allowAutoRequests: true } : {}),
|
|
3118
3160
|
};
|
|
3161
|
+
if (editableTags) {
|
|
3162
|
+
prepared.editableTags = editableTags;
|
|
3163
|
+
}
|
|
3164
|
+
if (allowAutoRequests) {
|
|
3165
|
+
prepared.allowAutoRequests = true;
|
|
3166
|
+
}
|
|
3167
|
+
return prepared;
|
|
3119
3168
|
});
|
|
3120
3169
|
byDoc.set(doc, { mode: modeOverride, payload, tabId, viewTabId });
|
|
3121
3170
|
return payload;
|
|
@@ -3180,18 +3229,12 @@ export async function mountIframeCanvas(
|
|
|
3180
3229
|
paneOfContainer(canvasEl),
|
|
3181
3230
|
modeOverride,
|
|
3182
3231
|
);
|
|
3183
|
-
const message:
|
|
3232
|
+
const message: RenderMsg = {
|
|
3184
3233
|
...prepared,
|
|
3185
3234
|
// Per-TAB, and read at POST time so a scheme flip that raced the shared resolution is not
|
|
3186
3235
|
// Baked into the payload every host shares. `viewTab` is this artboard's tab — defaulted from
|
|
3187
3236
|
// `tabOfContainer(canvasEl)`, the same route the rest of this mount takes.
|
|
3188
3237
|
colorScheme: schemeWireFor(viewTab),
|
|
3189
|
-
/* Per-ARTBOARD, and post-time for a sharper version of the same reason. `preparePassRender`
|
|
3190
|
-
memoizes on the document and hands the SAME payload object to every host in the pass, and a
|
|
3191
|
-
git-diff pass has two hosts holding two documents — but marks are a function of BOTH sides,
|
|
3192
|
-
not of the document this host draws, so they are not derivable from that cache key at all.
|
|
3193
|
-
Baking them in would make the two artboards race for whose marks the pass kept. */
|
|
3194
|
-
...(diffMarks ? { diffMarks } : {}),
|
|
3195
3238
|
gen,
|
|
3196
3239
|
kind: "render",
|
|
3197
3240
|
// Read at POST time for the same reason `colorScheme` is: a render replaces the DOM, so a panel
|
|
@@ -3199,6 +3242,15 @@ export async function mountIframeCanvas(
|
|
|
3199
3242
|
popoverOpen: viewTab?.session.ui.openPopover ?? null,
|
|
3200
3243
|
dialogOpen: viewTab?.session.ui.openDialog ?? null,
|
|
3201
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
|
+
}
|
|
3202
3254
|
state.popoverOpen = message.popoverOpen ?? null;
|
|
3203
3255
|
state.dialogOpen = message.dialogOpen ?? null;
|
|
3204
3256
|
// Preview is the fidelity view: no editing messages are honoured from it, no overlay is painted
|
|
@@ -3250,10 +3302,8 @@ export function mountStylebookCanvas(
|
|
|
3250
3302
|
state.iframe.style.width = widthPx ? `${widthPx}px` : "100%";
|
|
3251
3303
|
// Two independent plain clones: the iframe renders `doc` and folds styleUpdates into `shadowDoc`
|
|
3252
3304
|
// (and fake test channels pass messages by reference, so sharing one object would alias them).
|
|
3253
|
-
|
|
3254
|
-
const
|
|
3255
|
-
// oxlint-disable-next-line unicorn/prefer-structured-clone
|
|
3256
|
-
const cloneableShadow = JSON.parse(JSON.stringify(generated.doc)) as unknown;
|
|
3305
|
+
const cloneableDoc = plainCopy(generated.doc);
|
|
3306
|
+
const cloneableShadow = plainCopy(generated.doc);
|
|
3257
3307
|
const message: ParentToIframe = {
|
|
3258
3308
|
// The specimen carries no tab identity, but the STAGE it is mounted into does: a stylebook is
|
|
3259
3309
|
// Opened as a tab like anything else, and its `previewColorScheme` is that tab's.
|
|
@@ -3371,8 +3421,7 @@ export function postLocaleToLiveHosts(locale: string | null, root?: HTMLElement
|
|
|
3371
3421
|
* off a tab's reactive record is a proxy, and a proxy cannot be structured-cloned.
|
|
3372
3422
|
*/
|
|
3373
3423
|
export function postRedefineElementToLiveHosts(doc: JxMutableNode, base: string): number {
|
|
3374
|
-
|
|
3375
|
-
const plain = JSON.parse(JSON.stringify(doc)) as JxMutableNode;
|
|
3424
|
+
const plain = plainCopy(doc);
|
|
3376
3425
|
let posted = 0;
|
|
3377
3426
|
for (const host of liveHosts) {
|
|
3378
3427
|
if (!host.iframe.isConnected) {
|
|
@@ -3398,13 +3447,8 @@ export function postSiteStyleToLiveHosts(): void {
|
|
|
3398
3447
|
return;
|
|
3399
3448
|
}
|
|
3400
3449
|
// Site config comes off a reactive store — only plain values may cross postMessage.
|
|
3401
|
-
|
|
3402
|
-
const
|
|
3403
|
-
string,
|
|
3404
|
-
unknown
|
|
3405
|
-
> | null;
|
|
3406
|
-
// oxlint-disable-next-line unicorn/prefer-structured-clone
|
|
3407
|
-
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 ?? {});
|
|
3408
3452
|
for (const host of liveHosts) {
|
|
3409
3453
|
if (!host.iframe.isConnected) {
|
|
3410
3454
|
liveHosts.delete(host);
|
|
@@ -3422,11 +3466,10 @@ export function postSiteStyleToLiveHosts(): void {
|
|
|
3422
3466
|
* received it — zero means no stylebook iframe is live yet and the caller should fall through to a
|
|
3423
3467
|
* full render. Each post is followed by a selection re-measure so the box tracks the reflow.
|
|
3424
3468
|
*/
|
|
3425
|
-
export function postStyleUpdateToStylebookHosts(style:
|
|
3469
|
+
export function postStyleUpdateToStylebookHosts(style: JxStyle): number {
|
|
3426
3470
|
let posted = 0;
|
|
3427
3471
|
// Style objects come off the reactive doc — only plain values may cross postMessage.
|
|
3428
|
-
|
|
3429
|
-
const cloneable = JSON.parse(JSON.stringify(style)) as Record<string, unknown>;
|
|
3472
|
+
const cloneable = plainCopy(style);
|
|
3430
3473
|
for (const host of liveHosts) {
|
|
3431
3474
|
if (!host.iframe.isConnected) {
|
|
3432
3475
|
liveHosts.delete(host);
|
|
@@ -3462,12 +3505,8 @@ export function panToStylebookTag(tag: string): void {
|
|
|
3462
3505
|
|
|
3463
3506
|
// ─── Format-toolbar bridge (Phase 4b-2) ─────────────────────────────────────────
|
|
3464
3507
|
|
|
3465
|
-
/** The current edit session's
|
|
3466
|
-
export function getEditSnapshot(): {
|
|
3467
|
-
editing: boolean;
|
|
3468
|
-
editingProp: string | null;
|
|
3469
|
-
snapshot: SelectionSnapshot | null;
|
|
3470
|
-
} {
|
|
3508
|
+
/** The current edit session's state, for the parent toolbar. */
|
|
3509
|
+
export function getEditSnapshot(): EditSnapshotState {
|
|
3471
3510
|
/* The same connectivity guard {@link isCaretActive} has, and for the same reason: a session
|
|
3472
3511
|
belongs to a frame, and a frame that has left the document has no caret in it. `releaseHost`
|
|
3473
3512
|
clears `activeEditHost`, so this is the second line rather than the first — it covers the frame
|
|
@@ -3578,7 +3617,7 @@ export function commitActiveEditSession(): void {
|
|
|
3578
3617
|
/** The live host backing the active panel's canvas (for non-edit selection-bar positioning). */
|
|
3579
3618
|
function hostForActivePanel(): HostState | null {
|
|
3580
3619
|
const panel = getActivePanel();
|
|
3581
|
-
return panel ? hostForCanvas(panel.canvas
|
|
3620
|
+
return panel ? hostForCanvas(panel.canvas) : null;
|
|
3582
3621
|
}
|
|
3583
3622
|
|
|
3584
3623
|
/**
|
|
@@ -3592,7 +3631,7 @@ function hostForActivePanel(): HostState | null {
|
|
|
3592
3631
|
* (where it evaluates to exactly `editZoom` — the iframe's layout width is `renderWidth / editZoom`
|
|
3593
3632
|
* while its rendered width is `renderWidth`).
|
|
3594
3633
|
*/
|
|
3595
|
-
export function getEditBarAnchorRect():
|
|
3634
|
+
export function getEditBarAnchorRect(): OverlayPlacement | null {
|
|
3596
3635
|
// The bar rests on the SELECTED ELEMENT's box, edit session or not. It used to prefer the caret's
|
|
3597
3636
|
// Snapshot rect while editing, so it hopped line to line with the caret and sat over the text the
|
|
3598
3637
|
// Author was typing; the snapshot still feeds the format state, never the position. Only an edit
|
|
@@ -51,11 +51,21 @@ import type {
|
|
|
51
51
|
SerializableRect,
|
|
52
52
|
} from "./iframe-protocol";
|
|
53
53
|
import type { DocPos } from "./iframe-position";
|
|
54
|
+
import { isNonNullObject, isString } from "@jxsuite/schema/guards";
|
|
54
55
|
import type { JxPath } from "../state";
|
|
55
56
|
import type { JxMutableNode } from "@jxsuite/schema/types";
|
|
56
57
|
|
|
58
|
+
/** The commit a block session posts when its text reaches the document. */
|
|
59
|
+
type EditCommitMsg = Extract<IframeToParent, { kind: "editCommit" }>;
|
|
60
|
+
|
|
61
|
+
/** The commit a prop-bound session posts for its instance's `$props` value. */
|
|
62
|
+
type EditCommitPropMsg = Extract<IframeToParent, { kind: "editCommitProp" }>;
|
|
63
|
+
|
|
64
|
+
/** The toolbar commands that toggle an inline tag (every intent but `link` and `insertData`). */
|
|
65
|
+
type InlineFormatCommand = Exclude<ApplyFormatIntent["command"], "link" | "insertData">;
|
|
66
|
+
|
|
57
67
|
/** Toolbar command → inline tag (mirrors the parent's old `cmdToTag`, now iframe-side). */
|
|
58
|
-
const CMD_TO_TAG
|
|
68
|
+
const CMD_TO_TAG = {
|
|
59
69
|
bold: "strong",
|
|
60
70
|
code: "code",
|
|
61
71
|
italic: "em",
|
|
@@ -63,7 +73,19 @@ const CMD_TO_TAG: Record<string, string> = {
|
|
|
63
73
|
subscript: "sub",
|
|
64
74
|
superscript: "sup",
|
|
65
75
|
underline: "u",
|
|
66
|
-
}
|
|
76
|
+
} satisfies Record<InlineFormatCommand, string>;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* The CSS Custom Highlight API as this realm may or may not provide it. lib.dom declares both
|
|
80
|
+
* members unconditionally, but happy-dom and non-Chromium engines ship neither.
|
|
81
|
+
*/
|
|
82
|
+
interface HighlightRealm {
|
|
83
|
+
Highlight?: typeof Highlight;
|
|
84
|
+
CSS?: { highlights?: HighlightRegistry };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** The global object, read through the optional shape above so the feature probes stay honest. */
|
|
88
|
+
const highlightRealm: HighlightRealm = globalThis;
|
|
67
89
|
|
|
68
90
|
/** Inline tags whose active state the snapshot reports (everything except `a`, handled via link). */
|
|
69
91
|
const ACTIVE_TAG_PROBES = ["strong", "em", "u", "del", "sub", "sup", "code"];
|
|
@@ -125,19 +147,19 @@ function deliveredOutsideProps(node: JxMutableNode | undefined, prop: string): b
|
|
|
125
147
|
if (!node) {
|
|
126
148
|
return false;
|
|
127
149
|
}
|
|
128
|
-
const attrs = node.attributes
|
|
150
|
+
const attrs = node.attributes;
|
|
129
151
|
if (attrs) {
|
|
130
152
|
if (attrs[`props.${prop}`] !== undefined) {
|
|
131
153
|
return true;
|
|
132
154
|
}
|
|
133
155
|
const reflected = new Set([prop.toLowerCase(), camelToKebab(prop).toLowerCase()]);
|
|
134
|
-
for (const
|
|
135
|
-
if (
|
|
156
|
+
for (const name of Object.keys(attrs)) {
|
|
157
|
+
if (attrs[name] !== undefined && reflected.has(name.toLowerCase())) {
|
|
136
158
|
return true;
|
|
137
159
|
}
|
|
138
160
|
}
|
|
139
161
|
const payload = attrs["data-jx-props"];
|
|
140
|
-
if (
|
|
162
|
+
if (isString(payload) && payloadNames(payload, prop)) {
|
|
141
163
|
return true;
|
|
142
164
|
}
|
|
143
165
|
}
|
|
@@ -145,14 +167,14 @@ function deliveredOutsideProps(node: JxMutableNode | undefined, prop: string): b
|
|
|
145
167
|
if (RESERVED_KEYS.has(prop) || prop.startsWith("$")) {
|
|
146
168
|
return false;
|
|
147
169
|
}
|
|
148
|
-
return
|
|
170
|
+
return node[prop] !== undefined;
|
|
149
171
|
}
|
|
150
172
|
|
|
151
173
|
/** Whether a `data-jx-props` JSON payload carries `prop`. Unparseable payloads deliver nothing. */
|
|
152
174
|
function payloadNames(payload: string, prop: string): boolean {
|
|
153
175
|
try {
|
|
154
176
|
const parsed: unknown = JSON.parse(payload);
|
|
155
|
-
return
|
|
177
|
+
return isNonNullObject(parsed) && prop in parsed;
|
|
156
178
|
} catch {
|
|
157
179
|
return false;
|
|
158
180
|
}
|
|
@@ -238,11 +260,8 @@ export function startIframeInlineEdit(
|
|
|
238
260
|
* `Highlight`/`CSS.highlights`, so this is a silent no-op there (and in non-Chromium engines).
|
|
239
261
|
*/
|
|
240
262
|
const updateHighlight = () => {
|
|
241
|
-
const HighlightCtor =
|
|
242
|
-
|
|
243
|
-
| undefined;
|
|
244
|
-
const highlights = (globalThis.CSS as unknown as { highlights?: Map<string, unknown> })
|
|
245
|
-
?.highlights;
|
|
263
|
+
const HighlightCtor = highlightRealm.Highlight;
|
|
264
|
+
const highlights = highlightRealm.CSS?.highlights;
|
|
246
265
|
if (!HighlightCtor || !highlights) {
|
|
247
266
|
return;
|
|
248
267
|
}
|
|
@@ -256,9 +275,7 @@ export function startIframeInlineEdit(
|
|
|
256
275
|
|
|
257
276
|
/** Tear down the Custom Highlight (on teardown / real editEnd). */
|
|
258
277
|
const clearHighlight = () => {
|
|
259
|
-
|
|
260
|
-
?.highlights;
|
|
261
|
-
highlights?.delete(HIGHLIGHT_NAME);
|
|
278
|
+
highlightRealm.CSS?.highlights?.delete(HIGHLIGHT_NAME);
|
|
262
279
|
};
|
|
263
280
|
|
|
264
281
|
/**
|
|
@@ -321,13 +338,11 @@ export function startIframeInlineEdit(
|
|
|
321
338
|
// Optional, so omitting it keeps the message shape unchanged for every non-tick commit.
|
|
322
339
|
onCommit: (p, children, textContent, inPlace) => {
|
|
323
340
|
inputAnnounced = false;
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
...(inPlace ? { inPlace: true } : {}),
|
|
330
|
-
});
|
|
341
|
+
const commit: EditCommitMsg = { children, kind: "editCommit", path: p, textContent };
|
|
342
|
+
if (inPlace) {
|
|
343
|
+
commit.inPlace = true;
|
|
344
|
+
}
|
|
345
|
+
channel.post(commit);
|
|
331
346
|
},
|
|
332
347
|
onEnd: () => {
|
|
333
348
|
clearHighlight();
|
|
@@ -356,11 +371,11 @@ export function startIframeInlineEdit(
|
|
|
356
371
|
if (!shadowDoc) {
|
|
357
372
|
return true;
|
|
358
373
|
}
|
|
359
|
-
const node = getNodeAtPath(shadowDoc, hostPath)
|
|
374
|
+
const node = getNodeAtPath(shadowDoc, hostPath);
|
|
360
375
|
if (deliveredOutsideProps(node, prop)) {
|
|
361
376
|
return false;
|
|
362
377
|
}
|
|
363
|
-
const raw =
|
|
378
|
+
const raw = node?.$props?.[prop];
|
|
364
379
|
if (raw == null) {
|
|
365
380
|
return true; // Unset — editing ADDS the prop, overriding the definition default.
|
|
366
381
|
}
|
|
@@ -371,7 +386,7 @@ export function startIframeInlineEdit(
|
|
|
371
386
|
* Objects were already excluded; the scalar cases were not, and are the ones a component
|
|
372
387
|
* actually declares. They stay editable in the properties panel, which knows their type.
|
|
373
388
|
*/
|
|
374
|
-
if (
|
|
389
|
+
if (!isString(raw)) {
|
|
375
390
|
return false;
|
|
376
391
|
}
|
|
377
392
|
return !raw.includes("${");
|
|
@@ -390,13 +405,16 @@ export function startIframeInlineEdit(
|
|
|
390
405
|
{
|
|
391
406
|
onCommit: (p, _children, textContent, inPlace) => {
|
|
392
407
|
inputAnnounced = false;
|
|
393
|
-
|
|
408
|
+
const commit: EditCommitPropMsg = {
|
|
394
409
|
kind: "editCommitProp",
|
|
395
410
|
path: p,
|
|
396
411
|
prop,
|
|
397
412
|
value: textContent ?? "",
|
|
398
|
-
|
|
399
|
-
|
|
413
|
+
};
|
|
414
|
+
if (inPlace) {
|
|
415
|
+
commit.inPlace = true;
|
|
416
|
+
}
|
|
417
|
+
channel.post(commit);
|
|
400
418
|
},
|
|
401
419
|
onEnd: () => {
|
|
402
420
|
clearHighlight();
|
|
@@ -519,6 +537,7 @@ export function startIframeInlineEdit(
|
|
|
519
537
|
if (start === -1 || end === -1 || end <= start) {
|
|
520
538
|
return false;
|
|
521
539
|
}
|
|
540
|
+
// SAFETY: `blocksInOrder` selects `[data-jx-path]`, so every block it returns carries the key.
|
|
522
541
|
const between = blocks
|
|
523
542
|
.slice(start + 1, end)
|
|
524
543
|
.map((el) => parseJxPath(el.dataset.jxPath as string));
|
|
@@ -573,7 +592,7 @@ export function startIframeInlineEdit(
|
|
|
573
592
|
owns what a slash MEANS (start of a block or after a space; anywhere else it is punctuation).
|
|
574
593
|
The matching `input` half re-filters the open menu, for the same reason: a contenteditable's
|
|
575
594
|
`input` targets its host, not the block the caret happens to be in. */
|
|
576
|
-
const onSlashKey = (e:
|
|
595
|
+
const onSlashKey = (e: KeyboardEvent) => handleSlashTrigger(e);
|
|
577
596
|
const onSlashInput = () => {
|
|
578
597
|
if (isSlashActive()) {
|
|
579
598
|
refreshSlashMenu();
|