@jxsuite/studio 6.1.1 → 6.1.2

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 (637) hide show
  1. package/dist/chunks/{2020-va2wwra4.js → 2020-f2gkpy8d.js} +3 -3
  2. package/dist/chunks/{action-group-2mqby73c.js → action-group-4aan7g6g.js} +3 -3
  3. package/dist/chunks/adapter-4912g339.js +4 -0
  4. package/dist/chunks/cf-account-picker-wccaenh6.js +4 -0
  5. package/dist/chunks/cf-settings-br6105tr.js +4 -0
  6. package/dist/chunks/color-28ksk2qm.js +4 -0
  7. package/dist/chunks/color-area-0fj8a4ga.js +4 -0
  8. package/dist/chunks/color-field-xch8kx2g.js +4 -0
  9. package/dist/chunks/color-slider-jxd8v350.js +4 -0
  10. package/dist/chunks/combobox-p0efwjke.js +4 -0
  11. package/dist/chunks/components-db68vsn7.js +4 -0
  12. package/dist/chunks/content-source-1449qesq.js +4 -0
  13. package/dist/chunks/convert-to-repeater-5h457egj.js +4 -0
  14. package/dist/chunks/dialog-c4x05vyx.js +4 -0
  15. package/dist/chunks/editor-x9jn86a7.js +4 -0
  16. package/dist/chunks/entry-commands-may24cpt.js +4 -0
  17. package/dist/chunks/extension-sections-pvr14vxr.js +4 -0
  18. package/dist/chunks/file-ops-x9v54pcj.js +4 -0
  19. package/dist/chunks/files-j3knqf0s.js +4 -0
  20. package/dist/chunks/format-host-tyre2trb.js +4 -0
  21. package/dist/chunks/fs-events-64ma9htc.js +4 -0
  22. package/dist/chunks/git-panel-84ps5dex.js +4 -0
  23. package/dist/chunks/grid-view-d2wq9ezg.js +51 -0
  24. package/dist/chunks/icons-pnfz478q.js +4 -0
  25. package/dist/chunks/iframe-entry-fvbk89gm.js +5 -0
  26. package/dist/chunks/iframe-entry-jdcktez8.js +5 -0
  27. package/dist/chunks/iframe-entry-x0ygf2yr.js +5 -0
  28. package/dist/chunks/iframe-entry-zap785cw.js +5 -0
  29. package/dist/chunks/iframe-host-ck6vejt5.js +4 -0
  30. package/dist/chunks/index-b8xw3vy9.js +4 -0
  31. package/dist/chunks/{index-2veqmnhr.js → index-zpjmzqfk.js} +3 -3
  32. package/dist/chunks/{javascript-8nbvs12s.js → javascript-m54mnwp6.js} +3 -3
  33. package/dist/chunks/{jsonMode-s8kt9dsj.js → jsonMode-w15cmrcm.js} +8 -8
  34. package/dist/chunks/jx-validate-at3zn8wa.js +4 -0
  35. package/dist/chunks/layers-h4xp1pss.js +4 -0
  36. package/dist/chunks/layers-panel-m5hw1d7g.js +4 -0
  37. package/dist/chunks/listbox-e74qjyq6.js +4 -0
  38. package/dist/chunks/lit-html-8t8t3dnr.js +4 -0
  39. package/dist/chunks/media-picker-2cweexc5.js +4 -0
  40. package/dist/chunks/menu-n6yzswmy.js +4 -0
  41. package/dist/chunks/menu-ynw13y0s.js +4 -0
  42. package/dist/chunks/monaco-binding-7gx83x3r.js +4 -0
  43. package/dist/chunks/monaco-buffer-qzxn567r.js +4 -0
  44. package/dist/chunks/monaco-setup-gxf6656g.js +4 -0
  45. package/dist/chunks/notify-cj5zbrs2.js +4 -0
  46. package/dist/chunks/number-field-y62xq0ty.js +4 -0
  47. package/dist/chunks/parse-b7ddhr8m.js +4 -0
  48. package/dist/chunks/platform-3dfws9js.js +4 -0
  49. package/dist/chunks/popover-jt2gxmzs.js +4 -0
  50. package/dist/chunks/publish-panel-1gvxbj21.js +4 -0
  51. package/dist/chunks/quick-search-0dajrwqg.js +4 -0
  52. package/dist/chunks/references-49qgt404.js +4 -0
  53. package/dist/chunks/right-panel-jm1bwe53.js +4 -0
  54. package/dist/chunks/section-registry-6kwc4fky.js +4 -0
  55. package/dist/chunks/select-rzds841e.js +4 -0
  56. package/dist/chunks/split-n2gfpm5m.js +4 -0
  57. package/dist/chunks/{studio-1q1sh2ax.js → studio-0q988f9w.js} +3 -3
  58. package/dist/chunks/studio-0rt52vpq.js +5 -0
  59. package/dist/chunks/studio-18vgbhs5.js +5 -0
  60. package/dist/chunks/{studio-h46vtzk8.js → studio-1fxkaaea.js} +4 -4
  61. package/dist/chunks/studio-24mccdrj.js +5 -0
  62. package/dist/chunks/studio-2eh507zk.js +9 -0
  63. package/dist/chunks/studio-2hcbccfv.js +5 -0
  64. package/dist/chunks/studio-2j1cb95x.js +5 -0
  65. package/dist/chunks/studio-2jbs3rxv.js +5 -0
  66. package/dist/chunks/{studio-rv11kfwa.js → studio-485046te.js} +7 -7
  67. package/dist/chunks/studio-4h8k4dw9.js +5 -0
  68. package/dist/chunks/studio-5f6n18kx.js +5 -0
  69. package/dist/chunks/studio-5gthpky6.js +5 -0
  70. package/dist/chunks/studio-5ve6bbep.js +5 -0
  71. package/dist/chunks/studio-6ep3js6b.js +9 -0
  72. package/dist/chunks/studio-6wkmf3wz.js +9 -0
  73. package/dist/chunks/studio-841rf3cg.js +5 -0
  74. package/dist/chunks/studio-8gmwgheg.js +5 -0
  75. package/dist/chunks/studio-8qm0ep50.js +5 -0
  76. package/dist/chunks/{studio-8grwxtqk.js → studio-90pq9km1.js} +4 -4
  77. package/dist/chunks/studio-924p1tm1.js +6 -0
  78. package/dist/chunks/{studio-pre0skq6.js → studio-a3g98wjr.js} +4 -4
  79. package/dist/chunks/studio-a3shpz9y.js +5 -0
  80. package/dist/chunks/studio-amsbaaar.js +6 -0
  81. package/dist/chunks/studio-at5spjbc.js +7 -0
  82. package/dist/chunks/studio-b2xv945e.js +5 -0
  83. package/dist/chunks/studio-bn5nkafw.js +5 -0
  84. package/dist/chunks/studio-bw6q5xjf.js +9 -0
  85. package/dist/chunks/studio-c7q0t9x1.js +5 -0
  86. package/dist/chunks/studio-camnhc96.js +6 -0
  87. package/dist/chunks/studio-cffqvnzd.js +5 -0
  88. package/dist/chunks/studio-d81xfh1g.js +5 -0
  89. package/dist/chunks/studio-dgz8d0c1.js +5 -0
  90. package/dist/chunks/studio-efvfrsf8.js +5 -0
  91. package/dist/chunks/studio-er30bpcx.js +5 -0
  92. package/dist/chunks/studio-ezscgr64.js +5 -0
  93. package/dist/chunks/studio-ffrrncvz.js +5 -0
  94. package/dist/chunks/studio-fpphgn8y.js +10 -0
  95. package/dist/chunks/studio-j1kvhdjk.js +4 -0
  96. package/dist/chunks/{studio-vrmcjf9g.js → studio-j430n16g.js} +5 -5
  97. package/dist/chunks/studio-jjkg84nj.js +5 -0
  98. package/dist/chunks/studio-m0q32ars.js +4 -0
  99. package/dist/chunks/studio-m6bdst11.js +5 -0
  100. package/dist/chunks/studio-nv2cptd4.js +64 -0
  101. package/dist/chunks/studio-nwfrc98n.js +5 -0
  102. package/dist/chunks/studio-p1wgvp7r.js +5 -0
  103. package/dist/chunks/studio-pag2wncm.js +5 -0
  104. package/dist/chunks/studio-qvanvzfd.js +5 -0
  105. package/dist/chunks/studio-qwa64kt7.js +5 -0
  106. package/dist/chunks/studio-rk1zc4x3.js +928 -0
  107. package/dist/chunks/studio-se2r3ptc.js +5 -0
  108. package/dist/chunks/studio-sg2a0dh0.js +5 -0
  109. package/dist/chunks/studio-tjzjhe68.js +5 -0
  110. package/dist/chunks/{studio-wszjyh0j.js → studio-tq0rtfwj.js} +4 -4
  111. package/dist/chunks/{studio-kggey1jt.js → studio-v0jzqdjm.js} +4 -4
  112. package/dist/chunks/studio-v2w7q8r1.js +7 -0
  113. package/dist/chunks/studio-v5vjq1h0.js +4 -0
  114. package/dist/chunks/studio-v8aga3vp.js +14 -0
  115. package/dist/chunks/studio-vfcdrfmv.js +5 -0
  116. package/dist/chunks/studio-vmfkgdjf.js +5 -0
  117. package/dist/chunks/studio-wt1816jj.js +5 -0
  118. package/dist/chunks/studio-wz73q5kq.js +4 -0
  119. package/dist/chunks/studio-y04qtxvp.js +7 -0
  120. package/dist/chunks/studio-y21g8zzg.js +5 -0
  121. package/dist/chunks/{studio-zey7zsdw.js → studio-y64hrt8p.js} +7 -7
  122. package/dist/chunks/studio-ynn90f58.js +16 -0
  123. package/dist/chunks/studio-yxz682sx.js +5 -0
  124. package/dist/chunks/studio-zp7snvkq.js +5 -0
  125. package/dist/chunks/studio-zq4z6tm6.js +5 -0
  126. package/dist/chunks/swatch-group-ewh24n1f.js +4 -0
  127. package/dist/chunks/tabs-f5cw3tgp.js +4 -0
  128. package/dist/chunks/textfield-wewc8rq2.js +4 -0
  129. package/dist/chunks/toast-c9fn075p.js +4 -0
  130. package/dist/chunks/toast-host-ke5z4ng7.js +4 -0
  131. package/dist/chunks/{toolbar-2nnzqhrj.js → toolbar-44cm5cta.js} +3 -3
  132. package/dist/chunks/tooltip-5v8ngwj2.js +4 -0
  133. package/dist/chunks/tree-mdq3v5cw.js +4 -0
  134. package/dist/chunks/{tsMode-2frah6h1.js → tsMode-sf49ee9x.js} +7 -7
  135. package/dist/chunks/workspace-jtfahpee.js +4 -0
  136. package/dist/chunks/ws-client-nze0k6mv.js +4 -0
  137. package/dist/iframe-entry.js +16 -16
  138. package/dist/manifest.json +63 -63
  139. package/dist/studio.js +97 -97
  140. package/package.json +6 -6
  141. package/src/about/about-modal.ts +4 -3
  142. package/src/account/action-flow.ts +45 -38
  143. package/src/account-status.ts +7 -2
  144. package/src/browse/library-layouts.ts +8 -5
  145. package/src/browse/library-model.ts +18 -6
  146. package/src/browse/library-pane.ts +37 -21
  147. package/src/browse/library-preview.ts +14 -9
  148. package/src/browse/library-source.ts +1 -1
  149. package/src/canvas/asset-refs.ts +24 -9
  150. package/src/canvas/asset-resolve.ts +19 -23
  151. package/src/canvas/canvas-helpers.ts +7 -6
  152. package/src/canvas/canvas-live-render.ts +44 -53
  153. package/src/canvas/canvas-patcher.ts +30 -30
  154. package/src/canvas/canvas-perf.ts +11 -5
  155. package/src/canvas/canvas-render.ts +62 -41
  156. package/src/canvas/canvas-surface.ts +5 -3
  157. package/src/canvas/canvas-utils.ts +90 -49
  158. package/src/canvas/dialog-path.ts +9 -4
  159. package/src/canvas/dialog-state.ts +1 -2
  160. package/src/canvas/diff-marks.ts +9 -16
  161. package/src/canvas/diff-toolbar.ts +8 -7
  162. package/src/canvas/edit-width-drag.ts +4 -1
  163. package/src/canvas/edit-width.ts +1 -3
  164. package/src/canvas/iframe-channel.ts +27 -13
  165. package/src/canvas/iframe-drop.ts +13 -12
  166. package/src/canvas/iframe-editable-root.ts +29 -16
  167. package/src/canvas/iframe-entry.ts +80 -63
  168. package/src/canvas/iframe-eval.ts +73 -49
  169. package/src/canvas/iframe-host.ts +135 -96
  170. package/src/canvas/iframe-inline-edit.ts +49 -30
  171. package/src/canvas/iframe-insert.ts +5 -4
  172. package/src/canvas/iframe-interaction.ts +30 -25
  173. package/src/canvas/iframe-overlay.ts +1 -1
  174. package/src/canvas/iframe-patch.ts +18 -15
  175. package/src/canvas/iframe-position.ts +12 -6
  176. package/src/canvas/iframe-protocol.ts +12 -16
  177. package/src/canvas/iframe-render.ts +36 -34
  178. package/src/canvas/iframe-slash.ts +24 -11
  179. package/src/canvas/iframe-subtree.ts +6 -2
  180. package/src/canvas/path-mapping.ts +19 -12
  181. package/src/canvas/popover-path.ts +7 -3
  182. package/src/canvas/popover-state.ts +1 -2
  183. package/src/canvas/serialize-scope.ts +13 -5
  184. package/src/canvas/stage-scrollbar.ts +2 -1
  185. package/src/canvas/surface-registry.ts +21 -3
  186. package/src/collab/collab-commands.ts +7 -2
  187. package/src/collab/collab-session.ts +84 -45
  188. package/src/collab/collab-state.ts +4 -3
  189. package/src/collab/monaco-binding.ts +16 -13
  190. package/src/collab/monaco-cursors.ts +5 -2
  191. package/src/commands/budget.ts +3 -3
  192. package/src/commands/command-args.ts +103 -71
  193. package/src/commands/context.ts +22 -20
  194. package/src/commands/keymap.ts +47 -43
  195. package/src/commands/levels.ts +3 -3
  196. package/src/commands/live-context.ts +7 -7
  197. package/src/commands/reference.ts +2 -1
  198. package/src/commands/registry.ts +12 -10
  199. package/src/commands/run-reported.ts +15 -10
  200. package/src/component-props.ts +46 -30
  201. package/src/content/collection-match.ts +5 -4
  202. package/src/content/draft-state.ts +4 -3
  203. package/src/content/entry-commands.ts +3 -2
  204. package/src/content/entry-editor.ts +29 -17
  205. package/src/content/entry-fields.ts +12 -7
  206. package/src/content/entry-model.ts +21 -12
  207. package/src/editor/canvas-context-menu.ts +1 -2
  208. package/src/editor/canvas-slash-bridge.ts +3 -6
  209. package/src/editor/content-slice.ts +16 -14
  210. package/src/editor/context-menu.ts +35 -22
  211. package/src/editor/convert-targets.ts +30 -35
  212. package/src/editor/convert-to-component.ts +11 -5
  213. package/src/editor/convert-to-repeater.ts +34 -22
  214. package/src/editor/editable-tags.ts +17 -2
  215. package/src/editor/file-drop-action.ts +21 -22
  216. package/src/editor/inline-edit-apply.ts +35 -17
  217. package/src/editor/inline-edit.ts +66 -50
  218. package/src/editor/inline-format.ts +59 -56
  219. package/src/editor/inline-link.ts +40 -15
  220. package/src/editor/insert-zone-action.ts +1 -1
  221. package/src/editor/merge-tags.ts +58 -19
  222. package/src/editor/repeater-scope.ts +39 -28
  223. package/src/editor/shortcuts.ts +32 -20
  224. package/src/editor/slash-menu.ts +1 -6
  225. package/src/files/asset-versions.ts +4 -4
  226. package/src/files/components.ts +15 -10
  227. package/src/files/elements.ts +5 -6
  228. package/src/files/file-ops.ts +77 -36
  229. package/src/files/files.ts +90 -95
  230. package/src/files/media-meta.ts +2 -1
  231. package/src/files/media-paths.ts +3 -0
  232. package/src/files/serialize-document.ts +2 -2
  233. package/src/format/constraints.ts +1 -1
  234. package/src/format/convert-file.ts +27 -13
  235. package/src/format/format-choices.ts +2 -1
  236. package/src/format/format-host.ts +76 -50
  237. package/src/github/github-auth-status.ts +27 -3
  238. package/src/github/github-auth.ts +19 -9
  239. package/src/github/github-publish.ts +24 -20
  240. package/src/grid/cell-editors.ts +46 -31
  241. package/src/grid/cell-popovers.ts +5 -3
  242. package/src/grid/edit-buffer.ts +10 -9
  243. package/src/grid/grid-controller.ts +20 -22
  244. package/src/grid/grid-layout.ts +21 -5
  245. package/src/grid/grid-open.ts +3 -6
  246. package/src/grid/grid-panel.ts +11 -4
  247. package/src/grid/grid-source.ts +8 -8
  248. package/src/grid/grid-view.ts +14 -17
  249. package/src/grid/redirects-grid.ts +14 -5
  250. package/src/grid/redirects.ts +16 -14
  251. package/src/grid/schema-columns.ts +25 -19
  252. package/src/grid/sources/connector-source.ts +47 -20
  253. package/src/grid/sources/content-source.ts +25 -24
  254. package/src/grid/sources/csv-file-source.ts +2 -2
  255. package/src/grid/tabulator-tables.d.ts +55 -34
  256. package/src/hosting/stage.ts +7 -7
  257. package/src/i18n/i18n-commands.ts +1 -2
  258. package/src/media/media-pane.ts +4 -1
  259. package/src/new-project/add-repo-modal.ts +20 -19
  260. package/src/new-project/import-tab.ts +10 -14
  261. package/src/new-project/location-fields.ts +2 -1
  262. package/src/new-project/new-project-modal.ts +12 -9
  263. package/src/packages/jxsuite-update.ts +4 -3
  264. package/src/packages/pull-package-sync.ts +26 -25
  265. package/src/page-params.ts +97 -68
  266. package/src/panels/activity-panel.ts +17 -9
  267. package/src/panels/ai-chat/attached-context.ts +13 -7
  268. package/src/panels/ai-chat/chat-view.ts +80 -73
  269. package/src/panels/ai-chat/composer.ts +30 -33
  270. package/src/panels/ai-chat/sessions-view.ts +1 -2
  271. package/src/panels/ai-panel.ts +23 -20
  272. package/src/panels/block-action-bar.ts +46 -35
  273. package/src/panels/bottom-dock.ts +5 -3
  274. package/src/panels/canvas-dnd-bridge.ts +31 -24
  275. package/src/panels/data-explorer.ts +62 -25
  276. package/src/panels/data-grid.ts +14 -11
  277. package/src/panels/dnd.ts +108 -118
  278. package/src/panels/editors.ts +52 -21
  279. package/src/panels/elements-panel.ts +10 -3
  280. package/src/panels/events-panel.ts +84 -69
  281. package/src/panels/formula-workspace.ts +76 -51
  282. package/src/panels/frontmatter-fields.ts +24 -19
  283. package/src/panels/frontmatter-panel.ts +44 -34
  284. package/src/panels/git-diff-open.ts +4 -4
  285. package/src/panels/git-panel.ts +49 -61
  286. package/src/panels/head-panel.ts +131 -111
  287. package/src/panels/i18n-panel.ts +10 -3
  288. package/src/panels/imports-panel.ts +23 -47
  289. package/src/panels/jump-bar.ts +48 -29
  290. package/src/panels/layers-panel.ts +97 -74
  291. package/src/panels/left-panel.ts +3 -3
  292. package/src/panels/pane-context.ts +31 -22
  293. package/src/panels/pane-grid.ts +49 -20
  294. package/src/panels/panel-registry.ts +22 -37
  295. package/src/panels/properties-panel.ts +175 -121
  296. package/src/panels/quick-search.ts +53 -31
  297. package/src/panels/right-panel.ts +3 -3
  298. package/src/panels/seo-modal.ts +13 -17
  299. package/src/panels/settings-menu.ts +15 -15
  300. package/src/panels/signals-panel.ts +153 -131
  301. package/src/panels/statement-editor.ts +230 -140
  302. package/src/panels/style-panel.ts +218 -205
  303. package/src/panels/style-utils.ts +114 -51
  304. package/src/panels/stylebook-doc.ts +57 -54
  305. package/src/panels/stylebook-layers-panel.ts +9 -9
  306. package/src/panels/stylebook-panel.ts +13 -17
  307. package/src/panels/tab-drop.ts +27 -11
  308. package/src/panels/tab-strip.ts +36 -26
  309. package/src/platform-errors.ts +57 -43
  310. package/src/platform.ts +58 -30
  311. package/src/platforms/cloud.ts +345 -175
  312. package/src/platforms/default-platform.ts +10 -4
  313. package/src/platforms/devserver.ts +129 -117
  314. package/src/platforms/read-batcher.ts +16 -8
  315. package/src/project-list.ts +2 -1
  316. package/src/publish/deploy-checklist.ts +8 -2
  317. package/src/publish/pages-service.ts +28 -13
  318. package/src/publish/publish-commands.ts +5 -4
  319. package/src/publish/publish-panel.ts +10 -6
  320. package/src/recent-projects.ts +15 -8
  321. package/src/resize-edges.ts +26 -36
  322. package/src/services/a11y-report.ts +26 -19
  323. package/src/services/agent-seed.ts +23 -11
  324. package/src/services/ai-ask.ts +9 -12
  325. package/src/services/ai-command-tools.ts +68 -62
  326. package/src/services/ai-import-tools.ts +80 -67
  327. package/src/services/ai-models.ts +17 -13
  328. package/src/services/ai-project-tools.ts +68 -32
  329. package/src/services/ai-session-store.ts +19 -10
  330. package/src/services/ai-system-prompt.ts +46 -20
  331. package/src/services/ai-tools.ts +71 -27
  332. package/src/services/ai-write-report.ts +20 -12
  333. package/src/services/ai-writes.ts +4 -4
  334. package/src/services/automation.ts +58 -31
  335. package/src/services/cem-export.ts +149 -58
  336. package/src/services/clock.ts +6 -1
  337. package/src/services/code-services.ts +37 -31
  338. package/src/services/context-manager.ts +14 -10
  339. package/src/services/context-resolver.ts +20 -8
  340. package/src/services/data-service.ts +19 -15
  341. package/src/services/directory-picker.ts +18 -12
  342. package/src/services/document-assistant.ts +39 -19
  343. package/src/services/gated-registry.ts +10 -6
  344. package/src/services/harness/chat-reducer.ts +23 -1
  345. package/src/services/import-client.ts +91 -38
  346. package/src/services/import-seed.ts +8 -2
  347. package/src/services/jx-validate.ts +28 -31
  348. package/src/services/live-preview.ts +0 -0
  349. package/src/services/live-surfaces.ts +6 -3
  350. package/src/services/model-uri.ts +10 -2
  351. package/src/services/module-preloads.ts +12 -8
  352. package/src/services/monaco-buffer.ts +43 -24
  353. package/src/services/monaco-lazy.ts +7 -8
  354. package/src/services/monaco-setup.ts +23 -16
  355. package/src/services/notify.ts +44 -17
  356. package/src/services/popover-report.ts +25 -10
  357. package/src/services/preview-eval.ts +20 -8
  358. package/src/services/profile.ts +13 -6
  359. package/src/services/project-path.ts +13 -10
  360. package/src/services/references.ts +0 -0
  361. package/src/services/render-critic.ts +8 -7
  362. package/src/services/settings/kernel.ts +13 -4
  363. package/src/services/settings/write-queue.ts +9 -9
  364. package/src/services/token-lint.ts +12 -10
  365. package/src/services/tool-executor.ts +17 -5
  366. package/src/services/tool-outcomes.ts +44 -24
  367. package/src/services/trusted-types.ts +24 -7
  368. package/src/settings/contexts-section.ts +11 -8
  369. package/src/settings/contributed-section.ts +79 -60
  370. package/src/settings/css-vars-editor.ts +37 -16
  371. package/src/settings/defs-editor.ts +38 -35
  372. package/src/settings/extension-rows.ts +16 -8
  373. package/src/settings/extension-sections.ts +23 -13
  374. package/src/settings/extensions-section.ts +4 -1
  375. package/src/settings/general-settings.ts +11 -8
  376. package/src/settings/locales-section.ts +20 -12
  377. package/src/settings/preferences-dialog.ts +9 -6
  378. package/src/settings/preferences-keymap.ts +7 -5
  379. package/src/settings/preferences-sections.ts +11 -5
  380. package/src/settings/project-sections.ts +1 -1
  381. package/src/settings/schema-field-ui.ts +9 -0
  382. package/src/settings/settings-document.ts +5 -5
  383. package/src/shell/tree.ts +6 -5
  384. package/src/shell.ts +104 -81
  385. package/src/site-context.ts +37 -22
  386. package/src/state.ts +41 -49
  387. package/src/store.ts +54 -34
  388. package/src/studio.ts +25 -75
  389. package/src/style/live-preview.ts +1 -1
  390. package/src/style/project-styles.ts +6 -7
  391. package/src/style/token-ref.ts +5 -4
  392. package/src/surfaces/about.ts +18 -19
  393. package/src/surfaces/add-repo.ts +17 -19
  394. package/src/surfaces/ai-chat.ts +31 -36
  395. package/src/surfaces/ai-credentials-form.ts +6 -16
  396. package/src/surfaces/ai-managed-connect.ts +3 -4
  397. package/src/surfaces/ai-model-picker.ts +3 -5
  398. package/src/surfaces/block-action-bar.ts +22 -11
  399. package/src/surfaces/boot-failure.ts +4 -5
  400. package/src/surfaces/bottom-dock.ts +9 -18
  401. package/src/surfaces/canvas-stage.ts +12 -11
  402. package/src/surfaces/cf-account-picker.ts +17 -18
  403. package/src/surfaces/commandbar.ts +14 -9
  404. package/src/surfaces/convert-repeater.ts +17 -19
  405. package/src/surfaces/data-actions.ts +9 -7
  406. package/src/surfaces/dialog.ts +26 -28
  407. package/src/surfaces/diff-toolbar.ts +9 -7
  408. package/src/surfaces/doc-header.ts +10 -19
  409. package/src/surfaces/empty-state.ts +7 -10
  410. package/src/surfaces/entry-editor.ts +14 -11
  411. package/src/surfaces/expression-editor.ts +11 -25
  412. package/src/surfaces/files-panel.ts +27 -14
  413. package/src/surfaces/formula-palette.ts +4 -5
  414. package/src/surfaces/git-panel.ts +7 -15
  415. package/src/surfaces/github-auth.ts +16 -20
  416. package/src/surfaces/github-publish.ts +17 -22
  417. package/src/surfaces/grid-cell.ts +30 -31
  418. package/src/surfaces/grid-open.ts +10 -14
  419. package/src/surfaces/grid-panel.ts +13 -9
  420. package/src/surfaces/grid-replace.ts +13 -13
  421. package/src/surfaces/grid-views.ts +15 -18
  422. package/src/surfaces/inspector-dock.ts +13 -12
  423. package/src/surfaces/jump-bar.ts +5 -6
  424. package/src/surfaces/jxsuite-update.ts +16 -22
  425. package/src/surfaces/library-pane.ts +19 -20
  426. package/src/surfaces/logic-panel.ts +17 -30
  427. package/src/surfaces/logic-workspace.ts +13 -15
  428. package/src/surfaces/media-browser.ts +11 -10
  429. package/src/surfaces/media-field.ts +4 -5
  430. package/src/surfaces/media-pane.ts +8 -7
  431. package/src/surfaces/menu.ts +29 -23
  432. package/src/surfaces/navigator-dock.ts +11 -12
  433. package/src/surfaces/new-project.ts +27 -26
  434. package/src/surfaces/pane-context.ts +20 -25
  435. package/src/surfaces/pane-grid.ts +15 -10
  436. package/src/surfaces/panel-activity.ts +5 -6
  437. package/src/surfaces/panel-data.ts +3 -4
  438. package/src/surfaces/panel-deploy-checklist.ts +5 -6
  439. package/src/surfaces/panel-elements.ts +5 -7
  440. package/src/surfaces/panel-i18n.ts +5 -7
  441. package/src/surfaces/panel-imports.ts +6 -13
  442. package/src/surfaces/panel-outline.ts +25 -19
  443. package/src/surfaces/panel-page.ts +11 -18
  444. package/src/surfaces/panel-problems.ts +5 -7
  445. package/src/surfaces/panel-signals.ts +20 -34
  446. package/src/surfaces/panel-stylebook-layers.ts +5 -8
  447. package/src/surfaces/preferences.ts +21 -11
  448. package/src/surfaces/progress-modal.ts +15 -9
  449. package/src/surfaces/properties-panel.json +1 -1
  450. package/src/surfaces/properties-panel.ts +20 -42
  451. package/src/surfaces/publish.ts +18 -18
  452. package/src/surfaces/push-plan.ts +7 -8
  453. package/src/surfaces/rail.ts +13 -13
  454. package/src/surfaces/reference-field.ts +11 -15
  455. package/src/surfaces/schema-builder.ts +16 -22
  456. package/src/surfaces/schema-form.ts +15 -25
  457. package/src/surfaces/secret-field.ts +9 -6
  458. package/src/surfaces/seo.ts +21 -15
  459. package/src/surfaces/settings-contexts.ts +9 -7
  460. package/src/surfaces/settings-contributed.ts +14 -10
  461. package/src/surfaces/settings-css-vars.ts +5 -12
  462. package/src/surfaces/settings-defs.json +2 -2
  463. package/src/surfaces/settings-defs.ts +17 -21
  464. package/src/surfaces/settings-deploy.ts +8 -15
  465. package/src/surfaces/settings-extensions.ts +5 -6
  466. package/src/surfaces/settings-head.ts +33 -39
  467. package/src/surfaces/settings-locales.ts +8 -20
  468. package/src/surfaces/settings-overview.ts +5 -6
  469. package/src/surfaces/settings-packages.ts +8 -7
  470. package/src/surfaces/settings-pane.ts +9 -18
  471. package/src/surfaces/settings-rawjson.ts +5 -6
  472. package/src/surfaces/shell.ts +1 -2
  473. package/src/surfaces/slash-menu.ts +19 -9
  474. package/src/surfaces/statements.ts +13 -18
  475. package/src/surfaces/statusbar.ts +17 -14
  476. package/src/surfaces/style-panel.ts +18 -31
  477. package/src/surfaces/stylebook-chrome.ts +3 -5
  478. package/src/surfaces/tab-strip.ts +14 -13
  479. package/src/surfaces/target-line.ts +6 -7
  480. package/src/surfaces/welcome.ts +5 -7
  481. package/src/tabs/patch-ops.ts +4 -3
  482. package/src/tabs/project-config.ts +32 -21
  483. package/src/tabs/selection.ts +36 -8
  484. package/src/tabs/tab.ts +52 -41
  485. package/src/tabs/transact.ts +98 -53
  486. package/src/types.ts +32 -17
  487. package/src/ui/ai-credentials-form.ts +10 -13
  488. package/src/ui/ai-model-picker.ts +3 -3
  489. package/src/ui/cf-account-picker.ts +7 -9
  490. package/src/ui/color-selector.ts +9 -5
  491. package/src/ui/dynamic-slot.ts +7 -8
  492. package/src/ui/expression-editor.ts +112 -105
  493. package/src/ui/form-controls.ts +57 -48
  494. package/src/ui/formula-catalog.ts +239 -230
  495. package/src/ui/formula-chips.ts +33 -18
  496. package/src/ui/layers.ts +44 -31
  497. package/src/ui/media-picker.ts +18 -9
  498. package/src/ui/popover-surface.ts +20 -12
  499. package/src/ui/progress-modal.ts +13 -8
  500. package/src/ui/regions.ts +7 -6
  501. package/src/ui/schema-form.ts +113 -70
  502. package/src/ui/surface.ts +71 -8
  503. package/src/ui/timing.ts +9 -0
  504. package/src/ui/value-source.ts +44 -31
  505. package/src/ui/virtual-window.ts +3 -2
  506. package/src/utils/base64.ts +3 -1
  507. package/src/utils/edit-display.ts +73 -73
  508. package/src/utils/element-selectors.ts +3 -2
  509. package/src/utils/google-fonts.ts +15 -14
  510. package/src/utils/inherited-style.ts +18 -20
  511. package/src/utils/link-target.ts +1 -1
  512. package/src/utils/preview-format.ts +25 -3
  513. package/src/utils/strip-events.ts +49 -22
  514. package/src/utils/studio-utils.ts +29 -14
  515. package/src/view.ts +2 -3
  516. package/src/workspace/pane-derive.ts +10 -12
  517. package/src/workspace/session.ts +53 -43
  518. package/src/workspace/workspace.ts +40 -36
  519. package/dist/chunks/adapter-f93pafd7.js +0 -4
  520. package/dist/chunks/cf-account-picker-af1h381v.js +0 -4
  521. package/dist/chunks/cf-settings-125tdm0w.js +0 -4
  522. package/dist/chunks/color-area-jqhna8zy.js +0 -4
  523. package/dist/chunks/color-field-embq5ctg.js +0 -4
  524. package/dist/chunks/color-fpezvnkt.js +0 -4
  525. package/dist/chunks/color-slider-1qmw7wqy.js +0 -4
  526. package/dist/chunks/combobox-773hdzyj.js +0 -4
  527. package/dist/chunks/components-ax2f1fnn.js +0 -4
  528. package/dist/chunks/content-source-108aqtk1.js +0 -4
  529. package/dist/chunks/convert-to-repeater-ry5rmppr.js +0 -4
  530. package/dist/chunks/dialog-mtm9fq5t.js +0 -4
  531. package/dist/chunks/editor-pfgdmkb0.js +0 -4
  532. package/dist/chunks/entry-commands-t0k1q0kx.js +0 -4
  533. package/dist/chunks/extension-sections-6mwh2hf8.js +0 -4
  534. package/dist/chunks/file-ops-meej5mqf.js +0 -4
  535. package/dist/chunks/files-44vp8a2s.js +0 -4
  536. package/dist/chunks/format-host-7q1petb9.js +0 -4
  537. package/dist/chunks/fs-events-h2mwnxaz.js +0 -4
  538. package/dist/chunks/git-panel-zngbymvd.js +0 -4
  539. package/dist/chunks/grid-view-sx9vynsp.js +0 -51
  540. package/dist/chunks/icons-p44xhjf0.js +0 -4
  541. package/dist/chunks/iframe-entry-f7mqjwpm.js +0 -5
  542. package/dist/chunks/iframe-entry-haw7jkvz.js +0 -5
  543. package/dist/chunks/iframe-entry-z6qrytv3.js +0 -5
  544. package/dist/chunks/iframe-host-qk3ycq87.js +0 -4
  545. package/dist/chunks/index-wkyfjeqz.js +0 -4
  546. package/dist/chunks/jx-validate-psgd7vsx.js +0 -4
  547. package/dist/chunks/layers-panel-1kq2jyfk.js +0 -4
  548. package/dist/chunks/layers-xd92fg8d.js +0 -4
  549. package/dist/chunks/listbox-s8fkmnq8.js +0 -4
  550. package/dist/chunks/lit-html-ac4cwwr4.js +0 -4
  551. package/dist/chunks/media-picker-0svzkdyb.js +0 -4
  552. package/dist/chunks/menu-37d07z9m.js +0 -4
  553. package/dist/chunks/menu-5c55ea3d.js +0 -4
  554. package/dist/chunks/monaco-binding-z6r70pdt.js +0 -4
  555. package/dist/chunks/monaco-buffer-fz6gq5y7.js +0 -4
  556. package/dist/chunks/monaco-setup-q4axkgj7.js +0 -4
  557. package/dist/chunks/notify-0xgtn8q1.js +0 -4
  558. package/dist/chunks/number-field-gw7sq8rn.js +0 -4
  559. package/dist/chunks/parse-897fvqah.js +0 -4
  560. package/dist/chunks/platform-v1qctbe6.js +0 -4
  561. package/dist/chunks/popover-8htra4er.js +0 -4
  562. package/dist/chunks/publish-panel-ym1fmgq5.js +0 -4
  563. package/dist/chunks/quick-search-a54e6t5n.js +0 -4
  564. package/dist/chunks/references-gmqp82fs.js +0 -4
  565. package/dist/chunks/right-panel-v7t9awbk.js +0 -4
  566. package/dist/chunks/section-registry-vhyf3zsr.js +0 -4
  567. package/dist/chunks/select-n3v7gwas.js +0 -4
  568. package/dist/chunks/split-pff8f3ze.js +0 -4
  569. package/dist/chunks/studio-0bhx5hz6.js +0 -5
  570. package/dist/chunks/studio-0k1ddnyy.js +0 -6
  571. package/dist/chunks/studio-1b04pd0j.js +0 -64
  572. package/dist/chunks/studio-4dwbj6gb.js +0 -5
  573. package/dist/chunks/studio-4tanh828.js +0 -5
  574. package/dist/chunks/studio-55h4mstj.js +0 -4
  575. package/dist/chunks/studio-5tnvjkz4.js +0 -5
  576. package/dist/chunks/studio-60dqgb0c.js +0 -5
  577. package/dist/chunks/studio-61dp09qg.js +0 -9
  578. package/dist/chunks/studio-63epcrj2.js +0 -5
  579. package/dist/chunks/studio-74k29dy9.js +0 -5
  580. package/dist/chunks/studio-7vg6jcd3.js +0 -5
  581. package/dist/chunks/studio-7zx31knw.js +0 -9
  582. package/dist/chunks/studio-8bxk97km.js +0 -5
  583. package/dist/chunks/studio-933e30n4.js +0 -5
  584. package/dist/chunks/studio-98wnwhbg.js +0 -5
  585. package/dist/chunks/studio-9mccjwjh.js +0 -14
  586. package/dist/chunks/studio-a2ke1e4t.js +0 -5
  587. package/dist/chunks/studio-e3a2a6v3.js +0 -4
  588. package/dist/chunks/studio-e81q1vb9.js +0 -5
  589. package/dist/chunks/studio-epgrmqqm.js +0 -5
  590. package/dist/chunks/studio-ery42sqr.js +0 -4
  591. package/dist/chunks/studio-g1shz58g.js +0 -5
  592. package/dist/chunks/studio-gf0fz03c.js +0 -5
  593. package/dist/chunks/studio-gjtpe62q.js +0 -6
  594. package/dist/chunks/studio-gkskhg7m.js +0 -5
  595. package/dist/chunks/studio-gx4dnjzd.js +0 -5
  596. package/dist/chunks/studio-j03zga3y.js +0 -9
  597. package/dist/chunks/studio-jhpxeckz.js +0 -5
  598. package/dist/chunks/studio-k01r7ykp.js +0 -5
  599. package/dist/chunks/studio-kk7h30ne.js +0 -7
  600. package/dist/chunks/studio-kt1zqney.js +0 -5
  601. package/dist/chunks/studio-m3cwhvye.js +0 -5
  602. package/dist/chunks/studio-mcayt6hz.js +0 -5
  603. package/dist/chunks/studio-myjcghv3.js +0 -5
  604. package/dist/chunks/studio-n8bxwc3y.js +0 -4
  605. package/dist/chunks/studio-ngm8gvpb.js +0 -5
  606. package/dist/chunks/studio-nj5a01jy.js +0 -928
  607. package/dist/chunks/studio-pcgz8heb.js +0 -5
  608. package/dist/chunks/studio-qcsq0t15.js +0 -5
  609. package/dist/chunks/studio-qkstvve9.js +0 -5
  610. package/dist/chunks/studio-qv1pwd3c.js +0 -5
  611. package/dist/chunks/studio-rc6dvxjb.js +0 -7
  612. package/dist/chunks/studio-s8dmmz66.js +0 -5
  613. package/dist/chunks/studio-sp5xzbj4.js +0 -6
  614. package/dist/chunks/studio-szsjbj0g.js +0 -5
  615. package/dist/chunks/studio-t1xzawhr.js +0 -16
  616. package/dist/chunks/studio-t6b6qe31.js +0 -5
  617. package/dist/chunks/studio-tdcprbqb.js +0 -5
  618. package/dist/chunks/studio-vyc0b4he.js +0 -10
  619. package/dist/chunks/studio-w0cgf6jg.js +0 -5
  620. package/dist/chunks/studio-w3hskzqk.js +0 -5
  621. package/dist/chunks/studio-xgrgcdyh.js +0 -9
  622. package/dist/chunks/studio-xz2yxfcb.js +0 -5
  623. package/dist/chunks/studio-y6n42tgs.js +0 -5
  624. package/dist/chunks/studio-yb560vxr.js +0 -5
  625. package/dist/chunks/studio-yn9f8vtx.js +0 -5
  626. package/dist/chunks/studio-yw05w8f0.js +0 -7
  627. package/dist/chunks/studio-z16sgavc.js +0 -5
  628. package/dist/chunks/studio-zyqn40w4.js +0 -5
  629. package/dist/chunks/swatch-group-8qh9a3bm.js +0 -4
  630. package/dist/chunks/tabs-jwthg40w.js +0 -4
  631. package/dist/chunks/textfield-spy3hc77.js +0 -4
  632. package/dist/chunks/toast-4d35zd64.js +0 -4
  633. package/dist/chunks/toast-host-8sjmfed3.js +0 -4
  634. package/dist/chunks/tooltip-fd6g9xy3.js +0 -4
  635. package/dist/chunks/tree-h19v1jfz.js +0 -4
  636. package/dist/chunks/workspace-zt81g1ms.js +0 -4
  637. package/dist/chunks/ws-client-n2bh4hkf.js +0 -4
@@ -17,6 +17,7 @@
17
17
  * (happy-dom's `elementFromPoint` returns null) and lives in iframe-interaction.
18
18
  */
19
19
 
20
+ import { isNumber } from "@jxsuite/schema/guards";
20
21
  import { parseJxPath } from "./path-mapping";
21
22
  import { rectOf } from "../utils/geometry";
22
23
  import { childIndex, parentElementPath } from "../state";
@@ -48,7 +49,7 @@ function isRowLayout(parent: HTMLElement): boolean {
48
49
  const isGrid = display === "grid" || display === "inline-grid";
49
50
  return (
50
51
  (isFlex && style.flexDirection.startsWith("row")) ||
51
- (isGrid && (style.gridAutoFlow ?? "").startsWith("column"))
52
+ (isGrid && style.gridAutoFlow.startsWith("column"))
52
53
  );
53
54
  }
54
55
 
@@ -78,11 +79,11 @@ export function computeInsertZones(
78
79
  shadowDoc: JxMutableNode,
79
80
  ): InsertZone[] | null {
80
81
  void shadowDoc;
81
- const serialized = targetEl.dataset?.jxPath;
82
+ const serialized = targetEl.dataset.jxPath;
82
83
  if (serialized == null) {
83
84
  return null;
84
85
  }
85
- const targetPath = parseJxPath(serialized) as JxPath;
86
+ const targetPath = parseJxPath(serialized);
86
87
 
87
88
  // Empty container: one centered "+" that inserts as the container's first child.
88
89
  if (targetEl.classList.contains(EMPTY_CONTAINER_CLASS)) {
@@ -99,7 +100,7 @@ export function computeInsertZones(
99
100
  return null;
100
101
  }
101
102
  const childIdx = childIndex(targetPath);
102
- if (typeof childIdx !== "number") {
103
+ if (!isNumber(childIdx)) {
103
104
  return null;
104
105
  }
105
106
 
@@ -7,6 +7,7 @@
7
7
  */
8
8
 
9
9
  import { jxPathSelector, parseJxPath, serializeJxPath } from "./path-mapping";
10
+ import { isFunction } from "@jxsuite/schema/guards";
10
11
  import { rectOf } from "../utils/geometry";
11
12
  import { computeInsertZones, insertZonesKey } from "./iframe-insert";
12
13
  import { getActiveElement, isEditing } from "../editor/inline-edit";
@@ -32,9 +33,10 @@ function isCanvasLeave(e: Event, doc: Document): boolean {
32
33
 
33
34
  /** Walk up from an element to the nearest ancestor carrying a `data-jx-path`; null if none. */
34
35
  function nearestPathEl(start: Element | null): HTMLElement | null {
35
- let el = start instanceof Element ? (start as HTMLElement) : null;
36
+ let el = start instanceof Element ? start : null;
36
37
  while (el) {
37
- if (el.dataset?.jxPath) {
38
+ // Only HTML elements are stamped (`makeStamper` skips everything else), so only they can match.
39
+ if (el instanceof HTMLElement && el.dataset.jxPath) {
38
40
  return el;
39
41
  }
40
42
  el = el.parentElement;
@@ -57,6 +59,7 @@ export function nearestHit(target: EventTarget | null): NodeHit | null {
57
59
  if (!el) {
58
60
  return null;
59
61
  }
62
+ // SAFETY: nearestPathEl returns only an element whose `data-jx-path` is a non-empty string.
60
63
  return measureHit(el, el.dataset.jxPath as string);
61
64
  }
62
65
 
@@ -75,8 +78,9 @@ export function nearestHit(target: EventTarget | null): NodeHit | null {
75
78
  * from a node that is on screen is a worse failure than drawing one for a node that is not.
76
79
  */
77
80
  function isRendered(el: Element): boolean {
78
- const check = (el as { checkVisibility?: (o?: object) => boolean }).checkVisibility;
79
- return typeof check === "function" ? check.call(el, { checkVisibilityCSS: true }) : true;
81
+ // Absent on engines that predate it, whatever lib.dom says.
82
+ const check: Element["checkVisibility"] | undefined = el.checkVisibility;
83
+ return isFunction(check) ? check.call(el, { checkVisibilityCSS: true }) : true;
80
84
  }
81
85
 
82
86
  /**
@@ -92,10 +96,7 @@ function isRendered(el: Element): boolean {
92
96
  * The serialized path is the same string the renderer stamps, so a stored selection path
93
97
  * round-trips back to its element.
94
98
  */
95
- export function measureHits(
96
- paths: (string | number)[][],
97
- doc: Document = document,
98
- ): { hits: NodeHit[]; hidden: (string | number)[][] } {
99
+ export function measureHits(paths: (string | number)[][], doc: Document = document) {
99
100
  const hits: NodeHit[] = [];
100
101
  const hidden: (string | number)[][] = [];
101
102
  for (const path of paths) {
@@ -119,8 +120,15 @@ export function measureHits(
119
120
  * {@link file://./iframe-drop.ts}'s `startGrabDetector` receives its deps rather than reaching for
120
121
  * module state.
121
122
  */
123
+ type InvokerAction = Extract<IframeToParent, { kind: "popoverTargetClick" }>["action"];
124
+
122
125
  /** The three `popovertargetaction` keywords. Anything else falls back to the HTML default. */
123
- const INVOKER_ACTIONS = new Set(["toggle", "show", "hide"]);
126
+ const INVOKER_ACTIONS = new Set<string>(["toggle", "show", "hide"] satisfies InvokerAction[]);
127
+
128
+ /** Whether an attribute value is one of the {@link INVOKER_ACTIONS} keywords. */
129
+ function isInvokerAction(value: string): value is InvokerAction {
130
+ return INVOKER_ACTIONS.has(value);
131
+ }
124
132
 
125
133
  /**
126
134
  * Report an invoker click, when the click landed on one and it names an addressable popover.
@@ -152,14 +160,14 @@ function postPopoverInvoke(
152
160
  need escaping — a rule this file already keeps in exactly one place (`jxPathSelector`) and
153
161
  should not gain a second spelling of. The set scanned is the addressable POPOVERS, which is
154
162
  also the set the answer has to come from, so the scan is the test. */
155
- const panels = invoker.ownerDocument.querySelectorAll("[data-jx-popover]");
156
- const panel = [...panels].find((el) => el.id === id) as HTMLElement | undefined;
163
+ const panels = invoker.ownerDocument.querySelectorAll<HTMLElement>("[data-jx-popover]");
164
+ const panel = [...panels].find((el) => el.id === id);
157
165
  const serialized = panel?.dataset.jxPath;
158
166
  if (!serialized) {
159
167
  return;
160
168
  }
161
169
  const raw = invoker.getAttribute("popovertargetaction") ?? "toggle";
162
- const action = INVOKER_ACTIONS.has(raw) ? (raw as "toggle" | "show" | "hide") : "toggle";
170
+ const action = isInvokerAction(raw) ? raw : "toggle";
163
171
  channel.post({ action, kind: "popoverTargetClick", targetPath: parseJxPath(serialized) });
164
172
  }
165
173
 
@@ -190,10 +198,10 @@ function postCommandInvoke(
190
198
  }
191
199
  // Scanned, not selected, for the reason `postPopoverInvoke` gives; the addressable overlays are
192
200
  // The de-popovered panels and the stamped dialogs.
193
- const overlays = invoker.ownerDocument.querySelectorAll(
201
+ const overlays = invoker.ownerDocument.querySelectorAll<HTMLElement>(
194
202
  "[data-jx-popover], dialog[data-jx-path]",
195
203
  );
196
- const overlay = [...overlays].find((el) => el.id === id) as HTMLElement | undefined;
204
+ const overlay = [...overlays].find((el) => el.id === id);
197
205
  const serialized = overlay?.dataset.jxPath;
198
206
  if (!serialized) {
199
207
  return;
@@ -270,7 +278,7 @@ export function startInteraction(
270
278
  channel.post({ kind: "paneFocus" });
271
279
  };
272
280
 
273
- const onClick = (e: Event) => {
281
+ const onClick = (e: MouseEvent) => {
274
282
  /*
275
283
  * Preview keeps anchors live, so a click would navigate this iframe and destroy the render (and
276
284
  * the editing session with it). Report the intent so the parent can open the real page in a real
@@ -303,9 +311,8 @@ export function startInteraction(
303
311
  // Ctrl/Cmd is the accumulate gesture (studio-ui-guidelines.md §8.1). The iframe reports the
304
312
  // Modifier and nothing else — it holds no selection state, so what a modified click MEANS is
305
313
  // The parent's to decide, exactly as the unmodified click already was.
306
- const mouse = e as MouseEvent;
307
314
  channel.post({
308
- additive: mouse.ctrlKey === true || mouse.metaKey === true,
315
+ additive: e.ctrlKey === true || e.metaKey === true,
309
316
  hit,
310
317
  kind: "hit",
311
318
  });
@@ -394,11 +401,10 @@ export function startInteraction(
394
401
  reportInsertZones(target, { x: moveX, y: moveY });
395
402
  };
396
403
 
397
- const onMove = (e: Event) => {
398
- const pe = e as PointerEvent;
404
+ const onMove = (e: PointerEvent) => {
399
405
  moveTarget = e.target;
400
- moveX = pe.clientX;
401
- moveY = pe.clientY;
406
+ moveX = e.clientX;
407
+ moveY = e.clientY;
402
408
  if (movePending) {
403
409
  return;
404
410
  }
@@ -415,8 +421,7 @@ export function startInteraction(
415
421
  }
416
422
  };
417
423
 
418
- const onContextMenu = (e: Event) => {
419
- const me = e as MouseEvent;
424
+ const onContextMenu = (e: MouseEvent) => {
420
425
  // Preview keeps the NATIVE menu: the Jx element menu's verbs (duplicate, delete, paste, wrap)
421
426
  // Are document edits, and preview does not edit. Copy Link Address does what it says instead.
422
427
  if (isPreview()) {
@@ -447,8 +452,8 @@ export function startInteraction(
447
452
  channel.post({
448
453
  kind: "contextMenu",
449
454
  path: hit.path,
450
- x: me.clientX,
451
- y: me.clientY,
455
+ x: e.clientX,
456
+ y: e.clientY,
452
457
  });
453
458
  };
454
459
 
@@ -47,7 +47,7 @@ export function parentCursorToIframe(
47
47
  cursor: { x: number; y: number },
48
48
  iframeRect: { left: number; top: number },
49
49
  scale = 1,
50
- ): { x: number; y: number } {
50
+ ) {
51
51
  return {
52
52
  x: (cursor.x - iframeRect.left) / scale,
53
53
  y: (cursor.y - iframeRect.top) / scale,
@@ -15,7 +15,8 @@
15
15
  */
16
16
 
17
17
  import { reapplyStyle } from "@jxsuite/runtime";
18
- import { getNodeAtPath } from "../state";
18
+ import { isNonNullObject, isNumber, isString } from "@jxsuite/schema/guards";
19
+ import { getNodeAtPath } from "@jxsuite/schema/doc-ops";
19
20
  import { applyDocOpToDoc } from "../tabs/doc-op-apply";
20
21
  import { parseJxPath, serializeJxPath } from "./path-mapping";
21
22
  import { disposeSubtree, renderSubtreeIframe } from "./iframe-subtree";
@@ -25,7 +26,7 @@ import {
25
26
  templateToEditDisplay,
26
27
  } from "../utils/edit-display";
27
28
  import type { IframeRenderCtx } from "./iframe-render";
28
- import type { WireDocOp } from "./iframe-protocol";
29
+ import type { JxDocOp } from "../tabs/patch-ops";
29
30
  import type { JxPath } from "../state";
30
31
  import type { JxMutableNode, JxStyle } from "@jxsuite/schema/types";
31
32
 
@@ -36,7 +37,7 @@ import type { JxMutableNode, JxStyle } from "@jxsuite/schema/types";
36
37
  */
37
38
  export function applyIframePatch(
38
39
  shadowDoc: JxMutableNode,
39
- forwardOps: WireDocOp[],
40
+ forwardOps: JxDocOp[],
40
41
  container: HTMLElement,
41
42
  ctx?: IframeRenderCtx,
42
43
  echoPaths?: JxPath[],
@@ -98,7 +99,7 @@ function requireCtx(ctx: IframeRenderCtx | undefined): IframeRenderCtx {
98
99
 
99
100
  function applyOpToDom(
100
101
  doc: JxMutableNode,
101
- op: WireDocOp,
102
+ op: JxDocOp,
102
103
  container: HTMLElement,
103
104
  ctx: IframeRenderCtx | undefined,
104
105
  ): void {
@@ -138,7 +139,7 @@ function applyOpToDom(
138
139
  return;
139
140
  }
140
141
  default: {
141
- // The WireDocOp union is exhaustively handled above; this guards a future op kind.
142
+ // The JxDocOp union is exhaustively handled above; this guards a future op kind.
142
143
  throw new Error(`iframe-patch-unsupported-op:${JSON.stringify(op)}`);
143
144
  }
144
145
  }
@@ -292,7 +293,7 @@ function remapChildPaths(
292
293
  continue;
293
294
  }
294
295
  const idx = p[depth + 1];
295
- if (typeof idx !== "number" || idx < fromIndex) {
296
+ if (!isNumber(idx) || idx < fromIndex) {
296
297
  continue;
297
298
  }
298
299
  if (!parentPath.every((seg, i) => p[i] === seg)) {
@@ -338,7 +339,9 @@ function patchStyle(
338
339
  ): void {
339
340
  const el = requireElement(container, path);
340
341
  const node = getNodeAtPath(doc, path);
341
- const mediaQueries = (ctx?.defs?.["$media"] as Record<string, string> | undefined) ?? {};
342
+ /* SAFETY: buildScope writes `$media` only from the document's own `$media` map or the runtime's
343
+ * root media map, both Record<string, string>, and the host scope may not supply the key. */
344
+ const mediaQueries = (ctx?.defs["$media"] as Record<string, string> | undefined) ?? {};
342
345
  reapplyStyle(el, editModeStyle(node?.style), mediaQueries);
343
346
  }
344
347
 
@@ -372,20 +375,20 @@ function findElement(container: HTMLElement, path: (string | number)[]): HTMLEle
372
375
  * top-level template-string values are blanked so no reactive bindings are created for them.
373
376
  */
374
377
  function editModeStyle(style: JxStyle | undefined): JxStyle | undefined {
375
- if (!style || typeof style !== "object") {
378
+ if (!style || !isNonNullObject(style)) {
376
379
  return undefined;
377
380
  }
378
- const out: Record<string, unknown> = {};
381
+ const out: JxStyle = {};
379
382
  for (const [k, v] of Object.entries(style)) {
380
383
  /* OMITTED, not blanked. It used to be written as `""`, which was a silent no-op while a
381
384
  declaration went to `el.style` and is a malformed declaration now that it goes into a rule.
382
385
  Dropping the key is what blanking always meant: the property falls back to the cascade. */
383
- if (typeof v === "string" && v.includes("${")) {
386
+ if (isString(v) && v.includes("${")) {
384
387
  continue;
385
388
  }
386
389
  out[k] = v;
387
390
  }
388
- return out as JxStyle;
391
+ return out;
389
392
  }
390
393
 
391
394
  /**
@@ -393,15 +396,15 @@ function editModeStyle(style: JxStyle | undefined): JxStyle | undefined {
393
396
  * template-string and $ref display rules (and the legacy patcher's textDisplayValue).
394
397
  */
395
398
  function textDisplayValue(node: JxMutableNode | undefined): string {
396
- const v = (node as { textContent?: unknown } | undefined)?.textContent;
399
+ const v = node?.textContent;
397
400
  if (v == null) {
398
401
  return "";
399
402
  }
400
- if (typeof v === "string") {
403
+ if (isString(v)) {
401
404
  return v.includes("${") ? templateToEditDisplay(v) : v;
402
405
  }
403
- if (typeof v === "object" && (v as Record<string, unknown>).$ref) {
404
- const ref = String((v as Record<string, unknown>).$ref);
406
+ if (isNonNullObject(v) && v.$ref) {
407
+ const ref = String(v.$ref);
405
408
  const label = ref.startsWith("#/state/") ? ref.slice(8) : ref;
406
409
  return `{${label}}`;
407
410
  }
@@ -33,6 +33,12 @@ export interface DocRange {
33
33
  head: DocPos;
34
34
  }
35
35
 
36
+ /** A live DOM caret position: a node and an offset into it, as a Selection endpoint carries. */
37
+ export interface DomPosition {
38
+ node: Node;
39
+ offset: number;
40
+ }
41
+
36
42
  /** Whether an element is a block the caret may live inside. Injected so the editable set is policy. */
37
43
  export type EditablePredicate = (el: HTMLElement) => boolean;
38
44
 
@@ -91,7 +97,7 @@ export function elementForPath(container: HTMLElement, path: JxPath): HTMLElemen
91
97
 
92
98
  /** The block's rendered text length — the maximum valid offset within it. */
93
99
  export function blockTextLength(block: HTMLElement): number {
94
- return block.textContent?.length ?? 0;
100
+ return block.textContent.length;
95
101
  }
96
102
 
97
103
  /**
@@ -126,11 +132,12 @@ export function offsetOf(block: HTMLElement, node: Node, offset: number): number
126
132
  * every offset-based editor carries at a line break, and it is invisible for the paths that use
127
133
  * this (caret restore after a patch, and block-boundary edits, which clamp to 0 / length anyway).
128
134
  */
129
- export function domPositionAt(block: HTMLElement, offset: number): { node: Node; offset: number } {
135
+ export function domPositionAt(block: HTMLElement, offset: number): DomPosition {
130
136
  const target = Math.max(0, Math.min(offset, blockTextLength(block)));
131
137
  const walker = block.ownerDocument.createTreeWalker(block, NodeFilter.SHOW_TEXT);
132
138
  let seen = 0;
133
139
  let last: Text | null = null;
140
+ // SAFETY: the walker was created with NodeFilter.SHOW_TEXT, so every node it yields is a Text.
134
141
  let current = walker.nextNode() as Text | null;
135
142
  while (current) {
136
143
  const len = current.length;
@@ -139,6 +146,7 @@ export function domPositionAt(block: HTMLElement, offset: number): { node: Node;
139
146
  }
140
147
  seen += len;
141
148
  last = current;
149
+ // SAFETY: the same SHOW_TEXT walker as above, so the next node is a Text or the walk's end.
142
150
  current = walker.nextNode() as Text | null;
143
151
  }
144
152
  // No text node reaches the target: either the block has no text at all (caret goes to the element
@@ -169,10 +177,7 @@ export function toDocPos(
169
177
  * block whose text shrank under a remote edit lands at the block's new end instead of being
170
178
  * dropped.
171
179
  */
172
- export function toDomPosition(
173
- container: HTMLElement,
174
- pos: DocPos,
175
- ): { node: Node; offset: number } | null {
180
+ export function toDomPosition(container: HTMLElement, pos: DocPos): DomPosition | null {
176
181
  const el = elementForPath(container, pos.path);
177
182
  return el ? domPositionAt(el, pos.offset) : null;
178
183
  }
@@ -246,6 +251,7 @@ export function adjacentBlock(
246
251
  const key = serializeJxPath(path);
247
252
  const index = blocks.findIndex((el) => el.dataset.jxPath === key);
248
253
  const neighbour = index === -1 ? undefined : blocks[index + direction];
254
+ // SAFETY: blocksInOrder collects only elements matching `[data-jx-path]`, so the attribute is set.
249
255
  return neighbour
250
256
  ? { el: neighbour, path: parseJxPath(neighbour.dataset.jxPath as string) }
251
257
  : null;
@@ -12,16 +12,7 @@
12
12
  import type { AssetContext } from "./asset-resolve";
13
13
  import type { JxDocOp } from "../tabs/patch-ops";
14
14
  import type { JxContentResult, SlashCommand } from "../editor/inline-edit";
15
- import type { JxExpressionNode, JxMutableNode } from "@jxsuite/schema/types";
16
-
17
- /**
18
- * The wire form of a value-carrying document op (the `forward` half of a recorded
19
- * {@link JxDocOpPair} — see {@link file://../tabs/patch-ops.ts}). It is structurally a
20
- * {@link JxDocOp}: it carries the inserted/replaced `node` and the set `value`, NOT just a path, so
21
- * the iframe can fold it into its shadow doc and re-render subtrees without ever reading the
22
- * parent's reactive document.
23
- */
24
- export type WireDocOp = JxDocOp;
15
+ import type { JsonObject, JxExpressionNode, JxMutableNode, JxStyle } from "@jxsuite/schema/types";
25
16
 
26
17
  export const CANVAS_MODES = ["preview", "design", "edit", "stylebook", "git-diff"] as const;
27
18
 
@@ -37,7 +28,7 @@ export const CANVAS_MODES = ["preview", "design", "edit", "stylebook", "git-diff
37
28
  export type CanvasMode = (typeof CANVAS_MODES)[number];
38
29
 
39
30
  export function isCanvasMode(value: unknown): value is CanvasMode {
40
- return typeof value === "string" && (CANVAS_MODES as readonly string[]).includes(value);
31
+ return typeof value === "string" && CANVAS_MODES.some((mode) => mode === value);
41
32
  }
42
33
 
43
34
  /**
@@ -121,7 +112,7 @@ export type ParentToIframe =
121
112
  */
122
113
  assets?: AssetContext | null;
123
114
  mapperCtx: WireMapperCtx;
124
- siteStyle: Record<string, unknown> | null;
115
+ siteStyle: JxStyle | null;
125
116
  // Forced color-scheme preview (spec.md §9.5): "light"/"dark" sets data-color-scheme on the
126
117
  // Iframe root, null clears it (auto — follow the OS).
127
118
  colorScheme: "light" | "dark" | null;
@@ -239,7 +230,7 @@ export type ParentToIframe =
239
230
  // Render-free; the superseding render carries the same style via its own siteStyle.
240
231
  | {
241
232
  kind: "siteStyleUpdate";
242
- siteStyle: Record<string, unknown> | null;
233
+ siteStyle: JxStyle | null;
243
234
  media: Record<string, string>;
244
235
  }
245
236
  // Ask the iframe to measure the given document paths and post their current rects back. Used to
@@ -255,7 +246,12 @@ export type ParentToIframe =
255
246
  // In place. `gen` matches the last render so the iframe drops patches superseded by a re-render.
256
247
  | {
257
248
  kind: "patch";
258
- forwardOps: WireDocOp[];
249
+ /**
250
+ * The `forward` halves of the recorded {@link JxDocOp} pairs (tabs/patch-ops.ts). Each carries
251
+ * the inserted/replaced `node` and the set `value`, not just a path, so the iframe folds it
252
+ * into its shadow doc without ever reading the parent's reactive document.
253
+ */
254
+ forwardOps: JxDocOp[];
259
255
  gen: number;
260
256
  /**
261
257
  * Paths whose DOM the RECIPIENT already has correct, because this patch is the echo of an
@@ -273,7 +269,7 @@ export type ParentToIframe =
273
269
  // Regenerates the whole scoped-CSS cascade (real @media included) without a re-render. `style` is
274
270
  // Already transposed parent-side (transposeStylebookStyle); `gen` must equal the iframe's
275
271
  // RenderedGen — a stale update is dropped (the superseding render carries the same style).
276
- | { kind: "styleUpdate"; style: Record<string, unknown>; gen: number }
272
+ | { kind: "styleUpdate"; style: JxStyle; gen: number }
277
273
  // Enter inline editing on the node at `path` (used to re-enter after a split/insert re-renders).
278
274
  | {
279
275
  kind: "enterEdit";
@@ -490,7 +486,7 @@ export type IframeToParent =
490
486
  // `S.canvas.scope` so the data-explorer panel shows live data instead of "pending" (the iframe,
491
487
  // Not the parent, now resolves the scope). `gen` lets the parent drop a snapshot from a superseded
492
488
  // Render. Posted right after `renderComplete`; values are JSON-safe deep clones (see serialize-scope).
493
- | { kind: "dataScope"; gen: number; scope: Record<string, unknown> }
489
+ | { kind: "dataScope"; gen: number; scope: JsonObject }
494
490
  // The frame's own quiescence, ANSWERED rather than polled (studio.md §13.5).
495
491
  // Nothing in the parent realm can see inside a cross-origin frame, so a parent that wanted to
496
492
  // Know whether the canvas had settled could only sleep. The frame samples itself at its own rAF
@@ -38,7 +38,8 @@ import { elementForPath } from "./iframe-position";
38
38
  import type { AssetContext } from "./asset-resolve";
39
39
  import { SITE_STYLE_ID, buildSiteStyleCSS } from "@jxsuite/site/site-style";
40
40
  import type { CanvasMode, WireDiffMarks } from "./iframe-protocol";
41
- import type { JxDocument } from "@jxsuite/schema/types";
41
+ import { isNonNullObject, isString } from "@jxsuite/schema/guards";
42
+ import type { JxDocument, JxElement, JxStyle } from "@jxsuite/schema/types";
42
43
  import type { PathMapCtx } from "./path-mapping";
43
44
 
44
45
  /**
@@ -61,18 +62,12 @@ export interface RenderHandle {
61
62
  ctx: IframeRenderCtx;
62
63
  }
63
64
 
64
- interface HeadEntry {
65
- tagName?: string;
66
- attributes?: Record<string, unknown>;
67
- textContent?: string;
68
- }
69
-
70
65
  /**
71
66
  * Register the document's `$elements` (components) in this iframe realm so the runtime can render
72
67
  * them.
73
68
  */
74
69
  export async function registerElements(doc: JxDocument, docBase: string): Promise<void> {
75
- const elements = (doc as { $elements?: unknown[] }).$elements;
70
+ const elements = doc.$elements;
76
71
  if (!Array.isArray(elements)) {
77
72
  return;
78
73
  }
@@ -81,13 +76,16 @@ export async function registerElements(doc: JxDocument, docBase: string): Promis
81
76
  await Promise.all(
82
77
  elements.map(async (entry) => {
83
78
  const task = (async () => {
84
- if (typeof entry === "string") {
79
+ if (isString(entry)) {
85
80
  const specifier =
86
81
  entry.startsWith("/") || entry.startsWith(".") ? entry : `/node_modules/${entry}`;
87
82
  await import(specifier);
88
- } else if (entry && typeof entry === "object" && "$ref" in entry) {
89
- await defineElement(new URL(String((entry as { $ref: string }).$ref), docBase).href);
90
- } else if (entry && typeof entry === "object") {
83
+ } else if (isNonNullObject(entry) && "$ref" in entry) {
84
+ await defineElement(new URL(String(entry.$ref), docBase).href);
85
+ } else if (isNonNullObject(entry)) {
86
+ /* SAFETY: an `$elements` entry that is neither a specifier nor a `$ref` is an inline
87
+ * component definition by the schema (JxDocument is JxElement with a literal tagName).
88
+ * A malformed one throws inside this task, which the race below catches and logs. */
91
89
  await defineElement(entry as JxDocument, docBase);
92
90
  }
93
91
  })();
@@ -696,11 +694,11 @@ export function syncStylebookCss(doc: Document, mode: CanvasMode): void {
696
694
  * selectors can win (spec.md §9.5), and so removed tokens can't linger on reused iframes.
697
695
  */
698
696
  export function applySiteStyle(
699
- siteStyle: Record<string, unknown> | null | undefined,
697
+ siteStyle: JxStyle | null | undefined,
700
698
  mediaQueries: Record<string, string> = {},
701
699
  ): void {
702
700
  const existing = document.head.querySelector(`#${SITE_STYLE_ID}`);
703
- if (!siteStyle || typeof siteStyle !== "object") {
701
+ if (!siteStyle || !isNonNullObject(siteStyle)) {
704
702
  existing?.remove();
705
703
  return;
706
704
  }
@@ -746,15 +744,15 @@ export function applyPreviewColorScheme(doc: Document, scheme: "light" | "dark"
746
744
  * @docs studio/interface/canvas
747
745
  */
748
746
  export function applyCanvasPopoverOpen(root: ParentNode, path: string | null): void {
749
- for (const el of root.querySelectorAll("[data-jx-popover-open]")) {
750
- delete (el as HTMLElement).dataset.jxPopoverOpen;
747
+ for (const el of root.querySelectorAll<HTMLElement>("[data-jx-popover-open]")) {
748
+ delete el.dataset.jxPopoverOpen;
751
749
  }
752
750
  if (path === null) {
753
751
  return;
754
752
  }
755
- const target = root.querySelector(`[data-jx-popover]${jxPathSelector(path)}`);
753
+ const target = root.querySelector<HTMLElement>(`[data-jx-popover]${jxPathSelector(path)}`);
756
754
  if (target) {
757
- (target as HTMLElement).dataset.jxPopoverOpen = "";
755
+ target.dataset.jxPopoverOpen = "";
758
756
  }
759
757
  }
760
758
 
@@ -783,26 +781,27 @@ export function applyCanvasPopoverOpen(root: ParentNode, path: string | null): v
783
781
  * backdrop and all.
784
782
  */
785
783
  export function applyCanvasDialogOpen(root: ParentNode, path: string | null): void {
786
- for (const el of root.querySelectorAll("[data-jx-dialog-open]")) {
787
- delete (el as HTMLElement).dataset.jxDialogOpen;
784
+ for (const el of root.querySelectorAll<HTMLElement>("[data-jx-dialog-open]")) {
785
+ delete el.dataset.jxDialogOpen;
788
786
  }
789
787
  if (path === null) {
790
788
  return;
791
789
  }
792
- const target = root.querySelector(`dialog${jxPathSelector(path)}`);
790
+ const target = root.querySelector<HTMLElement>(`dialog${jxPathSelector(path)}`);
793
791
  if (target) {
794
- (target as HTMLElement).dataset.jxDialogOpen = "";
792
+ target.dataset.jxDialogOpen = "";
795
793
  }
796
794
  }
797
795
 
798
796
  /** Inject the document's `$head` (link/meta/script) into the iframe's <head>, de-duped by href/src. */
799
797
  export function injectHead(doc: JxDocument, assets: AssetContext | null = null): void {
800
- const head = (doc as { $head?: HeadEntry[] }).$head;
798
+ const head = doc.$head;
801
799
  if (!Array.isArray(head)) {
802
800
  return;
803
801
  }
804
802
  for (const entry of head) {
805
- if (!entry?.tagName) {
803
+ // A `$head` array read off disk can hold a null or a tagless entry; neither emits anything.
804
+ if (!isNonNullObject(entry) || !entry.tagName) {
806
805
  continue;
807
806
  }
808
807
  const tag = String(entry.tagName).toLowerCase();
@@ -810,10 +809,10 @@ export function injectHead(doc: JxDocument, assets: AssetContext | null = null):
810
809
  if (tag === "script" && !entry.attributes?.src) {
811
810
  continue;
812
811
  }
813
- const attrs = { ...entry.attributes } as Record<string, unknown>;
812
+ const attrs = { ...entry.attributes };
814
813
  for (const key of ["href", "src"]) {
815
814
  const val = attrs[key];
816
- if (typeof val !== "string" || val === "") {
815
+ if (!isString(val) || val === "") {
817
816
  continue;
818
817
  }
819
818
  if (!val.startsWith("/") && !val.startsWith(".") && !val.startsWith("http")) {
@@ -833,7 +832,7 @@ export function injectHead(doc: JxDocument, assets: AssetContext | null = null):
833
832
  el.setAttribute(k, String(v));
834
833
  }
835
834
  if (entry.textContent) {
836
- el.textContent = entry.textContent;
835
+ el.textContent = String(entry.textContent);
837
836
  }
838
837
  document.head.append(el);
839
838
  }
@@ -856,7 +855,7 @@ export function makeStamper(ctx: PathMapCtx) {
856
855
  (island) => path.length > island.length && island.every((seg, i) => path[i] === seg),
857
856
  );
858
857
 
859
- return (created: Node, path: (string | number)[], def: unknown) => {
858
+ return (created: Node, path: (string | number)[], def: JxElement | string) => {
860
859
  if (!(created instanceof HTMLElement)) {
861
860
  return;
862
861
  }
@@ -866,7 +865,10 @@ export function makeStamper(ctx: PathMapCtx) {
866
865
  // Editable tree and re-render a live instance with default state. Mark the root so the
867
866
  // Runtime's element class leaves it alone (see defineElement's connectedCallback guard).
868
867
  const isDefinitionRoot =
869
- path.length === 0 && (def as { tagName?: string } | null)?.tagName?.includes("-");
868
+ path.length === 0 &&
869
+ isNonNullObject(def) &&
870
+ isString(def.tagName) &&
871
+ def.tagName.includes("-");
870
872
  if (isDefinitionRoot) {
871
873
  created.dataset.jxDefinitionRoot = "";
872
874
  }
@@ -984,7 +986,7 @@ export async function renderResolvedDocument(opts: {
984
986
  docBase: string;
985
987
  mode: CanvasMode;
986
988
  mapperCtx: PathMapCtx;
987
- siteStyle?: Record<string, unknown> | null;
989
+ siteStyle?: JxStyle | null;
988
990
  /**
989
991
  * How this host addresses project media, or null when the canvas origin serves the site's own URL
990
992
  * space (desktop, `jx dev`) and references need no resolution at all.
@@ -1037,7 +1039,7 @@ export async function renderResolvedDocument(opts: {
1037
1039
  // Iframe clears it (page-level templates are inert in design/edit via prepareForEditMode, so only
1038
1040
  // Component internals get stamped).
1039
1041
  setStampPropBindings(opts.mode === "design" || opts.mode === "edit");
1040
- applySiteStyle(opts.siteStyle, (opts.doc as { $media?: Record<string, string> }).$media ?? {});
1042
+ applySiteStyle(opts.siteStyle, opts.doc.$media ?? {});
1041
1043
  injectHead(opts.doc, assets);
1042
1044
  syncEditModeCss(opts.container.ownerDocument, opts.mode);
1043
1045
  // The substitute rules for the attributes the de-link above renamed. Same predicate as the
@@ -1052,7 +1054,7 @@ export async function renderResolvedDocument(opts: {
1052
1054
  // But no own `$media` resolves the breakpoint to its real query (the iframe path calls buildScope
1053
1055
  // Directly and never the runtime's `Jx()` entry, which is the only other place _rootMedia is set).
1054
1056
  // Set it every render (even to `{}`) so a stale map from a previous document cannot leak.
1055
- setRootMedia((opts.doc as { $media?: Record<string, string> }).$media ?? {});
1057
+ setRootMedia(opts.doc.$media ?? {});
1056
1058
  // Register components BEFORE renderNode. The runtime only applies a custom element's `$props` when
1057
1059
  // That element is ALREADY defined (renderNode gates renderCustomElementWithProps on a truthy
1058
1060
  // `customElements.get(tagName)`); if we register after render, every component paints with its
@@ -1066,8 +1068,8 @@ export async function renderResolvedDocument(opts: {
1066
1068
  // The scope MUST be the runtime's (runScoped): renderNode creates its binding effects with the
1067
1069
  // Runtime's copy of @vue/reactivity, and scope collection is per module instance — a studio
1068
1070
  // EffectScope here collects nothing and dispose() would leak every effect of this render.
1069
- const { result: el, stop } = runScoped(
1070
- () => renderNode(opts.doc, $defs, { _path: [], onNodeCreated }) as HTMLElement,
1071
+ const { result: el, stop } = runScoped(() =>
1072
+ renderNode(opts.doc, $defs, { _path: [], onNodeCreated }),
1071
1073
  );
1072
1074
  opts.container.replaceChildren(el);
1073
1075
  applyCanvasPopoverOpen(opts.container, opts.popoverOpen ?? null);