themelia-react-ui 2.0.1 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (480) hide show
  1. package/CHANGELOG.md +307 -131
  2. package/README.md +28 -8
  3. package/THIRD_PARTY_NOTICES.md +13 -0
  4. package/dist/{accordion-B6a3vVgA.js → accordion-Cjb6sx0G.js} +14 -13
  5. package/dist/accordion-Cjb6sx0G.js.map +1 -0
  6. package/dist/action-menu-CllU52Mm.js +280 -0
  7. package/dist/action-menu-CllU52Mm.js.map +1 -0
  8. package/dist/affordance-geometry.generated-tF36bREk.js +140 -0
  9. package/dist/affordance-geometry.generated-tF36bREk.js.map +1 -0
  10. package/dist/ai-artifact-DvTwDVyL.js +1148 -0
  11. package/dist/ai-artifact-DvTwDVyL.js.map +1 -0
  12. package/dist/{app-shell-ZK5RWdo6.js → app-shell-C4FhvCqF.js} +5 -5
  13. package/dist/{app-shell-ZK5RWdo6.js.map → app-shell-C4FhvCqF.js.map} +1 -1
  14. package/dist/attachment-BxDfL2mw.js +246 -0
  15. package/dist/attachment-BxDfL2mw.js.map +1 -0
  16. package/dist/{auth-CYxKfo69.js → auth-ax2BqjrI.js} +58 -54
  17. package/dist/auth-ax2BqjrI.js.map +1 -0
  18. package/dist/{avatar-BBnEJIx8.js → avatar-DAPlDvhJ.js} +7 -7
  19. package/dist/avatar-DAPlDvhJ.js.map +1 -0
  20. package/dist/{badge-MrKVNzW9.js → badge-HpFqoqSY.js} +40 -40
  21. package/dist/badge-HpFqoqSY.js.map +1 -0
  22. package/dist/base/accordion.js +1 -1
  23. package/dist/base/action-menu.js +1 -1
  24. package/dist/base/attachment.js +1 -1
  25. package/dist/base/avatar.js +1 -1
  26. package/dist/base/badge.js +1 -1
  27. package/dist/base/batch-action-bar.js +1 -1
  28. package/dist/base/buttons.js +1 -1
  29. package/dist/base/cards.js +2 -2
  30. package/dist/base/carousel.js +40 -36
  31. package/dist/base/carousel.js.map +1 -1
  32. package/dist/base/cascader.js +92 -92
  33. package/dist/base/cascader.js.map +1 -1
  34. package/dist/base/chart.js +1 -1
  35. package/dist/base/choice-inputs.js +2 -2
  36. package/dist/base/code-block.js +1 -1
  37. package/dist/base/combobox.js +2 -2
  38. package/dist/base/command.js +1 -1
  39. package/dist/base/copyable.js +1 -1
  40. package/dist/base/date-pickers.js +2 -2
  41. package/dist/base/display.js +6 -6
  42. package/dist/base/feedback.js +3 -3
  43. package/dist/base/forms-numeric.js +1 -1
  44. package/dist/base/forms.js +2 -2
  45. package/dist/base/inline-edit.js +14 -14
  46. package/dist/base/inline-edit.js.map +1 -1
  47. package/dist/base/item.js +1 -1
  48. package/dist/base/media-gallery.js +1 -1
  49. package/dist/base/metadata-list.js +1 -1
  50. package/dist/base/navigation.js +6 -6
  51. package/dist/base/popover-menu.js +1 -1
  52. package/dist/base/popover.js +1 -1
  53. package/dist/base/qr-code.js +1 -1
  54. package/dist/base/repeaters.js +171 -176
  55. package/dist/base/repeaters.js.map +1 -1
  56. package/dist/base/sheet.js +1 -1
  57. package/dist/base/sidebar.js +1 -1
  58. package/dist/base/signature-pad.js +6 -6
  59. package/dist/base/skeleton.js +1 -1
  60. package/dist/base/spinner.js +79 -2
  61. package/dist/base/spinner.js.map +1 -0
  62. package/dist/base/structure.js +1 -1
  63. package/dist/base/table.js +1 -1
  64. package/dist/base/text-inputs.js +2 -2
  65. package/dist/base/toaster.js +46 -45
  66. package/dist/base/toaster.js.map +1 -1
  67. package/dist/base/tree.js +1 -1
  68. package/dist/base/upload-queue.js +1 -1
  69. package/dist/base/upload.js +3 -3
  70. package/dist/base/value-inputs.js +1 -1
  71. package/dist/{batch-action-bar-BZGDG-Si.js → batch-action-bar-DnUJ21NQ.js} +6 -5
  72. package/dist/batch-action-bar-DnUJ21NQ.js.map +1 -0
  73. package/dist/blocks/admin.js +42 -42
  74. package/dist/blocks/admin.js.map +1 -1
  75. package/dist/blocks/ai.js +260 -240
  76. package/dist/blocks/ai.js.map +1 -1
  77. package/dist/blocks/analytics/usage-card.js +1 -1
  78. package/dist/blocks/analytics.js +620 -585
  79. package/dist/blocks/analytics.js.map +1 -1
  80. package/dist/blocks/collaboration.js +1 -1
  81. package/dist/blocks/commerce/receipt.js +1 -1
  82. package/dist/blocks/commerce.js +1152 -1109
  83. package/dist/blocks/commerce.js.map +1 -1
  84. package/dist/blocks/data-display.js +2 -2
  85. package/dist/blocks/onboarding.js +48 -39
  86. package/dist/blocks/onboarding.js.map +1 -1
  87. package/dist/blocks/planning.js +13 -12
  88. package/dist/blocks/planning.js.map +1 -1
  89. package/dist/blocks/timelines.js +1 -1
  90. package/dist/{breadcrumbs-D5t7I023.js → breadcrumbs-C-oqs1sQ.js} +5 -5
  91. package/dist/breadcrumbs-C-oqs1sQ.js.map +1 -0
  92. package/dist/{button-QYwiyhD2.js → button-DVzspB_G.js} +2 -2
  93. package/dist/{button-QYwiyhD2.js.map → button-DVzspB_G.js.map} +1 -1
  94. package/dist/{buttons-SbIcm1HJ.js → buttons-DPZekJFu.js} +20 -15
  95. package/dist/buttons-DPZekJFu.js.map +1 -0
  96. package/dist/cards-BaBZR-AU.js +68 -0
  97. package/dist/cards-BaBZR-AU.js.map +1 -0
  98. package/dist/{chart-QfrARkXl.js → chart-ZOYyK2xG.js} +58 -55
  99. package/dist/chart-ZOYyK2xG.js.map +1 -0
  100. package/dist/{checkbox-DhB6K0bK.js → checkbox-AWIhNhmo.js} +2 -2
  101. package/dist/{checkbox-DhB6K0bK.js.map → checkbox-AWIhNhmo.js.map} +1 -1
  102. package/dist/{choice-inputs-t6w3ATNz.js → choice-inputs-CNHvARCJ.js} +49 -45
  103. package/dist/choice-inputs-CNHvARCJ.js.map +1 -0
  104. package/dist/{code-block-Dgbu-CU3.js → code-block-DeneBJR_.js} +8 -8
  105. package/dist/code-block-DeneBJR_.js.map +1 -0
  106. package/dist/{collapsible-D8AEGU1-.js → collapsible-C-_l4hpy.js} +3 -3
  107. package/dist/{collapsible-D8AEGU1-.js.map → collapsible-C-_l4hpy.js.map} +1 -1
  108. package/dist/{collection-content-uK16Grv0.js → collection-content-By56pLog.js} +3 -3
  109. package/dist/{collection-content-uK16Grv0.js.map → collection-content-By56pLog.js.map} +1 -1
  110. package/dist/combobox-C0EQW6dr.js +875 -0
  111. package/dist/combobox-C0EQW6dr.js.map +1 -0
  112. package/dist/combobox-xCQ2RMNE.js +309 -0
  113. package/dist/combobox-xCQ2RMNE.js.map +1 -0
  114. package/dist/{command-kNR20o7x.js → command-C25VMRII.js} +7 -7
  115. package/dist/{command-kNR20o7x.js.map → command-C25VMRII.js.map} +1 -1
  116. package/dist/{comments-BpDuCUUu.js → comments-BYYlTA8E.js} +114 -105
  117. package/dist/comments-BYYlTA8E.js.map +1 -0
  118. package/dist/components/base/badge/badge.recipes.d.ts +1 -1
  119. package/dist/components/base/buttons/loader-button.d.ts +2 -1
  120. package/dist/components/base/cards/card.recipes.d.ts +2 -3
  121. package/dist/components/base/cards/partials/smart-card-skeleton.d.ts +3 -13
  122. package/dist/components/base/cards/smart-card.types.d.ts +11 -4
  123. package/dist/components/base/chart/chart.d.ts +2 -5
  124. package/dist/components/base/combobox/combobox.strings.d.ts +7 -0
  125. package/dist/components/base/combobox/index.d.ts +30 -4
  126. package/dist/components/base/forms/form-sizing.d.ts +11 -3
  127. package/dist/components/base/navigation/pagination.d.ts +5 -2
  128. package/dist/components/base/popover/popover.recipes.d.ts +15 -1
  129. package/dist/components/base/table/index.d.ts +9 -2
  130. package/dist/components/base/text-inputs/input-group.d.ts +2 -2
  131. package/dist/components/blocks/ai/ai-shimmer/ai-shimmer.d.ts +1 -1
  132. package/dist/components/blocks/ai/ai-shimmer/types.d.ts +3 -0
  133. package/dist/components/blocks/commerce/fulfillment-group/types.d.ts +3 -1
  134. package/dist/components/blocks/data-display/inline-stat/inline-stat.d.ts +16 -8
  135. package/dist/components/features/activities/partials/activity-marker.d.ts +6 -3
  136. package/dist/components/features/appointment-calendar/appointment-calendar.d.ts +5 -0
  137. package/dist/components/features/appointment-calendar/appointment-calendar.types.d.ts +220 -0
  138. package/dist/components/features/appointment-calendar/appointment-calendar.utils.d.ts +41 -0
  139. package/dist/components/features/appointment-calendar/index.d.ts +3 -0
  140. package/dist/components/features/appointment-calendar/partials/appointment-agenda.d.ts +32 -0
  141. package/dist/components/features/appointment-calendar/partials/appointment-month.d.ts +13 -0
  142. package/dist/components/features/combobox/combobox.strings.d.ts +15 -1
  143. package/dist/components/features/combobox/types.d.ts +4 -0
  144. package/dist/components/features/media-library/media-library.strings.d.ts +2 -0
  145. package/dist/components/features/rich-text-editor/index.d.ts +1 -1
  146. package/dist/components/features/rich-text-editor/rich-text-editor.recipes.d.ts +6 -0
  147. package/dist/components/features/rich-text-editor/rich-text-editor.types.d.ts +9 -1
  148. package/dist/components/features/table/table-header.d.ts +1 -1
  149. package/dist/components/features/table/table.strings.d.ts +55 -1
  150. package/dist/components/features/table/table.types.d.ts +17 -4
  151. package/dist/components/features/theme-tweaker/theme-tweaker.types.d.ts +5 -0
  152. package/dist/components/primitives/number.d.ts +4 -2
  153. package/dist/components/primitives/value.d.ts +3 -1
  154. package/dist/components/typography/text-link.d.ts +4 -0
  155. package/dist/components/ui/combobox.d.ts +6 -2
  156. package/dist/components/ui/item.d.ts +8 -8
  157. package/dist/components/ui/tabs.d.ts +1 -1
  158. package/dist/{containers-DmWiJa2I.js → containers-Mu1LMGV1.js} +2 -2
  159. package/dist/{containers-DmWiJa2I.js.map → containers-Mu1LMGV1.js.map} +1 -1
  160. package/dist/{copyable-B3Gwgdqc.js → copyable-ClBuk_UK.js} +4 -4
  161. package/dist/{copyable-B3Gwgdqc.js.map → copyable-ClBuk_UK.js.map} +1 -1
  162. package/dist/{data-display-DafIvCl5.js → data-display-DT_khPl_.js} +98 -87
  163. package/dist/data-display-DT_khPl_.js.map +1 -0
  164. package/dist/{date-BgK3bTdo.js → date-DCrsDTZc.js} +5 -5
  165. package/dist/{date-BgK3bTdo.js.map → date-DCrsDTZc.js.map} +1 -1
  166. package/dist/{date-picker-CF-DtUpF.js → date-picker-ay0Pha_a.js} +594 -593
  167. package/dist/date-picker-ay0Pha_a.js.map +1 -0
  168. package/dist/date-pickers-Ccw8DL2b.js +175 -0
  169. package/dist/date-pickers-Ccw8DL2b.js.map +1 -0
  170. package/dist/{display-DsQTVzMz.js → display-hAc1HjpI.js} +49 -49
  171. package/dist/display-hAc1HjpI.js.map +1 -0
  172. package/dist/dropdown-menu-Cl4X7L5S.js +193 -0
  173. package/dist/dropdown-menu-Cl4X7L5S.js.map +1 -0
  174. package/dist/editable-text-recipe-Cn61kEcv.js +10 -0
  175. package/dist/editable-text-recipe-Cn61kEcv.js.map +1 -0
  176. package/dist/features/activities.js +398 -375
  177. package/dist/features/activities.js.map +1 -1
  178. package/dist/features/ai-chat.js +188 -179
  179. package/dist/features/ai-chat.js.map +1 -1
  180. package/dist/features/appointment-calendar.js +683 -0
  181. package/dist/features/appointment-calendar.js.map +1 -0
  182. package/dist/features/async-preview.js +109 -107
  183. package/dist/features/async-preview.js.map +1 -1
  184. package/dist/features/combobox.js +1 -1
  185. package/dist/features/comments.js +1 -1
  186. package/dist/features/data-view.js +137 -137
  187. package/dist/features/data-view.js.map +1 -1
  188. package/dist/features/email-composer.js +255 -255
  189. package/dist/features/email-composer.js.map +1 -1
  190. package/dist/features/event-calendar.js +254 -248
  191. package/dist/features/event-calendar.js.map +1 -1
  192. package/dist/features/filters.js +1 -1
  193. package/dist/features/global-search.js +35 -32
  194. package/dist/features/global-search.js.map +1 -1
  195. package/dist/features/kanban.js +118 -117
  196. package/dist/features/kanban.js.map +1 -1
  197. package/dist/features/map.js +233 -231
  198. package/dist/features/map.js.map +1 -1
  199. package/dist/features/media-library.js +789 -775
  200. package/dist/features/media-library.js.map +1 -1
  201. package/dist/features/mentions.js +1 -1
  202. package/dist/features/overlays.js +1 -1
  203. package/dist/features/products.js +922 -902
  204. package/dist/features/products.js.map +1 -1
  205. package/dist/features/questionnaire.js +28 -24
  206. package/dist/features/questionnaire.js.map +1 -1
  207. package/dist/features/resource-assignment.js +18 -15
  208. package/dist/features/resource-assignment.js.map +1 -1
  209. package/dist/features/resource.js +12 -12
  210. package/dist/features/resource.js.map +1 -1
  211. package/dist/features/rich-text-editor.js +2 -2
  212. package/dist/features/schema-form.js +15 -13
  213. package/dist/features/schema-form.js.map +1 -1
  214. package/dist/features/suggestions.js +3 -3
  215. package/dist/features/sync.js +11 -5
  216. package/dist/features/sync.js.map +1 -1
  217. package/dist/features/table.js +1 -1
  218. package/dist/features/theme-tweaker.js +493 -489
  219. package/dist/features/theme-tweaker.js.map +1 -1
  220. package/dist/feedback-BYIhtitP.js +239 -0
  221. package/dist/feedback-BYIhtitP.js.map +1 -0
  222. package/dist/{field-affordance-recipes-qQeIf4lG.js → field-affordance-recipes-DZhnIL_Y.js} +11 -18
  223. package/dist/field-affordance-recipes-DZhnIL_Y.js.map +1 -0
  224. package/dist/{filters-BkHH53uv.js → filters-BGfvjP4d.js} +589 -580
  225. package/dist/filters-BGfvjP4d.js.map +1 -0
  226. package/dist/{form-field-DUt4UxSV.js → form-field-CwH9y77i.js} +6 -5
  227. package/dist/form-field-CwH9y77i.js.map +1 -0
  228. package/dist/{form-sizing-By94KzXE.js → form-sizing-BdP_Mf5p.js} +39 -44
  229. package/dist/form-sizing-BdP_Mf5p.js.map +1 -0
  230. package/dist/{forms-Bzha-Y3B.js → forms-B9G_xwzi.js} +8 -8
  231. package/dist/{forms-Bzha-Y3B.js.map → forms-B9G_xwzi.js.map} +1 -1
  232. package/dist/{forms-numeric-C0bvjRPZ.js → forms-numeric-B_jraJaQ.js} +309 -309
  233. package/dist/forms-numeric-B_jraJaQ.js.map +1 -0
  234. package/dist/{header-BOefOKd1.js → header-CGXuhcRm.js} +160 -153
  235. package/dist/header-CGXuhcRm.js.map +1 -0
  236. package/dist/{hooks-9k_TtmKh.js → hooks-Dkz0K2WT.js} +2 -2
  237. package/dist/{hooks-9k_TtmKh.js.map → hooks-Dkz0K2WT.js.map} +1 -1
  238. package/dist/{icon-badge-CAuKupo9.js → icon-badge-DYKIwvOV.js} +4 -4
  239. package/dist/{icon-badge-CAuKupo9.js.map → icon-badge-DYKIwvOV.js.map} +1 -1
  240. package/dist/index.js +3 -3
  241. package/dist/input-CZw8iU99.js +21 -0
  242. package/dist/input-CZw8iU99.js.map +1 -0
  243. package/dist/input-DQdEd0YD.js +263 -0
  244. package/dist/input-DQdEd0YD.js.map +1 -0
  245. package/dist/{interaction-recipes-CHr0dJUs.js → interaction-recipes-XR9ZpVYL.js} +2 -1
  246. package/dist/interaction-recipes-XR9ZpVYL.js.map +1 -0
  247. package/dist/item-K5_ghvze.js +275 -0
  248. package/dist/item-K5_ghvze.js.map +1 -0
  249. package/dist/layout/app-shell.js +1 -1
  250. package/dist/layout/auth.js +1 -1
  251. package/dist/layout/containers.js +1 -1
  252. package/dist/layout/header.js +1 -1
  253. package/dist/layout/hooks.js +1 -1
  254. package/dist/layout/navigation.js +1 -1
  255. package/dist/layout/page.js +1 -1
  256. package/dist/layout/settings.js +1 -1
  257. package/dist/layout/sidebar.js +2 -2
  258. package/dist/layout/workspace.js +1 -1
  259. package/dist/layout.js +10 -10
  260. package/dist/lib/affordance-geometry.generated.d.ts +71 -0
  261. package/dist/lib/editable-text-recipe.d.ts +4 -4
  262. package/dist/lib/field-affordance-recipes.d.ts +2 -2
  263. package/dist/lib/interaction-recipes.d.ts +5 -0
  264. package/dist/lib/theme-mode-css.d.ts +7 -0
  265. package/dist/lib/tone-recipes.d.ts +8 -0
  266. package/dist/lib/ui-provider/types.d.ts +2 -2
  267. package/dist/lib/utils.js +1 -1
  268. package/dist/{media-gallery-DcTtAaeC.js → media-gallery-3zIVLMWH.js} +8 -8
  269. package/dist/media-gallery-3zIVLMWH.js.map +1 -0
  270. package/dist/{mentions-D-uyCh01.js → mentions-utuUvH1K.js} +144 -142
  271. package/dist/mentions-utuUvH1K.js.map +1 -0
  272. package/dist/{message-CdHgIWKf.js → message-DZ_ruyUV.js} +6 -5
  273. package/dist/message-DZ_ruyUV.js.map +1 -0
  274. package/dist/{metadata-list-X5rYAKSB.js → metadata-list-8N16ZMW_.js} +130 -119
  275. package/dist/metadata-list-8N16ZMW_.js.map +1 -0
  276. package/dist/{navigation-D3KwXmaq.js → navigation-Bnotn4AQ.js} +19 -19
  277. package/dist/navigation-Bnotn4AQ.js.map +1 -0
  278. package/dist/{navigation-HJf5zxlH.js → navigation-BzhHI3lo.js} +36 -35
  279. package/dist/navigation-BzhHI3lo.js.map +1 -0
  280. package/dist/{navigation-row-recipes-BVowojQw.js → navigation-row-recipes-BFLCk_Aq.js} +2 -2
  281. package/dist/{navigation-row-recipes-BVowojQw.js.map → navigation-row-recipes-BFLCk_Aq.js.map} +1 -1
  282. package/dist/{number-DMhe-Vsk.js → number-DbV1Dija.js} +36 -34
  283. package/dist/{number-DMhe-Vsk.js.map → number-DbV1Dija.js.map} +1 -1
  284. package/dist/{overflow-tab-bar-sQHXLlwQ.js → overflow-tab-bar-CWY7Nogn.js} +105 -103
  285. package/dist/overflow-tab-bar-CWY7Nogn.js.map +1 -0
  286. package/dist/{overlays-I0axtYA6.js → overlays-DNWmZrJ4.js} +14 -12
  287. package/dist/overlays-DNWmZrJ4.js.map +1 -0
  288. package/dist/{page-B5dTH9gE.js → page-Bgl1F560.js} +8 -8
  289. package/dist/{page-B5dTH9gE.js.map → page-Bgl1F560.js.map} +1 -1
  290. package/dist/{page-header-commands-DjzFEq3E.js → page-header-commands-DOb6WsfD.js} +5 -5
  291. package/dist/{page-header-commands-DjzFEq3E.js.map → page-header-commands-DOb6WsfD.js.map} +1 -1
  292. package/dist/pagination-BL25hu2s.js +158 -0
  293. package/dist/pagination-BL25hu2s.js.map +1 -0
  294. package/dist/{popover-Di55PyAI.js → popover-7_m66eYW.js} +8 -7
  295. package/dist/{popover-Di55PyAI.js.map → popover-7_m66eYW.js.map} +1 -1
  296. package/dist/popover-menu-B9WWygpa.js +100 -0
  297. package/dist/popover-menu-B9WWygpa.js.map +1 -0
  298. package/dist/{popover.recipes-Bdyhj2db.js → popover.recipes-D3j8R8Yp.js} +17 -10
  299. package/dist/popover.recipes-D3j8R8Yp.js.map +1 -0
  300. package/dist/{primitives-B-CkiEMU.js → primitives-BFK08r9M.js} +45 -44
  301. package/dist/primitives-BFK08r9M.js.map +1 -0
  302. package/dist/primitives.js +4 -4
  303. package/dist/{progress-rnS8-uAW.js → progress-B1VnCT0K.js} +5 -5
  304. package/dist/{progress-rnS8-uAW.js.map → progress-B1VnCT0K.js.map} +1 -1
  305. package/dist/{receipt-D0oswZ0p.js → receipt-BVSOH3Xo.js} +9 -6
  306. package/dist/{receipt-D0oswZ0p.js.map → receipt-BVSOH3Xo.js.map} +1 -1
  307. package/dist/{rich-text-DvGulsNJ.js → rich-text-GOUyKQ-s.js} +3 -3
  308. package/dist/{rich-text-DvGulsNJ.js.map → rich-text-GOUyKQ-s.js.map} +1 -1
  309. package/dist/{rich-text-editor-sMU_Scqm.js → rich-text-editor-cRLC-eBK.js} +418 -426
  310. package/dist/rich-text-editor-cRLC-eBK.js.map +1 -0
  311. package/dist/rich-text-editor-toolbar-DfXg0-VC.js +94 -0
  312. package/dist/rich-text-editor-toolbar-DfXg0-VC.js.map +1 -0
  313. package/dist/{scroll-area-Bt_vXY2b.js → scroll-area-DcI-M1UT.js} +2 -2
  314. package/dist/{scroll-area-Bt_vXY2b.js.map → scroll-area-DcI-M1UT.js.map} +1 -1
  315. package/dist/{separator-C8DlRGwF.js → separator-BDV-Y648.js} +3 -3
  316. package/dist/{separator-C8DlRGwF.js.map → separator-BDV-Y648.js.map} +1 -1
  317. package/dist/{separator-CYHnjsAb.js → separator-Bom7NsGO.js} +2 -2
  318. package/dist/{separator-CYHnjsAb.js.map → separator-Bom7NsGO.js.map} +1 -1
  319. package/dist/services/actions.js +1 -1
  320. package/dist/{settings-CQW3b-Cu.js → settings-ybnjVwbd.js} +20 -19
  321. package/dist/settings-ybnjVwbd.js.map +1 -0
  322. package/dist/{sheet-4SEvVYzA.js → sheet-CGpB3omz.js} +8 -7
  323. package/dist/{sheet-4SEvVYzA.js.map → sheet-CGpB3omz.js.map} +1 -1
  324. package/dist/{sidebar-d7Dg80ln.js → sidebar-A0ElHINE.js} +14 -13
  325. package/dist/{sidebar-d7Dg80ln.js.map → sidebar-A0ElHINE.js.map} +1 -1
  326. package/dist/{sidebar-C7WWR29L.js → sidebar-CPx_7YBa.js} +183 -182
  327. package/dist/sidebar-CPx_7YBa.js.map +1 -0
  328. package/dist/{skeleton-Cz890JZF.js → skeleton-Byjnt7qr.js} +3 -3
  329. package/dist/{skeleton-Cz890JZF.js.map → skeleton-Byjnt7qr.js.map} +1 -1
  330. package/dist/smart-card-DiC5aac3.js +604 -0
  331. package/dist/smart-card-DiC5aac3.js.map +1 -0
  332. package/dist/{structure-DC2dygdA.js → structure-BmisBK-3.js} +2 -2
  333. package/dist/{structure-DC2dygdA.js.map → structure-BmisBK-3.js.map} +1 -1
  334. package/dist/style.css +1 -1
  335. package/dist/table-BweFy_P9.js +1530 -0
  336. package/dist/table-BweFy_P9.js.map +1 -0
  337. package/dist/{table-CIKyLUsy.js → table-DsfzoUia.js} +75 -63
  338. package/dist/table-DsfzoUia.js.map +1 -0
  339. package/dist/{tabs-DwBJfjxX.js → tabs-CDocW5D1.js} +14 -13
  340. package/dist/tabs-CDocW5D1.js.map +1 -0
  341. package/dist/text-inputs-f9Ia-aCi.js +353 -0
  342. package/dist/text-inputs-f9Ia-aCi.js.map +1 -0
  343. package/dist/theme-mode-css-BB-_RYab.js +14 -0
  344. package/dist/theme-mode-css-BB-_RYab.js.map +1 -0
  345. package/dist/theme-scope-BJ6eE2xt.js +50 -0
  346. package/dist/theme-scope-BJ6eE2xt.js.map +1 -0
  347. package/dist/theme.css +285 -228
  348. package/dist/themes/green.css +16 -12
  349. package/dist/timelines-CwM_9IhD.js +457 -0
  350. package/dist/timelines-CwM_9IhD.js.map +1 -0
  351. package/dist/{tone-recipes-CPoExcTE.js → tone-recipes-BPsRAvhu.js} +5 -2
  352. package/dist/tone-recipes-BPsRAvhu.js.map +1 -0
  353. package/dist/{tooltip-CsfgrfS7.js → tooltip-yiRJUFjp.js} +4 -4
  354. package/dist/{tooltip-CsfgrfS7.js.map → tooltip-yiRJUFjp.js.map} +1 -1
  355. package/dist/{tree-BiKhg8AY.js → tree-WnKQzwbq.js} +9 -9
  356. package/dist/{tree-BiKhg8AY.js.map → tree-WnKQzwbq.js.map} +1 -1
  357. package/dist/typography/rich-text.js +1 -1
  358. package/dist/{typography-DTRkE9zL.js → typography-UTnveOEy.js} +6 -6
  359. package/dist/typography-UTnveOEy.js.map +1 -0
  360. package/dist/typography.js +2 -2
  361. package/dist/{ui-provider-1D_NSYzO.js → ui-provider-C_U0Xma4.js} +3 -3
  362. package/dist/ui-provider-C_U0Xma4.js.map +1 -0
  363. package/dist/ui-provider.js +2 -2
  364. package/dist/{upload-BO8-CLN6.js → upload-CXyxmQBP.js} +13 -12
  365. package/dist/upload-CXyxmQBP.js.map +1 -0
  366. package/dist/{upload-queue-EOC8g1gf.js → upload-queue-Boscubn9.js} +11 -9
  367. package/dist/upload-queue-Boscubn9.js.map +1 -0
  368. package/dist/{usage-card-obRaBskq.js → usage-card-BhO5eqkX.js} +53 -37
  369. package/dist/usage-card-BhO5eqkX.js.map +1 -0
  370. package/dist/{utils-l5LpDw2z.js → utils-BRhFDwuU.js} +59 -44
  371. package/dist/utils-BRhFDwuU.js.map +1 -0
  372. package/dist/{value-inputs-TAYMX111.js → value-inputs-DXPDjvBU.js} +268 -252
  373. package/dist/value-inputs-DXPDjvBU.js.map +1 -0
  374. package/dist/{value-typography-b8wpz1eX.js → value-typography-BP8OG6h5.js} +2 -2
  375. package/dist/{value-typography-b8wpz1eX.js.map → value-typography-BP8OG6h5.js.map} +1 -1
  376. package/dist/{workspace-DH0v0KcB.js → workspace-Cdrg7k9f.js} +34 -33
  377. package/dist/workspace-Cdrg7k9f.js.map +1 -0
  378. package/docs/consumer-skill/SKILL.md +2 -2
  379. package/docs/consumer-skill/references/agents-md.md +1 -1
  380. package/docs/consumer-skill/references/composition.md +8 -6
  381. package/docs/consumer-skill/references/integration.md +4 -3
  382. package/docs/consumer-skill/references/public-api.json +105 -2
  383. package/docs/consumer-skill/references/review.md +7 -0
  384. package/docs/consumer-skill/references/theming.md +71 -6
  385. package/docs/consumer-skill/references/tokens.json +1 -1
  386. package/docs/consumer-skill/references/workflows.md +25 -0
  387. package/docs/consumer-skill/scripts/composition-policy.mjs +3 -2
  388. package/docs/consumer-skill/scripts/surface-policy.mjs +11 -0
  389. package/package.json +8 -4
  390. package/dist/accordion-B6a3vVgA.js.map +0 -1
  391. package/dist/action-menu-TzCoSlwL.js +0 -280
  392. package/dist/action-menu-TzCoSlwL.js.map +0 -1
  393. package/dist/affordance-geometry.generated-B5iu-Mkr.js +0 -69
  394. package/dist/affordance-geometry.generated-B5iu-Mkr.js.map +0 -1
  395. package/dist/ai-artifact-BMJdv-6q.js +0 -1115
  396. package/dist/ai-artifact-BMJdv-6q.js.map +0 -1
  397. package/dist/attachment-BtfhGm8i.js +0 -245
  398. package/dist/attachment-BtfhGm8i.js.map +0 -1
  399. package/dist/auth-CYxKfo69.js.map +0 -1
  400. package/dist/avatar-BBnEJIx8.js.map +0 -1
  401. package/dist/badge-MrKVNzW9.js.map +0 -1
  402. package/dist/batch-action-bar-BZGDG-Si.js.map +0 -1
  403. package/dist/breadcrumbs-D5t7I023.js.map +0 -1
  404. package/dist/buttons-SbIcm1HJ.js.map +0 -1
  405. package/dist/cards-CiiHpKYd.js +0 -66
  406. package/dist/cards-CiiHpKYd.js.map +0 -1
  407. package/dist/chart-QfrARkXl.js.map +0 -1
  408. package/dist/choice-inputs-t6w3ATNz.js.map +0 -1
  409. package/dist/code-block-Dgbu-CU3.js.map +0 -1
  410. package/dist/combobox-2Ic8N9bL.js +0 -278
  411. package/dist/combobox-2Ic8N9bL.js.map +0 -1
  412. package/dist/combobox-DLl0bfiq.js +0 -867
  413. package/dist/combobox-DLl0bfiq.js.map +0 -1
  414. package/dist/comments-BpDuCUUu.js.map +0 -1
  415. package/dist/data-display-DafIvCl5.js.map +0 -1
  416. package/dist/date-picker-CF-DtUpF.js.map +0 -1
  417. package/dist/date-pickers-BmzxJl5l.js +0 -174
  418. package/dist/date-pickers-BmzxJl5l.js.map +0 -1
  419. package/dist/display-DsQTVzMz.js.map +0 -1
  420. package/dist/dropdown-menu-E2qmdC7o.js +0 -193
  421. package/dist/dropdown-menu-E2qmdC7o.js.map +0 -1
  422. package/dist/editable-text-recipe-Bkm6wKHp.js +0 -10
  423. package/dist/editable-text-recipe-Bkm6wKHp.js.map +0 -1
  424. package/dist/feedback-qNuMBtRH.js +0 -233
  425. package/dist/feedback-qNuMBtRH.js.map +0 -1
  426. package/dist/field-affordance-recipes-qQeIf4lG.js.map +0 -1
  427. package/dist/filters-BkHH53uv.js.map +0 -1
  428. package/dist/form-field-DUt4UxSV.js.map +0 -1
  429. package/dist/form-sizing-By94KzXE.js.map +0 -1
  430. package/dist/forms-numeric-C0bvjRPZ.js.map +0 -1
  431. package/dist/header-BOefOKd1.js.map +0 -1
  432. package/dist/input-DWhBBBww.js +0 -262
  433. package/dist/input-DWhBBBww.js.map +0 -1
  434. package/dist/input-Ddi_LSYv.js +0 -20
  435. package/dist/input-Ddi_LSYv.js.map +0 -1
  436. package/dist/interaction-recipes-CHr0dJUs.js.map +0 -1
  437. package/dist/item-DEmDiTlD.js +0 -265
  438. package/dist/item-DEmDiTlD.js.map +0 -1
  439. package/dist/media-gallery-DcTtAaeC.js.map +0 -1
  440. package/dist/mentions-D-uyCh01.js.map +0 -1
  441. package/dist/message-CdHgIWKf.js.map +0 -1
  442. package/dist/metadata-list-X5rYAKSB.js.map +0 -1
  443. package/dist/navigation-D3KwXmaq.js.map +0 -1
  444. package/dist/navigation-HJf5zxlH.js.map +0 -1
  445. package/dist/overflow-tab-bar-sQHXLlwQ.js.map +0 -1
  446. package/dist/overlays-I0axtYA6.js.map +0 -1
  447. package/dist/pagination-3bPA_a6K.js +0 -149
  448. package/dist/pagination-3bPA_a6K.js.map +0 -1
  449. package/dist/popover-menu-B71Tn2Qz.js +0 -99
  450. package/dist/popover-menu-B71Tn2Qz.js.map +0 -1
  451. package/dist/popover.recipes-Bdyhj2db.js.map +0 -1
  452. package/dist/primitives-B-CkiEMU.js.map +0 -1
  453. package/dist/rich-text-editor-sMU_Scqm.js.map +0 -1
  454. package/dist/rich-text-editor.recipes-CadiF_Uu.js +0 -88
  455. package/dist/rich-text-editor.recipes-CadiF_Uu.js.map +0 -1
  456. package/dist/settings-CQW3b-Cu.js.map +0 -1
  457. package/dist/sidebar-C7WWR29L.js.map +0 -1
  458. package/dist/smart-card-lFKxn5Hu.js +0 -595
  459. package/dist/smart-card-lFKxn5Hu.js.map +0 -1
  460. package/dist/spinner-fa3h1Aif.js +0 -80
  461. package/dist/spinner-fa3h1Aif.js.map +0 -1
  462. package/dist/table-CIKyLUsy.js.map +0 -1
  463. package/dist/table-CrcLN9Io.js +0 -1458
  464. package/dist/table-CrcLN9Io.js.map +0 -1
  465. package/dist/tabs-DwBJfjxX.js.map +0 -1
  466. package/dist/text-inputs-aaK9wcDT.js +0 -326
  467. package/dist/text-inputs-aaK9wcDT.js.map +0 -1
  468. package/dist/theme-scope-kStaAer0.js +0 -39
  469. package/dist/theme-scope-kStaAer0.js.map +0 -1
  470. package/dist/timelines-C_SBwHNP.js +0 -442
  471. package/dist/timelines-C_SBwHNP.js.map +0 -1
  472. package/dist/tone-recipes-CPoExcTE.js.map +0 -1
  473. package/dist/typography-DTRkE9zL.js.map +0 -1
  474. package/dist/ui-provider-1D_NSYzO.js.map +0 -1
  475. package/dist/upload-BO8-CLN6.js.map +0 -1
  476. package/dist/upload-queue-EOC8g1gf.js.map +0 -1
  477. package/dist/usage-card-obRaBskq.js.map +0 -1
  478. package/dist/utils-l5LpDw2z.js.map +0 -1
  479. package/dist/value-inputs-TAYMX111.js.map +0 -1
  480. package/dist/workspace-DH0v0KcB.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ai-chat.js","names":["_Fragment","cn","Button","DisplayLabel","Text","focusRecipes","Stack","Badge","Textarea","EmptyState","messageColumns","messageContentColumn","hasMessageMedia","AiMessageBubble","AiCodeBlock","AiChainOfThought","AiToolCall","AiConfirmation","AiAttachment","AiSources","AiAgent","AiTask","AiReasoning","AiArtifact","AiShimmer","Fragment$1","defaultAiChatPromptInputStrings","defaultAiChatConversationStrings","defaultAiChatQueueStrings","defaultAiChatSuggestionsStrings","defaultAiChatMessageStrings","defaultAiChatStrings","AiChatAttachmentsStrip","attachments","className","att","onOpen","onRemove","useAiChatScroll","containerRef","useRef","endRef","isAtBottom","setIsAtBottom","useState","scrollToBottom","useCallback","useEffect","el","onScroll","distance","threshold","disableAutoScroll","id","dependency","AiChatConversation","stringsProp","strings","useStrings","messages","isEmpty","intro","empty","ctx","idx","renderMessage","message","footer","ArrowDown","AiChatEmptyState","IconComponent","Sparkles","media","description","below","AiChatMessage","align","inBubble","part","plainText","p","extractPlain","bubbleContent","hasBubble","hasAvatar","continuationColumn","onCopy","PartRenderer","onAttachmentOpen","node","AiChatPromptInput","textareaRef","canSubmit","streaming","disabled","value","handleSubmit","onSubmit","handleKeyDown","showAttachBtn","showAttach","onAttach","onRemoveAttachment","onValueChange","leadingActions","Paperclip","trailingActions","onStop","Square","ArrowUp","hideHint","interpolateString","submitKeyLabel","AiChatQueue","items","hideHeader","status","item","Loader2","onCancel","X","AiChatSuggestionsRow","suggestions","Icon","s","onPick","AiChat","force","slots","onMessageCopy","onMessageRegenerate","attachmentId","Header","agent","headerActions","Empty","Queue","queue","onCancelQueueItem","Suggestions","onPickSuggestion","Input","inputValue","onInputChange","values","v"],"sources":["../../src/components/features/ai-chat/ai-chat.strings.ts","../../src/components/features/ai-chat/partials/ai-chat-attachments-strip.tsx","../../src/components/features/ai-chat/hooks/use-ai-chat-scroll.ts","../../src/components/features/ai-chat/partials/ai-chat-conversation.tsx","../../src/components/features/ai-chat/partials/ai-chat-empty-state.tsx","../../src/components/features/ai-chat/partials/ai-chat-message.tsx","../../src/components/features/ai-chat/partials/ai-chat-prompt-input.tsx","../../src/components/features/ai-chat/partials/ai-chat-queue.tsx","../../src/components/features/ai-chat/partials/ai-chat-suggestions-row.tsx","../../src/components/features/ai-chat/ai-chat.tsx"],"sourcesContent":["/**\n * Strings for `<AiChat>` and its partials. Each interface is co-located so\n * partials and the feature root all read from one source of truth (rule 19).\n * Consumers override via the `strings` prop on the relevant component; values\n * are deep-merged over the defaults so partial overrides are safe.\n */\n\nexport interface AiChatPromptInputStrings {\n\t/** Placeholder copy for the textarea. */\n\tplaceholder: string;\n\t/** Aria label for the attach button. */\n\tattachAria: string;\n\t/** Aria label for the submit button. */\n\tsubmitAria: string;\n\t/** Aria label for the stop button (replaces submit while streaming). */\n\tstopAria: string;\n\t/** Aria label for the model picker button (when `modelPicker` is provided). */\n\tmodelPickerAria: string;\n\t/** Hint shown under the input. Supports `{{key}}` for the submit shortcut. */\n\thint: string;\n}\n\nexport const defaultAiChatPromptInputStrings: AiChatPromptInputStrings = {\n\tplaceholder: 'Ask anything…',\n\tattachAria: 'Attach files',\n\tsubmitAria: 'Send message',\n\tstopAria: 'Stop generating',\n\tmodelPickerAria: 'Choose model',\n\thint: 'Press {{submitKey}} to send · {{newlineKey}} for newline',\n};\n\nexport interface AiChatConversationStrings {\n\ttranscriptAria: string;\n\t/** Shown in place of the collection when it has no entries. */\n\tempty: string;\n\tscrollToBottom: string;\n\tscrollToBottomAria: string;\n}\n\nexport const defaultAiChatConversationStrings: AiChatConversationStrings = {\n\ttranscriptAria: 'Conversation messages',\n\tempty: 'No messages yet.',\n\tscrollToBottom: 'Jump to latest',\n\tscrollToBottomAria: 'Scroll to bottom',\n};\n\nexport interface AiChatQueueStrings {\n\theader: string;\n\tcancelAria: string;\n\tqueuedLabel: string;\n\trunningLabel: string;\n}\n\nexport const defaultAiChatQueueStrings: AiChatQueueStrings = {\n\theader: 'In queue',\n\tcancelAria: 'Remove from queue',\n\tqueuedLabel: 'Queued',\n\trunningLabel: 'Running',\n};\n\nexport interface AiChatSuggestionsStrings {\n\theader: string;\n}\n\nexport const defaultAiChatSuggestionsStrings: AiChatSuggestionsStrings = {\n\theader: 'Try',\n};\n\nexport interface AiChatMessageStrings {\n\tpending: string;\n}\n\nexport const defaultAiChatMessageStrings: AiChatMessageStrings = {\n\tpending: 'Thinking…',\n};\n\nexport interface AiChatStrings {\n\tprompt: AiChatPromptInputStrings;\n\tconversation: AiChatConversationStrings;\n\tqueue: AiChatQueueStrings;\n\tsuggestions: AiChatSuggestionsStrings;\n\tmessage: AiChatMessageStrings;\n\temptyTitle: string;\n\temptyDescription: string;\n\t/** Screen-reader announcement emitted while the composer is disabled. */\n\tdisabledAnnouncement: string;\n}\n\nexport const defaultAiChatStrings: AiChatStrings = {\n\tprompt: defaultAiChatPromptInputStrings,\n\tconversation: defaultAiChatConversationStrings,\n\tqueue: defaultAiChatQueueStrings,\n\tsuggestions: defaultAiChatSuggestionsStrings,\n\tmessage: defaultAiChatMessageStrings,\n\temptyTitle: 'Start a conversation',\n\temptyDescription: 'Ask a question, share context, or attach a file to get going.',\n\tdisabledAnnouncement: 'Chat is disabled',\n};\n","/**\n * AiChatAttachmentsStrip — flex-wrap row of `<AiAttachment>` chips. Used both\n * in the prompt input (staged uploads — pass `onRemove` to enable a remove\n * button) and inside messages (read-only attachment list).\n */\nimport { AiAttachment } from '../../../blocks/ai/ai-attachment';\nimport { Stack } from '../../../base/structure';\nimport { cn } from '../../../../lib/utils';\n\nimport type { AiChatAttachment } from '../ai-chat.types';\n\nexport interface AiChatAttachmentsStripProps {\n\t/** Files staged on the draft. */\n\tattachments: ReadonlyArray<AiChatAttachment>;\n\t/** When set, each chip gets a remove button wired to this handler. */\n\tonRemove?: (id: string) => void;\n\t/** When set, click on a chip calls this. */\n\tonOpen?: (att: AiChatAttachment) => void;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n}\n\nexport function AiChatAttachmentsStrip({\n\tattachments,\n\tonRemove,\n\tonOpen,\n\tclassName,\n}: AiChatAttachmentsStripProps) {\n\tif (attachments.length === 0) return null;\n\treturn (\n\t\t<Stack\n\t\t\tdirection=\"horizontal\"\n\t\t\tgap=\"sm\"\n\t\t\tclassName={cn('ai-chat-attachments-strip--component', className)}\n\t\t>\n\t\t\t{attachments.map((att) => (\n\t\t\t\t<AiAttachment\n\t\t\t\t\tkey={att.id}\n\t\t\t\t\tname={att.name}\n\t\t\t\t\tmeta={att.meta}\n\t\t\t\t\tkind={att.kind}\n\t\t\t\t\ticon={att.icon}\n\t\t\t\t\tthumbnailUrl={att.thumbnailUrl}\n\t\t\t\t\tprogress={att.progress}\n\t\t\t\t\terrored={att.errored}\n\t\t\t\t\tonOpen={onOpen ? () => onOpen(att) : undefined}\n\t\t\t\t\tonRemove={onRemove ? () => onRemove(att.id) : undefined}\n\t\t\t\t/>\n\t\t\t))}\n\t\t</Stack>\n\t);\n}\n\nAiChatAttachmentsStrip.displayName = 'AiChatAttachmentsStrip';\n","/**\n * useAiChatScroll — auto-stick-to-bottom scroll behaviour for chat\n * conversations. Detects when the user has scrolled away from the latest\n * message and pauses auto-scroll until they return.\n *\n * Returns:\n * - `containerRef` — attach to the scroll viewport.\n * - `endRef` — attach to a sentinel at the very bottom.\n * - `isAtBottom` — true when the viewport is pinned to the latest content.\n * - `scrollToBottom` — imperatively scroll to the sentinel.\n */\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nexport interface UseAiChatScrollOptions {\n\t/** Distance (px) from bottom counted as \"at bottom\". */\n\tthreshold?: number;\n\t/** Re-evaluate on these dependencies (typically the message count). */\n\tdependency?: unknown;\n\t/** Disable auto-scroll-on-update behaviour. */\n\tdisableAutoScroll?: boolean;\n}\n\nexport interface UseAiChatScrollReturn {\n\tcontainerRef: React.RefObject<HTMLDivElement | null>;\n\tendRef: React.RefObject<HTMLDivElement | null>;\n\tisAtBottom: boolean;\n\tscrollToBottom: (behavior?: ScrollBehavior) => void;\n}\n\nexport function useAiChatScroll({\n\tthreshold = 80,\n\tdependency,\n\tdisableAutoScroll = false,\n}: UseAiChatScrollOptions = {}): UseAiChatScrollReturn {\n\tconst containerRef = useRef<HTMLDivElement | null>(null);\n\tconst endRef = useRef<HTMLDivElement | null>(null);\n\tconst [isAtBottom, setIsAtBottom] = useState(true);\n\n\tconst scrollToBottom = useCallback(\n\t\t(behavior: ScrollBehavior = 'smooth') => {\n\t\t\tendRef.current?.scrollIntoView({ behavior, block: 'end' });\n\t\t},\n\t\t[],\n\t);\n\n\t// Track scroll position so we can pause auto-scroll when the user reads up.\n\tuseEffect(() => {\n\t\tconst el = containerRef.current;\n\t\tif (!el) return;\n\t\tconst onScroll = () => {\n\t\t\tconst distance = el.scrollHeight - el.clientHeight - el.scrollTop;\n\t\t\tsetIsAtBottom(distance <= threshold);\n\t\t};\n\t\tonScroll();\n\t\tel.addEventListener('scroll', onScroll, { passive: true });\n\t\treturn () => el.removeEventListener('scroll', onScroll);\n\t}, [threshold]);\n\n\t// Auto-scroll when content updates and the user is pinned at the bottom.\n\tuseEffect(() => {\n\t\tif (disableAutoScroll) return;\n\t\tif (!isAtBottom) return;\n\t\t// Use rAF so we wait for layout to settle after the new content paints.\n\t\tconst id = window.requestAnimationFrame(() => scrollToBottom('auto'));\n\t\treturn () => window.cancelAnimationFrame(id);\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [dependency, disableAutoScroll]);\n\n\treturn { containerRef, endRef, isAtBottom, scrollToBottom };\n}\n","/**\n * AiChatConversation — scrollable list container for chat messages with\n * auto-stick-to-bottom behaviour. Renders each message via the consumer's\n * `renderMessage` slot (or the default `<AiChatMessage>` via the parent\n * `<AiChat>`). Surfaces a \"Jump to latest\" pill when the user scrolls away\n * from the bottom while content streams in.\n */\nimport { ArrowDown } from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport { Button } from '../../../base/buttons';\nimport { Stack } from '../../../base/structure';\nimport { Text } from '../../../typography';\nimport { useStrings, type StringsProp } from '../../../../lib/strings';\nimport { cn } from '../../../../lib/utils';\n\nimport {\n\tdefaultAiChatConversationStrings,\n\ttype AiChatConversationStrings,\n} from '../ai-chat.strings';\nimport type {\n\tAiChatMessage as AiChatMessageType,\n\tAiChatRenderMessageContext,\n} from '../ai-chat.types';\nimport { useAiChatScroll } from '../hooks/use-ai-chat-scroll';\nimport { focusRecipes } from '../../../../lib/focus-recipes';\n\nexport interface AiChatConversationProps {\n\t/** Messages to render, oldest first. */\n\tmessages: ReadonlyArray<AiChatMessageType>;\n\t/** Replaces the default message rendering. */\n\trenderMessage: (\n\t\t/** The message this row represents. */\n\t\tmessage: AiChatMessageType,\n\t\tctx: AiChatRenderMessageContext,\n\t) => ReactNode;\n\t/** Render before the messages list (intro card, agent greeting). */\n\tintro?: ReactNode;\n\t/** Render after the messages list (e.g. tip ribbon). */\n\tfooter?: ReactNode;\n\t/** Replaces the empty state when `messages.length === 0`. */\n\tempty?: ReactNode;\n\t/** Pause auto-scroll-on-update. */\n\tdisableAutoScroll?: boolean;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n\t/** Overrides this surface's own copy. */\n\tstrings?: StringsProp<AiChatConversationStrings>;\n}\n\nexport function AiChatConversation({\n\tmessages,\n\trenderMessage,\n\tintro,\n\tfooter,\n\tempty,\n\tdisableAutoScroll,\n\tclassName,\n\tstrings: stringsProp,\n}: AiChatConversationProps) {\n\tconst strings = useStrings(defaultAiChatConversationStrings, stringsProp);\n\tconst { containerRef, endRef, isAtBottom, scrollToBottom } = useAiChatScroll({\n\t\tdependency: messages.length,\n\t\tdisableAutoScroll,\n\t});\n\n\tconst isEmpty = messages.length === 0 && !intro;\n\n\treturn (\n\t\t<div className={cn('ai-chat-conversation--component relative flex h-full min-h-0 flex-col', className)}>\n\t\t\t<div\n\t\t\t\tref={containerRef}\n\t\t\t\ttabIndex={0}\n\t\t\t\taria-label={strings.transcriptAria}\n\t\t\t\tclassName={`flex-1 overflow-y-auto p-surface focus-visible:outline-none ${focusRecipes.inset}`}\n\t\t\t>\n\t\t\t\t{!!intro && <div className=\"mb-space-xl\">{intro}</div>}\n\n\t\t\t\t{isEmpty ? (\n\t\t\t\t\tempty ?? (\n\t\t\t\t\t\t<div className=\"flex h-full items-center justify-center p-surface-lg\">\n\t\t\t\t\t\t\t<Text type=\"secondary\">{strings.empty}</Text>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)\n\t\t\t\t) : (\n\t\t\t\t\t<Stack render={<ol />} gap=\"xl\" className=\"ai-chat-conversation--messages m-0 list-none p-0 font-sans\">\n\t\t\t\t\t\t{messages.map((message, idx) => {\n\t\t\t\t\t\t\tconst ctx: AiChatRenderMessageContext = {\n\t\t\t\t\t\t\t\tisLast: idx === messages.length - 1,\n\t\t\t\t\t\t\t\tindex: idx,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<li key={message.id}>{renderMessage(message, ctx)}</li>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t</Stack>\n\t\t\t\t)}\n\n\t\t\t\t{!!footer && <div className=\"mt-space-xl\">{footer}</div>}\n\n\t\t\t\t<div ref={endRef} aria-hidden className=\"h-px\" />\n\t\t\t</div>\n\n\t\t\t{!isAtBottom && (\n\t\t\t\t<div className=\"ai-chat-conversation--jump flex shrink-0 justify-center border-t border-border/60 bg-background px-space-md py-space-sm\">\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\tbuttonStyle=\"solid\"\n\t\t\t\t\t\taria-label={strings.scrollToBottomAria}\n\t\t\t\t\t\tonClick={() => scrollToBottom('smooth')}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'shadow-sm max-sm:size-action-sm max-sm:min-h-0 max-sm:p-0',\n\t\t\t\t\t\t\t'border border-border/60',\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ArrowDown className=\"size-icon-md\" />\n\t\t\t\t\t\t<Text tag=\"span\" size=\"pxs\" className=\"max-sm:sr-only\">\n\t\t\t\t\t\t\t{strings.scrollToBottom}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nAiChatConversation.displayName = 'AiChatConversation';\n","/**\n * AiChatEmptyState — default empty surface for `<AiChat>` when no messages\n * are present and no intro is provided. Centers a title + description with\n * an optional below-content slot for prompt-suggestion grids.\n */\nimport type { ReactNode } from 'react';\nimport { Sparkles } from 'lucide-react';\nimport { Stack } from '../../../base/structure';\nimport { EmptyState } from '../../../blocks/data-display';\nimport { cn } from '../../../../lib/utils';\n\nexport interface AiChatEmptyStateProps {\n\t/** Surface title. */\n\ttitle?: ReactNode;\n\t/** Supporting copy shown under the label. */\n\tdescription?: ReactNode;\n\t/** Leading glyph. */\n\ticon?: React.ElementType;\n\t/** Content rendered under the main body. */\n\tbelow?: ReactNode;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n}\n\nexport function AiChatEmptyState({\n\ttitle = 'Start a conversation',\n\tdescription,\n\ticon: IconComponent = Sparkles,\n\tbelow,\n\tclassName,\n}: AiChatEmptyStateProps) {\n\tconst media = <IconComponent className=\"size-icon\" aria-hidden=\"true\" />;\n\n\treturn (\n\t\t<Stack\n\t\t\tgap=\"md\"\n\t\t\talign=\"center\"\n\t\t\tjustify=\"center\"\n\t\t\tclassName={cn('ai-chat-empty-state--component min-h-full text-center', className)}\n\t\t>\n\t\t\t<EmptyState\n\t\t\t\ttitle={title}\n\t\t\t\tdescription={description ?? false}\n\t\t\t\tmedia={media}\n\t\t\t\tmediaVariant=\"icon\"\n\t\t\t\tpadding=\"md\"\n\t\t\t\tclassName=\"w-full\"\n\t\t\t/>\n\t\t\t{!!below && <div className=\"w-full max-w-2xl\">{below}</div>}\n\t\t</Stack>\n\t);\n}\n\nAiChatEmptyState.displayName = 'AiChatEmptyState';\n","/**\n * AiChatMessage — message renderer that wraps `<AiMessageBubble>` and routes\n * each `parts[]` entry to its dedicated `blocks/ai/*` surface (text, code,\n * tool calls, reasoning, sources, attachments, …).\n *\n * Most surfaces sit BELOW the bubble (artifact, sources, task) since they\n * carry their own chrome; plain text and inline citations render INSIDE the\n * bubble. Custom-typed parts call `render()` directly.\n */\nimport type { ReactNode } from 'react';\nimport { AiArtifact } from '../../../blocks/ai/ai-artifact';\nimport { AiChainOfThought } from '../../../blocks/ai/ai-chain-of-thought';\nimport { AiCodeBlock } from '../../../blocks/ai/ai-code-block';\nimport { AiConfirmation } from '../../../blocks/ai/ai-confirmation';\nimport { AiMessageBubble } from '../../../blocks/ai/ai-message-bubble';\nimport { AiReasoning } from '../../../blocks/ai/ai-reasoning';\nimport { AiShimmer } from '../../../blocks/ai/ai-shimmer';\nimport { AiSources } from '../../../blocks/ai/ai-sources';\nimport { AiTask } from '../../../blocks/ai/ai-task';\nimport { AiToolCall } from '../../../blocks/ai/ai-tool-call';\nimport { Stack } from '../../../base/structure';\nimport { Text } from '../../../typography';\nimport { useStrings, type StringsProp } from '../../../../lib/strings';\nimport { cn } from '../../../../lib/utils';\n\nimport {\n\tdefaultAiChatMessageStrings,\n\ttype AiChatMessageStrings,\n} from '../ai-chat.strings';\nimport type {\n\tAiChatMessage as AiChatMessageType,\n\tAiChatMessagePart,\n} from '../ai-chat.types';\nimport { AiChatAttachmentsStrip } from './ai-chat-attachments-strip';\nimport { hasMessageMedia, messageColumns, messageContentColumn } from '../../../blocks/collaboration/message/message.recipes';\n\nexport interface AiChatMessageProps {\n\t/** The message this row represents. */\n\tmessage: AiChatMessageType;\n\t/** Copy callback forwarded to the underlying bubble. */\n\tonCopy?: () => void;\n\t/** Regenerate callback forwarded to the underlying bubble (assistant only). */\n\tonRegenerate?: () => void;\n\t/** Open handler for attachment chips inside the message. */\n\tonAttachmentOpen?: (attachmentId: string) => void;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n\t/** Overrides this surface's own copy. */\n\tstrings?: StringsProp<AiChatMessageStrings>;\n}\n\nexport function AiChatMessage({\n\tmessage,\n\tonCopy,\n\tonRegenerate,\n\tonAttachmentOpen,\n\tclassName,\n\tstrings: stringsProp,\n}: AiChatMessageProps) {\n\tconst strings = useStrings(defaultAiChatMessageStrings, stringsProp);\n\tconst align = message.role === 'user' ? 'end' : 'start';\n\n\t// Split parts: in-bubble (text) vs below-bubble (everything else).\n\tconst inBubble: AiChatMessagePart[] = [];\n\tconst below: AiChatMessagePart[] = [];\n\tfor (const part of message.parts) {\n\t\tif (part.type === 'text') inBubble.push(part);\n\t\telse below.push(part);\n\t}\n\n\tconst plainText =\n\t\tinBubble\n\t\t\t.map((p) => (p.type === 'text' ? p.plain ?? extractPlain(p.content) : ''))\n\t\t\t.filter(Boolean)\n\t\t\t.join('\\n') || undefined;\n\n\tconst bubbleContent: ReactNode = message.pending ? (\n\t\t<AiShimmer>{strings.pending}</AiShimmer>\n\t) : inBubble.length === 0 && below.length > 0 ? null : (\n\t\t<Stack gap=\"md\">\n\t\t\t{inBubble.map((part, idx) =>\n\t\t\t\tpart.type === 'text' ? (\n\t\t\t\t\t<div key={idx} className=\"whitespace-pre-wrap\">\n\t\t\t\t\t\t{part.content}\n\t\t\t\t\t</div>\n\t\t\t\t) : null,\n\t\t\t)}\n\t\t</Stack>\n\t);\n\tconst hasBubble = bubbleContent !== null || message.pending;\n\t// Nullish values select AiMessageBubble's default avatar; other empty nodes do not.\n\tconst hasAvatar = hasBubble && (message.avatar == null || hasMessageMedia(message.avatar));\n\tconst continuationColumn = hasAvatar ? messageContentColumn[align] : 'col-start-1';\n\n\treturn (\n\t\t<Stack gap=\"md\" className={cn('ai-chat-message--component grid min-w-0', hasAvatar ? messageColumns[align] : 'grid-cols-1', className)}>\n\t\t\t{hasBubble && (\n\t\t\t\t<AiMessageBubble\n\t\t\t\t\trole={message.role}\n\t\t\t\t\tavatar={message.avatar}\n\t\t\t\t\tauthorName={message.authorName}\n\t\t\t\t\ttimestamp={message.timestamp}\n\t\t\t\t\tplainText={plainText}\n\t\t\t\t\tloading={message.loading}\n\t\t\t\t\tclassName=\"col-span-full grid-cols-subgrid\"\n\t\t\t\t\tonCopy={plainText ? onCopy ?? (() => undefined) : undefined}\n\t\t\t\t\tonRegenerate={onRegenerate}\n\t\t\t\t>\n\t\t\t\t\t{bubbleContent}\n\t\t\t\t</AiMessageBubble>\n\t\t\t)}\n\n\t\t\t{below.length > 0 && (\n\t\t\t\t<Stack\n\t\t\t\t\tgap=\"md\"\n\t\t\t\t\tclassName={cn('ai-chat-message--parts min-w-0', continuationColumn)}\n\t\t\t\t>\n\t\t\t\t\t{below.map((part, idx) => (\n\t\t\t\t\t\t<PartRenderer\n\t\t\t\t\t\t\tkey={idx}\n\t\t\t\t\t\t\tpart={part}\n\t\t\t\t\t\t\tonAttachmentOpen={onAttachmentOpen}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t</Stack>\n\t\t\t)}\n\n\t\t\t{!!message.trailing && (\n\t\t\t\t<div\n\t\t\t\t\tclassName={cn('ai-chat-message--trailing min-w-0', continuationColumn)}\n\t\t\t\t>\n\t\t\t\t\t{message.trailing}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</Stack>\n\t);\n}\n\nAiChatMessage.displayName = 'AiChatMessage';\n\nfunction PartRenderer({\n\tpart,\n\tonAttachmentOpen,\n}: {\n\tpart: AiChatMessagePart;\n\tonAttachmentOpen?: (id: string) => void;\n}) {\n\tswitch (part.type) {\n\t\tcase 'text':\n\t\t\t// In-bubble. Should not reach here.\n\t\t\treturn <Text>{part.content}</Text>;\n\t\tcase 'reasoning':\n\t\t\treturn (\n\t\t\t\t<AiReasoning\n\t\t\t\t\tstreaming={part.streaming}\n\t\t\t\t\tdurationSeconds={part.durationSeconds}\n\t\t\t\t>\n\t\t\t\t\t{part.content}\n\t\t\t\t</AiReasoning>\n\t\t\t);\n\t\tcase 'chain-of-thought':\n\t\t\treturn <AiChainOfThought steps={part.steps} streaming={part.streaming} />;\n\t\tcase 'tool':\n\t\t\treturn (\n\t\t\t\t<AiToolCall\n\t\t\t\t\tname={part.name}\n\t\t\t\t\tstatus={part.status}\n\t\t\t\t\ticon={part.icon}\n\t\t\t\t\targs={part.args}\n\t\t\t\t\tresult={part.result}\n\t\t\t\t\terror={part.error}\n\t\t\t\t\tdurationMs={part.durationMs}\n\t\t\t\t\tdefaultExpanded={part.defaultExpanded}\n\t\t\t\t/>\n\t\t\t);\n\t\tcase 'code':\n\t\t\treturn (\n\t\t\t\t<AiCodeBlock\n\t\t\t\t\tcode={part.code}\n\t\t\t\t\tlanguage={part.language}\n\t\t\t\t\tfilename={part.filename}\n\t\t\t\t\tshowLineNumbers={part.showLineNumbers}\n\t\t\t\t\thighlightLines={part.highlightLines}\n\t\t\t\t/>\n\t\t\t);\n\t\tcase 'attachments':\n\t\t\treturn (\n\t\t\t\t<AiChatAttachmentsStrip\n\t\t\t\t\tattachments={part.items}\n\t\t\t\t\tonOpen={onAttachmentOpen ? (att) => onAttachmentOpen(att.id) : undefined}\n\t\t\t\t/>\n\t\t\t);\n\t\tcase 'sources':\n\t\t\treturn (\n\t\t\t\t<AiSources\n\t\t\t\t\tsources={part.items}\n\t\t\t\t\tvariant={part.variant}\n\t\t\t\t\tdefaultExpanded={part.defaultExpanded}\n\t\t\t\t/>\n\t\t\t);\n\t\tcase 'task':\n\t\t\treturn <AiTask task={part.task} />;\n\t\tcase 'artifact':\n\t\t\treturn (\n\t\t\t\t<AiArtifact\n\t\t\t\t\ttitle={part.title}\n\t\t\t\t\tsubtitle={part.subtitle}\n\t\t\t\t\ticon={part.icon}\n\t\t\t\t\tcopyText={part.copyText}\n\t\t\t\t\tactions={part.actions}\n\t\t\t\t\tonOpen={part.onOpen}\n\t\t\t\t\tonDownload={part.onDownload}\n\t\t\t\t>\n\t\t\t\t\t{part.body}\n\t\t\t\t</AiArtifact>\n\t\t\t);\n\t\tcase 'confirmation':\n\t\t\treturn (\n\t\t\t\t<AiConfirmation\n\t\t\t\t\ttitle={part.title}\n\t\t\t\t\tdescription={part.description}\n\t\t\t\t\ttone={part.tone}\n\t\t\t\t\tstatus={part.status}\n\t\t\t\t\tdetails={part.details}\n\t\t\t\t\tonApprove={part.onApprove}\n\t\t\t\t\tonReject={part.onReject}\n\t\t\t\t/>\n\t\t\t);\n\t\tcase 'custom':\n\t\t\treturn <>{part.render()}</>;\n\t\tdefault:\n\t\t\treturn null;\n\t}\n}\n\nfunction extractPlain(node: ReactNode): string {\n\tif (typeof node === 'string' || typeof node === 'number') return String(node);\n\tif (Array.isArray(node)) return node.map(extractPlain).join('');\n\treturn '';\n}\n","/**\n * AiChatPromptInput — multi-line composer for the chat. Carries:\n * - auto-resizing textarea\n * - staged attachment chips above the field\n * - leading actions slot (model picker, attach)\n * - submit / stop buttons (stop replaces submit while `streaming` is true)\n * - keyboard discipline: Enter to submit, Shift+Enter for newline\n *\n * Stateless: the consumer owns `value`, `attachments`, and `streaming`. The\n * component fires `onSubmit` with `{ text, attachments }` on submit.\n */\nimport { useCallback, useRef, type ReactNode } from 'react';\nimport { ArrowUp, Paperclip, Square } from 'lucide-react';\nimport { Button } from '../../../base/buttons';\nimport { Textarea } from '../../../base/text-inputs';\nimport { Text } from '../../../typography';\nimport { interpolateString, useStrings, type StringsProp } from '../../../../lib/strings';\nimport { cn } from '../../../../lib/utils';\n\nimport {\n\tdefaultAiChatPromptInputStrings,\n\ttype AiChatPromptInputStrings,\n} from '../ai-chat.strings';\nimport type {\n\tAiChatAttachment,\n\tAiChatSubmitValues,\n} from '../ai-chat.types';\nimport { AiChatAttachmentsStrip } from './ai-chat-attachments-strip';\n\nexport interface AiChatPromptInputProps {\n\t/** Current text value (controlled). */\n\tvalue: string;\n\t/** Text change callback. */\n\tonValueChange: (value: string) => void;\n\t/** Submit callback — fires on Enter or send-button click. */\n\tonSubmit?: (values: AiChatSubmitValues) => void;\n\t/** Stop callback — wired to the stop button while `streaming`. */\n\tonStop?: () => void;\n\t/** Streaming flag — flips submit ↔ stop and disables the submit button. */\n\tstreaming?: boolean;\n\t/** Disable the entire composer (e.g. while waiting for an upload). */\n\tdisabled?: boolean;\n\t/** Staged attachments (controlled). */\n\tattachments?: ReadonlyArray<AiChatAttachment>;\n\t/** Remove a staged attachment. */\n\tonRemoveAttachment?: (id: string) => void;\n\t/** Triggered when the attach button is pressed. */\n\tonAttach?: () => void;\n\t/** Show the attach button (default: when `onAttach` is provided). */\n\tshowAttach?: boolean;\n\t/** Leading slot rendered before the attach button (typically a model picker). */\n\tleadingActions?: ReactNode;\n\t/** Trailing slot rendered before submit (custom action buttons). */\n\ttrailingActions?: ReactNode;\n\t/** Hide the keyboard hint under the field. */\n\thideHint?: boolean;\n\t/** Override the textarea minimum row count. */\n\tminRows?: number;\n\t/** Override the textarea maximum row count before scroll. */\n\tmaxRows?: number;\n\t/** Auto-focus the textarea on mount. */\n\tautoFocus?: boolean;\n\t/** Display label interpolated into the submit hint. Defaults to the neutral Enter glyph. */\n\tsubmitKeyLabel?: string;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n\t/** Overrides this surface's own copy. */\n\tstrings?: StringsProp<AiChatPromptInputStrings>;\n}\n\nexport function AiChatPromptInput({\n\tvalue,\n\tonValueChange,\n\tonSubmit,\n\tonStop,\n\tstreaming = false,\n\tdisabled = false,\n\tattachments = [],\n\tonRemoveAttachment,\n\tonAttach,\n\tshowAttach,\n\tleadingActions,\n\ttrailingActions,\n\thideHint = false,\n\tminRows = 1,\n\tmaxRows = 8,\n\tautoFocus = false,\n\tsubmitKeyLabel = '↩',\n\tclassName,\n\tstrings: stringsProp,\n}: AiChatPromptInputProps) {\n\tconst strings = useStrings(defaultAiChatPromptInputStrings, stringsProp);\n\tconst textareaRef = useRef<HTMLTextAreaElement | null>(null);\n\n\tconst canSubmit =\n\t\t!streaming && !disabled && (value.trim().length > 0 || attachments.length > 0);\n\n\tconst handleSubmit = useCallback(() => {\n\t\tif (!canSubmit) return;\n\t\tonSubmit?.({ text: value, attachments });\n\t}, [canSubmit, onSubmit, value, attachments]);\n\n\tconst handleKeyDown = useCallback(\n\t\t(e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n\t\t\tif (e.key === 'Enter' && !e.shiftKey && !e.nativeEvent.isComposing) {\n\t\t\t\te.preventDefault();\n\t\t\t\thandleSubmit();\n\t\t\t}\n\t\t},\n\t\t[handleSubmit],\n\t);\n\n\tconst showAttachBtn = showAttach ?? Boolean(onAttach);\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t'ai-chat-prompt-input--component',\n\t\t\t\t'rounded-radius border border-input bg-card transition-[color,box-shadow] duration-150',\n\t\t\t\t// The frame is the field: its textarea draws no frame of its own.\n\t\t\t\t'has-[textarea:focus-visible]:border-ring has-[textarea:focus-visible]:ring-3 has-[textarea:focus-visible]:ring-ring/50',\n\t\t\t\tdisabled && 'opacity-50 pointer-events-none',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t{attachments.length > 0 && (\n\t\t\t\t<div className=\"border-b border-border/60 p-surface-xs\">\n\t\t\t\t\t<AiChatAttachmentsStrip\n\t\t\t\t\t\tattachments={attachments}\n\t\t\t\t\t\tonRemove={onRemoveAttachment}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t<Textarea\n\t\t\t\tref={textareaRef}\n\t\t\t\tvalue={value}\n\t\t\t\tonChange={(e) => onValueChange(e.target.value)}\n\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\tplaceholder={strings.placeholder}\n\t\t\t\tautoResize\n\t\t\t\tminRows={minRows}\n\t\t\t\tmaxRows={maxRows}\n\t\t\t\tautoFocus={autoFocus}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'!border-0 !bg-transparent !shadow-none focus-visible:!ring-0 resize-none',\n\t\t\t\t)}\n\t\t\t/>\n\n\t\t\t<div className=\"flex items-center gap-space-xs border-t border-border/60 px-surface-xs py-space-sm\">\n\t\t\t\t{leadingActions}\n\t\t\t\t{showAttachBtn && (\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\t\tsize=\"sm\" iconOnly\n\t\t\t\t\t\taria-label={strings.attachAria}\n\t\t\t\t\t\tonClick={onAttach}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Paperclip className=\"size-icon\" />\n\t\t\t\t\t</Button>\n\t\t\t\t)}\n\t\t\t\t<div className=\"ml-auto flex items-center gap-space-xs\">\n\t\t\t\t\t{trailingActions}\n\t\t\t\t\t{streaming ? (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\t\tbuttonStyle=\"solid\"\n\t\t\t\t\t\t\tsize=\"sm\" iconOnly\n\t\t\t\t\t\t\taria-label={strings.stopAria}\n\t\t\t\t\t\t\tonClick={onStop}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Square className=\"size-icon-md fill-current\" />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\ttone=\"primary\"\n\t\t\t\t\t\t\tbuttonStyle=\"solid\"\n\t\t\t\t\t\t\tsize=\"sm\" iconOnly\n\t\t\t\t\t\t\taria-label={strings.submitAria}\n\t\t\t\t\t\t\tonClick={handleSubmit}\n\t\t\t\t\t\t\tdisabled={!canSubmit}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<ArrowUp className=\"size-icon\" />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{!hideHint && (\n\t\t\t\t<div className=\"px-surface-xs pb-surface-xs\">\n\t\t\t\t\t<Text size=\"xs\" type=\"discrete\">\n\t\t\t\t\t\t{interpolateString(strings.hint, {\n\t\t\t\t\t\t\tsubmitKey: submitKeyLabel,\n\t\t\t\t\t\t\tnewlineKey: '⇧↩',\n\t\t\t\t\t\t})}\n\t\t\t\t\t</Text>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nAiChatPromptInput.displayName = 'AiChatPromptInput';\n","/**\n * AiChatQueue — pending message queue rendered above the prompt input. Used\n * to surface messages the user submitted faster than the assistant could\n * process — each item shows a status pill and an optional cancel control.\n */\nimport { Loader2, X } from 'lucide-react';\nimport { Badge } from '../../../base/badge';\nimport { Button } from '../../../base/buttons';\nimport { Stack } from '../../../base/structure';\nimport { DisplayLabel, Text } from '../../../typography';\nimport { useStrings, type StringsProp } from '../../../../lib/strings';\nimport { cn } from '../../../../lib/utils';\n\nimport {\n\tdefaultAiChatQueueStrings,\n\ttype AiChatQueueStrings,\n} from '../ai-chat.strings';\nimport type { AiChatQueueItem } from '../ai-chat.types';\n\nexport interface AiChatQueueProps {\n\t/** Entries to render. */\n\titems: ReadonlyArray<AiChatQueueItem>;\n\t/** Hides the header region. */\n\thideHeader?: boolean;\n\t/** Fired when entry editing is cancelled. */\n\tonCancel?: (id: string) => void;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n\t/** Overrides this surface's own copy. */\n\tstrings?: StringsProp<AiChatQueueStrings>;\n}\n\nexport function AiChatQueue({\n\titems,\n\thideHeader = false,\n\tonCancel,\n\tclassName,\n\tstrings: stringsProp,\n}: AiChatQueueProps) {\n\tconst strings = useStrings(defaultAiChatQueueStrings, stringsProp);\n\tif (items.length === 0) return null;\n\treturn (\n\t\t<Stack gap=\"sm\"\n\t\t\tclassName={cn(\n\t\t\t\t'ai-chat-queue--component',\n\t\t\t\t'rounded-radius border border-border/60 bg-muted/30 p-surface-xs',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t{!hideHeader && (\n\t\t\t\t<DisplayLabel className=\"px-1\">\n\t\t\t\t\t{strings.header} · {items.length}\n\t\t\t\t</DisplayLabel>\n\t\t\t)}\n\t\t\t<Stack render={<ul />} gap=\"xs\" className=\"ai-chat-queue--list m-0 list-none p-0 font-sans\">\n\t\t\t\t{items.map((item) => {\n\t\t\t\t\tconst status = item.status ?? 'queued';\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<li\n\t\t\t\t\t\t\tkey={item.id}\n\t\t\t\t\t\t\tclassName=\"flex items-center gap-space-md rounded-inner bg-card px-space-md py-space-sm\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{status === 'running' ? (\n\t\t\t\t\t\t\t\t<Loader2 className=\"size-icon-md shrink-0 animate-spin text-primary-accent\" />\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t// The dot sits in the spinner's footprint so labels align across rows.\n\t\t\t\t\t\t\t\t<span aria-hidden className=\"flex size-icon-md shrink-0 items-center justify-center\">\n\t\t\t\t\t\t\t\t\t<span className=\"size-2 rounded-full bg-muted-foreground\" />\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<Text className=\"flex-1 truncate\">\n\t\t\t\t\t\t\t\t{item.label}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t<Badge tone={status === 'running' ? 'info' : 'secondary'}>\n\t\t\t\t\t\t\t\t{status === 'running' ? strings.runningLabel : strings.queuedLabel}\n\t\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t\t{(!!item.onCancel || !!onCancel) && (\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\t\t\t\t\tsize=\"sm\" iconOnly\n\t\t\t\t\t\t\t\t\taria-label={strings.cancelAria}\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\titem.onCancel?.();\n\t\t\t\t\t\t\t\t\t\tonCancel?.(item.id);\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<X className=\"size-icon-md\" />\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</li>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</Stack>\n\t\t</Stack>\n\t);\n}\n\nAiChatQueue.displayName = 'AiChatQueue';\n","/**\n * AiChatSuggestionsRow — horizontal scrollable strip of small suggestion\n * chips rendered above the prompt input. Distinct from\n * `<AiPromptSuggestions>` (which is a card-grid of richer suggestions used\n * as a welcome surface): this is the inline, dense variant.\n */\nimport { Button } from '../../../base/buttons';\nimport { DisplayLabel, Text } from '../../../typography';\nimport { useStrings, type StringsProp } from '../../../../lib/strings';\nimport { cn } from '../../../../lib/utils';\n\nimport {\n\tdefaultAiChatSuggestionsStrings,\n\ttype AiChatSuggestionsStrings,\n} from '../ai-chat.strings';\nimport type { AiChatSuggestion } from '../ai-chat.types';\n\nexport interface AiChatSuggestionsRowProps<TData = unknown> {\n\t/** Matches for the current query. */\n\tsuggestions: ReadonlyArray<AiChatSuggestion<TData>>;\n\tonPick?: (s: AiChatSuggestion<TData>) => void;\n\t/** Hides the header region. */\n\thideHeader?: boolean;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n\t/** Overrides this surface's own copy. */\n\tstrings?: StringsProp<AiChatSuggestionsStrings>;\n}\n\nexport function AiChatSuggestionsRow<TData = unknown>({\n\tsuggestions,\n\tonPick,\n\thideHeader = false,\n\tclassName,\n\tstrings: stringsProp,\n}: AiChatSuggestionsRowProps<TData>) {\n\tconst strings = useStrings(defaultAiChatSuggestionsStrings, stringsProp);\n\tif (suggestions.length === 0) return null;\n\treturn (\n\t\t<div className={cn('ai-chat-suggestions-row--component flex items-center gap-space-md', className)}>\n\t\t\t{!hideHeader && (\n\t\t\t\t<DisplayLabel className=\"shrink-0\">\n\t\t\t\t\t{strings.header}\n\t\t\t\t</DisplayLabel>\n\t\t\t)}\n\t\t\t<div className=\"flex min-w-0 flex-1 items-center gap-space-sm overflow-x-auto p-space-xs [scrollbar-width:none] [&::-webkit-scrollbar]:hidden\">\n\t\t\t\t{suggestions.map((s) => {\n\t\t\t\t\tconst Icon = s.icon;\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tkey={s.id}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\t\tbuttonStyle=\"outline\"\n\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\tonClick={() => onPick?.(s)}\n\t\t\t\t\t\t\tclassName=\"shrink-0 gap-space-sm\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{!!Icon && <Icon className=\"size-icon-sm text-muted-foreground\" />}\n\t\t\t\t\t\t\t<Text tag=\"span\" weight=\"medium\">\n\t\t\t\t\t\t\t\t{s.label}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nAiChatSuggestionsRow.displayName = 'AiChatSuggestionsRow';\n","/**\n * AiChat — framework-agnostic AI chat surface. Tie-together component for\n * the `features/ai-chat/*` partials. Renders an optional agent header, the\n * scrollable conversation, an optional queue + suggestions row, and the\n * prompt input.\n *\n * Composition seams:\n * - `slots` — replace any region (header, intro, empty, queue,\n * suggestions, input, belowMessages) or per-message\n * (`renderMessage`).\n * - `strings` — deep-partial override of every default copy line\n * (prompt, conversation, queue, suggestions, message).\n * - Partials — every partial is exported individually so a consumer\n * can build a custom layout against the same data shape.\n *\n * Headless usage:\n * - The `useAiChatScroll` hook is exported for consumers building a\n * custom conversation layout while keeping auto-stick-to-bottom.\n *\n * Framework-agnostic:\n * - No router, no i18n SDK, no fetcher. Submission is a callback\n * (`onSubmit`); messages, queue, attachments are all controlled props.\n */\nimport { useCallback, useState, type ReactNode } from 'react';\nimport { AiAgent } from '../../blocks/ai/ai-agent';\nimport { Stack } from '../../base/structure';\nimport { Text } from '../../typography';\nimport { useStrings, type StringsProp } from '../../../lib/strings';\nimport { cn } from '../../../lib/utils';\n\nimport {\n\tdefaultAiChatStrings,\n\ttype AiChatStrings,\n} from './ai-chat.strings';\nimport type {\n\tAiChatAgent,\n\tAiChatAttachment,\n\tAiChatMessage as AiChatMessageType,\n\tAiChatQueueItem,\n\tAiChatSlots,\n\tAiChatSubmitValues,\n\tAiChatSuggestion,\n} from './ai-chat.types';\nimport {\n\tAiChatConversation,\n\tAiChatEmptyState,\n\tAiChatMessage,\n\tAiChatPromptInput,\n\tAiChatQueue,\n\tAiChatSuggestionsRow,\n} from './partials';\n\nexport interface AiChatProps<TSuggestionData = unknown> {\n\t/** Conversation messages — order is significant. */\n\tmessages: ReadonlyArray<AiChatMessageType>;\n\n\t/** Controlled prompt input value. */\n\tinputValue: string;\n\t/** Prompt input change callback. */\n\tonInputChange: (value: string) => void;\n\t/** Fired on submit (Enter or send button). */\n\tonSubmit?: (values: AiChatSubmitValues) => void;\n\t/** Fired when the user clicks the stop button while `streaming`. */\n\tonStop?: () => void;\n\t/** Streaming flag — controls submit/stop UI in the prompt input. */\n\tstreaming?: boolean;\n\t/** Disable composer entirely. */\n\tdisabled?: boolean;\n\n\t/** Currently staged attachments. */\n\tattachments?: ReadonlyArray<AiChatAttachment>;\n\t/** Remove a staged attachment. */\n\tonRemoveAttachment?: (id: string) => void;\n\t/** Fires when the user clicks the attach button. */\n\tonAttach?: () => void;\n\t/** Toggles the attach button visibility. Defaults to `true` when `onAttach` is provided. */\n\tshowAttach?: boolean;\n\n\t/** Agent identity — drives the optional header strip. Pass `null` to hide. */\n\tagent?: AiChatAgent | null;\n\t/** Trailing slot inside the header (e.g. settings button). */\n\theaderActions?: ReactNode;\n\n\t/** Pending message queue (rendered above the input). */\n\tqueue?: ReadonlyArray<AiChatQueueItem>;\n\t/** Cancel callback — fires per-item when the queue chip's × is clicked. */\n\tonCancelQueueItem?: (id: string) => void;\n\n\t/** Inline quick suggestions (rendered above the input). */\n\tsuggestions?: ReadonlyArray<AiChatSuggestion<TSuggestionData>>;\n\t/** Suggestion select callback. */\n\tonPickSuggestion?: (s: AiChatSuggestion<TSuggestionData>) => void;\n\n\t/** Per-message copy callback. */\n\tonMessageCopy?: (message: AiChatMessageType) => void;\n\t/** Per-message regenerate callback (assistant only). */\n\tonMessageRegenerate?: (message: AiChatMessageType) => void;\n\t/** Per-message attachment open callback. */\n\tonAttachmentOpen?: (messageId: string, attachmentId: string) => void;\n\n\t/** Disable auto-stick-to-bottom in the conversation. */\n\tdisableAutoScroll?: boolean;\n\n\t/** Slot map for replacing default surfaces. */\n\tslots?: AiChatSlots;\n\t/** String overrides. */\n\tstrings?: StringsProp<AiChatStrings>;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n}\n\nexport function AiChat<TSuggestionData = unknown>({\n\tmessages,\n\tinputValue,\n\tonInputChange,\n\tonSubmit,\n\tonStop,\n\tstreaming = false,\n\tdisabled = false,\n\tattachments = [],\n\tonRemoveAttachment,\n\tonAttach,\n\tshowAttach,\n\tagent,\n\theaderActions,\n\tqueue = [],\n\tonCancelQueueItem,\n\tsuggestions = [],\n\tonPickSuggestion,\n\tonMessageCopy,\n\tonMessageRegenerate,\n\tonAttachmentOpen,\n\tdisableAutoScroll,\n\tslots,\n\tstrings: stringsProp,\n\tclassName,\n}: AiChatProps<TSuggestionData>) {\n\tconst strings = useStrings(defaultAiChatStrings, stringsProp);\n\tconst [, force] = useState(0);\n\n\tconst renderMessage = useCallback(\n\t\t(\n\t\t\tmessage: AiChatMessageType,\n\t\t\tctx: { isLast: boolean; index: number },\n\t\t): ReactNode => {\n\t\t\tif (slots?.renderMessage) {\n\t\t\t\treturn slots.renderMessage(message, ctx);\n\t\t\t}\n\t\t\treturn (\n\t\t\t\t<AiChatMessage className=\"ai-chat-message--component\"\n\t\t\t\t\tmessage={message}\n\t\t\t\t\tstrings={strings.message}\n\t\t\t\t\tonCopy={\n\t\t\t\t\t\tonMessageCopy ? () => onMessageCopy(message) : undefined\n\t\t\t\t\t}\n\t\t\t\t\tonRegenerate={\n\t\t\t\t\t\tonMessageRegenerate\n\t\t\t\t\t\t\t? () => onMessageRegenerate(message)\n\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t}\n\t\t\t\t\tonAttachmentOpen={\n\t\t\t\t\t\tonAttachmentOpen\n\t\t\t\t\t\t\t? (attachmentId) => onAttachmentOpen(message.id, attachmentId)\n\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t);\n\t\t},\n\t\t[\n\t\t\tonAttachmentOpen,\n\t\t\tonMessageCopy,\n\t\t\tonMessageRegenerate,\n\t\t\tslots,\n\t\t\tstrings.message,\n\t\t],\n\t);\n\n\tconst Header: ReactNode =\n\t\tslots?.header ??\n\t\t(agent ? (\n\t\t\t<div className=\"border-b border-border bg-card p-surface\">\n\t\t\t<Stack direction=\"horizontal\" align=\"center\" gap=\"lg\">\n\t\t\t\t<AiAgent\n\t\t\t\t\tname={agent.name}\n\t\t\t\t\ticon={agent.icon}\n\t\t\t\t\tavatar={agent.avatar}\n\t\t\t\t\tsubtitle={agent.subtitle}\n\t\t\t\t\ttone={agent.tone}\n\t\t\t\t\tstatus={agent.status}\n\t\t\t\t\tvariant=\"inline\"\n\t\t\t\t/>\n\t\t\t\t{!!headerActions && (\n\t\t\t\t\t<div className=\"ml-auto flex items-center gap-space-xs\">{headerActions}</div>\n\t\t\t\t)}\n\t\t\t</Stack>\n\t\t\t</div>\n\t\t) : null);\n\n\tconst Empty: ReactNode =\n\t\tslots?.empty ??\n\t\t(messages.length === 0 ? (\n\t\t\t<AiChatEmptyState\n\t\t\t\ttitle={strings.emptyTitle}\n\t\t\t\tdescription={strings.emptyDescription}\n\t\t\t/>\n\t\t) : null);\n\n\tconst Queue: ReactNode =\n\t\tslots?.queue ??\n\t\t(queue.length > 0 ? (\n\t\t\t<AiChatQueue\n\t\t\t\titems={queue}\n\t\t\t\tonCancel={onCancelQueueItem}\n\t\t\t\tstrings={strings.queue}\n\t\t\t/>\n\t\t) : null);\n\n\tconst Suggestions: ReactNode =\n\t\tslots?.suggestions ??\n\t\t(suggestions.length > 0 ? (\n\t\t\t<AiChatSuggestionsRow<TSuggestionData>\n\t\t\t\tsuggestions={suggestions}\n\t\t\t\tonPick={onPickSuggestion}\n\t\t\t\tstrings={strings.suggestions}\n\t\t\t/>\n\t\t) : null);\n\n\tconst Input: ReactNode =\n\t\tslots?.input ?? (\n\t\t\t<AiChatPromptInput\n\t\t\t\tvalue={inputValue}\n\t\t\t\tonValueChange={onInputChange}\n\t\t\t\tonSubmit={(values) => {\n\t\t\t\t\tonSubmit?.(values);\n\t\t\t\t\t// Force re-render so consumers that read inputValue/attachments\n\t\t\t\t\t// from controlled state see the freshly cleared values they\n\t\t\t\t\t// pushed in their onSubmit handler.\n\t\t\t\t\tforce((v) => v + 1);\n\t\t\t\t}}\n\t\t\t\tonStop={onStop}\n\t\t\t\tstreaming={streaming}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tattachments={attachments}\n\t\t\t\tonRemoveAttachment={onRemoveAttachment}\n\t\t\t\tonAttach={onAttach}\n\t\t\t\tshowAttach={showAttach}\n\t\t\t\tstrings={strings.prompt}\n\t\t\t/>\n\t\t);\n\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t'ai-chat--component flex h-full flex-col overflow-hidden rounded-radius border border-border bg-background',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t{Header}\n\n\t\t\t<AiChatConversation\n\t\t\t\tmessages={messages}\n\t\t\t\trenderMessage={renderMessage}\n\t\t\t\tintro={slots?.intro}\n\t\t\t\tfooter={slots?.belowMessages}\n\t\t\t\tempty={Empty}\n\t\t\t\tdisableAutoScroll={disableAutoScroll}\n\t\t\t\tstrings={strings.conversation}\n\t\t\t/>\n\n\t\t\t{(Queue || Suggestions || Input) && (\n\t\t\t\t\t<div className=\"border-t border-border bg-card p-surface\">\n\t\t\t\t\t<Stack gap=\"md\">\n\t\t\t\t\t{Queue}\n\t\t\t\t\t{Suggestions}\n\t\t\t\t\t{Input}\n\t\t\t\t\t</Stack>\n\t\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{disabled && (\n\t\t\t\t<Text className=\"sr-only\" aria-live=\"polite\">\n\t\t\t\t\t{strings.disabledAnnouncement}\n\t\t\t\t</Text>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nAiChat.displayName = 'AiChat';\n"],"mappings":"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"}
1
+ {"version":3,"file":"ai-chat.js","names":["_Fragment","cn","Button","Text","DisplayLabel","focusRecipes","Stack","dotRecipes","Badge","fieldStateRecipes","EmptyState","messageColumns","messageContentColumn","hasMessageMedia","AiMessageBubble","AiChainOfThought","AiToolCall","AiConfirmation","AiAttachment","AiSources","AiAgent","AiTask","AiReasoning","AiArtifact","AiShimmer","Fragment$1","defaultAiChatPromptInputStrings","defaultAiChatConversationStrings","defaultAiChatQueueStrings","defaultAiChatSuggestionsStrings","defaultAiChatMessageStrings","defaultAiChatStrings","AiChatAttachmentsStrip","attachments","className","att","onOpen","onRemove","useAiChatScroll","containerRef","useRef","endRef","isAtBottom","setIsAtBottom","useState","scrollToBottom","useCallback","useEffect","el","onScroll","distance","threshold","disableAutoScroll","id","dependency","AiChatConversation","stringsProp","strings","useStrings","messages","isEmpty","intro","empty","ctx","idx","renderMessage","message","footer","ArrowDown","AiChatEmptyState","IconComponent","Sparkles","media","description","below","AiChatMessage","align","inBubble","part","plainText","p","extractPlain","bubbleContent","hasBubble","hasAvatar","continuationColumn","onCopy","PartRenderer","AiCodeBlock","onAttachmentOpen","node","AiChatPromptInput","textareaRef","canSubmit","streaming","disabled","value","handleSubmit","onSubmit","handleKeyDown","showAttachBtn","showAttach","onAttach","onRemoveAttachment","Textarea","onValueChange","leadingActions","Paperclip","trailingActions","onStop","Square","ArrowUp","hideHint","interpolateString","submitKeyLabel","AiChatQueue","items","hideHeader","status","item","Loader2","onCancel","X","AiChatSuggestionsRow","suggestions","Icon","s","onPick","AiChat","force","slots","onMessageCopy","onMessageRegenerate","attachmentId","Header","agent","headerActions","Empty","Queue","queue","onCancelQueueItem","Suggestions","onPickSuggestion","Input","inputValue","onInputChange","values","v"],"sources":["../../src/components/features/ai-chat/ai-chat.strings.ts","../../src/components/features/ai-chat/partials/ai-chat-attachments-strip.tsx","../../src/components/features/ai-chat/hooks/use-ai-chat-scroll.ts","../../src/components/features/ai-chat/partials/ai-chat-conversation.tsx","../../src/components/features/ai-chat/partials/ai-chat-empty-state.tsx","../../src/components/features/ai-chat/partials/ai-chat-message.tsx","../../src/components/features/ai-chat/partials/ai-chat-prompt-input.tsx","../../src/components/features/ai-chat/partials/ai-chat-queue.tsx","../../src/components/features/ai-chat/partials/ai-chat-suggestions-row.tsx","../../src/components/features/ai-chat/ai-chat.tsx"],"sourcesContent":["/**\n * Strings for `<AiChat>` and its partials. Each interface is co-located so\n * partials and the feature root all read from one source of truth (rule 19).\n * Consumers override via the `strings` prop on the relevant component; values\n * are deep-merged over the defaults so partial overrides are safe.\n */\n\nexport interface AiChatPromptInputStrings {\n\t/** Placeholder copy for the textarea. */\n\tplaceholder: string;\n\t/** Aria label for the attach button. */\n\tattachAria: string;\n\t/** Aria label for the submit button. */\n\tsubmitAria: string;\n\t/** Aria label for the stop button (replaces submit while streaming). */\n\tstopAria: string;\n\t/** Aria label for the model picker button (when `modelPicker` is provided). */\n\tmodelPickerAria: string;\n\t/** Hint shown under the input. Supports `{{key}}` for the submit shortcut. */\n\thint: string;\n}\n\nexport const defaultAiChatPromptInputStrings: AiChatPromptInputStrings = {\n\tplaceholder: 'Ask anything…',\n\tattachAria: 'Attach files',\n\tsubmitAria: 'Send message',\n\tstopAria: 'Stop generating',\n\tmodelPickerAria: 'Choose model',\n\thint: 'Press {{submitKey}} to send · {{newlineKey}} for newline',\n};\n\nexport interface AiChatConversationStrings {\n\ttranscriptAria: string;\n\t/** Shown in place of the collection when it has no entries. */\n\tempty: string;\n\tscrollToBottom: string;\n\tscrollToBottomAria: string;\n}\n\nexport const defaultAiChatConversationStrings: AiChatConversationStrings = {\n\ttranscriptAria: 'Conversation messages',\n\tempty: 'No messages yet.',\n\tscrollToBottom: 'Jump to latest',\n\tscrollToBottomAria: 'Scroll to bottom',\n};\n\nexport interface AiChatQueueStrings {\n\theader: string;\n\tcancelAria: string;\n\tqueuedLabel: string;\n\trunningLabel: string;\n}\n\nexport const defaultAiChatQueueStrings: AiChatQueueStrings = {\n\theader: 'In queue',\n\tcancelAria: 'Remove from queue',\n\tqueuedLabel: 'Queued',\n\trunningLabel: 'Running',\n};\n\nexport interface AiChatSuggestionsStrings {\n\theader: string;\n}\n\nexport const defaultAiChatSuggestionsStrings: AiChatSuggestionsStrings = {\n\theader: 'Try',\n};\n\nexport interface AiChatMessageStrings {\n\tpending: string;\n}\n\nexport const defaultAiChatMessageStrings: AiChatMessageStrings = {\n\tpending: 'Thinking…',\n};\n\nexport interface AiChatStrings {\n\tprompt: AiChatPromptInputStrings;\n\tconversation: AiChatConversationStrings;\n\tqueue: AiChatQueueStrings;\n\tsuggestions: AiChatSuggestionsStrings;\n\tmessage: AiChatMessageStrings;\n\temptyTitle: string;\n\temptyDescription: string;\n\t/** Screen-reader announcement emitted while the composer is disabled. */\n\tdisabledAnnouncement: string;\n}\n\nexport const defaultAiChatStrings: AiChatStrings = {\n\tprompt: defaultAiChatPromptInputStrings,\n\tconversation: defaultAiChatConversationStrings,\n\tqueue: defaultAiChatQueueStrings,\n\tsuggestions: defaultAiChatSuggestionsStrings,\n\tmessage: defaultAiChatMessageStrings,\n\temptyTitle: 'Start a conversation',\n\temptyDescription: 'Ask a question, share context, or attach a file to get going.',\n\tdisabledAnnouncement: 'Chat is disabled',\n};\n","/**\n * AiChatAttachmentsStrip — flex-wrap row of `<AiAttachment>` chips. Used both\n * in the prompt input (staged uploads — pass `onRemove` to enable a remove\n * button) and inside messages (read-only attachment list).\n */\nimport { AiAttachment } from '../../../blocks/ai/ai-attachment';\nimport { Stack } from '../../../base/structure';\nimport { cn } from '../../../../lib/utils';\n\nimport type { AiChatAttachment } from '../ai-chat.types';\n\nexport interface AiChatAttachmentsStripProps {\n\t/** Files staged on the draft. */\n\tattachments: ReadonlyArray<AiChatAttachment>;\n\t/** When set, each chip gets a remove button wired to this handler. */\n\tonRemove?: (id: string) => void;\n\t/** When set, click on a chip calls this. */\n\tonOpen?: (att: AiChatAttachment) => void;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n}\n\nexport function AiChatAttachmentsStrip({\n\tattachments,\n\tonRemove,\n\tonOpen,\n\tclassName,\n}: AiChatAttachmentsStripProps) {\n\tif (attachments.length === 0) return null;\n\treturn (\n\t\t<Stack\n\t\t\tdirection=\"horizontal\"\n\t\t\tgap=\"sm\"\n\t\t\tclassName={cn('ai-chat-attachments-strip--component', className)}\n\t\t>\n\t\t\t{attachments.map((att) => (\n\t\t\t\t<AiAttachment\n\t\t\t\t\tkey={att.id}\n\t\t\t\t\tname={att.name}\n\t\t\t\t\tmeta={att.meta}\n\t\t\t\t\tkind={att.kind}\n\t\t\t\t\ticon={att.icon}\n\t\t\t\t\tthumbnailUrl={att.thumbnailUrl}\n\t\t\t\t\tprogress={att.progress}\n\t\t\t\t\terrored={att.errored}\n\t\t\t\t\tonOpen={onOpen ? () => onOpen(att) : undefined}\n\t\t\t\t\tonRemove={onRemove ? () => onRemove(att.id) : undefined}\n\t\t\t\t/>\n\t\t\t))}\n\t\t</Stack>\n\t);\n}\n\nAiChatAttachmentsStrip.displayName = 'AiChatAttachmentsStrip';\n","/**\n * useAiChatScroll — auto-stick-to-bottom scroll behaviour for chat\n * conversations. Detects when the user has scrolled away from the latest\n * message and pauses auto-scroll until they return.\n *\n * Returns:\n * - `containerRef` — attach to the scroll viewport.\n * - `endRef` — attach to a sentinel at the very bottom.\n * - `isAtBottom` — true when the viewport is pinned to the latest content.\n * - `scrollToBottom` — imperatively scroll to the sentinel.\n */\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nexport interface UseAiChatScrollOptions {\n\t/** Distance (px) from bottom counted as \"at bottom\". */\n\tthreshold?: number;\n\t/** Re-evaluate on these dependencies (typically the message count). */\n\tdependency?: unknown;\n\t/** Disable auto-scroll-on-update behaviour. */\n\tdisableAutoScroll?: boolean;\n}\n\nexport interface UseAiChatScrollReturn {\n\tcontainerRef: React.RefObject<HTMLDivElement | null>;\n\tendRef: React.RefObject<HTMLDivElement | null>;\n\tisAtBottom: boolean;\n\tscrollToBottom: (behavior?: ScrollBehavior) => void;\n}\n\nexport function useAiChatScroll({\n\tthreshold = 80,\n\tdependency,\n\tdisableAutoScroll = false,\n}: UseAiChatScrollOptions = {}): UseAiChatScrollReturn {\n\tconst containerRef = useRef<HTMLDivElement | null>(null);\n\tconst endRef = useRef<HTMLDivElement | null>(null);\n\tconst [isAtBottom, setIsAtBottom] = useState(true);\n\n\tconst scrollToBottom = useCallback(\n\t\t(behavior: ScrollBehavior = 'smooth') => {\n\t\t\tendRef.current?.scrollIntoView({ behavior, block: 'end' });\n\t\t},\n\t\t[],\n\t);\n\n\t// Track scroll position so we can pause auto-scroll when the user reads up.\n\tuseEffect(() => {\n\t\tconst el = containerRef.current;\n\t\tif (!el) return;\n\t\tconst onScroll = () => {\n\t\t\tconst distance = el.scrollHeight - el.clientHeight - el.scrollTop;\n\t\t\tsetIsAtBottom(distance <= threshold);\n\t\t};\n\t\tonScroll();\n\t\tel.addEventListener('scroll', onScroll, { passive: true });\n\t\treturn () => el.removeEventListener('scroll', onScroll);\n\t}, [threshold]);\n\n\t// Auto-scroll when content updates and the user is pinned at the bottom.\n\tuseEffect(() => {\n\t\tif (disableAutoScroll) return;\n\t\tif (!isAtBottom) return;\n\t\t// Use rAF so we wait for layout to settle after the new content paints.\n\t\tconst id = window.requestAnimationFrame(() => scrollToBottom('auto'));\n\t\treturn () => window.cancelAnimationFrame(id);\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [dependency, disableAutoScroll]);\n\n\treturn { containerRef, endRef, isAtBottom, scrollToBottom };\n}\n","/**\n * AiChatConversation — scrollable list container for chat messages with\n * auto-stick-to-bottom behaviour. Renders each message via the consumer's\n * `renderMessage` slot (or the default `<AiChatMessage>` via the parent\n * `<AiChat>`). Surfaces a \"Jump to latest\" pill when the user scrolls away\n * from the bottom while content streams in.\n */\nimport { ArrowDown } from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport { Button } from '../../../base/buttons';\nimport { Stack } from '../../../base/structure';\nimport { Text } from '../../../typography';\nimport { useStrings, type StringsProp } from '../../../../lib/strings';\nimport { cn } from '../../../../lib/utils';\n\nimport {\n\tdefaultAiChatConversationStrings,\n\ttype AiChatConversationStrings,\n} from '../ai-chat.strings';\nimport type {\n\tAiChatMessage as AiChatMessageType,\n\tAiChatRenderMessageContext,\n} from '../ai-chat.types';\nimport { useAiChatScroll } from '../hooks/use-ai-chat-scroll';\nimport { focusRecipes } from '../../../../lib/focus-recipes';\n\nexport interface AiChatConversationProps {\n\t/** Messages to render, oldest first. */\n\tmessages: ReadonlyArray<AiChatMessageType>;\n\t/** Replaces the default message rendering. */\n\trenderMessage: (\n\t\t/** The message this row represents. */\n\t\tmessage: AiChatMessageType,\n\t\tctx: AiChatRenderMessageContext,\n\t) => ReactNode;\n\t/** Render before the messages list (intro card, agent greeting). */\n\tintro?: ReactNode;\n\t/** Render after the messages list (e.g. tip ribbon). */\n\tfooter?: ReactNode;\n\t/** Replaces the empty state when `messages.length === 0`. */\n\tempty?: ReactNode;\n\t/** Pause auto-scroll-on-update. */\n\tdisableAutoScroll?: boolean;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n\t/** Overrides this surface's own copy. */\n\tstrings?: StringsProp<AiChatConversationStrings>;\n}\n\nexport function AiChatConversation({\n\tmessages,\n\trenderMessage,\n\tintro,\n\tfooter,\n\tempty,\n\tdisableAutoScroll,\n\tclassName,\n\tstrings: stringsProp,\n}: AiChatConversationProps) {\n\tconst strings = useStrings(defaultAiChatConversationStrings, stringsProp);\n\tconst { containerRef, endRef, isAtBottom, scrollToBottom } = useAiChatScroll({\n\t\tdependency: messages.length,\n\t\tdisableAutoScroll,\n\t});\n\n\tconst isEmpty = messages.length === 0 && !intro;\n\n\treturn (\n\t\t<div className={cn('ai-chat-conversation--component relative flex h-full min-h-0 flex-col', className)}>\n\t\t\t<div\n\t\t\t\tref={containerRef}\n\t\t\t\ttabIndex={0}\n\t\t\t\taria-label={strings.transcriptAria}\n\t\t\t\tclassName={`flex-1 overflow-y-auto p-surface focus-visible:outline-none ${focusRecipes.inset}`}\n\t\t\t>\n\t\t\t\t{!!intro && <div className=\"mb-space-xl\">{intro}</div>}\n\n\t\t\t\t{isEmpty ? (\n\t\t\t\t\tempty ?? (\n\t\t\t\t\t\t<div className=\"flex h-full items-center justify-center p-surface-lg\">\n\t\t\t\t\t\t\t<Text type=\"secondary\">{strings.empty}</Text>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)\n\t\t\t\t) : (\n\t\t\t\t\t<Stack render={<ol />} gap=\"xl\" className=\"ai-chat-conversation--messages m-0 list-none p-0 font-sans\">\n\t\t\t\t\t\t{messages.map((message, idx) => {\n\t\t\t\t\t\t\tconst ctx: AiChatRenderMessageContext = {\n\t\t\t\t\t\t\t\tisLast: idx === messages.length - 1,\n\t\t\t\t\t\t\t\tindex: idx,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<li key={message.id}>{renderMessage(message, ctx)}</li>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t</Stack>\n\t\t\t\t)}\n\n\t\t\t\t{!!footer && <div className=\"mt-space-xl\">{footer}</div>}\n\n\t\t\t\t<div ref={endRef} aria-hidden className=\"h-px\" />\n\t\t\t</div>\n\n\t\t\t{!isAtBottom && (\n\t\t\t\t<div className=\"ai-chat-conversation--jump flex shrink-0 justify-center border-t border-border/60 bg-background px-space-md py-space-sm\">\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\tbuttonStyle=\"solid\"\n\t\t\t\t\t\taria-label={strings.scrollToBottomAria}\n\t\t\t\t\t\tonClick={() => scrollToBottom('smooth')}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'shadow-sm max-sm:size-action-sm max-sm:min-h-0 max-sm:p-0',\n\t\t\t\t\t\t\t'border border-border/60',\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ArrowDown className=\"size-icon-md\" />\n\t\t\t\t\t\t<Text tag=\"span\" size=\"pxs\" className=\"max-sm:sr-only\">\n\t\t\t\t\t\t\t{strings.scrollToBottom}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nAiChatConversation.displayName = 'AiChatConversation';\n","/**\n * AiChatEmptyState — default empty surface for `<AiChat>` when no messages\n * are present and no intro is provided. Centers a title + description with\n * an optional below-content slot for prompt-suggestion grids.\n */\nimport type { ReactNode } from 'react';\nimport { Sparkles } from 'lucide-react';\nimport { Stack } from '../../../base/structure';\nimport { EmptyState } from '../../../blocks/data-display';\nimport { cn } from '../../../../lib/utils';\n\nexport interface AiChatEmptyStateProps {\n\t/** Surface title. */\n\ttitle?: ReactNode;\n\t/** Supporting copy shown under the label. */\n\tdescription?: ReactNode;\n\t/** Leading glyph. */\n\ticon?: React.ElementType;\n\t/** Content rendered under the main body. */\n\tbelow?: ReactNode;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n}\n\nexport function AiChatEmptyState({\n\ttitle = 'Start a conversation',\n\tdescription,\n\ticon: IconComponent = Sparkles,\n\tbelow,\n\tclassName,\n}: AiChatEmptyStateProps) {\n\tconst media = <IconComponent className=\"size-icon\" aria-hidden=\"true\" />;\n\n\treturn (\n\t\t<Stack\n\t\t\tgap=\"md\"\n\t\t\talign=\"center\"\n\t\t\tjustify=\"center\"\n\t\t\tclassName={cn('ai-chat-empty-state--component min-h-full text-center', className)}\n\t\t>\n\t\t\t<EmptyState\n\t\t\t\ttitle={title}\n\t\t\t\tdescription={description ?? false}\n\t\t\t\tmedia={media}\n\t\t\t\tmediaVariant=\"icon\"\n\t\t\t\tpadding=\"md\"\n\t\t\t\tclassName=\"w-full\"\n\t\t\t/>\n\t\t\t{!!below && <div className=\"w-full max-w-2xl\">{below}</div>}\n\t\t</Stack>\n\t);\n}\n\nAiChatEmptyState.displayName = 'AiChatEmptyState';\n","/**\n * AiChatMessage — message renderer that wraps `<AiMessageBubble>` and routes\n * each `parts[]` entry to its dedicated `blocks/ai/*` surface (text, code,\n * tool calls, reasoning, sources, attachments, …).\n *\n * Most surfaces sit BELOW the bubble (artifact, sources, task) since they\n * carry their own chrome; plain text and inline citations render INSIDE the\n * bubble. Custom-typed parts call `render()` directly.\n */\nimport type { ReactNode } from 'react';\nimport { AiArtifact } from '../../../blocks/ai/ai-artifact';\nimport { AiChainOfThought } from '../../../blocks/ai/ai-chain-of-thought';\nimport { AiCodeBlock } from '../../../blocks/ai/ai-code-block';\nimport { AiConfirmation } from '../../../blocks/ai/ai-confirmation';\nimport { AiMessageBubble } from '../../../blocks/ai/ai-message-bubble';\nimport { AiReasoning } from '../../../blocks/ai/ai-reasoning';\nimport { AiShimmer } from '../../../blocks/ai/ai-shimmer';\nimport { AiSources } from '../../../blocks/ai/ai-sources';\nimport { AiTask } from '../../../blocks/ai/ai-task';\nimport { AiToolCall } from '../../../blocks/ai/ai-tool-call';\nimport { Stack } from '../../../base/structure';\nimport { Text } from '../../../typography';\nimport { useStrings, type StringsProp } from '../../../../lib/strings';\nimport { cn } from '../../../../lib/utils';\n\nimport {\n\tdefaultAiChatMessageStrings,\n\ttype AiChatMessageStrings,\n} from '../ai-chat.strings';\nimport type {\n\tAiChatMessage as AiChatMessageType,\n\tAiChatMessagePart,\n} from '../ai-chat.types';\nimport { AiChatAttachmentsStrip } from './ai-chat-attachments-strip';\nimport { hasMessageMedia, messageColumns, messageContentColumn } from '../../../blocks/collaboration/message/message.recipes';\n\nexport interface AiChatMessageProps {\n\t/** The message this row represents. */\n\tmessage: AiChatMessageType;\n\t/** Copy callback forwarded to the underlying bubble. */\n\tonCopy?: () => void;\n\t/** Regenerate callback forwarded to the underlying bubble (assistant only). */\n\tonRegenerate?: () => void;\n\t/** Open handler for attachment chips inside the message. */\n\tonAttachmentOpen?: (attachmentId: string) => void;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n\t/** Overrides this surface's own copy. */\n\tstrings?: StringsProp<AiChatMessageStrings>;\n}\n\nexport function AiChatMessage({\n\tmessage,\n\tonCopy,\n\tonRegenerate,\n\tonAttachmentOpen,\n\tclassName,\n\tstrings: stringsProp,\n}: AiChatMessageProps) {\n\tconst strings = useStrings(defaultAiChatMessageStrings, stringsProp);\n\tconst align = message.role === 'user' ? 'end' : 'start';\n\n\t// Split parts: in-bubble (text) vs below-bubble (everything else).\n\tconst inBubble: AiChatMessagePart[] = [];\n\tconst below: AiChatMessagePart[] = [];\n\tfor (const part of message.parts) {\n\t\tif (part.type === 'text') inBubble.push(part);\n\t\telse below.push(part);\n\t}\n\n\tconst plainText =\n\t\tinBubble\n\t\t\t.map((p) => (p.type === 'text' ? p.plain ?? extractPlain(p.content) : ''))\n\t\t\t.filter(Boolean)\n\t\t\t.join('\\n') || undefined;\n\n\tconst bubbleContent: ReactNode = message.pending ? (\n\t\t<AiShimmer>{strings.pending}</AiShimmer>\n\t) : inBubble.length === 0 && below.length > 0 ? null : (\n\t\t<Stack gap=\"md\">\n\t\t\t{inBubble.map((part, idx) =>\n\t\t\t\tpart.type === 'text' ? (\n\t\t\t\t\t<div key={idx} className=\"whitespace-pre-wrap\">\n\t\t\t\t\t\t{part.content}\n\t\t\t\t\t</div>\n\t\t\t\t) : null,\n\t\t\t)}\n\t\t</Stack>\n\t);\n\tconst hasBubble = bubbleContent !== null || message.pending;\n\t// Nullish values select AiMessageBubble's default avatar; other empty nodes do not.\n\tconst hasAvatar = hasBubble && (message.avatar == null || hasMessageMedia(message.avatar));\n\tconst continuationColumn = hasAvatar ? messageContentColumn[align] : 'col-start-1';\n\n\treturn (\n\t\t<Stack gap=\"md\" className={cn('ai-chat-message--component grid min-w-0', hasAvatar ? messageColumns[align] : 'grid-cols-1', className)}>\n\t\t\t{hasBubble && (\n\t\t\t\t<AiMessageBubble\n\t\t\t\t\trole={message.role}\n\t\t\t\t\tavatar={message.avatar}\n\t\t\t\t\tauthorName={message.authorName}\n\t\t\t\t\ttimestamp={message.timestamp}\n\t\t\t\t\tplainText={plainText}\n\t\t\t\t\tloading={message.loading}\n\t\t\t\t\tclassName=\"col-span-full grid-cols-subgrid\"\n\t\t\t\t\tonCopy={plainText ? onCopy ?? (() => undefined) : undefined}\n\t\t\t\t\tonRegenerate={onRegenerate}\n\t\t\t\t>\n\t\t\t\t\t{bubbleContent}\n\t\t\t\t</AiMessageBubble>\n\t\t\t)}\n\n\t\t\t{below.length > 0 && (\n\t\t\t\t<Stack\n\t\t\t\t\tgap=\"md\"\n\t\t\t\t\tclassName={cn('ai-chat-message--parts min-w-0', continuationColumn)}\n\t\t\t\t>\n\t\t\t\t\t{below.map((part, idx) => (\n\t\t\t\t\t\t<PartRenderer\n\t\t\t\t\t\t\tkey={idx}\n\t\t\t\t\t\t\tpart={part}\n\t\t\t\t\t\t\tonAttachmentOpen={onAttachmentOpen}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t</Stack>\n\t\t\t)}\n\n\t\t\t{!!message.trailing && (\n\t\t\t\t<div\n\t\t\t\t\tclassName={cn('ai-chat-message--trailing min-w-0', continuationColumn)}\n\t\t\t\t>\n\t\t\t\t\t{message.trailing}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</Stack>\n\t);\n}\n\nAiChatMessage.displayName = 'AiChatMessage';\n\nfunction PartRenderer({\n\tpart,\n\tonAttachmentOpen,\n}: {\n\tpart: AiChatMessagePart;\n\tonAttachmentOpen?: (id: string) => void;\n}) {\n\tswitch (part.type) {\n\t\tcase 'text':\n\t\t\t// In-bubble. Should not reach here.\n\t\t\treturn <Text>{part.content}</Text>;\n\t\tcase 'reasoning':\n\t\t\treturn (\n\t\t\t\t<AiReasoning\n\t\t\t\t\tstreaming={part.streaming}\n\t\t\t\t\tdurationSeconds={part.durationSeconds}\n\t\t\t\t>\n\t\t\t\t\t{part.content}\n\t\t\t\t</AiReasoning>\n\t\t\t);\n\t\tcase 'chain-of-thought':\n\t\t\treturn <AiChainOfThought steps={part.steps} streaming={part.streaming} />;\n\t\tcase 'tool':\n\t\t\treturn (\n\t\t\t\t<AiToolCall\n\t\t\t\t\tname={part.name}\n\t\t\t\t\tstatus={part.status}\n\t\t\t\t\ticon={part.icon}\n\t\t\t\t\targs={part.args}\n\t\t\t\t\tresult={part.result}\n\t\t\t\t\terror={part.error}\n\t\t\t\t\tdurationMs={part.durationMs}\n\t\t\t\t\tdefaultExpanded={part.defaultExpanded}\n\t\t\t\t/>\n\t\t\t);\n\t\tcase 'code':\n\t\t\treturn (\n\t\t\t\t<AiCodeBlock\n\t\t\t\t\tcode={part.code}\n\t\t\t\t\tlanguage={part.language}\n\t\t\t\t\tfilename={part.filename}\n\t\t\t\t\tshowLineNumbers={part.showLineNumbers}\n\t\t\t\t\thighlightLines={part.highlightLines}\n\t\t\t\t/>\n\t\t\t);\n\t\tcase 'attachments':\n\t\t\treturn (\n\t\t\t\t<AiChatAttachmentsStrip\n\t\t\t\t\tattachments={part.items}\n\t\t\t\t\tonOpen={onAttachmentOpen ? (att) => onAttachmentOpen(att.id) : undefined}\n\t\t\t\t/>\n\t\t\t);\n\t\tcase 'sources':\n\t\t\treturn (\n\t\t\t\t<AiSources\n\t\t\t\t\tsources={part.items}\n\t\t\t\t\tvariant={part.variant}\n\t\t\t\t\tdefaultExpanded={part.defaultExpanded}\n\t\t\t\t/>\n\t\t\t);\n\t\tcase 'task':\n\t\t\treturn <AiTask task={part.task} />;\n\t\tcase 'artifact':\n\t\t\treturn (\n\t\t\t\t<AiArtifact\n\t\t\t\t\ttitle={part.title}\n\t\t\t\t\tsubtitle={part.subtitle}\n\t\t\t\t\ticon={part.icon}\n\t\t\t\t\tcopyText={part.copyText}\n\t\t\t\t\tactions={part.actions}\n\t\t\t\t\tonOpen={part.onOpen}\n\t\t\t\t\tonDownload={part.onDownload}\n\t\t\t\t>\n\t\t\t\t\t{part.body}\n\t\t\t\t</AiArtifact>\n\t\t\t);\n\t\tcase 'confirmation':\n\t\t\treturn (\n\t\t\t\t<AiConfirmation\n\t\t\t\t\ttitle={part.title}\n\t\t\t\t\tdescription={part.description}\n\t\t\t\t\ttone={part.tone}\n\t\t\t\t\tstatus={part.status}\n\t\t\t\t\tdetails={part.details}\n\t\t\t\t\tonApprove={part.onApprove}\n\t\t\t\t\tonReject={part.onReject}\n\t\t\t\t/>\n\t\t\t);\n\t\tcase 'custom':\n\t\t\treturn <>{part.render()}</>;\n\t\tdefault:\n\t\t\treturn null;\n\t}\n}\n\nfunction extractPlain(node: ReactNode): string {\n\tif (typeof node === 'string' || typeof node === 'number') return String(node);\n\tif (Array.isArray(node)) return node.map(extractPlain).join('');\n\treturn '';\n}\n","/**\n * AiChatPromptInput — multi-line composer for the chat. Carries:\n * - auto-resizing textarea\n * - staged attachment chips above the field\n * - leading actions slot (model picker, attach)\n * - submit / stop buttons (stop replaces submit while `streaming` is true)\n * - keyboard discipline: Enter to submit, Shift+Enter for newline\n *\n * Stateless: the consumer owns `value`, `attachments`, and `streaming`. The\n * component fires `onSubmit` with `{ text, attachments }` on submit.\n */\nimport { useCallback, useRef, type ReactNode } from 'react';\nimport { ArrowUp, Paperclip, Square } from 'lucide-react';\nimport { Button } from '../../../base/buttons';\nimport { Textarea } from '../../../base/text-inputs';\nimport { Text } from '../../../typography';\nimport { interpolateString, useStrings, type StringsProp } from '../../../../lib/strings';\nimport { cn } from '../../../../lib/utils';\nimport { fieldStateRecipes } from '../../../../lib/field-state-recipes';\n\nimport {\n\tdefaultAiChatPromptInputStrings,\n\ttype AiChatPromptInputStrings,\n} from '../ai-chat.strings';\nimport type {\n\tAiChatAttachment,\n\tAiChatSubmitValues,\n} from '../ai-chat.types';\nimport { AiChatAttachmentsStrip } from './ai-chat-attachments-strip';\n\nexport interface AiChatPromptInputProps {\n\t/** Current text value (controlled). */\n\tvalue: string;\n\t/** Text change callback. */\n\tonValueChange: (value: string) => void;\n\t/** Submit callback — fires on Enter or send-button click. */\n\tonSubmit?: (values: AiChatSubmitValues) => void;\n\t/** Stop callback — wired to the stop button while `streaming`. */\n\tonStop?: () => void;\n\t/** Streaming flag — flips submit ↔ stop and disables the submit button. */\n\tstreaming?: boolean;\n\t/** Disable the entire composer (e.g. while waiting for an upload). */\n\tdisabled?: boolean;\n\t/** Staged attachments (controlled). */\n\tattachments?: ReadonlyArray<AiChatAttachment>;\n\t/** Remove a staged attachment. */\n\tonRemoveAttachment?: (id: string) => void;\n\t/** Triggered when the attach button is pressed. */\n\tonAttach?: () => void;\n\t/** Show the attach button (default: when `onAttach` is provided). */\n\tshowAttach?: boolean;\n\t/** Leading slot rendered before the attach button (typically a model picker). */\n\tleadingActions?: ReactNode;\n\t/** Trailing slot rendered before submit (custom action buttons). */\n\ttrailingActions?: ReactNode;\n\t/** Hide the keyboard hint under the field. */\n\thideHint?: boolean;\n\t/** Override the textarea minimum row count. */\n\tminRows?: number;\n\t/** Override the textarea maximum row count before scroll. */\n\tmaxRows?: number;\n\t/** Auto-focus the textarea on mount. */\n\tautoFocus?: boolean;\n\t/** Display label interpolated into the submit hint. Defaults to the neutral Enter glyph. */\n\tsubmitKeyLabel?: string;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n\t/** Overrides this surface's own copy. */\n\tstrings?: StringsProp<AiChatPromptInputStrings>;\n}\n\nexport function AiChatPromptInput({\n\tvalue,\n\tonValueChange,\n\tonSubmit,\n\tonStop,\n\tstreaming = false,\n\tdisabled = false,\n\tattachments = [],\n\tonRemoveAttachment,\n\tonAttach,\n\tshowAttach,\n\tleadingActions,\n\ttrailingActions,\n\thideHint = false,\n\tminRows = 1,\n\tmaxRows = 8,\n\tautoFocus = false,\n\tsubmitKeyLabel = '↩',\n\tclassName,\n\tstrings: stringsProp,\n}: AiChatPromptInputProps) {\n\tconst strings = useStrings(defaultAiChatPromptInputStrings, stringsProp);\n\tconst textareaRef = useRef<HTMLTextAreaElement | null>(null);\n\n\tconst canSubmit =\n\t\t!streaming && !disabled && (value.trim().length > 0 || attachments.length > 0);\n\n\tconst handleSubmit = useCallback(() => {\n\t\tif (!canSubmit) return;\n\t\tonSubmit?.({ text: value, attachments });\n\t}, [canSubmit, onSubmit, value, attachments]);\n\n\tconst handleKeyDown = useCallback(\n\t\t(e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n\t\t\tif (e.key === 'Enter' && !e.shiftKey && !e.nativeEvent.isComposing) {\n\t\t\t\te.preventDefault();\n\t\t\t\thandleSubmit();\n\t\t\t}\n\t\t},\n\t\t[handleSubmit],\n\t);\n\n\tconst showAttachBtn = showAttach ?? Boolean(onAttach);\n\treturn (\n\t\t<div\n\t\t\tinert={disabled || undefined}\n\t\t\tclassName={cn(\n\t\t\t\t'ai-chat-prompt-input--component',\n\t\t\t\t'rounded-radius border border-input bg-card text-card-foreground transition-[color,box-shadow] duration-150',\n\t\t\t\t// The frame is the field: it takes the shared compound-field focus and\n\t\t\t\t// invalid states from its control, which draws no frame of its own.\n\t\t\t\tfieldStateRecipes.groupFocus,\n\t\t\t\tfieldStateRecipes.groupInvalid,\n\t\t\t\tdisabled && 'opacity-50 pointer-events-none',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t{attachments.length > 0 && (\n\t\t\t\t<div className=\"border-b border-border/60 p-surface-xs\">\n\t\t\t\t\t<AiChatAttachmentsStrip\n\t\t\t\t\t\tattachments={attachments}\n\t\t\t\t\t\tonRemove={onRemoveAttachment}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t<Textarea\n\t\t\t\tref={textareaRef}\n\t\t\t\tvalue={value}\n\t\t\t\tonChange={(e) => onValueChange(e.target.value)}\n\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\tplaceholder={strings.placeholder}\n\t\t\t\tautoResize\n\t\t\t\tminRows={minRows}\n\t\t\t\tmaxRows={maxRows}\n\t\t\t\tautoFocus={autoFocus}\n\t\t\t\tdisabled={disabled}\n\t\t\t\t// The composer frame's control, as InputGroupTextarea marks it. The\n\t\t\t\t// textarea keeps auto-resize, which InputGroupTextarea does not offer.\n\t\t\t\tdata-slot=\"input-group-control\"\n\t\t\t\tclassName=\"rounded-none border-0 bg-transparent text-inherit shadow-none ring-0 focus-visible:ring-0 aria-invalid:ring-0 resize-none disabled:opacity-100\"\n\t\t\t/>\n\n\t\t\t<div className=\"flex items-center gap-space-xs border-t border-border/60 px-surface-xs py-space-sm\">\n\t\t\t\t{leadingActions}\n\t\t\t\t{showAttachBtn && (\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\t\tsize=\"sm\" iconOnly\n\t\t\t\t\t\taria-label={strings.attachAria}\n\t\t\t\t\t\tclassName=\"disabled:opacity-100\"\n\t\t\t\t\t\tonClick={onAttach}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Paperclip className=\"size-icon\" />\n\t\t\t\t\t</Button>\n\t\t\t\t)}\n\t\t\t\t<div className=\"ml-auto flex items-center gap-space-xs\">\n\t\t\t\t\t{trailingActions}\n\t\t\t\t\t{streaming ? (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\t\tbuttonStyle=\"solid\"\n\t\t\t\t\t\t\tsize=\"sm\" iconOnly\n\t\t\t\t\t\t\taria-label={strings.stopAria}\n\t\t\t\t\t\t\tclassName=\"disabled:opacity-100\"\n\t\t\t\t\t\t\tonClick={onStop}\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Square className=\"size-icon-md fill-current\" />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\ttone=\"primary\"\n\t\t\t\t\t\t\tbuttonStyle=\"solid\"\n\t\t\t\t\t\t\tsize=\"sm\" iconOnly\n\t\t\t\t\t\t\taria-label={strings.submitAria}\n\t\t\t\t\t\t\tclassName={disabled ? 'disabled:opacity-100' : undefined}\n\t\t\t\t\t\t\tonClick={handleSubmit}\n\t\t\t\t\t\t\tdisabled={!canSubmit}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<ArrowUp className=\"size-icon\" />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{!hideHint && (\n\t\t\t\t<div className=\"px-surface-xs pb-surface-xs\">\n\t\t\t\t\t<Text size=\"xs\" type=\"discrete\">\n\t\t\t\t\t\t{interpolateString(strings.hint, {\n\t\t\t\t\t\t\tsubmitKey: submitKeyLabel,\n\t\t\t\t\t\t\tnewlineKey: '⇧↩',\n\t\t\t\t\t\t})}\n\t\t\t\t\t</Text>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nAiChatPromptInput.displayName = 'AiChatPromptInput';\n","/**\n * AiChatQueue — pending message queue rendered above the prompt input. Used\n * to surface messages the user submitted faster than the assistant could\n * process — each item shows a status pill and an optional cancel control.\n */\nimport { Loader2, X } from 'lucide-react';\nimport { Badge } from '../../../base/badge';\nimport { Button } from '../../../base/buttons';\nimport { Stack } from '../../../base/structure';\nimport { DisplayLabel, Text } from '../../../typography';\nimport { useStrings, type StringsProp } from '../../../../lib/strings';\nimport { cn } from '../../../../lib/utils';\n\nimport {\n\tdefaultAiChatQueueStrings,\n\ttype AiChatQueueStrings,\n} from '../ai-chat.strings';\nimport type { AiChatQueueItem } from '../ai-chat.types';\nimport { dotRecipes } from '../../../../lib/tone-recipes';\n\nexport interface AiChatQueueProps {\n\t/** Entries to render. */\n\titems: ReadonlyArray<AiChatQueueItem>;\n\t/** Hides the header region. */\n\thideHeader?: boolean;\n\t/** Fired when entry editing is cancelled. */\n\tonCancel?: (id: string) => void;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n\t/** Overrides this surface's own copy. */\n\tstrings?: StringsProp<AiChatQueueStrings>;\n}\n\nexport function AiChatQueue({\n\titems,\n\thideHeader = false,\n\tonCancel,\n\tclassName,\n\tstrings: stringsProp,\n}: AiChatQueueProps) {\n\tconst strings = useStrings(defaultAiChatQueueStrings, stringsProp);\n\tif (items.length === 0) return null;\n\treturn (\n\t\t<Stack gap=\"sm\"\n\t\t\tclassName={cn(\n\t\t\t\t'ai-chat-queue--component',\n\t\t\t\t'rounded-radius border border-border/60 bg-muted/30 p-surface-xs',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t{!hideHeader && (\n\t\t\t\t<DisplayLabel className=\"px-1\">\n\t\t\t\t\t{strings.header} · {items.length}\n\t\t\t\t</DisplayLabel>\n\t\t\t)}\n\t\t\t<Stack render={<ul />} gap=\"xs\" className=\"ai-chat-queue--list m-0 list-none p-0 font-sans\">\n\t\t\t\t{items.map((item) => {\n\t\t\t\t\tconst status = item.status ?? 'queued';\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<li\n\t\t\t\t\t\t\tkey={item.id}\n\t\t\t\t\t\t\tclassName=\"flex items-center gap-space-md rounded-inner bg-card text-card-foreground px-space-md py-space-sm\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{status === 'running' ? (\n\t\t\t\t\t\t\t\t<Loader2 className=\"size-icon-md shrink-0 animate-spin text-primary-accent\" />\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t// The dot sits in the spinner's footprint so labels align across rows.\n\t\t\t\t\t\t\t\t<span aria-hidden className=\"flex size-icon-md shrink-0 items-center justify-center\">\n\t\t\t\t\t\t\t\t\t<span className={cn(dotRecipes.marker, 'bg-muted-foreground')} />\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<Text type=\"inherit\" className=\"flex-1 truncate\">\n\t\t\t\t\t\t\t\t{item.label}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t<Badge tone={status === 'running' ? 'info' : 'secondary'}>\n\t\t\t\t\t\t\t\t{status === 'running' ? strings.runningLabel : strings.queuedLabel}\n\t\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t\t{(!!item.onCancel || !!onCancel) && (\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\t\t\t\t\tsize=\"sm\" iconOnly\n\t\t\t\t\t\t\t\t\taria-label={strings.cancelAria}\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\titem.onCancel?.();\n\t\t\t\t\t\t\t\t\t\tonCancel?.(item.id);\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<X className=\"size-icon-md\" />\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</li>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</Stack>\n\t\t</Stack>\n\t);\n}\n\nAiChatQueue.displayName = 'AiChatQueue';\n","/**\n * AiChatSuggestionsRow — horizontal scrollable strip of small suggestion\n * chips rendered above the prompt input. Distinct from\n * `<AiPromptSuggestions>` (which is a card-grid of richer suggestions used\n * as a welcome surface): this is the inline, dense variant.\n */\nimport { Button } from '../../../base/buttons';\nimport { DisplayLabel, Text } from '../../../typography';\nimport { useStrings, type StringsProp } from '../../../../lib/strings';\nimport { cn } from '../../../../lib/utils';\n\nimport {\n\tdefaultAiChatSuggestionsStrings,\n\ttype AiChatSuggestionsStrings,\n} from '../ai-chat.strings';\nimport type { AiChatSuggestion } from '../ai-chat.types';\n\nexport interface AiChatSuggestionsRowProps<TData = unknown> {\n\t/** Matches for the current query. */\n\tsuggestions: ReadonlyArray<AiChatSuggestion<TData>>;\n\tonPick?: (s: AiChatSuggestion<TData>) => void;\n\t/** Hides the header region. */\n\thideHeader?: boolean;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n\t/** Overrides this surface's own copy. */\n\tstrings?: StringsProp<AiChatSuggestionsStrings>;\n}\n\nexport function AiChatSuggestionsRow<TData = unknown>({\n\tsuggestions,\n\tonPick,\n\thideHeader = false,\n\tclassName,\n\tstrings: stringsProp,\n}: AiChatSuggestionsRowProps<TData>) {\n\tconst strings = useStrings(defaultAiChatSuggestionsStrings, stringsProp);\n\tif (suggestions.length === 0) return null;\n\treturn (\n\t\t<div className={cn('ai-chat-suggestions-row--component flex items-center gap-space-md', className)}>\n\t\t\t{!hideHeader && (\n\t\t\t\t<DisplayLabel className=\"shrink-0\">\n\t\t\t\t\t{strings.header}\n\t\t\t\t</DisplayLabel>\n\t\t\t)}\n\t\t\t<div className=\"flex min-w-0 flex-1 items-center gap-space-sm overflow-x-auto p-space-xs [scrollbar-width:none] [&::-webkit-scrollbar]:hidden\">\n\t\t\t\t{suggestions.map((s) => {\n\t\t\t\t\tconst Icon = s.icon;\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tkey={s.id}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\t\tbuttonStyle=\"outline\"\n\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\tonClick={() => onPick?.(s)}\n\t\t\t\t\t\t\tclassName=\"shrink-0 gap-space-sm\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{!!Icon && <Icon className=\"size-icon-sm text-muted-foreground\" />}\n\t\t\t\t\t\t\t<Text tag=\"span\" weight=\"medium\">\n\t\t\t\t\t\t\t\t{s.label}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nAiChatSuggestionsRow.displayName = 'AiChatSuggestionsRow';\n","/**\n * AiChat — framework-agnostic AI chat surface. Tie-together component for\n * the `features/ai-chat/*` partials. Renders an optional agent header, the\n * scrollable conversation, an optional queue + suggestions row, and the\n * prompt input.\n *\n * Composition seams:\n * - `slots` — replace any region (header, intro, empty, queue,\n * suggestions, input, belowMessages) or per-message\n * (`renderMessage`).\n * - `strings` — deep-partial override of every default copy line\n * (prompt, conversation, queue, suggestions, message).\n * - Partials — every partial is exported individually so a consumer\n * can build a custom layout against the same data shape.\n *\n * Headless usage:\n * - The `useAiChatScroll` hook is exported for consumers building a\n * custom conversation layout while keeping auto-stick-to-bottom.\n *\n * Framework-agnostic:\n * - No router, no i18n SDK, no fetcher. Submission is a callback\n * (`onSubmit`); messages, queue, attachments are all controlled props.\n */\nimport { useCallback, useState, type ReactNode } from 'react';\nimport { AiAgent } from '../../blocks/ai/ai-agent';\nimport { Stack } from '../../base/structure';\nimport { Text } from '../../typography';\nimport { useStrings, type StringsProp } from '../../../lib/strings';\nimport { cn } from '../../../lib/utils';\n\nimport {\n\tdefaultAiChatStrings,\n\ttype AiChatStrings,\n} from './ai-chat.strings';\nimport type {\n\tAiChatAgent,\n\tAiChatAttachment,\n\tAiChatMessage as AiChatMessageType,\n\tAiChatQueueItem,\n\tAiChatSlots,\n\tAiChatSubmitValues,\n\tAiChatSuggestion,\n} from './ai-chat.types';\nimport {\n\tAiChatConversation,\n\tAiChatEmptyState,\n\tAiChatMessage,\n\tAiChatPromptInput,\n\tAiChatQueue,\n\tAiChatSuggestionsRow,\n} from './partials';\n\nexport interface AiChatProps<TSuggestionData = unknown> {\n\t/** Conversation messages — order is significant. */\n\tmessages: ReadonlyArray<AiChatMessageType>;\n\n\t/** Controlled prompt input value. */\n\tinputValue: string;\n\t/** Prompt input change callback. */\n\tonInputChange: (value: string) => void;\n\t/** Fired on submit (Enter or send button). */\n\tonSubmit?: (values: AiChatSubmitValues) => void;\n\t/** Fired when the user clicks the stop button while `streaming`. */\n\tonStop?: () => void;\n\t/** Streaming flag — controls submit/stop UI in the prompt input. */\n\tstreaming?: boolean;\n\t/** Disable composer entirely. */\n\tdisabled?: boolean;\n\n\t/** Currently staged attachments. */\n\tattachments?: ReadonlyArray<AiChatAttachment>;\n\t/** Remove a staged attachment. */\n\tonRemoveAttachment?: (id: string) => void;\n\t/** Fires when the user clicks the attach button. */\n\tonAttach?: () => void;\n\t/** Toggles the attach button visibility. Defaults to `true` when `onAttach` is provided. */\n\tshowAttach?: boolean;\n\n\t/** Agent identity — drives the optional header strip. Pass `null` to hide. */\n\tagent?: AiChatAgent | null;\n\t/** Trailing slot inside the header (e.g. settings button). */\n\theaderActions?: ReactNode;\n\n\t/** Pending message queue (rendered above the input). */\n\tqueue?: ReadonlyArray<AiChatQueueItem>;\n\t/** Cancel callback — fires per-item when the queue chip's × is clicked. */\n\tonCancelQueueItem?: (id: string) => void;\n\n\t/** Inline quick suggestions (rendered above the input). */\n\tsuggestions?: ReadonlyArray<AiChatSuggestion<TSuggestionData>>;\n\t/** Suggestion select callback. */\n\tonPickSuggestion?: (s: AiChatSuggestion<TSuggestionData>) => void;\n\n\t/** Per-message copy callback. */\n\tonMessageCopy?: (message: AiChatMessageType) => void;\n\t/** Per-message regenerate callback (assistant only). */\n\tonMessageRegenerate?: (message: AiChatMessageType) => void;\n\t/** Per-message attachment open callback. */\n\tonAttachmentOpen?: (messageId: string, attachmentId: string) => void;\n\n\t/** Disable auto-stick-to-bottom in the conversation. */\n\tdisableAutoScroll?: boolean;\n\n\t/** Slot map for replacing default surfaces. */\n\tslots?: AiChatSlots;\n\t/** String overrides. */\n\tstrings?: StringsProp<AiChatStrings>;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n}\n\nexport function AiChat<TSuggestionData = unknown>({\n\tmessages,\n\tinputValue,\n\tonInputChange,\n\tonSubmit,\n\tonStop,\n\tstreaming = false,\n\tdisabled = false,\n\tattachments = [],\n\tonRemoveAttachment,\n\tonAttach,\n\tshowAttach,\n\tagent,\n\theaderActions,\n\tqueue = [],\n\tonCancelQueueItem,\n\tsuggestions = [],\n\tonPickSuggestion,\n\tonMessageCopy,\n\tonMessageRegenerate,\n\tonAttachmentOpen,\n\tdisableAutoScroll,\n\tslots,\n\tstrings: stringsProp,\n\tclassName,\n}: AiChatProps<TSuggestionData>) {\n\tconst strings = useStrings(defaultAiChatStrings, stringsProp);\n\tconst [, force] = useState(0);\n\n\tconst renderMessage = useCallback(\n\t\t(\n\t\t\tmessage: AiChatMessageType,\n\t\t\tctx: { isLast: boolean; index: number },\n\t\t): ReactNode => {\n\t\t\tif (slots?.renderMessage) {\n\t\t\t\treturn slots.renderMessage(message, ctx);\n\t\t\t}\n\t\t\treturn (\n\t\t\t\t<AiChatMessage className=\"ai-chat-message--component\"\n\t\t\t\t\tmessage={message}\n\t\t\t\t\tstrings={strings.message}\n\t\t\t\t\tonCopy={\n\t\t\t\t\t\tonMessageCopy ? () => onMessageCopy(message) : undefined\n\t\t\t\t\t}\n\t\t\t\t\tonRegenerate={\n\t\t\t\t\t\tonMessageRegenerate\n\t\t\t\t\t\t\t? () => onMessageRegenerate(message)\n\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t}\n\t\t\t\t\tonAttachmentOpen={\n\t\t\t\t\t\tonAttachmentOpen\n\t\t\t\t\t\t\t? (attachmentId) => onAttachmentOpen(message.id, attachmentId)\n\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t);\n\t\t},\n\t\t[\n\t\t\tonAttachmentOpen,\n\t\t\tonMessageCopy,\n\t\t\tonMessageRegenerate,\n\t\t\tslots,\n\t\t\tstrings.message,\n\t\t],\n\t);\n\n\tconst Header: ReactNode =\n\t\tslots?.header ??\n\t\t(agent ? (\n\t\t\t<div className=\"border-b border-border bg-card text-card-foreground p-surface\">\n\t\t\t<Stack direction=\"horizontal\" align=\"center\" gap=\"lg\">\n\t\t\t\t<AiAgent\n\t\t\t\t\tname={agent.name}\n\t\t\t\t\ticon={agent.icon}\n\t\t\t\t\tavatar={agent.avatar}\n\t\t\t\t\tsubtitle={agent.subtitle}\n\t\t\t\t\ttone={agent.tone}\n\t\t\t\t\tstatus={agent.status}\n\t\t\t\t\tvariant=\"inline\"\n\t\t\t\t/>\n\t\t\t\t{!!headerActions && (\n\t\t\t\t\t<div className=\"ml-auto flex items-center gap-space-xs\">{headerActions}</div>\n\t\t\t\t)}\n\t\t\t</Stack>\n\t\t\t</div>\n\t\t) : null);\n\n\tconst Empty: ReactNode =\n\t\tslots?.empty ??\n\t\t(messages.length === 0 ? (\n\t\t\t<AiChatEmptyState\n\t\t\t\ttitle={strings.emptyTitle}\n\t\t\t\tdescription={strings.emptyDescription}\n\t\t\t/>\n\t\t) : null);\n\n\tconst Queue: ReactNode =\n\t\tslots?.queue ??\n\t\t(queue.length > 0 ? (\n\t\t\t<AiChatQueue\n\t\t\t\titems={queue}\n\t\t\t\tonCancel={onCancelQueueItem}\n\t\t\t\tstrings={strings.queue}\n\t\t\t/>\n\t\t) : null);\n\n\tconst Suggestions: ReactNode =\n\t\tslots?.suggestions ??\n\t\t(suggestions.length > 0 ? (\n\t\t\t<AiChatSuggestionsRow<TSuggestionData>\n\t\t\t\tsuggestions={suggestions}\n\t\t\t\tonPick={onPickSuggestion}\n\t\t\t\tstrings={strings.suggestions}\n\t\t\t/>\n\t\t) : null);\n\n\tconst Input: ReactNode =\n\t\tslots?.input ?? (\n\t\t\t<AiChatPromptInput\n\t\t\t\tvalue={inputValue}\n\t\t\t\tonValueChange={onInputChange}\n\t\t\t\tonSubmit={(values) => {\n\t\t\t\t\tonSubmit?.(values);\n\t\t\t\t\t// Force re-render so consumers that read inputValue/attachments\n\t\t\t\t\t// from controlled state see the freshly cleared values they\n\t\t\t\t\t// pushed in their onSubmit handler.\n\t\t\t\t\tforce((v) => v + 1);\n\t\t\t\t}}\n\t\t\t\tonStop={onStop}\n\t\t\t\tstreaming={streaming}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tattachments={attachments}\n\t\t\t\tonRemoveAttachment={onRemoveAttachment}\n\t\t\t\tonAttach={onAttach}\n\t\t\t\tshowAttach={showAttach}\n\t\t\t\tstrings={strings.prompt}\n\t\t\t/>\n\t\t);\n\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t'ai-chat--component box-border flex h-full flex-col overflow-hidden rounded-radius border border-border bg-background text-foreground',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t{Header}\n\n\t\t\t<AiChatConversation\n\t\t\t\tmessages={messages}\n\t\t\t\trenderMessage={renderMessage}\n\t\t\t\tintro={slots?.intro}\n\t\t\t\tfooter={slots?.belowMessages}\n\t\t\t\tempty={Empty}\n\t\t\t\tdisableAutoScroll={disableAutoScroll}\n\t\t\t\tstrings={strings.conversation}\n\t\t\t/>\n\n\t\t\t{(Queue || Suggestions || Input) && (\n\t\t\t\t\t<div className=\"border-t border-border bg-card text-card-foreground p-surface\">\n\t\t\t\t\t<Stack gap=\"md\">\n\t\t\t\t\t{Queue}\n\t\t\t\t\t{Suggestions}\n\t\t\t\t\t{Input}\n\t\t\t\t\t</Stack>\n\t\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{disabled && (\n\t\t\t\t<Text className=\"sr-only\" aria-live=\"polite\">\n\t\t\t\t\t{strings.disabledAnnouncement}\n\t\t\t\t</Text>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nAiChat.displayName = 'AiChat';\n"],"mappings":"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"}