@jxsuite/studio 6.1.2 → 8.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/chunks/2020-5wtzce5g.js +4 -0
- package/dist/chunks/adapter-5tphg7xe.js +4 -0
- package/dist/chunks/add-new-flow-psym14sn.js +4 -0
- package/dist/chunks/cf-account-picker-haqazq5r.js +4 -0
- package/dist/chunks/cf-settings-h2wrh6hq.js +4 -0
- package/dist/chunks/{color-area-0fj8a4ga.js → color-area-6rbra5dy.js} +2 -2
- package/dist/chunks/{color-field-xch8kx2g.js → color-field-gy56c94g.js} +3 -3
- package/dist/chunks/color-m7r1vk54.js +4 -0
- package/dist/chunks/{color-slider-jxd8v350.js → color-slider-sqqdyf6c.js} +2 -2
- package/dist/chunks/{combobox-p0efwjke.js → combobox-72h32ejk.js} +3 -3
- package/dist/chunks/components-r22xca09.js +4 -0
- package/dist/chunks/content-source-mmppmcyg.js +4 -0
- package/dist/chunks/convert-to-repeater-he70fc2b.js +4 -0
- package/dist/chunks/editor-ccd9jwsa.js +4 -0
- package/dist/chunks/entry-commands-6qxz9e8p.js +4 -0
- package/dist/chunks/extension-sections-0egb88dm.js +4 -0
- package/dist/chunks/file-ops-qnab36ek.js +4 -0
- package/dist/chunks/files-rcn56qvm.js +4 -0
- package/dist/chunks/format-host-yxz0kjjs.js +4 -0
- package/dist/chunks/fs-events-d1qxq4z4.js +4 -0
- package/dist/chunks/grid-open-4z1g062t.js +4 -0
- package/dist/chunks/{grid-view-d2wq9ezg.js → grid-view-qg1b5eqx.js} +25 -25
- package/dist/chunks/{icons-pnfz478q.js → icons-63bjtbs7.js} +2 -2
- package/dist/chunks/{iframe-entry-jdcktez8.js → iframe-entry-2zggzajv.js} +4 -4
- package/dist/chunks/{iframe-entry-zap785cw.js → iframe-entry-76j8vwwx.js} +4 -4
- package/dist/chunks/iframe-entry-99nr5zfb.js +5 -0
- package/dist/chunks/{iframe-entry-x0ygf2yr.js → iframe-entry-pkgmcgp0.js} +4 -4
- package/dist/chunks/iframe-host-ssv7kyj0.js +4 -0
- package/dist/chunks/{index-zpjmzqfk.js → index-32eqzv1k.js} +3 -3
- package/dist/chunks/index-f0jn7nnp.js +4 -0
- package/dist/chunks/{javascript-m54mnwp6.js → javascript-pjp734q4.js} +3 -3
- package/dist/chunks/jsonMode-njkvsa02.js +13 -0
- package/dist/chunks/jx-validate-ttasrbh7.js +4 -0
- package/dist/chunks/layers-bgyr11tr.js +4 -0
- package/dist/chunks/layers-panel-7ez66zeq.js +4 -0
- package/dist/chunks/{listbox-e74qjyq6.js → listbox-c421cf8c.js} +2 -2
- package/dist/chunks/lit-html-v9gh687x.js +4 -0
- package/dist/chunks/media-library-sq468wts.js +4 -0
- package/dist/chunks/media-picker-shfe59pt.js +4 -0
- package/dist/chunks/{menu-n6yzswmy.js → menu-bdpzbfvs.js} +2 -2
- package/dist/chunks/{monaco-binding-7gx83x3r.js → monaco-binding-vq1hgnn0.js} +3 -3
- package/dist/chunks/monaco-buffer-3afgwvbp.js +4 -0
- package/dist/chunks/monaco-setup-xrd2cbkp.js +4 -0
- package/dist/chunks/notify-kzrjr3fv.js +4 -0
- package/dist/chunks/parse-v77xtwv7.js +4 -0
- package/dist/chunks/platform-7v4rtd7m.js +4 -0
- package/dist/chunks/popover-b89sfej7.js +4 -0
- package/dist/chunks/publish-panel-2z9gw8ee.js +4 -0
- package/dist/chunks/publish-quick-qx2455cj.js +4 -0
- package/dist/chunks/publish-workspace-wrc1dgwx.js +4 -0
- package/dist/chunks/quick-search-n0t0eqxb.js +4 -0
- package/dist/chunks/references-9547rg5s.js +4 -0
- package/dist/chunks/right-panel-wsgnr9pn.js +4 -0
- package/dist/chunks/source-control-kwktr9y6.js +4 -0
- package/dist/chunks/{split-n2gfpm5m.js → split-c9zfdgxf.js} +2 -2
- package/dist/chunks/studio-03ct6yfv.js +9 -0
- package/dist/chunks/studio-07rcfje3.js +5 -0
- package/dist/chunks/studio-3e54qh39.js +7 -0
- package/dist/chunks/studio-3exxhz5g.js +5 -0
- package/dist/chunks/studio-3q40e3rj.js +5 -0
- package/dist/chunks/studio-3qeh9t0h.js +6 -0
- package/dist/chunks/studio-3qqjeep5.js +6 -0
- package/dist/chunks/studio-43sd2mam.js +4 -0
- package/dist/chunks/studio-4hp8pkyt.js +5 -0
- package/dist/chunks/studio-58xg6j2q.js +9 -0
- package/dist/chunks/studio-5g0rprdt.js +7 -0
- package/dist/chunks/{studio-2j1cb95x.js → studio-6m380wp7.js} +4 -4
- package/dist/chunks/studio-80jyh1xh.js +4 -0
- package/dist/chunks/studio-83mk4bgg.js +9 -0
- package/dist/chunks/{studio-v0jzqdjm.js → studio-881z1xrx.js} +4 -4
- package/dist/chunks/studio-8m0y2qe7.js +5 -0
- package/dist/chunks/{studio-d81xfh1g.js → studio-8tr6cfrc.js} +4 -4
- package/dist/chunks/studio-8vcvfs7r.js +6 -0
- package/dist/chunks/studio-9tmebf0s.js +5 -0
- package/dist/chunks/studio-a2bvaptz.js +5 -0
- package/dist/chunks/studio-b7y5mr30.js +5 -0
- package/dist/chunks/studio-bavb31r0.js +5 -0
- package/dist/chunks/{studio-dgz8d0c1.js → studio-bbe4c90a.js} +4 -4
- package/dist/chunks/studio-c05wdnt3.js +5 -0
- package/dist/chunks/studio-ccv2svc6.js +5 -0
- package/dist/chunks/studio-d5grtb9e.js +16 -0
- package/dist/chunks/studio-df0baea9.js +5 -0
- package/dist/chunks/studio-dgk4dqtx.js +7 -0
- package/dist/chunks/studio-e1g64q43.js +5 -0
- package/dist/chunks/studio-ed1hp6zf.js +6 -0
- package/dist/chunks/studio-ed3xx40h.js +7 -0
- package/dist/chunks/studio-f14e1zdj.js +5 -0
- package/dist/chunks/studio-fbhxxc5f.js +5 -0
- package/dist/chunks/studio-fyh0jc96.js +5 -0
- package/dist/chunks/studio-gcxk20n7.js +5 -0
- package/dist/chunks/studio-jaaz8ce9.js +5 -0
- package/dist/chunks/{studio-90pq9km1.js → studio-jcnsdaep.js} +4 -4
- package/dist/chunks/studio-jsgf2q5k.js +7 -0
- package/dist/chunks/{studio-0q988f9w.js → studio-k3xxbagr.js} +3 -3
- package/dist/chunks/{studio-5ve6bbep.js → studio-k7evxqh4.js} +4 -4
- package/dist/chunks/studio-kt3pjkwd.js +5 -0
- package/dist/chunks/studio-m8g16bgz.js +5 -0
- package/dist/chunks/studio-mn0476ag.js +5 -0
- package/dist/chunks/studio-mx1smyq0.js +5 -0
- package/dist/chunks/studio-n0c5h6mf.js +5 -0
- package/dist/chunks/{studio-485046te.js → studio-nh6d342n.js} +7 -7
- package/dist/chunks/studio-nqxqf8p2.js +4 -0
- package/dist/chunks/studio-p4nrkvqr.js +5 -0
- package/dist/chunks/{studio-1fxkaaea.js → studio-pbxa5fpc.js} +4 -4
- package/dist/chunks/studio-pgmvdv7z.js +7 -0
- package/dist/chunks/studio-ph84avkf.js +5 -0
- package/dist/chunks/{studio-tq0rtfwj.js → studio-q0mvbaq6.js} +4 -4
- package/dist/chunks/studio-q0tccd43.js +5 -0
- package/dist/chunks/studio-q7rtx6zq.js +14 -0
- package/dist/chunks/{studio-a3g98wjr.js → studio-qgh13jtz.js} +4 -4
- package/dist/chunks/studio-qmn1xc24.js +5 -0
- package/dist/chunks/studio-qwdqwkj0.js +5 -0
- package/dist/chunks/studio-r5qy30vx.js +5 -0
- package/dist/chunks/studio-rj9eamf8.js +5 -0
- package/dist/chunks/studio-rptgsk96.js +5 -0
- package/dist/chunks/studio-rthyg42z.js +928 -0
- package/dist/chunks/studio-s19tp1xr.js +5 -0
- package/dist/chunks/studio-s32578pn.js +5 -0
- package/dist/chunks/studio-svb7yyve.js +5 -0
- package/dist/chunks/studio-syreb644.js +5 -0
- package/dist/chunks/studio-tf9jryb1.js +10 -0
- package/dist/chunks/studio-tfkznv39.js +5 -0
- package/dist/chunks/studio-tft6r105.js +5 -0
- package/dist/chunks/studio-txf2kysx.js +5 -0
- package/dist/chunks/studio-v8867ddv.js +12 -0
- package/dist/chunks/studio-vxq7fcvv.js +5 -0
- package/dist/chunks/studio-w4rz9hdk.js +5 -0
- package/dist/chunks/studio-wbcjbhy1.js +9 -0
- package/dist/chunks/studio-wc649wss.js +5 -0
- package/dist/chunks/studio-wys23mxz.js +5 -0
- package/dist/chunks/studio-x1x167jh.js +5 -0
- package/dist/chunks/studio-x9hsze61.js +5 -0
- package/dist/chunks/studio-y0n7yxea.js +9 -0
- package/dist/chunks/studio-y3ahhdpx.js +5 -0
- package/dist/chunks/studio-z97c48fk.js +5 -0
- package/dist/chunks/studio-zat62m0c.js +5 -0
- package/dist/chunks/studio-zcd2e7yz.js +5 -0
- package/dist/chunks/studio-zz9qe3rw.js +64 -0
- package/dist/chunks/toast-1gv0h53h.js +4 -0
- package/dist/chunks/{toast-host-ke5z4ng7.js → toast-host-1yg5ar8d.js} +3 -3
- package/dist/chunks/{tooltip-5v8ngwj2.js → tooltip-yypz28gq.js} +3 -3
- package/dist/chunks/{tree-mdq3v5cw.js → tree-9xa4hm7n.js} +2 -2
- package/dist/chunks/tsMode-epyfz1hv.js +14 -0
- package/dist/chunks/workspace-dz7nxfhv.js +4 -0
- package/dist/chunks/workspace-home-xsd7hkjw.js +4 -0
- package/dist/chunks/{ws-client-nze0k6mv.js → ws-client-bv552sfx.js} +3 -3
- package/dist/iframe-entry.js +20 -16
- package/dist/manifest.json +77 -63
- package/dist/studio.js +103 -104
- package/dist/workers/ts.worker.js +3 -3
- package/package.json +12 -11
- package/src/browse/component-examples.ts +272 -0
- package/src/browse/library-commands.ts +64 -104
- package/src/browse/library-layouts.ts +263 -49
- package/src/browse/library-model.ts +181 -133
- package/src/browse/library-pane.ts +738 -446
- package/src/browse/library-preview.ts +149 -19
- package/src/browse/library-source.ts +308 -41
- package/src/browse/preview-root.ts +78 -0
- package/src/browse/preview-style.ts +155 -0
- package/src/canvas/asset-refs.ts +16 -1
- package/src/canvas/canvas-live-render.ts +222 -30
- package/src/canvas/canvas-origin.ts +37 -12
- package/src/canvas/canvas-page-context.ts +112 -0
- package/src/canvas/canvas-render.ts +113 -107
- package/src/canvas/canvas-utils.ts +57 -12
- package/src/canvas/iframe-drop.ts +107 -0
- package/src/canvas/iframe-entry.ts +24 -12
- package/src/canvas/iframe-host.ts +134 -62
- package/src/canvas/iframe-keys.ts +11 -0
- package/src/canvas/iframe-patch.ts +8 -7
- package/src/canvas/iframe-protocol.ts +24 -5
- package/src/canvas/iframe-render.ts +48 -1
- package/src/canvas/iframe-subtree.ts +5 -2
- package/src/canvas/npm-modules.ts +22 -0
- package/src/canvas/preview-navigate.ts +16 -0
- package/src/canvas/repeater-sources.ts +200 -0
- package/src/canvas/stage-scrollbar.ts +5 -1
- package/src/canvas/surface-registry.ts +6 -0
- package/src/commands/app-commands.ts +16 -6
- package/src/commands/budget.ts +10 -8
- package/src/commands/context.ts +35 -10
- package/src/commands/defaults.ts +69 -45
- package/src/commands/keymap.ts +9 -0
- package/src/commands/levels.ts +11 -5
- package/src/commands/live-context.ts +2 -0
- package/src/commands/registry.ts +10 -1
- package/src/content/collection-match.ts +6 -5
- package/src/content/collection-pages.ts +412 -0
- package/src/content/content-collections.ts +270 -0
- package/src/content/entry-commands.ts +51 -60
- package/src/content/entry-editor.ts +111 -18
- package/src/content/entry-fields.ts +13 -1
- package/src/content/entry-inspector.ts +225 -0
- package/src/content/entry-model.ts +17 -3
- package/src/content/entry-open.ts +80 -0
- package/src/content/entry-summaries.ts +440 -0
- package/src/content/file-record-ids.ts +80 -0
- package/src/content/file-records.ts +125 -0
- package/src/content/page-summaries.ts +129 -0
- package/src/content/record-entry.ts +201 -0
- package/src/content/writing-banner.ts +177 -0
- package/src/create/add-new-commands.ts +185 -0
- package/src/create/add-new-flow.ts +1116 -0
- package/src/create/add-new.ts +1014 -0
- package/src/create/element-name.ts +121 -0
- package/src/editor/convert-to-component.ts +67 -43
- package/src/editor/file-drop-action.ts +9 -1
- package/src/editor/inline-edit-apply.ts +44 -0
- package/src/editor/inline-edit.ts +10 -0
- package/src/editor/insert-component.ts +91 -0
- package/src/editor/insert-zone-action.ts +13 -4
- package/src/editor/shortcuts.ts +44 -22
- package/src/editor/slash-menu.ts +51 -8
- package/src/files/components.ts +74 -10
- package/src/files/file-ops.ts +15 -5
- package/src/files/files.ts +164 -150
- package/src/files/fs-events.ts +18 -7
- package/src/files/media-meta.ts +95 -1
- package/src/files/media-types.ts +55 -0
- package/src/files/media-upload.ts +209 -52
- package/src/files/new-file-name.ts +156 -0
- package/src/files/serialize-document.ts +13 -3
- package/src/format/format-host.ts +15 -0
- package/src/github/github-auth.ts +2 -2
- package/src/github/github-publish.ts +4 -3
- package/src/grid/grid-controller.ts +5 -1
- package/src/grid/grid-open.ts +0 -27
- package/src/grid/grid-panel.ts +54 -2
- package/src/grid/grid-reveal.ts +34 -0
- package/src/grid/grid-source.ts +3 -25
- package/src/grid/grid-view.ts +31 -6
- package/src/grid/sources/content-source.ts +75 -7
- package/src/grid/tabulator-tables.d.ts +6 -0
- package/src/hosting/document.ts +2 -2
- package/src/i18n/i18n-commands.ts +2 -1
- package/src/media/media-commands.ts +181 -0
- package/src/media/media-library-model.ts +232 -0
- package/src/media/media-library.ts +1283 -0
- package/src/media/media-pane.ts +47 -19
- package/src/packages/pull-package-sync.ts +1 -1
- package/src/panels/activity-panel.ts +21 -5
- package/src/panels/ai-chat/chat-markdown.ts +8 -8
- package/src/panels/block-action-bar.ts +11 -11
- package/src/panels/canvas-dnd-bridge.ts +5 -2
- package/src/panels/chat-panel.ts +6 -6
- package/src/panels/collections-panel.ts +306 -0
- package/src/panels/component-preview.ts +35 -13
- package/src/panels/data-explorer.ts +1 -1
- package/src/panels/data-grid.ts +4 -0
- package/src/panels/dnd.ts +17 -30
- package/src/panels/elements-panel.ts +9 -2
- package/src/panels/empty-state.ts +2 -2
- package/src/panels/formula-workspace.ts +2 -3
- package/src/panels/frontmatter-fields.ts +9 -9
- package/src/panels/git-diff-open.ts +9 -5
- package/src/panels/head-panel.ts +369 -103
- package/src/panels/i18n-panel.ts +11 -10
- package/src/panels/imports-panel.ts +2 -0
- package/src/panels/jump-bar.ts +27 -2
- package/src/panels/layers-panel.ts +36 -30
- package/src/panels/left-panel.ts +22 -8
- package/src/panels/navigator-panels.ts +23 -11
- package/src/panels/pane-context.ts +111 -29
- package/src/panels/pane-grid.ts +6 -6
- package/src/panels/panel-registry.ts +14 -9
- package/src/panels/properties-panel.ts +7 -3
- package/src/panels/right-panel.ts +199 -43
- package/src/panels/seo-modal.ts +41 -108
- package/src/panels/settings-menu.ts +52 -50
- package/src/panels/settings-pane.ts +268 -162
- package/src/panels/signals-panel.ts +3 -4
- package/src/panels/site-model.ts +367 -0
- package/src/panels/site-panel.ts +638 -0
- package/src/panels/style-panel.ts +37 -3
- package/src/panels/stylebook-doc.ts +142 -10
- package/src/panels/stylebook-layers-panel.ts +39 -80
- package/src/panels/stylebook-panel.ts +47 -10
- package/src/panels/styles-panel.ts +327 -0
- package/src/panels/tab-strip.ts +109 -25
- package/src/platform.ts +1 -1
- package/src/platforms/cloud.ts +28 -1
- package/src/platforms/default-platform.ts +4 -4
- package/src/platforms/devserver.ts +51 -25
- package/src/publish/deploy-checklist.ts +12 -7
- package/src/publish/pages-service.ts +38 -14
- package/src/publish/publish-changes.ts +491 -0
- package/src/publish/publish-commands.ts +83 -18
- package/src/publish/publish-ids.ts +49 -0
- package/src/publish/publish-quick.ts +148 -0
- package/src/publish/publish-workspace.ts +926 -0
- package/src/publish/source-control.ts +907 -0
- package/src/services/automation.ts +16 -20
- package/src/services/cf-settings.ts +4 -4
- package/src/services/connection.ts +2 -2
- package/src/services/directory-picker.ts +2 -2
- package/src/services/references.ts +0 -0
- package/src/services/render-critic.ts +21 -2
- package/src/services/settings/definitions.ts +25 -14
- package/src/settings/contributed-section.ts +49 -10
- package/src/settings/css-vars-editor.ts +93 -27
- package/src/settings/developer-panels.ts +43 -0
- package/src/settings/extension-sections.ts +20 -2
- package/src/settings/general-settings.ts +91 -21
- package/src/settings/preferences-dialog.ts +8 -1
- package/src/settings/project-sections.ts +27 -10
- package/src/settings/schema-field-ui.ts +3 -1
- package/src/settings/section-registry.ts +116 -11
- package/src/settings/settings-dialog.ts +192 -0
- package/src/settings/settings-document.ts +182 -162
- package/src/shell.ts +467 -431
- package/src/site-context.ts +64 -10
- package/src/state.ts +28 -9
- package/src/studio.ts +194 -41
- package/src/style/project-styles.ts +34 -0
- package/src/style/stylebook-specimens.ts +89 -0
- package/src/style/stylebook-target.ts +26 -0
- package/src/style/tag-inheritance.ts +105 -0
- package/src/style/variables-focus.ts +61 -0
- package/src/style/variables-view.ts +235 -0
- package/src/surfaces/add-new.json +1482 -0
- package/src/surfaces/add-new.ts +325 -0
- package/src/surfaces/ai-chat.ts +2 -2
- package/src/surfaces/boot-failure.json +4 -3
- package/src/surfaces/bottom-dock.json +1 -1
- package/src/surfaces/canvas-stage.json +30 -19
- package/src/surfaces/canvas-stage.ts +5 -5
- package/src/surfaces/collections-panel.json +615 -0
- package/src/surfaces/collections-panel.ts +168 -0
- package/src/surfaces/commandbar.json +241 -96
- package/src/surfaces/commandbar.ts +134 -99
- package/src/surfaces/empty-state.json +1 -1
- package/src/surfaces/entry-editor.json +136 -0
- package/src/surfaces/entry-editor.ts +21 -0
- package/src/surfaces/entry-inspector.json +371 -0
- package/src/surfaces/entry-inspector.ts +143 -0
- package/src/surfaces/inspector-dock.json +162 -14
- package/src/surfaces/inspector-dock.ts +46 -19
- package/src/surfaces/library-pane.json +670 -437
- package/src/surfaces/library-pane.ts +94 -59
- package/src/surfaces/media-browser.json +62 -6
- package/src/surfaces/media-browser.ts +15 -1
- package/src/surfaces/media-field.json +1 -1
- package/src/surfaces/media-library.json +1586 -0
- package/src/surfaces/media-library.ts +282 -0
- package/src/surfaces/media-pick-dialog.json +71 -0
- package/src/surfaces/media-pick-dialog.ts +132 -0
- package/src/surfaces/menu.ts +18 -0
- package/src/surfaces/pane-context.json +144 -77
- package/src/surfaces/pane-context.ts +24 -0
- package/src/surfaces/panel-deploy-checklist.json +12 -6
- package/src/surfaces/panel-deploy-checklist.ts +3 -1
- package/src/surfaces/panel-page.json +72 -2
- package/src/surfaces/panel-page.ts +38 -7
- package/src/surfaces/panel-signals.json +1 -1
- package/src/surfaces/panel-signals.ts +5 -5
- package/src/surfaces/panel-stylebook-layers.json +71 -204
- package/src/surfaces/panel-stylebook-layers.ts +0 -21
- package/src/surfaces/preferences.json +120 -48
- package/src/surfaces/preferences.ts +8 -0
- package/src/surfaces/publish-quick.json +428 -0
- package/src/surfaces/publish-quick.ts +165 -0
- package/src/surfaces/publish-workspace.json +2892 -0
- package/src/surfaces/publish-workspace.ts +391 -0
- package/src/surfaces/rail.json +1 -159
- package/src/surfaces/rail.ts +18 -75
- package/src/surfaces/schema-form.json +10 -2
- package/src/surfaces/schema-form.ts +2 -0
- package/src/surfaces/seo.json +1 -1
- package/src/surfaces/settings-contributed.json +5 -5
- package/src/surfaces/settings-contributed.ts +18 -2
- package/src/surfaces/settings-css-vars.json +44 -36
- package/src/surfaces/settings-css-vars.ts +77 -4
- package/src/surfaces/settings-deploy.json +2 -15
- package/src/surfaces/settings-deploy.ts +1 -1
- package/src/surfaces/settings-dialog.json +51 -0
- package/src/surfaces/settings-dialog.ts +169 -0
- package/src/surfaces/settings-overview.json +3 -3
- package/src/surfaces/settings-overview.ts +9 -2
- package/src/surfaces/settings-pane.json +269 -46
- package/src/surfaces/settings-pane.ts +85 -24
- package/src/surfaces/shell.json +2 -1
- package/src/surfaces/site-panel.json +1029 -0
- package/src/surfaces/site-panel.ts +233 -0
- package/src/surfaces/slash-menu.json +63 -21
- package/src/surfaces/slash-menu.ts +23 -0
- package/src/surfaces/statusbar.ts +39 -15
- package/src/surfaces/styles-panel.json +735 -0
- package/src/surfaces/styles-panel.ts +195 -0
- package/src/surfaces/styles-variables.json +149 -0
- package/src/surfaces/styles-variables.ts +145 -0
- package/src/surfaces/tab-strip.json +4 -4
- package/src/surfaces/welcome.ts +1 -1
- package/src/surfaces/writing-banner.json +94 -0
- package/src/surfaces/writing-banner.ts +80 -0
- package/src/tabs/bare-repeaters.ts +101 -0
- package/src/tabs/tab.ts +47 -7
- package/src/types.ts +21 -26
- package/src/ui/form-controls.ts +47 -8
- package/src/ui/layers.ts +13 -0
- package/src/ui/media-picker.ts +284 -40
- package/src/ui/regions.ts +7 -6
- package/src/ui/schema-form.ts +259 -27
- package/src/ui/virtual-window.ts +26 -1
- package/src/utils/base64.ts +3 -3
- package/src/utils/edit-display.ts +322 -67
- package/src/utils/local-day.ts +18 -0
- package/src/workspace/pane-derive.ts +4 -4
- package/src/workspace/session.ts +28 -7
- package/src/workspace/tab-workspace.ts +137 -0
- package/src/workspace/workspace-back.ts +189 -0
- package/src/workspace/workspace-home.ts +133 -0
- package/src/workspace/workspace-ids.ts +129 -0
- package/src/workspace/workspace-switch.ts +372 -0
- package/src/workspace/workspace.ts +125 -11
- package/styles/shell-frame.css +30 -7
- package/styles/shell-frame.json +15 -3
- package/dist/chunks/2020-f2gkpy8d.js +0 -4
- package/dist/chunks/adapter-4912g339.js +0 -4
- package/dist/chunks/cf-account-picker-wccaenh6.js +0 -4
- package/dist/chunks/cf-settings-br6105tr.js +0 -4
- package/dist/chunks/color-28ksk2qm.js +0 -4
- package/dist/chunks/components-db68vsn7.js +0 -4
- package/dist/chunks/content-source-1449qesq.js +0 -4
- package/dist/chunks/convert-to-repeater-5h457egj.js +0 -4
- package/dist/chunks/editor-x9jn86a7.js +0 -4
- package/dist/chunks/entry-commands-may24cpt.js +0 -4
- package/dist/chunks/extension-sections-pvr14vxr.js +0 -4
- package/dist/chunks/file-ops-x9v54pcj.js +0 -4
- package/dist/chunks/files-j3knqf0s.js +0 -4
- package/dist/chunks/format-host-tyre2trb.js +0 -4
- package/dist/chunks/fs-events-64ma9htc.js +0 -4
- package/dist/chunks/git-panel-84ps5dex.js +0 -4
- package/dist/chunks/iframe-entry-fvbk89gm.js +0 -5
- package/dist/chunks/iframe-host-ck6vejt5.js +0 -4
- package/dist/chunks/index-b8xw3vy9.js +0 -4
- package/dist/chunks/jsonMode-w15cmrcm.js +0 -13
- package/dist/chunks/jx-validate-at3zn8wa.js +0 -4
- package/dist/chunks/layers-h4xp1pss.js +0 -4
- package/dist/chunks/layers-panel-m5hw1d7g.js +0 -4
- package/dist/chunks/lit-html-8t8t3dnr.js +0 -4
- package/dist/chunks/media-picker-2cweexc5.js +0 -4
- package/dist/chunks/menu-ynw13y0s.js +0 -4
- package/dist/chunks/monaco-buffer-qzxn567r.js +0 -4
- package/dist/chunks/monaco-setup-gxf6656g.js +0 -4
- package/dist/chunks/notify-cj5zbrs2.js +0 -4
- package/dist/chunks/parse-b7ddhr8m.js +0 -4
- package/dist/chunks/platform-3dfws9js.js +0 -4
- package/dist/chunks/popover-jt2gxmzs.js +0 -4
- package/dist/chunks/publish-panel-1gvxbj21.js +0 -4
- package/dist/chunks/quick-search-0dajrwqg.js +0 -4
- package/dist/chunks/references-49qgt404.js +0 -4
- package/dist/chunks/right-panel-jm1bwe53.js +0 -4
- package/dist/chunks/section-registry-6kwc4fky.js +0 -4
- package/dist/chunks/studio-0rt52vpq.js +0 -5
- package/dist/chunks/studio-18vgbhs5.js +0 -5
- package/dist/chunks/studio-24mccdrj.js +0 -5
- package/dist/chunks/studio-2eh507zk.js +0 -9
- package/dist/chunks/studio-2hcbccfv.js +0 -5
- package/dist/chunks/studio-2jbs3rxv.js +0 -5
- package/dist/chunks/studio-4h8k4dw9.js +0 -5
- package/dist/chunks/studio-5f6n18kx.js +0 -5
- package/dist/chunks/studio-5gthpky6.js +0 -5
- package/dist/chunks/studio-6ep3js6b.js +0 -9
- package/dist/chunks/studio-6wkmf3wz.js +0 -9
- package/dist/chunks/studio-841rf3cg.js +0 -5
- package/dist/chunks/studio-8gmwgheg.js +0 -5
- package/dist/chunks/studio-8qm0ep50.js +0 -5
- package/dist/chunks/studio-924p1tm1.js +0 -6
- package/dist/chunks/studio-a3shpz9y.js +0 -5
- package/dist/chunks/studio-amsbaaar.js +0 -6
- package/dist/chunks/studio-at5spjbc.js +0 -7
- package/dist/chunks/studio-b2xv945e.js +0 -5
- package/dist/chunks/studio-bn5nkafw.js +0 -5
- package/dist/chunks/studio-bw6q5xjf.js +0 -9
- package/dist/chunks/studio-c7q0t9x1.js +0 -5
- package/dist/chunks/studio-camnhc96.js +0 -6
- package/dist/chunks/studio-cffqvnzd.js +0 -5
- package/dist/chunks/studio-efvfrsf8.js +0 -5
- package/dist/chunks/studio-er30bpcx.js +0 -5
- package/dist/chunks/studio-ezscgr64.js +0 -5
- package/dist/chunks/studio-ffrrncvz.js +0 -5
- package/dist/chunks/studio-fpphgn8y.js +0 -10
- package/dist/chunks/studio-j1kvhdjk.js +0 -4
- package/dist/chunks/studio-j430n16g.js +0 -7
- package/dist/chunks/studio-jjkg84nj.js +0 -5
- package/dist/chunks/studio-m0q32ars.js +0 -4
- package/dist/chunks/studio-m6bdst11.js +0 -5
- package/dist/chunks/studio-nv2cptd4.js +0 -64
- package/dist/chunks/studio-nwfrc98n.js +0 -5
- package/dist/chunks/studio-p1wgvp7r.js +0 -5
- package/dist/chunks/studio-pag2wncm.js +0 -5
- package/dist/chunks/studio-qvanvzfd.js +0 -5
- package/dist/chunks/studio-qwa64kt7.js +0 -5
- package/dist/chunks/studio-rk1zc4x3.js +0 -928
- package/dist/chunks/studio-se2r3ptc.js +0 -5
- package/dist/chunks/studio-sg2a0dh0.js +0 -5
- package/dist/chunks/studio-tjzjhe68.js +0 -5
- package/dist/chunks/studio-v2w7q8r1.js +0 -7
- package/dist/chunks/studio-v5vjq1h0.js +0 -4
- package/dist/chunks/studio-v8aga3vp.js +0 -14
- package/dist/chunks/studio-vfcdrfmv.js +0 -5
- package/dist/chunks/studio-vmfkgdjf.js +0 -5
- package/dist/chunks/studio-wt1816jj.js +0 -5
- package/dist/chunks/studio-wz73q5kq.js +0 -4
- package/dist/chunks/studio-y04qtxvp.js +0 -7
- package/dist/chunks/studio-y21g8zzg.js +0 -5
- package/dist/chunks/studio-y64hrt8p.js +0 -12
- package/dist/chunks/studio-ynn90f58.js +0 -16
- package/dist/chunks/studio-yxz682sx.js +0 -5
- package/dist/chunks/studio-zp7snvkq.js +0 -5
- package/dist/chunks/studio-zq4z6tm6.js +0 -5
- package/dist/chunks/toast-c9fn075p.js +0 -4
- package/dist/chunks/tsMode-sf49ee9x.js +0 -14
- package/dist/chunks/workspace-jtfahpee.js +0 -4
- package/src/panels/frontmatter-panel.ts +0 -711
- package/src/panels/git-panel.ts +0 -1108
- package/src/surfaces/doc-header.json +0 -776
- package/src/surfaces/doc-header.ts +0 -222
- package/src/surfaces/git-panel.json +0 -1880
- package/src/surfaces/git-panel.ts +0 -264
|
@@ -23,6 +23,7 @@ import { disposeSubtree, renderSubtreeIframe } from "./iframe-subtree";
|
|
|
23
23
|
import {
|
|
24
24
|
computeEmptyPlaceholderClass,
|
|
25
25
|
EMPTY_PLACEHOLDER_CLASSES,
|
|
26
|
+
isRowBound,
|
|
26
27
|
templateToEditDisplay,
|
|
27
28
|
} from "../utils/edit-display";
|
|
28
29
|
import type { IframeRenderCtx } from "./iframe-render";
|
|
@@ -342,7 +343,7 @@ function patchStyle(
|
|
|
342
343
|
/* SAFETY: buildScope writes `$media` only from the document's own `$media` map or the runtime's
|
|
343
344
|
* root media map, both Record<string, string>, and the host scope may not supply the key. */
|
|
344
345
|
const mediaQueries = (ctx?.defs["$media"] as Record<string, string> | undefined) ?? {};
|
|
345
|
-
reapplyStyle(el, editModeStyle(node?.style), mediaQueries);
|
|
346
|
+
reapplyStyle(el, editModeStyle(node?.style), mediaQueries, ctx?.defs ?? {});
|
|
346
347
|
}
|
|
347
348
|
|
|
348
349
|
/** Write the node's display text, syncing the empty-placeholder class like the full render. */
|
|
@@ -371,8 +372,9 @@ function findElement(container: HTMLElement, path: (string | number)[]): HTMLEle
|
|
|
371
372
|
}
|
|
372
373
|
|
|
373
374
|
/**
|
|
374
|
-
* Edit-mode style transform — mirrors prepareForEditMode
|
|
375
|
-
*
|
|
375
|
+
* Edit-mode style transform — mirrors prepareForEditMode: bindings are live and resolve against the
|
|
376
|
+
* render's scope, except a declaration that reads the repeater row, which the perimeter cannot
|
|
377
|
+
* supply and so is omitted.
|
|
376
378
|
*/
|
|
377
379
|
function editModeStyle(style: JxStyle | undefined): JxStyle | undefined {
|
|
378
380
|
if (!style || !isNonNullObject(style)) {
|
|
@@ -380,10 +382,9 @@ function editModeStyle(style: JxStyle | undefined): JxStyle | undefined {
|
|
|
380
382
|
}
|
|
381
383
|
const out: JxStyle = {};
|
|
382
384
|
for (const [k, v] of Object.entries(style)) {
|
|
383
|
-
/* OMITTED, not blanked
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
if (isString(v) && v.includes("${")) {
|
|
385
|
+
/* OMITTED, not blanked: `color: ` is a malformed declaration in a rule, and an absent one lets
|
|
386
|
+
the cascade answer, which is what blanking always meant. */
|
|
387
|
+
if (isRowBound(v)) {
|
|
387
388
|
continue;
|
|
388
389
|
}
|
|
389
390
|
out[k] = v;
|
|
@@ -77,6 +77,12 @@ export interface WireDiffMark {
|
|
|
77
77
|
/** An artboard's whole mark set. Each side receives only its own; `[]` clears. */
|
|
78
78
|
export type WireDiffMarks = readonly WireDiffMark[];
|
|
79
79
|
|
|
80
|
+
/** A language as the frame applies it: the BCP 47 tag for `lang`, and its direction for `dir`. */
|
|
81
|
+
export interface WireLocale {
|
|
82
|
+
locale: string;
|
|
83
|
+
dir: "ltr" | "rtl";
|
|
84
|
+
}
|
|
85
|
+
|
|
80
86
|
/** Messages the editor (parent) sends into the canvas iframe. */
|
|
81
87
|
export type ParentToIframe =
|
|
82
88
|
| { kind: "init"; gen: number }
|
|
@@ -135,6 +141,13 @@ export type ParentToIframe =
|
|
|
135
141
|
* every re-render would close the panel the author is editing.
|
|
136
142
|
*/
|
|
137
143
|
popoverOpen?: (string | number)[] | null;
|
|
144
|
+
/**
|
|
145
|
+
* The language the artboard is drawn in, carried on `render` for `colorScheme`'s reason: a
|
|
146
|
+
* frame that boots after the pane's locale was posted (a new host, a reload) would otherwise
|
|
147
|
+
* draw an Arabic document left to right until the locale next CHANGED. Absent or null clears
|
|
148
|
+
* `lang` and `dir`.
|
|
149
|
+
*/
|
|
150
|
+
locale?: WireLocale | null;
|
|
138
151
|
/** The dialog to draw open after this render, for the same reason. */
|
|
139
152
|
dialogOpen?: (string | number)[] | null;
|
|
140
153
|
gen: number;
|
|
@@ -188,8 +201,10 @@ export type ParentToIframe =
|
|
|
188
201
|
* the frame — `localeDirection` is CLDR's answer via `Intl.Locale`, and the frame has no reason
|
|
189
202
|
* to hold a second copy of the RTL script list.
|
|
190
203
|
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
204
|
+
* The host posts the language the pane DRAWS, not only an override: the preview choice, else the
|
|
205
|
+
* file's own, else the site default (`canvasLocaleOf`). `null` is a project that declares no
|
|
206
|
+
* locales: both attributes come off, and the frame falls back to whatever the rendered document
|
|
207
|
+
* declares.
|
|
193
208
|
*/
|
|
194
209
|
| { kind: "setLocale"; locale: string | null; dir: "ltr" | "rtl" }
|
|
195
210
|
/**
|
|
@@ -377,10 +392,14 @@ export type DropInstructionType = "reorder-above" | "reorder-below" | "make-chil
|
|
|
377
392
|
|
|
378
393
|
/**
|
|
379
394
|
* The kind of thing being dragged. `tree-node` carries the source's existing document path (a
|
|
380
|
-
* move); `block` carries
|
|
381
|
-
* retained PARENT-SIDE keyed by `dragSeq` and never crosses the boundary.
|
|
395
|
+
* move); `block` carries only its fragment's tag on the wire — its full `fragment` (a
|
|
396
|
+
* {@link JxMutableNode}) is retained PARENT-SIDE keyed by `dragSeq` and never crosses the boundary.
|
|
397
|
+
* The tag is what lets the iframe keep a block out of a paragraph (`iframe-drop.ts`); an OS file
|
|
398
|
+
* drag has none, and is placed as a block.
|
|
382
399
|
*/
|
|
383
|
-
export type DragSrcKind =
|
|
400
|
+
export type DragSrcKind =
|
|
401
|
+
| { type: "tree-node"; path: (string | number)[] }
|
|
402
|
+
| { type: "block"; tag?: string };
|
|
384
403
|
|
|
385
404
|
/**
|
|
386
405
|
* A display-only drop preview the iframe posts on `dragOver`: where the drop indicator should draw
|
|
@@ -37,7 +37,7 @@ import { classifyRenderNode, jxPathSelector, serializeJxPath } from "./path-mapp
|
|
|
37
37
|
import { elementForPath } from "./iframe-position";
|
|
38
38
|
import type { AssetContext } from "./asset-resolve";
|
|
39
39
|
import { SITE_STYLE_ID, buildSiteStyleCSS } from "@jxsuite/site/site-style";
|
|
40
|
-
import type { CanvasMode, WireDiffMarks } from "./iframe-protocol";
|
|
40
|
+
import type { CanvasMode, WireDiffMarks, WireLocale } from "./iframe-protocol";
|
|
41
41
|
import { isNonNullObject, isString } from "@jxsuite/schema/guards";
|
|
42
42
|
import type { JxDocument, JxElement, JxStyle } from "@jxsuite/schema/types";
|
|
43
43
|
import type { PathMapCtx } from "./path-mapping";
|
|
@@ -631,6 +631,10 @@ export const STYLEBOOK_CSS = `
|
|
|
631
631
|
.element-card-preview > * {
|
|
632
632
|
max-width: 100%;
|
|
633
633
|
margin: 0;
|
|
634
|
+
}
|
|
635
|
+
/* A list keeps its inline-start padding: its markers are drawn in it, and with none they are
|
|
636
|
+
clipped by the card ("1." shows as "."). Every other specimen sits flush in its card. */
|
|
637
|
+
.element-card-preview > :not(ol, ul, menu) {
|
|
634
638
|
padding: 0;
|
|
635
639
|
}
|
|
636
640
|
.element-card-preview > hr {
|
|
@@ -728,6 +732,49 @@ export function applyPreviewColorScheme(doc: Document, scheme: "light" | "dark"
|
|
|
728
732
|
}
|
|
729
733
|
}
|
|
730
734
|
|
|
735
|
+
/** The `lang` and `dir` a frame's root booted with, which a frame with no language goes back to. */
|
|
736
|
+
export interface LocaleBaseline {
|
|
737
|
+
lang: string | null;
|
|
738
|
+
dir: string | null;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
/** Read the root's `lang` and `dir` as the frame booted them (`canvas.html` is `lang="en"`). */
|
|
742
|
+
export function captureLocaleBaseline(doc: Document): LocaleBaseline {
|
|
743
|
+
const root = doc.documentElement;
|
|
744
|
+
return { dir: root.getAttribute("dir"), lang: root.getAttribute("lang") };
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
/** Write one root attribute, or remove it for null. */
|
|
748
|
+
function setRootAttribute(root: Element, name: string, value: string | null): void {
|
|
749
|
+
if (value === null) {
|
|
750
|
+
root.removeAttribute(name);
|
|
751
|
+
} else {
|
|
752
|
+
root.setAttribute(name, value);
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
/**
|
|
757
|
+
* Set the artboard's language (studio.md §20.2): `lang` and `dir` on the frame's root, the only
|
|
758
|
+
* writer of either. `dir` is what makes an RTL document actually mirror, and `lang` is what CSS's
|
|
759
|
+
* `:lang()` and the font stack select on. The root survives a render, which replaces only the
|
|
760
|
+
* container's children, so the value holds until the next one arrives.
|
|
761
|
+
*
|
|
762
|
+
* `null`, a project that declares no locales, restores the language the frame booted with rather
|
|
763
|
+
* than removing it, so applying the value on every render does not strip `canvas.html`'s
|
|
764
|
+
* `lang="en"` from every canvas of a monolingual project. A left-to-right language writes no
|
|
765
|
+
* `dir="ltr"`, as the built page never does (`site-architecture.md` §13.4): it restores the booted
|
|
766
|
+
* `dir`.
|
|
767
|
+
*/
|
|
768
|
+
export function applyPreviewLocale(
|
|
769
|
+
doc: Document,
|
|
770
|
+
locale: WireLocale | null,
|
|
771
|
+
baseline: LocaleBaseline,
|
|
772
|
+
): void {
|
|
773
|
+
const root = doc.documentElement;
|
|
774
|
+
setRootAttribute(root, "lang", locale?.locale ?? baseline.lang);
|
|
775
|
+
setRootAttribute(root, "dir", locale?.dir === "rtl" ? "rtl" : baseline.dir);
|
|
776
|
+
}
|
|
777
|
+
|
|
731
778
|
/**
|
|
732
779
|
* Draw the popover at `path` open, and every other one closed.
|
|
733
780
|
*
|
|
@@ -15,7 +15,7 @@ import { releaseElementStyles, renderNode, runScoped } from "@jxsuite/runtime";
|
|
|
15
15
|
import { isNumber, isString } from "@jxsuite/schema/guards";
|
|
16
16
|
import { getNodeAtPath } from "../state";
|
|
17
17
|
import { makeStamper } from "./iframe-render";
|
|
18
|
-
import { prepareForEditMode } from "../utils/edit-display";
|
|
18
|
+
import { prepareForEditMode, sampleRowAt } from "../utils/edit-display";
|
|
19
19
|
import { stripEventHandlers } from "../utils/strip-events";
|
|
20
20
|
import type { IframeRenderCtx } from "./iframe-render";
|
|
21
21
|
import type { JxPath } from "../state";
|
|
@@ -47,7 +47,10 @@ export function renderSubtreeIframe(
|
|
|
47
47
|
if (node === undefined) {
|
|
48
48
|
throw new Error(`iframe-patch-node-not-found:${docPath.join("/")}`);
|
|
49
49
|
}
|
|
50
|
-
|
|
50
|
+
// Inside a repeater, the template is drawn with the sample row the full render used.
|
|
51
|
+
const def = isString(node)
|
|
52
|
+
? node
|
|
53
|
+
: prepareForEditMode(stripEventHandlers(node), sampleRowAt(shadowDoc, docPath));
|
|
51
54
|
const { result: rendered, stop } = runScoped(() =>
|
|
52
55
|
renderNode(def, ctx.defs, {
|
|
53
56
|
_path: docPathToRenderPath(docPath, ctx),
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a live render imports an `npm:` package from (spec.md §5.3, 4c).
|
|
3
|
+
*
|
|
4
|
+
* The dev server answers `/node_modules/<package>/<subpath>` by resolving the package's `exports`
|
|
5
|
+
* and bundling the entry on demand (`@jxsuite/server`), the same URL space a bare `$elements`
|
|
6
|
+
* specifier and a bare `$head` asset are already fetched from. Both realms that render a project
|
|
7
|
+
* live install it into the runtime (`setNpmModuleResolver`): the canvas frame against its own
|
|
8
|
+
* address, and the editor window, which draws the Site panel's and the Content home's previews,
|
|
9
|
+
* against the project's asset origin.
|
|
10
|
+
*
|
|
11
|
+
* Dependency-free so it rides in the slim canvas bundle.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The URL a package specifier is imported from, under `base`.
|
|
16
|
+
*
|
|
17
|
+
* @param specifier - `@scope/pkg/subpath`, as the document wrote it after `npm:`
|
|
18
|
+
* @param base - The origin (or any URL on it) that serves the project
|
|
19
|
+
*/
|
|
20
|
+
export function npmModuleUrl(specifier: string, base: string): string {
|
|
21
|
+
return new URL(`/node_modules/${specifier}`, base).href;
|
|
22
|
+
}
|
|
@@ -24,3 +24,19 @@ export function setPreviewNavigateHandler(next: PreviewNavigateHandler | null):
|
|
|
24
24
|
export function getPreviewNavigateHandler(): PreviewNavigateHandler | null {
|
|
25
25
|
return handler;
|
|
26
26
|
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Hand a URL to the user's real browser.
|
|
30
|
+
*
|
|
31
|
+
* Reuses the seam the desktop launchers already register for Preview link clicks, which routes
|
|
32
|
+
* through the OS rather than navigating a webview with no address bar; the browser build falls back
|
|
33
|
+
* to a new tab. One function, because Open in Browser and the Publish workspace's Visit site and
|
|
34
|
+
* deployment links all mean the same thing by "open this outside Studio".
|
|
35
|
+
*/
|
|
36
|
+
export function openUrlExternally(url: string): void {
|
|
37
|
+
if (handler) {
|
|
38
|
+
handler(url);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
42
|
+
}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The data a repeater is drawn from in Edit and Design, resolved before the canvas renders.
|
|
3
|
+
*
|
|
4
|
+
* Edit mode draws a repeater as one instance of its row template, with the repeater's first item as
|
|
5
|
+
* that instance's sample row (`utils/edit-display.ts`). A collection is a class-backed state entry
|
|
6
|
+
* (`ContentCollection`) the canvas runtime resolves through the dev proxy AFTER its first render,
|
|
7
|
+
* so the instance connected with an empty row: a component that formats a date or a locale threw,
|
|
8
|
+
* was reported as not rendered, and drew itself only when the data arrived. Resolving the entry
|
|
9
|
+
* here, the way `page-params.ts` bakes a param-bound entry for Preview, puts the row in the state
|
|
10
|
+
* the canvas builds its scope from, so the first render is a render of the data.
|
|
11
|
+
*
|
|
12
|
+
* The same resolution serves every mode for an entry that names an enabled extension's class by a
|
|
13
|
+
* bare `$prototype` ({@link extensionClassKeys}), which the build also resolves before rendering.
|
|
14
|
+
*
|
|
15
|
+
* Only an entry whose configuration holds no template is baked: one that does is re-resolved by the
|
|
16
|
+
* runtime whenever what it reads changes, and a baked copy would freeze it. Answers are cached by
|
|
17
|
+
* the entry's configuration until the project's content changes ({@link
|
|
18
|
+
* invalidateRepeaterSources}).
|
|
19
|
+
*
|
|
20
|
+
* @docs studio/interface/canvas
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { isJsonObject, isNodeObject, isRef, isString } from "@jxsuite/schema/guards";
|
|
24
|
+
import { getPlatform } from "../platform";
|
|
25
|
+
import type {
|
|
26
|
+
JsonObject,
|
|
27
|
+
JsonValue,
|
|
28
|
+
JxDocumentValue,
|
|
29
|
+
JxMutableNode,
|
|
30
|
+
JxStateDefinition,
|
|
31
|
+
} from "@jxsuite/schema/types";
|
|
32
|
+
|
|
33
|
+
/** What the backend answered for one entry, or `null` when it could not resolve it. */
|
|
34
|
+
type Resolved = JsonValue | null;
|
|
35
|
+
|
|
36
|
+
/** Resolved entries by their request body, so a re-render does not ask the backend again. */
|
|
37
|
+
let _cache = new Map<string, Promise<Resolved>>();
|
|
38
|
+
|
|
39
|
+
/** Forget every resolved entry; the next render asks the backend again. */
|
|
40
|
+
export function invalidateRepeaterSources(): void {
|
|
41
|
+
_cache = new Map();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** The top-level state key a `#/state/<key>/…` pointer reads, or null for any other pointer. */
|
|
45
|
+
function stateKeyOf(ref: string): string | null {
|
|
46
|
+
if (!ref.startsWith("#/state/")) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
const [key] = ref.slice("#/state/".length).split("/");
|
|
50
|
+
return key ? key.replaceAll("~1", "/").replaceAll("~0", "~") : null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Whether a configuration value holds a `${…}` template anywhere inside it. */
|
|
54
|
+
function holdsTemplate(value: JsonValue | undefined): boolean {
|
|
55
|
+
if (isString(value)) {
|
|
56
|
+
return value.includes("${");
|
|
57
|
+
}
|
|
58
|
+
if (Array.isArray(value)) {
|
|
59
|
+
return value.some((member) => holdsTemplate(member));
|
|
60
|
+
}
|
|
61
|
+
return isJsonObject(value) && Object.values(value).some((member) => holdsTemplate(member));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Extension class names to their descriptor paths, as `getEffectiveImports` merges them. */
|
|
65
|
+
export type ClassPaths = Readonly<Record<string, string>>;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The `$src` a class-backed state entry resolves from: its own, else the enabled extension class
|
|
69
|
+
* its bare `$prototype` names (spec.md §12.5), else null.
|
|
70
|
+
*/
|
|
71
|
+
function classSourceOf(entry: JsonObject, classes: ClassPaths): string | null {
|
|
72
|
+
if (isString(entry.$src)) {
|
|
73
|
+
return entry.$src;
|
|
74
|
+
}
|
|
75
|
+
return isString(entry.$prototype) && Object.hasOwn(classes, entry.$prototype)
|
|
76
|
+
? (classes[entry.$prototype] ?? null)
|
|
77
|
+
: null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Whether a state entry is a class-backed source the backend can resolve once, for good. */
|
|
81
|
+
function isStaticClassEntry(
|
|
82
|
+
entry: JxStateDefinition | undefined,
|
|
83
|
+
classes: ClassPaths = {},
|
|
84
|
+
): entry is JsonObject {
|
|
85
|
+
return (
|
|
86
|
+
isJsonObject(entry) &&
|
|
87
|
+
isString(entry.$prototype) &&
|
|
88
|
+
classSourceOf(entry, classes) !== null &&
|
|
89
|
+
!holdsTemplate(entry)
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* The state keys of `doc` that name an enabled extension's class by a bare `$prototype` (a layout's
|
|
95
|
+
* `{ "$prototype": "ContentEntry", ... }`) and can be resolved once.
|
|
96
|
+
*
|
|
97
|
+
* The build resolves these before any template runs (`compiler/src/site/prototype-resolver.ts`).
|
|
98
|
+
* Left to the canvas runtime, the class's descriptor path, a file on disk, was first fetched as a
|
|
99
|
+
* URL of the canvas, answered 404, and only then asked of the dev proxy: one failed request per
|
|
100
|
+
* entry per render, on every page of a site whose layout reads its navigation this way.
|
|
101
|
+
*/
|
|
102
|
+
export function extensionClassKeys(doc: JxMutableNode, classes: ClassPaths): string[] {
|
|
103
|
+
return Object.entries(doc.state ?? {})
|
|
104
|
+
.filter(
|
|
105
|
+
([, entry]) =>
|
|
106
|
+
isJsonObject(entry) && !isString(entry.$src) && isStaticClassEntry(entry, classes),
|
|
107
|
+
)
|
|
108
|
+
.map(([key]) => key);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* The state keys `doc`'s repeaters read their items from, among them only the class-backed entries
|
|
113
|
+
* {@link bakeRepeaterSources} can resolve.
|
|
114
|
+
*/
|
|
115
|
+
export function repeaterSourceKeys(doc: JxMutableNode): string[] {
|
|
116
|
+
const keys = new Set<string>();
|
|
117
|
+
const walk = (value: JxDocumentValue | undefined): void => {
|
|
118
|
+
if (Array.isArray(value)) {
|
|
119
|
+
for (const member of value) {
|
|
120
|
+
walk(member);
|
|
121
|
+
}
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (!isNodeObject(value)) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (value.$prototype === "Array" && isRef(value.items)) {
|
|
128
|
+
const key = stateKeyOf(value.items.$ref);
|
|
129
|
+
if (key) {
|
|
130
|
+
keys.add(key);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
walk(value.map);
|
|
134
|
+
walk(value.children);
|
|
135
|
+
for (const branch of Object.values(value.cases ?? {})) {
|
|
136
|
+
walk(branch);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
walk(doc.children);
|
|
140
|
+
const state = doc.state ?? {};
|
|
141
|
+
return [...keys].filter((key) => isStaticClassEntry(state[key]));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** Say why an entry could not be resolved, and answer that it was not. */
|
|
145
|
+
function unresolved(key: string, error: Error | string): Resolved {
|
|
146
|
+
console.warn(`canvas: could not resolve state.${key} before the render:`, error);
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* `renderDoc` with each of `keys` replaced by its resolved value, or `renderDoc` itself when there
|
|
152
|
+
* is nothing to resolve. A rebuild, never a write: the render document shares its `state` with the
|
|
153
|
+
* tab's source document. An entry the backend cannot resolve is left as written, and the runtime's
|
|
154
|
+
* own resolution remains the fallback.
|
|
155
|
+
*/
|
|
156
|
+
export async function bakeRepeaterSources(
|
|
157
|
+
renderDoc: JxMutableNode,
|
|
158
|
+
keys: readonly string[],
|
|
159
|
+
docBase?: string,
|
|
160
|
+
classes: ClassPaths = {},
|
|
161
|
+
): Promise<JxMutableNode> {
|
|
162
|
+
const platform = getPlatform();
|
|
163
|
+
const { resolveClass } = platform;
|
|
164
|
+
const source = renderDoc.state;
|
|
165
|
+
if (keys.length === 0 || !resolveClass || !source) {
|
|
166
|
+
return renderDoc;
|
|
167
|
+
}
|
|
168
|
+
const state = { ...source };
|
|
169
|
+
await Promise.all(
|
|
170
|
+
keys.map(async (key) => {
|
|
171
|
+
const entry = state[key];
|
|
172
|
+
if (!isStaticClassEntry(entry, classes)) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
const body: JsonObject = { ...entry, $src: classSourceOf(entry, classes) };
|
|
176
|
+
if (docBase) {
|
|
177
|
+
body.$base = docBase;
|
|
178
|
+
}
|
|
179
|
+
const id = JSON.stringify(body);
|
|
180
|
+
let pending = _cache.get(id);
|
|
181
|
+
if (!pending) {
|
|
182
|
+
pending = resolveClass.call(platform, body).then(
|
|
183
|
+
(value): Resolved => value ?? null,
|
|
184
|
+
(error: Error | string) => {
|
|
185
|
+
_cache.delete(id);
|
|
186
|
+
return unresolved(key, error);
|
|
187
|
+
},
|
|
188
|
+
);
|
|
189
|
+
_cache.set(id, pending);
|
|
190
|
+
}
|
|
191
|
+
const value = await pending;
|
|
192
|
+
if (value !== null) {
|
|
193
|
+
/* SAFETY: the backend answers with the class's resolved JSON value (no `$prototype`), which
|
|
194
|
+
the runtime reads as a naked-value state entry, so it is a JxStateDefinition. */
|
|
195
|
+
state[key] = value as JxStateDefinition;
|
|
196
|
+
}
|
|
197
|
+
}),
|
|
198
|
+
);
|
|
199
|
+
return { ...renderDoc, state };
|
|
200
|
+
}
|
|
@@ -92,10 +92,14 @@ export function trackStageScrollbar(surface: CanvasSurface, scroller: HTMLElemen
|
|
|
92
92
|
const write = () => {
|
|
93
93
|
cell.style.setProperty(STAGE_SCROLLBAR_VAR, `${scrollbarWidthOf(scroller)}px`);
|
|
94
94
|
};
|
|
95
|
+
/* No measurement here: observing an element delivers its first notification after the frame's
|
|
96
|
+
layout, so the observer's own first call is the initial write. Reading `offsetWidth` here, on a
|
|
97
|
+
stage the render has just rebuilt, forced a style recalculation of the whole document (24 ms on
|
|
98
|
+
each return to Design in the perf trace); the cell keeps the `0px` the release wrote until
|
|
99
|
+
then, which is what a stage with no scrollbar yet has. */
|
|
95
100
|
const observer = new ResizeObserver(write);
|
|
96
101
|
observer.observe(scroller);
|
|
97
102
|
surface.stageScrollbar = { observer, scroller };
|
|
98
|
-
write();
|
|
99
103
|
}
|
|
100
104
|
|
|
101
105
|
/**
|
|
@@ -101,6 +101,12 @@ export interface CanvasSurface {
|
|
|
101
101
|
*/
|
|
102
102
|
prevStylebookFilter: string | null;
|
|
103
103
|
prevStylebookCustomizedOnly: boolean | null;
|
|
104
|
+
/**
|
|
105
|
+
* The breakpoint this stage's catalogue was drawn at. The sheet is ONE artboard at the active
|
|
106
|
+
* breakpoint, so a size switch changes which board exists and must rebuild it, exactly as a
|
|
107
|
+
* filter change does. `undefined` is "never drawn"; `null` is the base.
|
|
108
|
+
*/
|
|
109
|
+
prevStylebookMedia?: string | null | undefined;
|
|
104
110
|
/** Teardown for this stage's source-mode collab binding (unbind + release the lock). */
|
|
105
111
|
sourceCollabCleanup: (() => void) | null;
|
|
106
112
|
/**
|
|
@@ -54,12 +54,14 @@ import { collabCommands } from "../collab/collab-commands";
|
|
|
54
54
|
import { assistantCommands } from "../panels/ai-panel";
|
|
55
55
|
import { preferencesCommands } from "../settings/preferences-dialog";
|
|
56
56
|
import { aboutCommands } from "../about/about-modal";
|
|
57
|
-
import {
|
|
58
|
-
import { sourceControlCommands } from "../
|
|
57
|
+
import { contentViewCommands } from "../browse/library-commands";
|
|
58
|
+
import { sourceControlCommands } from "../publish/source-control";
|
|
59
59
|
import { publishCommands } from "../publish/publish-commands";
|
|
60
60
|
import { gridViewCommands } from "../grid/grid-panel";
|
|
61
61
|
import { redirectsCommands } from "../grid/redirects-grid";
|
|
62
62
|
import { contentCommands } from "../content/entry-commands";
|
|
63
|
+
import { addNewCommands } from "../create/add-new-commands";
|
|
64
|
+
import { mediaCommands } from "../media/media-commands";
|
|
63
65
|
import { i18nCommands } from "../i18n/i18n-commands";
|
|
64
66
|
import { newProjectCommands } from "../new-project/new-project-modal";
|
|
65
67
|
import { canvasCommands } from "../editor/shortcuts";
|
|
@@ -67,6 +69,7 @@ import { formatCommands, registerSelectionCommands } from "../panels/block-actio
|
|
|
67
69
|
import { fileFormatCommands } from "../format/convert-file";
|
|
68
70
|
import { registerTabCommands } from "../workspace/workspace";
|
|
69
71
|
import { derivationCommands, noopDerivationDeps } from "../workspace/pane-derive";
|
|
72
|
+
import { workspaceBackCommands } from "../workspace/workspace-back";
|
|
70
73
|
import type { AnyCommand } from "./registry";
|
|
71
74
|
|
|
72
75
|
/** A verb set that does nothing — the checks read declarations, never behaviour. */
|
|
@@ -111,13 +114,15 @@ function viaRegistration(): AnyCommand[] {
|
|
|
111
114
|
*/
|
|
112
115
|
export function appCommandSet(): AnyCommand[] {
|
|
113
116
|
return [
|
|
114
|
-
// The panel roster is the one dependency the checks must supply for real: the
|
|
115
|
-
//
|
|
116
|
-
//
|
|
117
|
+
// The panel roster is the one dependency the checks must supply for real: the `panel.focus.*`
|
|
118
|
+
// Records are generated from it, so an empty one would hide a command per panel from the level
|
|
119
|
+
// Check, the chrome budget and the generated command sheet alike.
|
|
117
120
|
...defaultCommands({ ...noopCommandDeps(), panelRoster: panelFocusRoster() }),
|
|
118
121
|
...viaRegistration(),
|
|
119
122
|
...derivationCommands(noopDerivationDeps()),
|
|
120
123
|
...shellViewCommands({ inspectorTab: () => DEFAULT_INSPECTOR_TAB, setInspectorTab: NO_OP }),
|
|
124
|
+
// Back to a strip-less workspace's home: the pane context bar's Back control, and Escape.
|
|
125
|
+
...workspaceBackCommands({ closeTab: NO_OP, setCanvasMode: NO_OP }),
|
|
121
126
|
...canvasViewCommands({
|
|
122
127
|
getCanvasMode: () => "design",
|
|
123
128
|
renderPane: NO_OP,
|
|
@@ -150,8 +155,13 @@ export function appCommandSet(): AnyCommand[] {
|
|
|
150
155
|
...assistantCommands(),
|
|
151
156
|
...preferencesCommands(),
|
|
152
157
|
...aboutCommands(),
|
|
153
|
-
|
|
158
|
+
// The Content home's verbs: which collection it shows, and that collection's own view.
|
|
159
|
+
...contentViewCommands(),
|
|
154
160
|
...contentCommands(),
|
|
161
|
+
// Add new (`file.new`): the one creation dialog, and its no-dialog form for a named kind.
|
|
162
|
+
...addNewCommands(),
|
|
163
|
+
// The Media workspace's four verbs: browse, upload, replace and delete (studio.md §22.6).
|
|
164
|
+
...mediaCommands(),
|
|
155
165
|
// The four translation verbs. `i18n.switchLocale` is deliberately not among them: it is a
|
|
156
166
|
// Rendering context, defined in `canvas/canvas-utils.ts` beside the per-tab UI state it writes.
|
|
157
167
|
...i18nCommands(),
|
package/src/commands/budget.ts
CHANGED
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
* region table, because `registerPanel()` did not exist. It does now, so the two `rail/*` rows are
|
|
16
16
|
* a QUERY over `railDeclarations()` ({@link dockTabs}) and adding a ninth rail panel fails this
|
|
17
17
|
* check without anyone remembering to update a list. The two rows that remain declared are the two
|
|
18
|
-
* docks whose tab sets this module cannot see from a bare Bun process: the Inspector's
|
|
19
|
-
* from `commands/defaults.ts`'s `
|
|
18
|
+
* docks whose tab sets this module cannot see from a bare Bun process: the Inspector's three come
|
|
19
|
+
* from `commands/defaults.ts`'s `INSPECTOR_STRIP` (a query in all but name), and the Bottom dock's
|
|
20
20
|
* four are records in `panels/bottom-dock.ts`, which renders lit templates and therefore cannot be
|
|
21
21
|
* imported here. `tests/bottom-dock.test.ts` asserts the declared row and the registered set are
|
|
22
22
|
* the same four titles, so the copy cannot drift — the same bargain `tests/right-panel.test.ts`
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* joins them the way it already joins the rail.
|
|
25
25
|
*/
|
|
26
26
|
|
|
27
|
-
import {
|
|
27
|
+
import { INSPECTOR_STRIP } from "./defaults";
|
|
28
28
|
|
|
29
29
|
/** The caps. Raising either one is a design decision, so it happens here, in one place. */
|
|
30
30
|
export const CHROME_BUDGET = {
|
|
@@ -65,10 +65,12 @@ export interface DockDeclaration {
|
|
|
65
65
|
/**
|
|
66
66
|
* The tabbed regions that are still WRITTEN DOWN rather than observed.
|
|
67
67
|
*
|
|
68
|
-
* The Inspector's row is a query in all but name — `
|
|
69
|
-
* renders
|
|
70
|
-
* it.
|
|
71
|
-
*
|
|
68
|
+
* The Inspector's row is a query in all but name — `INSPECTOR_STRIP` is the strip `right-panel.ts`
|
|
69
|
+
* renders (Page · Element · Assistant), so a fifth strip tab fails this check in the commit that
|
|
70
|
+
* adds it. Element's Content · Style · Logic sub-switch lives inside a tab's body and is not
|
|
71
|
+
* counted: it is three views of one target, not three places (`studio-ui-guidelines.md` §12.2). The
|
|
72
|
+
* Bottom dock's row is the same shape: the four ids live in `shell.ts`'s `BOTTOM_TAB_IDS` (so
|
|
73
|
+
* `view.setBottomTab`'s enum can be read in a bare Bun process) and the four RECORDS live in
|
|
72
74
|
* `panels/bottom-dock.ts`. It inherited this cap before it existed, which is why Deploy folded into
|
|
73
75
|
* Activity rather than becoming a fifth tab.
|
|
74
76
|
*
|
|
@@ -78,7 +80,7 @@ export interface DockDeclaration {
|
|
|
78
80
|
* those could disagree.
|
|
79
81
|
*/
|
|
80
82
|
export const DECLARED_DOCK_TABS: readonly DockDeclaration[] = [
|
|
81
|
-
{ dock: "inspector", tabs:
|
|
83
|
+
{ dock: "inspector", tabs: INSPECTOR_STRIP.map((tab) => tab.title) },
|
|
82
84
|
{ dock: "bottom", tabs: ["Problems", "Logic", "Activity"] },
|
|
83
85
|
];
|
|
84
86
|
|