@jxsuite/studio 4.0.0 → 5.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 +1 -1
- package/data/elements-meta.json +5 -15
- package/data/html-meta.json +51 -6
- package/dist/chunks/{2020-xp8vnwma.js → 2020-g79n01v9.js} +14 -14
- package/dist/chunks/action-group-sp6tna8v.js +118 -0
- package/dist/chunks/adapter-nj7tnjfn.js +13 -0
- package/dist/chunks/cf-account-picker-fyf63pmy.js +495 -0
- package/dist/chunks/cf-settings-71bv5zn9.js +20 -0
- package/dist/chunks/color-area-v17df7b8.js +154 -0
- package/dist/chunks/color-field-anwybnkn.js +208 -0
- package/dist/chunks/color-slider-44ez96fc.js +79 -0
- package/dist/chunks/color-xgg3kfw7.js +35 -0
- package/dist/chunks/combobox-5e7jev23.js +236 -0
- package/dist/chunks/components-2w1f35qs.js +18 -0
- package/dist/chunks/content-source-3wqeas45.js +46 -0
- package/dist/chunks/convert-to-repeater-d0cgnb6d.js +639 -0
- package/dist/chunks/dialog-s890b918.js +85 -0
- package/dist/chunks/editor-3qhbg51x.js +35 -0
- package/dist/chunks/entry-commands-d6g50j7s.js +42 -0
- package/dist/chunks/extension-sections-fy7q4fe9.js +651 -0
- package/dist/chunks/file-ops-3btj6st0.js +47 -0
- package/dist/chunks/files-ef8fgs3w.js +72 -0
- package/dist/chunks/format-host-3c33nwr8.js +40 -0
- package/dist/chunks/fs-events-13tj6sex.js +18 -0
- package/dist/chunks/git-panel-4wp2rn9b.js +49 -0
- package/dist/chunks/icons-yy10wk9r.js +402 -0
- package/dist/chunks/iframe-entry-15g3n6xv.js +114 -0
- package/dist/chunks/iframe-entry-b27vq81n.js +203 -0
- package/dist/chunks/iframe-entry-nbyxee1y.js +154 -0
- package/dist/chunks/iframe-host-jgesd924.js +115 -0
- package/dist/chunks/{index-nj44jpzj.js → index-mdmyx6s2.js} +11 -11
- package/dist/chunks/index-n4j7qxyr.js +109 -0
- package/dist/chunks/{javascript-q8kpmfah.js → javascript-xvrfrpkb.js} +8 -9
- package/dist/chunks/{jsonMode-dkr040ga.js → jsonMode-tyx2kj6p.js} +526 -527
- package/dist/chunks/jx-validate-j0wxk72w.js +15 -0
- package/dist/chunks/layers-1nq5evsh.js +29 -0
- package/dist/chunks/layers-panel-ar2gh90g.js +40 -0
- package/dist/chunks/listbox-6v2ac08j.js +44 -0
- package/dist/chunks/lit-html-m244w9nh.js +17 -0
- package/dist/chunks/media-picker-2qbetq73.js +33 -0
- package/dist/chunks/menu-q99sy9rf.js +285 -0
- package/dist/chunks/menu-rf7n72mf.js +14 -0
- package/dist/chunks/{monaco-binding-rj6xpx9y.js → monaco-binding-sw6en4dw.js} +12 -15
- package/dist/chunks/monaco-buffer-bhy3hb6m.js +24 -0
- package/dist/chunks/{monaco-setup-rws7k4br.js → monaco-setup-8r62fj6y.js} +27 -37
- package/dist/chunks/notify-628t0anh.js +21 -0
- package/dist/chunks/number-field-5cndyft8.js +72 -0
- package/dist/chunks/parse-0zx14y15.js +10 -0
- package/dist/chunks/platform-ts9cg1a4.js +15 -0
- package/dist/chunks/popover-47z3ytva.js +25 -0
- package/dist/chunks/publish-panel-98f7sr3g.js +27 -0
- package/dist/chunks/quick-search-srzz83k2.js +45 -0
- package/dist/chunks/references-n553f0e1.js +26 -0
- package/dist/chunks/right-panel-rrgx2dn3.js +45 -0
- package/dist/chunks/section-registry-5pq32t0q.js +25 -0
- package/dist/chunks/select-2r16ez41.js +49 -0
- package/dist/chunks/split-g7nm1rgb.js +191 -0
- package/dist/chunks/studio-0hqbpbd0.js +62 -0
- package/dist/chunks/studio-18avnhjp.js +2430 -0
- package/dist/chunks/{studio-kryvsw6j.js → studio-1k325pwf.js} +48 -48
- package/dist/chunks/{studio-hbtp0eh1.js → studio-25hkdrkw.js} +356 -85
- package/dist/chunks/studio-26d7myd1.js +258 -0
- package/dist/chunks/{studio-p8j86wag.js → studio-38emantv.js} +22 -5
- package/dist/chunks/studio-3gxv60tn.js +422 -0
- package/dist/chunks/{studio-8swrjbny.js → studio-3hxkd92t.js} +275 -163
- package/dist/chunks/studio-4m0haseg.js +185 -0
- package/dist/chunks/{studio-ynxwkrzd.js → studio-4wbb9ct0.js} +1953 -1785
- package/dist/chunks/{studio-gv8vvshc.js → studio-5523bpzt.js} +11 -11
- package/dist/chunks/{studio-5q69gfag.js → studio-57mf66w2.js} +1753 -2484
- package/dist/chunks/studio-5jy81t3s.js +17463 -0
- package/dist/chunks/studio-5rt7sqa0.js +1168 -0
- package/dist/chunks/studio-5te5tqng.js +81 -0
- package/dist/chunks/{studio-p4ngc046.js → studio-6ewqv390.js} +9 -9
- package/dist/chunks/{studio-9ab8gqsm.js → studio-6nzaktvy.js} +7 -7
- package/dist/chunks/studio-6xa21ej9.js +28 -0
- package/dist/chunks/{studio-5ehhackm.js → studio-727xh0e3.js} +19 -19
- package/dist/chunks/{studio-eenfkt4e.js → studio-79y5sz51.js} +52 -38
- package/dist/chunks/{studio-4q0wznzf.js → studio-7e11jpa9.js} +461 -145
- package/dist/chunks/{studio-q7v10cg2.js → studio-7r42c6ca.js} +17 -7
- package/dist/chunks/studio-7xptrg0j.js +954 -0
- package/dist/chunks/{studio-cft9r4r7.js → studio-81390n6f.js} +22 -22
- package/dist/chunks/{studio-q43a5y9h.js → studio-8jn5yhyn.js} +16 -16
- package/dist/chunks/studio-8qtrpzr3.js +839 -0
- package/dist/chunks/{studio-dg7zyt5x.js → studio-98b3z07n.js} +1 -1
- package/dist/chunks/studio-9xxz1q69.js +1356 -0
- package/dist/chunks/studio-akbww0j5.js +13615 -0
- package/dist/chunks/studio-arfpe389.js +195 -0
- package/dist/chunks/{studio-2zkz8evn.js → studio-az3zd49t.js} +473 -281
- package/dist/chunks/studio-cpvb2ed1.js +1171 -0
- package/dist/chunks/{studio-9r6j5ev1.js → studio-d0300636.js} +5078 -19
- package/dist/chunks/{studio-bgxt93ga.js → studio-d055c37e.js} +13 -13
- package/dist/chunks/studio-d1ja2x9r.js +362 -0
- package/dist/chunks/{studio-b9b6t1dg.js → studio-e1f24eff.js} +5664 -5666
- package/dist/chunks/{studio-4pqqxbrt.js → studio-em9nw8eh.js} +301 -112
- package/dist/chunks/studio-erdatzvp.js +1190 -0
- package/dist/chunks/{studio-g1wdche0.js → studio-esrxgwh6.js} +80 -80
- package/dist/chunks/studio-fabxk6r9.js +2811 -0
- package/dist/chunks/{studio-3n4ndrzh.js → studio-h4nvnjvz.js} +303 -303
- package/dist/chunks/studio-hhvs4sdg.js +195 -0
- package/dist/chunks/{studio-68n67094.js → studio-kcgff4r0.js} +15 -18
- package/dist/chunks/{studio-685s0ytq.js → studio-nqgawfks.js} +572 -572
- package/dist/chunks/{studio-xrapxwwc.js → studio-p1dw8wfw.js} +55 -29
- package/dist/chunks/studio-pm6hgy7r.js +4763 -0
- package/dist/chunks/studio-q0a3yk4n.js +33 -0
- package/dist/chunks/{studio-wcy8trfx.js → studio-q3x06vmj.js} +23 -22
- package/dist/chunks/studio-qahxvnan.js +111 -0
- package/dist/chunks/{studio-53n8bp04.js → studio-r6xmmtfh.js} +1 -1
- package/dist/chunks/{studio-kjjsjak4.js → studio-rkstz940.js} +3661 -6136
- package/dist/chunks/{studio-tvgyw9xw.js → studio-rnyf3f8e.js} +83 -250
- package/dist/chunks/studio-rpyah2ew.js +2805 -0
- package/dist/chunks/studio-rs76k67r.js +12 -0
- package/dist/chunks/{studio-yxrkyv8a.js → studio-s6z853aq.js} +12108 -11766
- package/dist/chunks/{studio-sf7zjgv1.js → studio-sgdc5pfc.js} +8 -8
- package/dist/chunks/studio-tb3ev01j.js +763 -0
- package/dist/chunks/{studio-t5wqwzdh.js → studio-tjjk7jvk.js} +1 -1
- package/dist/chunks/studio-vhv5tgxm.js +51 -0
- package/dist/chunks/{studio-htsf0w6m.js → studio-vz68yn9e.js} +31 -154
- package/dist/chunks/studio-wqpngpsk.js +174 -0
- package/dist/chunks/{studio-eesa1myv.js → studio-x3rty6tr.js} +58 -58
- package/dist/chunks/studio-xsykpvsh.js +8448 -0
- package/dist/chunks/{studio-92ab2jqe.js → studio-y9zedyjn.js} +14 -14
- package/dist/chunks/studio-yxa81f45.js +12 -0
- package/dist/chunks/swatch-group-t0n6h2rn.js +139 -0
- package/dist/chunks/tabs-wbp1cdws.js +156 -0
- package/dist/chunks/textfield-abk6qyee.js +73 -0
- package/dist/chunks/toast-780pvfbv.js +27 -0
- package/dist/chunks/toast-host-3sqv46sn.js +116 -0
- package/dist/chunks/toolbar-xbh5bhtr.js +194 -0
- package/dist/chunks/tooltip-eptb614w.js +369 -0
- package/dist/chunks/tree-a73p0pqm.js +367 -0
- package/dist/chunks/{tsMode-76kr53q0.js → tsMode-jy4m86rv.js} +83 -85
- package/dist/chunks/workspace-wrew8zk4.js +69 -0
- package/dist/chunks/{ws-client-6shc5rze.js → ws-client-ny4zc51r.js} +20 -22
- package/dist/iframe-entry.js +1812 -698
- package/dist/manifest.json +7 -0
- package/dist/studio.js +52900 -36573
- package/dist/workers/editor.worker.js +1040 -1085
- package/dist/workers/json.worker.js +1946 -1991
- package/dist/workers/ts.worker.js +4960 -5005
- package/favicon.ico +0 -0
- package/index.html +2 -0
- package/package.json +22 -55
- package/src/about/about-modal.ts +73 -123
- package/src/browse/library-commands.ts +20 -49
- package/src/browse/library-layouts.ts +87 -218
- package/src/browse/library-pane.ts +406 -438
- package/src/canvas/canvas-helpers.ts +0 -49
- package/src/canvas/canvas-live-render.ts +25 -2
- package/src/canvas/canvas-render.ts +666 -231
- package/src/canvas/canvas-surface.ts +0 -1
- package/src/canvas/canvas-utils.ts +310 -117
- package/src/canvas/dialog-path.ts +76 -0
- package/src/canvas/dialog-state.ts +67 -0
- package/src/canvas/diff-marks.ts +252 -0
- package/src/canvas/diff-toolbar.ts +349 -0
- package/src/canvas/diff-view.ts +123 -0
- package/src/canvas/edit-width-drag.ts +187 -0
- package/src/canvas/edit-width.ts +150 -0
- package/src/canvas/iframe-entry.ts +125 -8
- package/src/canvas/iframe-host.ts +271 -15
- package/src/canvas/iframe-interaction.ts +133 -13
- package/src/canvas/iframe-patch.ts +7 -1
- package/src/canvas/iframe-position.ts +5 -6
- package/src/canvas/iframe-protocol.ts +106 -5
- package/src/canvas/iframe-render.ts +373 -5
- package/src/canvas/iframe-slash.ts +2 -2
- package/src/canvas/iframe-subtree.ts +5 -8
- package/src/canvas/path-mapping.ts +25 -3
- package/src/canvas/popover-path.ts +106 -0
- package/src/canvas/popover-state.ts +155 -0
- package/src/canvas/surface-registry.ts +21 -10
- package/src/collab/presence-chips.ts +51 -73
- package/src/commands/app-commands.ts +10 -0
- package/src/commands/budget.ts +12 -0
- package/src/commands/command-args.ts +369 -6
- package/src/commands/defaults.ts +44 -14
- package/src/commands/live-context.ts +11 -5
- package/src/commands/reference.ts +12 -2
- package/src/commands/registry.ts +165 -8
- package/src/content/entry-commands.ts +16 -23
- package/src/content/entry-editor.ts +144 -101
- package/src/editor/canvas-slash-bridge.ts +2 -2
- package/src/editor/context-menu.ts +49 -200
- package/src/editor/convert-to-component.ts +42 -82
- package/src/editor/convert-to-repeater.ts +132 -173
- package/src/editor/inline-edit.ts +11 -0
- package/src/editor/shortcuts.ts +65 -26
- package/src/editor/slash-menu.ts +150 -157
- package/src/files/file-ops.ts +117 -11
- package/src/files/files.ts +949 -664
- package/src/files/json-layout.ts +474 -0
- package/src/files/media-paths.ts +13 -42
- package/src/files/media-usage.ts +41 -131
- package/src/files/serialize-document.ts +8 -1
- package/src/format/convert-file.ts +16 -10
- package/src/format/format-host.ts +50 -1
- package/src/github/github-auth.ts +71 -29
- package/src/github/github-publish.ts +57 -65
- package/src/grid/cell-editors.ts +46 -4
- package/src/grid/cell-popovers.ts +65 -62
- package/src/grid/grid-open.ts +86 -64
- package/src/grid/grid-panel.ts +390 -469
- package/src/grid/redirects-grid.ts +40 -44
- package/src/hosting/document.ts +2 -0
- package/src/hosting/layout.ts +10 -0
- package/src/i18n/i18n-commands.ts +127 -62
- package/src/media/media-pane.ts +83 -133
- package/src/new-project/add-repo-modal.ts +125 -176
- package/src/new-project/import-tab.ts +201 -250
- package/src/new-project/location-fields.ts +101 -165
- package/src/new-project/new-project-modal.ts +376 -367
- package/src/packages/jxsuite-update.ts +76 -18
- package/src/panels/activity-panel.ts +137 -104
- package/src/panels/ai-chat/chat-markdown.ts +15 -13
- package/src/panels/ai-chat/chat-view.ts +307 -472
- package/src/panels/ai-chat/composer.ts +175 -153
- package/src/panels/ai-chat/sessions-view.ts +31 -62
- package/src/panels/ai-panel.ts +210 -185
- package/src/panels/block-action-bar.ts +437 -643
- package/src/panels/bottom-dock.ts +112 -47
- package/src/panels/chat-panel.ts +19 -14
- package/src/panels/data-explorer.ts +141 -102
- package/src/panels/data-grid.ts +183 -150
- package/src/panels/dnd.ts +75 -20
- package/src/panels/editors.ts +26 -19
- package/src/panels/elements-panel.ts +243 -186
- package/src/panels/empty-state.ts +26 -42
- package/src/panels/events-panel.ts +950 -729
- package/src/panels/formula-workspace.ts +434 -207
- package/src/panels/frontmatter-fields.ts +185 -153
- package/src/panels/frontmatter-panel.ts +411 -187
- package/src/panels/git-diff-open.ts +148 -0
- package/src/panels/git-panel.ts +679 -605
- package/src/panels/head-panel.ts +617 -435
- package/src/panels/i18n-panel.ts +153 -133
- package/src/panels/imports-panel.ts +388 -414
- package/src/panels/jump-bar.ts +174 -147
- package/src/panels/layers-panel.ts +785 -671
- package/src/panels/left-panel.ts +166 -94
- package/src/panels/navigator-panels.ts +1 -1
- package/src/panels/pane-context.ts +529 -677
- package/src/panels/pane-grid.ts +265 -241
- package/src/panels/panel-registry.ts +15 -4
- package/src/panels/problems-panel.ts +177 -99
- package/src/panels/properties-panel.ts +1525 -966
- package/src/panels/provenance.ts +31 -113
- package/src/panels/quick-search.ts +217 -172
- package/src/panels/right-panel.ts +135 -169
- package/src/panels/seo-modal.ts +346 -167
- package/src/panels/settings-menu.ts +109 -646
- package/src/panels/settings-pane.ts +102 -86
- package/src/panels/signals-panel.ts +1318 -1172
- package/src/panels/statement-editor.ts +556 -428
- package/src/panels/style-panel.ts +1367 -630
- package/src/panels/style-utils.ts +36 -32
- package/src/panels/stylebook-doc.ts +30 -73
- package/src/panels/stylebook-layers-panel.ts +202 -109
- package/src/panels/stylebook-panel.ts +124 -88
- package/src/panels/tab-strip.ts +385 -287
- package/src/platforms/cloud.ts +347 -86
- package/src/platforms/devserver.ts +13 -0
- package/src/publish/deploy-checklist.ts +124 -78
- package/src/publish/publish-commands.ts +4 -12
- package/src/publish/publish-panel.ts +165 -299
- package/src/services/a11y-report.ts +100 -43
- package/src/services/ai-command-tools.ts +468 -0
- package/src/services/ai-import-tools.ts +50 -12
- package/src/services/ai-models.ts +108 -1
- package/src/services/ai-session-store.ts +6 -0
- package/src/services/ai-system-prompt.ts +110 -18
- package/src/services/ai-tools.ts +28 -143
- package/src/services/ai-write-report.ts +174 -0
- package/src/services/context-manager.ts +12 -1
- package/src/services/document-assistant.ts +50 -2
- package/src/services/idle.ts +16 -14
- package/src/services/live-surfaces.ts +237 -0
- package/src/services/model-uri.ts +75 -0
- package/src/services/notify.ts +63 -6
- package/src/services/popover-report.ts +325 -0
- package/src/services/surface-registry.ts +56 -0
- package/src/services/tool-executor.ts +17 -0
- package/src/settings/contexts-section.ts +301 -299
- package/src/settings/contributed-section.ts +361 -222
- package/src/settings/css-vars-editor.ts +320 -325
- package/src/settings/defs-editor.ts +572 -535
- package/src/settings/dependencies-editor.ts +79 -107
- package/src/settings/extension-commands.ts +379 -0
- package/src/settings/extension-rows.ts +113 -0
- package/src/settings/extensions-section.ts +287 -0
- package/src/settings/general-settings.ts +130 -181
- package/src/settings/head-editor.ts +10 -305
- package/src/settings/locales-section.ts +146 -196
- package/src/settings/preferences-accounts.ts +193 -12
- package/src/settings/preferences-dialog.ts +384 -307
- package/src/settings/project-sections.ts +108 -181
- package/src/settings/schema-field-ui.ts +11 -399
- package/src/settings/section-registry.ts +8 -1
- package/src/settings/settings-document.ts +31 -29
- package/src/shell/tree.ts +42 -87
- package/src/shell.ts +48 -36
- package/src/studio.ts +90 -67
- package/src/style/token-ref.ts +0 -39
- package/src/surfaces/about.json +263 -0
- package/src/surfaces/about.ts +163 -0
- package/src/surfaces/add-repo.json +486 -0
- package/src/surfaces/add-repo.ts +236 -0
- package/src/surfaces/ai-chat.json +2185 -0
- package/src/surfaces/ai-chat.ts +549 -0
- package/src/surfaces/ai-credentials-form.json +332 -0
- package/src/surfaces/ai-credentials-form.ts +151 -0
- package/src/surfaces/ai-managed-connect.json +108 -0
- package/src/surfaces/ai-managed-connect.ts +123 -0
- package/src/surfaces/ai-model-picker.json +114 -0
- package/src/surfaces/ai-model-picker.ts +139 -0
- package/src/surfaces/block-action-bar.json +640 -0
- package/src/surfaces/block-action-bar.ts +368 -0
- package/src/surfaces/bottom-dock.json +154 -0
- package/src/surfaces/bottom-dock.ts +125 -0
- package/src/surfaces/canvas-stage.json +444 -0
- package/src/surfaces/canvas-stage.ts +253 -0
- package/src/surfaces/cf-account-picker.json +300 -0
- package/src/surfaces/cf-account-picker.ts +214 -0
- package/src/surfaces/commandbar.json +984 -0
- package/src/{panels/toolbar.ts → surfaces/commandbar.ts} +414 -389
- package/src/surfaces/convert-repeater.json +309 -0
- package/src/surfaces/convert-repeater.ts +276 -0
- package/src/surfaces/data-actions.json +157 -0
- package/src/surfaces/data-actions.ts +115 -0
- package/src/surfaces/dialog.json +289 -0
- package/src/surfaces/dialog.ts +343 -0
- package/src/surfaces/diff-toolbar.json +266 -0
- package/src/surfaces/diff-toolbar.ts +139 -0
- package/src/surfaces/doc-header.json +739 -0
- package/src/surfaces/doc-header.ts +223 -0
- package/src/surfaces/empty-state.json +152 -0
- package/src/surfaces/empty-state.ts +173 -0
- package/src/surfaces/entry-editor.json +281 -0
- package/src/surfaces/entry-editor.ts +191 -0
- package/src/surfaces/expression-editor.json +977 -0
- package/src/surfaces/expression-editor.ts +266 -0
- package/src/surfaces/files-panel.json +592 -0
- package/src/surfaces/files-panel.ts +301 -0
- package/src/surfaces/formula-palette.json +364 -0
- package/src/surfaces/formula-palette.ts +340 -0
- package/src/surfaces/git-panel.json +1822 -0
- package/src/surfaces/git-panel.ts +272 -0
- package/src/surfaces/github-auth.json +112 -0
- package/src/surfaces/github-auth.ts +139 -0
- package/src/surfaces/github-publish.json +206 -0
- package/src/surfaces/github-publish.ts +169 -0
- package/src/surfaces/grid-cell.json +218 -0
- package/src/surfaces/grid-cell.ts +120 -0
- package/src/surfaces/grid-open.json +147 -0
- package/src/surfaces/grid-open.ts +87 -0
- package/src/surfaces/grid-panel.json +706 -0
- package/src/surfaces/grid-panel.ts +206 -0
- package/src/surfaces/grid-replace.json +179 -0
- package/src/surfaces/grid-replace.ts +89 -0
- package/src/surfaces/grid-views.json +446 -0
- package/src/surfaces/grid-views.ts +172 -0
- package/src/surfaces/inspector-dock.json +187 -0
- package/src/surfaces/inspector-dock.ts +161 -0
- package/src/surfaces/jump-bar.json +243 -0
- package/src/surfaces/jump-bar.ts +129 -0
- package/src/surfaces/jxsuite-update.json +146 -0
- package/src/surfaces/jxsuite-update.ts +149 -0
- package/src/surfaces/library-pane.json +1509 -0
- package/src/surfaces/library-pane.ts +363 -0
- package/src/surfaces/logic-panel.json +1949 -0
- package/src/surfaces/logic-panel.ts +369 -0
- package/src/surfaces/logic-workspace.json +685 -0
- package/src/surfaces/logic-workspace.ts +238 -0
- package/src/surfaces/media-browser.json +303 -0
- package/src/surfaces/media-browser.ts +145 -0
- package/src/surfaces/media-field.json +163 -0
- package/src/surfaces/media-field.ts +116 -0
- package/src/surfaces/media-pane.json +513 -0
- package/src/surfaces/media-pane.ts +197 -0
- package/src/surfaces/menu.json +232 -0
- package/src/surfaces/menu.ts +375 -0
- package/src/surfaces/navigator-dock.json +113 -0
- package/src/surfaces/navigator-dock.ts +130 -0
- package/src/surfaces/new-project.json +1654 -0
- package/src/surfaces/new-project.ts +411 -0
- package/src/surfaces/palette.json +535 -0
- package/src/surfaces/pane-context.json +1497 -0
- package/src/surfaces/pane-context.ts +513 -0
- package/src/surfaces/pane-grid.json +188 -0
- package/src/surfaces/pane-grid.ts +250 -0
- package/src/surfaces/panel-activity.json +563 -0
- package/src/surfaces/panel-activity.ts +187 -0
- package/src/surfaces/panel-data.json +141 -0
- package/src/surfaces/panel-data.ts +156 -0
- package/src/surfaces/panel-deploy-checklist.json +283 -0
- package/src/surfaces/panel-deploy-checklist.ts +175 -0
- package/src/surfaces/panel-elements.json +367 -0
- package/src/surfaces/panel-elements.ts +175 -0
- package/src/surfaces/panel-i18n.json +569 -0
- package/src/surfaces/panel-i18n.ts +212 -0
- package/src/surfaces/panel-imports.json +780 -0
- package/src/surfaces/panel-imports.ts +209 -0
- package/src/surfaces/panel-outline.json +734 -0
- package/src/surfaces/panel-outline.ts +326 -0
- package/src/surfaces/panel-page.json +1017 -0
- package/src/surfaces/panel-page.ts +240 -0
- package/src/surfaces/panel-problems.json +497 -0
- package/src/surfaces/panel-problems.ts +157 -0
- package/src/surfaces/panel-signals.json +1973 -0
- package/src/surfaces/panel-signals.ts +436 -0
- package/src/surfaces/panel-stylebook-layers.json +317 -0
- package/src/surfaces/panel-stylebook-layers.ts +155 -0
- package/src/surfaces/preferences.json +850 -0
- package/src/surfaces/preferences.ts +332 -0
- package/src/surfaces/progress-modal.json +110 -0
- package/src/surfaces/progress-modal.ts +150 -0
- package/src/surfaces/properties-panel.json +1578 -0
- package/src/surfaces/properties-panel.ts +337 -0
- package/src/surfaces/publish.json +945 -0
- package/src/surfaces/publish.ts +392 -0
- package/src/surfaces/push-plan.json +110 -0
- package/src/surfaces/push-plan.ts +87 -0
- package/src/surfaces/rail.json +255 -0
- package/src/surfaces/rail.ts +206 -0
- package/src/surfaces/reference-field.json +191 -0
- package/src/surfaces/reference-field.ts +168 -0
- package/src/surfaces/schema-builder.json +1011 -0
- package/src/surfaces/schema-builder.ts +181 -0
- package/src/surfaces/schema-form.json +1013 -0
- package/src/surfaces/schema-form.ts +287 -0
- package/src/surfaces/secret-field.json +60 -0
- package/src/surfaces/secret-field.ts +146 -0
- package/src/surfaces/seo.json +932 -0
- package/src/surfaces/seo.ts +334 -0
- package/src/surfaces/settings-contexts.json +538 -0
- package/src/surfaces/settings-contexts.ts +196 -0
- package/src/surfaces/settings-contributed.json +489 -0
- package/src/surfaces/settings-contributed.ts +199 -0
- package/src/surfaces/settings-css-vars.json +820 -0
- package/src/surfaces/settings-css-vars.ts +199 -0
- package/src/surfaces/settings-defs.json +1363 -0
- package/src/surfaces/settings-defs.ts +232 -0
- package/src/surfaces/settings-deploy.json +108 -0
- package/src/surfaces/settings-deploy.ts +135 -0
- package/src/surfaces/settings-extensions.json +486 -0
- package/src/surfaces/settings-extensions.ts +201 -0
- package/src/surfaces/settings-head.json +779 -0
- package/src/surfaces/settings-head.ts +397 -0
- package/src/surfaces/settings-locales.json +420 -0
- package/src/surfaces/settings-locales.ts +137 -0
- package/src/surfaces/settings-overview.json +423 -0
- package/src/surfaces/settings-overview.ts +218 -0
- package/src/surfaces/settings-packages.json +549 -0
- package/src/surfaces/settings-packages.ts +158 -0
- package/src/surfaces/settings-pane.json +147 -0
- package/src/surfaces/settings-pane.ts +150 -0
- package/src/surfaces/settings-rawjson.json +104 -0
- package/src/surfaces/settings-rawjson.ts +107 -0
- package/src/surfaces/shell.json +99 -0
- package/src/surfaces/shell.ts +30 -0
- package/src/surfaces/slash-menu.json +180 -0
- package/src/surfaces/slash-menu.ts +272 -0
- package/src/surfaces/statements.json +607 -0
- package/src/surfaces/statements.ts +238 -0
- package/src/surfaces/statusbar.json +94 -0
- package/src/{panels → surfaces}/statusbar.ts +163 -90
- package/src/surfaces/style-panel.json +1643 -0
- package/src/surfaces/style-panel.ts +338 -0
- package/src/surfaces/stylebook-chrome.json +122 -0
- package/src/surfaces/stylebook-chrome.ts +122 -0
- package/src/surfaces/tab-strip.json +448 -0
- package/src/surfaces/tab-strip.ts +200 -0
- package/src/surfaces/target-line.json +419 -0
- package/src/surfaces/target-line.ts +349 -0
- package/src/surfaces/toasts.json +189 -0
- package/src/surfaces/welcome.json +571 -0
- package/src/surfaces/welcome.ts +338 -0
- package/src/tabs/project-config.ts +71 -15
- package/src/tabs/tab.ts +52 -1
- package/src/types.ts +49 -3
- package/src/ui/ai-credentials-form.ts +104 -100
- package/src/ui/ai-managed-connect.ts +116 -49
- package/src/ui/ai-model-picker.ts +102 -47
- package/src/ui/cf-account-picker.ts +135 -0
- package/src/ui/color-selector.ts +80 -301
- package/src/ui/dynamic-slot.ts +43 -283
- package/src/ui/expression-editor.ts +797 -576
- package/src/ui/field-input.ts +8 -181
- package/src/ui/form-controls.ts +838 -366
- package/src/ui/formula-chips.ts +80 -85
- package/src/ui/kit.ts +33 -0
- package/src/ui/layers.ts +293 -593
- package/src/ui/media-picker.ts +203 -284
- package/src/ui/panel-resize.ts +251 -64
- package/src/ui/popover-surface.ts +153 -0
- package/src/ui/progress-modal.ts +22 -60
- package/src/ui/regions.ts +13 -7
- package/src/ui/schema-form.ts +906 -440
- package/src/ui/surface.ts +122 -0
- package/src/ui/unit-selector.ts +15 -131
- package/src/ui/value-source.ts +14 -0
- package/src/ui/virtual-window.ts +88 -9
- package/src/utils/canvas-media.ts +72 -0
- package/src/utils/edit-display.ts +7 -2
- package/src/utils/element-selectors.ts +69 -0
- package/src/utils/link-target.ts +2 -2
- package/src/utils/studio-utils.ts +0 -10
- package/src/view.ts +15 -0
- package/src/workspace/pane-derive.ts +36 -14
- package/src/workspace/workspace.ts +15 -6
- package/styles/canvas.css +72 -467
- package/styles/forced-colors.css +48 -82
- package/styles/forced-colors.json +41 -0
- package/styles/inspector.css +2 -1301
- package/styles/overlays.css +96 -2823
- package/styles/panels.css +6 -1423
- package/styles/shell-frame.css +272 -0
- package/styles/shell-frame.json +227 -0
- package/styles/shell.css +0 -1532
- package/styles/tokens.css +65 -136
- package/styles/tokens.json +84 -0
- package/dist/chunks/Overlay.dev-723bv0df.js +0 -23
- package/dist/chunks/adapter-jkcyhgtr.js +0 -14
- package/dist/chunks/cf-settings-45fgyx8y.js +0 -21
- package/dist/chunks/components-zmx10t62.js +0 -21
- package/dist/chunks/content-source-t88vb2dr.js +0 -49
- package/dist/chunks/convert-to-repeater-dhw1nrz9.js +0 -268
- package/dist/chunks/editor-cptq5jp1.js +0 -37
- package/dist/chunks/entry-commands-6z6bhxg0.js +0 -46
- package/dist/chunks/extension-sections-3ydgjbdy.js +0 -311
- package/dist/chunks/file-ops-rskmhxyq.js +0 -48
- package/dist/chunks/files-0cratsr0.js +0 -92
- package/dist/chunks/flow-qbfgrpeh.js +0 -634
- package/dist/chunks/focus-trap.esm-ggawf1hy.js +0 -1024
- package/dist/chunks/focus-visible-6eg70z18.js +0 -167
- package/dist/chunks/format-host-tgcmfs4p.js +0 -43
- package/dist/chunks/fs-events-hrrg328g.js +0 -21
- package/dist/chunks/git-panel-0yywyk76.js +0 -58
- package/dist/chunks/index-zqxmqxmh.js +0 -109
- package/dist/chunks/jx-validate-8q2g05x1.js +0 -19
- package/dist/chunks/layers-panel-z3tqe5cd.js +0 -67
- package/dist/chunks/layers-q75tj2mf.js +0 -45
- package/dist/chunks/lit-html-j055mkh8.js +0 -22
- package/dist/chunks/monaco-buffer-dqw0xxpx.js +0 -25
- package/dist/chunks/notify-yjm79n4s.js +0 -30
- package/dist/chunks/parse-24d0gay3.js +0 -19
- package/dist/chunks/platform-ba1j1gbh.js +0 -16
- package/dist/chunks/publish-panel-54jvhskq.js +0 -28
- package/dist/chunks/quick-search-cgfmjwq5.js +0 -65
- package/dist/chunks/references-3qx8fkyp.js +0 -29
- package/dist/chunks/right-panel-cqp8bc4v.js +0 -46
- package/dist/chunks/section-registry-sx1ykvkw.js +0 -30
- package/dist/chunks/sp-overlay.dev-yztmtrs1.js +0 -18
- package/dist/chunks/sp-popover.dev-n2etmqdp.js +0 -9
- package/dist/chunks/sp-progress-circle.dev-hryhj0es.js +0 -15
- package/dist/chunks/sp-tooltip.dev-xcvpnqr0.js +0 -15
- package/dist/chunks/sp-tray.dev-tkbscm06.js +0 -199
- package/dist/chunks/studio-0a5qrh01.js +0 -3
- package/dist/chunks/studio-18j3bmcz.js +0 -14
- package/dist/chunks/studio-1hbqnt19.js +0 -1823
- package/dist/chunks/studio-4rzyrtjz.js +0 -426
- package/dist/chunks/studio-5rywrkxz.js +0 -1903
- package/dist/chunks/studio-7afd21nw.js +0 -67
- package/dist/chunks/studio-7nte2hj4.js +0 -613
- package/dist/chunks/studio-8jpzqk5s.js +0 -128
- package/dist/chunks/studio-8q517dfr.js +0 -24
- package/dist/chunks/studio-9c4k4vhv.js +0 -357
- package/dist/chunks/studio-9n4mrmnb.js +0 -184
- package/dist/chunks/studio-a0tswy0w.js +0 -58
- package/dist/chunks/studio-ahjfdy6e.js +0 -387
- package/dist/chunks/studio-ahnzd9rg.js +0 -23
- package/dist/chunks/studio-bw5dz6km.js +0 -608
- package/dist/chunks/studio-cb12yz9w.js +0 -15055
- package/dist/chunks/studio-d1ks410h.js +0 -175
- package/dist/chunks/studio-eqq1w638.js +0 -113
- package/dist/chunks/studio-ex8zyp98.js +0 -1813
- package/dist/chunks/studio-h4rxscfc.js +0 -10
- package/dist/chunks/studio-kyh9avvv.js +0 -28
- package/dist/chunks/studio-kyk2v92a.js +0 -659
- package/dist/chunks/studio-m3hwn7y1.js +0 -120
- package/dist/chunks/studio-mmv72a27.js +0 -4344
- package/dist/chunks/studio-n8b9wqwy.js +0 -291
- package/dist/chunks/studio-pdfjntbk.js +0 -6939
- package/dist/chunks/studio-qq6jym04.js +0 -53
- package/dist/chunks/studio-r1r7afxx.js +0 -1066
- package/dist/chunks/studio-rdx8jcxy.js +0 -83
- package/dist/chunks/studio-rn9ta2mz.js +0 -111
- package/dist/chunks/studio-t7qb9db8.js +0 -665
- package/dist/chunks/studio-tmc5emrw.js +0 -8
- package/dist/chunks/studio-txwkm6p9.js +0 -12
- package/dist/chunks/studio-v38hmvx1.js +0 -390
- package/dist/chunks/studio-vadzgkrz.js +0 -318
- package/dist/chunks/studio-wx5609xd.js +0 -341
- package/dist/chunks/studio-z6nw2ek2.js +0 -18
- package/dist/chunks/studio-zczps70q.js +0 -378
- package/dist/chunks/workspace-xpres40v.js +0 -89
- package/src/panels/activity-bar.ts +0 -251
- package/src/panels/panel-scheduler.ts +0 -219
- package/src/panels/style-inputs.ts +0 -237
- package/src/panels/target-line.ts +0 -274
- package/src/panels/welcome-screen.ts +0 -346
- package/src/ui/button-group.ts +0 -102
- package/src/ui/choice-field.ts +0 -72
- package/src/ui/field-row.ts +0 -249
- package/src/ui/formula-palette.ts +0 -213
- package/src/ui/icons.ts +0 -52
- package/src/ui/jx-theme.ts +0 -130
- package/src/ui/spectrum.ts +0 -340
- package/src/ui/value-selector.ts +0 -174
- package/src/ui/widgets.ts +0 -172
- /package/dist/chunks/{javascript-s56a8dpk.css → javascript-4abzjcy9.css} +0 -0
- /package/dist/chunks/{jsonMode-zr9sw0c7.css → jsonMode-vvmpmk34.css} +0 -0
- /package/dist/chunks/{monaco-setup-pav68602.css → monaco-setup-8vbyqnhr.css} +0 -0
- /package/dist/chunks/{tsMode-ef187txx.css → tsMode-hnxxb73h.css} +0 -0
|
@@ -25,28 +25,54 @@
|
|
|
25
25
|
* press"), and rebindable — as a LAYER over the registry (`settings/preferences-keymap.ts`), so
|
|
26
26
|
* the sheet stays a projection and the app's own record of a default is never edited.
|
|
27
27
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
28
|
+
* **This module is the FLOW; `surfaces/preferences.json` is what it draws.** Every function below
|
|
29
|
+
* either answers a question about state or changes some, and the answers leave here as strings and
|
|
30
|
+
* booleans — `keyboardEmpty` is a sentence rather than a case name, a row's chord is already
|
|
31
|
+
* formatted, an account's buttons are already decided. Which of those add up to which branch of the
|
|
32
|
+
* document is `surfaces/preferences.ts`'s.
|
|
33
|
+
*
|
|
34
|
+
* **Only the showing section is projected.** `accountsView()` reads three credential stores and
|
|
35
|
+
* `keyboardView()` walks the whole registry, and a repaint of the theme toggle has no business
|
|
36
|
+
* doing either — so each is built when its own section is up and left empty otherwise, exactly as
|
|
37
|
+
* the four `*Tpl()` functions this replaced were called one at a time.
|
|
38
|
+
*
|
|
39
|
+
* Modality: a `jx-dialog` in the dialog layer, which is focus-managed, dismissed by Escape and
|
|
40
|
+
* backed by the platform's own top layer — not the full-viewport blackout the lit modal path used
|
|
41
|
+
* to paint. Preferences does not suspend the app.
|
|
30
42
|
*/
|
|
31
43
|
|
|
32
|
-
import { html, nothing, render as litRender } from "lit-html";
|
|
33
|
-
import { ref } from "lit-html/directives/ref.js";
|
|
34
44
|
import { CHROME_THEMES, setChromeTheme, shell } from "../shell";
|
|
35
|
-
import {
|
|
45
|
+
import { layerHost } from "../ui/layers";
|
|
36
46
|
import { createAiCredentialsForm } from "../ui/ai-credentials-form";
|
|
37
47
|
import { createManagedConnect } from "../ui/ai-managed-connect";
|
|
38
48
|
import { activeRegistry } from "../commands/active-registry";
|
|
39
49
|
import { shortcutReference, SCOPE_LABELS } from "../commands/reference";
|
|
40
50
|
import { chordFromEvent } from "../commands/keymap";
|
|
41
|
-
import {
|
|
51
|
+
import {
|
|
52
|
+
ensureCfConnection,
|
|
53
|
+
listAccounts,
|
|
54
|
+
notifyCredentialsChanged,
|
|
55
|
+
platformBrokersCf,
|
|
56
|
+
refreshCfConnection,
|
|
57
|
+
resetCfConnectionCache,
|
|
58
|
+
revokeAccount,
|
|
59
|
+
} from "./preferences-accounts";
|
|
42
60
|
import { applyKeybindingOverrides, rebindCommand, resetKeybinding } from "./preferences-keymap";
|
|
43
|
-
import {
|
|
61
|
+
import { openPreferencesSurface } from "../surfaces/preferences";
|
|
44
62
|
|
|
45
|
-
import type { TemplateResult } from "lit-html";
|
|
46
63
|
import type { ChromeTheme } from "../shell";
|
|
47
64
|
import type { ShortcutRow } from "../commands/reference";
|
|
48
65
|
import type { RebindResult } from "./preferences-keymap";
|
|
49
66
|
import type { AnyCommand, CommandRegistry } from "../commands/registry";
|
|
67
|
+
import type {
|
|
68
|
+
PreferencesAccountRow,
|
|
69
|
+
PreferencesIsland,
|
|
70
|
+
PreferencesKeyGroup,
|
|
71
|
+
PreferencesSectionRow,
|
|
72
|
+
PreferencesSurfaceHandle,
|
|
73
|
+
PreferencesThemeRow,
|
|
74
|
+
PreferencesView,
|
|
75
|
+
} from "../surfaces/preferences";
|
|
50
76
|
|
|
51
77
|
/*
|
|
52
78
|
* The sections moved to `./preferences-sections`, a leaf with no imports, so the rail's gear menu
|
|
@@ -71,15 +97,12 @@ export type { PreferencesSection } from "./preferences-sections";
|
|
|
71
97
|
|
|
72
98
|
let _section = DEFAULT_PREFERENCES_SECTION;
|
|
73
99
|
|
|
74
|
-
/**
|
|
75
|
-
let
|
|
76
|
-
|
|
77
|
-
/** Dismiss the open sheet, if one is up. */
|
|
78
|
-
let _close: (() => void) | null = null;
|
|
100
|
+
/** The mounted sheet, or `null` while none is up. */
|
|
101
|
+
let _surface: PreferencesSurfaceHandle | null = null;
|
|
79
102
|
|
|
80
103
|
/** Whether Preferences is on screen. */
|
|
81
104
|
export function isPreferencesOpen(): boolean {
|
|
82
|
-
return
|
|
105
|
+
return _surface !== null;
|
|
83
106
|
}
|
|
84
107
|
|
|
85
108
|
/** The section currently showing. Exposed for tests and for the `app.preferences` round-trip. */
|
|
@@ -88,7 +111,8 @@ export function preferencesSection(): string {
|
|
|
88
111
|
}
|
|
89
112
|
|
|
90
113
|
function repaint(): void {
|
|
91
|
-
|
|
114
|
+
_surface?.update(view());
|
|
115
|
+
fillIslands();
|
|
92
116
|
}
|
|
93
117
|
|
|
94
118
|
/** Save/revoke both change what other surfaces show, so they announce as well as repaint. */
|
|
@@ -97,12 +121,25 @@ function credentialsChanged(): void {
|
|
|
97
121
|
repaint();
|
|
98
122
|
}
|
|
99
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Showing a section is a chance to find out it is stale.
|
|
126
|
+
*
|
|
127
|
+
* Only Accounts has anything to re-read: the brokered Cloudflare connection lives on the server, so
|
|
128
|
+
* a grant that lapsed while Preferences was closed — or while the author was in Keyboard — would
|
|
129
|
+
* otherwise be reported from a cache taken before it did.
|
|
130
|
+
*/
|
|
131
|
+
function sectionShown(): void {
|
|
132
|
+
if (_section === "accounts" && platformBrokersCf()) {
|
|
133
|
+
void refreshCfConnection().then(repaint);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
100
137
|
/** The shared credentials form — draft state lives inside the form's closure. */
|
|
101
138
|
const credsForm = createAiCredentialsForm({
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
139
|
+
/* A sentence rather than a template: the form is a document now, and a document renders text
|
|
140
|
+
rather than another module's markup. */
|
|
141
|
+
intro:
|
|
142
|
+
"Any OpenAI-compatible key works. Stored locally on this machine; sent only to the Studio proxy (never to a third party except your chosen endpoint).",
|
|
106
143
|
// Both buttons keep the sheet open: Preferences is a place, not a wizard step, and the previous
|
|
107
144
|
// Dialog's habit of vanishing on Save is what made "did that take?" unanswerable.
|
|
108
145
|
onCancel: repaint,
|
|
@@ -113,69 +150,157 @@ const credsForm = createAiCredentialsForm({
|
|
|
113
150
|
/** Shared with the New Project modal's gates — see ui/ai-managed-connect.ts. */
|
|
114
151
|
const managedConnect = createManagedConnect({ requestRender: credentialsChanged });
|
|
115
152
|
|
|
153
|
+
// ─── The Assistant islands ────────────────────────────────────────────────────
|
|
154
|
+
|
|
155
|
+
/*
|
|
156
|
+
* The two elements the Assistant section renders and does not fill.
|
|
157
|
+
*
|
|
158
|
+
* Both belong to a controller that outlives this sheet and is embedded by three other credentials
|
|
159
|
+
* gates, so the document renders an empty box for each and the elements are MOVED into it. Moving a
|
|
160
|
+
* node keeps everything inside it — which is the whole point: the credentials form is three fields
|
|
161
|
+
* a reader is typing into, and a repaint that rebuilt them would take the caret with it.
|
|
162
|
+
*/
|
|
163
|
+
let _managedSlot: HTMLElement | null = null;
|
|
164
|
+
let _credsSlot: HTMLElement | null = null;
|
|
165
|
+
|
|
166
|
+
/** A slot was created by the document. Remember it, and fill it. */
|
|
167
|
+
function islandCreated(island: PreferencesIsland, host: HTMLElement): void {
|
|
168
|
+
if (island === "managed") {
|
|
169
|
+
_managedSlot = host;
|
|
170
|
+
} else {
|
|
171
|
+
_credsSlot = host;
|
|
172
|
+
}
|
|
173
|
+
fillIslands();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Put each controller's element in its slot, and bring both up to date.
|
|
178
|
+
*
|
|
179
|
+
* `render()` on either controller is an UPDATE when the surface already exists, so this is also how
|
|
180
|
+
* a repaint reaches them. The parent check is what keeps it from being a rebuild: re-appending a
|
|
181
|
+
* node that is already there would be a move, and a move of a focused field takes the caret.
|
|
182
|
+
*/
|
|
183
|
+
function fillIslands(): void {
|
|
184
|
+
if (_managedSlot) {
|
|
185
|
+
managedConnect.ensureProbe();
|
|
186
|
+
const element = managedConnect.render();
|
|
187
|
+
if (element === null) {
|
|
188
|
+
_managedSlot.replaceChildren();
|
|
189
|
+
} else if (element.parentNode !== _managedSlot) {
|
|
190
|
+
_managedSlot.replaceChildren(element);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (_credsSlot) {
|
|
194
|
+
const element = credsForm.render();
|
|
195
|
+
if (element.parentNode !== _credsSlot) {
|
|
196
|
+
_credsSlot.replaceChildren(element);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
116
201
|
// ─── Sections ─────────────────────────────────────────────────────────────────
|
|
117
202
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
203
|
+
/** The nav, with the showing row marked as the accessibility tree already marks it. */
|
|
204
|
+
function sectionsView(): PreferencesSectionRow[] {
|
|
205
|
+
return PREFERENCES_SECTIONS.map((section) => ({
|
|
206
|
+
current: section.id === _section ? "true" : "false",
|
|
207
|
+
id: section.id,
|
|
208
|
+
title: section.title,
|
|
209
|
+
}));
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** The theme segments. `checked` is a string because that is what `aria-checked` takes. */
|
|
213
|
+
function themesView(): PreferencesThemeRow[] {
|
|
214
|
+
return CHROME_THEMES.map((theme) => ({
|
|
215
|
+
checked: shell.theme === theme ? "true" : "false",
|
|
216
|
+
label: theme === "dark" ? "Dark" : "Light",
|
|
217
|
+
value: theme,
|
|
218
|
+
}));
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function selectSection(id: string): void {
|
|
222
|
+
_section = id;
|
|
223
|
+
// Leaving a section abandons what it was in the middle of: an armed key capture whose listener
|
|
224
|
+
// Is no longer mounted would otherwise swallow the first chord pressed on the author's NEXT
|
|
225
|
+
// Visit.
|
|
226
|
+
resetKeyboardState();
|
|
227
|
+
repaint();
|
|
228
|
+
sectionShown();
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function setTheme(value: string): void {
|
|
232
|
+
setChromeTheme(value as ChromeTheme);
|
|
233
|
+
repaint();
|
|
140
234
|
}
|
|
141
235
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
236
|
+
// ─── Accounts ─────────────────────────────────────────────────────────────────
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* What each account button does, by the key the row carries.
|
|
240
|
+
*
|
|
241
|
+
* Rebuilt with the rows, because `listAccounts()` mints a fresh closure per call and the one a
|
|
242
|
+
* click must run is the one that was drawn. A key that is no longer in the map is a click on a row
|
|
243
|
+
* that has since been redrawn, which is a no-op rather than an error.
|
|
244
|
+
*/
|
|
245
|
+
let _accountRuns = new Map<string, () => void | Promise<void>>();
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* The accounts, as rows.
|
|
249
|
+
*
|
|
250
|
+
* A record that declares `actions` decides its own verbs; everything else keeps the original rule —
|
|
251
|
+
* a connected credential offers Disconnect and a disconnected one offers nothing.
|
|
252
|
+
*/
|
|
253
|
+
function accountsView(): PreferencesAccountRow[] {
|
|
254
|
+
// First paint asks the broker what it holds; the answer arrives as a credentials-changed repaint.
|
|
255
|
+
ensureCfConnection();
|
|
256
|
+
const runs = new Map<string, () => void | Promise<void>>();
|
|
257
|
+
const rows = listAccounts().map((account) => {
|
|
258
|
+
const declared =
|
|
259
|
+
account.actions ??
|
|
260
|
+
(account.connected
|
|
261
|
+
? [
|
|
262
|
+
{
|
|
263
|
+
id: "disconnect",
|
|
264
|
+
label: "Disconnect",
|
|
265
|
+
run: () => {
|
|
266
|
+
revokeAccount(account.id);
|
|
267
|
+
},
|
|
268
|
+
variant: "negative",
|
|
269
|
+
},
|
|
270
|
+
]
|
|
271
|
+
: []);
|
|
272
|
+
return {
|
|
273
|
+
actions: declared.map((action) => {
|
|
274
|
+
const key = `${account.id}/${action.id}`;
|
|
275
|
+
runs.set(key, action.run);
|
|
276
|
+
return {
|
|
277
|
+
id: action.id,
|
|
278
|
+
key,
|
|
279
|
+
label: action.label,
|
|
280
|
+
variant: action.variant ?? "secondary",
|
|
281
|
+
};
|
|
282
|
+
}),
|
|
283
|
+
detail: account.detail,
|
|
284
|
+
id: account.id,
|
|
285
|
+
label: account.label,
|
|
286
|
+
};
|
|
287
|
+
});
|
|
288
|
+
_accountRuns = runs;
|
|
289
|
+
return rows;
|
|
145
290
|
}
|
|
146
291
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
? html`
|
|
160
|
-
<sp-button
|
|
161
|
-
size="s"
|
|
162
|
-
variant="negative"
|
|
163
|
-
treatment="outline"
|
|
164
|
-
@click=${() => {
|
|
165
|
-
revokeAccount(account.id);
|
|
166
|
-
repaint();
|
|
167
|
-
}}
|
|
168
|
-
>
|
|
169
|
-
Disconnect
|
|
170
|
-
</sp-button>
|
|
171
|
-
`
|
|
172
|
-
: nothing
|
|
173
|
-
}
|
|
174
|
-
</div>
|
|
175
|
-
`,
|
|
176
|
-
)}
|
|
177
|
-
</div>
|
|
178
|
-
`;
|
|
292
|
+
/**
|
|
293
|
+
* Run one account button.
|
|
294
|
+
*
|
|
295
|
+
* Every one of them repaints when it settles, because a hosted Reconnect is a round trip through a
|
|
296
|
+
* Cloudflare popup and the row must not still be reading "expired" when it comes back.
|
|
297
|
+
*/
|
|
298
|
+
function runAccountAction(key: string): void {
|
|
299
|
+
const run = _accountRuns.get(key);
|
|
300
|
+
if (!run) {
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
void Promise.resolve(run()).finally(repaint);
|
|
179
304
|
}
|
|
180
305
|
|
|
181
306
|
// ─── Keyboard ─────────────────────────────────────────────────────────────────
|
|
@@ -189,8 +314,15 @@ function accountsTpl(): TemplateResult {
|
|
|
189
314
|
*/
|
|
190
315
|
type KeyFilter = { kind: "text"; value: string } | { kind: "chord"; chord: string } | null;
|
|
191
316
|
|
|
192
|
-
/**
|
|
193
|
-
|
|
317
|
+
/**
|
|
318
|
+
* The next chord goes to the search box, or onto a command. `null` while nothing is listening.
|
|
319
|
+
*
|
|
320
|
+
* A rebind capture holds the command's ID rather than its record, because the click that armed it
|
|
321
|
+
* arrived from a document and carried a string. The record is looked up when the chord lands, which
|
|
322
|
+
* is also the one moment at which "the registry went away under the open sheet" can be answered
|
|
323
|
+
* honestly rather than asserted against.
|
|
324
|
+
*/
|
|
325
|
+
type KeyCapture = { mode: "search" } | { mode: "rebind"; commandId: string } | null;
|
|
194
326
|
|
|
195
327
|
/** Keydowns that are not a chord yet: a modifier held on its way to one. */
|
|
196
328
|
const MODIFIER_KEYS = new Set(["Meta", "Control", "Alt", "Shift", "CapsLock", "OS"]);
|
|
@@ -253,96 +385,87 @@ function onKeyboardKeyDown(event: KeyboardEvent): void {
|
|
|
253
385
|
_keyFilter = { kind: "chord", chord };
|
|
254
386
|
_keyRefusal = null;
|
|
255
387
|
} else {
|
|
256
|
-
const
|
|
257
|
-
|
|
388
|
+
const command = commandById(registry, capture.commandId);
|
|
389
|
+
if (command) {
|
|
390
|
+
const result = rebindCommand(registry, command, chord);
|
|
391
|
+
_keyRefusal = result.ok ? null : result;
|
|
392
|
+
}
|
|
258
393
|
}
|
|
259
394
|
repaint();
|
|
260
395
|
}
|
|
261
396
|
|
|
262
|
-
/** The
|
|
263
|
-
function
|
|
264
|
-
|
|
265
|
-
|
|
397
|
+
/** The record behind a row's id, or `undefined` when the registry no longer holds one. */
|
|
398
|
+
function commandById(registry: CommandRegistry, commandId: string): AnyCommand | undefined {
|
|
399
|
+
return [...registry.list()].find((candidate) => candidate.id === commandId);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/** Arm or disarm the search box's chord capture. */
|
|
403
|
+
function toggleKeystroke(): void {
|
|
404
|
+
_keyCapture = _keyCapture?.mode === "search" ? null : { mode: "search" };
|
|
405
|
+
_keyRefusal = null;
|
|
406
|
+
repaint();
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/** Arm or disarm one row's rebind. */
|
|
410
|
+
function toggleRebind(commandId: string): void {
|
|
411
|
+
const capturing = _keyCapture?.mode === "rebind" && _keyCapture.commandId === commandId;
|
|
412
|
+
_keyCapture = capturing ? null : { mode: "rebind", commandId };
|
|
413
|
+
_keyRefusal = null;
|
|
414
|
+
repaint();
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/** Put a rebound chord back, and forget whatever the last attempt said. */
|
|
418
|
+
function resetBinding(commandId: string): void {
|
|
419
|
+
const registry = activeRegistry();
|
|
420
|
+
if (registry) {
|
|
421
|
+
resetKeybinding(registry, commandId);
|
|
266
422
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
<div class="prefs-field">
|
|
270
|
-
<sp-help-text variant="negative">${_keyRefusal.reason}</sp-help-text>
|
|
271
|
-
${
|
|
272
|
-
conflict
|
|
273
|
-
? html`
|
|
274
|
-
<sp-button
|
|
275
|
-
size="s"
|
|
276
|
-
treatment="outline"
|
|
277
|
-
@click=${() => {
|
|
278
|
-
_keyFilter = { kind: "text", value: conflict.title };
|
|
279
|
-
_keyRefusal = null;
|
|
280
|
-
repaint();
|
|
281
|
-
}}
|
|
282
|
-
>
|
|
283
|
-
Show ${conflict.title}
|
|
284
|
-
</sp-button>
|
|
285
|
-
`
|
|
286
|
-
: nothing
|
|
287
|
-
}
|
|
288
|
-
</div>
|
|
289
|
-
`;
|
|
423
|
+
_keyRefusal = null;
|
|
424
|
+
repaint();
|
|
290
425
|
}
|
|
291
426
|
|
|
292
|
-
/**
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
command: AnyCommand,
|
|
302
|
-
registry: CommandRegistry,
|
|
303
|
-
): TemplateResult {
|
|
304
|
-
const capturing = _keyCapture?.mode === "rebind" && _keyCapture.command.id === row.commandId;
|
|
305
|
-
return html`
|
|
306
|
-
<div class="prefs-key" data-command=${row.commandId}>
|
|
307
|
-
<kbd class="prefs-key-chord">
|
|
308
|
-
${capturing ? "Press a shortcut…" : registry.keymap.format(row.chord)}
|
|
309
|
-
</kbd>
|
|
310
|
-
<span class="prefs-key-title">${row.title}${row.overridden ? " — changed" : ""}</span>
|
|
311
|
-
<sp-action-button
|
|
312
|
-
size="s"
|
|
313
|
-
quiet
|
|
314
|
-
?selected=${capturing}
|
|
315
|
-
aria-label=${capturing ? `Stop changing ${row.title}` : `Change the shortcut for ${row.title}`}
|
|
316
|
-
@click=${() => {
|
|
317
|
-
_keyCapture = capturing ? null : { mode: "rebind", command };
|
|
318
|
-
_keyRefusal = null;
|
|
319
|
-
repaint();
|
|
320
|
-
}}
|
|
321
|
-
>
|
|
322
|
-
${capturing ? "Cancel" : "Change"}
|
|
323
|
-
</sp-action-button>
|
|
324
|
-
${
|
|
325
|
-
row.overridden
|
|
326
|
-
? html`
|
|
327
|
-
<sp-action-button
|
|
328
|
-
size="s"
|
|
329
|
-
quiet
|
|
330
|
-
aria-label=${`Reset the shortcut for ${row.title}`}
|
|
331
|
-
@click=${() => {
|
|
332
|
-
resetKeybinding(registry, row.commandId);
|
|
333
|
-
_keyRefusal = null;
|
|
334
|
-
repaint();
|
|
335
|
-
}}
|
|
336
|
-
>
|
|
337
|
-
Reset
|
|
338
|
-
</sp-action-button>
|
|
339
|
-
`
|
|
340
|
-
: nothing
|
|
341
|
-
}
|
|
342
|
-
</div>
|
|
343
|
-
`;
|
|
427
|
+
/** Go and look at the command holding the chord that was refused. */
|
|
428
|
+
function showConflict(): void {
|
|
429
|
+
const conflict = _keyRefusal?.conflict;
|
|
430
|
+
if (!conflict) {
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
_keyFilter = { kind: "text", value: conflict.title };
|
|
434
|
+
_keyRefusal = null;
|
|
435
|
+
repaint();
|
|
344
436
|
}
|
|
345
437
|
|
|
438
|
+
/** Type into the search box. A keystroke capture is abandoned: the author changed their mind. */
|
|
439
|
+
function setKeyQuery(value: string): void {
|
|
440
|
+
_keyFilter = value ? { kind: "text", value } : null;
|
|
441
|
+
_keyCapture = null;
|
|
442
|
+
repaint();
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/** The Keyboard half of the view, with nothing to say when its section is not up. */
|
|
446
|
+
type KeyboardView = Pick<
|
|
447
|
+
PreferencesView,
|
|
448
|
+
| "capturingSearch"
|
|
449
|
+
| "conflictLabel"
|
|
450
|
+
| "groups"
|
|
451
|
+
| "keyboardEmpty"
|
|
452
|
+
| "keyQuery"
|
|
453
|
+
| "keystrokeLabel"
|
|
454
|
+
| "refusal"
|
|
455
|
+
| "rowsEmpty"
|
|
456
|
+
>;
|
|
457
|
+
|
|
458
|
+
const KEYBOARD_IDLE: KeyboardView = {
|
|
459
|
+
capturingSearch: false,
|
|
460
|
+
conflictLabel: "",
|
|
461
|
+
groups: [],
|
|
462
|
+
keyboardEmpty: "",
|
|
463
|
+
keyQuery: "",
|
|
464
|
+
keystrokeLabel: "",
|
|
465
|
+
refusal: "",
|
|
466
|
+
rowsEmpty: "",
|
|
467
|
+
};
|
|
468
|
+
|
|
346
469
|
/**
|
|
347
470
|
* The keyboard sheet — every live binding, grouped by the scope it is live in.
|
|
348
471
|
*
|
|
@@ -351,94 +474,80 @@ function keyRowTpl(
|
|
|
351
474
|
* the same projection rather than patched into its output.
|
|
352
475
|
*
|
|
353
476
|
* A command that declares two chords has two rows and rebinding either one leaves it with one — a
|
|
354
|
-
* user who asked for ⌥⌘Y is not also asking to keep ⌘Y, and Reset brings both back.
|
|
477
|
+
* user who asked for ⌥⌘Y is not also asking to keep ⌘Y, and Reset brings both back. The two rows
|
|
478
|
+
* share a `commandId` and differ by chord, which is why the row key is both.
|
|
355
479
|
*/
|
|
356
|
-
function
|
|
480
|
+
function keyboardView(): KeyboardView {
|
|
357
481
|
const registry = activeRegistry();
|
|
358
482
|
const commands: readonly AnyCommand[] = registry ? [...registry.list()] : [];
|
|
359
483
|
const rows = registry ? shortcutReference(commands, registry.keymap.overrides()) : [];
|
|
360
484
|
if (!registry || rows.length === 0) {
|
|
361
|
-
return
|
|
485
|
+
return { ...KEYBOARD_IDLE, keyboardEmpty: "No commands are registered in this window." };
|
|
362
486
|
}
|
|
363
487
|
const format = (chord: string) => registry.keymap.format(chord);
|
|
364
|
-
const
|
|
365
|
-
const visible = rows.
|
|
366
|
-
const command = byId.get(row.commandId);
|
|
367
|
-
return command && keyRowMatches(row, format) ? [{ command, row }] : [];
|
|
368
|
-
});
|
|
369
|
-
const scopes = [...new Set(visible.map(({ row }) => row.scope))];
|
|
488
|
+
const known = new Set(commands.map((command) => command.id));
|
|
489
|
+
const visible = rows.filter((row) => known.has(row.commandId) && keyRowMatches(row, format));
|
|
370
490
|
const capturingSearch = _keyCapture?.mode === "search";
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
<sp-action-button
|
|
393
|
-
size="s"
|
|
394
|
-
?selected=${capturingSearch}
|
|
395
|
-
@click=${() => {
|
|
396
|
-
_keyCapture = capturingSearch ? null : { mode: "search" };
|
|
397
|
-
_keyRefusal = null;
|
|
398
|
-
repaint();
|
|
399
|
-
}}
|
|
400
|
-
>
|
|
401
|
-
${capturingSearch ? "Press it now" : "Search by keystroke"}
|
|
402
|
-
</sp-action-button>
|
|
403
|
-
</div>
|
|
404
|
-
${keyRefusalTpl()}
|
|
405
|
-
${
|
|
406
|
-
visible.length === 0
|
|
407
|
-
? html`<p class="prefs-empty">
|
|
408
|
-
${
|
|
409
|
-
_keyFilter?.kind === "chord"
|
|
410
|
-
? `Nothing is bound to ${format(_keyFilter.chord)}.`
|
|
411
|
-
: "No shortcut matches that."
|
|
412
|
-
}
|
|
413
|
-
</p>`
|
|
414
|
-
: scopes.map(
|
|
415
|
-
(scope) => html`
|
|
416
|
-
<h4 class="prefs-keys-scope">${SCOPE_LABELS[scope]}</h4>
|
|
417
|
-
${visible
|
|
418
|
-
.filter(({ row }) => row.scope === scope)
|
|
419
|
-
.map(({ command, row }) => keyRowTpl(row, command, registry))}
|
|
420
|
-
`,
|
|
421
|
-
)
|
|
422
|
-
}
|
|
423
|
-
</div>
|
|
424
|
-
`;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
function sectionBodyTpl(): TemplateResult {
|
|
428
|
-
if (_section === "assistant") {
|
|
429
|
-
return assistantTpl();
|
|
491
|
+
const groups: PreferencesKeyGroup[] = [];
|
|
492
|
+
const byScope = new Map<string, PreferencesKeyGroup>();
|
|
493
|
+
for (const row of visible) {
|
|
494
|
+
const capturing = _keyCapture?.mode === "rebind" && _keyCapture.commandId === row.commandId;
|
|
495
|
+
let group = byScope.get(row.scope);
|
|
496
|
+
if (!group) {
|
|
497
|
+
group = { label: SCOPE_LABELS[row.scope], rows: [], scope: row.scope };
|
|
498
|
+
byScope.set(row.scope, group);
|
|
499
|
+
groups.push(group);
|
|
500
|
+
}
|
|
501
|
+
group.rows.push({
|
|
502
|
+
capturing,
|
|
503
|
+
changeLabel: capturing ? "Cancel" : "Change",
|
|
504
|
+
changeName: capturing ? `Stop changing ${row.title}` : `Change the shortcut for ${row.title}`,
|
|
505
|
+
chord: capturing ? "Press a shortcut…" : format(row.chord),
|
|
506
|
+
commandId: row.commandId,
|
|
507
|
+
key: `${row.commandId}/${row.chord}`,
|
|
508
|
+
overridden: row.overridden,
|
|
509
|
+
resetName: `Reset the shortcut for ${row.title}`,
|
|
510
|
+
title: `${row.title}${row.overridden ? " — changed" : ""}`,
|
|
511
|
+
});
|
|
430
512
|
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
513
|
+
return {
|
|
514
|
+
capturingSearch,
|
|
515
|
+
conflictLabel: _keyRefusal?.conflict ? `Show ${_keyRefusal.conflict.title}` : "",
|
|
516
|
+
groups,
|
|
517
|
+
keyboardEmpty: "",
|
|
518
|
+
keyQuery:
|
|
519
|
+
_keyFilter === null
|
|
520
|
+
? ""
|
|
521
|
+
: _keyFilter.kind === "chord"
|
|
522
|
+
? format(_keyFilter.chord)
|
|
523
|
+
: _keyFilter.value,
|
|
524
|
+
keystrokeLabel: capturingSearch ? "Press it now" : "Search by keystroke",
|
|
525
|
+
refusal: _keyRefusal?.reason ?? "",
|
|
526
|
+
rowsEmpty:
|
|
527
|
+
visible.length > 0
|
|
528
|
+
? ""
|
|
529
|
+
: _keyFilter?.kind === "chord"
|
|
530
|
+
? `Nothing is bound to ${format(_keyFilter.chord)}.`
|
|
531
|
+
: "No shortcut matches that.",
|
|
532
|
+
};
|
|
438
533
|
}
|
|
439
534
|
|
|
440
535
|
// ─── The sheet ────────────────────────────────────────────────────────────────
|
|
441
536
|
|
|
537
|
+
/** Everything the document reads, built from the section that is actually showing. */
|
|
538
|
+
function view(): PreferencesView {
|
|
539
|
+
const active = PREFERENCES_SECTIONS.find((candidate) => candidate.id === _section);
|
|
540
|
+
return {
|
|
541
|
+
accounts: _section === "accounts" ? accountsView() : [],
|
|
542
|
+
section: _section,
|
|
543
|
+
sectionBlurb: active?.blurb ?? "",
|
|
544
|
+
sectionTitle: active?.title ?? "",
|
|
545
|
+
sections: sectionsView(),
|
|
546
|
+
themes: themesView(),
|
|
547
|
+
...(_section === "keyboard" ? keyboardView() : KEYBOARD_IDLE),
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
|
|
442
551
|
/**
|
|
443
552
|
* Open Preferences, optionally on a named section. Resolves when it is dismissed.
|
|
444
553
|
*
|
|
@@ -449,92 +558,60 @@ function sectionBodyTpl(): TemplateResult {
|
|
|
449
558
|
* @param section One of {@link PREFERENCES_SECTIONS}' ids. An unknown id falls back to Appearance.
|
|
450
559
|
*/
|
|
451
560
|
export function openPreferences(section?: string): Promise<null> {
|
|
561
|
+
/* Opening is a fresh look, so nothing may be reported from the last one: a brokered Cloudflare
|
|
562
|
+
grant can lapse between visits, and a row that repaints the previous answer first is stating
|
|
563
|
+
something it has no reason to believe. */
|
|
564
|
+
resetCfConnectionCache();
|
|
452
565
|
_section = section !== undefined && isPreferencesSection(section) ? section : _section;
|
|
453
|
-
if (
|
|
566
|
+
if (_surface) {
|
|
454
567
|
repaint();
|
|
568
|
+
sectionShown();
|
|
455
569
|
return Promise.resolve(null);
|
|
456
570
|
}
|
|
457
571
|
_section =
|
|
458
572
|
section !== undefined && isPreferencesSection(section) ? section : DEFAULT_PREFERENCES_SECTION;
|
|
459
573
|
credsForm.startEdit();
|
|
460
574
|
resetKeyboardState();
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
underlay
|
|
477
|
-
headline="Preferences"
|
|
478
|
-
cancel-label="Close"
|
|
479
|
-
size="l"
|
|
480
|
-
@cancel=${finish}
|
|
481
|
-
@close=${finish}
|
|
482
|
-
${ref((el?: Element) => {
|
|
483
|
-
if (el) {
|
|
484
|
-
wrapperEl = el as HTMLElement;
|
|
485
|
-
}
|
|
486
|
-
})}
|
|
487
|
-
>
|
|
488
|
-
<div class="prefs-sheet">
|
|
489
|
-
<nav class="prefs-nav" aria-label="Preferences sections">
|
|
490
|
-
${PREFERENCES_SECTIONS.map(
|
|
491
|
-
(candidate) => html`
|
|
492
|
-
<button
|
|
493
|
-
type="button"
|
|
494
|
-
class="prefs-nav-item ${candidate.id === _section ? "active" : ""}"
|
|
495
|
-
aria-current=${candidate.id === _section ? "true" : "false"}
|
|
496
|
-
@click=${() => {
|
|
497
|
-
_section = candidate.id;
|
|
498
|
-
// Leaving a section abandons what it was in the middle of: an armed key
|
|
499
|
-
// Capture whose listener is no longer mounted would otherwise swallow the
|
|
500
|
-
// First chord pressed on the author's NEXT visit.
|
|
501
|
-
resetKeyboardState();
|
|
502
|
-
repaint();
|
|
503
|
-
}}
|
|
504
|
-
>
|
|
505
|
-
${candidate.title}
|
|
506
|
-
</button>
|
|
507
|
-
`,
|
|
508
|
-
)}
|
|
509
|
-
</nav>
|
|
510
|
-
<section class="prefs-body">
|
|
511
|
-
<h3 class="prefs-title">${active?.title ?? ""}</h3>
|
|
512
|
-
<p class="prefs-blurb">${active?.blurb ?? ""}</p>
|
|
513
|
-
${sectionBodyTpl()}
|
|
514
|
-
</section>
|
|
515
|
-
</div>
|
|
516
|
-
</sp-dialog-wrapper>
|
|
517
|
-
`;
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
_close = finish;
|
|
521
|
-
_rerender = () => {
|
|
522
|
-
// Resolved lazily: lit commits element refs before inserting the fragment, so the slot the
|
|
523
|
-
// Sheet was rendered into is only reachable once the first render has landed.
|
|
524
|
-
const host = wrapperEl?.parentElement;
|
|
525
|
-
if (host) {
|
|
526
|
-
litRender(build(), host);
|
|
575
|
+
sectionShown();
|
|
576
|
+
return new Promise<null>((resolve) => {
|
|
577
|
+
/* Guarded rather than trusted to the handle, because closing is what RAISES `onClosed` — so a
|
|
578
|
+
teardown that re-entered through it would call itself until the stack ran out. The close is
|
|
579
|
+
made HERE and not left to the platform: a `close` the flow did not ask for (Escape, or the
|
|
580
|
+
Close button) must also take the document out of the dialog layer, or the surface outlives
|
|
581
|
+
the dialog it drew. */
|
|
582
|
+
let closing = false;
|
|
583
|
+
_surface = openPreferencesSurface({
|
|
584
|
+
layer: layerHost("dialog"),
|
|
585
|
+
onAccountAction: runAccountAction,
|
|
586
|
+
onCaptureKey: onKeyboardKeyDown,
|
|
587
|
+
onClosed: () => {
|
|
588
|
+
if (closing) {
|
|
589
|
+
return;
|
|
527
590
|
}
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
591
|
+
closing = true;
|
|
592
|
+
const handle = _surface;
|
|
593
|
+
_surface = null;
|
|
594
|
+
_managedSlot = null;
|
|
595
|
+
_credsSlot = null;
|
|
596
|
+
handle?.close();
|
|
597
|
+
resolve(null);
|
|
598
|
+
},
|
|
599
|
+
onIsland: islandCreated,
|
|
600
|
+
onKeyQuery: setKeyQuery,
|
|
601
|
+
onResetBinding: resetBinding,
|
|
602
|
+
onSelectSection: selectSection,
|
|
603
|
+
onSetTheme: setTheme,
|
|
604
|
+
onShowConflict: showConflict,
|
|
605
|
+
onToggleKeystroke: toggleKeystroke,
|
|
606
|
+
onToggleRebind: toggleRebind,
|
|
607
|
+
view: view(),
|
|
608
|
+
});
|
|
609
|
+
});
|
|
533
610
|
}
|
|
534
611
|
|
|
535
612
|
/** Close Preferences if it is open. Tests, and the shell teardown. */
|
|
536
613
|
export function closePreferences(): void {
|
|
537
|
-
|
|
614
|
+
_surface?.close();
|
|
538
615
|
}
|
|
539
616
|
|
|
540
617
|
// ─── Command ──────────────────────────────────────────────────────────────────
|