@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,198 @@
1
+ /**
2
+ * The block grammar for `Markdown`: folds markdown source into an ordered list of
3
+ * blocks. Pure and total — any string parses, and text that matches no block
4
+ * construct becomes a paragraph rather than being discarded.
5
+ */
6
+
7
+ /** The heading levels ATX syntax can express, `#` through `######`. */
8
+ export type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
9
+
10
+ /** A parsed block. Inline markup inside `text` is resolved at render time. */
11
+ export type MarkdownBlock =
12
+ | { readonly type: 'heading'; readonly level: HeadingLevel; readonly text: string }
13
+ | { readonly type: 'paragraph'; readonly text: string }
14
+ | { readonly type: 'code'; readonly language: string | undefined; readonly code: string }
15
+ | {
16
+ readonly type: 'list';
17
+ readonly ordered: boolean;
18
+ readonly items: readonly string[];
19
+ /** The first item's number on an ordered list, so the render can offset `<ol start>`. */
20
+ readonly start?: number;
21
+ }
22
+ | { readonly type: 'blockquote'; readonly children: readonly MarkdownBlock[] }
23
+ | { readonly type: 'thematicBreak' };
24
+
25
+ const BLANK = /^[ \t]*$/;
26
+ /** A fence opener: three-or-more backticks or tildes, then an info string. */
27
+ const FENCE_OPEN = /^[ \t]{0,3}(`{3,}|~{3,})[ \t]*(.*)$/;
28
+ /**
29
+ * An ATX heading: 1–6 hashes, a required space, then text. A closing hash run is
30
+ * stripped only when whitespace separates it from the content, so `# C#` keeps
31
+ * its literal `C#`.
32
+ */
33
+ const HEADING = /^[ \t]{0,3}(#{1,6})[ \t]+(.*?)(?:[ \t]+#+)?[ \t]*$/;
34
+ /** A thematic break: three-or-more `-`, `*` or `_`, spaces allowed between. */
35
+ const THEMATIC_BREAK = /^[ \t]{0,3}([-*_])(?:[ \t]*\1){2,}[ \t]*$/;
36
+ /** A blockquote line: a `>` marker and its (optionally space-prefixed) content. */
37
+ const BLOCKQUOTE = /^[ \t]{0,3}>[ \t]?(.*)$/;
38
+ /** An unordered list item: a `-`, `*` or `+` bullet, a space, then content. */
39
+ const UNORDERED_ITEM = /^[ \t]*[-*+][ \t]+(.*)$/;
40
+ /** An ordered list item: a start number, a `.` or `)` delimiter, a space, then content. */
41
+ const ORDERED_ITEM = /^[ \t]*(\d{1,9})[.)][ \t]+(.*)$/;
42
+
43
+ /** True when a line starts a block that interrupts an open paragraph. */
44
+ function startsBlock(line: string): boolean {
45
+ return (
46
+ FENCE_OPEN.test(line) ||
47
+ HEADING.test(line) ||
48
+ THEMATIC_BREAK.test(line) ||
49
+ BLOCKQUOTE.test(line) ||
50
+ UNORDERED_ITEM.test(line) ||
51
+ ORDERED_ITEM.test(line)
52
+ );
53
+ }
54
+
55
+ /**
56
+ * The `closer` for an open fence: the same marker character, at least as long as
57
+ * the opener, alone on its line. A source that never closes its fence takes the
58
+ * rest of the document as code — the same run-to-end rule CommonMark applies —
59
+ * rather than silently dropping the block.
60
+ */
61
+ function fenceCloser(marker: string): RegExp {
62
+ const char = marker.startsWith('`') ? '`' : '~';
63
+ return new RegExp(`^[ \\t]{0,3}${char}{${String(marker.length)},}[ \\t]*$`);
64
+ }
65
+
66
+ /** One parsed block and the line index the parse advanced past. */
67
+ interface ParseStep {
68
+ readonly block: MarkdownBlock;
69
+ readonly next: number;
70
+ }
71
+
72
+ /** A fenced code block; runs to its closing fence or the end of the document. */
73
+ function parseFence(lines: readonly string[], i: number): ParseStep | null {
74
+ const fence = FENCE_OPEN.exec(lines[i] ?? '');
75
+ if (fence === null) return null;
76
+ const closer = fenceCloser(fence[1] ?? '');
77
+ const info = (fence[2] ?? '').trim();
78
+ const body: string[] = [];
79
+ let j = i + 1;
80
+ for (; j < lines.length; j += 1) {
81
+ const next = lines[j] ?? '';
82
+ if (closer.test(next)) break;
83
+ body.push(next);
84
+ }
85
+ // Step past the closing fence when one is present; at end-of-document there is
86
+ // nothing to step past.
87
+ if (j < lines.length) j += 1;
88
+ return {
89
+ block: { type: 'code', language: info.length > 0 ? info : undefined, code: body.join('\n') },
90
+ next: j,
91
+ };
92
+ }
93
+
94
+ /** An ATX heading on a single line. */
95
+ function parseHeading(lines: readonly string[], i: number): ParseStep | null {
96
+ const heading = HEADING.exec(lines[i] ?? '');
97
+ if (heading === null) return null;
98
+ return {
99
+ block: {
100
+ type: 'heading',
101
+ level: (heading[1] ?? '').length as HeadingLevel,
102
+ text: heading[2] ?? '',
103
+ },
104
+ next: i + 1,
105
+ };
106
+ }
107
+
108
+ /** A thematic break on a single line. */
109
+ function parseThematicBreak(lines: readonly string[], i: number): ParseStep | null {
110
+ if (!THEMATIC_BREAK.test(lines[i] ?? '')) return null;
111
+ return { block: { type: 'thematicBreak' }, next: i + 1 };
112
+ }
113
+
114
+ /** A blockquote: the run of `>`-marked lines, parsed recursively as its own blocks. */
115
+ function parseBlockquote(lines: readonly string[], i: number): ParseStep | null {
116
+ if (!BLOCKQUOTE.test(lines[i] ?? '')) return null;
117
+ const inner: string[] = [];
118
+ let j = i;
119
+ for (; j < lines.length; j += 1) {
120
+ const quoted = BLOCKQUOTE.exec(lines[j] ?? '');
121
+ if (quoted === null) break;
122
+ inner.push(quoted[1] ?? '');
123
+ }
124
+ return { block: { type: 'blockquote', children: parseBlocks(inner) }, next: j };
125
+ }
126
+
127
+ /** An ordered or unordered list: the run of item lines sharing the leading marker. */
128
+ function parseList(lines: readonly string[], i: number): ParseStep | null {
129
+ const line = lines[i] ?? '';
130
+ const unordered = UNORDERED_ITEM.exec(line);
131
+ const ordered = unordered === null ? ORDERED_ITEM.exec(line) : null;
132
+ if (unordered === null && ordered === null) return null;
133
+ const pattern = ordered !== null ? ORDERED_ITEM : UNORDERED_ITEM;
134
+ // An ordered item's content is its second group, behind the start number; an
135
+ // unordered item's content is its first.
136
+ const textGroup = ordered !== null ? 2 : 1;
137
+ const items: string[] = [];
138
+ let j = i;
139
+ for (; j < lines.length; j += 1) {
140
+ const item = pattern.exec(lines[j] ?? '');
141
+ if (item === null) break;
142
+ items.push(item[textGroup] ?? '');
143
+ }
144
+ const block: MarkdownBlock =
145
+ ordered !== null
146
+ ? { type: 'list', ordered: true, items, start: Number(ordered[1] ?? '1') }
147
+ : { type: 'list', ordered: false, items };
148
+ return { block, next: j };
149
+ }
150
+
151
+ /**
152
+ * A paragraph: this line and the following lines up to a blank line or the start
153
+ * of another block. The total fallback — always succeeds. Soft line breaks are
154
+ * kept as newlines.
155
+ */
156
+ function parseParagraph(lines: readonly string[], i: number): ParseStep {
157
+ const paragraph: string[] = [lines[i] ?? ''];
158
+ let j = i + 1;
159
+ for (; j < lines.length; j += 1) {
160
+ const next = lines[j] ?? '';
161
+ if (BLANK.test(next) || startsBlock(next)) break;
162
+ paragraph.push(next);
163
+ }
164
+ return { block: { type: 'paragraph', text: paragraph.join('\n') }, next: j };
165
+ }
166
+
167
+ function parseBlocks(lines: readonly string[]): MarkdownBlock[] {
168
+ const blocks: MarkdownBlock[] = [];
169
+ let i = 0;
170
+
171
+ while (i < lines.length) {
172
+ if (BLANK.test(lines[i] ?? '')) {
173
+ i += 1;
174
+ continue;
175
+ }
176
+ const step =
177
+ parseFence(lines, i) ??
178
+ parseHeading(lines, i) ??
179
+ parseThematicBreak(lines, i) ??
180
+ parseBlockquote(lines, i) ??
181
+ parseList(lines, i) ??
182
+ parseParagraph(lines, i);
183
+ blocks.push(step.block);
184
+ i = step.next;
185
+ }
186
+
187
+ return blocks;
188
+ }
189
+
190
+ /**
191
+ * Folds markdown source into an ordered list of blocks. Pure and total: any
192
+ * string parses, and text that matches no block construct becomes a paragraph
193
+ * rather than being discarded.
194
+ */
195
+ export function parseMarkdown(markdown: string): MarkdownBlock[] {
196
+ const lines = markdown.replace(/\r\n?/g, '\n').split('\n');
197
+ return parseBlocks(lines);
198
+ }
@@ -0,0 +1,365 @@
1
+ /**
2
+ * The inline grammar for `Markdown`: locating code spans, links, images, strong
3
+ * and emphasis runs, and resolving them to escaped React nodes. A single
4
+ * forward-only cursor keeps the pass linear; a link is admitted only when
5
+ * `safeHttpUrl` accepts it, and an image contributes its `alt` text alone.
6
+ */
7
+ import type { ReactNode } from 'react';
8
+
9
+ import { safeHttpUrl } from './primitives';
10
+
11
+ // Single-character predicates, so the `\S` and `\w` classes decide flanking
12
+ // exactly — a non-breaking space is whitespace, an underscore a word character —
13
+ // rather than an open-coded space test getting those edges wrong.
14
+ const NON_SPACE = /\S/;
15
+ const WORD = /\w/;
16
+
17
+ /** Inline code: a run of backticks and its literal, unparsed content, on one line. */
18
+ const CODE_SPAN = /`([^`\n]+)`/g;
19
+
20
+ // Emphasis runs carry CommonMark flanking: the opening marker must be followed by
21
+ // a non-space and the closing marker preceded by a non-space, so spaced prose like
22
+ // `w * h * d` is left literal. An `_` marker is additionally barred from touching a
23
+ // word character on its outer side, so intraword underscores (`user_id_field`,
24
+ // `a__proto__b`) never open or close a run; `*` keeps working everywhere.
25
+
26
+ /** A resolved emphasis or strong run: where it sits and the text between its markers. */
27
+ interface EmphasisSpan {
28
+ readonly index: number;
29
+ readonly length: number;
30
+ readonly content: string;
31
+ }
32
+
33
+ /**
34
+ * Whether the marker ending at `j` closes the pending `opener`: at least one body
35
+ * character in, preceded by a non-space (and, for `_`, not followed by a word
36
+ * character on its outer edge).
37
+ */
38
+ function isEmphasisCloser(
39
+ text: string,
40
+ j: number,
41
+ opener: number,
42
+ m: number,
43
+ underscore: boolean,
44
+ ): boolean {
45
+ return (
46
+ opener !== -1 &&
47
+ j >= opener + m + 1 &&
48
+ NON_SPACE.test(text[j - 1] ?? '') &&
49
+ (!underscore || j + m >= text.length || !WORD.test(text[j + m] ?? ''))
50
+ );
51
+ }
52
+
53
+ /**
54
+ * Whether the marker at `j` opens a run: no opener pending, followed by a
55
+ * non-space (and, for `_`, not abutting a word character on its left).
56
+ */
57
+ function isEmphasisOpener(
58
+ text: string,
59
+ j: number,
60
+ opener: number,
61
+ m: number,
62
+ underscore: boolean,
63
+ ): boolean {
64
+ return (
65
+ opener === -1 &&
66
+ j + m < text.length &&
67
+ NON_SPACE.test(text[j + m] ?? '') &&
68
+ (!underscore || j === 0 || !WORD.test(text[j - 1] ?? ''))
69
+ );
70
+ }
71
+
72
+ /**
73
+ * The earliest run delimited by `marker` (`**`, `__`, `*` or `_`) at or after
74
+ * `from`. Walks once, holding one pending opener per line and closing it at the
75
+ * first marker a non-space away (and, for `_`, not abutting a word character on
76
+ * its outer edges). One pending opener per line reproduces the leftmost lazy
77
+ * match, quirks and all (`***a***` yields `***a**`, and `**a*` matches none); a
78
+ * newline drops the opener. O(1) per character.
79
+ */
80
+ function findEmphasisSpan(text: string, from: number, marker: string): EmphasisSpan | null {
81
+ const m = marker.length;
82
+ const mark = marker[0];
83
+ const underscore = mark === '_';
84
+ let opener = -1;
85
+ for (let j = from; j + m <= text.length; j += 1) {
86
+ const ch = text[j];
87
+ if (ch === '\n') {
88
+ opener = -1;
89
+ continue;
90
+ }
91
+ if (ch !== mark || (m === 2 && text[j + 1] !== mark)) continue;
92
+ if (isEmphasisCloser(text, j, opener, m, underscore)) {
93
+ return { index: opener, length: j + m - opener, content: text.slice(opener + m, j) };
94
+ }
95
+ if (isEmphasisOpener(text, j, opener, m, underscore)) opener = j;
96
+ }
97
+ return null;
98
+ }
99
+
100
+ /** The outcome of a `scanDestination` sweep: the `)` it found, and where it halted. */
101
+ interface DestinationScan {
102
+ /** The closing `)` index, or `-1` when the run is empty or unterminated. */
103
+ readonly end: number;
104
+ /**
105
+ * Where the walk halted — the `)` on success, else the whitespace or end-of-text
106
+ * that ended a failure. On a failure that advanced, `[start, stop)` provably
107
+ * holds no `)`, which the caller memoizes as a dead span.
108
+ */
109
+ readonly stop: number;
110
+ }
111
+
112
+ /**
113
+ * The destination run of a bracketed construct: one-or-more non-`)`, non-space
114
+ * characters bounded by `)`. Forward-only cursor. See {@link DestinationScan} for
115
+ * `end`/`stop`.
116
+ */
117
+ function scanDestination(text: string, start: number): DestinationScan {
118
+ let k = start;
119
+ while (k < text.length && text[k] !== ')' && NON_SPACE.test(text[k] ?? '')) k += 1;
120
+ if (k > start && text[k] === ')') return { end: k, stop: k };
121
+ // A failure halts at `k`: the whitespace that stopped the walk, or `text.length`
122
+ // when the run reached the end. Either way `[start, k)` holds no `)`.
123
+ return { end: -1, stop: k };
124
+ }
125
+
126
+ /** A resolved link or image: its label/alt `content` and its destination `extra`. */
127
+ interface BracketedSpan {
128
+ readonly index: number;
129
+ readonly length: number;
130
+ readonly content: string;
131
+ readonly extra: string;
132
+ }
133
+
134
+ /**
135
+ * The forward-only memo one `findBracketed` sweep threads through its candidates:
136
+ * the reusable `]` pointer, the destination cached on a `]`, and the span a scan
137
+ * proved to hold no `)`.
138
+ */
139
+ interface BracketMemo {
140
+ /** First `]` at an index the current candidate can still use. */
141
+ close: number;
142
+ /** The `]` the memoized destination belongs to. */
143
+ destKey: number;
144
+ /** Closing `)` for `destKey`, or -1. */
145
+ destEnd: number;
146
+ /**
147
+ * Exclusive index up to which a scan proved no `)` exists; a destination start
148
+ * below it skips the scan. A start at or past it must still scan.
149
+ */
150
+ deadUntil: number;
151
+ }
152
+
153
+ /**
154
+ * The closing `)` for the destination of the label ending at `close`, memoized on
155
+ * that `]`. A destination start inside a proven no-`)` span skips the scan.
156
+ */
157
+ function resolveDestination(text: string, close: number, memo: BracketMemo): number {
158
+ if (memo.destKey === close) return memo.destEnd;
159
+ memo.destKey = close;
160
+ const destStart = close + 2;
161
+ if (memo.deadUntil !== -1 && destStart < memo.deadUntil) {
162
+ memo.destEnd = -1;
163
+ return -1;
164
+ }
165
+ const scan = scanDestination(text, destStart);
166
+ memo.destEnd = scan.end;
167
+ if (scan.end === -1 && scan.stop > destStart) memo.deadUntil = scan.stop;
168
+ return memo.destEnd;
169
+ }
170
+
171
+ /**
172
+ * The bracketed span opening at `bracket` (label `start` accounts for an image's
173
+ * `!`), or `null` when this candidate has no non-empty label followed by a
174
+ * `(dest)`. Requires `memo.close` already advanced to a live `]`.
175
+ */
176
+ function matchAt(
177
+ text: string,
178
+ bracket: number,
179
+ start: number,
180
+ image: boolean,
181
+ memo: BracketMemo,
182
+ ): BracketedSpan | null {
183
+ const labelOk = image || memo.close > bracket + 1;
184
+ if (!labelOk || text[memo.close + 1] !== '(') return null;
185
+ const destEnd = resolveDestination(text, memo.close, memo);
186
+ if (destEnd === -1) return null;
187
+ return {
188
+ index: start,
189
+ length: destEnd + 1 - start,
190
+ content: text.slice(bracket + 1, memo.close),
191
+ extra: text.slice(memo.close + 2, destEnd),
192
+ };
193
+ }
194
+
195
+ /**
196
+ * The earliest `[label](dest)` (or, when `image`, `![alt](dest)`) at or after
197
+ * `from`. A label runs from `[` to the first `]`; a link needs a non-empty label,
198
+ * an image admits an empty one. Linear: each `[` candidate reuses a forward-only
199
+ * `]` pointer and a destination memoized on that `]`, and `deadUntil` records a
200
+ * proven no-`)` span so later candidates starting inside it skip the scan.
201
+ */
202
+ function findBracketed(text: string, from: number, image: boolean): BracketedSpan | null {
203
+ const memo: BracketMemo = { close: -1, destKey: -1, destEnd: -1, deadUntil: -1 };
204
+
205
+ let bracket = text.indexOf('[', from);
206
+ while (bracket !== -1) {
207
+ // An image opens at the `!` immediately before its `[`.
208
+ const start = image ? bracket - 1 : bracket;
209
+ if (!image || (start >= from && text[start] === '!')) {
210
+ if (memo.close < bracket + 1) memo.close = text.indexOf(']', bracket + 1);
211
+ if (memo.close === -1) return null;
212
+ const span = matchAt(text, bracket, start, image, memo);
213
+ if (span !== null) return span;
214
+ }
215
+ bracket = text.indexOf('[', bracket + 1);
216
+ }
217
+ return null;
218
+ }
219
+
220
+ type InlineKind = 'code' | 'image' | 'link' | 'strong' | 'emphasis';
221
+
222
+ /** An inline construct located at an absolute `index`, ready to render. */
223
+ interface InlineFound {
224
+ readonly kind: InlineKind;
225
+ readonly index: number;
226
+ readonly length: number;
227
+ /** Inline code text, image alt, link label, or emphasis/strong body. */
228
+ readonly content: string;
229
+ /** A link's or image's destination. */
230
+ readonly extra?: string;
231
+ }
232
+
233
+ /** Inline code at or after `from`; the shared cursor is set immediately before the scan. */
234
+ function findCode(text: string, from: number): InlineFound | null {
235
+ CODE_SPAN.lastIndex = from;
236
+ const match = CODE_SPAN.exec(text);
237
+ if (match === null) return null;
238
+ return { kind: 'code', index: match.index, length: match[0].length, content: match[1] ?? '' };
239
+ }
240
+
241
+ interface InlineRule {
242
+ readonly kind: InlineKind;
243
+ readonly find: (text: string, from: number) => InlineFound | null;
244
+ }
245
+
246
+ /** Tags an emphasis span with its element kind, or passes `null` through. */
247
+ function asFound(kind: InlineKind, span: EmphasisSpan | null): InlineFound | null {
248
+ return span === null
249
+ ? null
250
+ : { kind, index: span.index, length: span.length, content: span.content };
251
+ }
252
+
253
+ /**
254
+ * Inline constructs in tie-break order at a shared position: code, image, link,
255
+ * strong, emphasis — so `**` reads as one strong span, not two emphasis markers.
256
+ * Strong and emphasis are split per marker (`**`/`__`, `*`/`_`) so each marker
257
+ * caches its own exhaustion and the pass stays linear; star precedes underscore.
258
+ */
259
+ const INLINE_RULES: readonly InlineRule[] = [
260
+ { kind: 'code', find: findCode },
261
+ {
262
+ kind: 'image',
263
+ find: (text, from) => {
264
+ const span = findBracketed(text, from, true);
265
+ return span === null ? null : { kind: 'image', ...span };
266
+ },
267
+ },
268
+ {
269
+ kind: 'link',
270
+ find: (text, from) => {
271
+ const span = findBracketed(text, from, false);
272
+ return span === null ? null : { kind: 'link', ...span };
273
+ },
274
+ },
275
+ { kind: 'strong', find: (text, from) => asFound('strong', findEmphasisSpan(text, from, '**')) },
276
+ { kind: 'strong', find: (text, from) => asFound('strong', findEmphasisSpan(text, from, '__')) },
277
+ {
278
+ kind: 'emphasis',
279
+ find: (text, from) => asFound('emphasis', findEmphasisSpan(text, from, '*')),
280
+ },
281
+ {
282
+ kind: 'emphasis',
283
+ find: (text, from) => asFound('emphasis', findEmphasisSpan(text, from, '_')),
284
+ },
285
+ ];
286
+
287
+ /**
288
+ * Resolves inline markup to React nodes. A cursor walks the text once; each rule
289
+ * caches its earliest match at or after the cursor and is rescanned only when the
290
+ * cursor passes that match, so the rules' rescans cover disjoint forward ranges
291
+ * and the pass is linear. Plain runs are pushed as text children that React
292
+ * escapes; a link is admitted only when `safeHttpUrl` accepts it, and an image
293
+ * contributes its `alt` text alone.
294
+ */
295
+ export function renderInline(text: string, keyBase: string): ReactNode[] {
296
+ const nodes: ReactNode[] = [];
297
+ // Per rule: `undefined` not yet scanned, `null` no match through the end
298
+ // (final), otherwise the pending match to reuse until the cursor passes it.
299
+ const cache: (InlineFound | null | undefined)[] = INLINE_RULES.map(() => undefined);
300
+ let pos = 0;
301
+
302
+ while (pos < text.length) {
303
+ let best: InlineFound | null = null;
304
+ for (const [r, rule] of INLINE_RULES.entries()) {
305
+ let hit = cache[r];
306
+ if (hit === undefined || (hit !== null && hit.index < pos)) {
307
+ hit = rule.find(text, pos);
308
+ cache[r] = hit;
309
+ }
310
+ if (hit !== null && (best === null || hit.index < best.index)) {
311
+ best = hit;
312
+ }
313
+ }
314
+ if (best === null) {
315
+ nodes.push(text.slice(pos));
316
+ break;
317
+ }
318
+ if (best.index > pos) {
319
+ nodes.push(text.slice(pos, best.index));
320
+ }
321
+ nodes.push(renderInlineMatch(best, `${keyBase}-${String(best.index)}`));
322
+ pos = best.index + best.length;
323
+ }
324
+
325
+ return nodes;
326
+ }
327
+
328
+ /**
329
+ * Test-only entry point to the inline scanner. Resolves inline markup to React
330
+ * nodes exactly as `renderInline` does, but without mounting or serializing a
331
+ * DOM, so a test can time the scan itself in isolation from render cost. Not part
332
+ * of the public API.
333
+ */
334
+ export function scanInline(text: string): ReactNode[] {
335
+ return renderInline(text, 'k');
336
+ }
337
+
338
+ function renderInlineMatch(found: InlineFound, key: string): ReactNode {
339
+ switch (found.kind) {
340
+ case 'code':
341
+ return <code key={key}>{found.content}</code>;
342
+ case 'image':
343
+ // Images are not rendered: the alt text is all that survives, and no URL
344
+ // is fetched.
345
+ return found.content;
346
+ case 'link': {
347
+ const url = safeHttpUrl(found.extra ?? '');
348
+ const children = renderInline(found.content, `${key}-t`);
349
+ if (url === undefined) {
350
+ // A destination that is not an absolute http(s) URL never becomes a live
351
+ // anchor: the display text is rendered as plain text.
352
+ return <span key={key}>{children}</span>;
353
+ }
354
+ return (
355
+ <a key={key} href={url} target="_blank" rel="noopener noreferrer external">
356
+ {children}
357
+ </a>
358
+ );
359
+ }
360
+ case 'strong':
361
+ return <strong key={key}>{renderInline(found.content, `${key}-t`)}</strong>;
362
+ case 'emphasis':
363
+ return <em key={key}>{renderInline(found.content, `${key}-t`)}</em>;
364
+ }
365
+ }