@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
@@ -21,6 +21,11 @@ import { componentRegistry } from "../files/components";
21
21
  import { activeRegistry } from "../commands/active-registry";
22
22
  import { registerAiTools } from "./ai-tools";
23
23
  import { cancelAsk, registerAskTool, resetAsk } from "./ai-ask";
24
+ import {
25
+ commandToolBlurbs,
26
+ composeToolRegistries,
27
+ createCommandToolRegistry,
28
+ } from "./ai-command-tools";
24
29
  import { registerProjectTools } from "./ai-project-tools";
25
30
  import { registerImportTools, resetImportGuard } from "./ai-import-tools";
26
31
  import { createGatedToolRegistry } from "./gated-registry";
@@ -29,12 +34,14 @@ import { adoptProject } from "./project-adoption";
29
34
  import { abortImportRun, resetImportRuns } from "./import-run";
30
35
  import { runAgentLoop } from "./tool-executor";
31
36
  import { AI_TOOL_TIERS, buildSystemPrompt, toolActive } from "./ai-system-prompt";
37
+ import type { ExtensionCatalogSummary } from "./ai-system-prompt";
32
38
  import { getBaseUrl, getOpenAiKey } from "./ai-settings";
33
39
  import { preferredModel } from "./ai-models";
34
40
  import { pruneOrphanToolMessages, trimContext } from "./context-manager";
35
41
  import { renderCheck } from "./render-critic";
42
+ import { validateDoc } from "./jx-validate";
36
43
  import { openFileInTab, reloadFileInTab } from "../files/files";
37
- import { refreshExtensionUi } from "../format/format-host";
44
+ import { getExtensionCatalog, refreshExtensionUi } from "../format/format-host";
38
45
  import * as sessionStore from "./ai-session-store";
39
46
 
40
47
  /**
@@ -189,7 +196,26 @@ export function createDocumentAssistant() {
189
196
  },
190
197
  ]),
191
198
  );
192
- const toolRegistry = createGatedToolRegistry(innerRegistry, availability);
199
+ /*
200
+ * The other kind of tool: every command record that declares `aiTool`, as a VIEW over the active
201
+ * registry (`services/ai-command-tools.ts`). Nothing is registered — the record IS the tool, its
202
+ * `when` / `enablement` is the gate, `registry.run` is the executor — so `enable_extension`,
203
+ * `delete_node` and the rest need no row in the tier table and no registrar here. The deps are
204
+ * the write reporter's, the same three the hand tree tools take, because a bridged document write
205
+ * is held to the same verdict (new schema errors, the render check, the token hints).
206
+ */
207
+ const commandTools = createCommandToolRegistry({
208
+ getProjectStyle,
209
+ getTab: () => activeTab.value,
210
+ renderCheck: renderCheck as (
211
+ doc: unknown,
212
+ ) => Promise<{ ok: true } | { ok: false; error: string }>,
213
+ validate: validateDoc,
214
+ });
215
+ const toolRegistry = composeToolRegistries(
216
+ createGatedToolRegistry(innerRegistry, availability),
217
+ commandTools,
218
+ );
193
219
 
194
220
  let controller: AbortController | null = null;
195
221
 
@@ -201,6 +227,19 @@ export function createDocumentAssistant() {
201
227
  .filter((e) => e.type === "file")
202
228
  .map((e) => e.path)
203
229
  : undefined;
230
+ /* The synchronous snapshot beside the async load, exactly as `getExtensions()` sits beside
231
+ `loadExtensions()`: `buildSystemPrompt` is a pure function and this is called per turn, so
232
+ the catalogue is read from the ONE cache the Extensions section also reads. Two caches would
233
+ be two answers to "what can this project turn on". */
234
+ const catalog: ExtensionCatalogSummary[] = [];
235
+ for (const entry of getExtensionCatalog()) {
236
+ catalog.push({
237
+ name: entry.name,
238
+ sections: entry.sections.map((section) => section.key),
239
+ ...(entry.title === undefined ? {} : { title: entry.title }),
240
+ ...(entry.description === undefined ? {} : { description: entry.description }),
241
+ });
242
+ }
204
243
  return buildSystemPrompt({
205
244
  document: tab ? toRaw(tab.doc.document) : undefined,
206
245
  projectConfig: (workspace.projectConfig as ProjectConfig | null) || undefined,
@@ -208,7 +247,16 @@ export function createDocumentAssistant() {
208
247
  projectRoot: workspace.projectRoot || undefined,
209
248
  hasProject: Boolean(workspace.projectRoot),
210
249
  canImport: Boolean(getPlatform().importSite),
250
+ /* The same reading the gate makes, so the prompt advertises exactly what `execute` will
251
+ honour. This was never passed: with Project Settings focused the prompt listed the seven
252
+ hand tree writers while the `document-tree` gate refused every one of them, and the model
253
+ spent a round learning it. */
254
+ treeEditable: treeEditable(),
255
+ /* Read per turn from the live registry — a projected tool the gate will honour this round is
256
+ listed this round, and one it will not is not. */
257
+ commandTools: commandToolBlurbs(activeRegistry()),
211
258
  ...(inventory && inventory.length > 0 ? { fileInventory: inventory } : {}),
259
+ ...(catalog.length > 0 ? { extensionCatalog: catalog } : {}),
212
260
  });
213
261
  }
214
262
 
@@ -12,22 +12,29 @@
12
12
  * in-flight (gitStatus)"]` — so the slow subsystem identifies itself.
13
13
  *
14
14
  * Nothing here polls a subsystem it does not own. Each source is a function the owning module
15
- * already had to write for its own reasons:
15
+ * already had to write for its own reasons.
16
+ *
17
+ * There WAS a seventh, `panel-scheduler.pendingSchedulers()`, and it went with the scheduler. It
18
+ * reported a panel with an animation frame queued or a render withheld while a field had focus —
19
+ * both facts about a lit dock repainting itself. The Navigator and the Inspector are documents now
20
+ * (`surfaces/navigator-dock.json`, `surfaces/inspector-dock.json`): a projection is written
21
+ * synchronously and a binding whose value did not move writes nothing, so there is no queued frame
22
+ * to be outstanding and no withheld render to wait for. The panel bodies that ARE still lit are
23
+ * painted synchronously from the same call.
16
24
  *
17
25
  * 1. `store.rendersInFlight()` — renderers mid-paint.
18
- * 2. `panel-scheduler.pendingSchedulers()` — panels with a frame queued or a render withheld.
19
- * 3. `iframe-host.canvasIdleBlockers()` — per host: unacked generations and patches, plus the frame's
26
+ * 2. `iframe-host.canvasIdleBlockers()` — per host: unacked generations and patches, plus the frame's
20
27
  * own cross-realm report of fonts, running animations and pending image retries.
21
- * 4. `platform.platformInFlight()` — unsettled PAL calls, counted at the one seam every adapter and
28
+ * 3. `platform.platformInFlight()` — unsettled PAL calls, counted at the one seam every adapter and
22
29
  * all thirty-odd `git*`/fs/fetch methods pass through.
23
- * 5. `layers.overlayIdleBlockers()` — overlays still in transition. Only the SETTLING window counts: a
30
+ * 4. `layers.overlayIdleBlockers()` — overlays still in transition. Only the SETTLING window counts: a
24
31
  * resting toast is not a blocker, which is what lets `toastsAreHeld()` hold one open for a
25
32
  * capture without `probeIdle()` waiting forever alongside it (plan §13.7's named exception).
26
- * 6. `activity-panel.activityIdleBlockers()` — operations still RUNNING in the Activity tab. Not a
33
+ * 5. `activity-panel.activityIdleBlockers()` — operations still RUNNING in the Activity tab. Not a
27
34
  * duplicate of `platform`: an activity spans a whole operation (an install, a deploy, a clone)
28
35
  * across many PAL calls, so the gaps between them look quiet at the seam while the operation is
29
36
  * plainly mid-flight. A finished entry never blocks — the list stays on screen forever.
30
- * 7. `grid-idle.gridIdleBlockers()` — tables still building, or built but not yet showing the
37
+ * 6. `grid-idle.gridIdleBlockers()` — tables still building, or built but not yet showing the
31
38
  * selection range `selectableRange: 1` gives them. Nothing else covered Tabulator: a grid
32
39
  * command resolves when the panel mounts, which is several frames before the table is drawn.
33
40
  *
@@ -37,7 +44,6 @@
37
44
 
38
45
  import { rendersInFlight } from "../store";
39
46
  import { activityIdleBlockers } from "../panels/activity-panel";
40
- import { pendingSchedulers } from "../panels/panel-scheduler";
41
47
  import { canvasIdleBlockers } from "../canvas/iframe-host";
42
48
  import { platformInFlight } from "../platform";
43
49
  import { overlayIdleBlockers } from "../ui/layers";
@@ -45,7 +51,7 @@ import { gridIdleBlockers } from "../grid/grid-idle";
45
51
 
46
52
  /** One subsystem that can be outstanding, and its account of why. */
47
53
  export interface IdleSource {
48
- /** Stable name — `render`, `panels`, `canvas`, `platform`, `overlay`. */
54
+ /** Stable name — `render`, `canvas`, `platform`, `overlay`. */
49
55
  readonly name: string;
50
56
  /** Empty when quiet; otherwise one human-readable line per outstanding item. */
51
57
  blockers: () => readonly string[];
@@ -73,7 +79,7 @@ export class NotIdleError extends Error {
73
79
  }
74
80
 
75
81
  /**
76
- * The seven live sources.
82
+ * The six live sources.
77
83
  *
78
84
  * Built per call rather than held in a module constant so a test can substitute one without
79
85
  * unpicking the others, and so a second window's hosts are never read through the first window's
@@ -88,10 +94,6 @@ export function defaultIdleSources(): IdleSource[] {
88
94
  },
89
95
  name: "render",
90
96
  },
91
- {
92
- blockers: () => pendingSchedulers().map((panel) => `panels: ${panel}`),
93
- name: "panels",
94
- },
95
97
  { blockers: canvasIdleBlockers, name: "canvas" },
96
98
  {
97
99
  blockers: () => {
@@ -0,0 +1,237 @@
1
+ /**
2
+ * Live authoring of Studio's own chrome.
3
+ *
4
+ * Studio's surfaces are Jx documents (`src/surfaces/*.json`) and its controls are the kit's
5
+ * (`packages/ui/components/*.json`), so both are things Studio can open and edit. This is what
6
+ * closes the loop: a saved surface document re-mounts every root drawn from it, and a saved kit
7
+ * component redefines the element and re-mounts every root that used it, so the edit shows in the
8
+ * shell the reader is standing in (studio-ui-guidelines.md §9.3, embedding.md §7).
9
+ *
10
+ * **The lane is keyed on the saved PATH, and that is the whole of how it stays inert.** A save is
11
+ * something to act on only when the file, joined to the open project's root, is one of the two
12
+ * places the chrome comes from. Any other project — a site, a starter, the examples — saves files
13
+ * this never looks at, and the shipped app never reads its chrome from disk: the document that
14
+ * re-mounts is the one the tab just wrote, handed over by the save path, never read back.
15
+ *
16
+ * Two things are deliberately NOT here. The lane does not watch the filesystem: an edit made
17
+ * outside Studio reaches the shell on the next reload, as it always did, because a watcher is a
18
+ * second writer racing the tab. And it does not diff: a saved document is re-registered whole and
19
+ * every root re-mounted, because a surface's host scope is reused (`SurfaceMount.remount`) and only
20
+ * the surface-local state resets, which is the contract §9.3 gives the registry.
21
+ *
22
+ * A kit redefinition reaches the canvas frames too, with the FILE's URL under the project as its
23
+ * base: the frame draws a project's elements from the project's own files, so a sibling `$ref` in
24
+ * the definition must resolve to the project's copy, not to the bundle's. The frame answers the
25
+ * definition's `jx-ui:` sidecars from the loaders it registered at boot (`iframe-entry.ts`), one
26
+ * chunk per behaviour on first use.
27
+ *
28
+ * @docs extending/ui-kit
29
+ */
30
+ import { redefineElement } from "@jxsuite/runtime";
31
+ import { KIT_BASE } from "@jxsuite/ui";
32
+ import type { JxDocument } from "@jxsuite/schema/types";
33
+ import { mountsOf, mountsUsing } from "./surface-registry";
34
+ import { registerSurface, surfaceDocument } from "../ui/surface";
35
+ import { documentBase } from "../canvas/canvas-origin";
36
+
37
+ /** What a saved file IS to the running shell. */
38
+ export type LiveTarget =
39
+ | { readonly kind: "surface"; readonly name: string }
40
+ | { readonly kind: "element"; readonly tag: string };
41
+
42
+ /** Where a surface document lives, from any root that contains it. */
43
+ const SURFACE_PATH = /\/packages\/studio\/src\/surfaces\/([\w-]+)\.json$/;
44
+ /** Where a kit component lives, from any root that contains it. */
45
+ const ELEMENT_PATH = /\/packages\/ui\/components\/(jx-[\w-]+)\.json$/;
46
+
47
+ /**
48
+ * Join a project root and a path the way the platform reports them, and normalise the separators so
49
+ * a Windows root and a POSIX-relative path meet in one spelling.
50
+ */
51
+ function joined(projectRoot: string, path: string): string {
52
+ const root = projectRoot.replaceAll("\\", "/").replace(/\/+$/, "");
53
+ const rel = path.replaceAll("\\", "/").replace(/^\.?\//, "");
54
+ return `${root}/${rel}`;
55
+ }
56
+
57
+ /**
58
+ * Which surface or element a saved path is, or null for every other file.
59
+ *
60
+ * Matched by suffix against the root JOINED to the path rather than by which project is open, so
61
+ * the same answer comes from the kit opened as its own project (`components/jx-tree.json` under
62
+ * `packages/ui`), from Studio opened as one (`src/surfaces/menu.json` under `packages/studio`), or
63
+ * from any root above them. A path that is neither — including every file of every other project —
64
+ * is null, and null is the lane doing nothing.
65
+ *
66
+ * @param projectRoot The open project's root, as the platform reports it.
67
+ * @param path The saved path, relative to that root.
68
+ */
69
+ export function liveSurfaceTarget(
70
+ projectRoot: string | null | undefined,
71
+ path: string | null | undefined,
72
+ ): LiveTarget | null {
73
+ if (!projectRoot || !path) {
74
+ return null;
75
+ }
76
+ const full = joined(projectRoot, path);
77
+ const surface = SURFACE_PATH.exec(full);
78
+ if (surface) {
79
+ return { kind: "surface", name: surface[1]! };
80
+ }
81
+ const element = ELEMENT_PATH.exec(full);
82
+ if (element) {
83
+ return { kind: "element", tag: element[1]! };
84
+ }
85
+ return null;
86
+ }
87
+
88
+ /** What one save did. */
89
+ export interface LiveSurfaceResult {
90
+ readonly target: LiveTarget;
91
+ /** How many roots were re-mounted. Zero is a document nothing on screen was drawn from. */
92
+ readonly remounted: number;
93
+ /** How many canvas frames were told of an element's redefinition. Absent for a surface. */
94
+ readonly canvases?: number;
95
+ /** Why nothing was applied, when nothing was. */
96
+ readonly refused?: string;
97
+ }
98
+
99
+ /**
100
+ * The URL a frame resolves a saved kit component against: the file's own URL under the project,
101
+ * which is where the frame fetched the definition it holds and where its sibling `$ref`s live.
102
+ *
103
+ * @param projectRoot The open project's root.
104
+ * @param path The saved path, relative to it.
105
+ */
106
+ export function canvasBaseFor(projectRoot: string, path: string): string {
107
+ return new URL(path.replaceAll("\\", "/").replace(/^\.?\//, ""), documentBase(projectRoot)).href;
108
+ }
109
+
110
+ /**
111
+ * Apply a saved document to the running shell.
112
+ *
113
+ * A surface is re-registered under its name — the same call the bundle makes at boot, so the
114
+ * runtime's own resolution paths see the new document too — and every root of that name is
115
+ * re-mounted. An element is redefined through the runtime (embedding.md §7) and every root whose
116
+ * render instantiated it is re-mounted, which is what turns a redefinition into something visible:
117
+ * an instance already connected keeps the definition it rendered until it is re-mounted.
118
+ *
119
+ * A surface name nothing has registered is refused rather than registered: a new file under
120
+ * `src/surfaces/` has no adapter to mount it, so registering it would promise a mount nothing will
121
+ * make. An element whose document names a different tag than its file is refused too — the file is
122
+ * what the kit's registry keys on, and a document that disagrees with its own name is a mistake to
123
+ * report, not one to define under either spelling.
124
+ *
125
+ * @param target What the saved file is.
126
+ * @param doc The document the tab just wrote.
127
+ */
128
+ export async function applyLiveSave(
129
+ target: LiveTarget,
130
+ doc: JxDocument,
131
+ ): Promise<LiveSurfaceResult> {
132
+ if (target.kind === "surface") {
133
+ if (!surfaceDocument(target.name)) {
134
+ return { refused: `no surface is registered as "${target.name}"`, remounted: 0, target };
135
+ }
136
+ registerSurface(target.name, doc);
137
+ const roots = mountsOf(target.name);
138
+ await Promise.all(roots.map((m) => m.remount()));
139
+ return { remounted: roots.length, target };
140
+ }
141
+ if (doc.tagName !== target.tag) {
142
+ return {
143
+ refused: `the document names <${String(doc.tagName)}>, but the file is ${target.tag}.json`,
144
+ remounted: 0,
145
+ target,
146
+ };
147
+ }
148
+ await redefineElement(doc, KIT_BASE);
149
+ const roots = mountsUsing(target.tag);
150
+ await Promise.all(roots.map((m) => m.remount()));
151
+ return { remounted: roots.length, target };
152
+ }
153
+
154
+ /** The two channels a save's outcome is said on. A refusal is a problem; a re-mount is a toast. */
155
+ export interface LiveSurfaceNotifier {
156
+ info: (message: string, options: { key: string; source: string }) => void;
157
+ warn: (message: string, options: { key: string; source: string; tier: "problem" }) => void;
158
+ }
159
+
160
+ /**
161
+ * What the lane needs from the shell, as the records themselves rather than closures over them, so
162
+ * the bootstrap hands over objects it already holds and writes no function of its own.
163
+ */
164
+ export interface LiveSurfaceDeps {
165
+ /** The workspace record; `projectRoot` is read at save time, never captured. */
166
+ workspace: { readonly projectRoot: string | null };
167
+ notify: LiveSurfaceNotifier;
168
+ /**
169
+ * Redefine an element in every live canvas frame and render them; answers how many were told.
170
+ * `canvas-render.ts`'s `redefineElementOnCanvases`, injected so this module imports no canvas.
171
+ */
172
+ redefineOnCanvases: (doc: JxDocument, base: string) => number;
173
+ }
174
+
175
+ /** The sentence a result is said in. Exported so the wording is tested, not only the branch. */
176
+ export function liveSaveNotice(result: LiveSurfaceResult): {
177
+ key: string;
178
+ level: "info" | "warn";
179
+ message: string;
180
+ } {
181
+ const what =
182
+ result.target.kind === "surface" ? `surface ${result.target.name}` : result.target.tag;
183
+ const key = `live-chrome:${what}`;
184
+ if (result.refused) {
185
+ return { key, level: "warn", message: `Not applied to the running shell: ${result.refused}.` };
186
+ }
187
+ const canvases =
188
+ result.canvases === undefined || result.canvases === 0
189
+ ? ""
190
+ : result.canvases === 1
191
+ ? " and on the canvas"
192
+ : ` and on ${result.canvases} canvases`;
193
+ if (result.remounted === 0) {
194
+ return {
195
+ key,
196
+ level: "info",
197
+ message: `${what} saved; nothing in the shell is drawn from it${canvases ? `, redefined${canvases}` : ""}.`,
198
+ };
199
+ }
200
+ const places = result.remounted === 1 ? "1 place" : `${result.remounted} places`;
201
+ return {
202
+ key,
203
+ level: "info",
204
+ message: `${what} saved and re-mounted in ${places}${canvases}.`,
205
+ };
206
+ }
207
+
208
+ /**
209
+ * The save listener: decide whether the saved file is chrome, and if it is, apply it and say so.
210
+ *
211
+ * Returns the result, or null when the save was not chrome, so a caller — and a test — can tell
212
+ * "nothing to do" from "did nothing".
213
+ *
214
+ * @param deps The shell's workspace record and notifier.
215
+ */
216
+ export function createLiveSurfaceSaver(
217
+ deps: LiveSurfaceDeps,
218
+ ): (path: string | null, doc: JxDocument | null) => Promise<LiveSurfaceResult | null> {
219
+ return async (path, doc) => {
220
+ const root = deps.workspace.projectRoot;
221
+ const target = liveSurfaceTarget(root, path);
222
+ if (!target || !doc || !root || !path) {
223
+ return null;
224
+ }
225
+ let result = await applyLiveSave(target, doc);
226
+ if (target.kind === "element" && !result.refused) {
227
+ result = { ...result, canvases: deps.redefineOnCanvases(doc, canvasBaseFor(root, path)) };
228
+ }
229
+ const notice = liveSaveNotice(result);
230
+ if (notice.level === "warn") {
231
+ deps.notify.warn(notice.message, { key: notice.key, source: "Studio", tier: "problem" });
232
+ } else {
233
+ deps.notify.info(notice.message, { key: notice.key, source: "Studio" });
234
+ }
235
+ return result;
236
+ };
237
+ }
@@ -29,3 +29,78 @@ export const ENTRY_SCHEMA_FILES = new Set(["project.schema.json", "document.sche
29
29
  export function modelUriFor(path: string): string {
30
30
  return ENTRY_SCHEMA_FILES.has(path) ? `file:///.jx/generated/${path}` : `file:///${path}`;
31
31
  }
32
+
33
+ /**
34
+ * The two model URIs a comparison's Monaco diff editor mounts at.
35
+ *
36
+ * **A reserved namespace, because the collision is otherwise unrepresentable-by-luck rather than
37
+ * unrepresentable.** Two models on one URI throws (`Cannot create model because a model with the
38
+ * same URI already exists`), and `workspace/pane-derive.ts` refuses a Code lens on a file whose
39
+ * source editor is already open for exactly that reason. A diff editor is a THIRD claimant on the
40
+ * same path, and neither existing guard can see it: one asks about panes, the other about presets.
41
+ * Disjoint URIs make the collision impossible instead of refused.
42
+ *
43
+ * **Per pane**, because the primary can hold a comparison in Code while a Diff lens beside it holds
44
+ * the same file's — two diff editors over one file, four models, all four distinct.
45
+ *
46
+ * The cost, stated: a relative `$schema` resolves against the model URI, so the HEAD side gets no
47
+ * JSON validation. That is correct rather than merely tolerable — a comparison is read-only, and
48
+ * red squiggles on a git object nobody can edit would be noise. The Code lens on the real URI keeps
49
+ * its markers.
50
+ *
51
+ * @param {string} paneId
52
+ * @param {string} path - Project-relative file path
53
+ * @returns {{ head: string; work: string }}
54
+ */
55
+ export function diffModelUrisFor(paneId: string, path: string): { head: string; work: string } {
56
+ return {
57
+ head: `file:///.jx/diff/${paneId}/head/${path}`,
58
+ work: `file:///.jx/diff/${paneId}/work/${path}`,
59
+ };
60
+ }
61
+
62
+ /**
63
+ * Monaco's language id for a path, for a buffer with no tab and no format class behind it.
64
+ *
65
+ * `sourceLang` answers from a Tab's format class, which a comparison may not have: a diff can be
66
+ * over a `.ts`, a `.css` or a `.gitignore`, none of which opens as a document at all. Unknown
67
+ * extensions resolve to `plaintext` rather than being forced into a registered language —
68
+ * `monaco-setup` contributes only JSON, TypeScript and JavaScript, and the red/green line
69
+ * decorations come from the diff algorithm rather than from a tokenizer, so plaintext loses
70
+ * highlighting and nothing else.
71
+ */
72
+ export function monacoLangForPath(path: string): string {
73
+ const ext = path.slice(path.lastIndexOf(".") + 1).toLowerCase();
74
+ switch (ext) {
75
+ case "cjs":
76
+ case "js":
77
+ case "mjs": {
78
+ return "javascript";
79
+ }
80
+ case "css": {
81
+ return "css";
82
+ }
83
+ case "htm":
84
+ case "html": {
85
+ return "html";
86
+ }
87
+ case "json": {
88
+ return "json";
89
+ }
90
+ case "md": {
91
+ return "markdown";
92
+ }
93
+ case "cts":
94
+ case "mts":
95
+ case "ts": {
96
+ return "typescript";
97
+ }
98
+ case "yaml":
99
+ case "yml": {
100
+ return "yaml";
101
+ }
102
+ default: {
103
+ return "plaintext";
104
+ }
105
+ }
106
+ }
@@ -14,12 +14,13 @@
14
14
  * | `toast` | the fourth overlay layer | timed, dismissible | reversible, or needs no action |
15
15
  * | `problem` | the Bottom dock's Problems | until it is fixed | it must be fixed |
16
16
  *
17
- * §7.1 names a third tier — **inline**, the `error` slot on `ui/field-row.ts`'s `renderFieldRow`.
18
- * It is deliberately NOT a member of {@link NotificationTier}: an inline error is a value a control
19
- * renders next to the field the user is editing, not a record the app posts to a host, and it has
20
- * no store to live in. Declaring a tier here whose only possible outcome is being dropped on the
21
- * floor would be exactly the silence this module exists to end, so the union has two members and
22
- * the third tier arrives as `renderFieldRow`'s own parameter (P4.4).
17
+ * §7.1 names a third tier — **inline**, the refusal a field draws at the control (`jx-field`'s own
18
+ * `[part="error"]`, projected by whichever inspector document owns the row). It is deliberately NOT
19
+ * a member of {@link NotificationTier}: an inline error is a value a control renders next to the
20
+ * field the user is editing, not a record the app posts to a host, and it has no store to live in.
21
+ * Declaring a tier here whose only possible outcome is being dropped on the floor would be exactly
22
+ * the silence this module exists to end, so the union has two members and the third tier arrives as
23
+ * a field's own projected value (P4.4).
23
24
  *
24
25
  * **Recovery is a command id, not a per-call-site closure.** `notify.error("Save failed", { action:
25
26
  * "file.save" })` gives the toast and the Problems row a Retry button whose label, availability,
@@ -254,6 +255,62 @@ export function clearProblems(match?: (record: Notification) => boolean): number
254
255
  return removed;
255
256
  }
256
257
 
258
+ /**
259
+ * One outstanding problem, as a REPORT hands it to a caller that cannot see the store: the
260
+ * assistant, whose `check_accessibility` / `check_popovers` / `validate_redirects` tools return the
261
+ * findings the person sees in the dock as `ToolResult.data`.
262
+ *
263
+ * The record's identity and clock are left out on purpose (`id` is a lit key, `at` is for "2m
264
+ * ago"); what remains is what a reader acts on — the sentence, the long form, the file, how bad it
265
+ * is, and the repair command a Fix button would run.
266
+ */
267
+ export interface ProblemFinding {
268
+ message: string;
269
+ severity: Severity;
270
+ detail?: string;
271
+ path?: string;
272
+ key?: string;
273
+ action?: string;
274
+ actionArgs?: Record<string, unknown>;
275
+ }
276
+
277
+ /**
278
+ * The outstanding problems one reporter filed, in the order they were filed — the same read the
279
+ * Problems tab makes when it groups by `source`, projected to {@link ProblemFinding}.
280
+ *
281
+ * @param {string} source - The `source` the reporter files under.
282
+ * @returns {ProblemFinding[]}
283
+ */
284
+ export function problemFindings(source: string): ProblemFinding[] {
285
+ const findings: ProblemFinding[] = [];
286
+ for (const record of problems) {
287
+ if (record.source !== source) {
288
+ continue;
289
+ }
290
+ const finding: ProblemFinding = { message: record.message, severity: record.severity };
291
+ /* Copied key by key rather than spread from the record: `exactOptionalPropertyTypes` refuses
292
+ an explicit `undefined`, and the model reads the JSON, where an absent key and an undefined
293
+ one serialise the same but a `undefined`-valued key is a lie about what the row holds. */
294
+ if (record.detail !== undefined) {
295
+ finding.detail = record.detail;
296
+ }
297
+ if (record.path !== undefined) {
298
+ finding.path = record.path;
299
+ }
300
+ if (record.key !== undefined) {
301
+ finding.key = record.key;
302
+ }
303
+ if (record.action !== undefined) {
304
+ finding.action = record.action;
305
+ }
306
+ if (record.actionArgs !== undefined) {
307
+ finding.actionArgs = record.actionArgs;
308
+ }
309
+ findings.push(finding);
310
+ }
311
+ return findings;
312
+ }
313
+
257
314
  /** How many problems are outstanding, optionally of one severity — the badge and the status bar. */
258
315
  export function problemCount(severity?: Severity): number {
259
316
  return severity === undefined