@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
|
@@ -27,21 +27,34 @@
|
|
|
27
27
|
* Failures are surfaced, not swallowed: every write runs through {@link persistMedia}, which
|
|
28
28
|
* schema-validates the candidate `project.json` with `jx-validate` first (the human editing this
|
|
29
29
|
* file used to get **no validation at all** — that was wired to the AI's `write_project_config`
|
|
30
|
-
* alone), parks any rejection under the control that caused it, and re-
|
|
30
|
+
* alone), parks any rejection under the control that caused it, and re-projects. §7.1's third tier:
|
|
31
31
|
* a bad value belongs at its control, not in a toast that expires.
|
|
32
32
|
*
|
|
33
|
+
* **The markup is `surfaces/settings-contexts.json`.** This module is the section's decisions —
|
|
34
|
+
* what a context is, what refuses one, and what reaches disk — and the surface adapter beside that
|
|
35
|
+
* document owns the mount. The registry seam did not move: `renderContextsSection` is still the
|
|
36
|
+
* `render(container)` a `SettingsSection` declares, and it is still called again for every change
|
|
37
|
+
* the host notices. What changed underneath is that a call is now a PROJECTION rather than a
|
|
38
|
+
* repaint: the reactive scope takes the new view and the runtime touches the rows that differ,
|
|
39
|
+
* where the lit version rebuilt the whole section on every keystroke's write.
|
|
40
|
+
*
|
|
33
41
|
* @docs studio/projects/settings
|
|
34
42
|
*/
|
|
35
43
|
|
|
36
|
-
import { html, render as litRender, nothing } from "lit-html";
|
|
37
|
-
import { live } from "lit-html/directives/live.js";
|
|
38
44
|
import { errorMessage } from "@jxsuite/schema/parse";
|
|
39
45
|
import { projectState } from "../store";
|
|
40
46
|
import { updateSiteConfig } from "../site-context";
|
|
41
47
|
import { validateProjectConfig } from "../services/jx-validate";
|
|
42
48
|
import { isSchemeQuery, schemeOfQuery } from "../utils/canvas-media";
|
|
43
49
|
import { mediaDisplayName } from "../panels/shared";
|
|
44
|
-
|
|
50
|
+
import { mountContextsSurface } from "../surfaces/settings-contexts";
|
|
51
|
+
|
|
52
|
+
import type {
|
|
53
|
+
ContextGroupView,
|
|
54
|
+
ContextRowView,
|
|
55
|
+
ContextsSurfaceHandle,
|
|
56
|
+
ContextsView,
|
|
57
|
+
} from "../surfaces/settings-contexts";
|
|
45
58
|
import type { ProjectConfig } from "@jxsuite/schema/types";
|
|
46
59
|
|
|
47
60
|
/** The `$media` key the base width lives under. Not a query — a number of CSS pixels. */
|
|
@@ -123,6 +136,58 @@ export function contextKeyOf(name: string): string {
|
|
|
123
136
|
return slug ? `--${slug}` : "";
|
|
124
137
|
}
|
|
125
138
|
|
|
139
|
+
// ─── The three groups ─────────────────────────────────────────────────────────
|
|
140
|
+
|
|
141
|
+
/** A group's fixed half: its words, and what its add button creates. */
|
|
142
|
+
interface GroupSpec {
|
|
143
|
+
kind: ContextKind;
|
|
144
|
+
label: string;
|
|
145
|
+
desc: string;
|
|
146
|
+
addLabel: string;
|
|
147
|
+
empty: string;
|
|
148
|
+
/** The `--<stem>` an added entry is named after, before de-duplication. */
|
|
149
|
+
stem: string;
|
|
150
|
+
/** The query an added entry starts as — always a real one, never a blank to fill in. */
|
|
151
|
+
newQuery: string;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* The groups, in render order.
|
|
156
|
+
*
|
|
157
|
+
* A table rather than three call sites, because the only thing that differed between them in the
|
|
158
|
+
* lit version was seven strings and a control choice — and the control choice is derived from the
|
|
159
|
+
* kind, so there was nothing left for a hand-written group to decide.
|
|
160
|
+
*/
|
|
161
|
+
const GROUPS: readonly GroupSpec[] = [
|
|
162
|
+
{
|
|
163
|
+
addLabel: "Add breakpoint",
|
|
164
|
+
desc: "Screen widths that get their own canvas and their own style values.",
|
|
165
|
+
empty: "No breakpoints yet — every width uses the base styles.",
|
|
166
|
+
kind: "size",
|
|
167
|
+
label: "Size breakpoints",
|
|
168
|
+
newQuery: NEW_BREAKPOINT_QUERY,
|
|
169
|
+
stem: "breakpoint",
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
addLabel: "Add colour scheme",
|
|
173
|
+
desc: "Light and dark renderings. Defining one turns on the Auto / Light / Dark control.",
|
|
174
|
+
empty: "No colour schemes yet — the project renders one way.",
|
|
175
|
+
kind: "scheme",
|
|
176
|
+
label: "Colour schemes",
|
|
177
|
+
newQuery: "(prefers-color-scheme: dark)",
|
|
178
|
+
stem: "dark",
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
addLabel: "Add feature query",
|
|
182
|
+
desc: "Anything else a media query can ask: reduced motion, print, hover, orientation.",
|
|
183
|
+
empty: "No feature queries yet.",
|
|
184
|
+
kind: "feature",
|
|
185
|
+
label: "Feature queries",
|
|
186
|
+
newQuery: NEW_FEATURE_QUERY,
|
|
187
|
+
stem: "feature",
|
|
188
|
+
},
|
|
189
|
+
];
|
|
190
|
+
|
|
126
191
|
// ─── Per-container error state ────────────────────────────────────────────────
|
|
127
192
|
|
|
128
193
|
/**
|
|
@@ -149,321 +214,258 @@ const errors = new WeakMap<HTMLElement, { target: ErrorTarget; message: string }
|
|
|
149
214
|
*/
|
|
150
215
|
const inheritedErrors = new WeakMap<HTMLElement, string[]>();
|
|
151
216
|
|
|
217
|
+
/** The mounted surface, per container — see {@link renderContextsSection}. */
|
|
218
|
+
const mounts = new WeakMap<HTMLElement, ContextsSurfaceHandle>();
|
|
219
|
+
|
|
152
220
|
/** Read the current failure for a container — exported for tests and for re-render helpers. */
|
|
153
221
|
export function contextsError(container: HTMLElement): { target: string; message: string } | null {
|
|
154
222
|
return errors.get(container) ?? null;
|
|
155
223
|
}
|
|
156
224
|
|
|
157
|
-
// ───
|
|
225
|
+
// ─── The project, as it stands now ────────────────────────────────────────────
|
|
158
226
|
|
|
159
227
|
/**
|
|
160
|
-
*
|
|
228
|
+
* The config and its `$media`, read at the moment they are needed.
|
|
161
229
|
*
|
|
162
|
-
*
|
|
230
|
+
* The lit version closed over both at render time and rebuilt every handler on every render, so a
|
|
231
|
+
* stale closure was impossible only because there were no long-lived ones. The handlers now outlive
|
|
232
|
+
* a projection, which makes reading through to the store the thing that keeps them honest.
|
|
163
233
|
*/
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
const shown = errors.get(container);
|
|
168
|
-
const { base, entries } = splitContexts(media);
|
|
169
|
-
|
|
170
|
-
/** Park a failure under one control without writing anything. */
|
|
171
|
-
const reject = (target: ErrorTarget, message: string) => {
|
|
172
|
-
errors.set(container, { message, target });
|
|
173
|
-
renderContextsSection(container);
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Write a whole `$media` map, validating it first and surfacing whatever refuses it.
|
|
178
|
-
*
|
|
179
|
-
* Both failure modes are real and both used to be invisible here: the schema can refuse the
|
|
180
|
-
* shape, and the disk can refuse the write. The predecessor surfaces (`Properties › Media` and
|
|
181
|
-
* the CSS-variables "Enable dark scheme") did `void updateSiteConfig(...)` and dropped the
|
|
182
|
-
* rejection, so a failed write read as the field snapping back for no reason.
|
|
183
|
-
*
|
|
184
|
-
* **Only the errors THIS edit introduces block it.** The candidate is the whole `project.json`,
|
|
185
|
-
* so a violation anywhere else in the file used to refuse every context edit and park the reason
|
|
186
|
-
* under whichever control had been touched — typing `1280px` into Base width reported three
|
|
187
|
-
* unevaluated-property errors about `title`, `description` and `$style`, none of which is a
|
|
188
|
-
* width. The baseline is validated first and subtracted, the same way `services/ai-tools.ts`
|
|
189
|
-
* subtracts it before blaming the model for a document it inherited. A pre-existing problem is
|
|
190
|
-
* still worth saying, so it is reported once at section level, where a whole-file problem belongs
|
|
191
|
-
* — and it is reported rather than repaired, because `project.json` is the author's file and a
|
|
192
|
-
* settings screen that silently drops keys it did not recognise is worse than one that names
|
|
193
|
-
* them.
|
|
194
|
-
*/
|
|
195
|
-
const persistMedia = async (next: Record<string, string>, target: ErrorTarget) => {
|
|
196
|
-
const candidate = { ...config, $media: next } as unknown;
|
|
197
|
-
let schemaErrors: string[] = [];
|
|
198
|
-
let inherited: string[] = [];
|
|
199
|
-
try {
|
|
200
|
-
inherited = await validateProjectConfig(config);
|
|
201
|
-
const found = await validateProjectConfig(candidate);
|
|
202
|
-
schemaErrors = found.filter((error) => !inherited.includes(error));
|
|
203
|
-
} catch (error) {
|
|
204
|
-
/* A validator that cannot compile must not block the edit — but it must not be silent
|
|
205
|
-
either, so the message rides the same inline slot the schema errors would have used. */
|
|
206
|
-
reject(target, `Could not validate project.json — ${errorMessage(error)}`);
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
if (schemaErrors.length > 0) {
|
|
210
|
-
reject(target, schemaErrors.join("; "));
|
|
211
|
-
return;
|
|
212
|
-
}
|
|
213
|
-
inheritedErrors.set(container, inherited);
|
|
214
|
-
try {
|
|
215
|
-
await updateSiteConfig({ $media: next });
|
|
216
|
-
errors.delete(container);
|
|
217
|
-
} catch (error) {
|
|
218
|
-
errors.set(container, {
|
|
219
|
-
message: `Could not save project.json — ${errorMessage(error)}`,
|
|
220
|
-
target,
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
renderContextsSection(container);
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* What is already wrong with `project.json`, said once and not blamed on a control.
|
|
228
|
-
*
|
|
229
|
-
* It does not block anything — the edit that surfaced it went through. It is here because a file
|
|
230
|
-
* that fails its own schema will keep failing it, and until this notice existed the only place
|
|
231
|
-
* that fact appeared was as an unexplained refusal of an unrelated field.
|
|
232
|
-
*/
|
|
233
|
-
const inheritedNotice = () => {
|
|
234
|
-
const inherited = inheritedErrors.get(container) ?? [];
|
|
235
|
-
return inherited.length === 0
|
|
236
|
-
? nothing
|
|
237
|
-
: html`<p class="settings-section-notice" role="status">
|
|
238
|
-
project.json has ${inherited.length} pre-existing schema
|
|
239
|
-
${inherited.length === 1 ? "problem" : "problems"} that this section did not cause:
|
|
240
|
-
${inherited.join("; ")}
|
|
241
|
-
</p>`;
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
/** The error line for one control, when that is where the current failure belongs. */
|
|
245
|
-
const errorFor = (target: ErrorTarget) =>
|
|
246
|
-
shown?.target === target
|
|
247
|
-
? html`<p class="settings-field-error" role="alert">${shown.message}</p>`
|
|
248
|
-
: nothing;
|
|
234
|
+
function currentConfig(): ProjectConfig {
|
|
235
|
+
return (projectState?.projectConfig || {}) as ProjectConfig;
|
|
236
|
+
}
|
|
249
237
|
|
|
250
|
-
|
|
238
|
+
function currentMedia(): Record<string, string> {
|
|
239
|
+
return (currentConfig().$media || {}) as Record<string, string>;
|
|
240
|
+
}
|
|
251
241
|
|
|
252
|
-
|
|
253
|
-
const value = (e.target as HTMLInputElement).value.trim();
|
|
254
|
-
if (value && !/^\d+px$/.test(value)) {
|
|
255
|
-
reject("base", "Enter a width in pixels, like 1280px.");
|
|
256
|
-
return;
|
|
257
|
-
}
|
|
258
|
-
const next = { ...media };
|
|
259
|
-
if (value) {
|
|
260
|
-
next[BASE_KEY] = value;
|
|
261
|
-
} else {
|
|
262
|
-
delete next[BASE_KEY];
|
|
263
|
-
}
|
|
264
|
-
void persistMedia(next, "base");
|
|
265
|
-
};
|
|
242
|
+
// ─── Writing ──────────────────────────────────────────────────────────────────
|
|
266
243
|
|
|
267
|
-
|
|
244
|
+
/** Park a failure under one control without writing anything. */
|
|
245
|
+
function reject(container: HTMLElement, target: ErrorTarget, message: string): void {
|
|
246
|
+
errors.set(container, { message, target });
|
|
247
|
+
renderContextsSection(container);
|
|
248
|
+
}
|
|
268
249
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
250
|
+
/**
|
|
251
|
+
* Write a whole `$media` map, validating it first and surfacing whatever refuses it.
|
|
252
|
+
*
|
|
253
|
+
* Both failure modes are real and both used to be invisible here: the schema can refuse the shape,
|
|
254
|
+
* and the disk can refuse the write. The predecessor surfaces (`Properties › Media` and the
|
|
255
|
+
* CSS-variables "Enable dark scheme") did `void updateSiteConfig(...)` and dropped the rejection,
|
|
256
|
+
* so a failed write read as the field snapping back for no reason.
|
|
257
|
+
*
|
|
258
|
+
* **Only the errors THIS edit introduces block it.** The candidate is the whole `project.json`, so
|
|
259
|
+
* a violation anywhere else in the file used to refuse every context edit and park the reason under
|
|
260
|
+
* whichever control had been touched — typing `1280px` into Base width reported three
|
|
261
|
+
* unevaluated-property errors about `title`, `description` and `$style`, none of which is a width.
|
|
262
|
+
* The baseline is validated first and subtracted, the same way `services/ai-tools.ts` subtracts it
|
|
263
|
+
* before blaming the model for a document it inherited. A pre-existing problem is still worth
|
|
264
|
+
* saying, so it is reported once at section level, where a whole-file problem belongs — and it is
|
|
265
|
+
* reported rather than repaired, because `project.json` is the author's file and a settings screen
|
|
266
|
+
* that silently drops keys it did not recognise is worse than one that names them.
|
|
267
|
+
*/
|
|
268
|
+
async function persistMedia(
|
|
269
|
+
container: HTMLElement,
|
|
270
|
+
next: Record<string, string>,
|
|
271
|
+
target: ErrorTarget,
|
|
272
|
+
): Promise<void> {
|
|
273
|
+
const config = currentConfig();
|
|
274
|
+
const candidate = { ...config, $media: next } as unknown;
|
|
275
|
+
let schemaErrors: string[] = [];
|
|
276
|
+
let inherited: string[] = [];
|
|
277
|
+
try {
|
|
278
|
+
inherited = await validateProjectConfig(config);
|
|
279
|
+
const found = await validateProjectConfig(candidate);
|
|
280
|
+
schemaErrors = found.filter((error) => !inherited.includes(error));
|
|
281
|
+
} catch (error) {
|
|
282
|
+
/* A validator that cannot compile must not block the edit — but it must not be silent either,
|
|
283
|
+
so the message rides the same inline slot the schema errors would have used. */
|
|
284
|
+
reject(container, target, `Could not validate project.json — ${errorMessage(error)}`);
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
if (schemaErrors.length > 0) {
|
|
288
|
+
reject(container, target, schemaErrors.join("; "));
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
inheritedErrors.set(container, inherited);
|
|
292
|
+
try {
|
|
293
|
+
await updateSiteConfig({ $media: next });
|
|
294
|
+
errors.delete(container);
|
|
295
|
+
} catch (error) {
|
|
296
|
+
errors.set(container, {
|
|
297
|
+
message: `Could not save project.json — ${errorMessage(error)}`,
|
|
298
|
+
target,
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
renderContextsSection(container);
|
|
302
|
+
}
|
|
290
303
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
304
|
+
/** What every control in one container does. Built once, and read through to the store. */
|
|
305
|
+
function actionsFor(container: HTMLElement): Parameters<typeof mountContextsSurface>[1] {
|
|
306
|
+
return {
|
|
307
|
+
/** Add an entry under the first free `--<stem>` / `--<stem>-2` … name. */
|
|
308
|
+
add(kind) {
|
|
309
|
+
const spec = GROUPS.find((group) => group.kind === kind);
|
|
310
|
+
if (!spec) {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
const media = currentMedia();
|
|
314
|
+
let key = `--${spec.stem}`;
|
|
315
|
+
let n = 2;
|
|
316
|
+
while (key in media) {
|
|
317
|
+
key = `--${spec.stem}-${n}`;
|
|
318
|
+
n += 1;
|
|
319
|
+
}
|
|
320
|
+
void persistMedia(container, { ...media, [key]: spec.newQuery }, key);
|
|
321
|
+
},
|
|
322
|
+
remove(key) {
|
|
323
|
+
const next = { ...currentMedia() };
|
|
324
|
+
delete next[key];
|
|
325
|
+
void persistMedia(container, next, "section");
|
|
326
|
+
},
|
|
327
|
+
rename(oldKey, value) {
|
|
328
|
+
const media = currentMedia();
|
|
329
|
+
const newKey = contextKeyOf(value);
|
|
330
|
+
if (!newKey) {
|
|
331
|
+
reject(container, oldKey, "A context needs a name.");
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
if (newKey === oldKey) {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
if (newKey in media) {
|
|
338
|
+
reject(container, oldKey, `"${mediaDisplayName(newKey)}" is already defined.`);
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
/* Rebuild in place so renaming never reorders the list — the order is the order the pane
|
|
342
|
+
context bar offers them in, and a rename is not a reordering. */
|
|
343
|
+
const next: Record<string, string> = {};
|
|
344
|
+
for (const [key, entry] of Object.entries(media)) {
|
|
345
|
+
next[key === oldKey ? newKey : key] = entry;
|
|
346
|
+
}
|
|
347
|
+
void persistMedia(container, next, newKey);
|
|
348
|
+
},
|
|
349
|
+
setBase(value) {
|
|
350
|
+
const width = value.trim();
|
|
351
|
+
if (width && !/^\d+px$/.test(width)) {
|
|
352
|
+
reject(container, "base", "Enter a width in pixels, like 1280px.");
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
const next = { ...currentMedia() };
|
|
356
|
+
if (width) {
|
|
357
|
+
next[BASE_KEY] = width;
|
|
358
|
+
} else {
|
|
359
|
+
delete next[BASE_KEY];
|
|
360
|
+
}
|
|
361
|
+
void persistMedia(container, next, "base");
|
|
362
|
+
},
|
|
363
|
+
setQuery(key, value) {
|
|
364
|
+
const query = value.trim();
|
|
365
|
+
if (!query) {
|
|
366
|
+
reject(container, key, "A context needs a media query, like (max-width: 768px).");
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
void persistMedia(container, { ...currentMedia(), [key]: query }, key);
|
|
370
|
+
},
|
|
371
|
+
/** The scheme picker writes the canonical query, so a scheme is never mistyped into a feature. */
|
|
372
|
+
setScheme(key, scheme) {
|
|
373
|
+
void persistMedia(
|
|
374
|
+
container,
|
|
375
|
+
{ ...currentMedia(), [key]: `(prefers-color-scheme: ${scheme})` },
|
|
376
|
+
key,
|
|
377
|
+
);
|
|
378
|
+
},
|
|
298
379
|
};
|
|
380
|
+
}
|
|
299
381
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
382
|
+
// ─── Projection ───────────────────────────────────────────────────────────────
|
|
383
|
+
|
|
384
|
+
/** One `$media` entry, as the document draws it. */
|
|
385
|
+
function rowView(
|
|
386
|
+
entry: ContextEntry,
|
|
387
|
+
shown: { target: ErrorTarget; message: string } | undefined,
|
|
388
|
+
): ContextRowView {
|
|
389
|
+
const display = mediaDisplayName(entry.key);
|
|
390
|
+
const invalid = shown?.target === entry.key;
|
|
391
|
+
return {
|
|
392
|
+
control: entry.kind === "scheme" ? "scheme" : "query",
|
|
393
|
+
error: invalid ? shown.message : "",
|
|
394
|
+
invalid,
|
|
395
|
+
key: entry.key,
|
|
396
|
+
name: entry.key.replace(/^--/, ""),
|
|
397
|
+
nameLabel: `Name for ${display}`,
|
|
398
|
+
query: entry.query,
|
|
399
|
+
removeLabel: `Remove ${display}`,
|
|
400
|
+
scheme: schemeOfQuery(entry.query) ?? "dark",
|
|
401
|
+
valueLabel:
|
|
402
|
+
entry.kind === "scheme" ? `Colour scheme for ${display}` : `Media query for ${display}`,
|
|
304
403
|
};
|
|
404
|
+
}
|
|
305
405
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
406
|
+
/**
|
|
407
|
+
* What the file already got wrong, said once and not blamed on a control.
|
|
408
|
+
*
|
|
409
|
+
* It does not block anything — the edit that surfaced it went through. It is here because a file
|
|
410
|
+
* that fails its own schema will keep failing it, and until this notice existed the only place that
|
|
411
|
+
* fact appeared was as an unexplained refusal of an unrelated field.
|
|
412
|
+
*/
|
|
413
|
+
function noticeOf(inherited: readonly string[]): string {
|
|
414
|
+
if (inherited.length === 0) {
|
|
415
|
+
return "";
|
|
416
|
+
}
|
|
417
|
+
const what = inherited.length === 1 ? "problem" : "problems";
|
|
418
|
+
return `project.json has ${inherited.length} pre-existing schema ${what} that this section did not cause: ${inherited.join("; ")}`;
|
|
419
|
+
}
|
|
316
420
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
421
|
+
/** The whole section, as one value the document can be handed. */
|
|
422
|
+
function project(container: HTMLElement): ContextsView {
|
|
423
|
+
const shown = errors.get(container);
|
|
424
|
+
const { base, entries } = splitContexts(currentMedia());
|
|
425
|
+
const groups: ContextGroupView[] = GROUPS.map((spec) => {
|
|
426
|
+
const rows = entries
|
|
427
|
+
.filter((entry) => entry.kind === spec.kind)
|
|
428
|
+
.map((entry) => rowView(entry, shown));
|
|
429
|
+
return {
|
|
430
|
+
addLabel: spec.addLabel,
|
|
431
|
+
desc: spec.desc,
|
|
432
|
+
empty: spec.empty,
|
|
433
|
+
hasRows: rows.length > 0,
|
|
434
|
+
kind: spec.kind,
|
|
435
|
+
label: spec.label,
|
|
436
|
+
rows,
|
|
437
|
+
};
|
|
438
|
+
});
|
|
439
|
+
return {
|
|
440
|
+
base,
|
|
441
|
+
baseError: shown?.target === "base" ? shown.message : "",
|
|
442
|
+
baseInvalid: shown?.target === "base",
|
|
443
|
+
groups,
|
|
444
|
+
notice: noticeOf(inheritedErrors.get(container) ?? []),
|
|
445
|
+
queryPlaceholder: NEW_BREAKPOINT_QUERY,
|
|
446
|
+
sectionError: shown?.target === "section" ? shown.message : "",
|
|
321
447
|
};
|
|
448
|
+
}
|
|
322
449
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
const removeButton = (key: string) => html`
|
|
326
|
-
<sp-action-button
|
|
327
|
-
size="s"
|
|
328
|
-
quiet
|
|
329
|
-
data-remove=${key}
|
|
330
|
-
title="Remove ${mediaDisplayName(key)}"
|
|
331
|
-
@click=${onRemove(key)}
|
|
332
|
-
>
|
|
333
|
-
×
|
|
334
|
-
</sp-action-button>
|
|
335
|
-
`;
|
|
336
|
-
|
|
337
|
-
const nameField = (key: string) => html`
|
|
338
|
-
<sp-textfield
|
|
339
|
-
size="s"
|
|
340
|
-
class="settings-media-name"
|
|
341
|
-
.value=${live(key.replace(/^--/, ""))}
|
|
342
|
-
placeholder="name"
|
|
343
|
-
?invalid=${shown?.target === key}
|
|
344
|
-
@change=${onRename(key)}
|
|
345
|
-
></sp-textfield>
|
|
346
|
-
`;
|
|
347
|
-
|
|
348
|
-
const queryRow = (entry: ContextEntry) => html`
|
|
349
|
-
<div class="settings-media-row" data-context=${entry.key}>
|
|
350
|
-
${nameField(entry.key)}
|
|
351
|
-
<sp-textfield
|
|
352
|
-
size="s"
|
|
353
|
-
class="settings-media-value"
|
|
354
|
-
.value=${live(entry.query)}
|
|
355
|
-
placeholder=${NEW_BREAKPOINT_QUERY}
|
|
356
|
-
?invalid=${shown?.target === entry.key}
|
|
357
|
-
@change=${onQueryChange(entry.key)}
|
|
358
|
-
></sp-textfield>
|
|
359
|
-
${removeButton(entry.key)}
|
|
360
|
-
</div>
|
|
361
|
-
${errorFor(entry.key)}
|
|
362
|
-
`;
|
|
363
|
-
|
|
364
|
-
const schemeRow = (entry: ContextEntry) => html`
|
|
365
|
-
<div class="settings-media-row" data-context=${entry.key}>
|
|
366
|
-
${nameField(entry.key)}
|
|
367
|
-
<sp-picker
|
|
368
|
-
size="s"
|
|
369
|
-
class="settings-media-value"
|
|
370
|
-
label="Scheme"
|
|
371
|
-
.value=${schemeOfQuery(entry.query) ?? "dark"}
|
|
372
|
-
@change=${onSchemeChange(entry.key)}
|
|
373
|
-
>
|
|
374
|
-
<sp-menu-item value="light">Light</sp-menu-item>
|
|
375
|
-
<sp-menu-item value="dark">Dark</sp-menu-item>
|
|
376
|
-
</sp-picker>
|
|
377
|
-
${removeButton(entry.key)}
|
|
378
|
-
</div>
|
|
379
|
-
${errorFor(entry.key)}
|
|
380
|
-
`;
|
|
381
|
-
|
|
382
|
-
const group = (
|
|
383
|
-
kind: ContextKind,
|
|
384
|
-
label: string,
|
|
385
|
-
desc: string,
|
|
386
|
-
row: (entry: ContextEntry) => unknown,
|
|
387
|
-
addLabel: string,
|
|
388
|
-
onAdd: () => void,
|
|
389
|
-
empty: string,
|
|
390
|
-
) => {
|
|
391
|
-
const rows = entries.filter((entry) => entry.kind === kind);
|
|
392
|
-
return html`
|
|
393
|
-
<div class="settings-field" data-context-group=${kind}>
|
|
394
|
-
<label class="settings-field-label">${label}</label>
|
|
395
|
-
<p class="settings-field-desc">${desc}</p>
|
|
396
|
-
<div class="settings-media-list">
|
|
397
|
-
${
|
|
398
|
-
rows.length === 0
|
|
399
|
-
? html`<p class="settings-field-desc">${empty}</p>`
|
|
400
|
-
: rows.map((entry) => row(entry))
|
|
401
|
-
}
|
|
402
|
-
</div>
|
|
403
|
-
<sp-action-button size="s" data-add=${kind} @click=${onAdd}>${addLabel}</sp-action-button>
|
|
404
|
-
</div>
|
|
405
|
-
`;
|
|
406
|
-
};
|
|
450
|
+
// ─── Render ───────────────────────────────────────────────────────────────────
|
|
407
451
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
class="settings-media-value"
|
|
428
|
-
data-context="base"
|
|
429
|
-
placeholder="1280px"
|
|
430
|
-
.value=${live(base)}
|
|
431
|
-
?invalid=${shown?.target === "base"}
|
|
432
|
-
@change=${onBaseChange}
|
|
433
|
-
></sp-textfield>
|
|
434
|
-
</div>
|
|
435
|
-
${errorFor("base")}
|
|
436
|
-
</div>
|
|
437
|
-
|
|
438
|
-
${group(
|
|
439
|
-
"size",
|
|
440
|
-
"Size breakpoints",
|
|
441
|
-
"Screen widths that get their own canvas and their own style values.",
|
|
442
|
-
queryRow,
|
|
443
|
-
"+ Add breakpoint",
|
|
444
|
-
add("breakpoint", NEW_BREAKPOINT_QUERY),
|
|
445
|
-
"No breakpoints yet — every width uses the base styles.",
|
|
446
|
-
)}
|
|
447
|
-
${group(
|
|
448
|
-
"scheme",
|
|
449
|
-
"Colour schemes",
|
|
450
|
-
"Light and dark renderings. Defining one turns on the Auto / Light / Dark control.",
|
|
451
|
-
schemeRow,
|
|
452
|
-
"+ Add colour scheme",
|
|
453
|
-
add("dark", "(prefers-color-scheme: dark)"),
|
|
454
|
-
"No colour schemes yet — the project renders one way.",
|
|
455
|
-
)}
|
|
456
|
-
${group(
|
|
457
|
-
"feature",
|
|
458
|
-
"Feature queries",
|
|
459
|
-
"Anything else a media query can ask: reduced motion, print, hover, orientation.",
|
|
460
|
-
queryRow,
|
|
461
|
-
"+ Add feature query",
|
|
462
|
-
add("feature", NEW_FEATURE_QUERY),
|
|
463
|
-
"No feature queries yet.",
|
|
464
|
-
)}
|
|
465
|
-
</div>
|
|
466
|
-
`;
|
|
467
|
-
|
|
468
|
-
litRender(tpl, container);
|
|
452
|
+
/**
|
|
453
|
+
* Render Project Settings › Contexts into `container`.
|
|
454
|
+
*
|
|
455
|
+
* One mount per container, re-used for every subsequent call. The host calls this again for any
|
|
456
|
+
* change it notices, and a section whose container has meanwhile been given to a DIFFERENT section
|
|
457
|
+
* finds its document gone — `litRender` into the same node replaces everything in it — so the mount
|
|
458
|
+
* is rebuilt exactly when it has actually been evicted, and disposed on the way out rather than
|
|
459
|
+
* left running over detached nodes.
|
|
460
|
+
*
|
|
461
|
+
* @param {HTMLElement} container
|
|
462
|
+
*/
|
|
463
|
+
export function renderContextsSection(container: HTMLElement): void {
|
|
464
|
+
let handle = mounts.get(container);
|
|
465
|
+
if (!handle?.attached()) {
|
|
466
|
+
handle?.dispose();
|
|
467
|
+
handle = mountContextsSurface(container, actionsFor(container));
|
|
468
|
+
mounts.set(container, handle);
|
|
469
|
+
}
|
|
470
|
+
handle.update(project(container));
|
|
469
471
|
}
|