@tai42/studio-sdk 16.0.0 → 17.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 (486) hide show
  1. package/dist/components/code-block.js +1 -1
  2. package/dist/components/code-block.js.map +1 -1
  3. package/dist/components/confirm-dialog.js +1 -1
  4. package/dist/components/confirm-dialog.js.map +1 -1
  5. package/dist/components/copy-field.js +1 -1
  6. package/dist/components/copy-field.js.map +1 -1
  7. package/dist/components/date-range-picker.d.ts.map +1 -1
  8. package/dist/components/date-range-picker.js.map +1 -1
  9. package/dist/components/dialog.d.ts.map +1 -1
  10. package/dist/components/dialog.js.map +1 -1
  11. package/dist/components/dirty-guard.d.ts.map +1 -1
  12. package/dist/components/dirty-guard.js +1 -1
  13. package/dist/components/dirty-guard.js.map +1 -1
  14. package/dist/components/explorer-body.d.ts +49 -0
  15. package/dist/components/explorer-body.d.ts.map +1 -0
  16. package/dist/components/explorer-body.js +67 -0
  17. package/dist/components/explorer-body.js.map +1 -0
  18. package/dist/components/explorer-page-size.d.ts +4 -0
  19. package/dist/components/explorer-page-size.d.ts.map +1 -0
  20. package/dist/components/explorer-page-size.js +36 -0
  21. package/dist/components/explorer-page-size.js.map +1 -0
  22. package/dist/components/explorer-tag-filter.d.ts +17 -0
  23. package/dist/components/explorer-tag-filter.d.ts.map +1 -0
  24. package/dist/components/explorer-tag-filter.js +29 -0
  25. package/dist/components/explorer-tag-filter.js.map +1 -0
  26. package/dist/components/explorer-tags.d.ts +22 -0
  27. package/dist/components/explorer-tags.d.ts.map +1 -0
  28. package/dist/components/explorer-tags.js +51 -0
  29. package/dist/components/explorer-tags.js.map +1 -0
  30. package/dist/components/explorer-view.d.ts +3 -17
  31. package/dist/components/explorer-view.d.ts.map +1 -1
  32. package/dist/components/explorer-view.js +53 -170
  33. package/dist/components/explorer-view.js.map +1 -1
  34. package/dist/components/extension-combo-builder.d.ts +1 -6
  35. package/dist/components/extension-combo-builder.d.ts.map +1 -1
  36. package/dist/components/extension-combo-builder.js +4 -79
  37. package/dist/components/extension-combo-builder.js.map +1 -1
  38. package/dist/components/extension-combo-parts.d.ts +44 -0
  39. package/dist/components/extension-combo-parts.d.ts.map +1 -0
  40. package/dist/components/extension-combo-parts.js +52 -0
  41. package/dist/components/extension-combo-parts.js.map +1 -0
  42. package/dist/components/field.d.ts +8 -0
  43. package/dist/components/field.d.ts.map +1 -1
  44. package/dist/components/field.js +0 -8
  45. package/dist/components/field.js.map +1 -1
  46. package/dist/components/fleet-report.d.ts +1 -1
  47. package/dist/components/fleet-report.d.ts.map +1 -1
  48. package/dist/components/fleet-report.js +51 -37
  49. package/dist/components/fleet-report.js.map +1 -1
  50. package/dist/components/folder-nav.d.ts.map +1 -1
  51. package/dist/components/folder-nav.js +1 -1
  52. package/dist/components/folder-nav.js.map +1 -1
  53. package/dist/components/form-dialog.d.ts.map +1 -1
  54. package/dist/components/form-dialog.js +1 -1
  55. package/dist/components/form-dialog.js.map +1 -1
  56. package/dist/components/icons/chrome-marks.d.ts +50 -0
  57. package/dist/components/icons/chrome-marks.d.ts.map +1 -0
  58. package/dist/components/icons/chrome-marks.js +51 -0
  59. package/dist/components/icons/chrome-marks.js.map +1 -0
  60. package/dist/components/icons/icon-frame.d.ts +29 -0
  61. package/dist/components/icons/icon-frame.d.ts.map +1 -0
  62. package/dist/components/icons/icon-frame.js +19 -0
  63. package/dist/components/icons/icon-frame.js.map +1 -0
  64. package/dist/components/icons/index.d.ts +40 -0
  65. package/dist/components/icons/index.d.ts.map +1 -0
  66. package/dist/components/icons/index.js +39 -0
  67. package/dist/components/icons/index.js.map +1 -0
  68. package/dist/components/icons/nav-map.d.ts +14 -0
  69. package/dist/components/icons/nav-map.d.ts.map +1 -0
  70. package/dist/components/icons/nav-map.js +28 -0
  71. package/dist/components/icons/nav-map.js.map +1 -0
  72. package/dist/components/icons/nav-marks.d.ts +44 -0
  73. package/dist/components/icons/nav-marks.d.ts.map +1 -0
  74. package/dist/components/icons/nav-marks.js +45 -0
  75. package/dist/components/icons/nav-marks.js.map +1 -0
  76. package/dist/components/icons/status-marks.d.ts +21 -0
  77. package/dist/components/icons/status-marks.d.ts.map +1 -0
  78. package/dist/components/icons/status-marks.js +22 -0
  79. package/dist/components/icons/status-marks.js.map +1 -0
  80. package/dist/components/icons/theme-marks.d.ts +9 -0
  81. package/dist/components/icons/theme-marks.d.ts.map +1 -0
  82. package/dist/components/icons/theme-marks.js +10 -0
  83. package/dist/components/icons/theme-marks.js.map +1 -0
  84. package/dist/components/inputs.js.map +1 -1
  85. package/dist/components/json-diff.d.ts.map +1 -1
  86. package/dist/components/json-diff.js +1 -3
  87. package/dist/components/json-diff.js.map +1 -1
  88. package/dist/components/json-tree-context.d.ts +13 -0
  89. package/dist/components/json-tree-context.d.ts.map +1 -0
  90. package/dist/components/json-tree-context.js +15 -0
  91. package/dist/components/json-tree-context.js.map +1 -0
  92. package/dist/components/json-tree-model.d.ts +56 -0
  93. package/dist/components/json-tree-model.d.ts.map +1 -0
  94. package/dist/components/json-tree-model.js +125 -0
  95. package/dist/components/json-tree-model.js.map +1 -0
  96. package/dist/components/json-tree-nodes.d.ts +35 -0
  97. package/dist/components/json-tree-nodes.d.ts.map +1 -0
  98. package/dist/components/json-tree-nodes.js +113 -0
  99. package/dist/components/json-tree-nodes.js.map +1 -0
  100. package/dist/components/json-tree.d.ts +20 -0
  101. package/dist/components/json-tree.d.ts.map +1 -1
  102. package/dist/components/json-tree.js +7 -315
  103. package/dist/components/json-tree.js.map +1 -1
  104. package/dist/components/json-value-format.d.ts +20 -0
  105. package/dist/components/json-value-format.d.ts.map +1 -0
  106. package/dist/components/json-value-format.js +63 -0
  107. package/dist/components/json-value-format.js.map +1 -0
  108. package/dist/components/markdown-blocks.d.ts +38 -0
  109. package/dist/components/markdown-blocks.d.ts.map +1 -0
  110. package/dist/components/markdown-blocks.js +168 -0
  111. package/dist/components/markdown-blocks.js.map +1 -0
  112. package/dist/components/markdown-inline.d.ts +24 -0
  113. package/dist/components/markdown-inline.d.ts.map +1 -0
  114. package/dist/components/markdown-inline.js +257 -0
  115. package/dist/components/markdown-inline.js.map +1 -0
  116. package/dist/components/markdown.d.ts +3 -52
  117. package/dist/components/markdown.d.ts.map +1 -1
  118. package/dist/components/markdown.js +4 -376
  119. package/dist/components/markdown.js.map +1 -1
  120. package/dist/components/observer-registry.d.ts +38 -0
  121. package/dist/components/observer-registry.d.ts.map +1 -0
  122. package/dist/components/observer-registry.js +131 -0
  123. package/dist/components/observer-registry.js.map +1 -0
  124. package/dist/components/overflow-measure.d.ts +38 -0
  125. package/dist/components/overflow-measure.d.ts.map +1 -0
  126. package/dist/components/overflow-measure.js +54 -0
  127. package/dist/components/overflow-measure.js.map +1 -0
  128. package/dist/components/page-fill.d.ts.map +1 -1
  129. package/dist/components/page-fill.js.map +1 -1
  130. package/dist/components/prose-regions.d.ts +81 -0
  131. package/dist/components/prose-regions.d.ts.map +1 -0
  132. package/dist/components/prose-regions.js +128 -0
  133. package/dist/components/prose-regions.js.map +1 -0
  134. package/dist/components/radio-group.d.ts.map +1 -1
  135. package/dist/components/radio-group.js.map +1 -1
  136. package/dist/components/scroll-region.d.ts +24 -0
  137. package/dist/components/scroll-region.d.ts.map +1 -1
  138. package/dist/components/scroll-region.js +3 -322
  139. package/dist/components/scroll-region.js.map +1 -1
  140. package/dist/components/tab-stop-parse.d.ts +53 -0
  141. package/dist/components/tab-stop-parse.d.ts.map +1 -0
  142. package/dist/components/tab-stop-parse.js +202 -0
  143. package/dist/components/tab-stop-parse.js.map +1 -0
  144. package/dist/components/table.d.ts +1 -1
  145. package/dist/components/table.d.ts.map +1 -1
  146. package/dist/components/tags.d.ts.map +1 -1
  147. package/dist/components/tags.js +1 -1
  148. package/dist/components/tags.js.map +1 -1
  149. package/dist/components/templated-text-field.d.ts +1 -1
  150. package/dist/components/templated-text-field.d.ts.map +1 -1
  151. package/dist/components/templated-text-field.js +10 -174
  152. package/dist/components/templated-text-field.js.map +1 -1
  153. package/dist/components/templated-text-kwargs-editor.d.ts +24 -0
  154. package/dist/components/templated-text-kwargs-editor.d.ts.map +1 -0
  155. package/dist/components/templated-text-kwargs-editor.js +48 -0
  156. package/dist/components/templated-text-kwargs-editor.js.map +1 -0
  157. package/dist/components/templated-text-kwargs.d.ts +37 -0
  158. package/dist/components/templated-text-kwargs.d.ts.map +1 -0
  159. package/dist/components/templated-text-kwargs.js +66 -0
  160. package/dist/components/templated-text-kwargs.js.map +1 -0
  161. package/dist/components/templated-text-source.d.ts +33 -0
  162. package/dist/components/templated-text-source.d.ts.map +1 -0
  163. package/dist/components/templated-text-source.js +53 -0
  164. package/dist/components/templated-text-source.js.map +1 -0
  165. package/dist/components/tool-picker-parts.d.ts +39 -0
  166. package/dist/components/tool-picker-parts.d.ts.map +1 -0
  167. package/dist/components/tool-picker-parts.js +87 -0
  168. package/dist/components/tool-picker-parts.js.map +1 -0
  169. package/dist/components/tool-picker.d.ts +1 -2
  170. package/dist/components/tool-picker.d.ts.map +1 -1
  171. package/dist/components/tool-picker.js +4 -66
  172. package/dist/components/tool-picker.js.map +1 -1
  173. package/dist/components/version-history-panel.d.ts.map +1 -1
  174. package/dist/components/version-history-panel.js +7 -34
  175. package/dist/components/version-history-panel.js.map +1 -1
  176. package/dist/components/version-history-rows.d.ts +48 -0
  177. package/dist/components/version-history-rows.d.ts.map +1 -0
  178. package/dist/components/version-history-rows.js +51 -0
  179. package/dist/components/version-history-rows.js.map +1 -0
  180. package/dist/components/view-toggle.d.ts.map +1 -1
  181. package/dist/components/view-toggle.js.map +1 -1
  182. package/dist/element-slot.d.ts +11 -0
  183. package/dist/element-slot.d.ts.map +1 -1
  184. package/dist/element-slot.js +0 -11
  185. package/dist/element-slot.js.map +1 -1
  186. package/dist/guards.d.ts +6 -0
  187. package/dist/guards.d.ts.map +1 -0
  188. package/dist/guards.js +8 -0
  189. package/dist/guards.js.map +1 -0
  190. package/dist/hooks/interactions-connection.d.ts +43 -0
  191. package/dist/hooks/interactions-connection.d.ts.map +1 -0
  192. package/dist/hooks/interactions-connection.js +171 -0
  193. package/dist/hooks/interactions-connection.js.map +1 -0
  194. package/dist/hooks/interactions-stream.d.ts +80 -0
  195. package/dist/hooks/interactions-stream.d.ts.map +1 -0
  196. package/dist/hooks/interactions-stream.js +233 -0
  197. package/dist/hooks/interactions-stream.js.map +1 -0
  198. package/dist/hooks/useApi.d.ts +2259 -2189
  199. package/dist/hooks/useApi.d.ts.map +1 -1
  200. package/dist/hooks/useApi.js +0 -11
  201. package/dist/hooks/useApi.js.map +1 -1
  202. package/dist/hooks/useAuth.d.ts +6 -0
  203. package/dist/hooks/useAuth.d.ts.map +1 -1
  204. package/dist/hooks/useAuth.js +0 -6
  205. package/dist/hooks/useAuth.js.map +1 -1
  206. package/dist/hooks/useCapabilities.d.ts +18 -2
  207. package/dist/hooks/useCapabilities.d.ts.map +1 -1
  208. package/dist/hooks/useCapabilities.js +1 -17
  209. package/dist/hooks/useCapabilities.js.map +1 -1
  210. package/dist/hooks/useSse.d.ts +34 -6
  211. package/dist/hooks/useSse.d.ts.map +1 -1
  212. package/dist/hooks/useSse.js +27 -471
  213. package/dist/hooks/useSse.js.map +1 -1
  214. package/dist/hooks/useSystemKinds.d.ts +1 -1
  215. package/dist/hooks/useSystemKinds.d.ts.map +1 -1
  216. package/dist/hooks/useSystemKinds.js +0 -18
  217. package/dist/hooks/useSystemKinds.js.map +1 -1
  218. package/dist/hooks/useTheme.d.ts +15 -0
  219. package/dist/hooks/useTheme.d.ts.map +1 -1
  220. package/dist/hooks/useTheme.js +0 -15
  221. package/dist/hooks/useTheme.js.map +1 -1
  222. package/dist/hooks/useToolDisplayNames.d.ts +0 -14
  223. package/dist/hooks/useToolDisplayNames.d.ts.map +1 -1
  224. package/dist/hooks/useToolDisplayNames.js +0 -14
  225. package/dist/hooks/useToolDisplayNames.js.map +1 -1
  226. package/dist/host.d.ts +3 -3
  227. package/dist/host.d.ts.map +1 -1
  228. package/dist/host.js +2 -9
  229. package/dist/host.js.map +1 -1
  230. package/dist/index.d.ts +103 -103
  231. package/dist/index.d.ts.map +1 -1
  232. package/dist/index.js +49 -62
  233. package/dist/index.js.map +1 -1
  234. package/dist/navigation/app-link.d.ts +25 -0
  235. package/dist/navigation/app-link.d.ts.map +1 -0
  236. package/dist/navigation/app-link.js +33 -0
  237. package/dist/navigation/app-link.js.map +1 -0
  238. package/dist/navigation/context.d.ts +3 -20
  239. package/dist/navigation/context.d.ts.map +1 -1
  240. package/dist/navigation/context.js +7 -267
  241. package/dist/navigation/context.js.map +1 -1
  242. package/dist/navigation/entry-state.d.ts +23 -0
  243. package/dist/navigation/entry-state.d.ts.map +1 -0
  244. package/dist/navigation/entry-state.js +39 -0
  245. package/dist/navigation/entry-state.js.map +1 -0
  246. package/dist/navigation/guard-registry.d.ts +30 -0
  247. package/dist/navigation/guard-registry.d.ts.map +1 -0
  248. package/dist/navigation/guard-registry.js +46 -0
  249. package/dist/navigation/guard-registry.js.map +1 -0
  250. package/dist/navigation/guarded-navigation.d.ts +24 -0
  251. package/dist/navigation/guarded-navigation.d.ts.map +1 -0
  252. package/dist/navigation/guarded-navigation.js +102 -0
  253. package/dist/navigation/guarded-navigation.js.map +1 -0
  254. package/dist/navigation/index.d.ts +5 -4
  255. package/dist/navigation/index.d.ts.map +1 -1
  256. package/dist/navigation/index.js +2 -1
  257. package/dist/navigation/index.js.map +1 -1
  258. package/dist/navigation/types.d.ts +8 -11
  259. package/dist/navigation/types.d.ts.map +1 -1
  260. package/dist/navigation/use-back-forward-guard.d.ts +12 -0
  261. package/dist/navigation/use-back-forward-guard.d.ts.map +1 -0
  262. package/dist/navigation/use-back-forward-guard.js +75 -0
  263. package/dist/navigation/use-back-forward-guard.js.map +1 -0
  264. package/dist/navigation/use-search-commit.d.ts.map +1 -1
  265. package/dist/navigation/use-search-commit.js.map +1 -1
  266. package/dist/plugin/host-state.d.ts.map +1 -1
  267. package/dist/plugin/host-state.js.map +1 -1
  268. package/dist/plugin/registry.d.ts +6 -15
  269. package/dist/plugin/registry.d.ts.map +1 -1
  270. package/dist/plugin/registry.js +83 -75
  271. package/dist/plugin/registry.js.map +1 -1
  272. package/dist/schema-editor/SchemaEditor.d.ts.map +1 -1
  273. package/dist/schema-editor/SchemaEditor.js.map +1 -1
  274. package/dist/schema-editor/index.d.ts +3 -3
  275. package/dist/schema-editor/index.d.ts.map +1 -1
  276. package/dist/schema-editor/index.js +1 -6
  277. package/dist/schema-editor/index.js.map +1 -1
  278. package/dist/schema-form/SecretRefField.d.ts +18 -3
  279. package/dist/schema-form/SecretRefField.d.ts.map +1 -1
  280. package/dist/schema-form/SecretRefField.js +21 -26
  281. package/dist/schema-form/SecretRefField.js.map +1 -1
  282. package/dist/schema-form/classify.d.ts +1 -113
  283. package/dist/schema-form/classify.d.ts.map +1 -1
  284. package/dist/schema-form/classify.js +174 -246
  285. package/dist/schema-form/classify.js.map +1 -1
  286. package/dist/schema-form/context.d.ts +6 -0
  287. package/dist/schema-form/context.d.ts.map +1 -1
  288. package/dist/schema-form/context.js +0 -6
  289. package/dist/schema-form/context.js.map +1 -1
  290. package/dist/schema-form/default-value.d.ts.map +1 -1
  291. package/dist/schema-form/default-value.js +42 -19
  292. package/dist/schema-form/default-value.js.map +1 -1
  293. package/dist/schema-form/enum-field.d.ts +1 -1
  294. package/dist/schema-form/enum-field.d.ts.map +1 -1
  295. package/dist/schema-form/field-group.d.ts +6 -0
  296. package/dist/schema-form/field-group.d.ts.map +1 -1
  297. package/dist/schema-form/field-group.js +0 -6
  298. package/dist/schema-form/field-group.js.map +1 -1
  299. package/dist/schema-form/field-model.d.ts +121 -0
  300. package/dist/schema-form/field-model.d.ts.map +1 -0
  301. package/dist/schema-form/field-model.js +2 -0
  302. package/dist/schema-form/field-model.js.map +1 -0
  303. package/dist/schema-form/field-node.d.ts.map +1 -1
  304. package/dist/schema-form/field-node.js +25 -14
  305. package/dist/schema-form/field-node.js.map +1 -1
  306. package/dist/schema-form/index.d.ts +8 -8
  307. package/dist/schema-form/index.d.ts.map +1 -1
  308. package/dist/schema-form/index.js +3 -34
  309. package/dist/schema-form/index.js.map +1 -1
  310. package/dist/schema-form/json-field.d.ts +19 -0
  311. package/dist/schema-form/json-field.d.ts.map +1 -1
  312. package/dist/schema-form/json-field.js +0 -19
  313. package/dist/schema-form/json-field.js.map +1 -1
  314. package/dist/schema-form/media-field.d.ts +1 -1
  315. package/dist/schema-form/media-field.d.ts.map +1 -1
  316. package/dist/schema-form/media-field.js +49 -30
  317. package/dist/schema-form/media-field.js.map +1 -1
  318. package/dist/schema-form/record-field.d.ts +12 -0
  319. package/dist/schema-form/record-field.d.ts.map +1 -1
  320. package/dist/schema-form/record-field.js +1 -13
  321. package/dist/schema-form/record-field.js.map +1 -1
  322. package/dist/schema-form/string-annotations.d.ts +20 -0
  323. package/dist/schema-form/string-annotations.d.ts.map +1 -0
  324. package/dist/schema-form/string-annotations.js +105 -0
  325. package/dist/schema-form/string-annotations.js.map +1 -0
  326. package/dist/schema-form/string-field.d.ts +1 -1
  327. package/dist/schema-form/string-field.d.ts.map +1 -1
  328. package/dist/schema-form/string-field.js +1 -1
  329. package/dist/schema-form/string-field.js.map +1 -1
  330. package/dist/schema-form/union-field.d.ts +1 -1
  331. package/dist/schema-form/union-field.d.ts.map +1 -1
  332. package/dist/schema-form/union-field.js.map +1 -1
  333. package/dist/schema-form/union.d.ts +8 -1
  334. package/dist/schema-form/union.d.ts.map +1 -1
  335. package/dist/schema-form/union.js +0 -7
  336. package/dist/schema-form/union.js.map +1 -1
  337. package/dist/schema-form/validate.d.ts.map +1 -1
  338. package/dist/schema-form/validate.js +126 -105
  339. package/dist/schema-form/validate.js.map +1 -1
  340. package/dist/state-binding/AdapterMapping.d.ts.map +1 -1
  341. package/dist/state-binding/AdapterMapping.js +0 -0
  342. package/dist/state-binding/AdapterMapping.js.map +1 -1
  343. package/dist/state-binding/BindingJqField.d.ts.map +1 -1
  344. package/dist/state-binding/BindingJqField.js +2 -2
  345. package/dist/state-binding/BindingJqField.js.map +1 -1
  346. package/dist/state-binding/InputInjectionRow.d.ts.map +1 -1
  347. package/dist/state-binding/InputInjectionRow.js +3 -3
  348. package/dist/state-binding/InputInjectionRow.js.map +1 -1
  349. package/dist/state-binding/StateAttachRow.d.ts.map +1 -1
  350. package/dist/state-binding/StateAttachRow.js +57 -41
  351. package/dist/state-binding/StateAttachRow.js.map +1 -1
  352. package/dist/state-binding/StateBindingSection.d.ts.map +1 -1
  353. package/dist/state-binding/StateBindingSection.js.map +1 -1
  354. package/dist/state-binding/SubjectScopeFields.d.ts.map +1 -1
  355. package/dist/state-binding/SubjectScopeFields.js.map +1 -1
  356. package/dist/state-binding/UpdateRow.d.ts.map +1 -1
  357. package/dist/state-binding/UpdateRow.js +2 -2
  358. package/dist/state-binding/UpdateRow.js.map +1 -1
  359. package/dist/state-binding/adapter-mapping-row.d.ts +17 -0
  360. package/dist/state-binding/adapter-mapping-row.d.ts.map +1 -0
  361. package/dist/state-binding/adapter-mapping-row.js +87 -0
  362. package/dist/state-binding/adapter-mapping-row.js.map +1 -0
  363. package/dist/state-binding/index.d.ts +21 -21
  364. package/dist/state-binding/index.d.ts.map +1 -1
  365. package/dist/state-binding/index.js +9 -15
  366. package/dist/state-binding/index.js.map +1 -1
  367. package/dist/state-binding/templated-text-catalog.d.ts.map +1 -1
  368. package/dist/state-binding/templated-text-catalog.js.map +1 -1
  369. package/dist/state-binding/types.d.ts +2 -2
  370. package/dist/state-binding/types.d.ts.map +1 -1
  371. package/dist/structured-output/StructuredOutput.d.ts.map +1 -1
  372. package/dist/structured-output/StructuredOutput.js +1 -3
  373. package/dist/structured-output/StructuredOutput.js.map +1 -1
  374. package/package.json +2 -2
  375. package/src/components/code-block.tsx +1 -1
  376. package/src/components/confirm-dialog.tsx +1 -1
  377. package/src/components/copy-field.tsx +1 -1
  378. package/src/components/date-range-picker.tsx +1 -1
  379. package/src/components/dialog.tsx +1 -1
  380. package/src/components/dirty-guard.tsx +3 -3
  381. package/src/components/explorer-body.tsx +239 -0
  382. package/src/components/explorer-page-size.ts +39 -0
  383. package/src/components/explorer-tag-filter.tsx +80 -0
  384. package/src/components/explorer-tags.ts +64 -0
  385. package/src/components/explorer-view.tsx +115 -367
  386. package/src/components/extension-combo-builder.tsx +35 -153
  387. package/src/components/extension-combo-parts.tsx +236 -0
  388. package/src/components/field.tsx +1 -1
  389. package/src/components/fleet-report.tsx +98 -55
  390. package/src/components/folder-nav.tsx +2 -2
  391. package/src/components/form-dialog.tsx +2 -2
  392. package/src/components/icons/chrome-marks.tsx +195 -0
  393. package/src/components/icons/icon-frame.tsx +50 -0
  394. package/src/components/icons/index.ts +84 -0
  395. package/src/components/icons/nav-map.ts +55 -0
  396. package/src/components/icons/nav-marks.tsx +205 -0
  397. package/src/components/icons/status-marks.tsx +46 -0
  398. package/src/components/icons/theme-marks.tsx +33 -0
  399. package/src/components/inputs.tsx +1 -1
  400. package/src/components/json-diff.tsx +1 -4
  401. package/src/components/json-tree-context.ts +26 -0
  402. package/src/components/json-tree-model.ts +139 -0
  403. package/src/components/json-tree-nodes.tsx +224 -0
  404. package/src/components/json-tree.tsx +15 -434
  405. package/src/components/json-value-format.ts +64 -0
  406. package/src/components/markdown-blocks.ts +198 -0
  407. package/src/components/markdown-inline.tsx +365 -0
  408. package/src/components/markdown.tsx +6 -472
  409. package/src/components/observer-registry.ts +139 -0
  410. package/src/components/overflow-measure.ts +69 -0
  411. package/src/components/page-fill.tsx +1 -1
  412. package/src/components/prose-regions.ts +153 -0
  413. package/src/components/radio-group.tsx +1 -1
  414. package/src/components/scroll-region.tsx +22 -361
  415. package/src/components/tab-stop-parse.ts +217 -0
  416. package/src/components/table.tsx +1 -1
  417. package/src/components/tags.tsx +2 -2
  418. package/src/components/templated-text-field.tsx +39 -332
  419. package/src/components/templated-text-kwargs-editor.tsx +147 -0
  420. package/src/components/templated-text-kwargs.ts +92 -0
  421. package/src/components/templated-text-source.tsx +226 -0
  422. package/src/components/tool-picker-parts.tsx +184 -0
  423. package/src/components/tool-picker.tsx +22 -114
  424. package/src/components/version-history-panel.tsx +39 -143
  425. package/src/components/version-history-rows.tsx +220 -0
  426. package/src/components/view-toggle.tsx +1 -1
  427. package/src/element-slot.ts +1 -1
  428. package/src/guards.ts +7 -0
  429. package/src/hooks/interactions-connection.ts +227 -0
  430. package/src/hooks/interactions-stream.ts +274 -0
  431. package/src/hooks/useApi.ts +1 -1
  432. package/src/hooks/useAuth.ts +1 -1
  433. package/src/hooks/useCapabilities.ts +3 -3
  434. package/src/hooks/useSse.ts +51 -478
  435. package/src/hooks/useSystemKinds.tsx +2 -2
  436. package/src/hooks/useTheme.ts +1 -1
  437. package/src/hooks/useToolDisplayNames.tsx +2 -2
  438. package/src/host.ts +7 -7
  439. package/src/index.ts +292 -292
  440. package/src/navigation/app-link.tsx +70 -0
  441. package/src/navigation/context.tsx +12 -331
  442. package/src/navigation/entry-state.ts +42 -0
  443. package/src/navigation/guard-registry.ts +65 -0
  444. package/src/navigation/guarded-navigation.ts +147 -0
  445. package/src/navigation/index.ts +14 -14
  446. package/src/navigation/types.ts +8 -11
  447. package/src/navigation/use-back-forward-guard.ts +90 -0
  448. package/src/navigation/use-search-commit.ts +1 -1
  449. package/src/plugin/host-state.ts +1 -1
  450. package/src/plugin/registry.ts +111 -90
  451. package/src/schema-editor/SchemaEditor.tsx +1 -1
  452. package/src/schema-editor/index.ts +3 -3
  453. package/src/schema-form/SecretRefField.tsx +122 -72
  454. package/src/schema-form/classify.ts +245 -396
  455. package/src/schema-form/context.ts +1 -1
  456. package/src/schema-form/default-value.ts +48 -17
  457. package/src/schema-form/enum-field.tsx +1 -1
  458. package/src/schema-form/field-group.tsx +1 -1
  459. package/src/schema-form/field-model.ts +133 -0
  460. package/src/schema-form/field-node.tsx +95 -39
  461. package/src/schema-form/index.ts +10 -10
  462. package/src/schema-form/json-field.tsx +1 -1
  463. package/src/schema-form/media-field.tsx +136 -67
  464. package/src/schema-form/record-field.tsx +2 -2
  465. package/src/schema-form/string-annotations.ts +111 -0
  466. package/src/schema-form/string-field.tsx +2 -2
  467. package/src/schema-form/union-field.tsx +3 -2
  468. package/src/schema-form/union.ts +1 -1
  469. package/src/schema-form/validate.ts +185 -104
  470. package/src/state-binding/AdapterMapping.tsx +0 -0
  471. package/src/state-binding/BindingJqField.tsx +3 -3
  472. package/src/state-binding/InputInjectionRow.tsx +4 -4
  473. package/src/state-binding/StateAttachRow.tsx +229 -154
  474. package/src/state-binding/StateBindingSection.tsx +1 -1
  475. package/src/state-binding/SubjectScopeFields.tsx +1 -1
  476. package/src/state-binding/UpdateRow.tsx +3 -3
  477. package/src/state-binding/adapter-mapping-row.tsx +232 -0
  478. package/src/state-binding/index.ts +43 -43
  479. package/src/state-binding/templated-text-catalog.ts +0 -1
  480. package/src/state-binding/types.ts +2 -2
  481. package/src/structured-output/StructuredOutput.tsx +1 -4
  482. package/dist/components/icons.d.ts +0 -160
  483. package/dist/components/icons.d.ts.map +0 -1
  484. package/dist/components/icons.js +0 -160
  485. package/dist/components/icons.js.map +0 -1
  486. package/src/components/icons.tsx +0 -586
@@ -0,0 +1,69 @@
1
+ /**
2
+ * The overflow measurement and the region-attribute contract: whether a box
3
+ * scrolls right now, and the conditional `tabindex`/`role`/`aria-label` a
4
+ * scrolling box wears. The leaf the React surface and the prose walk both build
5
+ * on; it imports neither of them, which is what breaks the write/measure cycle.
6
+ */
7
+
8
+ export const SCROLL_REGION_CLASS = 'tai-scroll-region';
9
+
10
+ export function overflows(element: HTMLElement): boolean {
11
+ return element.scrollWidth > element.clientWidth;
12
+ }
13
+
14
+ /**
15
+ * Whether the element should carry the region attributes right now.
16
+ *
17
+ * A region that stops overflowing keeps its tab stop for as long as it holds
18
+ * focus: taking `tabindex` off the focused element drops the reader onto the
19
+ * document body, and a window resize is not their doing. Only an element that
20
+ * already has the stop can be the active element, so this can hold a stop open
21
+ * but never invent one.
22
+ */
23
+ export function needsRegion(element: HTMLElement): boolean {
24
+ return overflows(element) || element.ownerDocument.activeElement === element;
25
+ }
26
+
27
+ /** A tracked scrollable surface, with the name it wears while it scrolls. */
28
+ export interface TrackedSurface {
29
+ readonly surface: HTMLElement;
30
+ readonly label: string;
31
+ }
32
+
33
+ /** Strips the region attributes from a surface that is not a region now. */
34
+ export function clearScrollRegionAttributes(wrapper: HTMLElement): void {
35
+ wrapper.removeAttribute('tabindex');
36
+ wrapper.removeAttribute('role');
37
+ wrapper.removeAttribute('aria-label');
38
+ }
39
+
40
+ /** Applies the same conditional attribute set `ScrollRegion` renders. */
41
+ export function applyScrollRegionAttributes(
42
+ wrapper: HTMLElement,
43
+ label: string,
44
+ scrolling: boolean,
45
+ ): void {
46
+ if (!scrolling) {
47
+ clearScrollRegionAttributes(wrapper);
48
+ return;
49
+ }
50
+ wrapper.setAttribute('tabindex', '0');
51
+ wrapper.setAttribute('role', 'region');
52
+ wrapper.setAttribute('aria-label', label);
53
+ }
54
+
55
+ /**
56
+ * Re-applies the region attributes to `tracked`, reading ALL of them before
57
+ * writing any.
58
+ *
59
+ * `needsRegion` reads `scrollWidth`, which forces layout if anything has been
60
+ * written since the last one — so measuring and writing surface by surface makes
61
+ * the browser re-lay-out the prose once per surface, every time. Two phases cost
62
+ * one layout for the whole batch however many surfaces it holds.
63
+ */
64
+ export function refreshRegions(tracked: readonly TrackedSurface[]): void {
65
+ const scrolling = tracked.map((entry) => needsRegion(entry.surface));
66
+ for (const [index, entry] of tracked.entries()) {
67
+ applyScrollRegionAttributes(entry.surface, entry.label, scrolling[index] === true);
68
+ }
69
+ }
@@ -11,7 +11,7 @@
11
11
  * the modifier survives a route transition (old page unmounts after the new one
12
12
  * mounts) and clears exactly when the last fill page leaves.
13
13
  */
14
- import { createContext, useContext, useEffect, useMemo, useState, type ReactNode } from 'react';
14
+ import { createContext, type ReactNode, useContext, useEffect, useMemo, useState } from 'react';
15
15
 
16
16
  /** The registrar a fill page acquires against; each acquire returns its own
17
17
  * one-shot release, so double-release is inert. */
@@ -0,0 +1,153 @@
1
+ /**
2
+ * The prose DOM walk: finding every scrollable `<table>` and `<pre>` inside
3
+ * injected markup, naming each by the heading that precedes it, and disambiguating
4
+ * names a section shares. React never renders these surfaces, so they are located
5
+ * and wrapped imperatively.
6
+ */
7
+ import { SCROLL_REGION_CLASS, type TrackedSurface } from './overflow-measure';
8
+
9
+ /**
10
+ * The names for a prose surface that has no heading above it.
11
+ *
12
+ * They say what the surface IS and nothing about which document it came from,
13
+ * because this walk cannot know: it instruments whatever markup the caller
14
+ * injected. A default that named one document put that document's name on every
15
+ * caller's regions, and a region a reader hears the wrong name for is worse than
16
+ * a plain one.
17
+ */
18
+ export const DEFAULT_PROSE_LABELS = { table: 'Table', pre: 'Code block' } as const;
19
+
20
+ const HEADING_SELECTOR = 'h1, h2, h3, h4, h5, h6';
21
+
22
+ /**
23
+ * Headings AND the surfaces they name, in one selector: a single query returns
24
+ * both interleaved in document order, which is what lets one walk name every
25
+ * surface (see `labelledProseSurfaces`).
26
+ */
27
+ const PROSE_SURFACE_SELECTOR = `${HEADING_SELECTOR}, table, pre`;
28
+
29
+ /**
30
+ * The most surfaces one rendered document is given regions for.
31
+ *
32
+ * The prose is publisher-authored and unbounded in length, and every region is
33
+ * an entry in the landmark list a screen-reader user navigates the page by: a
34
+ * README with more surfaces than this turns that list into the very thing the
35
+ * regions exist to spare a reader. Past the cap a table still gets its scrolling
36
+ * wrapper — the wrapper is what keeps it inside the column — but no name and no
37
+ * tab stop, so the landmark list stays a list a person can read.
38
+ */
39
+ export const MAX_PROSE_REGIONS = 200;
40
+
41
+ /**
42
+ * The wrapper a prose table sits inside, creating it on first pass. Idempotent:
43
+ * a table already inside a `.tai-scroll-region` keeps the wrapper it has.
44
+ */
45
+ export function ensureScrollWrapper(table: HTMLTableElement): HTMLElement {
46
+ const parent = table.parentElement;
47
+ if (parent?.classList.contains(SCROLL_REGION_CLASS) === true) return parent;
48
+ const wrapper = table.ownerDocument.createElement('div');
49
+ wrapper.className = SCROLL_REGION_CLASS;
50
+ table.replaceWith(wrapper);
51
+ wrapper.append(table);
52
+ return wrapper;
53
+ }
54
+
55
+ /** A heading that can name the surfaces below it, and the text it would give. */
56
+ interface ProseHeading {
57
+ readonly element: Element;
58
+ readonly text: string;
59
+ }
60
+
61
+ /** A scrollable prose surface, with the heading text that names it. */
62
+ interface LabelledProseSurface {
63
+ readonly element: HTMLElement;
64
+ readonly heading: string | undefined;
65
+ }
66
+
67
+ /**
68
+ * The text of the last heading in `headings` that does not ENCLOSE `surface`.
69
+ *
70
+ * A heading wrapping the surface does precede it in document order, but it is
71
+ * not a section the surface sits UNDER, so it is stepped over in favour of the
72
+ * heading before it — which is the answer an outward walk from the surface
73
+ * reaches. In well-formed prose no heading contains a table or a code block, so
74
+ * this returns the last heading on the first look.
75
+ */
76
+ function namingHeadingText(
77
+ headings: readonly ProseHeading[],
78
+ surface: Element,
79
+ ): string | undefined {
80
+ for (let index = headings.length - 1; index >= 0; index -= 1) {
81
+ const heading = headings[index];
82
+ if (heading !== undefined && !heading.element.contains(surface)) return heading.text;
83
+ }
84
+ return undefined;
85
+ }
86
+
87
+ /**
88
+ * Every scrollable prose surface under `root` — each `<table>` and each `<pre>`
89
+ * — paired with the text of the nearest heading PRECEDING it, or `undefined`
90
+ * when no heading does.
91
+ *
92
+ * One query returns the headings and the surfaces interleaved in document order,
93
+ * so a single walk over that list names all of them: the heading a surface
94
+ * belongs to is the last one seen before reaching it. Naming each surface by
95
+ * searching backwards from it instead would re-read the same prose once per
96
+ * surface, at a cost that grows with the product of the two.
97
+ *
98
+ * Blank headings never enter the list, so a decorative empty heading names
99
+ * nothing and the section above it is used instead. A heading INSIDE a surface
100
+ * (a `<pre>` or a table cell holding one) comes AFTER that surface in document
101
+ * order and so can never name it, though it does name later surfaces — exactly
102
+ * as being the last heading before them implies.
103
+ *
104
+ * Read in full before the pass wraps anything, and safely so: a name depends
105
+ * only on what PRECEDES its surface, and `ensureScrollWrapper` puts the wrapper
106
+ * in the table's own place, moving nothing else and leaving every heading where
107
+ * it was — so a name stays true whether its table is wrapped yet or not.
108
+ */
109
+ export function labelledProseSurfaces(root: Element): LabelledProseSurface[] {
110
+ const headings: ProseHeading[] = [];
111
+ const surfaces: LabelledProseSurface[] = [];
112
+
113
+ for (const node of root.querySelectorAll<HTMLElement>(PROSE_SURFACE_SELECTOR)) {
114
+ if (node.matches(HEADING_SELECTOR)) {
115
+ // textContent is nullable under strict DOM typings; the local eslint
116
+ // profile assumes non-null, so the necessary guard trips its rule.
117
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
118
+ const text = (node.textContent ?? '').trim();
119
+ if (text !== '') headings.push({ element: node, text });
120
+ continue;
121
+ }
122
+ surfaces.push({ element: node, heading: namingHeadingText(headings, node) });
123
+ }
124
+ return surfaces;
125
+ }
126
+
127
+ /** A prose surface's scrolling box and the name it would take on its own. */
128
+ interface ProseSurfaceBox {
129
+ readonly surface: HTMLElement;
130
+ readonly name: string;
131
+ }
132
+
133
+ /**
134
+ * The same surfaces, each given a name no other one in the list carries.
135
+ *
136
+ * A name is only as useful as it is distinguishing, and one heading names every
137
+ * surface under it: two wide tables in one section, or two code blocks under no
138
+ * heading at all, would otherwise be two landmarks a reader hears identically
139
+ * and cannot choose between. A name more than one surface claims is therefore
140
+ * numbered, in document order, and a name only one surface claims is left alone.
141
+ */
142
+ export function uniquelyNamed(boxes: readonly ProseSurfaceBox[]): TrackedSurface[] {
143
+ const claims = new Map<string, number>();
144
+ for (const { name } of boxes) claims.set(name, (claims.get(name) ?? 0) + 1);
145
+
146
+ const taken = new Map<string, number>();
147
+ return boxes.map(({ surface, name }) => {
148
+ if (claims.get(name) === 1) return { surface, label: name };
149
+ const ordinal = (taken.get(name) ?? 0) + 1;
150
+ taken.set(name, ordinal);
151
+ return { surface, label: `${name} (${String(ordinal)})` };
152
+ });
153
+ }
@@ -22,8 +22,8 @@
22
22
  * rather than being pinned to one.
23
23
  */
24
24
  import * as RadixRadioGroup from '@radix-ui/react-radio-group';
25
- import { useId } from 'react';
26
25
  import type { ReactNode } from 'react';
26
+ import { useId } from 'react';
27
27
 
28
28
  import { useFieldControl } from './field';
29
29
 
@@ -22,8 +22,29 @@
22
22
  * mounts later than the hook (a README that arrives with the second render) and
23
23
  * would never notice one being swapped for another.
24
24
  */
25
- import { useCallback, useState } from 'react';
26
25
  import type { CSSProperties, ReactNode, Ref, RefCallback } from 'react';
26
+ import { useCallback, useState } from 'react';
27
+
28
+ import {
29
+ holdContentTarget,
30
+ holdResizeTarget,
31
+ releaseContentTarget,
32
+ releaseResizeTarget,
33
+ } from './observer-registry';
34
+ import {
35
+ clearScrollRegionAttributes,
36
+ needsRegion,
37
+ refreshRegions,
38
+ SCROLL_REGION_CLASS,
39
+ type TrackedSurface,
40
+ } from './overflow-measure';
41
+ import {
42
+ DEFAULT_PROSE_LABELS,
43
+ ensureScrollWrapper,
44
+ labelledProseSurfaces,
45
+ MAX_PROSE_REGIONS,
46
+ uniquelyNamed,
47
+ } from './prose-regions';
27
48
 
28
49
  export interface ScrollRegionProps {
29
50
  /** The region's accessible name, applied only while it actually scrolls. */
@@ -43,65 +64,12 @@ export interface ScrollRegionProps {
43
64
  readonly ref?: Ref<HTMLDivElement>;
44
65
  }
45
66
 
46
- /**
47
- * The names for a prose surface that has no heading above it.
48
- *
49
- * They say what the surface IS and nothing about which document it came from,
50
- * because this hook cannot know: it instruments whatever markup the caller
51
- * injected. A default that named one document put that document's name on every
52
- * caller's regions, and a region a reader hears the wrong name for is worse than
53
- * a plain one. A caller that CAN say which document it is showing passes its own
54
- * `labels`; a surface with a heading above it takes that heading instead, which
55
- * is the usual case.
56
- */
57
- const DEFAULT_PROSE_LABELS = { table: 'Table', pre: 'Code block' } as const;
58
-
59
67
  /** The fallback name per instrumented surface, when no heading precedes it. */
60
68
  export interface ProseScrollLabels {
61
69
  readonly table?: string;
62
70
  readonly pre?: string;
63
71
  }
64
72
 
65
- const HEADING_SELECTOR = 'h1, h2, h3, h4, h5, h6';
66
-
67
- /**
68
- * Headings AND the surfaces they name, in one selector: a single query returns
69
- * both interleaved in document order, which is what lets one walk name every
70
- * surface (see `labelledProseSurfaces`).
71
- */
72
- const PROSE_SURFACE_SELECTOR = `${HEADING_SELECTOR}, table, pre`;
73
-
74
- const SCROLL_REGION_CLASS = 'tai-scroll-region';
75
-
76
- /**
77
- * The most surfaces one rendered document is given regions for.
78
- *
79
- * The prose is publisher-authored and unbounded in length, and every region is
80
- * an entry in the landmark list a screen-reader user navigates the page by: a
81
- * README with more surfaces than this turns that list into the very thing the
82
- * regions exist to spare a reader. Past the cap a table still gets its scrolling
83
- * wrapper — the wrapper is what keeps it inside the column — but no name and no
84
- * tab stop, so the landmark list stays a list a person can read.
85
- */
86
- const MAX_PROSE_REGIONS = 200;
87
-
88
- function overflows(element: HTMLElement): boolean {
89
- return element.scrollWidth > element.clientWidth;
90
- }
91
-
92
- /**
93
- * Whether the element should carry the region attributes right now.
94
- *
95
- * A region that stops overflowing keeps its tab stop for as long as it holds
96
- * focus: taking `tabindex` off the focused element drops the reader onto the
97
- * document body, and a window resize is not their doing. Only an element that
98
- * already has the stop can be the active element, so this can hold a stop open
99
- * but never invent one.
100
- */
101
- function needsRegion(element: HTMLElement): boolean {
102
- return overflows(element) || element.ownerDocument.activeElement === element;
103
- }
104
-
105
73
  /**
106
74
  * Attaches `element` to a consumer ref of either form, and returns the detach
107
75
  * for it. A callback ref that answers with its own cleanup gets that cleanup
@@ -123,155 +91,6 @@ function attachRef(ref: Ref<HTMLElement> | undefined, element: HTMLElement): ()
123
91
  };
124
92
  }
125
93
 
126
- /**
127
- * ONE `ResizeObserver` and ONE `MutationObserver` for every scrolling box in the
128
- * document, rather than a pair per mount.
129
- *
130
- * `useOverflowRegion` is per-INSTANCE — a timeline renders two `CodeBlock`s per
131
- * tool call and windows none of them — so an observer per mount grows with the
132
- * content, and each one is a separate callback the browser schedules and a
133
- * separate registration it maintains. One observer of each kind costs one of
134
- * each however many boxes are on screen, and each callback still only measures
135
- * the boxes whose records it was handed. (`useProseScrollRegions` keeps its own
136
- * pair: there is one of it per rendered document, not one per surface, and its
137
- * callbacks drive DOM writes rather than a React state setter.)
138
- *
139
- * Created on first use, because the module is imported in environments that have
140
- * no `ResizeObserver` at all until a test installs one.
141
- */
142
- type ResizeHandler = () => void;
143
-
144
- /**
145
- * The handlers waiting on each observed element. A SET, not a single handler:
146
- * one element can be both a box and another box's child — a `<pre>` inside a
147
- * `ScrollRegion` is exactly that — and both owners must still hear its resize.
148
- */
149
- const resizeHandlers = new WeakMap<Element, Set<ResizeHandler>>();
150
- let sharedResize: ResizeObserver | undefined;
151
-
152
- function sharedResizeObserver(): ResizeObserver {
153
- sharedResize ??= new ResizeObserver((entries) => {
154
- // A box and its children are observed separately, so one frame can deliver
155
- // several entries owned by the same handler; measuring once is enough.
156
- const fired = new Set<ResizeHandler>();
157
- for (const entry of entries) {
158
- for (const handler of resizeHandlers.get(entry.target) ?? []) fired.add(handler);
159
- }
160
- for (const handler of fired) handler();
161
- });
162
- return sharedResize;
163
- }
164
-
165
- /**
166
- * Registers `handler` for `target`'s resizes, observing the element only the
167
- * first time anyone asks for it: re-observing an element already under a
168
- * `ResizeObserver` re-arms its initial notification, which spends a forced
169
- * layout on a measurement nobody asked for.
170
- */
171
- function holdResizeTarget(target: Element, handler: ResizeHandler): void {
172
- const handlers = resizeHandlers.get(target);
173
- if (handlers !== undefined) {
174
- handlers.add(handler);
175
- return;
176
- }
177
- // Registered before the element is observed, so the initial notification the
178
- // observation arms reaches the handler that asked for it.
179
- resizeHandlers.set(target, new Set<ResizeHandler>([handler]));
180
- sharedResizeObserver().observe(target);
181
- }
182
-
183
- /** Stops observing `target` for `handler`, and entirely once nobody wants it. */
184
- function releaseResizeTarget(target: Element, handler: ResizeHandler): void {
185
- const handlers = resizeHandlers.get(target);
186
- if (handlers === undefined) return;
187
- handlers.delete(handler);
188
- if (handlers.size > 0) return;
189
- resizeHandlers.delete(target);
190
- sharedResizeObserver().unobserve(target);
191
- }
192
-
193
- /** What a box wants to hear about: its content replaced, appended or edited. */
194
- const CONTENT_OBSERVER_INIT: MutationObserverInit = {
195
- childList: true,
196
- subtree: true,
197
- characterData: true,
198
- };
199
-
200
- type ContentHandler = () => void;
201
-
202
- /**
203
- * The handlers waiting on each observed box, and the boxes the shared observer
204
- * currently holds. Keyed by `Node` because a `characterData` record names the
205
- * TEXT node that changed, and the walk to the box that owns it goes through
206
- * whatever nodes lie between.
207
- */
208
- const contentHandlers = new WeakMap<Node, Set<ContentHandler>>();
209
- const contentTargets = new Set<Element>();
210
- let sharedContent: MutationObserver | undefined;
211
- /** Registrations the shared observer still holds for released boxes. */
212
- let staleContentTargets = 0;
213
-
214
- function deliverContentRecords(records: readonly MutationRecord[]): void {
215
- const fired = new Set<ContentHandler>();
216
- for (const record of records) {
217
- // A `childList` record names the changed parent and a `characterData` record
218
- // the text node itself, either of them at any depth under a box. Every box
219
- // on the ancestor chain therefore owns the change, exactly as a separate
220
- // observer on each of them would have seen it — a `<pre>` inside a
221
- // `ScrollRegion` measures both.
222
- for (let node: Node | null = record.target; node !== null; node = node.parentNode) {
223
- for (const handler of contentHandlers.get(node) ?? []) fired.add(handler);
224
- }
225
- }
226
- for (const handler of fired) handler();
227
- }
228
-
229
- function sharedContentObserver(): MutationObserver {
230
- sharedContent ??= new MutationObserver(deliverContentRecords);
231
- return sharedContent;
232
- }
233
-
234
- function holdContentTarget(target: Element, handler: ContentHandler): void {
235
- let handlers = contentHandlers.get(target);
236
- if (handlers === undefined) {
237
- handlers = new Set<ContentHandler>();
238
- contentHandlers.set(target, handlers);
239
- contentTargets.add(target);
240
- sharedContentObserver().observe(target, CONTENT_OBSERVER_INIT);
241
- }
242
- handlers.add(handler);
243
- }
244
-
245
- /**
246
- * Stops watching `target`'s content for `handler`.
247
- *
248
- * `MutationObserver` has no `unobserve`: the only way to drop one registration
249
- * is to disconnect the observer and re-observe everything else, which would cost
250
- * one registration per surviving box every time a box unmounts. A released box
251
- * is therefore dropped from the handler map at once — its records find no
252
- * handler and are ignored — and the observer is rebuilt only once the dead
253
- * registrations outnumber the live ones, which keeps the total registration work
254
- * proportional to the number of mounts. Records already queued survive the
255
- * rebuild: they are taken off the observer and delivered by hand.
256
- */
257
- function releaseContentTarget(target: Element, handler: ContentHandler): void {
258
- const handlers = contentHandlers.get(target);
259
- if (handlers === undefined) return;
260
- handlers.delete(handler);
261
- if (handlers.size > 0) return;
262
- contentHandlers.delete(target);
263
- contentTargets.delete(target);
264
- staleContentTargets += 1;
265
- if (staleContentTargets <= contentTargets.size) return;
266
-
267
- const observer = sharedContentObserver();
268
- const queued = observer.takeRecords();
269
- observer.disconnect();
270
- staleContentTargets = 0;
271
- for (const live of contentTargets) observer.observe(live, CONTENT_OBSERVER_INIT);
272
- if (queued.length > 0) deliverContentRecords(queued);
273
- }
274
-
275
94
  /** The attribute set a scrolling box wears; every value is absent while it fits. */
276
95
  export interface OverflowRegionAttributes {
277
96
  /** Attach to the scrolling element; it is what the measurement follows. */
@@ -389,164 +208,6 @@ export function ScrollRegion({
389
208
  );
390
209
  }
391
210
 
392
- /**
393
- * The wrapper a prose table sits inside, creating it on first pass. Idempotent:
394
- * a table already inside a `.tai-scroll-region` keeps the wrapper it has.
395
- */
396
- function ensureScrollWrapper(table: HTMLTableElement): HTMLElement {
397
- const parent = table.parentElement;
398
- if (parent?.classList.contains(SCROLL_REGION_CLASS) === true) return parent;
399
- const wrapper = table.ownerDocument.createElement('div');
400
- wrapper.className = SCROLL_REGION_CLASS;
401
- table.replaceWith(wrapper);
402
- wrapper.append(table);
403
- return wrapper;
404
- }
405
-
406
- /** A heading that can name the surfaces below it, and the text it would give. */
407
- interface ProseHeading {
408
- readonly element: Element;
409
- readonly text: string;
410
- }
411
-
412
- /** A scrollable prose surface, with the heading text that names it. */
413
- interface LabelledProseSurface {
414
- readonly element: HTMLElement;
415
- readonly heading: string | undefined;
416
- }
417
-
418
- /**
419
- * The text of the last heading in `headings` that does not ENCLOSE `surface`.
420
- *
421
- * A heading wrapping the surface does precede it in document order, but it is
422
- * not a section the surface sits UNDER, so it is stepped over in favour of the
423
- * heading before it — which is the answer an outward walk from the surface
424
- * reaches. In well-formed prose no heading contains a table or a code block, so
425
- * this returns the last heading on the first look.
426
- */
427
- function namingHeadingText(
428
- headings: readonly ProseHeading[],
429
- surface: Element,
430
- ): string | undefined {
431
- for (let index = headings.length - 1; index >= 0; index -= 1) {
432
- const heading = headings[index];
433
- if (heading !== undefined && !heading.element.contains(surface)) return heading.text;
434
- }
435
- return undefined;
436
- }
437
-
438
- /**
439
- * Every scrollable prose surface under `root` — each `<table>` and each `<pre>`
440
- * — paired with the text of the nearest heading PRECEDING it, or `undefined`
441
- * when no heading does.
442
- *
443
- * One query returns the headings and the surfaces interleaved in document order,
444
- * so a single walk over that list names all of them: the heading a surface
445
- * belongs to is the last one seen before reaching it. Naming each surface by
446
- * searching backwards from it instead would re-read the same prose once per
447
- * surface, at a cost that grows with the product of the two.
448
- *
449
- * Blank headings never enter the list, so a decorative empty heading names
450
- * nothing and the section above it is used instead. A heading INSIDE a surface
451
- * (a `<pre>` or a table cell holding one) comes AFTER that surface in document
452
- * order and so can never name it, though it does name later surfaces — exactly
453
- * as being the last heading before them implies.
454
- *
455
- * Read in full before the pass wraps anything, and safely so: a name depends
456
- * only on what PRECEDES its surface, and `ensureScrollWrapper` puts the wrapper
457
- * in the table's own place, moving nothing else and leaving every heading where
458
- * it was — so a name stays true whether its table is wrapped yet or not.
459
- */
460
- function labelledProseSurfaces(root: Element): LabelledProseSurface[] {
461
- const headings: ProseHeading[] = [];
462
- const surfaces: LabelledProseSurface[] = [];
463
-
464
- for (const node of root.querySelectorAll<HTMLElement>(PROSE_SURFACE_SELECTOR)) {
465
- if (node.matches(HEADING_SELECTOR)) {
466
- // textContent is nullable under strict DOM typings; the local eslint
467
- // profile assumes non-null, so the necessary guard trips its rule.
468
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
469
- const text = (node.textContent ?? '').trim();
470
- if (text !== '') headings.push({ element: node, text });
471
- continue;
472
- }
473
- surfaces.push({ element: node, heading: namingHeadingText(headings, node) });
474
- }
475
- return surfaces;
476
- }
477
-
478
- /** An instrumented prose surface, with the name it wears while it scrolls. */
479
- interface TrackedSurface {
480
- readonly surface: HTMLElement;
481
- readonly label: string;
482
- }
483
-
484
- /** A prose surface's scrolling box and the name it would take on its own. */
485
- interface ProseSurfaceBox {
486
- readonly surface: HTMLElement;
487
- readonly name: string;
488
- }
489
-
490
- /**
491
- * The same surfaces, each given a name no other one in the list carries.
492
- *
493
- * A name is only as useful as it is distinguishing, and one heading names every
494
- * surface under it: two wide tables in one section, or two code blocks under no
495
- * heading at all, would otherwise be two landmarks a reader hears identically
496
- * and cannot choose between. A name more than one surface claims is therefore
497
- * numbered, in document order, and a name only one surface claims is left alone.
498
- */
499
- function uniquelyNamed(boxes: readonly ProseSurfaceBox[]): TrackedSurface[] {
500
- const claims = new Map<string, number>();
501
- for (const { name } of boxes) claims.set(name, (claims.get(name) ?? 0) + 1);
502
-
503
- const taken = new Map<string, number>();
504
- return boxes.map(({ surface, name }) => {
505
- if (claims.get(name) === 1) return { surface, label: name };
506
- const ordinal = (taken.get(name) ?? 0) + 1;
507
- taken.set(name, ordinal);
508
- return { surface, label: `${name} (${String(ordinal)})` };
509
- });
510
- }
511
-
512
- /** Strips the region attributes from a surface that is not a region now. */
513
- function clearScrollRegionAttributes(wrapper: HTMLElement): void {
514
- wrapper.removeAttribute('tabindex');
515
- wrapper.removeAttribute('role');
516
- wrapper.removeAttribute('aria-label');
517
- }
518
-
519
- /** Applies the same conditional attribute set `ScrollRegion` renders. */
520
- function applyScrollRegionAttributes(
521
- wrapper: HTMLElement,
522
- label: string,
523
- scrolling: boolean,
524
- ): void {
525
- if (!scrolling) {
526
- clearScrollRegionAttributes(wrapper);
527
- return;
528
- }
529
- wrapper.setAttribute('tabindex', '0');
530
- wrapper.setAttribute('role', 'region');
531
- wrapper.setAttribute('aria-label', label);
532
- }
533
-
534
- /**
535
- * Re-applies the region attributes to `tracked`, reading ALL of them before
536
- * writing any.
537
- *
538
- * `needsRegion` reads `scrollWidth`, which forces layout if anything has been
539
- * written since the last one — so measuring and writing surface by surface makes
540
- * the browser re-lay-out the prose once per surface, every time. Two phases cost
541
- * one layout for the whole batch however many surfaces it holds.
542
- */
543
- function refreshRegions(tracked: readonly TrackedSurface[]): void {
544
- const scrolling = tracked.map((entry) => needsRegion(entry.surface));
545
- for (const [index, entry] of tracked.entries()) {
546
- applyScrollRegionAttributes(entry.surface, entry.label, scrolling[index] === true);
547
- }
548
- }
549
-
550
211
  /**
551
212
  * Instruments the scrollable surfaces under the element the returned ref is
552
213
  * attached to — every `<table>` and every `<pre>` — as scroll regions. React