@adea-ai/ui 0.140.0 → 0.142.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 (455) hide show
  1. package/dist/components/composites/appearance-editor/appearance-editor.js +2 -2
  2. package/dist/components/composites/appearance-editor/appearance-editor.js.map +1 -1
  3. package/dist/components/composites/catalog-browser/catalog-browser-group.js +1 -1
  4. package/dist/components/composites/chain-of-thought/chain-of-thought.d.ts +56 -0
  5. package/dist/components/composites/chain-of-thought/chain-of-thought.d.ts.map +1 -0
  6. package/dist/components/composites/chain-of-thought/chain-of-thought.js +117 -0
  7. package/dist/components/composites/chain-of-thought/chain-of-thought.js.map +1 -0
  8. package/dist/components/composites/chain-of-thought/index.d.ts +2 -0
  9. package/dist/components/composites/chain-of-thought/index.d.ts.map +1 -0
  10. package/dist/components/composites/chain-of-thought/index.js +2 -0
  11. package/dist/components/composites/chat/chat.d.ts +67 -0
  12. package/dist/components/composites/chat/chat.d.ts.map +1 -0
  13. package/dist/components/composites/chat/chat.js +179 -0
  14. package/dist/components/composites/chat/chat.js.map +1 -0
  15. package/dist/components/composites/chat/index.d.ts +2 -0
  16. package/dist/components/composites/chat/index.d.ts.map +1 -0
  17. package/dist/components/composites/chat/index.js +2 -0
  18. package/dist/components/composites/checkpoint/checkpoint-model.d.ts +34 -0
  19. package/dist/components/composites/checkpoint/checkpoint-model.d.ts.map +1 -0
  20. package/dist/components/composites/checkpoint/checkpoint-model.js +48 -0
  21. package/dist/components/composites/checkpoint/checkpoint-model.js.map +1 -0
  22. package/dist/components/composites/checkpoint/checkpoint.d.ts +48 -0
  23. package/dist/components/composites/checkpoint/checkpoint.d.ts.map +1 -0
  24. package/dist/components/composites/checkpoint/checkpoint.js +160 -0
  25. package/dist/components/composites/checkpoint/checkpoint.js.map +1 -0
  26. package/dist/components/composites/checkpoint/index.d.ts +3 -0
  27. package/dist/components/composites/checkpoint/index.d.ts.map +1 -0
  28. package/dist/components/composites/checkpoint/index.js +3 -0
  29. package/dist/components/composites/confirmation/confirmation-model.d.ts +45 -0
  30. package/dist/components/composites/confirmation/confirmation-model.d.ts.map +1 -0
  31. package/dist/components/composites/confirmation/confirmation-model.js +51 -0
  32. package/dist/components/composites/confirmation/confirmation-model.js.map +1 -0
  33. package/dist/components/composites/confirmation/confirmation.d.ts +72 -0
  34. package/dist/components/composites/confirmation/confirmation.d.ts.map +1 -0
  35. package/dist/components/composites/confirmation/confirmation.js +300 -0
  36. package/dist/components/composites/confirmation/confirmation.js.map +1 -0
  37. package/dist/components/composites/confirmation/index.d.ts +3 -0
  38. package/dist/components/composites/confirmation/index.d.ts.map +1 -0
  39. package/dist/components/composites/confirmation/index.js +3 -0
  40. package/dist/components/composites/context/context-model.d.ts +69 -0
  41. package/dist/components/composites/context/context-model.d.ts.map +1 -0
  42. package/dist/components/composites/context/context-model.js +122 -0
  43. package/dist/components/composites/context/context-model.js.map +1 -0
  44. package/dist/components/composites/context/context.d.ts +38 -0
  45. package/dist/components/composites/context/context.d.ts.map +1 -0
  46. package/dist/components/composites/context/context.js +234 -0
  47. package/dist/components/composites/context/context.js.map +1 -0
  48. package/dist/components/composites/context/index.d.ts +3 -0
  49. package/dist/components/composites/context/index.d.ts.map +1 -0
  50. package/dist/components/composites/context/index.js +3 -0
  51. package/dist/components/composites/file-tree/build-file-tree.d.ts +138 -0
  52. package/dist/components/composites/file-tree/build-file-tree.d.ts.map +1 -0
  53. package/dist/components/composites/file-tree/build-file-tree.js +325 -0
  54. package/dist/components/composites/file-tree/build-file-tree.js.map +1 -0
  55. package/dist/components/composites/file-tree/file-tree.d.ts +74 -0
  56. package/dist/components/composites/file-tree/file-tree.d.ts.map +1 -0
  57. package/dist/components/composites/file-tree/file-tree.js +389 -0
  58. package/dist/components/composites/file-tree/file-tree.js.map +1 -0
  59. package/dist/components/composites/file-tree/index.d.ts +3 -0
  60. package/dist/components/composites/file-tree/index.d.ts.map +1 -0
  61. package/dist/components/composites/file-tree/index.js +3 -0
  62. package/dist/components/composites/inline-citation/citation.d.ts +37 -0
  63. package/dist/components/composites/inline-citation/citation.d.ts.map +1 -0
  64. package/dist/components/composites/inline-citation/citation.js +52 -0
  65. package/dist/components/composites/inline-citation/citation.js.map +1 -0
  66. package/dist/components/composites/inline-citation/index.d.ts +3 -0
  67. package/dist/components/composites/inline-citation/index.d.ts.map +1 -0
  68. package/dist/components/composites/inline-citation/index.js +3 -0
  69. package/dist/components/composites/inline-citation/inline-citation.d.ts +64 -0
  70. package/dist/components/composites/inline-citation/inline-citation.d.ts.map +1 -0
  71. package/dist/components/composites/inline-citation/inline-citation.js +272 -0
  72. package/dist/components/composites/inline-citation/inline-citation.js.map +1 -0
  73. package/dist/components/composites/message-scroller/index.d.ts +3 -0
  74. package/dist/components/composites/message-scroller/index.d.ts.map +1 -0
  75. package/dist/components/composites/message-scroller/index.js +3 -0
  76. package/dist/components/composites/message-scroller/message-scroller.d.ts +55 -0
  77. package/dist/components/composites/message-scroller/message-scroller.d.ts.map +1 -0
  78. package/dist/components/composites/message-scroller/message-scroller.js +201 -0
  79. package/dist/components/composites/message-scroller/message-scroller.js.map +1 -0
  80. package/dist/components/composites/message-scroller/scroll-anchor.d.ts +66 -0
  81. package/dist/components/composites/message-scroller/scroll-anchor.d.ts.map +1 -0
  82. package/dist/components/composites/message-scroller/scroll-anchor.js +122 -0
  83. package/dist/components/composites/message-scroller/scroll-anchor.js.map +1 -0
  84. package/dist/components/composites/model-selector/index.d.ts +3 -0
  85. package/dist/components/composites/model-selector/index.d.ts.map +1 -0
  86. package/dist/components/composites/model-selector/index.js +3 -0
  87. package/dist/components/composites/model-selector/model-selector.d.ts +55 -0
  88. package/dist/components/composites/model-selector/model-selector.d.ts.map +1 -0
  89. package/dist/components/composites/model-selector/model-selector.js +490 -0
  90. package/dist/components/composites/model-selector/model-selector.js.map +1 -0
  91. package/dist/components/composites/model-selector/models.d.ts +51 -0
  92. package/dist/components/composites/model-selector/models.d.ts.map +1 -0
  93. package/dist/components/composites/model-selector/models.js +71 -0
  94. package/dist/components/composites/model-selector/models.js.map +1 -0
  95. package/dist/components/composites/plan/index.d.ts +2 -0
  96. package/dist/components/composites/plan/index.d.ts.map +1 -0
  97. package/dist/components/composites/plan/index.js +2 -0
  98. package/dist/components/composites/plan/plan.d.ts +61 -0
  99. package/dist/components/composites/plan/plan.d.ts.map +1 -0
  100. package/dist/components/composites/plan/plan.js +130 -0
  101. package/dist/components/composites/plan/plan.js.map +1 -0
  102. package/dist/components/composites/queue/index.d.ts +2 -0
  103. package/dist/components/composites/queue/index.d.ts.map +1 -0
  104. package/dist/components/composites/queue/index.js +2 -0
  105. package/dist/components/composites/queue/queue.d.ts +77 -0
  106. package/dist/components/composites/queue/queue.d.ts.map +1 -0
  107. package/dist/components/composites/queue/queue.js +271 -0
  108. package/dist/components/composites/queue/queue.js.map +1 -0
  109. package/dist/components/composites/reasoning/index.d.ts +2 -0
  110. package/dist/components/composites/reasoning/index.d.ts.map +1 -0
  111. package/dist/components/composites/reasoning/index.js +2 -0
  112. package/dist/components/composites/reasoning/reasoning.d.ts +62 -0
  113. package/dist/components/composites/reasoning/reasoning.d.ts.map +1 -0
  114. package/dist/components/composites/reasoning/reasoning.js +156 -0
  115. package/dist/components/composites/reasoning/reasoning.js.map +1 -0
  116. package/dist/components/composites/sources/index.d.ts +3 -0
  117. package/dist/components/composites/sources/index.d.ts.map +1 -0
  118. package/dist/components/composites/sources/index.js +3 -0
  119. package/dist/components/composites/sources/source.d.ts +46 -0
  120. package/dist/components/composites/sources/source.d.ts.map +1 -0
  121. package/dist/components/composites/sources/source.js +74 -0
  122. package/dist/components/composites/sources/source.js.map +1 -0
  123. package/dist/components/composites/sources/sources.d.ts +45 -0
  124. package/dist/components/composites/sources/sources.d.ts.map +1 -0
  125. package/dist/components/composites/sources/sources.js +175 -0
  126. package/dist/components/composites/sources/sources.js.map +1 -0
  127. package/dist/components/composites/stack-trace/index.d.ts +3 -0
  128. package/dist/components/composites/stack-trace/index.d.ts.map +1 -0
  129. package/dist/components/composites/stack-trace/index.js +3 -0
  130. package/dist/components/composites/stack-trace/parse-stack-trace.d.ts +118 -0
  131. package/dist/components/composites/stack-trace/parse-stack-trace.d.ts.map +1 -0
  132. package/dist/components/composites/stack-trace/parse-stack-trace.js +376 -0
  133. package/dist/components/composites/stack-trace/parse-stack-trace.js.map +1 -0
  134. package/dist/components/composites/stack-trace/stack-trace.d.ts +63 -0
  135. package/dist/components/composites/stack-trace/stack-trace.d.ts.map +1 -0
  136. package/dist/components/composites/stack-trace/stack-trace.js +491 -0
  137. package/dist/components/composites/stack-trace/stack-trace.js.map +1 -0
  138. package/dist/components/composites/subagent/index.d.ts +2 -0
  139. package/dist/components/composites/subagent/index.d.ts.map +1 -0
  140. package/dist/components/composites/subagent/index.js +2 -0
  141. package/dist/components/composites/subagent/subagent.d.ts +55 -0
  142. package/dist/components/composites/subagent/subagent.d.ts.map +1 -0
  143. package/dist/components/composites/subagent/subagent.js +138 -0
  144. package/dist/components/composites/subagent/subagent.js.map +1 -0
  145. package/dist/components/composites/suggestion/index.d.ts +2 -0
  146. package/dist/components/composites/suggestion/index.d.ts.map +1 -0
  147. package/dist/components/composites/suggestion/index.js +2 -0
  148. package/dist/components/composites/suggestion/suggestion.d.ts +37 -0
  149. package/dist/components/composites/suggestion/suggestion.d.ts.map +1 -0
  150. package/dist/components/composites/suggestion/suggestion.js +100 -0
  151. package/dist/components/composites/suggestion/suggestion.js.map +1 -0
  152. package/dist/components/composites/task/index.d.ts +2 -0
  153. package/dist/components/composites/task/index.d.ts.map +1 -0
  154. package/dist/components/composites/task/index.js +2 -0
  155. package/dist/components/composites/task/task.d.ts +96 -0
  156. package/dist/components/composites/task/task.d.ts.map +1 -0
  157. package/dist/components/composites/task/task.js +311 -0
  158. package/dist/components/composites/task/task.js.map +1 -0
  159. package/dist/components/composites/terminal/ansi.d.ts +101 -0
  160. package/dist/components/composites/terminal/ansi.d.ts.map +1 -0
  161. package/dist/components/composites/terminal/ansi.js +544 -0
  162. package/dist/components/composites/terminal/ansi.js.map +1 -0
  163. package/dist/components/composites/terminal/index.d.ts +4 -0
  164. package/dist/components/composites/terminal/index.d.ts.map +1 -0
  165. package/dist/components/composites/terminal/index.js +4 -0
  166. package/dist/components/composites/terminal/terminal-model.d.ts +63 -0
  167. package/dist/components/composites/terminal/terminal-model.d.ts.map +1 -0
  168. package/dist/components/composites/terminal/terminal-model.js +69 -0
  169. package/dist/components/composites/terminal/terminal-model.js.map +1 -0
  170. package/dist/components/composites/terminal/terminal.d.ts +88 -0
  171. package/dist/components/composites/terminal/terminal.d.ts.map +1 -0
  172. package/dist/components/composites/terminal/terminal.js +500 -0
  173. package/dist/components/composites/terminal/terminal.js.map +1 -0
  174. package/dist/components/composites/test-results/index.d.ts +3 -0
  175. package/dist/components/composites/test-results/index.d.ts.map +1 -0
  176. package/dist/components/composites/test-results/index.js +3 -0
  177. package/dist/components/composites/test-results/test-results-model.d.ts +154 -0
  178. package/dist/components/composites/test-results/test-results-model.d.ts.map +1 -0
  179. package/dist/components/composites/test-results/test-results-model.js +252 -0
  180. package/dist/components/composites/test-results/test-results-model.js.map +1 -0
  181. package/dist/components/composites/test-results/test-results.d.ts +60 -0
  182. package/dist/components/composites/test-results/test-results.d.ts.map +1 -0
  183. package/dist/components/composites/test-results/test-results.js +631 -0
  184. package/dist/components/composites/test-results/test-results.js.map +1 -0
  185. package/dist/components/composites/tool/format-tool-value.d.ts +37 -0
  186. package/dist/components/composites/tool/format-tool-value.d.ts.map +1 -0
  187. package/dist/components/composites/tool/format-tool-value.js +135 -0
  188. package/dist/components/composites/tool/format-tool-value.js.map +1 -0
  189. package/dist/components/composites/tool/index.d.ts +3 -0
  190. package/dist/components/composites/tool/index.d.ts.map +1 -0
  191. package/dist/components/composites/tool/index.js +3 -0
  192. package/dist/components/composites/tool/tool.d.ts +69 -0
  193. package/dist/components/composites/tool/tool.d.ts.map +1 -0
  194. package/dist/components/composites/tool/tool.js +214 -0
  195. package/dist/components/composites/tool/tool.js.map +1 -0
  196. package/dist/components/composites/update-dialog/update-dialog.js +1 -1
  197. package/dist/components/conversation/conversation-surface.d.ts +7 -0
  198. package/dist/components/conversation/conversation-surface.d.ts.map +1 -1
  199. package/dist/components/conversation/conversation-surface.js +2 -0
  200. package/dist/components/conversation/conversation-surface.js.map +1 -1
  201. package/dist/components/conversation/scroll-follow-core.d.ts +24 -0
  202. package/dist/components/conversation/scroll-follow-core.d.ts.map +1 -1
  203. package/dist/components/conversation/scroll-follow-core.js +23 -1
  204. package/dist/components/conversation/scroll-follow-core.js.map +1 -1
  205. package/dist/components/conversation/scroll-follow.d.ts +3 -0
  206. package/dist/components/conversation/scroll-follow.d.ts.map +1 -1
  207. package/dist/components/conversation/scroll-follow.js +80 -1
  208. package/dist/components/conversation/scroll-follow.js.map +1 -1
  209. package/dist/components/ui/attachment/attachment.d.ts +58 -0
  210. package/dist/components/ui/attachment/attachment.d.ts.map +1 -0
  211. package/dist/components/ui/attachment/attachment.js +279 -0
  212. package/dist/components/ui/attachment/attachment.js.map +1 -0
  213. package/dist/components/ui/attachment/index.d.ts +2 -0
  214. package/dist/components/ui/attachment/index.d.ts.map +1 -0
  215. package/dist/components/ui/attachment/index.js +2 -0
  216. package/dist/components/ui/badge/badge.d.ts +1 -1
  217. package/dist/components/ui/bubble/bubble.d.ts +33 -0
  218. package/dist/components/ui/bubble/bubble.d.ts.map +1 -0
  219. package/dist/components/ui/bubble/bubble.js +95 -0
  220. package/dist/components/ui/bubble/bubble.js.map +1 -0
  221. package/dist/components/ui/bubble/index.d.ts +2 -0
  222. package/dist/components/ui/bubble/index.d.ts.map +1 -0
  223. package/dist/components/ui/bubble/index.js +2 -0
  224. package/dist/components/ui/button/button.d.ts +1 -1
  225. package/dist/components/ui/code-block/code-block.d.ts +56 -3
  226. package/dist/components/ui/code-block/code-block.d.ts.map +1 -1
  227. package/dist/components/ui/code-block/code-block.js +231 -50
  228. package/dist/components/ui/code-block/code-block.js.map +1 -1
  229. package/dist/components/ui/code-block/index.d.ts +1 -1
  230. package/dist/components/ui/code-block/index.d.ts.map +1 -1
  231. package/dist/components/ui/code-block/index.js +2 -2
  232. package/dist/components/ui/field/number-field.d.ts +21 -4
  233. package/dist/components/ui/field/number-field.d.ts.map +1 -1
  234. package/dist/components/ui/field/number-field.js +22 -11
  235. package/dist/components/ui/field/number-field.js.map +1 -1
  236. package/dist/components/ui/marker/index.d.ts +2 -0
  237. package/dist/components/ui/marker/index.d.ts.map +1 -0
  238. package/dist/components/ui/marker/index.js +2 -0
  239. package/dist/components/ui/marker/marker.d.ts +35 -0
  240. package/dist/components/ui/marker/marker.d.ts.map +1 -0
  241. package/dist/components/ui/marker/marker.js +123 -0
  242. package/dist/components/ui/marker/marker.js.map +1 -0
  243. package/dist/components/ui/message/cite-ranges.d.ts +42 -0
  244. package/dist/components/ui/message/cite-ranges.d.ts.map +1 -0
  245. package/dist/components/ui/message/cite-ranges.js +105 -0
  246. package/dist/components/ui/message/cite-ranges.js.map +1 -0
  247. package/dist/components/ui/message/index.d.ts +4 -0
  248. package/dist/components/ui/message/index.d.ts.map +1 -0
  249. package/dist/components/ui/message/index.js +4 -0
  250. package/dist/components/ui/message/message.d.ts +95 -0
  251. package/dist/components/ui/message/message.d.ts.map +1 -0
  252. package/dist/components/ui/message/message.js +443 -0
  253. package/dist/components/ui/message/message.js.map +1 -0
  254. package/dist/components/ui/message/parse-message-text.d.ts +93 -0
  255. package/dist/components/ui/message/parse-message-text.d.ts.map +1 -0
  256. package/dist/components/ui/message/parse-message-text.js +365 -0
  257. package/dist/components/ui/message/parse-message-text.js.map +1 -0
  258. package/dist/components/ui/questionnaire/index.d.ts +2 -0
  259. package/dist/components/ui/questionnaire/index.d.ts.map +1 -0
  260. package/dist/components/ui/questionnaire/index.js +2 -0
  261. package/dist/components/ui/questionnaire/questionnaire.d.ts +83 -0
  262. package/dist/components/ui/questionnaire/questionnaire.d.ts.map +1 -0
  263. package/dist/components/ui/questionnaire/questionnaire.js +470 -0
  264. package/dist/components/ui/questionnaire/questionnaire.js.map +1 -0
  265. package/dist/components/ui/status-chip/status-chip.d.ts +1 -1
  266. package/dist/components/ui/switch/switch.js +11 -11
  267. package/dist/components/ui/switch/switch.js.map +1 -1
  268. package/dist/components/ui/trace/index.d.ts +2 -0
  269. package/dist/components/ui/trace/index.d.ts.map +1 -0
  270. package/dist/components/ui/trace/index.js +2 -0
  271. package/dist/components/ui/trace/trace.d.ts +72 -0
  272. package/dist/components/ui/trace/trace.d.ts.map +1 -0
  273. package/dist/components/ui/trace/trace.js +340 -0
  274. package/dist/components/ui/trace/trace.js.map +1 -0
  275. package/dist/index.d.ts +26 -0
  276. package/dist/index.d.ts.map +1 -1
  277. package/dist/index.js +46 -5
  278. package/dist/r/attachment.json +25 -0
  279. package/dist/r/bubble.json +22 -0
  280. package/dist/r/chain-of-thought.json +26 -0
  281. package/dist/r/chat.json +24 -0
  282. package/dist/r/checkpoint.json +35 -0
  283. package/dist/r/confirmation.json +34 -0
  284. package/dist/r/context.json +33 -0
  285. package/dist/r/file-tree.json +32 -0
  286. package/dist/r/inline-citation.json +35 -0
  287. package/dist/r/marker.json +22 -0
  288. package/dist/r/message-scroller.json +31 -0
  289. package/dist/r/message.json +33 -0
  290. package/dist/r/model-selector.json +34 -0
  291. package/dist/r/plan.json +26 -0
  292. package/dist/r/questionnaire.json +28 -0
  293. package/dist/r/queue.json +26 -0
  294. package/dist/r/reasoning.json +26 -0
  295. package/dist/r/registry.json +811 -52
  296. package/dist/r/sources.json +32 -0
  297. package/dist/r/src/components/composites/chain-of-thought/chain-of-thought.tsx +141 -0
  298. package/dist/r/src/components/composites/chain-of-thought/index.ts +11 -0
  299. package/dist/r/src/components/composites/chat/chat.tsx +190 -0
  300. package/dist/r/src/components/composites/chat/index.ts +11 -0
  301. package/dist/r/src/components/composites/checkpoint/checkpoint-model.ts +71 -0
  302. package/dist/r/src/components/composites/checkpoint/checkpoint.tsx +214 -0
  303. package/dist/r/src/components/composites/checkpoint/index.ts +8 -0
  304. package/dist/r/src/components/composites/confirmation/confirmation-model.ts +83 -0
  305. package/dist/r/src/components/composites/confirmation/confirmation.tsx +311 -0
  306. package/dist/r/src/components/composites/confirmation/index.ts +9 -0
  307. package/dist/r/src/components/composites/context/context-model.ts +168 -0
  308. package/dist/r/src/components/composites/context/context.tsx +187 -0
  309. package/dist/r/src/components/composites/context/index.ts +18 -0
  310. package/dist/r/src/components/composites/file-tree/build-file-tree.ts +456 -0
  311. package/dist/r/src/components/composites/file-tree/file-tree.tsx +405 -0
  312. package/dist/r/src/components/composites/file-tree/index.ts +25 -0
  313. package/dist/r/src/components/composites/inline-citation/citation.ts +78 -0
  314. package/dist/r/src/components/composites/inline-citation/index.ts +9 -0
  315. package/dist/r/src/components/composites/inline-citation/inline-citation.tsx +285 -0
  316. package/dist/r/src/components/composites/message-scroller/index.ts +2 -0
  317. package/dist/r/src/components/composites/message-scroller/message-scroller.tsx +301 -0
  318. package/dist/r/src/components/composites/message-scroller/scroll-anchor.ts +170 -0
  319. package/dist/r/src/components/composites/model-selector/index.ts +14 -0
  320. package/dist/r/src/components/composites/model-selector/model-selector.tsx +420 -0
  321. package/dist/r/src/components/composites/model-selector/models.ts +103 -0
  322. package/dist/r/src/components/composites/plan/index.ts +1 -0
  323. package/dist/r/src/components/composites/plan/plan.tsx +155 -0
  324. package/dist/r/src/components/composites/queue/index.ts +10 -0
  325. package/dist/r/src/components/composites/queue/queue.tsx +264 -0
  326. package/dist/r/src/components/composites/reasoning/index.ts +1 -0
  327. package/dist/r/src/components/composites/reasoning/reasoning.tsx +176 -0
  328. package/dist/r/src/components/composites/sources/index.ts +11 -0
  329. package/dist/r/src/components/composites/sources/source.ts +116 -0
  330. package/dist/r/src/components/composites/sources/sources.tsx +163 -0
  331. package/dist/r/src/components/composites/stack-trace/index.ts +19 -0
  332. package/dist/r/src/components/composites/stack-trace/parse-stack-trace.ts +507 -0
  333. package/dist/r/src/components/composites/stack-trace/stack-trace.tsx +395 -0
  334. package/dist/r/src/components/composites/subagent/index.ts +1 -0
  335. package/dist/r/src/components/composites/subagent/subagent.tsx +159 -0
  336. package/dist/r/src/components/composites/suggestion/index.ts +1 -0
  337. package/dist/r/src/components/composites/suggestion/suggestion.tsx +140 -0
  338. package/dist/r/src/components/composites/task/index.ts +14 -0
  339. package/dist/r/src/components/composites/task/task.tsx +317 -0
  340. package/dist/r/src/components/composites/terminal/ansi.ts +674 -0
  341. package/dist/r/src/components/composites/terminal/index.ts +20 -0
  342. package/dist/r/src/components/composites/terminal/terminal-model.ts +111 -0
  343. package/dist/r/src/components/composites/terminal/terminal.tsx +574 -0
  344. package/dist/r/src/components/composites/test-results/index.ts +20 -0
  345. package/dist/r/src/components/composites/test-results/test-results-model.ts +368 -0
  346. package/dist/r/src/components/composites/test-results/test-results.tsx +586 -0
  347. package/dist/r/src/components/composites/tool/format-tool-value.ts +221 -0
  348. package/dist/r/src/components/composites/tool/index.ts +2 -0
  349. package/dist/r/src/components/composites/tool/tool.tsx +228 -0
  350. package/dist/r/src/components/conversation/conversation-surface.tsx +9 -0
  351. package/dist/r/src/components/conversation/scroll-follow-core.ts +31 -0
  352. package/dist/r/src/components/conversation/scroll-follow.ts +92 -0
  353. package/dist/r/src/components/ui/attachment/attachment.tsx +282 -0
  354. package/dist/r/src/components/ui/attachment/index.ts +10 -0
  355. package/dist/r/src/components/ui/bubble/bubble.tsx +86 -0
  356. package/dist/r/src/components/ui/bubble/index.ts +1 -0
  357. package/dist/r/src/components/ui/code-block/code-block.tsx +256 -26
  358. package/dist/r/src/components/ui/code-block/index.ts +9 -1
  359. package/dist/r/src/components/ui/field/number-field.tsx +51 -14
  360. package/dist/r/src/components/ui/marker/index.ts +1 -0
  361. package/dist/r/src/components/ui/marker/marker.tsx +90 -0
  362. package/dist/r/src/components/ui/message/cite-ranges.ts +144 -0
  363. package/dist/r/src/components/ui/message/index.ts +23 -0
  364. package/dist/r/src/components/ui/message/message.tsx +434 -0
  365. package/dist/r/src/components/ui/message/parse-message-text.ts +450 -0
  366. package/dist/r/src/components/ui/questionnaire/index.ts +10 -0
  367. package/dist/r/src/components/ui/questionnaire/questionnaire.tsx +446 -0
  368. package/dist/r/src/components/ui/trace/index.ts +9 -0
  369. package/dist/r/src/components/ui/trace/trace.tsx +334 -0
  370. package/dist/r/src/styles/base.css +34 -0
  371. package/dist/r/stack-trace.json +32 -0
  372. package/dist/r/subagent.json +27 -0
  373. package/dist/r/suggestion.json +24 -0
  374. package/dist/r/task.json +28 -0
  375. package/dist/r/terminal.json +35 -0
  376. package/dist/r/test-results.json +33 -0
  377. package/dist/r/tool.json +31 -0
  378. package/dist/r/trace.json +25 -0
  379. package/package.json +6 -3
  380. package/registry.json +811 -52
  381. package/src/components/composites/chain-of-thought/chain-of-thought.tsx +141 -0
  382. package/src/components/composites/chain-of-thought/index.ts +11 -0
  383. package/src/components/composites/chat/chat.tsx +190 -0
  384. package/src/components/composites/chat/index.ts +11 -0
  385. package/src/components/composites/checkpoint/checkpoint-model.ts +71 -0
  386. package/src/components/composites/checkpoint/checkpoint.tsx +214 -0
  387. package/src/components/composites/checkpoint/index.ts +8 -0
  388. package/src/components/composites/confirmation/confirmation-model.ts +83 -0
  389. package/src/components/composites/confirmation/confirmation.tsx +311 -0
  390. package/src/components/composites/confirmation/index.ts +9 -0
  391. package/src/components/composites/context/context-model.ts +168 -0
  392. package/src/components/composites/context/context.tsx +187 -0
  393. package/src/components/composites/context/index.ts +18 -0
  394. package/src/components/composites/file-tree/build-file-tree.ts +456 -0
  395. package/src/components/composites/file-tree/file-tree.tsx +405 -0
  396. package/src/components/composites/file-tree/index.ts +25 -0
  397. package/src/components/composites/inline-citation/citation.ts +78 -0
  398. package/src/components/composites/inline-citation/index.ts +9 -0
  399. package/src/components/composites/inline-citation/inline-citation.tsx +285 -0
  400. package/src/components/composites/message-scroller/index.ts +2 -0
  401. package/src/components/composites/message-scroller/message-scroller.tsx +301 -0
  402. package/src/components/composites/message-scroller/scroll-anchor.ts +170 -0
  403. package/src/components/composites/model-selector/index.ts +14 -0
  404. package/src/components/composites/model-selector/model-selector.tsx +420 -0
  405. package/src/components/composites/model-selector/models.ts +103 -0
  406. package/src/components/composites/plan/index.ts +1 -0
  407. package/src/components/composites/plan/plan.tsx +155 -0
  408. package/src/components/composites/queue/index.ts +10 -0
  409. package/src/components/composites/queue/queue.tsx +264 -0
  410. package/src/components/composites/reasoning/index.ts +1 -0
  411. package/src/components/composites/reasoning/reasoning.tsx +176 -0
  412. package/src/components/composites/sources/index.ts +11 -0
  413. package/src/components/composites/sources/source.ts +116 -0
  414. package/src/components/composites/sources/sources.tsx +163 -0
  415. package/src/components/composites/stack-trace/index.ts +19 -0
  416. package/src/components/composites/stack-trace/parse-stack-trace.ts +507 -0
  417. package/src/components/composites/stack-trace/stack-trace.tsx +395 -0
  418. package/src/components/composites/subagent/index.ts +1 -0
  419. package/src/components/composites/subagent/subagent.tsx +159 -0
  420. package/src/components/composites/suggestion/index.ts +1 -0
  421. package/src/components/composites/suggestion/suggestion.tsx +140 -0
  422. package/src/components/composites/task/index.ts +14 -0
  423. package/src/components/composites/task/task.tsx +317 -0
  424. package/src/components/composites/terminal/ansi.ts +674 -0
  425. package/src/components/composites/terminal/index.ts +20 -0
  426. package/src/components/composites/terminal/terminal-model.ts +111 -0
  427. package/src/components/composites/terminal/terminal.tsx +574 -0
  428. package/src/components/composites/test-results/index.ts +20 -0
  429. package/src/components/composites/test-results/test-results-model.ts +368 -0
  430. package/src/components/composites/test-results/test-results.tsx +586 -0
  431. package/src/components/composites/tool/format-tool-value.ts +221 -0
  432. package/src/components/composites/tool/index.ts +2 -0
  433. package/src/components/composites/tool/tool.tsx +228 -0
  434. package/src/components/conversation/conversation-surface.tsx +9 -0
  435. package/src/components/conversation/scroll-follow-core.ts +31 -0
  436. package/src/components/conversation/scroll-follow.ts +92 -0
  437. package/src/components/ui/attachment/attachment.tsx +282 -0
  438. package/src/components/ui/attachment/index.ts +10 -0
  439. package/src/components/ui/bubble/bubble.tsx +86 -0
  440. package/src/components/ui/bubble/index.ts +1 -0
  441. package/src/components/ui/code-block/code-block.tsx +256 -26
  442. package/src/components/ui/code-block/index.ts +9 -1
  443. package/src/components/ui/field/number-field.tsx +51 -14
  444. package/src/components/ui/marker/index.ts +1 -0
  445. package/src/components/ui/marker/marker.tsx +90 -0
  446. package/src/components/ui/message/cite-ranges.ts +144 -0
  447. package/src/components/ui/message/index.ts +23 -0
  448. package/src/components/ui/message/message.tsx +434 -0
  449. package/src/components/ui/message/parse-message-text.ts +450 -0
  450. package/src/components/ui/questionnaire/index.ts +10 -0
  451. package/src/components/ui/questionnaire/questionnaire.tsx +446 -0
  452. package/src/components/ui/trace/index.ts +9 -0
  453. package/src/components/ui/trace/trace.tsx +334 -0
  454. package/src/index.ts +26 -0
  455. package/src/styles/base.css +34 -0
@@ -0,0 +1,272 @@
1
+ import { cn } from "../../../lib/utils.js";
2
+ import { Button } from "../../ui/button/button.js";
3
+ import { ActionButton } from "../action-button/action-button.js";
4
+ import { Popover, PopoverContent, PopoverTitle, PopoverTrigger } from "../../ui/popover/popover.js";
5
+ import { TextLink } from "../../ui/text-link/text-link.js";
6
+ import { boundText, safeSourceUrl, sourceHost, sourceTitle } from "../sources/source.js";
7
+ import { citationLabel, citationName, nextCitationMode, wrapIndex } from "./citation.js";
8
+ import { createComponent, insert, memo, template } from "solid-js/web";
9
+ import { ChevronLeft, ChevronRight } from "lucide-solid";
10
+ import { Show, createSignal, onCleanup, splitProps } from "solid-js";
11
+ //#region src/components/composites/inline-citation/inline-citation.tsx
12
+ var _tmpl$ = /*#__PURE__*/ template(`<span aria-hidden=true class="max-w-32 truncate">`);
13
+ var _tmpl$2 = /*#__PURE__*/ template(`<span aria-hidden=true>+`);
14
+ var _tmpl$3 = /*#__PURE__*/ template(`<div class="flex items-center justify-between gap-2"><span role=status aria-live=polite class="text-xs text-muted-foreground tabular-nums">Source <!> of </span><span class="flex items-center gap-0.5">`);
15
+ var _tmpl$4 = /*#__PURE__*/ template(`<div class="flex min-w-0 flex-col gap-1.5 px-2 py-1.5">`);
16
+ var _tmpl$5 = /*#__PURE__*/ template(`<p class="m-0 text-xs text-muted-foreground [overflow-wrap:anywhere]">`);
17
+ var _tmpl$6 = /*#__PURE__*/ template(`<p class="m-0 text-xs text-muted-foreground">Address not linked`);
18
+ var _tmpl$7 = /*#__PURE__*/ template(`<p class="m-0 line-clamp-6 text-xs text-muted-foreground [overflow-wrap:anywhere]">`);
19
+ var _tmpl$8 = /*#__PURE__*/ template(`<span class=visually-hidden> (opens in a new tab)`);
20
+ var LEAVE_DELAY = 200;
21
+ function InlineCitation(props) {
22
+ const [local] = splitProps(props, [
23
+ "sources",
24
+ "index",
25
+ "hoverDelay",
26
+ "class"
27
+ ]);
28
+ const [mode, setMode] = createSignal("closed");
29
+ const [position, setPosition] = createSignal(0);
30
+ let timer;
31
+ let content;
32
+ let pressing = false;
33
+ let restoringFocus = false;
34
+ const count = () => local.sources.length;
35
+ const active = () => local.sources[wrapIndex(position(), count())];
36
+ const clear = () => {
37
+ if (timer !== void 0) clearTimeout(timer);
38
+ timer = void 0;
39
+ };
40
+ onCleanup(clear);
41
+ const dispatch = (event) => setMode((current) => nextCitationMode(current, event));
42
+ const schedule = (event, delay) => {
43
+ clear();
44
+ timer = setTimeout(() => dispatch(event), delay);
45
+ };
46
+ const onPointerEnter = (event) => {
47
+ if (event.pointerType === "touch") return;
48
+ schedule("enter", local.hoverDelay ?? 150);
49
+ };
50
+ const onPointerLeave = (event) => {
51
+ if (event.pointerType === "touch") return;
52
+ schedule("leave", LEAVE_DELAY);
53
+ };
54
+ const onClick = () => {
55
+ clear();
56
+ const wasPeeking = mode() === "peek";
57
+ dispatch("press");
58
+ pressing = true;
59
+ queueMicrotask(() => {
60
+ pressing = false;
61
+ });
62
+ if (wasPeeking) queueMicrotask(() => content?.focus());
63
+ };
64
+ return createComponent(Show, {
65
+ get when() {
66
+ return count() > 0;
67
+ },
68
+ get children() {
69
+ return createComponent(Popover, {
70
+ get open() {
71
+ return mode() !== "closed";
72
+ },
73
+ onOpenChange: (next) => {
74
+ if (!next && !pressing) dispatch("dismiss");
75
+ },
76
+ placement: "bottom",
77
+ gutter: 6,
78
+ get children() {
79
+ return [createComponent(PopoverTrigger, {
80
+ as: Button,
81
+ variant: "subtle",
82
+ size: "2xs",
83
+ touchTarget: "comfortable",
84
+ "data-slot": "inline-citation",
85
+ get ["aria-label"]() {
86
+ return citationName(local.sources, local.index);
87
+ },
88
+ get ["class"]() {
89
+ return cn("mx-0.5 align-baseline tabular-nums", local.class);
90
+ },
91
+ onClick,
92
+ onPointerEnter,
93
+ onPointerLeave,
94
+ onFocus: (event) => {
95
+ if (restoringFocus) return;
96
+ if (event.currentTarget.matches(":focus-visible")) dispatch("focus");
97
+ },
98
+ onBlur: () => dispatch("blur"),
99
+ get children() {
100
+ return [(() => {
101
+ var _el$ = _tmpl$();
102
+ insert(_el$, () => citationLabel(local.index, local.sources[0]));
103
+ return _el$;
104
+ })(), createComponent(Show, {
105
+ get when() {
106
+ return count() > 1;
107
+ },
108
+ get children() {
109
+ var _el$2 = _tmpl$2();
110
+ _el$2.firstChild;
111
+ insert(_el$2, () => count() - 1, null);
112
+ return _el$2;
113
+ }
114
+ })];
115
+ }
116
+ }), createComponent(PopoverContent, {
117
+ ref: (element) => content = element,
118
+ "class": "w-72 max-w-full",
119
+ onOpenAutoFocus: (event) => {
120
+ if (mode() === "peek") event.preventDefault();
121
+ },
122
+ onCloseAutoFocus: () => {
123
+ restoringFocus = true;
124
+ queueMicrotask(() => {
125
+ restoringFocus = false;
126
+ });
127
+ },
128
+ onPointerEnter: (event) => {
129
+ if (event.pointerType !== "touch") clear();
130
+ },
131
+ onPointerLeave,
132
+ get children() {
133
+ return createComponent(Show, {
134
+ get when() {
135
+ return active();
136
+ },
137
+ children: (source) => (() => {
138
+ var _el$4 = _tmpl$4();
139
+ insert(_el$4, createComponent(Show, {
140
+ get when() {
141
+ return count() > 1;
142
+ },
143
+ get children() {
144
+ var _el$5 = _tmpl$3(), _el$6 = _el$5.firstChild, _el$9 = _el$6.firstChild.nextSibling;
145
+ _el$9.nextSibling;
146
+ var _el$0 = _el$6.nextSibling;
147
+ insert(_el$6, () => wrapIndex(position(), count()) + 1, _el$9);
148
+ insert(_el$6, count, null);
149
+ insert(_el$0, createComponent(ActionButton, {
150
+ variant: "ghost",
151
+ size: "icon-xs",
152
+ "aria-label": "Previous source",
153
+ tooltip: "Previous source",
154
+ onClick: () => setPosition((value) => wrapIndex(value - 1, count())),
155
+ get children() {
156
+ return createComponent(ChevronLeft, {});
157
+ }
158
+ }), null);
159
+ insert(_el$0, createComponent(ActionButton, {
160
+ variant: "ghost",
161
+ size: "icon-xs",
162
+ "aria-label": "Next source",
163
+ tooltip: "Next source",
164
+ onClick: () => setPosition((value) => wrapIndex(value + 1, count())),
165
+ get children() {
166
+ return createComponent(ChevronRight, {});
167
+ }
168
+ }), null);
169
+ return _el$5;
170
+ }
171
+ }), null);
172
+ insert(_el$4, createComponent(PopoverTitle, {
173
+ "class": "p-0 [overflow-wrap:anywhere]",
174
+ get children() {
175
+ return sourceTitle(source());
176
+ }
177
+ }), null);
178
+ insert(_el$4, createComponent(CitationDetails, { get source() {
179
+ return source();
180
+ } }), null);
181
+ return _el$4;
182
+ })()
183
+ });
184
+ }
185
+ })];
186
+ }
187
+ });
188
+ }
189
+ });
190
+ }
191
+ /**
192
+ * Citation markers for `MessageText`, from the sources a reply really used.
193
+ *
194
+ * `[^2]` in the text becomes the second source's badge; `[^1,3]` one badge for
195
+ * sources 1 and 3. A number beyond the list leaves the marker as written, and an
196
+ * empty list makes every marker literal, so text can never cite a source the host
197
+ * did not supply.
198
+ *
199
+ * <MessageText text={reply} citations={messageCitations(sources)} />
200
+ */
201
+ function messageCitations(sources) {
202
+ return {
203
+ count: sources.length,
204
+ render: (numbers) => createComponent(InlineCitation, {
205
+ get index() {
206
+ return numbers[0];
207
+ },
208
+ get sources() {
209
+ return numbers.flatMap((number) => {
210
+ const source = sources[number - 1];
211
+ return source ? [source] : [];
212
+ });
213
+ }
214
+ })
215
+ };
216
+ }
217
+ function CitationDetails(props) {
218
+ const href = () => safeSourceUrl(props.source.url);
219
+ const host = () => sourceHost(props.source.url);
220
+ const snippet = () => props.source.snippet ? boundText(props.source.snippet, 480) : "";
221
+ const withheld = () => props.source.url !== void 0 && props.source.url !== "" && !href();
222
+ return [
223
+ createComponent(Show, {
224
+ get when() {
225
+ return host();
226
+ },
227
+ get children() {
228
+ var _el$1 = _tmpl$5();
229
+ insert(_el$1, host);
230
+ return _el$1;
231
+ }
232
+ }),
233
+ createComponent(Show, {
234
+ get when() {
235
+ return href();
236
+ },
237
+ children: (url) => createComponent(TextLink, {
238
+ get href() {
239
+ return url();
240
+ },
241
+ target: "_blank",
242
+ rel: "noreferrer noopener",
243
+ "class": "w-fit max-w-full text-xs [overflow-wrap:anywhere]",
244
+ get children() {
245
+ return [memo(() => boundText(url(), 96)), _tmpl$8()];
246
+ }
247
+ })
248
+ }),
249
+ createComponent(Show, {
250
+ get when() {
251
+ return withheld();
252
+ },
253
+ get children() {
254
+ return _tmpl$6();
255
+ }
256
+ }),
257
+ createComponent(Show, {
258
+ get when() {
259
+ return snippet();
260
+ },
261
+ get children() {
262
+ var _el$11 = _tmpl$7();
263
+ insert(_el$11, snippet);
264
+ return _el$11;
265
+ }
266
+ })
267
+ ];
268
+ }
269
+ //#endregion
270
+ export { InlineCitation, messageCitations };
271
+
272
+ //# sourceMappingURL=inline-citation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inline-citation.js","names":["ChevronLeft","ChevronRight","createSignal","onCleanup","Show","splitProps","cn","ActionButton","Button","MessageCitations","Popover","PopoverContent","PopoverTitle","PopoverTrigger","TextLink","SOURCE_SNIPPET_LIMIT","boundText","safeSourceUrl","sourceHost","sourceTitle","Source","citationLabel","citationName","nextCitationMode","wrapIndex","CitationEvent","CitationMode","InlineCitationProps","sources","index","hoverDelay","class","LEAVE_DELAY","InlineCitation","props","local","mode","setMode","position","setPosition","timer","ReturnType","setTimeout","content","HTMLElement","pressing","restoringFocus","count","length","active","clear","undefined","clearTimeout","dispatch","event","current","schedule","delay","onPointerEnter","PointerEvent","pointerType","onPointerLeave","onClick","wasPeeking","queueMicrotask","focus","_$createComponent","when","children","open","onOpenChange","next","placement","gutter","as","variant","size","touchTarget","aria-label","onFocus","FocusEvent","currentTarget","matches","onBlur","_el$","_tmpl$","_$insert","_el$2","_tmpl$2","_el$3","firstChild","ref","element","onOpenAutoFocus","Event","preventDefault","onCloseAutoFocus","source","_el$4","_tmpl$4","_el$5","_tmpl$3","_el$6","_el$7","_el$9","nextSibling","_el$8","_el$0","tooltip","value","CitationDetails","messageCitations","render","numbers","flatMap","number","href","url","host","snippet","withheld","_el$1","_tmpl$5","target","rel","_$memo","_tmpl$8","_tmpl$6","_el$11","_tmpl$7","_$createComponent","_$memo"],"sources":["../../../../src/components/composites/inline-citation/inline-citation.tsx"],"sourcesContent":["import { ChevronLeft, ChevronRight } from 'lucide-solid'\nimport { createSignal, onCleanup, Show, splitProps } from 'solid-js'\nimport { cn } from '#lib/utils'\nimport { ActionButton } from '../action-button'\nimport { Button } from '../../ui/button'\nimport type { MessageCitations } from '../../ui/message'\nimport { Popover, PopoverContent, PopoverTitle, PopoverTrigger } from '../../ui/popover'\nimport { TextLink } from '../../ui/text-link'\nimport {\n SOURCE_SNIPPET_LIMIT,\n boundText,\n safeSourceUrl,\n sourceHost,\n sourceTitle,\n type Source,\n} from '../sources/source'\nimport {\n citationLabel,\n citationName,\n nextCitationMode,\n wrapIndex,\n type CitationEvent,\n type CitationMode,\n} from './citation'\n\n/**\n * InlineCitation.\n *\n * A small badge inside a sentence — \"1\", or a host — that opens the source(s)\n * behind the claim: title, host, address, snippet, and Previous/Next when several\n * sources share one marker. It is an inline element for prose such as\n * `MessageText`: it never breaks across lines, stays on the text baseline, and\n * adds no block of its own. For the list of everything a reply used, reach for\n * `Sources`; the two number sources the same way.\n *\n * ## One popover, two ways to open it\n *\n * A hover card would exclude everyone who is not holding a mouse, so this is a\n * `Popover` that a pointer can also *peek* at:\n *\n * - **Hover or keyboard focus peeks.** The popover opens without taking focus\n * and closes when the pointer or focus leaves. Touch has no hover, so a touch\n * never peeks.\n * - **Click, tap, Enter or Space pins.** Focus moves into the popover so its\n * link and Previous/Next are reachable; it stays until Escape, an outside press,\n * or the badge is pressed again, and focus returns to the badge. Pressing a badge\n * that is only peeking pins it rather than toggling it shut — the transitions\n * are the pure `nextCitationMode`.\n *\n * Kobalte's trigger toggles on every press, so `open` is controlled and its own\n * close request is ignored for the press that we already decided (`pressing`).\n * Without that, hover-then-click, the commonest pointer path, would close the card.\n *\n * ## It makes no claim without sources\n *\n * No sources renders nothing: a marker that points nowhere is not a citation.\n * The address is a link only when `safeSourceUrl` allows it; the host comes from\n * the parsed URL; titles and snippets are clipped, cleaned of direction\n * overrides and rendered as text. The badge's accessible name carries the title\n * and host (the visible label is only a number or a host), so a reader hears\n * what is cited without opening anything.\n */\nexport type InlineCitationProps = {\n /** One source, or several that support the same claim. */\n sources: readonly Source[]\n /**\n * The 1-based number to show, matching the source's position in `Sources`.\n * Omit it to show the host instead; a number is never guessed.\n */\n index?: number\n /** Milliseconds a pointer rests before the peek opens. */\n hoverDelay?: number\n class?: string\n}\n\nconst LEAVE_DELAY = 200\n\nexport function InlineCitation(props: InlineCitationProps) {\n const [local] = splitProps(props, ['sources', 'index', 'hoverDelay', 'class'])\n const [mode, setMode] = createSignal<CitationMode>('closed')\n const [position, setPosition] = createSignal(0)\n let timer: ReturnType<typeof setTimeout> | undefined\n let content: HTMLElement | undefined\n let pressing = false\n // Focus handed back to the badge as the popover closes is not a request to\n // peek again; without this, Escape from a pinned card reopens it as a preview.\n let restoringFocus = false\n\n const count = () => local.sources.length\n const active = () => local.sources[wrapIndex(position(), count())]\n const clear = () => {\n if (timer !== undefined) clearTimeout(timer)\n timer = undefined\n }\n onCleanup(clear)\n\n const dispatch = (event: CitationEvent) => setMode((current) => nextCitationMode(current, event))\n const schedule = (event: CitationEvent, delay: number) => {\n clear()\n timer = setTimeout(() => dispatch(event), delay)\n }\n\n const onPointerEnter = (event: PointerEvent) => {\n if (event.pointerType === 'touch') return\n schedule('enter', local.hoverDelay ?? 150)\n }\n const onPointerLeave = (event: PointerEvent) => {\n if (event.pointerType === 'touch') return\n schedule('leave', LEAVE_DELAY)\n }\n\n const onClick = () => {\n clear()\n const wasPeeking = mode() === 'peek'\n dispatch('press')\n // Kobalte toggles right after this handler; its request is not a dismissal.\n pressing = true\n queueMicrotask(() => {\n pressing = false\n })\n // The peek never took focus; a deliberate press must hand it over.\n if (wasPeeking) queueMicrotask(() => content?.focus())\n }\n\n return (\n <Show when={count() > 0}>\n <Popover\n open={mode() !== 'closed'}\n onOpenChange={(next) => {\n if (!next && !pressing) dispatch('dismiss')\n }}\n placement=\"bottom\"\n gutter={6}\n >\n <PopoverTrigger\n as={Button}\n variant=\"subtle\"\n size=\"2xs\"\n touchTarget=\"comfortable\"\n data-slot=\"inline-citation\"\n aria-label={citationName(local.sources, local.index)}\n class={cn('mx-0.5 align-baseline tabular-nums', local.class)}\n onClick={onClick}\n onPointerEnter={onPointerEnter}\n onPointerLeave={onPointerLeave}\n onFocus={(event: FocusEvent & { currentTarget: HTMLElement }) => {\n // Mouse focus follows the press; only keyboard focus peeks.\n if (restoringFocus) return\n if (event.currentTarget.matches(':focus-visible')) dispatch('focus')\n }}\n onBlur={() => dispatch('blur')}\n >\n <span aria-hidden=\"true\" class=\"max-w-32 truncate\">\n {citationLabel(local.index, local.sources[0])}\n </span>\n <Show when={count() > 1}>\n <span aria-hidden=\"true\">+{count() - 1}</span>\n </Show>\n </PopoverTrigger>\n <PopoverContent\n ref={(element: HTMLElement) => (content = element)}\n class=\"w-72 max-w-full\"\n onOpenAutoFocus={(event: Event) => {\n if (mode() === 'peek') event.preventDefault()\n }}\n onCloseAutoFocus={() => {\n // The focus move that follows is synchronous; the microtask ends the window.\n restoringFocus = true\n queueMicrotask(() => {\n restoringFocus = false\n })\n }}\n onPointerEnter={(event: PointerEvent) => {\n if (event.pointerType !== 'touch') clear()\n }}\n onPointerLeave={onPointerLeave}\n >\n <Show when={active()}>\n {(source) => (\n <div class=\"flex min-w-0 flex-col gap-1.5 px-2 py-1.5\">\n <Show when={count() > 1}>\n <div class=\"flex items-center justify-between gap-2\">\n <span\n role=\"status\"\n aria-live=\"polite\"\n class=\"text-xs text-muted-foreground tabular-nums\"\n >\n Source {wrapIndex(position(), count()) + 1} of {count()}\n </span>\n <span class=\"flex items-center gap-0.5\">\n <ActionButton\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label=\"Previous source\"\n tooltip=\"Previous source\"\n onClick={() => setPosition((value) => wrapIndex(value - 1, count()))}\n >\n <ChevronLeft />\n </ActionButton>\n <ActionButton\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label=\"Next source\"\n tooltip=\"Next source\"\n onClick={() => setPosition((value) => wrapIndex(value + 1, count()))}\n >\n <ChevronRight />\n </ActionButton>\n </span>\n </div>\n </Show>\n <PopoverTitle class=\"p-0 [overflow-wrap:anywhere]\">\n {sourceTitle(source())}\n </PopoverTitle>\n <CitationDetails source={source()} />\n </div>\n )}\n </Show>\n </PopoverContent>\n </Popover>\n </Show>\n )\n}\n\n/**\n * Citation markers for `MessageText`, from the sources a reply really used.\n *\n * `[^2]` in the text becomes the second source's badge; `[^1,3]` one badge for\n * sources 1 and 3. A number beyond the list leaves the marker as written, and an\n * empty list makes every marker literal, so text can never cite a source the host\n * did not supply.\n *\n * <MessageText text={reply} citations={messageCitations(sources)} />\n */\nexport function messageCitations(sources: readonly Source[]): MessageCitations {\n return {\n count: sources.length,\n render: (numbers) => (\n <InlineCitation\n index={numbers[0]}\n sources={numbers.flatMap((number) => {\n const source = sources[number - 1]\n return source ? [source] : []\n })}\n />\n ),\n }\n}\n\nfunction CitationDetails(props: { source: Source }) {\n const href = () => safeSourceUrl(props.source.url)\n const host = () => sourceHost(props.source.url)\n const snippet = () =>\n props.source.snippet ? boundText(props.source.snippet, SOURCE_SNIPPET_LIMIT) : ''\n const withheld = () => props.source.url !== undefined && props.source.url !== '' && !href()\n\n return (\n <>\n <Show when={host()}>\n <p class=\"m-0 text-xs text-muted-foreground [overflow-wrap:anywhere]\">{host()}</p>\n </Show>\n <Show when={href()}>\n {(url) => (\n <TextLink\n href={url()}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n class=\"w-fit max-w-full text-xs [overflow-wrap:anywhere]\"\n >\n {boundText(url(), 96)}\n <span class=\"visually-hidden\"> (opens in a new tab)</span>\n </TextLink>\n )}\n </Show>\n <Show when={withheld()}>\n <p class=\"m-0 text-xs text-muted-foreground\">Address not linked</p>\n </Show>\n <Show when={snippet()}>\n <p class=\"m-0 line-clamp-6 text-xs text-muted-foreground [overflow-wrap:anywhere]\">\n {snippet()}\n </p>\n </Show>\n </>\n )\n}\n"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { MessageScroller, type MessageScrollerProps } from './message-scroller';
2
+ export { captureAnchor, restoreAnchor, type ScrollAnchor } from './scroll-anchor';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/message-scroller/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAC/E,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAA"}
@@ -0,0 +1,3 @@
1
+ import { captureAnchor, restoreAnchor } from "./scroll-anchor.js";
2
+ import { MessageScroller } from "./message-scroller.js";
3
+ export { MessageScroller, captureAnchor, restoreAnchor };
@@ -0,0 +1,55 @@
1
+ import { type JSX } from 'solid-js';
2
+ import { type ConversationSurfaceProps } from '../../conversation/conversation-surface';
3
+ /**
4
+ * MessageScroller.
5
+ *
6
+ * The thread. It owns the three scroll behaviours a chat gets wrong when each
7
+ * is bolted on separately, and keeps them from fighting:
8
+ *
9
+ * 1. **Follow the reply only while the reader is at the bottom.** New and
10
+ * streaming content scrolls into view when the reader is already at the end,
11
+ * and never otherwise. Scrolling up parks the view; the "Jump to latest"
12
+ * control brings it back. (This is `ConversationSurface`'s follow contract,
13
+ * which this component wraps rather than reimplements.)
14
+ * 2. **Load history without moving what the reader is looking at.** When the
15
+ * reader reaches the top, `onLoadOlder` is asked for earlier turns. Turns
16
+ * inserted *above* the viewport would normally push the visible content down
17
+ * by exactly their height; here the first visible turn (found by
18
+ * `data-anchor-id`, which `Message` sets from `anchorId`) is measured before
19
+ * the load and put back to the same offset after it, on every layout change
20
+ * until the load settles — so images and code blocks that size themselves
21
+ * late do not jolt the view either. A "Load earlier" button is always present
22
+ * while there is more, because the scroll trigger alone is unreachable to a
23
+ * keyboard or switch user and fires nothing in a short pane.
24
+ * 3. **Announce without flooding.** The scroller is a polite log, and a turn that
25
+ * is still arriving marks itself `aria-busy`, so a screen reader waits for the
26
+ * settled turn instead of reading every token. `announcement` is a separate
27
+ * status region for the two moments that matter: a response starting and a
28
+ * response finishing.
29
+ *
30
+ * What it does not own: which turns exist, their identity, or what "older"
31
+ * means. The host passes children and a loader; a session switch is
32
+ * `resetKey`, which re-arms follow and discards any in-flight anchor.
33
+ */
34
+ export type MessageScrollerProps = Omit<ConversationSurfaceProps, 'header' | 'empty'> & {
35
+ /** There are earlier turns the host can load. */
36
+ hasOlder?: boolean;
37
+ /** The host is loading earlier turns right now. */
38
+ loadingOlder?: boolean;
39
+ /**
40
+ * Load earlier turns. The scroller preserves the reader's position across the
41
+ * resulting insert whether the host resolves before or after rendering them.
42
+ */
43
+ onLoadOlder?: () => void | Promise<void>;
44
+ /** Words for the loader row; override for another language. */
45
+ olderLabel?: string;
46
+ loadingOlderLabel?: string;
47
+ /** Rendered above the first turn, below the history control. */
48
+ header?: JSX.Element;
49
+ /** Rendered when there are no turns. */
50
+ empty?: JSX.Element;
51
+ /** A short sentence for the live status region ("Assistant is responding"). */
52
+ announcement?: string;
53
+ };
54
+ export declare function MessageScroller(props: MessageScrollerProps): JSX.Element;
55
+ //# sourceMappingURL=message-scroller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-scroller.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/message-scroller/message-scroller.tsx"],"names":[],"mappings":"AACA,OAAO,EAA2D,KAAK,GAAG,EAAE,MAAM,UAAU,CAAA;AAG5F,OAAO,EAEL,KAAK,wBAAwB,EAC9B,MAAM,yCAAyC,CAAA;AAGhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,wBAAwB,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG;IACtF,iDAAiD;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,mDAAmD;IACnD,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACxC,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,gEAAgE;IAChE,MAAM,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;IACpB,wCAAwC;IACxC,KAAK,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;IACnB,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAQD,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,eAwO1D"}
@@ -0,0 +1,201 @@
1
+ import { cn } from "../../../lib/utils.js";
2
+ import { Button } from "../../ui/button/button.js";
3
+ import { ConversationSurface } from "../../conversation/conversation-surface.js";
4
+ import { anchorIds, captureAnchor, restoreAnchor } from "./scroll-anchor.js";
5
+ import { className, createComponent, effect, insert, memo, mergeProps, template, use } from "solid-js/web";
6
+ import { History, LoaderCircle } from "lucide-solid";
7
+ import { Show, createEffect, createSignal, onCleanup, splitProps } from "solid-js";
8
+ //#region src/components/composites/message-scroller/message-scroller.tsx
9
+ var _tmpl$ = /*#__PURE__*/ template(`<div data-slot=message-scroller><p role=status class=sr-only>`);
10
+ var _tmpl$2 = /*#__PURE__*/ template(`<p role=status class="flex h-control-sm items-center gap-1.5 text-xs text-muted-foreground">`);
11
+ var _tmpl$3 = /*#__PURE__*/ template(`<div data-slot=message-scroller-older class="flex justify-center py-2">`);
12
+ /** How far from the top counts as "reached the top", in px. */
13
+ var TOP_MARGIN = 160;
14
+ /** How long a host that still reports `loadingOlder` is waited for, in frames (~10 s). */
15
+ var MAX_HOST_WAIT_FRAMES = 600;
16
+ function MessageScroller(props) {
17
+ const [local, rest] = splitProps(props, [
18
+ "class",
19
+ "hasOlder",
20
+ "loadingOlder",
21
+ "onLoadOlder",
22
+ "olderLabel",
23
+ "loadingOlderLabel",
24
+ "header",
25
+ "empty",
26
+ "announcement",
27
+ "ref",
28
+ "resetKey",
29
+ "children"
30
+ ]);
31
+ let scroller;
32
+ let holdFollow;
33
+ let epoch = 0;
34
+ const [inFlight, setInFlight] = createSignal(false);
35
+ let nativeAnchoring;
36
+ const holdNativeAnchoring = () => {
37
+ if (!scroller || nativeAnchoring !== void 0) return;
38
+ nativeAnchoring = scroller.style.overflowAnchor;
39
+ scroller.style.overflowAnchor = "none";
40
+ };
41
+ const releaseNativeAnchoring = () => {
42
+ if (scroller && nativeAnchoring !== void 0) scroller.style.overflowAnchor = nativeAnchoring;
43
+ nativeAnchoring = void 0;
44
+ };
45
+ createEffect(() => {
46
+ local.resetKey;
47
+ epoch += 1;
48
+ setInFlight(false);
49
+ stopWatching();
50
+ releaseNativeAnchoring();
51
+ });
52
+ const settle = (anchor, run, heightBefore, restoreFocus, releaseHold) => {
53
+ const finish = () => {
54
+ if (run !== epoch) return releaseHold?.();
55
+ if (scroller) restoreAnchor(scroller, anchor);
56
+ stopWatching();
57
+ releaseNativeAnchoring();
58
+ setInFlight(false);
59
+ if (restoreFocus && scroller && document.activeElement === document.body) (scroller.querySelector("[data-slot=\"message-scroller-older\"] button") ?? scroller).focus({ preventScroll: true });
60
+ if (scroller && local.hasOlder && scroller.scrollTop < TOP_MARGIN && scroller.scrollHeight > heightBefore) load();
61
+ releaseHold?.();
62
+ };
63
+ const wait = (waited) => requestAnimationFrame(() => {
64
+ if (run !== epoch) return releaseHold?.();
65
+ if (local.loadingOlder && waited < MAX_HOST_WAIT_FRAMES) return void wait(waited + 1);
66
+ finish();
67
+ });
68
+ requestAnimationFrame(() => wait(0));
69
+ };
70
+ let observer;
71
+ let resizer;
72
+ let unfollow;
73
+ const stopWatching = () => {
74
+ observer?.disconnect();
75
+ resizer?.disconnect();
76
+ unfollow?.();
77
+ unfollow = void 0;
78
+ };
79
+ const load = async (fromControl = false) => {
80
+ if (!scroller || !local.onLoadOlder || !local.hasOlder || local.loadingOlder || inFlight()) return;
81
+ const run = epoch;
82
+ const anchor = captureAnchor(scroller);
83
+ anchor.known = anchorIds(scroller);
84
+ const heightBefore = scroller.scrollHeight;
85
+ const restoreFocus = fromControl && document.activeElement?.closest("[data-slot=\"message-scroller-older\"]") != null;
86
+ setInFlight(true);
87
+ holdNativeAnchoring();
88
+ stopWatching();
89
+ observer = new MutationObserver(() => {
90
+ if (run === epoch && scroller) restoreAnchor(scroller, anchor);
91
+ });
92
+ observer.observe(scroller, {
93
+ childList: true,
94
+ subtree: true
95
+ });
96
+ const content = scroller.querySelector("[data-slot=\"conversation-content\"]");
97
+ if (content && typeof ResizeObserver !== "undefined") {
98
+ resizer = new ResizeObserver(() => {
99
+ if (run === epoch && scroller) restoreAnchor(scroller, anchor);
100
+ });
101
+ resizer.observe(content);
102
+ }
103
+ const follow = () => {
104
+ if (run === epoch && scroller) restoreAnchor(scroller, anchor);
105
+ };
106
+ scroller.addEventListener("scroll", follow, { passive: true });
107
+ const watched = scroller;
108
+ unfollow = () => watched.removeEventListener("scroll", follow);
109
+ try {
110
+ await local.onLoadOlder();
111
+ } catch {}
112
+ settle(anchor, run, heightBefore, restoreFocus, run !== epoch ? holdFollow?.() : void 0);
113
+ };
114
+ onCleanup(() => {
115
+ epoch += 1;
116
+ stopWatching();
117
+ releaseNativeAnchoring();
118
+ });
119
+ const watchTop = (element) => {
120
+ if (typeof IntersectionObserver === "undefined") return;
121
+ const io = new IntersectionObserver((entries) => {
122
+ if (entries.some((entry) => entry.isIntersecting)) load();
123
+ }, {
124
+ root: scroller ?? null,
125
+ rootMargin: `${TOP_MARGIN}px 0px 0px 0px`
126
+ });
127
+ io.observe(element);
128
+ onCleanup(() => io.disconnect());
129
+ };
130
+ return (() => {
131
+ var _el$ = _tmpl$(), _el$2 = _el$.firstChild;
132
+ insert(_el$, createComponent(ConversationSurface, mergeProps({
133
+ role: "log",
134
+ "aria-live": "polite",
135
+ "aria-relevant": "additions",
136
+ get resetKey() {
137
+ return local.resetKey;
138
+ },
139
+ onFollowHold: (hold) => {
140
+ holdFollow = hold;
141
+ }
142
+ }, rest, {
143
+ ref: (element) => {
144
+ scroller = element;
145
+ if (typeof local.ref === "function") local.ref(element);
146
+ },
147
+ "class": "flex-1",
148
+ get header() {
149
+ return [createComponent(Show, {
150
+ get when() {
151
+ return local.hasOlder || local.loadingOlder;
152
+ },
153
+ get children() {
154
+ var _el$3 = _tmpl$3();
155
+ use(watchTop, _el$3);
156
+ insert(_el$3, createComponent(Show, {
157
+ get when() {
158
+ return local.loadingOlder || inFlight();
159
+ },
160
+ get fallback() {
161
+ return createComponent(Button, {
162
+ type: "button",
163
+ variant: "ghost",
164
+ size: "sm",
165
+ "class": "gap-1.5 text-muted-foreground",
166
+ onClick: () => void load(true),
167
+ get children() {
168
+ return [createComponent(History, { "aria-hidden": "true" }), memo(() => local.olderLabel ?? "Load earlier messages")];
169
+ }
170
+ });
171
+ },
172
+ get children() {
173
+ var _el$4 = _tmpl$2();
174
+ insert(_el$4, createComponent(LoaderCircle, {
175
+ "aria-hidden": "true",
176
+ "class": "size-3.5 motion-safe:animate-spin"
177
+ }), null);
178
+ insert(_el$4, () => local.loadingOlderLabel ?? "Loading earlier messages…", null);
179
+ return _el$4;
180
+ }
181
+ }));
182
+ return _el$3;
183
+ }
184
+ }), memo(() => local.header)];
185
+ },
186
+ get empty() {
187
+ return local.empty;
188
+ },
189
+ get children() {
190
+ return local.children;
191
+ }
192
+ })), _el$2);
193
+ insert(_el$2, () => local.announcement);
194
+ effect(() => className(_el$, cn("relative flex min-h-0 flex-1 flex-col", local.class)));
195
+ return _el$;
196
+ })();
197
+ }
198
+ //#endregion
199
+ export { MessageScroller };
200
+
201
+ //# sourceMappingURL=message-scroller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-scroller.js","names":["History","LoaderCircle","createEffect","onCleanup","Show","splitProps","createSignal","JSX","cn","Button","ConversationSurface","ConversationSurfaceProps","anchorIds","captureAnchor","restoreAnchor","ScrollAnchor","MessageScrollerProps","Omit","hasOlder","loadingOlder","onLoadOlder","Promise","olderLabel","loadingOlderLabel","header","Element","empty","announcement","TOP_MARGIN","MAX_HOST_WAIT_FRAMES","MessageScroller","props","local","rest","scroller","HTMLDivElement","holdFollow","epoch","inFlight","setInFlight","nativeAnchoring","holdNativeAnchoring","undefined","style","overflowAnchor","releaseNativeAnchoring","resetKey","stopWatching","settle","anchor","run","heightBefore","restoreFocus","releaseHold","finish","document","activeElement","body","again","querySelector","HTMLElement","focus","preventScroll","scrollTop","scrollHeight","load","wait","waited","requestAnimationFrame","observer","MutationObserver","resizer","ResizeObserver","unfollow","disconnect","fromControl","known","closest","observe","childList","subtree","content","follow","addEventListener","passive","watched","removeEventListener","watchTop","element","IntersectionObserver","io","entries","some","entry","isIntersecting","root","rootMargin","_el$","_tmpl$","_el$2","firstChild","_$insert","_$createComponent","_$mergeProps","role","onFollowHold","hold","ref","when","children","_el$3","_tmpl$3","_$use","fallback","type","variant","size","onClick","_$memo","_el$4","_tmpl$2","_$effect","_$className","class","_$createComponent","_$mergeProps","_$memo","_$className"],"sources":["../../../../src/components/composites/message-scroller/message-scroller.tsx"],"sourcesContent":["import { History, LoaderCircle } from 'lucide-solid'\nimport { createEffect, onCleanup, Show, splitProps, createSignal, type JSX } from 'solid-js'\nimport { cn } from '#lib/utils'\nimport { Button } from '../../ui/button'\nimport {\n ConversationSurface,\n type ConversationSurfaceProps,\n} from '../../conversation/conversation-surface'\nimport { anchorIds, captureAnchor, restoreAnchor, type ScrollAnchor } from './scroll-anchor'\n\n/**\n * MessageScroller.\n *\n * The thread. It owns the three scroll behaviours a chat gets wrong when each\n * is bolted on separately, and keeps them from fighting:\n *\n * 1. **Follow the reply only while the reader is at the bottom.** New and\n * streaming content scrolls into view when the reader is already at the end,\n * and never otherwise. Scrolling up parks the view; the \"Jump to latest\"\n * control brings it back. (This is `ConversationSurface`'s follow contract,\n * which this component wraps rather than reimplements.)\n * 2. **Load history without moving what the reader is looking at.** When the\n * reader reaches the top, `onLoadOlder` is asked for earlier turns. Turns\n * inserted *above* the viewport would normally push the visible content down\n * by exactly their height; here the first visible turn (found by\n * `data-anchor-id`, which `Message` sets from `anchorId`) is measured before\n * the load and put back to the same offset after it, on every layout change\n * until the load settles — so images and code blocks that size themselves\n * late do not jolt the view either. A \"Load earlier\" button is always present\n * while there is more, because the scroll trigger alone is unreachable to a\n * keyboard or switch user and fires nothing in a short pane.\n * 3. **Announce without flooding.** The scroller is a polite log, and a turn that\n * is still arriving marks itself `aria-busy`, so a screen reader waits for the\n * settled turn instead of reading every token. `announcement` is a separate\n * status region for the two moments that matter: a response starting and a\n * response finishing.\n *\n * What it does not own: which turns exist, their identity, or what \"older\"\n * means. The host passes children and a loader; a session switch is\n * `resetKey`, which re-arms follow and discards any in-flight anchor.\n */\nexport type MessageScrollerProps = Omit<ConversationSurfaceProps, 'header' | 'empty'> & {\n /** There are earlier turns the host can load. */\n hasOlder?: boolean\n /** The host is loading earlier turns right now. */\n loadingOlder?: boolean\n /**\n * Load earlier turns. The scroller preserves the reader's position across the\n * resulting insert whether the host resolves before or after rendering them.\n */\n onLoadOlder?: () => void | Promise<void>\n /** Words for the loader row; override for another language. */\n olderLabel?: string\n loadingOlderLabel?: string\n /** Rendered above the first turn, below the history control. */\n header?: JSX.Element\n /** Rendered when there are no turns. */\n empty?: JSX.Element\n /** A short sentence for the live status region (\"Assistant is responding\"). */\n announcement?: string\n}\n\n/** How far from the top counts as \"reached the top\", in px. */\nconst TOP_MARGIN = 160\n\n/** How long a host that still reports `loadingOlder` is waited for, in frames (~10 s). */\nconst MAX_HOST_WAIT_FRAMES = 600\n\nexport function MessageScroller(props: MessageScrollerProps) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'hasOlder',\n 'loadingOlder',\n 'onLoadOlder',\n 'olderLabel',\n 'loadingOlderLabel',\n 'header',\n 'empty',\n 'announcement',\n 'ref',\n 'resetKey',\n 'children',\n ])\n let scroller: HTMLDivElement | undefined\n let holdFollow: (() => () => void) | undefined\n let epoch = 0\n const [inFlight, setInFlight] = createSignal(false)\n\n // While a load holds the reader's place, the browser's own scroll anchoring is\n // switched off: it moves the offset by the same insert, and the two corrections\n // would be added together.\n let nativeAnchoring: string | undefined\n const holdNativeAnchoring = () => {\n if (!scroller || nativeAnchoring !== undefined) return\n nativeAnchoring = scroller.style.overflowAnchor\n scroller.style.overflowAnchor = 'none'\n }\n const releaseNativeAnchoring = () => {\n if (scroller && nativeAnchoring !== undefined) scroller.style.overflowAnchor = nativeAnchoring\n nativeAnchoring = undefined\n }\n\n // A session switch invalidates a load that was started for the previous one.\n createEffect(() => {\n void local.resetKey\n epoch += 1\n setInFlight(false)\n stopWatching()\n releaseNativeAnchoring()\n })\n\n const settle = (\n anchor: ScrollAnchor | undefined,\n run: number,\n heightBefore: number,\n restoreFocus: boolean,\n releaseHold?: () => void\n ) => {\n const finish = () => {\n if (run !== epoch) return releaseHold?.()\n if (scroller) restoreAnchor(scroller, anchor)\n stopWatching()\n releaseNativeAnchoring()\n setInFlight(false)\n // The control that started the load was replaced by the loading line, which\n // takes focus with it. Put it back on the control (or the thread), so a\n // keyboard user is not dropped onto the page.\n if (restoreFocus && scroller && document.activeElement === document.body) {\n const again = scroller.querySelector<HTMLElement>(\n '[data-slot=\"message-scroller-older\"] button'\n )\n ;(again ?? scroller).focus({ preventScroll: true })\n }\n // Still at the top after a load that added content: keep going, so a\n // pane taller than one page of history fills without a second scroll.\n if (\n scroller &&\n local.hasOlder &&\n scroller.scrollTop < TOP_MARGIN &&\n scroller.scrollHeight > heightBefore\n )\n void load()\n releaseHold?.()\n }\n // Two frames: the first lets the host's insert commit, the second lets\n // late-sizing content (images, highlighted code) report its height. A host\n // that says it is still loading (`loadingOlder`) after its promise resolved\n // is not finished either: its turns will land later, and the anchor must\n // still be held when they do.\n const wait = (waited: number) =>\n requestAnimationFrame(() => {\n if (run !== epoch) return releaseHold?.()\n if (local.loadingOlder && waited < MAX_HOST_WAIT_FRAMES) return void wait(waited + 1)\n finish()\n })\n requestAnimationFrame(() => wait(0))\n }\n\n let observer: MutationObserver | undefined\n let resizer: ResizeObserver | undefined\n let unfollow: (() => void) | undefined\n const stopWatching = () => {\n observer?.disconnect()\n resizer?.disconnect()\n unfollow?.()\n unfollow = undefined\n }\n const load = async (fromControl = false) => {\n if (!scroller || !local.onLoadOlder || !local.hasOlder || local.loadingOlder || inFlight())\n return\n const run = epoch\n const anchor = captureAnchor(scroller)\n anchor.known = anchorIds(scroller)\n const heightBefore = scroller.scrollHeight\n const restoreFocus =\n fromControl && document.activeElement?.closest('[data-slot=\"message-scroller-older\"]') != null\n setInFlight(true)\n holdNativeAnchoring()\n // Every layout change while the load is open re-pins the anchor *before\n // paint*, which is what makes the insert invisible.\n stopWatching()\n observer = new MutationObserver(() => {\n if (run === epoch && scroller) restoreAnchor(scroller, anchor)\n })\n observer.observe(scroller, { childList: true, subtree: true })\n // Turns that size themselves late (`content-visibility`, images, highlighted code)\n // move the anchor without adding or removing a node, and with the browser's own\n // anchoring held off nothing else would carry the reader through that.\n const content = scroller.querySelector('[data-slot=\"conversation-content\"]')\n if (content && typeof ResizeObserver !== 'undefined') {\n resizer = new ResizeObserver(() => {\n if (run === epoch && scroller) restoreAnchor(scroller, anchor)\n })\n resizer.observe(content)\n }\n // The reader may carry on scrolling while the host answers. A restore re-takes the\n // anchor on the turn they have come to, whichever of the observers or this event\n // reaches it first.\n const follow = () => {\n if (run === epoch && scroller) restoreAnchor(scroller, anchor)\n }\n scroller.addEventListener('scroll', follow, { passive: true })\n const watched = scroller\n unfollow = () => watched.removeEventListener('scroll', follow)\n try {\n await local.onLoadOlder()\n } catch {\n // The host reports its own failure; the control stays so the reader can retry.\n }\n // A load that outlived its conversation inserts into a thread whose reader it knows\n // nothing about, and the anchor it held is gone. What it does to the layout (rows\n // taking their height, a clamp, the insert itself) is not the reader scrolling, so the\n // follow position is held until the two frames the insert needs have passed.\n settle(anchor, run, heightBefore, restoreFocus, run !== epoch ? holdFollow?.() : undefined)\n }\n\n onCleanup(() => {\n epoch += 1\n stopWatching()\n releaseNativeAnchoring()\n })\n\n const watchTop = (element: HTMLDivElement) => {\n if (typeof IntersectionObserver === 'undefined') return\n const io = new IntersectionObserver(\n (entries) => {\n if (entries.some((entry) => entry.isIntersecting)) void load()\n },\n { root: scroller ?? null, rootMargin: `${TOP_MARGIN}px 0px 0px 0px` }\n )\n io.observe(element)\n onCleanup(() => io.disconnect())\n }\n\n return (\n <div\n class={cn('relative flex min-h-0 flex-1 flex-col', local.class)}\n data-slot=\"message-scroller\"\n >\n <ConversationSurface\n role=\"log\"\n aria-live=\"polite\"\n aria-relevant=\"additions\"\n resetKey={local.resetKey}\n onFollowHold={(hold) => {\n holdFollow = hold\n }}\n {...rest}\n ref={(element) => {\n scroller = element\n if (typeof local.ref === 'function') local.ref(element)\n }}\n class=\"flex-1\"\n header={\n <>\n <Show when={local.hasOlder || local.loadingOlder}>\n <div\n ref={watchTop}\n data-slot=\"message-scroller-older\"\n class=\"flex justify-center py-2\"\n >\n <Show\n when={local.loadingOlder || inFlight()}\n fallback={\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n class=\"gap-1.5 text-muted-foreground\"\n onClick={() => void load(true)}\n >\n <History aria-hidden=\"true\" />\n {local.olderLabel ?? 'Load earlier messages'}\n </Button>\n }\n >\n <p\n role=\"status\"\n // The button's own height: swapping one for the other must not move\n // the turns below it by even a pixel while the anchor is being held.\n class=\"flex h-control-sm items-center gap-1.5 text-xs text-muted-foreground\"\n >\n <LoaderCircle aria-hidden=\"true\" class=\"size-3.5 motion-safe:animate-spin\" />\n {local.loadingOlderLabel ?? 'Loading earlier messages…'}\n </p>\n </Show>\n </div>\n </Show>\n {local.header}\n </>\n }\n empty={local.empty}\n >\n {local.children}\n </ConversationSurface>\n <p role=\"status\" class=\"sr-only\">\n {local.announcement}\n </p>\n </div>\n )\n}\n"],"mappings":"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"}