@jxsuite/studio 6.1.2 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/chunks/2020-5wtzce5g.js +4 -0
- package/dist/chunks/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
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which workspace a tab belongs to, and which of a pane's tabs its strip draws.
|
|
3
|
+
*
|
|
4
|
+
* Every tab belongs to exactly one workspace, and the answer is DERIVED from the tab rather than
|
|
5
|
+
* stored on it: what a tab is (a home, a media file, a comparison) and how it is being edited (the
|
|
6
|
+
* configuration document's stylebook editor) are already on the tab, so a stored field would be a
|
|
7
|
+
* second record of the same fact, free to disagree with it.
|
|
8
|
+
*
|
|
9
|
+
* - **Content**: the Content home and the collection and page grids; an entry's form editor; and any
|
|
10
|
+
* file a content collection owns (collection-match.ts is the one matcher), because an entry is
|
|
11
|
+
* written in Content even when it is opened from somewhere else.
|
|
12
|
+
* - **Media**: the media home and every media file's viewer.
|
|
13
|
+
* - **Styles**: `project.json`, in any of its three views: Elements (`stylebook`), Variables
|
|
14
|
+
* (`tokens`) and Code (`source`). Project Settings is a dialog over every workspace (§17.1), not
|
|
15
|
+
* a tab, so it belongs to none.
|
|
16
|
+
* - **Publish**: the publish home and every comparison (`git-diff`).
|
|
17
|
+
* - **Design**: everything else: pages, templates, components and every other file.
|
|
18
|
+
*
|
|
19
|
+
* The rules read the tab's CURRENT editor, so switching an entry from its form to the canvas keeps
|
|
20
|
+
* it in Content while a grid's kind decides between Content and Design, and
|
|
21
|
+
* `workspace/workspace-switch.ts` follows the tab wherever that puts it.
|
|
22
|
+
*
|
|
23
|
+
* @docs studio/interface
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { shell } from "../shell";
|
|
27
|
+
import { workspace } from "./workspace";
|
|
28
|
+
import { homeWorkspaceOfTabId } from "./workspace-ids";
|
|
29
|
+
import { parseGridTabId } from "../grid/grid-source";
|
|
30
|
+
import { collectionForFile } from "../content/collection-match";
|
|
31
|
+
import { PROJECT_CONFIG_PATH } from "../tabs/tab";
|
|
32
|
+
import type { Pane } from "./workspace";
|
|
33
|
+
import type { WorkspaceId } from "./workspace-ids";
|
|
34
|
+
import type { Tab } from "../tabs/tab";
|
|
35
|
+
|
|
36
|
+
/** The editors that are Content's whatever document they are over. */
|
|
37
|
+
const CONTENT_MODES: ReadonlySet<string> = new Set(["entry"]);
|
|
38
|
+
|
|
39
|
+
/** The workspace `tab` belongs to. Pure over the tab and the open project's configuration. */
|
|
40
|
+
export function workspaceOfTab(tab: Tab): WorkspaceId {
|
|
41
|
+
const home = homeWorkspaceOfTabId(tab.id);
|
|
42
|
+
if (home) {
|
|
43
|
+
return home;
|
|
44
|
+
}
|
|
45
|
+
const mode = tab.session.ui.canvasMode;
|
|
46
|
+
if (mode === "git-diff") {
|
|
47
|
+
return "publish";
|
|
48
|
+
}
|
|
49
|
+
if (mode === "media") {
|
|
50
|
+
return "media";
|
|
51
|
+
}
|
|
52
|
+
if (CONTENT_MODES.has(mode)) {
|
|
53
|
+
return "content";
|
|
54
|
+
}
|
|
55
|
+
const grid = parseGridTabId(tab.id);
|
|
56
|
+
if (grid) {
|
|
57
|
+
// A data-table grid is the Data panel's, which is Design's; every other grid is content.
|
|
58
|
+
return grid.kind === "data" ? "design" : "content";
|
|
59
|
+
}
|
|
60
|
+
if (tab.documentPath === PROJECT_CONFIG_PATH) {
|
|
61
|
+
return "styles";
|
|
62
|
+
}
|
|
63
|
+
/* A file-backed collection's file too: its grid is where its records are written, and the
|
|
64
|
+
Content home opens it for any of them, so it must not carry the author off to Design. */
|
|
65
|
+
return collectionForFile(tab.documentPath) ? "content" : "design";
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* The editors in which a document is written on the canvas, where the Inspector applies: a page's
|
|
70
|
+
* canvas, and the Elements view (`stylebook`), whose canvas selects the element default the
|
|
71
|
+
* Inspector's Style tab edits.
|
|
72
|
+
*/
|
|
73
|
+
const CANVAS_WRITING_MODES: ReadonlySet<string> = new Set(["edit", "design", "stylebook"]);
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Whether a tab is a document being written on the canvas: a file-backed tab in an editing canvas
|
|
77
|
+
* mode. A grid, an entry's form, a home, the Variables view and a code view are not. Content's and
|
|
78
|
+
* Styles' presets read it to draw the Inspector while the canvas is being written (`shell.ts`'s
|
|
79
|
+
* `WORKSPACE_PRESETS`).
|
|
80
|
+
*/
|
|
81
|
+
export function writesOnCanvas(tab: Tab): boolean {
|
|
82
|
+
return (
|
|
83
|
+
tab.documentPath !== null &&
|
|
84
|
+
parseGridTabId(tab.id) === null &&
|
|
85
|
+
CANVAS_WRITING_MODES.has(tab.session.ui.canvasMode)
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Whether a tab id names an open tab of the workspace on screen. */
|
|
90
|
+
export function isTabInWorkspace(tabId: string, id: WorkspaceId = shell.workspace): boolean {
|
|
91
|
+
const tab = workspace.tabs.get(tabId);
|
|
92
|
+
return tab !== undefined && workspaceOfTab(tab) === id;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* The tabs a pane's strip draws: its own, in strip order, less every tab of another workspace.
|
|
97
|
+
*
|
|
98
|
+
* The order is the pane's, so a drop index computed against {@link Pane.tabOrder} still lands
|
|
99
|
+
* between the two chips it was dropped between: the hidden tabs keep their slots, they are only not
|
|
100
|
+
* drawn.
|
|
101
|
+
*/
|
|
102
|
+
export function workspaceTabOrder(pane: Pane, id: WorkspaceId = shell.workspace): string[] {
|
|
103
|
+
return pane.tabOrder.filter((tabId) => isTabInWorkspace(tabId, id));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* The tab a workspace was last in: the most recently used of its open tabs, in any pane, or the
|
|
108
|
+
* first of them in strip order when none has been used yet (a restored session's tabs are opened
|
|
109
|
+
* without being focused). `null` when the workspace has no tab open.
|
|
110
|
+
*/
|
|
111
|
+
export function lastTabOfWorkspace(id: WorkspaceId): string | null {
|
|
112
|
+
const recent = workspace.mruOrder.find((tabId) => isTabInWorkspace(tabId, id));
|
|
113
|
+
if (recent) {
|
|
114
|
+
return recent;
|
|
115
|
+
}
|
|
116
|
+
for (const pane of workspace.panes) {
|
|
117
|
+
const first = pane.tabOrder.find((tabId) => isTabInWorkspace(tabId, id));
|
|
118
|
+
if (first) {
|
|
119
|
+
return first;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** The tab `pane` should show for a workspace: its most recent one there, or `null`. */
|
|
126
|
+
export function paneTabOfWorkspace(pane: Pane, id: WorkspaceId): string | null {
|
|
127
|
+
if (pane.activeTabId && isTabInWorkspace(pane.activeTabId, id)) {
|
|
128
|
+
return pane.activeTabId;
|
|
129
|
+
}
|
|
130
|
+
return (
|
|
131
|
+
workspace.mruOrder.find(
|
|
132
|
+
(tabId) => pane.tabOrder.includes(tabId) && isTabInWorkspace(tabId, id),
|
|
133
|
+
) ??
|
|
134
|
+
pane.tabOrder.find((tabId) => isTabInWorkspace(tabId, id)) ??
|
|
135
|
+
null
|
|
136
|
+
);
|
|
137
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Back to the workspace home — the way out of a view in a workspace that draws no tab strip.
|
|
3
|
+
*
|
|
4
|
+
* Media, Styles and Publish draw their home surface without a strip (`shell.ts`'s
|
|
5
|
+
* `WorkspacePreset.tabStrip`, `specs/studio.md` §22.3). What they open beside their home has to be
|
|
6
|
+
* leave-able anyway, and without a strip there is no chip to click and no × to press:
|
|
7
|
+
*
|
|
8
|
+
* - **Media**: a media file opened in its viewer leads back to the media library.
|
|
9
|
+
* - **Publish**: a comparison (`git-diff`) leads back to the Publish home.
|
|
10
|
+
* - **Styles**: `project.json` in its Code view leads back to the view the Styles home was left in,
|
|
11
|
+
* Variables or Elements. Code is a view of the same tab, so going back switches the view and
|
|
12
|
+
* closes nothing.
|
|
13
|
+
*
|
|
14
|
+
* {@link backTargetOf} is the one rule, read by the pane context bar (which draws the Back control,
|
|
15
|
+
* naming the destination) and by `pane.backToHome` (the control's command, and Escape's). A media
|
|
16
|
+
* viewer or a comparison is CLOSED on the way back, so the home is what is left: a strip-less pane
|
|
17
|
+
* holds its home and one view beside it rather than a pile of views nobody can see, and the close
|
|
18
|
+
* lands on the home (`workspace/workspace-switch.ts`'s close landing). Closing such a view any
|
|
19
|
+
* other way (⌘W) lands there too.
|
|
20
|
+
*
|
|
21
|
+
* @docs studio/interface/tabs
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { shell, workspaceDrawsTabStrip } from "../shell";
|
|
25
|
+
import { PROJECT_CONFIG_PATH } from "../tabs/tab";
|
|
26
|
+
import { tabOfPane } from "../canvas/canvas-surface";
|
|
27
|
+
import { workspace } from "./workspace";
|
|
28
|
+
import { workspaceOfTab } from "./tab-workspace";
|
|
29
|
+
import { homeWorkspaceOfTabId, isHomeWorkspace, workspaceInfo } from "./workspace-ids";
|
|
30
|
+
import { argsSchema, optionalStringArg, stringProperty } from "../commands/command-args";
|
|
31
|
+
import { EDITOR_KIND_LABELS, editorKindForMode } from "../commands/context";
|
|
32
|
+
import { isPopoverOpen } from "../ui/layers";
|
|
33
|
+
import type { WorkspaceId } from "./workspace-ids";
|
|
34
|
+
import type { Tab } from "../tabs/tab";
|
|
35
|
+
import type { AnyCommand } from "../commands/registry";
|
|
36
|
+
|
|
37
|
+
/** Where the Back control leads, and how it gets there. */
|
|
38
|
+
export type BackTarget =
|
|
39
|
+
| {
|
|
40
|
+
/** Close the view: the home beside it is what the pane shows next. */
|
|
41
|
+
kind: "close";
|
|
42
|
+
/** The control's text, naming the destination: "Back to Media". */
|
|
43
|
+
label: string;
|
|
44
|
+
/** Its tooltip: what happens to the view. */
|
|
45
|
+
hint: string;
|
|
46
|
+
}
|
|
47
|
+
| {
|
|
48
|
+
/** Switch the tab to another of its views (Styles' Code view back to the home view). */
|
|
49
|
+
kind: "view";
|
|
50
|
+
label: string;
|
|
51
|
+
hint: string;
|
|
52
|
+
/** The canvas mode to switch to: `tokens` or `stylebook`. */
|
|
53
|
+
mode: string;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/** The Code view's mode over `project.json`. */
|
|
57
|
+
const SOURCE_MODE = "source";
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Where a tab's Back control leads in workspace `id`, or `null` when there is nowhere to go back
|
|
61
|
+
* to: a workspace that draws a strip (its strip is the way between documents), a tab of another
|
|
62
|
+
* workspace, and a workspace's home itself.
|
|
63
|
+
*
|
|
64
|
+
* @param tab The tab a pane is showing
|
|
65
|
+
* @param id The workspace on screen
|
|
66
|
+
*/
|
|
67
|
+
export function backTargetOf(
|
|
68
|
+
tab: Tab | null,
|
|
69
|
+
id: WorkspaceId = shell.workspace,
|
|
70
|
+
): BackTarget | null {
|
|
71
|
+
if (!tab || workspaceDrawsTabStrip(id) || workspaceOfTab(tab) !== id) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
if (id === "styles") {
|
|
75
|
+
if (tab.documentPath !== PROJECT_CONFIG_PATH || tab.session.ui.canvasMode !== SOURCE_MODE) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
const mode = shell.stylebook.view;
|
|
79
|
+
const name = EDITOR_KIND_LABELS[editorKindForMode(mode)];
|
|
80
|
+
return {
|
|
81
|
+
hint: `Leave the Code view for the ${name} view of your styles`,
|
|
82
|
+
kind: "view",
|
|
83
|
+
label: `Back to ${name}`,
|
|
84
|
+
mode,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
if (!isHomeWorkspace(id) || homeWorkspaceOfTabId(tab.id) === id) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
const home = workspaceInfo(id).title;
|
|
91
|
+
return {
|
|
92
|
+
hint: `Close this view and return to ${home}`,
|
|
93
|
+
kind: "close",
|
|
94
|
+
label: `Back to ${home}`,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** {@link backTargetOf} for the tab a pane is showing. */
|
|
99
|
+
export function backTargetOfPane(paneId: string): BackTarget | null {
|
|
100
|
+
return backTargetOf(tabOfPane(paneId));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** What going back needs that this module may not import. */
|
|
104
|
+
export interface WorkspaceBackDeps {
|
|
105
|
+
/** Close a tab through the strip's guarded close (`panels/tab-strip.ts` `requestClose`). */
|
|
106
|
+
closeTab: (tabId: string) => void | Promise<void>;
|
|
107
|
+
/** Switch a tab's editor (`studio.ts` `setCanvasMode`). */
|
|
108
|
+
setCanvasMode: (tab: Tab, mode: string) => void;
|
|
109
|
+
/**
|
|
110
|
+
* Give the keyboard to the home a close landed on: the Media home's tile, the Publish change the
|
|
111
|
+
* comparison was opened from. Without it the focus falls to the page body with the view.
|
|
112
|
+
*/
|
|
113
|
+
focusHome?: (paneId: string, id: WorkspaceId) => void;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Go back from what `paneId` shows to its workspace's home. `false` when there is nowhere to go.
|
|
118
|
+
*
|
|
119
|
+
* @param paneId The pane whose Back control was pressed
|
|
120
|
+
* @param deps The close and the view switch
|
|
121
|
+
*/
|
|
122
|
+
export async function goBack(paneId: string, deps: WorkspaceBackDeps): Promise<boolean> {
|
|
123
|
+
const tab = tabOfPane(paneId);
|
|
124
|
+
const target = backTargetOf(tab);
|
|
125
|
+
if (!tab || !target) {
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
if (target.kind === "view") {
|
|
129
|
+
tab.session.ui.preview = false;
|
|
130
|
+
deps.setCanvasMode(tab, target.mode);
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
const id = shell.workspace;
|
|
134
|
+
await deps.closeTab(tab.id);
|
|
135
|
+
// Only when the close went through: a refused close (unsaved work kept) leaves the view standing.
|
|
136
|
+
if (!workspace.tabs.has(tab.id)) {
|
|
137
|
+
deps.focusHome?.(paneId, id);
|
|
138
|
+
}
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* `pane.backToHome`: the Back control's command, and Escape's.
|
|
144
|
+
*
|
|
145
|
+
* Gated with `when`, not `enablement`, because Escape is the chord: a disabled record still claims
|
|
146
|
+
* its chord, and every other Escape in the global scope would be swallowed by a Back that is not
|
|
147
|
+
* there. Three places keep their own Escape: a text field (the caret is a field's, and Escape there
|
|
148
|
+
* is the field's own); the Code view, where Escape belongs to the code editor's widgets, so the
|
|
149
|
+
* Back control is how Code is left; and an open popover (the pane context bar's Context menu, for
|
|
150
|
+
* one), which the platform closes on Escape, and which a cancelled Escape would leave standing over
|
|
151
|
+
* a view that had gone.
|
|
152
|
+
*
|
|
153
|
+
* @param deps The close and the view switch
|
|
154
|
+
*/
|
|
155
|
+
export function workspaceBackCommands(deps: WorkspaceBackDeps): AnyCommand[] {
|
|
156
|
+
return [
|
|
157
|
+
{
|
|
158
|
+
args: argsSchema(
|
|
159
|
+
{
|
|
160
|
+
pane: stringProperty("Which pane to go back in. Defaults to the focused one."),
|
|
161
|
+
},
|
|
162
|
+
[],
|
|
163
|
+
),
|
|
164
|
+
id: "pane.backToHome",
|
|
165
|
+
title: "Back to Workspace Home",
|
|
166
|
+
category: "View",
|
|
167
|
+
level: "document",
|
|
168
|
+
keybinding: "escape",
|
|
169
|
+
menus: ["palette"],
|
|
170
|
+
group: "5_pane",
|
|
171
|
+
when: (ctx) =>
|
|
172
|
+
!ctx.caret.active &&
|
|
173
|
+
ctx.editor.kind !== "code" &&
|
|
174
|
+
!isPopoverOpen() &&
|
|
175
|
+
backTargetOfPane(workspace.activePaneId) !== null,
|
|
176
|
+
requires: "a view opened beside a workspace home",
|
|
177
|
+
undo: "none",
|
|
178
|
+
run: async (_ctx, args) => {
|
|
179
|
+
const paneId = optionalStringArg("pane.backToHome", args, "pane") ?? workspace.activePaneId;
|
|
180
|
+
if (!(await goBack(paneId, deps))) {
|
|
181
|
+
throw new RangeError(
|
|
182
|
+
`command "pane.backToHome": pane "${paneId}" shows no view opened beside a ` +
|
|
183
|
+
"workspace home, so there is nothing to go back from",
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
];
|
|
189
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
2
|
+
/**
|
|
3
|
+
* Workspace homes — the virtual tab a workspace opens on when none of its own tabs is open.
|
|
4
|
+
*
|
|
5
|
+
* A home is a tab like a grid is a tab: it sits in a pane's strip, it can be closed, and it has a
|
|
6
|
+
* canvas mode of its own (`content-home`, `media-home`, `publish-home`) that
|
|
7
|
+
* `canvas/canvas-render.ts` routes here. It has no document — the tab carries a stub, exactly as
|
|
8
|
+
* the grid tabs do — and its id is in the `workspace://` space `workspace/workspace-ids.ts`
|
|
9
|
+
* declares, so it can never collide with a file.
|
|
10
|
+
*
|
|
11
|
+
* What a home DRAWS is its workspace's own surface: the Content home is the collection it shows
|
|
12
|
+
* (`browse/library-pane.ts`, studio.md §22.5), the Media home is the media library
|
|
13
|
+
* (`media/media-library.ts`, §22.6) and the Publish home is the Publish workspace
|
|
14
|
+
* (`publish/publish-workspace.ts`, §22.8). The mechanism (the tab, the mode, the routing and the
|
|
15
|
+
* per-pane mount) is the same for all three, and this module only routes.
|
|
16
|
+
*
|
|
17
|
+
* @docs studio/interface
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { activateTab, openTab, workspace } from "./workspace";
|
|
21
|
+
import { WORKSPACE_HOME_MODES, homeWorkspaceOfTabId, workspaceHomeTabId } from "./workspace-ids";
|
|
22
|
+
import {
|
|
23
|
+
detachMediaLibrary,
|
|
24
|
+
mediaLibraryMounted,
|
|
25
|
+
renderMediaLibrary,
|
|
26
|
+
} from "../media/media-library";
|
|
27
|
+
import { detachLibraryPane, libraryPaneMounted, renderLibraryMode } from "../browse/library-pane";
|
|
28
|
+
import {
|
|
29
|
+
detachPublishWorkspace,
|
|
30
|
+
publishWorkspaceMounted,
|
|
31
|
+
renderPublishWorkspace,
|
|
32
|
+
} from "../publish/publish-workspace";
|
|
33
|
+
import type { HomeWorkspaceId } from "./workspace-ids";
|
|
34
|
+
import type { Tab } from "../tabs/tab";
|
|
35
|
+
import type { CanvasSurface } from "../canvas/canvas-surface";
|
|
36
|
+
|
|
37
|
+
/** The stub a home tab carries: it is never read, and nothing is ever saved from it. */
|
|
38
|
+
const HOME_STUB_DOCUMENT = { children: [], tagName: "div" };
|
|
39
|
+
|
|
40
|
+
/** The canvas modes a home draws under. */
|
|
41
|
+
export const WORKSPACE_HOME_MODE_SET: ReadonlySet<string> = new Set(
|
|
42
|
+
Object.values(WORKSPACE_HOME_MODES),
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
/** Whether a canvas mode is a workspace home's. */
|
|
46
|
+
export function isWorkspaceHomeMode(mode: string): boolean {
|
|
47
|
+
return WORKSPACE_HOME_MODE_SET.has(mode);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Open (or activate) a workspace's home.
|
|
52
|
+
*
|
|
53
|
+
* Idempotent by construction, which is what lets `view.setWorkspace` say "show me Media" without
|
|
54
|
+
* caring whether an earlier switch opened its home already.
|
|
55
|
+
*/
|
|
56
|
+
export function openWorkspaceHome(id: HomeWorkspaceId): Tab {
|
|
57
|
+
const tabId = workspaceHomeTabId(id);
|
|
58
|
+
const existing = workspace.tabs.get(tabId);
|
|
59
|
+
if (existing) {
|
|
60
|
+
activateTab(tabId);
|
|
61
|
+
return existing;
|
|
62
|
+
}
|
|
63
|
+
return openTab({
|
|
64
|
+
capabilities: { modes: [WORKSPACE_HOME_MODES[id]] },
|
|
65
|
+
document: structuredClone(HOME_STUB_DOCUMENT),
|
|
66
|
+
documentPath: null,
|
|
67
|
+
id: tabId,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Put a workspace's home in `paneId`'s strip without showing it, unless it is open already.
|
|
73
|
+
*
|
|
74
|
+
* A workspace with no Navigator (Media, Publish) has no other way back to its home than its tab: a
|
|
75
|
+
* media file opened from the Site panel lands in Media on its viewer, and with the home absent the
|
|
76
|
+
* strip offered that viewer alone and closing it left an empty stage. Keeping the home beside it is
|
|
77
|
+
* what makes the grid one click away, and what closing the viewer falls back to.
|
|
78
|
+
*/
|
|
79
|
+
export function placeWorkspaceHome(id: HomeWorkspaceId, paneId: string): void {
|
|
80
|
+
openTab({
|
|
81
|
+
background: true,
|
|
82
|
+
capabilities: { modes: [WORKSPACE_HOME_MODES[id]] },
|
|
83
|
+
document: structuredClone(HOME_STUB_DOCUMENT),
|
|
84
|
+
documentPath: null,
|
|
85
|
+
id: workspaceHomeTabId(id),
|
|
86
|
+
paneId,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ─── Mounting ────────────────────────────────────────────────────────────────
|
|
91
|
+
|
|
92
|
+
/** Whether this tab's home is already mounted in this pane and still in the document. */
|
|
93
|
+
export function workspaceHomeMounted(paneId: string, tab: Tab): boolean {
|
|
94
|
+
const id = homeWorkspaceOfTabId(tab.id);
|
|
95
|
+
if (id === "media") {
|
|
96
|
+
return mediaLibraryMounted(paneId, tab);
|
|
97
|
+
}
|
|
98
|
+
if (id === "content") {
|
|
99
|
+
return libraryPaneMounted(paneId, tab);
|
|
100
|
+
}
|
|
101
|
+
return publishWorkspaceMounted(paneId, tab);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Tear one pane's home down (mode change, tab switch, project close). Idempotent. */
|
|
105
|
+
export function detachWorkspaceHome(paneId: string): void {
|
|
106
|
+
detachMediaLibrary(paneId);
|
|
107
|
+
detachLibraryPane(paneId);
|
|
108
|
+
detachPublishWorkspace(paneId);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Draw a home tab into its pane's stage.
|
|
113
|
+
*
|
|
114
|
+
* @param {CanvasSurface} surface
|
|
115
|
+
* @param {Tab} tab
|
|
116
|
+
*/
|
|
117
|
+
export function renderWorkspaceHome(surface: CanvasSurface, tab: Tab): void {
|
|
118
|
+
const { paneId } = surface;
|
|
119
|
+
if (workspaceHomeMounted(paneId, tab)) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
detachWorkspaceHome(paneId);
|
|
123
|
+
const id = homeWorkspaceOfTabId(tab.id);
|
|
124
|
+
if (id === "media") {
|
|
125
|
+
renderMediaLibrary(surface, tab);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (id === "content") {
|
|
129
|
+
renderLibraryMode(surface, tab);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
renderPublishWorkspace(surface, tab);
|
|
133
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The five workspaces, declared where a bare Bun process can read them.
|
|
3
|
+
*
|
|
4
|
+
* A workspace is the answer to "what am I doing right now": designing pages, writing content,
|
|
5
|
+
* managing media, editing the project's styles, or publishing. Studio's top bar switches between
|
|
6
|
+
* them, and every open tab belongs to exactly one (`workspace/tab-workspace.ts` derives which).
|
|
7
|
+
*
|
|
8
|
+
* The ids live in a module with no DOM and no state for the reason `NAVIGATOR_PANEL_IDS` does:
|
|
9
|
+
* `view.setWorkspace`'s `args` enum is built from {@link WORKSPACE_IDS}, and
|
|
10
|
+
* `commands/app-commands.ts` must load that enum in the bare Bun process the CI checks run in. A
|
|
11
|
+
* manifest step naming a workspace this list does not declare is then a red check in the PR that
|
|
12
|
+
* renamed it, rather than a screenshot of the wrong screen.
|
|
13
|
+
*
|
|
14
|
+
* The workspace HOME tab ids are declared here too. A home is a virtual tab (a document the pane
|
|
15
|
+
* draws that no file backs), and both the derivation that says which workspace a tab belongs to and
|
|
16
|
+
* the module that opens one must agree on its id, so the id has one definition site that imports
|
|
17
|
+
* nothing.
|
|
18
|
+
*
|
|
19
|
+
* @docs studio/interface
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/** The workspaces, in top-bar order. ⌘1 to ⌘5 follow this order. */
|
|
23
|
+
export const WORKSPACE_IDS = ["design", "content", "media", "styles", "publish"] as const;
|
|
24
|
+
|
|
25
|
+
export type WorkspaceId = (typeof WORKSPACE_IDS)[number];
|
|
26
|
+
|
|
27
|
+
/** The workspace a project wakes up in when nothing usable is stored. */
|
|
28
|
+
export const DEFAULT_WORKSPACE: WorkspaceId = "design";
|
|
29
|
+
|
|
30
|
+
/** One workspace, as the top bar and the palette name it. */
|
|
31
|
+
export interface WorkspaceInfo {
|
|
32
|
+
id: WorkspaceId;
|
|
33
|
+
/** What the top-bar tab reads, and what the palette row says after "Show". */
|
|
34
|
+
title: string;
|
|
35
|
+
/** A key into the kit's glyph manifest (`@jxsuite/ui/icons`), checked by this module's test. */
|
|
36
|
+
icon: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Every workspace, in {@link WORKSPACE_IDS} order. */
|
|
40
|
+
export const WORKSPACES: readonly WorkspaceInfo[] = [
|
|
41
|
+
{
|
|
42
|
+
icon: "frame-corners",
|
|
43
|
+
id: "design",
|
|
44
|
+
title: "Design",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
icon: "file-text",
|
|
48
|
+
id: "content",
|
|
49
|
+
title: "Content",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
icon: "image",
|
|
53
|
+
id: "media",
|
|
54
|
+
title: "Media",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
icon: "paint-brush",
|
|
58
|
+
id: "styles",
|
|
59
|
+
title: "Styles",
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
icon: "paper-plane-tilt",
|
|
63
|
+
id: "publish",
|
|
64
|
+
title: "Publish",
|
|
65
|
+
},
|
|
66
|
+
];
|
|
67
|
+
|
|
68
|
+
/** Whether a value is a declared workspace id. A stored value is untrusted input. */
|
|
69
|
+
export function isWorkspaceId(value: unknown): value is WorkspaceId {
|
|
70
|
+
return typeof value === "string" && WORKSPACE_IDS.some((id) => id === value);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** The record for a workspace id. Total over {@link WorkspaceId}. */
|
|
74
|
+
export function workspaceInfo(id: WorkspaceId): WorkspaceInfo {
|
|
75
|
+
/* SAFETY of the `!`: WORKSPACES holds one entry per WORKSPACE_IDS member, which this module's
|
|
76
|
+
test asserts in both directions. */
|
|
77
|
+
return WORKSPACES.find((entry) => entry.id === id)!;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ─── Workspace homes ─────────────────────────────────────────────────────────
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* The scheme a workspace home's tab id carries. Not a path, so it can never collide with a file,
|
|
84
|
+
* and not `grid://`, which is the grid's id space.
|
|
85
|
+
*/
|
|
86
|
+
const HOME_SCHEME = "workspace://";
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* The workspaces whose home is a virtual tab of the generic home mechanism, and the canvas mode
|
|
90
|
+
* that tab draws under.
|
|
91
|
+
*
|
|
92
|
+
* Design has no home (an empty stage is its home), and Styles' is `project.json` in its stylebook
|
|
93
|
+
* editor, opened by the module that owns that document. These three are the generic mechanism's:
|
|
94
|
+
* Content's home is the collection it shows (`browse/library-pane.ts`), Media's the media library,
|
|
95
|
+
* and Publish's its own surface.
|
|
96
|
+
*/
|
|
97
|
+
export const WORKSPACE_HOME_MODES = {
|
|
98
|
+
content: "content-home",
|
|
99
|
+
media: "media-home",
|
|
100
|
+
publish: "publish-home",
|
|
101
|
+
} as const satisfies Partial<Record<WorkspaceId, string>>;
|
|
102
|
+
|
|
103
|
+
/** A workspace whose home is a generic home tab. */
|
|
104
|
+
export type HomeWorkspaceId = keyof typeof WORKSPACE_HOME_MODES;
|
|
105
|
+
|
|
106
|
+
/** Whether a workspace's home is a generic home tab. */
|
|
107
|
+
export function isHomeWorkspace(id: WorkspaceId): id is HomeWorkspaceId {
|
|
108
|
+
return Object.hasOwn(WORKSPACE_HOME_MODES, id);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** The tab id of a workspace's home. */
|
|
112
|
+
export function workspaceHomeTabId(id: HomeWorkspaceId): string {
|
|
113
|
+
return `${HOME_SCHEME}${id}`;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** The workspace a home tab id names, or `null` for any other id. */
|
|
117
|
+
export function homeWorkspaceOfTabId(tabId: string): HomeWorkspaceId | null {
|
|
118
|
+
if (!tabId.startsWith(HOME_SCHEME)) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
const rest = tabId.slice(HOME_SCHEME.length);
|
|
122
|
+
return isWorkspaceId(rest) && isHomeWorkspace(rest) ? rest : null;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** The label a home tab's chip reads: the workspace's own title. `null` for any other id. */
|
|
126
|
+
export function workspaceHomeLabel(tabId: string): string | null {
|
|
127
|
+
const id = homeWorkspaceOfTabId(tabId);
|
|
128
|
+
return id ? workspaceInfo(id).title : null;
|
|
129
|
+
}
|