@jxsuite/studio 4.0.0 → 5.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 +1 -1
- package/data/elements-meta.json +5 -15
- package/data/html-meta.json +51 -6
- package/dist/chunks/{2020-xp8vnwma.js → 2020-g79n01v9.js} +14 -14
- package/dist/chunks/action-group-sp6tna8v.js +118 -0
- package/dist/chunks/adapter-nj7tnjfn.js +13 -0
- package/dist/chunks/cf-account-picker-fyf63pmy.js +495 -0
- package/dist/chunks/cf-settings-71bv5zn9.js +20 -0
- package/dist/chunks/color-area-v17df7b8.js +154 -0
- package/dist/chunks/color-field-anwybnkn.js +208 -0
- package/dist/chunks/color-slider-44ez96fc.js +79 -0
- package/dist/chunks/color-xgg3kfw7.js +35 -0
- package/dist/chunks/combobox-5e7jev23.js +236 -0
- package/dist/chunks/components-2w1f35qs.js +18 -0
- package/dist/chunks/content-source-3wqeas45.js +46 -0
- package/dist/chunks/convert-to-repeater-d0cgnb6d.js +639 -0
- package/dist/chunks/dialog-s890b918.js +85 -0
- package/dist/chunks/editor-3qhbg51x.js +35 -0
- package/dist/chunks/entry-commands-d6g50j7s.js +42 -0
- package/dist/chunks/extension-sections-fy7q4fe9.js +651 -0
- package/dist/chunks/file-ops-3btj6st0.js +47 -0
- package/dist/chunks/files-ef8fgs3w.js +72 -0
- package/dist/chunks/format-host-3c33nwr8.js +40 -0
- package/dist/chunks/fs-events-13tj6sex.js +18 -0
- package/dist/chunks/git-panel-4wp2rn9b.js +49 -0
- package/dist/chunks/icons-yy10wk9r.js +402 -0
- package/dist/chunks/iframe-entry-15g3n6xv.js +114 -0
- package/dist/chunks/iframe-entry-b27vq81n.js +203 -0
- package/dist/chunks/iframe-entry-nbyxee1y.js +154 -0
- package/dist/chunks/iframe-host-jgesd924.js +115 -0
- package/dist/chunks/{index-nj44jpzj.js → index-mdmyx6s2.js} +11 -11
- package/dist/chunks/index-n4j7qxyr.js +109 -0
- package/dist/chunks/{javascript-q8kpmfah.js → javascript-xvrfrpkb.js} +8 -9
- package/dist/chunks/{jsonMode-dkr040ga.js → jsonMode-tyx2kj6p.js} +526 -527
- package/dist/chunks/jx-validate-j0wxk72w.js +15 -0
- package/dist/chunks/layers-1nq5evsh.js +29 -0
- package/dist/chunks/layers-panel-ar2gh90g.js +40 -0
- package/dist/chunks/listbox-6v2ac08j.js +44 -0
- package/dist/chunks/lit-html-m244w9nh.js +17 -0
- package/dist/chunks/media-picker-2qbetq73.js +33 -0
- package/dist/chunks/menu-q99sy9rf.js +285 -0
- package/dist/chunks/menu-rf7n72mf.js +14 -0
- package/dist/chunks/{monaco-binding-rj6xpx9y.js → monaco-binding-sw6en4dw.js} +12 -15
- package/dist/chunks/monaco-buffer-bhy3hb6m.js +24 -0
- package/dist/chunks/{monaco-setup-rws7k4br.js → monaco-setup-8r62fj6y.js} +27 -37
- package/dist/chunks/notify-628t0anh.js +21 -0
- package/dist/chunks/number-field-5cndyft8.js +72 -0
- package/dist/chunks/parse-0zx14y15.js +10 -0
- package/dist/chunks/platform-ts9cg1a4.js +15 -0
- package/dist/chunks/popover-47z3ytva.js +25 -0
- package/dist/chunks/publish-panel-98f7sr3g.js +27 -0
- package/dist/chunks/quick-search-srzz83k2.js +45 -0
- package/dist/chunks/references-n553f0e1.js +26 -0
- package/dist/chunks/right-panel-rrgx2dn3.js +45 -0
- package/dist/chunks/section-registry-5pq32t0q.js +25 -0
- package/dist/chunks/select-2r16ez41.js +49 -0
- package/dist/chunks/split-g7nm1rgb.js +191 -0
- package/dist/chunks/studio-0hqbpbd0.js +62 -0
- package/dist/chunks/studio-18avnhjp.js +2430 -0
- package/dist/chunks/{studio-kryvsw6j.js → studio-1k325pwf.js} +48 -48
- package/dist/chunks/{studio-hbtp0eh1.js → studio-25hkdrkw.js} +356 -85
- package/dist/chunks/studio-26d7myd1.js +258 -0
- package/dist/chunks/{studio-p8j86wag.js → studio-38emantv.js} +22 -5
- package/dist/chunks/studio-3gxv60tn.js +422 -0
- package/dist/chunks/{studio-8swrjbny.js → studio-3hxkd92t.js} +275 -163
- package/dist/chunks/studio-4m0haseg.js +185 -0
- package/dist/chunks/{studio-ynxwkrzd.js → studio-4wbb9ct0.js} +1953 -1785
- package/dist/chunks/{studio-gv8vvshc.js → studio-5523bpzt.js} +11 -11
- package/dist/chunks/{studio-5q69gfag.js → studio-57mf66w2.js} +1753 -2484
- package/dist/chunks/studio-5jy81t3s.js +17463 -0
- package/dist/chunks/studio-5rt7sqa0.js +1168 -0
- package/dist/chunks/studio-5te5tqng.js +81 -0
- package/dist/chunks/{studio-p4ngc046.js → studio-6ewqv390.js} +9 -9
- package/dist/chunks/{studio-9ab8gqsm.js → studio-6nzaktvy.js} +7 -7
- package/dist/chunks/studio-6xa21ej9.js +28 -0
- package/dist/chunks/{studio-5ehhackm.js → studio-727xh0e3.js} +19 -19
- package/dist/chunks/{studio-eenfkt4e.js → studio-79y5sz51.js} +52 -38
- package/dist/chunks/{studio-4q0wznzf.js → studio-7e11jpa9.js} +461 -145
- package/dist/chunks/{studio-q7v10cg2.js → studio-7r42c6ca.js} +17 -7
- package/dist/chunks/studio-7xptrg0j.js +954 -0
- package/dist/chunks/{studio-cft9r4r7.js → studio-81390n6f.js} +22 -22
- package/dist/chunks/{studio-q43a5y9h.js → studio-8jn5yhyn.js} +16 -16
- package/dist/chunks/studio-8qtrpzr3.js +839 -0
- package/dist/chunks/{studio-dg7zyt5x.js → studio-98b3z07n.js} +1 -1
- package/dist/chunks/studio-9xxz1q69.js +1356 -0
- package/dist/chunks/studio-akbww0j5.js +13615 -0
- package/dist/chunks/studio-arfpe389.js +195 -0
- package/dist/chunks/{studio-2zkz8evn.js → studio-az3zd49t.js} +473 -281
- package/dist/chunks/studio-cpvb2ed1.js +1171 -0
- package/dist/chunks/{studio-9r6j5ev1.js → studio-d0300636.js} +5078 -19
- package/dist/chunks/{studio-bgxt93ga.js → studio-d055c37e.js} +13 -13
- package/dist/chunks/studio-d1ja2x9r.js +362 -0
- package/dist/chunks/{studio-b9b6t1dg.js → studio-e1f24eff.js} +5664 -5666
- package/dist/chunks/{studio-4pqqxbrt.js → studio-em9nw8eh.js} +301 -112
- package/dist/chunks/studio-erdatzvp.js +1190 -0
- package/dist/chunks/{studio-g1wdche0.js → studio-esrxgwh6.js} +80 -80
- package/dist/chunks/studio-fabxk6r9.js +2811 -0
- package/dist/chunks/{studio-3n4ndrzh.js → studio-h4nvnjvz.js} +303 -303
- package/dist/chunks/studio-hhvs4sdg.js +195 -0
- package/dist/chunks/{studio-68n67094.js → studio-kcgff4r0.js} +15 -18
- package/dist/chunks/{studio-685s0ytq.js → studio-nqgawfks.js} +572 -572
- package/dist/chunks/{studio-xrapxwwc.js → studio-p1dw8wfw.js} +55 -29
- package/dist/chunks/studio-pm6hgy7r.js +4763 -0
- package/dist/chunks/studio-q0a3yk4n.js +33 -0
- package/dist/chunks/{studio-wcy8trfx.js → studio-q3x06vmj.js} +23 -22
- package/dist/chunks/studio-qahxvnan.js +111 -0
- package/dist/chunks/{studio-53n8bp04.js → studio-r6xmmtfh.js} +1 -1
- package/dist/chunks/{studio-kjjsjak4.js → studio-rkstz940.js} +3661 -6136
- package/dist/chunks/{studio-tvgyw9xw.js → studio-rnyf3f8e.js} +83 -250
- package/dist/chunks/studio-rpyah2ew.js +2805 -0
- package/dist/chunks/studio-rs76k67r.js +12 -0
- package/dist/chunks/{studio-yxrkyv8a.js → studio-s6z853aq.js} +12108 -11766
- package/dist/chunks/{studio-sf7zjgv1.js → studio-sgdc5pfc.js} +8 -8
- package/dist/chunks/studio-tb3ev01j.js +763 -0
- package/dist/chunks/{studio-t5wqwzdh.js → studio-tjjk7jvk.js} +1 -1
- package/dist/chunks/studio-vhv5tgxm.js +51 -0
- package/dist/chunks/{studio-htsf0w6m.js → studio-vz68yn9e.js} +31 -154
- package/dist/chunks/studio-wqpngpsk.js +174 -0
- package/dist/chunks/{studio-eesa1myv.js → studio-x3rty6tr.js} +58 -58
- package/dist/chunks/studio-xsykpvsh.js +8448 -0
- package/dist/chunks/{studio-92ab2jqe.js → studio-y9zedyjn.js} +14 -14
- package/dist/chunks/studio-yxa81f45.js +12 -0
- package/dist/chunks/swatch-group-t0n6h2rn.js +139 -0
- package/dist/chunks/tabs-wbp1cdws.js +156 -0
- package/dist/chunks/textfield-abk6qyee.js +73 -0
- package/dist/chunks/toast-780pvfbv.js +27 -0
- package/dist/chunks/toast-host-3sqv46sn.js +116 -0
- package/dist/chunks/toolbar-xbh5bhtr.js +194 -0
- package/dist/chunks/tooltip-eptb614w.js +369 -0
- package/dist/chunks/tree-a73p0pqm.js +367 -0
- package/dist/chunks/{tsMode-76kr53q0.js → tsMode-jy4m86rv.js} +83 -85
- package/dist/chunks/workspace-wrew8zk4.js +69 -0
- package/dist/chunks/{ws-client-6shc5rze.js → ws-client-ny4zc51r.js} +20 -22
- package/dist/iframe-entry.js +1812 -698
- package/dist/manifest.json +7 -0
- package/dist/studio.js +52900 -36573
- package/dist/workers/editor.worker.js +1040 -1085
- package/dist/workers/json.worker.js +1946 -1991
- package/dist/workers/ts.worker.js +4960 -5005
- package/favicon.ico +0 -0
- package/index.html +2 -0
- package/package.json +22 -55
- package/src/about/about-modal.ts +73 -123
- package/src/browse/library-commands.ts +20 -49
- package/src/browse/library-layouts.ts +87 -218
- package/src/browse/library-pane.ts +406 -438
- package/src/canvas/canvas-helpers.ts +0 -49
- package/src/canvas/canvas-live-render.ts +25 -2
- package/src/canvas/canvas-render.ts +666 -231
- package/src/canvas/canvas-surface.ts +0 -1
- package/src/canvas/canvas-utils.ts +310 -117
- package/src/canvas/dialog-path.ts +76 -0
- package/src/canvas/dialog-state.ts +67 -0
- package/src/canvas/diff-marks.ts +252 -0
- package/src/canvas/diff-toolbar.ts +349 -0
- package/src/canvas/diff-view.ts +123 -0
- package/src/canvas/edit-width-drag.ts +187 -0
- package/src/canvas/edit-width.ts +150 -0
- package/src/canvas/iframe-entry.ts +125 -8
- package/src/canvas/iframe-host.ts +271 -15
- package/src/canvas/iframe-interaction.ts +133 -13
- package/src/canvas/iframe-patch.ts +7 -1
- package/src/canvas/iframe-position.ts +5 -6
- package/src/canvas/iframe-protocol.ts +106 -5
- package/src/canvas/iframe-render.ts +373 -5
- package/src/canvas/iframe-slash.ts +2 -2
- package/src/canvas/iframe-subtree.ts +5 -8
- package/src/canvas/path-mapping.ts +25 -3
- package/src/canvas/popover-path.ts +106 -0
- package/src/canvas/popover-state.ts +155 -0
- package/src/canvas/surface-registry.ts +21 -10
- package/src/collab/presence-chips.ts +51 -73
- package/src/commands/app-commands.ts +10 -0
- package/src/commands/budget.ts +12 -0
- package/src/commands/command-args.ts +369 -6
- package/src/commands/defaults.ts +44 -14
- package/src/commands/live-context.ts +11 -5
- package/src/commands/reference.ts +12 -2
- package/src/commands/registry.ts +165 -8
- package/src/content/entry-commands.ts +16 -23
- package/src/content/entry-editor.ts +144 -101
- package/src/editor/canvas-slash-bridge.ts +2 -2
- package/src/editor/context-menu.ts +49 -200
- package/src/editor/convert-to-component.ts +42 -82
- package/src/editor/convert-to-repeater.ts +132 -173
- package/src/editor/inline-edit.ts +11 -0
- package/src/editor/shortcuts.ts +65 -26
- package/src/editor/slash-menu.ts +150 -157
- package/src/files/file-ops.ts +117 -11
- package/src/files/files.ts +949 -664
- package/src/files/json-layout.ts +474 -0
- package/src/files/media-paths.ts +13 -42
- package/src/files/media-usage.ts +41 -131
- package/src/files/serialize-document.ts +8 -1
- package/src/format/convert-file.ts +16 -10
- package/src/format/format-host.ts +50 -1
- package/src/github/github-auth.ts +71 -29
- package/src/github/github-publish.ts +57 -65
- package/src/grid/cell-editors.ts +46 -4
- package/src/grid/cell-popovers.ts +65 -62
- package/src/grid/grid-open.ts +86 -64
- package/src/grid/grid-panel.ts +390 -469
- package/src/grid/redirects-grid.ts +40 -44
- package/src/hosting/document.ts +2 -0
- package/src/hosting/layout.ts +10 -0
- package/src/i18n/i18n-commands.ts +127 -62
- package/src/media/media-pane.ts +83 -133
- package/src/new-project/add-repo-modal.ts +125 -176
- package/src/new-project/import-tab.ts +201 -250
- package/src/new-project/location-fields.ts +101 -165
- package/src/new-project/new-project-modal.ts +376 -367
- package/src/packages/jxsuite-update.ts +76 -18
- package/src/panels/activity-panel.ts +137 -104
- package/src/panels/ai-chat/chat-markdown.ts +15 -13
- package/src/panels/ai-chat/chat-view.ts +307 -472
- package/src/panels/ai-chat/composer.ts +175 -153
- package/src/panels/ai-chat/sessions-view.ts +31 -62
- package/src/panels/ai-panel.ts +210 -185
- package/src/panels/block-action-bar.ts +437 -643
- package/src/panels/bottom-dock.ts +112 -47
- package/src/panels/chat-panel.ts +19 -14
- package/src/panels/data-explorer.ts +141 -102
- package/src/panels/data-grid.ts +183 -150
- package/src/panels/dnd.ts +75 -20
- package/src/panels/editors.ts +26 -19
- package/src/panels/elements-panel.ts +243 -186
- package/src/panels/empty-state.ts +26 -42
- package/src/panels/events-panel.ts +950 -729
- package/src/panels/formula-workspace.ts +434 -207
- package/src/panels/frontmatter-fields.ts +185 -153
- package/src/panels/frontmatter-panel.ts +411 -187
- package/src/panels/git-diff-open.ts +148 -0
- package/src/panels/git-panel.ts +679 -605
- package/src/panels/head-panel.ts +617 -435
- package/src/panels/i18n-panel.ts +153 -133
- package/src/panels/imports-panel.ts +388 -414
- package/src/panels/jump-bar.ts +174 -147
- package/src/panels/layers-panel.ts +785 -671
- package/src/panels/left-panel.ts +166 -94
- package/src/panels/navigator-panels.ts +1 -1
- package/src/panels/pane-context.ts +529 -677
- package/src/panels/pane-grid.ts +265 -241
- package/src/panels/panel-registry.ts +15 -4
- package/src/panels/problems-panel.ts +177 -99
- package/src/panels/properties-panel.ts +1525 -966
- package/src/panels/provenance.ts +31 -113
- package/src/panels/quick-search.ts +217 -172
- package/src/panels/right-panel.ts +135 -169
- package/src/panels/seo-modal.ts +346 -167
- package/src/panels/settings-menu.ts +109 -646
- package/src/panels/settings-pane.ts +102 -86
- package/src/panels/signals-panel.ts +1318 -1172
- package/src/panels/statement-editor.ts +556 -428
- package/src/panels/style-panel.ts +1367 -630
- package/src/panels/style-utils.ts +36 -32
- package/src/panels/stylebook-doc.ts +30 -73
- package/src/panels/stylebook-layers-panel.ts +202 -109
- package/src/panels/stylebook-panel.ts +124 -88
- package/src/panels/tab-strip.ts +385 -287
- package/src/platforms/cloud.ts +347 -86
- package/src/platforms/devserver.ts +13 -0
- package/src/publish/deploy-checklist.ts +124 -78
- package/src/publish/publish-commands.ts +4 -12
- package/src/publish/publish-panel.ts +165 -299
- package/src/services/a11y-report.ts +100 -43
- package/src/services/ai-command-tools.ts +468 -0
- package/src/services/ai-import-tools.ts +50 -12
- package/src/services/ai-models.ts +108 -1
- package/src/services/ai-session-store.ts +6 -0
- package/src/services/ai-system-prompt.ts +110 -18
- package/src/services/ai-tools.ts +28 -143
- package/src/services/ai-write-report.ts +174 -0
- package/src/services/context-manager.ts +12 -1
- package/src/services/document-assistant.ts +50 -2
- package/src/services/idle.ts +16 -14
- package/src/services/live-surfaces.ts +237 -0
- package/src/services/model-uri.ts +75 -0
- package/src/services/notify.ts +63 -6
- package/src/services/popover-report.ts +325 -0
- package/src/services/surface-registry.ts +56 -0
- package/src/services/tool-executor.ts +17 -0
- package/src/settings/contexts-section.ts +301 -299
- package/src/settings/contributed-section.ts +361 -222
- package/src/settings/css-vars-editor.ts +320 -325
- package/src/settings/defs-editor.ts +572 -535
- package/src/settings/dependencies-editor.ts +79 -107
- package/src/settings/extension-commands.ts +379 -0
- package/src/settings/extension-rows.ts +113 -0
- package/src/settings/extensions-section.ts +287 -0
- package/src/settings/general-settings.ts +130 -181
- package/src/settings/head-editor.ts +10 -305
- package/src/settings/locales-section.ts +146 -196
- package/src/settings/preferences-accounts.ts +193 -12
- package/src/settings/preferences-dialog.ts +384 -307
- package/src/settings/project-sections.ts +108 -181
- package/src/settings/schema-field-ui.ts +11 -399
- package/src/settings/section-registry.ts +8 -1
- package/src/settings/settings-document.ts +31 -29
- package/src/shell/tree.ts +42 -87
- package/src/shell.ts +48 -36
- package/src/studio.ts +90 -67
- package/src/style/token-ref.ts +0 -39
- package/src/surfaces/about.json +263 -0
- package/src/surfaces/about.ts +163 -0
- package/src/surfaces/add-repo.json +486 -0
- package/src/surfaces/add-repo.ts +236 -0
- package/src/surfaces/ai-chat.json +2185 -0
- package/src/surfaces/ai-chat.ts +549 -0
- package/src/surfaces/ai-credentials-form.json +332 -0
- package/src/surfaces/ai-credentials-form.ts +151 -0
- package/src/surfaces/ai-managed-connect.json +108 -0
- package/src/surfaces/ai-managed-connect.ts +123 -0
- package/src/surfaces/ai-model-picker.json +114 -0
- package/src/surfaces/ai-model-picker.ts +139 -0
- package/src/surfaces/block-action-bar.json +640 -0
- package/src/surfaces/block-action-bar.ts +368 -0
- package/src/surfaces/bottom-dock.json +154 -0
- package/src/surfaces/bottom-dock.ts +125 -0
- package/src/surfaces/canvas-stage.json +444 -0
- package/src/surfaces/canvas-stage.ts +253 -0
- package/src/surfaces/cf-account-picker.json +300 -0
- package/src/surfaces/cf-account-picker.ts +214 -0
- package/src/surfaces/commandbar.json +984 -0
- package/src/{panels/toolbar.ts → surfaces/commandbar.ts} +414 -389
- package/src/surfaces/convert-repeater.json +309 -0
- package/src/surfaces/convert-repeater.ts +276 -0
- package/src/surfaces/data-actions.json +157 -0
- package/src/surfaces/data-actions.ts +115 -0
- package/src/surfaces/dialog.json +289 -0
- package/src/surfaces/dialog.ts +343 -0
- package/src/surfaces/diff-toolbar.json +266 -0
- package/src/surfaces/diff-toolbar.ts +139 -0
- package/src/surfaces/doc-header.json +739 -0
- package/src/surfaces/doc-header.ts +223 -0
- package/src/surfaces/empty-state.json +152 -0
- package/src/surfaces/empty-state.ts +173 -0
- package/src/surfaces/entry-editor.json +281 -0
- package/src/surfaces/entry-editor.ts +191 -0
- package/src/surfaces/expression-editor.json +977 -0
- package/src/surfaces/expression-editor.ts +266 -0
- package/src/surfaces/files-panel.json +592 -0
- package/src/surfaces/files-panel.ts +301 -0
- package/src/surfaces/formula-palette.json +364 -0
- package/src/surfaces/formula-palette.ts +340 -0
- package/src/surfaces/git-panel.json +1822 -0
- package/src/surfaces/git-panel.ts +272 -0
- package/src/surfaces/github-auth.json +112 -0
- package/src/surfaces/github-auth.ts +139 -0
- package/src/surfaces/github-publish.json +206 -0
- package/src/surfaces/github-publish.ts +169 -0
- package/src/surfaces/grid-cell.json +218 -0
- package/src/surfaces/grid-cell.ts +120 -0
- package/src/surfaces/grid-open.json +147 -0
- package/src/surfaces/grid-open.ts +87 -0
- package/src/surfaces/grid-panel.json +706 -0
- package/src/surfaces/grid-panel.ts +206 -0
- package/src/surfaces/grid-replace.json +179 -0
- package/src/surfaces/grid-replace.ts +89 -0
- package/src/surfaces/grid-views.json +446 -0
- package/src/surfaces/grid-views.ts +172 -0
- package/src/surfaces/inspector-dock.json +187 -0
- package/src/surfaces/inspector-dock.ts +161 -0
- package/src/surfaces/jump-bar.json +243 -0
- package/src/surfaces/jump-bar.ts +129 -0
- package/src/surfaces/jxsuite-update.json +146 -0
- package/src/surfaces/jxsuite-update.ts +149 -0
- package/src/surfaces/library-pane.json +1509 -0
- package/src/surfaces/library-pane.ts +363 -0
- package/src/surfaces/logic-panel.json +1949 -0
- package/src/surfaces/logic-panel.ts +369 -0
- package/src/surfaces/logic-workspace.json +685 -0
- package/src/surfaces/logic-workspace.ts +238 -0
- package/src/surfaces/media-browser.json +303 -0
- package/src/surfaces/media-browser.ts +145 -0
- package/src/surfaces/media-field.json +163 -0
- package/src/surfaces/media-field.ts +116 -0
- package/src/surfaces/media-pane.json +513 -0
- package/src/surfaces/media-pane.ts +197 -0
- package/src/surfaces/menu.json +232 -0
- package/src/surfaces/menu.ts +375 -0
- package/src/surfaces/navigator-dock.json +113 -0
- package/src/surfaces/navigator-dock.ts +130 -0
- package/src/surfaces/new-project.json +1654 -0
- package/src/surfaces/new-project.ts +411 -0
- package/src/surfaces/palette.json +535 -0
- package/src/surfaces/pane-context.json +1497 -0
- package/src/surfaces/pane-context.ts +513 -0
- package/src/surfaces/pane-grid.json +188 -0
- package/src/surfaces/pane-grid.ts +250 -0
- package/src/surfaces/panel-activity.json +563 -0
- package/src/surfaces/panel-activity.ts +187 -0
- package/src/surfaces/panel-data.json +141 -0
- package/src/surfaces/panel-data.ts +156 -0
- package/src/surfaces/panel-deploy-checklist.json +283 -0
- package/src/surfaces/panel-deploy-checklist.ts +175 -0
- package/src/surfaces/panel-elements.json +367 -0
- package/src/surfaces/panel-elements.ts +175 -0
- package/src/surfaces/panel-i18n.json +569 -0
- package/src/surfaces/panel-i18n.ts +212 -0
- package/src/surfaces/panel-imports.json +780 -0
- package/src/surfaces/panel-imports.ts +209 -0
- package/src/surfaces/panel-outline.json +734 -0
- package/src/surfaces/panel-outline.ts +326 -0
- package/src/surfaces/panel-page.json +1017 -0
- package/src/surfaces/panel-page.ts +240 -0
- package/src/surfaces/panel-problems.json +497 -0
- package/src/surfaces/panel-problems.ts +157 -0
- package/src/surfaces/panel-signals.json +1973 -0
- package/src/surfaces/panel-signals.ts +436 -0
- package/src/surfaces/panel-stylebook-layers.json +317 -0
- package/src/surfaces/panel-stylebook-layers.ts +155 -0
- package/src/surfaces/preferences.json +850 -0
- package/src/surfaces/preferences.ts +332 -0
- package/src/surfaces/progress-modal.json +110 -0
- package/src/surfaces/progress-modal.ts +150 -0
- package/src/surfaces/properties-panel.json +1578 -0
- package/src/surfaces/properties-panel.ts +337 -0
- package/src/surfaces/publish.json +945 -0
- package/src/surfaces/publish.ts +392 -0
- package/src/surfaces/push-plan.json +110 -0
- package/src/surfaces/push-plan.ts +87 -0
- package/src/surfaces/rail.json +255 -0
- package/src/surfaces/rail.ts +206 -0
- package/src/surfaces/reference-field.json +191 -0
- package/src/surfaces/reference-field.ts +168 -0
- package/src/surfaces/schema-builder.json +1011 -0
- package/src/surfaces/schema-builder.ts +181 -0
- package/src/surfaces/schema-form.json +1013 -0
- package/src/surfaces/schema-form.ts +287 -0
- package/src/surfaces/secret-field.json +60 -0
- package/src/surfaces/secret-field.ts +146 -0
- package/src/surfaces/seo.json +932 -0
- package/src/surfaces/seo.ts +334 -0
- package/src/surfaces/settings-contexts.json +538 -0
- package/src/surfaces/settings-contexts.ts +196 -0
- package/src/surfaces/settings-contributed.json +489 -0
- package/src/surfaces/settings-contributed.ts +199 -0
- package/src/surfaces/settings-css-vars.json +820 -0
- package/src/surfaces/settings-css-vars.ts +199 -0
- package/src/surfaces/settings-defs.json +1363 -0
- package/src/surfaces/settings-defs.ts +232 -0
- package/src/surfaces/settings-deploy.json +108 -0
- package/src/surfaces/settings-deploy.ts +135 -0
- package/src/surfaces/settings-extensions.json +486 -0
- package/src/surfaces/settings-extensions.ts +201 -0
- package/src/surfaces/settings-head.json +779 -0
- package/src/surfaces/settings-head.ts +397 -0
- package/src/surfaces/settings-locales.json +420 -0
- package/src/surfaces/settings-locales.ts +137 -0
- package/src/surfaces/settings-overview.json +423 -0
- package/src/surfaces/settings-overview.ts +218 -0
- package/src/surfaces/settings-packages.json +549 -0
- package/src/surfaces/settings-packages.ts +158 -0
- package/src/surfaces/settings-pane.json +147 -0
- package/src/surfaces/settings-pane.ts +150 -0
- package/src/surfaces/settings-rawjson.json +104 -0
- package/src/surfaces/settings-rawjson.ts +107 -0
- package/src/surfaces/shell.json +99 -0
- package/src/surfaces/shell.ts +30 -0
- package/src/surfaces/slash-menu.json +180 -0
- package/src/surfaces/slash-menu.ts +272 -0
- package/src/surfaces/statements.json +607 -0
- package/src/surfaces/statements.ts +238 -0
- package/src/surfaces/statusbar.json +94 -0
- package/src/{panels → surfaces}/statusbar.ts +163 -90
- package/src/surfaces/style-panel.json +1643 -0
- package/src/surfaces/style-panel.ts +338 -0
- package/src/surfaces/stylebook-chrome.json +122 -0
- package/src/surfaces/stylebook-chrome.ts +122 -0
- package/src/surfaces/tab-strip.json +448 -0
- package/src/surfaces/tab-strip.ts +200 -0
- package/src/surfaces/target-line.json +419 -0
- package/src/surfaces/target-line.ts +349 -0
- package/src/surfaces/toasts.json +189 -0
- package/src/surfaces/welcome.json +571 -0
- package/src/surfaces/welcome.ts +338 -0
- package/src/tabs/project-config.ts +71 -15
- package/src/tabs/tab.ts +52 -1
- package/src/types.ts +49 -3
- package/src/ui/ai-credentials-form.ts +104 -100
- package/src/ui/ai-managed-connect.ts +116 -49
- package/src/ui/ai-model-picker.ts +102 -47
- package/src/ui/cf-account-picker.ts +135 -0
- package/src/ui/color-selector.ts +80 -301
- package/src/ui/dynamic-slot.ts +43 -283
- package/src/ui/expression-editor.ts +797 -576
- package/src/ui/field-input.ts +8 -181
- package/src/ui/form-controls.ts +838 -366
- package/src/ui/formula-chips.ts +80 -85
- package/src/ui/kit.ts +33 -0
- package/src/ui/layers.ts +293 -593
- package/src/ui/media-picker.ts +203 -284
- package/src/ui/panel-resize.ts +251 -64
- package/src/ui/popover-surface.ts +153 -0
- package/src/ui/progress-modal.ts +22 -60
- package/src/ui/regions.ts +13 -7
- package/src/ui/schema-form.ts +906 -440
- package/src/ui/surface.ts +122 -0
- package/src/ui/unit-selector.ts +15 -131
- package/src/ui/value-source.ts +14 -0
- package/src/ui/virtual-window.ts +88 -9
- package/src/utils/canvas-media.ts +72 -0
- package/src/utils/edit-display.ts +7 -2
- package/src/utils/element-selectors.ts +69 -0
- package/src/utils/link-target.ts +2 -2
- package/src/utils/studio-utils.ts +0 -10
- package/src/view.ts +15 -0
- package/src/workspace/pane-derive.ts +36 -14
- package/src/workspace/workspace.ts +15 -6
- package/styles/canvas.css +72 -467
- package/styles/forced-colors.css +48 -82
- package/styles/forced-colors.json +41 -0
- package/styles/inspector.css +2 -1301
- package/styles/overlays.css +96 -2823
- package/styles/panels.css +6 -1423
- package/styles/shell-frame.css +272 -0
- package/styles/shell-frame.json +227 -0
- package/styles/shell.css +0 -1532
- package/styles/tokens.css +65 -136
- package/styles/tokens.json +84 -0
- package/dist/chunks/Overlay.dev-723bv0df.js +0 -23
- package/dist/chunks/adapter-jkcyhgtr.js +0 -14
- package/dist/chunks/cf-settings-45fgyx8y.js +0 -21
- package/dist/chunks/components-zmx10t62.js +0 -21
- package/dist/chunks/content-source-t88vb2dr.js +0 -49
- package/dist/chunks/convert-to-repeater-dhw1nrz9.js +0 -268
- package/dist/chunks/editor-cptq5jp1.js +0 -37
- package/dist/chunks/entry-commands-6z6bhxg0.js +0 -46
- package/dist/chunks/extension-sections-3ydgjbdy.js +0 -311
- package/dist/chunks/file-ops-rskmhxyq.js +0 -48
- package/dist/chunks/files-0cratsr0.js +0 -92
- package/dist/chunks/flow-qbfgrpeh.js +0 -634
- package/dist/chunks/focus-trap.esm-ggawf1hy.js +0 -1024
- package/dist/chunks/focus-visible-6eg70z18.js +0 -167
- package/dist/chunks/format-host-tgcmfs4p.js +0 -43
- package/dist/chunks/fs-events-hrrg328g.js +0 -21
- package/dist/chunks/git-panel-0yywyk76.js +0 -58
- package/dist/chunks/index-zqxmqxmh.js +0 -109
- package/dist/chunks/jx-validate-8q2g05x1.js +0 -19
- package/dist/chunks/layers-panel-z3tqe5cd.js +0 -67
- package/dist/chunks/layers-q75tj2mf.js +0 -45
- package/dist/chunks/lit-html-j055mkh8.js +0 -22
- package/dist/chunks/monaco-buffer-dqw0xxpx.js +0 -25
- package/dist/chunks/notify-yjm79n4s.js +0 -30
- package/dist/chunks/parse-24d0gay3.js +0 -19
- package/dist/chunks/platform-ba1j1gbh.js +0 -16
- package/dist/chunks/publish-panel-54jvhskq.js +0 -28
- package/dist/chunks/quick-search-cgfmjwq5.js +0 -65
- package/dist/chunks/references-3qx8fkyp.js +0 -29
- package/dist/chunks/right-panel-cqp8bc4v.js +0 -46
- package/dist/chunks/section-registry-sx1ykvkw.js +0 -30
- package/dist/chunks/sp-overlay.dev-yztmtrs1.js +0 -18
- package/dist/chunks/sp-popover.dev-n2etmqdp.js +0 -9
- package/dist/chunks/sp-progress-circle.dev-hryhj0es.js +0 -15
- package/dist/chunks/sp-tooltip.dev-xcvpnqr0.js +0 -15
- package/dist/chunks/sp-tray.dev-tkbscm06.js +0 -199
- package/dist/chunks/studio-0a5qrh01.js +0 -3
- package/dist/chunks/studio-18j3bmcz.js +0 -14
- package/dist/chunks/studio-1hbqnt19.js +0 -1823
- package/dist/chunks/studio-4rzyrtjz.js +0 -426
- package/dist/chunks/studio-5rywrkxz.js +0 -1903
- package/dist/chunks/studio-7afd21nw.js +0 -67
- package/dist/chunks/studio-7nte2hj4.js +0 -613
- package/dist/chunks/studio-8jpzqk5s.js +0 -128
- package/dist/chunks/studio-8q517dfr.js +0 -24
- package/dist/chunks/studio-9c4k4vhv.js +0 -357
- package/dist/chunks/studio-9n4mrmnb.js +0 -184
- package/dist/chunks/studio-a0tswy0w.js +0 -58
- package/dist/chunks/studio-ahjfdy6e.js +0 -387
- package/dist/chunks/studio-ahnzd9rg.js +0 -23
- package/dist/chunks/studio-bw5dz6km.js +0 -608
- package/dist/chunks/studio-cb12yz9w.js +0 -15055
- package/dist/chunks/studio-d1ks410h.js +0 -175
- package/dist/chunks/studio-eqq1w638.js +0 -113
- package/dist/chunks/studio-ex8zyp98.js +0 -1813
- package/dist/chunks/studio-h4rxscfc.js +0 -10
- package/dist/chunks/studio-kyh9avvv.js +0 -28
- package/dist/chunks/studio-kyk2v92a.js +0 -659
- package/dist/chunks/studio-m3hwn7y1.js +0 -120
- package/dist/chunks/studio-mmv72a27.js +0 -4344
- package/dist/chunks/studio-n8b9wqwy.js +0 -291
- package/dist/chunks/studio-pdfjntbk.js +0 -6939
- package/dist/chunks/studio-qq6jym04.js +0 -53
- package/dist/chunks/studio-r1r7afxx.js +0 -1066
- package/dist/chunks/studio-rdx8jcxy.js +0 -83
- package/dist/chunks/studio-rn9ta2mz.js +0 -111
- package/dist/chunks/studio-t7qb9db8.js +0 -665
- package/dist/chunks/studio-tmc5emrw.js +0 -8
- package/dist/chunks/studio-txwkm6p9.js +0 -12
- package/dist/chunks/studio-v38hmvx1.js +0 -390
- package/dist/chunks/studio-vadzgkrz.js +0 -318
- package/dist/chunks/studio-wx5609xd.js +0 -341
- package/dist/chunks/studio-z6nw2ek2.js +0 -18
- package/dist/chunks/studio-zczps70q.js +0 -378
- package/dist/chunks/workspace-xpres40v.js +0 -89
- package/src/panels/activity-bar.ts +0 -251
- package/src/panels/panel-scheduler.ts +0 -219
- package/src/panels/style-inputs.ts +0 -237
- package/src/panels/target-line.ts +0 -274
- package/src/panels/welcome-screen.ts +0 -346
- package/src/ui/button-group.ts +0 -102
- package/src/ui/choice-field.ts +0 -72
- package/src/ui/field-row.ts +0 -249
- package/src/ui/formula-palette.ts +0 -213
- package/src/ui/icons.ts +0 -52
- package/src/ui/jx-theme.ts +0 -130
- package/src/ui/spectrum.ts +0 -340
- package/src/ui/value-selector.ts +0 -174
- package/src/ui/widgets.ts +0 -172
- /package/dist/chunks/{javascript-s56a8dpk.css → javascript-4abzjcy9.css} +0 -0
- /package/dist/chunks/{jsonMode-zr9sw0c7.css → jsonMode-vvmpmk34.css} +0 -0
- /package/dist/chunks/{monaco-setup-pav68602.css → monaco-setup-8vbyqnhr.css} +0 -0
- /package/dist/chunks/{tsMode-ef187txx.css → tsMode-hnxxb73h.css} +0 -0
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
* In-iframe render core — turns a fully-resolved document into live DOM via @jxsuite/runtime,
|
|
4
4
|
* stamping `data-jx-path` so the editor can map nodes back to document paths across the frame
|
|
5
5
|
* boundary. The parent does the heavy resolution (layout distribution, site-context, `$head`,
|
|
6
|
-
* components, edit-mode transforms) and posts the result; this core stays dependency-light
|
|
7
|
-
*
|
|
6
|
+
* components, edit-mode transforms) and posts the result; this core stays dependency-light
|
|
7
|
+
* (runtime
|
|
8
|
+
*
|
|
9
|
+
* - Reactivity + the pure path-mapping helpers) so the iframe bundle is small.
|
|
8
10
|
*
|
|
9
11
|
* Because the iframe is served from the real project origin, the runtime's verbatim
|
|
10
12
|
* `el.setAttribute("src", "/images/foo.jpg")` resolves natively — the fix that motivated the whole
|
|
@@ -19,6 +21,8 @@ import {
|
|
|
19
21
|
runScoped,
|
|
20
22
|
setCanvasAssetResolver,
|
|
21
23
|
setCanvasDelinkAnchors,
|
|
24
|
+
setCanvasDelinkCommands,
|
|
25
|
+
setCanvasDelinkPopovers,
|
|
22
26
|
setCanvasViewportTranspose,
|
|
23
27
|
setRootMedia,
|
|
24
28
|
setSkipAutoRequests,
|
|
@@ -26,10 +30,14 @@ import {
|
|
|
26
30
|
setStampPropBindings,
|
|
27
31
|
} from "@jxsuite/runtime";
|
|
28
32
|
import { resolveAssetRef } from "./asset-resolve";
|
|
29
|
-
import { classifyRenderNode, serializeJxPath } from "./path-mapping";
|
|
33
|
+
import { classifyRenderNode, jxPathSelector, serializeJxPath } from "./path-mapping";
|
|
34
|
+
/* No cycle: `iframe-position.ts` imports only `path-mapping` and a type. It already owns the
|
|
35
|
+
stamped-attribute lookup, escaping included, so a second query built here would be a second
|
|
36
|
+
answer to "which element is this path". */
|
|
37
|
+
import { elementForPath } from "./iframe-position";
|
|
30
38
|
import type { AssetContext } from "./asset-resolve";
|
|
31
39
|
import { SITE_STYLE_ID, buildSiteStyleCSS } from "@jxsuite/site/site-style";
|
|
32
|
-
import type { CanvasMode } from "./iframe-protocol";
|
|
40
|
+
import type { CanvasMode, WireDiffMarks } from "./iframe-protocol";
|
|
33
41
|
import type { JxDocument } from "@jxsuite/schema/types";
|
|
34
42
|
import type { PathMapCtx } from "./path-mapping";
|
|
35
43
|
|
|
@@ -125,6 +133,10 @@ export const EDIT_PLACEHOLDER_STYLE_ID = "jx-canvas-edit-css";
|
|
|
125
133
|
* both rules match the same element, and the emptiness test broke the specificity tie that used to
|
|
126
134
|
* decide it by source order.
|
|
127
135
|
*/
|
|
136
|
+
/*
|
|
137
|
+
* NOTE: this is a template literal, so a BACKTICK anywhere inside — including in a CSS comment —
|
|
138
|
+
* ends the string and produces a syntax error several lines later. Quote property names bare.
|
|
139
|
+
*/
|
|
128
140
|
export const EDIT_PLACEHOLDER_CSS = `
|
|
129
141
|
.empty-media-placeholder {
|
|
130
142
|
display: inline-block;
|
|
@@ -236,6 +248,270 @@ export function syncEditModeCss(doc: Document, mode: CanvasMode): void {
|
|
|
236
248
|
doc.head.append(style);
|
|
237
249
|
}
|
|
238
250
|
|
|
251
|
+
/** Id of the injected canvas UA-substitute stylesheet (the overlay rules). */
|
|
252
|
+
export const CANVAS_OVERLAY_STYLE_ID = "jx-canvas-overlay-css";
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* The rules that stand in for the UA behaviour a de-linked overlay has just lost.
|
|
256
|
+
*
|
|
257
|
+
* **This sheet's predicate IS the predicate of `setCanvasDelinkPopovers` /
|
|
258
|
+
* `setCanvasDelinkCommands` — every mode but Preview — and that is the invariant to keep.** An
|
|
259
|
+
* attribute renamed without its substitute rule is an overlay that can never be drawn: `popover`
|
|
260
|
+
* renamed to `data-jx-popover` with no replacement hide rule lays every CLOSED panel out as
|
|
261
|
+
* ordinary in-flow content and inflates the artboard, and a dialog stamped `data-jx-dialog-open`
|
|
262
|
+
* stays hidden behind the UA `dialog:not([open])` for good. These rules used to ship inside
|
|
263
|
+
* `EDIT_PLACEHOLDER_CSS`, which is installed for design/edit alone, so Stylebook and a git-diff
|
|
264
|
+
* side de-linked without them. A read-only artboard must draw an overlay exactly as the design
|
|
265
|
+
* canvas does — a git-diff pair is read side by side, and the artboard-growth argument below is
|
|
266
|
+
* about a content-sized frame, not about editing.
|
|
267
|
+
*/
|
|
268
|
+
/*
|
|
269
|
+
* NOTE: this is a template literal, so a BACKTICK anywhere inside — including in a CSS comment —
|
|
270
|
+
* ends the string and produces a syntax error several lines later. Quote property names bare.
|
|
271
|
+
*/
|
|
272
|
+
export const CANVAS_OVERLAY_CSS = `
|
|
273
|
+
/* The UA rule a de-popovered element lost, re-supplied at UA-EQUIVALENT PRECEDENCE.
|
|
274
|
+
|
|
275
|
+
The cascade layer is the mechanism and it is the whole point. An unlayered author declaration
|
|
276
|
+
beats a layered one whatever its specificity, and every declaration applyStyle emits is an
|
|
277
|
+
unlayered rule in an adopted sheet. That is exactly how author origin beats UA origin on the
|
|
278
|
+
shipped page, so the canvas reproduces the real cascade rather than an approximation of it.
|
|
279
|
+
|
|
280
|
+
This used to read "a base declaration is written as an INLINE style", which was true and is the
|
|
281
|
+
reason the guarantee survived the move: inline beat layered harder still, and unlayered beats it
|
|
282
|
+
by the same rule one step down. Jx emits no layer of its own, which is what keeps that true.
|
|
283
|
+
|
|
284
|
+
Deliberately NOT forced with a priority flag. A popover whose base rule sets display is laid out
|
|
285
|
+
on every page whether open or not; that is a real defect, @jxsuite/schema/overlays reports it as
|
|
286
|
+
base-display, and the canvas's job is to SHOW it, not to hide it behind a stronger rule. */
|
|
287
|
+
@layer jx-canvas-ua {
|
|
288
|
+
[data-jx-popover]:not([data-jx-popover-open]) {
|
|
289
|
+
display: none;
|
|
290
|
+
}
|
|
291
|
+
dialog[data-jx-dialog-open] {
|
|
292
|
+
display: block;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
/* SHOWN IN PLACE, and the position declaration is what makes that true.
|
|
296
|
+
|
|
297
|
+
Dropping the popover attribute drops the UA rule that made the panel fixed, so a panel that never
|
|
298
|
+
set position itself — every one in the fleet — lands in normal flow at its document position,
|
|
299
|
+
contributes to #jx-canvas-root's scrollHeight, and the host grows the artboard to fit it. That is
|
|
300
|
+
the whole geometry fix, and it is why an open panel is reachable at all.
|
|
301
|
+
|
|
302
|
+
The two alignment declarations are the other half, and they were found by measuring rather than
|
|
303
|
+
by reasoning. Every drawer in the fleet is declared inside its header's flex row, so in flow it
|
|
304
|
+
becomes a FLEX ITEM: align-items:center on the row centres a 904px panel on a 64px header and
|
|
305
|
+
half of it sits above the artboard at a negative offset, where it contributes nothing to the
|
|
306
|
+
scrollable overflow the host measures. Pinned to the start and refused any flex sizing, the same
|
|
307
|
+
panel hangs down from its own position and the artboard grows by its full height.
|
|
308
|
+
|
|
309
|
+
Forced, because a panel that DOES set position: fixed would otherwise keep it and be laid out
|
|
310
|
+
against the frame's own viewport — which in a de-linked mode is the document's full height, so a
|
|
311
|
+
drawer pinned with inset: 0 lands halfway down a long page and a short component frame clips it.
|
|
312
|
+
This is a presentation override for a canvas affordance, the same kind as the layout-region
|
|
313
|
+
dimming in EDIT_PLACEHOLDER_CSS, and it is NOT the same move as forcing display: that would hide
|
|
314
|
+
a real defect in the document (base-display), while this hides nothing — Preview renders the
|
|
315
|
+
panel natively, top layer and all. */
|
|
316
|
+
[data-jx-popover][data-jx-popover-open] {
|
|
317
|
+
position: relative !important;
|
|
318
|
+
inset: auto !important;
|
|
319
|
+
align-self: start !important;
|
|
320
|
+
flex: none !important;
|
|
321
|
+
outline: 1px dashed color-mix(in srgb, #808080 55%, transparent);
|
|
322
|
+
outline-offset: 2px;
|
|
323
|
+
}
|
|
324
|
+
[data-jx-popover][data-jx-popover-open]::before {
|
|
325
|
+
content: "POPOVER \\00B7 SHOWN IN PLACE";
|
|
326
|
+
position: absolute;
|
|
327
|
+
top: 0;
|
|
328
|
+
left: 0;
|
|
329
|
+
z-index: 2;
|
|
330
|
+
padding: 1px 5px;
|
|
331
|
+
border-radius: 0 0 3px 0;
|
|
332
|
+
background: color-mix(in srgb, #808080 78%, transparent);
|
|
333
|
+
color: #fff;
|
|
334
|
+
font: 700 9px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
335
|
+
letter-spacing: 0.08em;
|
|
336
|
+
pointer-events: none;
|
|
337
|
+
}
|
|
338
|
+
dialog[data-jx-dialog-open] {
|
|
339
|
+
position: relative !important;
|
|
340
|
+
inset: auto !important;
|
|
341
|
+
align-self: start !important;
|
|
342
|
+
flex: none !important;
|
|
343
|
+
outline: 1px dashed color-mix(in srgb, #808080 55%, transparent);
|
|
344
|
+
outline-offset: 2px;
|
|
345
|
+
}
|
|
346
|
+
dialog[data-jx-dialog-open]::before {
|
|
347
|
+
content: "DIALOG \\00B7 SHOWN IN PLACE";
|
|
348
|
+
position: absolute;
|
|
349
|
+
top: 0;
|
|
350
|
+
left: 0;
|
|
351
|
+
z-index: 2;
|
|
352
|
+
padding: 1px 5px;
|
|
353
|
+
border-radius: 0 0 3px 0;
|
|
354
|
+
background: color-mix(in srgb, #808080 78%, transparent);
|
|
355
|
+
color: #fff;
|
|
356
|
+
font: 700 9px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
357
|
+
letter-spacing: 0.08em;
|
|
358
|
+
pointer-events: none;
|
|
359
|
+
}
|
|
360
|
+
`;
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Keep the overlay stylesheet in sync with the render mode: present (idempotently) wherever the
|
|
364
|
+
* render de-links its overlays, removed for preview — which keeps the real `popover`/`open`
|
|
365
|
+
* attributes, so the real UA rules and the real top layer apply there.
|
|
366
|
+
*/
|
|
367
|
+
export function syncCanvasOverlayCss(doc: Document, mode: CanvasMode): void {
|
|
368
|
+
const existing = doc.head.querySelector(`#${CANVAS_OVERLAY_STYLE_ID}`);
|
|
369
|
+
if (mode === "preview") {
|
|
370
|
+
existing?.remove();
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
if (existing) {
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
const style = doc.createElement("style");
|
|
377
|
+
style.id = CANVAS_OVERLAY_STYLE_ID;
|
|
378
|
+
style.textContent = CANVAS_OVERLAY_CSS;
|
|
379
|
+
doc.head.append(style);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/** Id of the injected git-diff change-mark stylesheet. */
|
|
383
|
+
export const DIFF_MARK_STYLE_ID = "jx-canvas-diff-css";
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Change marks for the diff artboards.
|
|
387
|
+
*
|
|
388
|
+
* **Colour is never the only encoding.** Each kind carries a distinct `border-left-style` and a
|
|
389
|
+
* distinct gutter glyph, so the three states stay apart for a reader with a red/green deficiency in
|
|
390
|
+
* the ordinary render, not only under forced colours. That is also what makes the forced-colours
|
|
391
|
+
* block below cheap: it drops the wash and keeps style and glyph, which were already carrying the
|
|
392
|
+
* meaning.
|
|
393
|
+
*
|
|
394
|
+
* **The forced-colours block has to live HERE, in the frame.** `styles/forced-colors.css` is chrome
|
|
395
|
+
* and never reaches this document. The artboard's own opt-out (`forced-color-adjust: none` on
|
|
396
|
+
* `iframe.canvas-iframe`) is about not repainting the AUTHOR'S palette, which is why these rules
|
|
397
|
+
* add editor chrome through an attribute selector rather than restyling content.
|
|
398
|
+
*
|
|
399
|
+
* Hexes rather than custom properties for the reason `EDIT_PLACEHOLDER_CSS` gives: this is a
|
|
400
|
+
* separate document where the parent's tokens do not exist. The pair is chosen against the white
|
|
401
|
+
* artboard (`.canvas-panel-viewport` pins `background: white; color-scheme: light` whatever the
|
|
402
|
+
* chrome theme is), so the dark chrome tints `--success`/`--danger` carry would be illegible here.
|
|
403
|
+
*/
|
|
404
|
+
export const DIFF_MARK_CSS = `
|
|
405
|
+
[data-jx-diff] {
|
|
406
|
+
position: relative;
|
|
407
|
+
border-left-width: 3px;
|
|
408
|
+
border-left-color: currentColor;
|
|
409
|
+
}
|
|
410
|
+
[data-jx-diff]::before {
|
|
411
|
+
position: absolute;
|
|
412
|
+
top: 0;
|
|
413
|
+
left: -3px;
|
|
414
|
+
width: 3px;
|
|
415
|
+
content: "";
|
|
416
|
+
}
|
|
417
|
+
[data-jx-diff="added"] {
|
|
418
|
+
border-left-style: solid;
|
|
419
|
+
border-left-color: #0a7c42;
|
|
420
|
+
background: color-mix(in srgb, #0a7c42 12%, transparent);
|
|
421
|
+
}
|
|
422
|
+
[data-jx-diff="removed"] {
|
|
423
|
+
border-left-style: double;
|
|
424
|
+
border-left-color: #c9252d;
|
|
425
|
+
background: color-mix(in srgb, #c9252d 12%, transparent);
|
|
426
|
+
}
|
|
427
|
+
[data-jx-diff="modified-before"] {
|
|
428
|
+
border-left-style: dashed;
|
|
429
|
+
border-left-color: #c9252d;
|
|
430
|
+
background: color-mix(in srgb, #c9252d 8%, transparent);
|
|
431
|
+
}
|
|
432
|
+
[data-jx-diff="modified-after"] {
|
|
433
|
+
border-left-style: dashed;
|
|
434
|
+
border-left-color: #0a7c42;
|
|
435
|
+
background: color-mix(in srgb, #0a7c42 8%, transparent);
|
|
436
|
+
}
|
|
437
|
+
[data-jx-diff-within] {
|
|
438
|
+
border-left: 3px dotted color-mix(in srgb, #808080 60%, transparent);
|
|
439
|
+
}
|
|
440
|
+
@media (forced-colors: active) {
|
|
441
|
+
[data-jx-diff],
|
|
442
|
+
[data-jx-diff-within] {
|
|
443
|
+
background: none;
|
|
444
|
+
border-left-color: CanvasText;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
`;
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Keep the change-mark stylesheet in sync with whether this render carries marks.
|
|
451
|
+
*
|
|
452
|
+
* Gated on the MARKS, not on the mode. The decoration should depend on the payload the decoration
|
|
453
|
+
* needs: a git-diff artboard whose comparison is still loading has no marks to show, and a mode
|
|
454
|
+
* check would leave a stale sheet behind it.
|
|
455
|
+
*/
|
|
456
|
+
export function syncDiffCss(doc: Document, on: boolean): void {
|
|
457
|
+
const existing = doc.head.querySelector(`#${DIFF_MARK_STYLE_ID}`);
|
|
458
|
+
if (!on) {
|
|
459
|
+
existing?.remove();
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
if (existing) {
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
const style = doc.createElement("style");
|
|
466
|
+
style.id = DIFF_MARK_STYLE_ID;
|
|
467
|
+
style.textContent = DIFF_MARK_CSS;
|
|
468
|
+
doc.head.append(style);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Stamp this artboard's change marks onto the rendered tree.
|
|
473
|
+
*
|
|
474
|
+
* Replaces the whole set: every previous `data-jx-diff` comes off first, so a render carrying no
|
|
475
|
+
* marks clears the last one's rather than layering on it.
|
|
476
|
+
*
|
|
477
|
+
* **An unresolvable mark climbs to the nearest stamped ancestor** and lands there as
|
|
478
|
+
* `data-jx-diff-within` — "something inside here changed that cannot be drawn here". Not every
|
|
479
|
+
* document path reaches an element: a component's internals are created by its own
|
|
480
|
+
* `connectedCallback` and never pass through {@link makeStamper}, and only the first expanded row
|
|
481
|
+
* of a repeater carries the template's collapsed path. Dropping those marks silently would make the
|
|
482
|
+
* artboard disagree with a count the header states out loud; climbing keeps the change locatable
|
|
483
|
+
* and honest about its resolution.
|
|
484
|
+
*/
|
|
485
|
+
export function applyDiffMarks(container: HTMLElement, marks: WireDiffMarks | null): void {
|
|
486
|
+
for (const stale of container.querySelectorAll("[data-jx-diff], [data-jx-diff-within]")) {
|
|
487
|
+
if (stale instanceof HTMLElement) {
|
|
488
|
+
delete stale.dataset.jxDiff;
|
|
489
|
+
delete stale.dataset.jxDiffWithin;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
if (!marks?.length) {
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
for (const mark of marks) {
|
|
496
|
+
const exact = elementForPath(container, mark.path);
|
|
497
|
+
if (exact) {
|
|
498
|
+
exact.dataset.jxDiff = mark.kind;
|
|
499
|
+
continue;
|
|
500
|
+
}
|
|
501
|
+
/* Climb by whole `["children", i]` hops: a path's segments come in that pairing, so dropping
|
|
502
|
+
one at a time would ask for `[..., "children"]`, which is never an address. */
|
|
503
|
+
let { path } = mark;
|
|
504
|
+
while (path.length >= 2) {
|
|
505
|
+
path = path.slice(0, -2);
|
|
506
|
+
const ancestor = elementForPath(container, path);
|
|
507
|
+
if (ancestor) {
|
|
508
|
+
ancestor.dataset.jxDiffWithin = "";
|
|
509
|
+
break;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
239
515
|
/**
|
|
240
516
|
* Flag the canvas document as a preview shell, so `canvas.html`'s preview rules apply.
|
|
241
517
|
*
|
|
@@ -454,6 +730,71 @@ export function applyPreviewColorScheme(doc: Document, scheme: "light" | "dark"
|
|
|
454
730
|
}
|
|
455
731
|
}
|
|
456
732
|
|
|
733
|
+
/**
|
|
734
|
+
* Draw the popover at `path` open, and every other one closed.
|
|
735
|
+
*
|
|
736
|
+
* The canvas-only twin of `showPopover()` — one attribute, no top layer, no light dismiss, and
|
|
737
|
+
* idempotent, so the parent may post the same value as often as it likes. Re-applied after every
|
|
738
|
+
* render AND after every patch: an `attributes` op routes through `replaceSubtree`, which rebuilds
|
|
739
|
+
* the element and takes the attribute with it.
|
|
740
|
+
*
|
|
741
|
+
* A path naming a node that is not a de-popovered panel opens nothing rather than throwing — the
|
|
742
|
+
* frame's copy of a value the host may have computed against a document it has since changed.
|
|
743
|
+
*
|
|
744
|
+
* @param root The render container (`#jx-canvas-root`).
|
|
745
|
+
* @param path Serialized document path of the popover to open, or null to close them all.
|
|
746
|
+
* @docs studio/interface/canvas
|
|
747
|
+
*/
|
|
748
|
+
export function applyCanvasPopoverOpen(root: ParentNode, path: string | null): void {
|
|
749
|
+
for (const el of root.querySelectorAll("[data-jx-popover-open]")) {
|
|
750
|
+
delete (el as HTMLElement).dataset.jxPopoverOpen;
|
|
751
|
+
}
|
|
752
|
+
if (path === null) {
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
const target = root.querySelector(`[data-jx-popover]${jxPathSelector(path)}`);
|
|
756
|
+
if (target) {
|
|
757
|
+
(target as HTMLElement).dataset.jxPopoverOpen = "";
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
/**
|
|
762
|
+
* Mark the one `<dialog>` the canvas draws open — the dialog twin of
|
|
763
|
+
* {@link applyCanvasPopoverOpen}.
|
|
764
|
+
*
|
|
765
|
+
* @param root The render container (`#jx-canvas-root`).
|
|
766
|
+
* @param path Serialized document path of the dialog to open, or null to close them all.
|
|
767
|
+
* @docs studio/interface/canvas
|
|
768
|
+
*/
|
|
769
|
+
/*
|
|
770
|
+
* The dialog rules in the sheet above, explained here rather than inside the template literal,
|
|
771
|
+
* because a comment inside the string ships in iframe-entry.js.
|
|
772
|
+
*
|
|
773
|
+
* `dialog[data-jx-dialog-open] { display: block }` in the `jx-canvas-ua` layer is the dialog's
|
|
774
|
+
* other half: its authored `open` is renamed away, so the browser's own
|
|
775
|
+
* `dialog:not([open]) { display: none }` keeps every dialog closed, and this is the one rule that
|
|
776
|
+
* shows the dialog the canvas opened. Layered for the reason the popover rule gives: an author
|
|
777
|
+
* `display` on the base rule beats it, and that defect (@jxsuite/schema/dialogs' base-display) has
|
|
778
|
+
* to show on the canvas rather than hide behind a stronger rule.
|
|
779
|
+
*
|
|
780
|
+
* The forced `position` block is the popover's, by the same move: the UA's absolute positioning
|
|
781
|
+
* and modal top layer are gone with the renamed attributes, so the open dialog lays out in normal
|
|
782
|
+
* flow at its document position and the artboard grows to fit it. Preview renders it modally,
|
|
783
|
+
* backdrop and all.
|
|
784
|
+
*/
|
|
785
|
+
export function applyCanvasDialogOpen(root: ParentNode, path: string | null): void {
|
|
786
|
+
for (const el of root.querySelectorAll("[data-jx-dialog-open]")) {
|
|
787
|
+
delete (el as HTMLElement).dataset.jxDialogOpen;
|
|
788
|
+
}
|
|
789
|
+
if (path === null) {
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
const target = root.querySelector(`dialog${jxPathSelector(path)}`);
|
|
793
|
+
if (target) {
|
|
794
|
+
(target as HTMLElement).dataset.jxDialogOpen = "";
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
|
|
457
798
|
/** Inject the document's `$head` (link/meta/script) into the iframe's <head>, de-duped by href/src. */
|
|
458
799
|
export function injectHead(doc: JxDocument, assets: AssetContext | null = null): void {
|
|
459
800
|
const head = (doc as { $head?: HeadEntry[] }).$head;
|
|
@@ -500,7 +841,8 @@ export function injectHead(doc: JxDocument, assets: AssetContext | null = null):
|
|
|
500
841
|
|
|
501
842
|
/**
|
|
502
843
|
* Build the `onNodeCreated` hook that stamps `data-jx-path` (page content) or `data-jx-layout-path`
|
|
503
|
-
*
|
|
844
|
+
*
|
|
845
|
+
* - `data-jx-layout-file` (layout-originated nodes) on rendered nodes.
|
|
504
846
|
*/
|
|
505
847
|
export function makeStamper(ctx: PathMapCtx) {
|
|
506
848
|
/*
|
|
@@ -650,6 +992,12 @@ export async function renderResolvedDocument(opts: {
|
|
|
650
992
|
assets?: AssetContext | null;
|
|
651
993
|
/** This render may fetch automatic `Request` entries even outside preview (Data-panel Refresh). */
|
|
652
994
|
allowAutoRequests?: boolean;
|
|
995
|
+
/** Change marks for a git-diff artboard, in this side's own document coordinates. */
|
|
996
|
+
diffMarks?: WireDiffMarks | null;
|
|
997
|
+
/** Serialized path of the popover to draw open, or null/absent for none. */
|
|
998
|
+
popoverOpen?: string | null;
|
|
999
|
+
/** The dialog to draw open after this render, serialized; the twin of `popoverOpen`. */
|
|
1000
|
+
dialogOpen?: string | null;
|
|
653
1001
|
}): Promise<RenderHandle> {
|
|
654
1002
|
/* FIRST, before anything emits CSS or an attribute. The resolver is module-global in the runtime,
|
|
655
1003
|
so it is set on every render — including to null — or a previous document's context would
|
|
@@ -672,6 +1020,15 @@ export async function renderResolvedDocument(opts: {
|
|
|
672
1020
|
// De-link `<a href>` in design/edit so clicks select the anchor instead of navigating the iframe;
|
|
673
1021
|
// Preview keeps real links live (mirrors the server-function gate above).
|
|
674
1022
|
setCanvasDelinkAnchors(opts.mode !== "preview");
|
|
1023
|
+
/* De-popover in the same modes and for the same reason: an OPEN popover is in the top layer,
|
|
1024
|
+
whose containing block is the viewport — a fiction here, since the frame is sized to its own
|
|
1025
|
+
content — and which contributes to no ancestor's scrollable overflow, so the artboard could
|
|
1026
|
+
never grow to fit one. Preview keeps the real top layer, backdrop and all. */
|
|
1027
|
+
setCanvasDelinkPopovers(opts.mode !== "preview");
|
|
1028
|
+
/* And de-link invoker commands, `inert` and a dialog's `open` with them: a `show-modal` invoker
|
|
1029
|
+
would put its dialog in the top layer and make the rest of the page inert, which is the
|
|
1030
|
+
popover problem plus an unclickable document. The frame reports the click instead. */
|
|
1031
|
+
setCanvasDelinkCommands(opts.mode !== "preview");
|
|
675
1032
|
// Stamp `data-jx-bound-prop` on component-internal invertible text bindings in design/edit only —
|
|
676
1033
|
// The inline prop-edit affordance. Set every render so a preview/stylebook render in the same
|
|
677
1034
|
// Iframe clears it (page-level templates are inert in design/edit via prepareForEditMode, so only
|
|
@@ -680,8 +1037,14 @@ export async function renderResolvedDocument(opts: {
|
|
|
680
1037
|
applySiteStyle(opts.siteStyle, (opts.doc as { $media?: Record<string, string> }).$media ?? {});
|
|
681
1038
|
injectHead(opts.doc, assets);
|
|
682
1039
|
syncEditModeCss(opts.container.ownerDocument, opts.mode);
|
|
1040
|
+
// The substitute rules for the attributes the de-link above renamed. Same predicate as the
|
|
1041
|
+
// De-link, not the narrower design/edit one: a Stylebook specimen and a git-diff side rename
|
|
1042
|
+
// Their overlays too, and without this sheet a closed panel would lay out in flow and an open
|
|
1043
|
+
// Dialog could never be shown.
|
|
1044
|
+
syncCanvasOverlayCss(opts.container.ownerDocument, opts.mode);
|
|
683
1045
|
syncPreviewShell(opts.container.ownerDocument, opts.mode);
|
|
684
1046
|
syncStylebookCss(opts.container.ownerDocument, opts.mode);
|
|
1047
|
+
syncDiffCss(opts.container.ownerDocument, Boolean(opts.diffMarks?.length));
|
|
685
1048
|
// Seed the runtime's root $media before buildScope so a COMPONENT with its own `@--name` blocks
|
|
686
1049
|
// But no own `$media` resolves the breakpoint to its real query (the iframe path calls buildScope
|
|
687
1050
|
// Directly and never the runtime's `Jx()` entry, which is the only other place _rootMedia is set).
|
|
@@ -704,9 +1067,14 @@ export async function renderResolvedDocument(opts: {
|
|
|
704
1067
|
() => renderNode(opts.doc, $defs, { _path: [], onNodeCreated }) as HTMLElement,
|
|
705
1068
|
);
|
|
706
1069
|
opts.container.replaceChildren(el);
|
|
1070
|
+
applyCanvasPopoverOpen(opts.container, opts.popoverOpen ?? null);
|
|
1071
|
+
applyCanvasDialogOpen(opts.container, opts.dialogOpen ?? null);
|
|
707
1072
|
// Claim (or release) the editing host AFTER the tree lands, so the browser computes editability
|
|
708
1073
|
// Against the final DOM rather than an empty container.
|
|
709
1074
|
syncEditableRoot(opts.container, opts.mode);
|
|
1075
|
+
// Marks last, and for the same reason: they are resolved by querying stamped attributes, which
|
|
1076
|
+
// Only exist once the tree the stamper walked is actually in the container.
|
|
1077
|
+
applyDiffMarks(opts.container, opts.diffMarks ?? null);
|
|
710
1078
|
return {
|
|
711
1079
|
ctx: { defs: $defs, docBase: opts.docBase, mapperCtx: opts.mapperCtx, mode: opts.mode },
|
|
712
1080
|
dispose: stop,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/// <reference lib="dom" />
|
|
2
2
|
/**
|
|
3
3
|
* Iframe-realm slash-menu bridge — the inline-edit engine detects "/" and drives a DI'd
|
|
4
|
-
* {@link SlashController}; the real
|
|
5
|
-
*
|
|
4
|
+
* {@link SlashController}; the real host-realm menu can't render in the slim iframe bundle, so this
|
|
5
|
+
* controller proxies it across the postMessage bridge. It posts `slashShow` (with the edited
|
|
6
6
|
* element's IFRAME-VIEWPORT rect + the typed filter) / `slashDismiss`; the host shows the parent
|
|
7
7
|
* menu and posts back `slashSelect` / `slashDismissed`.
|
|
8
8
|
*
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* WeakMap, this stamps `data-jx-path` and tracks per-subtree effect scopes locally.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import { releaseElementStyles, renderNode, runScoped } from "@jxsuite/runtime";
|
|
15
15
|
import { getNodeAtPath } from "../state";
|
|
16
16
|
import { makeStamper } from "./iframe-render";
|
|
17
17
|
import { prepareForEditMode } from "../utils/edit-display";
|
|
@@ -60,8 +60,9 @@ export function renderSubtreeIframe(
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
|
-
* Release a removed/replaced subtree: stop the effect scopes rooted inside it and
|
|
64
|
-
*
|
|
63
|
+
* Release a removed/replaced subtree: stop the effect scopes rooted inside it and hand every
|
|
64
|
+
* element's rule set back to the runtime's stylesheet engine (otherwise its rules orphan in the
|
|
65
|
+
* iframe's adopted sheet).
|
|
65
66
|
*/
|
|
66
67
|
export function disposeSubtree(el: Element): void {
|
|
67
68
|
const targets: Element[] = [el, ...el.querySelectorAll("*")];
|
|
@@ -69,11 +70,7 @@ export function disposeSubtree(el: Element): void {
|
|
|
69
70
|
if (!(t instanceof HTMLElement)) {
|
|
70
71
|
continue;
|
|
71
72
|
}
|
|
72
|
-
|
|
73
|
-
if (tag) {
|
|
74
|
-
tag.remove();
|
|
75
|
-
elementStyleTags.delete(t);
|
|
76
|
-
}
|
|
73
|
+
releaseElementStyles(t);
|
|
77
74
|
const stop = elScope.get(t);
|
|
78
75
|
if (stop) {
|
|
79
76
|
stop();
|
|
@@ -13,6 +13,23 @@
|
|
|
13
13
|
|
|
14
14
|
import type { JxPath } from "../state";
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* A `[data-jx-path='…']` selector for a serialized path.
|
|
18
|
+
*
|
|
19
|
+
* Single quotes because the serialized path is JSON and only ever uses double ones; the two escapes
|
|
20
|
+
* cover the characters that could still break out of an attribute-value selector. Shared because
|
|
21
|
+
* two callers need the same string — `measureHits` locating a node to measure, and
|
|
22
|
+
* `applyCanvasPopoverOpen` locating one to flip — and a second copy of an escaping rule is a second
|
|
23
|
+
* chance to get an escape wrong.
|
|
24
|
+
*
|
|
25
|
+
* @param serialized A path already through {@link serializeJxPath}.
|
|
26
|
+
* @returns The attribute selector, without a leading tag or combinator.
|
|
27
|
+
*/
|
|
28
|
+
export function jxPathSelector(serialized: string): string {
|
|
29
|
+
const escaped = serialized.replaceAll("\\", String.raw`\\`).replaceAll("'", String.raw`\'`);
|
|
30
|
+
return `[data-jx-path='${escaped}']`;
|
|
31
|
+
}
|
|
32
|
+
|
|
16
33
|
/** Context the mapper needs, computed once per render by whoever prepared the document. */
|
|
17
34
|
export interface PathMapCtx {
|
|
18
35
|
canvasMode: string;
|
|
@@ -102,9 +119,14 @@ export function classifyRenderNode(path: JxPath, def: unknown, ctx: PathMapCtx):
|
|
|
102
119
|
}
|
|
103
120
|
}
|
|
104
121
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
122
|
+
/* Collapse repeater-perimeter template hops: for an array document path P, a render path of
|
|
123
|
+
`[...P, "children", 0, ...rest]` maps to `[...P, "map", ...rest]`. Loop for nested repeaters.
|
|
124
|
+
|
|
125
|
+
`arrayPaths` IS the mode test, and naming modes here as well was a second copy of it that
|
|
126
|
+
disagreed. Only the caller knows whether `prepareForEditMode` ran, and it says so by filling
|
|
127
|
+
this set; a non-empty set in a mode this list did not name meant the perimeters existed and the
|
|
128
|
+
collapse did not, so the stamped path pointed at a node the document has no address for. */
|
|
129
|
+
if (ctx.arrayPaths.size > 0) {
|
|
108
130
|
let changed = true;
|
|
109
131
|
while (changed) {
|
|
110
132
|
changed = false;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
2
|
+
/**
|
|
3
|
+
* Which popover a document path belongs to — the pure half of the open-on-selection rule.
|
|
4
|
+
*
|
|
5
|
+
* Separate from `popover-state.ts` because of who needs it. The command record in `canvas-utils.ts`
|
|
6
|
+
* has to answer "is there a popover here?" for its `enablement`, and `popover-state.ts` reaches
|
|
7
|
+
* `iframe-host.ts`, which reaches `canvas-utils.ts` — so importing the whole rule from the command
|
|
8
|
+
* file would close a cycle. Nothing here touches a frame, a channel or the DOM, which is also what
|
|
9
|
+
* makes it the easy half to test.
|
|
10
|
+
*
|
|
11
|
+
* @docs studio/interface/canvas
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { activeTab } from "../workspace/workspace";
|
|
15
|
+
import { getNodeAtPath } from "../state";
|
|
16
|
+
import { documentHasPopover, isPopover } from "@jxsuite/schema/overlays";
|
|
17
|
+
import { INVOKER_TAGS, POPOVER_TAGS } from "@jxsuite/ui";
|
|
18
|
+
import { primarySelection } from "../tabs/selection";
|
|
19
|
+
import type { JxMutableNode } from "@jxsuite/schema/types";
|
|
20
|
+
import type { JxPath } from "../state";
|
|
21
|
+
import type { Tab } from "../tabs/tab";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The nearest ancestor-or-self of `path` that declares `popover`, or null when there is none.
|
|
25
|
+
*
|
|
26
|
+
* Walks prefixes of the path rather than the tree, so it costs one `getNodeAtPath` per level and
|
|
27
|
+
* needs no parent pointers. A prefix that lands on a non-node (the `"children"` segment itself, an
|
|
28
|
+
* index into a repeater's `items`) simply is not a popover, so nothing here has to enumerate the
|
|
29
|
+
* segment vocabulary — which is what keeps it correct across `map` and `cases` hops for free.
|
|
30
|
+
*
|
|
31
|
+
* @param doc The document the path addresses.
|
|
32
|
+
* @param path The selected node's path.
|
|
33
|
+
* @returns The popover's path, or null.
|
|
34
|
+
*/
|
|
35
|
+
/**
|
|
36
|
+
* The kit's overlay elements, so one of them on the canvas counts as the popover it is. Their
|
|
37
|
+
* `popover` attribute lives in the DEFINITION, which the edited document never carries, so without
|
|
38
|
+
* this an author who drops one on a page could not open it on the canvas at all.
|
|
39
|
+
*/
|
|
40
|
+
const KIT_SCOPE = { invokerTags: INVOKER_TAGS, popoverTags: POPOVER_TAGS };
|
|
41
|
+
|
|
42
|
+
export function ancestorPopoverPath(
|
|
43
|
+
doc: JxMutableNode | null | undefined,
|
|
44
|
+
path: JxPath | null | undefined,
|
|
45
|
+
): JxPath | null {
|
|
46
|
+
if (!doc || !path) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
for (let end = path.length; end >= 0; end -= 1) {
|
|
50
|
+
const prefix = path.slice(0, end);
|
|
51
|
+
const node = getNodeAtPath(doc, prefix);
|
|
52
|
+
if (node && typeof node === "object" && isPopover(node, KIT_SCOPE)) {
|
|
53
|
+
return prefix;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* The popover a `canvas.setPopoverOpen` call means for `tab`, or null when there is none.
|
|
61
|
+
*
|
|
62
|
+
* An explicit `path` is taken at its word but still CHECKED — the palette, the assistant and the
|
|
63
|
+
* automation runner all reach the command, and a path that is not a popover must be refused rather
|
|
64
|
+
* than silently opening nothing. With no argument the answer is the popover the SELECTION is at or
|
|
65
|
+
* inside, which is what makes the command usable from a keystroke with nothing else stated.
|
|
66
|
+
*
|
|
67
|
+
* Takes the tab rather than reading the active one, so the command's `pane` argument decides which
|
|
68
|
+
* document is consulted: a split view can have a different popover open in each pane's tab.
|
|
69
|
+
*
|
|
70
|
+
* @param tab The tab to resolve against.
|
|
71
|
+
* @param explicit A path supplied by the caller, if any.
|
|
72
|
+
* @returns The popover's path, or null.
|
|
73
|
+
*/
|
|
74
|
+
export function popoverPathFor(tab: Tab, explicit?: JxPath): JxPath | null {
|
|
75
|
+
const doc = tab.doc.document as JxMutableNode | undefined;
|
|
76
|
+
if (!doc) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
if (explicit) {
|
|
80
|
+
const node = getNodeAtPath(doc, explicit);
|
|
81
|
+
return node && typeof node === "object" && isPopover(node, KIT_SCOPE) ? explicit : null;
|
|
82
|
+
}
|
|
83
|
+
return ancestorPopoverPath(doc, primarySelection(tab.session.selection));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Whether the focused document has any popover — what the command's `enablement` asks.
|
|
88
|
+
*
|
|
89
|
+
* A fact about the DOCUMENT, not about the selection. Gating on the selection looked tighter and
|
|
90
|
+
* was wrong: the palette, the assistant and a screenshot step all name a popover by path, and an
|
|
91
|
+
* enablement predicate cannot see the arguments, so it would have refused every one of them before
|
|
92
|
+
* the path was read. The specific refusal — "that path is not a popover" — belongs to the run,
|
|
93
|
+
* where the argument exists.
|
|
94
|
+
*
|
|
95
|
+
* Reading the focused tab is correct here and only here: enablement describes what would happen if
|
|
96
|
+
* you pressed Enter now, and that is the pane you are in. The command's `run` resolves its tab
|
|
97
|
+
* through `contextTab` instead, so a `pane` argument still decides the write. That split is why
|
|
98
|
+
* this lives here rather than in `canvas-utils.ts`, whose stage-geometry functions must never read
|
|
99
|
+
* the focused tab (`check-pane-singletons.ts` enforces it).
|
|
100
|
+
*
|
|
101
|
+
* @returns True when the focused document declares at least one popover.
|
|
102
|
+
*/
|
|
103
|
+
export function activeDocumentHasPopover(): boolean {
|
|
104
|
+
const doc = activeTab.value?.doc.document as JxMutableNode | undefined;
|
|
105
|
+
return doc ? documentHasPopover(doc, KIT_SCOPE) : false;
|
|
106
|
+
}
|