@jxsuite/studio 4.1.0 → 5.1.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-n6tfwnda.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-qwkm9zrf.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-vj72gqtq.js +20 -0
- package/dist/chunks/content-source-5mex4x1h.js +46 -0
- package/dist/chunks/convert-to-repeater-n64h8znc.js +639 -0
- package/dist/chunks/dialog-s890b918.js +85 -0
- package/dist/chunks/editor-3qhbg51x.js +35 -0
- package/dist/chunks/entry-commands-234hjnqw.js +42 -0
- package/dist/chunks/extension-sections-3hpcambp.js +651 -0
- package/dist/chunks/file-ops-8yhd83xr.js +47 -0
- package/dist/chunks/files-hnxqxtsg.js +72 -0
- package/dist/chunks/format-host-779sfp2n.js +40 -0
- package/dist/chunks/fs-events-b88z7g4h.js +18 -0
- package/dist/chunks/git-panel-xwj8fpab.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-syr0f9sb.js +115 -0
- package/dist/chunks/{index-wcnt3r9g.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-ff81wthn.js +30 -0
- package/dist/chunks/layers-panel-pnnghw12.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-cqhhxhhe.js +33 -0
- package/dist/chunks/menu-9p2w46gj.js +15 -0
- package/dist/chunks/menu-q99sy9rf.js +285 -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-vx9bhp1d.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-5zt840sy.js +27 -0
- package/dist/chunks/quick-search-3748564r.js +45 -0
- package/dist/chunks/references-qvvxej7h.js +26 -0
- package/dist/chunks/right-panel-eccz92qt.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-kryvsw6j.js → studio-1k325pwf.js} +48 -48
- package/dist/chunks/{studio-b55y6ewx.js → studio-1knfqgy7.js} +58 -58
- package/dist/chunks/{studio-2b946z26.js → studio-1z1kcjv4.js} +3628 -6095
- package/dist/chunks/studio-3773086z.js +111 -0
- package/dist/chunks/{studio-4r1pv6zf.js → studio-38emantv.js} +22 -5
- package/dist/chunks/{studio-x813zp48.js → studio-3rz5md06.js} +30 -30
- package/dist/chunks/{studio-ynxwkrzd.js → studio-4wbb9ct0.js} +1953 -1785
- package/dist/chunks/studio-5te5tqng.js +81 -0
- package/dist/chunks/studio-5wt9nvhd.js +4763 -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-gcye7qka.js → studio-7e11jpa9.js} +21 -21
- package/dist/chunks/{studio-q7v10cg2.js → studio-7r42c6ca.js} +17 -7
- package/dist/chunks/studio-7xnmgv66.js +13615 -0
- package/dist/chunks/studio-8scdew0e.js +258 -0
- package/dist/chunks/{studio-fbf92ckf.js → studio-93zafjcm.js} +275 -163
- package/dist/chunks/{studio-dg7zyt5x.js → studio-98b3z07n.js} +1 -1
- package/dist/chunks/studio-a79k90n9.js +1162 -0
- package/dist/chunks/studio-aj37eer3.js +422 -0
- package/dist/chunks/studio-b0k5tqgp.js +2432 -0
- package/dist/chunks/studio-b4s9eykd.js +2811 -0
- package/dist/chunks/{studio-f3wqjtk5.js → studio-d0300636.js} +5076 -18
- package/dist/chunks/{studio-b9b6t1dg.js → studio-e1f24eff.js} +5664 -5666
- package/dist/chunks/studio-e1pgga3k.js +839 -0
- package/dist/chunks/{studio-g1wdche0.js → studio-esrxgwh6.js} +80 -80
- package/dist/chunks/{studio-q43a5y9h.js → studio-g3jevyjt.js} +16 -16
- package/dist/chunks/studio-gb13095a.js +2806 -0
- package/dist/chunks/{studio-3n4ndrzh.js → studio-h4nvnjvz.js} +303 -303
- package/dist/chunks/{studio-dm19q43r.js → studio-hhvs4sdg.js} +10 -10
- package/dist/chunks/{studio-x4qkdat5.js → studio-js8nv53n.js} +1749 -2481
- package/dist/chunks/{studio-qjy2z9bv.js → studio-jxp12rnj.js} +32 -137
- package/dist/chunks/{studio-trxrabqf.js → studio-k75n7vhp.js} +527 -283
- package/dist/chunks/{studio-q9jd1a60.js → studio-kcgff4r0.js} +15 -18
- package/dist/chunks/studio-kkqkcp3d.js +17668 -0
- package/dist/chunks/studio-mhhyamxf.js +763 -0
- package/dist/chunks/{studio-cft9r4r7.js → studio-nq5yf5mp.js} +22 -22
- package/dist/chunks/{studio-685s0ytq.js → studio-nqgawfks.js} +572 -572
- package/dist/chunks/studio-nzzpvzx9.js +185 -0
- package/dist/chunks/{studio-xrapxwwc.js → studio-p1dw8wfw.js} +55 -29
- package/dist/chunks/{studio-3bqpr0zh.js → studio-pxbgypmg.js} +299 -110
- package/dist/chunks/studio-q0a3yk4n.js +33 -0
- package/dist/chunks/{studio-wcy8trfx.js → studio-q3x06vmj.js} +23 -22
- package/dist/chunks/{studio-6yw4y3my.js → studio-qhhm6hbt.js} +8 -8
- package/dist/chunks/studio-qk4bfsq2.js +362 -0
- package/dist/chunks/{studio-msd847zn.js → studio-qk90fgqm.js} +361 -90
- package/dist/chunks/{studio-jkftxyvz.js → studio-r6nvacqs.js} +5861 -2154
- package/dist/chunks/{studio-53n8bp04.js → studio-r6xmmtfh.js} +1 -1
- package/dist/chunks/{studio-tvgyw9xw.js → studio-rnyf3f8e.js} +83 -250
- package/dist/chunks/studio-rs76k67r.js +12 -0
- package/dist/chunks/studio-sbjyc8bt.js +954 -0
- package/dist/chunks/{studio-1wagb550.js → studio-syg2tadj.js} +11 -11
- package/dist/chunks/{studio-t5wqwzdh.js → studio-tjjk7jvk.js} +1 -1
- package/dist/chunks/studio-tqgryxwg.js +1171 -0
- package/dist/chunks/studio-try13h8c.js +8448 -0
- package/dist/chunks/studio-vfq8qpjt.js +1219 -0
- package/dist/chunks/studio-vhv5tgxm.js +51 -0
- package/dist/chunks/{studio-ahn3pdgx.js → studio-vw7mzp6z.js} +52 -38
- package/dist/chunks/studio-wqpngpsk.js +174 -0
- package/dist/chunks/studio-wqz6dggm.js +1356 -0
- package/dist/chunks/{studio-92ab2jqe.js → studio-y9zedyjn.js} +14 -14
- package/dist/chunks/studio-yxa81f45.js +12 -0
- package/dist/chunks/studio-zdn2g6dt.js +148 -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-t55jdjbx.js +69 -0
- package/dist/chunks/{ws-client-6shc5rze.js → ws-client-ny4zc51r.js} +20 -22
- package/dist/iframe-entry.js +1873 -673
- package/dist/studio.js +52757 -36535
- 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/index.html +1 -0
- package/package.json +18 -52
- package/src/about/about-modal.ts +72 -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 +333 -113
- 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 +404 -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 +177 -10
- package/src/commands/run-reported.ts +120 -0
- 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 +76 -49
- package/src/editor/slash-menu.ts +150 -157
- package/src/files/components.ts +39 -0
- package/src/files/file-ops.ts +117 -11
- package/src/files/files.ts +944 -660
- package/src/files/json-layout.ts +474 -0
- 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/layout.ts +2 -0
- package/src/i18n/i18n-commands.ts +137 -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 +181 -252
- package/src/new-project/location-fields.ts +93 -160
- package/src/new-project/new-project-modal.ts +376 -367
- package/src/packages/jxsuite-update.ts +76 -18
- package/src/packages/pull-package-sync.ts +5 -1
- 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 -163
- package/src/panels/ai-chat/sessions-view.ts +31 -62
- package/src/panels/ai-panel.ts +213 -185
- package/src/panels/block-action-bar.ts +444 -645
- 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 +148 -135
- package/src/panels/imports-panel.ts +388 -414
- package/src/panels/jump-bar.ts +175 -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 +181 -99
- package/src/panels/properties-panel.ts +1525 -966
- package/src/panels/provenance.ts +31 -113
- package/src/panels/quick-search.ts +223 -184
- package/src/panels/right-panel.ts +135 -169
- package/src/panels/seo-modal.ts +346 -167
- package/src/panels/settings-menu.ts +114 -661
- 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 +386 -288
- package/src/platforms/cloud.ts +106 -16
- 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 +134 -328
- package/src/services/a11y-report.ts +100 -43
- package/src/services/ai-command-tools.ts +538 -0
- package/src/services/ai-project-tools.ts +8 -2
- package/src/services/ai-session-store.ts +6 -0
- package/src/services/ai-system-prompt.ts +112 -24
- package/src/services/ai-tools.ts +36 -212
- package/src/services/ai-write-report.ts +174 -0
- package/src/services/document-assistant.ts +59 -8
- 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 +6 -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 +1 -1
- package/src/settings/preferences-dialog.ts +350 -330
- 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 +104 -69
- 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 +985 -0
- package/src/{panels/toolbar.ts → surfaces/commandbar.ts} +417 -391
- 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 +164 -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 +111 -21
- package/src/tabs/tab.ts +52 -1
- package/src/types.ts +22 -0
- package/src/ui/ai-credentials-form.ts +104 -100
- package/src/ui/ai-managed-connect.ts +54 -36
- package/src/ui/ai-model-picker.ts +75 -47
- package/src/ui/cf-account-picker.ts +76 -141
- 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 +296 -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 +75 -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 -1568
- package/styles/tokens.css +65 -136
- package/styles/tokens.json +84 -0
- package/dist/chunks/Overlay.dev-etqjwyf9.js +0 -23
- package/dist/chunks/adapter-jkcyhgtr.js +0 -14
- package/dist/chunks/cf-account-picker-en86v7x7.js +0 -163
- package/dist/chunks/cf-settings-45fgyx8y.js +0 -21
- package/dist/chunks/components-zmx10t62.js +0 -21
- package/dist/chunks/content-source-48xg86wj.js +0 -49
- package/dist/chunks/convert-to-repeater-43tfn7cs.js +0 -268
- package/dist/chunks/editor-cptq5jp1.js +0 -37
- package/dist/chunks/entry-commands-e63f1xc0.js +0 -46
- package/dist/chunks/extension-sections-txv08xxg.js +0 -311
- package/dist/chunks/file-ops-wbh4hhsx.js +0 -48
- package/dist/chunks/files-3kfkwhk4.js +0 -93
- package/dist/chunks/flow-qbfgrpeh.js +0 -634
- package/dist/chunks/focus-trap.esm-9t2drp0g.js +0 -1025
- package/dist/chunks/focus-visible-6eg70z18.js +0 -167
- package/dist/chunks/format-host-w16q81tf.js +0 -43
- package/dist/chunks/fs-events-hrrg328g.js +0 -21
- package/dist/chunks/git-panel-532whr1y.js +0 -59
- package/dist/chunks/index-zqxmqxmh.js +0 -109
- package/dist/chunks/jx-validate-8er6gbxy.js +0 -19
- package/dist/chunks/layers-panel-07hm7g5j.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-v9st96ja.js +0 -29
- package/dist/chunks/quick-search-zccjp6gv.js +0 -66
- package/dist/chunks/references-3qx8fkyp.js +0 -29
- package/dist/chunks/right-panel-vm3b6kwy.js +0 -46
- package/dist/chunks/section-registry-sx1ykvkw.js +0 -30
- package/dist/chunks/sp-overlay.dev-qgvhnxf4.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-4sastdnw.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-0bq6eh7v.js +0 -12
- package/dist/chunks/studio-18j3bmcz.js +0 -14
- package/dist/chunks/studio-1ngbejft.js +0 -181
- package/dist/chunks/studio-4b5z1x43.js +0 -424
- package/dist/chunks/studio-4n2b5gzb.js +0 -357
- package/dist/chunks/studio-4rzyrtjz.js +0 -426
- package/dist/chunks/studio-5fx3g9jg.js +0 -4325
- package/dist/chunks/studio-5myknm0a.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-950k0dx6.js +0 -6939
- package/dist/chunks/studio-9n4mrmnb.js +0 -184
- package/dist/chunks/studio-a0tswy0w.js +0 -58
- package/dist/chunks/studio-ahnzd9rg.js +0 -23
- package/dist/chunks/studio-bgxt93ga.js +0 -62
- package/dist/chunks/studio-cmb03bg5.js +0 -13890
- package/dist/chunks/studio-d1ks410h.js +0 -175
- package/dist/chunks/studio-ef49pnzx.js +0 -387
- package/dist/chunks/studio-eqq1w638.js +0 -113
- package/dist/chunks/studio-ew0djmhg.js +0 -341
- package/dist/chunks/studio-gfgb8pe6.js +0 -1652
- package/dist/chunks/studio-h4rxscfc.js +0 -10
- package/dist/chunks/studio-jc994dnr.js +0 -1066
- package/dist/chunks/studio-kyh9avvv.js +0 -28
- package/dist/chunks/studio-m3hwn7y1.js +0 -120
- package/dist/chunks/studio-mtfnaqs9.js +0 -659
- package/dist/chunks/studio-n6j9t10q.js +0 -318
- package/dist/chunks/studio-n8b9wqwy.js +0 -291
- package/dist/chunks/studio-qcy05dp8.js +0 -1743
- package/dist/chunks/studio-qq6jym04.js +0 -53
- 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-z6nw2ek2.js +0 -18
- package/dist/chunks/studio-zczps70q.js +0 -378
- package/dist/chunks/studio-zqazsct2.js +0 -1823
- package/dist/chunks/workspace-fjx52ryv.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,14 +25,24 @@
|
|
|
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";
|
|
@@ -48,13 +58,21 @@ import {
|
|
|
48
58
|
revokeAccount,
|
|
49
59
|
} from "./preferences-accounts";
|
|
50
60
|
import { applyKeybindingOverrides, rebindCommand, resetKeybinding } from "./preferences-keymap";
|
|
51
|
-
import {
|
|
61
|
+
import { openPreferencesSurface } from "../surfaces/preferences";
|
|
52
62
|
|
|
53
|
-
import type { TemplateResult } from "lit-html";
|
|
54
63
|
import type { ChromeTheme } from "../shell";
|
|
55
64
|
import type { ShortcutRow } from "../commands/reference";
|
|
56
65
|
import type { RebindResult } from "./preferences-keymap";
|
|
57
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";
|
|
58
76
|
|
|
59
77
|
/*
|
|
60
78
|
* The sections moved to `./preferences-sections`, a leaf with no imports, so the rail's gear menu
|
|
@@ -79,15 +97,12 @@ export type { PreferencesSection } from "./preferences-sections";
|
|
|
79
97
|
|
|
80
98
|
let _section = DEFAULT_PREFERENCES_SECTION;
|
|
81
99
|
|
|
82
|
-
/**
|
|
83
|
-
let
|
|
84
|
-
|
|
85
|
-
/** Dismiss the open sheet, if one is up. */
|
|
86
|
-
let _close: (() => void) | null = null;
|
|
100
|
+
/** The mounted sheet, or `null` while none is up. */
|
|
101
|
+
let _surface: PreferencesSurfaceHandle | null = null;
|
|
87
102
|
|
|
88
103
|
/** Whether Preferences is on screen. */
|
|
89
104
|
export function isPreferencesOpen(): boolean {
|
|
90
|
-
return
|
|
105
|
+
return _surface !== null;
|
|
91
106
|
}
|
|
92
107
|
|
|
93
108
|
/** The section currently showing. Exposed for tests and for the `app.preferences` round-trip. */
|
|
@@ -96,7 +111,8 @@ export function preferencesSection(): string {
|
|
|
96
111
|
}
|
|
97
112
|
|
|
98
113
|
function repaint(): void {
|
|
99
|
-
|
|
114
|
+
_surface?.update(view());
|
|
115
|
+
fillIslands();
|
|
100
116
|
}
|
|
101
117
|
|
|
102
118
|
/** Save/revoke both change what other surfaces show, so they announce as well as repaint. */
|
|
@@ -120,10 +136,10 @@ function sectionShown(): void {
|
|
|
120
136
|
|
|
121
137
|
/** The shared credentials form — draft state lives inside the form's closure. */
|
|
122
138
|
const credsForm = createAiCredentialsForm({
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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).",
|
|
127
143
|
// Both buttons keep the sheet open: Preferences is a place, not a wizard step, and the previous
|
|
128
144
|
// Dialog's habit of vanishing on Save is what made "did that take?" unanswerable.
|
|
129
145
|
onCancel: repaint,
|
|
@@ -134,98 +150,157 @@ const credsForm = createAiCredentialsForm({
|
|
|
134
150
|
/** Shared with the New Project modal's gates — see ui/ai-managed-connect.ts. */
|
|
135
151
|
const managedConnect = createManagedConnect({ requestRender: credentialsChanged });
|
|
136
152
|
|
|
137
|
-
// ───
|
|
153
|
+
// ─── The Assistant islands ────────────────────────────────────────────────────
|
|
138
154
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
@click=${() => {
|
|
150
|
-
setChromeTheme(theme as ChromeTheme);
|
|
151
|
-
repaint();
|
|
152
|
-
}}
|
|
153
|
-
>
|
|
154
|
-
${theme === "dark" ? "Dark" : "Light"}
|
|
155
|
-
</sp-action-button>
|
|
156
|
-
`,
|
|
157
|
-
)}
|
|
158
|
-
</sp-action-group>
|
|
159
|
-
</div>
|
|
160
|
-
`;
|
|
161
|
-
}
|
|
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;
|
|
162
165
|
|
|
163
|
-
|
|
164
|
-
|
|
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();
|
|
166
174
|
}
|
|
167
175
|
|
|
168
176
|
/**
|
|
169
|
-
*
|
|
177
|
+
* Put each controller's element in its slot, and bring both up to date.
|
|
170
178
|
*
|
|
171
|
-
*
|
|
172
|
-
* a
|
|
173
|
-
*
|
|
174
|
-
* and the row must not still be reading "expired" when it comes back.
|
|
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.
|
|
175
182
|
*/
|
|
176
|
-
function
|
|
177
|
-
if (
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
@click=${() => {
|
|
186
|
-
void Promise.resolve(action.run()).finally(repaint);
|
|
187
|
-
}}
|
|
188
|
-
>
|
|
189
|
-
${action.label}
|
|
190
|
-
</sp-button>
|
|
191
|
-
`,
|
|
192
|
-
);
|
|
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
|
+
}
|
|
193
192
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
:
|
|
193
|
+
if (_credsSlot) {
|
|
194
|
+
const element = credsForm.render();
|
|
195
|
+
if (element.parentNode !== _credsSlot) {
|
|
196
|
+
_credsSlot.replaceChildren(element);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// ─── Sections ─────────────────────────────────────────────────────────────────
|
|
202
|
+
|
|
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
|
+
}));
|
|
209
210
|
}
|
|
210
211
|
|
|
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();
|
|
234
|
+
}
|
|
235
|
+
|
|
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[] {
|
|
212
254
|
// First paint asks the broker what it holds; the answer arrives as a credentials-changed repaint.
|
|
213
255
|
ensureCfConnection();
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
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;
|
|
290
|
+
}
|
|
291
|
+
|
|
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);
|
|
229
304
|
}
|
|
230
305
|
|
|
231
306
|
// ─── Keyboard ─────────────────────────────────────────────────────────────────
|
|
@@ -239,8 +314,15 @@ function accountsTpl(): TemplateResult {
|
|
|
239
314
|
*/
|
|
240
315
|
type KeyFilter = { kind: "text"; value: string } | { kind: "chord"; chord: string } | null;
|
|
241
316
|
|
|
242
|
-
/**
|
|
243
|
-
|
|
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;
|
|
244
326
|
|
|
245
327
|
/** Keydowns that are not a chord yet: a modifier held on its way to one. */
|
|
246
328
|
const MODIFIER_KEYS = new Set(["Meta", "Control", "Alt", "Shift", "CapsLock", "OS"]);
|
|
@@ -303,96 +385,87 @@ function onKeyboardKeyDown(event: KeyboardEvent): void {
|
|
|
303
385
|
_keyFilter = { kind: "chord", chord };
|
|
304
386
|
_keyRefusal = null;
|
|
305
387
|
} else {
|
|
306
|
-
const
|
|
307
|
-
|
|
388
|
+
const command = commandById(registry, capture.commandId);
|
|
389
|
+
if (command) {
|
|
390
|
+
const result = rebindCommand(registry, command, chord);
|
|
391
|
+
_keyRefusal = result.ok ? null : result;
|
|
392
|
+
}
|
|
308
393
|
}
|
|
309
394
|
repaint();
|
|
310
395
|
}
|
|
311
396
|
|
|
312
|
-
/** The
|
|
313
|
-
function
|
|
314
|
-
|
|
315
|
-
|
|
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);
|
|
316
422
|
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
<div class="prefs-field">
|
|
320
|
-
<sp-help-text variant="negative">${_keyRefusal.reason}</sp-help-text>
|
|
321
|
-
${
|
|
322
|
-
conflict
|
|
323
|
-
? html`
|
|
324
|
-
<sp-button
|
|
325
|
-
size="s"
|
|
326
|
-
treatment="outline"
|
|
327
|
-
@click=${() => {
|
|
328
|
-
_keyFilter = { kind: "text", value: conflict.title };
|
|
329
|
-
_keyRefusal = null;
|
|
330
|
-
repaint();
|
|
331
|
-
}}
|
|
332
|
-
>
|
|
333
|
-
Show ${conflict.title}
|
|
334
|
-
</sp-button>
|
|
335
|
-
`
|
|
336
|
-
: nothing
|
|
337
|
-
}
|
|
338
|
-
</div>
|
|
339
|
-
`;
|
|
423
|
+
_keyRefusal = null;
|
|
424
|
+
repaint();
|
|
340
425
|
}
|
|
341
426
|
|
|
342
|
-
/**
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
${capturing ? "Press a shortcut…" : registry.keymap.format(row.chord)}
|
|
359
|
-
</kbd>
|
|
360
|
-
<span class="prefs-key-title">${row.title}${row.overridden ? " — changed" : ""}</span>
|
|
361
|
-
<sp-action-button
|
|
362
|
-
size="s"
|
|
363
|
-
quiet
|
|
364
|
-
?selected=${capturing}
|
|
365
|
-
aria-label=${capturing ? `Stop changing ${row.title}` : `Change the shortcut for ${row.title}`}
|
|
366
|
-
@click=${() => {
|
|
367
|
-
_keyCapture = capturing ? null : { mode: "rebind", command };
|
|
368
|
-
_keyRefusal = null;
|
|
369
|
-
repaint();
|
|
370
|
-
}}
|
|
371
|
-
>
|
|
372
|
-
${capturing ? "Cancel" : "Change"}
|
|
373
|
-
</sp-action-button>
|
|
374
|
-
${
|
|
375
|
-
row.overridden
|
|
376
|
-
? html`
|
|
377
|
-
<sp-action-button
|
|
378
|
-
size="s"
|
|
379
|
-
quiet
|
|
380
|
-
aria-label=${`Reset the shortcut for ${row.title}`}
|
|
381
|
-
@click=${() => {
|
|
382
|
-
resetKeybinding(registry, row.commandId);
|
|
383
|
-
_keyRefusal = null;
|
|
384
|
-
repaint();
|
|
385
|
-
}}
|
|
386
|
-
>
|
|
387
|
-
Reset
|
|
388
|
-
</sp-action-button>
|
|
389
|
-
`
|
|
390
|
-
: nothing
|
|
391
|
-
}
|
|
392
|
-
</div>
|
|
393
|
-
`;
|
|
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();
|
|
436
|
+
}
|
|
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();
|
|
394
443
|
}
|
|
395
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
|
+
|
|
396
469
|
/**
|
|
397
470
|
* The keyboard sheet — every live binding, grouped by the scope it is live in.
|
|
398
471
|
*
|
|
@@ -401,94 +474,80 @@ function keyRowTpl(
|
|
|
401
474
|
* the same projection rather than patched into its output.
|
|
402
475
|
*
|
|
403
476
|
* A command that declares two chords has two rows and rebinding either one leaves it with one — a
|
|
404
|
-
* 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.
|
|
405
479
|
*/
|
|
406
|
-
function
|
|
480
|
+
function keyboardView(): KeyboardView {
|
|
407
481
|
const registry = activeRegistry();
|
|
408
482
|
const commands: readonly AnyCommand[] = registry ? [...registry.list()] : [];
|
|
409
483
|
const rows = registry ? shortcutReference(commands, registry.keymap.overrides()) : [];
|
|
410
484
|
if (!registry || rows.length === 0) {
|
|
411
|
-
return
|
|
485
|
+
return { ...KEYBOARD_IDLE, keyboardEmpty: "No commands are registered in this window." };
|
|
412
486
|
}
|
|
413
487
|
const format = (chord: string) => registry.keymap.format(chord);
|
|
414
|
-
const
|
|
415
|
-
const visible = rows.
|
|
416
|
-
const command = byId.get(row.commandId);
|
|
417
|
-
return command && keyRowMatches(row, format) ? [{ command, row }] : [];
|
|
418
|
-
});
|
|
419
|
-
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));
|
|
420
490
|
const capturingSearch = _keyCapture?.mode === "search";
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
<sp-action-button
|
|
443
|
-
size="s"
|
|
444
|
-
?selected=${capturingSearch}
|
|
445
|
-
@click=${() => {
|
|
446
|
-
_keyCapture = capturingSearch ? null : { mode: "search" };
|
|
447
|
-
_keyRefusal = null;
|
|
448
|
-
repaint();
|
|
449
|
-
}}
|
|
450
|
-
>
|
|
451
|
-
${capturingSearch ? "Press it now" : "Search by keystroke"}
|
|
452
|
-
</sp-action-button>
|
|
453
|
-
</div>
|
|
454
|
-
${keyRefusalTpl()}
|
|
455
|
-
${
|
|
456
|
-
visible.length === 0
|
|
457
|
-
? html`<p class="prefs-empty">
|
|
458
|
-
${
|
|
459
|
-
_keyFilter?.kind === "chord"
|
|
460
|
-
? `Nothing is bound to ${format(_keyFilter.chord)}.`
|
|
461
|
-
: "No shortcut matches that."
|
|
462
|
-
}
|
|
463
|
-
</p>`
|
|
464
|
-
: scopes.map(
|
|
465
|
-
(scope) => html`
|
|
466
|
-
<h4 class="prefs-keys-scope">${SCOPE_LABELS[scope]}</h4>
|
|
467
|
-
${visible
|
|
468
|
-
.filter(({ row }) => row.scope === scope)
|
|
469
|
-
.map(({ command, row }) => keyRowTpl(row, command, registry))}
|
|
470
|
-
`,
|
|
471
|
-
)
|
|
472
|
-
}
|
|
473
|
-
</div>
|
|
474
|
-
`;
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
function sectionBodyTpl(): TemplateResult {
|
|
478
|
-
if (_section === "assistant") {
|
|
479
|
-
return assistantTpl();
|
|
480
|
-
}
|
|
481
|
-
if (_section === "accounts") {
|
|
482
|
-
return accountsTpl();
|
|
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
|
+
});
|
|
483
512
|
}
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
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
|
+
};
|
|
488
533
|
}
|
|
489
534
|
|
|
490
535
|
// ─── The sheet ────────────────────────────────────────────────────────────────
|
|
491
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
|
+
|
|
492
551
|
/**
|
|
493
552
|
* Open Preferences, optionally on a named section. Resolves when it is dismissed.
|
|
494
553
|
*
|
|
@@ -504,7 +563,7 @@ export function openPreferences(section?: string): Promise<null> {
|
|
|
504
563
|
something it has no reason to believe. */
|
|
505
564
|
resetCfConnectionCache();
|
|
506
565
|
_section = section !== undefined && isPreferencesSection(section) ? section : _section;
|
|
507
|
-
if (
|
|
566
|
+
if (_surface) {
|
|
508
567
|
repaint();
|
|
509
568
|
sectionShown();
|
|
510
569
|
return Promise.resolve(null);
|
|
@@ -514,84 +573,45 @@ export function openPreferences(section?: string): Promise<null> {
|
|
|
514
573
|
credsForm.startEdit();
|
|
515
574
|
resetKeyboardState();
|
|
516
575
|
sectionShown();
|
|
517
|
-
return
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
open
|
|
532
|
-
underlay
|
|
533
|
-
headline="Preferences"
|
|
534
|
-
cancel-label="Close"
|
|
535
|
-
size="l"
|
|
536
|
-
@cancel=${finish}
|
|
537
|
-
@close=${finish}
|
|
538
|
-
${ref((el?: Element) => {
|
|
539
|
-
if (el) {
|
|
540
|
-
wrapperEl = el as HTMLElement;
|
|
541
|
-
}
|
|
542
|
-
})}
|
|
543
|
-
>
|
|
544
|
-
<div class="prefs-sheet">
|
|
545
|
-
<nav class="prefs-nav" aria-label="Preferences sections">
|
|
546
|
-
${PREFERENCES_SECTIONS.map(
|
|
547
|
-
(candidate) => html`
|
|
548
|
-
<button
|
|
549
|
-
type="button"
|
|
550
|
-
class="prefs-nav-item ${candidate.id === _section ? "active" : ""}"
|
|
551
|
-
aria-current=${candidate.id === _section ? "true" : "false"}
|
|
552
|
-
@click=${() => {
|
|
553
|
-
_section = candidate.id;
|
|
554
|
-
// Leaving a section abandons what it was in the middle of: an armed key
|
|
555
|
-
// Capture whose listener is no longer mounted would otherwise swallow the
|
|
556
|
-
// First chord pressed on the author's NEXT visit.
|
|
557
|
-
resetKeyboardState();
|
|
558
|
-
repaint();
|
|
559
|
-
sectionShown();
|
|
560
|
-
}}
|
|
561
|
-
>
|
|
562
|
-
${candidate.title}
|
|
563
|
-
</button>
|
|
564
|
-
`,
|
|
565
|
-
)}
|
|
566
|
-
</nav>
|
|
567
|
-
<section class="prefs-body">
|
|
568
|
-
<h3 class="prefs-title">${active?.title ?? ""}</h3>
|
|
569
|
-
<p class="prefs-blurb">${active?.blurb ?? ""}</p>
|
|
570
|
-
${sectionBodyTpl()}
|
|
571
|
-
</section>
|
|
572
|
-
</div>
|
|
573
|
-
</sp-dialog-wrapper>
|
|
574
|
-
`;
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
_close = finish;
|
|
578
|
-
_rerender = () => {
|
|
579
|
-
// Resolved lazily: lit commits element refs before inserting the fragment, so the slot the
|
|
580
|
-
// Sheet was rendered into is only reachable once the first render has landed.
|
|
581
|
-
const host = wrapperEl?.parentElement;
|
|
582
|
-
if (host) {
|
|
583
|
-
litRender(build(), host);
|
|
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;
|
|
584
590
|
}
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
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
|
+
});
|
|
590
610
|
}
|
|
591
611
|
|
|
592
612
|
/** Close Preferences if it is open. Tests, and the shell teardown. */
|
|
593
613
|
export function closePreferences(): void {
|
|
594
|
-
|
|
614
|
+
_surface?.close();
|
|
595
615
|
}
|
|
596
616
|
|
|
597
617
|
// ─── Command ──────────────────────────────────────────────────────────────────
|