@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
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* (happy-dom's `elementFromPoint` returns null) and lives in iframe-interaction.
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
+
import { isNumber } from "@jxsuite/schema/guards";
|
|
20
21
|
import { parseJxPath } from "./path-mapping";
|
|
21
22
|
import { rectOf } from "../utils/geometry";
|
|
22
23
|
import { childIndex, parentElementPath } from "../state";
|
|
@@ -48,7 +49,7 @@ function isRowLayout(parent: HTMLElement): boolean {
|
|
|
48
49
|
const isGrid = display === "grid" || display === "inline-grid";
|
|
49
50
|
return (
|
|
50
51
|
(isFlex && style.flexDirection.startsWith("row")) ||
|
|
51
|
-
(isGrid &&
|
|
52
|
+
(isGrid && style.gridAutoFlow.startsWith("column"))
|
|
52
53
|
);
|
|
53
54
|
}
|
|
54
55
|
|
|
@@ -78,11 +79,11 @@ export function computeInsertZones(
|
|
|
78
79
|
shadowDoc: JxMutableNode,
|
|
79
80
|
): InsertZone[] | null {
|
|
80
81
|
void shadowDoc;
|
|
81
|
-
const serialized = targetEl.dataset
|
|
82
|
+
const serialized = targetEl.dataset.jxPath;
|
|
82
83
|
if (serialized == null) {
|
|
83
84
|
return null;
|
|
84
85
|
}
|
|
85
|
-
const targetPath = parseJxPath(serialized)
|
|
86
|
+
const targetPath = parseJxPath(serialized);
|
|
86
87
|
|
|
87
88
|
// Empty container: one centered "+" that inserts as the container's first child.
|
|
88
89
|
if (targetEl.classList.contains(EMPTY_CONTAINER_CLASS)) {
|
|
@@ -99,7 +100,7 @@ export function computeInsertZones(
|
|
|
99
100
|
return null;
|
|
100
101
|
}
|
|
101
102
|
const childIdx = childIndex(targetPath);
|
|
102
|
-
if (
|
|
103
|
+
if (!isNumber(childIdx)) {
|
|
103
104
|
return null;
|
|
104
105
|
}
|
|
105
106
|
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { jxPathSelector, parseJxPath, serializeJxPath } from "./path-mapping";
|
|
10
|
+
import { isFunction } from "@jxsuite/schema/guards";
|
|
10
11
|
import { rectOf } from "../utils/geometry";
|
|
11
12
|
import { computeInsertZones, insertZonesKey } from "./iframe-insert";
|
|
12
13
|
import { getActiveElement, isEditing } from "../editor/inline-edit";
|
|
@@ -32,9 +33,10 @@ function isCanvasLeave(e: Event, doc: Document): boolean {
|
|
|
32
33
|
|
|
33
34
|
/** Walk up from an element to the nearest ancestor carrying a `data-jx-path`; null if none. */
|
|
34
35
|
function nearestPathEl(start: Element | null): HTMLElement | null {
|
|
35
|
-
let el = start instanceof Element ?
|
|
36
|
+
let el = start instanceof Element ? start : null;
|
|
36
37
|
while (el) {
|
|
37
|
-
|
|
38
|
+
// Only HTML elements are stamped (`makeStamper` skips everything else), so only they can match.
|
|
39
|
+
if (el instanceof HTMLElement && el.dataset.jxPath) {
|
|
38
40
|
return el;
|
|
39
41
|
}
|
|
40
42
|
el = el.parentElement;
|
|
@@ -57,6 +59,7 @@ export function nearestHit(target: EventTarget | null): NodeHit | null {
|
|
|
57
59
|
if (!el) {
|
|
58
60
|
return null;
|
|
59
61
|
}
|
|
62
|
+
// SAFETY: nearestPathEl returns only an element whose `data-jx-path` is a non-empty string.
|
|
60
63
|
return measureHit(el, el.dataset.jxPath as string);
|
|
61
64
|
}
|
|
62
65
|
|
|
@@ -75,8 +78,9 @@ export function nearestHit(target: EventTarget | null): NodeHit | null {
|
|
|
75
78
|
* from a node that is on screen is a worse failure than drawing one for a node that is not.
|
|
76
79
|
*/
|
|
77
80
|
function isRendered(el: Element): boolean {
|
|
78
|
-
|
|
79
|
-
|
|
81
|
+
// Absent on engines that predate it, whatever lib.dom says.
|
|
82
|
+
const check: Element["checkVisibility"] | undefined = el.checkVisibility;
|
|
83
|
+
return isFunction(check) ? check.call(el, { checkVisibilityCSS: true }) : true;
|
|
80
84
|
}
|
|
81
85
|
|
|
82
86
|
/**
|
|
@@ -92,10 +96,7 @@ function isRendered(el: Element): boolean {
|
|
|
92
96
|
* The serialized path is the same string the renderer stamps, so a stored selection path
|
|
93
97
|
* round-trips back to its element.
|
|
94
98
|
*/
|
|
95
|
-
export function measureHits(
|
|
96
|
-
paths: (string | number)[][],
|
|
97
|
-
doc: Document = document,
|
|
98
|
-
): { hits: NodeHit[]; hidden: (string | number)[][] } {
|
|
99
|
+
export function measureHits(paths: (string | number)[][], doc: Document = document) {
|
|
99
100
|
const hits: NodeHit[] = [];
|
|
100
101
|
const hidden: (string | number)[][] = [];
|
|
101
102
|
for (const path of paths) {
|
|
@@ -119,8 +120,15 @@ export function measureHits(
|
|
|
119
120
|
* {@link file://./iframe-drop.ts}'s `startGrabDetector` receives its deps rather than reaching for
|
|
120
121
|
* module state.
|
|
121
122
|
*/
|
|
123
|
+
type InvokerAction = Extract<IframeToParent, { kind: "popoverTargetClick" }>["action"];
|
|
124
|
+
|
|
122
125
|
/** The three `popovertargetaction` keywords. Anything else falls back to the HTML default. */
|
|
123
|
-
const INVOKER_ACTIONS = new Set(["toggle", "show", "hide"]);
|
|
126
|
+
const INVOKER_ACTIONS = new Set<string>(["toggle", "show", "hide"] satisfies InvokerAction[]);
|
|
127
|
+
|
|
128
|
+
/** Whether an attribute value is one of the {@link INVOKER_ACTIONS} keywords. */
|
|
129
|
+
function isInvokerAction(value: string): value is InvokerAction {
|
|
130
|
+
return INVOKER_ACTIONS.has(value);
|
|
131
|
+
}
|
|
124
132
|
|
|
125
133
|
/**
|
|
126
134
|
* Report an invoker click, when the click landed on one and it names an addressable popover.
|
|
@@ -152,14 +160,14 @@ function postPopoverInvoke(
|
|
|
152
160
|
need escaping — a rule this file already keeps in exactly one place (`jxPathSelector`) and
|
|
153
161
|
should not gain a second spelling of. The set scanned is the addressable POPOVERS, which is
|
|
154
162
|
also the set the answer has to come from, so the scan is the test. */
|
|
155
|
-
const panels = invoker.ownerDocument.querySelectorAll("[data-jx-popover]");
|
|
156
|
-
const panel = [...panels].find((el) => el.id === id)
|
|
163
|
+
const panels = invoker.ownerDocument.querySelectorAll<HTMLElement>("[data-jx-popover]");
|
|
164
|
+
const panel = [...panels].find((el) => el.id === id);
|
|
157
165
|
const serialized = panel?.dataset.jxPath;
|
|
158
166
|
if (!serialized) {
|
|
159
167
|
return;
|
|
160
168
|
}
|
|
161
169
|
const raw = invoker.getAttribute("popovertargetaction") ?? "toggle";
|
|
162
|
-
const action =
|
|
170
|
+
const action = isInvokerAction(raw) ? raw : "toggle";
|
|
163
171
|
channel.post({ action, kind: "popoverTargetClick", targetPath: parseJxPath(serialized) });
|
|
164
172
|
}
|
|
165
173
|
|
|
@@ -190,10 +198,10 @@ function postCommandInvoke(
|
|
|
190
198
|
}
|
|
191
199
|
// Scanned, not selected, for the reason `postPopoverInvoke` gives; the addressable overlays are
|
|
192
200
|
// The de-popovered panels and the stamped dialogs.
|
|
193
|
-
const overlays = invoker.ownerDocument.querySelectorAll(
|
|
201
|
+
const overlays = invoker.ownerDocument.querySelectorAll<HTMLElement>(
|
|
194
202
|
"[data-jx-popover], dialog[data-jx-path]",
|
|
195
203
|
);
|
|
196
|
-
const overlay = [...overlays].find((el) => el.id === id)
|
|
204
|
+
const overlay = [...overlays].find((el) => el.id === id);
|
|
197
205
|
const serialized = overlay?.dataset.jxPath;
|
|
198
206
|
if (!serialized) {
|
|
199
207
|
return;
|
|
@@ -270,7 +278,7 @@ export function startInteraction(
|
|
|
270
278
|
channel.post({ kind: "paneFocus" });
|
|
271
279
|
};
|
|
272
280
|
|
|
273
|
-
const onClick = (e:
|
|
281
|
+
const onClick = (e: MouseEvent) => {
|
|
274
282
|
/*
|
|
275
283
|
* Preview keeps anchors live, so a click would navigate this iframe and destroy the render (and
|
|
276
284
|
* the editing session with it). Report the intent so the parent can open the real page in a real
|
|
@@ -303,9 +311,8 @@ export function startInteraction(
|
|
|
303
311
|
// Ctrl/Cmd is the accumulate gesture (studio-ui-guidelines.md §8.1). The iframe reports the
|
|
304
312
|
// Modifier and nothing else — it holds no selection state, so what a modified click MEANS is
|
|
305
313
|
// The parent's to decide, exactly as the unmodified click already was.
|
|
306
|
-
const mouse = e as MouseEvent;
|
|
307
314
|
channel.post({
|
|
308
|
-
additive:
|
|
315
|
+
additive: e.ctrlKey === true || e.metaKey === true,
|
|
309
316
|
hit,
|
|
310
317
|
kind: "hit",
|
|
311
318
|
});
|
|
@@ -394,11 +401,10 @@ export function startInteraction(
|
|
|
394
401
|
reportInsertZones(target, { x: moveX, y: moveY });
|
|
395
402
|
};
|
|
396
403
|
|
|
397
|
-
const onMove = (e:
|
|
398
|
-
const pe = e as PointerEvent;
|
|
404
|
+
const onMove = (e: PointerEvent) => {
|
|
399
405
|
moveTarget = e.target;
|
|
400
|
-
moveX =
|
|
401
|
-
moveY =
|
|
406
|
+
moveX = e.clientX;
|
|
407
|
+
moveY = e.clientY;
|
|
402
408
|
if (movePending) {
|
|
403
409
|
return;
|
|
404
410
|
}
|
|
@@ -415,8 +421,7 @@ export function startInteraction(
|
|
|
415
421
|
}
|
|
416
422
|
};
|
|
417
423
|
|
|
418
|
-
const onContextMenu = (e:
|
|
419
|
-
const me = e as MouseEvent;
|
|
424
|
+
const onContextMenu = (e: MouseEvent) => {
|
|
420
425
|
// Preview keeps the NATIVE menu: the Jx element menu's verbs (duplicate, delete, paste, wrap)
|
|
421
426
|
// Are document edits, and preview does not edit. Copy Link Address does what it says instead.
|
|
422
427
|
if (isPreview()) {
|
|
@@ -447,8 +452,8 @@ export function startInteraction(
|
|
|
447
452
|
channel.post({
|
|
448
453
|
kind: "contextMenu",
|
|
449
454
|
path: hit.path,
|
|
450
|
-
x:
|
|
451
|
-
y:
|
|
455
|
+
x: e.clientX,
|
|
456
|
+
y: e.clientY,
|
|
452
457
|
});
|
|
453
458
|
};
|
|
454
459
|
|
|
@@ -47,7 +47,7 @@ export function parentCursorToIframe(
|
|
|
47
47
|
cursor: { x: number; y: number },
|
|
48
48
|
iframeRect: { left: number; top: number },
|
|
49
49
|
scale = 1,
|
|
50
|
-
)
|
|
50
|
+
) {
|
|
51
51
|
return {
|
|
52
52
|
x: (cursor.x - iframeRect.left) / scale,
|
|
53
53
|
y: (cursor.y - iframeRect.top) / scale,
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import { reapplyStyle } from "@jxsuite/runtime";
|
|
18
|
-
import {
|
|
18
|
+
import { isNonNullObject, isNumber, isString } from "@jxsuite/schema/guards";
|
|
19
|
+
import { getNodeAtPath } from "@jxsuite/schema/doc-ops";
|
|
19
20
|
import { applyDocOpToDoc } from "../tabs/doc-op-apply";
|
|
20
21
|
import { parseJxPath, serializeJxPath } from "./path-mapping";
|
|
21
22
|
import { disposeSubtree, renderSubtreeIframe } from "./iframe-subtree";
|
|
@@ -25,7 +26,7 @@ import {
|
|
|
25
26
|
templateToEditDisplay,
|
|
26
27
|
} from "../utils/edit-display";
|
|
27
28
|
import type { IframeRenderCtx } from "./iframe-render";
|
|
28
|
-
import type {
|
|
29
|
+
import type { JxDocOp } from "../tabs/patch-ops";
|
|
29
30
|
import type { JxPath } from "../state";
|
|
30
31
|
import type { JxMutableNode, JxStyle } from "@jxsuite/schema/types";
|
|
31
32
|
|
|
@@ -36,7 +37,7 @@ import type { JxMutableNode, JxStyle } from "@jxsuite/schema/types";
|
|
|
36
37
|
*/
|
|
37
38
|
export function applyIframePatch(
|
|
38
39
|
shadowDoc: JxMutableNode,
|
|
39
|
-
forwardOps:
|
|
40
|
+
forwardOps: JxDocOp[],
|
|
40
41
|
container: HTMLElement,
|
|
41
42
|
ctx?: IframeRenderCtx,
|
|
42
43
|
echoPaths?: JxPath[],
|
|
@@ -98,7 +99,7 @@ function requireCtx(ctx: IframeRenderCtx | undefined): IframeRenderCtx {
|
|
|
98
99
|
|
|
99
100
|
function applyOpToDom(
|
|
100
101
|
doc: JxMutableNode,
|
|
101
|
-
op:
|
|
102
|
+
op: JxDocOp,
|
|
102
103
|
container: HTMLElement,
|
|
103
104
|
ctx: IframeRenderCtx | undefined,
|
|
104
105
|
): void {
|
|
@@ -138,7 +139,7 @@ function applyOpToDom(
|
|
|
138
139
|
return;
|
|
139
140
|
}
|
|
140
141
|
default: {
|
|
141
|
-
// The
|
|
142
|
+
// The JxDocOp union is exhaustively handled above; this guards a future op kind.
|
|
142
143
|
throw new Error(`iframe-patch-unsupported-op:${JSON.stringify(op)}`);
|
|
143
144
|
}
|
|
144
145
|
}
|
|
@@ -292,7 +293,7 @@ function remapChildPaths(
|
|
|
292
293
|
continue;
|
|
293
294
|
}
|
|
294
295
|
const idx = p[depth + 1];
|
|
295
|
-
if (
|
|
296
|
+
if (!isNumber(idx) || idx < fromIndex) {
|
|
296
297
|
continue;
|
|
297
298
|
}
|
|
298
299
|
if (!parentPath.every((seg, i) => p[i] === seg)) {
|
|
@@ -338,7 +339,9 @@ function patchStyle(
|
|
|
338
339
|
): void {
|
|
339
340
|
const el = requireElement(container, path);
|
|
340
341
|
const node = getNodeAtPath(doc, path);
|
|
341
|
-
|
|
342
|
+
/* SAFETY: buildScope writes `$media` only from the document's own `$media` map or the runtime's
|
|
343
|
+
* root media map, both Record<string, string>, and the host scope may not supply the key. */
|
|
344
|
+
const mediaQueries = (ctx?.defs["$media"] as Record<string, string> | undefined) ?? {};
|
|
342
345
|
reapplyStyle(el, editModeStyle(node?.style), mediaQueries);
|
|
343
346
|
}
|
|
344
347
|
|
|
@@ -372,20 +375,20 @@ function findElement(container: HTMLElement, path: (string | number)[]): HTMLEle
|
|
|
372
375
|
* top-level template-string values are blanked so no reactive bindings are created for them.
|
|
373
376
|
*/
|
|
374
377
|
function editModeStyle(style: JxStyle | undefined): JxStyle | undefined {
|
|
375
|
-
if (!style ||
|
|
378
|
+
if (!style || !isNonNullObject(style)) {
|
|
376
379
|
return undefined;
|
|
377
380
|
}
|
|
378
|
-
const out:
|
|
381
|
+
const out: JxStyle = {};
|
|
379
382
|
for (const [k, v] of Object.entries(style)) {
|
|
380
383
|
/* OMITTED, not blanked. It used to be written as `""`, which was a silent no-op while a
|
|
381
384
|
declaration went to `el.style` and is a malformed declaration now that it goes into a rule.
|
|
382
385
|
Dropping the key is what blanking always meant: the property falls back to the cascade. */
|
|
383
|
-
if (
|
|
386
|
+
if (isString(v) && v.includes("${")) {
|
|
384
387
|
continue;
|
|
385
388
|
}
|
|
386
389
|
out[k] = v;
|
|
387
390
|
}
|
|
388
|
-
return out
|
|
391
|
+
return out;
|
|
389
392
|
}
|
|
390
393
|
|
|
391
394
|
/**
|
|
@@ -393,15 +396,15 @@ function editModeStyle(style: JxStyle | undefined): JxStyle | undefined {
|
|
|
393
396
|
* template-string and $ref display rules (and the legacy patcher's textDisplayValue).
|
|
394
397
|
*/
|
|
395
398
|
function textDisplayValue(node: JxMutableNode | undefined): string {
|
|
396
|
-
const v =
|
|
399
|
+
const v = node?.textContent;
|
|
397
400
|
if (v == null) {
|
|
398
401
|
return "";
|
|
399
402
|
}
|
|
400
|
-
if (
|
|
403
|
+
if (isString(v)) {
|
|
401
404
|
return v.includes("${") ? templateToEditDisplay(v) : v;
|
|
402
405
|
}
|
|
403
|
-
if (
|
|
404
|
-
const ref = String(
|
|
406
|
+
if (isNonNullObject(v) && v.$ref) {
|
|
407
|
+
const ref = String(v.$ref);
|
|
405
408
|
const label = ref.startsWith("#/state/") ? ref.slice(8) : ref;
|
|
406
409
|
return `{${label}}`;
|
|
407
410
|
}
|
|
@@ -33,6 +33,12 @@ export interface DocRange {
|
|
|
33
33
|
head: DocPos;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
/** A live DOM caret position: a node and an offset into it, as a Selection endpoint carries. */
|
|
37
|
+
export interface DomPosition {
|
|
38
|
+
node: Node;
|
|
39
|
+
offset: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
36
42
|
/** Whether an element is a block the caret may live inside. Injected so the editable set is policy. */
|
|
37
43
|
export type EditablePredicate = (el: HTMLElement) => boolean;
|
|
38
44
|
|
|
@@ -91,7 +97,7 @@ export function elementForPath(container: HTMLElement, path: JxPath): HTMLElemen
|
|
|
91
97
|
|
|
92
98
|
/** The block's rendered text length — the maximum valid offset within it. */
|
|
93
99
|
export function blockTextLength(block: HTMLElement): number {
|
|
94
|
-
return block.textContent
|
|
100
|
+
return block.textContent.length;
|
|
95
101
|
}
|
|
96
102
|
|
|
97
103
|
/**
|
|
@@ -126,11 +132,12 @@ export function offsetOf(block: HTMLElement, node: Node, offset: number): number
|
|
|
126
132
|
* every offset-based editor carries at a line break, and it is invisible for the paths that use
|
|
127
133
|
* this (caret restore after a patch, and block-boundary edits, which clamp to 0 / length anyway).
|
|
128
134
|
*/
|
|
129
|
-
export function domPositionAt(block: HTMLElement, offset: number):
|
|
135
|
+
export function domPositionAt(block: HTMLElement, offset: number): DomPosition {
|
|
130
136
|
const target = Math.max(0, Math.min(offset, blockTextLength(block)));
|
|
131
137
|
const walker = block.ownerDocument.createTreeWalker(block, NodeFilter.SHOW_TEXT);
|
|
132
138
|
let seen = 0;
|
|
133
139
|
let last: Text | null = null;
|
|
140
|
+
// SAFETY: the walker was created with NodeFilter.SHOW_TEXT, so every node it yields is a Text.
|
|
134
141
|
let current = walker.nextNode() as Text | null;
|
|
135
142
|
while (current) {
|
|
136
143
|
const len = current.length;
|
|
@@ -139,6 +146,7 @@ export function domPositionAt(block: HTMLElement, offset: number): { node: Node;
|
|
|
139
146
|
}
|
|
140
147
|
seen += len;
|
|
141
148
|
last = current;
|
|
149
|
+
// SAFETY: the same SHOW_TEXT walker as above, so the next node is a Text or the walk's end.
|
|
142
150
|
current = walker.nextNode() as Text | null;
|
|
143
151
|
}
|
|
144
152
|
// No text node reaches the target: either the block has no text at all (caret goes to the element
|
|
@@ -169,10 +177,7 @@ export function toDocPos(
|
|
|
169
177
|
* block whose text shrank under a remote edit lands at the block's new end instead of being
|
|
170
178
|
* dropped.
|
|
171
179
|
*/
|
|
172
|
-
export function toDomPosition(
|
|
173
|
-
container: HTMLElement,
|
|
174
|
-
pos: DocPos,
|
|
175
|
-
): { node: Node; offset: number } | null {
|
|
180
|
+
export function toDomPosition(container: HTMLElement, pos: DocPos): DomPosition | null {
|
|
176
181
|
const el = elementForPath(container, pos.path);
|
|
177
182
|
return el ? domPositionAt(el, pos.offset) : null;
|
|
178
183
|
}
|
|
@@ -246,6 +251,7 @@ export function adjacentBlock(
|
|
|
246
251
|
const key = serializeJxPath(path);
|
|
247
252
|
const index = blocks.findIndex((el) => el.dataset.jxPath === key);
|
|
248
253
|
const neighbour = index === -1 ? undefined : blocks[index + direction];
|
|
254
|
+
// SAFETY: blocksInOrder collects only elements matching `[data-jx-path]`, so the attribute is set.
|
|
249
255
|
return neighbour
|
|
250
256
|
? { el: neighbour, path: parseJxPath(neighbour.dataset.jxPath as string) }
|
|
251
257
|
: null;
|
|
@@ -12,16 +12,7 @@
|
|
|
12
12
|
import type { AssetContext } from "./asset-resolve";
|
|
13
13
|
import type { JxDocOp } from "../tabs/patch-ops";
|
|
14
14
|
import type { JxContentResult, SlashCommand } from "../editor/inline-edit";
|
|
15
|
-
import type { JxExpressionNode, JxMutableNode } from "@jxsuite/schema/types";
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* The wire form of a value-carrying document op (the `forward` half of a recorded
|
|
19
|
-
* {@link JxDocOpPair} — see {@link file://../tabs/patch-ops.ts}). It is structurally a
|
|
20
|
-
* {@link JxDocOp}: it carries the inserted/replaced `node` and the set `value`, NOT just a path, so
|
|
21
|
-
* the iframe can fold it into its shadow doc and re-render subtrees without ever reading the
|
|
22
|
-
* parent's reactive document.
|
|
23
|
-
*/
|
|
24
|
-
export type WireDocOp = JxDocOp;
|
|
15
|
+
import type { JsonObject, JxExpressionNode, JxMutableNode, JxStyle } from "@jxsuite/schema/types";
|
|
25
16
|
|
|
26
17
|
export const CANVAS_MODES = ["preview", "design", "edit", "stylebook", "git-diff"] as const;
|
|
27
18
|
|
|
@@ -37,7 +28,7 @@ export const CANVAS_MODES = ["preview", "design", "edit", "stylebook", "git-diff
|
|
|
37
28
|
export type CanvasMode = (typeof CANVAS_MODES)[number];
|
|
38
29
|
|
|
39
30
|
export function isCanvasMode(value: unknown): value is CanvasMode {
|
|
40
|
-
return typeof value === "string" && (
|
|
31
|
+
return typeof value === "string" && CANVAS_MODES.some((mode) => mode === value);
|
|
41
32
|
}
|
|
42
33
|
|
|
43
34
|
/**
|
|
@@ -121,7 +112,7 @@ export type ParentToIframe =
|
|
|
121
112
|
*/
|
|
122
113
|
assets?: AssetContext | null;
|
|
123
114
|
mapperCtx: WireMapperCtx;
|
|
124
|
-
siteStyle:
|
|
115
|
+
siteStyle: JxStyle | null;
|
|
125
116
|
// Forced color-scheme preview (spec.md §9.5): "light"/"dark" sets data-color-scheme on the
|
|
126
117
|
// Iframe root, null clears it (auto — follow the OS).
|
|
127
118
|
colorScheme: "light" | "dark" | null;
|
|
@@ -239,7 +230,7 @@ export type ParentToIframe =
|
|
|
239
230
|
// Render-free; the superseding render carries the same style via its own siteStyle.
|
|
240
231
|
| {
|
|
241
232
|
kind: "siteStyleUpdate";
|
|
242
|
-
siteStyle:
|
|
233
|
+
siteStyle: JxStyle | null;
|
|
243
234
|
media: Record<string, string>;
|
|
244
235
|
}
|
|
245
236
|
// Ask the iframe to measure the given document paths and post their current rects back. Used to
|
|
@@ -255,7 +246,12 @@ export type ParentToIframe =
|
|
|
255
246
|
// In place. `gen` matches the last render so the iframe drops patches superseded by a re-render.
|
|
256
247
|
| {
|
|
257
248
|
kind: "patch";
|
|
258
|
-
|
|
249
|
+
/**
|
|
250
|
+
* The `forward` halves of the recorded {@link JxDocOp} pairs (tabs/patch-ops.ts). Each carries
|
|
251
|
+
* the inserted/replaced `node` and the set `value`, not just a path, so the iframe folds it
|
|
252
|
+
* into its shadow doc without ever reading the parent's reactive document.
|
|
253
|
+
*/
|
|
254
|
+
forwardOps: JxDocOp[];
|
|
259
255
|
gen: number;
|
|
260
256
|
/**
|
|
261
257
|
* Paths whose DOM the RECIPIENT already has correct, because this patch is the echo of an
|
|
@@ -273,7 +269,7 @@ export type ParentToIframe =
|
|
|
273
269
|
// Regenerates the whole scoped-CSS cascade (real @media included) without a re-render. `style` is
|
|
274
270
|
// Already transposed parent-side (transposeStylebookStyle); `gen` must equal the iframe's
|
|
275
271
|
// RenderedGen — a stale update is dropped (the superseding render carries the same style).
|
|
276
|
-
| { kind: "styleUpdate"; style:
|
|
272
|
+
| { kind: "styleUpdate"; style: JxStyle; gen: number }
|
|
277
273
|
// Enter inline editing on the node at `path` (used to re-enter after a split/insert re-renders).
|
|
278
274
|
| {
|
|
279
275
|
kind: "enterEdit";
|
|
@@ -490,7 +486,7 @@ export type IframeToParent =
|
|
|
490
486
|
// `S.canvas.scope` so the data-explorer panel shows live data instead of "pending" (the iframe,
|
|
491
487
|
// Not the parent, now resolves the scope). `gen` lets the parent drop a snapshot from a superseded
|
|
492
488
|
// Render. Posted right after `renderComplete`; values are JSON-safe deep clones (see serialize-scope).
|
|
493
|
-
| { kind: "dataScope"; gen: number; scope:
|
|
489
|
+
| { kind: "dataScope"; gen: number; scope: JsonObject }
|
|
494
490
|
// The frame's own quiescence, ANSWERED rather than polled (studio.md §13.5).
|
|
495
491
|
// Nothing in the parent realm can see inside a cross-origin frame, so a parent that wanted to
|
|
496
492
|
// Know whether the canvas had settled could only sleep. The frame samples itself at its own rAF
|
|
@@ -38,7 +38,8 @@ import { elementForPath } from "./iframe-position";
|
|
|
38
38
|
import type { AssetContext } from "./asset-resolve";
|
|
39
39
|
import { SITE_STYLE_ID, buildSiteStyleCSS } from "@jxsuite/site/site-style";
|
|
40
40
|
import type { CanvasMode, WireDiffMarks } from "./iframe-protocol";
|
|
41
|
-
import
|
|
41
|
+
import { isNonNullObject, isString } from "@jxsuite/schema/guards";
|
|
42
|
+
import type { JxDocument, JxElement, JxStyle } from "@jxsuite/schema/types";
|
|
42
43
|
import type { PathMapCtx } from "./path-mapping";
|
|
43
44
|
|
|
44
45
|
/**
|
|
@@ -61,18 +62,12 @@ export interface RenderHandle {
|
|
|
61
62
|
ctx: IframeRenderCtx;
|
|
62
63
|
}
|
|
63
64
|
|
|
64
|
-
interface HeadEntry {
|
|
65
|
-
tagName?: string;
|
|
66
|
-
attributes?: Record<string, unknown>;
|
|
67
|
-
textContent?: string;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
65
|
/**
|
|
71
66
|
* Register the document's `$elements` (components) in this iframe realm so the runtime can render
|
|
72
67
|
* them.
|
|
73
68
|
*/
|
|
74
69
|
export async function registerElements(doc: JxDocument, docBase: string): Promise<void> {
|
|
75
|
-
const elements =
|
|
70
|
+
const elements = doc.$elements;
|
|
76
71
|
if (!Array.isArray(elements)) {
|
|
77
72
|
return;
|
|
78
73
|
}
|
|
@@ -81,13 +76,16 @@ export async function registerElements(doc: JxDocument, docBase: string): Promis
|
|
|
81
76
|
await Promise.all(
|
|
82
77
|
elements.map(async (entry) => {
|
|
83
78
|
const task = (async () => {
|
|
84
|
-
if (
|
|
79
|
+
if (isString(entry)) {
|
|
85
80
|
const specifier =
|
|
86
81
|
entry.startsWith("/") || entry.startsWith(".") ? entry : `/node_modules/${entry}`;
|
|
87
82
|
await import(specifier);
|
|
88
|
-
} else if (entry &&
|
|
89
|
-
await defineElement(new URL(String(
|
|
90
|
-
} else if (entry
|
|
83
|
+
} else if (isNonNullObject(entry) && "$ref" in entry) {
|
|
84
|
+
await defineElement(new URL(String(entry.$ref), docBase).href);
|
|
85
|
+
} else if (isNonNullObject(entry)) {
|
|
86
|
+
/* SAFETY: an `$elements` entry that is neither a specifier nor a `$ref` is an inline
|
|
87
|
+
* component definition by the schema (JxDocument is JxElement with a literal tagName).
|
|
88
|
+
* A malformed one throws inside this task, which the race below catches and logs. */
|
|
91
89
|
await defineElement(entry as JxDocument, docBase);
|
|
92
90
|
}
|
|
93
91
|
})();
|
|
@@ -696,11 +694,11 @@ export function syncStylebookCss(doc: Document, mode: CanvasMode): void {
|
|
|
696
694
|
* selectors can win (spec.md §9.5), and so removed tokens can't linger on reused iframes.
|
|
697
695
|
*/
|
|
698
696
|
export function applySiteStyle(
|
|
699
|
-
siteStyle:
|
|
697
|
+
siteStyle: JxStyle | null | undefined,
|
|
700
698
|
mediaQueries: Record<string, string> = {},
|
|
701
699
|
): void {
|
|
702
700
|
const existing = document.head.querySelector(`#${SITE_STYLE_ID}`);
|
|
703
|
-
if (!siteStyle ||
|
|
701
|
+
if (!siteStyle || !isNonNullObject(siteStyle)) {
|
|
704
702
|
existing?.remove();
|
|
705
703
|
return;
|
|
706
704
|
}
|
|
@@ -746,15 +744,15 @@ export function applyPreviewColorScheme(doc: Document, scheme: "light" | "dark"
|
|
|
746
744
|
* @docs studio/interface/canvas
|
|
747
745
|
*/
|
|
748
746
|
export function applyCanvasPopoverOpen(root: ParentNode, path: string | null): void {
|
|
749
|
-
for (const el of root.querySelectorAll("[data-jx-popover-open]")) {
|
|
750
|
-
delete
|
|
747
|
+
for (const el of root.querySelectorAll<HTMLElement>("[data-jx-popover-open]")) {
|
|
748
|
+
delete el.dataset.jxPopoverOpen;
|
|
751
749
|
}
|
|
752
750
|
if (path === null) {
|
|
753
751
|
return;
|
|
754
752
|
}
|
|
755
|
-
const target = root.querySelector(`[data-jx-popover]${jxPathSelector(path)}`);
|
|
753
|
+
const target = root.querySelector<HTMLElement>(`[data-jx-popover]${jxPathSelector(path)}`);
|
|
756
754
|
if (target) {
|
|
757
|
-
|
|
755
|
+
target.dataset.jxPopoverOpen = "";
|
|
758
756
|
}
|
|
759
757
|
}
|
|
760
758
|
|
|
@@ -783,26 +781,27 @@ export function applyCanvasPopoverOpen(root: ParentNode, path: string | null): v
|
|
|
783
781
|
* backdrop and all.
|
|
784
782
|
*/
|
|
785
783
|
export function applyCanvasDialogOpen(root: ParentNode, path: string | null): void {
|
|
786
|
-
for (const el of root.querySelectorAll("[data-jx-dialog-open]")) {
|
|
787
|
-
delete
|
|
784
|
+
for (const el of root.querySelectorAll<HTMLElement>("[data-jx-dialog-open]")) {
|
|
785
|
+
delete el.dataset.jxDialogOpen;
|
|
788
786
|
}
|
|
789
787
|
if (path === null) {
|
|
790
788
|
return;
|
|
791
789
|
}
|
|
792
|
-
const target = root.querySelector(`dialog${jxPathSelector(path)}`);
|
|
790
|
+
const target = root.querySelector<HTMLElement>(`dialog${jxPathSelector(path)}`);
|
|
793
791
|
if (target) {
|
|
794
|
-
|
|
792
|
+
target.dataset.jxDialogOpen = "";
|
|
795
793
|
}
|
|
796
794
|
}
|
|
797
795
|
|
|
798
796
|
/** Inject the document's `$head` (link/meta/script) into the iframe's <head>, de-duped by href/src. */
|
|
799
797
|
export function injectHead(doc: JxDocument, assets: AssetContext | null = null): void {
|
|
800
|
-
const head =
|
|
798
|
+
const head = doc.$head;
|
|
801
799
|
if (!Array.isArray(head)) {
|
|
802
800
|
return;
|
|
803
801
|
}
|
|
804
802
|
for (const entry of head) {
|
|
805
|
-
|
|
803
|
+
// A `$head` array read off disk can hold a null or a tagless entry; neither emits anything.
|
|
804
|
+
if (!isNonNullObject(entry) || !entry.tagName) {
|
|
806
805
|
continue;
|
|
807
806
|
}
|
|
808
807
|
const tag = String(entry.tagName).toLowerCase();
|
|
@@ -810,10 +809,10 @@ export function injectHead(doc: JxDocument, assets: AssetContext | null = null):
|
|
|
810
809
|
if (tag === "script" && !entry.attributes?.src) {
|
|
811
810
|
continue;
|
|
812
811
|
}
|
|
813
|
-
const attrs = { ...entry.attributes }
|
|
812
|
+
const attrs = { ...entry.attributes };
|
|
814
813
|
for (const key of ["href", "src"]) {
|
|
815
814
|
const val = attrs[key];
|
|
816
|
-
if (
|
|
815
|
+
if (!isString(val) || val === "") {
|
|
817
816
|
continue;
|
|
818
817
|
}
|
|
819
818
|
if (!val.startsWith("/") && !val.startsWith(".") && !val.startsWith("http")) {
|
|
@@ -833,7 +832,7 @@ export function injectHead(doc: JxDocument, assets: AssetContext | null = null):
|
|
|
833
832
|
el.setAttribute(k, String(v));
|
|
834
833
|
}
|
|
835
834
|
if (entry.textContent) {
|
|
836
|
-
el.textContent = entry.textContent;
|
|
835
|
+
el.textContent = String(entry.textContent);
|
|
837
836
|
}
|
|
838
837
|
document.head.append(el);
|
|
839
838
|
}
|
|
@@ -856,7 +855,7 @@ export function makeStamper(ctx: PathMapCtx) {
|
|
|
856
855
|
(island) => path.length > island.length && island.every((seg, i) => path[i] === seg),
|
|
857
856
|
);
|
|
858
857
|
|
|
859
|
-
return (created: Node, path: (string | number)[], def:
|
|
858
|
+
return (created: Node, path: (string | number)[], def: JxElement | string) => {
|
|
860
859
|
if (!(created instanceof HTMLElement)) {
|
|
861
860
|
return;
|
|
862
861
|
}
|
|
@@ -866,7 +865,10 @@ export function makeStamper(ctx: PathMapCtx) {
|
|
|
866
865
|
// Editable tree and re-render a live instance with default state. Mark the root so the
|
|
867
866
|
// Runtime's element class leaves it alone (see defineElement's connectedCallback guard).
|
|
868
867
|
const isDefinitionRoot =
|
|
869
|
-
path.length === 0 &&
|
|
868
|
+
path.length === 0 &&
|
|
869
|
+
isNonNullObject(def) &&
|
|
870
|
+
isString(def.tagName) &&
|
|
871
|
+
def.tagName.includes("-");
|
|
870
872
|
if (isDefinitionRoot) {
|
|
871
873
|
created.dataset.jxDefinitionRoot = "";
|
|
872
874
|
}
|
|
@@ -984,7 +986,7 @@ export async function renderResolvedDocument(opts: {
|
|
|
984
986
|
docBase: string;
|
|
985
987
|
mode: CanvasMode;
|
|
986
988
|
mapperCtx: PathMapCtx;
|
|
987
|
-
siteStyle?:
|
|
989
|
+
siteStyle?: JxStyle | null;
|
|
988
990
|
/**
|
|
989
991
|
* How this host addresses project media, or null when the canvas origin serves the site's own URL
|
|
990
992
|
* space (desktop, `jx dev`) and references need no resolution at all.
|
|
@@ -1037,7 +1039,7 @@ export async function renderResolvedDocument(opts: {
|
|
|
1037
1039
|
// Iframe clears it (page-level templates are inert in design/edit via prepareForEditMode, so only
|
|
1038
1040
|
// Component internals get stamped).
|
|
1039
1041
|
setStampPropBindings(opts.mode === "design" || opts.mode === "edit");
|
|
1040
|
-
applySiteStyle(opts.siteStyle,
|
|
1042
|
+
applySiteStyle(opts.siteStyle, opts.doc.$media ?? {});
|
|
1041
1043
|
injectHead(opts.doc, assets);
|
|
1042
1044
|
syncEditModeCss(opts.container.ownerDocument, opts.mode);
|
|
1043
1045
|
// The substitute rules for the attributes the de-link above renamed. Same predicate as the
|
|
@@ -1052,7 +1054,7 @@ export async function renderResolvedDocument(opts: {
|
|
|
1052
1054
|
// But no own `$media` resolves the breakpoint to its real query (the iframe path calls buildScope
|
|
1053
1055
|
// Directly and never the runtime's `Jx()` entry, which is the only other place _rootMedia is set).
|
|
1054
1056
|
// Set it every render (even to `{}`) so a stale map from a previous document cannot leak.
|
|
1055
|
-
setRootMedia(
|
|
1057
|
+
setRootMedia(opts.doc.$media ?? {});
|
|
1056
1058
|
// Register components BEFORE renderNode. The runtime only applies a custom element's `$props` when
|
|
1057
1059
|
// That element is ALREADY defined (renderNode gates renderCustomElementWithProps on a truthy
|
|
1058
1060
|
// `customElements.get(tagName)`); if we register after render, every component paints with its
|
|
@@ -1066,8 +1068,8 @@ export async function renderResolvedDocument(opts: {
|
|
|
1066
1068
|
// The scope MUST be the runtime's (runScoped): renderNode creates its binding effects with the
|
|
1067
1069
|
// Runtime's copy of @vue/reactivity, and scope collection is per module instance — a studio
|
|
1068
1070
|
// EffectScope here collects nothing and dispose() would leak every effect of this render.
|
|
1069
|
-
const { result: el, stop } = runScoped(
|
|
1070
|
-
|
|
1071
|
+
const { result: el, stop } = runScoped(() =>
|
|
1072
|
+
renderNode(opts.doc, $defs, { _path: [], onNodeCreated }),
|
|
1071
1073
|
);
|
|
1072
1074
|
opts.container.replaceChildren(el);
|
|
1073
1075
|
applyCanvasPopoverOpen(opts.container, opts.popoverOpen ?? null);
|