@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
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
2
|
+
/**
|
|
3
|
+
* The writing-mode banner surface: one line over the canvas while a collection entry is written
|
|
4
|
+
* inside its template's layout (`specs/studio.md` §22.5).
|
|
5
|
+
*
|
|
6
|
+
* This is the adapter. `content/writing-banner.ts` decides what the line says and where its button
|
|
7
|
+
* goes; this module writes the projection into a scope and mounts `writing-banner.json`.
|
|
8
|
+
*
|
|
9
|
+
* @docs studio/projects/content-types
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { reactive } from "../reactivity";
|
|
13
|
+
import { mountSurface, registerSurface } from "../ui/surface";
|
|
14
|
+
import writingBannerDoc from "./writing-banner.json";
|
|
15
|
+
import type { SurfaceHandle } from "../ui/surface";
|
|
16
|
+
|
|
17
|
+
registerSurface("writing-banner", writingBannerDoc);
|
|
18
|
+
|
|
19
|
+
/** What the banner draws. */
|
|
20
|
+
export interface WritingBannerView {
|
|
21
|
+
/** The region id stamped on the root: `pane.<id>/writing-banner`. */
|
|
22
|
+
region: string;
|
|
23
|
+
text: string;
|
|
24
|
+
/** "Design the post page", or "Edit the Base template in Design" when the entry has no page. */
|
|
25
|
+
actionLabel: string;
|
|
26
|
+
/** Whether there is a template to open at all. */
|
|
27
|
+
actionState: "hidden" | "shown";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface WritingBannerActions {
|
|
31
|
+
/** Open the entry's template in Design. */
|
|
32
|
+
openTemplate: () => void;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface WritingBannerHandle {
|
|
36
|
+
readonly ready: Promise<unknown>;
|
|
37
|
+
update: (view: WritingBannerView) => void;
|
|
38
|
+
dispose: () => void;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface WritingBannerScope extends WritingBannerView, WritingBannerActions {}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Mount the banner into `host`, the empty node the canvas stage drew for it.
|
|
45
|
+
*
|
|
46
|
+
* @param host The stage's `writing-banner` host.
|
|
47
|
+
* @param view What it says.
|
|
48
|
+
* @param actions What its button does.
|
|
49
|
+
*/
|
|
50
|
+
export function mountWritingBannerSurface(
|
|
51
|
+
host: HTMLElement,
|
|
52
|
+
view: WritingBannerView,
|
|
53
|
+
actions: WritingBannerActions,
|
|
54
|
+
): WritingBannerHandle {
|
|
55
|
+
const scope: WritingBannerScope = reactive<WritingBannerScope>({ ...view, ...actions });
|
|
56
|
+
let mounted: SurfaceHandle | null = null;
|
|
57
|
+
let disposed = false;
|
|
58
|
+
const ready = mountSurface("writing-banner", scope, host).then((surface) => {
|
|
59
|
+
if (disposed) {
|
|
60
|
+
surface.dispose();
|
|
61
|
+
} else {
|
|
62
|
+
mounted = surface;
|
|
63
|
+
}
|
|
64
|
+
return surface;
|
|
65
|
+
});
|
|
66
|
+
return {
|
|
67
|
+
dispose() {
|
|
68
|
+
disposed = true;
|
|
69
|
+
mounted?.dispose();
|
|
70
|
+
mounted = null;
|
|
71
|
+
},
|
|
72
|
+
ready,
|
|
73
|
+
update(next) {
|
|
74
|
+
scope.region = next.region;
|
|
75
|
+
scope.text = next.text;
|
|
76
|
+
scope.actionLabel = next.actionLabel;
|
|
77
|
+
scope.actionState = next.actionState;
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The repeaters a file wrote as a node's whole `children`, so a save can write them back that way.
|
|
3
|
+
*
|
|
4
|
+
* A node may hold a repeater two ways: as a member of its children array (`children: [{ $prototype:
|
|
5
|
+
* "Array", … }]`) or as the whole children slot (`children: { $prototype: "Array", … }`). The two
|
|
6
|
+
* render the same, and the editor works in the first form only: `normalizeArrayChildren` rewrites
|
|
7
|
+
* every document a tab loads, because every mutation, path and history checkpoint assumes a
|
|
8
|
+
* children array. Without a record of what the file said, a save then rewrote every bare repeater
|
|
9
|
+
* in it into the member form, so one inserted paragraph produced a diff in a list nobody touched,
|
|
10
|
+
* and undoing every edit still left the file different from the one on disk.
|
|
11
|
+
*
|
|
12
|
+
* **Two keys, either of which is enough.** The pointer of the node that held the repeater survives
|
|
13
|
+
* an edit inside the repeater (a restyled template); the repeater's own JSON survives an edit that
|
|
14
|
+
* moves it (a sibling inserted above an ancestor shifts every pointer below it). A repeater both
|
|
15
|
+
* moved and changed loses both and is written in the member form, which renders the same. Only a
|
|
16
|
+
* children array whose ONLY member is a repeater is unwrapped: a node that has gained a sibling of
|
|
17
|
+
* its repeater can no longer be written the bare way at all.
|
|
18
|
+
*
|
|
19
|
+
* @docs studio/interface/tabs
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { isJsonObject, isMappedArray } from "@jxsuite/schema/guards";
|
|
23
|
+
import type { JsonObject, JsonValue, JxMutableNode } from "@jxsuite/schema/types";
|
|
24
|
+
import { normalizeArrayChildren, pointerToken } from "../state";
|
|
25
|
+
|
|
26
|
+
/** What a file said about its bare repeaters, in the normalized document's coordinates. */
|
|
27
|
+
export interface BareRepeaters {
|
|
28
|
+
/** The JSON Pointer of each node whose `children` WAS the repeater. */
|
|
29
|
+
readonly pointers: ReadonlySet<string>;
|
|
30
|
+
/** `JSON.stringify` of each such repeater as it was read. */
|
|
31
|
+
readonly fingerprints: ReadonlySet<string>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Normalize a freshly read document in place (`normalizeArrayChildren`) and return what it rewrote,
|
|
36
|
+
* or null when the file held no bare repeater — the common case, which needs no record.
|
|
37
|
+
*/
|
|
38
|
+
export function normalizeDocument(document: JxMutableNode): BareRepeaters | null {
|
|
39
|
+
const pointers = new Set<string>();
|
|
40
|
+
const fingerprints = new Set<string>();
|
|
41
|
+
normalizeArrayChildren(document, (pointer, repeater) => {
|
|
42
|
+
pointers.add(pointer);
|
|
43
|
+
fingerprints.add(JSON.stringify(repeater));
|
|
44
|
+
});
|
|
45
|
+
return pointers.size === 0 ? null : { fingerprints, pointers };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The document as the file should hold it: every single-member children array whose repeater the
|
|
50
|
+
* record names, written back as the node's whole `children`. Copy-on-write, so the tab's document
|
|
51
|
+
* (a reactive tree the editor owns) is never touched, and a document with nothing to restore is
|
|
52
|
+
* returned as it is.
|
|
53
|
+
*/
|
|
54
|
+
export function restoreBareRepeaters(
|
|
55
|
+
document: JxMutableNode,
|
|
56
|
+
record: BareRepeaters | null,
|
|
57
|
+
): JxMutableNode {
|
|
58
|
+
if (!record) {
|
|
59
|
+
return document;
|
|
60
|
+
}
|
|
61
|
+
/* SAFETY: a Jx document is JSON (it is read from, and written to, a JSON file); the restored copy
|
|
62
|
+
is the same node with some `children` slots holding their sole repeater directly — the bare
|
|
63
|
+
form the node's schema allows. */
|
|
64
|
+
return restoreValue(document as JsonValue, "", record) as JxMutableNode;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Restore inside one value of the tree, returning it unchanged when nothing below it moved. */
|
|
68
|
+
function restoreValue(value: JsonValue, pointer: string, record: BareRepeaters): JsonValue {
|
|
69
|
+
if (Array.isArray(value)) {
|
|
70
|
+
let copy: JsonValue[] | null = null;
|
|
71
|
+
for (const [i, item] of value.entries()) {
|
|
72
|
+
const next = restoreValue(item, `${pointer}/${i}`, record);
|
|
73
|
+
if (next !== item) {
|
|
74
|
+
copy ??= [...value];
|
|
75
|
+
copy[i] = next;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return copy ?? value;
|
|
79
|
+
}
|
|
80
|
+
if (!isJsonObject(value)) {
|
|
81
|
+
return value;
|
|
82
|
+
}
|
|
83
|
+
let copy: JsonObject | null = null;
|
|
84
|
+
for (const [key, child] of Object.entries(value)) {
|
|
85
|
+
let next = restoreValue(child, `${pointer}/${pointerToken(key)}`, record);
|
|
86
|
+
if (key === "children" && Array.isArray(next) && next.length === 1) {
|
|
87
|
+
const [only] = next;
|
|
88
|
+
if (
|
|
89
|
+
isMappedArray(only) &&
|
|
90
|
+
(record.pointers.has(pointer) || record.fingerprints.has(JSON.stringify(only)))
|
|
91
|
+
) {
|
|
92
|
+
next = only;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (next !== child) {
|
|
96
|
+
copy ??= { ...value };
|
|
97
|
+
copy[key] = next;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return copy ?? value;
|
|
101
|
+
}
|
package/src/tabs/tab.ts
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
import { effectScope, reactive } from "../reactivity";
|
|
3
3
|
import { formatByName, formatForPath } from "../format/format-host";
|
|
4
4
|
import type { FormatFrontmatter } from "../format/format-host";
|
|
5
|
-
import {
|
|
5
|
+
import { normalizeDocument } from "./bare-repeaters";
|
|
6
|
+
import type { BareRepeaters } from "./bare-repeaters";
|
|
6
7
|
import type { JxPath } from "../state";
|
|
7
8
|
import type { FormulaEditDef, FunctionEditDef, InlineEditDef, JsonValue } from "../types";
|
|
8
9
|
import { editorKindForMode } from "../commands/context";
|
|
@@ -15,13 +16,20 @@ import type { JsonLayout } from "@jxsuite/schema/json-layout";
|
|
|
15
16
|
* The project's configuration file, project-relative.
|
|
16
17
|
*
|
|
17
18
|
* Named here rather than at the four places that used to spell it, because it is a DOCUMENT PATH —
|
|
18
|
-
* `inferModes` answers `["stylebook", "source"]` for it (
|
|
19
|
-
* `tabs/project-config.ts` binds the tab at
|
|
19
|
+
* `inferModes` answers `["stylebook", "tokens", "source"]` for it (the Styles workspace's Elements,
|
|
20
|
+
* Variables and Code views; editor kind `config`), and `tabs/project-config.ts` binds the tab at
|
|
21
|
+
* this path as the configuration document.
|
|
20
22
|
*/
|
|
21
23
|
export const PROJECT_CONFIG_PATH = "project.json";
|
|
22
24
|
|
|
23
25
|
export interface TabUi {
|
|
26
|
+
/** The Inspector leaf showing (`shell.ts`'s `INSPECTOR_TAB_IDS`); Page on a fresh tab (§6). */
|
|
24
27
|
rightTab: string;
|
|
28
|
+
/**
|
|
29
|
+
* The Element leaf last shown — Content, Style or Logic — so the selection-driven switch from
|
|
30
|
+
* Page returns to the view the author was using rather than always to Content (§6).
|
|
31
|
+
*/
|
|
32
|
+
elementTab: string;
|
|
25
33
|
canvasMode: string;
|
|
26
34
|
/** Preview toggle — composes with an edit/design canvasMode; the effective mode becomes "preview". */
|
|
27
35
|
preview: boolean;
|
|
@@ -198,6 +206,22 @@ export interface Tab {
|
|
|
198
206
|
* file.
|
|
199
207
|
*/
|
|
200
208
|
layout: JsonLayout | null;
|
|
209
|
+
/**
|
|
210
|
+
* The text a format-class file (Markdown) was read as, or null for a JSON document, a new
|
|
211
|
+
* document or a stub. The format's serializer is handed it on save
|
|
212
|
+
* (`files/serialize-document.ts`) so every frontmatter key the author did not edit keeps its
|
|
213
|
+
* own spelling and the body keeps its markers (`@jxsuite/parser` `source-style.ts`). The
|
|
214
|
+
* lifetime is `layout`'s: an edit leaves it alone, and a read from disk, a source-view commit,
|
|
215
|
+
* a peer's text or a save replaces it with the text just read or written.
|
|
216
|
+
*/
|
|
217
|
+
source: string | null;
|
|
218
|
+
/**
|
|
219
|
+
* The repeaters the file wrote as a node's whole `children`, which loading rewrote into the
|
|
220
|
+
* member form the editor works in (`tabs/bare-repeaters.ts`); null when it wrote none. A fact
|
|
221
|
+
* about the file with the lifetime `layout` has: a reload or a source-view commit replaces it,
|
|
222
|
+
* an edit or an undo leaves it alone, and a save writes those repeaters back as they were.
|
|
223
|
+
*/
|
|
224
|
+
bareRepeaters: BareRepeaters | null;
|
|
201
225
|
};
|
|
202
226
|
session: {
|
|
203
227
|
/**
|
|
@@ -267,7 +291,8 @@ function createDefaultUi(canvasMode: string, preview = false): TabUi {
|
|
|
267
291
|
previewLocale: null,
|
|
268
292
|
previewParams: {},
|
|
269
293
|
previewProps: null,
|
|
270
|
-
rightTab: "
|
|
294
|
+
rightTab: "page",
|
|
295
|
+
elementTab: "properties",
|
|
271
296
|
showLayout: true,
|
|
272
297
|
styleFilter: "",
|
|
273
298
|
styleSections: {},
|
|
@@ -302,6 +327,7 @@ const ALL_MODES = ["edit", "design", "preview", "source", "stylebook", "git-diff
|
|
|
302
327
|
* openedFrom?: TabOrigin | null;
|
|
303
328
|
* preview?: boolean;
|
|
304
329
|
* layout?: JsonLayout | null;
|
|
330
|
+
* source?: string | null;
|
|
305
331
|
* }} opts
|
|
306
332
|
* @returns {Tab}
|
|
307
333
|
*/
|
|
@@ -316,6 +342,8 @@ export function createTab({
|
|
|
316
342
|
openedFrom = null,
|
|
317
343
|
preview: previewTab = false,
|
|
318
344
|
layout = null,
|
|
345
|
+
source = null,
|
|
346
|
+
canvasMode,
|
|
319
347
|
}: {
|
|
320
348
|
id: string;
|
|
321
349
|
documentPath?: string | null;
|
|
@@ -327,28 +355,37 @@ export function createTab({
|
|
|
327
355
|
openedFrom?: TabOrigin | null;
|
|
328
356
|
preview?: boolean;
|
|
329
357
|
layout?: JsonLayout | null;
|
|
358
|
+
/** The text a format-class file was read as (`doc.source`). */
|
|
359
|
+
source?: string | null;
|
|
360
|
+
/**
|
|
361
|
+
* The mode to open in instead of the first declared one: a comparison opens straight into
|
|
362
|
+
* `git-diff`, so the tab is never active in an edit mode that belongs to another workspace.
|
|
363
|
+
*/
|
|
364
|
+
canvasMode?: string | undefined;
|
|
330
365
|
}) {
|
|
331
366
|
const scope = effectScope();
|
|
332
367
|
|
|
333
368
|
// Normalize legacy whole-children repeaters to the canonical array-member form before the doc
|
|
334
369
|
// (and its first history checkpoint) are stored.
|
|
335
|
-
|
|
370
|
+
const bareRepeaters = normalizeDocument(document);
|
|
336
371
|
|
|
337
372
|
const resolvedModes = capabilities?.modes ?? inferModes(documentPath, sourceFormat);
|
|
338
373
|
// A tab opens in its first allowed mode — never one the toolbar would disable.
|
|
339
374
|
// Formats author mode order so the default comes first (edit, stylebook, etc.).
|
|
340
375
|
// "preview" is a per-tab toggle rather than a base mode: a preview-first format opens
|
|
341
376
|
// In its first non-preview mode with the toggle already on.
|
|
342
|
-
const initialCanvasMode = resolvedModes.find((m) => m !== "preview") ?? "edit";
|
|
377
|
+
const initialCanvasMode = canvasMode ?? resolvedModes.find((m) => m !== "preview") ?? "edit";
|
|
343
378
|
const initialPreview = resolvedModes[0] === "preview";
|
|
344
379
|
|
|
345
380
|
const doc: Tab["doc"] = {
|
|
381
|
+
bareRepeaters,
|
|
346
382
|
content: { frontmatter: frontmatter || {} },
|
|
347
383
|
dirty: false,
|
|
348
384
|
document,
|
|
349
385
|
handlersSource: null,
|
|
350
386
|
layout,
|
|
351
387
|
mode: inferDocumentMode(documentPath, sourceFormat),
|
|
388
|
+
source,
|
|
352
389
|
sourceFormat,
|
|
353
390
|
};
|
|
354
391
|
const history: Tab["history"] = {
|
|
@@ -404,7 +441,10 @@ export function createTab({
|
|
|
404
441
|
*/
|
|
405
442
|
function inferModes(documentPath: string | null | undefined, sourceFormat: string | null) {
|
|
406
443
|
if (documentPath === PROJECT_CONFIG_PATH) {
|
|
407
|
-
|
|
444
|
+
/* Elements, Variables and Code: the Styles workspace's three views. Spelled here rather than
|
|
445
|
+
imported from `style/project-styles` (`STYLES_TAB_MODES`), whose imports reach `store`,
|
|
446
|
+
which imports this module; `tests/project-config.test.ts` holds the two lists equal. */
|
|
447
|
+
return ["stylebook", "tokens", "source"];
|
|
408
448
|
}
|
|
409
449
|
const format = formatByName(sourceFormat) ?? formatForPath(documentPath);
|
|
410
450
|
if (format) {
|
package/src/types.ts
CHANGED
|
@@ -311,25 +311,9 @@ export interface StudioPlatform {
|
|
|
311
311
|
/**
|
|
312
312
|
* URL of the canvas iframe document. Optional: when set (chromium serves it from the project
|
|
313
313
|
* server under the studio namespace), the iframe host uses it; otherwise the host falls back to
|
|
314
|
-
* the default dev-server path. Not keyed on `id
|
|
315
|
-
* "desktop"`, but only chromium sets this.
|
|
314
|
+
* the default dev-server path. Not keyed on `id`.
|
|
316
315
|
*/
|
|
317
316
|
canvasUrl?: string;
|
|
318
|
-
/**
|
|
319
|
-
* True when this platform resolves {@link canvasUrl} ASYNCHRONOUSLY.
|
|
320
|
-
*
|
|
321
|
-
* Electrobun does: the url is this window's loopback port, fetched over RPC inside `activate()`.
|
|
322
|
-
* Until the canvas fallback was anchored to the bundle it did not matter — the old literal
|
|
323
|
-
* `/packages/studio/canvas.html` resolved to nothing servable under `views://`, so an early frame
|
|
324
|
-
* simply failed and the host rebuilt when the real url landed. Now the fallback RESOLVES:
|
|
325
|
-
* `views://studio/canvas.html` is a document electrobun really stages. An early frame would boot
|
|
326
|
-
* the whole canvas bundle inside the SHELL's app-privileged origin, in a CEF instance running
|
|
327
|
-
* `disable-site-isolation-trials` — and the cross-origin loopback canvas exists precisely so that
|
|
328
|
-
* cannot happen. Declaring it makes the host wait instead.
|
|
329
|
-
*
|
|
330
|
-
* Not keyed on `id`: chromium and electrobun both report `"desktop"`, and only electrobun defers.
|
|
331
|
-
*/
|
|
332
|
-
canvasUrlDeferred?: boolean;
|
|
333
317
|
/**
|
|
334
318
|
* Base URL the canvas fetches PROJECT FILES from — component `$ref`s, `$src` modules, images.
|
|
335
319
|
*
|
|
@@ -408,12 +392,11 @@ export interface StudioPlatform {
|
|
|
408
392
|
* image. So a caller that must DECODE a project file — the image editor — needs this instead.
|
|
409
393
|
*
|
|
410
394
|
* **The `<img>` route is not an alternative, on the one platform that matters most.** A preview
|
|
411
|
-
* `src` from `files/media-paths.ts`
|
|
412
|
-
*
|
|
413
|
-
* `
|
|
414
|
-
*
|
|
415
|
-
*
|
|
416
|
-
* worked around.
|
|
395
|
+
* `src` from `files/media-paths.ts` can be a cross-origin loopback URL while the shell sits on
|
|
396
|
+
* another origin, so drawing it into a canvas taints the canvas and `toBlob()` throws; and
|
|
397
|
+
* `server.md` §4.2 bans CORS outright, because the whole loopback security model rests on the
|
|
398
|
+
* browser refusing cross-origin reads. Bytes through the PAL become a same-origin `Blob`, so
|
|
399
|
+
* tainting stops being a thing that can happen rather than a thing that is worked around.
|
|
417
400
|
*
|
|
418
401
|
* Optional, and feature-detected like every optional member: a backend without it simply does not
|
|
419
402
|
* offer the image editor, which is the honest degradation `specs/desktop.md` §3.1 asks for.
|
|
@@ -595,6 +578,16 @@ export interface StudioPlatform {
|
|
|
595
578
|
gitDiscard: (files: string[]) => Promise<void>;
|
|
596
579
|
gitClone?: (url: string) => Promise<{ ok: boolean; root: string }>;
|
|
597
580
|
gitInit: () => Promise<void>;
|
|
581
|
+
/**
|
|
582
|
+
* True on a host whose git is the remote's: a commit lands on GitHub as it is made, a push is
|
|
583
|
+
* only a check that it did, and each branch is a session of its own, so a checkout reloads the
|
|
584
|
+
* window into that branch's session (the cloud). Absent means an ordinary working tree, where a
|
|
585
|
+
* commit is local until it is pushed and a checkout swaps files in place.
|
|
586
|
+
*
|
|
587
|
+
* A declaration rather than a method, because what differs is the meaning of the verbs every host
|
|
588
|
+
* has: the Publish workspace reads it to say what a verb will do (studio.md §22.8).
|
|
589
|
+
*/
|
|
590
|
+
gitHosted?: boolean;
|
|
598
591
|
/**
|
|
599
592
|
* Build the site to its output directory, so a reader opens what the author is looking at.
|
|
600
593
|
*
|
|
@@ -864,9 +857,9 @@ export interface StudioPlatform {
|
|
|
864
857
|
* Watch the backend connection, on platforms whose transport can lose one.
|
|
865
858
|
*
|
|
866
859
|
* Only a socket-based launcher implements this: the dev server talks over `fetch` and has nothing
|
|
867
|
-
* to lose,
|
|
868
|
-
*
|
|
869
|
-
*
|
|
860
|
+
* to lose, The chromium launcher holds one long-lived WebSocket, and when it died every call
|
|
861
|
+
* after it hung with no error anywhere — so the transport reports the state, and the studio says
|
|
862
|
+
* it out loud.
|
|
870
863
|
*
|
|
871
864
|
* The handler is called on each transition, never repeatedly for one state.
|
|
872
865
|
*/
|
|
@@ -886,6 +879,8 @@ export interface ContentSectionEntry {
|
|
|
886
879
|
source?: string;
|
|
887
880
|
format?: string;
|
|
888
881
|
schema?: ContentTypeSchema;
|
|
882
|
+
/** The field a file-backed collection's records are identified by (the loader's `idField`). */
|
|
883
|
+
idField?: string;
|
|
889
884
|
$elements?: unknown[];
|
|
890
885
|
}
|
|
891
886
|
|
package/src/ui/form-controls.ts
CHANGED
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
import { mountSchemaBuilderSurface } from "../surfaces/schema-builder";
|
|
35
35
|
import { mountReferenceFieldSurface } from "../surfaces/reference-field";
|
|
36
36
|
import { mountSecretFieldSurface } from "../surfaces/secret-field";
|
|
37
|
+
import { mountMediaPicker, unmountMediaPicker } from "./media-picker";
|
|
37
38
|
import { camelToLabel, toCamelCase } from "../utils/studio-utils";
|
|
38
39
|
|
|
39
40
|
import type { JsonObject, JsonValue } from "@jxsuite/schema/types";
|
|
@@ -710,6 +711,44 @@ export const secretControl: SchemaFormMountedControl = { mount: mountSecret };
|
|
|
710
711
|
|
|
711
712
|
registerFormControl("secret", secretControl);
|
|
712
713
|
|
|
714
|
+
// ─── Media control ───────────────────────────────────────────────────────────
|
|
715
|
+
|
|
716
|
+
/**
|
|
717
|
+
* An image field as the media field: the path, its thumbnail, **Upload media** and **Browse
|
|
718
|
+
* media**, exactly as the page's Icon and OG Image rows draw them. The flow is
|
|
719
|
+
* `ui/media-picker.ts`'s, which already makes a repeat mount into the same host an update, so this
|
|
720
|
+
* control only keeps the latest commit hook and clears the field to absent rather than to "".
|
|
721
|
+
*
|
|
722
|
+
* @param {HTMLElement} host - The field's `[part="control-host"]`
|
|
723
|
+
* @param {SchemaFormControlArgs} args - The value and the commit hook
|
|
724
|
+
* @returns {SchemaFormControlHandle}
|
|
725
|
+
*/
|
|
726
|
+
function mountMedia(host: HTMLElement, args: SchemaFormControlArgs): SchemaFormControlHandle {
|
|
727
|
+
let latest = args;
|
|
728
|
+
const draw = (): void => {
|
|
729
|
+
mountMediaPicker(
|
|
730
|
+
host,
|
|
731
|
+
latest.key,
|
|
732
|
+
isString(latest.value) ? latest.value : "",
|
|
733
|
+
(value: string) => latest.onChange(value === "" ? undefined : value),
|
|
734
|
+
{ images: true },
|
|
735
|
+
);
|
|
736
|
+
};
|
|
737
|
+
draw();
|
|
738
|
+
return {
|
|
739
|
+
dispose: () => unmountMediaPicker(host),
|
|
740
|
+
update(next) {
|
|
741
|
+
latest = next;
|
|
742
|
+
draw();
|
|
743
|
+
},
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
/** The media control as the registry holds it, named so a test can drive it as the engine does. */
|
|
748
|
+
export const mediaControl: SchemaFormMountedControl = { mount: mountMedia };
|
|
749
|
+
|
|
750
|
+
registerFormControl("media", mediaControl);
|
|
751
|
+
|
|
713
752
|
// ─── Reference control ───────────────────────────────────────────────────────
|
|
714
753
|
|
|
715
754
|
/**
|
|
@@ -804,13 +843,13 @@ function entryIdsFor(collection: string): Promise<string[]> {
|
|
|
804
843
|
* `null` means the read is still in flight, and `onSettled` is called when it lands — which is the
|
|
805
844
|
* second frame a document has to be GIVEN, since nothing repaints it on the read's behalf.
|
|
806
845
|
*
|
|
807
|
-
* Exported because
|
|
808
|
-
*
|
|
809
|
-
*
|
|
810
|
-
*
|
|
811
|
-
*
|
|
812
|
-
*
|
|
813
|
-
*
|
|
846
|
+
* Exported because a surface draws the choices and is not this control: the Inspector's Page tab
|
|
847
|
+
* projects a `$ref` field as a picker row of its own (`panels/frontmatter-fields.ts`), and what it
|
|
848
|
+
* needs is not the widget but the answer behind it. Taking it from here rather than calling
|
|
849
|
+
* `listCollectionEntryIds` directly is what keeps ONE cache and ONE invalidation: a collection
|
|
850
|
+
* listed for the Page tab is not listed again for the entry editor, and
|
|
851
|
+
* {@link invalidateReferenceEntries} after an entry is created is still the single event that
|
|
852
|
+
* forgets it.
|
|
814
853
|
*
|
|
815
854
|
* @param {string} collection
|
|
816
855
|
* @param {() => void} [onSettled]
|
|
@@ -990,4 +1029,4 @@ export const referenceControl: SchemaFormMountedControl = { mount: mountReferenc
|
|
|
990
1029
|
registerFormControl("reference", referenceControl);
|
|
991
1030
|
|
|
992
1031
|
// Keep an explicit export so hosts can assert the built-ins module loaded
|
|
993
|
-
export const builtinFormControls = ["schema-builder", "secret", "reference"] as const;
|
|
1032
|
+
export const builtinFormControls = ["schema-builder", "secret", "reference", "media"] as const;
|
package/src/ui/layers.ts
CHANGED
|
@@ -99,6 +99,19 @@ export function isModalOpen(): boolean {
|
|
|
99
99
|
return Boolean(_dialogLayer?.querySelector(UNDERLAID) || _modalLayer?.querySelector(UNDERLAID));
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Whether a popover is showing anywhere in the chrome: a kit `jx-popover`, a menu, any element in
|
|
104
|
+
* the platform's popover top layer.
|
|
105
|
+
*
|
|
106
|
+
* A popover leaves Escape to the platform, which closes it as the keystroke's default action, so an
|
|
107
|
+
* app chord on bare Escape has to stand down while one is up: cancelling the keystroke would cancel
|
|
108
|
+
* the close as well, and whatever the chord did would happen under a popover that stays open. Asked
|
|
109
|
+
* of the live DOM for the reason {@link isModalOpen} is.
|
|
110
|
+
*/
|
|
111
|
+
export function isPopoverOpen(): boolean {
|
|
112
|
+
return document.querySelector(":popover-open") !== null;
|
|
113
|
+
}
|
|
114
|
+
|
|
102
115
|
/*
|
|
103
116
|
* `showDialog` was here, with `openOverlaySlot`, `focusOverlay`, `focusablesIn` and
|
|
104
117
|
* `BODY_FOCUSABLE` under it — and all five are GONE together.
|