@jxsuite/studio 6.1.1 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/chunks/2020-5wtzce5g.js +4 -0
- package/dist/chunks/{action-group-2mqby73c.js → action-group-4aan7g6g.js} +3 -3
- 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-6rbra5dy.js +4 -0
- package/dist/chunks/color-field-gy56c94g.js +4 -0
- package/dist/chunks/color-m7r1vk54.js +4 -0
- package/dist/chunks/color-slider-sqqdyf6c.js +4 -0
- package/dist/chunks/combobox-72h32ejk.js +4 -0
- 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/dialog-c4x05vyx.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-qg1b5eqx.js +51 -0
- package/dist/chunks/icons-63bjtbs7.js +4 -0
- package/dist/chunks/iframe-entry-2zggzajv.js +5 -0
- package/dist/chunks/iframe-entry-76j8vwwx.js +5 -0
- package/dist/chunks/iframe-entry-99nr5zfb.js +5 -0
- package/dist/chunks/iframe-entry-pkgmcgp0.js +5 -0
- package/dist/chunks/iframe-host-ssv7kyj0.js +4 -0
- package/dist/chunks/{index-2veqmnhr.js → index-32eqzv1k.js} +3 -3
- package/dist/chunks/index-f0jn7nnp.js +4 -0
- package/dist/chunks/{javascript-8nbvs12s.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-c421cf8c.js +4 -0
- 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-bdpzbfvs.js +4 -0
- package/dist/chunks/monaco-binding-vq1hgnn0.js +4 -0
- 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/number-field-y62xq0ty.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/select-rzds841e.js +4 -0
- package/dist/chunks/source-control-kwktr9y6.js +4 -0
- package/dist/chunks/split-c9zfdgxf.js +4 -0
- 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-6m380wp7.js +5 -0
- package/dist/chunks/studio-80jyh1xh.js +4 -0
- package/dist/chunks/studio-83mk4bgg.js +9 -0
- package/dist/chunks/{studio-kggey1jt.js → studio-881z1xrx.js} +4 -4
- package/dist/chunks/studio-8m0y2qe7.js +5 -0
- package/dist/chunks/studio-8tr6cfrc.js +5 -0
- 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-bbe4c90a.js +5 -0
- 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-8grwxtqk.js → studio-jcnsdaep.js} +4 -4
- package/dist/chunks/studio-jsgf2q5k.js +7 -0
- package/dist/chunks/{studio-1q1sh2ax.js → studio-k3xxbagr.js} +3 -3
- package/dist/chunks/studio-k7evxqh4.js +5 -0
- 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-rv11kfwa.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-h46vtzk8.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-wszjyh0j.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-pre0skq6.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-t6b6qe31.js → studio-r5qy30vx.js} +4 -4
- 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/swatch-group-ewh24n1f.js +4 -0
- package/dist/chunks/tabs-f5cw3tgp.js +4 -0
- package/dist/chunks/textfield-wewc8rq2.js +4 -0
- package/dist/chunks/toast-1gv0h53h.js +4 -0
- package/dist/chunks/toast-host-1yg5ar8d.js +4 -0
- package/dist/chunks/{toolbar-2nnzqhrj.js → toolbar-44cm5cta.js} +3 -3
- package/dist/chunks/tooltip-yypz28gq.js +4 -0
- package/dist/chunks/tree-9xa4hm7n.js +4 -0
- 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-bv552sfx.js +4 -0
- package/dist/iframe-entry.js +20 -16
- package/dist/manifest.json +77 -63
- package/dist/studio.js +106 -107
- package/dist/workers/ts.worker.js +3 -3
- package/package.json +17 -16
- package/src/about/about-modal.ts +4 -3
- package/src/account/action-flow.ts +45 -38
- package/src/account-status.ts +7 -2
- package/src/browse/component-examples.ts +272 -0
- package/src/browse/library-commands.ts +64 -104
- package/src/browse/library-layouts.ts +270 -53
- package/src/browse/library-model.ts +194 -134
- package/src/browse/library-pane.ts +748 -440
- package/src/browse/library-preview.ts +161 -26
- 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 +40 -10
- package/src/canvas/asset-resolve.ts +19 -23
- package/src/canvas/canvas-helpers.ts +7 -6
- package/src/canvas/canvas-live-render.ts +260 -77
- package/src/canvas/canvas-origin.ts +37 -12
- package/src/canvas/canvas-page-context.ts +112 -0
- package/src/canvas/canvas-patcher.ts +30 -30
- package/src/canvas/canvas-perf.ts +11 -5
- package/src/canvas/canvas-render.ts +175 -148
- package/src/canvas/canvas-surface.ts +5 -3
- package/src/canvas/canvas-utils.ts +147 -61
- package/src/canvas/dialog-path.ts +9 -4
- package/src/canvas/dialog-state.ts +1 -2
- package/src/canvas/diff-marks.ts +9 -16
- package/src/canvas/diff-toolbar.ts +8 -7
- package/src/canvas/edit-width-drag.ts +4 -1
- package/src/canvas/edit-width.ts +1 -3
- package/src/canvas/iframe-channel.ts +27 -13
- package/src/canvas/iframe-drop.ts +120 -12
- package/src/canvas/iframe-editable-root.ts +29 -16
- package/src/canvas/iframe-entry.ts +104 -75
- package/src/canvas/iframe-eval.ts +73 -49
- package/src/canvas/iframe-host.ts +269 -158
- package/src/canvas/iframe-inline-edit.ts +49 -30
- package/src/canvas/iframe-insert.ts +5 -4
- package/src/canvas/iframe-interaction.ts +30 -25
- package/src/canvas/iframe-keys.ts +11 -0
- package/src/canvas/iframe-overlay.ts +1 -1
- package/src/canvas/iframe-patch.ts +25 -21
- package/src/canvas/iframe-position.ts +12 -6
- package/src/canvas/iframe-protocol.ts +36 -21
- package/src/canvas/iframe-render.ts +84 -35
- package/src/canvas/iframe-slash.ts +24 -11
- package/src/canvas/iframe-subtree.ts +10 -3
- package/src/canvas/npm-modules.ts +22 -0
- package/src/canvas/path-mapping.ts +19 -12
- package/src/canvas/popover-path.ts +7 -3
- package/src/canvas/popover-state.ts +1 -2
- package/src/canvas/preview-navigate.ts +16 -0
- package/src/canvas/repeater-sources.ts +200 -0
- package/src/canvas/serialize-scope.ts +13 -5
- package/src/canvas/stage-scrollbar.ts +7 -2
- package/src/canvas/surface-registry.ts +27 -3
- package/src/collab/collab-commands.ts +7 -2
- package/src/collab/collab-session.ts +84 -45
- package/src/collab/collab-state.ts +4 -3
- package/src/collab/monaco-binding.ts +16 -13
- package/src/collab/monaco-cursors.ts +5 -2
- package/src/commands/app-commands.ts +16 -6
- package/src/commands/budget.ts +13 -11
- package/src/commands/command-args.ts +103 -71
- package/src/commands/context.ts +55 -28
- package/src/commands/defaults.ts +69 -45
- package/src/commands/keymap.ts +56 -43
- package/src/commands/levels.ts +14 -8
- package/src/commands/live-context.ts +9 -7
- package/src/commands/reference.ts +2 -1
- package/src/commands/registry.ts +22 -11
- package/src/commands/run-reported.ts +15 -10
- package/src/component-props.ts +46 -30
- package/src/content/collection-match.ts +11 -9
- package/src/content/collection-pages.ts +412 -0
- package/src/content/content-collections.ts +270 -0
- package/src/content/draft-state.ts +4 -3
- package/src/content/entry-commands.ts +54 -62
- package/src/content/entry-editor.ts +137 -32
- package/src/content/entry-fields.ts +25 -8
- package/src/content/entry-inspector.ts +225 -0
- package/src/content/entry-model.ts +38 -15
- 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/canvas-context-menu.ts +1 -2
- package/src/editor/canvas-slash-bridge.ts +3 -6
- package/src/editor/content-slice.ts +16 -14
- package/src/editor/context-menu.ts +35 -22
- package/src/editor/convert-targets.ts +30 -35
- package/src/editor/convert-to-component.ts +78 -48
- package/src/editor/convert-to-repeater.ts +34 -22
- package/src/editor/editable-tags.ts +17 -2
- package/src/editor/file-drop-action.ts +29 -22
- package/src/editor/inline-edit-apply.ts +79 -17
- package/src/editor/inline-edit.ts +76 -50
- package/src/editor/inline-format.ts +59 -56
- package/src/editor/inline-link.ts +40 -15
- package/src/editor/insert-component.ts +91 -0
- package/src/editor/insert-zone-action.ts +14 -5
- package/src/editor/merge-tags.ts +58 -19
- package/src/editor/repeater-scope.ts +39 -28
- package/src/editor/shortcuts.ts +76 -42
- package/src/editor/slash-menu.ts +52 -14
- package/src/files/asset-versions.ts +4 -4
- package/src/files/components.ts +89 -20
- package/src/files/elements.ts +5 -6
- package/src/files/file-ops.ts +92 -41
- package/src/files/files.ts +248 -239
- package/src/files/fs-events.ts +18 -7
- package/src/files/media-meta.ts +97 -2
- package/src/files/media-paths.ts +3 -0
- 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 +15 -5
- package/src/format/constraints.ts +1 -1
- package/src/format/convert-file.ts +27 -13
- package/src/format/format-choices.ts +2 -1
- package/src/format/format-host.ts +91 -50
- package/src/github/github-auth-status.ts +27 -3
- package/src/github/github-auth.ts +21 -11
- package/src/github/github-publish.ts +28 -23
- package/src/grid/cell-editors.ts +46 -31
- package/src/grid/cell-popovers.ts +5 -3
- package/src/grid/edit-buffer.ts +10 -9
- package/src/grid/grid-controller.ts +25 -23
- package/src/grid/grid-layout.ts +21 -5
- package/src/grid/grid-open.ts +3 -33
- package/src/grid/grid-panel.ts +65 -6
- package/src/grid/grid-reveal.ts +34 -0
- package/src/grid/grid-source.ts +9 -31
- package/src/grid/grid-view.ts +45 -23
- package/src/grid/redirects-grid.ts +14 -5
- package/src/grid/redirects.ts +16 -14
- package/src/grid/schema-columns.ts +25 -19
- package/src/grid/sources/connector-source.ts +47 -20
- package/src/grid/sources/content-source.ts +100 -31
- package/src/grid/sources/csv-file-source.ts +2 -2
- package/src/grid/tabulator-tables.d.ts +61 -34
- package/src/hosting/document.ts +2 -2
- package/src/hosting/stage.ts +7 -7
- package/src/i18n/i18n-commands.ts +3 -3
- 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 +51 -20
- package/src/new-project/add-repo-modal.ts +20 -19
- package/src/new-project/import-tab.ts +10 -14
- package/src/new-project/location-fields.ts +2 -1
- package/src/new-project/new-project-modal.ts +12 -9
- package/src/packages/jxsuite-update.ts +4 -3
- package/src/packages/pull-package-sync.ts +26 -25
- package/src/page-params.ts +97 -68
- package/src/panels/activity-panel.ts +38 -14
- package/src/panels/ai-chat/attached-context.ts +13 -7
- package/src/panels/ai-chat/chat-markdown.ts +8 -8
- package/src/panels/ai-chat/chat-view.ts +80 -73
- package/src/panels/ai-chat/composer.ts +30 -33
- package/src/panels/ai-chat/sessions-view.ts +1 -2
- package/src/panels/ai-panel.ts +23 -20
- package/src/panels/block-action-bar.ts +57 -46
- package/src/panels/bottom-dock.ts +5 -3
- package/src/panels/canvas-dnd-bridge.ts +36 -26
- 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 +63 -26
- package/src/panels/data-grid.ts +18 -11
- package/src/panels/dnd.ts +115 -138
- package/src/panels/editors.ts +52 -21
- package/src/panels/elements-panel.ts +19 -5
- package/src/panels/empty-state.ts +2 -2
- package/src/panels/events-panel.ts +84 -69
- package/src/panels/formula-workspace.ts +78 -54
- package/src/panels/frontmatter-fields.ts +33 -28
- package/src/panels/git-diff-open.ts +10 -6
- package/src/panels/head-panel.ts +488 -202
- package/src/panels/i18n-panel.ts +20 -12
- package/src/panels/imports-panel.ts +25 -47
- package/src/panels/jump-bar.ts +75 -31
- package/src/panels/layers-panel.ts +130 -101
- package/src/panels/left-panel.ts +25 -11
- package/src/panels/navigator-panels.ts +23 -11
- package/src/panels/pane-context.ts +140 -49
- package/src/panels/pane-grid.ts +55 -26
- package/src/panels/panel-registry.ts +36 -46
- package/src/panels/properties-panel.ts +182 -124
- package/src/panels/quick-search.ts +53 -31
- package/src/panels/right-panel.ts +201 -45
- package/src/panels/seo-modal.ts +54 -125
- package/src/panels/settings-menu.ts +63 -61
- package/src/panels/settings-pane.ts +268 -162
- package/src/panels/signals-panel.ts +156 -135
- package/src/panels/site-model.ts +367 -0
- package/src/panels/site-panel.ts +638 -0
- package/src/panels/statement-editor.ts +230 -140
- package/src/panels/style-panel.ts +253 -206
- package/src/panels/style-utils.ts +114 -51
- package/src/panels/stylebook-doc.ts +195 -60
- package/src/panels/stylebook-layers-panel.ts +48 -89
- package/src/panels/stylebook-panel.ts +60 -27
- package/src/panels/styles-panel.ts +327 -0
- package/src/panels/tab-drop.ts +27 -11
- package/src/panels/tab-strip.ts +143 -49
- package/src/platform-errors.ts +57 -43
- package/src/platform.ts +59 -31
- package/src/platforms/cloud.ts +373 -176
- package/src/platforms/default-platform.ts +14 -8
- package/src/platforms/devserver.ts +180 -142
- package/src/platforms/read-batcher.ts +16 -8
- package/src/project-list.ts +2 -1
- package/src/publish/deploy-checklist.ts +20 -9
- package/src/publish/pages-service.ts +66 -27
- package/src/publish/publish-changes.ts +491 -0
- package/src/publish/publish-commands.ts +88 -22
- package/src/publish/publish-ids.ts +49 -0
- package/src/publish/publish-panel.ts +10 -6
- 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/recent-projects.ts +15 -8
- package/src/resize-edges.ts +26 -36
- package/src/services/a11y-report.ts +26 -19
- package/src/services/agent-seed.ts +23 -11
- package/src/services/ai-ask.ts +9 -12
- package/src/services/ai-command-tools.ts +68 -62
- package/src/services/ai-import-tools.ts +80 -67
- package/src/services/ai-models.ts +17 -13
- package/src/services/ai-project-tools.ts +68 -32
- package/src/services/ai-session-store.ts +19 -10
- package/src/services/ai-system-prompt.ts +46 -20
- package/src/services/ai-tools.ts +71 -27
- package/src/services/ai-write-report.ts +20 -12
- package/src/services/ai-writes.ts +4 -4
- package/src/services/automation.ts +74 -51
- package/src/services/cem-export.ts +149 -58
- package/src/services/cf-settings.ts +4 -4
- package/src/services/clock.ts +6 -1
- package/src/services/code-services.ts +37 -31
- package/src/services/connection.ts +2 -2
- package/src/services/context-manager.ts +14 -10
- package/src/services/context-resolver.ts +20 -8
- package/src/services/data-service.ts +19 -15
- package/src/services/directory-picker.ts +20 -14
- package/src/services/document-assistant.ts +39 -19
- package/src/services/gated-registry.ts +10 -6
- package/src/services/harness/chat-reducer.ts +23 -1
- package/src/services/import-client.ts +91 -38
- package/src/services/import-seed.ts +8 -2
- package/src/services/jx-validate.ts +28 -31
- package/src/services/live-preview.ts +0 -0
- package/src/services/live-surfaces.ts +6 -3
- package/src/services/model-uri.ts +10 -2
- package/src/services/module-preloads.ts +12 -8
- package/src/services/monaco-buffer.ts +43 -24
- package/src/services/monaco-lazy.ts +7 -8
- package/src/services/monaco-setup.ts +23 -16
- package/src/services/notify.ts +44 -17
- package/src/services/popover-report.ts +25 -10
- package/src/services/preview-eval.ts +20 -8
- package/src/services/profile.ts +13 -6
- package/src/services/project-path.ts +13 -10
- package/src/services/references.ts +0 -0
- package/src/services/render-critic.ts +29 -9
- package/src/services/settings/definitions.ts +25 -14
- package/src/services/settings/kernel.ts +13 -4
- package/src/services/settings/write-queue.ts +9 -9
- package/src/services/token-lint.ts +12 -10
- package/src/services/tool-executor.ts +17 -5
- package/src/services/tool-outcomes.ts +44 -24
- package/src/services/trusted-types.ts +24 -7
- package/src/settings/contexts-section.ts +11 -8
- package/src/settings/contributed-section.ts +128 -70
- package/src/settings/css-vars-editor.ts +119 -32
- package/src/settings/defs-editor.ts +38 -35
- package/src/settings/developer-panels.ts +43 -0
- package/src/settings/extension-rows.ts +16 -8
- package/src/settings/extension-sections.ts +42 -14
- package/src/settings/extensions-section.ts +4 -1
- package/src/settings/general-settings.ts +101 -28
- package/src/settings/locales-section.ts +20 -12
- package/src/settings/preferences-dialog.ts +17 -7
- package/src/settings/preferences-keymap.ts +7 -5
- package/src/settings/preferences-sections.ts +11 -5
- package/src/settings/project-sections.ts +28 -11
- package/src/settings/schema-field-ui.ts +12 -1
- package/src/settings/section-registry.ts +116 -11
- package/src/settings/settings-dialog.ts +192 -0
- package/src/settings/settings-document.ts +186 -166
- package/src/shell/tree.ts +6 -5
- package/src/shell.ts +536 -477
- package/src/site-context.ts +101 -32
- package/src/state.ts +68 -57
- package/src/store.ts +54 -34
- package/src/studio.ts +219 -116
- package/src/style/live-preview.ts +1 -1
- package/src/style/project-styles.ts +40 -7
- 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/token-ref.ts +5 -4
- package/src/style/variables-focus.ts +61 -0
- package/src/style/variables-view.ts +235 -0
- package/src/surfaces/about.ts +18 -19
- package/src/surfaces/add-new.json +1482 -0
- package/src/surfaces/add-new.ts +325 -0
- package/src/surfaces/add-repo.ts +17 -19
- package/src/surfaces/ai-chat.ts +33 -38
- package/src/surfaces/ai-credentials-form.ts +6 -16
- package/src/surfaces/ai-managed-connect.ts +3 -4
- package/src/surfaces/ai-model-picker.ts +3 -5
- package/src/surfaces/block-action-bar.ts +22 -11
- package/src/surfaces/boot-failure.json +4 -3
- package/src/surfaces/boot-failure.ts +4 -5
- package/src/surfaces/bottom-dock.json +1 -1
- package/src/surfaces/bottom-dock.ts +9 -18
- package/src/surfaces/canvas-stage.json +30 -19
- package/src/surfaces/canvas-stage.ts +17 -16
- package/src/surfaces/cf-account-picker.ts +17 -18
- 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 +145 -105
- package/src/surfaces/convert-repeater.ts +17 -19
- package/src/surfaces/data-actions.ts +9 -7
- package/src/surfaces/dialog.ts +26 -28
- package/src/surfaces/diff-toolbar.ts +9 -7
- package/src/surfaces/empty-state.json +1 -1
- package/src/surfaces/empty-state.ts +7 -10
- package/src/surfaces/entry-editor.json +136 -0
- package/src/surfaces/entry-editor.ts +35 -11
- package/src/surfaces/entry-inspector.json +371 -0
- package/src/surfaces/entry-inspector.ts +143 -0
- package/src/surfaces/expression-editor.ts +11 -25
- package/src/surfaces/files-panel.ts +27 -14
- package/src/surfaces/formula-palette.ts +4 -5
- package/src/surfaces/github-auth.ts +16 -20
- package/src/surfaces/github-publish.ts +17 -22
- package/src/surfaces/grid-cell.ts +30 -31
- package/src/surfaces/grid-open.ts +10 -14
- package/src/surfaces/grid-panel.ts +13 -9
- package/src/surfaces/grid-replace.ts +13 -13
- package/src/surfaces/grid-views.ts +15 -18
- package/src/surfaces/inspector-dock.json +162 -14
- package/src/surfaces/inspector-dock.ts +59 -31
- package/src/surfaces/jump-bar.ts +5 -6
- package/src/surfaces/jxsuite-update.ts +16 -22
- package/src/surfaces/library-pane.json +670 -437
- package/src/surfaces/library-pane.ts +111 -77
- package/src/surfaces/logic-panel.ts +17 -30
- package/src/surfaces/logic-workspace.ts +13 -15
- package/src/surfaces/media-browser.json +62 -6
- package/src/surfaces/media-browser.ts +26 -11
- package/src/surfaces/media-field.json +1 -1
- package/src/surfaces/media-field.ts +4 -5
- package/src/surfaces/media-library.json +1586 -0
- package/src/surfaces/media-library.ts +282 -0
- package/src/surfaces/media-pane.ts +8 -7
- package/src/surfaces/media-pick-dialog.json +71 -0
- package/src/surfaces/media-pick-dialog.ts +132 -0
- package/src/surfaces/menu.ts +47 -23
- package/src/surfaces/navigator-dock.ts +11 -12
- package/src/surfaces/new-project.ts +27 -26
- package/src/surfaces/pane-context.json +144 -77
- package/src/surfaces/pane-context.ts +44 -25
- package/src/surfaces/pane-grid.ts +15 -10
- package/src/surfaces/panel-activity.ts +5 -6
- package/src/surfaces/panel-data.ts +3 -4
- package/src/surfaces/panel-deploy-checklist.json +12 -6
- package/src/surfaces/panel-deploy-checklist.ts +8 -7
- package/src/surfaces/panel-elements.ts +5 -7
- package/src/surfaces/panel-i18n.ts +5 -7
- package/src/surfaces/panel-imports.ts +6 -13
- package/src/surfaces/panel-outline.ts +25 -19
- package/src/surfaces/panel-page.json +72 -2
- package/src/surfaces/panel-page.ts +49 -25
- package/src/surfaces/panel-problems.ts +5 -7
- package/src/surfaces/panel-signals.json +1 -1
- package/src/surfaces/panel-signals.ts +25 -39
- package/src/surfaces/panel-stylebook-layers.json +71 -204
- package/src/surfaces/panel-stylebook-layers.ts +5 -29
- package/src/surfaces/preferences.json +120 -48
- package/src/surfaces/preferences.ts +29 -11
- package/src/surfaces/progress-modal.ts +15 -9
- package/src/surfaces/properties-panel.json +1 -1
- package/src/surfaces/properties-panel.ts +20 -42
- 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/publish.ts +18 -18
- package/src/surfaces/push-plan.ts +7 -8
- package/src/surfaces/rail.json +1 -159
- package/src/surfaces/rail.ts +22 -79
- package/src/surfaces/reference-field.ts +11 -15
- package/src/surfaces/schema-builder.ts +16 -22
- package/src/surfaces/schema-form.json +10 -2
- package/src/surfaces/schema-form.ts +17 -25
- package/src/surfaces/secret-field.ts +9 -6
- package/src/surfaces/seo.json +1 -1
- package/src/surfaces/seo.ts +21 -15
- package/src/surfaces/settings-contexts.ts +9 -7
- package/src/surfaces/settings-contributed.json +5 -5
- package/src/surfaces/settings-contributed.ts +32 -12
- package/src/surfaces/settings-css-vars.json +44 -36
- package/src/surfaces/settings-css-vars.ts +82 -16
- package/src/surfaces/settings-defs.json +2 -2
- package/src/surfaces/settings-defs.ts +17 -21
- package/src/surfaces/settings-deploy.json +2 -15
- package/src/surfaces/settings-deploy.ts +9 -16
- package/src/surfaces/settings-dialog.json +51 -0
- package/src/surfaces/settings-dialog.ts +169 -0
- package/src/surfaces/settings-extensions.ts +5 -6
- package/src/surfaces/settings-head.ts +33 -39
- package/src/surfaces/settings-locales.ts +8 -20
- package/src/surfaces/settings-overview.json +3 -3
- package/src/surfaces/settings-overview.ts +14 -8
- package/src/surfaces/settings-packages.ts +8 -7
- package/src/surfaces/settings-pane.json +269 -46
- package/src/surfaces/settings-pane.ts +88 -36
- package/src/surfaces/settings-rawjson.ts +5 -6
- package/src/surfaces/shell.json +2 -1
- package/src/surfaces/shell.ts +1 -2
- 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 +42 -9
- package/src/surfaces/statements.ts +13 -18
- package/src/surfaces/statusbar.ts +56 -29
- package/src/surfaces/style-panel.ts +18 -31
- package/src/surfaces/stylebook-chrome.ts +3 -5
- 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/tab-strip.ts +14 -13
- package/src/surfaces/target-line.ts +6 -7
- package/src/surfaces/welcome.ts +6 -8
- 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/patch-ops.ts +4 -3
- package/src/tabs/project-config.ts +32 -21
- package/src/tabs/selection.ts +36 -8
- package/src/tabs/tab.ts +99 -48
- package/src/tabs/transact.ts +98 -53
- package/src/types.ts +53 -43
- package/src/ui/ai-credentials-form.ts +10 -13
- package/src/ui/ai-model-picker.ts +3 -3
- package/src/ui/cf-account-picker.ts +7 -9
- package/src/ui/color-selector.ts +9 -5
- package/src/ui/dynamic-slot.ts +7 -8
- package/src/ui/expression-editor.ts +112 -105
- package/src/ui/form-controls.ts +104 -56
- package/src/ui/formula-catalog.ts +239 -230
- package/src/ui/formula-chips.ts +33 -18
- package/src/ui/layers.ts +57 -31
- package/src/ui/media-picker.ts +300 -47
- package/src/ui/popover-surface.ts +20 -12
- package/src/ui/progress-modal.ts +13 -8
- package/src/ui/regions.ts +14 -12
- package/src/ui/schema-form.ts +372 -97
- package/src/ui/surface.ts +71 -8
- package/src/ui/timing.ts +9 -0
- package/src/ui/value-source.ts +44 -31
- package/src/ui/virtual-window.ts +29 -3
- package/src/utils/base64.ts +6 -4
- package/src/utils/edit-display.ts +366 -111
- package/src/utils/element-selectors.ts +3 -2
- package/src/utils/google-fonts.ts +15 -14
- package/src/utils/inherited-style.ts +18 -20
- package/src/utils/link-target.ts +1 -1
- package/src/utils/local-day.ts +18 -0
- package/src/utils/preview-format.ts +25 -3
- package/src/utils/strip-events.ts +49 -22
- package/src/utils/studio-utils.ts +29 -14
- package/src/view.ts +2 -3
- package/src/workspace/pane-derive.ts +14 -16
- package/src/workspace/session.ts +81 -50
- 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 +165 -47
- package/styles/shell-frame.css +30 -7
- package/styles/shell-frame.json +15 -3
- package/dist/chunks/2020-va2wwra4.js +0 -4
- package/dist/chunks/adapter-f93pafd7.js +0 -4
- package/dist/chunks/cf-account-picker-af1h381v.js +0 -4
- package/dist/chunks/cf-settings-125tdm0w.js +0 -4
- package/dist/chunks/color-area-jqhna8zy.js +0 -4
- package/dist/chunks/color-field-embq5ctg.js +0 -4
- package/dist/chunks/color-fpezvnkt.js +0 -4
- package/dist/chunks/color-slider-1qmw7wqy.js +0 -4
- package/dist/chunks/combobox-773hdzyj.js +0 -4
- package/dist/chunks/components-ax2f1fnn.js +0 -4
- package/dist/chunks/content-source-108aqtk1.js +0 -4
- package/dist/chunks/convert-to-repeater-ry5rmppr.js +0 -4
- package/dist/chunks/dialog-mtm9fq5t.js +0 -4
- package/dist/chunks/editor-pfgdmkb0.js +0 -4
- package/dist/chunks/entry-commands-t0k1q0kx.js +0 -4
- package/dist/chunks/extension-sections-6mwh2hf8.js +0 -4
- package/dist/chunks/file-ops-meej5mqf.js +0 -4
- package/dist/chunks/files-44vp8a2s.js +0 -4
- package/dist/chunks/format-host-7q1petb9.js +0 -4
- package/dist/chunks/fs-events-h2mwnxaz.js +0 -4
- package/dist/chunks/git-panel-zngbymvd.js +0 -4
- package/dist/chunks/grid-view-sx9vynsp.js +0 -51
- package/dist/chunks/icons-p44xhjf0.js +0 -4
- package/dist/chunks/iframe-entry-f7mqjwpm.js +0 -5
- package/dist/chunks/iframe-entry-haw7jkvz.js +0 -5
- package/dist/chunks/iframe-entry-z6qrytv3.js +0 -5
- package/dist/chunks/iframe-host-qk3ycq87.js +0 -4
- package/dist/chunks/index-wkyfjeqz.js +0 -4
- package/dist/chunks/jsonMode-s8kt9dsj.js +0 -13
- package/dist/chunks/jx-validate-psgd7vsx.js +0 -4
- package/dist/chunks/layers-panel-1kq2jyfk.js +0 -4
- package/dist/chunks/layers-xd92fg8d.js +0 -4
- package/dist/chunks/listbox-s8fkmnq8.js +0 -4
- package/dist/chunks/lit-html-ac4cwwr4.js +0 -4
- package/dist/chunks/media-picker-0svzkdyb.js +0 -4
- package/dist/chunks/menu-37d07z9m.js +0 -4
- package/dist/chunks/menu-5c55ea3d.js +0 -4
- package/dist/chunks/monaco-binding-z6r70pdt.js +0 -4
- package/dist/chunks/monaco-buffer-fz6gq5y7.js +0 -4
- package/dist/chunks/monaco-setup-q4axkgj7.js +0 -4
- package/dist/chunks/notify-0xgtn8q1.js +0 -4
- package/dist/chunks/number-field-gw7sq8rn.js +0 -4
- package/dist/chunks/parse-897fvqah.js +0 -4
- package/dist/chunks/platform-v1qctbe6.js +0 -4
- package/dist/chunks/popover-8htra4er.js +0 -4
- package/dist/chunks/publish-panel-ym1fmgq5.js +0 -4
- package/dist/chunks/quick-search-a54e6t5n.js +0 -4
- package/dist/chunks/references-gmqp82fs.js +0 -4
- package/dist/chunks/right-panel-v7t9awbk.js +0 -4
- package/dist/chunks/section-registry-vhyf3zsr.js +0 -4
- package/dist/chunks/select-n3v7gwas.js +0 -4
- package/dist/chunks/split-pff8f3ze.js +0 -4
- package/dist/chunks/studio-0bhx5hz6.js +0 -5
- package/dist/chunks/studio-0k1ddnyy.js +0 -6
- package/dist/chunks/studio-1b04pd0j.js +0 -64
- package/dist/chunks/studio-4dwbj6gb.js +0 -5
- package/dist/chunks/studio-4tanh828.js +0 -5
- package/dist/chunks/studio-55h4mstj.js +0 -4
- package/dist/chunks/studio-5tnvjkz4.js +0 -5
- package/dist/chunks/studio-60dqgb0c.js +0 -5
- package/dist/chunks/studio-61dp09qg.js +0 -9
- package/dist/chunks/studio-63epcrj2.js +0 -5
- package/dist/chunks/studio-74k29dy9.js +0 -5
- package/dist/chunks/studio-7vg6jcd3.js +0 -5
- package/dist/chunks/studio-7zx31knw.js +0 -9
- package/dist/chunks/studio-8bxk97km.js +0 -5
- package/dist/chunks/studio-933e30n4.js +0 -5
- package/dist/chunks/studio-98wnwhbg.js +0 -5
- package/dist/chunks/studio-9mccjwjh.js +0 -14
- package/dist/chunks/studio-a2ke1e4t.js +0 -5
- package/dist/chunks/studio-e3a2a6v3.js +0 -4
- package/dist/chunks/studio-e81q1vb9.js +0 -5
- package/dist/chunks/studio-epgrmqqm.js +0 -5
- package/dist/chunks/studio-ery42sqr.js +0 -4
- package/dist/chunks/studio-g1shz58g.js +0 -5
- package/dist/chunks/studio-gf0fz03c.js +0 -5
- package/dist/chunks/studio-gjtpe62q.js +0 -6
- package/dist/chunks/studio-gkskhg7m.js +0 -5
- package/dist/chunks/studio-gx4dnjzd.js +0 -5
- package/dist/chunks/studio-j03zga3y.js +0 -9
- package/dist/chunks/studio-jhpxeckz.js +0 -5
- package/dist/chunks/studio-k01r7ykp.js +0 -5
- package/dist/chunks/studio-kk7h30ne.js +0 -7
- package/dist/chunks/studio-kt1zqney.js +0 -5
- package/dist/chunks/studio-m3cwhvye.js +0 -5
- package/dist/chunks/studio-mcayt6hz.js +0 -5
- package/dist/chunks/studio-myjcghv3.js +0 -5
- package/dist/chunks/studio-n8bxwc3y.js +0 -4
- package/dist/chunks/studio-ngm8gvpb.js +0 -5
- package/dist/chunks/studio-nj5a01jy.js +0 -928
- package/dist/chunks/studio-pcgz8heb.js +0 -5
- package/dist/chunks/studio-qcsq0t15.js +0 -5
- package/dist/chunks/studio-qkstvve9.js +0 -5
- package/dist/chunks/studio-qv1pwd3c.js +0 -5
- package/dist/chunks/studio-rc6dvxjb.js +0 -7
- package/dist/chunks/studio-s8dmmz66.js +0 -5
- package/dist/chunks/studio-sp5xzbj4.js +0 -6
- package/dist/chunks/studio-szsjbj0g.js +0 -5
- package/dist/chunks/studio-t1xzawhr.js +0 -16
- package/dist/chunks/studio-tdcprbqb.js +0 -5
- package/dist/chunks/studio-vrmcjf9g.js +0 -7
- package/dist/chunks/studio-vyc0b4he.js +0 -10
- package/dist/chunks/studio-w0cgf6jg.js +0 -5
- package/dist/chunks/studio-w3hskzqk.js +0 -5
- package/dist/chunks/studio-xgrgcdyh.js +0 -9
- package/dist/chunks/studio-xz2yxfcb.js +0 -5
- package/dist/chunks/studio-y6n42tgs.js +0 -5
- package/dist/chunks/studio-yb560vxr.js +0 -5
- package/dist/chunks/studio-yn9f8vtx.js +0 -5
- package/dist/chunks/studio-yw05w8f0.js +0 -7
- package/dist/chunks/studio-z16sgavc.js +0 -5
- package/dist/chunks/studio-zey7zsdw.js +0 -12
- package/dist/chunks/studio-zyqn40w4.js +0 -5
- package/dist/chunks/swatch-group-8qh9a3bm.js +0 -4
- package/dist/chunks/tabs-jwthg40w.js +0 -4
- package/dist/chunks/textfield-spy3hc77.js +0 -4
- package/dist/chunks/toast-4d35zd64.js +0 -4
- package/dist/chunks/toast-host-8sjmfed3.js +0 -4
- package/dist/chunks/tooltip-fd6g9xy3.js +0 -4
- package/dist/chunks/tree-h19v1jfz.js +0 -4
- package/dist/chunks/tsMode-2frah6h1.js +0 -14
- package/dist/chunks/workspace-zt81g1ms.js +0 -4
- package/dist/chunks/ws-client-n2bh4hkf.js +0 -4
- package/src/panels/frontmatter-panel.ts +0 -701
- package/src/panels/git-panel.ts +0 -1120
- package/src/surfaces/doc-header.json +0 -776
- package/src/surfaces/doc-header.ts +0 -231
- package/src/surfaces/git-panel.json +0 -1880
- package/src/surfaces/git-panel.ts +0 -272
package/src/panels/tab-strip.ts
CHANGED
|
@@ -54,6 +54,9 @@ import {
|
|
|
54
54
|
workspace,
|
|
55
55
|
} from "../workspace/workspace";
|
|
56
56
|
import { gridTabLabel } from "../grid/grid-source";
|
|
57
|
+
import { workspaceTabOrder } from "../workspace/tab-workspace";
|
|
58
|
+
import { workspaceHomeLabel } from "../workspace/workspace-ids";
|
|
59
|
+
import { shell, workspaceDrawsTabStrip } from "../shell";
|
|
57
60
|
import { entryDraftPill } from "../content/entry-editor";
|
|
58
61
|
import { DRAFT_FIELD, isDraftEntry } from "../content/draft-state";
|
|
59
62
|
import { entryFields } from "../content/entry-fields";
|
|
@@ -62,6 +65,8 @@ import { activeRegistry } from "../commands/active-registry";
|
|
|
62
65
|
import { runActiveReported, runReported } from "../commands/run-reported";
|
|
63
66
|
import { PRESET_LABELS } from "../workspace/pane-derive";
|
|
64
67
|
import { localeLabel } from "@jxsuite/schema/locale";
|
|
68
|
+
import { isBoolean } from "@jxsuite/schema/guards";
|
|
69
|
+
import type { CommandArgValues } from "../commands/command-args";
|
|
65
70
|
import { tabOfPane } from "../canvas/canvas-surface";
|
|
66
71
|
import { mediaDisplayName } from "./shared";
|
|
67
72
|
import { mountTabStripSurface } from "../surfaces/tab-strip";
|
|
@@ -183,8 +188,8 @@ export function mount(host: HTMLElement) {
|
|
|
183
188
|
}
|
|
184
189
|
_drag =
|
|
185
190
|
source.data.type === "tab"
|
|
186
|
-
? { kind: "tab", tabId: source.data.tabId
|
|
187
|
-
: { kind: "file", path: source.data.path
|
|
191
|
+
? { kind: "tab", tabId: source.data.tabId }
|
|
192
|
+
: { kind: "file", path: source.data.path };
|
|
188
193
|
// The tail target does not exist until a pane with no tabs is asked to grow one (§14.4's
|
|
189
194
|
// "Between panes" row; `project` draws it).
|
|
190
195
|
render();
|
|
@@ -198,6 +203,9 @@ export function mount(host: HTMLElement) {
|
|
|
198
203
|
}
|
|
199
204
|
const [target] = location.current.dropTargets;
|
|
200
205
|
const data = target?.data;
|
|
206
|
+
/* SAFETY: a `tab-slot` record comes only from this module's own two `getData` closures (a
|
|
207
|
+
chip's in `adoptChip`, the tail's in `adoptStrip`), and both write a numeric `index` and a
|
|
208
|
+
string `paneId` beside that type. */
|
|
201
209
|
_over =
|
|
202
210
|
data?.type === "tab-slot"
|
|
203
211
|
? {
|
|
@@ -241,7 +249,11 @@ export function mount(host: HTMLElement) {
|
|
|
241
249
|
so a fact about a pane it does not draw — or about a tab in another pane's strip — has
|
|
242
250
|
no reader inside this effect. */
|
|
243
251
|
}
|
|
252
|
+
// The strip draws the workspace on screen's tabs alone, so a switch repaints every strip.
|
|
253
|
+
void shell.workspace;
|
|
244
254
|
for (const tab of workspace.tabs.values()) {
|
|
255
|
+
// A tab's workspace follows its editor (`project.json` is Styles' in its stylebook only).
|
|
256
|
+
void tab.session.ui.canvasMode;
|
|
245
257
|
void tab.doc.dirty;
|
|
246
258
|
void tab.documentPath;
|
|
247
259
|
void tab.pinned;
|
|
@@ -249,7 +261,7 @@ export function mount(host: HTMLElement) {
|
|
|
249
261
|
void tab.session.openedFrom;
|
|
250
262
|
// The draft pill is on the chip, so the chip has to repaint when the flag changes — reading
|
|
251
263
|
// The absent key tracks its ADDITION too, which is the transition that matters most.
|
|
252
|
-
void tab.doc.content
|
|
264
|
+
void tab.doc.content.frontmatter[DRAFT_FIELD];
|
|
253
265
|
}
|
|
254
266
|
// An edit is a commitment: a preview tab with unsaved changes is no longer disposable, and
|
|
255
267
|
// The dirty flags this effect already tracks are exactly the signal.
|
|
@@ -260,6 +272,7 @@ export function mount(host: HTMLElement) {
|
|
|
260
272
|
}
|
|
261
273
|
|
|
262
274
|
export function unmount() {
|
|
275
|
+
cancelMeasures();
|
|
263
276
|
dismissOverflowMenu();
|
|
264
277
|
dismissTabContextMenu();
|
|
265
278
|
_scope?.stop();
|
|
@@ -296,6 +309,14 @@ function releaseHostDnD(host: HTMLElement): void {
|
|
|
296
309
|
}
|
|
297
310
|
|
|
298
311
|
function render() {
|
|
312
|
+
/* A workspace that draws no strip (Media, Styles, Publish) has its strips out of the grid
|
|
313
|
+
(`TAB_STRIP_HIDDEN_CLASS`), so painting them would be work nobody sees, and measuring a strip
|
|
314
|
+
that is not laid out reads zeros that flip the overflow chevron on every switch. They are left
|
|
315
|
+
standing as they were and repainted on the way back: this effect tracks `shell.workspace`.
|
|
316
|
+
A DERIVED pane is the exception. It follows the author into every workspace, and its row is
|
|
317
|
+
its derivation chip there (no tab of its own is the workspace's), which the frame keeps drawn
|
|
318
|
+
because it names the pane and holds the ✕ that closes it. So it is painted everywhere. */
|
|
319
|
+
const strips = workspaceDrawsTabStrip();
|
|
299
320
|
/* One host draws ONE pane. While the shell has a single strip, both panes resolve to the same
|
|
300
321
|
div — and the one whose tabs are on screen is the focused one, so it wins the tie. Without
|
|
301
322
|
that rule the answer was render order, which is how the strip came to mark a tab active in a
|
|
@@ -309,7 +330,10 @@ function render() {
|
|
|
309
330
|
}
|
|
310
331
|
const drawn = new Set<string>();
|
|
311
332
|
for (const [host, pane] of claims) {
|
|
312
|
-
|
|
333
|
+
if (strips || pane.derived) {
|
|
334
|
+
paint(pane, host);
|
|
335
|
+
}
|
|
336
|
+
// Counted as drawn either way: a strip left standing is kept, not taken down below.
|
|
313
337
|
_hosts.set(pane.id, host);
|
|
314
338
|
drawn.add(pane.id);
|
|
315
339
|
}
|
|
@@ -354,27 +378,81 @@ function paint(pane: Pane, host: HTMLElement): void {
|
|
|
354
378
|
|
|
355
379
|
/* The strip is HELD — `surfaces/tab-strip.ts` takes it as the element is created — so this is an
|
|
356
380
|
imperative USE of a node this module owns rather than a re-find of one it renders
|
|
357
|
-
(studio-ui-guidelines.md §9.4).
|
|
358
|
-
the accessibility tree's own answer to "which tab is current".
|
|
381
|
+
(studio-ui-guidelines.md §9.4).
|
|
359
382
|
|
|
360
383
|
THE REVEAL IS RECORDED ONLY WHEN THERE WAS A STRIP TO REVEAL IT IN. A mount is asynchronous,
|
|
361
384
|
so the first paint into a fresh host has no document yet — and moving `_lastActive` there
|
|
362
385
|
anyway would consume the transition and leave the chip off-screen with nothing left to notice.
|
|
363
386
|
That is exactly the case a derived pane produces: its strip is created the moment its one tab
|
|
364
|
-
comes back.
|
|
387
|
+
comes back.
|
|
388
|
+
|
|
389
|
+
The DECISION is taken here, in the paint that saw the transition, and only the scroll waits
|
|
390
|
+
for the frame: several paints can land in one task (a derivation and its return), and the
|
|
391
|
+
frame sees only the last of them, which may name the very tab `_lastActive` already held. */
|
|
365
392
|
const strip = _strips.get(host)?.strip();
|
|
366
393
|
if (strip && pane.activeTabId !== _lastActive.get(pane.id)) {
|
|
367
394
|
_lastActive.set(pane.id, pane.activeTabId);
|
|
395
|
+
_revealPending.add(host);
|
|
396
|
+
}
|
|
397
|
+
scheduleMeasure(host);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* The frame each host's strip is next read in: one per host, however many paints ask for it.
|
|
402
|
+
*
|
|
403
|
+
* Both reads the strip owes after a paint (bringing the active chip into view, and whether the
|
|
404
|
+
* chevron is needed) need LAYOUT, and both used to run inline at the tail of {@link paint}. A paint
|
|
405
|
+
* is never the last write of its task: a workspace switch or a tab activation goes on to swap the
|
|
406
|
+
* stage, the docks and the Inspector, so an inline read paid for a style recalculation of the whole
|
|
407
|
+
* half-written document (10 to 27 ms each, on every tab or workspace change in the perf trace), and
|
|
408
|
+
* the frame then paid again once the rest of the task had dirtied it. Read in the next frame, the
|
|
409
|
+
* strip shares the one layout the frame does anyway. The chevron already tolerated a lag (see
|
|
410
|
+
* {@link syncOverflow}), and the reveal still lands before that frame paints.
|
|
411
|
+
*/
|
|
412
|
+
const _measureFrames = new Map<HTMLElement, number>();
|
|
413
|
+
|
|
414
|
+
/** Hosts whose active chip changed since their last frame, so the frame scrolls it into view. */
|
|
415
|
+
const _revealPending = new Set<HTMLElement>();
|
|
416
|
+
|
|
417
|
+
function scheduleMeasure(host: HTMLElement): void {
|
|
418
|
+
if (_measureFrames.has(host)) {
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
_measureFrames.set(
|
|
422
|
+
host,
|
|
423
|
+
requestAnimationFrame(() => {
|
|
424
|
+
_measureFrames.delete(host);
|
|
425
|
+
const pane = drawnPane(host);
|
|
426
|
+
if (pane && workspaceDrawsTabStrip()) {
|
|
427
|
+
measureStrip(pane, host);
|
|
428
|
+
}
|
|
429
|
+
_revealPending.delete(host);
|
|
430
|
+
}),
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/** Drop every pending read: the strips they would measure are going away. */
|
|
435
|
+
function cancelMeasures(): void {
|
|
436
|
+
for (const frame of _measureFrames.values()) {
|
|
437
|
+
cancelAnimationFrame(frame);
|
|
438
|
+
}
|
|
439
|
+
_measureFrames.clear();
|
|
440
|
+
_revealPending.clear();
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/** The reads {@link scheduleMeasure} runs for one host, in a frame of their own. */
|
|
444
|
+
function measureStrip(pane: Pane, host: HTMLElement): void {
|
|
445
|
+
const strip = _strips.get(host)?.strip();
|
|
446
|
+
if (strip && _revealPending.has(host)) {
|
|
368
447
|
/* Found by the id the DOCUMENT stamped, not by `aria-selected`. The kit is the single writer
|
|
369
448
|
of a tab's selected state and it writes it on a MutationObserver when the tab SET moved — a
|
|
370
|
-
microtask later — so a strip whose one tab has just come back
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
.find((chip) => chip.dataset.tab === pane.activeTabId)
|
|
449
|
+
microtask later — so a strip whose one tab has just come back may have no tab marked current
|
|
450
|
+
yet. The flow already knows which chip it wants; asking the tree instead is asking a
|
|
451
|
+
question we have the answer to. */
|
|
452
|
+
[...strip.children]
|
|
453
|
+
.find((chip) => chip instanceof HTMLElement && chip.dataset.tab === pane.activeTabId)
|
|
375
454
|
?.scrollIntoView({ block: "nearest", inline: "nearest" });
|
|
376
455
|
}
|
|
377
|
-
|
|
378
456
|
syncOverflow(pane, host);
|
|
379
457
|
}
|
|
380
458
|
|
|
@@ -513,23 +591,31 @@ function project(pane: Pane): TabStripValues {
|
|
|
513
591
|
that could put one there (`moveTabToPane`, through `revealOpenTab`) is reached solely by
|
|
514
592
|
`openFileInPane`, which the follow calls for COMPANIONS. So the second disjunct is already
|
|
515
593
|
total over a lens and the first chose nothing. */
|
|
516
|
-
|
|
594
|
+
/* The tabs of the workspace on screen, in strip order. A pane's other tabs are another
|
|
595
|
+
workspace's: they keep their slots in `pane.tabOrder` and are simply not drawn. */
|
|
596
|
+
const visible = workspaceTabOrder(pane);
|
|
597
|
+
/* A derived pane none of whose tabs is in the workspace on screen draws its derivation chip too.
|
|
598
|
+
A COMPANION owns real tabs, and after a switch to Media or Publish the one it follows is
|
|
599
|
+
another workspace's: filtered away, it left a stage drawing a document under a blank row, with
|
|
600
|
+
no chip, no ✕ and no way out of the derivation. */
|
|
601
|
+
if (derived && visible.length === 0) {
|
|
517
602
|
/* A COMPANION whose rule has not resolved reaches this too, and it has to. Its `tabOrder` is
|
|
518
603
|
empty for a different reason than a lens's — the document it wants is not open YET, or the
|
|
519
604
|
selection has nothing under it — and the branch below drew nothing: a pane with no chip,
|
|
520
605
|
no ✕ and no way out, which `paneIsEmpty` will not collapse because the derivation counts as
|
|
521
606
|
a subject. The chip is the pane's name and its exit.
|
|
522
607
|
NO `_lastActive` / `_overflowing` RESET HERE, and both were, until each was shown to be a
|
|
523
|
-
write nothing can read. `_overflowing` is measured by {@link syncOverflow}
|
|
524
|
-
every ordinary render,
|
|
525
|
-
derivation is corrected before
|
|
608
|
+
write nothing can read. `_overflowing` is measured by {@link syncOverflow} in the frame
|
|
609
|
+
after every ordinary render, before that frame paints, so a stale `true` carried through a
|
|
610
|
+
derivation is corrected before anybody sees it. `_lastActive` cannot survive the round trip
|
|
526
611
|
either: a tab can only come back through `insertIntoPane` and then `activateTab`, which are
|
|
527
612
|
two reactive writes and therefore two renders, and the first of them lands here with
|
|
528
613
|
`tabOrder` full and `activeTabId` still `null` — which resets the field anyway. Both were
|
|
529
614
|
written as bookkeeping and both were unfalsifiable; the branch below owns the answer. */
|
|
530
615
|
return derivationValues(pane, derived);
|
|
531
616
|
}
|
|
532
|
-
|
|
617
|
+
// A non-derived pane whose every tab belongs elsewhere draws the same blank row an empty one does.
|
|
618
|
+
if (visible.length === 0) {
|
|
533
619
|
/* An empty, non-derived pane WHILE A DRAG IS LIVE draws a `tabs` row with no chips instead of
|
|
534
620
|
going blank: `blankValues` hides the row outright, and a hidden row has no `jx-tabs` element
|
|
535
621
|
for `adoptStrip` to make a target of — so a tab dragged toward the empty primary beside a
|
|
@@ -564,7 +650,8 @@ function project(pane: Pane): TabStripValues {
|
|
|
564
650
|
preset: "",
|
|
565
651
|
stripLabel: stripLabel(pane),
|
|
566
652
|
subject: "",
|
|
567
|
-
|
|
653
|
+
// The chip's index is its slot in the pane's FULL order, which is what a drop is measured in.
|
|
654
|
+
tabs: visible.flatMap((id) => chipView(pane, id, pane.tabOrder.indexOf(id), labels)),
|
|
568
655
|
trailing: _overflowing.get(pane.id) === true,
|
|
569
656
|
trailingGlyph: "⌄",
|
|
570
657
|
// ONE accessible name (`studio-ui-guidelines.md` §10): the glyph is hidden, so `title` is both
|
|
@@ -753,11 +840,11 @@ function syncDrag(): void {
|
|
|
753
840
|
/**
|
|
754
841
|
* Re-measure a pane's strip and re-project once if the chevron's presence changed.
|
|
755
842
|
*
|
|
756
|
-
* Measurement can only happen after the document has written the DOM, so this runs
|
|
757
|
-
* {@link paint} and guards its own re-entry on the boolean
|
|
758
|
-
* oscillate. Before the mount resolves there is no strip to
|
|
759
|
-
* next repaint measures it, and a strip that overflows on its
|
|
760
|
-
* reader could be looking for yet.
|
|
843
|
+
* Measurement can only happen after the document has written the DOM, so this runs in the frame
|
|
844
|
+
* after a {@link paint} ({@link scheduleMeasure}) and guards its own re-entry on the boolean
|
|
845
|
+
* actually flipping — the chevron cannot oscillate. Before the mount resolves there is no strip to
|
|
846
|
+
* measure and nothing to correct: the next repaint measures it, and a strip that overflows on its
|
|
847
|
+
* first frame has no hidden tab a reader could be looking for yet.
|
|
761
848
|
*/
|
|
762
849
|
function syncOverflow(pane: Pane, host: HTMLElement) {
|
|
763
850
|
const surface = _strips.get(host);
|
|
@@ -801,8 +888,8 @@ function onWheel(e: WheelEvent) {
|
|
|
801
888
|
if (e.ctrlKey) {
|
|
802
889
|
return;
|
|
803
890
|
}
|
|
804
|
-
const el = e.currentTarget
|
|
805
|
-
if (el.scrollWidth <= el.clientWidth) {
|
|
891
|
+
const el = e.currentTarget;
|
|
892
|
+
if (!(el instanceof HTMLElement) || el.scrollWidth <= el.clientWidth) {
|
|
806
893
|
return;
|
|
807
894
|
}
|
|
808
895
|
const delta = Math.abs(e.deltaX) > Math.abs(e.deltaY) ? e.deltaX : e.deltaY;
|
|
@@ -832,9 +919,13 @@ export function hiddenTabIds(paneId: string = workspace.activePaneId): string[]
|
|
|
832
919
|
const left = strip.scrollLeft;
|
|
833
920
|
const right = left + strip.clientWidth;
|
|
834
921
|
const hidden: string[] = [];
|
|
835
|
-
|
|
922
|
+
/* Typed, not filtered: a chip's position is what pairs it with the strip's drawn order, so dropping
|
|
923
|
+
a node here would shift every later chip onto the wrong tab id. The drawn order is the
|
|
924
|
+
workspace's tabs alone, which is what `project` drew. */
|
|
925
|
+
const drawn = workspaceTabOrder(pane);
|
|
926
|
+
const chips = [...strip.querySelectorAll<HTMLElement>('[part="tab"]')];
|
|
836
927
|
for (const [index, chip] of chips.entries()) {
|
|
837
|
-
const id =
|
|
928
|
+
const id = drawn[index];
|
|
838
929
|
if (id && (chip.offsetLeft < left || chip.offsetLeft + chip.offsetWidth > right)) {
|
|
839
930
|
hidden.push(id);
|
|
840
931
|
}
|
|
@@ -870,7 +961,7 @@ export function dismissOverflowMenu() {
|
|
|
870
961
|
function openOverflowMenu(pane: Pane, labels: Map<string, string>, anchorEl: HTMLElement | null) {
|
|
871
962
|
dismissOverflowMenu();
|
|
872
963
|
const hidden = hiddenTabIds(pane.id);
|
|
873
|
-
const ids = hidden.length > 0 ? hidden :
|
|
964
|
+
const ids = hidden.length > 0 ? hidden : workspaceTabOrder(pane);
|
|
874
965
|
const anchor = rectOf(anchorEl ?? document.body);
|
|
875
966
|
_overflowHandle = openMenu({
|
|
876
967
|
/* The trigger says "Show hidden tabs" and this is the panel it opens, so it takes the same
|
|
@@ -889,8 +980,8 @@ function openOverflowMenu(pane: Pane, labels: Map<string, string>, anchorEl: HTM
|
|
|
889
980
|
place: (box) => ({ x: Math.max(4, anchor.right - box.width), y: anchor.bottom }),
|
|
890
981
|
placement: "block-end span-inline-start",
|
|
891
982
|
region: "tab-overflow",
|
|
892
|
-
rows: ids.map((id) => ({
|
|
893
|
-
checked:
|
|
983
|
+
rows: ids.map((id): MenuRowProjection => ({
|
|
984
|
+
checked: id === pane.activeTabId ? "true" : "false",
|
|
894
985
|
destructive: false,
|
|
895
986
|
disabled: false,
|
|
896
987
|
dividerAbove: false,
|
|
@@ -931,8 +1022,8 @@ export function dismissTabContextMenu() {
|
|
|
931
1022
|
* where it lands (`content/draft-state.ts` says why), so the row offers the flip of what is true
|
|
932
1023
|
* now and {@link statedChecked} reads the current state back out of it for the checkmark.
|
|
933
1024
|
*/
|
|
934
|
-
function tabRowFacts(tab: Tab):
|
|
935
|
-
const facts:
|
|
1025
|
+
function tabRowFacts(tab: Tab): CommandArgValues {
|
|
1026
|
+
const facts: CommandArgValues = {};
|
|
936
1027
|
if (collectionOfPath(tab.documentPath)) {
|
|
937
1028
|
facts.draft = !isDraftEntry(entryFields(tab));
|
|
938
1029
|
}
|
|
@@ -961,14 +1052,14 @@ function tabRowFacts(tab: Tab): Record<string, unknown> {
|
|
|
961
1052
|
* already knows how to announce — and the five rows that carry no state stay plain `menuitem`s,
|
|
962
1053
|
* which `selects` on the old menu would have made impossible.
|
|
963
1054
|
*/
|
|
964
|
-
function statedChecked(args:
|
|
1055
|
+
function statedChecked(args: CommandArgValues): "true" | "false" | undefined {
|
|
965
1056
|
const entries = Object.entries(args);
|
|
966
|
-
const
|
|
967
|
-
if (!
|
|
1057
|
+
const value = entries.length === 1 ? entries[0]?.[1] : undefined;
|
|
1058
|
+
if (!isBoolean(value)) {
|
|
968
1059
|
return undefined;
|
|
969
1060
|
}
|
|
970
1061
|
// The fact is the state the row would REACH, so the state it is in now is the negation.
|
|
971
|
-
return
|
|
1062
|
+
return value ? "false" : "true";
|
|
972
1063
|
}
|
|
973
1064
|
|
|
974
1065
|
/**
|
|
@@ -989,13 +1080,11 @@ function placedTabItems(tab: Tab): MenuRowProjection[] {
|
|
|
989
1080
|
const items: MenuRowProjection[] = [];
|
|
990
1081
|
let group: string | undefined;
|
|
991
1082
|
for (const command of registry.forPlacement("context/tab")) {
|
|
992
|
-
const schema = command.args
|
|
993
|
-
| { properties?: Record<string, unknown>; required?: readonly string[] }
|
|
994
|
-
| undefined;
|
|
1083
|
+
const schema = command.args;
|
|
995
1084
|
if (!(schema?.required ?? []).every((key) => key in facts)) {
|
|
996
1085
|
continue;
|
|
997
1086
|
}
|
|
998
|
-
const args:
|
|
1087
|
+
const args: CommandArgValues = {};
|
|
999
1088
|
for (const key of Object.keys(schema?.properties ?? {})) {
|
|
1000
1089
|
if (key in facts) {
|
|
1001
1090
|
args[key] = facts[key];
|
|
@@ -1005,21 +1094,26 @@ function placedTabItems(tab: Tab): MenuRowProjection[] {
|
|
|
1005
1094
|
({ group } = command);
|
|
1006
1095
|
const reason = registry.disabledReason(command.id);
|
|
1007
1096
|
const checked = statedChecked(args);
|
|
1008
|
-
|
|
1097
|
+
const row: Omit<MenuRowProjection, "disabled"> = {
|
|
1009
1098
|
destructive: command.destructive === true,
|
|
1010
1099
|
dividerAbove,
|
|
1011
1100
|
id: command.id,
|
|
1012
1101
|
title: command.title,
|
|
1013
|
-
|
|
1014
|
-
|
|
1102
|
+
};
|
|
1103
|
+
if (checked !== undefined) {
|
|
1104
|
+
row.checked = checked;
|
|
1105
|
+
}
|
|
1106
|
+
items.push(
|
|
1107
|
+
reason === undefined
|
|
1015
1108
|
? {
|
|
1109
|
+
...row,
|
|
1016
1110
|
disabled: false,
|
|
1017
1111
|
run: () => {
|
|
1018
1112
|
void runReported(registry, command.id, args, "Tabs");
|
|
1019
1113
|
},
|
|
1020
1114
|
}
|
|
1021
|
-
: { disabled: true, requires: reason }
|
|
1022
|
-
|
|
1115
|
+
: { ...row, disabled: true, requires: reason },
|
|
1116
|
+
);
|
|
1023
1117
|
}
|
|
1024
1118
|
return items;
|
|
1025
1119
|
}
|
|
@@ -1193,7 +1287,7 @@ function tabLabels(pane: Pane): Map<string, string> {
|
|
|
1193
1287
|
? [
|
|
1194
1288
|
{
|
|
1195
1289
|
documentPath: tab.documentPath,
|
|
1196
|
-
fallback: gridTabLabel(tab.id) ?? "Untitled",
|
|
1290
|
+
fallback: gridTabLabel(tab.id) ?? workspaceHomeLabel(tab.id) ?? "Untitled",
|
|
1197
1291
|
id,
|
|
1198
1292
|
},
|
|
1199
1293
|
]
|
|
@@ -1209,7 +1303,7 @@ function tabLabels(pane: Pane): Map<string, string> {
|
|
|
1209
1303
|
* @returns {string}
|
|
1210
1304
|
*/
|
|
1211
1305
|
function tabTooltip(tab: Tab): string {
|
|
1212
|
-
const base = tab.documentPath || gridTabLabel(tab.id) || "Untitled";
|
|
1306
|
+
const base = tab.documentPath || gridTabLabel(tab.id) || workspaceHomeLabel(tab.id) || "Untitled";
|
|
1213
1307
|
const origin = tab.session.openedFrom;
|
|
1214
1308
|
const withOrigin = origin?.documentPath ? `${base}\nOpened from ${origin.documentPath}` : base;
|
|
1215
1309
|
return tab.preview ? `${withOrigin}\nPreview — double-click to keep open` : withOrigin;
|
|
@@ -1270,7 +1364,7 @@ export function shouldWarnOnClose(tab: Tab): boolean {
|
|
|
1270
1364
|
if (residue) {
|
|
1271
1365
|
return true;
|
|
1272
1366
|
}
|
|
1273
|
-
const peersHere = state.peers.filter((p) => p.state
|
|
1367
|
+
const peersHere = state.peers.filter((p) => p.state.focusedPath === tab.documentPath);
|
|
1274
1368
|
return peersHere.length === 0;
|
|
1275
1369
|
}
|
|
1276
1370
|
|
package/src/platform-errors.ts
CHANGED
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
|
|
15
15
|
import { problemSlug } from "@jxsuite/protocol";
|
|
16
16
|
import type { OfferedAction, RetryHint } from "@jxsuite/protocol";
|
|
17
|
+
import { isJsonObject, isString } from "@jxsuite/schema/guards";
|
|
18
|
+
import type { JsonValue } from "@jxsuite/schema/types";
|
|
17
19
|
|
|
18
20
|
export interface PlatformErrorInfo {
|
|
19
21
|
code?: string;
|
|
@@ -32,36 +34,44 @@ const RETRY_HINTS = new Set<string>(["reload", "repeat", "none"]);
|
|
|
32
34
|
* The offered actions a wire value holds, each one checked: an action needs an `id` and a `label`
|
|
33
35
|
* to be drawn at all, and anything else it carries is kept only when it has the right type. A
|
|
34
36
|
* malformed entry is dropped rather than drawn as a button that does nothing.
|
|
37
|
+
*
|
|
38
|
+
* A typed `OfferedAction[]` is accepted too, and checked the same way: it is what a response body
|
|
39
|
+
* cast to its protocol type holds, and nothing has verified that cast.
|
|
35
40
|
*/
|
|
36
|
-
export function offeredActions(
|
|
41
|
+
export function offeredActions(
|
|
42
|
+
value: JsonValue | readonly OfferedAction[] | undefined,
|
|
43
|
+
): OfferedAction[] {
|
|
37
44
|
if (!Array.isArray(value)) {
|
|
38
45
|
return [];
|
|
39
46
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
!raw.label
|
|
48
|
-
) {
|
|
47
|
+
const entries: readonly (JsonValue | OfferedAction)[] = value;
|
|
48
|
+
return entries.flatMap((entry): OfferedAction[] => {
|
|
49
|
+
if (!isJsonObject(entry)) {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
const { href, id, label, primary } = entry;
|
|
53
|
+
if (!isString(id) || !id || !isString(label) || !label) {
|
|
49
54
|
return [];
|
|
50
55
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
];
|
|
56
|
+
const action: OfferedAction = { id, label };
|
|
57
|
+
if (isString(href) && href) {
|
|
58
|
+
action.href = href;
|
|
59
|
+
}
|
|
60
|
+
if (primary === true) {
|
|
61
|
+
action.primary = true;
|
|
62
|
+
}
|
|
63
|
+
return [action];
|
|
59
64
|
});
|
|
60
65
|
}
|
|
61
66
|
|
|
67
|
+
/** Whether a value names one of the retry hints this client knows. */
|
|
68
|
+
function isRetryHint(value: JsonValue | undefined): value is RetryHint {
|
|
69
|
+
return isString(value) && RETRY_HINTS.has(value);
|
|
70
|
+
}
|
|
71
|
+
|
|
62
72
|
/** The retry hint a wire value names, or undefined when it names none we know. */
|
|
63
|
-
export function retryHint(value:
|
|
64
|
-
return
|
|
73
|
+
export function retryHint(value: JsonValue | undefined): RetryHint | undefined {
|
|
74
|
+
return isRetryHint(value) ? value : undefined;
|
|
65
75
|
}
|
|
66
76
|
|
|
67
77
|
/**
|
|
@@ -74,33 +84,37 @@ function normalizeCode(value: string): string {
|
|
|
74
84
|
}
|
|
75
85
|
|
|
76
86
|
/** Machine-readable fields carried by a thrown platform error (empty object when none). */
|
|
77
|
-
export function platformErrorInfo(
|
|
78
|
-
|
|
87
|
+
export function platformErrorInfo(cause: unknown): PlatformErrorInfo {
|
|
88
|
+
/* An Error carrying the members an adapter assigned onto it passes as a JSON object here: every
|
|
89
|
+
member below is read through a check that accepts any value, so nothing trusts that typing. */
|
|
90
|
+
if (!isJsonObject(cause)) {
|
|
79
91
|
return {};
|
|
80
92
|
}
|
|
81
|
-
const { actions, code, heading, installUrl, retry, type } =
|
|
82
|
-
|
|
83
|
-
code?: unknown;
|
|
84
|
-
heading?: unknown;
|
|
85
|
-
installUrl?: unknown;
|
|
86
|
-
retry?: unknown;
|
|
87
|
-
type?: unknown;
|
|
88
|
-
};
|
|
89
|
-
const hint = retryHint(retry);
|
|
93
|
+
const { actions, code, heading, installUrl, retry, type } = cause;
|
|
94
|
+
const info: PlatformErrorInfo = {};
|
|
90
95
|
// A problem type wins over a legacy code: it is the shape the backend is migrating toward.
|
|
91
|
-
const derived = problemSlug(type) ?? (
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
96
|
+
const derived = problemSlug(type) ?? (isString(code) ? normalizeCode(code) : null);
|
|
97
|
+
if (derived !== null) {
|
|
98
|
+
info.code = derived;
|
|
99
|
+
}
|
|
100
|
+
if (isString(installUrl)) {
|
|
101
|
+
info.installUrl = installUrl;
|
|
102
|
+
}
|
|
103
|
+
if (actions !== undefined) {
|
|
104
|
+
info.actions = offeredActions(actions);
|
|
105
|
+
}
|
|
106
|
+
if (isString(heading) && heading) {
|
|
107
|
+
info.heading = heading;
|
|
108
|
+
}
|
|
109
|
+
if (isRetryHint(retry)) {
|
|
110
|
+
info.retry = retry;
|
|
111
|
+
}
|
|
112
|
+
return info;
|
|
99
113
|
}
|
|
100
114
|
|
|
101
115
|
/** The GitHub-App install link when the error is the structured needs-installation 403. */
|
|
102
|
-
export function installUrlOf(
|
|
103
|
-
const info = platformErrorInfo(
|
|
116
|
+
export function installUrlOf(cause: unknown): string | null {
|
|
117
|
+
const info = platformErrorInfo(cause);
|
|
104
118
|
return info.code === "needs-installation-access" && info.installUrl ? info.installUrl : null;
|
|
105
119
|
}
|
|
106
120
|
|
|
@@ -108,6 +122,6 @@ export function installUrlOf(error: unknown): string | null {
|
|
|
108
122
|
* True when the error is an `action-required` refusal (HTTP 403, desktop.md §10.4) — whether the
|
|
109
123
|
* backend sent the problem type or the legacy `action_required` code.
|
|
110
124
|
*/
|
|
111
|
-
export function isActionRequired(
|
|
112
|
-
return platformErrorInfo(
|
|
125
|
+
export function isActionRequired(cause: unknown): boolean {
|
|
126
|
+
return platformErrorInfo(cause).code === "action-required";
|
|
113
127
|
}
|