themelia-react-ui 1.0.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (542) hide show
  1. package/CHANGELOG.md +281 -1
  2. package/README.md +10 -5
  3. package/dist/{accordion-BRTcsp8J.js → accordion-CQXVcd7Q.js} +13 -13
  4. package/dist/accordion-CQXVcd7Q.js.map +1 -0
  5. package/dist/action-menu-BTpyPWJ2.js +264 -0
  6. package/dist/action-menu-BTpyPWJ2.js.map +1 -0
  7. package/dist/{affordance-geometry.generated-CL84ZN9A.js → affordance-geometry.generated-CCIXb2A1.js} +7 -2
  8. package/dist/affordance-geometry.generated-CCIXb2A1.js.map +1 -0
  9. package/dist/{ai-artifact-DLVdK0Py.js → ai-artifact-2PQ2fItc.js} +171 -176
  10. package/dist/ai-artifact-2PQ2fItc.js.map +1 -0
  11. package/dist/{app-shell-C_fKpljx.js → app-shell-BE_j8-AT.js} +4 -4
  12. package/dist/{app-shell-C_fKpljx.js.map → app-shell-BE_j8-AT.js.map} +1 -1
  13. package/dist/{attachment-DbjUWsP0.js → attachment-q69dlt5Y.js} +9 -9
  14. package/dist/{attachment-DbjUWsP0.js.map → attachment-q69dlt5Y.js.map} +1 -1
  15. package/dist/{auth-CAQcasMV.js → auth-M3vGMgDR.js} +42 -42
  16. package/dist/{auth-CAQcasMV.js.map → auth-M3vGMgDR.js.map} +1 -1
  17. package/dist/{avatar-Bu2HhitA.js → avatar-djdaaQ_s.js} +14 -12
  18. package/dist/avatar-djdaaQ_s.js.map +1 -0
  19. package/dist/{badge-CzId1Wlm.js → badge-0tATj-tW.js} +9 -9
  20. package/dist/badge-0tATj-tW.js.map +1 -0
  21. package/dist/base/accordion.js +1 -1
  22. package/dist/base/action-menu.js +1 -1
  23. package/dist/base/attachment.js +1 -1
  24. package/dist/base/avatar.js +1 -1
  25. package/dist/base/badge.js +1 -1
  26. package/dist/base/buttons.js +2 -2
  27. package/dist/base/cards.js +2 -2
  28. package/dist/base/carousel.js +11 -11
  29. package/dist/base/carousel.js.map +1 -1
  30. package/dist/base/cascader.js +244 -222
  31. package/dist/base/cascader.js.map +1 -1
  32. package/dist/base/chart.js +1 -1
  33. package/dist/base/choice-inputs.js +2 -2
  34. package/dist/base/code-block.js +1 -1
  35. package/dist/base/combobox.js +1 -1
  36. package/dist/base/command.js +1 -1
  37. package/dist/base/copyable.js +1 -1
  38. package/dist/base/date-pickers.js +2 -2
  39. package/dist/base/display.js +6 -6
  40. package/dist/base/feedback.js +3 -3
  41. package/dist/base/forms-numeric.js +1 -1
  42. package/dist/base/forms.js +2 -2
  43. package/dist/base/inline-edit.js +81 -76
  44. package/dist/base/inline-edit.js.map +1 -1
  45. package/dist/base/item.js +1 -1
  46. package/dist/base/media-gallery.js +1 -1
  47. package/dist/base/navigation.js +6 -6
  48. package/dist/base/popover-menu.js +1 -1
  49. package/dist/base/popover.js +1 -1
  50. package/dist/base/qr-code.js +7 -4
  51. package/dist/base/qr-code.js.map +1 -1
  52. package/dist/base/repeaters.js +42 -42
  53. package/dist/base/repeaters.js.map +1 -1
  54. package/dist/base/sheet.js +1 -1
  55. package/dist/base/sidebar.js +1 -1
  56. package/dist/base/signature-pad.js +9 -9
  57. package/dist/base/signature-pad.js.map +1 -1
  58. package/dist/base/skeleton.js +1 -1
  59. package/dist/base/spinner.js +1 -1
  60. package/dist/base/structure.js +1 -1
  61. package/dist/base/table.js +1 -1
  62. package/dist/base/text-inputs.js +2 -2
  63. package/dist/base/toaster.js +4 -4
  64. package/dist/base/toaster.js.map +1 -1
  65. package/dist/base/tree.js +1 -1
  66. package/dist/base/upload-queue.js +1 -1
  67. package/dist/base/upload.js +3 -3
  68. package/dist/base/value-inputs.js +1 -1
  69. package/dist/blocks/admin.js +229 -220
  70. package/dist/blocks/admin.js.map +1 -1
  71. package/dist/blocks/ai.js +147 -180
  72. package/dist/blocks/ai.js.map +1 -1
  73. package/dist/blocks/analytics/usage-card.js +1 -1
  74. package/dist/blocks/analytics.js +530 -523
  75. package/dist/blocks/analytics.js.map +1 -1
  76. package/dist/blocks/collaboration.js +1 -1
  77. package/dist/blocks/commerce/receipt.js +1 -1
  78. package/dist/blocks/commerce.js +1390 -1516
  79. package/dist/blocks/commerce.js.map +1 -1
  80. package/dist/blocks/data-display.js +1 -1
  81. package/dist/blocks/onboarding.js +5 -5
  82. package/dist/blocks/planning.js +82 -91
  83. package/dist/blocks/planning.js.map +1 -1
  84. package/dist/blocks/timelines.js +1 -1
  85. package/dist/{breadcrumbs-BuYz5SDU.js → breadcrumbs-BG_FfMK4.js} +5 -5
  86. package/dist/{breadcrumbs-BuYz5SDU.js.map → breadcrumbs-BG_FfMK4.js.map} +1 -1
  87. package/dist/{button-BZDasD04.js → button-BS3KDg00.js} +185 -162
  88. package/dist/button-BS3KDg00.js.map +1 -0
  89. package/dist/{button-BZyfTvwm.js → button-R9CCoH7A.js} +2 -2
  90. package/dist/{button-BZyfTvwm.js.map → button-R9CCoH7A.js.map} +1 -1
  91. package/dist/{buttons-D_6KJvEE.js → buttons-DS0ZIwJ_.js} +11 -11
  92. package/dist/buttons-DS0ZIwJ_.js.map +1 -0
  93. package/dist/{cards-qGSErLw_.js → cards-QoJ4syG9.js} +7 -7
  94. package/dist/{cards-qGSErLw_.js.map → cards-QoJ4syG9.js.map} +1 -1
  95. package/dist/{chart-Bsc5BICK.js → chart-DwYRKKc-.js} +17 -15
  96. package/dist/chart-DwYRKKc-.js.map +1 -0
  97. package/dist/checkbox-B7ygNTYp.js +35 -0
  98. package/dist/checkbox-B7ygNTYp.js.map +1 -0
  99. package/dist/choice-inputs-DrJ17tpL.js +752 -0
  100. package/dist/choice-inputs-DrJ17tpL.js.map +1 -0
  101. package/dist/{code-block-DzHKRybS.js → code-block-CD0B7M93.js} +19 -19
  102. package/dist/{code-block-DzHKRybS.js.map → code-block-CD0B7M93.js.map} +1 -1
  103. package/dist/{collapsible-ClvC7Bj3.js → collapsible-oMUGM4tr.js} +3 -3
  104. package/dist/{collapsible-ClvC7Bj3.js.map → collapsible-oMUGM4tr.js.map} +1 -1
  105. package/dist/{collection-content-D6S8cv_n.js → collection-content-Ys-OZOkY.js} +3 -3
  106. package/dist/{collection-content-D6S8cv_n.js.map → collection-content-Ys-OZOkY.js.map} +1 -1
  107. package/dist/{combobox-BFnbJJp3.js → combobox-6dvVny2q.js} +96 -97
  108. package/dist/combobox-6dvVny2q.js.map +1 -0
  109. package/dist/{combobox-hozNwUcc.js → combobox-CB7039j7.js} +326 -308
  110. package/dist/combobox-CB7039j7.js.map +1 -0
  111. package/dist/{command-BnmSchli.js → command-kPMPjIxJ.js} +34 -30
  112. package/dist/command-kPMPjIxJ.js.map +1 -0
  113. package/dist/{comments-u5L0OGip.js → comments-You0Bzbr.js} +349 -348
  114. package/dist/comments-You0Bzbr.js.map +1 -0
  115. package/dist/components/base/accordion/accordion-variants.d.ts +3 -3
  116. package/dist/components/base/action-menu/action-menu.d.ts +7 -2
  117. package/dist/components/base/avatar/stacked-avatars.d.ts +5 -4
  118. package/dist/components/base/badge/badge.d.ts +1 -1
  119. package/dist/components/base/badge/badge.recipes.d.ts +4 -4
  120. package/dist/components/base/buttons/base-button.d.ts +7 -0
  121. package/dist/components/base/buttons/button-group.recipes.d.ts +2 -2
  122. package/dist/components/base/buttons/button.variants.d.ts +1 -0
  123. package/dist/components/base/buttons/loader-button.d.ts +3 -1
  124. package/dist/components/base/buttons/text-button.d.ts +2 -2
  125. package/dist/components/base/carousel/carousel.d.ts +3 -1
  126. package/dist/components/base/chart/chart.d.ts +7 -7
  127. package/dist/components/base/choice-inputs/checkbox.d.ts +6 -7
  128. package/dist/components/base/choice-inputs/choice-types.d.ts +10 -1
  129. package/dist/components/base/choice-inputs/pill-radio-group.d.ts +9 -0
  130. package/dist/components/base/choice-inputs/select-popup.d.ts +9 -1
  131. package/dist/components/base/choice-inputs/switch-card.d.ts +1 -1
  132. package/dist/components/base/date-pickers/date-picker-field.d.ts +23 -0
  133. package/dist/components/base/date-pickers/datepicker.types.d.ts +13 -3
  134. package/dist/components/base/display/alert-dialog.d.ts +8 -2
  135. package/dist/components/base/display/content-block.d.ts +4 -2
  136. package/dist/components/base/display/date-block.d.ts +1 -1
  137. package/dist/components/base/display/dialog.d.ts +12 -5
  138. package/dist/components/base/display/surface-title.d.ts +6 -1
  139. package/dist/components/base/feedback/alert.d.ts +1 -1
  140. package/dist/components/base/feedback/state-display.d.ts +5 -4
  141. package/dist/components/base/forms/form-sizing.d.ts +32 -0
  142. package/dist/components/base/forms/workflow.d.ts +2 -0
  143. package/dist/components/base/forms-numeric/coordinates-input.d.ts +3 -0
  144. package/dist/components/base/forms-numeric/rounding-mode-select.d.ts +4 -1
  145. package/dist/components/base/navigation/dropdown-menu.d.ts +2 -2
  146. package/dist/components/base/navigation/language-switcher.d.ts +4 -1
  147. package/dist/components/base/navigation/overflow-tab-bar.d.ts +7 -0
  148. package/dist/components/base/navigation/page-header/page-header.d.ts +4 -1
  149. package/dist/components/base/qr-code/qr-code.d.ts +2 -0
  150. package/dist/components/base/sheet/index.d.ts +29 -1
  151. package/dist/components/base/sheet/sheet.d.ts +14 -5
  152. package/dist/components/base/spinner/spinner.d.ts +3 -2
  153. package/dist/components/base/structure/structure.types.d.ts +1 -1
  154. package/dist/components/base/text-inputs/input-group.d.ts +2 -2
  155. package/dist/components/base/upload/upload.recipes.d.ts +11 -0
  156. package/dist/components/base/value-inputs/date-time-input.d.ts +4 -2
  157. package/dist/components/base/value-inputs/tags-input.d.ts +2 -0
  158. package/dist/components/blocks/admin/api-key-list/api-key-list.types.d.ts +1 -1
  159. package/dist/components/blocks/analytics/format-metric-value.d.ts +11 -1
  160. package/dist/components/blocks/analytics/index.d.ts +1 -1
  161. package/dist/components/blocks/analytics/use-metric-format-options.d.ts +3 -0
  162. package/dist/components/blocks/commerce/address-card/address-card.d.ts +1 -1
  163. package/dist/components/blocks/commerce/address-card/types.d.ts +3 -1
  164. package/dist/components/blocks/commerce/booking-calendar-event-card/booking-calendar-event-card.d.ts +4 -0
  165. package/dist/components/blocks/commerce/booking-calendar-event-card/booking-calendar-event-card.types.d.ts +2 -2
  166. package/dist/components/blocks/commerce/discount-stack/types.d.ts +1 -1
  167. package/dist/components/blocks/commerce/inventory-section/types.d.ts +4 -1
  168. package/dist/components/blocks/commerce/loyalty-points/types.d.ts +1 -1
  169. package/dist/components/blocks/commerce/order-status/types.d.ts +4 -0
  170. package/dist/components/blocks/commerce/payment-method/payment-method.d.ts +1 -1
  171. package/dist/components/blocks/commerce/payment-method/types.d.ts +3 -1
  172. package/dist/components/blocks/commerce/seo-listing/seo-listing-card.d.ts +1 -1
  173. package/dist/components/blocks/commerce/seo-listing/types.d.ts +3 -1
  174. package/dist/components/blocks/commerce/vendor-profile/types.d.ts +4 -1
  175. package/dist/components/blocks/data-display/dense-info-card/dense-info.strings.d.ts +4 -1
  176. package/dist/components/blocks/data-display/inline-stat/inline-stat.d.ts +4 -1
  177. package/dist/components/features/global-search/partials/global-search-idle-state.d.ts +1 -1
  178. package/dist/components/features/overlays/alert-dialog.d.ts +1 -1
  179. package/dist/components/features/overlays/drawer.d.ts +1 -1
  180. package/dist/components/features/overlays/hooks/use-overlay-actions.d.ts +2 -2
  181. package/dist/components/features/overlays/hooks/use-overlay-visibility.d.ts +11 -4
  182. package/dist/components/features/overlays/overlay-tone-icon.d.ts +37 -0
  183. package/dist/components/features/overlays/overlays.types.d.ts +42 -19
  184. package/dist/components/features/products/components/product-variants-manager.d.ts +1 -1
  185. package/dist/components/features/products/partials/index.d.ts +1 -1
  186. package/dist/components/features/products/partials/product-metric-tile.d.ts +6 -0
  187. package/dist/components/features/products/partials/product-tone.d.ts +11 -1
  188. package/dist/components/features/products/products.types.d.ts +2 -1
  189. package/dist/components/features/table/partials/cell-renderers.d.ts +1 -1
  190. package/dist/components/layout/page/index.d.ts +1 -1
  191. package/dist/components/layout/page/page.types.d.ts +53 -3
  192. package/dist/components/layout/page/partials/page-header-commands.d.ts +13 -0
  193. package/dist/components/layout/page/partials/page-header.d.ts +1 -1
  194. package/dist/components/primitives/date.d.ts +16 -3
  195. package/dist/components/primitives/dimensions.d.ts +6 -0
  196. package/dist/components/primitives/duration.d.ts +6 -0
  197. package/dist/components/primitives/file-size.d.ts +6 -0
  198. package/dist/components/primitives/index.d.ts +1 -1
  199. package/dist/components/primitives/initials.d.ts +11 -2
  200. package/dist/components/primitives/link.d.ts +7 -0
  201. package/dist/components/primitives/money.d.ts +29 -7
  202. package/dist/components/primitives/number.d.ts +17 -0
  203. package/dist/components/primitives/value-typography.d.ts +54 -0
  204. package/dist/components/primitives/value.d.ts +31 -6
  205. package/dist/components/typography/heading.d.ts +9 -1
  206. package/dist/components/typography/label.d.ts +3 -0
  207. package/dist/components/typography/running-text.d.ts +12 -0
  208. package/dist/components/typography/text-link.d.ts +23 -1
  209. package/dist/components/typography/text.d.ts +12 -0
  210. package/dist/components/typography/text.styles.d.ts +35 -13
  211. package/dist/components/ui/button.d.ts +1 -1
  212. package/dist/components/ui/checkbox.d.ts +5 -0
  213. package/dist/components/ui/overlay.recipes.d.ts +15 -2
  214. package/dist/components/ui/select.d.ts +3 -1
  215. package/dist/components/ui/switch.d.ts +5 -0
  216. package/dist/{containers-DqB-bSYE.js → containers-D_L4mTVb.js} +3 -3
  217. package/dist/{containers-DqB-bSYE.js.map → containers-D_L4mTVb.js.map} +1 -1
  218. package/dist/{copyable-BTSByfmq.js → copyable-DDjTeW_j.js} +4 -4
  219. package/dist/{copyable-BTSByfmq.js.map → copyable-DDjTeW_j.js.map} +1 -1
  220. package/dist/{data-display-Bihs9Ven.js → data-display-3xWQUnMA.js} +471 -478
  221. package/dist/data-display-3xWQUnMA.js.map +1 -0
  222. package/dist/date-picker-DrDFj8Lo.js +1527 -0
  223. package/dist/date-picker-DrDFj8Lo.js.map +1 -0
  224. package/dist/date-pickers-CnFCb0n2.js +174 -0
  225. package/dist/date-pickers-CnFCb0n2.js.map +1 -0
  226. package/dist/date-uf3z37Nm.js +144 -0
  227. package/dist/date-uf3z37Nm.js.map +1 -0
  228. package/dist/{display-CS6Hbk18.js → display-DrdvPwF0.js} +25 -25
  229. package/dist/display-DrdvPwF0.js.map +1 -0
  230. package/dist/{dropdown-menu-D-boNgGO.js → dropdown-menu-CURh59jb.js} +22 -15
  231. package/dist/dropdown-menu-CURh59jb.js.map +1 -0
  232. package/dist/features/activities.js +38 -35
  233. package/dist/features/activities.js.map +1 -1
  234. package/dist/features/ai-chat.js +36 -35
  235. package/dist/features/ai-chat.js.map +1 -1
  236. package/dist/features/async-preview.js +8 -8
  237. package/dist/features/combobox.js +1 -1
  238. package/dist/features/comments.js +1 -1
  239. package/dist/features/data-view.js +10 -10
  240. package/dist/features/email-composer.js +325 -326
  241. package/dist/features/email-composer.js.map +1 -1
  242. package/dist/features/event-calendar.js +190 -200
  243. package/dist/features/event-calendar.js.map +1 -1
  244. package/dist/features/filters.js +1 -1
  245. package/dist/features/global-search.js +77 -77
  246. package/dist/features/global-search.js.map +1 -1
  247. package/dist/features/kanban.js +4 -4
  248. package/dist/features/map.js +8 -8
  249. package/dist/features/media-library.js +499 -502
  250. package/dist/features/media-library.js.map +1 -1
  251. package/dist/features/mentions.js +1 -1
  252. package/dist/features/overlays.js +1 -1
  253. package/dist/features/products.js +1216 -1248
  254. package/dist/features/products.js.map +1 -1
  255. package/dist/features/questionnaire.js +46 -44
  256. package/dist/features/questionnaire.js.map +1 -1
  257. package/dist/features/resource-assignment.js +96 -88
  258. package/dist/features/resource-assignment.js.map +1 -1
  259. package/dist/features/resource.js +11 -11
  260. package/dist/features/rich-text-editor.js +2 -2
  261. package/dist/features/schema-form.js +188 -184
  262. package/dist/features/schema-form.js.map +1 -1
  263. package/dist/features/suggestions.js +3 -3
  264. package/dist/features/sync.js +7 -7
  265. package/dist/features/sync.js.map +1 -1
  266. package/dist/features/table.js +1 -1
  267. package/dist/features/theme-tweaker.js +469 -470
  268. package/dist/features/theme-tweaker.js.map +1 -1
  269. package/dist/{feedback-CJkUAapr.js → feedback-C7nR0UtT.js} +9 -10
  270. package/dist/feedback-C7nR0UtT.js.map +1 -0
  271. package/dist/field-affordance-recipes-CkOCdE2y.js +46 -0
  272. package/dist/field-affordance-recipes-CkOCdE2y.js.map +1 -0
  273. package/dist/{field-state-recipes-DQQpiLWC.js → field-state-recipes-C-MFBX_8.js} +3 -3
  274. package/dist/field-state-recipes-C-MFBX_8.js.map +1 -0
  275. package/dist/{filters-D6FF8L6s.js → filters-Da-gNPsE.js} +467 -467
  276. package/dist/filters-Da-gNPsE.js.map +1 -0
  277. package/dist/{form-field-CZwrkP7m.js → form-field-VZRULhUK.js} +7 -7
  278. package/dist/{form-field-CZwrkP7m.js.map → form-field-VZRULhUK.js.map} +1 -1
  279. package/dist/form-sizing-uWP4lzVh.js +126 -0
  280. package/dist/form-sizing-uWP4lzVh.js.map +1 -0
  281. package/dist/{forms-B5NCbkSC.js → forms-DDeEnXSY.js} +11 -11
  282. package/dist/forms-DDeEnXSY.js.map +1 -0
  283. package/dist/forms-numeric-D3CO60IF.js +905 -0
  284. package/dist/forms-numeric-D3CO60IF.js.map +1 -0
  285. package/dist/{header-kxruN3RM.js → header-2ycNqGOR.js} +43 -42
  286. package/dist/header-2ycNqGOR.js.map +1 -0
  287. package/dist/{hooks-BrlnCwQd.js → hooks-DQ5SPwZw.js} +2 -2
  288. package/dist/{hooks-BrlnCwQd.js.map → hooks-DQ5SPwZw.js.map} +1 -1
  289. package/dist/{icon-badge-Btc6pQrp.js → icon-badge-DKlaKXoo.js} +3 -3
  290. package/dist/{icon-badge-Btc6pQrp.js.map → icon-badge-DKlaKXoo.js.map} +1 -1
  291. package/dist/index.js +2 -2
  292. package/dist/{input-vxcaNCYC.js → input-BoLm9Hks.js} +3 -3
  293. package/dist/{input-vxcaNCYC.js.map → input-BoLm9Hks.js.map} +1 -1
  294. package/dist/input-DhQdBnV3.js +255 -0
  295. package/dist/{input-SX9V0AL3.js.map → input-DhQdBnV3.js.map} +1 -1
  296. package/dist/item-xzh8Df65.js +264 -0
  297. package/dist/item-xzh8Df65.js.map +1 -0
  298. package/dist/layout/app-shell.js +1 -1
  299. package/dist/layout/auth.js +1 -1
  300. package/dist/layout/containers.js +1 -1
  301. package/dist/layout/header.js +1 -1
  302. package/dist/layout/hooks.js +1 -1
  303. package/dist/layout/navigation.js +1 -1
  304. package/dist/layout/page.js +1 -1
  305. package/dist/layout/settings.js +1 -1
  306. package/dist/layout/sidebar.js +2 -2
  307. package/dist/layout/workspace.js +1 -1
  308. package/dist/layout.js +10 -10
  309. package/dist/lib/affordance-geometry.generated.d.ts +6 -1
  310. package/dist/lib/field-affordance-recipes.d.ts +35 -0
  311. package/dist/lib/field-state-recipes.d.ts +4 -2
  312. package/dist/lib/format.d.ts +9 -0
  313. package/dist/lib/money-format.d.ts +30 -0
  314. package/dist/lib/overlay-anatomy-recipes.d.ts +1 -1
  315. package/dist/lib/surface-recipes.d.ts +8 -6
  316. package/dist/lib/token-merge.generated.d.ts +11 -11
  317. package/dist/lib/track-recipes.d.ts +1 -1
  318. package/dist/lib/ui-provider/provider.d.ts +7 -2
  319. package/dist/lib/ui-provider/store.d.ts +6 -2
  320. package/dist/lib/ui-provider/types.d.ts +5 -2
  321. package/dist/lib/utils.js +1 -1
  322. package/dist/{media-gallery-DLp3HAz0.js → media-gallery-DQUQ0m3O.js} +8 -8
  323. package/dist/media-gallery-DQUQ0m3O.js.map +1 -0
  324. package/dist/{mentions-Cl0Kt_Pd.js → mentions-DwnO1hh4.js} +34 -35
  325. package/dist/{mentions-Cl0Kt_Pd.js.map → mentions-DwnO1hh4.js.map} +1 -1
  326. package/dist/{message-SZUNB1eX.js → message-YfFmbXNP.js} +5 -5
  327. package/dist/{message-SZUNB1eX.js.map → message-YfFmbXNP.js.map} +1 -1
  328. package/dist/{navigation-DyytsLRB.js → navigation-Cbp5V8gG.js} +33 -34
  329. package/dist/navigation-Cbp5V8gG.js.map +1 -0
  330. package/dist/{navigation-DnQSNMT0.js → navigation-Cs1npsPm.js} +111 -87
  331. package/dist/navigation-Cs1npsPm.js.map +1 -0
  332. package/dist/{navigation-row-recipes-DQEXQcqY.js → navigation-row-recipes-DlU-4QYO.js} +2 -2
  333. package/dist/{navigation-row-recipes-DQEXQcqY.js.map → navigation-row-recipes-DlU-4QYO.js.map} +1 -1
  334. package/dist/number-CKRBYmZK.js +352 -0
  335. package/dist/number-CKRBYmZK.js.map +1 -0
  336. package/dist/overlay.recipes-CNO2S9V6.js +34 -0
  337. package/dist/overlay.recipes-CNO2S9V6.js.map +1 -0
  338. package/dist/overlays-DhZO7N-I.js +994 -0
  339. package/dist/overlays-DhZO7N-I.js.map +1 -0
  340. package/dist/page-C6R_8jFt.js +325 -0
  341. package/dist/page-C6R_8jFt.js.map +1 -0
  342. package/dist/{page-header-D8nERkn5.js → page-header-hUTzcRZX.js} +9 -9
  343. package/dist/page-header-hUTzcRZX.js.map +1 -0
  344. package/dist/{pagination-NLGqRirf.js → pagination-Cm0jqa3I.js} +8 -8
  345. package/dist/{pagination-NLGqRirf.js.map → pagination-Cm0jqa3I.js.map} +1 -1
  346. package/dist/{popover-CghIYdQf.js → popover-Dcv_9jxr.js} +6 -6
  347. package/dist/{popover-CghIYdQf.js.map → popover-Dcv_9jxr.js.map} +1 -1
  348. package/dist/{popover-menu-B4PoWhRl.js → popover-menu-DnRFKnHP.js} +6 -6
  349. package/dist/{popover-menu-B4PoWhRl.js.map → popover-menu-DnRFKnHP.js.map} +1 -1
  350. package/dist/{popover.recipes-QlD4JenO.js → popover.recipes-wmbvL8Ah.js} +2 -2
  351. package/dist/{popover.recipes-QlD4JenO.js.map → popover.recipes-wmbvL8Ah.js.map} +1 -1
  352. package/dist/primitives-BHrwQXFC.js +379 -0
  353. package/dist/primitives-BHrwQXFC.js.map +1 -0
  354. package/dist/primitives.js +5 -5
  355. package/dist/{progress-BroqrAyV.js → progress-Br9WTFya.js} +7 -7
  356. package/dist/progress-Br9WTFya.js.map +1 -0
  357. package/dist/{receipt-BuJynLgf.js → receipt-CV89q1fs.js} +6 -6
  358. package/dist/{receipt-BuJynLgf.js.map → receipt-CV89q1fs.js.map} +1 -1
  359. package/dist/{rich-text-editor-BKyG7rWz.js → rich-text-editor-CF8QYt5p.js} +6 -6
  360. package/dist/{rich-text-editor-BKyG7rWz.js.map → rich-text-editor-CF8QYt5p.js.map} +1 -1
  361. package/dist/{rich-text-editor.recipes-B72Nfuze.js → rich-text-editor.recipes-CnrbmTS1.js} +4 -4
  362. package/dist/{rich-text-editor.recipes-B72Nfuze.js.map → rich-text-editor.recipes-CnrbmTS1.js.map} +1 -1
  363. package/dist/{rich-text-DlxDOtf4.js → rich-text-j-FGAeZW.js} +4 -4
  364. package/dist/{rich-text-DlxDOtf4.js.map → rich-text-j-FGAeZW.js.map} +1 -1
  365. package/dist/{scroll-area-D-pIhEKl.js → scroll-area-DRdr16Pt.js} +3 -3
  366. package/dist/scroll-area-DRdr16Pt.js.map +1 -0
  367. package/dist/{separator-BhtFyo4x.js → separator-BMEvwnSX.js} +2 -2
  368. package/dist/{separator-BhtFyo4x.js.map → separator-BMEvwnSX.js.map} +1 -1
  369. package/dist/{separator-BNIgG3au.js → separator-Do5GWDYi.js} +4 -4
  370. package/dist/separator-Do5GWDYi.js.map +1 -0
  371. package/dist/services/actions/action-adapters.d.ts +4 -0
  372. package/dist/services/actions.js +8 -3
  373. package/dist/services/actions.js.map +1 -1
  374. package/dist/{settings-DOTOzeZ2.js → settings-DHk0L2MF.js} +17 -17
  375. package/dist/settings-DHk0L2MF.js.map +1 -0
  376. package/dist/sheet-DRFNY1_D.js +207 -0
  377. package/dist/sheet-DRFNY1_D.js.map +1 -0
  378. package/dist/sidebar-Cb8WzOvE.js +511 -0
  379. package/dist/sidebar-Cb8WzOvE.js.map +1 -0
  380. package/dist/{sidebar-CyR4XKwR.js → sidebar-Crc9M9JV.js} +18 -18
  381. package/dist/sidebar-Crc9M9JV.js.map +1 -0
  382. package/dist/{skeleton-3F0uhYn3.js → skeleton-DVMXr15h.js} +4 -4
  383. package/dist/{skeleton-3F0uhYn3.js.map → skeleton-DVMXr15h.js.map} +1 -1
  384. package/dist/{smart-card-DjGVV2xr.js → smart-card-Bek-TwUp.js} +222 -207
  385. package/dist/smart-card-Bek-TwUp.js.map +1 -0
  386. package/dist/{spinner-Cpf7oRkF.js → spinner-CmTAbEp0.js} +8 -6
  387. package/dist/spinner-CmTAbEp0.js.map +1 -0
  388. package/dist/{structure-CRdqVawd.js → structure-hzCW-XsV.js} +3 -3
  389. package/dist/{structure-CRdqVawd.js.map → structure-hzCW-XsV.js.map} +1 -1
  390. package/dist/{structure.recipes-Bqhf9oIh.js → structure.recipes-EPz60cU8.js} +37 -19
  391. package/dist/structure.recipes-EPz60cU8.js.map +1 -0
  392. package/dist/style.css +1 -1
  393. package/dist/surface-recipes-DOdoBXGm.js +28 -0
  394. package/dist/surface-recipes-DOdoBXGm.js.map +1 -0
  395. package/dist/table-D6zKeYQX.js +162 -0
  396. package/dist/table-D6zKeYQX.js.map +1 -0
  397. package/dist/{table-CcRDZiLP.js → table-Dn4XSrSB.js} +348 -348
  398. package/dist/table-Dn4XSrSB.js.map +1 -0
  399. package/dist/{tabs-BNgu7g0u.js → tabs-Dk8E_knt.js} +14 -13
  400. package/dist/tabs-Dk8E_knt.js.map +1 -0
  401. package/dist/{text-inputs-DsR56TR-.js → text-inputs-BFpku0Qd.js} +150 -149
  402. package/dist/text-inputs-BFpku0Qd.js.map +1 -0
  403. package/dist/{text.styles-Q4sGAIgA.js → text.styles-g4He6UIW.js} +17 -14
  404. package/dist/text.styles-g4He6UIW.js.map +1 -0
  405. package/dist/theme.css +16 -12
  406. package/dist/themes/green.css +24 -0
  407. package/dist/{timelines-D1pkt3se.js → timelines-CxuAFIc2.js} +25 -38
  408. package/dist/timelines-CxuAFIc2.js.map +1 -0
  409. package/dist/track-recipes-CDcKmndW.js +10 -0
  410. package/dist/track-recipes-CDcKmndW.js.map +1 -0
  411. package/dist/{tree-BtmYyMZV.js → tree-BotPlyiD.js} +13 -13
  412. package/dist/{tree-BtmYyMZV.js.map → tree-BotPlyiD.js.map} +1 -1
  413. package/dist/typography/rich-text.js +1 -1
  414. package/dist/typography-CAr3dQhX.js +116 -0
  415. package/dist/typography-CAr3dQhX.js.map +1 -0
  416. package/dist/typography.js +2 -2
  417. package/dist/{ui-provider-DRPn3qNl.js → ui-provider-D2_TeLqw.js} +20 -21
  418. package/dist/ui-provider-D2_TeLqw.js.map +1 -0
  419. package/dist/ui-provider.js +1 -1
  420. package/dist/{upload-CDbYw1WN.js → upload-B0WHW7ak.js} +221 -220
  421. package/dist/upload-B0WHW7ak.js.map +1 -0
  422. package/dist/{upload-queue-CNd_hH_a.js → upload-queue-BHZ_wBfd.js} +59 -62
  423. package/dist/upload-queue-BHZ_wBfd.js.map +1 -0
  424. package/dist/{usage-card-VyJLUwRr.js → usage-card-U0YBLTNT.js} +42 -43
  425. package/dist/{usage-card-VyJLUwRr.js.map → usage-card-U0YBLTNT.js.map} +1 -1
  426. package/dist/{utils-BvH9PSmq.js → utils-Cospvlj1.js} +221 -51
  427. package/dist/utils-Cospvlj1.js.map +1 -0
  428. package/dist/value-inputs-CjfzGMsN.js +854 -0
  429. package/dist/value-inputs-CjfzGMsN.js.map +1 -0
  430. package/dist/value-typography-Deb3yQZg.js +116 -0
  431. package/dist/value-typography-Deb3yQZg.js.map +1 -0
  432. package/dist/{workspace-CcR8r-Nt.js → workspace-YoFjXi6i.js} +44 -45
  433. package/dist/workspace-YoFjXi6i.js.map +1 -0
  434. package/docs/consumer-skill/SKILL.md +51 -38
  435. package/docs/consumer-skill/examples/app-layout.tsx +2 -4
  436. package/docs/consumer-skill/examples/detail.tsx +3 -4
  437. package/docs/consumer-skill/examples/edit.tsx +1 -1
  438. package/docs/consumer-skill/examples/layout-blocks.tsx +20 -0
  439. package/docs/consumer-skill/examples/manifest.json +28 -6
  440. package/docs/consumer-skill/examples/scoped-directory.tsx +2 -2
  441. package/docs/consumer-skill/references/composition.md +89 -17
  442. package/docs/consumer-skill/references/discovery.md +4 -0
  443. package/docs/consumer-skill/references/installation.md +22 -0
  444. package/docs/consumer-skill/references/integration.md +32 -1
  445. package/docs/consumer-skill/references/public-api.json +111 -70
  446. package/docs/consumer-skill/references/review.md +20 -4
  447. package/docs/consumer-skill/references/theming.md +7 -1
  448. package/docs/consumer-skill/references/tokens.json +5 -2
  449. package/docs/consumer-skill/references/workflows.md +4 -2
  450. package/docs/consumer-skill/scripts/composition-policy.mjs +93 -2
  451. package/docs/consumer-skill/scripts/discovery.mjs +11 -3
  452. package/docs/consumer-skill/scripts/pin-button-defaults.mjs +95 -0
  453. package/package.json +5 -3
  454. package/dist/accordion-BRTcsp8J.js.map +0 -1
  455. package/dist/action-menu-Drxw_vJk.js +0 -265
  456. package/dist/action-menu-Drxw_vJk.js.map +0 -1
  457. package/dist/affordance-geometry.generated-CL84ZN9A.js.map +0 -1
  458. package/dist/ai-artifact-DLVdK0Py.js.map +0 -1
  459. package/dist/avatar-Bu2HhitA.js.map +0 -1
  460. package/dist/badge-CzId1Wlm.js.map +0 -1
  461. package/dist/button-BZDasD04.js.map +0 -1
  462. package/dist/buttons-D_6KJvEE.js.map +0 -1
  463. package/dist/chart-Bsc5BICK.js.map +0 -1
  464. package/dist/checkbox-BQNDjUCh.js +0 -34
  465. package/dist/checkbox-BQNDjUCh.js.map +0 -1
  466. package/dist/choice-inputs-Mk3iWbhr.js +0 -725
  467. package/dist/choice-inputs-Mk3iWbhr.js.map +0 -1
  468. package/dist/combobox-BFnbJJp3.js.map +0 -1
  469. package/dist/combobox-hozNwUcc.js.map +0 -1
  470. package/dist/command-BnmSchli.js.map +0 -1
  471. package/dist/comments-u5L0OGip.js.map +0 -1
  472. package/dist/data-display-Bihs9Ven.js.map +0 -1
  473. package/dist/date-DOKhJPu7.js +0 -140
  474. package/dist/date-DOKhJPu7.js.map +0 -1
  475. package/dist/date-picker-DzP5HQq7.js +0 -1541
  476. package/dist/date-picker-DzP5HQq7.js.map +0 -1
  477. package/dist/date-pickers-BpgGz7S-.js +0 -196
  478. package/dist/date-pickers-BpgGz7S-.js.map +0 -1
  479. package/dist/display-CS6Hbk18.js.map +0 -1
  480. package/dist/dropdown-menu-D-boNgGO.js.map +0 -1
  481. package/dist/feedback-CJkUAapr.js.map +0 -1
  482. package/dist/field-affordance-recipes-uKY4MsZ_.js +0 -25
  483. package/dist/field-affordance-recipes-uKY4MsZ_.js.map +0 -1
  484. package/dist/field-state-recipes-DQQpiLWC.js.map +0 -1
  485. package/dist/filters-D6FF8L6s.js.map +0 -1
  486. package/dist/form-sizing-QP8aIRaW.js +0 -103
  487. package/dist/form-sizing-QP8aIRaW.js.map +0 -1
  488. package/dist/format-iamDSqs2.js +0 -110
  489. package/dist/format-iamDSqs2.js.map +0 -1
  490. package/dist/forms-B5NCbkSC.js.map +0 -1
  491. package/dist/forms-numeric-Crrm80Lm.js +0 -867
  492. package/dist/forms-numeric-Crrm80Lm.js.map +0 -1
  493. package/dist/header-kxruN3RM.js.map +0 -1
  494. package/dist/input-SX9V0AL3.js +0 -255
  495. package/dist/item-DE4YnuJx.js +0 -258
  496. package/dist/item-DE4YnuJx.js.map +0 -1
  497. package/dist/media-gallery-DLp3HAz0.js.map +0 -1
  498. package/dist/navigation-DnQSNMT0.js.map +0 -1
  499. package/dist/navigation-DyytsLRB.js.map +0 -1
  500. package/dist/number-DasMFWEG.js +0 -269
  501. package/dist/number-DasMFWEG.js.map +0 -1
  502. package/dist/overlay.recipes-BxW5FIfK.js +0 -6
  503. package/dist/overlay.recipes-BxW5FIfK.js.map +0 -1
  504. package/dist/overlays-DUbs1KEi.js +0 -1011
  505. package/dist/overlays-DUbs1KEi.js.map +0 -1
  506. package/dist/page-hGmT4nWK.js +0 -213
  507. package/dist/page-hGmT4nWK.js.map +0 -1
  508. package/dist/page-header-D8nERkn5.js.map +0 -1
  509. package/dist/primitives-C7ff0QaI.js +0 -337
  510. package/dist/primitives-C7ff0QaI.js.map +0 -1
  511. package/dist/progress-BroqrAyV.js.map +0 -1
  512. package/dist/scroll-area-D-pIhEKl.js.map +0 -1
  513. package/dist/separator-BNIgG3au.js.map +0 -1
  514. package/dist/settings-DOTOzeZ2.js.map +0 -1
  515. package/dist/sheet-BFhrNehm.js +0 -205
  516. package/dist/sheet-BFhrNehm.js.map +0 -1
  517. package/dist/sidebar-CyR4XKwR.js.map +0 -1
  518. package/dist/sidebar-SvGJ0Zwi.js +0 -506
  519. package/dist/sidebar-SvGJ0Zwi.js.map +0 -1
  520. package/dist/smart-card-DjGVV2xr.js.map +0 -1
  521. package/dist/spinner-Cpf7oRkF.js.map +0 -1
  522. package/dist/structure.recipes-Bqhf9oIh.js.map +0 -1
  523. package/dist/surface-recipes-Dd__PD-w.js +0 -28
  524. package/dist/surface-recipes-Dd__PD-w.js.map +0 -1
  525. package/dist/table-CLtJTxoR.js +0 -147
  526. package/dist/table-CLtJTxoR.js.map +0 -1
  527. package/dist/table-CcRDZiLP.js.map +0 -1
  528. package/dist/tabs-BNgu7g0u.js.map +0 -1
  529. package/dist/text-inputs-DsR56TR-.js.map +0 -1
  530. package/dist/text.styles-Q4sGAIgA.js.map +0 -1
  531. package/dist/timelines-D1pkt3se.js.map +0 -1
  532. package/dist/track-recipes-LLPNVwFg.js +0 -10
  533. package/dist/track-recipes-LLPNVwFg.js.map +0 -1
  534. package/dist/typography-BxQgiZyw.js +0 -96
  535. package/dist/typography-BxQgiZyw.js.map +0 -1
  536. package/dist/ui-provider-DRPn3qNl.js.map +0 -1
  537. package/dist/upload-CDbYw1WN.js.map +0 -1
  538. package/dist/upload-queue-CNd_hH_a.js.map +0 -1
  539. package/dist/utils-BvH9PSmq.js.map +0 -1
  540. package/dist/value-inputs-D0KCrfVC.js +0 -840
  541. package/dist/value-inputs-D0KCrfVC.js.map +0 -1
  542. package/dist/workspace-CcR8r-Nt.js.map +0 -1
@@ -1,14 +1,14 @@
1
1
  "use client";
2
2
  import { interpolateString as e, useStrings as t } from "../lib/strings.js";
3
- import { t as n } from "../utils-BvH9PSmq.js";
4
- import { a as r, r as i } from "../typography-BxQgiZyw.js";
5
- import { t as a } from "../button-BZDasD04.js";
6
- import { t as o } from "../structure-CRdqVawd.js";
7
- import { t as s } from "../badge-CzId1Wlm.js";
8
- import { d as c } from "../text-inputs-DsR56TR-.js";
9
- import { l } from "../data-display-Bihs9Ven.js";
10
- import { c as u, l as d, s as f } from "../message-SZUNB1eX.js";
11
- import { S as p, _ as m, a as h, b as g, d as _, h as v, l as y, p as b, r as x, s as S, t as C, y as w } from "../ai-artifact-DLVdK0Py.js";
3
+ import { t as n } from "../utils-Cospvlj1.js";
4
+ import { a as r, s as i } from "../typography-CAr3dQhX.js";
5
+ import { t as a } from "../button-BS3KDg00.js";
6
+ import { t as o } from "../structure-hzCW-XsV.js";
7
+ import { t as s } from "../badge-0tATj-tW.js";
8
+ import { d as c } from "../text-inputs-BFpku0Qd.js";
9
+ import { l } from "../data-display-3xWQUnMA.js";
10
+ import { c as u, l as d, s as f } from "../message-YfFmbXNP.js";
11
+ import { S as p, _ as m, a as h, b as g, d as _, h as v, l as y, p as b, r as x, s as S, t as C, y as w } from "../ai-artifact-2PQ2fItc.js";
12
12
  import { useCallback as T, useEffect as E, useRef as D, useState as O } from "react";
13
13
  import { Fragment as k, jsx as A, jsxs as j } from "react/jsx-runtime";
14
14
  import { ArrowDown as M, ArrowUp as N, Loader2 as P, Paperclip as F, Sparkles as I, Square as L, X as R } from "lucide-react";
@@ -91,7 +91,7 @@ function K({ threshold: e = 80, dependency: t, disableAutoScroll: n = !1 } = {})
91
91
  }
92
92
  //#endregion
93
93
  //#region src/components/features/ai-chat/partials/ai-chat-conversation.tsx
94
- function q({ messages: e, renderMessage: i, intro: s, footer: c, empty: l, disableAutoScroll: u, className: d, strings: f }) {
94
+ function q({ messages: e, renderMessage: r, intro: s, footer: c, empty: l, disableAutoScroll: u, className: d, strings: f }) {
95
95
  let p = t(B, f), { containerRef: m, endRef: h, isAtBottom: g, scrollToBottom: _ } = K({
96
96
  dependency: e.length,
97
97
  disableAutoScroll: u
@@ -110,7 +110,7 @@ function q({ messages: e, renderMessage: i, intro: s, footer: c, empty: l, disab
110
110
  }),
111
111
  v ? l ?? /* @__PURE__ */ A("div", {
112
112
  className: "flex h-full items-center justify-center p-surface-lg",
113
- children: /* @__PURE__ */ A(r, {
113
+ children: /* @__PURE__ */ A(i, {
114
114
  type: "secondary",
115
115
  children: p.empty
116
116
  })
@@ -119,11 +119,11 @@ function q({ messages: e, renderMessage: i, intro: s, footer: c, empty: l, disab
119
119
  gap: "xl",
120
120
  className: "ai-chat-conversation--messages m-0 list-none p-0 font-sans",
121
121
  children: e.map((t, n) => {
122
- let r = {
122
+ let i = {
123
123
  isLast: n === e.length - 1,
124
124
  index: n
125
125
  };
126
- return /* @__PURE__ */ A("li", { children: i(t, r) }, t.id);
126
+ return /* @__PURE__ */ A("li", { children: r(t, i) }, t.id);
127
127
  })
128
128
  }),
129
129
  !!c && /* @__PURE__ */ A("div", {
@@ -144,8 +144,8 @@ function q({ messages: e, renderMessage: i, intro: s, footer: c, empty: l, disab
144
144
  buttonStyle: "solid",
145
145
  "aria-label": p.scrollToBottomAria,
146
146
  onClick: () => _("smooth"),
147
- className: n("shadow-sm max-sm:size-action-sm max-sm:p-0", "border border-border/60"),
148
- children: [/* @__PURE__ */ A(M, { className: "size-icon-md" }), /* @__PURE__ */ A(r, {
147
+ className: n("shadow-sm max-sm:size-action-sm max-sm:min-h-0 max-sm:p-0", "border border-border/60"),
148
+ children: [/* @__PURE__ */ A(M, { className: "size-icon-md" }), /* @__PURE__ */ A(i, {
149
149
  tag: "span",
150
150
  size: "pxs",
151
151
  className: "max-sm:sr-only",
@@ -167,7 +167,7 @@ function J({ title: e = "Start a conversation", description: t, icon: r = I, bel
167
167
  gap: "md",
168
168
  align: "center",
169
169
  justify: "center",
170
- className: n("ai-chat-empty-state--component h-full text-center", a),
170
+ className: n("ai-chat-empty-state--component min-h-full text-center", a),
171
171
  children: [/* @__PURE__ */ A(l, {
172
172
  title: e,
173
173
  description: t ?? !1,
@@ -228,7 +228,7 @@ function Y({ message: e, onCopy: r, onRegenerate: i, onAttachmentOpen: a, classN
228
228
  Y.displayName = "AiChatMessage";
229
229
  function ee({ part: e, onAttachmentOpen: t }) {
230
230
  switch (e.type) {
231
- case "text": return /* @__PURE__ */ A(r, { children: e.content });
231
+ case "text": return /* @__PURE__ */ A(i, { children: e.content });
232
232
  case "reasoning": return /* @__PURE__ */ A(S, {
233
233
  streaming: e.streaming,
234
234
  durationSeconds: e.durationSeconds,
@@ -293,16 +293,16 @@ function X(e) {
293
293
  }
294
294
  //#endregion
295
295
  //#region src/components/features/ai-chat/partials/ai-chat-prompt-input.tsx
296
- function Z({ value: i, onValueChange: o, onSubmit: s, onStop: l, streaming: u = !1, disabled: d = !1, attachments: f = [], onRemoveAttachment: p, onAttach: m, showAttach: h, leadingActions: g, trailingActions: _, hideHint: v = !1, minRows: y = 1, maxRows: b = 8, autoFocus: x = !1, submitKeyLabel: S = "↩", className: C, strings: w }) {
297
- let E = t(z, w), O = D(null), k = !u && !d && (i.trim().length > 0 || f.length > 0), M = T(() => {
296
+ function Z({ value: r, onValueChange: o, onSubmit: s, onStop: l, streaming: u = !1, disabled: d = !1, attachments: f = [], onRemoveAttachment: p, onAttach: m, showAttach: h, leadingActions: g, trailingActions: _, hideHint: v = !1, minRows: y = 1, maxRows: b = 8, autoFocus: x = !1, submitKeyLabel: S = "↩", className: C, strings: w }) {
297
+ let E = t(z, w), O = D(null), k = !u && !d && (r.trim().length > 0 || f.length > 0), M = T(() => {
298
298
  k && s?.({
299
- text: i,
299
+ text: r,
300
300
  attachments: f
301
301
  });
302
302
  }, [
303
303
  k,
304
304
  s,
305
- i,
305
+ r,
306
306
  f
307
307
  ]), P = T((e) => {
308
308
  e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing && (e.preventDefault(), M());
@@ -319,7 +319,7 @@ function Z({ value: i, onValueChange: o, onSubmit: s, onStop: l, streaming: u =
319
319
  }),
320
320
  /* @__PURE__ */ A(c, {
321
321
  ref: O,
322
- value: i,
322
+ value: r,
323
323
  onChange: (e) => o(e.target.value),
324
324
  onKeyDown: P,
325
325
  placeholder: E.placeholder,
@@ -372,7 +372,7 @@ function Z({ value: i, onValueChange: o, onSubmit: s, onStop: l, streaming: u =
372
372
  }),
373
373
  !v && /* @__PURE__ */ A("div", {
374
374
  className: "px-surface-xs pb-surface-xs",
375
- children: /* @__PURE__ */ A(r, {
375
+ children: /* @__PURE__ */ A(i, {
376
376
  size: "xs",
377
377
  type: "discrete",
378
378
  children: e(E.hint, {
@@ -392,7 +392,7 @@ function Q({ items: e, hideHeader: c = !1, onCancel: l, className: u, strings: d
392
392
  return e.length === 0 ? null : /* @__PURE__ */ j(o, {
393
393
  gap: "sm",
394
394
  className: n("ai-chat-queue--component", "rounded-radius border border-border/60 bg-muted/20 p-surface-xs", u),
395
- children: [!c && /* @__PURE__ */ j(i, {
395
+ children: [!c && /* @__PURE__ */ j(r, {
396
396
  className: "px-1",
397
397
  children: [
398
398
  f.header,
@@ -406,18 +406,19 @@ function Q({ items: e, hideHeader: c = !1, onCancel: l, className: u, strings: d
406
406
  children: e.map((e) => {
407
407
  let t = e.status ?? "queued";
408
408
  return /* @__PURE__ */ j("li", {
409
- className: "flex items-center gap-space-md rounded-radius bg-card px-space-md py-space-sm",
409
+ className: "flex items-center gap-space-md rounded-inner bg-card px-space-md py-space-sm",
410
410
  children: [
411
411
  t === "running" ? /* @__PURE__ */ A(P, { className: "size-icon-md shrink-0 animate-spin text-primary-accent" }) : /* @__PURE__ */ A("span", {
412
412
  "aria-hidden": !0,
413
- className: "size-2 shrink-0 rounded-full bg-muted-foreground/50"
413
+ className: "flex size-icon-md shrink-0 items-center justify-center",
414
+ children: /* @__PURE__ */ A("span", { className: "size-2 rounded-full bg-muted-foreground/50" })
414
415
  }),
415
- /* @__PURE__ */ A(r, {
416
+ /* @__PURE__ */ A(i, {
416
417
  className: "flex-1 truncate",
417
418
  children: e.label
418
419
  }),
419
420
  /* @__PURE__ */ A(s, {
420
- tone: t === "running" ? "primary" : "secondary",
421
+ tone: t === "running" ? "info" : "secondary",
421
422
  children: t === "running" ? f.runningLabel : f.queuedLabel
422
423
  }),
423
424
  (!!e.onCancel || !!l) && /* @__PURE__ */ A(a, {
@@ -445,9 +446,9 @@ function $({ suggestions: e, onPick: o, hideHeader: s = !1, className: c, string
445
446
  let u = t(H, l);
446
447
  return e.length === 0 ? null : /* @__PURE__ */ j("div", {
447
448
  className: n("ai-chat-suggestions-row--component flex items-center gap-space-md", c),
448
- children: [!s && /* @__PURE__ */ j("div", {
449
- className: "inline-flex shrink-0 items-center gap-space-sm",
450
- children: [/* @__PURE__ */ A(I, { className: "size-icon-md text-muted-foreground" }), /* @__PURE__ */ A(i, { children: u.header })]
449
+ children: [!s && /* @__PURE__ */ A(r, {
450
+ className: "shrink-0",
451
+ children: u.header
451
452
  }), /* @__PURE__ */ A("div", {
452
453
  className: "flex min-w-0 flex-1 items-center gap-space-sm overflow-x-auto p-space-xs [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
453
454
  children: e.map((e) => {
@@ -459,7 +460,7 @@ function $({ suggestions: e, onPick: o, hideHeader: s = !1, className: c, string
459
460
  size: "sm",
460
461
  onClick: () => o?.(e),
461
462
  className: n("shrink-0 gap-space-sm border border-border/60 bg-card", "transition-[border-color,background] duration-150", "hover:border-foreground/20 hover:bg-muted/40"),
462
- children: [!!t && /* @__PURE__ */ A(t, { className: "size-icon-sm text-muted-foreground" }), /* @__PURE__ */ A(r, {
463
+ children: [!!t && /* @__PURE__ */ A(t, { className: "size-icon-sm text-muted-foreground" }), /* @__PURE__ */ A(i, {
463
464
  tag: "span",
464
465
  weight: "medium",
465
466
  children: e.label
@@ -472,7 +473,7 @@ function $({ suggestions: e, onPick: o, hideHeader: s = !1, className: c, string
472
473
  $.displayName = "AiChatSuggestionsRow";
473
474
  //#endregion
474
475
  //#region src/components/features/ai-chat/ai-chat.tsx
475
- function te({ messages: e, inputValue: i, onInputChange: a, onSubmit: s, onStop: c, streaming: l = !1, disabled: u = !1, attachments: d = [], onRemoveAttachment: f, onAttach: p, showAttach: m, agent: h, headerActions: g, queue: _ = [], onCancelQueueItem: v, suggestions: y = [], onPickSuggestion: x, onMessageCopy: S, onMessageRegenerate: C, onAttachmentOpen: w, disableAutoScroll: E, slots: D, strings: k, className: M }) {
476
+ function te({ messages: e, inputValue: r, onInputChange: a, onSubmit: s, onStop: c, streaming: l = !1, disabled: u = !1, attachments: d = [], onRemoveAttachment: f, onAttach: p, showAttach: m, agent: h, headerActions: g, queue: _ = [], onCancelQueueItem: v, suggestions: y = [], onPickSuggestion: x, onMessageCopy: S, onMessageRegenerate: C, onAttachmentOpen: w, disableAutoScroll: E, slots: D, strings: k, className: M }) {
476
477
  let N = t(W, k), [, P] = O(0), F = T((e, t) => D?.renderMessage ? D.renderMessage(e, t) : /* @__PURE__ */ A(Y, {
477
478
  className: "ai-chat-message--component",
478
479
  message: e,
@@ -517,7 +518,7 @@ function te({ messages: e, inputValue: i, onInputChange: a, onSubmit: s, onStop:
517
518
  onPick: x,
518
519
  strings: N.suggestions
519
520
  }) : null), B = D?.input ?? /* @__PURE__ */ A(Z, {
520
- value: i,
521
+ value: r,
521
522
  onValueChange: a,
522
523
  onSubmit: (e) => {
523
524
  s?.(e), P((e) => e + 1);
@@ -555,7 +556,7 @@ function te({ messages: e, inputValue: i, onInputChange: a, onSubmit: s, onStop:
555
556
  ]
556
557
  })
557
558
  }),
558
- u && /* @__PURE__ */ A(r, {
559
+ u && /* @__PURE__ */ A(i, {
559
560
  className: "sr-only",
560
561
  "aria-live": "polite",
561
562
  children: N.disabledAnnouncement
@@ -1 +1 @@
1
- {"version":3,"file":"ai-chat.js","names":["_Fragment","cn","Text","DisplayLabel","Button","Stack","Badge","Textarea","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","EmptyState","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';\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 focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring\"\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/50 bg-background/95 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: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 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-border bg-card transition-colors duration-150',\n\t\t\t\t'focus-within:border-foreground/20 focus-within:ring-2 focus-within:ring-ring',\n\t\t\t\tdisabled && 'opacity-60 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/20 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-radius 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<span\n\t\t\t\t\t\t\t\t\taria-hidden\n\t\t\t\t\t\t\t\t\tclassName=\"size-2 shrink-0 rounded-full bg-muted-foreground/50\"\n\t\t\t\t\t\t\t\t/>\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' ? 'primary' : '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 { Sparkles } from 'lucide-react';\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<div className=\"inline-flex shrink-0 items-center gap-space-sm\">\n\t\t\t\t\t<Sparkles className=\"size-icon-md text-muted-foreground\" />\n\t\t\t\t\t<DisplayLabel>\n\t\t\t\t\t\t{strings.header}\n\t\t\t\t\t</DisplayLabel>\n\t\t\t\t</div>\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=\"ghost\"\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={cn(\n\t\t\t\t\t\t\t\t'shrink-0 gap-space-sm border border-border/60 bg-card',\n\t\t\t\t\t\t\t\t'transition-[border-color,background] duration-150',\n\t\t\t\t\t\t\t\t'hover:border-foreground/20 hover:bg-muted/40',\n\t\t\t\t\t\t\t)}\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/60 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","DisplayLabel","Text","Button","Stack","Badge","Textarea","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","EmptyState","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';\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 focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring\"\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/50 bg-background/95 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-border bg-card transition-colors duration-150',\n\t\t\t\t'focus-within:border-foreground/20 focus-within:ring-2 focus-within:ring-ring',\n\t\t\t\tdisabled && 'opacity-60 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/20 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/50\" />\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=\"ghost\"\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={cn(\n\t\t\t\t\t\t\t\t'shrink-0 gap-space-sm border border-border/60 bg-card',\n\t\t\t\t\t\t\t\t'transition-[border-color,background] duration-150',\n\t\t\t\t\t\t\t\t'hover:border-foreground/20 hover:bg-muted/40',\n\t\t\t\t\t\t\t)}\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/60 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,13 +1,13 @@
1
1
  "use client";
2
2
  import { useStrings as e } from "../lib/strings.js";
3
- import { t } from "../utils-BvH9PSmq.js";
4
- import { t as n } from "../button-BZDasD04.js";
5
- import { t as r } from "../structure-CRdqVawd.js";
6
- import { n as i, t as a } from "../feedback-CJkUAapr.js";
7
- import { _ as o, d as s, g as c, p as l } from "../primitives-C7ff0QaI.js";
8
- import { t as u } from "../badge-CzId1Wlm.js";
9
- import { c as d, o as f, t as p } from "../popover-CghIYdQf.js";
10
- import { l as m } from "../data-display-Bihs9Ven.js";
3
+ import { t } from "../utils-Cospvlj1.js";
4
+ import { t as n } from "../button-BS3KDg00.js";
5
+ import { t as r } from "../structure-hzCW-XsV.js";
6
+ import { n as i, t as a } from "../feedback-C7nR0UtT.js";
7
+ import { _ as o, d as s, g as c, p as l } from "../primitives-BHrwQXFC.js";
8
+ import { t as u } from "../badge-0tATj-tW.js";
9
+ import { c as d, o as f, t as p } from "../popover-Dcv_9jxr.js";
10
+ import { l as m } from "../data-display-3xWQUnMA.js";
11
11
  import h, { createContext as g, useCallback as _, useContext as v, useEffect as y, useMemo as b, useRef as x, useState as S } from "react";
12
12
  import { Fragment as C, jsx as w, jsxs as T } from "react/jsx-runtime";
13
13
  import { ChevronDown as E } from "lucide-react";
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- import { a as e, i as t, n, o as r, r as i, t as a } from "../combobox-hozNwUcc.js";
2
+ import { a as e, i as t, n, o as r, r as i, t as a } from "../combobox-CB7039j7.js";
3
3
  export { a as AsyncResourceCombobox, i as Combobox, t as MultiCombobox, n as defaultAsyncResourceComboboxStrings, r as defaultComboboxStrings, e as useComboboxCore };
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- import { a as e, c as t, d as n, f as r, i, l as a, n as o, o as s, p as c, r as l, s as u, t as d, u as f } from "../comments-u5L0OGip.js";
2
+ import { a as e, c as t, d as n, f as r, i, l as a, n as o, o as s, p as c, r as l, s as u, t as d, u as f } from "../comments-You0Bzbr.js";
3
3
  export { a as CommentAttachmentChip, s as CommentComposer, i as CommentContent, e as CommentEmpty, l as CommentItem, o as CommentTimeline, d as Comments, c as defaultCommentsStrings, u as makeReplyEyebrow, t as useAttachmentUpload, f as useComments, n as useResolvedAccessors, r as useResolvedStrings };
@@ -1,15 +1,15 @@
1
1
  "use client";
2
2
  import { useStrings as e } from "../lib/strings.js";
3
- import { t } from "../utils-BvH9PSmq.js";
4
- import { a as n } from "../typography-BxQgiZyw.js";
5
- import { t as r } from "../button-BZDasD04.js";
6
- import { r as i, t as a } from "../structure-CRdqVawd.js";
7
- import { g as o } from "../primitives-C7ff0QaI.js";
8
- import { t as s } from "../number-DasMFWEG.js";
9
- import { i as c, r as l, t as u } from "../tabs-BNgu7g0u.js";
10
- import { t as d } from "../popover-menu-B4PoWhRl.js";
11
- import { f } from "../table-CcRDZiLP.js";
12
- import { N as p, O as m, P as h, T as g, l as _, w as v } from "../filters-D6FF8L6s.js";
3
+ import { t } from "../utils-Cospvlj1.js";
4
+ import { s as n } from "../typography-CAr3dQhX.js";
5
+ import { t as r } from "../button-BS3KDg00.js";
6
+ import { r as i, t as a } from "../structure-hzCW-XsV.js";
7
+ import { g as o } from "../primitives-BHrwQXFC.js";
8
+ import { t as s } from "../number-CKRBYmZK.js";
9
+ import { i as c, r as l, t as u } from "../tabs-Dk8E_knt.js";
10
+ import { t as d } from "../popover-menu-DnRFKnHP.js";
11
+ import { f } from "../table-Dn4XSrSB.js";
12
+ import { N as p, O as m, P as h, T as g, l as _, w as v } from "../filters-Da-gNPsE.js";
13
13
  import { useEffect as y, useMemo as b, useRef as x } from "react";
14
14
  import { Fragment as S, jsx as C, jsxs as w } from "react/jsx-runtime";
15
15
  import { Check as T, ChevronsUpDown as E } from "lucide-react";