@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
@@ -37,7 +37,7 @@
37
37
  * (`panels/problems-panel.ts`) and registered from here, like every other tab of this dock.
38
38
  */
39
39
 
40
- import { html, render as litRender, nothing } from "lit-html";
40
+ import { render as litRender, nothing } from "lit-html";
41
41
  import { effect, effectScope } from "../reactivity";
42
42
  import {
43
43
  BOTTOM_TAB_IDS,
@@ -53,11 +53,12 @@ import { getPanel, isPanelVisible, listPanels, panelContext } from "./panel-regi
53
53
  import { registerActivityPanel } from "./activity-panel";
54
54
  import { registerProblemsPanel } from "./problems-panel";
55
55
  import { logicTarget, registerLogicPanel, revealLogicPanel } from "./formula-workspace";
56
- import { renderEmptyState } from "./empty-state";
56
+ import { emptyState } from "../surfaces/empty-state";
57
+ import { mountBottomDockSurface } from "../surfaces/bottom-dock";
58
+ import type { BottomDockHandle, BottomDockValues } from "../surfaces/bottom-dock";
57
59
  import type { CommandContext } from "../commands/context";
58
60
  import type { NavigatorPanelContext, NavigatorPanelDeps, PanelRecord } from "./panel-registry";
59
61
  import type { EffectScope } from "@vue/reactivity";
60
- import type { TemplateResult } from "lit-html";
61
62
 
62
63
  /** The dock's host — a bare `<div id>` in index.html, like every other shell host. */
63
64
  export const BOTTOM_DOCK_SELECTOR = "#bottom-dock";
@@ -152,54 +153,46 @@ export function bottomTabLabel(panel: PanelRecord, ctx: CommandContext): string
152
153
  return badge === null || badge === 0 || badge === "" ? panel.title : `${panel.title} ${badge}`;
153
154
  }
154
155
 
155
- /** The dock, as a template. Exported so a test can render it without a host. */
156
- export function bottomDockTemplate(ctx: CommandContext = panelContext()): TemplateResult {
157
- const panels = visibleBottomPanels(ctx);
156
+ /**
157
+ * What the strip says right now: one row per admitted tab, and which of them is showing.
158
+ *
159
+ * Exported so a test can read the projection without a host — the same reason the template it
160
+ * replaced was exported, and a stronger one: this is a plain object, so an assertion about a tab's
161
+ * label or the selected id is a comparison rather than a DOM walk.
162
+ *
163
+ * @param {CommandContext} [ctx]
164
+ * @returns {BottomDockValues}
165
+ */
166
+ export function bottomDockValues(ctx: CommandContext = panelContext()): BottomDockValues {
158
167
  const active = activeBottomPanel(ctx);
159
- const body = active
160
- ? active.render(bottomContext())
161
- : renderEmptyState({ message: "Nothing to show here yet." });
162
- return html`
163
- <div class="bd-strip">
164
- <sp-tabs
165
- class="bd-tabs"
166
- quiet
167
- size="s"
168
- selected=${active?.id ?? ""}
169
- @change=${(e: Event & { target: { selected: string } }) => {
170
- const { selected } = e.target;
171
- if (selected && selected !== active?.id) {
172
- setBottomTab(selected);
173
- }
174
- }}
175
- >
176
- ${panels.map(
177
- (panel) => html`<sp-tab value=${panel.id} label=${bottomTabLabel(panel, ctx)}></sp-tab>`,
178
- )}
179
- </sp-tabs>
180
- <button
181
- class="bd-close"
182
- title="Close the Bottom dock"
183
- aria-label="Close the Bottom dock"
184
- @click=${() => {
185
- setDockCollapsed("bottom", true);
186
- }}
187
- >
188
- <span aria-hidden="true">×</span>
189
- </button>
190
- </div>
191
- ${
192
- active
193
- ? html`<div class="bd-body" data-jx-region=${bottomPanelRegion(active.id)}>${body}</div>`
194
- : html`<div class="bd-body">${body}</div>`
195
- }
196
- `;
168
+ return {
169
+ bodyRegion: active ? bottomPanelRegion(active.id) : "",
170
+ tab: active?.id ?? "",
171
+ tabId: active ? `bottom-dock-tab-${active.id}` : "",
172
+ tabs: visibleBottomPanels(ctx).map((panel) => ({
173
+ key: panel.id,
174
+ label: bottomTabLabel(panel, ctx),
175
+ tabId: `bottom-dock-tab-${panel.id}`,
176
+ })),
177
+ };
197
178
  }
198
179
 
199
180
  let _scope: EffectScope | null = null;
200
181
 
201
182
  let _host: HTMLElement | null = null;
202
183
 
184
+ /** The mounted chrome document, live only while the dock is open. */
185
+ let _dock: BottomDockHandle | null = null;
186
+
187
+ /**
188
+ * The `[part="dock-body"]` the document announced, or null while nothing is mounted.
189
+ *
190
+ * Held rather than re-queried: it is the one element every tab's `afterRender` is measured against,
191
+ * and a selector that returned a different node between the paint and the hook would hand a tab a
192
+ * body it had not been painted into.
193
+ */
194
+ let _body: HTMLElement | null = null;
195
+
203
196
  /**
204
197
  * The Logic target the dock has already revealed itself for.
205
198
  *
@@ -237,13 +230,79 @@ export function renderBottomDock(): void {
237
230
  }
238
231
  if (shell.docks.bottom.collapsed) {
239
232
  _host.removeAttribute(REGION_ATTR);
240
- litRender(nothing, _host);
233
+ /* The chrome is taken down rather than hidden, and `#bottom-dock:empty { display: none }` is
234
+ why: the shell's own sheet keeps a dock with nothing in it out of the grid, so a document
235
+ left mounted behind a `hidden` attribute would make that rule permanently unmatchable. Disposing also
236
+ makes the collapsed branch mean what it says to a tab — every one of them is handed the
237
+ emptied HOST, which is the fourth of the four ways Logic stops being on screen. */
238
+ _dock?.dispose();
239
+ _dock = null;
240
+ _body = null;
241
241
  runAfterRender(_host);
242
242
  return;
243
243
  }
244
244
  _host.setAttribute(REGION_ATTR, "dock.bottom");
245
- litRender(bottomDockTemplate(), _host);
246
- runAfterRender(_host.querySelector<HTMLElement>(".bd-body") ?? _host);
245
+ if (!_dock) {
246
+ /* The mount is asynchronous (the kit has to be defined first), so the body is painted from the
247
+ announcement rather than from here — `onBody` fires while the host is still inside the
248
+ runtime's fragment, one append before the strip is in the page. */
249
+ _dock = mountBottomDockSurface(
250
+ _host,
251
+ bottomDockValues(),
252
+ {
253
+ closeDock: () => {
254
+ setDockCollapsed("bottom", true);
255
+ },
256
+ selectTab: (id) => {
257
+ if (id !== "" && id !== activeBottomPanel()?.id) {
258
+ setBottomTab(id);
259
+ }
260
+ },
261
+ },
262
+ {
263
+ onBody: (host) => {
264
+ _body = host;
265
+ /* A MICROTASK, not this call. `onNodeCreated` fires the moment the element is CONSTRUCTED
266
+ — the runtime applies its attributes on the next line — so a tab's `afterRender` run
267
+ from here would be handed a body with no `part` and no `data-jx-region` on it yet, and
268
+ every tab that identifies its own container by attribute would decide it is off screen.
269
+ By the time a microtask runs, the synchronous render that created this node has
270
+ finished and the element is fully written. */
271
+ queueMicrotask(() => {
272
+ if (_body === host) {
273
+ paintBody();
274
+ }
275
+ });
276
+ },
277
+ },
278
+ );
279
+ return;
280
+ }
281
+ _dock.update(bottomDockValues());
282
+ paintBody();
283
+ }
284
+
285
+ /**
286
+ * Draw the selected tab into the one body the document leaves empty, and tell every tab about it.
287
+ *
288
+ * The record's `render` returns a lit template — that is what a `PanelRecord` is — so this is the
289
+ * one place lit still paints inside the dock, into an island the document owns and never touches
290
+ * (studio-ui-guidelines.md §9.4). With no visible tab at all there is still a body: the empty state
291
+ * is what a dock whose every tab is gated off says, and a blank box is not.
292
+ */
293
+ function paintBody(): void {
294
+ const host = _body;
295
+ if (!host) {
296
+ return;
297
+ }
298
+ const active = activeBottomPanel();
299
+ litRender(
300
+ active
301
+ ? active.render(bottomContext())
302
+ : emptyState(host, { message: "Nothing to show here yet." }),
303
+ host,
304
+ );
305
+ runAfterRender(host);
247
306
  }
248
307
 
249
308
  /**
@@ -328,9 +387,15 @@ export function unmountBottomDock(): void {
328
387
  _scope?.stop();
329
388
  _scope = null;
330
389
  _revealedLogicKey = null;
390
+ _dock?.dispose();
391
+ _dock = null;
392
+ _body = null;
331
393
  if (_host) {
332
394
  _host.removeAttribute(REGION_ATTR);
395
+ /* The document's dispose removed its own root; this clears anything a caller left beside it,
396
+ so the host is `:empty` again and the shell's sheet takes the dock out of the grid. */
333
397
  litRender(nothing, _host);
398
+ _host.textContent = "";
334
399
  runAfterRender(_host);
335
400
  _host = null;
336
401
  }
@@ -17,15 +17,17 @@
17
17
  * and never tears down on tab switches — the assistant's module state and DOM (composer draft,
18
18
  * scroll position) persist.
19
19
  *
20
- * Deliberately NOT built on createPanelScheduler: ai-panel owns a focus-guard-free rAF render loop
21
- * (streaming must repaint while the composer is focused). This module only provides the host
22
- * container, the initial paint, and the pending-agent-prompt handoff; ai-panel's watcher drives all
23
- * chat-state repaints through the same lit part cache.
20
+ * **This module is the SEAM, and it has no markup of its own.** The assistant is a Jx document
21
+ * (`surfaces/ai-chat.json`), and a document CLEARS the host it is given — so it needs a container
22
+ * nobody else writes into. That container is the one thing created here; `.ai-panel-host` is its
23
+ * layout rule in `styles/inspector.css`, which is why the class stays on a node the surface does
24
+ * not own. Everything below it is the surface's, and `ai-panel.ts` drives it from one effect —
25
+ * there is no scheduler, and there is no frame loop, because a document's bindings re-run per
26
+ * property and a streaming token never reaches the composer.
24
27
  *
25
28
  * @license MIT
26
29
  */
27
30
 
28
- import { render as litRender } from "lit-html";
29
31
  import { effect, effectScope } from "../reactivity";
30
32
  import { workspace } from "../workspace/workspace";
31
33
  import { consumePendingAgentPrompt, hasPendingAgentPrompt } from "../services/agent-seed";
@@ -33,7 +35,7 @@ import { REGION_ATTR } from "../ui/regions";
33
35
  import {
34
36
  bindAiPanelHost,
35
37
  mountAiPanel,
36
- renderAiPanelTemplate,
38
+ renderAiPanel,
37
39
  revealAssistant,
38
40
  seedAssistantPrompt,
39
41
  } from "./ai-panel";
@@ -49,9 +51,8 @@ let _scope: EffectScope | null = null;
49
51
 
50
52
  /**
51
53
  * Mount the assistant into the host the Inspector hands it. Idempotent per host: the persistent
52
- * `.ai-panel-host` container is created once and bound as the ai-panel render host (lit needs a
53
- * single render target for its part cache). A missing host (a reduced test fixture with no
54
- * inspector) is a no-op.
54
+ * `.ai-panel-host` container is created once and handed to `ai-panel.ts` as the surface's mount
55
+ * point. A missing host (a reduced test fixture with no inspector) is a no-op.
55
56
  *
56
57
  * @param {HTMLElement | null} host
57
58
  */
@@ -67,10 +68,7 @@ export function mount(host: HTMLElement | null) {
67
68
  host.append(_container);
68
69
 
69
70
  mountAiPanel();
70
- // The AI panel owns a focus-guard-free rAF render loop into this container so
71
- // Streaming repaints while the composer is focused (see ai-panel.ts).
72
71
  bindAiPanelHost(_container);
73
- render();
74
72
 
75
73
  _scope?.stop();
76
74
  _scope = effectScope();
@@ -100,6 +98,8 @@ export function mount(host: HTMLElement | null) {
100
98
  export function unmount() {
101
99
  _scope?.stop();
102
100
  _scope = null;
101
+ // `null` unbinds the surface: the document is disposed and the chat-state watcher stopped.
102
+ bindAiPanelHost(null);
103
103
  if (_host) {
104
104
  _host.textContent = "";
105
105
  }
@@ -107,9 +107,14 @@ export function unmount() {
107
107
  _container = null;
108
108
  }
109
109
 
110
- /** Repaint the assistant template into the persistent container (no-op before mount). */
110
+ /**
111
+ * Recompute the assistant's projection now (no-op before mount).
112
+ *
113
+ * Kept because `store.ts`'s `registerRenderer("chatPanel", …)` compat registry still names it. The
114
+ * surface follows the projection, so this is one function call rather than a repaint.
115
+ */
111
116
  export function render() {
112
117
  if (_container) {
113
- litRender(renderAiPanelTemplate(), _container);
118
+ renderAiPanel();
114
119
  }
115
120
  }
@@ -1,12 +1,13 @@
1
1
  /// <reference lib="dom" />
2
2
  // ─── Data Explorer ──────────────────────────────────────────────────────────
3
3
 
4
- import { html, nothing } from "lit-html";
5
- import type { TemplateResult } from "lit-html";
4
+ import { nothing } from "lit-html";
6
5
  import { activeTab } from "../workspace/workspace";
7
- import { renderOnly } from "../store";
8
6
  import { booleanArg, stringArg, stringProperty } from "../commands/command-args";
7
+ import { renderDataTreeSurface } from "../surfaces/panel-data";
9
8
  import { registerPanel } from "./panel-registry";
9
+ import type { PanelBody } from "./panel-registry";
10
+ import type { DataTreeRow } from "../surfaces/panel-data";
10
11
  import type { AnyCommand, CommandRegistry } from "../commands/registry";
11
12
 
12
13
  /**
@@ -62,32 +63,48 @@ export function raiseDataLimit(path: string, kind: "items" | "keys" | "depth"):
62
63
  }
63
64
 
64
65
  /**
65
- * One truncation marker: a button that shows more of what is already in hand.
66
+ * One truncation marker: a row the document draws as a button that shows more of what is in hand.
66
67
  *
67
- * It repaints through `renderOnly("leftPanel")` rather than a callback, because this renderer is
68
- * called from three places and threading a repaint through all of them to reach one `<button>`
69
- * would put a required callback on a pure formatter.
68
+ * It carries the subtree and the limit it raises rather than a callback. The press arrives back
69
+ * here through the surface's one action, so a pure formatter stays pure and there is a single
70
+ * repaint to reason about instead of one threaded through every caller.
70
71
  */
71
- function moreTemplate(
72
+ function moreRow(
72
73
  path: string,
73
- kind: "items" | "keys" | "depth",
74
+ limit: "items" | "keys" | "depth",
74
75
  indent: string,
75
- label: string,
76
- after?: () => string,
77
- ) {
78
- return html`<button
79
- type="button"
80
- class="data-leaf data-ellipsis data-more"
81
- style="padding-left:${indent}"
82
- title=${after?.() ?? `Show ${MORE_STEP} more`}
83
- @click=${(e: Event) => {
84
- e.stopPropagation();
85
- raiseDataLimit(path, kind);
86
- renderOnly("leftPanel");
87
- }}
88
- >
89
- ${label}
90
- </button>`;
76
+ text: string,
77
+ title = `Show ${MORE_STEP} more`,
78
+ ): DataTreeRow {
79
+ return {
80
+ indent,
81
+ key: `${path}\u0000${limit}`,
82
+ kind: "more",
83
+ label: "",
84
+ limit,
85
+ path,
86
+ text,
87
+ title,
88
+ tone: "marker",
89
+ };
90
+ }
91
+
92
+ /** A value as the tree prints it, capped at `max` characters. `undefined` prints as nothing. */
93
+ function valueText(value: unknown, max: number): string {
94
+ if (typeof value === "string" && value.length > max) {
95
+ return `"${value.slice(0, max)}…"`;
96
+ }
97
+ return JSON.stringify(value) ?? "";
98
+ }
99
+
100
+ /** Which colour a value takes. `null` and a summary label are the two the tree actually paints. */
101
+ function toneOf(value: unknown): string {
102
+ return value === null ? "null" : typeof value;
103
+ }
104
+
105
+ /** `Array(3)` or `{2}` — what a value you can open says while it is closed. */
106
+ function summaryLabel(value: object): string {
107
+ return Array.isArray(value) ? `Array(${value.length})` : `{${Object.keys(value).length}}`;
91
108
  }
92
109
 
93
110
  /** Unwrap a Vue ref (has .value and .__v_isRef) to get the underlying value. */
@@ -121,98 +138,110 @@ export function dataTypeLabel(value: unknown) {
121
138
  panel listing every state entry with its badge and how it is defined: the same names twice, and
122
139
  you read one to understand the other. Plan §11.2 asks for "definitions + live values in one row",
123
140
  so the definition row now carries the resolved type and expands to the value tree, and what is
124
- left here is the tree renderer, the type label and the row-expansion record the merged rows read.
125
- `renderDataTreeTemplate` is unchanged — it was never the redundant half. */
141
+ left here is the tree WALK, the type label and the row-expansion record the merged rows read. */
142
+
126
143
  /**
127
- * Recursively render a JSON value as a tree view (Lit template).
144
+ * Flatten a JSON value into the lines the Data surface draws (`surfaces/panel-data.{json,ts}`).
128
145
  *
129
- * @returns {import("lit-html").TemplateResult}
146
+ * The tree used to BE a lit template, one recursive call per level. It is a document now, and a
147
+ * document's one repeater walks a LIST — so the recursion moved here and comes out as rows that
148
+ * each carry their own indent. Nothing else changed: the caps are the same caps, the text is
149
+ * truncated at the same lengths, and a capped list still ends in a marker.
150
+ *
151
+ * @param {unknown} value The resolved value to read.
152
+ * @param {number} depth How deep this call already is; the indent is derived from it.
153
+ * @param {number} [maxDepth] The default depth cap, before whatever the reader has raised.
154
+ * @param {string} path This subtree's path, which is what a raised limit is remembered against.
155
+ * @returns {DataTreeRow[]}
130
156
  */
131
- export function renderDataTreeTemplate(
157
+ export function dataTreeRows(
132
158
  value: unknown,
133
159
  depth: number,
134
160
  maxDepth = 5,
135
161
  path = "",
136
- ): TemplateResult {
162
+ ): DataTreeRow[] {
137
163
  const indent = `${(depth + 1) * 12}px`;
164
+ const row = (label: string, text: string, tone: string, key: string): DataTreeRow => ({
165
+ indent,
166
+ key,
167
+ kind: "row",
168
+ label,
169
+ limit: "",
170
+ path: "",
171
+ text,
172
+ title: "",
173
+ tone,
174
+ });
138
175
 
139
176
  if (depth > capFor(path, "depth", maxDepth)) {
140
- return moreTemplate(path, "depth", indent, "…", () => `Show ${MORE_STEP} more levels`);
177
+ return [moreRow(path, "depth", indent, "…", `Show ${MORE_STEP} more levels`)];
141
178
  }
142
-
179
+ /* The one line a value with nothing under it renders as, keyed by the subtree's own path. That
180
+ is unique by construction: a descent only ever happens into an object or an array, so this
181
+ row exists only at the top of a tree, where it has no siblings to collide with. */
143
182
  if (value === null || value === undefined) {
144
- return html`<div class="data-leaf data-null" style="padding-left:${indent}">
145
- ${String(value)}
146
- </div>`;
183
+ return [row("", String(value), "null", path)];
147
184
  }
148
-
149
185
  if (typeof value !== "object") {
150
- const text =
151
- typeof value === "string" && value.length > 200
152
- ? `"${value.slice(0, 200)}\u2026"`
153
- : JSON.stringify(value);
154
- return html`<div class="data-leaf data-${typeof value}" style="padding-left:${indent}">
155
- ${text}
156
- </div>`;
186
+ return [row("", valueText(value, 200), toneOf(value), path)];
157
187
  }
158
188
 
159
- if (Array.isArray(value)) {
160
- const cap = capFor(path, "items", 20);
161
- const items: TemplateResult[] = value.slice(0, cap).map((item, i) => {
162
- if (item === null || item === undefined || typeof item !== "object") {
163
- const valText =
164
- typeof item === "string" && item.length > 80
165
- ? `"${item.slice(0, 80)}\u2026"`
166
- : JSON.stringify(item);
167
- return html`<div class="data-branch" style="padding-left:${indent}">
168
- <span class="data-key">[${i}] </span
169
- ><span class="data-value data-${item === null ? "null" : typeof item}">${valText}</span>
170
- </div>`;
171
- }
172
- const label = Array.isArray(item)
173
- ? `Array(${item.length})`
174
- : `{${Object.keys(item as object).length}}`;
175
- return html`
176
- <div class="data-branch" style="padding-left:${indent}">
177
- <span class="data-key">[${i}] </span
178
- ><span class="data-value data-object-label">${label}</span>
179
- </div>
180
- ${renderDataTreeTemplate(item, depth + 1, maxDepth, `${path}/${i}`)}
181
- `;
182
- });
183
- return html`${items}${
184
- value.length > cap
185
- ? moreTemplate(path, "items", indent, `… ${value.length - cap} more`)
186
- : nothing
187
- }`;
188
- }
189
+ const array = Array.isArray(value);
190
+ const entries: [string, string, unknown][] = array
191
+ ? value.map((item, i) => [`${i}`, `[${i}] `, item])
192
+ : Object.keys(value).map((key) => [key, `${key}: `, (value as Record<string, unknown>)[key]]);
193
+ const limit = array ? "items" : "keys";
194
+ const cap = capFor(path, limit, array ? 20 : 30);
189
195
 
190
- // Object
191
- const obj = value as Record<string, unknown>;
192
- const keys = Object.keys(obj);
193
- const cap = capFor(path, "keys", 30);
194
- const items: TemplateResult[] = keys.slice(0, cap).map((key) => {
195
- const v = obj[key];
196
- if (v === null || v === undefined || typeof v !== "object") {
197
- const valText =
198
- typeof v === "string" && v.length > 80 ? `"${v.slice(0, 80)}\u2026"` : JSON.stringify(v);
199
- return html`<div class="data-branch" style="padding-left:${indent}">
200
- <span class="data-key">${key}: </span
201
- ><span class="data-value data-${v === null ? "null" : typeof v}">${valText}</span>
202
- </div>`;
196
+ const rows: DataTreeRow[] = [];
197
+ for (const [segment, label, item] of entries.slice(0, cap)) {
198
+ const childPath = `${path}/${segment}`;
199
+ if (item === null || item === undefined || typeof item !== "object") {
200
+ rows.push(row(label, valueText(item, 80), toneOf(item), childPath));
201
+ continue;
203
202
  }
204
- const label = Array.isArray(v) ? `Array(${v.length})` : `{${Object.keys(v).length}}`;
205
- return html`
206
- <div class="data-branch" style="padding-left:${indent}">
207
- <span class="data-key">${key}: </span
208
- ><span class="data-value data-object-label">${label}</span>
209
- </div>
210
- ${renderDataTreeTemplate(v, depth + 1, maxDepth, `${path}/${key}`)}
211
- `;
203
+ rows.push(
204
+ row(label, summaryLabel(item), "object", childPath),
205
+ ...dataTreeRows(item, depth + 1, maxDepth, childPath),
206
+ );
207
+ }
208
+ if (entries.length > cap) {
209
+ rows.push(moreRow(path, limit, indent, `… ${entries.length - cap} more`));
210
+ }
211
+ return rows;
212
+ }
213
+
214
+ /**
215
+ * Draw one value tree into the host that was made for it, or bring the one already there up to
216
+ * date.
217
+ *
218
+ * Idempotent, because it runs on EVERY repaint: a host that already holds its document is assigned
219
+ * to rather than remounted, which is what keeps the reader's place inside a long tree. Taking a
220
+ * CLOSED tree down is the panel's job rather than this one's — a row the reader collapsed never
221
+ * reaches here again — so `panels/signals-panel.ts` calls `disposeDetachedDataTrees()` once per
222
+ * repaint instead of this sweeping per host.
223
+ *
224
+ * @param {HTMLElement} host The node the tree is drawn into.
225
+ * @param {unknown} value What the canvas resolved this entry to.
226
+ * @param {string} path The subtree's path, which is what a raised limit is remembered against.
227
+ * @param {() => void} rerender Repaint the panel, so that a raised limit is drawn.
228
+ * @param {number} [maxDepth] The default depth cap, before whatever the reader has raised.
229
+ */
230
+ export function paintDataTree(
231
+ host: HTMLElement,
232
+ value: unknown,
233
+ path: string,
234
+ rerender: () => void,
235
+ maxDepth = 5,
236
+ ): void {
237
+ renderDataTreeSurface(host, dataTreeRows(value, 0, maxDepth, path), {
238
+ showMore: (subtree, limit) => {
239
+ if (limit === "items" || limit === "keys" || limit === "depth") {
240
+ raiseDataLimit(subtree, limit);
241
+ }
242
+ rerender();
243
+ },
212
244
  });
213
- return html`${items}${
214
- keys.length > cap ? moreTemplate(path, "keys", indent, `… ${keys.length - cap} more`) : nothing
215
- }`;
216
245
  }
217
246
 
218
247
  // ─── Commands ─────────────────────────────────────────────────────────────────
@@ -349,6 +378,14 @@ export function registerDataExplorerCommands(
349
378
  *
350
379
  * Defining and watching are the same task interrupted: you add an entry, then look at what it
351
380
  * resolved to. Two panels made that two panels.
381
+ *
382
+ * **Both halves are documents now** — `surfaces/panel-signals.{json,ts}` for the entry list and its
383
+ * editors, `surfaces/panel-data.{json,ts}` for the value tree under an open row. So lit draws
384
+ * nothing at all here: `render` returns `nothing` and `afterRender` mounts against the painted DOM,
385
+ * which is the seam `panels/git-panel.ts` uses for the same reason. The mount comes through `deps`
386
+ * rather than an import — this module owns the expansion store that one reads, so importing it back
387
+ * would close a cycle — and it is idempotent, so running on every repaint is what keeps the
388
+ * projection current.
352
389
  */
353
390
  export function registerDataPanel(): void {
354
391
  registerPanel({
@@ -356,14 +393,16 @@ export function registerDataPanel(): void {
356
393
  title: "Data",
357
394
  level: "document",
358
395
  dock: "navigator",
359
- icon: "sp-icon-data",
396
+ icon: "database",
360
397
  requiresDocument: "Open a page to give it data — values it can read, compute or fetch.",
361
- render: (ctx) =>
398
+ render: (): PanelBody => nothing,
399
+ afterRender: (ctx, host) => {
362
400
  // `ctx.doc!` — `requiresDocument` means the registry renders the empty state instead of
363
401
  // Calling this, the same assertion `head-panel.ts` makes for the same reason.
364
- ctx.deps.renderSignalsTemplate(ctx.doc!, {
402
+ ctx.deps.mountSignalsPanel(host, ctx.doc!, {
365
403
  refreshData: ctx.deps.refreshData,
366
404
  renderLeftPanel: ctx.rerender,
367
- }),
405
+ });
406
+ },
368
407
  });
369
408
  }