@jxsuite/studio 6.1.1 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/chunks/2020-5wtzce5g.js +4 -0
- package/dist/chunks/{action-group-2mqby73c.js → action-group-4aan7g6g.js} +3 -3
- package/dist/chunks/adapter-5tphg7xe.js +4 -0
- package/dist/chunks/add-new-flow-psym14sn.js +4 -0
- package/dist/chunks/cf-account-picker-haqazq5r.js +4 -0
- package/dist/chunks/cf-settings-h2wrh6hq.js +4 -0
- package/dist/chunks/color-area-6rbra5dy.js +4 -0
- package/dist/chunks/color-field-gy56c94g.js +4 -0
- package/dist/chunks/color-m7r1vk54.js +4 -0
- package/dist/chunks/color-slider-sqqdyf6c.js +4 -0
- package/dist/chunks/combobox-72h32ejk.js +4 -0
- package/dist/chunks/components-r22xca09.js +4 -0
- package/dist/chunks/content-source-mmppmcyg.js +4 -0
- package/dist/chunks/convert-to-repeater-he70fc2b.js +4 -0
- package/dist/chunks/dialog-c4x05vyx.js +4 -0
- package/dist/chunks/editor-ccd9jwsa.js +4 -0
- package/dist/chunks/entry-commands-6qxz9e8p.js +4 -0
- package/dist/chunks/extension-sections-0egb88dm.js +4 -0
- package/dist/chunks/file-ops-qnab36ek.js +4 -0
- package/dist/chunks/files-rcn56qvm.js +4 -0
- package/dist/chunks/format-host-yxz0kjjs.js +4 -0
- package/dist/chunks/fs-events-d1qxq4z4.js +4 -0
- package/dist/chunks/grid-open-4z1g062t.js +4 -0
- package/dist/chunks/grid-view-qg1b5eqx.js +51 -0
- package/dist/chunks/icons-63bjtbs7.js +4 -0
- package/dist/chunks/iframe-entry-2zggzajv.js +5 -0
- package/dist/chunks/iframe-entry-76j8vwwx.js +5 -0
- package/dist/chunks/iframe-entry-99nr5zfb.js +5 -0
- package/dist/chunks/iframe-entry-pkgmcgp0.js +5 -0
- package/dist/chunks/iframe-host-ssv7kyj0.js +4 -0
- package/dist/chunks/{index-2veqmnhr.js → index-32eqzv1k.js} +3 -3
- package/dist/chunks/index-f0jn7nnp.js +4 -0
- package/dist/chunks/{javascript-8nbvs12s.js → javascript-pjp734q4.js} +3 -3
- package/dist/chunks/jsonMode-njkvsa02.js +13 -0
- package/dist/chunks/jx-validate-ttasrbh7.js +4 -0
- package/dist/chunks/layers-bgyr11tr.js +4 -0
- package/dist/chunks/layers-panel-7ez66zeq.js +4 -0
- package/dist/chunks/listbox-c421cf8c.js +4 -0
- package/dist/chunks/lit-html-v9gh687x.js +4 -0
- package/dist/chunks/media-library-sq468wts.js +4 -0
- package/dist/chunks/media-picker-shfe59pt.js +4 -0
- package/dist/chunks/menu-bdpzbfvs.js +4 -0
- package/dist/chunks/monaco-binding-vq1hgnn0.js +4 -0
- package/dist/chunks/monaco-buffer-3afgwvbp.js +4 -0
- package/dist/chunks/monaco-setup-xrd2cbkp.js +4 -0
- package/dist/chunks/notify-kzrjr3fv.js +4 -0
- package/dist/chunks/number-field-y62xq0ty.js +4 -0
- package/dist/chunks/parse-v77xtwv7.js +4 -0
- package/dist/chunks/platform-7v4rtd7m.js +4 -0
- package/dist/chunks/popover-b89sfej7.js +4 -0
- package/dist/chunks/publish-panel-2z9gw8ee.js +4 -0
- package/dist/chunks/publish-quick-qx2455cj.js +4 -0
- package/dist/chunks/publish-workspace-wrc1dgwx.js +4 -0
- package/dist/chunks/quick-search-n0t0eqxb.js +4 -0
- package/dist/chunks/references-9547rg5s.js +4 -0
- package/dist/chunks/right-panel-wsgnr9pn.js +4 -0
- package/dist/chunks/select-rzds841e.js +4 -0
- package/dist/chunks/source-control-kwktr9y6.js +4 -0
- package/dist/chunks/split-c9zfdgxf.js +4 -0
- package/dist/chunks/studio-03ct6yfv.js +9 -0
- package/dist/chunks/studio-07rcfje3.js +5 -0
- package/dist/chunks/studio-3e54qh39.js +7 -0
- package/dist/chunks/studio-3exxhz5g.js +5 -0
- package/dist/chunks/studio-3q40e3rj.js +5 -0
- package/dist/chunks/studio-3qeh9t0h.js +6 -0
- package/dist/chunks/studio-3qqjeep5.js +6 -0
- package/dist/chunks/studio-43sd2mam.js +4 -0
- package/dist/chunks/studio-4hp8pkyt.js +5 -0
- package/dist/chunks/studio-58xg6j2q.js +9 -0
- package/dist/chunks/studio-5g0rprdt.js +7 -0
- package/dist/chunks/studio-6m380wp7.js +5 -0
- package/dist/chunks/studio-80jyh1xh.js +4 -0
- package/dist/chunks/studio-83mk4bgg.js +9 -0
- package/dist/chunks/{studio-kggey1jt.js → studio-881z1xrx.js} +4 -4
- package/dist/chunks/studio-8m0y2qe7.js +5 -0
- package/dist/chunks/studio-8tr6cfrc.js +5 -0
- package/dist/chunks/studio-8vcvfs7r.js +6 -0
- package/dist/chunks/studio-9tmebf0s.js +5 -0
- package/dist/chunks/studio-a2bvaptz.js +5 -0
- package/dist/chunks/studio-b7y5mr30.js +5 -0
- package/dist/chunks/studio-bavb31r0.js +5 -0
- package/dist/chunks/studio-bbe4c90a.js +5 -0
- package/dist/chunks/studio-c05wdnt3.js +5 -0
- package/dist/chunks/studio-ccv2svc6.js +5 -0
- package/dist/chunks/studio-d5grtb9e.js +16 -0
- package/dist/chunks/studio-df0baea9.js +5 -0
- package/dist/chunks/studio-dgk4dqtx.js +7 -0
- package/dist/chunks/studio-e1g64q43.js +5 -0
- package/dist/chunks/studio-ed1hp6zf.js +6 -0
- package/dist/chunks/studio-ed3xx40h.js +7 -0
- package/dist/chunks/studio-f14e1zdj.js +5 -0
- package/dist/chunks/studio-fbhxxc5f.js +5 -0
- package/dist/chunks/studio-fyh0jc96.js +5 -0
- package/dist/chunks/studio-gcxk20n7.js +5 -0
- package/dist/chunks/studio-jaaz8ce9.js +5 -0
- package/dist/chunks/{studio-8grwxtqk.js → studio-jcnsdaep.js} +4 -4
- package/dist/chunks/studio-jsgf2q5k.js +7 -0
- package/dist/chunks/{studio-1q1sh2ax.js → studio-k3xxbagr.js} +3 -3
- package/dist/chunks/studio-k7evxqh4.js +5 -0
- package/dist/chunks/studio-kt3pjkwd.js +5 -0
- package/dist/chunks/studio-m8g16bgz.js +5 -0
- package/dist/chunks/studio-mn0476ag.js +5 -0
- package/dist/chunks/studio-mx1smyq0.js +5 -0
- package/dist/chunks/studio-n0c5h6mf.js +5 -0
- package/dist/chunks/{studio-rv11kfwa.js → studio-nh6d342n.js} +7 -7
- package/dist/chunks/studio-nqxqf8p2.js +4 -0
- package/dist/chunks/studio-p4nrkvqr.js +5 -0
- package/dist/chunks/{studio-h46vtzk8.js → studio-pbxa5fpc.js} +4 -4
- package/dist/chunks/studio-pgmvdv7z.js +7 -0
- package/dist/chunks/studio-ph84avkf.js +5 -0
- package/dist/chunks/{studio-wszjyh0j.js → studio-q0mvbaq6.js} +4 -4
- package/dist/chunks/studio-q0tccd43.js +5 -0
- package/dist/chunks/studio-q7rtx6zq.js +14 -0
- package/dist/chunks/{studio-pre0skq6.js → studio-qgh13jtz.js} +4 -4
- package/dist/chunks/studio-qmn1xc24.js +5 -0
- package/dist/chunks/studio-qwdqwkj0.js +5 -0
- package/dist/chunks/{studio-t6b6qe31.js → studio-r5qy30vx.js} +4 -4
- package/dist/chunks/studio-rj9eamf8.js +5 -0
- package/dist/chunks/studio-rptgsk96.js +5 -0
- package/dist/chunks/studio-rthyg42z.js +928 -0
- package/dist/chunks/studio-s19tp1xr.js +5 -0
- package/dist/chunks/studio-s32578pn.js +5 -0
- package/dist/chunks/studio-svb7yyve.js +5 -0
- package/dist/chunks/studio-syreb644.js +5 -0
- package/dist/chunks/studio-tf9jryb1.js +10 -0
- package/dist/chunks/studio-tfkznv39.js +5 -0
- package/dist/chunks/studio-tft6r105.js +5 -0
- package/dist/chunks/studio-txf2kysx.js +5 -0
- package/dist/chunks/studio-v8867ddv.js +12 -0
- package/dist/chunks/studio-vxq7fcvv.js +5 -0
- package/dist/chunks/studio-w4rz9hdk.js +5 -0
- package/dist/chunks/studio-wbcjbhy1.js +9 -0
- package/dist/chunks/studio-wc649wss.js +5 -0
- package/dist/chunks/studio-wys23mxz.js +5 -0
- package/dist/chunks/studio-x1x167jh.js +5 -0
- package/dist/chunks/studio-x9hsze61.js +5 -0
- package/dist/chunks/studio-y0n7yxea.js +9 -0
- package/dist/chunks/studio-y3ahhdpx.js +5 -0
- package/dist/chunks/studio-z97c48fk.js +5 -0
- package/dist/chunks/studio-zat62m0c.js +5 -0
- package/dist/chunks/studio-zcd2e7yz.js +5 -0
- package/dist/chunks/studio-zz9qe3rw.js +64 -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-1gv0h53h.js +4 -0
- package/dist/chunks/toast-host-1yg5ar8d.js +4 -0
- package/dist/chunks/{toolbar-2nnzqhrj.js → toolbar-44cm5cta.js} +3 -3
- package/dist/chunks/tooltip-yypz28gq.js +4 -0
- package/dist/chunks/tree-9xa4hm7n.js +4 -0
- package/dist/chunks/tsMode-epyfz1hv.js +14 -0
- package/dist/chunks/workspace-dz7nxfhv.js +4 -0
- package/dist/chunks/workspace-home-xsd7hkjw.js +4 -0
- package/dist/chunks/ws-client-bv552sfx.js +4 -0
- package/dist/iframe-entry.js +20 -16
- package/dist/manifest.json +77 -63
- package/dist/studio.js +106 -107
- package/dist/workers/ts.worker.js +3 -3
- package/package.json +17 -16
- 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/component-examples.ts +272 -0
- package/src/browse/library-commands.ts +64 -104
- package/src/browse/library-layouts.ts +270 -53
- package/src/browse/library-model.ts +194 -134
- package/src/browse/library-pane.ts +748 -440
- package/src/browse/library-preview.ts +161 -26
- package/src/browse/library-source.ts +308 -41
- package/src/browse/preview-root.ts +78 -0
- package/src/browse/preview-style.ts +155 -0
- package/src/canvas/asset-refs.ts +40 -10
- package/src/canvas/asset-resolve.ts +19 -23
- package/src/canvas/canvas-helpers.ts +7 -6
- package/src/canvas/canvas-live-render.ts +260 -77
- package/src/canvas/canvas-origin.ts +37 -12
- package/src/canvas/canvas-page-context.ts +112 -0
- package/src/canvas/canvas-patcher.ts +30 -30
- package/src/canvas/canvas-perf.ts +11 -5
- package/src/canvas/canvas-render.ts +175 -148
- package/src/canvas/canvas-surface.ts +5 -3
- package/src/canvas/canvas-utils.ts +147 -61
- 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 +120 -12
- package/src/canvas/iframe-editable-root.ts +29 -16
- package/src/canvas/iframe-entry.ts +104 -75
- package/src/canvas/iframe-eval.ts +73 -49
- package/src/canvas/iframe-host.ts +269 -158
- 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-keys.ts +11 -0
- package/src/canvas/iframe-overlay.ts +1 -1
- package/src/canvas/iframe-patch.ts +25 -21
- package/src/canvas/iframe-position.ts +12 -6
- package/src/canvas/iframe-protocol.ts +36 -21
- package/src/canvas/iframe-render.ts +84 -35
- package/src/canvas/iframe-slash.ts +24 -11
- package/src/canvas/iframe-subtree.ts +10 -3
- package/src/canvas/npm-modules.ts +22 -0
- 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/preview-navigate.ts +16 -0
- package/src/canvas/repeater-sources.ts +200 -0
- package/src/canvas/serialize-scope.ts +13 -5
- package/src/canvas/stage-scrollbar.ts +7 -2
- package/src/canvas/surface-registry.ts +27 -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/app-commands.ts +16 -6
- package/src/commands/budget.ts +13 -11
- package/src/commands/command-args.ts +103 -71
- package/src/commands/context.ts +55 -28
- package/src/commands/defaults.ts +69 -45
- package/src/commands/keymap.ts +56 -43
- package/src/commands/levels.ts +14 -8
- package/src/commands/live-context.ts +9 -7
- package/src/commands/reference.ts +2 -1
- package/src/commands/registry.ts +22 -11
- package/src/commands/run-reported.ts +15 -10
- package/src/component-props.ts +46 -30
- package/src/content/collection-match.ts +11 -9
- package/src/content/collection-pages.ts +412 -0
- package/src/content/content-collections.ts +270 -0
- package/src/content/draft-state.ts +4 -3
- package/src/content/entry-commands.ts +54 -62
- package/src/content/entry-editor.ts +137 -32
- package/src/content/entry-fields.ts +25 -8
- package/src/content/entry-inspector.ts +225 -0
- package/src/content/entry-model.ts +38 -15
- package/src/content/entry-open.ts +80 -0
- package/src/content/entry-summaries.ts +440 -0
- package/src/content/file-record-ids.ts +80 -0
- package/src/content/file-records.ts +125 -0
- package/src/content/page-summaries.ts +129 -0
- package/src/content/record-entry.ts +201 -0
- package/src/content/writing-banner.ts +177 -0
- package/src/create/add-new-commands.ts +185 -0
- package/src/create/add-new-flow.ts +1116 -0
- package/src/create/add-new.ts +1014 -0
- package/src/create/element-name.ts +121 -0
- 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 +78 -48
- package/src/editor/convert-to-repeater.ts +34 -22
- package/src/editor/editable-tags.ts +17 -2
- package/src/editor/file-drop-action.ts +29 -22
- package/src/editor/inline-edit-apply.ts +79 -17
- package/src/editor/inline-edit.ts +76 -50
- package/src/editor/inline-format.ts +59 -56
- package/src/editor/inline-link.ts +40 -15
- package/src/editor/insert-component.ts +91 -0
- package/src/editor/insert-zone-action.ts +14 -5
- package/src/editor/merge-tags.ts +58 -19
- package/src/editor/repeater-scope.ts +39 -28
- package/src/editor/shortcuts.ts +76 -42
- package/src/editor/slash-menu.ts +52 -14
- package/src/files/asset-versions.ts +4 -4
- package/src/files/components.ts +89 -20
- package/src/files/elements.ts +5 -6
- package/src/files/file-ops.ts +92 -41
- package/src/files/files.ts +248 -239
- package/src/files/fs-events.ts +18 -7
- package/src/files/media-meta.ts +97 -2
- package/src/files/media-paths.ts +3 -0
- package/src/files/media-types.ts +55 -0
- package/src/files/media-upload.ts +209 -52
- package/src/files/new-file-name.ts +156 -0
- package/src/files/serialize-document.ts +15 -5
- 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 +91 -50
- package/src/github/github-auth-status.ts +27 -3
- package/src/github/github-auth.ts +21 -11
- package/src/github/github-publish.ts +28 -23
- 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 +25 -23
- package/src/grid/grid-layout.ts +21 -5
- package/src/grid/grid-open.ts +3 -33
- package/src/grid/grid-panel.ts +65 -6
- package/src/grid/grid-reveal.ts +34 -0
- package/src/grid/grid-source.ts +9 -31
- package/src/grid/grid-view.ts +45 -23
- 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 +100 -31
- package/src/grid/sources/csv-file-source.ts +2 -2
- package/src/grid/tabulator-tables.d.ts +61 -34
- package/src/hosting/document.ts +2 -2
- package/src/hosting/stage.ts +7 -7
- package/src/i18n/i18n-commands.ts +3 -3
- package/src/media/media-commands.ts +181 -0
- package/src/media/media-library-model.ts +232 -0
- package/src/media/media-library.ts +1283 -0
- package/src/media/media-pane.ts +51 -20
- 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 +38 -14
- package/src/panels/ai-chat/attached-context.ts +13 -7
- package/src/panels/ai-chat/chat-markdown.ts +8 -8
- 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 +57 -46
- package/src/panels/bottom-dock.ts +5 -3
- package/src/panels/canvas-dnd-bridge.ts +36 -26
- package/src/panels/chat-panel.ts +6 -6
- package/src/panels/collections-panel.ts +306 -0
- package/src/panels/component-preview.ts +35 -13
- package/src/panels/data-explorer.ts +63 -26
- package/src/panels/data-grid.ts +18 -11
- package/src/panels/dnd.ts +115 -138
- package/src/panels/editors.ts +52 -21
- package/src/panels/elements-panel.ts +19 -5
- package/src/panels/empty-state.ts +2 -2
- package/src/panels/events-panel.ts +84 -69
- package/src/panels/formula-workspace.ts +78 -54
- package/src/panels/frontmatter-fields.ts +33 -28
- package/src/panels/git-diff-open.ts +10 -6
- package/src/panels/head-panel.ts +488 -202
- package/src/panels/i18n-panel.ts +20 -12
- package/src/panels/imports-panel.ts +25 -47
- package/src/panels/jump-bar.ts +75 -31
- package/src/panels/layers-panel.ts +130 -101
- package/src/panels/left-panel.ts +25 -11
- package/src/panels/navigator-panels.ts +23 -11
- package/src/panels/pane-context.ts +140 -49
- package/src/panels/pane-grid.ts +55 -26
- package/src/panels/panel-registry.ts +36 -46
- package/src/panels/properties-panel.ts +182 -124
- package/src/panels/quick-search.ts +53 -31
- package/src/panels/right-panel.ts +201 -45
- package/src/panels/seo-modal.ts +54 -125
- package/src/panels/settings-menu.ts +63 -61
- package/src/panels/settings-pane.ts +268 -162
- package/src/panels/signals-panel.ts +156 -135
- package/src/panels/site-model.ts +367 -0
- package/src/panels/site-panel.ts +638 -0
- package/src/panels/statement-editor.ts +230 -140
- package/src/panels/style-panel.ts +253 -206
- package/src/panels/style-utils.ts +114 -51
- package/src/panels/stylebook-doc.ts +195 -60
- package/src/panels/stylebook-layers-panel.ts +48 -89
- package/src/panels/stylebook-panel.ts +60 -27
- package/src/panels/styles-panel.ts +327 -0
- package/src/panels/tab-drop.ts +27 -11
- package/src/panels/tab-strip.ts +143 -49
- package/src/platform-errors.ts +57 -43
- package/src/platform.ts +59 -31
- package/src/platforms/cloud.ts +373 -176
- package/src/platforms/default-platform.ts +14 -8
- package/src/platforms/devserver.ts +180 -142
- package/src/platforms/read-batcher.ts +16 -8
- package/src/project-list.ts +2 -1
- package/src/publish/deploy-checklist.ts +20 -9
- package/src/publish/pages-service.ts +66 -27
- package/src/publish/publish-changes.ts +491 -0
- package/src/publish/publish-commands.ts +88 -22
- package/src/publish/publish-ids.ts +49 -0
- package/src/publish/publish-panel.ts +10 -6
- package/src/publish/publish-quick.ts +148 -0
- package/src/publish/publish-workspace.ts +926 -0
- package/src/publish/source-control.ts +907 -0
- 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 +74 -51
- package/src/services/cem-export.ts +149 -58
- package/src/services/cf-settings.ts +4 -4
- package/src/services/clock.ts +6 -1
- package/src/services/code-services.ts +37 -31
- package/src/services/connection.ts +2 -2
- 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 +20 -14
- 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 +29 -9
- package/src/services/settings/definitions.ts +25 -14
- 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 +128 -70
- package/src/settings/css-vars-editor.ts +119 -32
- package/src/settings/defs-editor.ts +38 -35
- package/src/settings/developer-panels.ts +43 -0
- package/src/settings/extension-rows.ts +16 -8
- package/src/settings/extension-sections.ts +42 -14
- package/src/settings/extensions-section.ts +4 -1
- package/src/settings/general-settings.ts +101 -28
- package/src/settings/locales-section.ts +20 -12
- package/src/settings/preferences-dialog.ts +17 -7
- package/src/settings/preferences-keymap.ts +7 -5
- package/src/settings/preferences-sections.ts +11 -5
- package/src/settings/project-sections.ts +28 -11
- package/src/settings/schema-field-ui.ts +12 -1
- package/src/settings/section-registry.ts +116 -11
- package/src/settings/settings-dialog.ts +192 -0
- package/src/settings/settings-document.ts +186 -166
- package/src/shell/tree.ts +6 -5
- package/src/shell.ts +536 -477
- package/src/site-context.ts +101 -32
- package/src/state.ts +68 -57
- package/src/store.ts +54 -34
- package/src/studio.ts +219 -116
- package/src/style/live-preview.ts +1 -1
- package/src/style/project-styles.ts +40 -7
- package/src/style/stylebook-specimens.ts +89 -0
- package/src/style/stylebook-target.ts +26 -0
- package/src/style/tag-inheritance.ts +105 -0
- package/src/style/token-ref.ts +5 -4
- package/src/style/variables-focus.ts +61 -0
- package/src/style/variables-view.ts +235 -0
- package/src/surfaces/about.ts +18 -19
- package/src/surfaces/add-new.json +1482 -0
- package/src/surfaces/add-new.ts +325 -0
- package/src/surfaces/add-repo.ts +17 -19
- package/src/surfaces/ai-chat.ts +33 -38
- 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.json +4 -3
- package/src/surfaces/boot-failure.ts +4 -5
- package/src/surfaces/bottom-dock.json +1 -1
- package/src/surfaces/bottom-dock.ts +9 -18
- package/src/surfaces/canvas-stage.json +30 -19
- package/src/surfaces/canvas-stage.ts +17 -16
- package/src/surfaces/cf-account-picker.ts +17 -18
- package/src/surfaces/collections-panel.json +615 -0
- package/src/surfaces/collections-panel.ts +168 -0
- package/src/surfaces/commandbar.json +241 -96
- package/src/surfaces/commandbar.ts +145 -105
- 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/empty-state.json +1 -1
- package/src/surfaces/empty-state.ts +7 -10
- package/src/surfaces/entry-editor.json +136 -0
- package/src/surfaces/entry-editor.ts +35 -11
- package/src/surfaces/entry-inspector.json +371 -0
- package/src/surfaces/entry-inspector.ts +143 -0
- 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/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.json +162 -14
- package/src/surfaces/inspector-dock.ts +59 -31
- package/src/surfaces/jump-bar.ts +5 -6
- package/src/surfaces/jxsuite-update.ts +16 -22
- package/src/surfaces/library-pane.json +670 -437
- package/src/surfaces/library-pane.ts +111 -77
- package/src/surfaces/logic-panel.ts +17 -30
- package/src/surfaces/logic-workspace.ts +13 -15
- package/src/surfaces/media-browser.json +62 -6
- package/src/surfaces/media-browser.ts +26 -11
- package/src/surfaces/media-field.json +1 -1
- package/src/surfaces/media-field.ts +4 -5
- package/src/surfaces/media-library.json +1586 -0
- package/src/surfaces/media-library.ts +282 -0
- package/src/surfaces/media-pane.ts +8 -7
- package/src/surfaces/media-pick-dialog.json +71 -0
- package/src/surfaces/media-pick-dialog.ts +132 -0
- package/src/surfaces/menu.ts +47 -23
- package/src/surfaces/navigator-dock.ts +11 -12
- package/src/surfaces/new-project.ts +27 -26
- package/src/surfaces/pane-context.json +144 -77
- package/src/surfaces/pane-context.ts +44 -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.json +12 -6
- package/src/surfaces/panel-deploy-checklist.ts +8 -7
- 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.json +72 -2
- package/src/surfaces/panel-page.ts +49 -25
- package/src/surfaces/panel-problems.ts +5 -7
- package/src/surfaces/panel-signals.json +1 -1
- package/src/surfaces/panel-signals.ts +25 -39
- package/src/surfaces/panel-stylebook-layers.json +71 -204
- package/src/surfaces/panel-stylebook-layers.ts +5 -29
- package/src/surfaces/preferences.json +120 -48
- package/src/surfaces/preferences.ts +29 -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-quick.json +428 -0
- package/src/surfaces/publish-quick.ts +165 -0
- package/src/surfaces/publish-workspace.json +2892 -0
- package/src/surfaces/publish-workspace.ts +391 -0
- package/src/surfaces/publish.ts +18 -18
- package/src/surfaces/push-plan.ts +7 -8
- package/src/surfaces/rail.json +1 -159
- package/src/surfaces/rail.ts +22 -79
- package/src/surfaces/reference-field.ts +11 -15
- package/src/surfaces/schema-builder.ts +16 -22
- package/src/surfaces/schema-form.json +10 -2
- package/src/surfaces/schema-form.ts +17 -25
- package/src/surfaces/secret-field.ts +9 -6
- package/src/surfaces/seo.json +1 -1
- package/src/surfaces/seo.ts +21 -15
- package/src/surfaces/settings-contexts.ts +9 -7
- package/src/surfaces/settings-contributed.json +5 -5
- package/src/surfaces/settings-contributed.ts +32 -12
- package/src/surfaces/settings-css-vars.json +44 -36
- package/src/surfaces/settings-css-vars.ts +82 -16
- package/src/surfaces/settings-defs.json +2 -2
- package/src/surfaces/settings-defs.ts +17 -21
- package/src/surfaces/settings-deploy.json +2 -15
- package/src/surfaces/settings-deploy.ts +9 -16
- package/src/surfaces/settings-dialog.json +51 -0
- package/src/surfaces/settings-dialog.ts +169 -0
- 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.json +3 -3
- package/src/surfaces/settings-overview.ts +14 -8
- package/src/surfaces/settings-packages.ts +8 -7
- package/src/surfaces/settings-pane.json +269 -46
- package/src/surfaces/settings-pane.ts +88 -36
- package/src/surfaces/settings-rawjson.ts +5 -6
- package/src/surfaces/shell.json +2 -1
- package/src/surfaces/shell.ts +1 -2
- package/src/surfaces/site-panel.json +1029 -0
- package/src/surfaces/site-panel.ts +233 -0
- package/src/surfaces/slash-menu.json +63 -21
- package/src/surfaces/slash-menu.ts +42 -9
- package/src/surfaces/statements.ts +13 -18
- package/src/surfaces/statusbar.ts +56 -29
- package/src/surfaces/style-panel.ts +18 -31
- package/src/surfaces/stylebook-chrome.ts +3 -5
- package/src/surfaces/styles-panel.json +735 -0
- package/src/surfaces/styles-panel.ts +195 -0
- package/src/surfaces/styles-variables.json +149 -0
- package/src/surfaces/styles-variables.ts +145 -0
- package/src/surfaces/tab-strip.json +4 -4
- package/src/surfaces/tab-strip.ts +14 -13
- package/src/surfaces/target-line.ts +6 -7
- package/src/surfaces/welcome.ts +6 -8
- package/src/surfaces/writing-banner.json +94 -0
- package/src/surfaces/writing-banner.ts +80 -0
- package/src/tabs/bare-repeaters.ts +101 -0
- 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 +99 -48
- package/src/tabs/transact.ts +98 -53
- package/src/types.ts +53 -43
- 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 +104 -56
- package/src/ui/formula-catalog.ts +239 -230
- package/src/ui/formula-chips.ts +33 -18
- package/src/ui/layers.ts +57 -31
- package/src/ui/media-picker.ts +300 -47
- package/src/ui/popover-surface.ts +20 -12
- package/src/ui/progress-modal.ts +13 -8
- package/src/ui/regions.ts +14 -12
- package/src/ui/schema-form.ts +372 -97
- 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 +29 -3
- package/src/utils/base64.ts +6 -4
- package/src/utils/edit-display.ts +366 -111
- 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/local-day.ts +18 -0
- 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 +14 -16
- package/src/workspace/session.ts +81 -50
- package/src/workspace/tab-workspace.ts +137 -0
- package/src/workspace/workspace-back.ts +189 -0
- package/src/workspace/workspace-home.ts +133 -0
- package/src/workspace/workspace-ids.ts +129 -0
- package/src/workspace/workspace-switch.ts +372 -0
- package/src/workspace/workspace.ts +165 -47
- package/styles/shell-frame.css +30 -7
- package/styles/shell-frame.json +15 -3
- package/dist/chunks/2020-va2wwra4.js +0 -4
- 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/jsonMode-s8kt9dsj.js +0 -13
- 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-tdcprbqb.js +0 -5
- package/dist/chunks/studio-vrmcjf9g.js +0 -7
- 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-zey7zsdw.js +0 -12
- 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/tsMode-2frah6h1.js +0 -14
- package/dist/chunks/workspace-zt81g1ms.js +0 -4
- package/dist/chunks/ws-client-n2bh4hkf.js +0 -4
- package/src/panels/frontmatter-panel.ts +0 -701
- package/src/panels/git-panel.ts +0 -1120
- package/src/surfaces/doc-header.json +0 -776
- package/src/surfaces/doc-header.ts +0 -231
- package/src/surfaces/git-panel.json +0 -1880
- package/src/surfaces/git-panel.ts +0 -272
|
@@ -3,13 +3,25 @@
|
|
|
3
3
|
* Edit-mode display transforms — extracted from studio.js (Phase 4i). Pure stateless functions that
|
|
4
4
|
* convert document trees for visual editing (template expressions, $map, $switch, empty
|
|
5
5
|
* placeholders).
|
|
6
|
+
*
|
|
7
|
+
* @docs studio/interface/modes
|
|
6
8
|
*/
|
|
7
9
|
|
|
8
|
-
import type { JxMutableNode } from "@jxsuite/schema/types";
|
|
9
|
-
import {
|
|
10
|
+
import type { JxDocumentValue, JxMutableNode } from "@jxsuite/schema/types";
|
|
11
|
+
import {
|
|
12
|
+
displayTagName,
|
|
13
|
+
isNodeObject,
|
|
14
|
+
isNonNullObject,
|
|
15
|
+
isNumber,
|
|
16
|
+
isRef,
|
|
17
|
+
isString,
|
|
18
|
+
} from "@jxsuite/schema/guards";
|
|
19
|
+
import { isDocumentContainer } from "./strip-events";
|
|
20
|
+
import type { RebuiltNode } from "./strip-events";
|
|
10
21
|
|
|
11
22
|
const mediaTags = new Set(["img", "video", "source", "iframe", "audio"]);
|
|
12
|
-
|
|
23
|
+
/** A 1×1 transparent GIF: what an unresolvable `src` binding shows in edit mode. */
|
|
24
|
+
export const TRANSPARENT_PX =
|
|
13
25
|
"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
14
26
|
// A neutral, visible gray placeholder for image-like bindings in edit mode (e.g. a component `image`
|
|
15
27
|
// Prop bound to ${...}). The component renders <img src={prop}> internally, so a transparent pixel
|
|
@@ -54,6 +66,37 @@ function isImageUrlKey(key: string): boolean {
|
|
|
54
66
|
return IMAGE_KEY_RE.test(key);
|
|
55
67
|
}
|
|
56
68
|
|
|
69
|
+
/** A template that reads the repeater row (`item`, `index`, `$map`), which edit mode cannot supply. */
|
|
70
|
+
const ROW_BINDING_RE = /(?<![\w$.])(?:item|index|\$map)\b/u;
|
|
71
|
+
|
|
72
|
+
/** Whether a value is a template or `$ref` that reads the repeater row. */
|
|
73
|
+
export function isRowBound(value: JxDocumentValue | undefined): boolean {
|
|
74
|
+
if (isString(value)) {
|
|
75
|
+
return value.includes("${") && ROW_BINDING_RE.test(value);
|
|
76
|
+
}
|
|
77
|
+
return isNodeObject(value) && isString(value.$ref) && /^(?:#\/)?\$map\//u.test(value.$ref);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* What a row-bound value shows in the perimeter: link targets are inert, image-like keys the
|
|
82
|
+
* placeholder image, anything else its readable binding text.
|
|
83
|
+
*
|
|
84
|
+
* @param {string} key
|
|
85
|
+
* @param {JxDocumentValue | undefined} value
|
|
86
|
+
*/
|
|
87
|
+
function rowBoundDisplay(key: string, value: JxDocumentValue | undefined): string {
|
|
88
|
+
if (key === "href" || key === "action") {
|
|
89
|
+
return "";
|
|
90
|
+
}
|
|
91
|
+
if (isImageUrlKey(key)) {
|
|
92
|
+
return PLACEHOLDER_IMG;
|
|
93
|
+
}
|
|
94
|
+
if (isString(value)) {
|
|
95
|
+
return templateToEditDisplay(value);
|
|
96
|
+
}
|
|
97
|
+
return isNodeObject(value) && isString(value.$ref) ? refDisplayLabel(value.$ref) : "";
|
|
98
|
+
}
|
|
99
|
+
|
|
57
100
|
const textTags = new Set([
|
|
58
101
|
"p",
|
|
59
102
|
"h1",
|
|
@@ -115,6 +158,31 @@ export const EMPTY_PLACEHOLDER_CLASSES = [
|
|
|
115
158
|
"empty-container-placeholder",
|
|
116
159
|
] as const;
|
|
117
160
|
|
|
161
|
+
/** The style keys that give an element a size of its own: its box, not its content, sets it. */
|
|
162
|
+
const SIZING_KEYS = ["width", "height", "inlineSize", "blockSize"] as const;
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Whether the node's own style fixes its width or height — a dot, a bar, a spacer.
|
|
166
|
+
*
|
|
167
|
+
* Such an element is drawn as a SHAPE, and an empty one is not missing anything: the jxsuite.com
|
|
168
|
+
* home's 6px status dot is an empty `<span>` sized in its style, and the text placeholder turned it
|
|
169
|
+
* into a column of letters one glyph wide over the hero. A placeholder that changes the box the
|
|
170
|
+
* author sized (the container one sets a `min-height` and a border) misdraws the page it is meant
|
|
171
|
+
* to explain, so a sized element gets none. Only the top-level declaration counts: a size set under
|
|
172
|
+
* a media query or a state is a variant of a box whose base the content still sizes.
|
|
173
|
+
*/
|
|
174
|
+
function fixesItsOwnSize(node: JxMutableNode): boolean {
|
|
175
|
+
const { style } = node;
|
|
176
|
+
if (!isNonNullObject(style)) {
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
return SIZING_KEYS.some((key) => {
|
|
180
|
+
const value = style[key];
|
|
181
|
+
const text = isNumber(value) ? String(value) : isString(value) ? value.trim() : "";
|
|
182
|
+
return text !== "" && text !== "auto";
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
118
186
|
/**
|
|
119
187
|
* The empty-placeholder class prepareForEditMode would add for this node, or null. Used by the
|
|
120
188
|
* canvas patcher to keep placeholder classes in sync when patching text without a full render.
|
|
@@ -133,6 +201,9 @@ export function computeEmptyPlaceholderClass(node: JxMutableNode): string | null
|
|
|
133
201
|
if (Array.isArray(node.children) && node.children.length > 0) {
|
|
134
202
|
return null;
|
|
135
203
|
}
|
|
204
|
+
if (fixesItsOwnSize(node)) {
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
136
207
|
if (textTags.has(displayTagName(node.tagName))) {
|
|
137
208
|
return "empty-text-placeholder";
|
|
138
209
|
}
|
|
@@ -161,6 +232,7 @@ export function templateToEditDisplay(str: string) {
|
|
|
161
232
|
export function restoreTemplateExpressions(el: HTMLElement) {
|
|
162
233
|
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
|
|
163
234
|
while (walker.nextNode()) {
|
|
235
|
+
// SAFETY: the walker was created with NodeFilter.SHOW_TEXT, so every node it stops on is Text.
|
|
164
236
|
const node = walker.currentNode as Text;
|
|
165
237
|
if (node.data.includes("\u276A")) {
|
|
166
238
|
node.data = node.data.replaceAll(/\u276A\s*(.*?)\s*\u276B/g, "${$1}");
|
|
@@ -175,52 +247,253 @@ export function restoreTemplateExpressions(el: HTMLElement) {
|
|
|
175
247
|
* edit-only device — it is never compiled or rendered in preview.
|
|
176
248
|
*
|
|
177
249
|
* @param {JxMutableNode} arrayObj
|
|
178
|
-
* @returns {
|
|
250
|
+
* @returns {JxMutableNode}
|
|
179
251
|
*/
|
|
180
|
-
function arrayToPerimeter(arrayObj: JxMutableNode):
|
|
252
|
+
function arrayToPerimeter(arrayObj: JxMutableNode, row: SampleRow): JxMutableNode {
|
|
181
253
|
const template = arrayObj.map;
|
|
182
254
|
return {
|
|
183
|
-
children:
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
: [],
|
|
255
|
+
children: isNonNullObject(template)
|
|
256
|
+
? [prepareNode(template, sampleRowOf(arrayObj.items, row))]
|
|
257
|
+
: [],
|
|
187
258
|
className: "repeater-perimeter",
|
|
188
259
|
tagName: "div",
|
|
189
260
|
};
|
|
190
261
|
}
|
|
191
262
|
|
|
263
|
+
// ─── Live component props ────────────────────────────────────────────────────
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* The row a repeater's template is drawn with in edit mode, as a JavaScript expression the runtime
|
|
267
|
+
* evaluates in the template's own scope, or null outside a repeater or where the repeater's items
|
|
268
|
+
* cannot be read.
|
|
269
|
+
*
|
|
270
|
+
* It is the repeater's FIRST item. A perimeter draws one instance of the template, and a component
|
|
271
|
+
* inside it used to be handed each bound prop's display text (`❪ item.data.date ❫`) as its value.
|
|
272
|
+
* Text survives that; a component that formats the prop does not: `Intl/formatDate` and a locale
|
|
273
|
+
* tag reject it with a `RangeError` (spec.md §16.4), and the instance was not rendered at all. The
|
|
274
|
+
* first item is real data of exactly the shape the template was written for, and it is the row
|
|
275
|
+
* Preview draws first.
|
|
276
|
+
*/
|
|
277
|
+
export type SampleRow = string | null;
|
|
278
|
+
|
|
279
|
+
/** A JSON value as a JavaScript literal: JSON is a subset of ECMAScript since ES2019. */
|
|
280
|
+
function jsLiteral(value: JxDocumentValue): string {
|
|
281
|
+
return JSON.stringify(value);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* A pointer the runtime resolves, as a JavaScript accessor over the template parameters, or null
|
|
286
|
+
* for a scheme a template cannot reach (`window#/`, `$defs`, an external file).
|
|
287
|
+
*/
|
|
288
|
+
function refAccessor(ref: string): string | null {
|
|
289
|
+
const pointer = ref.startsWith("#/") ? ref.slice(2) : ref;
|
|
290
|
+
const [head, ...rest] = pointer.split("/");
|
|
291
|
+
const base = head === "state" || head === "$map" ? head : null;
|
|
292
|
+
if (base === null) {
|
|
293
|
+
return null;
|
|
294
|
+
}
|
|
295
|
+
// JSON Pointer unescaping (RFC 6901): `~1` is `/`, `~0` is `~`, in that order.
|
|
296
|
+
const keys = rest.map((seg) => seg.replaceAll("~1", "/").replaceAll("~0", "~"));
|
|
297
|
+
return base + keys.map((key) => `?.[${jsLiteral(key)}]`).join("");
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/** Evaluate `expr` where `item`, `index` and `$map` are the sample `row`, or as-is with no row. */
|
|
301
|
+
function inRow(expr: string, row: SampleRow): string {
|
|
302
|
+
if (row === null) {
|
|
303
|
+
return `(${expr})`;
|
|
304
|
+
}
|
|
305
|
+
return `((r) => ((item, index, $map) => (${expr}))(r, 0, { index: 0, item: r }))(${row})`;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/** The first item of a repeater's `items`, read inside the enclosing sample `row` (if any). */
|
|
309
|
+
function sampleRowOf(items: JxDocumentValue | undefined, row: SampleRow): SampleRow {
|
|
310
|
+
if (Array.isArray(items)) {
|
|
311
|
+
return `${jsLiteral(items)}[0]`;
|
|
312
|
+
}
|
|
313
|
+
if (isRef(items)) {
|
|
314
|
+
const accessor = refAccessor(items.$ref);
|
|
315
|
+
return accessor === null ? null : `${inRow(accessor, row)}?.[0]`;
|
|
316
|
+
}
|
|
317
|
+
const parts = isString(items) ? templateExpressions(items) : [];
|
|
318
|
+
if (isString(items) && parts.length === 1 && isWholeTemplate(items, parts[0]!)) {
|
|
319
|
+
return `${inRow(parts[0]!.expr, row)}?.[0]`;
|
|
320
|
+
}
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/** One `${…}` of a template: where it starts and ends in the string, and its expression. */
|
|
325
|
+
interface TemplatePart {
|
|
326
|
+
start: number;
|
|
327
|
+
end: number;
|
|
328
|
+
expr: string;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/** Whether `part` is the whole of `template`: one expression end to end, so it keeps its type. */
|
|
332
|
+
function isWholeTemplate(template: string, part: TemplatePart): boolean {
|
|
333
|
+
return part.start === 0 && part.end === template.length - 1;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Each `${…}` of a template, located by brace depth rather than by pattern: an expression may hold
|
|
338
|
+
* an object literal or a nested template, which a `[^}]+` pattern cuts short.
|
|
339
|
+
*/
|
|
340
|
+
function templateExpressions(str: string): TemplatePart[] {
|
|
341
|
+
const found: TemplatePart[] = [];
|
|
342
|
+
let at = str.indexOf("${");
|
|
343
|
+
while (at !== -1) {
|
|
344
|
+
let depth = 0;
|
|
345
|
+
let end = -1;
|
|
346
|
+
for (let i = at + 1; i < str.length; i += 1) {
|
|
347
|
+
if (str[i] === "{") {
|
|
348
|
+
depth += 1;
|
|
349
|
+
} else if (str[i] === "}") {
|
|
350
|
+
depth -= 1;
|
|
351
|
+
if (depth === 0) {
|
|
352
|
+
end = i;
|
|
353
|
+
break;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
if (end === -1) {
|
|
358
|
+
break;
|
|
359
|
+
}
|
|
360
|
+
found.push({ end, expr: str.slice(at + 2, end), start: at });
|
|
361
|
+
at = str.indexOf("${", end + 1);
|
|
362
|
+
}
|
|
363
|
+
return found;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* A bound component prop as edit mode passes it: the binding itself, evaluated LIVE by the runtime
|
|
368
|
+
* (against the page's own state and `$page`, and inside a repeater against its sample row) and
|
|
369
|
+
* guarded, so a binding with nothing to read yet (a collection still loading, an empty one) reads
|
|
370
|
+
* as the empty string, a component prop's usual default, rather than throwing out of the binding's
|
|
371
|
+
* effect.
|
|
372
|
+
*
|
|
373
|
+
* Display text is what edit mode shows for a binding the PAGE draws, because the author edits that
|
|
374
|
+
* text in place. A component's prop is not drawn by the page: the component decides what it means,
|
|
375
|
+
* and a date, a locale, a count or a colour cannot be a label.
|
|
376
|
+
*/
|
|
377
|
+
export function liveEditProp(template: string, row: SampleRow = null): string {
|
|
378
|
+
const parts = templateExpressions(template);
|
|
379
|
+
if (parts.length === 0) {
|
|
380
|
+
return template;
|
|
381
|
+
}
|
|
382
|
+
let out = "";
|
|
383
|
+
let last = 0;
|
|
384
|
+
for (const { start, end, expr } of parts) {
|
|
385
|
+
out += template.slice(last, start);
|
|
386
|
+
out += `\${(() => { try { return ${inRow(expr, row)}; } catch { return ""; } })()}`;
|
|
387
|
+
last = end + 1;
|
|
388
|
+
}
|
|
389
|
+
return out + template.slice(last);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* A `$ref`-bound component prop in edit mode: a scope pointer resolves live as it is, and a row
|
|
394
|
+
* pointer (`$map/item/…`) is read from the sample row, or dropped where there is none so the
|
|
395
|
+
* component keeps its own default.
|
|
396
|
+
*/
|
|
397
|
+
function liveEditRefProp(ref: string, row: SampleRow): JxDocumentValue | undefined {
|
|
398
|
+
const pointer = ref.startsWith("#/") ? ref.slice(2) : ref;
|
|
399
|
+
if (pointer !== "$map" && !pointer.startsWith("$map/")) {
|
|
400
|
+
return { $ref: ref };
|
|
401
|
+
}
|
|
402
|
+
const accessor = refAccessor(ref);
|
|
403
|
+
return row === null || accessor === null ? undefined : liveEditProp(`\${${accessor}}`, row);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* The sample row of the repeater template at `path` in `doc` (what {@link prepareForEditMode} draws
|
|
408
|
+
* a perimeter's instance with), so a subtree re-rendered on its own (`iframe-subtree.ts`) is
|
|
409
|
+
* prepared exactly as the full render prepared it.
|
|
410
|
+
*/
|
|
411
|
+
export function sampleRowAt(doc: JxDocumentValue, path: readonly (string | number)[]): SampleRow {
|
|
412
|
+
let node: JxDocumentValue | undefined = doc;
|
|
413
|
+
let row: SampleRow = null;
|
|
414
|
+
for (const seg of path) {
|
|
415
|
+
if (Array.isArray(node)) {
|
|
416
|
+
node = isNumber(seg) ? node[seg] : undefined;
|
|
417
|
+
continue;
|
|
418
|
+
}
|
|
419
|
+
if (!isNodeObject(node)) {
|
|
420
|
+
return row;
|
|
421
|
+
}
|
|
422
|
+
if (seg === "map" && node.$prototype === "Array") {
|
|
423
|
+
row = sampleRowOf(node.items, row);
|
|
424
|
+
}
|
|
425
|
+
node = isString(seg) ? node[seg] : undefined;
|
|
426
|
+
}
|
|
427
|
+
return row;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* The text a `$ref` binding shows in edit mode: its pointer, with the `#/state/` prefix dropped.
|
|
432
|
+
*
|
|
433
|
+
* @param {string} ref
|
|
434
|
+
*/
|
|
435
|
+
function refDisplayLabel(ref: string): string {
|
|
436
|
+
const label = ref.startsWith("#/state/") ? ref.slice(8) : ref;
|
|
437
|
+
return `{${label}}`;
|
|
438
|
+
}
|
|
439
|
+
|
|
192
440
|
/**
|
|
193
441
|
* Prepare a document for edit-mode rendering. Replaces template strings with readable literal text,
|
|
194
442
|
* $prototype:Array with placeholders, and $ref bindings with display labels. Preserves state so the
|
|
195
|
-
* runtime can still initialise scope.
|
|
443
|
+
* runtime can still initialise scope. Arrays are prepared member by member, and primitives and a
|
|
444
|
+
* cleared (`undefined`) key return unchanged, so the walker can recurse through any document
|
|
445
|
+
* value.
|
|
196
446
|
*
|
|
197
447
|
* @param {JxMutableNode} node
|
|
198
448
|
* @returns {JxMutableNode}
|
|
199
449
|
*/
|
|
200
|
-
export function prepareForEditMode(node: JxMutableNode): JxMutableNode
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
450
|
+
export function prepareForEditMode(node: JxMutableNode, row?: SampleRow): JxMutableNode;
|
|
451
|
+
export function prepareForEditMode(node: JxDocumentValue, row?: SampleRow): JxDocumentValue;
|
|
452
|
+
export function prepareForEditMode(
|
|
453
|
+
node: JxDocumentValue | undefined,
|
|
454
|
+
row?: SampleRow,
|
|
455
|
+
): JxDocumentValue | undefined;
|
|
456
|
+
export function prepareForEditMode(
|
|
457
|
+
node: JxDocumentValue | undefined,
|
|
458
|
+
row: SampleRow = null,
|
|
459
|
+
): JxDocumentValue | undefined {
|
|
460
|
+
return prepareNode(node, row);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/** {@link prepareForEditMode} for one value, inside the sample `row` of its enclosing repeater. */
|
|
464
|
+
function prepareNode(node: JxMutableNode, row: SampleRow): JxMutableNode;
|
|
465
|
+
function prepareNode(node: JxDocumentValue, row: SampleRow): JxDocumentValue;
|
|
466
|
+
function prepareNode(
|
|
467
|
+
node: JxDocumentValue | undefined,
|
|
468
|
+
row: SampleRow,
|
|
469
|
+
): JxDocumentValue | undefined;
|
|
470
|
+
function prepareNode(
|
|
471
|
+
node: JxDocumentValue | undefined,
|
|
472
|
+
row: SampleRow,
|
|
473
|
+
): JxDocumentValue | undefined {
|
|
204
474
|
if (Array.isArray(node)) {
|
|
205
475
|
// Arrays of nodes round-trip element-wise; the array itself is not a node.
|
|
206
|
-
return
|
|
476
|
+
return node.map((n) => prepareNode(n, row));
|
|
477
|
+
}
|
|
478
|
+
if (!isNodeObject(node)) {
|
|
479
|
+
return node;
|
|
207
480
|
}
|
|
208
481
|
|
|
209
482
|
// A mapped-array node itself → its edit-mode perimeter (e.g. when the patcher re-renders an
|
|
210
483
|
// Array node directly). Members inside a children array funnel here via the children branch.
|
|
211
|
-
if (
|
|
212
|
-
return arrayToPerimeter(node)
|
|
484
|
+
if (node.$prototype === "Array") {
|
|
485
|
+
return arrayToPerimeter(node, row);
|
|
213
486
|
}
|
|
214
487
|
|
|
215
|
-
const
|
|
488
|
+
const obj = node;
|
|
216
489
|
|
|
217
|
-
const out:
|
|
490
|
+
const out: RebuiltNode = {};
|
|
218
491
|
let needsMediaPlaceholder = false;
|
|
219
|
-
const isMediaElement = mediaTags.has(
|
|
492
|
+
const isMediaElement = isString(obj.tagName) && mediaTags.has(obj.tagName);
|
|
220
493
|
|
|
221
494
|
// Check if this media element lacks a resolvable src (top-level or in attributes)
|
|
222
495
|
if (isMediaElement) {
|
|
223
|
-
const attrs = obj.attributes
|
|
496
|
+
const attrs = obj.attributes;
|
|
224
497
|
const topSrc = obj.src;
|
|
225
498
|
const attrSrc = attrs?.src;
|
|
226
499
|
const topPoster = obj.poster;
|
|
@@ -235,24 +508,28 @@ export function prepareForEditMode(node: JxMutableNode): JxMutableNode {
|
|
|
235
508
|
for (const [k, v] of Object.entries(obj)) {
|
|
236
509
|
if (k === "state" || k === "$media" || k === "$elements") {
|
|
237
510
|
out[k] = v; // Preserve as-is for runtime resolution
|
|
238
|
-
} else if (k === "$props" && v
|
|
239
|
-
|
|
240
|
-
|
|
511
|
+
} else if (k === "$props" && isDocumentContainer(v)) {
|
|
512
|
+
/* A component's inputs render LIVE. They are its configuration, not text the author edits in
|
|
513
|
+
place (a template-valued prop is refused by inline prop editing), and showing their binding
|
|
514
|
+
text instead fed it to the component as a value: a header's `variant` became the literal
|
|
515
|
+
`❪ state.headerVariant ❫` and matched none of its styles. A prop that reads the repeater
|
|
516
|
+
row is drawn with the repeater's sample row (see liveEditProp), guarded, so a date or a
|
|
517
|
+
locale the component formats is real data rather than a label; a row-bound link target is
|
|
518
|
+
inert and a row-bound image-like key the placeholder image. */
|
|
519
|
+
const propsOut: RebuiltNode = {};
|
|
241
520
|
for (const [pk, pv] of Object.entries(v)) {
|
|
242
|
-
if (
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
521
|
+
if (!isRowBound(pv)) {
|
|
522
|
+
propsOut[pk] = pv;
|
|
523
|
+
} else if (isString(pv)) {
|
|
524
|
+
propsOut[pk] =
|
|
525
|
+
isImageUrlKey(pk) || pk === "href" || pk === "action"
|
|
526
|
+
? rowBoundDisplay(pk, pv)
|
|
527
|
+
: liveEditProp(pv, row);
|
|
528
|
+
} else if (isRef(pv)) {
|
|
529
|
+
const live = liveEditRefProp(pv.$ref, row);
|
|
530
|
+
if (live !== undefined) {
|
|
531
|
+
propsOut[pk] = live;
|
|
251
532
|
}
|
|
252
|
-
} else if (pv && typeof pv === "object" && (pv as Record<string, unknown>).$ref) {
|
|
253
|
-
const ref = (pv as Record<string, unknown>).$ref as string;
|
|
254
|
-
const label = ref.startsWith("#/state/") ? ref.slice(8) : ref;
|
|
255
|
-
propsOut[pk] = `{${label}}`;
|
|
256
533
|
} else {
|
|
257
534
|
propsOut[pk] = pv;
|
|
258
535
|
}
|
|
@@ -262,25 +539,21 @@ export function prepareForEditMode(node: JxMutableNode): JxMutableNode {
|
|
|
262
539
|
if (Array.isArray(v)) {
|
|
263
540
|
// Each member recurses; array pseudo-elements become a single repeater-perimeter element
|
|
264
541
|
// (via the top-level array case) so they stay a 1:1 DOM node among their siblings.
|
|
265
|
-
out.children = v.map((c) =>
|
|
266
|
-
} else if (
|
|
267
|
-
v &&
|
|
268
|
-
typeof v === "object" &&
|
|
269
|
-
(v as Record<string, unknown>).$prototype === "Array"
|
|
270
|
-
) {
|
|
542
|
+
out.children = v.map((c) => prepareNode(c, row));
|
|
543
|
+
} else if (isNodeObject(v) && v.$prototype === "Array") {
|
|
271
544
|
// Legacy whole-children repeater → a single perimeter as the sole child.
|
|
272
|
-
out.children = [
|
|
545
|
+
out.children = [prepareNode(v, row)];
|
|
273
546
|
} else {
|
|
274
|
-
out.children =
|
|
547
|
+
out.children = prepareNode(v, row);
|
|
275
548
|
}
|
|
276
|
-
} else if (k === "cases" && obj.$switch && v
|
|
549
|
+
} else if (k === "cases" && obj.$switch && isDocumentContainer(v)) {
|
|
277
550
|
// Replace $switch cases with a placeholder showing the first case or a label
|
|
278
|
-
const
|
|
279
|
-
if (
|
|
280
|
-
const firstCase =
|
|
551
|
+
const [firstEntry] = Object.entries(v);
|
|
552
|
+
if (firstEntry) {
|
|
553
|
+
const [, firstCase] = firstEntry;
|
|
281
554
|
out.children =
|
|
282
|
-
firstCase &&
|
|
283
|
-
? [
|
|
555
|
+
isDocumentContainer(firstCase) && !(isNodeObject(firstCase) && firstCase.$ref)
|
|
556
|
+
? [prepareNode(firstCase, row)]
|
|
284
557
|
: [
|
|
285
558
|
{
|
|
286
559
|
style: {
|
|
@@ -294,43 +567,37 @@ export function prepareForEditMode(node: JxMutableNode): JxMutableNode {
|
|
|
294
567
|
padding: "6px 10px",
|
|
295
568
|
},
|
|
296
569
|
tagName: "div",
|
|
297
|
-
textContent: `[$switch: ${
|
|
570
|
+
textContent: `[$switch: ${Object.keys(v).join(" | ")}]`,
|
|
298
571
|
},
|
|
299
572
|
];
|
|
300
573
|
}
|
|
301
|
-
} else if (k === "attributes" && isMediaElement && v
|
|
302
|
-
//
|
|
303
|
-
const
|
|
304
|
-
const
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
processed[ak] = av;
|
|
309
|
-
} else {
|
|
310
|
-
needsMediaPlaceholder = true;
|
|
311
|
-
processed[ak] = TRANSPARENT_PX;
|
|
312
|
-
}
|
|
313
|
-
} else if (typeof av === "string" && av.includes("${")) {
|
|
314
|
-
const isUrlAttr = ak === "href" || ak === "action";
|
|
315
|
-
processed[ak] = isUrlAttr ? "" : templateToEditDisplay(av);
|
|
316
|
-
} else if (av && typeof av === "object" && (av as Record<string, unknown>).$ref) {
|
|
317
|
-
const ref = (av as Record<string, unknown>).$ref as string;
|
|
318
|
-
const label = ref.startsWith("#/state/") ? ref.slice(8) : ref;
|
|
319
|
-
processed[ak] = `{${label}}`;
|
|
574
|
+
} else if (k === "attributes" && isMediaElement && isDocumentContainer(v)) {
|
|
575
|
+
// A media element's src/poster: live, unless it reads the repeater row or names nothing.
|
|
576
|
+
const processed: RebuiltNode = {};
|
|
577
|
+
for (const [ak, av] of Object.entries(v)) {
|
|
578
|
+
if ((ak === "src" || ak === "poster") && (av === "" || av == null || isRowBound(av))) {
|
|
579
|
+
needsMediaPlaceholder = true;
|
|
580
|
+
processed[ak] = TRANSPARENT_PX;
|
|
320
581
|
} else {
|
|
321
|
-
processed[ak] = av;
|
|
582
|
+
processed[ak] = isRowBound(av) ? rowBoundDisplay(ak, av) : av;
|
|
322
583
|
}
|
|
323
584
|
}
|
|
324
585
|
out.attributes = processed;
|
|
586
|
+
} else if (k === "attributes" && isDocumentContainer(v)) {
|
|
587
|
+
const processed: RebuiltNode = {};
|
|
588
|
+
for (const [ak, av] of Object.entries(v)) {
|
|
589
|
+
processed[ak] = isRowBound(av) ? rowBoundDisplay(ak, av) : av;
|
|
590
|
+
}
|
|
591
|
+
out.attributes = processed;
|
|
325
592
|
} else if (k === "style") {
|
|
326
|
-
/*
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
if (v
|
|
331
|
-
const s:
|
|
593
|
+
/* Live, like every binding but text: state IS live on the canvas. Only a declaration that
|
|
594
|
+
reads the repeater row is omitted — the perimeter has no row — and omitted rather than
|
|
595
|
+
blanked, because `color: ` is a malformed declaration in a rule where the cascade answers
|
|
596
|
+
an absent one. Mirrored by iframe-patch's editModeStyle. */
|
|
597
|
+
if (isDocumentContainer(v)) {
|
|
598
|
+
const s: RebuiltNode = {};
|
|
332
599
|
for (const [sk, sv] of Object.entries(v)) {
|
|
333
|
-
if (
|
|
600
|
+
if (!isRowBound(sv)) {
|
|
334
601
|
s[sk] = sv;
|
|
335
602
|
}
|
|
336
603
|
}
|
|
@@ -338,53 +605,41 @@ export function prepareForEditMode(node: JxMutableNode): JxMutableNode {
|
|
|
338
605
|
} else {
|
|
339
606
|
out.style = v;
|
|
340
607
|
}
|
|
341
|
-
} else if (
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
} else if (v && typeof v === "object" && (v as Record<string, unknown>).$ref) {
|
|
353
|
-
// $ref binding → show ref path as literal text
|
|
354
|
-
const ref = (v as Record<string, unknown>).$ref as string;
|
|
355
|
-
const label = ref.startsWith("#/state/") ? ref.slice(8) : ref;
|
|
356
|
-
const isMediaSrc =
|
|
357
|
-
(k === "src" || k === "poster") && mediaTags.has((obj.tagName as string) || "");
|
|
358
|
-
if (isMediaSrc) {
|
|
608
|
+
} else if (k === "$switch" && isString(v) && v.includes("${")) {
|
|
609
|
+
/* Not a render input any more: `cases` is replaced by the first case above, so a live
|
|
610
|
+
expression would hand the runtime a switch with nothing to choose from. */
|
|
611
|
+
out[k] = templateToEditDisplay(v);
|
|
612
|
+
} else if (k === "textContent" && isString(v) && v.includes("${")) {
|
|
613
|
+
// The author's text: shown as its binding, so editing it in place edits the template.
|
|
614
|
+
out[k] = templateToEditDisplay(v);
|
|
615
|
+
} else if (k === "textContent" && isNodeObject(v) && v.$ref) {
|
|
616
|
+
out[k] = refDisplayLabel(v.$ref);
|
|
617
|
+
} else if (isMediaElement && (k === "src" || k === "poster")) {
|
|
618
|
+
if (v === "" || v == null || isRowBound(v)) {
|
|
359
619
|
needsMediaPlaceholder = true;
|
|
360
620
|
out[k] = TRANSPARENT_PX;
|
|
361
621
|
} else {
|
|
362
|
-
out[k] =
|
|
622
|
+
out[k] = v;
|
|
363
623
|
}
|
|
624
|
+
} else if (isRowBound(v)) {
|
|
625
|
+
out[k] = rowBoundDisplay(k, v);
|
|
626
|
+
} else if (isString(v) || (isNodeObject(v) && v.$ref)) {
|
|
627
|
+
// Any other bound or literal property renders as the page will.
|
|
628
|
+
out[k] = v;
|
|
364
629
|
} else {
|
|
365
|
-
|
|
366
|
-
if (
|
|
367
|
-
(k === "src" || k === "poster") &&
|
|
368
|
-
v === "" &&
|
|
369
|
-
mediaTags.has((obj.tagName as string) || "")
|
|
370
|
-
) {
|
|
371
|
-
needsMediaPlaceholder = true;
|
|
372
|
-
out[k] = TRANSPARENT_PX;
|
|
373
|
-
} else {
|
|
374
|
-
out[k] = prepareForEditMode(v as JxMutableNode);
|
|
375
|
-
}
|
|
630
|
+
out[k] = prepareNode(v, row);
|
|
376
631
|
}
|
|
377
632
|
}
|
|
378
633
|
|
|
379
634
|
// Mark empty elements with placeholder classes for design-mode visibility
|
|
380
|
-
const placeholderClass = computeEmptyPlaceholderClass(out
|
|
635
|
+
const placeholderClass = computeEmptyPlaceholderClass(out);
|
|
381
636
|
if (placeholderClass) {
|
|
382
637
|
out.className = out.className ? `${out.className} ${placeholderClass}` : placeholderClass;
|
|
383
638
|
}
|
|
384
639
|
|
|
385
640
|
// Media elements with missing/dynamic src get a placeholder class
|
|
386
641
|
if (needsMediaPlaceholder) {
|
|
387
|
-
const cls = (out.className
|
|
642
|
+
const cls = isString(out.className) ? out.className : "";
|
|
388
643
|
if (!cls.includes("empty-media-placeholder")) {
|
|
389
644
|
out.className = cls ? `${cls} empty-media-placeholder` : "empty-media-placeholder";
|
|
390
645
|
}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import { COMMON_SELECTORS } from "../store";
|
|
17
|
-
import { displayTagName } from "@jxsuite/schema/guards";
|
|
17
|
+
import { displayTagName, isNonNullObject } from "@jxsuite/schema/guards";
|
|
18
18
|
import { isPopover } from "@jxsuite/schema/overlays";
|
|
19
19
|
import type { JxMutableNode } from "@jxsuite/schema/types";
|
|
20
20
|
|
|
@@ -62,7 +62,8 @@ function extraSelectorsFor(node: JxMutableNode): string[] {
|
|
|
62
62
|
* @returns The offerable selectors.
|
|
63
63
|
*/
|
|
64
64
|
export function selectorsForNode(node: JxMutableNode | null | undefined): string[] {
|
|
65
|
-
|
|
65
|
+
// The style panel reads the node with getNodeAtPath, which can answer a bare string text child.
|
|
66
|
+
if (!isNonNullObject(node)) {
|
|
66
67
|
return [...COMMON_SELECTORS];
|
|
67
68
|
}
|
|
68
69
|
return [...new Set([...COMMON_SELECTORS, ...extraSelectorsFor(node)])];
|