themelia-react-ui 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (488) hide show
  1. package/CHANGELOG.md +137 -0
  2. package/README.md +59 -13
  3. package/dist/{accordion-B-5Focs8.js → accordion-BRTcsp8J.js} +8 -8
  4. package/dist/accordion-BRTcsp8J.js.map +1 -0
  5. package/dist/{action-menu-Cx3SdfbN.js → action-menu-Drxw_vJk.js} +36 -36
  6. package/dist/action-menu-Drxw_vJk.js.map +1 -0
  7. package/dist/affordance-geometry.generated-CL84ZN9A.js +63 -0
  8. package/dist/affordance-geometry.generated-CL84ZN9A.js.map +1 -0
  9. package/dist/{ai-artifact-B5tPpXnS.js → ai-artifact-DLVdK0Py.js} +151 -155
  10. package/dist/ai-artifact-DLVdK0Py.js.map +1 -0
  11. package/dist/{app-shell-at8Kt4l_.js → app-shell-C_fKpljx.js} +11 -10
  12. package/dist/app-shell-C_fKpljx.js.map +1 -0
  13. package/dist/{attachment-BO2R47wn.js → attachment-DbjUWsP0.js} +12 -12
  14. package/dist/{attachment-BO2R47wn.js.map → attachment-DbjUWsP0.js.map} +1 -1
  15. package/dist/auth-CAQcasMV.js +723 -0
  16. package/dist/auth-CAQcasMV.js.map +1 -0
  17. package/dist/{avatar-Bpzty83c.js → avatar-Bu2HhitA.js} +6 -6
  18. package/dist/{avatar-Bpzty83c.js.map → avatar-Bu2HhitA.js.map} +1 -1
  19. package/dist/{badge-BZXZT9wd.js → badge-CzId1Wlm.js} +4 -4
  20. package/dist/{badge-BZXZT9wd.js.map → badge-CzId1Wlm.js.map} +1 -1
  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 +3 -2
  27. package/dist/base/cards.js +3 -3
  28. package/dist/base/carousel.js +25 -27
  29. package/dist/base/carousel.js.map +1 -1
  30. package/dist/base/cascader.js +150 -148
  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 +3 -3
  39. package/dist/base/display.js +7 -7
  40. package/dist/base/feedback.js +4 -4
  41. package/dist/base/forms-numeric.js +1 -1
  42. package/dist/base/forms.js +2 -2
  43. package/dist/base/inline-edit.js +40 -43
  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 +1 -1
  51. package/dist/base/repeaters.js +33 -33
  52. package/dist/base/repeaters.js.map +1 -1
  53. package/dist/base/sheet.js +1 -1
  54. package/dist/base/sidebar.js +1 -1
  55. package/dist/base/signature-pad.js +83 -81
  56. package/dist/base/signature-pad.js.map +1 -1
  57. package/dist/base/skeleton.js +1 -1
  58. package/dist/base/spinner.js +1 -1
  59. package/dist/base/structure.js +1 -1
  60. package/dist/base/table.js +1 -1
  61. package/dist/base/text-inputs.js +2 -2
  62. package/dist/base/toaster.js +6 -6
  63. package/dist/base/toaster.js.map +1 -1
  64. package/dist/base/tree.js +1 -1
  65. package/dist/base/upload-queue.js +1 -1
  66. package/dist/base/upload.js +3 -3
  67. package/dist/base/value-inputs.js +1 -1
  68. package/dist/blocks/admin.js +134 -134
  69. package/dist/blocks/admin.js.map +1 -1
  70. package/dist/blocks/ai.js +120 -117
  71. package/dist/blocks/ai.js.map +1 -1
  72. package/dist/blocks/analytics/usage-card.js +1 -1
  73. package/dist/blocks/analytics.js +510 -472
  74. package/dist/blocks/analytics.js.map +1 -1
  75. package/dist/blocks/collaboration.js +2 -2
  76. package/dist/blocks/commerce/receipt.js +1 -1
  77. package/dist/blocks/commerce.js +395 -383
  78. package/dist/blocks/commerce.js.map +1 -1
  79. package/dist/blocks/data-display.js +1 -1
  80. package/dist/blocks/onboarding.js +6 -6
  81. package/dist/blocks/onboarding.js.map +1 -1
  82. package/dist/blocks/planning.js +36 -36
  83. package/dist/blocks/planning.js.map +1 -1
  84. package/dist/blocks/timelines.js +1 -1
  85. package/dist/{breadcrumbs-DdQ_I5ra.js → breadcrumbs-BuYz5SDU.js} +9 -8
  86. package/dist/breadcrumbs-BuYz5SDU.js.map +1 -0
  87. package/dist/button-BZDasD04.js +651 -0
  88. package/dist/button-BZDasD04.js.map +1 -0
  89. package/dist/{button-BS6l5JUw.js → button-BZyfTvwm.js} +3 -3
  90. package/dist/button-BZyfTvwm.js.map +1 -0
  91. package/dist/buttons-D_6KJvEE.js +99 -0
  92. package/dist/buttons-D_6KJvEE.js.map +1 -0
  93. package/dist/{cards-Cum56XOF.js → cards-qGSErLw_.js} +12 -12
  94. package/dist/{cards-Cum56XOF.js.map → cards-qGSErLw_.js.map} +1 -1
  95. package/dist/chart-Bsc5BICK.js +150 -0
  96. package/dist/chart-Bsc5BICK.js.map +1 -0
  97. package/dist/{checkbox-BavDRjF7.js → checkbox-BQNDjUCh.js} +3 -3
  98. package/dist/checkbox-BQNDjUCh.js.map +1 -0
  99. package/dist/choice-inputs-Mk3iWbhr.js +725 -0
  100. package/dist/choice-inputs-Mk3iWbhr.js.map +1 -0
  101. package/dist/{code-block-xHKbAJDj.js → code-block-DzHKRybS.js} +23 -23
  102. package/dist/code-block-DzHKRybS.js.map +1 -0
  103. package/dist/{collapsible-DsnktFNv.js → collapsible-ClvC7Bj3.js} +3 -3
  104. package/dist/{collapsible-DsnktFNv.js.map → collapsible-ClvC7Bj3.js.map} +1 -1
  105. package/dist/{collection-content-C4fthJV_.js → collection-content-D6S8cv_n.js} +3 -3
  106. package/dist/{collection-content-C4fthJV_.js.map → collection-content-D6S8cv_n.js.map} +1 -1
  107. package/dist/{combobox-DEbdr-3u.js → combobox-BFnbJJp3.js} +18 -18
  108. package/dist/combobox-BFnbJJp3.js.map +1 -0
  109. package/dist/{combobox-xv3yJbzl.js → combobox-hozNwUcc.js} +313 -316
  110. package/dist/combobox-hozNwUcc.js.map +1 -0
  111. package/dist/{command-C0xe7u9B.js → command-BnmSchli.js} +9 -9
  112. package/dist/command-BnmSchli.js.map +1 -0
  113. package/dist/comments-u5L0OGip.js +1156 -0
  114. package/dist/comments-u5L0OGip.js.map +1 -0
  115. package/dist/components/base/buttons/button-group.recipes.d.ts +1 -1
  116. package/dist/components/base/buttons/button.recipes.d.ts +10 -19
  117. package/dist/components/base/buttons/use-pending-button-focus.d.ts +3 -0
  118. package/dist/components/base/cards/card.recipes.d.ts +13 -5
  119. package/dist/components/base/cards/partials/card-primitives.d.ts +9 -4
  120. package/dist/components/base/cards/smart-card.types.d.ts +1 -1
  121. package/dist/components/base/date-pickers/date-picker.recipes.d.ts +5 -18
  122. package/dist/components/base/date-pickers/datepicker.types.d.ts +3 -0
  123. package/dist/components/base/forms/form-field.d.ts +1 -0
  124. package/dist/components/base/forms/form-sizing.d.ts +3 -3
  125. package/dist/components/base/navigation/tabs.d.ts +3 -5
  126. package/dist/components/base/popover/popover.recipes.d.ts +3 -3
  127. package/dist/components/base/table/index.d.ts +1 -1
  128. package/dist/components/base/text-inputs/clear-native-field.d.ts +2 -0
  129. package/dist/components/base/text-inputs/input-trailing-action.d.ts +3 -0
  130. package/dist/components/blocks/analytics/types.d.ts +1 -1
  131. package/dist/components/blocks/collaboration/message/message.recipes.d.ts +12 -0
  132. package/dist/components/blocks/data-display/empty-state/partials/illustrations/document-stack.d.ts +1 -4
  133. package/dist/components/blocks/data-display/empty-state/partials/illustrations/inbox-clean.d.ts +1 -4
  134. package/dist/components/blocks/data-display/empty-state/partials/illustrations/index.d.ts +3 -3
  135. package/dist/components/blocks/data-display/empty-state/partials/illustrations/stacked-cards.d.ts +1 -6
  136. package/dist/components/features/combobox/components/error-message.d.ts +1 -1
  137. package/dist/components/features/comments/hooks/use-attachment-upload.d.ts +5 -0
  138. package/dist/components/features/filters/facets/search-facet.d.ts +0 -12
  139. package/dist/components/features/filters/facets/tags-facet.d.ts +1 -1
  140. package/dist/components/features/media-library/media-library.d.ts +1 -1
  141. package/dist/components/features/media-library/media-library.types.d.ts +9 -1
  142. package/dist/components/features/media-library/partials/media-library-partials.d.ts +1 -1
  143. package/dist/components/features/overlays/hooks/use-pending-overlay-focus.d.ts +2 -0
  144. package/dist/components/features/overlays/overlays.types.d.ts +5 -4
  145. package/dist/components/features/rich-text-editor/rich-text-editor.recipes.d.ts +2 -1
  146. package/dist/components/features/table/data-table.d.ts +1 -1
  147. package/dist/components/features/table/table.types.d.ts +1 -1
  148. package/dist/components/features/theme-tweaker/theme-provider-settings.d.ts +3 -1
  149. package/dist/components/layout/auth/auth.types.d.ts +1 -0
  150. package/dist/components/layout/page/page.d.ts +0 -1
  151. package/dist/components/layout/page/page.types.d.ts +9 -3
  152. package/dist/components/layout/sidebar/sidebar.context.d.ts +1 -1
  153. package/dist/components/layout/sidebar/sidebar.types.d.ts +4 -0
  154. package/dist/components/layout/workspace/workspace.types.d.ts +3 -0
  155. package/dist/components/typography/heading.d.ts +5 -2
  156. package/dist/components/typography/index.d.ts +1 -1
  157. package/dist/components/typography/text.styles.d.ts +10 -0
  158. package/dist/components/ui/popover.d.ts +1 -1
  159. package/dist/components/ui/sidebar.d.ts +1 -1
  160. package/dist/components/ui/table.d.ts +2 -1
  161. package/dist/container.recipes-D9t8MHR3.js +27 -0
  162. package/dist/container.recipes-D9t8MHR3.js.map +1 -0
  163. package/dist/{containers-6s-ucRQQ.js → containers-DqB-bSYE.js} +33 -56
  164. package/dist/containers-DqB-bSYE.js.map +1 -0
  165. package/dist/control-group-recipes-DBXmfh2E.js +21 -0
  166. package/dist/control-group-recipes-DBXmfh2E.js.map +1 -0
  167. package/dist/{copyable-B7SBXJMr.js → copyable-BTSByfmq.js} +6 -6
  168. package/dist/{copyable-B7SBXJMr.js.map → copyable-BTSByfmq.js.map} +1 -1
  169. package/dist/{data-display-cWIRdeaf.js → data-display-Bihs9Ven.js} +545 -332
  170. package/dist/data-display-Bihs9Ven.js.map +1 -0
  171. package/dist/{date-BFNMnrS5.js → date-DOKhJPu7.js} +4 -4
  172. package/dist/{date-BFNMnrS5.js.map → date-DOKhJPu7.js.map} +1 -1
  173. package/dist/{date-picker-CA6ogMQB.js → date-picker-DzP5HQq7.js} +492 -472
  174. package/dist/date-picker-DzP5HQq7.js.map +1 -0
  175. package/dist/date-pickers-BpgGz7S-.js +196 -0
  176. package/dist/date-pickers-BpgGz7S-.js.map +1 -0
  177. package/dist/{display-CFM5myut.js → display-CS6Hbk18.js} +8 -8
  178. package/dist/{display-CFM5myut.js.map → display-CS6Hbk18.js.map} +1 -1
  179. package/dist/{dropdown-menu-BlnyHr-9.js → dropdown-menu-D-boNgGO.js} +7 -7
  180. package/dist/{dropdown-menu-BlnyHr-9.js.map → dropdown-menu-D-boNgGO.js.map} +1 -1
  181. package/dist/features/activities.js +152 -141
  182. package/dist/features/activities.js.map +1 -1
  183. package/dist/features/ai-chat.js +182 -179
  184. package/dist/features/ai-chat.js.map +1 -1
  185. package/dist/features/async-preview.js +9 -9
  186. package/dist/features/async-preview.js.map +1 -1
  187. package/dist/features/combobox.js +1 -1
  188. package/dist/features/comments.js +1 -1
  189. package/dist/features/data-view.js +25 -23
  190. package/dist/features/data-view.js.map +1 -1
  191. package/dist/features/email-composer/engine.js +1 -1
  192. package/dist/features/email-composer.js +103 -104
  193. package/dist/features/email-composer.js.map +1 -1
  194. package/dist/features/event-calendar.js +375 -373
  195. package/dist/features/event-calendar.js.map +1 -1
  196. package/dist/features/filters.js +1 -1
  197. package/dist/features/global-search.js +222 -224
  198. package/dist/features/global-search.js.map +1 -1
  199. package/dist/features/kanban.js +29 -29
  200. package/dist/features/kanban.js.map +1 -1
  201. package/dist/features/map.js +59 -58
  202. package/dist/features/map.js.map +1 -1
  203. package/dist/features/media-library.js +856 -855
  204. package/dist/features/media-library.js.map +1 -1
  205. package/dist/features/mentions.js +1 -1
  206. package/dist/features/overlays.js +1 -1
  207. package/dist/features/products.js +1209 -1209
  208. package/dist/features/products.js.map +1 -1
  209. package/dist/features/questionnaire.js +52 -52
  210. package/dist/features/questionnaire.js.map +1 -1
  211. package/dist/features/resource-assignment.js +29 -31
  212. package/dist/features/resource-assignment.js.map +1 -1
  213. package/dist/features/resource.js +13 -13
  214. package/dist/features/resource.js.map +1 -1
  215. package/dist/features/rich-text-editor.js +2 -2
  216. package/dist/features/schema-form.js +82 -82
  217. package/dist/features/schema-form.js.map +1 -1
  218. package/dist/features/suggestions.js +3 -3
  219. package/dist/features/sync.js +4 -4
  220. package/dist/features/sync.js.map +1 -1
  221. package/dist/features/table.js +1 -1
  222. package/dist/features/theme-tweaker.js +456 -450
  223. package/dist/features/theme-tweaker.js.map +1 -1
  224. package/dist/{feedback-DWUkgEjR.js → feedback-CJkUAapr.js} +29 -29
  225. package/dist/feedback-CJkUAapr.js.map +1 -0
  226. package/dist/field-affordance-recipes-uKY4MsZ_.js +25 -0
  227. package/dist/field-affordance-recipes-uKY4MsZ_.js.map +1 -0
  228. package/dist/{field-state-recipes-CBTRt9Bt.js → field-state-recipes-DQQpiLWC.js} +3 -3
  229. package/dist/field-state-recipes-DQQpiLWC.js.map +1 -0
  230. package/dist/{filters-BhsUtsxW.js → filters-D6FF8L6s.js} +715 -720
  231. package/dist/filters-D6FF8L6s.js.map +1 -0
  232. package/dist/{form-field-Bn7ZH1rA.js → form-field-CZwrkP7m.js} +17 -9
  233. package/dist/form-field-CZwrkP7m.js.map +1 -0
  234. package/dist/{form-sizing-BWs70_a2.js → form-sizing-QP8aIRaW.js} +8 -5
  235. package/dist/form-sizing-QP8aIRaW.js.map +1 -0
  236. package/dist/{forms-B7pzS25o.js → forms-B5NCbkSC.js} +35 -35
  237. package/dist/{forms-B7pzS25o.js.map → forms-B5NCbkSC.js.map} +1 -1
  238. package/dist/forms-numeric-Crrm80Lm.js +867 -0
  239. package/dist/forms-numeric-Crrm80Lm.js.map +1 -0
  240. package/dist/{header-C59QZyxV.js → header-kxruN3RM.js} +53 -49
  241. package/dist/header-kxruN3RM.js.map +1 -0
  242. package/dist/{hooks-CM1Vp9Pe.js → hooks-BrlnCwQd.js} +2 -2
  243. package/dist/{hooks-CM1Vp9Pe.js.map → hooks-BrlnCwQd.js.map} +1 -1
  244. package/dist/{http-CLTVJc5I.js → http-CdEIHyQf.js} +2 -2
  245. package/dist/http-CdEIHyQf.js.map +1 -0
  246. package/dist/{icon-badge-Dv0RYQwj.js → icon-badge-Btc6pQrp.js} +4 -4
  247. package/dist/{icon-badge-Dv0RYQwj.js.map → icon-badge-Btc6pQrp.js.map} +1 -1
  248. package/dist/index.js +2 -2
  249. package/dist/input-SX9V0AL3.js +255 -0
  250. package/dist/input-SX9V0AL3.js.map +1 -0
  251. package/dist/input-vxcaNCYC.js +20 -0
  252. package/dist/input-vxcaNCYC.js.map +1 -0
  253. package/dist/{item-pJ0GsOiJ.js → item-DE4YnuJx.js} +18 -17
  254. package/dist/item-DE4YnuJx.js.map +1 -0
  255. package/dist/layout/app-shell.js +1 -1
  256. package/dist/layout/auth.js +1 -1
  257. package/dist/layout/containers.js +1 -1
  258. package/dist/layout/header.js +1 -1
  259. package/dist/layout/hooks.js +1 -1
  260. package/dist/layout/navigation.js +1 -1
  261. package/dist/layout/page.js +1 -1
  262. package/dist/layout/settings.js +1 -1
  263. package/dist/layout/sidebar.js +2 -2
  264. package/dist/layout/workspace.js +1 -1
  265. package/dist/layout.js +10 -10
  266. package/dist/lib/affordance-geometry.generated.d.ts +40 -9
  267. package/dist/lib/control-group-recipes.d.ts +22 -0
  268. package/dist/lib/field-affordance-recipes.d.ts +35 -2
  269. package/dist/lib/field-state-recipes.d.ts +2 -2
  270. package/dist/lib/navigation-row-recipes.d.ts +3 -2
  271. package/dist/lib/overlay-anatomy-recipes.d.ts +1 -1
  272. package/dist/lib/surface-recipes.d.ts +5 -2
  273. package/dist/lib/token-merge.generated.d.ts +144 -2
  274. package/dist/lib/ui-provider/types.d.ts +4 -2
  275. package/dist/lib/use-prefers-reduced-motion.d.ts +2 -0
  276. package/dist/lib/utils.js +1 -1
  277. package/dist/{media-gallery-DhDRgnVZ.js → media-gallery-DLp3HAz0.js} +75 -74
  278. package/dist/media-gallery-DLp3HAz0.js.map +1 -0
  279. package/dist/{mentions-B8Ko-fhS.js → mentions-Cl0Kt_Pd.js} +52 -50
  280. package/dist/{mentions-B8Ko-fhS.js.map → mentions-Cl0Kt_Pd.js.map} +1 -1
  281. package/dist/message-SZUNB1eX.js +127 -0
  282. package/dist/message-SZUNB1eX.js.map +1 -0
  283. package/dist/{navigation-DBEu4POU.js → navigation-DnQSNMT0.js} +64 -55
  284. package/dist/navigation-DnQSNMT0.js.map +1 -0
  285. package/dist/{navigation-BUIn2Qxx.js → navigation-DyytsLRB.js} +37 -37
  286. package/dist/navigation-DyytsLRB.js.map +1 -0
  287. package/dist/{navigation-row-recipes-GVh11KiT.js → navigation-row-recipes-DQEXQcqY.js} +3 -3
  288. package/dist/navigation-row-recipes-DQEXQcqY.js.map +1 -0
  289. package/dist/{number-BNT_BIzJ.js → number-DasMFWEG.js} +4 -4
  290. package/dist/{number-BNT_BIzJ.js.map → number-DasMFWEG.js.map} +1 -1
  291. package/dist/overlays-DUbs1KEi.js +1011 -0
  292. package/dist/overlays-DUbs1KEi.js.map +1 -0
  293. package/dist/{page-BV6ioQg3.js → page-hGmT4nWK.js} +75 -64
  294. package/dist/page-hGmT4nWK.js.map +1 -0
  295. package/dist/{page-header-DQRa0jug.js → page-header-D8nERkn5.js} +9 -9
  296. package/dist/page-header-D8nERkn5.js.map +1 -0
  297. package/dist/{pagination-C29vvt3I.js → pagination-NLGqRirf.js} +20 -20
  298. package/dist/pagination-NLGqRirf.js.map +1 -0
  299. package/dist/{popover-CoLDEg19.js → popover-CghIYdQf.js} +23 -22
  300. package/dist/popover-CghIYdQf.js.map +1 -0
  301. package/dist/{popover-menu-GLIQTJTx.js → popover-menu-B4PoWhRl.js} +6 -6
  302. package/dist/{popover-menu-GLIQTJTx.js.map → popover-menu-B4PoWhRl.js.map} +1 -1
  303. package/dist/{popover.recipes-zgBhMlUu.js → popover.recipes-QlD4JenO.js} +5 -5
  304. package/dist/popover.recipes-QlD4JenO.js.map +1 -0
  305. package/dist/{primitives-DKPOGVpj.js → primitives-C7ff0QaI.js} +120 -113
  306. package/dist/primitives-C7ff0QaI.js.map +1 -0
  307. package/dist/primitives.js +3 -3
  308. package/dist/{progress-BOe8l_FZ.js → progress-BroqrAyV.js} +10 -9
  309. package/dist/progress-BroqrAyV.js.map +1 -0
  310. package/dist/{receipt-BM8xsGFy.js → receipt-BuJynLgf.js} +8 -8
  311. package/dist/{receipt-BM8xsGFy.js.map → receipt-BuJynLgf.js.map} +1 -1
  312. package/dist/{rich-text-B7sBAdDG.js → rich-text-DlxDOtf4.js} +4 -4
  313. package/dist/{rich-text-B7sBAdDG.js.map → rich-text-DlxDOtf4.js.map} +1 -1
  314. package/dist/rich-text-editor-BKyG7rWz.js +574 -0
  315. package/dist/rich-text-editor-BKyG7rWz.js.map +1 -0
  316. package/dist/{rich-text-editor.recipes-DxvOE0Lp.js → rich-text-editor.recipes-B72Nfuze.js} +35 -26
  317. package/dist/rich-text-editor.recipes-B72Nfuze.js.map +1 -0
  318. package/dist/{scroll-area-BheMQ270.js → scroll-area-D-pIhEKl.js} +3 -3
  319. package/dist/scroll-area-D-pIhEKl.js.map +1 -0
  320. package/dist/{separator-Gk_WXH-l.js → separator-BNIgG3au.js} +3 -3
  321. package/dist/{separator-Gk_WXH-l.js.map → separator-BNIgG3au.js.map} +1 -1
  322. package/dist/{separator-DO0EbCEm.js → separator-BhtFyo4x.js} +2 -2
  323. package/dist/{separator-DO0EbCEm.js.map → separator-BhtFyo4x.js.map} +1 -1
  324. package/dist/services/actions.js +1 -1
  325. package/dist/{settings-BnCyyPOJ.js → settings-DOTOzeZ2.js} +10 -9
  326. package/dist/{settings-BnCyyPOJ.js.map → settings-DOTOzeZ2.js.map} +1 -1
  327. package/dist/{sheet-B-q914Ad.js → sheet-BFhrNehm.js} +11 -11
  328. package/dist/sheet-BFhrNehm.js.map +1 -0
  329. package/dist/{sidebar-DPR7fmqN.js → sidebar-CyR4XKwR.js} +219 -200
  330. package/dist/sidebar-CyR4XKwR.js.map +1 -0
  331. package/dist/{sidebar-C_2p3Tfj.js → sidebar-SvGJ0Zwi.js} +63 -58
  332. package/dist/sidebar-SvGJ0Zwi.js.map +1 -0
  333. package/dist/{skeleton-CmT1ppqb.js → skeleton-3F0uhYn3.js} +4 -4
  334. package/dist/{skeleton-CmT1ppqb.js.map → skeleton-3F0uhYn3.js.map} +1 -1
  335. package/dist/{smart-card-CYLn46e6.js → smart-card-DjGVV2xr.js} +171 -165
  336. package/dist/smart-card-DjGVV2xr.js.map +1 -0
  337. package/dist/{spinner-BY9HbUEh.js → spinner-Cpf7oRkF.js} +5 -5
  338. package/dist/{spinner-BY9HbUEh.js.map → spinner-Cpf7oRkF.js.map} +1 -1
  339. package/dist/{structure-MvKVq-oL.js → structure-CRdqVawd.js} +2 -2
  340. package/dist/{structure-MvKVq-oL.js.map → structure-CRdqVawd.js.map} +1 -1
  341. package/dist/style.css +1 -1
  342. package/dist/{surface-recipes-CQfRr-VL.js → surface-recipes-Dd__PD-w.js} +4 -3
  343. package/dist/surface-recipes-Dd__PD-w.js.map +1 -0
  344. package/dist/{table-DnlAJ-xR.js → table-CLtJTxoR.js} +17 -16
  345. package/dist/table-CLtJTxoR.js.map +1 -0
  346. package/dist/table-CcRDZiLP.js +1444 -0
  347. package/dist/table-CcRDZiLP.js.map +1 -0
  348. package/dist/tabs-BNgu7g0u.js +188 -0
  349. package/dist/tabs-BNgu7g0u.js.map +1 -0
  350. package/dist/text-inputs-DsR56TR-.js +330 -0
  351. package/dist/text-inputs-DsR56TR-.js.map +1 -0
  352. package/dist/{text.styles-BwB7vAF2.js → text.styles-Q4sGAIgA.js} +18 -10
  353. package/dist/text.styles-Q4sGAIgA.js.map +1 -0
  354. package/dist/theme.css +77 -115
  355. package/dist/{timelines-B9ICkQcV.js → timelines-D1pkt3se.js} +84 -78
  356. package/dist/timelines-D1pkt3se.js.map +1 -0
  357. package/dist/{tree-BdWSaoFT.js → tree-BtmYyMZV.js} +8 -8
  358. package/dist/{tree-BdWSaoFT.js.map → tree-BtmYyMZV.js.map} +1 -1
  359. package/dist/typography/rich-text.js +1 -1
  360. package/dist/typography-BxQgiZyw.js +96 -0
  361. package/dist/typography-BxQgiZyw.js.map +1 -0
  362. package/dist/typography.js +1 -1
  363. package/dist/{ui-provider-CftIB6TY.js → ui-provider-DRPn3qNl.js} +3 -2
  364. package/dist/ui-provider-DRPn3qNl.js.map +1 -0
  365. package/dist/ui-provider.js +1 -1
  366. package/dist/{upload-D8Za5x_c.js → upload-CDbYw1WN.js} +326 -323
  367. package/dist/upload-CDbYw1WN.js.map +1 -0
  368. package/dist/{upload-queue-hIIYBLS7.js → upload-queue-CNd_hH_a.js} +25 -25
  369. package/dist/upload-queue-CNd_hH_a.js.map +1 -0
  370. package/dist/{usage-card-DnmnJ58D.js → usage-card-VyJLUwRr.js} +53 -54
  371. package/dist/usage-card-VyJLUwRr.js.map +1 -0
  372. package/dist/utils-BvH9PSmq.js +4275 -0
  373. package/dist/utils-BvH9PSmq.js.map +1 -0
  374. package/dist/value-inputs-D0KCrfVC.js +840 -0
  375. package/dist/value-inputs-D0KCrfVC.js.map +1 -0
  376. package/dist/{workspace-C1PZmk8L.js → workspace-CcR8r-Nt.js} +115 -122
  377. package/dist/workspace-CcR8r-Nt.js.map +1 -0
  378. package/docs/consumer-skill/SKILL.md +110 -119
  379. package/docs/consumer-skill/examples/analytics.tsx +34 -0
  380. package/docs/consumer-skill/examples/app-layout.tsx +42 -12
  381. package/docs/consumer-skill/examples/detail.tsx +20 -4
  382. package/docs/consumer-skill/examples/manifest.json +13 -1
  383. package/docs/consumer-skill/examples/website.tsx +56 -0
  384. package/docs/consumer-skill/references/analytics.md +70 -0
  385. package/docs/consumer-skill/references/composition.md +116 -2
  386. package/docs/consumer-skill/references/design-contract.md +33 -7
  387. package/docs/consumer-skill/references/discovery.md +76 -5
  388. package/docs/consumer-skill/references/integration.md +14 -0
  389. package/docs/consumer-skill/references/public-api.json +2023 -218
  390. package/docs/consumer-skill/references/review.md +55 -3
  391. package/docs/consumer-skill/references/theming.md +52 -7
  392. package/docs/consumer-skill/references/tokens.json +177 -9
  393. package/docs/consumer-skill/references/workflows.md +32 -0
  394. package/docs/consumer-skill/scripts/check-composition.mjs +1 -1
  395. package/docs/consumer-skill/scripts/composition-policy.mjs +179 -17
  396. package/docs/consumer-skill/scripts/discovery.mjs +61 -9
  397. package/docs/consumer-skill/scripts/surface-policy.mjs +44 -0
  398. package/package.json +7 -4
  399. package/dist/accordion-B-5Focs8.js.map +0 -1
  400. package/dist/action-menu-Cx3SdfbN.js.map +0 -1
  401. package/dist/affordance-geometry.generated-D8Jcfb0G.js +0 -32
  402. package/dist/affordance-geometry.generated-D8Jcfb0G.js.map +0 -1
  403. package/dist/ai-artifact-B5tPpXnS.js.map +0 -1
  404. package/dist/app-shell-at8Kt4l_.js.map +0 -1
  405. package/dist/auth-OFwWSAap.js +0 -704
  406. package/dist/auth-OFwWSAap.js.map +0 -1
  407. package/dist/breadcrumbs-DdQ_I5ra.js.map +0 -1
  408. package/dist/button-BS6l5JUw.js.map +0 -1
  409. package/dist/buttons-Co6GavvM.js +0 -674
  410. package/dist/buttons-Co6GavvM.js.map +0 -1
  411. package/dist/chart-DVfcwQu6.js +0 -149
  412. package/dist/chart-DVfcwQu6.js.map +0 -1
  413. package/dist/checkbox-BavDRjF7.js.map +0 -1
  414. package/dist/choice-inputs-CC7XqPQO.js +0 -619
  415. package/dist/choice-inputs-CC7XqPQO.js.map +0 -1
  416. package/dist/code-block-xHKbAJDj.js.map +0 -1
  417. package/dist/combobox-DEbdr-3u.js.map +0 -1
  418. package/dist/combobox-xv3yJbzl.js.map +0 -1
  419. package/dist/command-C0xe7u9B.js.map +0 -1
  420. package/dist/comments-DviPLnwy.js +0 -1132
  421. package/dist/comments-DviPLnwy.js.map +0 -1
  422. package/dist/containers-6s-ucRQQ.js.map +0 -1
  423. package/dist/data-display-cWIRdeaf.js.map +0 -1
  424. package/dist/date-picker-CA6ogMQB.js.map +0 -1
  425. package/dist/date-pickers-BPIKLdsD.js +0 -224
  426. package/dist/date-pickers-BPIKLdsD.js.map +0 -1
  427. package/dist/feedback-DWUkgEjR.js.map +0 -1
  428. package/dist/field-affordance-recipes-IjzPrCTw.js +0 -17
  429. package/dist/field-affordance-recipes-IjzPrCTw.js.map +0 -1
  430. package/dist/field-state-recipes-CBTRt9Bt.js.map +0 -1
  431. package/dist/filters-BhsUtsxW.js.map +0 -1
  432. package/dist/form-field-Bn7ZH1rA.js.map +0 -1
  433. package/dist/form-sizing-BWs70_a2.js.map +0 -1
  434. package/dist/forms-numeric-BUBxELBv.js +0 -867
  435. package/dist/forms-numeric-BUBxELBv.js.map +0 -1
  436. package/dist/header-C59QZyxV.js.map +0 -1
  437. package/dist/http-CLTVJc5I.js.map +0 -1
  438. package/dist/input-WwYQZJzG.js +0 -202
  439. package/dist/input-WwYQZJzG.js.map +0 -1
  440. package/dist/input-ci9fIgFH.js +0 -20
  441. package/dist/input-ci9fIgFH.js.map +0 -1
  442. package/dist/item-pJ0GsOiJ.js.map +0 -1
  443. package/dist/media-gallery-DhDRgnVZ.js.map +0 -1
  444. package/dist/message-COsdEvXT.js +0 -108
  445. package/dist/message-COsdEvXT.js.map +0 -1
  446. package/dist/navigation-BUIn2Qxx.js.map +0 -1
  447. package/dist/navigation-DBEu4POU.js.map +0 -1
  448. package/dist/navigation-row-recipes-GVh11KiT.js.map +0 -1
  449. package/dist/overlays-B11wZka6.js +0 -982
  450. package/dist/overlays-B11wZka6.js.map +0 -1
  451. package/dist/page-BV6ioQg3.js.map +0 -1
  452. package/dist/page-header-DQRa0jug.js.map +0 -1
  453. package/dist/pagination-C29vvt3I.js.map +0 -1
  454. package/dist/popover-CoLDEg19.js.map +0 -1
  455. package/dist/popover.recipes-zgBhMlUu.js.map +0 -1
  456. package/dist/primitives-DKPOGVpj.js.map +0 -1
  457. package/dist/progress-BOe8l_FZ.js.map +0 -1
  458. package/dist/rich-text-editor-CoVrTiSv.js +0 -575
  459. package/dist/rich-text-editor-CoVrTiSv.js.map +0 -1
  460. package/dist/rich-text-editor.recipes-DxvOE0Lp.js.map +0 -1
  461. package/dist/scroll-area-BheMQ270.js.map +0 -1
  462. package/dist/select-B2mb-qN2.js +0 -108
  463. package/dist/select-B2mb-qN2.js.map +0 -1
  464. package/dist/sheet-B-q914Ad.js.map +0 -1
  465. package/dist/sidebar-C_2p3Tfj.js.map +0 -1
  466. package/dist/sidebar-DPR7fmqN.js.map +0 -1
  467. package/dist/smart-card-CYLn46e6.js.map +0 -1
  468. package/dist/surface-recipes-CQfRr-VL.js.map +0 -1
  469. package/dist/table-BS39xnlq.js +0 -1424
  470. package/dist/table-BS39xnlq.js.map +0 -1
  471. package/dist/table-DnlAJ-xR.js.map +0 -1
  472. package/dist/tabs-B5cNMWiP.js +0 -187
  473. package/dist/tabs-B5cNMWiP.js.map +0 -1
  474. package/dist/text-inputs-Dh9XGyiS.js +0 -331
  475. package/dist/text-inputs-Dh9XGyiS.js.map +0 -1
  476. package/dist/text.styles-BwB7vAF2.js.map +0 -1
  477. package/dist/timelines-B9ICkQcV.js.map +0 -1
  478. package/dist/typography-Cv8MT-82.js +0 -96
  479. package/dist/typography-Cv8MT-82.js.map +0 -1
  480. package/dist/ui-provider-CftIB6TY.js.map +0 -1
  481. package/dist/upload-D8Za5x_c.js.map +0 -1
  482. package/dist/upload-queue-hIIYBLS7.js.map +0 -1
  483. package/dist/usage-card-DnmnJ58D.js.map +0 -1
  484. package/dist/utils-C2EKeIw3.js +0 -72
  485. package/dist/utils-C2EKeIw3.js.map +0 -1
  486. package/dist/value-inputs-DX2dbxjj.js +0 -824
  487. package/dist/value-inputs-DX2dbxjj.js.map +0 -1
  488. package/dist/workspace-C1PZmk8L.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ai-chat.js","names":["_Fragment","cn","Button","Text","DisplayLabel","Stack","Badge","Textarea","AiMessageBubble","AiCodeBlock","AiChainOfThought","AiToolCall","AiConfirmation","AiSources","AiAgent","AiTask","AiReasoning","AiArtifact","AiShimmer","Fragment$1","defaultAiChatPromptInputStrings","defaultAiChatConversationStrings","defaultAiChatQueueStrings","defaultAiChatSuggestionsStrings","defaultAiChatMessageStrings","defaultAiChatStrings","AiChatAttachmentsStrip","attachments","className","AiAttachment","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","inBubble","part","plainText","p","extractPlain","bubbleContent","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\">\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'rounded-full 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';\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\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\n\treturn (\n\t\t<Stack gap=\"md\" className={cn('ai-chat-message--component', className)}>\n\t\t\t{(bubbleContent !== null || message.pending) && (\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\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(\n\t\t\t\t\t\tmessage.role === 'user'\n\t\t\t\t\t\t\t? 'pr-9 sm:pl-12'\n\t\t\t\t\t\t\t: 'pl-9 sm:pr-12',\n\t\t\t\t\t)}\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(\n\t\t\t\t\t\tmessage.role === 'user' ? 'pr-9 sm:pl-12' : 'pl-9 sm:pr-12',\n\t\t\t\t\t)}\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-lg 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/30',\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 px-control py-2.5',\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<div\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=\"mb-1.5 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\">\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-md 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</div>\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=\"-mx-1 flex flex-1 items-center gap-space-sm overflow-x-auto px-1 py-0.5 [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'h-auto shrink-0 gap-space-sm rounded-full border border-border/60 bg-card px-control-sm py-1',\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-lg 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","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,13 +1,13 @@
1
1
  "use client";
2
2
  import { useStrings as e } from "../lib/strings.js";
3
- import { t } from "../utils-C2EKeIw3.js";
4
- import { n } from "../buttons-Co6GavvM.js";
5
- import { t as r } from "../structure-MvKVq-oL.js";
6
- import { n as i, t as a } from "../feedback-DWUkgEjR.js";
7
- import { _ as o, d as s, g as c, p as l } from "../primitives-DKPOGVpj.js";
8
- import { t as u } from "../badge-BZXZT9wd.js";
9
- import { c as d, o as f, t as p } from "../popover-CoLDEg19.js";
10
- import { l as m } from "../data-display-cWIRdeaf.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";
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";
@@ -465,7 +465,7 @@ var q = h.forwardRef(function({ value: e, name: r, secondary: i, leading: a, tra
465
465
  "aria-hidden": !0
466
466
  })]
467
467
  }) : /* @__PURE__ */ w("div", {
468
- className: t("preview-trigger-cell--component flex h-auto min-h-action-sm max-w-full items-center justify-start rounded-radius px-control-sm py-space-xs text-left", p),
468
+ className: t("preview-trigger-cell--component flex h-auto min-h-action-sm max-w-full items-center justify-start rounded-inner px-control-sm py-space-xs text-left", p),
469
469
  "aria-disabled": d ? !0 : void 0,
470
470
  title: typeof d == "string" ? d : void 0,
471
471
  children: /* @__PURE__ */ w(K, { ...v })
@@ -1 +1 @@
1
- {"version":3,"file":"async-preview.js","names":["_Fragment","Stack","LoadingState","ErrorState","Value","Name","SecondaryValue","EmptyValue","Badge","PopoverTrigger","Popover","PopoverContent","EmptyState","React","Fragment$1","defaultAsyncPreviewStrings","asyncPreviewCache","readCache","cacheKey","cached","staleTime","normalizeLoading","loading","hasStaticDataSource","options","useAsyncPreview","openProp","hasStaticData","staticData","onShow","isControlled","uncontrolledOpen","setUncontrolledOpen","useState","defaultOpen","open","data","setData","status","setStatus","error","setError","setLoadingState","meta","setMetaState","setCached","resolvedData","resolvedStatus","abortRef","useRef","requestIdRef","prefetchedRef","metaRef","openRunKeyRef","activeRunKeyRef","stateRef","setOpen","useCallback","nextOpen","currentState","onOpenChange","run","requestKey","type","activeController","reason","cachedEntry","cachePolicy","controller","requestId","hadCache","loadingState","onBeforeShow","onRefresh","applyIfCurrent","fn","result","nextLoading","next","nextMeta","nextStatus","nextData","settledState","onData","onSettled","err","onError","context","refresh","prefetch","close","state","useMemo","useEffect","openRunKey","clearAsyncPreviewCache","AsyncPreviewContext","createContext","useAsyncPreviewContext","ctx","useContext","AsyncPreviewRoot","stringsProp","strings","useStrings","preview","AsyncPreviewTrigger","maybePrefetch","prefetchOn","triggerProps","render","renderedTrigger","Button","AsyncPreviewContent","props","contentProps","sizeClassName","size","inset","padding","cn","className","children","AsyncPreviewState","AsyncPreviewBody","AsyncPreviewLoading","label","phase","progress","AsyncPreviewError","AsyncPreviewEmpty","createAsyncPreview","AsyncPreview","isEmpty","value","renderBadge","badge","PreviewTriggerCellInner","Icon","primaryIsEmpty","name","contentClassName","leading","emptyLabel","forceNameCase","secondary","trailing","PreviewTriggerCell","rootProps","cellProps","hasPreview","disabledReason","ChevronDown"],"sources":["../../src/components/features/async-preview/async-preview.strings.ts","../../src/components/features/async-preview/hooks/use-async-preview.ts","../../src/components/features/async-preview/async-preview.tsx","../../src/components/features/async-preview/preview-trigger-cell.tsx"],"sourcesContent":["/**\n * Strings for AsyncPreview. Consumers override with `strings={{ ... }}` on\n * `<AsyncPreview.Root />`; all user-facing copy is deep-merged via\n * `useStrings`.\n */\nexport interface AsyncPreviewStrings {\n\tloading: string;\n\terrorTitle: string;\n\terrorDescription: string;\n\tretry: string;\n\temptyTitle: string;\n\temptyDescription: string;\n}\n\nexport const defaultAsyncPreviewStrings: AsyncPreviewStrings = {\n\tloading: 'Loading preview...',\n\terrorTitle: 'Could not load preview',\n\terrorDescription: 'Try again or open the full record.',\n\tretry: 'Retry',\n\temptyTitle: 'No preview data',\n\temptyDescription: 'There is nothing to show for this record yet.',\n};\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport type {\n\t\tAsyncPreviewLoadingState,\n\t\tAsyncPreviewReason,\n\t\tAsyncPreviewRootProps,\n\t\tAsyncPreviewState,\n\t\tAsyncPreviewStatus,\n} from '../async-preview.types';\n\ninterface CacheEntry {\n\t\t/** Formatted time for the entry. */\n\t\ttimestamp: number;\n\t\t/** Records to render. */\n\t\tdata: unknown | null;\n\t\tstatus: 'success' | 'empty';\n\t\tmeta: Record<string, unknown>;\n}\n\nconst asyncPreviewCache = new Map<string, CacheEntry>();\n\nfunction readCache(cacheKey: string | undefined, staleTime: number): CacheEntry | undefined {\n\t\tif (!cacheKey) return undefined;\n\t\tconst cached = asyncPreviewCache.get(cacheKey);\n\t\tif (!cached) return undefined;\n\t\tif (Date.now() - cached.timestamp > staleTime) {\n\t\t\t\tasyncPreviewCache.delete(cacheKey);\n\t\t\t\treturn undefined;\n\t\t}\n\t\treturn cached;\n}\n\nfunction normalizeLoading(\n\t\tloading: AsyncPreviewLoadingState,\n): false | Exclude<AsyncPreviewLoadingState, false> {\n\t\treturn loading === false ? false : loading;\n}\n\nfunction hasStaticDataSource<\n\t\tTData,\n\t\tTContext,\n\t\tTType extends string,\n>(options: UseAsyncPreviewOptions<TData, TContext, TType>) {\n\t\treturn Object.prototype.hasOwnProperty.call(options, 'data');\n}\n\nexport interface UseAsyncPreviewOptions<\n\t\tTData,\n\t\tTContext = unknown,\n\t\tTType extends string = string,\n> extends Omit<AsyncPreviewRootProps<TData, TContext, TType>, 'children' | 'strings'> {}\n\nexport type UseAsyncPreviewReturn<\n\t\tTData,\n\t\tTContext = unknown,\n\t\tTType extends string = string,\n> = AsyncPreviewState<TData, TContext, TType> & {\n\t\tsetOpen: (open: boolean) => void;\n};\n\nexport function useAsyncPreview<\n\t\tTData,\n\t\tTContext = unknown,\n\t\tTType extends string = string,\n>(options: UseAsyncPreviewOptions<TData, TContext, TType>): UseAsyncPreviewReturn<TData, TContext, TType> {\n\t\tconst {\n\t\t\t\ttype,\n\t\t\t\tcontext,\n\t\t\t\tcacheKey,\n\t\t\t\tcachePolicy = 'cache-first',\n\t\t\t\tstaleTime = 300_000,\n\t\t\t\topen: openProp,\n\t\t\t\tdefaultOpen = false,\n\t\t\t\tonOpenChange,\n\t\t\t\tonBeforeShow,\n\t\t\t\tonData,\n\t\t\t\tonError,\n\t\t\t\tonSettled,\n\t\t\t\tonRefresh,\n\t\t} = options;\n\t\tconst hasStaticData = hasStaticDataSource(options);\n\t\tconst staticData = hasStaticData ? options.data ?? null : null;\n\t\tconst onShow = hasStaticData ? undefined : options.onShow;\n\n\t\tconst isControlled = openProp !== undefined;\n\t\tconst [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n\t\tconst open = openProp ?? uncontrolledOpen;\n\n\t\tconst [data, setData] = useState<TData | null>(() => {\n\t\t\t\tif (hasStaticData) return staticData as TData | null;\n\t\t\t\tconst cached = readCache(cacheKey, staleTime);\n\t\t\t\treturn cached?.status === 'success' ? cached.data as TData : null;\n\t\t});\n\t\tconst [status, setStatus] = useState<AsyncPreviewStatus>(() => {\n\t\t\t\tif (hasStaticData) return staticData === null ? 'empty' : 'success';\n\t\t\t\tconst cached = readCache(cacheKey, staleTime);\n\t\t\t\treturn cached?.status ?? 'idle';\n\t\t});\n\t\tconst [error, setError] = useState<unknown>(null);\n\t\tconst [loading, setLoadingState] = useState<false | Exclude<AsyncPreviewLoadingState, false>>(false);\n\t\tconst [meta, setMetaState] = useState<Record<string, unknown>>(() => {\n\t\t\t\tconst cached = readCache(cacheKey, staleTime);\n\t\t\t\treturn cached?.meta ?? {};\n\t\t});\n\t\tconst [cached, setCached] = useState(() => readCache(cacheKey, staleTime) !== undefined);\n\t\tconst resolvedData = hasStaticData ? staticData as TData | null : data;\n\t\tconst resolvedStatus = hasStaticData\n\t\t\t\t? staticData === null ? 'empty' : 'success'\n\t\t\t\t: status;\n\n\t\tconst abortRef = useRef<AbortController | null>(null);\n\t\tconst requestIdRef = useRef(0);\n\t\tconst prefetchedRef = useRef(false);\n\t\tconst metaRef = useRef(meta);\n\t\tconst openRunKeyRef = useRef<string | null>(null);\n\t\tconst activeRunKeyRef = useRef<string | null>(null);\n\n\t\tconst stateRef = useRef<AsyncPreviewState<TData, TContext, TType> | null>(null);\n\n\t\tconst setOpen = useCallback(\n\t\t\t\t(nextOpen: boolean) => {\n\t\t\t\t\t\tif (!isControlled) setUncontrolledOpen(nextOpen);\n\t\t\t\t\t\tconst currentState = stateRef.current;\n\t\t\t\t\t\tif (currentState) {\n\t\t\t\t\t\t\t\tonOpenChange?.(nextOpen, { ...currentState, open: nextOpen });\n\t\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t[isControlled, onOpenChange],\n\t\t);\n\n\t\tconst run = useCallback(\n\t\t\t\tasync (reason: AsyncPreviewReason) => {\n\t\t\t\t\t\tif (hasStaticData || !onShow) return;\n\n\t\t\t\t\t\tconst requestKey = cacheKey ?? type;\n\t\t\t\t\t\tconst activeController = abortRef.current;\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\treason === 'open' &&\n\t\t\t\t\t\t\t\tactiveRunKeyRef.current === requestKey &&\n\t\t\t\t\t\t\t\tactiveController &&\n\t\t\t\t\t\t\t\t!activeController.signal.aborted\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// A cache hit still supersedes work for the previous preview.\n\t\t\t\t\t\tabortRef.current?.abort();\n\t\t\t\t\t\tabortRef.current = null;\n\t\t\t\t\t\tactiveRunKeyRef.current = null;\n\n\t\t\t\t\t\tconst cachedEntry = readCache(cacheKey, staleTime);\n\t\t\t\t\t\tconst canUseCache =\n\t\t\t\t\t\t\t\treason === 'open' &&\n\t\t\t\t\t\t\t\tcachedEntry !== undefined &&\n\t\t\t\t\t\t\t\tcachePolicy === 'cache-first';\n\n\t\t\t\t\t\tif (canUseCache) {\n\t\t\t\t\t\t\t\tsetCached(true);\n\t\t\t\t\t\t\t\tsetError(null);\n\t\t\t\t\t\t\t\tmetaRef.current = cachedEntry.meta;\n\t\t\t\t\t\t\t\tsetMetaState(cachedEntry.meta);\n\t\t\t\t\t\t\t\tsetData(cachedEntry.status === 'success' ? cachedEntry.data as TData : null);\n\t\t\t\t\t\t\t\tsetStatus(cachedEntry.status);\n\t\t\t\t\t\t\t\tsetLoadingState(false);\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst controller = new AbortController();\n\t\t\t\t\t\tabortRef.current = controller;\n\t\t\t\t\t\tactiveRunKeyRef.current = requestKey;\n\t\t\t\t\t\tconst requestId = requestIdRef.current + 1;\n\t\t\t\t\t\trequestIdRef.current = requestId;\n\t\t\t\t\t\tconst hadCache = cachedEntry !== undefined;\n\n\t\t\t\t\t\tsetCached(false);\n\t\t\t\t\t\tsetError(null);\n\t\t\t\t\t\tsetStatus('loading');\n\t\t\t\t\t\tsetLoadingState({ label: undefined });\n\n\t\t\t\t\t\tconst loadingState = stateRef.current\n\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\t\t...stateRef.current,\n\t\t\t\t\t\t\t\t\t\t\t\terror: null,\n\t\t\t\t\t\t\t\t\t\t\t\tloading: { label: undefined },\n\t\t\t\t\t\t\t\t\t\t\t\tstatus: 'loading' as const,\n\t\t\t\t\t\t\t\t\t\t\t\tcached: false,\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t: null;\n\n\t\t\t\t\t\tif (loadingState) onBeforeShow?.(loadingState);\n\t\t\t\t\t\tif (reason === 'refresh') {\n\t\t\t\t\t\t\t\tif (loadingState) onRefresh?.(loadingState);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst applyIfCurrent = (fn: () => void) => {\n\t\t\t\t\t\t\t\tif (requestIdRef.current !== requestId || controller.signal.aborted) return;\n\t\t\t\t\t\t\t\tfn();\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst result = await onShow({\n\t\t\t\t\t\t\t\t\t\ttype,\n\t\t\t\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t\t\t\t\t\t\treason,\n\t\t\t\t\t\t\t\t\t\tcached: hadCache,\n\t\t\t\t\t\t\t\t\t\tsetLoading: (nextLoading) =>\n\t\t\t\t\t\t\t\t\t\t\t\tapplyIfCurrent(() => setLoadingState(normalizeLoading(nextLoading))),\n\t\t\t\t\t\t\t\t\t\tsetMeta: (nextMeta) =>\n\t\t\t\t\t\t\t\t\t\t\t\tapplyIfCurrent(() => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst next = { ...metaRef.current, ...nextMeta };\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tmetaRef.current = next;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetMetaState(next);\n\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\tapplyIfCurrent(() => {\n\t\t\t\t\t\t\t\t\t\tconst nextStatus: Extract<AsyncPreviewStatus, 'empty' | 'success'> =\n\t\t\t\t\t\t\t\t\t\t\t\tresult === null || result === undefined ? 'empty' : 'success';\n\t\t\t\t\t\t\t\t\t\tconst nextData = nextStatus === 'success' ? result as TData : null;\n\t\t\t\t\t\t\t\t\t\tsetData(nextData);\n\t\t\t\t\t\t\t\t\t\tsetStatus(nextStatus);\n\t\t\t\t\t\t\t\t\t\tsetLoadingState(false);\n\t\t\t\t\t\t\t\t\t\tsetError(null);\n\t\t\t\t\t\t\t\t\t\tsetCached(false);\n\n\t\t\t\t\t\t\t\t\t\tif (cacheKey) {\n\t\t\t\t\t\t\t\t\t\t\t\tasyncPreviewCache.set(cacheKey, {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata: nextData,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tstatus: nextStatus,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tmeta: metaRef.current,\n\t\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tconst settledState = stateRef.current\n\t\t\t\t\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t...stateRef.current,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata: nextData,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\terror: null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tloading: false as const,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstatus: nextStatus,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tmeta: metaRef.current,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcached: false,\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t: null;\n\n\t\t\t\t\t\t\t\t\t\tif (nextData !== null && settledState) {\n\t\t\t\t\t\t\t\t\t\t\t\tonData?.(nextData, settledState);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tif (settledState) onSettled?.(settledState);\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\tif (controller.signal.aborted) return;\n\t\t\t\t\t\t\t\tapplyIfCurrent(() => {\n\t\t\t\t\t\t\t\t\t\tsetError(err);\n\t\t\t\t\t\t\t\t\t\tsetStatus('error');\n\t\t\t\t\t\t\t\t\t\tsetLoadingState(false);\n\t\t\t\t\t\t\t\t\t\tconst settledState = stateRef.current\n\t\t\t\t\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t...stateRef.current,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\terror: err,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tloading: false as const,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstatus: 'error' as const,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcached: false,\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t: null;\n\t\t\t\t\t\t\t\t\t\tif (settledState) onError?.(err, settledState);\n\t\t\t\t\t\t\t\t\t\tif (settledState) onSettled?.(settledState);\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t\tif (requestIdRef.current === requestId) {\n\t\t\t\t\t\t\t\t\t\tif (abortRef.current === controller) abortRef.current = null;\n\t\t\t\t\t\t\t\t\t\tif (activeRunKeyRef.current === requestKey) activeRunKeyRef.current = null;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t[\n\t\t\t\t\t\tcacheKey,\n\t\t\t\t\t\tcachePolicy,\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\thasStaticData,\n\t\t\t\t\t\tonBeforeShow,\n\t\t\t\t\t\tonData,\n\t\t\t\t\t\tonError,\n\t\t\t\t\t\tonRefresh,\n\t\t\t\t\t\tonSettled,\n\t\t\t\t\t\tonShow,\n\t\t\t\t\t\tstaleTime,\n\t\t\t\t\t\ttype,\n\t\t\t\t],\n\t\t);\n\n\t\tconst refresh = useCallback(() => {\n\t\t\t\tvoid run('refresh');\n\t\t}, [run]);\n\n\t\tconst prefetch = useCallback(() => {\n\t\t\t\tif (hasStaticData) return;\n\t\t\t\tif (prefetchedRef.current) return;\n\t\t\t\tprefetchedRef.current = true;\n\t\t\t\tvoid run('prefetch');\n\t\t}, [hasStaticData, run]);\n\n\t\tconst close = useCallback(() => {\n\t\t\t\tsetOpen(false);\n\t\t}, [setOpen]);\n\n\t\tconst state = useMemo<AsyncPreviewState<TData, TContext, TType>>(\n\t\t\t\t() => ({\n\t\t\t\t\t\ttype,\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\tdata: resolvedData,\n\t\t\t\t\t\terror,\n\t\t\t\t\t\tloading,\n\t\t\t\t\t\tstatus: resolvedStatus,\n\t\t\t\t\t\tmeta,\n\t\t\t\t\t\topen,\n\t\t\t\t\t\tcached,\n\t\t\t\t\t\trefresh,\n\t\t\t\t\t\tprefetch,\n\t\t\t\t\t\tclose,\n\t\t\t\t}),\n\t\t\t\t[cached, close, context, error, loading, meta, open, prefetch, refresh, resolvedData, resolvedStatus, type],\n\t\t);\n\t\tstateRef.current = state;\n\t\tmetaRef.current = meta;\n\n\t\tuseEffect(() => {\n\t\t\t\tif (!hasStaticData) return;\n\t\t\t\tabortRef.current?.abort();\n\t\t\t\tabortRef.current = null;\n\t\t\t\tactiveRunKeyRef.current = null;\n\t\t\t\topenRunKeyRef.current = null;\n\t\t\t\tsetError(null);\n\t\t\t\tsetLoadingState(false);\n\t\t\t\tsetCached(false);\n\t\t}, [hasStaticData, staticData]);\n\n\t\tuseEffect(() => {\n\t\t\t\tif (!open) {\n\t\t\t\t\t\topenRunKeyRef.current = null;\n\t\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (hasStaticData) return;\n\n\t\t\t\tconst openRunKey = cacheKey ?? type;\n\t\t\t\tif (openRunKeyRef.current === openRunKey) return;\n\t\t\t\topenRunKeyRef.current = openRunKey;\n\t\t\t\tvoid run('open');\n\t\t}, [cacheKey, hasStaticData, open, run, type]);\n\n\t\tuseEffect(() => {\n\t\t\t\tprefetchedRef.current = false;\n\t\t}, [cacheKey, hasStaticData, type]);\n\n\t\tuseEffect(\n\t\t\t\t() => () => {\n\t\t\t\t\t\tabortRef.current?.abort();\n\t\t\t\t},\n\t\t\t\t[],\n\t\t);\n\n\t\treturn { ...state, setOpen };\n}\n\nexport function clearAsyncPreviewCache(cacheKey?: string) {\n\t\tif (cacheKey) {\n\t\t\t\tasyncPreviewCache.delete(cacheKey);\n\t\t\t\treturn;\n\t\t}\n\t\tasyncPreviewCache.clear();\n}\n","/**\n * AsyncPreview — generic lazy preview popover for table cells, inline values,\n * buttons, badges, or any other trigger.\n *\n * The library owns popover chrome, async state, abort/race protection, cache,\n * loading/error/empty defaults, and composition primitives. Consumers own the\n * fetcher, routing callbacks, telemetry, and domain rendering.\n */\nimport {\n\t\tcreateContext,\n\t\tuseContext,\n} from 'react';\n\nimport { Button } from '../../base/buttons';\nimport { ErrorState, LoadingState } from '../../base/feedback';\nimport { EmptyState } from '../../blocks/data-display';\nimport {\n\t\tPopover,\n\t\tPopoverContent,\n\t\tPopoverTrigger,\n} from '../../base/popover';\nimport { useStrings } from '../../../lib/strings';\nimport { cn } from '../../../lib/utils';\n\nimport {\n\t\tdefaultAsyncPreviewStrings,\n\t\ttype AsyncPreviewStrings,\n} from './async-preview.strings';\nimport type {\n\t\tAsyncPreviewBodyProps,\n\t\tAsyncPreviewContentProps,\n\t\tAsyncPreviewEmptyProps,\n\t\tAsyncPreviewErrorProps,\n\t\tAsyncPreviewLoadingProps,\n\t\tAsyncPreviewRootProps,\n\t\tAsyncPreviewState as AsyncPreviewStateValue,\n\t\tAsyncPreviewStateProps,\n\t\tAsyncPreviewTriggerProps,\n} from './async-preview.types';\nimport { useAsyncPreview } from './hooks/use-async-preview';\n\ninterface AsyncPreviewContextValue<TData, TContext, TType extends string> {\n\t\tstate: AsyncPreviewStateValue<TData, TContext, TType>;\n\t\tsetOpen: (open: boolean) => void;\n\t\t/** Overrides this surface's own copy. */\n\t\tstrings: AsyncPreviewStrings;\n\t\tprefetchOn: false | 'hover' | 'focus';\n}\n\nconst AsyncPreviewContext =\n\t\tcreateContext<AsyncPreviewContextValue<unknown, unknown, string> | null>(null);\n\nfunction useAsyncPreviewContext<\n\t\tTData = unknown,\n\t\tTContext = unknown,\n\t\tTType extends string = string,\n>(): AsyncPreviewContextValue<TData, TContext, TType> {\n\t\tconst ctx = useContext(AsyncPreviewContext);\n\t\tif (!ctx) {\n\t\t\t\tthrow new Error('AsyncPreview compound parts must be rendered inside <AsyncPreview.Root>.');\n\t\t}\n\t\treturn ctx as AsyncPreviewContextValue<TData, TContext, TType>;\n}\n\nfunction AsyncPreviewRoot<\n\t\tTData,\n\t\tTContext = unknown,\n\t\tTType extends string = string,\n>({\n\t\tchildren,\n\t\tstrings: stringsProp,\n\t\tprefetchOn = false,\n\t\t...options\n}: AsyncPreviewRootProps<TData, TContext, TType>) {\n\t\tconst strings = useStrings(defaultAsyncPreviewStrings, stringsProp);\n\t\tconst preview = useAsyncPreview<TData, TContext, TType>(options);\n\t\tconst state: AsyncPreviewStateValue<TData, TContext, TType> = {\n\t\t\t\ttype: preview.type,\n\t\t\t\tcontext: preview.context,\n\t\t\t\tdata: preview.data,\n\t\t\t\terror: preview.error,\n\t\t\t\tloading: preview.loading,\n\t\t\t\tstatus: preview.status,\n\t\t\t\tmeta: preview.meta,\n\t\t\t\topen: preview.open,\n\t\t\t\tcached: preview.cached,\n\t\t\t\trefresh: preview.refresh,\n\t\t\t\tprefetch: preview.prefetch,\n\t\t\t\tclose: () => preview.setOpen(false),\n\t\t};\n\n\t\treturn (\n\t\t\t\t<AsyncPreviewContext.Provider\n\t\t\t\t\t\tvalue={{\n\t\t\t\t\t\t\t\tstate: state as AsyncPreviewStateValue<unknown, unknown, string>,\n\t\t\t\t\t\t\t\tsetOpen: preview.setOpen,\n\t\t\t\t\t\t\t\tstrings,\n\t\t\t\t\t\t\t\tprefetchOn,\n\t\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t\t<span className=\"async-preview--component contents\">\n\t\t\t\t\t\t\t\t<Popover open={state.open} onOpenChange={preview.setOpen}>\n\t\t\t\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t\t\t</Popover>\n\t\t\t\t\t\t</span>\n\t\t\t\t</AsyncPreviewContext.Provider>\n\t\t);\n}\n\nfunction AsyncPreviewTrigger<\n\t\tTData = unknown,\n\t\tTContext = unknown,\n\t\tTType extends string = string,\n>({ render, children }: AsyncPreviewTriggerProps<TData, TContext, TType>) {\n\t\tconst { state, prefetchOn } = useAsyncPreviewContext<TData, TContext, TType>();\n\t\tconst maybePrefetch = () => {\n\t\t\t\tif (prefetchOn) state.prefetch();\n\t\t};\n\t\tconst triggerProps = {\n\t\t\t\t'aria-busy': state.status === 'loading' ? true as const : undefined,\n\t\t\t\t'data-state': state.open ? 'open' as const : 'closed' as const,\n\t\t\t\t'data-loading': state.status === 'loading' ? true as const : undefined,\n\t\t\t\tonPointerEnter: prefetchOn === 'hover' ? maybePrefetch : undefined,\n\t\t\t\tonFocus: prefetchOn === 'focus' ? maybePrefetch : undefined,\n\t\t};\n\n\t\tif (render) {\n\t\t\t\tconst renderedTrigger = typeof render === 'function'\n\t\t\t\t\t\t? render({ state, triggerProps })\n\t\t\t\t\t\t: render;\n\t\t\t\treturn (\n\t\t\t\t\t\t<PopoverTrigger\n\t\t\t\t\t\t\t\trender={renderedTrigger}\n\t\t\t\t\t\t\t\t{...triggerProps}\n\t\t\t\t\t\t/>\n\t\t\t\t);\n\t\t}\n\n\t\treturn (\n\t\t\t\t<PopoverTrigger\n\t\t\t\t\t\trender={\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t{...triggerProps}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t}\n\t\t\t\t/>\n\t\t);\n}\n\nfunction AsyncPreviewContent({\n\t\tclassName,\n\t\tchildren,\n\t\talign = 'start',\n\t\tsideOffset = 8,\n\t\tfinalFocus = true,\n\t\t...props\n}: AsyncPreviewContentProps) {\n\t\tconst { state } = useAsyncPreviewContext();\n\t\tconst { size = 'md', padding = 'none', ...contentProps } = props;\n\t\tconst sizeClassName = {\n\t\t\t\tsm: 'w-72',\n\t\t\t\tmd: 'w-80',\n\t\t\t\tlg: 'w-90',\n\t\t}[size];\n\t\tconst inset = ({\n\t\t\t\tnone: 'flush',\n\t\t\t\tsm: 'compact',\n\t\t\t\tmd: 'default',\n\t\t\t\tlg: 'flush',\n\t\t} as const)[padding];\n\t\tconst paddingClassName = padding === 'none'\n\t\t\t\t? 'gap-0'\n\t\t\t\t: undefined;\n\n\t\treturn (\n\t\t\t\t<PopoverContent\n\t\t\t\t\t\talign={align}\n\t\t\t\t\t\tsideOffset={sideOffset}\n\t\t\t\t\t\tfinalFocus={finalFocus}\n\t\t\t\t\t\tinset={inset}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t'async-preview--content max-w-[calc(100vw-2rem)] overflow-hidden',\n\t\t\t\t\t\t\t\tsizeClassName,\n\t\t\t\t\t\t\t\tpaddingClassName,\n\t\t\t\t\t\t\t\tclassName,\n\t\t\t\t\t\t)}\n\t\t\t\t\t\tdata-status={state.status}\n\t\t\t\t\t\tdata-preview-type={state.type}\n\t\t\t\t\t\t{...contentProps}\n\t\t\t\t>\n\t\t\t\t\t\t{padding === 'lg' ? <div className=\"p-surface-lg\">{children}</div> : children}\n\t\t\t\t</PopoverContent>\n\t\t);\n}\n\nfunction AsyncPreviewState<\n\t\tTData = unknown,\n\t\tTContext = unknown,\n\t\tTType extends string = string,\n>({ children }: AsyncPreviewStateProps<TData, TContext, TType>) {\n\t\tconst { state } = useAsyncPreviewContext<TData, TContext, TType>();\n\t\treturn <>{children(state)}</>;\n}\n\nfunction AsyncPreviewBody<\n\t\tTData = unknown,\n\t\tTContext = unknown,\n\t\tTType extends string = string,\n>({ children }: AsyncPreviewBodyProps<TData, TContext, TType>) {\n\t\tconst { state } = useAsyncPreviewContext<TData, TContext, TType>();\n\t\tif (state.status !== 'success' || state.data === null) return null;\n\t\treturn <>{children({ ...state, data: state.data })}</>;\n}\n\nfunction AsyncPreviewLoading<\n\t\tTData = unknown,\n\t\tTContext = unknown,\n\t\tTType extends string = string,\n>({ children, className }: AsyncPreviewLoadingProps<TData, TContext, TType>) {\n\t\tconst { state, strings } = useAsyncPreviewContext<TData, TContext, TType>();\n\t\tif (state.status !== 'loading') return null;\n\t\tif (children) return <>{children(state)}</>;\n\t\tconst label =\n\t\t\t\ttypeof state.loading === 'object' && state.loading !== null\n\t\t\t\t\t\t? state.loading.label\n\t\t\t\t\t\t: undefined;\n\t\tconst phase =\n\t\t\t\ttypeof state.loading === 'object' && state.loading !== null\n\t\t\t\t\t\t? state.loading.phase\n\t\t\t\t\t\t: undefined;\n\t\tconst progress =\n\t\t\t\ttypeof state.loading === 'object' &&\n\t\t\t\tstate.loading !== null &&\n\t\t\t\ttypeof state.loading.progress === 'number'\n\t\t\t\t\t\t? Math.min(100, Math.max(0, state.loading.progress))\n\t\t\t\t\t\t: undefined;\n\n\t\treturn (\n\t\t\t\t<LoadingState\n\t\t\t\t\t\tclassName={cn('async-preview--loading p-surface', className)}\n\t\t\t\t\t\tvariant=\"panel\"\n\t\t\t\t\t\tlabel={label ?? strings.loading}\n\t\t\t\t\t\tdescription={phase}\n\t\t\t\t\t\tprogress={progress}\n\t\t\t\t\t\tskeleton\n\t\t\t\t\t\tlines={3}\n\t\t\t\t/>\n\t\t);\n}\n\nfunction AsyncPreviewError<\n\t\tTData = unknown,\n\t\tTContext = unknown,\n\t\tTType extends string = string,\n>({ children, className }: AsyncPreviewErrorProps<TData, TContext, TType>) {\n\t\tconst { state, strings } = useAsyncPreviewContext<TData, TContext, TType>();\n\t\tif (state.status !== 'error') return null;\n\t\tif (children) return <>{children(state)}</>;\n\t\treturn (\n\t\t\t\t<ErrorState\n\t\t\t\t\t\tclassName={cn('async-preview--error p-surface', className)}\n\t\t\t\t\t\ttitle={strings.errorTitle}\n\t\t\t\t\t\tdescription={strings.errorDescription}\n\t\t\t\t\t\tonRetry={state.refresh}\n\t\t\t\t\t\tretryLabel={strings.retry}\n\t\t\t\t\t\tvariant=\"inline\"\n\t\t\t\t/>\n\t\t);\n}\n\nfunction AsyncPreviewEmpty<\n\t\tTData = unknown,\n\t\tTContext = unknown,\n\t\tTType extends string = string,\n>({ children, className }: AsyncPreviewEmptyProps<TData, TContext, TType>) {\n\t\tconst { state, strings } = useAsyncPreviewContext<TData, TContext, TType>();\n\t\tif (state.status !== 'empty') return null;\n\t\tif (children) return <>{children(state)}</>;\n\t\treturn (\n\t\t\t\t<EmptyState\n\t\t\t\t\t\tclassName={cn('async-preview--empty', className)}\n\t\t\t\t\t\tpadding=\"md\"\n\t\t\t\t\t\ttitle={strings.emptyTitle}\n\t\t\t\t\t\tdescription={strings.emptyDescription}\n\t\t\t\t/>\n\t\t);\n}\n\nfunction createAsyncPreview<\n\t\tTData,\n\t\tTContext = unknown,\n\t\tTType extends string = string,\n>() {\n\t\treturn {\n\t\t\t\tRoot: AsyncPreviewRoot<TData, TContext, TType>,\n\t\t\t\tTrigger: AsyncPreviewTrigger<TData, TContext, TType>,\n\t\t\t\tContent: AsyncPreviewContent,\n\t\t\t\tState: AsyncPreviewState<TData, TContext, TType>,\n\t\t\t\tBody: AsyncPreviewBody<TData, TContext, TType>,\n\t\t\t\tLoading: AsyncPreviewLoading<TData, TContext, TType>,\n\t\t\t\tError: AsyncPreviewError<TData, TContext, TType>,\n\t\t\t\tEmpty: AsyncPreviewEmpty<TData, TContext, TType>,\n\t\t};\n}\n\nconst AsyncPreview = {\n\t\tRoot: AsyncPreviewRoot,\n\t\tTrigger: AsyncPreviewTrigger,\n\t\tContent: AsyncPreviewContent,\n\t\tState: AsyncPreviewState,\n\t\tBody: AsyncPreviewBody,\n\t\tLoading: AsyncPreviewLoading,\n\t\tError: AsyncPreviewError,\n\t\tEmpty: AsyncPreviewEmpty,\n};\n\nAsyncPreviewRoot.displayName = 'AsyncPreviewRoot';\nAsyncPreviewTrigger.displayName = 'AsyncPreviewTrigger';\nAsyncPreviewContent.displayName = 'AsyncPreviewContent';\nAsyncPreviewState.displayName = 'AsyncPreviewState';\nAsyncPreviewBody.displayName = 'AsyncPreviewBody';\nAsyncPreviewLoading.displayName = 'AsyncPreviewLoading';\nAsyncPreviewError.displayName = 'AsyncPreviewError';\nAsyncPreviewEmpty.displayName = 'AsyncPreviewEmpty';\n\nexport {\n\t\tAsyncPreview,\n\t\tAsyncPreviewRoot,\n\t\tAsyncPreviewTrigger,\n\t\tAsyncPreviewContent,\n\t\tAsyncPreviewState,\n\t\tAsyncPreviewBody,\n\t\tAsyncPreviewLoading,\n\t\tAsyncPreviewError,\n\t\tAsyncPreviewEmpty,\n\t\tcreateAsyncPreview,\n\t\tuseAsyncPreviewContext,\n};\n","/**\n * PreviewTriggerCell — table-cell trigger chrome for AsyncPreview.\n *\n * It renders a button only when preview interaction exists. Empty, disabled,\n * or explicitly non-previewable values keep the same table rhythm without a\n * caret, pointer cursor, popup ARIA, or trigger padding that implies action.\n */\nimport { ChevronDown, type LucideIcon } from 'lucide-react';\nimport React, { type ReactNode } from 'react';\n\nimport { Badge, type BadgeProps } from '../../base/badge';\nimport { Button } from '../../base/buttons';\nimport { Stack } from '../../base/structure';\nimport {\n\tEmptyValue,\n\tName,\n\tSecondaryValue,\n\tValue,\n} from '../../primitives';\nimport { cn } from '../../../lib/utils';\n\ntype PreviewTriggerCellRootProps = Omit<\n\tReact.ButtonHTMLAttributes<HTMLButtonElement>,\n\t'children' | 'disabled' | 'name' | 'value'\n>;\n\nexport interface PreviewTriggerCellProps extends PreviewTriggerCellRootProps {\n\t/** Primary text of the cell. */\n\tvalue?: ReactNode | null;\n\t/** Display name. */\n\tname?: string | null;\n\t/** Supporting text under the value. */\n\tsecondary?: ReactNode | null;\n\t/** Content before the value. */\n\tleading?: ReactNode;\n\t/** Content after the value. */\n\ttrailing?: ReactNode;\n\t/** Chip rendered beside the label. */\n\tbadge?: ReactNode | { label: ReactNode; tone?: BadgeProps['tone']; size?: BadgeProps['size'] };\n\t/** Leading glyph. */\n\ticon?: LucideIcon;\n\t/** Copy shown when the value is empty. */\n\temptyLabel?: ReactNode;\n\t/** Whether this row has a preview to open. */\n\thasPreview?: boolean;\n\t/** Explains why the preview is unavailable, shown as a tooltip. */\n\tdisabledReason?: ReactNode;\n\t/** Applies name casing to the value regardless of how it arrives. */\n\tforceNameCase?: boolean;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n\t/** Merged onto the content. */\n\tcontentClassName?: string;\n}\n\nfunction isEmpty(value: ReactNode | null | undefined) {\n\treturn value === null || value === undefined || value === '';\n}\n\nfunction renderBadge(badge: PreviewTriggerCellProps['badge']) {\n\tif (!badge) return null;\n\tif (typeof badge === 'object' && !Array.isArray(badge) && 'label' in badge) {\n\t\treturn (\n\t\t\t<Badge inline tone={badge.tone ?? 'secondary'} size={badge.size}>\n\t\t\t\t{badge.label}\n\t\t\t</Badge>\n\t\t);\n\t}\n\treturn badge;\n}\n\nfunction PreviewTriggerCellInner({\n\tvalue,\n\tname,\n\tsecondary,\n\tleading,\n\ttrailing,\n\tbadge,\n\ticon: Icon,\n\temptyLabel = '--',\n\tforceNameCase,\n\tcontentClassName,\n}: PreviewTriggerCellProps) {\n\tconst primaryIsEmpty = isEmpty(name) && isEmpty(value);\n\treturn (\n\t\t<Stack render={<span />} direction=\"horizontal\" gap=\"sm\" wrap={false} className={cn('preview-trigger-cell--inner', contentClassName)}>\n\t\t\t{!!leading && <span className=\"preview-trigger-cell--leading inline-flex shrink-0 items-center\">{leading}</span>}\n\t\t\t{!!Icon && (\n\t\t\t\t<span className=\"preview-trigger-cell--icon inline-flex shrink-0 items-center text-muted-foreground\">\n\t\t\t\t\t<Icon className=\"size-icon-sm\" aria-hidden />\n\t\t\t\t</span>\n\t\t\t)}\n\t\t\t<span className=\"preview-trigger-cell--content flex min-w-0 flex-1 flex-col items-start\">\n\t\t\t\t<Stack render={<span />} direction=\"horizontal\" gap=\"sm\" wrap={false} className=\"max-w-full\">\n\t\t\t\t\t{primaryIsEmpty ? (\n\t\t\t\t\t\t<EmptyValue className=\"truncate\">\n\t\t\t\t\t\t\t{emptyLabel}\n\t\t\t\t\t\t</EmptyValue>\n\t\t\t\t\t) : name ? (\n\t\t\t\t\t\t<Name\n\t\t\t\t\t\t\tvalue={name}\n\t\t\t\t\t\t\tforce={forceNameCase}\n\t\t\t\t\t\t\tweight=\"medium\"\n\t\t\t\t\t\t\tclassName=\"truncate\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<Value weight=\"medium\" className=\"truncate\">\n\t\t\t\t\t\t\t{value}\n\t\t\t\t\t\t</Value>\n\t\t\t\t\t)}\n\t\t\t\t\t{renderBadge(badge)}\n\t\t\t\t</Stack>\n\t\t\t\t{!isEmpty(secondary) && (\n\t\t\t\t\t<SecondaryValue size=\"xs\" className=\"max-w-full truncate\">\n\t\t\t\t\t\t{secondary}\n\t\t\t\t\t</SecondaryValue>\n\t\t\t\t)}\n\t\t\t</span>\n\t\t\t{!!trailing && <span className=\"preview-trigger-cell--trailing inline-flex shrink-0 items-center\">{trailing}</span>}\n\t\t</Stack>\n\t);\n}\n\nexport const PreviewTriggerCell = React.forwardRef<HTMLButtonElement, PreviewTriggerCellProps>(function PreviewTriggerCell({\n\tvalue,\n\tname,\n\tsecondary,\n\tleading,\n\ttrailing,\n\tbadge,\n\ticon,\n\temptyLabel,\n\thasPreview,\n\tdisabledReason,\n\tforceNameCase,\n\tclassName,\n\tcontentClassName,\n\ttype,\n\t...rootProps\n}, ref) {\n\tconst cellProps = {\n\t\tvalue,\n\t\tname,\n\t\tsecondary,\n\t\tleading,\n\t\ttrailing,\n\t\tbadge,\n\t\ticon,\n\t\temptyLabel,\n\t\tforceNameCase,\n\t\tcontentClassName,\n\t};\n\tconst previewable =\n\t\thasPreview ?? (!isEmpty(name) || !isEmpty(value));\n\tconst interactive = previewable && !disabledReason;\n\n\tif (!interactive) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'preview-trigger-cell--component flex h-auto min-h-action-sm max-w-full items-center justify-start rounded-radius px-control-sm py-space-xs text-left',\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\taria-disabled={disabledReason ? true : undefined}\n\t\t\t\ttitle={typeof disabledReason === 'string' ? disabledReason : undefined}\n\t\t\t>\n\t\t\t\t<PreviewTriggerCellInner {...cellProps} />\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<Button\n\t\t\t{...rootProps}\n\t\t\tref={ref}\n\t\t\ttype={type ?? 'button'}\n\t\t\ttone=\"secondary\"\n\t\t\tbuttonStyle=\"ghost\"\n\t\t\tsize=\"sm\"\n\t\t\tclassName={cn(\n\t\t\t\t'preview-trigger-cell--component h-auto min-h-action-sm max-w-full justify-start px-control-sm py-space-xs text-left',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t<PreviewTriggerCellInner {...cellProps} />\n\t\t\t<ChevronDown className=\"preview-trigger-cell--caret size-icon-sm shrink-0 text-muted-foreground\" aria-hidden />\n\t\t</Button>\n\t);\n});\n\nPreviewTriggerCell.displayName = 'PreviewTriggerCell';\n"],"mappings":"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"}
1
+ {"version":3,"file":"async-preview.js","names":["_Fragment","Button","Stack","LoadingState","ErrorState","Value","Name","SecondaryValue","EmptyValue","Badge","PopoverTrigger","Popover","PopoverContent","EmptyState","React","Fragment$1","defaultAsyncPreviewStrings","asyncPreviewCache","readCache","cacheKey","cached","staleTime","normalizeLoading","loading","hasStaticDataSource","options","useAsyncPreview","openProp","hasStaticData","staticData","onShow","isControlled","uncontrolledOpen","setUncontrolledOpen","useState","defaultOpen","open","data","setData","status","setStatus","error","setError","setLoadingState","meta","setMetaState","setCached","resolvedData","resolvedStatus","abortRef","useRef","requestIdRef","prefetchedRef","metaRef","openRunKeyRef","activeRunKeyRef","stateRef","setOpen","useCallback","nextOpen","currentState","onOpenChange","run","requestKey","type","activeController","reason","cachedEntry","cachePolicy","controller","requestId","hadCache","loadingState","onBeforeShow","onRefresh","applyIfCurrent","fn","result","nextLoading","next","nextMeta","nextStatus","nextData","settledState","onData","onSettled","err","onError","context","refresh","prefetch","close","state","useMemo","useEffect","openRunKey","clearAsyncPreviewCache","AsyncPreviewContext","createContext","useAsyncPreviewContext","ctx","useContext","AsyncPreviewRoot","stringsProp","strings","useStrings","preview","AsyncPreviewTrigger","maybePrefetch","prefetchOn","triggerProps","render","renderedTrigger","AsyncPreviewContent","props","contentProps","sizeClassName","size","inset","padding","cn","className","children","AsyncPreviewState","AsyncPreviewBody","AsyncPreviewLoading","label","phase","progress","AsyncPreviewError","AsyncPreviewEmpty","createAsyncPreview","AsyncPreview","isEmpty","value","renderBadge","badge","PreviewTriggerCellInner","Icon","primaryIsEmpty","name","contentClassName","leading","emptyLabel","forceNameCase","secondary","trailing","PreviewTriggerCell","rootProps","cellProps","hasPreview","disabledReason","ChevronDown"],"sources":["../../src/components/features/async-preview/async-preview.strings.ts","../../src/components/features/async-preview/hooks/use-async-preview.ts","../../src/components/features/async-preview/async-preview.tsx","../../src/components/features/async-preview/preview-trigger-cell.tsx"],"sourcesContent":["/**\n * Strings for AsyncPreview. Consumers override with `strings={{ ... }}` on\n * `<AsyncPreview.Root />`; all user-facing copy is deep-merged via\n * `useStrings`.\n */\nexport interface AsyncPreviewStrings {\n\tloading: string;\n\terrorTitle: string;\n\terrorDescription: string;\n\tretry: string;\n\temptyTitle: string;\n\temptyDescription: string;\n}\n\nexport const defaultAsyncPreviewStrings: AsyncPreviewStrings = {\n\tloading: 'Loading preview...',\n\terrorTitle: 'Could not load preview',\n\terrorDescription: 'Try again or open the full record.',\n\tretry: 'Retry',\n\temptyTitle: 'No preview data',\n\temptyDescription: 'There is nothing to show for this record yet.',\n};\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport type {\n\t\tAsyncPreviewLoadingState,\n\t\tAsyncPreviewReason,\n\t\tAsyncPreviewRootProps,\n\t\tAsyncPreviewState,\n\t\tAsyncPreviewStatus,\n} from '../async-preview.types';\n\ninterface CacheEntry {\n\t\t/** Formatted time for the entry. */\n\t\ttimestamp: number;\n\t\t/** Records to render. */\n\t\tdata: unknown | null;\n\t\tstatus: 'success' | 'empty';\n\t\tmeta: Record<string, unknown>;\n}\n\nconst asyncPreviewCache = new Map<string, CacheEntry>();\n\nfunction readCache(cacheKey: string | undefined, staleTime: number): CacheEntry | undefined {\n\t\tif (!cacheKey) return undefined;\n\t\tconst cached = asyncPreviewCache.get(cacheKey);\n\t\tif (!cached) return undefined;\n\t\tif (Date.now() - cached.timestamp > staleTime) {\n\t\t\t\tasyncPreviewCache.delete(cacheKey);\n\t\t\t\treturn undefined;\n\t\t}\n\t\treturn cached;\n}\n\nfunction normalizeLoading(\n\t\tloading: AsyncPreviewLoadingState,\n): false | Exclude<AsyncPreviewLoadingState, false> {\n\t\treturn loading === false ? false : loading;\n}\n\nfunction hasStaticDataSource<\n\t\tTData,\n\t\tTContext,\n\t\tTType extends string,\n>(options: UseAsyncPreviewOptions<TData, TContext, TType>) {\n\t\treturn Object.prototype.hasOwnProperty.call(options, 'data');\n}\n\nexport interface UseAsyncPreviewOptions<\n\t\tTData,\n\t\tTContext = unknown,\n\t\tTType extends string = string,\n> extends Omit<AsyncPreviewRootProps<TData, TContext, TType>, 'children' | 'strings'> {}\n\nexport type UseAsyncPreviewReturn<\n\t\tTData,\n\t\tTContext = unknown,\n\t\tTType extends string = string,\n> = AsyncPreviewState<TData, TContext, TType> & {\n\t\tsetOpen: (open: boolean) => void;\n};\n\nexport function useAsyncPreview<\n\t\tTData,\n\t\tTContext = unknown,\n\t\tTType extends string = string,\n>(options: UseAsyncPreviewOptions<TData, TContext, TType>): UseAsyncPreviewReturn<TData, TContext, TType> {\n\t\tconst {\n\t\t\t\ttype,\n\t\t\t\tcontext,\n\t\t\t\tcacheKey,\n\t\t\t\tcachePolicy = 'cache-first',\n\t\t\t\tstaleTime = 300_000,\n\t\t\t\topen: openProp,\n\t\t\t\tdefaultOpen = false,\n\t\t\t\tonOpenChange,\n\t\t\t\tonBeforeShow,\n\t\t\t\tonData,\n\t\t\t\tonError,\n\t\t\t\tonSettled,\n\t\t\t\tonRefresh,\n\t\t} = options;\n\t\tconst hasStaticData = hasStaticDataSource(options);\n\t\tconst staticData = hasStaticData ? options.data ?? null : null;\n\t\tconst onShow = hasStaticData ? undefined : options.onShow;\n\n\t\tconst isControlled = openProp !== undefined;\n\t\tconst [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n\t\tconst open = openProp ?? uncontrolledOpen;\n\n\t\tconst [data, setData] = useState<TData | null>(() => {\n\t\t\t\tif (hasStaticData) return staticData as TData | null;\n\t\t\t\tconst cached = readCache(cacheKey, staleTime);\n\t\t\t\treturn cached?.status === 'success' ? cached.data as TData : null;\n\t\t});\n\t\tconst [status, setStatus] = useState<AsyncPreviewStatus>(() => {\n\t\t\t\tif (hasStaticData) return staticData === null ? 'empty' : 'success';\n\t\t\t\tconst cached = readCache(cacheKey, staleTime);\n\t\t\t\treturn cached?.status ?? 'idle';\n\t\t});\n\t\tconst [error, setError] = useState<unknown>(null);\n\t\tconst [loading, setLoadingState] = useState<false | Exclude<AsyncPreviewLoadingState, false>>(false);\n\t\tconst [meta, setMetaState] = useState<Record<string, unknown>>(() => {\n\t\t\t\tconst cached = readCache(cacheKey, staleTime);\n\t\t\t\treturn cached?.meta ?? {};\n\t\t});\n\t\tconst [cached, setCached] = useState(() => readCache(cacheKey, staleTime) !== undefined);\n\t\tconst resolvedData = hasStaticData ? staticData as TData | null : data;\n\t\tconst resolvedStatus = hasStaticData\n\t\t\t\t? staticData === null ? 'empty' : 'success'\n\t\t\t\t: status;\n\n\t\tconst abortRef = useRef<AbortController | null>(null);\n\t\tconst requestIdRef = useRef(0);\n\t\tconst prefetchedRef = useRef(false);\n\t\tconst metaRef = useRef(meta);\n\t\tconst openRunKeyRef = useRef<string | null>(null);\n\t\tconst activeRunKeyRef = useRef<string | null>(null);\n\n\t\tconst stateRef = useRef<AsyncPreviewState<TData, TContext, TType> | null>(null);\n\n\t\tconst setOpen = useCallback(\n\t\t\t\t(nextOpen: boolean) => {\n\t\t\t\t\t\tif (!isControlled) setUncontrolledOpen(nextOpen);\n\t\t\t\t\t\tconst currentState = stateRef.current;\n\t\t\t\t\t\tif (currentState) {\n\t\t\t\t\t\t\t\tonOpenChange?.(nextOpen, { ...currentState, open: nextOpen });\n\t\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t[isControlled, onOpenChange],\n\t\t);\n\n\t\tconst run = useCallback(\n\t\t\t\tasync (reason: AsyncPreviewReason) => {\n\t\t\t\t\t\tif (hasStaticData || !onShow) return;\n\n\t\t\t\t\t\tconst requestKey = cacheKey ?? type;\n\t\t\t\t\t\tconst activeController = abortRef.current;\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\treason === 'open' &&\n\t\t\t\t\t\t\t\tactiveRunKeyRef.current === requestKey &&\n\t\t\t\t\t\t\t\tactiveController &&\n\t\t\t\t\t\t\t\t!activeController.signal.aborted\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// A cache hit still supersedes work for the previous preview.\n\t\t\t\t\t\tabortRef.current?.abort();\n\t\t\t\t\t\tabortRef.current = null;\n\t\t\t\t\t\tactiveRunKeyRef.current = null;\n\n\t\t\t\t\t\tconst cachedEntry = readCache(cacheKey, staleTime);\n\t\t\t\t\t\tconst canUseCache =\n\t\t\t\t\t\t\t\treason === 'open' &&\n\t\t\t\t\t\t\t\tcachedEntry !== undefined &&\n\t\t\t\t\t\t\t\tcachePolicy === 'cache-first';\n\n\t\t\t\t\t\tif (canUseCache) {\n\t\t\t\t\t\t\t\tsetCached(true);\n\t\t\t\t\t\t\t\tsetError(null);\n\t\t\t\t\t\t\t\tmetaRef.current = cachedEntry.meta;\n\t\t\t\t\t\t\t\tsetMetaState(cachedEntry.meta);\n\t\t\t\t\t\t\t\tsetData(cachedEntry.status === 'success' ? cachedEntry.data as TData : null);\n\t\t\t\t\t\t\t\tsetStatus(cachedEntry.status);\n\t\t\t\t\t\t\t\tsetLoadingState(false);\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst controller = new AbortController();\n\t\t\t\t\t\tabortRef.current = controller;\n\t\t\t\t\t\tactiveRunKeyRef.current = requestKey;\n\t\t\t\t\t\tconst requestId = requestIdRef.current + 1;\n\t\t\t\t\t\trequestIdRef.current = requestId;\n\t\t\t\t\t\tconst hadCache = cachedEntry !== undefined;\n\n\t\t\t\t\t\tsetCached(false);\n\t\t\t\t\t\tsetError(null);\n\t\t\t\t\t\tsetStatus('loading');\n\t\t\t\t\t\tsetLoadingState({ label: undefined });\n\n\t\t\t\t\t\tconst loadingState = stateRef.current\n\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\t\t...stateRef.current,\n\t\t\t\t\t\t\t\t\t\t\t\terror: null,\n\t\t\t\t\t\t\t\t\t\t\t\tloading: { label: undefined },\n\t\t\t\t\t\t\t\t\t\t\t\tstatus: 'loading' as const,\n\t\t\t\t\t\t\t\t\t\t\t\tcached: false,\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t: null;\n\n\t\t\t\t\t\tif (loadingState) onBeforeShow?.(loadingState);\n\t\t\t\t\t\tif (reason === 'refresh') {\n\t\t\t\t\t\t\t\tif (loadingState) onRefresh?.(loadingState);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst applyIfCurrent = (fn: () => void) => {\n\t\t\t\t\t\t\t\tif (requestIdRef.current !== requestId || controller.signal.aborted) return;\n\t\t\t\t\t\t\t\tfn();\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst result = await onShow({\n\t\t\t\t\t\t\t\t\t\ttype,\n\t\t\t\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t\t\t\t\t\t\treason,\n\t\t\t\t\t\t\t\t\t\tcached: hadCache,\n\t\t\t\t\t\t\t\t\t\tsetLoading: (nextLoading) =>\n\t\t\t\t\t\t\t\t\t\t\t\tapplyIfCurrent(() => setLoadingState(normalizeLoading(nextLoading))),\n\t\t\t\t\t\t\t\t\t\tsetMeta: (nextMeta) =>\n\t\t\t\t\t\t\t\t\t\t\t\tapplyIfCurrent(() => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst next = { ...metaRef.current, ...nextMeta };\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tmetaRef.current = next;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetMetaState(next);\n\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\tapplyIfCurrent(() => {\n\t\t\t\t\t\t\t\t\t\tconst nextStatus: Extract<AsyncPreviewStatus, 'empty' | 'success'> =\n\t\t\t\t\t\t\t\t\t\t\t\tresult === null || result === undefined ? 'empty' : 'success';\n\t\t\t\t\t\t\t\t\t\tconst nextData = nextStatus === 'success' ? result as TData : null;\n\t\t\t\t\t\t\t\t\t\tsetData(nextData);\n\t\t\t\t\t\t\t\t\t\tsetStatus(nextStatus);\n\t\t\t\t\t\t\t\t\t\tsetLoadingState(false);\n\t\t\t\t\t\t\t\t\t\tsetError(null);\n\t\t\t\t\t\t\t\t\t\tsetCached(false);\n\n\t\t\t\t\t\t\t\t\t\tif (cacheKey) {\n\t\t\t\t\t\t\t\t\t\t\t\tasyncPreviewCache.set(cacheKey, {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata: nextData,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tstatus: nextStatus,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tmeta: metaRef.current,\n\t\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tconst settledState = stateRef.current\n\t\t\t\t\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t...stateRef.current,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata: nextData,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\terror: null,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tloading: false as const,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstatus: nextStatus,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tmeta: metaRef.current,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcached: false,\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t: null;\n\n\t\t\t\t\t\t\t\t\t\tif (nextData !== null && settledState) {\n\t\t\t\t\t\t\t\t\t\t\t\tonData?.(nextData, settledState);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tif (settledState) onSettled?.(settledState);\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\tif (controller.signal.aborted) return;\n\t\t\t\t\t\t\t\tapplyIfCurrent(() => {\n\t\t\t\t\t\t\t\t\t\tsetError(err);\n\t\t\t\t\t\t\t\t\t\tsetStatus('error');\n\t\t\t\t\t\t\t\t\t\tsetLoadingState(false);\n\t\t\t\t\t\t\t\t\t\tconst settledState = stateRef.current\n\t\t\t\t\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t...stateRef.current,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\terror: err,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tloading: false as const,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstatus: 'error' as const,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcached: false,\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t: null;\n\t\t\t\t\t\t\t\t\t\tif (settledState) onError?.(err, settledState);\n\t\t\t\t\t\t\t\t\t\tif (settledState) onSettled?.(settledState);\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t\tif (requestIdRef.current === requestId) {\n\t\t\t\t\t\t\t\t\t\tif (abortRef.current === controller) abortRef.current = null;\n\t\t\t\t\t\t\t\t\t\tif (activeRunKeyRef.current === requestKey) activeRunKeyRef.current = null;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t[\n\t\t\t\t\t\tcacheKey,\n\t\t\t\t\t\tcachePolicy,\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\thasStaticData,\n\t\t\t\t\t\tonBeforeShow,\n\t\t\t\t\t\tonData,\n\t\t\t\t\t\tonError,\n\t\t\t\t\t\tonRefresh,\n\t\t\t\t\t\tonSettled,\n\t\t\t\t\t\tonShow,\n\t\t\t\t\t\tstaleTime,\n\t\t\t\t\t\ttype,\n\t\t\t\t],\n\t\t);\n\n\t\tconst refresh = useCallback(() => {\n\t\t\t\tvoid run('refresh');\n\t\t}, [run]);\n\n\t\tconst prefetch = useCallback(() => {\n\t\t\t\tif (hasStaticData) return;\n\t\t\t\tif (prefetchedRef.current) return;\n\t\t\t\tprefetchedRef.current = true;\n\t\t\t\tvoid run('prefetch');\n\t\t}, [hasStaticData, run]);\n\n\t\tconst close = useCallback(() => {\n\t\t\t\tsetOpen(false);\n\t\t}, [setOpen]);\n\n\t\tconst state = useMemo<AsyncPreviewState<TData, TContext, TType>>(\n\t\t\t\t() => ({\n\t\t\t\t\t\ttype,\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\tdata: resolvedData,\n\t\t\t\t\t\terror,\n\t\t\t\t\t\tloading,\n\t\t\t\t\t\tstatus: resolvedStatus,\n\t\t\t\t\t\tmeta,\n\t\t\t\t\t\topen,\n\t\t\t\t\t\tcached,\n\t\t\t\t\t\trefresh,\n\t\t\t\t\t\tprefetch,\n\t\t\t\t\t\tclose,\n\t\t\t\t}),\n\t\t\t\t[cached, close, context, error, loading, meta, open, prefetch, refresh, resolvedData, resolvedStatus, type],\n\t\t);\n\t\tstateRef.current = state;\n\t\tmetaRef.current = meta;\n\n\t\tuseEffect(() => {\n\t\t\t\tif (!hasStaticData) return;\n\t\t\t\tabortRef.current?.abort();\n\t\t\t\tabortRef.current = null;\n\t\t\t\tactiveRunKeyRef.current = null;\n\t\t\t\topenRunKeyRef.current = null;\n\t\t\t\tsetError(null);\n\t\t\t\tsetLoadingState(false);\n\t\t\t\tsetCached(false);\n\t\t}, [hasStaticData, staticData]);\n\n\t\tuseEffect(() => {\n\t\t\t\tif (!open) {\n\t\t\t\t\t\topenRunKeyRef.current = null;\n\t\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (hasStaticData) return;\n\n\t\t\t\tconst openRunKey = cacheKey ?? type;\n\t\t\t\tif (openRunKeyRef.current === openRunKey) return;\n\t\t\t\topenRunKeyRef.current = openRunKey;\n\t\t\t\tvoid run('open');\n\t\t}, [cacheKey, hasStaticData, open, run, type]);\n\n\t\tuseEffect(() => {\n\t\t\t\tprefetchedRef.current = false;\n\t\t}, [cacheKey, hasStaticData, type]);\n\n\t\tuseEffect(\n\t\t\t\t() => () => {\n\t\t\t\t\t\tabortRef.current?.abort();\n\t\t\t\t},\n\t\t\t\t[],\n\t\t);\n\n\t\treturn { ...state, setOpen };\n}\n\nexport function clearAsyncPreviewCache(cacheKey?: string) {\n\t\tif (cacheKey) {\n\t\t\t\tasyncPreviewCache.delete(cacheKey);\n\t\t\t\treturn;\n\t\t}\n\t\tasyncPreviewCache.clear();\n}\n","/**\n * AsyncPreview — generic lazy preview popover for table cells, inline values,\n * buttons, badges, or any other trigger.\n *\n * The library owns popover chrome, async state, abort/race protection, cache,\n * loading/error/empty defaults, and composition primitives. Consumers own the\n * fetcher, routing callbacks, telemetry, and domain rendering.\n */\nimport {\n\t\tcreateContext,\n\t\tuseContext,\n} from 'react';\n\nimport { Button } from '../../base/buttons';\nimport { ErrorState, LoadingState } from '../../base/feedback';\nimport { EmptyState } from '../../blocks/data-display';\nimport {\n\t\tPopover,\n\t\tPopoverContent,\n\t\tPopoverTrigger,\n} from '../../base/popover';\nimport { useStrings } from '../../../lib/strings';\nimport { cn } from '../../../lib/utils';\n\nimport {\n\t\tdefaultAsyncPreviewStrings,\n\t\ttype AsyncPreviewStrings,\n} from './async-preview.strings';\nimport type {\n\t\tAsyncPreviewBodyProps,\n\t\tAsyncPreviewContentProps,\n\t\tAsyncPreviewEmptyProps,\n\t\tAsyncPreviewErrorProps,\n\t\tAsyncPreviewLoadingProps,\n\t\tAsyncPreviewRootProps,\n\t\tAsyncPreviewState as AsyncPreviewStateValue,\n\t\tAsyncPreviewStateProps,\n\t\tAsyncPreviewTriggerProps,\n} from './async-preview.types';\nimport { useAsyncPreview } from './hooks/use-async-preview';\n\ninterface AsyncPreviewContextValue<TData, TContext, TType extends string> {\n\t\tstate: AsyncPreviewStateValue<TData, TContext, TType>;\n\t\tsetOpen: (open: boolean) => void;\n\t\t/** Overrides this surface's own copy. */\n\t\tstrings: AsyncPreviewStrings;\n\t\tprefetchOn: false | 'hover' | 'focus';\n}\n\nconst AsyncPreviewContext =\n\t\tcreateContext<AsyncPreviewContextValue<unknown, unknown, string> | null>(null);\n\nfunction useAsyncPreviewContext<\n\t\tTData = unknown,\n\t\tTContext = unknown,\n\t\tTType extends string = string,\n>(): AsyncPreviewContextValue<TData, TContext, TType> {\n\t\tconst ctx = useContext(AsyncPreviewContext);\n\t\tif (!ctx) {\n\t\t\t\tthrow new Error('AsyncPreview compound parts must be rendered inside <AsyncPreview.Root>.');\n\t\t}\n\t\treturn ctx as AsyncPreviewContextValue<TData, TContext, TType>;\n}\n\nfunction AsyncPreviewRoot<\n\t\tTData,\n\t\tTContext = unknown,\n\t\tTType extends string = string,\n>({\n\t\tchildren,\n\t\tstrings: stringsProp,\n\t\tprefetchOn = false,\n\t\t...options\n}: AsyncPreviewRootProps<TData, TContext, TType>) {\n\t\tconst strings = useStrings(defaultAsyncPreviewStrings, stringsProp);\n\t\tconst preview = useAsyncPreview<TData, TContext, TType>(options);\n\t\tconst state: AsyncPreviewStateValue<TData, TContext, TType> = {\n\t\t\t\ttype: preview.type,\n\t\t\t\tcontext: preview.context,\n\t\t\t\tdata: preview.data,\n\t\t\t\terror: preview.error,\n\t\t\t\tloading: preview.loading,\n\t\t\t\tstatus: preview.status,\n\t\t\t\tmeta: preview.meta,\n\t\t\t\topen: preview.open,\n\t\t\t\tcached: preview.cached,\n\t\t\t\trefresh: preview.refresh,\n\t\t\t\tprefetch: preview.prefetch,\n\t\t\t\tclose: () => preview.setOpen(false),\n\t\t};\n\n\t\treturn (\n\t\t\t\t<AsyncPreviewContext.Provider\n\t\t\t\t\t\tvalue={{\n\t\t\t\t\t\t\t\tstate: state as AsyncPreviewStateValue<unknown, unknown, string>,\n\t\t\t\t\t\t\t\tsetOpen: preview.setOpen,\n\t\t\t\t\t\t\t\tstrings,\n\t\t\t\t\t\t\t\tprefetchOn,\n\t\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t\t<span className=\"async-preview--component contents\">\n\t\t\t\t\t\t\t\t<Popover open={state.open} onOpenChange={preview.setOpen}>\n\t\t\t\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t\t\t</Popover>\n\t\t\t\t\t\t</span>\n\t\t\t\t</AsyncPreviewContext.Provider>\n\t\t);\n}\n\nfunction AsyncPreviewTrigger<\n\t\tTData = unknown,\n\t\tTContext = unknown,\n\t\tTType extends string = string,\n>({ render, children }: AsyncPreviewTriggerProps<TData, TContext, TType>) {\n\t\tconst { state, prefetchOn } = useAsyncPreviewContext<TData, TContext, TType>();\n\t\tconst maybePrefetch = () => {\n\t\t\t\tif (prefetchOn) state.prefetch();\n\t\t};\n\t\tconst triggerProps = {\n\t\t\t\t'aria-busy': state.status === 'loading' ? true as const : undefined,\n\t\t\t\t'data-state': state.open ? 'open' as const : 'closed' as const,\n\t\t\t\t'data-loading': state.status === 'loading' ? true as const : undefined,\n\t\t\t\tonPointerEnter: prefetchOn === 'hover' ? maybePrefetch : undefined,\n\t\t\t\tonFocus: prefetchOn === 'focus' ? maybePrefetch : undefined,\n\t\t};\n\n\t\tif (render) {\n\t\t\t\tconst renderedTrigger = typeof render === 'function'\n\t\t\t\t\t\t? render({ state, triggerProps })\n\t\t\t\t\t\t: render;\n\t\t\t\treturn (\n\t\t\t\t\t\t<PopoverTrigger\n\t\t\t\t\t\t\t\trender={renderedTrigger}\n\t\t\t\t\t\t\t\t{...triggerProps}\n\t\t\t\t\t\t/>\n\t\t\t\t);\n\t\t}\n\n\t\treturn (\n\t\t\t\t<PopoverTrigger\n\t\t\t\t\t\trender={\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t{...triggerProps}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t}\n\t\t\t\t/>\n\t\t);\n}\n\nfunction AsyncPreviewContent({\n\t\tclassName,\n\t\tchildren,\n\t\talign = 'start',\n\t\tsideOffset = 8,\n\t\tfinalFocus = true,\n\t\t...props\n}: AsyncPreviewContentProps) {\n\t\tconst { state } = useAsyncPreviewContext();\n\t\tconst { size = 'md', padding = 'none', ...contentProps } = props;\n\t\tconst sizeClassName = {\n\t\t\t\tsm: 'w-72',\n\t\t\t\tmd: 'w-80',\n\t\t\t\tlg: 'w-90',\n\t\t}[size];\n\t\tconst inset = ({\n\t\t\t\tnone: 'flush',\n\t\t\t\tsm: 'compact',\n\t\t\t\tmd: 'default',\n\t\t\t\tlg: 'flush',\n\t\t} as const)[padding];\n\t\tconst paddingClassName = padding === 'none'\n\t\t\t\t? 'gap-0'\n\t\t\t\t: undefined;\n\n\t\treturn (\n\t\t\t\t<PopoverContent\n\t\t\t\t\t\talign={align}\n\t\t\t\t\t\tsideOffset={sideOffset}\n\t\t\t\t\t\tfinalFocus={finalFocus}\n\t\t\t\t\t\tinset={inset}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t'async-preview--content max-w-[calc(100vw-2rem)] overflow-hidden',\n\t\t\t\t\t\t\t\tsizeClassName,\n\t\t\t\t\t\t\t\tpaddingClassName,\n\t\t\t\t\t\t\t\tclassName,\n\t\t\t\t\t\t)}\n\t\t\t\t\t\tdata-status={state.status}\n\t\t\t\t\t\tdata-preview-type={state.type}\n\t\t\t\t\t\t{...contentProps}\n\t\t\t\t>\n\t\t\t\t\t\t{padding === 'lg' ? <div className=\"p-surface-lg\">{children}</div> : children}\n\t\t\t\t</PopoverContent>\n\t\t);\n}\n\nfunction AsyncPreviewState<\n\t\tTData = unknown,\n\t\tTContext = unknown,\n\t\tTType extends string = string,\n>({ children }: AsyncPreviewStateProps<TData, TContext, TType>) {\n\t\tconst { state } = useAsyncPreviewContext<TData, TContext, TType>();\n\t\treturn <>{children(state)}</>;\n}\n\nfunction AsyncPreviewBody<\n\t\tTData = unknown,\n\t\tTContext = unknown,\n\t\tTType extends string = string,\n>({ children }: AsyncPreviewBodyProps<TData, TContext, TType>) {\n\t\tconst { state } = useAsyncPreviewContext<TData, TContext, TType>();\n\t\tif (state.status !== 'success' || state.data === null) return null;\n\t\treturn <>{children({ ...state, data: state.data })}</>;\n}\n\nfunction AsyncPreviewLoading<\n\t\tTData = unknown,\n\t\tTContext = unknown,\n\t\tTType extends string = string,\n>({ children, className }: AsyncPreviewLoadingProps<TData, TContext, TType>) {\n\t\tconst { state, strings } = useAsyncPreviewContext<TData, TContext, TType>();\n\t\tif (state.status !== 'loading') return null;\n\t\tif (children) return <>{children(state)}</>;\n\t\tconst label =\n\t\t\t\ttypeof state.loading === 'object' && state.loading !== null\n\t\t\t\t\t\t? state.loading.label\n\t\t\t\t\t\t: undefined;\n\t\tconst phase =\n\t\t\t\ttypeof state.loading === 'object' && state.loading !== null\n\t\t\t\t\t\t? state.loading.phase\n\t\t\t\t\t\t: undefined;\n\t\tconst progress =\n\t\t\t\ttypeof state.loading === 'object' &&\n\t\t\t\tstate.loading !== null &&\n\t\t\t\ttypeof state.loading.progress === 'number'\n\t\t\t\t\t\t? Math.min(100, Math.max(0, state.loading.progress))\n\t\t\t\t\t\t: undefined;\n\n\t\treturn (\n\t\t\t\t<LoadingState\n\t\t\t\t\t\tclassName={cn('async-preview--loading p-surface', className)}\n\t\t\t\t\t\tvariant=\"panel\"\n\t\t\t\t\t\tlabel={label ?? strings.loading}\n\t\t\t\t\t\tdescription={phase}\n\t\t\t\t\t\tprogress={progress}\n\t\t\t\t\t\tskeleton\n\t\t\t\t\t\tlines={3}\n\t\t\t\t/>\n\t\t);\n}\n\nfunction AsyncPreviewError<\n\t\tTData = unknown,\n\t\tTContext = unknown,\n\t\tTType extends string = string,\n>({ children, className }: AsyncPreviewErrorProps<TData, TContext, TType>) {\n\t\tconst { state, strings } = useAsyncPreviewContext<TData, TContext, TType>();\n\t\tif (state.status !== 'error') return null;\n\t\tif (children) return <>{children(state)}</>;\n\t\treturn (\n\t\t\t\t<ErrorState\n\t\t\t\t\t\tclassName={cn('async-preview--error p-surface', className)}\n\t\t\t\t\t\ttitle={strings.errorTitle}\n\t\t\t\t\t\tdescription={strings.errorDescription}\n\t\t\t\t\t\tonRetry={state.refresh}\n\t\t\t\t\t\tretryLabel={strings.retry}\n\t\t\t\t\t\tvariant=\"inline\"\n\t\t\t\t/>\n\t\t);\n}\n\nfunction AsyncPreviewEmpty<\n\t\tTData = unknown,\n\t\tTContext = unknown,\n\t\tTType extends string = string,\n>({ children, className }: AsyncPreviewEmptyProps<TData, TContext, TType>) {\n\t\tconst { state, strings } = useAsyncPreviewContext<TData, TContext, TType>();\n\t\tif (state.status !== 'empty') return null;\n\t\tif (children) return <>{children(state)}</>;\n\t\treturn (\n\t\t\t\t<EmptyState\n\t\t\t\t\t\tclassName={cn('async-preview--empty', className)}\n\t\t\t\t\t\tpadding=\"md\"\n\t\t\t\t\t\ttitle={strings.emptyTitle}\n\t\t\t\t\t\tdescription={strings.emptyDescription}\n\t\t\t\t/>\n\t\t);\n}\n\nfunction createAsyncPreview<\n\t\tTData,\n\t\tTContext = unknown,\n\t\tTType extends string = string,\n>() {\n\t\treturn {\n\t\t\t\tRoot: AsyncPreviewRoot<TData, TContext, TType>,\n\t\t\t\tTrigger: AsyncPreviewTrigger<TData, TContext, TType>,\n\t\t\t\tContent: AsyncPreviewContent,\n\t\t\t\tState: AsyncPreviewState<TData, TContext, TType>,\n\t\t\t\tBody: AsyncPreviewBody<TData, TContext, TType>,\n\t\t\t\tLoading: AsyncPreviewLoading<TData, TContext, TType>,\n\t\t\t\tError: AsyncPreviewError<TData, TContext, TType>,\n\t\t\t\tEmpty: AsyncPreviewEmpty<TData, TContext, TType>,\n\t\t};\n}\n\nconst AsyncPreview = {\n\t\tRoot: AsyncPreviewRoot,\n\t\tTrigger: AsyncPreviewTrigger,\n\t\tContent: AsyncPreviewContent,\n\t\tState: AsyncPreviewState,\n\t\tBody: AsyncPreviewBody,\n\t\tLoading: AsyncPreviewLoading,\n\t\tError: AsyncPreviewError,\n\t\tEmpty: AsyncPreviewEmpty,\n};\n\nAsyncPreviewRoot.displayName = 'AsyncPreviewRoot';\nAsyncPreviewTrigger.displayName = 'AsyncPreviewTrigger';\nAsyncPreviewContent.displayName = 'AsyncPreviewContent';\nAsyncPreviewState.displayName = 'AsyncPreviewState';\nAsyncPreviewBody.displayName = 'AsyncPreviewBody';\nAsyncPreviewLoading.displayName = 'AsyncPreviewLoading';\nAsyncPreviewError.displayName = 'AsyncPreviewError';\nAsyncPreviewEmpty.displayName = 'AsyncPreviewEmpty';\n\nexport {\n\t\tAsyncPreview,\n\t\tAsyncPreviewRoot,\n\t\tAsyncPreviewTrigger,\n\t\tAsyncPreviewContent,\n\t\tAsyncPreviewState,\n\t\tAsyncPreviewBody,\n\t\tAsyncPreviewLoading,\n\t\tAsyncPreviewError,\n\t\tAsyncPreviewEmpty,\n\t\tcreateAsyncPreview,\n\t\tuseAsyncPreviewContext,\n};\n","/**\n * PreviewTriggerCell — table-cell trigger chrome for AsyncPreview.\n *\n * It renders a button only when preview interaction exists. Empty, disabled,\n * or explicitly non-previewable values keep the same table rhythm without a\n * caret, pointer cursor, popup ARIA, or trigger padding that implies action.\n */\nimport { ChevronDown, type LucideIcon } from 'lucide-react';\nimport React, { type ReactNode } from 'react';\n\nimport { Badge, type BadgeProps } from '../../base/badge';\nimport { Button } from '../../base/buttons';\nimport { Stack } from '../../base/structure';\nimport {\n\tEmptyValue,\n\tName,\n\tSecondaryValue,\n\tValue,\n} from '../../primitives';\nimport { cn } from '../../../lib/utils';\n\ntype PreviewTriggerCellRootProps = Omit<\n\tReact.ButtonHTMLAttributes<HTMLButtonElement>,\n\t'children' | 'disabled' | 'name' | 'value'\n>;\n\nexport interface PreviewTriggerCellProps extends PreviewTriggerCellRootProps {\n\t/** Primary text of the cell. */\n\tvalue?: ReactNode | null;\n\t/** Display name. */\n\tname?: string | null;\n\t/** Supporting text under the value. */\n\tsecondary?: ReactNode | null;\n\t/** Content before the value. */\n\tleading?: ReactNode;\n\t/** Content after the value. */\n\ttrailing?: ReactNode;\n\t/** Chip rendered beside the label. */\n\tbadge?: ReactNode | { label: ReactNode; tone?: BadgeProps['tone']; size?: BadgeProps['size'] };\n\t/** Leading glyph. */\n\ticon?: LucideIcon;\n\t/** Copy shown when the value is empty. */\n\temptyLabel?: ReactNode;\n\t/** Whether this row has a preview to open. */\n\thasPreview?: boolean;\n\t/** Explains why the preview is unavailable, shown as a tooltip. */\n\tdisabledReason?: ReactNode;\n\t/** Applies name casing to the value regardless of how it arrives. */\n\tforceNameCase?: boolean;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n\t/** Merged onto the content. */\n\tcontentClassName?: string;\n}\n\nfunction isEmpty(value: ReactNode | null | undefined) {\n\treturn value === null || value === undefined || value === '';\n}\n\nfunction renderBadge(badge: PreviewTriggerCellProps['badge']) {\n\tif (!badge) return null;\n\tif (typeof badge === 'object' && !Array.isArray(badge) && 'label' in badge) {\n\t\treturn (\n\t\t\t<Badge inline tone={badge.tone ?? 'secondary'} size={badge.size}>\n\t\t\t\t{badge.label}\n\t\t\t</Badge>\n\t\t);\n\t}\n\treturn badge;\n}\n\nfunction PreviewTriggerCellInner({\n\tvalue,\n\tname,\n\tsecondary,\n\tleading,\n\ttrailing,\n\tbadge,\n\ticon: Icon,\n\temptyLabel = '--',\n\tforceNameCase,\n\tcontentClassName,\n}: PreviewTriggerCellProps) {\n\tconst primaryIsEmpty = isEmpty(name) && isEmpty(value);\n\treturn (\n\t\t<Stack render={<span />} direction=\"horizontal\" gap=\"sm\" wrap={false} className={cn('preview-trigger-cell--inner', contentClassName)}>\n\t\t\t{!!leading && <span className=\"preview-trigger-cell--leading inline-flex shrink-0 items-center\">{leading}</span>}\n\t\t\t{!!Icon && (\n\t\t\t\t<span className=\"preview-trigger-cell--icon inline-flex shrink-0 items-center text-muted-foreground\">\n\t\t\t\t\t<Icon className=\"size-icon-sm\" aria-hidden />\n\t\t\t\t</span>\n\t\t\t)}\n\t\t\t<span className=\"preview-trigger-cell--content flex min-w-0 flex-1 flex-col items-start\">\n\t\t\t\t<Stack render={<span />} direction=\"horizontal\" gap=\"sm\" wrap={false} className=\"max-w-full\">\n\t\t\t\t\t{primaryIsEmpty ? (\n\t\t\t\t\t\t<EmptyValue className=\"truncate\">\n\t\t\t\t\t\t\t{emptyLabel}\n\t\t\t\t\t\t</EmptyValue>\n\t\t\t\t\t) : name ? (\n\t\t\t\t\t\t<Name\n\t\t\t\t\t\t\tvalue={name}\n\t\t\t\t\t\t\tforce={forceNameCase}\n\t\t\t\t\t\t\tweight=\"medium\"\n\t\t\t\t\t\t\tclassName=\"truncate\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<Value weight=\"medium\" className=\"truncate\">\n\t\t\t\t\t\t\t{value}\n\t\t\t\t\t\t</Value>\n\t\t\t\t\t)}\n\t\t\t\t\t{renderBadge(badge)}\n\t\t\t\t</Stack>\n\t\t\t\t{!isEmpty(secondary) && (\n\t\t\t\t\t<SecondaryValue size=\"xs\" className=\"max-w-full truncate\">\n\t\t\t\t\t\t{secondary}\n\t\t\t\t\t</SecondaryValue>\n\t\t\t\t)}\n\t\t\t</span>\n\t\t\t{!!trailing && <span className=\"preview-trigger-cell--trailing inline-flex shrink-0 items-center\">{trailing}</span>}\n\t\t</Stack>\n\t);\n}\n\nexport const PreviewTriggerCell = React.forwardRef<HTMLButtonElement, PreviewTriggerCellProps>(function PreviewTriggerCell({\n\tvalue,\n\tname,\n\tsecondary,\n\tleading,\n\ttrailing,\n\tbadge,\n\ticon,\n\temptyLabel,\n\thasPreview,\n\tdisabledReason,\n\tforceNameCase,\n\tclassName,\n\tcontentClassName,\n\ttype,\n\t...rootProps\n}, ref) {\n\tconst cellProps = {\n\t\tvalue,\n\t\tname,\n\t\tsecondary,\n\t\tleading,\n\t\ttrailing,\n\t\tbadge,\n\t\ticon,\n\t\temptyLabel,\n\t\tforceNameCase,\n\t\tcontentClassName,\n\t};\n\tconst previewable =\n\t\thasPreview ?? (!isEmpty(name) || !isEmpty(value));\n\tconst interactive = previewable && !disabledReason;\n\n\tif (!interactive) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'preview-trigger-cell--component flex h-auto min-h-action-sm max-w-full items-center justify-start rounded-inner px-control-sm py-space-xs text-left',\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\taria-disabled={disabledReason ? true : undefined}\n\t\t\t\ttitle={typeof disabledReason === 'string' ? disabledReason : undefined}\n\t\t\t>\n\t\t\t\t<PreviewTriggerCellInner {...cellProps} />\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<Button\n\t\t\t{...rootProps}\n\t\t\tref={ref}\n\t\t\ttype={type ?? 'button'}\n\t\t\ttone=\"secondary\"\n\t\t\tbuttonStyle=\"ghost\"\n\t\t\tsize=\"sm\"\n\t\t\tclassName={cn(\n\t\t\t\t'preview-trigger-cell--component h-auto min-h-action-sm max-w-full justify-start px-control-sm py-space-xs text-left',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t<PreviewTriggerCellInner {...cellProps} />\n\t\t\t<ChevronDown className=\"preview-trigger-cell--caret size-icon-sm shrink-0 text-muted-foreground\" aria-hidden />\n\t\t</Button>\n\t);\n});\n\nPreviewTriggerCell.displayName = 'PreviewTriggerCell';\n"],"mappings":"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"}
@@ -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-xv3yJbzl.js";
2
+ import { a as e, i as t, n, o as r, r as i, t as a } from "../combobox-hozNwUcc.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-DviPLnwy.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-u5L0OGip.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 };