@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
|
@@ -1,17 +1,27 @@
|
|
|
1
1
|
/// <reference lib="dom" />
|
|
2
2
|
/**
|
|
3
|
-
* Right panel — the Inspector dock:
|
|
3
|
+
* Right panel — the Inspector dock: three tabs, five views, one column (§6).
|
|
4
4
|
*
|
|
5
|
-
* **
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* **Page · Element · Assistant**, text-labelled. Page is the open document's own settings (the
|
|
6
|
+
* former Navigator Page panel, re-hosted), titled for what the document is: Page, Template,
|
|
7
|
+
* Component, Entry or Document. Element is the selected node, and keeps the three views the strip
|
|
8
|
+
* used to spend three tabs on — Content, Style, Logic — behind a sub-switch in its body. The
|
|
9
|
+
* Assistant is folded in from the grid column it used to own, which is the point of §3.1's "no
|
|
10
|
+
* assistant column": an inspector tab costs zero additional width.
|
|
11
|
+
*
|
|
12
|
+
* The five LEAVES stay addressable (`shell.ts`'s `INSPECTOR_TAB_IDS`): `view.setRightTab { tab:
|
|
13
|
+
* "style" }` shows Element with Style chosen, and ⌘⇧1–5 follow the leaves left to right.
|
|
14
|
+
*
|
|
15
|
+
* **The strip follows the selection, and yields to the author.** When the selection goes from empty
|
|
16
|
+
* to non-empty while Page is showing, the strip switches to Element on the leaf last used there;
|
|
17
|
+
* when it becomes empty while Element is showing, it switches to Page. Only the TRANSITION
|
|
18
|
+
* switches: a tab the author clicks is kept until the selection next crosses empty, and the
|
|
19
|
+
* Assistant is never switched away from.
|
|
10
20
|
*
|
|
11
21
|
* **This file no longer draws anything.** The dock's markup, its ARIA and its style are
|
|
12
22
|
* `surfaces/inspector-dock.json`, mounted through `surfaces/inspector-dock.ts`; what is left here
|
|
13
|
-
* is the flow — which
|
|
14
|
-
* body host is handed to. Two things came out of the move:
|
|
23
|
+
* is the flow — which leaf is selected, what the tab is pointed at, and which of the five seams
|
|
24
|
+
* each body host is handed to. Two things came out of the move:
|
|
15
25
|
*
|
|
16
26
|
* - **The strip is a real `tablist`.** It was `sp-tabs` with no `tabpanel` on the other end, so the
|
|
17
27
|
* four bodies were anonymous scrolling divs: a screen reader was told a tab was selected and
|
|
@@ -31,17 +41,27 @@ import { getNodeAtPath, nodeLabel, requireShellRef, rightPanel } from "../store"
|
|
|
31
41
|
import { effect, effectScope, reactive } from "../reactivity";
|
|
32
42
|
import { activeTab } from "../workspace/workspace";
|
|
33
43
|
import { primarySelection } from "../tabs/selection";
|
|
44
|
+
import { stylebookTarget } from "../style/stylebook-target";
|
|
34
45
|
import { bindLogicPanelHost } from "./events-panel";
|
|
35
46
|
import { bindContentHost } from "./properties-panel";
|
|
36
47
|
|
|
37
|
-
import {
|
|
38
|
-
|
|
48
|
+
import {
|
|
49
|
+
DEFAULT_ELEMENT_TAB,
|
|
50
|
+
DEFAULT_INSPECTOR_TAB,
|
|
51
|
+
isElementTabId,
|
|
52
|
+
isInspectorTabId,
|
|
53
|
+
shell,
|
|
54
|
+
} from "../shell";
|
|
55
|
+
import { INSPECTOR_STRIP, INSPECTOR_TABS } from "../commands/defaults";
|
|
56
|
+
import { bindPageHost, PAGE_TAB_EMPTY, pageTabTitle, renderPageTab } from "./head-panel";
|
|
39
57
|
import { inspectorTabRegion } from "../ui/regions";
|
|
40
58
|
import { bindStyleHost } from "./style-panel";
|
|
41
59
|
import { mountInspectorDock } from "../surfaces/inspector-dock";
|
|
42
60
|
|
|
43
61
|
import type { InspectorDockHandle, InspectorTabView } from "../surfaces/inspector-dock";
|
|
44
|
-
import type { InspectorTabId } from "../shell";
|
|
62
|
+
import type { ElementTabId, InspectorTabId } from "../shell";
|
|
63
|
+
import type { InspectorStripId } from "../commands/defaults";
|
|
64
|
+
import type { Tab } from "../tabs/tab";
|
|
45
65
|
import type { EffectScope } from "@vue/reactivity";
|
|
46
66
|
|
|
47
67
|
interface RightPanelCtx {
|
|
@@ -74,7 +94,17 @@ let _dock: InspectorDockHandle | null = null;
|
|
|
74
94
|
* reports whether the assistant is showing, and a plain field would leave that button lying on the
|
|
75
95
|
* welcome screen — which is the whole class of bug `shell.ts` was split out to end.
|
|
76
96
|
*/
|
|
77
|
-
const _detached = reactive
|
|
97
|
+
const _detached = reactive<{ tab: InspectorTabId; element: ElementTabId }>({
|
|
98
|
+
element: DEFAULT_ELEMENT_TAB,
|
|
99
|
+
tab: DEFAULT_INSPECTOR_TAB,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Whether each document had a selection the last time the dock looked, so the strip switches on a
|
|
104
|
+
* TRANSITION through empty rather than on every repaint (§6). Keyed on the tab, so focusing another
|
|
105
|
+
* document is not mistaken for its selection appearing.
|
|
106
|
+
*/
|
|
107
|
+
const _hadSelection = new WeakMap<Tab, boolean>();
|
|
78
108
|
|
|
79
109
|
/**
|
|
80
110
|
* Hand one tab's body host to its owner, once, and never let that stop the dock.
|
|
@@ -95,15 +125,21 @@ function bindBody(ctx: RightPanelCtx, tabId: string, host: HTMLElement): void {
|
|
|
95
125
|
}
|
|
96
126
|
|
|
97
127
|
/**
|
|
98
|
-
* The
|
|
128
|
+
* The five seams, keyed by the leaf whose body feeds them.
|
|
99
129
|
*
|
|
100
130
|
* A table rather than a chain of `if`s so that the ONE thing this module still does with a body
|
|
101
|
-
* host is stated in one place. Every entry is a binder another module published:
|
|
102
|
-
*
|
|
103
|
-
*
|
|
131
|
+
* host is stated in one place. Every entry is a binder another module published: four of them mount
|
|
132
|
+
* a document of their own into the host, and the assistant's arrives from `studio.ts` because a
|
|
133
|
+
* matching import here would be a cycle.
|
|
104
134
|
*/
|
|
105
135
|
function bindBodyUnguarded(ctx: RightPanelCtx, tabId: string, host: HTMLElement): void {
|
|
106
136
|
switch (tabId) {
|
|
137
|
+
case "page": {
|
|
138
|
+
/* The former Navigator Page panel, re-hosted unchanged: `head-panel.ts` draws it against the
|
|
139
|
+
focused document and empties it when nothing is open. */
|
|
140
|
+
bindPageHost(host);
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
107
143
|
case "assistant": {
|
|
108
144
|
/* The assistant owns its container for the life of the window: it is the mount point for the
|
|
109
145
|
Assistant's own Jx document, and rebuilding it would drop the transcript and the composer
|
|
@@ -127,7 +163,10 @@ function bindBodyUnguarded(ctx: RightPanelCtx, tabId: string, host: HTMLElement)
|
|
|
127
163
|
/* The canvas mode is what the tab cannot read for itself — Stylebook edits a tag catalogue
|
|
128
164
|
entry and Edit edits the selection — so it comes in from `studio.ts` the same way the
|
|
129
165
|
Content tab's navigation door does. */
|
|
130
|
-
bindStyleHost(host, {
|
|
166
|
+
bindStyleHost(host, {
|
|
167
|
+
getCanvasMode: ctx.getCanvasMode,
|
|
168
|
+
isShowing: () => inspectorTab() === "style",
|
|
169
|
+
});
|
|
131
170
|
break;
|
|
132
171
|
}
|
|
133
172
|
default: {
|
|
@@ -139,16 +178,49 @@ function bindBodyUnguarded(ctx: RightPanelCtx, tabId: string, host: HTMLElement)
|
|
|
139
178
|
}
|
|
140
179
|
}
|
|
141
180
|
|
|
142
|
-
/**
|
|
181
|
+
/** Which strip tab hosts a leaf. */
|
|
182
|
+
export function stripOf(leaf: InspectorTabId): InspectorStripId {
|
|
183
|
+
return INSPECTOR_TABS.find((tab) => tab.id === leaf)?.strip ?? "page";
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** The Page tab's title for the focused document (§6), or "Page" with nothing open. */
|
|
187
|
+
function pageTitle(): string {
|
|
188
|
+
const tab = activeTab.value;
|
|
189
|
+
return tab ? pageTabTitle(tab.documentPath) : "Page";
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** What a strip tab is called on screen: Page's title is the document's kind. */
|
|
193
|
+
function stripTitle(id: InspectorStripId): string {
|
|
194
|
+
return id === "page" ? pageTitle() : (INSPECTOR_STRIP.find((tab) => tab.id === id)?.title ?? id);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/** The tab rows the document draws, with the selected leaf resolved onto them. */
|
|
143
198
|
function tabViews(selected: InspectorTabId): InspectorTabView[] {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
199
|
+
const strip = stripOf(selected);
|
|
200
|
+
const noDocument = activeTab.value === null;
|
|
201
|
+
return INSPECTOR_STRIP.map((tab) => {
|
|
202
|
+
const leaves = INSPECTOR_TABS.filter((leaf) => leaf.strip === tab.id).map((leaf) => {
|
|
203
|
+
const empty = leaf.id === "page" && noDocument ? PAGE_TAB_EMPTY : "";
|
|
204
|
+
return {
|
|
205
|
+
active: leaf.id === selected,
|
|
206
|
+
empty,
|
|
207
|
+
hasEmpty: empty !== "",
|
|
208
|
+
key: leaf.id,
|
|
209
|
+
region: inspectorTabRegion(leaf.id),
|
|
210
|
+
shown: leaf.id === selected ? ("true" as const) : ("false" as const),
|
|
211
|
+
title: leaf.title,
|
|
212
|
+
};
|
|
213
|
+
});
|
|
214
|
+
return {
|
|
215
|
+
active: tab.id === strip,
|
|
216
|
+
hasLeaves: leaves.length > 1,
|
|
217
|
+
key: tab.id,
|
|
218
|
+
leaves,
|
|
219
|
+
panelId: `inspector-panel-${tab.id}`,
|
|
220
|
+
tabId: `inspector-tab-${tab.id}`,
|
|
221
|
+
title: stripTitle(tab.id),
|
|
222
|
+
};
|
|
223
|
+
});
|
|
152
224
|
}
|
|
153
225
|
|
|
154
226
|
/**
|
|
@@ -176,10 +248,15 @@ export function mount(ctx: RightPanelCtx) {
|
|
|
176
248
|
if (tab) {
|
|
177
249
|
// Track properties the right panel reads
|
|
178
250
|
void tab.doc.document;
|
|
251
|
+
// The Page tab reads the realm a content page keeps its head in, and its kind.
|
|
252
|
+
void tab.doc.mode;
|
|
253
|
+
void tab.doc.content;
|
|
254
|
+
void tab.documentPath;
|
|
179
255
|
// The whole SET, joined — a bare property read would not re-trigger when the selection
|
|
180
256
|
// Changes WITHIN the array, and §6.7's helpers always replace it but nothing enforces that.
|
|
181
257
|
void tab.session.selection.map((path) => path.join("/")).join("|");
|
|
182
258
|
void tab.session.ui.rightTab;
|
|
259
|
+
followSelection(tab);
|
|
183
260
|
}
|
|
184
261
|
void _detached.tab;
|
|
185
262
|
render();
|
|
@@ -197,33 +274,89 @@ export function unmount() {
|
|
|
197
274
|
bindLogicPanelHost(null);
|
|
198
275
|
bindContentHost(null);
|
|
199
276
|
bindStyleHost(null);
|
|
277
|
+
bindPageHost(null);
|
|
200
278
|
_detached.tab = DEFAULT_INSPECTOR_TAB;
|
|
279
|
+
_detached.element = DEFAULT_ELEMENT_TAB;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Switch the strip on a selection transition through empty (§6), and only then.
|
|
284
|
+
*
|
|
285
|
+
* Empty → non-empty while Page shows: Element, on the leaf last used there. Non-empty → empty while
|
|
286
|
+
* an Element leaf shows: Page. The first look at a document records its state and switches nothing,
|
|
287
|
+
* so focusing another tab is not a transition, and the Assistant is never left by this. Layout
|
|
288
|
+
* chrome counts as a selection: the Content view is what explains it. So does a Styles specimen's
|
|
289
|
+
* tag, which is a selection of the catalogue rather than of the document.
|
|
290
|
+
*/
|
|
291
|
+
function followSelection(tab: Tab): void {
|
|
292
|
+
// A tag picked in the Styles workspace's Elements view is a selection too: it is what the Style
|
|
293
|
+
// Leaf is editing, and it leaves the document selection empty (`selectStylebookTag`).
|
|
294
|
+
const has =
|
|
295
|
+
tab.session.selection.length > 0 ||
|
|
296
|
+
shell.layoutSelection !== null ||
|
|
297
|
+
stylebookTarget(tab) !== null;
|
|
298
|
+
const had = _hadSelection.get(tab);
|
|
299
|
+
_hadSelection.set(tab, has);
|
|
300
|
+
if (had === undefined || had === has) {
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
const current = inspectorTab();
|
|
304
|
+
if (has && current === "page") {
|
|
305
|
+
setInspectorTab(lastElementTab());
|
|
306
|
+
} else if (!has && isElementTabId(current)) {
|
|
307
|
+
setInspectorTab("page");
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* The tab the strip rests on when nothing chose one (§6): Page with nothing selected, otherwise the
|
|
313
|
+
* Element leaf last used. What closing the Assistant steps onto.
|
|
314
|
+
*/
|
|
315
|
+
export function restingInspectorTab(): InspectorTabId {
|
|
316
|
+
const tab = activeTab.value;
|
|
317
|
+
const has = tab !== null && (tab.session.selection.length > 0 || shell.layoutSelection !== null);
|
|
318
|
+
return has ? lastElementTab() : "page";
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/** The Element leaf last shown for the focused document, or with nothing open. */
|
|
322
|
+
function lastElementTab(): ElementTabId {
|
|
323
|
+
const tab = activeTab.value;
|
|
324
|
+
const stored: unknown = tab ? tab.session.ui.elementTab : _detached.element;
|
|
325
|
+
return isElementTabId(stored) ? stored : DEFAULT_ELEMENT_TAB;
|
|
201
326
|
}
|
|
202
327
|
|
|
203
328
|
/** The whole projection the document reads, built fresh from the state it names. */
|
|
204
329
|
function values() {
|
|
205
330
|
const tab = inspectorTab();
|
|
331
|
+
const strip = stripOf(tab);
|
|
206
332
|
return {
|
|
207
|
-
tab,
|
|
333
|
+
tab: strip,
|
|
208
334
|
tabs: tabViews(tab),
|
|
209
|
-
target: inspectorTarget(),
|
|
210
|
-
title:
|
|
335
|
+
target: inspectorTarget(tab),
|
|
336
|
+
title: stripTitle(strip),
|
|
211
337
|
};
|
|
212
338
|
}
|
|
213
339
|
|
|
214
340
|
/**
|
|
215
341
|
* Bring the dock up to date. Synchronous, and idempotent: the runtime skips a binding whose value
|
|
216
342
|
* did not move, so an explicit caller can never take a control mid-interaction.
|
|
343
|
+
*
|
|
344
|
+
* The Page body is redrawn only while it is the leaf showing: it builds a merged-head preview per
|
|
345
|
+
* paint, and a hidden one would pay for that on every selection change. Showing it draws it.
|
|
217
346
|
*/
|
|
218
347
|
export function render() {
|
|
219
|
-
|
|
348
|
+
const view = values();
|
|
349
|
+
_dock?.update(view);
|
|
350
|
+
if (inspectorTab() === "page") {
|
|
351
|
+
renderPageTab();
|
|
352
|
+
}
|
|
220
353
|
}
|
|
221
354
|
|
|
222
355
|
/**
|
|
223
|
-
* The
|
|
356
|
+
* The leaf showing right now — the stored value, coerced to a declared one.
|
|
224
357
|
*
|
|
225
358
|
* Coercion rather than trust because the value is persisted session state: a build that spelled a
|
|
226
|
-
* tab differently, or an automation step that guessed, must land on
|
|
359
|
+
* tab differently, or an automation step that guessed, must land on Page rather than on a blank
|
|
227
360
|
* dock with no tab selected.
|
|
228
361
|
*/
|
|
229
362
|
export function inspectorTab(): InspectorTabId {
|
|
@@ -243,38 +376,51 @@ export function setInspectorTab(tab: InspectorTabId): void {
|
|
|
243
376
|
const aTab = activeTab.value;
|
|
244
377
|
if (aTab) {
|
|
245
378
|
aTab.session.ui.rightTab = tab;
|
|
379
|
+
if (isElementTabId(tab)) {
|
|
380
|
+
aTab.session.ui.elementTab = tab;
|
|
381
|
+
}
|
|
246
382
|
} else {
|
|
247
383
|
_detached.tab = tab;
|
|
384
|
+
if (isElementTabId(tab)) {
|
|
385
|
+
_detached.element = tab;
|
|
386
|
+
}
|
|
248
387
|
}
|
|
249
388
|
render();
|
|
250
389
|
}
|
|
251
390
|
|
|
252
391
|
/**
|
|
253
|
-
* A pick from the strip.
|
|
392
|
+
* A pick from the strip, or from Element's sub-switch.
|
|
254
393
|
*
|
|
255
394
|
* The strip states a value and this decides what it means, which is why the document dispatches an
|
|
256
|
-
* id rather than writing one
|
|
257
|
-
* a
|
|
395
|
+
* id rather than writing one. `element` is a strip id with no leaf of its own: it means "the
|
|
396
|
+
* Element view I last used". Any other id must be a declared leaf, so an id the enum does not
|
|
397
|
+
* declare is refused here rather than becoming a dock with no tab selected.
|
|
258
398
|
*/
|
|
259
399
|
function selectFromStrip(id: string): void {
|
|
260
|
-
|
|
261
|
-
|
|
400
|
+
const leaf = id === "element" ? lastElementTab() : id;
|
|
401
|
+
if (leaf !== "" && leaf !== inspectorTab() && isInspectorTabId(leaf)) {
|
|
402
|
+
setInspectorTab(leaf);
|
|
262
403
|
}
|
|
263
404
|
}
|
|
264
405
|
|
|
265
406
|
/**
|
|
266
407
|
* What the selected tab is pointed AT, in the fewest words that are true.
|
|
267
408
|
*
|
|
268
|
-
* A tag name when a node is selected, the document's own name when nothing is
|
|
269
|
-
*
|
|
270
|
-
*
|
|
271
|
-
* with no on-screen
|
|
409
|
+
* A tag name when a node is selected, the document's own name when nothing is or when the Page tab
|
|
410
|
+
* is showing (it edits the document, whatever is selected), and "no document" when there is nothing
|
|
411
|
+
* open. The dock spent its whole life unable to answer this — three icon tabs and no statement of
|
|
412
|
+
* target anywhere — which is how "why is this field disabled" became a question with no on-screen
|
|
413
|
+
* answer.
|
|
272
414
|
*/
|
|
273
|
-
function inspectorTarget(): string {
|
|
415
|
+
function inspectorTarget(showing: InspectorTabId): string {
|
|
274
416
|
const tab = activeTab.value;
|
|
275
417
|
if (!tab) {
|
|
276
418
|
return "no document";
|
|
277
419
|
}
|
|
420
|
+
// The Page tab edits the document whatever is selected, so it is pointed at the document.
|
|
421
|
+
if (showing === "page") {
|
|
422
|
+
return documentName(tab.documentPath);
|
|
423
|
+
}
|
|
278
424
|
// Layout chrome first: it is mutually exclusive with a document selection, and it is the one
|
|
279
425
|
// Target whose name has to say where it came FROM — "<header> in layouts/base.json" is the whole
|
|
280
426
|
// Answer to "why can I not edit this".
|
|
@@ -282,6 +428,12 @@ function inspectorTarget(): string {
|
|
|
282
428
|
if (layout) {
|
|
283
429
|
return `<${layout.tagName || "element"}> in ${layout.layoutFile || "the layout"}`;
|
|
284
430
|
}
|
|
431
|
+
// The Styles workspace's Elements view styles a TAG: name it, as the Style body's `h1 · Base`
|
|
432
|
+
// Does, rather than whatever node the document selection happens to hold.
|
|
433
|
+
const tag = stylebookTarget(tab);
|
|
434
|
+
if (tag) {
|
|
435
|
+
return tag;
|
|
436
|
+
}
|
|
285
437
|
const paths = tab.session.selection;
|
|
286
438
|
const selection = primarySelection(paths);
|
|
287
439
|
if (selection) {
|
|
@@ -291,6 +443,10 @@ function inspectorTarget(): string {
|
|
|
291
443
|
? `${paths.length} elements`
|
|
292
444
|
: nodeLabel(getNodeAtPath(tab.doc.document, selection));
|
|
293
445
|
}
|
|
294
|
-
|
|
446
|
+
return documentName(tab.documentPath);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/** A document's own name in the header: its file name, or "document" for an unsaved one. */
|
|
450
|
+
function documentName(path: string | null | undefined): string {
|
|
295
451
|
return path ? (path.split("/").at(-1) ?? "document") : "document";
|
|
296
452
|
}
|
package/src/panels/seo-modal.ts
CHANGED
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
* writing. A previewed SERP result is not a field; it is a picture you study, and studying it in a
|
|
9
9
|
* strip above the canvas meant the card grew taller than the thing it describes.
|
|
10
10
|
*
|
|
11
|
-
* So it opens as a modal, from
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
11
|
+
* So it opens as a modal, from the Inspector's Page tab (and, once, from the Document Header card
|
|
12
|
+
* Edit used to dock above the page, studio.md §4.2). The tab's button runs `document.openSeo`, so
|
|
13
|
+
* there is a second door in the palette and no surface owns the capability (one definition site per
|
|
14
|
+
* action, §13).
|
|
15
15
|
*
|
|
16
|
-
* **The
|
|
17
|
-
*
|
|
18
|
-
*
|
|
16
|
+
* **The Page tab keeps the fields; the modal keeps the picture.** Title lives on the tab, because
|
|
17
|
+
* it is the one head value you type while writing. Everything the modal holds is either a rendering
|
|
18
|
+
* of what the build will emit or a field you set once and leave.
|
|
19
19
|
*
|
|
20
20
|
* **This module is the flow; `surfaces/seo.json` is the markup.** What lives here is every
|
|
21
21
|
* judgement the picture rests on: which realm a commit is written into, what each previewed line
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
* decision — it holds the parts, the ARIA and the styling, and it branches on flags this module
|
|
25
25
|
* hands it.
|
|
26
26
|
*
|
|
27
|
-
* The mutation path is the
|
|
28
|
-
*
|
|
29
|
-
*
|
|
27
|
+
* The mutation path is the Page tab's: a markdown page commits through `applyContentMutation` and a
|
|
28
|
+
* JSON one through `transact`, both taking the tab so the modal edits the document it was opened
|
|
29
|
+
* over rather than whichever pane has focus.
|
|
30
30
|
*
|
|
31
31
|
* @docs studio/editing/frontmatter
|
|
32
32
|
*/
|
|
@@ -34,21 +34,18 @@
|
|
|
34
34
|
import { activeRegistry } from "../commands/active-registry";
|
|
35
35
|
import { HEAD_EDIT_DEBOUNCE } from "../ui/timing";
|
|
36
36
|
import { previewAssetSrc } from "../canvas/asset-refs";
|
|
37
|
-
import { getPlatform } from "../platform";
|
|
38
37
|
import { layerHost } from "../ui/layers";
|
|
39
|
-
import { mediaSiteUrl } from "../files/media-paths";
|
|
40
|
-
import { openMenu } from "../surfaces/menu";
|
|
41
38
|
import { openSeoSurface } from "../surfaces/seo";
|
|
42
39
|
import { provenanceTitle } from "./provenance";
|
|
43
|
-
import { PUBLIC_DIR } from "@jxsuite/schema/asset-paths";
|
|
44
|
-
import { scanLibrary } from "../browse/library-model";
|
|
45
40
|
import { tabLabel } from "./tab-strip";
|
|
46
41
|
import { transact } from "../tabs/transact";
|
|
47
42
|
import { activeTab } from "../workspace/workspace";
|
|
48
|
-
import {
|
|
43
|
+
import { pickAndUpload, showMediaPickerPopover } from "../ui/media-picker";
|
|
49
44
|
import {
|
|
50
45
|
OG_FIELDS,
|
|
51
46
|
PAGE_FIELDS,
|
|
47
|
+
pageDescription,
|
|
48
|
+
setPageDescription,
|
|
52
49
|
applyContentMutation,
|
|
53
50
|
buildHeadDoc,
|
|
54
51
|
findLinkEntry,
|
|
@@ -226,6 +223,11 @@ function writeField(
|
|
|
226
223
|
applyMutation((doc: JxMutableNode) => upsertLink(doc, "icon", trimmed));
|
|
227
224
|
return;
|
|
228
225
|
}
|
|
226
|
+
if (key === "description") {
|
|
227
|
+
// The page's one description, written where the build reads it.
|
|
228
|
+
applyMutation((doc: JxMutableNode) => setPageDescription(doc, trimmed));
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
229
231
|
const field = META_BY_KEY.get(key);
|
|
230
232
|
if (!field) {
|
|
231
233
|
return;
|
|
@@ -252,35 +254,6 @@ function cancelPending(key?: string): void {
|
|
|
252
254
|
}
|
|
253
255
|
}
|
|
254
256
|
|
|
255
|
-
// ─── The project's media ──────────────────────────────────────────────────────
|
|
256
|
-
|
|
257
|
-
/** The listing, once. Invalidated by an upload, which is the only thing that changes it here. */
|
|
258
|
-
let _media: string[] | null = null;
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* Every media file under `public/`, as the site URLs a pick would write.
|
|
262
|
-
*
|
|
263
|
-
* `browse/library-model.ts`'s walker rather than a second one: it is the scanner the Library pane
|
|
264
|
-
* already runs over the same tree, it records what it could not read instead of swallowing it, and
|
|
265
|
-
* it skips the directories nobody wants walked. The site URL is the authored form — what production
|
|
266
|
-
* serves — and `files/media-paths.ts` holds the one definition of that mapping.
|
|
267
|
-
*/
|
|
268
|
-
async function mediaChoices(): Promise<string[]> {
|
|
269
|
-
if (_media) {
|
|
270
|
-
return _media;
|
|
271
|
-
}
|
|
272
|
-
const { files } = await scanLibrary([PUBLIC_DIR], getPlatform());
|
|
273
|
-
_media = files
|
|
274
|
-
.filter((file) => MEDIA_EXTENSIONS.has(file.ext))
|
|
275
|
-
.map((file) => mediaSiteUrl(file.path));
|
|
276
|
-
return _media;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
/** Forget the listing: it was derived from a tree an upload has just changed. */
|
|
280
|
-
function invalidateMediaChoices(): void {
|
|
281
|
-
_media = null;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
257
|
// ─── The modal ───────────────────────────────────────────────────────────────
|
|
285
258
|
|
|
286
259
|
/** The open surface, or `null`. One at a time: it is about the focused document. */
|
|
@@ -359,9 +332,12 @@ function buildView(tab: Tab, headDoc: JxMutableNode, head: JxHeadEntry[]): SeoVi
|
|
|
359
332
|
note: "",
|
|
360
333
|
rows: [
|
|
361
334
|
...PAGE_FIELDS.map((field) =>
|
|
362
|
-
editRow(
|
|
363
|
-
|
|
364
|
-
|
|
335
|
+
editRow(
|
|
336
|
+
field.key,
|
|
337
|
+
field.label,
|
|
338
|
+
field.key === "description" ? pageDescription(headDoc) : metaValue(head, field.key),
|
|
339
|
+
{ multiline: field.multiline },
|
|
340
|
+
),
|
|
365
341
|
),
|
|
366
342
|
editRow(ICON_KEY, "Icon", iconHref, { media: true }),
|
|
367
343
|
],
|
|
@@ -409,69 +385,26 @@ function commitField(key: string, value: string): void {
|
|
|
409
385
|
renderSeoModal();
|
|
410
386
|
}
|
|
411
387
|
|
|
412
|
-
/**
|
|
388
|
+
/**
|
|
389
|
+
* Upload into a media row: the image field's own Upload (`ui/media-picker.ts`), which opens the
|
|
390
|
+
* picker, uploads through the one core, and hands the first file's ref back. A commit that lands
|
|
391
|
+
* after the modal closed writes nothing, because {@link commitField} is about the open modal.
|
|
392
|
+
*/
|
|
413
393
|
function uploadInto(key: string): void {
|
|
414
|
-
|
|
415
|
-
a node the surface owns outside its own document, which is exactly what a surface may not
|
|
416
|
-
have. */
|
|
417
|
-
const input = document.createElement("input");
|
|
418
|
-
input.type = "file";
|
|
419
|
-
input.multiple = true;
|
|
420
|
-
input.accept = uploadAccept();
|
|
421
|
-
input.addEventListener("change", () => {
|
|
422
|
-
if (!input.files?.length) {
|
|
423
|
-
return;
|
|
424
|
-
}
|
|
425
|
-
void uploadAssets([...input.files]).then((uploaded) => {
|
|
426
|
-
invalidateMediaChoices();
|
|
427
|
-
const [first] = uploaded;
|
|
428
|
-
if (first) {
|
|
429
|
-
commitField(key, first.ref);
|
|
430
|
-
}
|
|
431
|
-
});
|
|
432
|
-
});
|
|
433
|
-
input.click();
|
|
394
|
+
pickAndUpload((ref: string) => commitField(key, ref));
|
|
434
395
|
}
|
|
435
396
|
|
|
436
397
|
/**
|
|
437
|
-
* Offer the project's
|
|
398
|
+
* Offer the project's images for one row: the media picker's own compact browser, with its **Browse
|
|
399
|
+
* all images…** row opening the Media workspace's surface in pick mode.
|
|
438
400
|
*
|
|
439
|
-
*
|
|
440
|
-
*
|
|
441
|
-
*
|
|
442
|
-
*
|
|
401
|
+
* Not a list of this module's own. It kept one (a walk of `public/` alone, and a kit menu of site
|
|
402
|
+
* URLs) because the old picker painted into a layer div UNDER the modal; the browser is a top-layer
|
|
403
|
+
* `jx-popover` now, so it paints over the modal that opened it, and the field and this dialog
|
|
404
|
+
* answer "what media does this project have" from the same listing (studio.md §9.3).
|
|
443
405
|
*/
|
|
444
406
|
function browseFor(key: string, anchor: HTMLElement): void {
|
|
445
|
-
|
|
446
|
-
openMenu({
|
|
447
|
-
label: "Project media",
|
|
448
|
-
opener: anchor,
|
|
449
|
-
region: "seo-media",
|
|
450
|
-
rows:
|
|
451
|
-
choices.length > 0
|
|
452
|
-
? choices.map((path) => ({
|
|
453
|
-
destructive: false,
|
|
454
|
-
disabled: false,
|
|
455
|
-
dividerAbove: false,
|
|
456
|
-
id: path,
|
|
457
|
-
run: () => commitField(key, path),
|
|
458
|
-
/* The site URL rather than the file name, because it is the string the pick writes
|
|
459
|
-
AND the only one of the two that is unique: two `hero.jpg`s in two directories are
|
|
460
|
-
one row twice over in a list that shows names. */
|
|
461
|
-
title: path,
|
|
462
|
-
}))
|
|
463
|
-
: [
|
|
464
|
-
{
|
|
465
|
-
destructive: false,
|
|
466
|
-
disabled: true,
|
|
467
|
-
dividerAbove: false,
|
|
468
|
-
id: "seo.media.empty",
|
|
469
|
-
requires: "a file under public/",
|
|
470
|
-
title: "No media in this project",
|
|
471
|
-
},
|
|
472
|
-
],
|
|
473
|
-
});
|
|
474
|
-
});
|
|
407
|
+
showMediaPickerPopover(anchor, (ref: string) => commitField(key, ref), { images: true });
|
|
475
408
|
}
|
|
476
409
|
|
|
477
410
|
/** Open it over `tab`. Idempotent — opening it again re-points it at the current document. */
|
|
@@ -529,10 +462,10 @@ export function closeSeoModal(): void {
|
|
|
529
462
|
/**
|
|
530
463
|
* `document.openSeo` — the one capability behind both buttons.
|
|
531
464
|
*
|
|
532
|
-
* The
|
|
533
|
-
*
|
|
534
|
-
*
|
|
535
|
-
*
|
|
465
|
+
* The Page tab renders a control that runs this, so it does not own it and the palette has it by
|
|
466
|
+
* name. A record rather than two click handlers, for the reason the rendering-context axes became
|
|
467
|
+
* records: a surface that IS the capability is a capability the palette, the assistant and
|
|
468
|
+
* `__jxAutomation` cannot reach.
|
|
536
469
|
*
|
|
537
470
|
* @returns {AnyCommand[]}
|
|
538
471
|
*/
|