@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
@@ -9,13 +9,23 @@
9
9
  * confirmation before apply), and Open Data Grid — which opens the grid-tab source picker; table
10
10
  * editing itself lives in the spreadsheet grid tabs (src/grid/), which replaced the old modal grid
11
11
  * at feature parity (paging, cell edit, add/delete row) and added batch save with undo.
12
+ *
13
+ * **The markup left.** The row is `surfaces/data-actions.json` and the push plan is
14
+ * `surfaces/push-plan.json`, mounted into the confirm dialog `ui/layers.ts` already owns — a push
15
+ * is a confirm, and a second answer to that question is a defect (studio-ui-guidelines.md §12.5).
16
+ * The actions slot became a MOUNT rather than a template: the section redraws on every keystroke
17
+ * its form takes, and re-rendering the row each time replaced the button the reader was pressing.
12
18
  */
13
19
 
14
- import { html, nothing } from "lit-html";
15
- import { openModal } from "../ui/layers";
20
+ import { layerHost } from "../ui/layers";
21
+ import { openDialogSurface } from "../surfaces/dialog";
22
+ import { mountDataActionsSurface } from "../surfaces/data-actions";
23
+ import { mountPushPlanSurface } from "../surfaces/push-plan";
16
24
  import { dataSurfaceAvailable, pushSchema, testConnection } from "../services/data-service";
17
25
  import { openGridSourcePicker } from "../grid/grid-open";
18
- import type { TemplateResult } from "lit-html";
26
+ import type { DataActionsSurfaceHandle, DataActionsView } from "../surfaces/data-actions";
27
+ import type { DialogSurfaceHandle } from "../surfaces/dialog";
28
+ import type { PushPlanSurfaceHandle, PushPlanView } from "../surfaces/push-plan";
19
29
  import type { DataConnectionTestResult, DataPushResult } from "../types";
20
30
  import type { SectionActionsContext } from "../settings/contributed-section";
21
31
 
@@ -25,6 +35,10 @@ import type { SectionActionsContext } from "../settings/contributed-section";
25
35
  export function resetDataGridState(): void {
26
36
  actionsState = { pushing: false, testResult: null, testing: null };
27
37
  closePushDialog();
38
+ for (const mount of mounted.values()) {
39
+ mount.dispose();
40
+ }
41
+ mounted.clear();
28
42
  }
29
43
 
30
44
  /** True when the platform serves the data grid. */
@@ -35,10 +49,12 @@ export function isDataGridAvailable(): boolean {
35
49
  // ─── Push dialog (dry-run plan confirmation before apply) ─────────────────────
36
50
 
37
51
  interface PushDialogState {
38
- handle: ReturnType<typeof openModal>;
52
+ handle: DialogSurfaceHandle;
53
+ /** The plan body, once the dialog's island exists. */
54
+ plan: PushPlanSurfaceHandle | null;
39
55
  connection: string | undefined;
40
56
  phase: "loading" | "confirm" | "applying" | "done";
41
- plan: DataPushResult | null;
57
+ dryRun: DataPushResult | null;
42
58
  result: DataPushResult | null;
43
59
  onDone: () => void;
44
60
  }
@@ -47,8 +63,65 @@ let pushDialog: PushDialogState | null = null;
47
63
 
48
64
  /** Close the push dialog (also part of resetDataGridState). */
49
65
  function closePushDialog(): void {
50
- pushDialog?.handle.close();
66
+ const open = pushDialog;
51
67
  pushDialog = null;
68
+ open?.plan?.dispose();
69
+ open?.handle.close();
70
+ }
71
+
72
+ /** Give every row of the plan an identity, so a re-projection reconciles rather than rebuilds. */
73
+ function noteRows(texts: readonly string[], prefix: string) {
74
+ return texts.map((text, index) => ({ key: `${prefix}:${index}`, text }));
75
+ }
76
+
77
+ /** What the body lists: the dry run until it has been applied, then what actually happened. */
78
+ function planView(state: PushDialogState): PushPlanView {
79
+ const shown = state.phase === "done" ? state.result : state.dryRun;
80
+ return {
81
+ errors: noteRows(shown?.errors ?? [], "error"),
82
+ steps: (shown?.plan ?? []).map((step, index) => ({
83
+ key: `${step.kind}:${index}`,
84
+ kind: step.kind,
85
+ summary: step.summary,
86
+ })),
87
+ warnings: noteRows(shown?.warnings ?? [], "warning"),
88
+ };
89
+ }
90
+
91
+ /**
92
+ * The sentence under the headline.
93
+ *
94
+ * The empty plan gets one of its own: "nothing to push" is the answer an author most needs and the
95
+ * one an empty list says worst.
96
+ */
97
+ function planMessage(state: PushDialogState): string {
98
+ if (state.phase === "loading") {
99
+ return "Compiling plan…";
100
+ }
101
+ if (state.phase === "applying") {
102
+ return "Applying…";
103
+ }
104
+ if (state.phase === "done") {
105
+ return state.result?.applied ? "Schema applied." : "Push failed.";
106
+ }
107
+ const steps = state.dryRun?.plan.length ?? 0;
108
+ const errors = state.dryRun?.errors?.length ?? 0;
109
+ return steps === 0 && errors === 0 ? "Nothing to push — the schema is up to date." : "";
110
+ }
111
+
112
+ /** Put the dialog's three moving parts — its buttons, its sentence and its list — in step. */
113
+ function paintPushDialog(): void {
114
+ const state = pushDialog;
115
+ if (!state) {
116
+ return;
117
+ }
118
+ const confirmable = state.phase === "confirm" && (state.dryRun?.plan.length ?? 0) > 0;
119
+ state.handle.update({
120
+ cancelLabel: state.phase === "done" ? "Close" : "Cancel",
121
+ confirmLabel: confirmable ? "Apply" : "",
122
+ message: planMessage(state),
123
+ });
124
+ state.plan?.update(planView(state));
52
125
  }
53
126
 
54
127
  /** Start a push: dry-run first, then a confirmation dialog gates the apply. */
@@ -56,109 +129,66 @@ export async function startPush(connection: string | undefined, onDone: () => vo
56
129
  if (pushDialog) {
57
130
  return;
58
131
  }
59
- const handle = openModal(html``, { label: "Push Schema", onDismiss: closePushDialog });
60
- pushDialog = { connection, handle, onDone, phase: "loading", plan: null, result: null };
61
- renderPushDialog();
132
+ const state: PushDialogState = {
133
+ connection,
134
+ dryRun: null,
135
+ handle: null as unknown as DialogSurfaceHandle,
136
+ onDone,
137
+ phase: "loading",
138
+ plan: null,
139
+ result: null,
140
+ };
141
+ state.handle = openDialogSurface({
142
+ cancelLabel: "Cancel",
143
+ confirmLabel: "",
144
+ headline: connection ? `Push Schema — ${connection}` : "Push Schema",
145
+ island: (host) => {
146
+ state.plan = mountPushPlanSurface(host, planView(state));
147
+ },
148
+ layer: layerHost("dialog"),
149
+ message: "Compiling plan…",
150
+ onCancel: closePushDialog,
151
+ onClosed: () => {
152
+ if (pushDialog === state) {
153
+ closePushDialog();
154
+ }
155
+ },
156
+ onConfirm: () => {
157
+ void applyPush();
158
+ },
159
+ region: "data/push",
160
+ });
161
+ pushDialog = state;
162
+
62
163
  const plan = await pushSchema({
63
164
  dryRun: true,
64
165
  ...(connection === undefined ? {} : { connection }),
65
166
  });
66
- if (!pushDialog) {
167
+ if (pushDialog !== state) {
67
168
  return;
68
169
  }
69
- pushDialog.plan = plan;
70
- pushDialog.phase = "confirm";
71
- renderPushDialog();
170
+ state.dryRun = plan;
171
+ state.phase = "confirm";
172
+ paintPushDialog();
72
173
  }
73
174
 
74
175
  async function applyPush(): Promise<void> {
75
- if (!pushDialog) {
176
+ const state = pushDialog;
177
+ if (!state) {
76
178
  return;
77
179
  }
78
- pushDialog.phase = "applying";
79
- renderPushDialog();
180
+ state.phase = "applying";
181
+ paintPushDialog();
80
182
  const result = await pushSchema(
81
- pushDialog.connection === undefined ? {} : { connection: pushDialog.connection },
183
+ state.connection === undefined ? {} : { connection: state.connection },
82
184
  );
83
- if (!pushDialog) {
84
- return;
85
- }
86
- pushDialog.result = result;
87
- pushDialog.phase = "done";
88
- renderPushDialog();
89
- pushDialog.onDone();
90
- }
91
-
92
- function pushDialogBody(state: PushDialogState): TemplateResult {
93
- if (state.phase === "loading" || state.phase === "applying") {
94
- return html`<div class="push-dialog-status">
95
- ${state.phase === "loading" ? "Compiling plan…" : "Applying…"}
96
- </div>`;
97
- }
98
- const shown = state.phase === "done" ? state.result : state.plan;
99
- const steps = shown?.plan ?? [];
100
- const warnings = shown?.warnings ?? [];
101
- const errors = shown?.errors ?? [];
102
- return html`
103
- <div class="push-dialog-plan">
104
- ${
105
- state.phase === "done"
106
- ? html`<div class="push-dialog-status">
107
- ${shown?.applied ? "Schema applied." : "Push failed."}
108
- </div>`
109
- : steps.length === 0 && errors.length === 0
110
- ? html`<div class="push-dialog-status">
111
- Nothing to push — the schema is up to date.
112
- </div>`
113
- : nothing
114
- }
115
- <ul class="push-dialog-steps">
116
- ${steps.map(
117
- (step) => html`<li class="push-step push-step-${step.kind}">${step.summary}</li>`,
118
- )}
119
- </ul>
120
- ${warnings.map((w) => html`<div class="push-dialog-warning">${w}</div>`)}
121
- ${errors.map((e) => html`<div class="push-dialog-error">${e}</div>`)}
122
- </div>
123
- `;
124
- }
125
-
126
- function renderPushDialog(): void {
127
- if (!pushDialog) {
185
+ if (pushDialog !== state) {
128
186
  return;
129
187
  }
130
- const state = pushDialog;
131
- const confirmable = state.phase === "confirm" && (state.plan?.plan.length ?? 0) > 0;
132
- const tpl = html`
133
- <sp-underlay open @close=${closePushDialog}></sp-underlay>
134
- <div class="settings-modal push-dialog">
135
- <div class="settings-modal-header">
136
- <h2 class="settings-modal-title">
137
- Push Schema${state.connection ? html` — ${state.connection}` : nothing}
138
- </h2>
139
- </div>
140
- <div class="settings-modal-body">${pushDialogBody(state)}</div>
141
- <div class="push-dialog-actions">
142
- <sp-action-button size="s" class="push-cancel" @click=${closePushDialog}>
143
- ${state.phase === "done" ? "Close" : "Cancel"}
144
- </sp-action-button>
145
- ${
146
- confirmable
147
- ? html`<sp-action-button
148
- size="s"
149
- emphasized
150
- class="push-apply"
151
- @click=${() => {
152
- void applyPush();
153
- }}
154
- >Apply</sp-action-button
155
- >`
156
- : nothing
157
- }
158
- </div>
159
- </div>
160
- `;
161
- state.handle.update(tpl);
188
+ state.result = result;
189
+ state.phase = "done";
190
+ paintPushDialog();
191
+ state.onDone();
162
192
  }
163
193
 
164
194
  // ─── Contributed-section actions (Test / Push / Open grid) ────────────────────
@@ -172,22 +202,49 @@ interface ActionsState {
172
202
 
173
203
  let actionsState: ActionsState = { pushing: false, testResult: null, testing: null };
174
204
 
205
+ /**
206
+ * The row mounted in each host the settings machinery has handed us.
207
+ *
208
+ * Keyed by the host node, because one settings pane per stage means one host per stage (§4.1) and a
209
+ * module-level single would make the second pane's row replace the first's.
210
+ */
211
+ const mounted = new Map<HTMLElement, DataActionsSurfaceHandle>();
212
+
213
+ /** What the row says right now, for one section and its selected entry. */
214
+ function projectActions(sectionKey: string, selected: string | null): DataActionsView {
215
+ const { testResult } = actionsState;
216
+ return {
217
+ resultOk: testResult?.ok ? "true" : "false",
218
+ resultState: testResult ? "shown" : "hidden",
219
+ resultText: testResult
220
+ ? `${testResult.connection}: ${testResult.ok ? "connected" : (testResult.error ?? "failed")}`
221
+ : "",
222
+ resultTitle: testResult?.error ?? "",
223
+ testDisabled: !selected || actionsState.testing !== null,
224
+ testLabel: actionsState.testing ? "Testing…" : "Test Connection",
225
+ testState: sectionKey === "connections" ? "shown" : "hidden",
226
+ };
227
+ }
228
+
175
229
  /**
176
230
  * The actions renderer for a data-domain contributed section, or null when the section is not
177
231
  * data-domain or the platform lacks the data routes. Section keys "connections"/"data" are the
178
232
  * connector's host wire contract (the same literals the backend's data routes serve) — the generic
179
233
  * contributed-section renderer itself stays extension-agnostic.
180
234
  *
235
+ * It is a MOUNT rather than a template: the returned function is handed the host the section
236
+ * document made, and the second call for the same host projects into the row already there.
237
+ *
181
238
  * @param {string} sectionKey
182
- * @returns {((ctx: SectionActionsContext) => TemplateResult) | null}
239
+ * @returns {((host: HTMLElement, ctx: SectionActionsContext) => void) | null}
183
240
  */
184
241
  export function dataSectionActions(
185
242
  sectionKey: string,
186
- ): ((ctx: SectionActionsContext) => TemplateResult) | null {
243
+ ): ((host: HTMLElement, ctx: SectionActionsContext) => void) | null {
187
244
  if ((sectionKey !== "connections" && sectionKey !== "data") || !dataSurfaceAvailable()) {
188
245
  return null;
189
246
  }
190
- return (ctx) => renderSectionActions(sectionKey, ctx);
247
+ return (host, ctx) => paintSectionActions(host, sectionKey, ctx);
191
248
  }
192
249
 
193
250
  async function runTest(connection: string, rerender: () => void): Promise<void> {
@@ -200,58 +257,34 @@ async function runTest(connection: string, rerender: () => void): Promise<void>
200
257
  rerender();
201
258
  }
202
259
 
203
- function renderSectionActions(sectionKey: string, ctx: SectionActionsContext): TemplateResult {
204
- const { selected, rerender } = ctx;
205
- const { testResult } = actionsState;
260
+ function paintSectionActions(
261
+ host: HTMLElement,
262
+ sectionKey: string,
263
+ ctx: SectionActionsContext,
264
+ ): void {
265
+ const { rerender, selected } = ctx;
266
+ const existing = mounted.get(host);
267
+ if (existing) {
268
+ existing.update(projectActions(sectionKey, selected));
269
+ return;
270
+ }
206
271
  // On the connections section a selected entry scopes both Test and Push to that connection.
207
- const pushTarget = sectionKey === "connections" && selected ? selected : undefined;
208
- return html`
209
- <div class="data-section-actions">
210
- ${
211
- sectionKey === "connections"
212
- ? html`<sp-action-button
213
- size="s"
214
- class="data-action-test"
215
- ?disabled=${!selected || actionsState.testing !== null}
216
- @click=${() => {
217
- if (selected) {
218
- void runTest(selected, rerender);
219
- }
220
- }}
221
- >
222
- ${actionsState.testing ? "Testing…" : "Test Connection"}
223
- </sp-action-button>`
224
- : nothing
225
- }
226
- <sp-action-button
227
- size="s"
228
- class="data-action-push"
229
- @click=${() => {
230
- void startPush(pushTarget, rerender);
231
- }}
232
- >
233
- Push Schema
234
- </sp-action-button>
235
- <sp-action-button
236
- size="s"
237
- class="data-action-grid"
238
- @click=${() => {
239
- void openGridSourcePicker();
240
- }}
241
- >
242
- Open Data Grid
243
- </sp-action-button>
244
- ${
245
- testResult
246
- ? html`<span
247
- class="data-test-result ${testResult.ok ? "ok" : "failed"}"
248
- title=${testResult.error ?? ""}
249
- >
250
- ${testResult.connection}:
251
- ${testResult.ok ? "connected" : (testResult.error ?? "failed")}
252
- </span>`
253
- : nothing
254
- }
255
- </div>
256
- `;
272
+ const target = () => (sectionKey === "connections" ? (ctx.selected ?? undefined) : undefined);
273
+ mounted.set(
274
+ host,
275
+ mountDataActionsSurface(host, projectActions(sectionKey, selected), {
276
+ openGrid: () => {
277
+ void openGridSourcePicker();
278
+ },
279
+ push: () => {
280
+ void startPush(target(), rerender);
281
+ },
282
+ test: () => {
283
+ const connection = ctx.selected;
284
+ if (connection) {
285
+ void runTest(connection, rerender);
286
+ }
287
+ },
288
+ }),
289
+ );
257
290
  }
package/src/panels/dnd.ts CHANGED
@@ -64,16 +64,71 @@ interface DragMonitorDropArgs {
64
64
  location: { current: { dropTargets: { data: Record<string, unknown> }[] } };
65
65
  }
66
66
 
67
- /** Register DnD on layer rows — called from left-panel.js after render */
67
+ /**
68
+ * How the drag island addresses the Outline, which is a Jx document and emits no classes.
69
+ *
70
+ * `surfaces/panel-outline.json` is the tree; `part` is the only style and query hook a document
71
+ * offers (`ui.md` §3.1), so these three selectors are the contract between it and this module.
72
+ *
73
+ * The two per-row STATES this file writes are `jx-tree-item`'s own, and that is the whole of what
74
+ * the kit changed here: the element STYLES `data-dragging` and `data-drop` and deliberately BINDS
75
+ * neither, because a prop mirroring either would be a second writer that a repaint clears mid-drag.
76
+ * `data-drop-target` is what this file used to write, and it was a name only this file and one
77
+ * stylesheet rule knew — so the row wore a state the element could not draw. The verb cluster is
78
+ * `[part="verbs"]` rather than `[part="actions"]` for the neighbouring reason: `actions` is the
79
+ * name of the ELEMENT's slot container, and a selector that matched both would be answering about
80
+ * whichever the query happened to reach first.
81
+ */
82
+ const OUTLINE_ROOT = '[part="outline"]';
83
+ const OUTLINE_ROWS = '[part="row"]';
84
+ const OUTLINE_ACTIONS = '[part="verbs"]';
85
+
86
+ /**
87
+ * The frame a queued Outline registration is waiting on, so a second call REPLACES it.
88
+ *
89
+ * Null whenever nothing is queued — including from inside the callback, which clears it before it
90
+ * registers anything, so a completed frame leaves nothing to cancel.
91
+ */
92
+ let _layersFrame: number | null = null;
93
+
94
+ /**
95
+ * Register DnD on the Outline's rows — called from the panel's mount, after every repaint.
96
+ *
97
+ * **This function owns `view.dndCleanups`, and that ownership is the fix for 369 warnings a
98
+ * session.** The caller used to release the list and then call this, which is correct only if the
99
+ * registrations are made by the time the next caller looks — and they are not: the `rAF` below
100
+ * defers them past the point the caller believes they happened. Two repaints inside one frame
101
+ * therefore both found an EMPTY list, released nothing, and queued two registration passes that ran
102
+ * back to back over the same surviving row elements. Pragmatic-dnd said so, twice per row, forever:
103
+ * "You have already registered a `draggable` on the same element".
104
+ *
105
+ * So the release happens HERE, where the list's contents are known, and it happens at CALL time
106
+ * rather than in the frame: `view.dndCleanups` then always holds exactly what is registered right
107
+ * now, and no observer can read a list that has been superseded. The pending frame is cancelled
108
+ * with it, because a registration nobody has made yet is not one worth making twice.
109
+ *
110
+ * The `rAF` itself stays. The Outline's rows arrive when the runtime's reactive scope commits,
111
+ * which is a microtask the mount cannot await — the surface handle's `ready` promise resolves once,
112
+ * at the FIRST mount, and every repaint after that settles before the rows it projected exist.
113
+ * Registering synchronously would walk the previous window's rows.
114
+ */
68
115
  export function registerLayersDnD() {
69
- requestAnimationFrame(() => {
70
- const container = leftPanel?.querySelector(".layers-container") as HTMLElement | null;
116
+ if (_layersFrame !== null) {
117
+ cancelAnimationFrame(_layersFrame);
118
+ }
119
+ for (const cleanup of view.dndCleanups) {
120
+ cleanup();
121
+ }
122
+ view.dndCleanups = [];
123
+ _layersFrame = requestAnimationFrame(() => {
124
+ _layersFrame = null;
125
+ const container = leftPanel?.querySelector(OUTLINE_ROOT) as HTMLElement | null;
71
126
  if (!container) {
72
127
  return;
73
128
  }
74
129
 
75
130
  for (const row of container.querySelectorAll("[data-dnd-row]") as NodeListOf<HTMLElement>) {
76
- const rowPath = (row.dataset.path as string)
131
+ const rowPath = (row.dataset.value as string)
77
132
  .split("/")
78
133
  .map((s: string) => (/^\d+$/.test(s) ? Math.trunc(Number(s)) : s)) as JxPath;
79
134
  const rowDepth = Math.trunc(Number(row.dataset.dndDepth as string)) || 0;
@@ -84,7 +139,7 @@ export function registerLayersDnD() {
84
139
  draggable({
85
140
  canDrag({ element: _el, input }: DragCanDragArgs) {
86
141
  const target = elementAtPoint(input.clientX, input.clientY) as HTMLElement;
87
- if (target?.closest(".layer-actions")) {
142
+ if (target?.closest(OUTLINE_ACTIONS)) {
88
143
  return false;
89
144
  }
90
145
  return true;
@@ -99,14 +154,14 @@ export function registerLayersDnD() {
99
154
  disableNativeDragPreview({ nativeSetDragImage });
100
155
  },
101
156
  onDragStart() {
102
- row.classList.add("dragging");
157
+ row.dataset.dragging = "";
103
158
  view.layerDragSourceHeight = row.offsetHeight;
104
159
  if (isExpanded) {
105
160
  hideDescendantRows(row, container);
106
161
  }
107
162
  },
108
163
  onDrop() {
109
- row.classList.remove("dragging");
164
+ delete row.dataset.dragging;
110
165
  if (isExpanded) {
111
166
  renderOnly("leftPanel");
112
167
  }
@@ -248,7 +303,7 @@ export function registerComponentsDnD() {
248
303
  /** Register DnD on element (HTML block) rows */
249
304
  export function registerElementsDnD() {
250
305
  requestAnimationFrame(() => {
251
- const container = leftPanel?.querySelector(".panel-body") as HTMLElement | null;
306
+ const container = leftPanel?.querySelector('[part="content"]') as HTMLElement | null;
252
307
  if (!container) {
253
308
  return;
254
309
  }
@@ -282,10 +337,10 @@ export function registerElementsDnD() {
282
337
  * @param {HTMLElement} container
283
338
  */
284
339
  function hideDescendantRows(parentRow: HTMLElement, container: HTMLElement) {
285
- const prefix = `${parentRow.dataset.path}/`;
286
- const rows = container.querySelectorAll(".layers-tree .layer-row");
340
+ const prefix = `${parentRow.dataset.value}/`;
341
+ const rows = container.querySelectorAll(OUTLINE_ROWS);
287
342
  for (const r of rows) {
288
- if ((r as HTMLElement).dataset.path?.startsWith(prefix)) {
343
+ if ((r as HTMLElement).dataset.value?.startsWith(prefix)) {
289
344
  (r as HTMLElement).style.display = "none";
290
345
  }
291
346
  }
@@ -303,9 +358,9 @@ export function showLayerDropGap(
303
358
  ) {
304
359
  const instruction = extractInstruction(data);
305
360
 
306
- // Clear previous drop-target highlight
361
+ // Clear the previous drop-target mark
307
362
  if (view._currentDropTargetRow && view._currentDropTargetRow !== rowEl) {
308
- view._currentDropTargetRow.classList.remove("drop-target");
363
+ delete view._currentDropTargetRow.dataset.drop;
309
364
  }
310
365
 
311
366
  if (!instruction || instruction.type === "instruction-blocked") {
@@ -315,21 +370,21 @@ export function showLayerDropGap(
315
370
 
316
371
  if (instruction.type === "make-child") {
317
372
  clearLayerDropGap(container);
318
- rowEl.classList.add("drop-target");
373
+ rowEl.dataset.drop = "";
319
374
  view._currentDropTargetRow = rowEl;
320
375
  return;
321
376
  }
322
377
 
323
- rowEl.classList.remove("drop-target");
378
+ delete rowEl.dataset.drop;
324
379
  view._currentDropTargetRow = rowEl;
325
380
 
326
381
  // Shift rows to create gap
327
- const rows = [...container.querySelectorAll(".layers-tree .layer-row")];
382
+ const rows = [...container.querySelectorAll(OUTLINE_ROWS)];
328
383
  const targetIdx = rows.indexOf(rowEl);
329
384
  const gap = view.layerDragSourceHeight;
330
385
 
331
386
  for (let i = 0; i < rows.length; i++) {
332
- if ((rows[i] as HTMLElement).classList.contains("dragging")) {
387
+ if ((rows[i] as HTMLElement).dataset.dragging !== undefined) {
333
388
  continue;
334
389
  }
335
390
  if (instruction.type === "reorder-above") {
@@ -343,13 +398,13 @@ export function showLayerDropGap(
343
398
  /** @param {HTMLElement} container */
344
399
  export function clearLayerDropGap(container: HTMLElement) {
345
400
  if (view._currentDropTargetRow) {
346
- view._currentDropTargetRow.classList.remove("drop-target");
401
+ delete view._currentDropTargetRow.dataset.drop;
347
402
  view._currentDropTargetRow = null;
348
403
  }
349
- const rows = container.querySelectorAll(".layers-tree .layer-row");
404
+ const rows = container.querySelectorAll(OUTLINE_ROWS);
350
405
  for (const r of rows) {
351
406
  (r as HTMLElement).style.transform = "";
352
- // Also clear `display:none` left by hideDescendantRows. The `.layer-row` div has no `style`
407
+ // Also clear `display:none` left by hideDescendantRows. The row has no `style`
353
408
  // Lit binding, so an imperative style set during the drag survives the post-drop re-render on
354
409
  // Whichever row keeps that key — and a move is exactly the edit that hands a key to a different
355
410
  // Node. (The rows ARE keyed, by `pathKey`; the earlier form of this note said they were not,
@@ -5,19 +5,21 @@
5
5
  * It used to take over the canvas: `renderFunctionEditor` cleared `canvasWrap`, dropped every
6
6
  * canvas panel and mounted Monaco over the stage, so the page whose handler you were writing was
7
7
  * the one thing you could not see while writing it. It is a surface of the Bottom dock's **Logic**
8
- * tab now (plan §12 P8.5); `panels/formula-workspace.ts` owns that tab's record and calls the three
9
- * exports below — {@link functionEditorTemplate} for the container, {@link syncFunctionEditor} from
10
- * the panel's `afterRender`, and {@link closeFunctionEditor} for its Close. The canvas keeps
11
- * rendering the page underneath the dock; `canvas/canvas-render.ts` no longer knows this surface
12
- * exists.
8
+ * tab now (plan §12 P8.5); `panels/formula-workspace.ts` owns that tab's record and calls the two
9
+ * exports below — {@link syncFunctionEditor} from the panel's `afterRender`, and
10
+ * {@link closeFunctionEditor} for its Close. The container is no longer one of them: the Logic tab
11
+ * is a Jx document (`surfaces/logic-workspace.json`) and it draws the empty
12
+ * {@link CODE_HOST_SELECTOR} node itself, which is what an island is (studio-ui-guidelines.md
13
+ * §9.4). The canvas keeps rendering the page underneath the dock; `canvas/canvas-render.ts` no
14
+ * longer knows this surface exists.
13
15
  *
14
- * **The mount is driven by the DOM, not by a render call.** A dock tab's body is re-rendered by lit
15
- * whenever anything it reads changes, and lit will happily replace the container element out from
16
- * under a live Monaco instance (switching to the formula surface and back does exactly that). So
17
- * `syncFunctionEditor` asks the one question that matters — is the editor I hold still inside the
18
- * container I was just handed? — and rebuilds when the answer is no. Re-checking the target string
19
- * alone, which is all the takeover ever did, would have left a detached editor holding the user's
20
- * unsaved body.
16
+ * **The mount is driven by the DOM, not by a render call.** A dock tab's body is re-rendered
17
+ * whenever anything it reads changes, and a repaint will happily replace the container element out
18
+ * from under a live Monaco instance (switching to the formula surface and back does exactly that).
19
+ * So `syncFunctionEditor` asks the one question that matters — is the editor I hold still inside
20
+ * the container I was just handed? — and rebuilds when the answer is no. Re-checking the target
21
+ * string alone, which is all the takeover ever did, would have left a detached editor holding the
22
+ * user's unsaved body.
21
23
  *
22
24
  * **The move changed the REPAINT rate, not just the teardown rate, and the repaint is the one that
23
25
  * runs with the user's hands on the keyboard.** The dock's `afterRender` effect tracks every badge
@@ -32,7 +34,6 @@ import type * as monaco from "monaco-editor";
32
34
  import { loadMonaco, mountStillWanted } from "../services/monaco-lazy";
33
35
  import { monacoTheme } from "../shell";
34
36
  import { isJsonObject } from "@jxsuite/schema/guards";
35
- import { html } from "lit-html";
36
37
 
37
38
  import { getNodeAtPath, renderOnly, updateUi } from "../store";
38
39
  import { activeTab, tabIsLive } from "../workspace/workspace";
@@ -55,7 +56,6 @@ import type { OxLintDiagnostic } from "../services/code-services";
55
56
  import type { JxPrototypeDef } from "@jxsuite/schema/types";
56
57
  import type { JxPath } from "../state";
57
58
  import type { Tab } from "../tabs/tab";
58
- import type { TemplateResult } from "lit-html";
59
59
 
60
60
  type EditingTarget =
61
61
  | { type: "def"; defName: string }
@@ -88,10 +88,17 @@ function getFunctionBody(tab: Tab | null | undefined, editing: EditingTarget | n
88
88
  return "";
89
89
  }
90
90
 
91
- /** Where Monaco goes inside the Logic tab. Empty on purpose — the editor fills it imperatively. */
92
- export function functionEditorTemplate(): TemplateResult {
93
- return html`<div class="fw-code"></div>`;
94
- }
91
+ /**
92
+ * The element the Logic tab draws for Monaco to fill.
93
+ *
94
+ * `surfaces/logic-workspace.json` renders it and nothing inside it — the island contract of
95
+ * studio-ui-guidelines.md §9.4 — so the code surface is addressed by `part` rather than by the
96
+ * `.fw-code` class the lit takeover carried. It is a SELECTOR rather than an announced node on
97
+ * purpose: this module mounts by asking the painted DOM what is there (see the header), and a node
98
+ * announced by `onNodeCreated` is one reconcile step short of being in the page, which is exactly
99
+ * the state an editor that measures its container must not be mounted into.
100
+ */
101
+ export const CODE_HOST_SELECTOR = '[part="code-host"]';
95
102
 
96
103
  /**
97
104
  * Create, re-target or tear down the Monaco instance for the Logic tab's current body.
@@ -103,7 +110,7 @@ export function functionEditorTemplate(): TemplateResult {
103
110
  export function syncFunctionEditor(host: HTMLElement): void {
104
111
  const tab = activeTab.value;
105
112
  const editing = tab?.session.ui.editingFunction as EditingTarget | null | undefined;
106
- const container = editing && tab ? host.querySelector<HTMLElement>(".fw-code") : null;
113
+ const container = editing && tab ? host.querySelector<HTMLElement>(CODE_HOST_SELECTOR) : null;
107
114
  if (!container || !tab || !editing) {
108
115
  // Either nothing is open in the code surface, or the formula surface is showing: whichever
109
116
  // Monaco instance we hold is detached DOM, and holding it leaks a model plus its listeners.