@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
|
@@ -12,38 +12,50 @@
|
|
|
12
12
|
* of the same merge is how the command and the form would come to disagree about what happens to
|
|
13
13
|
* `defaultLocale` when the first locale is added.
|
|
14
14
|
*
|
|
15
|
+
* **The form is a document.** The markup and the styling are `surfaces/settings-locales.json`, its
|
|
16
|
+
* mount is `surfaces/settings-locales.ts`, and what is left here is the part that was always this
|
|
17
|
+
* module's: what the file says, what a tag is allowed to be, and what each edit writes back. The
|
|
18
|
+
* section renderer is still `renderLocalesSection`, because a section is a contribution to
|
|
19
|
+
* CONFIGURATION and the registry's seam does not move when the substrate under it does.
|
|
20
|
+
*
|
|
15
21
|
* @docs studio/projects/settings
|
|
16
22
|
*/
|
|
17
23
|
|
|
18
|
-
import { html, render as litRender, nothing } from "lit-html";
|
|
19
24
|
import { canonicalizeLocale, isWellFormedLocale, localeLabel } from "@jxsuite/schema/locale";
|
|
20
25
|
import { errorMessage } from "@jxsuite/schema/parse";
|
|
21
26
|
import { notify } from "../services/notify";
|
|
22
27
|
import { projectState } from "../store";
|
|
28
|
+
import { renderLocalesSurface } from "../surfaces/settings-locales";
|
|
23
29
|
import { updateSiteConfig } from "../site-context";
|
|
30
|
+
import type { LocalesActions, LocalesView } from "../surfaces/settings-locales";
|
|
24
31
|
import type { LocaleRouting } from "@jxsuite/schema/locale";
|
|
25
32
|
import type { ProjectConfig } from "@jxsuite/schema/types";
|
|
26
33
|
|
|
27
34
|
/**
|
|
28
|
-
* The
|
|
35
|
+
* The form beside the file: the tag being typed, and the last write that failed.
|
|
29
36
|
*
|
|
30
|
-
* Keyed by container so two mounted copies (and two tests) never share
|
|
31
|
-
* `project-sections.ts` and `general-settings.ts` use, and for the same
|
|
32
|
-
* on change, so a silent rejection would read as "my edit just
|
|
37
|
+
* Keyed by container so two mounted copies (and two tests) never share either — the same shape
|
|
38
|
+
* `project-sections.ts` and `general-settings.ts` use for their own errors, and for the same
|
|
39
|
+
* reason: these sections save on change, so a silent rejection would read as "my edit just
|
|
40
|
+
* vanished". The pending tag is here rather than in the document because typing must survive the
|
|
41
|
+
* section being redrawn from outside — a nav click, an extension registering — and a document that
|
|
42
|
+
* remounts is a field that empties.
|
|
33
43
|
*/
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
function clearError(container: HTMLElement): void {
|
|
38
|
-
errors.delete(container);
|
|
44
|
+
interface Form {
|
|
45
|
+
pending: string;
|
|
46
|
+
error: string;
|
|
39
47
|
}
|
|
40
48
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
49
|
+
const forms = new WeakMap<HTMLElement, Form>();
|
|
50
|
+
|
|
51
|
+
/** This container's form, minted on first sight. */
|
|
52
|
+
function form(container: HTMLElement): Form {
|
|
53
|
+
let state = forms.get(container);
|
|
54
|
+
if (!state) {
|
|
55
|
+
state = { error: "", pending: "" };
|
|
56
|
+
forms.set(container, state);
|
|
57
|
+
}
|
|
58
|
+
return state;
|
|
47
59
|
}
|
|
48
60
|
|
|
49
61
|
/**
|
|
@@ -56,20 +68,15 @@ function errorLine(container: HTMLElement) {
|
|
|
56
68
|
*
|
|
57
69
|
* @param {HTMLElement} container
|
|
58
70
|
* @param {Partial<ProjectConfig>} patch
|
|
59
|
-
* @param {() => void} rerender
|
|
60
71
|
*/
|
|
61
|
-
async function persist(
|
|
62
|
-
container: HTMLElement,
|
|
63
|
-
patch: Partial<ProjectConfig>,
|
|
64
|
-
rerender: () => void,
|
|
65
|
-
): Promise<void> {
|
|
72
|
+
async function persist(container: HTMLElement, patch: Partial<ProjectConfig>): Promise<void> {
|
|
66
73
|
try {
|
|
67
74
|
await updateSiteConfig(patch);
|
|
68
|
-
|
|
75
|
+
form(container).error = "";
|
|
69
76
|
} catch (error) {
|
|
70
|
-
|
|
77
|
+
form(container).error = `Could not save project.json — ${errorMessage(error)}`;
|
|
71
78
|
}
|
|
72
|
-
|
|
79
|
+
refresh(container);
|
|
73
80
|
}
|
|
74
81
|
|
|
75
82
|
/** The live project configuration, or an empty one before a project is open. */
|
|
@@ -121,14 +128,23 @@ function alreadyDeclared(tag: string): boolean {
|
|
|
121
128
|
* added.
|
|
122
129
|
*
|
|
123
130
|
* Refusals are notified rather than thrown: the palette reports a rejected `run` to the console and
|
|
124
|
-
* nowhere else, so a thrown refusal is one the author never sees. The form
|
|
125
|
-
*
|
|
131
|
+
* nowhere else, so a thrown refusal is one the author never sees. The form refuses both of them
|
|
132
|
+
* before it gets here, with the reason under the field.
|
|
133
|
+
*
|
|
134
|
+
* **It answers whether it wrote.** The already-declared case is decided HERE, against the raw
|
|
135
|
+
* `locales` the author wrote — not against the resolved list, which unshifts a `defaultLocale` the
|
|
136
|
+
* array does not hold — and `i18n.addLocale`'s report has to tell the model the same thing this
|
|
137
|
+
* function told the file. A second reading of "is it declared" beside the command would be a second
|
|
138
|
+
* spelling of this predicate, and the two disagreed exactly on that default: the report said
|
|
139
|
+
* "already declared" for a tag this function had just written.
|
|
126
140
|
*
|
|
127
141
|
* @param {string} tag - A BCP 47 language tag, in any case.
|
|
142
|
+
* @returns {Promise<boolean>} `true` when `project.json` was written; `false` for a refused or
|
|
143
|
+
* already-declared tag, both of which have been notified.
|
|
128
144
|
* @throws {Error} Whatever `updateSiteConfig` rejects with — the caller decides where a failed
|
|
129
145
|
* write shows.
|
|
130
146
|
*/
|
|
131
|
-
export async function addProjectLocale(tag: string): Promise<
|
|
147
|
+
export async function addProjectLocale(tag: string): Promise<boolean> {
|
|
132
148
|
const canonical = canonicalizeLocale(tag);
|
|
133
149
|
if (canonical === null) {
|
|
134
150
|
notify.error(`"${tag}" is not a well-formed language tag.`, {
|
|
@@ -137,22 +153,20 @@ export async function addProjectLocale(tag: string): Promise<void> {
|
|
|
137
153
|
"`pt-BR`, `zh-Hant`. Underscores and spaces are not part of the grammar.",
|
|
138
154
|
source: "Languages",
|
|
139
155
|
});
|
|
140
|
-
return;
|
|
156
|
+
return false;
|
|
141
157
|
}
|
|
142
158
|
if (alreadyDeclared(canonical)) {
|
|
143
159
|
notify.info(`${localeLabel(canonical)} is already one of this project's languages.`, {
|
|
144
160
|
source: "Languages",
|
|
145
161
|
});
|
|
146
|
-
return;
|
|
162
|
+
return false;
|
|
147
163
|
}
|
|
148
164
|
await updateSiteConfig({
|
|
149
165
|
i18n: { ...config().i18n, locales: [...declaredLocales(), canonical] },
|
|
150
166
|
});
|
|
167
|
+
return true;
|
|
151
168
|
}
|
|
152
169
|
|
|
153
|
-
/** Pending tag per container, so typing survives the section re-rendering. */
|
|
154
|
-
const pendingTag = new WeakMap<HTMLElement, string>();
|
|
155
|
-
|
|
156
170
|
/**
|
|
157
171
|
* Why the pending tag cannot be added, or `""` when it can.
|
|
158
172
|
*
|
|
@@ -161,7 +175,7 @@ const pendingTag = new WeakMap<HTMLElement, string>();
|
|
|
161
175
|
* happened" is what a silently refused Add looks like.
|
|
162
176
|
*/
|
|
163
177
|
function pendingRefusal(container: HTMLElement): string {
|
|
164
|
-
const tag = (
|
|
178
|
+
const tag = form(container).pending.trim();
|
|
165
179
|
if (tag === "") {
|
|
166
180
|
return "";
|
|
167
181
|
}
|
|
@@ -172,176 +186,112 @@ function pendingRefusal(container: HTMLElement): string {
|
|
|
172
186
|
}
|
|
173
187
|
|
|
174
188
|
/**
|
|
175
|
-
*
|
|
189
|
+
* What the section shows right now.
|
|
176
190
|
*
|
|
177
|
-
*
|
|
178
|
-
* a plain module binding replaced wholesale on a project switch, and an extension
|
|
179
|
-
* editor can write `i18n` between
|
|
180
|
-
*
|
|
181
|
-
* @param {HTMLElement} container
|
|
191
|
+
* Read from `config()` at the moment of drawing rather than carried from the last one:
|
|
192
|
+
* `projectState` is a plain module binding replaced wholesale on a project switch, and an extension
|
|
193
|
+
* or the raw JSON editor can write `i18n` between two of these.
|
|
182
194
|
*/
|
|
183
|
-
|
|
184
|
-
const rerender = () => renderLocalesSection(container);
|
|
195
|
+
function view(container: HTMLElement): LocalesView {
|
|
185
196
|
const locales = declaredLocales();
|
|
186
197
|
const { i18n } = config();
|
|
187
|
-
const pending =
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
container,
|
|
198
|
-
{ i18n: { ...config().i18n, locales: [...declaredLocales(), canonicalizeLocale(tag)!] } },
|
|
199
|
-
rerender,
|
|
200
|
-
);
|
|
198
|
+
const { error, pending } = form(container);
|
|
199
|
+
return {
|
|
200
|
+
defaultLocale: i18n?.defaultLocale ?? locales[0] ?? "",
|
|
201
|
+
error,
|
|
202
|
+
localeOptions: locales.map((tag) => ({ label: localeLabel(tag), value: tag })),
|
|
203
|
+
locales: locales.map((tag) => ({ label: localeLabel(tag), tag })),
|
|
204
|
+
pending,
|
|
205
|
+
refusal: pendingRefusal(container),
|
|
206
|
+
routing: i18n?.routing ?? "prefix-except-default",
|
|
207
|
+
routings: LOCALE_ROUTINGS.map((mode) => ({ label: mode.label, value: mode.value })),
|
|
201
208
|
};
|
|
209
|
+
}
|
|
202
210
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
error (`resolveI18n`: "declared with no usable locale"), so removing the last row would
|
|
208
|
-
otherwise break the build of a project that is once again ordinary and monolingual. */
|
|
209
|
-
void persist(container, CLEAR_I18N, rerender);
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
const current = config().i18n;
|
|
213
|
-
/* A `defaultLocale` naming a locale that is no longer declared does not go away — `resolveI18n`
|
|
214
|
-
puts it BACK at the head of the list, so deleting the default row without this would delete
|
|
215
|
-
nothing and reorder the rest. */
|
|
216
|
-
const orphaned =
|
|
217
|
-
current?.defaultLocale !== undefined &&
|
|
218
|
-
canonicalizeLocale(current.defaultLocale) === canonicalizeLocale(tag);
|
|
219
|
-
void persist(
|
|
220
|
-
container,
|
|
221
|
-
{ i18n: { ...current, ...(orphaned ? { defaultLocale: kept[0]! } : {}), locales: kept } },
|
|
222
|
-
rerender,
|
|
223
|
-
);
|
|
224
|
-
};
|
|
211
|
+
/** Re-read the file and the form, and let the surface reconcile. */
|
|
212
|
+
function refresh(container: HTMLElement): void {
|
|
213
|
+
renderLocalesSurface(container, view(container), actions(container));
|
|
214
|
+
}
|
|
225
215
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
216
|
+
/** Add the pending tag, if it is one this project can take. */
|
|
217
|
+
function add(container: HTMLElement): void {
|
|
218
|
+
const tag = form(container).pending.trim();
|
|
219
|
+
if (tag === "" || pendingRefusal(container) !== "") {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
form(container).pending = "";
|
|
223
|
+
void persist(container, {
|
|
224
|
+
i18n: { ...config().i18n, locales: [...declaredLocales(), canonicalizeLocale(tag)!] },
|
|
225
|
+
});
|
|
226
|
+
}
|
|
233
227
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
228
|
+
/** Drop a language, and the block itself when it was the last one. */
|
|
229
|
+
function remove(container: HTMLElement, tag: string): void {
|
|
230
|
+
const kept = declaredLocales().filter((declared) => declared !== tag);
|
|
231
|
+
if (kept.length === 0) {
|
|
232
|
+
/* The last language leaves with the block. An `i18n` holding an empty `locales` is a build
|
|
233
|
+
error (`resolveI18n`: "declared with no usable locale"), so removing the last row would
|
|
234
|
+
otherwise break the build of a project that is once again ordinary and monolingual. */
|
|
235
|
+
void persist(container, CLEAR_I18N);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
const current = config().i18n;
|
|
239
|
+
/* A `defaultLocale` naming a locale that is no longer declared does not go away — `resolveI18n`
|
|
240
|
+
puts it BACK at the head of the list, so deleting the default row without this would delete
|
|
241
|
+
nothing and reorder the rest. */
|
|
242
|
+
const orphaned =
|
|
243
|
+
current?.defaultLocale !== undefined &&
|
|
244
|
+
canonicalizeLocale(current.defaultLocale) === canonicalizeLocale(tag);
|
|
245
|
+
void persist(container, {
|
|
246
|
+
i18n: { ...current, ...(orphaned ? { defaultLocale: kept[0]! } : {}), locales: kept },
|
|
247
|
+
});
|
|
248
|
+
}
|
|
246
249
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
const before = pendingRefusal(container);
|
|
287
|
-
pendingTag.set(container, (e.target as HTMLInputElement).value);
|
|
288
|
-
/* Re-render only when the VERDICT changes, not per keystroke: redrawing on every
|
|
289
|
-
character would push `.value` back into a field the author is typing in, and
|
|
290
|
-
never redrawing would leave the refusal below it describing an older tag. */
|
|
291
|
-
if (pendingRefusal(container) !== before) {
|
|
292
|
-
rerender();
|
|
293
|
-
}
|
|
294
|
-
}}
|
|
295
|
-
@keydown=${(e: KeyboardEvent) => {
|
|
296
|
-
if (e.key === "Enter") {
|
|
297
|
-
add();
|
|
298
|
-
}
|
|
299
|
-
}}
|
|
300
|
-
></sp-textfield>
|
|
301
|
-
<sp-action-button size="s" @click=${add}>Add</sp-action-button>
|
|
302
|
-
</div>
|
|
303
|
-
</div>
|
|
304
|
-
${refusal === "" ? nothing : html`<p class="settings-field-error">${refusal}</p>`}
|
|
305
|
-
</div>
|
|
306
|
-
<div class="settings-field">
|
|
307
|
-
<label class="settings-field-label">Default Language</label>
|
|
308
|
-
<p class="settings-field-desc">
|
|
309
|
-
The language a page is written in when its file carries no locale directory.
|
|
310
|
-
</p>
|
|
311
|
-
<sp-picker
|
|
312
|
-
size="s"
|
|
313
|
-
label="Default Language"
|
|
314
|
-
class="settings-default-locale"
|
|
315
|
-
.value=${i18n?.defaultLocale ?? locales[0] ?? ""}
|
|
316
|
-
?disabled=${locales.length === 0}
|
|
317
|
-
@change=${onDefaultChange}
|
|
318
|
-
>
|
|
319
|
-
${locales.map(
|
|
320
|
-
(tag) => html`<sp-menu-item value=${tag}>${localeLabel(tag)}</sp-menu-item>`,
|
|
321
|
-
)}
|
|
322
|
-
</sp-picker>
|
|
323
|
-
</div>
|
|
324
|
-
<div class="settings-field">
|
|
325
|
-
<label class="settings-field-label">URL Routing</label>
|
|
326
|
-
<p class="settings-field-desc">
|
|
327
|
-
Whether the default language owns the unprefixed URLs, or every language is named in its
|
|
328
|
-
own.
|
|
329
|
-
</p>
|
|
330
|
-
<sp-picker
|
|
331
|
-
size="s"
|
|
332
|
-
label="URL Routing"
|
|
333
|
-
class="settings-locale-routing"
|
|
334
|
-
.value=${i18n?.routing ?? "prefix-except-default"}
|
|
335
|
-
?disabled=${locales.length === 0}
|
|
336
|
-
@change=${onRoutingChange}
|
|
337
|
-
>
|
|
338
|
-
${LOCALE_ROUTINGS.map(
|
|
339
|
-
(routing) => html`<sp-menu-item value=${routing.value}>${routing.label}</sp-menu-item>`,
|
|
340
|
-
)}
|
|
341
|
-
</sp-picker>
|
|
342
|
-
</div>
|
|
343
|
-
</div>
|
|
344
|
-
`;
|
|
250
|
+
/**
|
|
251
|
+
* What the reader may do, bound to one container.
|
|
252
|
+
*
|
|
253
|
+
* Memoized per container so the surface is handed the same functions every time: they are read
|
|
254
|
+
* once, when it mounts, and a fresh set on every refresh would be a scope write that says nothing.
|
|
255
|
+
*/
|
|
256
|
+
const bound = new WeakMap<HTMLElement, LocalesActions>();
|
|
257
|
+
|
|
258
|
+
function actions(container: HTMLElement): LocalesActions {
|
|
259
|
+
let acts = bound.get(container);
|
|
260
|
+
if (!acts) {
|
|
261
|
+
acts = {
|
|
262
|
+
add: () => {
|
|
263
|
+
add(container);
|
|
264
|
+
},
|
|
265
|
+
chooseDefault: (value: string) => {
|
|
266
|
+
void persist(container, { i18n: { ...config().i18n, defaultLocale: value } });
|
|
267
|
+
},
|
|
268
|
+
chooseRouting: (value: string) => {
|
|
269
|
+
void persist(container, {
|
|
270
|
+
i18n: { ...config().i18n, routing: value as LocaleRouting },
|
|
271
|
+
});
|
|
272
|
+
},
|
|
273
|
+
edit: (value: string) => {
|
|
274
|
+
/* Every keystroke, with no verdict check in front of it. The lit form re-rendered only when
|
|
275
|
+
the refusal CHANGED, because redrawing pushed `.value` back into the field mid-word; the
|
|
276
|
+
document writes the same string the field already holds and `jx-textfield` leaves the
|
|
277
|
+
caret where it is, so the guard has nothing left to protect. */
|
|
278
|
+
form(container).pending = value;
|
|
279
|
+
refresh(container);
|
|
280
|
+
},
|
|
281
|
+
remove: (tag: string) => {
|
|
282
|
+
remove(container, tag);
|
|
283
|
+
},
|
|
284
|
+
};
|
|
285
|
+
bound.set(container, acts);
|
|
286
|
+
}
|
|
287
|
+
return acts;
|
|
288
|
+
}
|
|
345
289
|
|
|
346
|
-
|
|
290
|
+
/**
|
|
291
|
+
* The project's languages, its default, and how a locale is spelled in a URL.
|
|
292
|
+
*
|
|
293
|
+
* @param {HTMLElement} container
|
|
294
|
+
*/
|
|
295
|
+
export function renderLocalesSection(container: HTMLElement): void {
|
|
296
|
+
refresh(container);
|
|
347
297
|
}
|
|
@@ -17,12 +17,31 @@
|
|
|
17
17
|
*
|
|
18
18
|
* **No secret is ever returned.** A record says whether something is stored and what it is for;
|
|
19
19
|
* printing a token into a list is how a screenshot leaks one.
|
|
20
|
+
*
|
|
21
|
+
* **Cloudflare has two spellings, and this file used to know only one.** On a platform that brokers
|
|
22
|
+
* the connection (Jx Cloud), there is no local token to enumerate — `getCfToken()` is empty by
|
|
23
|
+
* design — so the row said "Not connected" to every hosted user, named no account, and offered a
|
|
24
|
+
* Disconnect that cleared nothing server-side. The hosted state comes from the PAL instead, cached
|
|
25
|
+
* here because a template must not start a fetch on every repaint.
|
|
20
26
|
*/
|
|
21
27
|
|
|
22
28
|
import { clearGithubToken, githubTokenLocation, githubTokenStored } from "../github/github-auth";
|
|
23
29
|
import { clearCfConnection, getCfAccountId, getCfToken } from "../services/cf-settings";
|
|
24
30
|
import { clearAiProvider, getBaseUrl, hasOpenAiKey } from "../services/ai-settings";
|
|
25
|
-
import { preferredModel } from "../services/ai-models";
|
|
31
|
+
import { preferredModel, resetModelCache } from "../services/ai-models";
|
|
32
|
+
import { getPlatform, hasPlatform } from "../platform";
|
|
33
|
+
import type { CfConnection } from "../types";
|
|
34
|
+
|
|
35
|
+
/** One thing a row can do besides existing. */
|
|
36
|
+
export interface AccountAction {
|
|
37
|
+
/** Stable key — the button's `data-action`, so a test names an intent rather than a label. */
|
|
38
|
+
id: string;
|
|
39
|
+
label: string;
|
|
40
|
+
/** The button's `variant`; omitted for the default treatment. */
|
|
41
|
+
variant?: string;
|
|
42
|
+
/** Do it. Async ones repaint the sheet when they settle. */
|
|
43
|
+
run: () => void | Promise<void>;
|
|
44
|
+
}
|
|
26
45
|
|
|
27
46
|
/** One stored credential, as the Accounts section renders it. */
|
|
28
47
|
export interface AccountRecord {
|
|
@@ -35,6 +54,178 @@ export interface AccountRecord {
|
|
|
35
54
|
connected: boolean;
|
|
36
55
|
/** Forget it. Idempotent: revoking a disconnected account is a no-op, not an error. */
|
|
37
56
|
revoke: () => void;
|
|
57
|
+
/**
|
|
58
|
+
* What this row offers, when a plain Disconnect is not the whole story.
|
|
59
|
+
*
|
|
60
|
+
* Absent on the rows whose only verb is "forget it", which is every locally stored credential. A
|
|
61
|
+
* brokered Cloudflare connection has three more — reconnect a lapsed grant, choose an account,
|
|
62
|
+
* connect for the first time — and none of them is expressible as `revoke`.
|
|
63
|
+
*/
|
|
64
|
+
actions?: AccountAction[];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ─── The brokered Cloudflare connection ──────────────────────────────────────
|
|
68
|
+
|
|
69
|
+
/** What the broker last said, or "checking" before it has been asked. */
|
|
70
|
+
let _cfState: CfConnection | null | "checking" = "checking";
|
|
71
|
+
|
|
72
|
+
/** The in-flight read, so a repaint during one does not start a second. */
|
|
73
|
+
let _cfInFlight: Promise<void> | null = null;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Whether the platform brokers the Cloudflare connection rather than holding a pasted token.
|
|
77
|
+
*
|
|
78
|
+
* Keyed on `cfConnect` — the hosted OAuth flow — because that is the member whose presence means
|
|
79
|
+
* "there is a connection this app did not store locally".
|
|
80
|
+
*/
|
|
81
|
+
export function platformBrokersCf(): boolean {
|
|
82
|
+
return hasPlatform() && Boolean(getPlatform().cfConnect);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Re-read the brokered connection and announce it. Always refetches; the Accounts section runs it
|
|
87
|
+
* when it is shown and after every action, because the answer changes server-side.
|
|
88
|
+
*/
|
|
89
|
+
export async function refreshCfConnection(): Promise<void> {
|
|
90
|
+
if (!platformBrokersCf()) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
_cfInFlight ??= (async () => {
|
|
94
|
+
try {
|
|
95
|
+
_cfState = (await getPlatform().cfConnection?.()) ?? null;
|
|
96
|
+
} catch {
|
|
97
|
+
/* An unreachable broker is not a connection. The row says "not connected", which is what the
|
|
98
|
+
app can act on; the error itself belongs to whatever surface made the call the user asked
|
|
99
|
+
for, not to a list that repaints itself. */
|
|
100
|
+
_cfState = null;
|
|
101
|
+
}
|
|
102
|
+
_cfInFlight = null;
|
|
103
|
+
notifyCredentialsChanged();
|
|
104
|
+
})();
|
|
105
|
+
await _cfInFlight;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Kick the first read, once. Safe to call from a template — later paints are no-ops. */
|
|
109
|
+
export function ensureCfConnection(): void {
|
|
110
|
+
if (platformBrokersCf() && _cfState === "checking" && !_cfInFlight) {
|
|
111
|
+
void refreshCfConnection();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Forget the cached broker answer.
|
|
117
|
+
*
|
|
118
|
+
* Called when Preferences opens, and that is the point: the row would otherwise paint the answer
|
|
119
|
+
* from the LAST visit — an hour-old "Connected — Acme" over a grant that has since lapsed — and
|
|
120
|
+
* only correct itself when the re-read landed. Saying "checking" while it checks is the honest
|
|
121
|
+
* version of the same half-second.
|
|
122
|
+
*/
|
|
123
|
+
export function resetCfConnectionCache(): void {
|
|
124
|
+
_cfState = "checking";
|
|
125
|
+
_cfInFlight = null;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** Run the hosted flow, then re-read. The models cache goes because the AI gate keys on it too. */
|
|
129
|
+
async function hostedConnect(): Promise<void> {
|
|
130
|
+
const outcome = await getPlatform().cfConnect?.();
|
|
131
|
+
if (outcome?.status === "connected" && !outcome.connection.accountId) {
|
|
132
|
+
/* Dynamically, and this is the load-bearing half: the picker imports THIS module for
|
|
133
|
+
`notifyCredentialsChanged`, so a static import here would close the cycle. */
|
|
134
|
+
const { openCfAccountPicker } = await import("../ui/cf-account-picker");
|
|
135
|
+
await openCfAccountPicker();
|
|
136
|
+
}
|
|
137
|
+
resetModelCache();
|
|
138
|
+
await refreshCfConnection();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** The brokered row — five states, and each one names the next move. */
|
|
142
|
+
function brokeredCloudflareRecord(): AccountRecord {
|
|
143
|
+
const disconnect: AccountAction = {
|
|
144
|
+
id: "disconnect",
|
|
145
|
+
label: "Disconnect",
|
|
146
|
+
run: async () => {
|
|
147
|
+
await getPlatform().cfDisconnect?.();
|
|
148
|
+
resetModelCache();
|
|
149
|
+
await refreshCfConnection();
|
|
150
|
+
},
|
|
151
|
+
variant: "negative",
|
|
152
|
+
};
|
|
153
|
+
const connect = (label: string): AccountAction => ({
|
|
154
|
+
id: label === "Connect" ? "connect" : "reconnect",
|
|
155
|
+
label,
|
|
156
|
+
run: hostedConnect,
|
|
157
|
+
variant: "accent",
|
|
158
|
+
});
|
|
159
|
+
const base = { id: "cloudflare", label: "Cloudflare", revoke: () => {} };
|
|
160
|
+
|
|
161
|
+
if (_cfState === "checking") {
|
|
162
|
+
return { ...base, actions: [], connected: false, detail: "Checking your connection…" };
|
|
163
|
+
}
|
|
164
|
+
if (!_cfState?.connected) {
|
|
165
|
+
return {
|
|
166
|
+
...base,
|
|
167
|
+
actions: [connect("Connect")],
|
|
168
|
+
connected: false,
|
|
169
|
+
detail: "Not connected. Connecting publishes this site and runs the assistant on Workers AI.",
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
const revoke = () => {
|
|
173
|
+
void disconnect.run();
|
|
174
|
+
};
|
|
175
|
+
if (_cfState.needsReconnect) {
|
|
176
|
+
return {
|
|
177
|
+
...base,
|
|
178
|
+
actions: [connect("Reconnect"), disconnect],
|
|
179
|
+
connected: true,
|
|
180
|
+
detail: "Connection expired. Reconnect to keep publishing and the assistant working.",
|
|
181
|
+
revoke,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
if (_cfState.needsAccount || !_cfState.accountId) {
|
|
185
|
+
return {
|
|
186
|
+
...base,
|
|
187
|
+
actions: [
|
|
188
|
+
{
|
|
189
|
+
id: "choose-account",
|
|
190
|
+
label: "Choose account",
|
|
191
|
+
run: async () => {
|
|
192
|
+
const { openCfAccountPicker } = await import("../ui/cf-account-picker");
|
|
193
|
+
if (await openCfAccountPicker()) {
|
|
194
|
+
resetModelCache();
|
|
195
|
+
await refreshCfConnection();
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
variant: "accent",
|
|
199
|
+
},
|
|
200
|
+
disconnect,
|
|
201
|
+
],
|
|
202
|
+
connected: true,
|
|
203
|
+
detail: "Connected, but no account is chosen yet — publishing and the assistant need one.",
|
|
204
|
+
revoke,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
...base,
|
|
209
|
+
actions: [disconnect],
|
|
210
|
+
connected: true,
|
|
211
|
+
detail: `Connected — ${_cfState.accountName ?? _cfState.accountId}.`,
|
|
212
|
+
revoke,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/** The locally stored row: a pasted API token, on desktop and the dev server. */
|
|
217
|
+
function localCloudflareRecord(): AccountRecord {
|
|
218
|
+
const cfToken = getCfToken();
|
|
219
|
+
const cfAccount = getCfAccountId();
|
|
220
|
+
return {
|
|
221
|
+
connected: Boolean(cfToken),
|
|
222
|
+
detail: cfToken
|
|
223
|
+
? `Connected${cfAccount ? ` — account ${cfAccount}` : ""}.`
|
|
224
|
+
: "Not connected. Publishing will ask when it needs it.",
|
|
225
|
+
id: "cloudflare",
|
|
226
|
+
label: "Cloudflare",
|
|
227
|
+
revoke: clearCfConnection,
|
|
228
|
+
};
|
|
38
229
|
}
|
|
39
230
|
|
|
40
231
|
/**
|
|
@@ -45,8 +236,6 @@ export interface AccountRecord {
|
|
|
45
236
|
*/
|
|
46
237
|
export function listAccounts(): AccountRecord[] {
|
|
47
238
|
const githubToken = githubTokenStored();
|
|
48
|
-
const cfToken = getCfToken();
|
|
49
|
-
const cfAccount = getCfAccountId();
|
|
50
239
|
const model = preferredModel();
|
|
51
240
|
const endpoint = getBaseUrl();
|
|
52
241
|
return [
|
|
@@ -70,15 +259,7 @@ export function listAccounts(): AccountRecord[] {
|
|
|
70
259
|
connected: hasOpenAiKey(),
|
|
71
260
|
revoke: clearAiProvider,
|
|
72
261
|
},
|
|
73
|
-
|
|
74
|
-
id: "cloudflare",
|
|
75
|
-
label: "Cloudflare",
|
|
76
|
-
detail: cfToken
|
|
77
|
-
? `Connected${cfAccount ? ` — account ${cfAccount}` : ""}.`
|
|
78
|
-
: "Not connected. Publishing will ask when it needs it.",
|
|
79
|
-
connected: Boolean(cfToken),
|
|
80
|
-
revoke: clearCfConnection,
|
|
81
|
-
},
|
|
262
|
+
platformBrokersCf() ? brokeredCloudflareRecord() : localCloudflareRecord(),
|
|
82
263
|
];
|
|
83
264
|
}
|
|
84
265
|
|