@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
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
setDiffView,
|
|
33
33
|
stepDiff,
|
|
34
34
|
} from "./diff-view";
|
|
35
|
+
import { isString } from "@jxsuite/schema/guards";
|
|
35
36
|
import type { DiffView } from "./diff-view";
|
|
36
37
|
import type { ChangeStep } from "./diff-marks";
|
|
37
38
|
import { panToParentRect } from "./canvas-utils";
|
|
@@ -158,7 +159,7 @@ function describeStep(step: ChangeStep, index: number, total: number): string {
|
|
|
158
159
|
* it is, so a reveal that could not measure leaves a correct toolbar over an unmoved canvas.
|
|
159
160
|
*/
|
|
160
161
|
function onStepClick(paneId: string, delta: 1 | -1): void {
|
|
161
|
-
stepDiffAndReveal(paneId, delta).catch((error
|
|
162
|
+
stepDiffAndReveal(paneId, delta).catch((error) => {
|
|
162
163
|
console.warn("stepDiffAndReveal:", error);
|
|
163
164
|
});
|
|
164
165
|
}
|
|
@@ -180,8 +181,8 @@ export async function stepDiffAndReveal(paneId: string, delta: 1 | -1): Promise<
|
|
|
180
181
|
renderDiffToolbar(paneId);
|
|
181
182
|
const step = diffChangeMapOf(paneId)?.steps[landed];
|
|
182
183
|
const { panels } = surfaceForPane(paneId);
|
|
183
|
-
const original = panels[0]?.canvas
|
|
184
|
-
const current = panels[1]?.canvas
|
|
184
|
+
const original = panels[0]?.canvas;
|
|
185
|
+
const current = panels[1]?.canvas;
|
|
185
186
|
if (!step) {
|
|
186
187
|
return;
|
|
187
188
|
}
|
|
@@ -252,10 +253,10 @@ export function diffToolbarView(paneId: string): DiffToolbarView {
|
|
|
252
253
|
return {
|
|
253
254
|
codeChecked: showing === "code" ? "true" : "false",
|
|
254
255
|
countLabel,
|
|
255
|
-
degraded: !code && map
|
|
256
|
+
degraded: !code && map.degraded ? "shown" : "hidden",
|
|
256
257
|
nextDisabled: index >= total - 1,
|
|
257
258
|
prevDisabled: index <= 0,
|
|
258
|
-
rootKeys: !code && map
|
|
259
|
+
rootKeys: !code && map.rootKeys.length > 0 ? "shown" : "hidden",
|
|
259
260
|
rootKeysTitle: `Changed: ${map?.rootKeys.join(", ") ?? ""}`,
|
|
260
261
|
stepper: total === 0 ? "hidden" : "shown",
|
|
261
262
|
// A file the canvas cannot render arrives with a null map: there is no visual half to offer.
|
|
@@ -266,8 +267,8 @@ export function diffToolbarView(paneId: string): DiffToolbarView {
|
|
|
266
267
|
|
|
267
268
|
/** The pane a diff verb addresses: named, or the focused one. */
|
|
268
269
|
function paneOfArgs(args: CommandArgValues): string {
|
|
269
|
-
const { pane } = args
|
|
270
|
-
return
|
|
270
|
+
const { pane } = args;
|
|
271
|
+
return isString(pane) ? pane : workspace.activePaneId;
|
|
271
272
|
}
|
|
272
273
|
|
|
273
274
|
const paneProperty = stringProperty("Which pane to act on. Defaults to the focused one.");
|
|
@@ -58,7 +58,7 @@ export function applyEditWidth(surface: CanvasSurface, column: HTMLElement, widt
|
|
|
58
58
|
return;
|
|
59
59
|
}
|
|
60
60
|
column.style.maxWidth = `${Math.round(width)}px`;
|
|
61
|
-
if (
|
|
61
|
+
if (tab.session.ui.editZoom !== 1) {
|
|
62
62
|
applyEditZoom(surface);
|
|
63
63
|
}
|
|
64
64
|
const rendered = rectOf(column).width || width;
|
|
@@ -183,5 +183,8 @@ export function mountEditWidthHandle(
|
|
|
183
183
|
if (!handle || !column || _wired.has(handle)) {
|
|
184
184
|
return;
|
|
185
185
|
}
|
|
186
|
+
/* SAFETY: Every caller passes one of the two `jx-split` slots `surfaces/canvas-stage.json` draws
|
|
187
|
+
beside the column, and a `jx-split` carries the `value`/`min`/`max`/`collapse` share
|
|
188
|
+
properties `SplitElement` names; `bindSplit` only writes them. */
|
|
186
189
|
_wired.set(handle, bindSplit(handle as SplitElement, editWidthTarget(surface, column, grow)));
|
|
187
190
|
}
|
package/src/canvas/edit-width.ts
CHANGED
|
@@ -78,9 +78,7 @@ const _editWidths = new Map<string, EditWidthRecord>();
|
|
|
78
78
|
|
|
79
79
|
/** The size breakpoints and base width a tab renders against, site context included. */
|
|
80
80
|
function mediaEntriesOfTab(tab: Tab) {
|
|
81
|
-
return parseMediaEntries(
|
|
82
|
-
getEffectiveMedia(tab.doc.document?.$media as Record<string, string> | undefined),
|
|
83
|
-
);
|
|
81
|
+
return parseMediaEntries(getEffectiveMedia(tab.doc.document.$media));
|
|
84
82
|
}
|
|
85
83
|
|
|
86
84
|
/**
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
* plus an in-memory `fakeChannelPair` so cross-frame logic is unit-testable without a live iframe.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
import { isNonNullObject } from "@jxsuite/schema/guards";
|
|
13
|
+
|
|
12
14
|
/**
|
|
13
15
|
* A typed, bidirectional message channel. `TOut` is what this side sends; `TIn` is what it
|
|
14
16
|
* receives. Implementations: a real `postMessage` channel over an `<iframe>` (added with the iframe
|
|
@@ -26,8 +28,14 @@ export interface IframeChannel<TOut, TIn> {
|
|
|
26
28
|
/** Envelope key that tags every cross-frame message so foreign `message` events are ignored. */
|
|
27
29
|
const ENVELOPE = "jx:canvas";
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
/** What crosses the frame boundary: the session token beside the typed message it authenticates. */
|
|
32
|
+
export interface CanvasEnvelope<T> {
|
|
33
|
+
[ENVELOPE]: string;
|
|
34
|
+
payload: T;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface PostMessageTarget<TOut> {
|
|
38
|
+
postMessage: (message: CanvasEnvelope<TOut>, targetOrigin: string) => void;
|
|
31
39
|
}
|
|
32
40
|
|
|
33
41
|
interface MessageSource {
|
|
@@ -46,7 +54,7 @@ interface MessageSource {
|
|
|
46
54
|
* origin.
|
|
47
55
|
*/
|
|
48
56
|
export function postMessageChannel<TOut, TIn>(opts: {
|
|
49
|
-
target: PostMessageTarget
|
|
57
|
+
target: PostMessageTarget<TOut>;
|
|
50
58
|
source: MessageSource;
|
|
51
59
|
targetOrigin: string;
|
|
52
60
|
acceptOrigin: string;
|
|
@@ -59,12 +67,15 @@ export function postMessageChannel<TOut, TIn>(opts: {
|
|
|
59
67
|
if (acceptOrigin !== "*" && event.origin !== acceptOrigin) {
|
|
60
68
|
return;
|
|
61
69
|
}
|
|
62
|
-
const
|
|
63
|
-
if (!
|
|
70
|
+
const envelope: unknown = event.data;
|
|
71
|
+
if (!isNonNullObject(envelope) || !(ENVELOPE in envelope) || envelope[ENVELOPE] !== token) {
|
|
64
72
|
return;
|
|
65
73
|
}
|
|
74
|
+
/* SAFETY: The envelope carries this session's secret token, which only the peer channel holds,
|
|
75
|
+
and that peer's `post` is typed to send exactly `TIn`; a foreign page cannot forge the token. */
|
|
76
|
+
const payload = ("payload" in envelope ? envelope.payload : undefined) as TIn;
|
|
66
77
|
for (const handler of handlers) {
|
|
67
|
-
handler(
|
|
78
|
+
handler(payload);
|
|
68
79
|
}
|
|
69
80
|
};
|
|
70
81
|
source.addEventListener("message", listener);
|
|
@@ -84,19 +95,22 @@ export function postMessageChannel<TOut, TIn>(opts: {
|
|
|
84
95
|
};
|
|
85
96
|
}
|
|
86
97
|
|
|
98
|
+
/** Both ends of an in-memory channel, and the controls that deliver what they posted. */
|
|
99
|
+
export interface FakeChannelPair<ParentOut, IframeOut> {
|
|
100
|
+
parent: IframeChannel<ParentOut, IframeOut>;
|
|
101
|
+
iframe: IframeChannel<IframeOut, ParentOut>;
|
|
102
|
+
flush: () => void;
|
|
103
|
+
/** Number of messages waiting to be delivered (both directions). */
|
|
104
|
+
pending: () => number;
|
|
105
|
+
}
|
|
106
|
+
|
|
87
107
|
/**
|
|
88
108
|
* Two in-memory channels wired to each other for tests. A message `parent.post(x)` is delivered to
|
|
89
109
|
* the `iframe` side's handlers (and vice versa) only when `flush()` is called — so tests drive the
|
|
90
110
|
* inherently-async postMessage ordering deterministically. Messages posted _during_ a flush are
|
|
91
111
|
* queued for the next flush, never delivered re-entrantly.
|
|
92
112
|
*/
|
|
93
|
-
export function fakeChannelPair<ParentOut, IframeOut>(): {
|
|
94
|
-
parent: IframeChannel<ParentOut, IframeOut>;
|
|
95
|
-
iframe: IframeChannel<IframeOut, ParentOut>;
|
|
96
|
-
flush: () => void;
|
|
97
|
-
/** Number of messages waiting to be delivered (both directions). */
|
|
98
|
-
pending: () => number;
|
|
99
|
-
} {
|
|
113
|
+
export function fakeChannelPair<ParentOut, IframeOut>(): FakeChannelPair<ParentOut, IframeOut> {
|
|
100
114
|
let toIframe: ParentOut[] = [];
|
|
101
115
|
let toParent: IframeOut[] = [];
|
|
102
116
|
const iframeHandlers = new Set<(m: ParentOut) => void>();
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import { parseJxPath } from "./path-mapping";
|
|
20
|
-
import { displayTagName } from "@jxsuite/schema/guards";
|
|
20
|
+
import { displayTagName, isNonNullObject } from "@jxsuite/schema/guards";
|
|
21
21
|
import { rectOf, elementAtPoint } from "../utils/geometry";
|
|
22
22
|
import { getNodeAtPath, isAncestor, pathsEqual } from "../state";
|
|
23
23
|
import type { DragSrcKind, DropPreview } from "./iframe-protocol";
|
|
@@ -52,9 +52,11 @@ const VOID_TAGS = new Set([
|
|
|
52
52
|
* reuse it. Returns null when no addressable node is found.
|
|
53
53
|
*/
|
|
54
54
|
function nearestPathEl(start: Element | null): HTMLElement | null {
|
|
55
|
-
|
|
55
|
+
// Only an `HTMLElement` is ever stamped (`makeStamper` skips every other node), so the walk
|
|
56
|
+
// Passes over SVG and other foreign elements on its way up.
|
|
57
|
+
let el = start;
|
|
56
58
|
while (el) {
|
|
57
|
-
if (el.dataset
|
|
59
|
+
if (el instanceof HTMLElement && el.dataset.jxPath) {
|
|
58
60
|
return el;
|
|
59
61
|
}
|
|
60
62
|
el = el.parentElement;
|
|
@@ -94,15 +96,15 @@ export function computeDropInstruction(
|
|
|
94
96
|
shadowDoc: JxMutableNode,
|
|
95
97
|
src: DragSrcKind,
|
|
96
98
|
): DropPreview | null {
|
|
97
|
-
const serialized = targetEl.dataset
|
|
99
|
+
const serialized = targetEl.dataset.jxPath;
|
|
98
100
|
if (serialized == null) {
|
|
99
101
|
return null;
|
|
100
102
|
}
|
|
101
|
-
const targetPath = parseJxPath(serialized)
|
|
103
|
+
const targetPath = parseJxPath(serialized);
|
|
102
104
|
|
|
103
105
|
// Root: pick the nearest child edge among the element's element children.
|
|
104
106
|
if (targetPath.length === 0) {
|
|
105
|
-
const children = [...targetEl.children]
|
|
107
|
+
const children = [...targetEl.children];
|
|
106
108
|
if (children.length === 0) {
|
|
107
109
|
return canDrop(src, targetPath)
|
|
108
110
|
? {
|
|
@@ -120,11 +122,10 @@ export function computeDropInstruction(
|
|
|
120
122
|
return null;
|
|
121
123
|
}
|
|
122
124
|
|
|
123
|
-
const node = getNodeAtPath(shadowDoc, targetPath)
|
|
125
|
+
const node = getNodeAtPath(shadowDoc, targetPath);
|
|
124
126
|
const tag = (displayTagName(node?.tagName) || "div").toLowerCase();
|
|
125
127
|
const hasElementChildren =
|
|
126
|
-
Array.isArray(node?.children) &&
|
|
127
|
-
node.children.some((c: unknown) => c != null && typeof c === "object");
|
|
128
|
+
Array.isArray(node?.children) && node.children.some((c) => isNonNullObject(c));
|
|
128
129
|
const isLeaf = VOID_TAGS.has(tag) || !hasElementChildren;
|
|
129
130
|
|
|
130
131
|
const rect = rectFor(targetEl);
|
|
@@ -150,7 +151,7 @@ export function computeDropInstruction(
|
|
|
150
151
|
* parentElementPath(slice(0,-2)) / childIndex(at(-1)) read the same parent + index.
|
|
151
152
|
*/
|
|
152
153
|
function nearestChildEdge(
|
|
153
|
-
children:
|
|
154
|
+
children: Element[],
|
|
154
155
|
cursorY: number,
|
|
155
156
|
parentPath: JxPath,
|
|
156
157
|
src: DragSrcKind,
|
|
@@ -175,7 +176,7 @@ function nearestChildEdge(
|
|
|
175
176
|
}
|
|
176
177
|
}
|
|
177
178
|
|
|
178
|
-
const childPath = [...parentPath, "children", closestIdx]
|
|
179
|
+
const childPath: JxPath = [...parentPath, "children", closestIdx];
|
|
179
180
|
if (!canDrop(src, childPath)) {
|
|
180
181
|
return null;
|
|
181
182
|
}
|
|
@@ -192,7 +193,7 @@ function canDrop(src: DragSrcKind, targetPath: JxPath): boolean {
|
|
|
192
193
|
if (src.type !== "tree-node") {
|
|
193
194
|
return true;
|
|
194
195
|
}
|
|
195
|
-
const srcPath = src.path
|
|
196
|
+
const srcPath = src.path;
|
|
196
197
|
if (pathsEqual(srcPath, targetPath)) {
|
|
197
198
|
return false;
|
|
198
199
|
}
|
|
@@ -35,6 +35,7 @@ import {
|
|
|
35
35
|
toDomPosition,
|
|
36
36
|
} from "./iframe-position";
|
|
37
37
|
import { serializeJxPath } from "./path-mapping";
|
|
38
|
+
import { isFunction } from "@jxsuite/schema/guards";
|
|
38
39
|
import type { DocPos, DocRange, EditablePredicate } from "./iframe-position";
|
|
39
40
|
import type { JxPath } from "../state";
|
|
40
41
|
|
|
@@ -167,6 +168,14 @@ export interface EditableRootHandle {
|
|
|
167
168
|
isComposing: () => boolean;
|
|
168
169
|
}
|
|
169
170
|
|
|
171
|
+
/**
|
|
172
|
+
* Whether an element carries `dataset`. HTML, SVG and MathML elements all mix in
|
|
173
|
+
* `HTMLOrSVGElement`; an element from any other namespace has no `dataset` at all.
|
|
174
|
+
*/
|
|
175
|
+
function hasDataset(el: Element): el is Element & HTMLOrSVGElement {
|
|
176
|
+
return "dataset" in el;
|
|
177
|
+
}
|
|
178
|
+
|
|
170
179
|
/** Wire the editing host on `container`. */
|
|
171
180
|
export function startEditableRoot(
|
|
172
181
|
container: HTMLElement,
|
|
@@ -183,13 +192,13 @@ export function startEditableRoot(
|
|
|
183
192
|
return mode === undefined || mode === "design" || mode === "edit";
|
|
184
193
|
};
|
|
185
194
|
|
|
186
|
-
/** Pending idle-commit timer, or
|
|
187
|
-
let commitTimer =
|
|
195
|
+
/** Pending idle-commit timer, or null when none is armed. */
|
|
196
|
+
let commitTimer: ReturnType<typeof setTimeout> | null = null;
|
|
188
197
|
|
|
189
198
|
const cancelCommitTick = () => {
|
|
190
|
-
if (commitTimer) {
|
|
199
|
+
if (commitTimer !== null) {
|
|
191
200
|
clearTimeout(commitTimer);
|
|
192
|
-
commitTimer =
|
|
201
|
+
commitTimer = null;
|
|
193
202
|
}
|
|
194
203
|
};
|
|
195
204
|
|
|
@@ -202,7 +211,7 @@ export function startEditableRoot(
|
|
|
202
211
|
* idle commit invisible — without it, typing would jump the caret every time you paused.
|
|
203
212
|
*/
|
|
204
213
|
const commitTick = () => {
|
|
205
|
-
commitTimer =
|
|
214
|
+
commitTimer = null;
|
|
206
215
|
if (!activeEl || !deps.onCommitTick) {
|
|
207
216
|
return;
|
|
208
217
|
}
|
|
@@ -233,7 +242,7 @@ export function startEditableRoot(
|
|
|
233
242
|
return;
|
|
234
243
|
}
|
|
235
244
|
cancelCommitTick();
|
|
236
|
-
commitTimer = setTimeout(commitTick, deps.commitDelayMs ?? COMMIT_IDLE_MS)
|
|
245
|
+
commitTimer = setTimeout(commitTick, deps.commitDelayMs ?? COMMIT_IDLE_MS);
|
|
237
246
|
};
|
|
238
247
|
|
|
239
248
|
const onCompositionStart = () => {
|
|
@@ -349,7 +358,8 @@ export function startEditableRoot(
|
|
|
349
358
|
const affectedRange = (
|
|
350
359
|
e: InputEvent,
|
|
351
360
|
): { from: DocPos; to: DocPos; endEl: HTMLElement } | null => {
|
|
352
|
-
|
|
361
|
+
// Happy-dom ships no `getTargetRanges` at all, so the method's presence is probed, not assumed.
|
|
362
|
+
const [target] = isFunction(e.getTargetRanges) ? e.getTargetRanges() : [];
|
|
353
363
|
const sel = doc.getSelection();
|
|
354
364
|
const useSelection = sel && sel.rangeCount > 0 && (sel.isCollapsed || !target);
|
|
355
365
|
let startNode: Node | null;
|
|
@@ -370,8 +380,7 @@ export function startEditableRoot(
|
|
|
370
380
|
return from && to && endBlock ? { endEl: endBlock.el, from, to } : null;
|
|
371
381
|
};
|
|
372
382
|
|
|
373
|
-
const onBeforeInput = (
|
|
374
|
-
const e = event as InputEvent;
|
|
383
|
+
const onBeforeInput = (e: InputEvent) => {
|
|
375
384
|
if (!editingAllowed()) {
|
|
376
385
|
return;
|
|
377
386
|
}
|
|
@@ -435,21 +444,25 @@ export function startEditableRoot(
|
|
|
435
444
|
if (!editingAllowed() || !deps.onPropActivate) {
|
|
436
445
|
return;
|
|
437
446
|
}
|
|
438
|
-
let el = e.target instanceof Element ?
|
|
447
|
+
let el = e.target instanceof Element ? e.target : null;
|
|
439
448
|
while (el && el !== container) {
|
|
440
|
-
if (el.dataset
|
|
441
|
-
|
|
449
|
+
if (hasDataset(el) && el.dataset.jxBoundProp) {
|
|
450
|
+
/* SAFETY: The runtime builds SVG and MathML nodes as `createElementNS(...) as HTMLElement`
|
|
451
|
+
and stamps `data-jx-bound-prop` through that same `HTMLElement`-typed path, so a
|
|
452
|
+
foreign-namespace prop host already travels downstream as an `HTMLElement`. */
|
|
453
|
+
const host = el as HTMLElement;
|
|
454
|
+
if (host !== activeEl) {
|
|
442
455
|
deactivate();
|
|
443
|
-
if (deps.onPropActivate(
|
|
456
|
+
if (deps.onPropActivate(host)) {
|
|
444
457
|
// Adopt the nested host so the caret landing inside it is not read as a block change.
|
|
445
|
-
activeEl =
|
|
458
|
+
activeEl = host;
|
|
446
459
|
activeKey = null;
|
|
447
460
|
}
|
|
448
461
|
}
|
|
449
462
|
return;
|
|
450
463
|
}
|
|
451
464
|
// A stamped page block first means this is ordinary page DOM, not component internals.
|
|
452
|
-
if (el.dataset
|
|
465
|
+
if (hasDataset(el) && el.dataset.jxPath) {
|
|
453
466
|
return;
|
|
454
467
|
}
|
|
455
468
|
el = el.parentElement;
|
|
@@ -493,7 +506,7 @@ export function startEditableRoot(
|
|
|
493
506
|
if (composing) {
|
|
494
507
|
return;
|
|
495
508
|
}
|
|
496
|
-
if (commitTimer) {
|
|
509
|
+
if (commitTimer !== null) {
|
|
497
510
|
cancelCommitTick();
|
|
498
511
|
commitTick();
|
|
499
512
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import { postMessageChannel } from "./iframe-channel";
|
|
9
9
|
import { rectOf } from "../utils/geometry";
|
|
10
|
-
import { displayTagName } from "@jxsuite/schema/guards";
|
|
10
|
+
import { displayTagName, isNonNullObject } from "@jxsuite/schema/guards";
|
|
11
11
|
import {
|
|
12
12
|
applyCanvasDialogOpen,
|
|
13
13
|
applyCanvasPopoverOpen,
|
|
@@ -59,16 +59,17 @@ import {
|
|
|
59
59
|
import { resolveAssetRef } from "./asset-resolve";
|
|
60
60
|
import type { AssetContext } from "./asset-resolve";
|
|
61
61
|
import { KIT_LOADERS } from "@jxsuite/ui/loaders";
|
|
62
|
-
import type { IframeChannel } from "./iframe-channel";
|
|
62
|
+
import type { CanvasEnvelope, IframeChannel } from "./iframe-channel";
|
|
63
63
|
import type {
|
|
64
64
|
CanvasMode,
|
|
65
|
+
DragOverMsg,
|
|
65
66
|
DragSrcKind,
|
|
66
67
|
FileDropHit,
|
|
67
68
|
IframeToParent,
|
|
68
69
|
LayoutHit,
|
|
69
70
|
ParentToIframe,
|
|
70
71
|
} from "./iframe-protocol";
|
|
71
|
-
import type { JxDocument, JxMutableNode
|
|
72
|
+
import type { JxDocument, JxMutableNode } from "@jxsuite/schema/types";
|
|
72
73
|
import type { IframeRenderCtx, RenderHandle } from "./iframe-render";
|
|
73
74
|
import { setBundleBase } from "../services/bundle-base";
|
|
74
75
|
|
|
@@ -153,12 +154,12 @@ export function fileDropHitFor(
|
|
|
153
154
|
targetEl: HTMLElement,
|
|
154
155
|
shadowDoc: JxMutableNode | null,
|
|
155
156
|
): FileDropHit | null {
|
|
156
|
-
const serialized = targetEl.dataset
|
|
157
|
+
const serialized = targetEl.dataset.jxPath;
|
|
157
158
|
if (serialized == null) {
|
|
158
159
|
return null;
|
|
159
160
|
}
|
|
160
161
|
const path = parseJxPath(serialized);
|
|
161
|
-
const node = shadowDoc ?
|
|
162
|
+
const node = shadowDoc ? getNodeAtPath(shadowDoc, path) : undefined;
|
|
162
163
|
return {
|
|
163
164
|
path,
|
|
164
165
|
rect: rectFor(targetEl),
|
|
@@ -186,7 +187,8 @@ export function layoutHitFor(target: EventTarget | null): LayoutHit | null {
|
|
|
186
187
|
return null;
|
|
187
188
|
}
|
|
188
189
|
return {
|
|
189
|
-
|
|
190
|
+
// An `HTMLElement`'s `className` is always the string form (only SVG's is an animated value).
|
|
191
|
+
className: el.className,
|
|
190
192
|
layoutFile: el.dataset.jxLayoutFile ?? "",
|
|
191
193
|
layoutPath: parseJxPath(el.dataset.jxLayoutPath ?? "[]"),
|
|
192
194
|
rect: rectFor(el),
|
|
@@ -194,6 +196,34 @@ export function layoutHitFor(target: EventTarget | null): LayoutHit | null {
|
|
|
194
196
|
};
|
|
195
197
|
}
|
|
196
198
|
|
|
199
|
+
/**
|
|
200
|
+
* The text a failed patch or render reports: the thrown value's `message` when it has one, the
|
|
201
|
+
* value itself otherwise.
|
|
202
|
+
*/
|
|
203
|
+
function failureText(cause: unknown): string {
|
|
204
|
+
const message = isNonNullObject(cause) && "message" in cause ? cause.message : undefined;
|
|
205
|
+
return String(message ?? cause);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/** The edge-hold auto-scroll loop's last cursor, and the drag it belongs to. */
|
|
209
|
+
interface AutoScrollCursor {
|
|
210
|
+
x: number;
|
|
211
|
+
y: number;
|
|
212
|
+
dragSeq: number;
|
|
213
|
+
withCursor: boolean;
|
|
214
|
+
src?: DragSrcKind;
|
|
215
|
+
gen?: number;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* The two document APIs the `idle` sample reads, as a frame may or may not provide them. lib.dom
|
|
220
|
+
* declares both unconditionally; happy-dom implements neither.
|
|
221
|
+
*/
|
|
222
|
+
interface IdleProbeDocument {
|
|
223
|
+
getAnimations?: Document["getAnimations"];
|
|
224
|
+
fonts?: FontFaceSet;
|
|
225
|
+
}
|
|
226
|
+
|
|
197
227
|
/** Set-key keys the patcher applies IN PLACE (never a subtree re-render) — safe under a live edit. */
|
|
198
228
|
const IN_PLACE_KEYS = new Set(["style", "textContent"]);
|
|
199
229
|
|
|
@@ -317,14 +347,7 @@ export function startCanvasIframe(opts: {
|
|
|
317
347
|
// (the parent has no pointer of its own then). Parent-driven flows (1/2/4) leave `src` undefined
|
|
318
348
|
// And `withCursor` false — the tick falls back to `dragSrc`/`dragGen` and the parent moves the
|
|
319
349
|
// Ghost from its own raw pointer.
|
|
320
|
-
let autoScrollCursor:
|
|
321
|
-
x: number;
|
|
322
|
-
y: number;
|
|
323
|
-
dragSeq: number;
|
|
324
|
-
withCursor: boolean;
|
|
325
|
-
src?: DragSrcKind;
|
|
326
|
-
gen?: number;
|
|
327
|
-
} | null = null;
|
|
350
|
+
let autoScrollCursor: AutoScrollCursor | null = null;
|
|
328
351
|
const win = container.ownerDocument.defaultView;
|
|
329
352
|
|
|
330
353
|
function stopAutoScroll(): void {
|
|
@@ -353,16 +376,17 @@ export function startCanvasIframe(opts: {
|
|
|
353
376
|
return;
|
|
354
377
|
}
|
|
355
378
|
const preview = previewAt(autoScrollCursor, src, shadowDoc, container.ownerDocument);
|
|
356
|
-
|
|
357
|
-
// Flow 3 (withCursor) re-posts the cursor so the parent keeps tracking the ghost at an edge-hold.
|
|
358
|
-
...(autoScrollCursor.withCursor
|
|
359
|
-
? { cursor: { x: autoScrollCursor.x, y: autoScrollCursor.y } }
|
|
360
|
-
: {}),
|
|
379
|
+
const over: DragOverMsg = {
|
|
361
380
|
dragSeq: autoScrollCursor.dragSeq,
|
|
362
381
|
gen: autoScrollCursor.gen ?? dragGen,
|
|
363
382
|
kind: "dragOver",
|
|
364
383
|
preview,
|
|
365
|
-
}
|
|
384
|
+
};
|
|
385
|
+
// Flow 3 (withCursor) re-posts the cursor so the parent keeps tracking the ghost at an edge-hold.
|
|
386
|
+
if (autoScrollCursor.withCursor) {
|
|
387
|
+
over.cursor = { x: autoScrollCursor.x, y: autoScrollCursor.y };
|
|
388
|
+
}
|
|
389
|
+
channel.post(over);
|
|
366
390
|
autoScrollFrame = win.requestAnimationFrame(autoScrollTick);
|
|
367
391
|
}
|
|
368
392
|
|
|
@@ -381,13 +405,12 @@ export function startCanvasIframe(opts: {
|
|
|
381
405
|
stopAutoScroll();
|
|
382
406
|
return;
|
|
383
407
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
};
|
|
408
|
+
const next: AutoScrollCursor = { dragSeq, withCursor: flow3 != null, x: cursor.x, y: cursor.y };
|
|
409
|
+
if (flow3) {
|
|
410
|
+
next.gen = flow3.gen;
|
|
411
|
+
next.src = flow3.src;
|
|
412
|
+
}
|
|
413
|
+
autoScrollCursor = next;
|
|
391
414
|
if (!autoScrollFrame) {
|
|
392
415
|
autoScrollFrame = win.requestAnimationFrame(autoScrollTick);
|
|
393
416
|
}
|
|
@@ -522,13 +545,11 @@ export function startCanvasIframe(opts: {
|
|
|
522
545
|
}
|
|
523
546
|
|
|
524
547
|
function sampleIdle(): Extract<IframeToParent, { kind: "idle" }> {
|
|
525
|
-
const
|
|
526
|
-
|
|
527
|
-
? frameDoc.getAnimations().filter((a) => a.playState === "running").length
|
|
528
|
-
: 0;
|
|
548
|
+
const probe: IdleProbeDocument = frameDoc;
|
|
549
|
+
const running = probe.getAnimations?.().filter((a) => a.playState === "running").length ?? 0;
|
|
529
550
|
return {
|
|
530
551
|
animations: running,
|
|
531
|
-
fonts:
|
|
552
|
+
fonts: probe.fonts ? probe.fonts.status === "loaded" : true,
|
|
532
553
|
gen: renderedGen,
|
|
533
554
|
images: pendingImageRetries(),
|
|
534
555
|
kind: "idle",
|
|
@@ -750,12 +771,7 @@ export function startCanvasIframe(opts: {
|
|
|
750
771
|
// The wrong scope); the parent additionally gen-gates the reply against its own state.
|
|
751
772
|
const results =
|
|
752
773
|
msg.gen === renderedGen && renderCtx && shadowDoc
|
|
753
|
-
? evaluateLiveExprs(
|
|
754
|
-
msg.exprs,
|
|
755
|
-
renderCtx.defs as Record<string, unknown>,
|
|
756
|
-
shadowDoc,
|
|
757
|
-
msg.contextPath,
|
|
758
|
-
)
|
|
774
|
+
? evaluateLiveExprs(msg.exprs, renderCtx.defs, shadowDoc, msg.contextPath)
|
|
759
775
|
: [];
|
|
760
776
|
channel.post({ gen: msg.gen, kind: "evalResult", reqId: msg.reqId, results });
|
|
761
777
|
return;
|
|
@@ -820,11 +836,7 @@ export function startCanvasIframe(opts: {
|
|
|
820
836
|
channel.post({ gen, kind: "patchComplete" });
|
|
821
837
|
armIdleWatch();
|
|
822
838
|
} catch (error) {
|
|
823
|
-
channel.post({
|
|
824
|
-
gen,
|
|
825
|
-
kind: "patchError",
|
|
826
|
-
message: String((error as Error)?.message ?? error),
|
|
827
|
-
});
|
|
839
|
+
channel.post({ gen, kind: "patchError", message: failureText(error) });
|
|
828
840
|
}
|
|
829
841
|
return;
|
|
830
842
|
}
|
|
@@ -835,14 +847,10 @@ export function startCanvasIframe(opts: {
|
|
|
835
847
|
if (msg.gen !== renderedGen || !shadowDoc) {
|
|
836
848
|
return;
|
|
837
849
|
}
|
|
838
|
-
|
|
850
|
+
shadowDoc.style = msg.style;
|
|
839
851
|
const rootEl = container.firstElementChild;
|
|
840
852
|
if (rootEl instanceof HTMLElement) {
|
|
841
|
-
reapplyStyle(
|
|
842
|
-
rootEl,
|
|
843
|
-
msg.style as JxStyle,
|
|
844
|
-
(shadowDoc as { $media?: Record<string, string> }).$media ?? {},
|
|
845
|
-
);
|
|
853
|
+
reapplyStyle(rootEl, msg.style, shadowDoc.$media ?? {});
|
|
846
854
|
}
|
|
847
855
|
return;
|
|
848
856
|
}
|
|
@@ -945,7 +953,10 @@ export function startCanvasIframe(opts: {
|
|
|
945
953
|
if (msg.kind === "redefineElement") {
|
|
946
954
|
/* The canvas half of embedding.md §7. The definition is replaced in THIS realm; instances
|
|
947
955
|
already on the canvas keep the old one until the host's next render replaces them. */
|
|
948
|
-
|
|
956
|
+
/* SAFETY: The host posts only the component definition a save just wrote
|
|
957
|
+
(`redefineElementOnCanvases`), a whole `.json` element document, and `redefineElement`
|
|
958
|
+
itself rejects one whose `tagName` is not a hyphenated literal. */
|
|
959
|
+
void redefineElement(msg.doc as JxDocument, msg.base);
|
|
949
960
|
return;
|
|
950
961
|
}
|
|
951
962
|
if (msg.kind === "setLocale") {
|
|
@@ -988,6 +999,8 @@ export function startCanvasIframe(opts: {
|
|
|
988
999
|
// A document with no format, where the studio's own element metadata answers on its own.
|
|
989
1000
|
setEditableVerdicts(msg.editableTags ?? null);
|
|
990
1001
|
const { gen, mapperCtx } = msg;
|
|
1002
|
+
/* SAFETY: The host posts `shadowDoc` as a JSON round-trip of the tab's raw page document (or of
|
|
1003
|
+
the stylebook specimen), so it is a `JxMutableNode` in the forward-op coordinate space. */
|
|
991
1004
|
const rawDoc = msg.shadowDoc as JxMutableNode;
|
|
992
1005
|
void (async () => {
|
|
993
1006
|
try {
|
|
@@ -1002,9 +1015,11 @@ export function startCanvasIframe(opts: {
|
|
|
1002
1015
|
than a theoretical one. It used to be exactly that, one orphaned `<style>` per styled
|
|
1003
1016
|
element per render. */
|
|
1004
1017
|
resetDocumentStyles(container.ownerDocument);
|
|
1005
|
-
|
|
1018
|
+
const renderOpts: Parameters<typeof renderResolvedDocument>[0] = {
|
|
1006
1019
|
assets: versionedAssets(msg.assets ?? null),
|
|
1007
1020
|
container,
|
|
1021
|
+
/* SAFETY: The host posts `doc` as a JSON round-trip of `resolveCanvasDocument`'s render
|
|
1022
|
+
document (or the stylebook specimen), which is the resolved `JxDocument` it renders. */
|
|
1008
1023
|
doc: msg.doc as JxDocument,
|
|
1009
1024
|
docBase: msg.docBase,
|
|
1010
1025
|
mapperCtx: {
|
|
@@ -1019,8 +1034,11 @@ export function startCanvasIframe(opts: {
|
|
|
1019
1034
|
popoverOpen: msg.popoverOpen ? serializeJxPath(msg.popoverOpen) : null,
|
|
1020
1035
|
dialogOpen: msg.dialogOpen ? serializeJxPath(msg.dialogOpen) : null,
|
|
1021
1036
|
siteStyle: msg.siteStyle,
|
|
1022
|
-
|
|
1023
|
-
|
|
1037
|
+
};
|
|
1038
|
+
if (msg.allowAutoRequests) {
|
|
1039
|
+
renderOpts.allowAutoRequests = true;
|
|
1040
|
+
}
|
|
1041
|
+
handle = await renderResolvedDocument(renderOpts);
|
|
1024
1042
|
if (gen === latestGen) {
|
|
1025
1043
|
/* A render replaces the DOM, so the open attribute goes with it. The host sends the value
|
|
1026
1044
|
on the render message for exactly this reason; a frame that kept only its own copy
|
|
@@ -1042,7 +1060,7 @@ export function startCanvasIframe(opts: {
|
|
|
1042
1060
|
// BuildScope returns, and serializeDataScope reads defs[key], so the effect tracks those
|
|
1043
1061
|
// Refs and RE-POSTS an updated snapshot when the data settles (the host gen-gates stale
|
|
1044
1062
|
// Ones). Isolated in try/catch: a serialization failure never breaks the render ack above.
|
|
1045
|
-
const defs = handle.ctx
|
|
1063
|
+
const { defs } = handle.ctx;
|
|
1046
1064
|
stopDataScopeWatch = observeScope(() => {
|
|
1047
1065
|
try {
|
|
1048
1066
|
channel.post({ gen, kind: "dataScope", scope: serializeDataScope(defs) });
|
|
@@ -1054,11 +1072,7 @@ export function startCanvasIframe(opts: {
|
|
|
1054
1072
|
postContentHeight();
|
|
1055
1073
|
}
|
|
1056
1074
|
} catch (error) {
|
|
1057
|
-
channel.post({
|
|
1058
|
-
gen,
|
|
1059
|
-
kind: "renderError",
|
|
1060
|
-
message: String((error as Error)?.message ?? error),
|
|
1061
|
-
});
|
|
1075
|
+
channel.post({ gen, kind: "renderError", message: failureText(error) });
|
|
1062
1076
|
}
|
|
1063
1077
|
})();
|
|
1064
1078
|
});
|
|
@@ -1094,7 +1108,9 @@ export function startCanvasIframe(opts: {
|
|
|
1094
1108
|
interface BootWindow {
|
|
1095
1109
|
location: { search: string };
|
|
1096
1110
|
document: { querySelector: (selectors: string) => Element | null; body: HTMLElement };
|
|
1097
|
-
parent: {
|
|
1111
|
+
parent: {
|
|
1112
|
+
postMessage: (message: CanvasEnvelope<IframeToParent>, targetOrigin: string) => void;
|
|
1113
|
+
};
|
|
1098
1114
|
addEventListener: (type: "message", listener: (event: MessageEvent) => void) => void;
|
|
1099
1115
|
removeEventListener: (type: "message", listener: (event: MessageEvent) => void) => void;
|
|
1100
1116
|
}
|
|
@@ -1122,8 +1138,9 @@ export function bootCanvasIframe(win: BootWindow): () => void {
|
|
|
1122
1138
|
"The parent origin did not round-trip; the channel relies on the shared token alone.",
|
|
1123
1139
|
);
|
|
1124
1140
|
}
|
|
1125
|
-
|
|
1126
|
-
|
|
1141
|
+
// `canvas.html` draws `#jx-canvas-root` as a `<div>`; a page without it renders into `<body>`.
|
|
1142
|
+
const root = win.document.querySelector("#jx-canvas-root");
|
|
1143
|
+
const container = root instanceof HTMLElement ? root : win.document.body;
|
|
1127
1144
|
const channel = postMessageChannel<IframeToParent, ParentToIframe>({
|
|
1128
1145
|
acceptOrigin: parentOrigin,
|
|
1129
1146
|
source: win,
|
|
@@ -1136,5 +1153,5 @@ export function bootCanvasIframe(win: BootWindow): () => void {
|
|
|
1136
1153
|
|
|
1137
1154
|
// Boot only when actually loaded as the iframe document (has a real parent frame), never in tests.
|
|
1138
1155
|
if (typeof window !== "undefined" && window.parent !== window) {
|
|
1139
|
-
bootCanvasIframe(window
|
|
1156
|
+
bootCanvasIframe(window);
|
|
1140
1157
|
}
|