@jxsuite/studio 8.0.1 → 9.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 (282) hide show
  1. package/dist/chunks/{2020-5wtzce5g.js → 2020-89fz3pfy.js} +3 -3
  2. package/dist/chunks/adapter-ay13gema.js +4 -0
  3. package/dist/chunks/add-new-flow-nmkqpjym.js +4 -0
  4. package/dist/chunks/cf-account-picker-2e06qxey.js +4 -0
  5. package/dist/chunks/cf-settings-5y04810c.js +4 -0
  6. package/dist/chunks/color-04361ttk.js +4 -0
  7. package/dist/chunks/{color-area-6rbra5dy.js → color-area-h8dbasp1.js} +2 -2
  8. package/dist/chunks/{color-field-gy56c94g.js → color-field-qv5r2b16.js} +3 -3
  9. package/dist/chunks/{color-slider-sqqdyf6c.js → color-slider-nz2mrzky.js} +2 -2
  10. package/dist/chunks/{combobox-72h32ejk.js → combobox-6hs00996.js} +2 -2
  11. package/dist/chunks/components-3vf75n83.js +4 -0
  12. package/dist/chunks/content-source-4f2raf4a.js +4 -0
  13. package/dist/chunks/{convert-to-repeater-he70fc2b.js → convert-to-repeater-j9hfcj4f.js} +3 -3
  14. package/dist/chunks/editor-645krvtz.js +4 -0
  15. package/dist/chunks/entry-commands-3qmv8wkr.js +4 -0
  16. package/dist/chunks/{extension-sections-0egb88dm.js → extension-sections-thfke054.js} +3 -3
  17. package/dist/chunks/file-ops-kkhp9ma7.js +4 -0
  18. package/dist/chunks/files-yswdhxrf.js +4 -0
  19. package/dist/chunks/format-host-4g8ex6bz.js +4 -0
  20. package/dist/chunks/fs-events-z9gpvc6t.js +4 -0
  21. package/dist/chunks/grid-open-fm4j183c.js +4 -0
  22. package/dist/chunks/{grid-view-qg1b5eqx.js → grid-view-7d2nx83y.js} +16 -15
  23. package/dist/chunks/{icons-63bjtbs7.js → icons-853n6qt3.js} +2 -2
  24. package/dist/chunks/{iframe-entry-pkgmcgp0.js → iframe-entry-2x9bn5ng.js} +4 -4
  25. package/dist/chunks/{iframe-entry-99nr5zfb.js → iframe-entry-42hpmwz5.js} +4 -4
  26. package/dist/chunks/{iframe-entry-76j8vwwx.js → iframe-entry-b5qgggyp.js} +2 -2
  27. package/dist/chunks/{iframe-entry-2zggzajv.js → iframe-entry-btck0e9s.js} +4 -4
  28. package/dist/chunks/iframe-host-q7fedsmr.js +4 -0
  29. package/dist/chunks/{index-32eqzv1k.js → index-jxmt7vh8.js} +3 -3
  30. package/dist/chunks/index-pt4wh98x.js +4 -0
  31. package/dist/chunks/{javascript-pjp734q4.js → javascript-vmqp56ke.js} +2 -2
  32. package/dist/chunks/{jsonMode-njkvsa02.js → jsonMode-n3wmpant.js} +5 -5
  33. package/dist/chunks/jx-validate-19y62knt.js +4 -0
  34. package/dist/chunks/layers-panel-1qvc83y9.js +4 -0
  35. package/dist/chunks/layers-qf0bc7ze.js +4 -0
  36. package/dist/chunks/{listbox-c421cf8c.js → listbox-7gka1h86.js} +2 -2
  37. package/dist/chunks/lit-html-wyqw04y2.js +4 -0
  38. package/dist/chunks/media-library-f9d5qcjb.js +4 -0
  39. package/dist/chunks/media-picker-rsb1fmk2.js +4 -0
  40. package/dist/chunks/{menu-bdpzbfvs.js → menu-d2jxpgma.js} +2 -2
  41. package/dist/chunks/{monaco-binding-vq1hgnn0.js → monaco-binding-wfhmz89d.js} +3 -3
  42. package/dist/chunks/monaco-buffer-ak0raadw.js +4 -0
  43. package/dist/chunks/{monaco-setup-xrd2cbkp.js → monaco-setup-fty7a8vg.js} +3 -3
  44. package/dist/chunks/notify-4qj70q0x.js +4 -0
  45. package/dist/chunks/parse-n8dfxnqf.js +4 -0
  46. package/dist/chunks/platform-ehg6t9vd.js +4 -0
  47. package/dist/chunks/{popover-b89sfej7.js → popover-9tf4cjrk.js} +2 -2
  48. package/dist/chunks/publish-panel-yhmda3cd.js +4 -0
  49. package/dist/chunks/{publish-quick-qx2455cj.js → publish-quick-12hh8926.js} +3 -3
  50. package/dist/chunks/publish-workspace-hx8qdv9p.js +4 -0
  51. package/dist/chunks/quick-search-r955m3q1.js +4 -0
  52. package/dist/chunks/references-8gxv0x7t.js +4 -0
  53. package/dist/chunks/right-panel-jarwqjpy.js +4 -0
  54. package/dist/chunks/source-control-84qt25m9.js +4 -0
  55. package/dist/chunks/{split-c9zfdgxf.js → split-m5rwn31z.js} +2 -2
  56. package/dist/chunks/studio-0nefxhar.js +7 -0
  57. package/dist/chunks/studio-0rg30pvs.js +5 -0
  58. package/dist/chunks/{studio-s32578pn.js → studio-14hh60j8.js} +4 -4
  59. package/dist/chunks/studio-1cfyd1ys.js +5 -0
  60. package/dist/chunks/studio-2bq7hheq.js +5 -0
  61. package/dist/chunks/{studio-zz9qe3rw.js → studio-32d8wyxq.js} +37 -37
  62. package/dist/chunks/studio-3hpcawh8.js +4 -0
  63. package/dist/chunks/{studio-svb7yyve.js → studio-4j35hgsw.js} +4 -4
  64. package/dist/chunks/{studio-x1x167jh.js → studio-4qg61g9j.js} +4 -4
  65. package/dist/chunks/studio-4rgem12q.js +5 -0
  66. package/dist/chunks/studio-6k9djnxw.js +5 -0
  67. package/dist/chunks/studio-6rbaedw2.js +9 -0
  68. package/dist/chunks/studio-732mw0g8.js +5 -0
  69. package/dist/chunks/studio-79r8msnr.js +7 -0
  70. package/dist/chunks/studio-7q6jdd4h.js +5 -0
  71. package/dist/chunks/{studio-r5qy30vx.js → studio-8hf8qcm1.js} +4 -4
  72. package/dist/chunks/{studio-8tr6cfrc.js → studio-8pne0rx4.js} +4 -4
  73. package/dist/chunks/{studio-y0n7yxea.js → studio-9179bsm7.js} +7 -7
  74. package/dist/chunks/{studio-pbxa5fpc.js → studio-9ff0vqff.js} +3 -3
  75. package/dist/chunks/studio-9gzvypw4.js +5 -0
  76. package/dist/chunks/studio-9ndgd55w.js +5 -0
  77. package/dist/chunks/studio-9ra9e7m4.js +5 -0
  78. package/dist/chunks/studio-a6e5fzve.js +5 -0
  79. package/dist/chunks/studio-a9k86nq6.js +5 -0
  80. package/dist/chunks/studio-ae7a69jc.js +6 -0
  81. package/dist/chunks/studio-aghsg0ds.js +7 -0
  82. package/dist/chunks/{studio-k3xxbagr.js → studio-ajw4k8hp.js} +3 -3
  83. package/dist/chunks/{studio-qmn1xc24.js → studio-apapy17g.js} +4 -4
  84. package/dist/chunks/{studio-8m0y2qe7.js → studio-by8x0jvc.js} +4 -4
  85. package/dist/chunks/{studio-wbcjbhy1.js → studio-c88gq88j.js} +5 -5
  86. package/dist/chunks/{studio-n0c5h6mf.js → studio-cg54vtet.js} +4 -4
  87. package/dist/chunks/studio-dvhxxxbd.js +5 -0
  88. package/dist/chunks/{studio-3q40e3rj.js → studio-e4rq6x0q.js} +4 -4
  89. package/dist/chunks/{studio-fbhxxc5f.js → studio-ekzbgnjp.js} +4 -4
  90. package/dist/chunks/studio-fg4fj9ec.js +10 -0
  91. package/dist/chunks/studio-fj6jzgxw.js +5 -0
  92. package/dist/chunks/{studio-nh6d342n.js → studio-g45r5vm8.js} +7 -7
  93. package/dist/chunks/{studio-a2bvaptz.js → studio-gczve8zf.js} +4 -4
  94. package/dist/chunks/studio-ge08zwpv.js +5 -0
  95. package/dist/chunks/studio-gk9yk8dj.js +12 -0
  96. package/dist/chunks/{studio-bbe4c90a.js → studio-gskkgfe3.js} +4 -4
  97. package/dist/chunks/{studio-83mk4bgg.js → studio-h4jbgne2.js} +8 -8
  98. package/dist/chunks/{studio-b7y5mr30.js → studio-hcy9zeac.js} +4 -4
  99. package/dist/chunks/studio-ht81xjkr.js +5 -0
  100. package/dist/chunks/{studio-jaaz8ce9.js → studio-jr30g4ae.js} +4 -4
  101. package/dist/chunks/{studio-qgh13jtz.js → studio-k5n4es74.js} +4 -4
  102. package/dist/chunks/{studio-ccv2svc6.js → studio-k6hbx2fc.js} +4 -4
  103. package/dist/chunks/{studio-9tmebf0s.js → studio-kqh7fxn6.js} +4 -4
  104. package/dist/chunks/{studio-q0mvbaq6.js → studio-kyw47pet.js} +4 -4
  105. package/dist/chunks/studio-mkw17ngg.js +5 -0
  106. package/dist/chunks/{studio-x9hsze61.js → studio-myb4mf0h.js} +4 -4
  107. package/dist/chunks/studio-n4qq1n57.js +5 -0
  108. package/dist/chunks/studio-nfmpmkqb.js +5 -0
  109. package/dist/chunks/studio-nfwacw31.js +5 -0
  110. package/dist/chunks/{studio-rthyg42z.js → studio-nm86874b.js} +172 -172
  111. package/dist/chunks/studio-nqexty8x.js +16 -0
  112. package/dist/chunks/studio-nr0kcqc6.js +5 -0
  113. package/dist/chunks/{studio-jsgf2q5k.js → studio-nvfa137z.js} +5 -5
  114. package/dist/chunks/studio-psh8mwnw.js +4 -0
  115. package/dist/chunks/studio-qd0cycm4.js +9 -0
  116. package/dist/chunks/{studio-tfkznv39.js → studio-qevf5z9d.js} +4 -4
  117. package/dist/chunks/studio-qs5fmhtj.js +14 -0
  118. package/dist/chunks/studio-ry4789ng.js +7 -0
  119. package/dist/chunks/studio-s4fq9jht.js +5 -0
  120. package/dist/chunks/studio-sc35ttdk.js +5 -0
  121. package/dist/chunks/studio-sm2f0sc6.js +6 -0
  122. package/dist/chunks/{studio-3qeh9t0h.js → studio-spza69tb.js} +5 -5
  123. package/dist/chunks/studio-t6dqnnft.js +5 -0
  124. package/dist/chunks/{studio-43sd2mam.js → studio-tfmhnwyr.js} +3 -3
  125. package/dist/chunks/studio-tn7v8gey.js +6 -0
  126. package/dist/chunks/{studio-tft6r105.js → studio-trcfer2b.js} +4 -4
  127. package/dist/chunks/studio-tyw7tk0x.js +5 -0
  128. package/dist/chunks/{studio-jcnsdaep.js → studio-tyzgte21.js} +4 -4
  129. package/dist/chunks/studio-vtey9w98.js +5 -0
  130. package/dist/chunks/studio-ws2r1d7e.js +5 -0
  131. package/dist/chunks/studio-x2trkhk5.js +5 -0
  132. package/dist/chunks/{studio-mn0476ag.js → studio-xzgp0cp7.js} +4 -4
  133. package/dist/chunks/studio-y47090vq.js +5 -0
  134. package/dist/chunks/{studio-5g0rprdt.js → studio-yjh9gddd.js} +5 -5
  135. package/dist/chunks/studio-ywf9y1e2.js +5 -0
  136. package/dist/chunks/{studio-k7evxqh4.js → studio-z1p91z5a.js} +4 -4
  137. package/dist/chunks/studio-ztppbam0.js +5 -0
  138. package/dist/chunks/{toast-host-1yg5ar8d.js → toast-host-g3r2s0kn.js} +2 -2
  139. package/dist/chunks/toast-w11qpkyz.js +4 -0
  140. package/dist/chunks/{tooltip-yypz28gq.js → tooltip-dj1pvgz7.js} +2 -2
  141. package/dist/chunks/{tree-9xa4hm7n.js → tree-j0ebwr5s.js} +2 -2
  142. package/dist/chunks/{tsMode-epyfz1hv.js → tsMode-byje4a01.js} +5 -5
  143. package/dist/chunks/workspace-7q4arnt3.js +4 -0
  144. package/dist/chunks/workspace-home-ge027kr6.js +4 -0
  145. package/dist/chunks/{ws-client-bv552sfx.js → ws-client-h09h6sqg.js} +3 -3
  146. package/dist/iframe-entry.js +14 -14
  147. package/dist/manifest.json +76 -76
  148. package/dist/studio.js +88 -88
  149. package/package.json +15 -16
  150. package/src/browse/component-examples.ts +15 -224
  151. package/src/browse/library-preview.ts +6 -13
  152. package/src/browse/preview-root.ts +7 -4
  153. package/src/canvas/canvas-utils.ts +18 -4
  154. package/src/canvas/iframe-editable-root.ts +13 -4
  155. package/src/canvas/iframe-entry.ts +3 -1
  156. package/src/canvas/iframe-interaction.ts +11 -2
  157. package/src/canvas/iframe-render.ts +25 -3
  158. package/src/canvas/preview-placeholder.ts +120 -0
  159. package/src/collab/collab-session.ts +6 -2
  160. package/src/commands/context.ts +4 -0
  161. package/src/commands/defaults.ts +2 -0
  162. package/src/commands/live-context.ts +2 -0
  163. package/src/editor/shortcuts.ts +3 -0
  164. package/src/files/files.ts +6 -3
  165. package/src/new-project/new-project-modal.ts +1 -4
  166. package/src/panels/ai-panel.ts +27 -34
  167. package/src/panels/component-preview.ts +5 -0
  168. package/src/panels/pane-context.ts +43 -18
  169. package/src/panels/site-model.ts +7 -19
  170. package/src/panels/site-panel.ts +2 -25
  171. package/src/panels/stylebook-doc.ts +2 -53
  172. package/src/platform.ts +20 -0
  173. package/src/platforms/devserver.ts +2 -120
  174. package/src/services/ai-ask.ts +29 -171
  175. package/src/services/ai-command-tools.ts +40 -50
  176. package/src/services/ai-import-tools.ts +4 -5
  177. package/src/services/ai-project-tools.ts +13 -3
  178. package/src/services/ai-tools.ts +26 -564
  179. package/src/services/ai-writes.ts +84 -2
  180. package/src/services/document-assistant.ts +29 -58
  181. package/src/services/harness/assistant-tools.ts +68 -0
  182. package/src/services/harness/interaction-store.ts +118 -0
  183. package/src/services/harness/studio-documents.ts +105 -0
  184. package/src/services/harness/turn-hooks.ts +1 -6
  185. package/src/services/project-adoption.ts +8 -16
  186. package/src/services/references.ts +0 -0
  187. package/src/services/tool-executor.ts +25 -22
  188. package/src/state.ts +3 -13
  189. package/src/style/stylebook-specimens.ts +11 -15
  190. package/src/surfaces/files-panel.json +12 -0
  191. package/src/surfaces/files-panel.ts +5 -2
  192. package/src/surfaces/pane-context.json +286 -265
  193. package/src/surfaces/pane-context.ts +17 -8
  194. package/src/surfaces/welcome.ts +4 -1
  195. package/src/tabs/selection.ts +14 -109
  196. package/src/tabs/tab.ts +15 -7
  197. package/src/tabs/transact.ts +316 -124
  198. package/src/types.ts +13 -8
  199. package/src/utils/geometry.ts +49 -2
  200. package/dist/chunks/adapter-5tphg7xe.js +0 -4
  201. package/dist/chunks/add-new-flow-psym14sn.js +0 -4
  202. package/dist/chunks/cf-account-picker-haqazq5r.js +0 -4
  203. package/dist/chunks/cf-settings-h2wrh6hq.js +0 -4
  204. package/dist/chunks/color-m7r1vk54.js +0 -4
  205. package/dist/chunks/components-r22xca09.js +0 -4
  206. package/dist/chunks/content-source-mmppmcyg.js +0 -4
  207. package/dist/chunks/editor-ccd9jwsa.js +0 -4
  208. package/dist/chunks/entry-commands-6qxz9e8p.js +0 -4
  209. package/dist/chunks/file-ops-qnab36ek.js +0 -4
  210. package/dist/chunks/files-rcn56qvm.js +0 -4
  211. package/dist/chunks/format-host-yxz0kjjs.js +0 -4
  212. package/dist/chunks/fs-events-d1qxq4z4.js +0 -4
  213. package/dist/chunks/grid-open-4z1g062t.js +0 -4
  214. package/dist/chunks/iframe-host-ssv7kyj0.js +0 -4
  215. package/dist/chunks/index-f0jn7nnp.js +0 -4
  216. package/dist/chunks/jx-validate-ttasrbh7.js +0 -4
  217. package/dist/chunks/layers-bgyr11tr.js +0 -4
  218. package/dist/chunks/layers-panel-7ez66zeq.js +0 -4
  219. package/dist/chunks/lit-html-v9gh687x.js +0 -4
  220. package/dist/chunks/media-library-sq468wts.js +0 -4
  221. package/dist/chunks/media-picker-shfe59pt.js +0 -4
  222. package/dist/chunks/monaco-buffer-3afgwvbp.js +0 -4
  223. package/dist/chunks/notify-kzrjr3fv.js +0 -4
  224. package/dist/chunks/parse-v77xtwv7.js +0 -4
  225. package/dist/chunks/platform-7v4rtd7m.js +0 -4
  226. package/dist/chunks/publish-panel-2z9gw8ee.js +0 -4
  227. package/dist/chunks/publish-workspace-wrc1dgwx.js +0 -4
  228. package/dist/chunks/quick-search-n0t0eqxb.js +0 -4
  229. package/dist/chunks/references-9547rg5s.js +0 -4
  230. package/dist/chunks/right-panel-wsgnr9pn.js +0 -4
  231. package/dist/chunks/source-control-kwktr9y6.js +0 -4
  232. package/dist/chunks/studio-03ct6yfv.js +0 -9
  233. package/dist/chunks/studio-07rcfje3.js +0 -5
  234. package/dist/chunks/studio-3e54qh39.js +0 -7
  235. package/dist/chunks/studio-3exxhz5g.js +0 -5
  236. package/dist/chunks/studio-3qqjeep5.js +0 -6
  237. package/dist/chunks/studio-4hp8pkyt.js +0 -5
  238. package/dist/chunks/studio-58xg6j2q.js +0 -9
  239. package/dist/chunks/studio-6m380wp7.js +0 -5
  240. package/dist/chunks/studio-80jyh1xh.js +0 -4
  241. package/dist/chunks/studio-8vcvfs7r.js +0 -6
  242. package/dist/chunks/studio-bavb31r0.js +0 -5
  243. package/dist/chunks/studio-c05wdnt3.js +0 -5
  244. package/dist/chunks/studio-d5grtb9e.js +0 -16
  245. package/dist/chunks/studio-df0baea9.js +0 -5
  246. package/dist/chunks/studio-dgk4dqtx.js +0 -7
  247. package/dist/chunks/studio-e1g64q43.js +0 -5
  248. package/dist/chunks/studio-ed1hp6zf.js +0 -6
  249. package/dist/chunks/studio-ed3xx40h.js +0 -7
  250. package/dist/chunks/studio-f14e1zdj.js +0 -5
  251. package/dist/chunks/studio-fyh0jc96.js +0 -5
  252. package/dist/chunks/studio-gcxk20n7.js +0 -5
  253. package/dist/chunks/studio-kt3pjkwd.js +0 -5
  254. package/dist/chunks/studio-m8g16bgz.js +0 -5
  255. package/dist/chunks/studio-mx1smyq0.js +0 -5
  256. package/dist/chunks/studio-nqxqf8p2.js +0 -4
  257. package/dist/chunks/studio-p4nrkvqr.js +0 -5
  258. package/dist/chunks/studio-pgmvdv7z.js +0 -7
  259. package/dist/chunks/studio-ph84avkf.js +0 -5
  260. package/dist/chunks/studio-q0tccd43.js +0 -5
  261. package/dist/chunks/studio-q7rtx6zq.js +0 -14
  262. package/dist/chunks/studio-qwdqwkj0.js +0 -5
  263. package/dist/chunks/studio-rj9eamf8.js +0 -5
  264. package/dist/chunks/studio-rptgsk96.js +0 -5
  265. package/dist/chunks/studio-s19tp1xr.js +0 -5
  266. package/dist/chunks/studio-syreb644.js +0 -5
  267. package/dist/chunks/studio-tf9jryb1.js +0 -10
  268. package/dist/chunks/studio-txf2kysx.js +0 -5
  269. package/dist/chunks/studio-v8867ddv.js +0 -12
  270. package/dist/chunks/studio-vxq7fcvv.js +0 -5
  271. package/dist/chunks/studio-w4rz9hdk.js +0 -5
  272. package/dist/chunks/studio-wc649wss.js +0 -5
  273. package/dist/chunks/studio-wys23mxz.js +0 -5
  274. package/dist/chunks/studio-y3ahhdpx.js +0 -5
  275. package/dist/chunks/studio-z97c48fk.js +0 -5
  276. package/dist/chunks/studio-zat62m0c.js +0 -5
  277. package/dist/chunks/studio-zcd2e7yz.js +0 -5
  278. package/dist/chunks/toast-1gv0h53h.js +0 -4
  279. package/dist/chunks/workspace-dz7nxfhv.js +0 -4
  280. package/dist/chunks/workspace-home-xsd7hkjw.js +0 -4
  281. package/src/services/directory-picker.ts +0 -187
  282. package/src/services/gated-registry.ts +0 -77
@@ -110,10 +110,12 @@ export interface PaneContextView {
110
110
  /** The lens's stated rendering context — "Tablet · français". */
111
111
  summary: string;
112
112
 
113
+ /** The Editor axis at all: drawn in the full bar, never in a lens. */
114
+ editorState: "shown" | "hidden";
113
115
  editorMode: "static" | "picker";
114
116
  editorLabel: string;
115
- editorValue: string;
116
- editorOptions: SurfaceOption[];
117
+ /** The declared editor kinds, one segment each, when there are several to choose between. */
118
+ editors: PaneContextChoice[];
117
119
 
118
120
  viewState: "shown" | "hidden";
119
121
  views: PaneContextChoice[];
@@ -126,7 +128,10 @@ export interface PaneContextView {
126
128
  previewOn: boolean;
127
129
  previewHint: string;
128
130
 
129
- /** "Base · Auto" — what the rendering-context trigger reads before it is opened. */
131
+ /**
132
+ * What the More rendering context trigger reads beside its glyph: only what its popover holds and
133
+ * is not at rest ("français", "No layout"); empty when there is nothing to say.
134
+ */
130
135
  contextSummary: string;
131
136
  resolvingState: "shown" | "hidden";
132
137
  /** "2 set", or "Defaults". */
@@ -135,6 +140,8 @@ export interface PaneContextView {
135
140
  params: PaneContextParam[];
136
141
  props: PaneContextProp[];
137
142
 
143
+ /** The size group on the bar: hidden when the project declares no breakpoint to choose. */
144
+ sizesState: "shown" | "hidden";
138
145
  sizes: PaneContextChoice[];
139
146
  schemeState: "shown" | "hidden";
140
147
  schemes: PaneContextChoice[];
@@ -237,10 +244,10 @@ function project(scope: PaneContextScope, view: PaneContextView): void {
237
244
  scope.backHint = view.backHint;
238
245
  scope.bannerState = view.bannerState;
239
246
  scope.summary = view.summary;
247
+ scope.editorState = view.editorState;
240
248
  scope.editorMode = view.editorMode;
241
249
  scope.editorLabel = view.editorLabel;
242
- scope.editorValue = view.editorValue;
243
- scope.editorOptions = view.editorOptions;
250
+ scope.editors = view.editors;
244
251
  scope.viewState = view.viewState;
245
252
  scope.contextState = view.contextState;
246
253
  scope.views = view.views;
@@ -254,6 +261,7 @@ function project(scope: PaneContextScope, view: PaneContextView): void {
254
261
  scope.params = view.params;
255
262
  scope.props = view.props;
256
263
  scope.sizes = view.sizes;
264
+ scope.sizesState = view.sizesState;
257
265
  scope.schemeState = view.schemeState;
258
266
  scope.schemes = view.schemes;
259
267
  scope.localeState = view.localeState;
@@ -281,11 +289,11 @@ export function emptyPaneContextView(): PaneContextView {
281
289
  barMode: "full",
282
290
  contextRegion: "",
283
291
  contextState: "shown",
284
- contextSummary: "Base",
292
+ contextSummary: "",
285
293
  editorLabel: "",
286
294
  editorMode: "static",
287
- editorOptions: [],
288
- editorValue: "",
295
+ editorState: "hidden",
296
+ editors: [],
289
297
  exportState: "hidden",
290
298
  featureState: "hidden",
291
299
  features: [],
@@ -309,6 +317,7 @@ export function emptyPaneContextView(): PaneContextView {
309
317
  resolvingState: "hidden",
310
318
  schemes: [],
311
319
  schemeState: "hidden",
320
+ sizesState: "hidden",
312
321
  sizes: [],
313
322
  summary: "Base",
314
323
  views: [],
@@ -22,6 +22,7 @@
22
22
  import { getAccountStatus, getBannerNotices, needsAppInstall } from "../account-status";
23
23
  import { runOfferedAction } from "../account/action-flow";
24
24
  import { platformSupportsAddRepo } from "../new-project/add-repo-modal";
25
+ import { canOpenProject, getPlatform } from "../platform";
25
26
  import { getProjectList } from "../project-list";
26
27
  import { reactive } from "../reactivity";
27
28
  import { MINUTE, now } from "../services/clock";
@@ -226,7 +227,9 @@ function project(): Omit<WelcomeScope, "run" | "open" | "remove" | "clear" | "no
226
227
  // One entry, not two: the starter gallery IS the first step of New Project now, so the
227
228
  // Separate "Start from an Example…" button it used to hide behind is gone.
228
229
  { icon: "plus", id: "new", title: "New Project…" },
229
- { icon: "folder-open", id: "open", title: "Open Project…" },
230
+ ...(canOpenProject(getPlatform())
231
+ ? [{ icon: "folder-open", id: "open", title: "Open Project…" } as const]
232
+ : []),
230
233
  ...(platformSupportsClone()
231
234
  ? [{ icon: "download-simple", id: "clone", title: "Clone Git Repository…" } as const]
232
235
  : []),
@@ -42,10 +42,22 @@
42
42
  * standing between a mixed selection and a half-applied, unrecorded delete.
43
43
  */
44
44
 
45
- import { isNumber } from "@jxsuite/schema/guards";
45
+ import { isAncestor } from "@jxsuite/schema/doc-ops";
46
46
 
47
47
  import type { JxPath } from "../state";
48
- import { isAncestor, pathsEqual } from "../state";
48
+ import { pathsEqual } from "../state";
49
+
50
+ /* The structural-path helpers live beside the doc-op vocabulary, so any host that edits a document
51
+ the way Studio does orders and filters a batch the same way. Re-exported here, where every
52
+ Studio caller already imports them. */
53
+ export {
54
+ comparePaths,
55
+ isSpliceablePath,
56
+ spliceCoordinate,
57
+ structuralBatch,
58
+ topLevelSelection,
59
+ } from "@jxsuite/schema/doc-ops";
60
+ export type { SpliceCoordinate } from "@jxsuite/schema/doc-ops";
49
61
 
50
62
  /**
51
63
  * The path single-target surfaces address — the most recently added, or `null` when empty.
@@ -171,113 +183,6 @@ export function pruneSelection(selection: readonly JxPath[], removed: JxPath): J
171
183
  return clonePaths(selection.filter((p) => !isAncestor(removed, p)));
172
184
  }
173
185
 
174
- /**
175
- * Order two paths the way the document reads: parents before children, siblings by index.
176
- *
177
- * Segments are compared pairwise; numbers numerically (so `children/10` follows `children/9`), and
178
- * anything else by string order. A prefix sorts before what extends it.
179
- *
180
- * @param {JxPath} a
181
- * @param {JxPath} b
182
- * @returns {number}
183
- */
184
- export function comparePaths(a: JxPath, b: JxPath): number {
185
- const len = Math.min(a.length, b.length);
186
- for (let i = 0; i < len; i++) {
187
- const x = a[i]!;
188
- const y = b[i]!;
189
- if (x === y) {
190
- continue;
191
- }
192
- if (isNumber(x) && isNumber(y)) {
193
- return x - y;
194
- }
195
- return String(x) < String(y) ? -1 : 1;
196
- }
197
- return a.length - b.length;
198
- }
199
-
200
- /**
201
- * Drop any path whose ancestor is also selected.
202
- *
203
- * Deleting a `<section>` and one of its own paragraphs is one deletion, not two: the paragraph goes
204
- * with its parent, and a second splice into coordinates that no longer exist is how a batch
205
- * corrupts a document.
206
- *
207
- * @param {readonly JxPath[]} selection
208
- * @returns {JxPath[]}
209
- */
210
- export function topLevelSelection(selection: readonly JxPath[]): JxPath[] {
211
- return clonePaths(
212
- selection.filter((p) => !selection.some((q) => !pathsEqual(q, p) && isAncestor(q, p))),
213
- );
214
- }
215
-
216
- /**
217
- * Whether `path` names a position a structural verb can splice — a tail of `"children"` + index.
218
- *
219
- * Every structural mutator (`mutateRemoveNode`, `mutateDuplicateNode`, `mutateWrapNode`) reaches
220
- * its parent with `parentElementPath` — drop the last two segments — and its position with
221
- * `childIndex` — take the last. That produces a splice coordinate for exactly one path shape, and
222
- * the Outline emits three others as first-class rows: the document element (`[]`), a repeater's map
223
- * template (`[…, "children", 1, "map"]`) and a `$switch` case (`[…, "cases", "warn"]`). For the
224
- * template, `parentElementPath` resolves to the enclosing children ARRAY, whose `.children` is
225
- * `undefined`, so the splice throws mid-transaction; for a case it splices at `NaN` and takes the
226
- * wrong child.
227
- *
228
- * Selecting one of those beside an ordinary element is a single ctrl-click, so this is the
229
- * invariant that keeps a batch from mutating the document and then throwing before anything is
230
- * recorded.
231
- *
232
- * @param {JxPath} path
233
- * @returns {boolean}
234
- */
235
- export function isSpliceablePath(path: JxPath): boolean {
236
- return spliceCoordinate(path) !== null;
237
- }
238
-
239
- /** Where a structural verb splices: the parent element's path and the index in its children. */
240
- export interface SpliceCoordinate {
241
- parentPath: JxPath;
242
- index: number;
243
- }
244
-
245
- /**
246
- * The splice coordinate `path` names, or `null` for no path and for every path
247
- * {@link isSpliceablePath} refuses.
248
- *
249
- * @param {JxPath | null | undefined} path
250
- * @returns {SpliceCoordinate | null}
251
- */
252
- export function spliceCoordinate(path: JxPath | null | undefined): SpliceCoordinate | null {
253
- const index = path?.at(-1);
254
- return path && path.at(-2) === "children" && isNumber(index)
255
- ? { index, parentPath: path.slice(0, -2) }
256
- : null;
257
- }
258
-
259
- /**
260
- * The order a structural batch must run in: contained paths dropped, unspliceable paths dropped,
261
- * then LAST node first.
262
- *
263
- * Descending document order is what makes a loop of splices safe. Removing or duplicating at index
264
- * `n` renumbers every sibling after `n`, so a batch that starts at the end never touches a
265
- * coordinate a later step still needs. It is also why duplicating a multi-selection inserts each
266
- * clone directly after its own original instead of walking the whole run forward.
267
- *
268
- * Containment is decided BEFORE spliceability, on the selection the user actually made: a selected
269
- * repeater template still shadows its own descendants, so selecting the template and something
270
- * inside it yields nothing rather than quietly deleting the child the user never pointed at.
271
- *
272
- * @param {readonly JxPath[]} selection
273
- * @returns {JxPath[]} Deepest/last first, every entry a splice coordinate.
274
- */
275
- export function structuralBatch(selection: readonly JxPath[]): JxPath[] {
276
- return topLevelSelection(selection)
277
- .filter((path) => isSpliceablePath(path))
278
- .toSorted((a, b) => comparePaths(b, a));
279
- }
280
-
281
186
  /**
282
187
  * Deduplicate a list of paths, keeping the FIRST occurrence of each.
283
188
  *
package/src/tabs/tab.ts CHANGED
@@ -132,7 +132,7 @@ export interface StoredLivePreview {
132
132
  error: string | null;
133
133
  }
134
134
 
135
- interface HistorySnapshot {
135
+ export interface HistorySnapshot {
136
136
  /** Full document at this state (checkpoint), or null when the ops describe the transition. */
137
137
  document: JxMutableNode | null;
138
138
  /** Selection after this state's transaction — the whole set, so a batch undoes back to it. */
@@ -153,6 +153,13 @@ interface HistorySnapshot {
153
153
  * back through the prose one pause at a time instead of undoing the edit.
154
154
  */
155
155
  coalesceKey?: string | null;
156
+ /**
157
+ * Who made this step, when it is not the person at the keyboard: the id of the actor whose batch
158
+ * lane closed it (specs/ai.md §3.3). Absent on a person's own edits.
159
+ */
160
+ actor?: string;
161
+ /** The turn whose batch this step is, beside {@link HistorySnapshot.actor}. */
162
+ turnId?: string;
156
163
  }
157
164
 
158
165
  /**
@@ -186,6 +193,8 @@ export interface Tab {
186
193
  scope: {
187
194
  stop: () => void;
188
195
  run: <T>(fn: () => T) => T | undefined;
196
+ /** False once {@link disposeTab} stopped it: how a record that outlives the tab can tell. */
197
+ readonly active?: boolean;
189
198
  };
190
199
  doc: {
191
200
  document: JxMutableNode;
@@ -304,12 +313,11 @@ function createDefaultUi(canvasMode: string, preview = false): TabUi {
304
313
  }
305
314
 
306
315
  /*
307
- * `git-diff` is here because a comparison is a MODE of a document, and until now nothing said so.
308
- * The Source Control panel reached it through the injected `setCanvasMode`, which performs no
309
- * capability check — so the mode worked while `editorKindsOf` could never report `diff`, the Editor
310
- * picker could never offer it, and `canvas.setMode { mode: "git-diff" }` threw for every document in
311
- * the project. Declaring it makes the palette, the assistant and the screenshot runner able to open
312
- * a comparison by name, and puts Diff on the Editor axis where §18.4 already says it belongs.
316
+ * `git-diff` is here because a comparison is a MODE of a document: the stage draws a document in
317
+ * it, `editorKindOf` names it, and a tab moved into it by the Source Control panel is a tab in a
318
+ * mode it declares. Declaring it does NOT make it a choice. Diff is implicit (§3): nothing offers it
319
+ * by name, neither the Editor axis (`panels/pane-context.ts` leaves it out) nor `canvas.setMode`
320
+ * (`SELECTABLE_CANVAS_MODES`), because a comparison is entered by choosing what to compare.
313
321
  */
314
322
  const ALL_MODES = ["edit", "design", "preview", "source", "stylebook", "git-diff"];
315
323