@jxsuite/studio 4.1.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-n6tfwnda.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-wcnt3r9g.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-vx9bhp1d.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-msd847zn.js → studio-25hkdrkw.js} +357 -86
- package/dist/chunks/studio-26d7myd1.js +258 -0
- package/dist/chunks/{studio-4r1pv6zf.js → studio-38emantv.js} +22 -5
- package/dist/chunks/studio-3gxv60tn.js +422 -0
- package/dist/chunks/{studio-fbf92ckf.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-1wagb550.js → studio-5523bpzt.js} +11 -11
- package/dist/chunks/{studio-x4qkdat5.js → studio-57mf66w2.js} +1749 -2481
- 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-ahn3pdgx.js → studio-79y5sz51.js} +52 -38
- package/dist/chunks/{studio-gcye7qka.js → studio-7e11jpa9.js} +21 -21
- 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-x813zp48.js → studio-arfpe389.js} +30 -30
- package/dist/chunks/{studio-trxrabqf.js → studio-az3zd49t.js} +475 -283
- package/dist/chunks/studio-cpvb2ed1.js +1171 -0
- package/dist/chunks/{studio-f3wqjtk5.js → studio-d0300636.js} +5076 -18
- 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-3bqpr0zh.js → studio-em9nw8eh.js} +299 -110
- 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-dm19q43r.js → studio-hhvs4sdg.js} +10 -10
- package/dist/chunks/{studio-q9jd1a60.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-2b946z26.js → studio-rkstz940.js} +3658 -6134
- 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-jkftxyvz.js → studio-s6z853aq.js} +5858 -2152
- package/dist/chunks/{studio-6yw4y3my.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-qjy2z9bv.js → studio-vz68yn9e.js} +32 -137
- package/dist/chunks/studio-wqpngpsk.js +174 -0
- package/dist/chunks/{studio-b55y6ewx.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 +1780 -667
- package/dist/studio.js +52819 -36480
- 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/index.html +1 -0
- package/package.json +18 -52
- package/src/about/about-modal.ts +72 -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 +943 -660
- package/src/files/json-layout.ts +474 -0
- 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/layout.ts +2 -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 +181 -252
- package/src/new-project/location-fields.ts +93 -160
- 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 -163
- 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 +106 -16
- 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 +134 -328
- package/src/services/a11y-report.ts +100 -43
- package/src/services/ai-command-tools.ts +468 -0
- 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/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 +6 -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 +1 -1
- package/src/settings/preferences-dialog.ts +350 -330
- 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 +22 -0
- package/src/ui/ai-credentials-form.ts +104 -100
- package/src/ui/ai-managed-connect.ts +54 -36
- package/src/ui/ai-model-picker.ts +75 -47
- package/src/ui/cf-account-picker.ts +76 -141
- 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 -1568
- package/styles/tokens.css +65 -136
- package/styles/tokens.json +84 -0
- package/dist/chunks/Overlay.dev-etqjwyf9.js +0 -23
- package/dist/chunks/adapter-jkcyhgtr.js +0 -14
- package/dist/chunks/cf-account-picker-en86v7x7.js +0 -163
- package/dist/chunks/cf-settings-45fgyx8y.js +0 -21
- package/dist/chunks/components-zmx10t62.js +0 -21
- package/dist/chunks/content-source-48xg86wj.js +0 -49
- package/dist/chunks/convert-to-repeater-43tfn7cs.js +0 -268
- package/dist/chunks/editor-cptq5jp1.js +0 -37
- package/dist/chunks/entry-commands-e63f1xc0.js +0 -46
- package/dist/chunks/extension-sections-txv08xxg.js +0 -311
- package/dist/chunks/file-ops-wbh4hhsx.js +0 -48
- package/dist/chunks/files-3kfkwhk4.js +0 -93
- package/dist/chunks/flow-qbfgrpeh.js +0 -634
- package/dist/chunks/focus-trap.esm-9t2drp0g.js +0 -1025
- package/dist/chunks/focus-visible-6eg70z18.js +0 -167
- package/dist/chunks/format-host-w16q81tf.js +0 -43
- package/dist/chunks/fs-events-hrrg328g.js +0 -21
- package/dist/chunks/git-panel-532whr1y.js +0 -59
- package/dist/chunks/index-zqxmqxmh.js +0 -109
- package/dist/chunks/jx-validate-8er6gbxy.js +0 -19
- package/dist/chunks/layers-panel-07hm7g5j.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-v9st96ja.js +0 -29
- package/dist/chunks/quick-search-zccjp6gv.js +0 -66
- package/dist/chunks/references-3qx8fkyp.js +0 -29
- package/dist/chunks/right-panel-vm3b6kwy.js +0 -46
- package/dist/chunks/section-registry-sx1ykvkw.js +0 -30
- package/dist/chunks/sp-overlay.dev-qgvhnxf4.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-4sastdnw.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-0bq6eh7v.js +0 -12
- package/dist/chunks/studio-18j3bmcz.js +0 -14
- package/dist/chunks/studio-1ngbejft.js +0 -181
- package/dist/chunks/studio-4b5z1x43.js +0 -424
- package/dist/chunks/studio-4n2b5gzb.js +0 -357
- package/dist/chunks/studio-4rzyrtjz.js +0 -426
- package/dist/chunks/studio-5fx3g9jg.js +0 -4325
- package/dist/chunks/studio-5myknm0a.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-950k0dx6.js +0 -6939
- package/dist/chunks/studio-9n4mrmnb.js +0 -184
- package/dist/chunks/studio-a0tswy0w.js +0 -58
- package/dist/chunks/studio-ahnzd9rg.js +0 -23
- package/dist/chunks/studio-cmb03bg5.js +0 -13890
- package/dist/chunks/studio-d1ks410h.js +0 -175
- package/dist/chunks/studio-ef49pnzx.js +0 -387
- package/dist/chunks/studio-eqq1w638.js +0 -113
- package/dist/chunks/studio-ew0djmhg.js +0 -341
- package/dist/chunks/studio-gfgb8pe6.js +0 -1652
- package/dist/chunks/studio-h4rxscfc.js +0 -10
- package/dist/chunks/studio-jc994dnr.js +0 -1066
- package/dist/chunks/studio-kyh9avvv.js +0 -28
- package/dist/chunks/studio-m3hwn7y1.js +0 -120
- package/dist/chunks/studio-mtfnaqs9.js +0 -659
- package/dist/chunks/studio-n6j9t10q.js +0 -318
- package/dist/chunks/studio-n8b9wqwy.js +0 -291
- package/dist/chunks/studio-qcy05dp8.js +0 -1743
- package/dist/chunks/studio-qq6jym04.js +0 -53
- 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-z6nw2ek2.js +0 -18
- package/dist/chunks/studio-zczps70q.js +0 -378
- package/dist/chunks/studio-zqazsct2.js +0 -1823
- package/dist/chunks/workspace-fjx52ryv.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
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* dispatches to manage/settings/source/edit/design/preview rendering paths.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
import { ref } from "lit-html/directives/ref.js";
|
|
7
|
+
import { render as litRender, nothing } from "lit-html";
|
|
9
8
|
import type * as monaco from "monaco-editor";
|
|
9
|
+
import type { WireDiffMarks } from "./iframe-protocol";
|
|
10
10
|
import type * as Y from "yjs";
|
|
11
11
|
import { loadedMonaco, loadMonaco, mountStillWanted } from "../services/monaco-lazy";
|
|
12
12
|
|
|
@@ -33,12 +33,18 @@ import {
|
|
|
33
33
|
stringProperty,
|
|
34
34
|
} from "../commands/command-args";
|
|
35
35
|
import { collabSourceContext } from "../collab/collab-session";
|
|
36
|
+
import { buildChangeMap } from "./diff-marks";
|
|
37
|
+
import type { ChangeMap, ChangeMark } from "./diff-marks";
|
|
38
|
+
import { clearDiffView, diffViewOf, setDiffChangeMap } from "./diff-view";
|
|
39
|
+
import { canRenderComparison } from "../panels/git-diff-open";
|
|
40
|
+
import { renderDiffToolbar, setDiffRepaint, setDiffToolbarHost } from "./diff-toolbar";
|
|
36
41
|
import { attachCursorStyles } from "../collab/monaco-cursors";
|
|
37
42
|
import type { AwarenessLike } from "../collab/monaco-cursors";
|
|
38
43
|
import type { BindingAwareness } from "../collab/monaco-binding";
|
|
39
44
|
import { monacoTheme, shell } from "../shell";
|
|
40
45
|
import { parseSourceForPath } from "../files/file-ops";
|
|
41
46
|
import { serializeDocument } from "../files/serialize-document";
|
|
47
|
+
import { parseJsonDocument, serializeJson } from "../files/json-layout";
|
|
42
48
|
import { detachGridPanel, gridPanelMounted, renderGridMode } from "../grid/grid-panel";
|
|
43
49
|
import { detachLibraryPane, libraryPaneMounted, renderLibraryMode } from "../browse/library-pane";
|
|
44
50
|
import { detachEntryPane, entryPaneMounted, renderEntryMode } from "../content/entry-editor";
|
|
@@ -56,24 +62,31 @@ import {
|
|
|
56
62
|
bufferWrites,
|
|
57
63
|
commitBufferWrites,
|
|
58
64
|
} from "../services/monaco-buffer";
|
|
59
|
-
import { modelUriFor } from "../services/model-uri";
|
|
60
|
-
import { renderWelcome } from "../
|
|
61
|
-
import {
|
|
62
|
-
import {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
import { diffModelUrisFor, modelUriFor, monacoLangForPath } from "../services/model-uri";
|
|
66
|
+
import { renderWelcome } from "../surfaces/welcome";
|
|
67
|
+
import { emptyState } from "../surfaces/empty-state";
|
|
68
|
+
import { attachDocumentHeaderHost, hasDocumentHeader } from "../panels/frontmatter-panel";
|
|
69
|
+
import { mountCanvasStage } from "../surfaces/canvas-stage";
|
|
70
|
+
import type {
|
|
71
|
+
CanvasStageActions,
|
|
72
|
+
CanvasStageHandle,
|
|
73
|
+
CanvasStageView,
|
|
74
|
+
} from "../surfaces/canvas-stage";
|
|
75
|
+
import type { CanvasPanelEntry } from "./canvas-utils";
|
|
67
76
|
import { projectState } from "../state";
|
|
68
77
|
import {
|
|
78
|
+
activateCanvasPanel,
|
|
69
79
|
applyEditZoom,
|
|
70
80
|
applyTransform,
|
|
71
|
-
|
|
81
|
+
bindCanvasPanels,
|
|
82
|
+
canvasPanelEntry,
|
|
72
83
|
fitOnCanvasEntry,
|
|
73
84
|
observeCenterUntilStable,
|
|
74
85
|
updateActivePanelHeaders,
|
|
75
86
|
} from "./canvas-utils";
|
|
76
87
|
import { parseMediaEntries } from "../utils/canvas-media";
|
|
88
|
+
import { clearEditWidth, resolveEditColumnWidth } from "./edit-width";
|
|
89
|
+
import { mountEditWidthHandle } from "./edit-width-drag";
|
|
77
90
|
import { getEffectiveMedia, getEffectiveStyle } from "../site-context";
|
|
78
91
|
import {
|
|
79
92
|
adoptCanvasPreviewMode,
|
|
@@ -82,6 +95,7 @@ import {
|
|
|
82
95
|
mountIframeCanvas,
|
|
83
96
|
postApplyFormat,
|
|
84
97
|
postOpenSlash,
|
|
98
|
+
postRedefineElementToLiveHosts,
|
|
85
99
|
postStyleUpdateToStylebookHosts,
|
|
86
100
|
releaseCanvasHosts,
|
|
87
101
|
} from "./iframe-host";
|
|
@@ -104,7 +118,6 @@ import { activeRegistry } from "../commands/active-registry";
|
|
|
104
118
|
import { notify } from "../services/notify";
|
|
105
119
|
import * as overlaysPanel from "../panels/overlays";
|
|
106
120
|
|
|
107
|
-
import type { TemplateResult } from "lit-html";
|
|
108
121
|
import type { CanvasPanel, GitDiffState } from "../types";
|
|
109
122
|
import type { AnyCommand, CommandRegistry } from "../commands/registry";
|
|
110
123
|
import type { JxMutableNode } from "@jxsuite/schema/types";
|
|
@@ -152,14 +165,16 @@ async function sourceContent(tab: Tab) {
|
|
|
152
165
|
if (formatByName(tab.doc.sourceFormat)) {
|
|
153
166
|
return serializeDocument(tab);
|
|
154
167
|
}
|
|
155
|
-
|
|
168
|
+
// The file's own layout (`files/json-layout.ts`), so the buffer shows the bytes a save writes and
|
|
169
|
+
// A commit from it reads the same layout back — what `serializeDocument`'s JSON branch does.
|
|
170
|
+
return serializeJson(tab.doc.document, tab.doc.layout ?? null);
|
|
156
171
|
}
|
|
157
172
|
|
|
158
173
|
// Single-RAF scheduling; concurrent schedule requests within the same frame are deduped.
|
|
159
174
|
//
|
|
160
175
|
/* Two nested rAFs used to make the canvas render "yield to higher-priority panel paints first".
|
|
161
|
-
Panels have since
|
|
162
|
-
bought nothing and put a hard ~32 ms floor under every escalated edit — canvas-patcher's
|
|
176
|
+
Panels have since stopped repainting their own chrome at all (the docks are Jx documents), so
|
|
177
|
+
the second frame bought nothing and put a hard ~32 ms floor under every escalated edit — canvas-patcher's
|
|
163
178
|
escalateToFullRender routes through here. */
|
|
164
179
|
/*
|
|
165
180
|
* One pending frame PER PANE. A shared id would have let the pane that scheduled first swallow the
|
|
@@ -215,45 +230,153 @@ function hardClearCanvasWrap(canvasWrap: HTMLElement) {
|
|
|
215
230
|
}
|
|
216
231
|
|
|
217
232
|
/**
|
|
218
|
-
*
|
|
233
|
+
* Where each stage's non-artboard hosts landed, keyed by part (and by the static mark that tells
|
|
234
|
+
* two of one part apart: a handle's side, a card's placement).
|
|
219
235
|
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
* has already been bound. Connectivity is the fact that settles it: only a host that really left
|
|
224
|
-
* the document releases the card.
|
|
236
|
+
* Per STAGE rather than per module, for the reason every other field on `CanvasSurface` is: two
|
|
237
|
+
* panes each have a Monaco host and a card slot, and one slot would hand the second pane's stage
|
|
238
|
+
* the first pane's editor.
|
|
225
239
|
*/
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
240
|
+
const _stageHosts = new WeakMap<CanvasSurface, Map<string, HTMLElement>>();
|
|
241
|
+
|
|
242
|
+
/** The artboards the last pass described, so a header's click can resolve one. */
|
|
243
|
+
const _stageEntries = new WeakMap<CanvasSurface, CanvasPanelEntry[]>();
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* One stable action record per stage.
|
|
247
|
+
*
|
|
248
|
+
* Stable because the document reads it ONCE, when it mounts, and the mount outlives every repaint:
|
|
249
|
+
* a record rebuilt per pass would leave the header clicking through to the first pass's artboards
|
|
250
|
+
* for the life of the stage. Both members close over the surface and read the pass's state through
|
|
251
|
+
* the two maps above, which is what makes one record correct forever.
|
|
252
|
+
*/
|
|
253
|
+
const _stageActions = new WeakMap<CanvasSurface, CanvasStageActions>();
|
|
254
|
+
|
|
255
|
+
/** This stage's host map, created on first use. */
|
|
256
|
+
function stageHosts(surface: CanvasSurface): Map<string, HTMLElement> {
|
|
257
|
+
let hosts = _stageHosts.get(surface);
|
|
258
|
+
if (!hosts) {
|
|
259
|
+
hosts = new Map();
|
|
260
|
+
_stageHosts.set(surface, hosts);
|
|
241
261
|
}
|
|
242
|
-
return
|
|
262
|
+
return hosts;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/** The node this stage drew for a part, or null when this frame draws none. */
|
|
266
|
+
function stageHost(surface: CanvasSurface, part: string): HTMLElement | null {
|
|
267
|
+
return _stageHosts.get(surface)?.get(part) ?? null;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/** This stage's action record — see {@link _stageActions}. */
|
|
271
|
+
function stageActions(surface: CanvasSurface): CanvasStageActions {
|
|
272
|
+
let actions = _stageActions.get(surface);
|
|
273
|
+
if (actions) {
|
|
274
|
+
return actions;
|
|
275
|
+
}
|
|
276
|
+
actions = {
|
|
277
|
+
host: (part, element, detail) => {
|
|
278
|
+
stageHosts(surface).set(detail ? `${part}:${detail}` : part, element);
|
|
279
|
+
if (part === "panzoom") {
|
|
280
|
+
surface.panzoomWrap = element;
|
|
281
|
+
} else if (part === "doc-header") {
|
|
282
|
+
attachDocumentHeaderHost(surface.paneId, element);
|
|
283
|
+
} else if (part === "diff-toolbar") {
|
|
284
|
+
setDiffToolbarHost(surface.paneId, element);
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
pickPanel: (key) => activateCanvasPanel(_stageEntries.get(surface) ?? [], key),
|
|
288
|
+
};
|
|
289
|
+
_stageActions.set(surface, actions);
|
|
290
|
+
return actions;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Draw this pane's stage, and settle once its artboards are in the page.
|
|
295
|
+
*
|
|
296
|
+
* **The mount is kept, and the view is written into it.** Every artboard owns a live iframe holding
|
|
297
|
+
* a rendered document, so keeping the stage across a content-only repaint is the difference between
|
|
298
|
+
* a repaint and a reload — the same guarantee lit's positional diffing gave, from a keyed array
|
|
299
|
+
* that follows a breakpoint's NAME rather than its index. {@link detachCanvasStage} is what ends a
|
|
300
|
+
* mount, and it runs on a real mode transition, which is exactly when the structure on the stage
|
|
301
|
+
* stops being the stage's.
|
|
302
|
+
*
|
|
303
|
+
* **Nothing may read an artboard's DOM on the next line.** A mapped array reconciles on a microtask
|
|
304
|
+
* (`surfaces/canvas-stage.ts` says why), so the records are filled here, behind the promise, and
|
|
305
|
+
* every caller's geometry hangs off it.
|
|
306
|
+
*
|
|
307
|
+
* @param {CanvasSurface} surface
|
|
308
|
+
* @param {CanvasStageView} view
|
|
309
|
+
* @param {CanvasPanelEntry[]} entries - The artboards `view.panels` describes, in the same order
|
|
310
|
+
* @returns {Promise<void>}
|
|
311
|
+
*/
|
|
312
|
+
function drawStage(
|
|
313
|
+
surface: CanvasSurface,
|
|
314
|
+
view: CanvasStageView,
|
|
315
|
+
entries: CanvasPanelEntry[],
|
|
316
|
+
): Promise<CanvasStageHandle | null> {
|
|
317
|
+
_stageEntries.set(surface, entries);
|
|
318
|
+
/* There is no card-host release here, and there must not be one: `renderCanvasImpl` already
|
|
319
|
+
releases it for EVERY mode that draws no header, one branch above this one. A second answer to
|
|
320
|
+
the same question is how the two drift — and this one would answer only for the frames that
|
|
321
|
+
reach a stage, leaving grid, library, entry, media and settings to the first. */
|
|
322
|
+
const standing = surface.stage;
|
|
323
|
+
const stage = standing ?? mountCanvasStage(surface.wrap, view, stageActions(surface));
|
|
324
|
+
surface.stage = stage;
|
|
325
|
+
return (standing ? stage.update(view) : stage.ready).then(() => {
|
|
326
|
+
/* NULL means "this stage is gone", and it is the ONLY staleness this seam answers. A second
|
|
327
|
+
pass in the same mode shares the handle and passes here, which is deliberate: its artboards
|
|
328
|
+
still mount, under their own (now stale) generation, and the FRAME drops them — the contract
|
|
329
|
+
`passGen` exists for. What must never run is work against a stage a mode transition has
|
|
330
|
+
already disposed, whose hosts are released and whose records would bind to nothing. */
|
|
331
|
+
if (surface.stage !== stage) {
|
|
332
|
+
return null;
|
|
333
|
+
}
|
|
334
|
+
bindCanvasPanels(entries, stage);
|
|
335
|
+
return stage;
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* The two frames that hold no artboards: one Monaco filling the stage, with or without the Compare
|
|
341
|
+
* bar over it. Written once because the difference between them is a lead and a part.
|
|
342
|
+
*
|
|
343
|
+
* @param {"source" | "code"} frame
|
|
344
|
+
* @returns {CanvasStageView}
|
|
345
|
+
*/
|
|
346
|
+
function editorStageView(frame: "source" | "code"): CanvasStageView {
|
|
347
|
+
return {
|
|
348
|
+
columnHeader: "hidden",
|
|
349
|
+
frame,
|
|
350
|
+
framePart: "panzoom",
|
|
351
|
+
frameVars: "",
|
|
352
|
+
handles: "hidden",
|
|
353
|
+
hug: false,
|
|
354
|
+
innerPart: "boards",
|
|
355
|
+
lead: frame === "code" ? "toolbar" : "none",
|
|
356
|
+
panels: [],
|
|
357
|
+
};
|
|
243
358
|
}
|
|
244
359
|
|
|
245
360
|
/**
|
|
246
|
-
*
|
|
361
|
+
* Release this pane's stage document.
|
|
247
362
|
*
|
|
248
|
-
*
|
|
249
|
-
*
|
|
250
|
-
*
|
|
363
|
+
* Called on a real mode transition and on a full reset — the two moments the structure standing on
|
|
364
|
+
* the stage stops being the stage's. The two hosts that are handed to another module go WITH it: a
|
|
365
|
+
* card slot or a Compare bar pointing at a detached node is a surface that draws into nothing and
|
|
366
|
+
* never says so.
|
|
251
367
|
*
|
|
252
|
-
* @param {
|
|
253
|
-
* @returns {TemplateResult}
|
|
368
|
+
* @param {CanvasSurface} surface
|
|
254
369
|
*/
|
|
255
|
-
function
|
|
256
|
-
|
|
370
|
+
function detachCanvasStage(surface: CanvasSurface): void {
|
|
371
|
+
if (!surface.stage) {
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
surface.stage.dispose();
|
|
375
|
+
surface.stage = null;
|
|
376
|
+
_stageHosts.delete(surface);
|
|
377
|
+
_stageEntries.delete(surface);
|
|
378
|
+
attachDocumentHeaderHost(surface.paneId, null);
|
|
379
|
+
setDiffToolbarHost(surface.paneId, null);
|
|
257
380
|
}
|
|
258
381
|
|
|
259
382
|
/**
|
|
@@ -366,6 +489,131 @@ function disposeSourceEditor(surface: CanvasSurface): void {
|
|
|
366
489
|
surface.monacoEditor = null;
|
|
367
490
|
}
|
|
368
491
|
|
|
492
|
+
/**
|
|
493
|
+
* Tear down a comparison's Code view.
|
|
494
|
+
*
|
|
495
|
+
* **Both models, explicitly.** Monaco never disposes models a caller created, and a leaked model
|
|
496
|
+
* keeps its URI claimed — which is the same throw one mount later, on a stage that looks empty
|
|
497
|
+
* rather than broken.
|
|
498
|
+
*
|
|
499
|
+
* **No `commitBufferWrites`.** `disposeSourceEditor` calls it because a source buffer can hold
|
|
500
|
+
* unsaved text; a comparison holds two read-only texts, one of which is a git object with no place
|
|
501
|
+
* on disk to be written back to. There is nothing to flush, which is the same reason this editor is
|
|
502
|
+
* deliberately absent from `buffersForTab`.
|
|
503
|
+
*/
|
|
504
|
+
function disposeDiffEditor(surface: CanvasSurface): void {
|
|
505
|
+
const editor = surface.monacoDiffEditor;
|
|
506
|
+
if (!editor) {
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
const model = editor.getModel();
|
|
510
|
+
editor.setModel(null);
|
|
511
|
+
model?.original.dispose();
|
|
512
|
+
model?.modified.dispose();
|
|
513
|
+
editor.dispose();
|
|
514
|
+
surface.monacoDiffEditor = null;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
/**
|
|
518
|
+
* Mount the comparison's Monaco diff editor: HEAD on the left, the working copy on the right.
|
|
519
|
+
*
|
|
520
|
+
* This is {@link mountSourceEditor} minus everything about writing — no change handler, no
|
|
521
|
+
* debounce, no collab binding. **The collab lock in particular is never entered**: `enter()` flips
|
|
522
|
+
* the room's canonical lock to "source" and freezes structural editing for every peer, and doing
|
|
523
|
+
* that to show somebody a read-only comparison would freeze a live co-editing session on a gesture
|
|
524
|
+
* nobody made.
|
|
525
|
+
*
|
|
526
|
+
* The post-await guard is the one `mountSourceEditor`'s comment explains at length, and it is not
|
|
527
|
+
* belt-and-braces here either: `renderCanvasImpl` writes `surface.prevCanvasMode` BEFORE this runs,
|
|
528
|
+
* so a second synchronous render inside the 12.6 MB cold load sees `modeChanged === false` and a
|
|
529
|
+
* still-null slot, falls through, and mounts again — and the second `createModel` claims a URI the
|
|
530
|
+
* first registered, which real Monaco throws on. Asked before `createModel`, for that reason.
|
|
531
|
+
*
|
|
532
|
+
* A RETARGET is the second, independent race, and `mountStillWanted` cannot catch it: it answers
|
|
533
|
+
* false when the slot is already filled, so a comparison switching to a different file would keep
|
|
534
|
+
* the old editor and its claimed URIs. That one is disposed synchronously, before the await.
|
|
535
|
+
*/
|
|
536
|
+
/**
|
|
537
|
+
* Whether this pane draws the comparison as TEXT.
|
|
538
|
+
*
|
|
539
|
+
* One definition, because two callers must never disagree about it: the render branch chooses which
|
|
540
|
+
* half to build, and the mount's post-await guard re-asks whether that half is still wanted. They
|
|
541
|
+
* were two spellings — the branch said "not renderable OR the author chose Code", the guard said
|
|
542
|
+
* only "the author chose Code" — so for a file with no visual half the branch built the Code
|
|
543
|
+
* container and the guard then refused to mount into it. An empty stage, no error, and a toolbar
|
|
544
|
+
* correctly describing an editor that was never there.
|
|
545
|
+
*/
|
|
546
|
+
/**
|
|
547
|
+
* One artboard's marks, with a modification given the face that side wears.
|
|
548
|
+
*
|
|
549
|
+
* {@link ChangeMap} names a modification once, semantically; the two artboards draw it as the before
|
|
550
|
+
* and the after. The split happens here because this is the only place that knows which document
|
|
551
|
+
* each mark set is about to be painted on.
|
|
552
|
+
*/
|
|
553
|
+
function sideMarks(
|
|
554
|
+
marks: readonly ChangeMark[] | undefined,
|
|
555
|
+
modified: "modified-before" | "modified-after",
|
|
556
|
+
): WireDiffMarks | null {
|
|
557
|
+
return (
|
|
558
|
+
marks?.map((mark) => ({
|
|
559
|
+
kind: mark.kind === "modified" ? modified : mark.kind,
|
|
560
|
+
path: mark.path,
|
|
561
|
+
})) ?? null
|
|
562
|
+
);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
function diffShowsCode(paneId: string, filePath: string): boolean {
|
|
566
|
+
return !canRenderComparison(filePath) || diffViewOf(paneId) === "code";
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
async function mountDiffEditor(
|
|
570
|
+
surface: CanvasSurface,
|
|
571
|
+
container: Element,
|
|
572
|
+
state: GitDiffState,
|
|
573
|
+
): Promise<void> {
|
|
574
|
+
const { paneId } = surface;
|
|
575
|
+
const key = state.filePath;
|
|
576
|
+
if (surface.monacoDiffEditor && surface.monacoDiffEditor._diffKey !== key) {
|
|
577
|
+
disposeDiffEditor(surface);
|
|
578
|
+
}
|
|
579
|
+
const monaco = await loadMonaco();
|
|
580
|
+
if (
|
|
581
|
+
!mountStillWanted(
|
|
582
|
+
container,
|
|
583
|
+
surface.monacoDiffEditor,
|
|
584
|
+
() => canvasModeOfPane(paneId) === "git-diff" && diffShowsCode(paneId, key),
|
|
585
|
+
)
|
|
586
|
+
) {
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
const uris = diffModelUrisFor(paneId, key || "document.json");
|
|
590
|
+
const lang = monacoLangForPath(key || "document.json");
|
|
591
|
+
const original = monaco.editor.createModel(
|
|
592
|
+
state.originalContent || "",
|
|
593
|
+
lang,
|
|
594
|
+
monaco.Uri.parse(uris.head),
|
|
595
|
+
);
|
|
596
|
+
const modified = monaco.editor.createModel(
|
|
597
|
+
state.currentContent || "",
|
|
598
|
+
lang,
|
|
599
|
+
monaco.Uri.parse(uris.work),
|
|
600
|
+
);
|
|
601
|
+
const editor = monaco.editor.createDiffEditor(container as HTMLElement, {
|
|
602
|
+
automaticLayout: true,
|
|
603
|
+
fontFamily: "'JetBrains Mono', 'SF Mono', 'Fira Code', 'Consolas', monospace",
|
|
604
|
+
fontSize: 12,
|
|
605
|
+
minimap: { enabled: false },
|
|
606
|
+
originalEditable: false,
|
|
607
|
+
readOnly: true,
|
|
608
|
+
renderSideBySide: true,
|
|
609
|
+
scrollBeyondLastLine: false,
|
|
610
|
+
theme: monacoTheme(),
|
|
611
|
+
}) as NonNullable<CanvasSurface["monacoDiffEditor"]>;
|
|
612
|
+
editor.setModel({ modified, original });
|
|
613
|
+
editor._diffKey = key;
|
|
614
|
+
surface.monacoDiffEditor = editor;
|
|
615
|
+
}
|
|
616
|
+
|
|
369
617
|
function resetCanvasView(surface: CanvasSurface) {
|
|
370
618
|
const canvasWrap = surface.wrap;
|
|
371
619
|
const { paneId } = surface;
|
|
@@ -376,6 +624,7 @@ function resetCanvasView(surface: CanvasSurface) {
|
|
|
376
624
|
detachSettingsPane(paneId);
|
|
377
625
|
disposeSourceCollab(surface);
|
|
378
626
|
disposeSourceEditor(surface);
|
|
627
|
+
disposeDiffEditor(surface);
|
|
379
628
|
if (surface.centerObserver) {
|
|
380
629
|
surface.centerObserver.disconnect();
|
|
381
630
|
surface.centerObserver = null;
|
|
@@ -598,7 +847,11 @@ async function mountSourceEditor(
|
|
|
598
847
|
}
|
|
599
848
|
} else if (lang === "json") {
|
|
600
849
|
try {
|
|
601
|
-
|
|
850
|
+
// The buffer's text is the author's own layout now — the objects they opened up or
|
|
851
|
+
// Closed, the blank lines they left — so it is what the next save preserves.
|
|
852
|
+
const parsed = parseJsonDocument(sourceEditor.getValue());
|
|
853
|
+
tab.doc.document = parsed.document as JxMutableNode;
|
|
854
|
+
tab.doc.layout = parsed.layout;
|
|
602
855
|
tab.doc.dirty = true;
|
|
603
856
|
writes.markSettled();
|
|
604
857
|
} catch {
|
|
@@ -627,6 +880,25 @@ export function renderCanvas(paneId: string = workspace.activePaneId) {
|
|
|
627
880
|
});
|
|
628
881
|
}
|
|
629
882
|
|
|
883
|
+
/**
|
|
884
|
+
* A kit component was saved: redefine it in every live frame, then render every pane, because a
|
|
885
|
+
* frame's instances keep the definition they rendered until something renders them again
|
|
886
|
+
* (embedding.md §7). The render is what makes the redefinition visible; the message alone would
|
|
887
|
+
* leave every open canvas drawing the old element beside a shell drawing the new one.
|
|
888
|
+
*
|
|
889
|
+
* @param {JxMutableNode} doc The component document, as saved.
|
|
890
|
+
* @param {string} base The URL the frame resolves the document's own references against — the
|
|
891
|
+
* file's URL under the project, so `$elements` siblings resolve to the project's copies.
|
|
892
|
+
* @returns {number} How many frames were told.
|
|
893
|
+
*/
|
|
894
|
+
export function redefineElementOnCanvases(doc: JxMutableNode, base: string): number {
|
|
895
|
+
const posted = postRedefineElementToLiveHosts(doc, base);
|
|
896
|
+
for (const pane of workspace.panes) {
|
|
897
|
+
renderCanvas(pane.id);
|
|
898
|
+
}
|
|
899
|
+
return posted;
|
|
900
|
+
}
|
|
901
|
+
|
|
630
902
|
/**
|
|
631
903
|
* Say, on this stage, why a derived pane has nothing to draw.
|
|
632
904
|
*
|
|
@@ -636,8 +908,11 @@ export function renderCanvas(paneId: string = workspace.activePaneId) {
|
|
|
636
908
|
* derivation, no tabs, no strip chip, no context bar and a blank stage that `paneIsEmpty` would not
|
|
637
909
|
* collapse. The sentence written for the honest empty state was dead code.
|
|
638
910
|
*
|
|
639
|
-
* Through {@link
|
|
640
|
-
*
|
|
911
|
+
* Through {@link emptyState} rather than a block of its own: the copy rules are inherited, and a
|
|
912
|
+
* derived pane with nothing to show is the same kind of region as any other. The stage stays a lit
|
|
913
|
+
* render root and the notice is a NODE it interpolates — `surfaces/empty-state.ts` owns a `display:
|
|
914
|
+
* contents` host, mounts the document into it once, and assigns after that, so the stage flipping
|
|
915
|
+
* between an artboard and this neither rebuilds the document nor strands it.
|
|
641
916
|
*
|
|
642
917
|
* **`held` is the document this pane still OWNS, and it is the difference between a notice and a
|
|
643
918
|
* riddle.** A companion that resolved once has a real tab, so `panels/tab-strip.ts` draws a real
|
|
@@ -661,7 +936,7 @@ function renderDerivationNotice(
|
|
|
661
936
|
const registry = activeRegistry();
|
|
662
937
|
const pin = registry?.get("pane.pin");
|
|
663
938
|
litRender(
|
|
664
|
-
|
|
939
|
+
emptyState(surface.wrap, {
|
|
665
940
|
message,
|
|
666
941
|
...(held && { detail: `${tabLabel(held)} is still open here.` }),
|
|
667
942
|
...(held &&
|
|
@@ -798,6 +1073,15 @@ function renderCanvasImpl(surface: CanvasSurface) {
|
|
|
798
1073
|
hardClearCanvasWrap(canvasWrap);
|
|
799
1074
|
}
|
|
800
1075
|
|
|
1076
|
+
/* LEAVING THE COMPARISON ENTIRELY, which is the one exit the git-diff branch cannot cover.
|
|
1077
|
+
The Visual/Code switch inside that branch disposes this itself, and so does a pane teardown —
|
|
1078
|
+
but a mode change OUT of git-diff reaches neither, and `hardClearCanvasWrap` above only detaches
|
|
1079
|
+
the DOM. A diff editor left alive holds two models whose URIs stay claimed, so reopening the
|
|
1080
|
+
comparison later finds a live editor for a stale pair of texts. */
|
|
1081
|
+
if (modeChanged && canvasMode !== "git-diff") {
|
|
1082
|
+
disposeDiffEditor(surface);
|
|
1083
|
+
}
|
|
1084
|
+
|
|
801
1085
|
/* There are no `editingFunction` / `editingFormula` branches here, and that is the point.
|
|
802
1086
|
Both used to RETURN from this function, which is what made the logic editors a takeover: the
|
|
803
1087
|
stage kept whatever DOM it was last painted with and stopped tracking the document. P8 moved
|
|
@@ -972,9 +1256,12 @@ function renderCanvasImpl(surface: CanvasSurface) {
|
|
|
972
1256
|
disposeSourceCollab(surface);
|
|
973
1257
|
disposeSourceEditor(surface);
|
|
974
1258
|
|
|
975
|
-
|
|
976
|
-
|
|
1259
|
+
/* Same reason as `hardClearCanvasWrap`: the stage is about to detach every artboard's iframe,
|
|
1260
|
+
and a detached host is otherwise only noticed by whichever lazy `liveHosts` walk runs next.
|
|
1261
|
+
Both writers are ended here — the stage document, whose structure belongs to the mode that is
|
|
1262
|
+
leaving, and lit's part, which the empty-state and welcome paths own. */
|
|
977
1263
|
releaseCanvasHosts(canvasWrap);
|
|
1264
|
+
detachCanvasStage(surface);
|
|
978
1265
|
litRender(nothing, canvasWrap);
|
|
979
1266
|
surface.panzoomWrap = null;
|
|
980
1267
|
// Reset inline style overrides from other modes
|
|
@@ -996,15 +1283,19 @@ function renderCanvasImpl(surface: CanvasSurface) {
|
|
|
996
1283
|
if (canvasMode === "stylebook") {
|
|
997
1284
|
surface.prevStylebookFilter = shell.stylebook.filter;
|
|
998
1285
|
surface.prevStylebookCustomizedOnly = shell.stylebook.customizedOnly;
|
|
999
|
-
renderStylebookMode(surface, {
|
|
1286
|
+
void renderStylebookMode(surface, {
|
|
1000
1287
|
applyTransform,
|
|
1001
|
-
|
|
1288
|
+
canvasPanelEntry,
|
|
1289
|
+
drawStage,
|
|
1002
1290
|
observeCenterUntilStable,
|
|
1291
|
+
stageHost,
|
|
1003
1292
|
updateActivePanelHeaders,
|
|
1293
|
+
}).then(() => {
|
|
1294
|
+
// After the catalogue's artboards are in the page: the fit measures them.
|
|
1295
|
+
if (modeChanged) {
|
|
1296
|
+
fitOnCanvasEntry(surface);
|
|
1297
|
+
}
|
|
1004
1298
|
});
|
|
1005
|
-
if (modeChanged) {
|
|
1006
|
-
fitOnCanvasEntry(surface);
|
|
1007
|
-
}
|
|
1008
1299
|
return;
|
|
1009
1300
|
}
|
|
1010
1301
|
|
|
@@ -1029,6 +1320,13 @@ function renderCanvasImpl(surface: CanvasSurface) {
|
|
|
1029
1320
|
* rendering. Same expression as Edit's column, so the same page at `md` is the same page
|
|
1030
1321
|
* whichever of the two the toggle is over.
|
|
1031
1322
|
*
|
|
1323
|
+
* That equality now holds at the BREAKPOINT, not at the pixel, and deliberately. Edit's column
|
|
1324
|
+
* can be dragged to any width between two declared ones (`edit-width.ts`); Preview does not read
|
|
1325
|
+
* that override, because Preview is the fidelity view and a fidelity view of "somewhere between
|
|
1326
|
+
* md and lg" is a width no visitor will ever have. Toggling Preview is a mode change, which is
|
|
1327
|
+
* also what discards the dragged width — so the two surfaces agree again the moment either one
|
|
1328
|
+
* is entered, rather than disagreeing silently.
|
|
1329
|
+
*
|
|
1032
1330
|
* The HEIGHT is untouched: the frame stays the pane's height and the document scrolls itself,
|
|
1033
1331
|
* which is what makes sticky, scroll-driven animation and IntersectionObserver fire here.
|
|
1034
1332
|
*/
|
|
@@ -1038,13 +1336,29 @@ function renderCanvasImpl(surface: CanvasSurface) {
|
|
|
1038
1336
|
const previewMedia = activeMediaOfPane(surface.paneId);
|
|
1039
1337
|
const previewWidth =
|
|
1040
1338
|
previewBreakpoints.find((bp) => bp.name === previewMedia)?.width ?? previewBase;
|
|
1041
|
-
const
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1339
|
+
const entry = canvasPanelEntry(null, null, true);
|
|
1340
|
+
canvasPanels.push(entry.panel);
|
|
1341
|
+
const { featureToggles: previewToggles } = S.ui;
|
|
1342
|
+
void drawStage(
|
|
1343
|
+
surface,
|
|
1344
|
+
{
|
|
1345
|
+
columnHeader: "hidden",
|
|
1346
|
+
frame: "boards",
|
|
1347
|
+
framePart: "preview-stage",
|
|
1348
|
+
frameVars: `--preview-w:${previewWidth}px`,
|
|
1349
|
+
handles: "hidden",
|
|
1350
|
+
hug: false,
|
|
1351
|
+
innerPart: "boards",
|
|
1352
|
+
lead: "none",
|
|
1353
|
+
panels: [entry.item],
|
|
1354
|
+
},
|
|
1355
|
+
[entry],
|
|
1356
|
+
).then((stage) => {
|
|
1357
|
+
if (!stage) {
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
renderCanvasIntoPanel(surface, entry.panel, previewToggles);
|
|
1361
|
+
});
|
|
1048
1362
|
return;
|
|
1049
1363
|
}
|
|
1050
1364
|
|
|
@@ -1102,24 +1416,17 @@ function renderCanvasImpl(surface: CanvasSurface) {
|
|
|
1102
1416
|
if (canvasMode === "source") {
|
|
1103
1417
|
canvasWrap.style.padding = "0";
|
|
1104
1418
|
canvasWrap.style.display = "block";
|
|
1105
|
-
let editorContainer: HTMLDivElement | null = null;
|
|
1106
|
-
litRender(
|
|
1107
|
-
html`<div class="source-wrap">
|
|
1108
|
-
<div
|
|
1109
|
-
class="source-editor"
|
|
1110
|
-
${ref((el) => {
|
|
1111
|
-
if (el) {
|
|
1112
|
-
editorContainer = el as HTMLDivElement;
|
|
1113
|
-
}
|
|
1114
|
-
})}
|
|
1115
|
-
></div>
|
|
1116
|
-
</div>`,
|
|
1117
|
-
canvasWrap,
|
|
1118
|
-
);
|
|
1119
|
-
|
|
1120
1419
|
const filePath = tab.documentPath || "document.json";
|
|
1121
1420
|
const lang = sourceLang(tab);
|
|
1122
|
-
void
|
|
1421
|
+
void drawStage(surface, editorStageView("source"), []).then((stage) => {
|
|
1422
|
+
if (!stage) {
|
|
1423
|
+
return;
|
|
1424
|
+
}
|
|
1425
|
+
const editorContainer = stageHost(surface, "source-editor");
|
|
1426
|
+
if (editorContainer) {
|
|
1427
|
+
void mountSourceEditor(tab, surface, editorContainer, filePath, lang);
|
|
1428
|
+
}
|
|
1429
|
+
});
|
|
1123
1430
|
return;
|
|
1124
1431
|
}
|
|
1125
1432
|
|
|
@@ -1151,39 +1458,66 @@ function renderCanvasImpl(surface: CanvasSurface) {
|
|
|
1151
1458
|
canvasWrap.style.overflow = "hidden";
|
|
1152
1459
|
}
|
|
1153
1460
|
|
|
1461
|
+
/* THE CODE HALF, and it is the whole branch rather than an extra artboard.
|
|
1462
|
+
A comparison read as text has no artboards, no pan/zoom and no marks: Monaco computes its own
|
|
1463
|
+
line diff from the two texts `readGitDiff` already holds, and draws its own red and green.
|
|
1464
|
+
This is the ONLY view for a file the canvas cannot render — a .ts, a .css, a .gitignore — and
|
|
1465
|
+
an alternate one for a document it can. */
|
|
1466
|
+
/* A file the canvas cannot DRAW has only the one half, and the renderer is where that is
|
|
1467
|
+
decided rather than the opener: a comparison reaches this branch from three doors (the panel,
|
|
1468
|
+
a Diff lens, the Editor axis) and only this one sees every arrival. Forcing it here also
|
|
1469
|
+
leaves `diffView` alone, so a document opened after a `.css` still comes up Visual. */
|
|
1470
|
+
const renderable = canRenderComparison(gitDiffState.filePath ?? "");
|
|
1471
|
+
if (diffShowsCode(surface.paneId, gitDiffState.filePath ?? "")) {
|
|
1472
|
+
/* A null map is how the toolbar learns there is no visual half to offer: it draws Code as a
|
|
1473
|
+
static label rather than as half of a choice, and reports the line marks instead of a node
|
|
1474
|
+
count. Cleared rather than left, so a pane that compared a document and then a stylesheet
|
|
1475
|
+
does not keep the document's count over the stylesheet's text. */
|
|
1476
|
+
if (!renderable) {
|
|
1477
|
+
setDiffChangeMap(surface.paneId, null);
|
|
1478
|
+
}
|
|
1479
|
+
disposeSourceEditor(surface);
|
|
1480
|
+
void drawStage(surface, editorStageView("code"), []).then((stage) => {
|
|
1481
|
+
if (!stage) {
|
|
1482
|
+
return;
|
|
1483
|
+
}
|
|
1484
|
+
// After the stage, because the bar's host is one of the nodes it draws.
|
|
1485
|
+
renderDiffToolbar(surface.paneId);
|
|
1486
|
+
const editorEl = stageHost(surface, "diff-code-editor");
|
|
1487
|
+
if (editorEl) {
|
|
1488
|
+
void mountDiffEditor(surface, editorEl, gitDiffState);
|
|
1489
|
+
}
|
|
1490
|
+
});
|
|
1491
|
+
return;
|
|
1492
|
+
}
|
|
1493
|
+
disposeDiffEditor(surface);
|
|
1494
|
+
|
|
1154
1495
|
const panelWidth = 800;
|
|
1155
1496
|
|
|
1156
|
-
const
|
|
1157
|
-
|
|
1158
|
-
"Original",
|
|
1159
|
-
false,
|
|
1160
|
-
panelWidth,
|
|
1161
|
-
);
|
|
1162
|
-
const { tpl: currTpl, panel: currPanel } = canvasPanelTemplate(
|
|
1163
|
-
"git-diff-current",
|
|
1164
|
-
"Current",
|
|
1165
|
-
false,
|
|
1166
|
-
panelWidth,
|
|
1167
|
-
);
|
|
1497
|
+
const origEntry = canvasPanelEntry("git-diff-original", "Original", false, panelWidth);
|
|
1498
|
+
const currEntry = canvasPanelEntry("git-diff-current", "Current", false, panelWidth);
|
|
1168
1499
|
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1500
|
+
/* The Compare bar leads the frame: it is absolutely positioned OVER the stage and a SIBLING of
|
|
1501
|
+
the pan/zoom surface, never a child. A child would be panned and scaled with the artboards,
|
|
1502
|
+
and a flow sibling would move the origin the pan transform and the centering observer both
|
|
1503
|
+
compute against. */
|
|
1504
|
+
const diffStage = drawStage(
|
|
1505
|
+
surface,
|
|
1506
|
+
{
|
|
1507
|
+
columnHeader: "hidden",
|
|
1508
|
+
frame: "boards",
|
|
1509
|
+
framePart: "panzoom",
|
|
1510
|
+
frameVars: "",
|
|
1511
|
+
handles: "hidden",
|
|
1512
|
+
hug: false,
|
|
1513
|
+
innerPart: "boards",
|
|
1514
|
+
lead: "toolbar",
|
|
1515
|
+
panels: [origEntry.item, currEntry.item],
|
|
1516
|
+
},
|
|
1517
|
+
[origEntry, currEntry],
|
|
1184
1518
|
);
|
|
1185
1519
|
|
|
1186
|
-
canvasPanels.push(
|
|
1520
|
+
canvasPanels.push(origEntry.panel, currEntry.panel);
|
|
1187
1521
|
|
|
1188
1522
|
/** @param {string} content */
|
|
1189
1523
|
const parseContent = (content: string): Promise<JxMutableNode> => {
|
|
@@ -1208,31 +1542,56 @@ function renderCanvasImpl(surface: CanvasSurface) {
|
|
|
1208
1542
|
// `passGen` at the design-mode artboard loop.
|
|
1209
1543
|
const diffGen = surface.renderGeneration;
|
|
1210
1544
|
void Promise.all([
|
|
1545
|
+
diffStage,
|
|
1211
1546
|
parseContent(gitDiffState.originalContent || ""),
|
|
1212
1547
|
parseContent(gitDiffState.currentContent || ""),
|
|
1213
|
-
]).then(([originalDoc, currentDoc]) => {
|
|
1548
|
+
]).then(([stage, originalDoc, currentDoc]) => {
|
|
1549
|
+
/* THE COMPARISON, computed once for both artboards and split by side.
|
|
1550
|
+
Structural rather than textual: the artboards render documents, so "what changed" has to be
|
|
1551
|
+
answered in document paths that `data-jx-path` can resolve. A failure here must not cost
|
|
1552
|
+
the author the comparison itself — an unparseable side already renders as a "Failed to
|
|
1553
|
+
parse" stub, and a stub aligns to zero changes rather than throwing — so the marks degrade
|
|
1554
|
+
to none and the two artboards draw exactly as they did before any of this existed. */
|
|
1555
|
+
let changeMap: ChangeMap | null = null;
|
|
1556
|
+
try {
|
|
1557
|
+
changeMap = buildChangeMap(originalDoc, currentDoc);
|
|
1558
|
+
} catch (error) {
|
|
1559
|
+
// Highlighting is an affordance over a comparison that is still on screen and still
|
|
1560
|
+
// Readable, so this degrades rather than surfacing: no toast, no empty stage.
|
|
1561
|
+
console.warn("buildChangeMap:", error);
|
|
1562
|
+
}
|
|
1563
|
+
if (!stage) {
|
|
1564
|
+
return;
|
|
1565
|
+
}
|
|
1566
|
+
setDiffChangeMap(surface.paneId, changeMap);
|
|
1567
|
+
renderDiffToolbar(surface.paneId);
|
|
1214
1568
|
renderCanvasIntoPanel(
|
|
1215
1569
|
surface,
|
|
1216
|
-
|
|
1570
|
+
origEntry.panel,
|
|
1217
1571
|
featureToggles,
|
|
1218
1572
|
originalDoc,
|
|
1219
|
-
|
|
1573
|
+
sideMarks(changeMap?.original, "modified-before"),
|
|
1220
1574
|
diffGen,
|
|
1221
1575
|
);
|
|
1222
1576
|
renderCanvasIntoPanel(
|
|
1223
1577
|
surface,
|
|
1224
|
-
|
|
1578
|
+
currEntry.panel,
|
|
1225
1579
|
featureToggles,
|
|
1226
1580
|
currentDoc,
|
|
1227
|
-
|
|
1581
|
+
sideMarks(changeMap?.current, "modified-after"),
|
|
1228
1582
|
diffGen,
|
|
1229
1583
|
);
|
|
1230
1584
|
});
|
|
1231
1585
|
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1586
|
+
void diffStage.then((stage) => {
|
|
1587
|
+
if (!stage) {
|
|
1588
|
+
return;
|
|
1589
|
+
}
|
|
1590
|
+
applyTransform(surface);
|
|
1591
|
+
if (modeChanged) {
|
|
1592
|
+
observeCenterUntilStable(surface);
|
|
1593
|
+
}
|
|
1594
|
+
});
|
|
1236
1595
|
return;
|
|
1237
1596
|
}
|
|
1238
1597
|
|
|
@@ -1242,10 +1601,14 @@ function renderCanvasImpl(surface: CanvasSurface) {
|
|
|
1242
1601
|
if (modeChanged) {
|
|
1243
1602
|
canvasWrap.style.padding = "0";
|
|
1244
1603
|
canvasWrap.style.overflow = "hidden";
|
|
1604
|
+
/* A dragged width is an INSPECTION, and it dies with the mode: entering Edit always starts at
|
|
1605
|
+
the breakpoint the switcher names. What survives is the breakpoint the drag landed on,
|
|
1606
|
+
which `activeMedia` already persists — see `canvas/edit-width.ts`. */
|
|
1607
|
+
clearEditWidth(surface.paneId);
|
|
1245
1608
|
}
|
|
1246
1609
|
|
|
1247
1610
|
/*
|
|
1248
|
-
* THE COLUMN IS AS WIDE AS THE CHOSEN BREAKPOINT.
|
|
1611
|
+
* THE COLUMN IS AS WIDE AS THE CHOSEN BREAKPOINT — OR AS WIDE AS IT HAS BEEN DRAGGED.
|
|
1249
1612
|
*
|
|
1250
1613
|
* It was always `baseWidth`, so the Context bar's size switcher did nothing here: it wrote
|
|
1251
1614
|
* `session.ui.activeMedia`, Design used that to highlight one of the artboards it already draws
|
|
@@ -1255,37 +1618,76 @@ function renderCanvasImpl(surface: CanvasSurface) {
|
|
|
1255
1618
|
* The width is the artboard width Design would give that breakpoint, so the same page at `md`
|
|
1256
1619
|
* is the same page in both modes; the iframe is that wide, so the document's own media queries
|
|
1257
1620
|
* evaluate against it and the content reflows for real rather than being scaled.
|
|
1621
|
+
*
|
|
1622
|
+
* The switcher's answer is now the FALLBACK rather than the whole story: a handle on either
|
|
1623
|
+
* side of the column drags it to any width in between, and the breakpoint follows the width
|
|
1624
|
+
* (`edit-width.ts`). With nothing dragged this is byte-for-byte the expression it replaced.
|
|
1258
1625
|
*/
|
|
1259
|
-
const
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1626
|
+
const columnWidth = resolveEditColumnWidth(surface, tab);
|
|
1627
|
+
/*
|
|
1628
|
+
* THE TEMPLATE MUST NOT BIND THIS WIDTH, and that is not a style preference.
|
|
1629
|
+
*
|
|
1630
|
+
* The drag writes `column.style.maxWidth` imperatively, once per pointermove, because a render
|
|
1631
|
+
* per move would rebuild the iframe. lit dirty-checks its own committed value, so a later pass
|
|
1632
|
+
* that computes the SAME width it last committed skips the write — and the imperative value
|
|
1633
|
+
* stays. That is not hypothetical: drag a page down to 330px, open a different document in the
|
|
1634
|
+
* pane, and the new one is 330px wide too, because both passes computed the base width and lit
|
|
1635
|
+
* wrote neither. One writer, applied after the render, is the fix (§9.4 of the UI guidelines);
|
|
1636
|
+
* `applyEditZoom` below already has exactly this shape for exactly this reason.
|
|
1637
|
+
*/
|
|
1638
|
+
const entry = canvasPanelEntry(null, null, true);
|
|
1265
1639
|
// A component-definition doc (root tag is a custom element) is a fragment, not a page: it should
|
|
1266
1640
|
// Hug its content rather than have the column fill+stretch to the viewport (dead scroll space).
|
|
1267
1641
|
const rootTag = (S.document as { tagName?: unknown }).tagName;
|
|
1268
1642
|
const isComponentDoc = typeof rootTag === "string" && rootTag.includes("-");
|
|
1269
|
-
const
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1643
|
+
const { featureToggles: editToggles } = S.ui;
|
|
1644
|
+
void drawStage(
|
|
1645
|
+
surface,
|
|
1646
|
+
{
|
|
1647
|
+
/* The card is the column's FIRST child by contract (`tests/canvas-render.test.ts`, "Edit
|
|
1648
|
+
puts it INSIDE the document column"). The two handles are not in the column at all: they
|
|
1649
|
+
are `jx-split`s standing beside it in the canvas's row, because the canvas is the track
|
|
1650
|
+
a splitter has to measure and the column is the thing being resized. */
|
|
1651
|
+
columnHeader: wantsDocHeader ? "shown" : "hidden",
|
|
1652
|
+
frame: "boards",
|
|
1653
|
+
framePart: "edit-canvas",
|
|
1654
|
+
frameVars: "",
|
|
1655
|
+
handles: "shown",
|
|
1656
|
+
hug: isComponentDoc,
|
|
1657
|
+
innerPart: "edit-column",
|
|
1658
|
+
lead: "none",
|
|
1659
|
+
panels: [entry.item],
|
|
1660
|
+
},
|
|
1661
|
+
[entry],
|
|
1662
|
+
).then((stage) => {
|
|
1663
|
+
if (!stage) {
|
|
1664
|
+
return;
|
|
1665
|
+
}
|
|
1666
|
+
const editColumn = stageHost(surface, "edit-column");
|
|
1667
|
+
entry.panel.scrollContainer = stageHost(surface, "edit-canvas") as HTMLElement;
|
|
1668
|
+
// The one writer of the column's width — see the note above.
|
|
1669
|
+
if (editColumn) {
|
|
1670
|
+
editColumn.style.maxWidth = `${Math.round(columnWidth)}px`;
|
|
1671
|
+
mountEditWidthHandle(
|
|
1672
|
+
surface,
|
|
1673
|
+
stageHost(surface, "edit-handle:start") ?? undefined,
|
|
1674
|
+
editColumn,
|
|
1675
|
+
-1,
|
|
1676
|
+
);
|
|
1677
|
+
mountEditWidthHandle(
|
|
1678
|
+
surface,
|
|
1679
|
+
stageHost(surface, "edit-handle:end") ?? undefined,
|
|
1680
|
+
editColumn,
|
|
1681
|
+
1,
|
|
1682
|
+
);
|
|
1683
|
+
}
|
|
1684
|
+
renderCanvasIntoPanel(surface, entry.panel, editToggles);
|
|
1685
|
+
// The column must exist in the DOM before the zoom's live width measurement — so the zoom is
|
|
1686
|
+
// Applied after the render rather than baked into the stage (the panel mounts fluid and is
|
|
1687
|
+
// Immediately re-fitted; the iframe hasn't painted yet, so nothing visibly jumps).
|
|
1688
|
+
applyEditZoom(surface);
|
|
1689
|
+
});
|
|
1690
|
+
canvasPanels.push(entry.panel);
|
|
1289
1691
|
return;
|
|
1290
1692
|
}
|
|
1291
1693
|
|
|
@@ -1300,7 +1702,7 @@ function renderCanvasImpl(surface: CanvasSurface) {
|
|
|
1300
1702
|
`#canvas-wrap` is a row by default and each surface states its own axis. */
|
|
1301
1703
|
canvasWrap.style.flexDirection = wantsDocHeader ? "column" : "";
|
|
1302
1704
|
canvasWrap.style.alignItems = wantsDocHeader ? "stretch" : "";
|
|
1303
|
-
const
|
|
1705
|
+
const designLead = wantsDocHeader ? "header" : "none";
|
|
1304
1706
|
|
|
1305
1707
|
const {
|
|
1306
1708
|
sizeBreakpoints,
|
|
@@ -1316,39 +1718,41 @@ function renderCanvasImpl(surface: CanvasSurface) {
|
|
|
1316
1718
|
const effectiveMedia = getEffectiveMedia(S.document.$media);
|
|
1317
1719
|
const hasBaseWidth = effectiveMedia && effectiveMedia["--"];
|
|
1318
1720
|
const label = hasBaseWidth ? `${mediaDisplayName("--")} (${baseWidth}px)` : null;
|
|
1319
|
-
const
|
|
1721
|
+
const entry = canvasPanelEntry(
|
|
1320
1722
|
hasBaseWidth ? "base" : null,
|
|
1321
1723
|
label,
|
|
1322
1724
|
!hasBaseWidth,
|
|
1323
1725
|
hasBaseWidth ? baseWidth : undefined,
|
|
1324
1726
|
);
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1727
|
+
void drawStage(
|
|
1728
|
+
surface,
|
|
1729
|
+
{
|
|
1730
|
+
columnHeader: "hidden",
|
|
1731
|
+
frame: "boards",
|
|
1732
|
+
framePart: "panzoom",
|
|
1733
|
+
frameVars: "",
|
|
1734
|
+
handles: "hidden",
|
|
1735
|
+
hug: false,
|
|
1736
|
+
innerPart: "boards",
|
|
1737
|
+
lead: designLead,
|
|
1738
|
+
panels: [entry.item],
|
|
1739
|
+
},
|
|
1740
|
+
[entry],
|
|
1741
|
+
).then((stage) => {
|
|
1742
|
+
if (!stage) {
|
|
1743
|
+
return;
|
|
1744
|
+
}
|
|
1745
|
+
renderCanvasIntoPanel(surface, entry.panel, featureToggles);
|
|
1746
|
+
applyTransform(surface);
|
|
1747
|
+
if (modeChanged) {
|
|
1748
|
+
// Fit BEFORE centering: the fit picks the zoom, centerCanvas then places the artboard at
|
|
1749
|
+
// That zoom (and top-aligns it, which beats fit's vertical centering for a page taller
|
|
1750
|
+
// Than the viewport).
|
|
1751
|
+
fitOnCanvasEntry(surface);
|
|
1752
|
+
observeCenterUntilStable(surface);
|
|
1753
|
+
}
|
|
1754
|
+
});
|
|
1755
|
+
canvasPanels.push(entry.panel);
|
|
1352
1756
|
return;
|
|
1353
1757
|
}
|
|
1354
1758
|
|
|
@@ -1382,28 +1786,24 @@ function renderCanvasImpl(surface: CanvasSurface) {
|
|
|
1382
1786
|
lensMedia === null ? allPanelDefs : allPanelDefs.filter((d) => d.name === lensMedia);
|
|
1383
1787
|
const panelDefs = chosen.length > 0 ? chosen : allPanelDefs;
|
|
1384
1788
|
|
|
1385
|
-
const panelEntries = panelDefs.map((def) =>
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
return { panel, tpl };
|
|
1389
|
-
});
|
|
1789
|
+
const panelEntries = panelDefs.map((def) =>
|
|
1790
|
+
canvasPanelEntry(def.name, `${def.displayName} (${def.width}px)`, false, def.width),
|
|
1791
|
+
);
|
|
1390
1792
|
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
`,
|
|
1406
|
-
canvasWrap,
|
|
1793
|
+
const stageDrawn = drawStage(
|
|
1794
|
+
surface,
|
|
1795
|
+
{
|
|
1796
|
+
columnHeader: "hidden",
|
|
1797
|
+
frame: "boards",
|
|
1798
|
+
framePart: "panzoom",
|
|
1799
|
+
frameVars: "",
|
|
1800
|
+
handles: "hidden",
|
|
1801
|
+
hug: false,
|
|
1802
|
+
innerPart: "boards",
|
|
1803
|
+
lead: designLead,
|
|
1804
|
+
panels: panelEntries.map((e) => e.item),
|
|
1805
|
+
},
|
|
1806
|
+
panelEntries,
|
|
1407
1807
|
);
|
|
1408
1808
|
|
|
1409
1809
|
/* Every artboard of this pass mounts under the generation the pass opened with, captured HERE
|
|
@@ -1413,29 +1813,44 @@ function renderCanvasImpl(surface: CanvasSurface) {
|
|
|
1413
1813
|
render under the NEW pass's number. And the host resolves the document once per generation
|
|
1414
1814
|
(`preparePassRender`), which only fans out if the pass has one. */
|
|
1415
1815
|
const passGen = surface.renderGeneration;
|
|
1416
|
-
for (
|
|
1417
|
-
|
|
1418
|
-
const p = panel as CanvasPanel;
|
|
1419
|
-
canvasPanels.push(p);
|
|
1420
|
-
if (i === 0) {
|
|
1421
|
-
renderCanvasIntoPanel(surface, p, featureToggles);
|
|
1422
|
-
} else {
|
|
1423
|
-
// Yield between artboards so the first one paints before the rest mount. They no longer pay
|
|
1424
|
-
// For the document — the pass already resolved it — but each is still a live iframe render.
|
|
1425
|
-
setTimeout(() => renderCanvasIntoPanel(surface, p, featureToggles, null, null, passGen), 0);
|
|
1426
|
-
}
|
|
1816
|
+
for (const { panel } of panelEntries) {
|
|
1817
|
+
canvasPanels.push(panel);
|
|
1427
1818
|
}
|
|
1819
|
+
void stageDrawn.then((stage) => {
|
|
1820
|
+
if (!stage) {
|
|
1821
|
+
return;
|
|
1822
|
+
}
|
|
1823
|
+
for (let i = 0; i < panelEntries.length; i++) {
|
|
1824
|
+
const { panel } = panelEntries[i]!;
|
|
1825
|
+
if (i === 0) {
|
|
1826
|
+
/* `passGen` EXPLICITLY, including for the first board. It used to be left to the default —
|
|
1827
|
+
"whatever generation the surface is on" — which was the pass's own only because this
|
|
1828
|
+
board mounted synchronously inside the pass. It does not any more: the stage settles a
|
|
1829
|
+
microtask later, by which time a second pass may already have opened, and reading the
|
|
1830
|
+
live number there would stamp this pass's artboard with the NEXT pass's — a duplicate
|
|
1831
|
+
render the frame cannot recognise as superseded. */
|
|
1832
|
+
renderCanvasIntoPanel(surface, panel, featureToggles, null, null, passGen);
|
|
1833
|
+
} else {
|
|
1834
|
+
// Yield between artboards so the first one paints before the rest mount. They no longer pay
|
|
1835
|
+
// For the document — the pass already resolved it — but each is still a live iframe render.
|
|
1836
|
+
setTimeout(
|
|
1837
|
+
() => renderCanvasIntoPanel(surface, panel, featureToggles, null, null, passGen),
|
|
1838
|
+
0,
|
|
1839
|
+
);
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1428
1842
|
|
|
1429
|
-
|
|
1430
|
-
|
|
1843
|
+
// Highlight active panel header — this pass's stage, not the focused pane's.
|
|
1844
|
+
updateActivePanelHeaders(surface);
|
|
1431
1845
|
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1846
|
+
// Apply current zoom + pan transform
|
|
1847
|
+
applyTransform(surface);
|
|
1848
|
+
if (modeChanged) {
|
|
1849
|
+
// See the single-panel path: fit picks the zoom, centerCanvas then places the artboards.
|
|
1850
|
+
fitOnCanvasEntry(surface);
|
|
1851
|
+
observeCenterUntilStable(surface);
|
|
1852
|
+
}
|
|
1853
|
+
});
|
|
1439
1854
|
}
|
|
1440
1855
|
|
|
1441
1856
|
/**
|
|
@@ -1451,8 +1866,10 @@ function renderCanvasImpl(surface: CanvasSurface) {
|
|
|
1451
1866
|
* render needs no structural-preview fallback); unused.
|
|
1452
1867
|
* @param {JxMutableNode | null} [docOverride] - Optional document to render (for diff mode). Uses
|
|
1453
1868
|
* active tab doc if not provided.
|
|
1454
|
-
* @param {
|
|
1455
|
-
*
|
|
1869
|
+
* @param {WireDiffMarks | null} [diffMarks] - This artboard's change marks, in ITS OWN document's
|
|
1870
|
+
* coordinates. The slot used to hold a `GitDiffState` "accepted for call-site symmetry" and
|
|
1871
|
+
* unread, which is what "the iframe path does not apply diff highlighting" meant; it does now,
|
|
1872
|
+
* and the marks are per-SIDE, so the whole comparison was never the right thing to pass.
|
|
1456
1873
|
* @param {number | null} [passGen] - The generation of the render pass this panel belongs to.
|
|
1457
1874
|
* Passed explicitly by a DEFERRED mount, whose callback would otherwise read whatever generation
|
|
1458
1875
|
* is current when the timer fires — a later pass's number, stamped on an earlier pass's
|
|
@@ -1463,7 +1880,7 @@ function renderCanvasIntoPanel(
|
|
|
1463
1880
|
panel: CanvasPanel,
|
|
1464
1881
|
_featureToggles: Record<string, boolean>,
|
|
1465
1882
|
docOverride: JxMutableNode | null = null,
|
|
1466
|
-
|
|
1883
|
+
diffMarks: WireDiffMarks | null = null,
|
|
1467
1884
|
passGen: number | null = null,
|
|
1468
1885
|
) {
|
|
1469
1886
|
const gen = passGen ?? surface.renderGeneration;
|
|
@@ -1490,9 +1907,17 @@ function renderCanvasIntoPanel(
|
|
|
1490
1907
|
panel._width,
|
|
1491
1908
|
docOverride ? null : (tab?.id ?? null),
|
|
1492
1909
|
// The VIEW tab, which an override does not null out: a git-diff frame routes no mutations
|
|
1493
|
-
// But is still a view of this pane's document, and its docBase
|
|
1494
|
-
//
|
|
1910
|
+
// But is still a view of this pane's document, and its docBase and layout toggle are that
|
|
1911
|
+
// Tab's. Explicit rather than left to the default, because this line already knows.
|
|
1495
1912
|
tab,
|
|
1913
|
+
/* …but NOT its mode, which is the one thing the view tab cannot answer for a lens. A lens
|
|
1914
|
+
draws the source pane's document in a mode of its own that is never written onto the tab,
|
|
1915
|
+
so resolving from `tab` gave a Diff lens's artboards the SOURCE pane's mode — an editable
|
|
1916
|
+
`design` frame for a comparison, with repeater paths collapsed on one entry point to the
|
|
1917
|
+
diff and not the other. `canvasModeOfPane` degrades to exactly the old answer for every
|
|
1918
|
+
pane that is not a lens, so this is unconditional rather than a git-diff special case. */
|
|
1919
|
+
canvasModeOfPane(surface.paneId),
|
|
1920
|
+
diffMarks,
|
|
1496
1921
|
),
|
|
1497
1922
|
)
|
|
1498
1923
|
.then(() => {
|
|
@@ -1525,7 +1950,14 @@ function renderCanvasIntoPanel(
|
|
|
1525
1950
|
* Same idiom as `setIframePatchEscalation`. Without it a pane removed from the grid would drop its
|
|
1526
1951
|
* record while its Monaco, its collab lock and its centering observer stayed alive.
|
|
1527
1952
|
*/
|
|
1953
|
+
/* The diff toolbar's Visual/Code switch rebuilds the stage, and it cannot import this module to
|
|
1954
|
+
do it — this one imports IT. Same injection as the teardown below. */
|
|
1955
|
+
setDiffRepaint(renderCanvas);
|
|
1956
|
+
|
|
1528
1957
|
setSurfaceTeardown((surface) => {
|
|
1958
|
+
disposeDiffEditor(surface);
|
|
1959
|
+
clearDiffView(surface.paneId);
|
|
1960
|
+
setDiffToolbarHost(surface.paneId, null);
|
|
1529
1961
|
detachGridPanel(surface.paneId);
|
|
1530
1962
|
detachLibraryPane(surface.paneId);
|
|
1531
1963
|
detachEntryPane(surface.paneId);
|
|
@@ -1537,7 +1969,7 @@ setSurfaceTeardown((surface) => {
|
|
|
1537
1969
|
surface.centerObserver?.disconnect();
|
|
1538
1970
|
surface.centerObserver = null;
|
|
1539
1971
|
surface.panzoomWrap = null;
|
|
1540
|
-
|
|
1972
|
+
detachCanvasStage(surface);
|
|
1541
1973
|
});
|
|
1542
1974
|
|
|
1543
1975
|
export function renderOverlays() {
|
|
@@ -1637,6 +2069,13 @@ export function selectionCommands(): AnyCommand[] {
|
|
|
1637
2069
|
"Select the element at a document path so the Inspector, the Outline and the canvas " +
|
|
1638
2070
|
"overlay all address it. Pass null to clear the selection.",
|
|
1639
2071
|
name: "select_node",
|
|
2072
|
+
/* The one pointing verb: how the assistant shows the person which element it means. The
|
|
2073
|
+
report reads the context's own `selection.kind` — the tag the status bar prints — so the
|
|
2074
|
+
model learns what it pointed at without a second read. */
|
|
2075
|
+
report: ({ after }) =>
|
|
2076
|
+
after.selection.count === 0
|
|
2077
|
+
? "Cleared the selection."
|
|
2078
|
+
: `Selected ${after.selection.kind || "the element"} at [${(after.selection.paths.at(-1) ?? []).join(", ")}]; the Inspector and the Outline now address it.`,
|
|
1640
2079
|
},
|
|
1641
2080
|
run: (_commandCtx, args) => {
|
|
1642
2081
|
const path = nullablePathArg("selection.set", args, "path");
|
|
@@ -1669,12 +2108,12 @@ export function selectionCommands(): AnyCommand[] {
|
|
|
1669
2108
|
group: "2_navigate",
|
|
1670
2109
|
requires: "an open document",
|
|
1671
2110
|
when: (ctx) => ctx.document.open,
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
2111
|
+
/*
|
|
2112
|
+
* No `aiTool`, by §12.4's fourth deletion rule (redundant with a tool the model has): the
|
|
2113
|
+
* assistant's bridge runs THIS record by id as the selector step of every selection-level
|
|
2114
|
+
* tool — `delete_node(paths)` is `selection.setPaths` then `selection.delete` — so a second
|
|
2115
|
+
* selection tool beside `select_node` would be prompt cost with no second job.
|
|
2116
|
+
*/
|
|
1678
2117
|
/**
|
|
1679
2118
|
* The idempotent SET for the whole selection, beside `selection.set`'s single path.
|
|
1680
2119
|
*
|
|
@@ -1730,12 +2169,8 @@ export function selectionCommands(): AnyCommand[] {
|
|
|
1730
2169
|
— `postApplyFormat` would no-op against a frame with no session and the palette row would
|
|
1731
2170
|
read as available. The `format.*` family is gated the same way, for the same reason. */
|
|
1732
2171
|
when: (ctx) => ctx.caret.inCanvas,
|
|
1733
|
-
aiTool
|
|
1734
|
-
|
|
1735
|
-
"Insert a live data placeholder at the text caret, binding that run of text to a state " +
|
|
1736
|
-
"entry or, inside a repeater template, to the current item.",
|
|
1737
|
-
name: "insert_data_token",
|
|
1738
|
-
},
|
|
2172
|
+
/* No `aiTool`: `when` is the CARET's, and the caret is the person's — never true for the
|
|
2173
|
+
agent, so a projection would be a tool advertised in no state the model can reach. */
|
|
1739
2174
|
run: (_commandCtx, args) => {
|
|
1740
2175
|
const token = stringArg("insert.data", args, "token");
|
|
1741
2176
|
refuseUnresolvableToken(token);
|