@jxsuite/studio 4.1.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.
Files changed (607) hide show
  1. package/README.md +1 -1
  2. package/data/elements-meta.json +5 -15
  3. package/data/html-meta.json +51 -6
  4. package/dist/chunks/{2020-n6tfwnda.js → 2020-g79n01v9.js} +14 -14
  5. package/dist/chunks/action-group-sp6tna8v.js +118 -0
  6. package/dist/chunks/adapter-nj7tnjfn.js +13 -0
  7. package/dist/chunks/cf-account-picker-fyf63pmy.js +495 -0
  8. package/dist/chunks/cf-settings-71bv5zn9.js +20 -0
  9. package/dist/chunks/color-area-v17df7b8.js +154 -0
  10. package/dist/chunks/color-field-anwybnkn.js +208 -0
  11. package/dist/chunks/color-slider-44ez96fc.js +79 -0
  12. package/dist/chunks/color-xgg3kfw7.js +35 -0
  13. package/dist/chunks/combobox-5e7jev23.js +236 -0
  14. package/dist/chunks/components-2w1f35qs.js +18 -0
  15. package/dist/chunks/content-source-3wqeas45.js +46 -0
  16. package/dist/chunks/convert-to-repeater-d0cgnb6d.js +639 -0
  17. package/dist/chunks/dialog-s890b918.js +85 -0
  18. package/dist/chunks/editor-3qhbg51x.js +35 -0
  19. package/dist/chunks/entry-commands-d6g50j7s.js +42 -0
  20. package/dist/chunks/extension-sections-fy7q4fe9.js +651 -0
  21. package/dist/chunks/file-ops-3btj6st0.js +47 -0
  22. package/dist/chunks/files-ef8fgs3w.js +72 -0
  23. package/dist/chunks/format-host-3c33nwr8.js +40 -0
  24. package/dist/chunks/fs-events-13tj6sex.js +18 -0
  25. package/dist/chunks/git-panel-4wp2rn9b.js +49 -0
  26. package/dist/chunks/icons-yy10wk9r.js +402 -0
  27. package/dist/chunks/iframe-entry-15g3n6xv.js +114 -0
  28. package/dist/chunks/iframe-entry-b27vq81n.js +203 -0
  29. package/dist/chunks/iframe-entry-nbyxee1y.js +154 -0
  30. package/dist/chunks/iframe-host-jgesd924.js +115 -0
  31. package/dist/chunks/{index-wcnt3r9g.js → index-mdmyx6s2.js} +11 -11
  32. package/dist/chunks/index-n4j7qxyr.js +109 -0
  33. package/dist/chunks/{javascript-q8kpmfah.js → javascript-xvrfrpkb.js} +8 -9
  34. package/dist/chunks/{jsonMode-dkr040ga.js → jsonMode-tyx2kj6p.js} +526 -527
  35. package/dist/chunks/jx-validate-j0wxk72w.js +15 -0
  36. package/dist/chunks/layers-1nq5evsh.js +29 -0
  37. package/dist/chunks/layers-panel-ar2gh90g.js +40 -0
  38. package/dist/chunks/listbox-6v2ac08j.js +44 -0
  39. package/dist/chunks/lit-html-m244w9nh.js +17 -0
  40. package/dist/chunks/media-picker-2qbetq73.js +33 -0
  41. package/dist/chunks/menu-q99sy9rf.js +285 -0
  42. package/dist/chunks/menu-rf7n72mf.js +14 -0
  43. package/dist/chunks/{monaco-binding-rj6xpx9y.js → monaco-binding-sw6en4dw.js} +12 -15
  44. package/dist/chunks/monaco-buffer-bhy3hb6m.js +24 -0
  45. package/dist/chunks/{monaco-setup-vx9bhp1d.js → monaco-setup-8r62fj6y.js} +27 -37
  46. package/dist/chunks/notify-628t0anh.js +21 -0
  47. package/dist/chunks/number-field-5cndyft8.js +72 -0
  48. package/dist/chunks/parse-0zx14y15.js +10 -0
  49. package/dist/chunks/platform-ts9cg1a4.js +15 -0
  50. package/dist/chunks/popover-47z3ytva.js +25 -0
  51. package/dist/chunks/publish-panel-98f7sr3g.js +27 -0
  52. package/dist/chunks/quick-search-srzz83k2.js +45 -0
  53. package/dist/chunks/references-n553f0e1.js +26 -0
  54. package/dist/chunks/right-panel-rrgx2dn3.js +45 -0
  55. package/dist/chunks/section-registry-5pq32t0q.js +25 -0
  56. package/dist/chunks/select-2r16ez41.js +49 -0
  57. package/dist/chunks/split-g7nm1rgb.js +191 -0
  58. package/dist/chunks/studio-0hqbpbd0.js +62 -0
  59. package/dist/chunks/studio-18avnhjp.js +2430 -0
  60. package/dist/chunks/{studio-kryvsw6j.js → studio-1k325pwf.js} +48 -48
  61. package/dist/chunks/{studio-msd847zn.js → studio-25hkdrkw.js} +357 -86
  62. package/dist/chunks/studio-26d7myd1.js +258 -0
  63. package/dist/chunks/{studio-4r1pv6zf.js → studio-38emantv.js} +22 -5
  64. package/dist/chunks/studio-3gxv60tn.js +422 -0
  65. package/dist/chunks/{studio-fbf92ckf.js → studio-3hxkd92t.js} +275 -163
  66. package/dist/chunks/studio-4m0haseg.js +185 -0
  67. package/dist/chunks/{studio-ynxwkrzd.js → studio-4wbb9ct0.js} +1953 -1785
  68. package/dist/chunks/{studio-1wagb550.js → studio-5523bpzt.js} +11 -11
  69. package/dist/chunks/{studio-x4qkdat5.js → studio-57mf66w2.js} +1749 -2481
  70. package/dist/chunks/studio-5jy81t3s.js +17463 -0
  71. package/dist/chunks/studio-5rt7sqa0.js +1168 -0
  72. package/dist/chunks/studio-5te5tqng.js +81 -0
  73. package/dist/chunks/{studio-p4ngc046.js → studio-6ewqv390.js} +9 -9
  74. package/dist/chunks/{studio-9ab8gqsm.js → studio-6nzaktvy.js} +7 -7
  75. package/dist/chunks/studio-6xa21ej9.js +28 -0
  76. package/dist/chunks/{studio-5ehhackm.js → studio-727xh0e3.js} +19 -19
  77. package/dist/chunks/{studio-ahn3pdgx.js → studio-79y5sz51.js} +52 -38
  78. package/dist/chunks/{studio-gcye7qka.js → studio-7e11jpa9.js} +21 -21
  79. package/dist/chunks/{studio-q7v10cg2.js → studio-7r42c6ca.js} +17 -7
  80. package/dist/chunks/studio-7xptrg0j.js +954 -0
  81. package/dist/chunks/{studio-cft9r4r7.js → studio-81390n6f.js} +22 -22
  82. package/dist/chunks/{studio-q43a5y9h.js → studio-8jn5yhyn.js} +16 -16
  83. package/dist/chunks/studio-8qtrpzr3.js +839 -0
  84. package/dist/chunks/{studio-dg7zyt5x.js → studio-98b3z07n.js} +1 -1
  85. package/dist/chunks/studio-9xxz1q69.js +1356 -0
  86. package/dist/chunks/studio-akbww0j5.js +13615 -0
  87. package/dist/chunks/{studio-x813zp48.js → studio-arfpe389.js} +30 -30
  88. package/dist/chunks/{studio-trxrabqf.js → studio-az3zd49t.js} +475 -283
  89. package/dist/chunks/studio-cpvb2ed1.js +1171 -0
  90. package/dist/chunks/{studio-f3wqjtk5.js → studio-d0300636.js} +5076 -18
  91. package/dist/chunks/{studio-bgxt93ga.js → studio-d055c37e.js} +13 -13
  92. package/dist/chunks/studio-d1ja2x9r.js +362 -0
  93. package/dist/chunks/{studio-b9b6t1dg.js → studio-e1f24eff.js} +5664 -5666
  94. package/dist/chunks/{studio-3bqpr0zh.js → studio-em9nw8eh.js} +299 -110
  95. package/dist/chunks/studio-erdatzvp.js +1190 -0
  96. package/dist/chunks/{studio-g1wdche0.js → studio-esrxgwh6.js} +80 -80
  97. package/dist/chunks/studio-fabxk6r9.js +2811 -0
  98. package/dist/chunks/{studio-3n4ndrzh.js → studio-h4nvnjvz.js} +303 -303
  99. package/dist/chunks/{studio-dm19q43r.js → studio-hhvs4sdg.js} +10 -10
  100. package/dist/chunks/{studio-q9jd1a60.js → studio-kcgff4r0.js} +15 -18
  101. package/dist/chunks/{studio-685s0ytq.js → studio-nqgawfks.js} +572 -572
  102. package/dist/chunks/{studio-xrapxwwc.js → studio-p1dw8wfw.js} +55 -29
  103. package/dist/chunks/studio-pm6hgy7r.js +4763 -0
  104. package/dist/chunks/studio-q0a3yk4n.js +33 -0
  105. package/dist/chunks/{studio-wcy8trfx.js → studio-q3x06vmj.js} +23 -22
  106. package/dist/chunks/studio-qahxvnan.js +111 -0
  107. package/dist/chunks/{studio-53n8bp04.js → studio-r6xmmtfh.js} +1 -1
  108. package/dist/chunks/{studio-2b946z26.js → studio-rkstz940.js} +3658 -6134
  109. package/dist/chunks/{studio-tvgyw9xw.js → studio-rnyf3f8e.js} +83 -250
  110. package/dist/chunks/studio-rpyah2ew.js +2805 -0
  111. package/dist/chunks/studio-rs76k67r.js +12 -0
  112. package/dist/chunks/{studio-jkftxyvz.js → studio-s6z853aq.js} +5858 -2152
  113. package/dist/chunks/{studio-6yw4y3my.js → studio-sgdc5pfc.js} +8 -8
  114. package/dist/chunks/studio-tb3ev01j.js +763 -0
  115. package/dist/chunks/{studio-t5wqwzdh.js → studio-tjjk7jvk.js} +1 -1
  116. package/dist/chunks/studio-vhv5tgxm.js +51 -0
  117. package/dist/chunks/{studio-qjy2z9bv.js → studio-vz68yn9e.js} +32 -137
  118. package/dist/chunks/studio-wqpngpsk.js +174 -0
  119. package/dist/chunks/{studio-b55y6ewx.js → studio-x3rty6tr.js} +58 -58
  120. package/dist/chunks/studio-xsykpvsh.js +8448 -0
  121. package/dist/chunks/{studio-92ab2jqe.js → studio-y9zedyjn.js} +14 -14
  122. package/dist/chunks/studio-yxa81f45.js +12 -0
  123. package/dist/chunks/swatch-group-t0n6h2rn.js +139 -0
  124. package/dist/chunks/tabs-wbp1cdws.js +156 -0
  125. package/dist/chunks/textfield-abk6qyee.js +73 -0
  126. package/dist/chunks/toast-780pvfbv.js +27 -0
  127. package/dist/chunks/toast-host-3sqv46sn.js +116 -0
  128. package/dist/chunks/toolbar-xbh5bhtr.js +194 -0
  129. package/dist/chunks/tooltip-eptb614w.js +369 -0
  130. package/dist/chunks/tree-a73p0pqm.js +367 -0
  131. package/dist/chunks/{tsMode-76kr53q0.js → tsMode-jy4m86rv.js} +83 -85
  132. package/dist/chunks/workspace-wrew8zk4.js +69 -0
  133. package/dist/chunks/{ws-client-6shc5rze.js → ws-client-ny4zc51r.js} +20 -22
  134. package/dist/iframe-entry.js +1780 -667
  135. package/dist/studio.js +52819 -36480
  136. package/dist/workers/editor.worker.js +1040 -1085
  137. package/dist/workers/json.worker.js +1946 -1991
  138. package/dist/workers/ts.worker.js +4960 -5005
  139. package/index.html +1 -0
  140. package/package.json +18 -52
  141. package/src/about/about-modal.ts +72 -123
  142. package/src/browse/library-commands.ts +20 -49
  143. package/src/browse/library-layouts.ts +87 -218
  144. package/src/browse/library-pane.ts +406 -438
  145. package/src/canvas/canvas-helpers.ts +0 -49
  146. package/src/canvas/canvas-live-render.ts +25 -2
  147. package/src/canvas/canvas-render.ts +666 -231
  148. package/src/canvas/canvas-surface.ts +0 -1
  149. package/src/canvas/canvas-utils.ts +310 -117
  150. package/src/canvas/dialog-path.ts +76 -0
  151. package/src/canvas/dialog-state.ts +67 -0
  152. package/src/canvas/diff-marks.ts +252 -0
  153. package/src/canvas/diff-toolbar.ts +349 -0
  154. package/src/canvas/diff-view.ts +123 -0
  155. package/src/canvas/edit-width-drag.ts +187 -0
  156. package/src/canvas/edit-width.ts +150 -0
  157. package/src/canvas/iframe-entry.ts +125 -8
  158. package/src/canvas/iframe-host.ts +271 -15
  159. package/src/canvas/iframe-interaction.ts +133 -13
  160. package/src/canvas/iframe-patch.ts +7 -1
  161. package/src/canvas/iframe-position.ts +5 -6
  162. package/src/canvas/iframe-protocol.ts +106 -5
  163. package/src/canvas/iframe-render.ts +373 -5
  164. package/src/canvas/iframe-slash.ts +2 -2
  165. package/src/canvas/iframe-subtree.ts +5 -8
  166. package/src/canvas/path-mapping.ts +25 -3
  167. package/src/canvas/popover-path.ts +106 -0
  168. package/src/canvas/popover-state.ts +155 -0
  169. package/src/canvas/surface-registry.ts +21 -10
  170. package/src/collab/presence-chips.ts +51 -73
  171. package/src/commands/app-commands.ts +10 -0
  172. package/src/commands/budget.ts +12 -0
  173. package/src/commands/command-args.ts +369 -6
  174. package/src/commands/defaults.ts +44 -14
  175. package/src/commands/live-context.ts +11 -5
  176. package/src/commands/reference.ts +12 -2
  177. package/src/commands/registry.ts +165 -8
  178. package/src/content/entry-commands.ts +16 -23
  179. package/src/content/entry-editor.ts +144 -101
  180. package/src/editor/canvas-slash-bridge.ts +2 -2
  181. package/src/editor/context-menu.ts +49 -200
  182. package/src/editor/convert-to-component.ts +42 -82
  183. package/src/editor/convert-to-repeater.ts +132 -173
  184. package/src/editor/inline-edit.ts +11 -0
  185. package/src/editor/shortcuts.ts +65 -26
  186. package/src/editor/slash-menu.ts +150 -157
  187. package/src/files/file-ops.ts +117 -11
  188. package/src/files/files.ts +943 -660
  189. package/src/files/json-layout.ts +474 -0
  190. package/src/files/serialize-document.ts +8 -1
  191. package/src/format/convert-file.ts +16 -10
  192. package/src/format/format-host.ts +50 -1
  193. package/src/github/github-auth.ts +71 -29
  194. package/src/github/github-publish.ts +57 -65
  195. package/src/grid/cell-editors.ts +46 -4
  196. package/src/grid/cell-popovers.ts +65 -62
  197. package/src/grid/grid-open.ts +86 -64
  198. package/src/grid/grid-panel.ts +390 -469
  199. package/src/grid/redirects-grid.ts +40 -44
  200. package/src/hosting/layout.ts +2 -0
  201. package/src/i18n/i18n-commands.ts +127 -62
  202. package/src/media/media-pane.ts +83 -133
  203. package/src/new-project/add-repo-modal.ts +125 -176
  204. package/src/new-project/import-tab.ts +181 -252
  205. package/src/new-project/location-fields.ts +93 -160
  206. package/src/new-project/new-project-modal.ts +376 -367
  207. package/src/packages/jxsuite-update.ts +76 -18
  208. package/src/panels/activity-panel.ts +137 -104
  209. package/src/panels/ai-chat/chat-markdown.ts +15 -13
  210. package/src/panels/ai-chat/chat-view.ts +307 -472
  211. package/src/panels/ai-chat/composer.ts +175 -163
  212. package/src/panels/ai-chat/sessions-view.ts +31 -62
  213. package/src/panels/ai-panel.ts +210 -185
  214. package/src/panels/block-action-bar.ts +437 -643
  215. package/src/panels/bottom-dock.ts +112 -47
  216. package/src/panels/chat-panel.ts +19 -14
  217. package/src/panels/data-explorer.ts +141 -102
  218. package/src/panels/data-grid.ts +183 -150
  219. package/src/panels/dnd.ts +75 -20
  220. package/src/panels/editors.ts +26 -19
  221. package/src/panels/elements-panel.ts +243 -186
  222. package/src/panels/empty-state.ts +26 -42
  223. package/src/panels/events-panel.ts +950 -729
  224. package/src/panels/formula-workspace.ts +434 -207
  225. package/src/panels/frontmatter-fields.ts +185 -153
  226. package/src/panels/frontmatter-panel.ts +411 -187
  227. package/src/panels/git-diff-open.ts +148 -0
  228. package/src/panels/git-panel.ts +679 -605
  229. package/src/panels/head-panel.ts +617 -435
  230. package/src/panels/i18n-panel.ts +153 -133
  231. package/src/panels/imports-panel.ts +388 -414
  232. package/src/panels/jump-bar.ts +174 -147
  233. package/src/panels/layers-panel.ts +785 -671
  234. package/src/panels/left-panel.ts +166 -94
  235. package/src/panels/navigator-panels.ts +1 -1
  236. package/src/panels/pane-context.ts +529 -677
  237. package/src/panels/pane-grid.ts +265 -241
  238. package/src/panels/panel-registry.ts +15 -4
  239. package/src/panels/problems-panel.ts +177 -99
  240. package/src/panels/properties-panel.ts +1525 -966
  241. package/src/panels/provenance.ts +31 -113
  242. package/src/panels/quick-search.ts +217 -172
  243. package/src/panels/right-panel.ts +135 -169
  244. package/src/panels/seo-modal.ts +346 -167
  245. package/src/panels/settings-menu.ts +109 -646
  246. package/src/panels/settings-pane.ts +102 -86
  247. package/src/panels/signals-panel.ts +1318 -1172
  248. package/src/panels/statement-editor.ts +556 -428
  249. package/src/panels/style-panel.ts +1367 -630
  250. package/src/panels/style-utils.ts +36 -32
  251. package/src/panels/stylebook-doc.ts +30 -73
  252. package/src/panels/stylebook-layers-panel.ts +202 -109
  253. package/src/panels/stylebook-panel.ts +124 -88
  254. package/src/panels/tab-strip.ts +385 -287
  255. package/src/platforms/cloud.ts +106 -16
  256. package/src/platforms/devserver.ts +13 -0
  257. package/src/publish/deploy-checklist.ts +124 -78
  258. package/src/publish/publish-commands.ts +4 -12
  259. package/src/publish/publish-panel.ts +134 -328
  260. package/src/services/a11y-report.ts +100 -43
  261. package/src/services/ai-command-tools.ts +468 -0
  262. package/src/services/ai-session-store.ts +6 -0
  263. package/src/services/ai-system-prompt.ts +110 -18
  264. package/src/services/ai-tools.ts +28 -143
  265. package/src/services/ai-write-report.ts +174 -0
  266. package/src/services/document-assistant.ts +50 -2
  267. package/src/services/idle.ts +16 -14
  268. package/src/services/live-surfaces.ts +237 -0
  269. package/src/services/model-uri.ts +75 -0
  270. package/src/services/notify.ts +63 -6
  271. package/src/services/popover-report.ts +325 -0
  272. package/src/services/surface-registry.ts +56 -0
  273. package/src/services/tool-executor.ts +6 -0
  274. package/src/settings/contexts-section.ts +301 -299
  275. package/src/settings/contributed-section.ts +361 -222
  276. package/src/settings/css-vars-editor.ts +320 -325
  277. package/src/settings/defs-editor.ts +572 -535
  278. package/src/settings/dependencies-editor.ts +79 -107
  279. package/src/settings/extension-commands.ts +379 -0
  280. package/src/settings/extension-rows.ts +113 -0
  281. package/src/settings/extensions-section.ts +287 -0
  282. package/src/settings/general-settings.ts +130 -181
  283. package/src/settings/head-editor.ts +10 -305
  284. package/src/settings/locales-section.ts +146 -196
  285. package/src/settings/preferences-accounts.ts +1 -1
  286. package/src/settings/preferences-dialog.ts +350 -330
  287. package/src/settings/project-sections.ts +108 -181
  288. package/src/settings/schema-field-ui.ts +11 -399
  289. package/src/settings/section-registry.ts +8 -1
  290. package/src/settings/settings-document.ts +31 -29
  291. package/src/shell/tree.ts +42 -87
  292. package/src/shell.ts +48 -36
  293. package/src/studio.ts +90 -67
  294. package/src/style/token-ref.ts +0 -39
  295. package/src/surfaces/about.json +263 -0
  296. package/src/surfaces/about.ts +163 -0
  297. package/src/surfaces/add-repo.json +486 -0
  298. package/src/surfaces/add-repo.ts +236 -0
  299. package/src/surfaces/ai-chat.json +2185 -0
  300. package/src/surfaces/ai-chat.ts +549 -0
  301. package/src/surfaces/ai-credentials-form.json +332 -0
  302. package/src/surfaces/ai-credentials-form.ts +151 -0
  303. package/src/surfaces/ai-managed-connect.json +108 -0
  304. package/src/surfaces/ai-managed-connect.ts +123 -0
  305. package/src/surfaces/ai-model-picker.json +114 -0
  306. package/src/surfaces/ai-model-picker.ts +139 -0
  307. package/src/surfaces/block-action-bar.json +640 -0
  308. package/src/surfaces/block-action-bar.ts +368 -0
  309. package/src/surfaces/bottom-dock.json +154 -0
  310. package/src/surfaces/bottom-dock.ts +125 -0
  311. package/src/surfaces/canvas-stage.json +444 -0
  312. package/src/surfaces/canvas-stage.ts +253 -0
  313. package/src/surfaces/cf-account-picker.json +300 -0
  314. package/src/surfaces/cf-account-picker.ts +214 -0
  315. package/src/surfaces/commandbar.json +984 -0
  316. package/src/{panels/toolbar.ts → surfaces/commandbar.ts} +414 -389
  317. package/src/surfaces/convert-repeater.json +309 -0
  318. package/src/surfaces/convert-repeater.ts +276 -0
  319. package/src/surfaces/data-actions.json +157 -0
  320. package/src/surfaces/data-actions.ts +115 -0
  321. package/src/surfaces/dialog.json +289 -0
  322. package/src/surfaces/dialog.ts +343 -0
  323. package/src/surfaces/diff-toolbar.json +266 -0
  324. package/src/surfaces/diff-toolbar.ts +139 -0
  325. package/src/surfaces/doc-header.json +739 -0
  326. package/src/surfaces/doc-header.ts +223 -0
  327. package/src/surfaces/empty-state.json +152 -0
  328. package/src/surfaces/empty-state.ts +173 -0
  329. package/src/surfaces/entry-editor.json +281 -0
  330. package/src/surfaces/entry-editor.ts +191 -0
  331. package/src/surfaces/expression-editor.json +977 -0
  332. package/src/surfaces/expression-editor.ts +266 -0
  333. package/src/surfaces/files-panel.json +592 -0
  334. package/src/surfaces/files-panel.ts +301 -0
  335. package/src/surfaces/formula-palette.json +364 -0
  336. package/src/surfaces/formula-palette.ts +340 -0
  337. package/src/surfaces/git-panel.json +1822 -0
  338. package/src/surfaces/git-panel.ts +272 -0
  339. package/src/surfaces/github-auth.json +112 -0
  340. package/src/surfaces/github-auth.ts +139 -0
  341. package/src/surfaces/github-publish.json +206 -0
  342. package/src/surfaces/github-publish.ts +169 -0
  343. package/src/surfaces/grid-cell.json +218 -0
  344. package/src/surfaces/grid-cell.ts +120 -0
  345. package/src/surfaces/grid-open.json +147 -0
  346. package/src/surfaces/grid-open.ts +87 -0
  347. package/src/surfaces/grid-panel.json +706 -0
  348. package/src/surfaces/grid-panel.ts +206 -0
  349. package/src/surfaces/grid-replace.json +179 -0
  350. package/src/surfaces/grid-replace.ts +89 -0
  351. package/src/surfaces/grid-views.json +446 -0
  352. package/src/surfaces/grid-views.ts +172 -0
  353. package/src/surfaces/inspector-dock.json +187 -0
  354. package/src/surfaces/inspector-dock.ts +161 -0
  355. package/src/surfaces/jump-bar.json +243 -0
  356. package/src/surfaces/jump-bar.ts +129 -0
  357. package/src/surfaces/jxsuite-update.json +146 -0
  358. package/src/surfaces/jxsuite-update.ts +149 -0
  359. package/src/surfaces/library-pane.json +1509 -0
  360. package/src/surfaces/library-pane.ts +363 -0
  361. package/src/surfaces/logic-panel.json +1949 -0
  362. package/src/surfaces/logic-panel.ts +369 -0
  363. package/src/surfaces/logic-workspace.json +685 -0
  364. package/src/surfaces/logic-workspace.ts +238 -0
  365. package/src/surfaces/media-browser.json +303 -0
  366. package/src/surfaces/media-browser.ts +145 -0
  367. package/src/surfaces/media-field.json +163 -0
  368. package/src/surfaces/media-field.ts +116 -0
  369. package/src/surfaces/media-pane.json +513 -0
  370. package/src/surfaces/media-pane.ts +197 -0
  371. package/src/surfaces/menu.json +232 -0
  372. package/src/surfaces/menu.ts +375 -0
  373. package/src/surfaces/navigator-dock.json +113 -0
  374. package/src/surfaces/navigator-dock.ts +130 -0
  375. package/src/surfaces/new-project.json +1654 -0
  376. package/src/surfaces/new-project.ts +411 -0
  377. package/src/surfaces/palette.json +535 -0
  378. package/src/surfaces/pane-context.json +1497 -0
  379. package/src/surfaces/pane-context.ts +513 -0
  380. package/src/surfaces/pane-grid.json +188 -0
  381. package/src/surfaces/pane-grid.ts +250 -0
  382. package/src/surfaces/panel-activity.json +563 -0
  383. package/src/surfaces/panel-activity.ts +187 -0
  384. package/src/surfaces/panel-data.json +141 -0
  385. package/src/surfaces/panel-data.ts +156 -0
  386. package/src/surfaces/panel-deploy-checklist.json +283 -0
  387. package/src/surfaces/panel-deploy-checklist.ts +175 -0
  388. package/src/surfaces/panel-elements.json +367 -0
  389. package/src/surfaces/panel-elements.ts +175 -0
  390. package/src/surfaces/panel-i18n.json +569 -0
  391. package/src/surfaces/panel-i18n.ts +212 -0
  392. package/src/surfaces/panel-imports.json +780 -0
  393. package/src/surfaces/panel-imports.ts +209 -0
  394. package/src/surfaces/panel-outline.json +734 -0
  395. package/src/surfaces/panel-outline.ts +326 -0
  396. package/src/surfaces/panel-page.json +1017 -0
  397. package/src/surfaces/panel-page.ts +240 -0
  398. package/src/surfaces/panel-problems.json +497 -0
  399. package/src/surfaces/panel-problems.ts +157 -0
  400. package/src/surfaces/panel-signals.json +1973 -0
  401. package/src/surfaces/panel-signals.ts +436 -0
  402. package/src/surfaces/panel-stylebook-layers.json +317 -0
  403. package/src/surfaces/panel-stylebook-layers.ts +155 -0
  404. package/src/surfaces/preferences.json +850 -0
  405. package/src/surfaces/preferences.ts +332 -0
  406. package/src/surfaces/progress-modal.json +110 -0
  407. package/src/surfaces/progress-modal.ts +150 -0
  408. package/src/surfaces/properties-panel.json +1578 -0
  409. package/src/surfaces/properties-panel.ts +337 -0
  410. package/src/surfaces/publish.json +945 -0
  411. package/src/surfaces/publish.ts +392 -0
  412. package/src/surfaces/push-plan.json +110 -0
  413. package/src/surfaces/push-plan.ts +87 -0
  414. package/src/surfaces/rail.json +255 -0
  415. package/src/surfaces/rail.ts +206 -0
  416. package/src/surfaces/reference-field.json +191 -0
  417. package/src/surfaces/reference-field.ts +168 -0
  418. package/src/surfaces/schema-builder.json +1011 -0
  419. package/src/surfaces/schema-builder.ts +181 -0
  420. package/src/surfaces/schema-form.json +1013 -0
  421. package/src/surfaces/schema-form.ts +287 -0
  422. package/src/surfaces/secret-field.json +60 -0
  423. package/src/surfaces/secret-field.ts +146 -0
  424. package/src/surfaces/seo.json +932 -0
  425. package/src/surfaces/seo.ts +334 -0
  426. package/src/surfaces/settings-contexts.json +538 -0
  427. package/src/surfaces/settings-contexts.ts +196 -0
  428. package/src/surfaces/settings-contributed.json +489 -0
  429. package/src/surfaces/settings-contributed.ts +199 -0
  430. package/src/surfaces/settings-css-vars.json +820 -0
  431. package/src/surfaces/settings-css-vars.ts +199 -0
  432. package/src/surfaces/settings-defs.json +1363 -0
  433. package/src/surfaces/settings-defs.ts +232 -0
  434. package/src/surfaces/settings-deploy.json +108 -0
  435. package/src/surfaces/settings-deploy.ts +135 -0
  436. package/src/surfaces/settings-extensions.json +486 -0
  437. package/src/surfaces/settings-extensions.ts +201 -0
  438. package/src/surfaces/settings-head.json +779 -0
  439. package/src/surfaces/settings-head.ts +397 -0
  440. package/src/surfaces/settings-locales.json +420 -0
  441. package/src/surfaces/settings-locales.ts +137 -0
  442. package/src/surfaces/settings-overview.json +423 -0
  443. package/src/surfaces/settings-overview.ts +218 -0
  444. package/src/surfaces/settings-packages.json +549 -0
  445. package/src/surfaces/settings-packages.ts +158 -0
  446. package/src/surfaces/settings-pane.json +147 -0
  447. package/src/surfaces/settings-pane.ts +150 -0
  448. package/src/surfaces/settings-rawjson.json +104 -0
  449. package/src/surfaces/settings-rawjson.ts +107 -0
  450. package/src/surfaces/shell.json +99 -0
  451. package/src/surfaces/shell.ts +30 -0
  452. package/src/surfaces/slash-menu.json +180 -0
  453. package/src/surfaces/slash-menu.ts +272 -0
  454. package/src/surfaces/statements.json +607 -0
  455. package/src/surfaces/statements.ts +238 -0
  456. package/src/surfaces/statusbar.json +94 -0
  457. package/src/{panels → surfaces}/statusbar.ts +163 -90
  458. package/src/surfaces/style-panel.json +1643 -0
  459. package/src/surfaces/style-panel.ts +338 -0
  460. package/src/surfaces/stylebook-chrome.json +122 -0
  461. package/src/surfaces/stylebook-chrome.ts +122 -0
  462. package/src/surfaces/tab-strip.json +448 -0
  463. package/src/surfaces/tab-strip.ts +200 -0
  464. package/src/surfaces/target-line.json +419 -0
  465. package/src/surfaces/target-line.ts +349 -0
  466. package/src/surfaces/toasts.json +189 -0
  467. package/src/surfaces/welcome.json +571 -0
  468. package/src/surfaces/welcome.ts +338 -0
  469. package/src/tabs/project-config.ts +71 -15
  470. package/src/tabs/tab.ts +52 -1
  471. package/src/types.ts +22 -0
  472. package/src/ui/ai-credentials-form.ts +104 -100
  473. package/src/ui/ai-managed-connect.ts +54 -36
  474. package/src/ui/ai-model-picker.ts +75 -47
  475. package/src/ui/cf-account-picker.ts +76 -141
  476. package/src/ui/color-selector.ts +80 -301
  477. package/src/ui/dynamic-slot.ts +43 -283
  478. package/src/ui/expression-editor.ts +797 -576
  479. package/src/ui/field-input.ts +8 -181
  480. package/src/ui/form-controls.ts +838 -366
  481. package/src/ui/formula-chips.ts +80 -85
  482. package/src/ui/kit.ts +33 -0
  483. package/src/ui/layers.ts +293 -593
  484. package/src/ui/media-picker.ts +203 -284
  485. package/src/ui/panel-resize.ts +251 -64
  486. package/src/ui/popover-surface.ts +153 -0
  487. package/src/ui/progress-modal.ts +22 -60
  488. package/src/ui/regions.ts +13 -7
  489. package/src/ui/schema-form.ts +906 -440
  490. package/src/ui/surface.ts +122 -0
  491. package/src/ui/unit-selector.ts +15 -131
  492. package/src/ui/value-source.ts +14 -0
  493. package/src/ui/virtual-window.ts +88 -9
  494. package/src/utils/canvas-media.ts +72 -0
  495. package/src/utils/edit-display.ts +7 -2
  496. package/src/utils/element-selectors.ts +69 -0
  497. package/src/utils/link-target.ts +2 -2
  498. package/src/utils/studio-utils.ts +0 -10
  499. package/src/view.ts +15 -0
  500. package/src/workspace/pane-derive.ts +36 -14
  501. package/src/workspace/workspace.ts +15 -6
  502. package/styles/canvas.css +72 -467
  503. package/styles/forced-colors.css +48 -82
  504. package/styles/forced-colors.json +41 -0
  505. package/styles/inspector.css +2 -1301
  506. package/styles/overlays.css +96 -2823
  507. package/styles/panels.css +6 -1423
  508. package/styles/shell-frame.css +272 -0
  509. package/styles/shell-frame.json +227 -0
  510. package/styles/shell.css +0 -1568
  511. package/styles/tokens.css +65 -136
  512. package/styles/tokens.json +84 -0
  513. package/dist/chunks/Overlay.dev-etqjwyf9.js +0 -23
  514. package/dist/chunks/adapter-jkcyhgtr.js +0 -14
  515. package/dist/chunks/cf-account-picker-en86v7x7.js +0 -163
  516. package/dist/chunks/cf-settings-45fgyx8y.js +0 -21
  517. package/dist/chunks/components-zmx10t62.js +0 -21
  518. package/dist/chunks/content-source-48xg86wj.js +0 -49
  519. package/dist/chunks/convert-to-repeater-43tfn7cs.js +0 -268
  520. package/dist/chunks/editor-cptq5jp1.js +0 -37
  521. package/dist/chunks/entry-commands-e63f1xc0.js +0 -46
  522. package/dist/chunks/extension-sections-txv08xxg.js +0 -311
  523. package/dist/chunks/file-ops-wbh4hhsx.js +0 -48
  524. package/dist/chunks/files-3kfkwhk4.js +0 -93
  525. package/dist/chunks/flow-qbfgrpeh.js +0 -634
  526. package/dist/chunks/focus-trap.esm-9t2drp0g.js +0 -1025
  527. package/dist/chunks/focus-visible-6eg70z18.js +0 -167
  528. package/dist/chunks/format-host-w16q81tf.js +0 -43
  529. package/dist/chunks/fs-events-hrrg328g.js +0 -21
  530. package/dist/chunks/git-panel-532whr1y.js +0 -59
  531. package/dist/chunks/index-zqxmqxmh.js +0 -109
  532. package/dist/chunks/jx-validate-8er6gbxy.js +0 -19
  533. package/dist/chunks/layers-panel-07hm7g5j.js +0 -67
  534. package/dist/chunks/layers-q75tj2mf.js +0 -45
  535. package/dist/chunks/lit-html-j055mkh8.js +0 -22
  536. package/dist/chunks/monaco-buffer-dqw0xxpx.js +0 -25
  537. package/dist/chunks/notify-yjm79n4s.js +0 -30
  538. package/dist/chunks/parse-24d0gay3.js +0 -19
  539. package/dist/chunks/platform-ba1j1gbh.js +0 -16
  540. package/dist/chunks/publish-panel-v9st96ja.js +0 -29
  541. package/dist/chunks/quick-search-zccjp6gv.js +0 -66
  542. package/dist/chunks/references-3qx8fkyp.js +0 -29
  543. package/dist/chunks/right-panel-vm3b6kwy.js +0 -46
  544. package/dist/chunks/section-registry-sx1ykvkw.js +0 -30
  545. package/dist/chunks/sp-overlay.dev-qgvhnxf4.js +0 -18
  546. package/dist/chunks/sp-popover.dev-n2etmqdp.js +0 -9
  547. package/dist/chunks/sp-progress-circle.dev-hryhj0es.js +0 -15
  548. package/dist/chunks/sp-tooltip.dev-4sastdnw.js +0 -15
  549. package/dist/chunks/sp-tray.dev-tkbscm06.js +0 -199
  550. package/dist/chunks/studio-0a5qrh01.js +0 -3
  551. package/dist/chunks/studio-0bq6eh7v.js +0 -12
  552. package/dist/chunks/studio-18j3bmcz.js +0 -14
  553. package/dist/chunks/studio-1ngbejft.js +0 -181
  554. package/dist/chunks/studio-4b5z1x43.js +0 -424
  555. package/dist/chunks/studio-4n2b5gzb.js +0 -357
  556. package/dist/chunks/studio-4rzyrtjz.js +0 -426
  557. package/dist/chunks/studio-5fx3g9jg.js +0 -4325
  558. package/dist/chunks/studio-5myknm0a.js +0 -1903
  559. package/dist/chunks/studio-7afd21nw.js +0 -67
  560. package/dist/chunks/studio-7nte2hj4.js +0 -613
  561. package/dist/chunks/studio-8jpzqk5s.js +0 -128
  562. package/dist/chunks/studio-8q517dfr.js +0 -24
  563. package/dist/chunks/studio-950k0dx6.js +0 -6939
  564. package/dist/chunks/studio-9n4mrmnb.js +0 -184
  565. package/dist/chunks/studio-a0tswy0w.js +0 -58
  566. package/dist/chunks/studio-ahnzd9rg.js +0 -23
  567. package/dist/chunks/studio-cmb03bg5.js +0 -13890
  568. package/dist/chunks/studio-d1ks410h.js +0 -175
  569. package/dist/chunks/studio-ef49pnzx.js +0 -387
  570. package/dist/chunks/studio-eqq1w638.js +0 -113
  571. package/dist/chunks/studio-ew0djmhg.js +0 -341
  572. package/dist/chunks/studio-gfgb8pe6.js +0 -1652
  573. package/dist/chunks/studio-h4rxscfc.js +0 -10
  574. package/dist/chunks/studio-jc994dnr.js +0 -1066
  575. package/dist/chunks/studio-kyh9avvv.js +0 -28
  576. package/dist/chunks/studio-m3hwn7y1.js +0 -120
  577. package/dist/chunks/studio-mtfnaqs9.js +0 -659
  578. package/dist/chunks/studio-n6j9t10q.js +0 -318
  579. package/dist/chunks/studio-n8b9wqwy.js +0 -291
  580. package/dist/chunks/studio-qcy05dp8.js +0 -1743
  581. package/dist/chunks/studio-qq6jym04.js +0 -53
  582. package/dist/chunks/studio-rdx8jcxy.js +0 -83
  583. package/dist/chunks/studio-rn9ta2mz.js +0 -111
  584. package/dist/chunks/studio-t7qb9db8.js +0 -665
  585. package/dist/chunks/studio-tmc5emrw.js +0 -8
  586. package/dist/chunks/studio-z6nw2ek2.js +0 -18
  587. package/dist/chunks/studio-zczps70q.js +0 -378
  588. package/dist/chunks/studio-zqazsct2.js +0 -1823
  589. package/dist/chunks/workspace-fjx52ryv.js +0 -89
  590. package/src/panels/activity-bar.ts +0 -251
  591. package/src/panels/panel-scheduler.ts +0 -219
  592. package/src/panels/style-inputs.ts +0 -237
  593. package/src/panels/target-line.ts +0 -274
  594. package/src/panels/welcome-screen.ts +0 -346
  595. package/src/ui/button-group.ts +0 -102
  596. package/src/ui/choice-field.ts +0 -72
  597. package/src/ui/field-row.ts +0 -249
  598. package/src/ui/formula-palette.ts +0 -213
  599. package/src/ui/icons.ts +0 -52
  600. package/src/ui/jx-theme.ts +0 -130
  601. package/src/ui/spectrum.ts +0 -340
  602. package/src/ui/value-selector.ts +0 -174
  603. package/src/ui/widgets.ts +0 -172
  604. /package/dist/chunks/{javascript-s56a8dpk.css → javascript-4abzjcy9.css} +0 -0
  605. /package/dist/chunks/{jsonMode-zr9sw0c7.css → jsonMode-vvmpmk34.css} +0 -0
  606. /package/dist/chunks/{monaco-setup-pav68602.css → monaco-setup-8vbyqnhr.css} +0 -0
  607. /package/dist/chunks/{tsMode-ef187txx.css → tsMode-hnxxb73h.css} +0 -0
@@ -8,6 +8,12 @@
8
8
  * so the catalogue, the canvas and this form all read the same vocabulary; this module is the form
9
9
  * over it.
10
10
  *
11
+ * **The markup left.** The section is the `settings-css-vars` surface
12
+ * (`surfaces/settings-css-vars.json`), mounted by `surfaces/settings-css-vars.ts`; what is here is
13
+ * the part that was always this module's — what a row shows, what an edit writes, and what a failed
14
+ * write says. `renderCssVarsEditor` is unchanged as a contract: the registry hands a container to a
15
+ * `render`, and this one mounts a document into it instead of rendering lit.
16
+ *
11
17
  * Three things it does NOT do, each on purpose:
12
18
  *
13
19
  * - **It does not define a context.** Breakpoints and colour schemes are declared once, in Project
@@ -20,27 +26,33 @@
20
26
  * change" true of the specimen canvas as well as the page one.
21
27
  */
22
28
 
23
- import { html, render as litRender, nothing } from "lit-html";
24
- import { ref } from "lit-html/directives/ref.js";
25
- import { classMap } from "lit-html/directives/class-map.js";
26
29
  import { errorMessage } from "@jxsuite/schema/parse";
27
30
  import { notify } from "../services/notify";
28
31
  import { projectState } from "../store";
29
32
  import { getEffectiveMedia, updateSiteConfig } from "../site-context";
30
33
  import {
34
+ TOKEN_GROUPS,
31
35
  addableContexts,
32
36
  groupTokens,
33
37
  listTokenContexts,
34
38
  readTokenOverride,
39
+ tokenLabel,
35
40
  writeTokenOverride,
36
41
  } from "../style/project-styles";
37
- import { renderTokenChip, resolveTokenValue, tokenRefName } from "../style/token-ref";
42
+ import { resolveTokenValue, toTokenRef, tokenRefName } from "../style/token-ref";
38
43
  import { pushProjectStylesToCanvas } from "../style/live-preview";
44
+ import { renderCssVarsSurface } from "../surfaces/settings-css-vars";
39
45
  import { friendlyNameToVar } from "../utils/studio-utils";
40
46
 
41
- import type { JxStyle } from "@jxsuite/schema/types";
47
+ import type { JxStyle, ProjectConfig } from "@jxsuite/schema/types";
42
48
  import type { ProjectToken, TokenContext, TokenGroup, TokenGroupId } from "../style/project-styles";
43
- import type { TemplateResult } from "lit-html";
49
+ import type {
50
+ CssVarsActions,
51
+ CssVarsView,
52
+ GroupView,
53
+ OverrideRowView,
54
+ TokenRowView,
55
+ } from "../surfaces/settings-css-vars";
44
56
 
45
57
  /**
46
58
  * What each group's add row hints with — an example friendly name and an example value. These are
@@ -60,379 +72,362 @@ const COLOR_INPUT_FALLBACK = "#3b82f6";
60
72
  /** The same, for an override row: a scheme override is usually a darker value than the base. */
61
73
  const OVERRIDE_INPUT_FALLBACK = "#111111";
62
74
 
63
- /** What one token row needs from the surrounding form — bound once per render, not per row. */
64
- interface TokenFormCtx {
65
- /** The project's root style, mutated in place and persisted through {@link updateSiteConfig}. */
66
- rootStyle: JxStyle;
67
- /** Every declared rendering context, schemes first ({@link listTokenContexts}). */
68
- contexts: TokenContext[];
69
- /** Commit the current style without re-rendering the form. */
70
- save: () => void;
71
- /** Commit and re-render — for anything that changes which rows exist. */
72
- commit: () => void;
73
- }
75
+ /** The picker's own first row: what it reads while nothing has been picked. */
76
+ const ADD_OVERRIDE_ROW = { label: "Add override…", value: "" };
74
77
 
75
78
  /**
76
- * Render the token editor into a container.
79
+ * The add row being typed into, per group, and the last write that failed.
77
80
  *
78
- * @param {HTMLElement} container
81
+ * Keyed by container so two mounted copies (and two tests) never share either — the same shape
82
+ * `general-settings.ts` and `locales-section.ts` use, and for the same reason: this section saves
83
+ * on change, so a silent rejection reads as "my edit just vanished". The pending add row is here
84
+ * rather than in the document because typing must survive the section being redrawn from outside;
85
+ * its predecessor held the two values in the DOM through `ref()`, which meant every redraw emptied
86
+ * them and the reader lost half a token name to a nav click they did not make.
79
87
  */
80
- export function renderCssVarsEditor(container: HTMLElement) {
81
- const config = projectState?.projectConfig || {};
82
- const rootStyle = (config.style || {}) as JxStyle;
83
- const contexts = listTokenContexts(getEffectiveMedia(config.$media));
84
- const hasScheme = contexts.some((c) => c.kind === "scheme");
85
-
86
- const save = () => {
87
- void updateSiteConfig({ style: { ...rootStyle } });
88
- pushProjectStylesToCanvas();
89
- };
90
-
91
- const commit = () => {
92
- save();
93
- renderCssVarsEditor(container);
94
- };
95
-
96
- const ctx: TokenFormCtx = { commit, contexts, rootStyle, save };
97
-
98
- const addVar = (prefix: string, friendlyName: string, val: string) => {
99
- const varName = friendlyNameToVar(friendlyName, prefix);
100
- if (!varName || !val) {
101
- return;
102
- }
103
- rootStyle[varName] = val;
104
- commit();
105
- };
88
+ interface Form {
89
+ add: Partial<Record<TokenGroupId, { name: string; value: string }>>;
90
+ error: string;
91
+ }
106
92
 
107
- /*
108
- * Without a declared scheme query there is nothing to override, so this section can only point at
109
- * the place a scheme is DEFINED. It used to define one itself — a button here appended
110
- * `'--dark': '(prefers-color-scheme: dark)'` to `$media` without ever using the word breakpoint,
111
- * which made this form the fourth and least discoverable definition site for a map whose other
112
- * three lived in the wizard, Overview and Properties › Media. The lazy import breaks the
113
- * css-vars-editor ↔ section-registry cycle.
114
- */
115
- const manageContexts = () => {
116
- void import("./section-registry")
117
- .then(({ setSettingsSection }) => setSettingsSection("contexts"))
118
- .catch((error: unknown) => {
119
- notify.error(`Could not open Settings › Contexts — ${errorMessage(error)}`, {
120
- source: "Settings",
121
- });
122
- });
123
- };
93
+ const forms = new WeakMap<HTMLElement, Form>();
124
94
 
125
- const tpl = html`
126
- <div class="settings-section">
127
- <h3 class="settings-section-title">CSS Variables</h3>
128
- ${groupTokens(rootStyle).map(({ group, tokens }) =>
129
- group.id === "other" && tokens.length === 0
130
- ? nothing
131
- : renderGroup(group, tokens, ctx, hasScheme, addVar, manageContexts),
132
- )}
133
- </div>
134
- `;
95
+ /** This container's form, minted on first sight. */
96
+ function form(container: HTMLElement): Form {
97
+ let state = forms.get(container);
98
+ if (!state) {
99
+ state = { add: {}, error: "" };
100
+ forms.set(container, state);
101
+ }
102
+ return state;
103
+ }
135
104
 
136
- litRender(tpl, container);
105
+ /** This container's pending add row for one group, minted on first sight. */
106
+ function pending(container: HTMLElement, group: TokenGroupId): { name: string; value: string } {
107
+ const { add } = form(container);
108
+ return (add[group] ??= { name: "", value: "" });
137
109
  }
138
110
 
139
- /**
140
- * One group: its heading, its token rows, its add row, and — for Colors with no scheme declared —
141
- * the sentence that says where a scheme comes from.
142
- *
143
- * @param {TokenGroup} group
144
- * @param {ProjectToken[]} tokens
145
- * @param {TokenFormCtx} ctx
146
- * @param {boolean} hasScheme
147
- * @param {(prefix: string, friendlyName: string, val: string) => void} addVar
148
- * @param {() => void} manageContexts
149
- */
150
- function renderGroup(
151
- group: TokenGroup,
152
- tokens: ProjectToken[],
153
- ctx: TokenFormCtx,
154
- hasScheme: boolean,
155
- addVar: (prefix: string, friendlyName: string, val: string) => void,
156
- manageContexts: () => void,
157
- ): TemplateResult {
158
- return html`
159
- <div class="css-vars-group">
160
- <h4 class="css-vars-group-title">${group.title}</h4>
161
- ${tokens.map((token) => renderTokenRow(token, group, ctx))} ${renderAddRow(group, addVar)}
162
- ${
163
- group.id === "color" && !hasScheme
164
- ? html`
165
- <p class="settings-field-desc">
166
- No colour scheme is defined yet, so these tokens have one value each.
167
- <sp-action-button
168
- size="s"
169
- quiet
170
- title="Define a colour scheme in Project Settings › Contexts"
171
- @click=${manageContexts}
172
- >
173
- Manage contexts…
174
- </sp-action-button>
175
- </p>
176
- `
177
- : nothing
178
- }
179
- </div>
180
- `;
111
+ /** The live project configuration, or an empty one before a project is open. */
112
+ function config(): ProjectConfig {
113
+ return (projectState?.projectConfig || {}) as ProjectConfig;
181
114
  }
182
115
 
183
116
  /**
184
- * One token: its swatch (colours only), its name, its value field, the chip it wears when that
185
- * value follows another token, its delete button — then its font preview and its overrides.
117
+ * The project's root style block, mutated IN PLACE and then persisted whole.
186
118
  *
187
- * @param {ProjectToken} token
188
- * @param {TokenGroup} group
189
- * @param {TokenFormCtx} ctx
119
+ * The `{}` fallback is a throwaway for a project that declares no styles at all: the first token
120
+ * added to one reaches disk through the patch below and comes back on the refresh that follows the
121
+ * write, because there is no object here for it to have been written into.
190
122
  */
191
- function renderTokenRow(token: ProjectToken, group: TokenGroup, ctx: TokenFormCtx): TemplateResult {
192
- const { rootStyle } = ctx;
193
- const isColor = group.id === "color";
194
- const refName = tokenRefName(token.value);
195
- const resolved = resolveTokenValue(rootStyle, token.value);
196
-
197
- const updateVar = (val: string) => {
198
- rootStyle[token.name] = val;
199
- ctx.save();
200
- };
201
- const deleteVar = () => {
202
- delete rootStyle[token.name];
203
- ctx.commit();
204
- };
123
+ function style(): JxStyle {
124
+ return (config().style || {}) as JxStyle;
125
+ }
205
126
 
206
- return html`
207
- <div class="css-var-row">
208
- ${isColor ? renderSwatch(resolved, COLOR_INPUT_FALLBACK, updateVar) : nothing}
209
- <span class="css-var-name">${token.label}</span>
210
- <sp-textfield
211
- size="s"
212
- .value=${String(token.value)}
213
- @change=${(e: Event) => updateVar((e.target as HTMLInputElement).value)}
214
- style=${valueFieldStyle(group)}
215
- ></sp-textfield>
216
- ${refName ? renderTokenChip(refName, resolved, { swatch: isColor }) : nothing}
217
- <sp-action-button quiet size="s" title="Delete ${token.label}" @click=${deleteVar}>
218
- <sp-icon-delete slot="icon"></sp-icon-delete>
219
- </sp-action-button>
220
- </div>
221
- ${
222
- group.id === "font"
223
- ? html`<div class="css-var-font-preview" style="font-family:${String(token.value)}">
224
- The quick brown fox jumps over the lazy dog
225
- </div>`
226
- : nothing
227
- }
228
- ${renderOverrides(token, group, ctx)}
229
- `;
127
+ /** Every rendering context this project declares, schemes first. */
128
+ function contexts(): TokenContext[] {
129
+ return listTokenContexts(getEffectiveMedia(config().$media));
230
130
  }
231
131
 
232
132
  /**
233
- * How wide the value field is — colours and sizes are short values beside a swatch or a unit, fonts
234
- * and free-form tokens are long ones. The predecessor said the same thing four times.
133
+ * Push the mutated style at the canvases, show it, and write it — in that order.
235
134
  *
236
- * @param {TokenGroup} group
135
+ * The canvas and the form are updated synchronously because the edit is already true of the model;
136
+ * the write is awaited only so that its REJECTION has somewhere to land. The predecessor dropped it
137
+ * with a bare `void`, so a read-only `project.json` took every edit and kept none of them without
138
+ * ever saying so.
139
+ *
140
+ * @param {HTMLElement} container
237
141
  */
238
- function valueFieldStyle(group: TokenGroup): string {
239
- if (group.id === "color") {
240
- return "flex:1;max-width:160px";
241
- }
242
- if (group.id === "size") {
243
- return "max-width:120px";
142
+ function commit(container: HTMLElement): void {
143
+ pushProjectStylesToCanvas();
144
+ refresh(container);
145
+ void persist(container);
146
+ }
147
+
148
+ /** @param {HTMLElement} container */
149
+ async function persist(container: HTMLElement): Promise<void> {
150
+ try {
151
+ await updateSiteConfig({ style: { ...style() } });
152
+ form(container).error = "";
153
+ } catch (error) {
154
+ form(container).error = `Could not save project.json — ${errorMessage(error)}`;
244
155
  }
245
- return "flex:1";
156
+ refresh(container);
157
+ }
158
+
159
+ // ─── Projection ──────────────────────────────────────────────────────────────
160
+
161
+ /** The colour a well is painted, and the colour the native input under it opens on. */
162
+ function well(
163
+ resolved: string | number | undefined,
164
+ fallback: string,
165
+ ): { swatchBg: string; swatchInput: string } {
166
+ const swatchBg = resolved === undefined ? "transparent" : String(resolved);
167
+ return { swatchBg, swatchInput: swatchBg.startsWith("#") ? swatchBg : fallback };
246
168
  }
247
169
 
248
170
  /**
249
- * The colour well: a background showing the value the token RESOLVES to (so an alias token is not a
250
- * blank square) over a native colour input.
171
+ * One override row: what this token is in one context, and what an edit to it names.
172
+ *
173
+ * The row carries its token AND its context because the document's inner `$map` shadows the outer
174
+ * one — a row cannot ask which token it hangs under, so it is told.
251
175
  *
252
- * @param {string | number | undefined} resolved
253
- * @param {string} fallback — what the native input shows when the value is not a hex literal
254
- * @param {(val: string) => void} onInput
176
+ * @param {ProjectToken} token
177
+ * @param {TokenContext} context
178
+ * @param {boolean} isColor
179
+ * @param {JxStyle} rootStyle
180
+ * @returns {OverrideRowView}
255
181
  */
256
- function renderSwatch(
257
- resolved: string | number | undefined,
258
- fallback: string,
259
- onInput: (val: string) => void,
260
- ): TemplateResult {
261
- const shown = resolved === undefined ? "transparent" : String(resolved);
262
- return html`
263
- <div class="css-var-swatch" style="background:${shown}">
264
- <input
265
- type="color"
266
- .value=${shown.startsWith("#") ? shown : fallback}
267
- @input=${(e: Event) => onInput((e.target as HTMLInputElement).value)}
268
- />
269
- </div>
270
- `;
182
+ function overrideRow(
183
+ token: ProjectToken,
184
+ context: TokenContext,
185
+ isColor: boolean,
186
+ rootStyle: JxStyle,
187
+ ): OverrideRowView {
188
+ const current = readTokenOverride(rootStyle, context, token.name);
189
+ return {
190
+ ctx: context.name,
191
+ fieldLabel: `${token.label} in ${context.label}`,
192
+ id: `${token.name} ${context.name}`,
193
+ kind: context.kind,
194
+ label: context.label,
195
+ swatchLabel: `${token.label} in ${context.label}`,
196
+ swatchState: isColor ? "swatch" : "none",
197
+ token: token.name,
198
+ value: current === undefined ? "" : String(current),
199
+ ...well(resolveTokenValue(rootStyle, current), OVERRIDE_INPUT_FALLBACK),
200
+ };
271
201
  }
272
202
 
273
203
  /**
274
- * A token's per-context values: one row per context it is overridden in, plus — for a colour, once
275
- * a scheme exists — a row per scheme whether or not it carries a value, because "what is this
276
- * colour in dark mode" is a question a palette is always answering. Then the add affordance.
204
+ * One token row: its value, the chip it wears when that value follows another token, its font
205
+ * preview, its per-context values and the contexts it could still be given one in.
277
206
  *
278
- * The add affordance is the change. Before it, a row appeared only for a token that already had an
279
- * `@media` block, so the first override for any token could only be written by hand in
280
- * `project.json` — the form could edit an override it could not create.
207
+ * A colour's scheme rows are shown whether or not they carry a value, because "what is this colour
208
+ * in dark mode" is a question a palette is always answering. A token with no value is offered no
209
+ * picker: writing an empty override is how one is CLEARED, so the affordance would be inert.
281
210
  *
282
211
  * @param {ProjectToken} token
283
212
  * @param {TokenGroup} group
284
- * @param {TokenFormCtx} ctx
213
+ * @param {JxStyle} rootStyle
214
+ * @param {TokenContext[]} declared
215
+ * @returns {TokenRowView}
285
216
  */
286
- function renderOverrides(
217
+ function tokenRow(
287
218
  token: ProjectToken,
288
219
  group: TokenGroup,
289
- ctx: TokenFormCtx,
290
- ): TemplateResult | typeof nothing {
291
- const { contexts, rootStyle } = ctx;
220
+ rootStyle: JxStyle,
221
+ declared: TokenContext[],
222
+ ): TokenRowView {
292
223
  const isColor = group.id === "color";
293
- const shown = contexts.filter(
224
+ const value = String(token.value);
225
+ const resolved = resolveTokenValue(rootStyle, token.value);
226
+ const refName = tokenRefName(token.value);
227
+ const shown = declared.filter(
294
228
  (context) =>
295
229
  (isColor && context.kind === "scheme") ||
296
230
  readTokenOverride(rootStyle, context, token.name) !== undefined,
297
231
  );
298
- /*
299
- * A token with no value has nothing to give a context, so the picker is not offered rather than
300
- * offered and silently inert — writing an empty override is how one is CLEARED.
301
- */
302
- const addable =
303
- String(token.value) === "" ? [] : addableContexts(rootStyle, contexts, token.name, shown);
232
+ const addable = value === "" ? [] : addableContexts(rootStyle, declared, token.name, shown);
233
+ return {
234
+ addLabel: `Add an override for ${token.label}`,
235
+ addOptions: [ADD_OVERRIDE_ROW, ...addable.map((c) => ({ label: c.label, value: c.name }))],
236
+ addPick: "",
237
+ addState: addable.length === 0 ? "none" : "shown",
238
+ chipLabel: refName === null ? "" : tokenLabel(refName),
239
+ chipState: refName === null ? "none" : isColor && resolved !== undefined ? "swatch" : "plain",
240
+ chipSwatch: resolved === undefined ? "" : String(resolved),
241
+ chipTitle:
242
+ refName === null
243
+ ? ""
244
+ : `${toTokenRef(refName)} → ${resolved === undefined ? "unresolved" : String(resolved)}`,
245
+ label: token.label,
246
+ name: token.name,
247
+ overrides: shown.map((context) => overrideRow(token, context, isColor, rootStyle)),
248
+ overrideState: shown.length === 0 && addable.length === 0 ? "none" : "shown",
249
+ previewFont: group.id === "font" ? value : "",
250
+ previewState: group.id === "font" ? "font" : "none",
251
+ removeLabel: `Delete ${token.label}`,
252
+ swatchLabel: `${token.label} colour`,
253
+ swatchState: isColor ? "swatch" : "none",
254
+ value,
255
+ ...well(isColor ? resolved : undefined, COLOR_INPUT_FALLBACK),
256
+ };
257
+ }
304
258
 
305
- if (shown.length === 0 && addable.length === 0) {
306
- return nothing;
259
+ /**
260
+ * What the section shows right now.
261
+ *
262
+ * Read from `config()` at the moment of drawing rather than carried from the last one:
263
+ * `projectState` is a plain module binding replaced wholesale on a project switch, and an extension
264
+ * or the raw JSON editor can write `style` between two of these.
265
+ *
266
+ * @param {HTMLElement} container
267
+ * @returns {CssVarsView}
268
+ */
269
+ function view(container: HTMLElement): CssVarsView {
270
+ const rootStyle = style();
271
+ const declared = contexts();
272
+ const hasScheme = declared.some((context) => context.kind === "scheme");
273
+ const groups: GroupView[] = [];
274
+ for (const { group, tokens } of groupTokens(rootStyle)) {
275
+ /* A bucket named "Other" over an empty list teaches nothing (§2 principle 6). Every other
276
+ group keeps its heading and its add row, because an empty one is where a palette starts. */
277
+ if (group.id === "other" && tokens.length === 0) {
278
+ continue;
279
+ }
280
+ const draft = pending(container, group.id);
281
+ groups.push({
282
+ addLabel: `Add a ${group.title} variable`,
283
+ addName: draft.name,
284
+ addValue: draft.value,
285
+ id: group.id,
286
+ nameHint: ADD_ROW_HINTS[group.id].name,
287
+ nameLabel: `New ${group.title} name`,
288
+ noticeState: group.id === "color" && !hasScheme ? "shown" : "none",
289
+ title: group.title,
290
+ tokens: tokens.map((token) => tokenRow(token, group, rootStyle, declared)),
291
+ valueHint: ADD_ROW_HINTS[group.id].value,
292
+ valueLabel: `New ${group.title} value`,
293
+ });
307
294
  }
295
+ return { error: form(container).error, groups };
296
+ }
308
297
 
309
- const setOverride = (context: TokenContext, val: string) => {
310
- writeTokenOverride(rootStyle, context, token.name, val);
311
- ctx.commit();
312
- };
298
+ /** Re-read the file and the form, and let the surface reconcile. */
299
+ function refresh(container: HTMLElement): void {
300
+ renderCssVarsSurface(container, view(container), actions(container));
301
+ }
302
+
303
+ // ─── Writes ──────────────────────────────────────────────────────────────────
304
+
305
+ /** The group a token can be added to, by id. */
306
+ function groupOf(id: string): TokenGroup | undefined {
307
+ return TOKEN_GROUPS.find((group) => group.id === id);
308
+ }
313
309
 
314
- return html`
315
- <div class="css-var-media-overrides">
316
- ${shown.map((context) => renderOverrideRow(token, context, isColor, rootStyle, setOverride))}
317
- ${
318
- addable.length === 0
319
- ? nothing
320
- : html`
321
- <div class="css-var-override-add">
322
- <sp-picker
323
- size="s"
324
- quiet
325
- label="Add override"
326
- placeholder="Add override…"
327
- title="Give ${token.label} a different value in one rendering context"
328
- @change=${(e: Event) => {
329
- const name = (e.target as HTMLInputElement).value;
330
- const context = addable.find((c) => c.name === name);
331
- if (context) {
332
- setOverride(context, String(token.value));
333
- }
334
- }}
335
- >
336
- ${addable.map(
337
- (context) =>
338
- html`<sp-menu-item value=${context.name}>${context.label}</sp-menu-item>`,
339
- )}
340
- </sp-picker>
341
- </div>
342
- `
343
- }
344
- </div>
345
- `;
310
+ /** Add the group's pending token, if it names one this project can take. */
311
+ function addToken(container: HTMLElement, groupId: string): void {
312
+ const group = groupOf(groupId);
313
+ if (!group) {
314
+ return;
315
+ }
316
+ const draft = pending(container, group.id);
317
+ const varName = friendlyNameToVar(draft.name, group.prefix);
318
+ if (!varName || !draft.value) {
319
+ return;
320
+ }
321
+ style()[varName] = draft.value;
322
+ draft.name = "";
323
+ draft.value = "";
324
+ commit(container);
346
325
  }
347
326
 
348
327
  /**
349
- * One override row. Empty means "inherits the base value", and clearing a row removes the override
350
- * (and the block, once it empties) — one write path for a scheme and a breakpoint alike.
328
+ * Give a token a value in a context it has none in, seeded from its base value.
351
329
  *
352
- * @param {ProjectToken} token
353
- * @param {TokenContext} context
354
- * @param {boolean} isColor
355
- * @param {JxStyle} rootStyle
356
- * @param {(context: TokenContext, val: string) => void} setOverride
330
+ * A name the picker did not offer is ignored rather than written: the control's first row is the
331
+ * placeholder, whose value is the empty string, and a context that already carries an override is
332
+ * not a context this can create one in.
333
+ *
334
+ * @param {HTMLElement} container
335
+ * @param {string} token
336
+ * @param {string} ctx
357
337
  */
358
- function renderOverrideRow(
359
- token: ProjectToken,
360
- context: TokenContext,
361
- isColor: boolean,
362
- rootStyle: JxStyle,
363
- setOverride: (context: TokenContext, val: string) => void,
364
- ): TemplateResult {
365
- const current = readTokenOverride(rootStyle, context, token.name);
366
- return html`
367
- <div
368
- class=${classMap({
369
- "css-var-media-row": true,
370
- "css-var-scheme-row": context.kind === "scheme",
371
- })}
372
- >
373
- <span class="css-var-media-label">${context.label}</span>
374
- ${
375
- isColor
376
- ? renderSwatch(resolveTokenValue(rootStyle, current), OVERRIDE_INPUT_FALLBACK, (val) =>
377
- setOverride(context, val),
378
- )
379
- : nothing
380
- }
381
- <sp-textfield
382
- size="s"
383
- placeholder="inherits"
384
- .value=${current === undefined ? "" : String(current)}
385
- @change=${(e: Event) => setOverride(context, (e.target as HTMLInputElement).value)}
386
- style=${isColor ? "flex:1;max-width:160px" : "max-width:120px"}
387
- ></sp-textfield>
388
- </div>
389
- `;
338
+ function addOverride(container: HTMLElement, token: string, ctx: string): void {
339
+ const rootStyle = style();
340
+ const context = contexts().find((c) => c.name === ctx);
341
+ if (!context || readTokenOverride(rootStyle, context, token) !== undefined) {
342
+ refresh(container);
343
+ return;
344
+ }
345
+ const base = rootStyle[token];
346
+ if (typeof base !== "string" && typeof base !== "number") {
347
+ return;
348
+ }
349
+ writeTokenOverride(rootStyle, context, token, String(base));
350
+ commit(container);
390
351
  }
391
352
 
392
353
  /**
393
- * The group's "add a token" row: a friendly name, a value, and the button that slugs the one into a
394
- * variable name under the group's prefix.
354
+ * What the reader may do, bound to one container.
395
355
  *
396
- * @param {TokenGroup} group
397
- * @param {(prefix: string, friendlyName: string, val: string) => void} addVar
356
+ * Memoized per container so the surface is handed the same functions every time: they are read
357
+ * once, when it mounts, and a fresh set on every refresh would be a scope write that says nothing.
398
358
  */
399
- function renderAddRow(
400
- group: TokenGroup,
401
- addVar: (prefix: string, friendlyName: string, val: string) => void,
402
- ): TemplateResult {
403
- let nameEl: HTMLInputElement | null = null;
404
- let valEl: HTMLInputElement | null = null;
405
- const hint = ADD_ROW_HINTS[group.id];
359
+ const bound = new WeakMap<HTMLElement, CssVarsActions>();
360
+
361
+ function actions(container: HTMLElement): CssVarsActions {
362
+ let acts = bound.get(container);
363
+ if (!acts) {
364
+ acts = {
365
+ addOverride: (token: string, ctx: string) => {
366
+ addOverride(container, token, ctx);
367
+ },
368
+ addToken: (groupId: string) => {
369
+ addToken(container, groupId);
370
+ },
371
+ /*
372
+ * Without a declared scheme query there is nothing to override, so this section can only
373
+ * point at the place a scheme is DEFINED. It used to define one itself — a button here
374
+ * appended `'--dark': '(prefers-color-scheme: dark)'` to `$media` without ever using the word
375
+ * breakpoint, which made this form the fourth and least discoverable definition site for a
376
+ * map whose other three lived in the wizard, Overview and Properties › Media. The lazy import
377
+ * breaks the css-vars-editor ↔ section-registry cycle.
378
+ */
379
+ manageContexts: () => {
380
+ void import("./section-registry")
381
+ .then(({ setSettingsSection }) => setSettingsSection("contexts"))
382
+ .catch((error: unknown) => {
383
+ notify.error(`Could not open Settings › Contexts — ${errorMessage(error)}`, {
384
+ source: "Settings",
385
+ });
386
+ });
387
+ },
388
+ removeToken: (name: string) => {
389
+ delete style()[name];
390
+ commit(container);
391
+ },
392
+ /*
393
+ * Recorded, and nothing redrawn. The field already holds what the reader typed — a refresh
394
+ * here would re-derive every group, every token and every override row to write each control
395
+ * the value it already has, once per keystroke. What the record buys is the redraw the reader
396
+ * did NOT ask for: a nav click, an extension registering, a write landing. The projection
397
+ * reads it, so the half-typed name comes back rather than being emptied, which is what the
398
+ * predecessor's `ref()` into the DOM could never do.
399
+ */
400
+ setAddName: (groupId: string, value: string) => {
401
+ pending(container, groupId as TokenGroupId).name = value;
402
+ },
403
+ setAddValue: (groupId: string, value: string) => {
404
+ pending(container, groupId as TokenGroupId).value = value;
405
+ },
406
+ setOverride: (token: string, ctx: string, value: string) => {
407
+ const context = contexts().find((c) => c.name === ctx);
408
+ if (!context) {
409
+ return;
410
+ }
411
+ /* The block is recreated on demand, so a caller holding a stale row still writes to the
412
+ right place — and an emptied block is removed rather than left as `"@--dark": {}`. */
413
+ writeTokenOverride(style(), context, token, value);
414
+ commit(container);
415
+ },
416
+ setToken: (name: string, value: string) => {
417
+ style()[name] = value;
418
+ commit(container);
419
+ },
420
+ };
421
+ bound.set(container, acts);
422
+ }
423
+ return acts;
424
+ }
406
425
 
407
- return html`
408
- <div class="css-var-add-row">
409
- <sp-textfield
410
- size="s"
411
- placeholder=${hint.name}
412
- ${ref((el) => {
413
- if (el) {
414
- nameEl = el as HTMLInputElement;
415
- }
416
- })}
417
- ></sp-textfield>
418
- <sp-textfield
419
- size="s"
420
- placeholder=${hint.value}
421
- ${ref((el) => {
422
- if (el) {
423
- valEl = el as HTMLInputElement;
424
- }
425
- })}
426
- ></sp-textfield>
427
- <sp-action-button
428
- size="s"
429
- @click=${() => {
430
- if (nameEl && valEl) {
431
- addVar(group.prefix, nameEl.value, valEl.value);
432
- }
433
- }}
434
- >Add</sp-action-button
435
- >
436
- </div>
437
- `;
426
+ /**
427
+ * The project's design tokens, grouped, with their per-context values.
428
+ *
429
+ * @param {HTMLElement} container
430
+ */
431
+ export function renderCssVarsEditor(container: HTMLElement): void {
432
+ refresh(container);
438
433
  }