themelia-react-ui 2.0.5 → 2.0.6

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 (489) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/MIGRATION.md +119 -0
  3. package/README.md +13 -6
  4. package/dist/{accordion-B9MHG0cT.js → accordion-0tQUZ20r.js} +7 -7
  5. package/dist/accordion-0tQUZ20r.js.map +1 -0
  6. package/dist/{action-menu-Dr8K-ghE.js → action-menu-C0gjzLyE.js} +7 -7
  7. package/dist/{action-menu-Dr8K-ghE.js.map → action-menu-C0gjzLyE.js.map} +1 -1
  8. package/dist/{ai-artifact-C58tQcBy.js → ai-artifact-CGGpQryR.js} +172 -157
  9. package/dist/ai-artifact-CGGpQryR.js.map +1 -0
  10. package/dist/{app-shell-B_IuNWOo.js → app-shell-EHuuRDGy.js} +5 -5
  11. package/dist/{app-shell-B_IuNWOo.js.map → app-shell-EHuuRDGy.js.map} +1 -1
  12. package/dist/{attachment-Dg_69lPS.js → attachment-BCpA4e7i.js} +8 -8
  13. package/dist/{attachment-Dg_69lPS.js.map → attachment-BCpA4e7i.js.map} +1 -1
  14. package/dist/{auth-DTkkshS8.js → auth-B0girIk_.js} +15 -15
  15. package/dist/auth-B0girIk_.js.map +1 -0
  16. package/dist/{avatar-CeZaFmNH.js → avatar-B9Jnp-T-.js} +3 -3
  17. package/dist/{avatar-CeZaFmNH.js.map → avatar-B9Jnp-T-.js.map} +1 -1
  18. package/dist/{badge-xIiV_E7f.js → badge-wWauMgAt.js} +3 -3
  19. package/dist/{badge-xIiV_E7f.js.map → badge-wWauMgAt.js.map} +1 -1
  20. package/dist/base/accordion.js +1 -1
  21. package/dist/base/action-menu.js +1 -1
  22. package/dist/base/attachment.js +1 -1
  23. package/dist/base/avatar.js +1 -1
  24. package/dist/base/badge.js +1 -1
  25. package/dist/base/batch-action-bar.js +1 -1
  26. package/dist/base/buttons.js +1 -1
  27. package/dist/base/cards.js +2 -2
  28. package/dist/base/carousel.js +3 -3
  29. package/dist/base/cascader.js +1 -1
  30. package/dist/base/chart.js +1 -1
  31. package/dist/base/choice-inputs.js +2 -2
  32. package/dist/base/code-block.js +1 -1
  33. package/dist/base/combobox.js +1 -1
  34. package/dist/base/command.js +1 -1
  35. package/dist/base/copyable.js +1 -1
  36. package/dist/base/date-pickers.js +2 -2
  37. package/dist/base/display.js +6 -6
  38. package/dist/base/feedback.js +4 -4
  39. package/dist/base/forms-numeric.js +1 -1
  40. package/dist/base/forms.js +2 -2
  41. package/dist/base/inline-edit.js +8 -8
  42. package/dist/base/item.js +1 -1
  43. package/dist/base/media-gallery.js +1 -1
  44. package/dist/base/metadata-list.js +1 -1
  45. package/dist/base/navigation.js +6 -6
  46. package/dist/base/popover-menu.js +1 -1
  47. package/dist/base/popover.js +1 -1
  48. package/dist/base/qr-code.js +1 -1
  49. package/dist/base/repeaters.js +195 -188
  50. package/dist/base/repeaters.js.map +1 -1
  51. package/dist/base/sheet.js +1 -1
  52. package/dist/base/sidebar.js +2 -2
  53. package/dist/base/signature-pad.js +7 -7
  54. package/dist/base/skeleton.js +1 -1
  55. package/dist/base/spinner.js +5 -5
  56. package/dist/base/spinner.js.map +1 -1
  57. package/dist/base/structure.js +1 -1
  58. package/dist/base/table.js +1 -1
  59. package/dist/base/text-inputs.js +2 -2
  60. package/dist/base/toaster.js +1 -1
  61. package/dist/base/tree.js +1 -1
  62. package/dist/base/upload-queue.js +1 -1
  63. package/dist/base/upload.js +3 -3
  64. package/dist/base/value-inputs.js +1 -1
  65. package/dist/{batch-action-bar-Cb8cuvyy.js → batch-action-bar-BoqWIIpV.js} +5 -5
  66. package/dist/{batch-action-bar-Cb8cuvyy.js.map → batch-action-bar-BoqWIIpV.js.map} +1 -1
  67. package/dist/blocks/admin.js +17 -17
  68. package/dist/blocks/ai.js +227 -221
  69. package/dist/blocks/ai.js.map +1 -1
  70. package/dist/blocks/analytics/usage-card.js +1 -1
  71. package/dist/blocks/analytics.js +424 -449
  72. package/dist/blocks/analytics.js.map +1 -1
  73. package/dist/blocks/collaboration.js +1 -1
  74. package/dist/blocks/commerce/receipt.js +1 -1
  75. package/dist/blocks/commerce.js +225 -220
  76. package/dist/blocks/commerce.js.map +1 -1
  77. package/dist/blocks/data-display.js +2 -2
  78. package/dist/blocks/onboarding.js +5 -5
  79. package/dist/blocks/planning.js +11 -11
  80. package/dist/blocks/timelines.js +1 -1
  81. package/dist/{breadcrumbs-J-K2kl4c.js → breadcrumbs-Bp9Ke7kd.js} +4 -4
  82. package/dist/breadcrumbs-Bp9Ke7kd.js.map +1 -0
  83. package/dist/{button-S2Cubiiz.js → button-ChBovTx0.js} +2 -2
  84. package/dist/{button-S2Cubiiz.js.map → button-ChBovTx0.js.map} +1 -1
  85. package/dist/{buttons-BedGfygC.js → buttons-DeW0bQeK.js} +6 -6
  86. package/dist/{buttons-BedGfygC.js.map → buttons-DeW0bQeK.js.map} +1 -1
  87. package/dist/{cards-rNX1M4Xn.js → cards-CNXnmvV5.js} +8 -8
  88. package/dist/{cards-rNX1M4Xn.js.map → cards-CNXnmvV5.js.map} +1 -1
  89. package/dist/{cascader-B1MiqkBq.js → cascader-CrAl9zD5.js} +15 -15
  90. package/dist/{cascader-B1MiqkBq.js.map → cascader-CrAl9zD5.js.map} +1 -1
  91. package/dist/{chart-Darg_0Kv.js → chart-I7ROnsl8.js} +5 -5
  92. package/dist/{chart-Darg_0Kv.js.map → chart-I7ROnsl8.js.map} +1 -1
  93. package/dist/{checkbox-fflqmODR.js → checkbox-MoyHIAPs.js} +3 -3
  94. package/dist/{checkbox-fflqmODR.js.map → checkbox-MoyHIAPs.js.map} +1 -1
  95. package/dist/{choice-inputs-zUgBZfE4.js → choice-inputs-DHGtx0QV.js} +122 -110
  96. package/dist/choice-inputs-DHGtx0QV.js.map +1 -0
  97. package/dist/{code-block-BzmM9Eig.js → code-block-BSJyq9e-.js} +7 -7
  98. package/dist/{code-block-BzmM9Eig.js.map → code-block-BSJyq9e-.js.map} +1 -1
  99. package/dist/{collapsible-BkAI_XD4.js → collapsible-BzJ91LUG.js} +3 -3
  100. package/dist/{collapsible-BkAI_XD4.js.map → collapsible-BzJ91LUG.js.map} +1 -1
  101. package/dist/{collection-content-gDh1v6O4.js → collection-content-CSnwtOTH.js} +3 -3
  102. package/dist/{collection-content-gDh1v6O4.js.map → collection-content-CSnwtOTH.js.map} +1 -1
  103. package/dist/{combobox-BEx0vJgF.js → combobox-Bcvu5J8O.js} +11 -10
  104. package/dist/{combobox-BEx0vJgF.js.map → combobox-Bcvu5J8O.js.map} +1 -1
  105. package/dist/combobox-C2JiSQPc.js +915 -0
  106. package/dist/combobox-C2JiSQPc.js.map +1 -0
  107. package/dist/{command-CrlPIL6m.js → command-9e52NPgK.js} +6 -6
  108. package/dist/{command-CrlPIL6m.js.map → command-9e52NPgK.js.map} +1 -1
  109. package/dist/{comments-Dmpp0YIc.js → comments-BsgErEqd.js} +33 -28
  110. package/dist/comments-BsgErEqd.js.map +1 -0
  111. package/dist/components/base/choice-inputs/choice-types.d.ts +4 -0
  112. package/dist/components/base/choice-inputs/pill-radio-group.d.ts +7 -6
  113. package/dist/components/base/combobox/combobox-field.d.ts +2 -2
  114. package/dist/components/base/date-pickers/date-picker-internals.d.ts +3 -1
  115. package/dist/components/base/date-pickers/datepicker.types.d.ts +10 -4
  116. package/dist/components/base/date-pickers/time-picker.d.ts +17 -3
  117. package/dist/components/base/feedback/state-display.d.ts +5 -1
  118. package/dist/components/base/feedback/state-display.strings.d.ts +9 -0
  119. package/dist/components/base/forms/form-field.d.ts +7 -2
  120. package/dist/components/base/forms-numeric/coordinates-input.d.ts +4 -1
  121. package/dist/components/base/forms-numeric/decimal-input.d.ts +2 -2
  122. package/dist/components/base/forms-numeric/dimensions-input.d.ts +4 -1
  123. package/dist/components/base/forms-numeric/numeric-composite-field.d.ts +12 -0
  124. package/dist/components/base/forms-numeric/weight-input.d.ts +6 -1
  125. package/dist/components/base/navigation/language-switcher.d.ts +12 -4
  126. package/dist/components/base/repeaters/key-value-editor.d.ts +2 -1
  127. package/dist/components/base/sidebar/sidebar.d.ts +2 -0
  128. package/dist/components/base/upload/avatar-upload.d.ts +2 -1
  129. package/dist/components/base/upload/image-upload.d.ts +2 -1
  130. package/dist/components/blocks/ai/ai-citation/types.d.ts +2 -0
  131. package/dist/components/blocks/ai/ai-reasoning/types.d.ts +2 -0
  132. package/dist/components/blocks/ai/ai-sources/types.d.ts +2 -0
  133. package/dist/components/blocks/ai/ai-tool-call/types.d.ts +2 -0
  134. package/dist/components/blocks/analytics/metric/metric.d.ts +4 -0
  135. package/dist/components/blocks/analytics/metric-comparison/metric-comparison.d.ts +2 -0
  136. package/dist/components/blocks/analytics/metric-grid/metric-grid.d.ts +4 -5
  137. package/dist/components/blocks/analytics/types.d.ts +2 -2
  138. package/dist/components/blocks/commerce/order-status/types.d.ts +4 -0
  139. package/dist/components/blocks/data-display/empty-state/empty-state.types.d.ts +4 -3
  140. package/dist/components/features/activities/activities.types.d.ts +18 -11
  141. package/dist/components/features/activities/hooks/use-activity-resources.d.ts +2 -1
  142. package/dist/components/features/ai-chat/hooks/use-ai-chat-scroll.d.ts +1 -1
  143. package/dist/components/features/appointment-calendar/appointment-calendar.d.ts +1 -1
  144. package/dist/components/features/appointment-calendar/appointment-calendar.types.d.ts +4 -2
  145. package/dist/components/features/combobox/async-resource-combobox.d.ts +2 -2
  146. package/dist/components/features/combobox/combobox.d.ts +2 -2
  147. package/dist/components/features/combobox/hooks/use-combobox-core.d.ts +2 -1
  148. package/dist/components/features/combobox/hooks/use-combobox-state.d.ts +1 -0
  149. package/dist/components/features/combobox/hooks/use-load-more.d.ts +1 -0
  150. package/dist/components/features/combobox/types.d.ts +37 -8
  151. package/dist/components/features/email-composer/types.d.ts +3 -1
  152. package/dist/components/features/filters/facets/date-facet.d.ts +4 -2
  153. package/dist/components/features/filters/facets/range-facet.d.ts +12 -0
  154. package/dist/components/features/filters/filters.types.d.ts +3 -3
  155. package/dist/components/features/filters/partials/date-filter-content.d.ts +3 -2
  156. package/dist/components/features/filters/partials/filter-popover-content.d.ts +4 -2
  157. package/dist/components/features/filters/partials/range-filter-content.d.ts +12 -0
  158. package/dist/components/features/filters/utils/filter-utils.d.ts +5 -1
  159. package/dist/components/features/media-library/hooks/use-media-library.d.ts +1 -1
  160. package/dist/components/features/media-library/media-library.d.ts +1 -1
  161. package/dist/components/features/media-library/media-library.strings.d.ts +6 -0
  162. package/dist/components/features/media-library/media-library.types.d.ts +36 -8
  163. package/dist/components/features/media-library/partials/media-library-partials.d.ts +3 -3
  164. package/dist/components/features/mentions/hooks/use-mentions.d.ts +16 -1
  165. package/dist/components/features/mentions/partials/mention-inline-suggestions.d.ts +5 -1
  166. package/dist/components/features/mentions/utils/split-html-by-mentions.d.ts +1 -7
  167. package/dist/components/features/overlays/hooks/use-overlay-visibility.d.ts +2 -2
  168. package/dist/components/features/products/products.types.d.ts +2 -2
  169. package/dist/components/features/questionnaire/questionnaire.types.d.ts +3 -0
  170. package/dist/components/features/resource/resource.d.ts +1 -1
  171. package/dist/components/features/resource/resource.types.d.ts +2 -0
  172. package/dist/components/features/rich-text-editor/form-rich-text-editor.d.ts +1 -1
  173. package/dist/components/features/rich-text-editor/partials/caret-helpers.d.ts +1 -1
  174. package/dist/components/features/rich-text-editor/partials/editor-field-aria.d.ts +14 -0
  175. package/dist/components/features/rich-text-editor/partials/rich-text-editor-toolbar.d.ts +3 -1
  176. package/dist/components/features/rich-text-editor/rich-text-editor.recipes.d.ts +1 -1
  177. package/dist/components/features/rich-text-editor/rich-text-editor.types.d.ts +17 -3
  178. package/dist/components/features/schema-form/hooks/use-schema-form.d.ts +5 -1
  179. package/dist/components/features/schema-form/partials/schema-form-field.d.ts +3 -1
  180. package/dist/components/features/schema-form/schema-form.utils.d.ts +1 -1
  181. package/dist/components/features/suggestions/suggestions.types.d.ts +1 -1
  182. package/dist/components/features/table/data-table.d.ts +1 -1
  183. package/dist/components/features/table/index.d.ts +1 -0
  184. package/dist/components/features/table/table-body.d.ts +1 -1
  185. package/dist/components/features/table/table-helpers.d.ts +6 -3
  186. package/dist/components/features/table/table.strings.d.ts +3 -0
  187. package/dist/components/features/table/table.types.d.ts +17 -1
  188. package/dist/components/layout/header/header.types.d.ts +3 -2
  189. package/dist/components/layout/layout.types.d.ts +5 -3
  190. package/dist/components/layout/navigation/side-nav.d.ts +3 -2
  191. package/dist/components/layout/normalize-layout-path.d.ts +1 -0
  192. package/dist/components/layout/settings/settings.d.ts +1 -1
  193. package/dist/components/layout/sidebar/app-sidebar.d.ts +1 -1
  194. package/dist/components/layout/sidebar/sidebar-navigation-rail.d.ts +3 -1
  195. package/dist/components/layout/sidebar/sidebar.context.d.ts +1 -0
  196. package/dist/components/layout/sidebar/sidebar.types.d.ts +2 -0
  197. package/dist/components/primitives/link.d.ts +3 -2
  198. package/dist/components/primitives/money.d.ts +1 -1
  199. package/dist/components/primitives/number.d.ts +1 -1
  200. package/dist/components/typography/rich-text/rich-text-tree.d.ts +7 -5
  201. package/dist/{containers-CIxwbZt5.js → containers-CSdc32h9.js} +2 -2
  202. package/dist/{containers-CIxwbZt5.js.map → containers-CSdc32h9.js.map} +1 -1
  203. package/dist/{copyable-DIznBqiT.js → copyable-3fdHfMR3.js} +4 -4
  204. package/dist/{copyable-DIznBqiT.js.map → copyable-3fdHfMR3.js.map} +1 -1
  205. package/dist/{data-display-BdgCAw8T.js → data-display-Cmj-xZYl.js} +16 -15
  206. package/dist/data-display-Cmj-xZYl.js.map +1 -0
  207. package/dist/{date-Cq8ioE4o.js → date-Br0FicVv.js} +4 -4
  208. package/dist/{date-Cq8ioE4o.js.map → date-Br0FicVv.js.map} +1 -1
  209. package/dist/date-picker-CyQlFYsP.js +1617 -0
  210. package/dist/date-picker-CyQlFYsP.js.map +1 -0
  211. package/dist/date-pickers-tj2MXmXd.js +185 -0
  212. package/dist/date-pickers-tj2MXmXd.js.map +1 -0
  213. package/dist/{display-KsZLw9Ov.js → display-CT_N2a3w.js} +7 -7
  214. package/dist/{display-KsZLw9Ov.js.map → display-CT_N2a3w.js.map} +1 -1
  215. package/dist/{dropdown-menu-CLs8Lihj.js → dropdown-menu-C08iIugv.js} +6 -6
  216. package/dist/{dropdown-menu-CLs8Lihj.js.map → dropdown-menu-C08iIugv.js.map} +1 -1
  217. package/dist/features/activities.js +283 -270
  218. package/dist/features/activities.js.map +1 -1
  219. package/dist/features/ai-chat.js +40 -27
  220. package/dist/features/ai-chat.js.map +1 -1
  221. package/dist/features/appointment-calendar.js +126 -126
  222. package/dist/features/appointment-calendar.js.map +1 -1
  223. package/dist/features/async-preview.js +9 -9
  224. package/dist/features/combobox.js +1 -1
  225. package/dist/features/comments.js +1 -1
  226. package/dist/features/data-view.js +10 -10
  227. package/dist/features/email-composer.js +24 -19
  228. package/dist/features/email-composer.js.map +1 -1
  229. package/dist/features/event-calendar.js +129 -125
  230. package/dist/features/event-calendar.js.map +1 -1
  231. package/dist/features/filters.js +2 -2
  232. package/dist/features/global-search.js +16 -20
  233. package/dist/features/global-search.js.map +1 -1
  234. package/dist/features/kanban.js +18 -28
  235. package/dist/features/kanban.js.map +1 -1
  236. package/dist/features/map/style.css +15 -0
  237. package/dist/features/map.js +331 -314
  238. package/dist/features/map.js.map +1 -1
  239. package/dist/features/media-library.js +1044 -866
  240. package/dist/features/media-library.js.map +1 -1
  241. package/dist/features/mentions.js +2 -2
  242. package/dist/features/overlays.js +1 -1
  243. package/dist/features/products.js +978 -964
  244. package/dist/features/products.js.map +1 -1
  245. package/dist/features/questionnaire.js +159 -152
  246. package/dist/features/questionnaire.js.map +1 -1
  247. package/dist/features/resource-assignment.js +8 -8
  248. package/dist/features/resource.js +74 -71
  249. package/dist/features/resource.js.map +1 -1
  250. package/dist/features/rich-text-editor.js +28 -19
  251. package/dist/features/rich-text-editor.js.map +1 -1
  252. package/dist/features/schema-form.js +297 -256
  253. package/dist/features/schema-form.js.map +1 -1
  254. package/dist/features/suggestions.js +57 -50
  255. package/dist/features/suggestions.js.map +1 -1
  256. package/dist/features/sync.js +3 -3
  257. package/dist/features/table.js +1 -1
  258. package/dist/features/theme-tweaker.js +400 -399
  259. package/dist/features/theme-tweaker.js.map +1 -1
  260. package/dist/feedback-Dzo1xtAU.js +246 -0
  261. package/dist/feedback-Dzo1xtAU.js.map +1 -0
  262. package/dist/{field-affordance-recipes-DWcNcOjh.js → field-affordance-recipes-D6H7tVJi.js} +2 -2
  263. package/dist/{field-affordance-recipes-DWcNcOjh.js.map → field-affordance-recipes-D6H7tVJi.js.map} +1 -1
  264. package/dist/field-control-attributes-B6i335wr.js +18 -0
  265. package/dist/field-control-attributes-B6i335wr.js.map +1 -0
  266. package/dist/{field-state-recipes-BVA2CWHo.js → field-state-recipes-7sza8QbC.js} +4 -2
  267. package/dist/{field-state-recipes-BVA2CWHo.js.map → field-state-recipes-7sza8QbC.js.map} +1 -1
  268. package/dist/{filters-DzgSJpMK.js → filters-Dl80yYtN.js} +763 -605
  269. package/dist/filters-Dl80yYtN.js.map +1 -0
  270. package/dist/form-field-CAPdwdnZ.js +74 -0
  271. package/dist/form-field-CAPdwdnZ.js.map +1 -0
  272. package/dist/{form-sizing-Bs2qFUeE.js → form-sizing-CgcrUbLU.js} +2 -2
  273. package/dist/{form-sizing-Bs2qFUeE.js.map → form-sizing-CgcrUbLU.js.map} +1 -1
  274. package/dist/{forms-C0RGnJTe.js → forms-B3W8CH7-.js} +8 -8
  275. package/dist/{forms-C0RGnJTe.js.map → forms-B3W8CH7-.js.map} +1 -1
  276. package/dist/forms-numeric-CwjQJe-O.js +991 -0
  277. package/dist/forms-numeric-CwjQJe-O.js.map +1 -0
  278. package/dist/{header-DMMxG__r.js → header-ZIIsRKxP.js} +113 -113
  279. package/dist/header-ZIIsRKxP.js.map +1 -0
  280. package/dist/hooks/use-files.d.ts +2 -0
  281. package/dist/{hooks-DB6CJ4MR.js → hooks-BitHSh-Y.js} +3 -3
  282. package/dist/{hooks-DB6CJ4MR.js.map → hooks-BitHSh-Y.js.map} +1 -1
  283. package/dist/{icon-badge-DZF-YjQp.js → icon-badge-npxF1SLX.js} +2 -2
  284. package/dist/{icon-badge-DZF-YjQp.js.map → icon-badge-npxF1SLX.js.map} +1 -1
  285. package/dist/index.js +1 -1
  286. package/dist/{input-CvyDQlY7.js → input-7KAc7XQL.js} +6 -6
  287. package/dist/{input-CvyDQlY7.js.map → input-7KAc7XQL.js.map} +1 -1
  288. package/dist/{input-DMBwAZmr.js → input-DIREVYHs.js} +3 -3
  289. package/dist/{input-DMBwAZmr.js.map → input-DIREVYHs.js.map} +1 -1
  290. package/dist/{interaction-recipes-XR9ZpVYL.js → interaction-recipes-4wZ2tvfb.js} +2 -2
  291. package/dist/{interaction-recipes-XR9ZpVYL.js.map → interaction-recipes-4wZ2tvfb.js.map} +1 -1
  292. package/dist/{item-DjCcM18E.js → item-FfWnaYST.js} +99 -98
  293. package/dist/item-FfWnaYST.js.map +1 -0
  294. package/dist/layout/app-shell.js +1 -1
  295. package/dist/layout/auth.js +1 -1
  296. package/dist/layout/containers.js +1 -1
  297. package/dist/layout/header.js +1 -1
  298. package/dist/layout/hooks.js +1 -1
  299. package/dist/layout/navigation.js +1 -1
  300. package/dist/layout/page.js +1 -1
  301. package/dist/layout/settings.js +1 -1
  302. package/dist/layout/sidebar.js +2 -2
  303. package/dist/layout/workspace.js +1 -1
  304. package/dist/layout.js +11 -11
  305. package/dist/layout.types-E_GAApzO.js +30 -0
  306. package/dist/layout.types-E_GAApzO.js.map +1 -0
  307. package/dist/lib/field-control-attributes.d.ts +11 -0
  308. package/dist/lib/field-state-recipes.d.ts +2 -0
  309. package/dist/lib/format.d.ts +1 -0
  310. package/dist/lib/surface-recipes.d.ts +1 -1
  311. package/dist/lib/token-merge.generated.d.ts +6 -6
  312. package/dist/lib/utils.js +1 -1
  313. package/dist/{media-gallery-C-vChPmE.js → media-gallery-C81DAnKI.js} +6 -6
  314. package/dist/{media-gallery-C-vChPmE.js.map → media-gallery-C81DAnKI.js.map} +1 -1
  315. package/dist/{mentions-0_4nWuI-.js → mentions-qOnedSt4.js} +236 -167
  316. package/dist/mentions-qOnedSt4.js.map +1 -0
  317. package/dist/message-BJHnn43M.js +135 -0
  318. package/dist/message-BJHnn43M.js.map +1 -0
  319. package/dist/{metadata-list-C3MkU-Om.js → metadata-list-XkqZ_UXH.js} +11 -11
  320. package/dist/{metadata-list-C3MkU-Om.js.map → metadata-list-XkqZ_UXH.js.map} +1 -1
  321. package/dist/{navigation-DaRjthVk.js → navigation-BgtPJAhi.js} +119 -119
  322. package/dist/navigation-BgtPJAhi.js.map +1 -0
  323. package/dist/{navigation-C90-oQFq.js → navigation-Bt-v7rWP.js} +52 -46
  324. package/dist/navigation-Bt-v7rWP.js.map +1 -0
  325. package/dist/normalize-layout-path-BmEgg6fu.js +14 -0
  326. package/dist/normalize-layout-path-BmEgg6fu.js.map +1 -0
  327. package/dist/{number-CRU3kGuk.js → number-CYqBcrSj.js} +78 -86
  328. package/dist/number-CYqBcrSj.js.map +1 -0
  329. package/dist/{overflow-tab-bar-IVFVQFV6.js → overflow-tab-bar-BQCA2Zn2.js} +7 -7
  330. package/dist/{overflow-tab-bar-IVFVQFV6.js.map → overflow-tab-bar-BQCA2Zn2.js.map} +1 -1
  331. package/dist/{overlays-BSgCtM2v.js → overlays-CC8zI3Du.js} +264 -260
  332. package/dist/overlays-CC8zI3Du.js.map +1 -0
  333. package/dist/{page-DUUKDAjo.js → page-BoQ1VaFJ.js} +13 -13
  334. package/dist/{page-DUUKDAjo.js.map → page-BoQ1VaFJ.js.map} +1 -1
  335. package/dist/{page-header-commands-7P3sfE9u.js → page-header-commands-DIKspJfx.js} +4 -4
  336. package/dist/{page-header-commands-7P3sfE9u.js.map → page-header-commands-DIKspJfx.js.map} +1 -1
  337. package/dist/{pagination-CgCjElfu.js → pagination-Br8TdV9A.js} +4 -4
  338. package/dist/{pagination-CgCjElfu.js.map → pagination-Br8TdV9A.js.map} +1 -1
  339. package/dist/{popover-B85RenIl.js → popover-k8TdUcAt.js} +10 -10
  340. package/dist/popover-k8TdUcAt.js.map +1 -0
  341. package/dist/{popover-menu-DlnQ2zlR.js → popover-menu-yn-o0kyA.js} +7 -7
  342. package/dist/{popover-menu-DlnQ2zlR.js.map → popover-menu-yn-o0kyA.js.map} +1 -1
  343. package/dist/{popover.recipes-DdiEp0rd.js → popover.recipes-DJ0AkUan.js} +2 -2
  344. package/dist/{popover.recipes-DdiEp0rd.js.map → popover.recipes-DJ0AkUan.js.map} +1 -1
  345. package/dist/{portal-recipes-BpsV_iRw.js → portal-recipes-DyUXqUtD.js} +2 -2
  346. package/dist/{portal-recipes-BpsV_iRw.js.map → portal-recipes-DyUXqUtD.js.map} +1 -1
  347. package/dist/{primitives-ByWgGUgt.js → primitives-BkkQjYl7.js} +22 -17
  348. package/dist/primitives-BkkQjYl7.js.map +1 -0
  349. package/dist/primitives.js +4 -4
  350. package/dist/{progress-BJhQP9WX.js → progress-DZFXXzPs.js} +4 -4
  351. package/dist/{progress-BJhQP9WX.js.map → progress-DZFXXzPs.js.map} +1 -1
  352. package/dist/{receipt-tOc7B3hw.js → receipt-C7LhOg7Q.js} +6 -6
  353. package/dist/{receipt-tOc7B3hw.js.map → receipt-C7LhOg7Q.js.map} +1 -1
  354. package/dist/rich-text-BnTzZjIo.js +45 -0
  355. package/dist/rich-text-BnTzZjIo.js.map +1 -0
  356. package/dist/rich-text-editor-CAurDwT5.js +1273 -0
  357. package/dist/rich-text-editor-CAurDwT5.js.map +1 -0
  358. package/dist/{rich-text-editor-toolbar-laT3tpBT.js → rich-text-editor-toolbar-DbXig7Jk.js} +36 -35
  359. package/dist/rich-text-editor-toolbar-DbXig7Jk.js.map +1 -0
  360. package/dist/rich-text-tree-BqyQ_7-R.js +66 -0
  361. package/dist/rich-text-tree-BqyQ_7-R.js.map +1 -0
  362. package/dist/{sanitize-html-DsQmI48u.js → sanitize-html-BWkH4dLM.js} +29 -16
  363. package/dist/sanitize-html-BWkH4dLM.js.map +1 -0
  364. package/dist/{scroll-area-B0dB2cBi.js → scroll-area-Bj6CRUif.js} +2 -2
  365. package/dist/{scroll-area-B0dB2cBi.js.map → scroll-area-Bj6CRUif.js.map} +1 -1
  366. package/dist/{separator-Bb17I4pu.js → separator-B9ewiCGO.js} +2 -2
  367. package/dist/{separator-Bb17I4pu.js.map → separator-B9ewiCGO.js.map} +1 -1
  368. package/dist/{separator-Ct_WSWTJ.js → separator-DM6gs2vu.js} +3 -3
  369. package/dist/{separator-Ct_WSWTJ.js.map → separator-DM6gs2vu.js.map} +1 -1
  370. package/dist/services/actions.js +1 -1
  371. package/dist/settings-DZPHgpx4.js +155 -0
  372. package/dist/settings-DZPHgpx4.js.map +1 -0
  373. package/dist/{sheet-BGPERY55.js → sheet-C4DHsgLk.js} +6 -6
  374. package/dist/{sheet-BGPERY55.js.map → sheet-C4DHsgLk.js.map} +1 -1
  375. package/dist/sidebar-C8BnDwTH.js +709 -0
  376. package/dist/sidebar-C8BnDwTH.js.map +1 -0
  377. package/dist/{sidebar-f9gRWXIR.js → sidebar-CmD6a-HK.js} +16 -13
  378. package/dist/sidebar-CmD6a-HK.js.map +1 -0
  379. package/dist/{skeleton-BapcJd9C.js → skeleton-DDgdhmu9.js} +5 -5
  380. package/dist/{skeleton-BapcJd9C.js.map → skeleton-DDgdhmu9.js.map} +1 -1
  381. package/dist/{smart-card-CW0hjetE.js → smart-card-B6vLxqa_.js} +8 -8
  382. package/dist/{smart-card-CW0hjetE.js.map → smart-card-B6vLxqa_.js.map} +1 -1
  383. package/dist/{structure-DuxKl954.js → structure-DZJ2wbAU.js} +2 -2
  384. package/dist/{structure-DuxKl954.js.map → structure-DZJ2wbAU.js.map} +1 -1
  385. package/dist/style.css +1 -1
  386. package/dist/{surface-recipes-BKRVW8Os.js → surface-recipes-C8mNycaY.js} +2 -2
  387. package/dist/{surface-recipes-BKRVW8Os.js.map → surface-recipes-C8mNycaY.js.map} +1 -1
  388. package/dist/{table-CFOWY9pQ.js → table-CBonSdTp.js} +534 -486
  389. package/dist/table-CBonSdTp.js.map +1 -0
  390. package/dist/{table-B4TE7iOV.js → table-CXSPHH25.js} +75 -71
  391. package/dist/table-CXSPHH25.js.map +1 -0
  392. package/dist/{tabs-e7ko9S2o.js → tabs-C4Kr_hCr.js} +50 -49
  393. package/dist/tabs-C4Kr_hCr.js.map +1 -0
  394. package/dist/{text-inputs-B1culiSK.js → text-inputs-jdkS3ReG.js} +9 -9
  395. package/dist/{text-inputs-B1culiSK.js.map → text-inputs-jdkS3ReG.js.map} +1 -1
  396. package/dist/{timelines-D3Sl9ueq.js → timelines-CoPwdJP0.js} +10 -10
  397. package/dist/{timelines-D3Sl9ueq.js.map → timelines-CoPwdJP0.js.map} +1 -1
  398. package/dist/{tooltip-8wz5S_Zr.js → tooltip-31NwIpTo.js} +4 -4
  399. package/dist/{tooltip-8wz5S_Zr.js.map → tooltip-31NwIpTo.js.map} +1 -1
  400. package/dist/{tree-CzUJHnFs.js → tree-CeYVzdFE.js} +6 -6
  401. package/dist/{tree-CzUJHnFs.js.map → tree-CeYVzdFE.js.map} +1 -1
  402. package/dist/typography/rich-text.js +1 -1
  403. package/dist/{typography-BQnine1k.js → typography-C7-YMW1S.js} +2 -2
  404. package/dist/{typography-BQnine1k.js.map → typography-C7-YMW1S.js.map} +1 -1
  405. package/dist/typography.js +1 -1
  406. package/dist/{upload-BOW6U2tI.js → upload-Hdm5gObf.js} +303 -291
  407. package/dist/upload-Hdm5gObf.js.map +1 -0
  408. package/dist/{upload-queue-qUXn1ykN.js → upload-queue-D0sYPuqo.js} +8 -8
  409. package/dist/{upload-queue-qUXn1ykN.js.map → upload-queue-D0sYPuqo.js.map} +1 -1
  410. package/dist/{usage-card-BeSLY0i0.js → usage-card-9s8hLDfn.js} +9 -9
  411. package/dist/{usage-card-BeSLY0i0.js.map → usage-card-9s8hLDfn.js.map} +1 -1
  412. package/dist/{utils-B6kKb8jB.js → utils-DhuoqFy4.js} +31 -37
  413. package/dist/utils-DhuoqFy4.js.map +1 -0
  414. package/dist/{value-inputs-skdVB2zh.js → value-inputs-D3aPgq9H.js} +15 -15
  415. package/dist/{value-inputs-skdVB2zh.js.map → value-inputs-D3aPgq9H.js.map} +1 -1
  416. package/dist/{value-typography-uAmWUAL1.js → value-typography-uSzzG9Gf.js} +32 -26
  417. package/dist/value-typography-uSzzG9Gf.js.map +1 -0
  418. package/dist/{workspace-DHeHv0qw.js → workspace-CC8Vchiu.js} +12 -12
  419. package/dist/{workspace-DHeHv0qw.js.map → workspace-CC8Vchiu.js.map} +1 -1
  420. package/docs/consumer-skill/examples/edit.tsx +3 -3
  421. package/docs/consumer-skill/references/agents-md.md +19 -19
  422. package/docs/consumer-skill/references/analytics.md +15 -0
  423. package/docs/consumer-skill/references/component-contracts.json +14724 -13057
  424. package/docs/consumer-skill/references/composition.md +21 -4
  425. package/docs/consumer-skill/references/design-contract.md +1 -0
  426. package/docs/consumer-skill/references/installation.md +51 -8
  427. package/docs/consumer-skill/references/integration.md +24 -1
  428. package/docs/consumer-skill/references/public-api.json +172 -34
  429. package/docs/consumer-skill/references/review.md +51 -11
  430. package/docs/consumer-skill/references/rhf-workflows.md +72 -0
  431. package/docs/consumer-skill/references/theming.md +7 -2
  432. package/docs/consumer-skill/references/tokens.json +1 -1
  433. package/docs/consumer-skill/scripts/composition-policy.mjs +144 -30
  434. package/docs/consumer-skill/scripts/setup-skills.mjs +46 -9
  435. package/package.json +4 -2
  436. package/templates/admin-shell-template.tsx +1 -2
  437. package/templates/customers-template.tsx +18 -16
  438. package/dist/accordion-B9MHG0cT.js.map +0 -1
  439. package/dist/ai-artifact-C58tQcBy.js.map +0 -1
  440. package/dist/auth-DTkkshS8.js.map +0 -1
  441. package/dist/breadcrumbs-J-K2kl4c.js.map +0 -1
  442. package/dist/choice-inputs-zUgBZfE4.js.map +0 -1
  443. package/dist/combobox-BwzoXFSG.js +0 -884
  444. package/dist/combobox-BwzoXFSG.js.map +0 -1
  445. package/dist/comments-Dmpp0YIc.js.map +0 -1
  446. package/dist/data-display-BdgCAw8T.js.map +0 -1
  447. package/dist/date-picker-RlIzKom_.js +0 -1551
  448. package/dist/date-picker-RlIzKom_.js.map +0 -1
  449. package/dist/date-pickers-DY-CpXS1.js +0 -179
  450. package/dist/date-pickers-DY-CpXS1.js.map +0 -1
  451. package/dist/feedback-Dm4izqFn.js +0 -240
  452. package/dist/feedback-Dm4izqFn.js.map +0 -1
  453. package/dist/filters-DzgSJpMK.js.map +0 -1
  454. package/dist/form-field-BriWAXyg.js +0 -63
  455. package/dist/form-field-BriWAXyg.js.map +0 -1
  456. package/dist/forms-numeric-DIhghX1Q.js +0 -910
  457. package/dist/forms-numeric-DIhghX1Q.js.map +0 -1
  458. package/dist/header-DMMxG__r.js.map +0 -1
  459. package/dist/item-DjCcM18E.js.map +0 -1
  460. package/dist/layout.types-Cn7aUzJp.js +0 -20
  461. package/dist/layout.types-Cn7aUzJp.js.map +0 -1
  462. package/dist/mentions-0_4nWuI-.js.map +0 -1
  463. package/dist/message-g8p7eVtN.js +0 -128
  464. package/dist/message-g8p7eVtN.js.map +0 -1
  465. package/dist/navigation-C90-oQFq.js.map +0 -1
  466. package/dist/navigation-DaRjthVk.js.map +0 -1
  467. package/dist/number-CRU3kGuk.js.map +0 -1
  468. package/dist/overlays-BSgCtM2v.js.map +0 -1
  469. package/dist/popover-B85RenIl.js.map +0 -1
  470. package/dist/primitives-ByWgGUgt.js.map +0 -1
  471. package/dist/rich-text-Dth5E882.js +0 -78
  472. package/dist/rich-text-Dth5E882.js.map +0 -1
  473. package/dist/rich-text-editor-C1fOjBTd.js +0 -1195
  474. package/dist/rich-text-editor-C1fOjBTd.js.map +0 -1
  475. package/dist/rich-text-editor-toolbar-laT3tpBT.js.map +0 -1
  476. package/dist/safe-image-src-C6kQSMBZ.js +0 -17
  477. package/dist/safe-image-src-C6kQSMBZ.js.map +0 -1
  478. package/dist/sanitize-html-DsQmI48u.js.map +0 -1
  479. package/dist/settings-Bar5wiSo.js +0 -167
  480. package/dist/settings-Bar5wiSo.js.map +0 -1
  481. package/dist/sidebar-D-JYMMbY.js +0 -686
  482. package/dist/sidebar-D-JYMMbY.js.map +0 -1
  483. package/dist/sidebar-f9gRWXIR.js.map +0 -1
  484. package/dist/table-B4TE7iOV.js.map +0 -1
  485. package/dist/table-CFOWY9pQ.js.map +0 -1
  486. package/dist/tabs-e7ko9S2o.js.map +0 -1
  487. package/dist/upload-BOW6U2tI.js.map +0 -1
  488. package/dist/utils-B6kKb8jB.js.map +0 -1
  489. package/dist/value-typography-uAmWUAL1.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comments-BsgErEqd.js","names":["ImageIcon","_Fragment","NumberValue","_Fragment","useCommentsUIDefaults","useCommentsConfig","useDatesConfig","cn","Button","TextButton","Text","DisplayLabel","TextLink","TooltipTrigger","TooltipContent","TooltipProvider","Tooltip","Stack","toneRecipes","rowBlockPaddingClasses","compositionRhythm","useOverlayVisibility","ConfirmDialog","interactionRecipes","sanitizeHtml","contentTypographyClassName","RichText","SecondaryValue","FileSize","Percent","Number$1","RelativeTime","AvatarFallback","Avatar","AvatarImage","Badge","fieldAffordanceRecipes","PopoverTrigger","Popover","EmptyState","RichTextEditor","MentionPicker","useMentions","MentionInlineSuggestions","MentionContent","parseMentionsFromHtml","Fragment$1","defaultCommentsStrings","useResolvedStrings","useStrings","propStrings","useResolvedAccessors","dates","useMemo","propAccessors","useComments","options","composerMode","setComposerMode","useState","isSubmitting","setIsSubmitting","isSubmittingRef","useRef","formErrors","setFormErrors","resetKey","setResetKey","setSubmitting","useCallback","submitting","resetComposer","k","helpers","reportError","error","onError","comment","onUpdate","payload","values","onAfterMutate","onSubmit","onDelete","id","pickIcon","att","Image","FileText","File","Paperclip","CommentAttachmentChip","stringsProp","strings","url","accessors","attachment","name","Icon","isUploading","isFailed","meta","surface","compact","className","iconNode","Loader2","labelRow","onRetry","editable","onRemove","X","defaultAttachmentUploadStrings","useAttachmentUpload","attachments","setAttachmentsState","initialAttachments","inFlightRef","fileCacheRef","attachmentsRef","commitAttachments","list","next","onValueChangeRef","onValueChange","updateAttachment","a","patch","setAttachments","beginUpload","onUpload","controller","uploaded","message","err","addFiles","disabled","files","filesInput","pending","file","maxFiles","maxSize","removeAttachment","entry","retryAttachment","reset","useEffect","inFlight","cache","hasMeaningfulContent","html","CommentComposer","forwardRef","resourcesProp","onResourceSearchProp","attachmentsProp","maxAttachmentsProp","allowAttachmentsProp","resources","onResourceSearch","allowAttachments","maxAttachments","attachmentsConfig","editorRef","body","setBody","initialValues","editingComment","contentError","setContentError","attachmentError","setAttachmentError","mentions","attachmentUpload","handleCancel","onCancel","useImperativeHandle","ref","context","errors","handleSubmit","event","replyingTo","fileInputRef","handleAttachmentClick","handleFiles","hasAttachments","isEditing","isReplying","submitLabel","eyebrow","ComposerEyebrow","makeReplyEyebrow","extraToolbarItems","items","AtSign","canComment","submitButton","cancelButton","attachmentChips","footerSlot","trailingSubmit","inlineSubmit","showFooterRow","kind","parsed","previous","m","byId","merged","p","placeholder","autoFocus","label","onClose","closeLabel","interpolateString","template","CommentEmpty","icon","MessageCircle","CommentContent","props","contentType","richContent","renderRichContent","renderReference","plainContent","decodeQuotedString","rawContent","Fragment","renderRichBlock","block","index","decoded","data","raw","text","stripHtml","level","createElement","sanitizedItems","item","caption","value","trimmed","FALLBACK_INITIAL","defaultGetMediaUrl","defaultGetMediaName","defaultGetStatusLabel","s","CommentItem","memo","allowReactionsProp","allowRepliesProp","allowReactions","allowReplies","resolvedGetMediaUrl","resolvedGetMediaName","resolvedGetStatusLabel","resolvedFormatRelativeTime","authorName","avatarUrl","fallbackInitial","tagList","tag","reactions","isPinned","isEdited","showStatus","statusLabel","canDeleteComment","canModerate","canEditComment","canReply","onReply","canReact","onReact","canPin","onPinToggle","canEdit","onEdit","canDelete","hasActions","attachmentConfirm","pendingAttachmentId","setPendingAttachmentId","requestAttachmentRemoval","attachmentId","Pin","renderAttachment","canRemoveAttachment","onAttachmentRemove","reaction","CornerDownRight","Smile","Pencil","Trash2","CommentTimeline","comments","defaultItem","renderItem","emptySlot","Comments","ui","composerPosition","title","confirmDelete","deleteConfirm","pendingDeleteId","setPendingDeleteId","commentsState","requestDelete","startReply","handleReply","commentId","composer","timeline","composerBlock","inner","ariaLabel"],"sources":["../src/components/features/comments/comments.strings.ts","../src/components/features/comments/comments-provider.tsx","../src/components/features/comments/hooks/use-comments.ts","../src/components/features/comments/partials/comment-attachment-chip.tsx","../src/components/features/comments/hooks/use-attachment-upload.ts","../src/components/features/comments/partials/comment-composer.tsx","../src/components/features/comments/partials/comment-empty.tsx","../src/components/features/comments/partials/comment-content.tsx","../src/components/features/comments/partials/comment-item.tsx","../src/components/features/comments/partials/comment-timeline.tsx","../src/components/features/comments/comments.tsx"],"sourcesContent":["/**\n * Strings for the Comments feature. Consumers override via the `strings`\n * prop on `<Comments>` / sub-components — values are\n * deep-merged over these defaults.\n */\nexport interface CommentsStrings {\n\t/** Card title — usually \"Comments\". Set to \"\" to hide. */\n\ttitle: string;\n\t/** Subtitle under the card title — optional. */\n\tsubtitle: string;\n\t/** Empty-state copy for the timeline. */\n\tempty: string;\n\t/** Empty-state secondary copy. */\n\temptyHint: string;\n\n\t// Composer ---------------------------------------------------------\n\t/** Composer rich-text placeholder. */\n\tcomposerPlaceholder: string;\n\t/** Submit label for new comments. */\n\tcomposerSubmit: string;\n\t/** Submit label while pending. */\n\tcomposerSubmitting: string;\n\t/** Submit label when editing. */\n\tcomposerSave: string;\n\t/** Required-content error. */\n\tinvalidContent: string;\n\t/** Cancel/dismiss draft. */\n\tcomposerCancel: string;\n\t/** \"Edit comment\" eyebrow shown above the composer in edit mode. */\n\tcomposerEditingEyebrow: string;\n\t/** \"Reply to {{name}}\" eyebrow shown above the composer in reply mode. */\n\tcomposerReplyingEyebrow: string;\n\n\t// Toolbar buttons --------------------------------------------------\n\tcomposerAttachmentLabel: string;\n\t/** Control that inserts a mention or link. */\n\tcomposerReferenceLabel: string;\n\t/** Heading of the insert-reference menu. */\n\tcomposerReferenceMenuTitle: string;\n\t/** Placeholder in the reference search field. */\n\tcomposerReferenceSearchPlaceholder: string;\n\t/** Shown when a reference search matches nothing. */\n\tcomposerReferenceEmpty: string;\n\t/** Shown while reference results are loading. */\n\tcomposerReferenceLoading: string;\n\n\t// Item -------------------------------------------------------------\n\tfallbackAuthor: string;\n\t/** Chip marking a pinned comment. */\n\tpinned: string;\n\t/** Suffix marking an edited comment. */\n\tedited: string;\n\t/** Trash button aria-label / tooltip. */\n\tdeleteLabel: string;\n\t/** Edit button label. */\n\teditLabel: string;\n\t/** Reply button label. */\n\treplyLabel: string;\n\t/** Pin/unpin button label. */\n\tpinLabel: string;\n\t/** Action that unpins a comment. */\n\tunpinLabel: string;\n\t/** \"More actions\" trigger aria-label. */\n\tmoreActionsLabel: string;\n\t/** Confirm-delete button label inside the action menu. */\n\tconfirmDeleteLabel: string;\n\t/** Title of the confirmation shown before a comment is deleted. */\n\tconfirmDeleteTitle: string;\n\t/** Title of the confirmation shown before an attachment is removed. */\n\tconfirmRemoveAttachmentTitle: string;\n\t/** Consequence of removing an attachment from a posted comment. */\n\tconfirmRemoveAttachmentDescription: string;\n\t/** Sentence explaining the consequence before the delete is committed. */\n\tconfirmDeleteDescription: string;\n\n\t// Attachments ------------------------------------------------------\n\tattachmentFallback: string;\n\t/** Removes an attachment — staged in the composer, or posted on a comment. */\n\tattachmentRemoveLabel: string;\n\t/** Shown while an attachment uploads. */\n\tattachmentUploadingLabel: string;\n\t/** Shown when an attachment upload fails. */\n\tattachmentFailedLabel: string;\n\t/** Shown when a file exceeds the size limit. */\n\tattachmentTooLargeError: string;\n\t/** Shown when too many files are attached. */\n\tattachmentTooManyError: string;\n\t/** Action that retries a failed upload. */\n\tattachmentRetryLabel: string;\n\t/** Action that downloads an attachment. */\n\tattachmentDownloadLabel: string;\n\n\t// Reactions --------------------------------------------------------\n\taddReactionLabel: string;\n\t/** Reaction button name; interpolates {{emoji}} and {{count}}. Optional for existing complete string objects. */\n\treactionLabel?: string;\n\n\t// Misc -------------------------------------------------------------\n\tshowRepliesLabel: string;\n\t/** Control that collapses a reply thread. */\n\thideRepliesLabel: string;\n}\n\nexport const defaultCommentsStrings: CommentsStrings = {\n\ttitle: 'Comments',\n\tsubtitle: '',\n\tempty: 'No comments yet.',\n\temptyHint: 'Start the conversation — your team will see it instantly.',\n\n\tcomposerPlaceholder: 'Write a comment…',\n\tcomposerSubmit: 'Post comment',\n\tcomposerSubmitting: 'Posting…',\n\tcomposerSave: 'Save changes',\n\tinvalidContent: 'Comment cannot be empty.',\n\tcomposerCancel: 'Cancel',\n\tcomposerEditingEyebrow: 'Editing comment',\n\tcomposerReplyingEyebrow: 'Replying to {{name}}',\n\n\tcomposerAttachmentLabel: 'Attach file',\n\tcomposerReferenceLabel: 'Mention or link',\n\tcomposerReferenceMenuTitle: 'Insert reference',\n\tcomposerReferenceSearchPlaceholder: 'Search…',\n\tcomposerReferenceEmpty: 'No matches.',\n\tcomposerReferenceLoading: 'Searching…',\n\n\tfallbackAuthor: 'Anonymous',\n\tpinned: 'Pinned',\n\tedited: 'edited',\n\tdeleteLabel: 'Delete',\n\teditLabel: 'Edit',\n\treplyLabel: 'Reply',\n\tpinLabel: 'Pin',\n\tunpinLabel: 'Unpin',\n\tmoreActionsLabel: 'More actions',\n\tconfirmDeleteLabel: 'Delete comment',\n\tconfirmDeleteTitle: 'Delete this comment?',\n\tconfirmRemoveAttachmentTitle: 'Remove this attachment?',\n\tconfirmRemoveAttachmentDescription: 'The file is detached from the comment for everyone. This cannot be undone.',\n\tconfirmDeleteDescription: 'The comment and its replies are removed for everyone. This cannot be undone.',\n\n\tattachmentFallback: 'Attachment',\n\tattachmentRemoveLabel: 'Remove attachment',\n\tattachmentUploadingLabel: 'Uploading…',\n\tattachmentFailedLabel: 'Upload failed',\n\tattachmentTooLargeError: 'File is too large.',\n\tattachmentTooManyError: 'Too many attachments.',\n\tattachmentRetryLabel: 'Retry',\n\tattachmentDownloadLabel: 'Download',\n\n\taddReactionLabel: 'Add reaction',\n\treactionLabel: 'Reaction {{emoji}}: {{count}}',\n\n\tshowRepliesLabel: 'Show replies',\n\thideRepliesLabel: 'Hide replies',\n};\n","/**\n * Comments — internal helper hooks for resolving strings and accessors.\n *\n * Rationale: the previous `<CommentsProvider>` is gone. Library-wide\n * Per-mount overrides flow as direct props on `<Comments>` and its partials.\n * Date formatting may still inherit the app-wide dates configuration.\n *\n * Resolution order everywhere:\n *\n * props.strings ← deep-merged over `defaultCommentsStrings`\n * props.accessor.X ← falls back to UIProvider's dates formatter, then\n * to a built-in default at the call site.\n */\nimport { useMemo } from 'react';\n\nimport { useStrings, type StringsProp } from '../../../lib/strings';\nimport { useDatesConfig } from '../../../lib/ui-provider';\n\nimport {\n\tdefaultCommentsStrings,\n\ttype CommentsStrings,\n} from './comments.strings';\nimport type { CommentsAccessors } from './comments.types';\n\n/**\n * Resolve final strings by merging defaults → component prop. Stable\n * identity when the prop reference is unchanged.\n */\nexport function useResolvedStrings(\n\tpropStrings?: StringsProp<CommentsStrings>,\n): CommentsStrings {\n\treturn useStrings(defaultCommentsStrings, propStrings);\n}\n\n/**\n * Resolve accessors. Order:\n * 1. explicit prop accessor\n * 2. the UIProvider date formatter for relative time\n * 3. caller's own fallback when neither is present (handled at call site)\n */\nexport function useResolvedAccessors(\n\tpropAccessors?: CommentsAccessors,\n): CommentsAccessors {\n\tconst dates = useDatesConfig();\n\treturn useMemo<CommentsAccessors>(\n\t\t() => ({\n\t\t\tgetMediaUrl: propAccessors?.getMediaUrl,\n\t\t\tgetMediaName: propAccessors?.getMediaName,\n\t\t\tgetStatusLabel: propAccessors?.getStatusLabel,\n\t\t\tformatRelativeTime:\n\t\t\t\tpropAccessors?.formatRelativeTime ?? dates.formatRelativeTime,\n\t\t}),\n\t\t[propAccessors, dates.formatRelativeTime],\n\t);\n}\n","/**\n * useComments — headless state machine for the Comments feature.\n *\n * Tracks composer mode (idle | replying | editing), submit/delete\n * helpers, error state, and resetKey bumping. The default `<Comments>`\n * component composes this hook; consumers building a fully custom UI\n * can use it directly.\n */\nimport { useCallback, useMemo, useRef, useState } from 'react';\n\nimport type {\n\tCommentData,\n\tCommentFormValues,\n\tCommentSubmitHelpers,\n\tCommentUser,\n\tCommentsConfig,\n} from '../comments.types';\n\nexport type ComposerMode<\n\tTResource extends string = string,\n\tTUser extends CommentUser = CommentUser,\n\tTMeta = unknown,\n> =\n\t| { kind: 'idle' }\n\t| { kind: 'editing'; comment: CommentData<TUser, TMeta, TResource> }\n\t| { kind: 'replying'; commentId: string; authorName?: string };\n\nexport interface UseCommentsOptions<\n\tTUser extends CommentUser = CommentUser,\n\tTMeta = unknown,\n\tTResource extends string = string,\n> {\n\tonSubmit?: CommentsConfig<TUser, TMeta, TResource>['onSubmit'];\n\tonUpdate?: CommentsConfig<TUser, TMeta, TResource>['onUpdate'];\n\tonDelete?: CommentsConfig<TUser, TMeta, TResource>['onDelete'];\n\tonAfterMutate?: CommentsConfig<TUser, TMeta, TResource>['onAfterMutate'];\n\tonError?: CommentsConfig<TUser, TMeta, TResource>['onError'];\n}\n\nexport interface UseCommentsReturn<\n\tTUser extends CommentUser = CommentUser,\n\tTMeta = unknown,\n\tTResource extends string = string,\n> {\n\tcomposerMode: ComposerMode<TResource, TUser, TMeta>;\n\tisSubmitting: boolean;\n\tformErrors: Record<string, string>;\n\tresetKey: number;\n\n\tstartReply: (comment: CommentData<TUser, TMeta, TResource>) => void;\n\tstartEdit: (comment: CommentData<TUser, TMeta, TResource>) => void;\n\tcancelComposerMode: () => void;\n\n\tsubmit: (values: CommentFormValues<TResource>) => Promise<void>;\n\tdeleteComment: (id: string) => Promise<void>;\n\n\t/** Imperative reset — bumps `resetKey` so the composer clears itself. */\n\tresetComposer: () => void;\n\t/** Helpers exposed to onSubmit/onUpdate. */\n\thelpers: CommentSubmitHelpers;\n}\n\nexport function useComments<\n\tTUser extends CommentUser = CommentUser,\n\tTMeta = unknown,\n\tTResource extends string = string,\n>(\n\toptions: UseCommentsOptions<TUser, TMeta, TResource> = {},\n): UseCommentsReturn<TUser, TMeta, TResource> {\n\tconst { onSubmit, onUpdate, onDelete, onAfterMutate, onError } = options;\n\n\tconst [composerMode, setComposerMode] = useState<\n\t\tComposerMode<TResource, TUser, TMeta>\n\t>({\n\t\tkind: 'idle',\n\t});\n\tconst [isSubmitting, setIsSubmitting] = useState(false);\n\tconst isSubmittingRef = useRef(false);\n\tconst [formErrors, setFormErrors] = useState<Record<string, string>>({});\n\tconst [resetKey, setResetKey] = useState(0);\n\n\tconst setSubmitting = useCallback((submitting: boolean) => {\n\t\tisSubmittingRef.current = submitting;\n\t\tsetIsSubmitting(submitting);\n\t}, []);\n\n\tconst resetComposer = useCallback(() => {\n\t\tsetResetKey((k) => k + 1);\n\t\tsetComposerMode({ kind: 'idle' });\n\t\tsetFormErrors({});\n\t\tsetSubmitting(false);\n\t}, [setSubmitting]);\n\n\tconst helpers = useMemo<CommentSubmitHelpers>(\n\t\t() => ({\n\t\t\tsetErrors: setFormErrors,\n\t\t\treset: resetComposer,\n\t\t\tsetSubmitting,\n\t\t}),\n\t\t[resetComposer, setSubmitting],\n\t);\n\n\tconst reportError = useCallback(\n\t\t(error: unknown) => {\n\t\t\ttry {\n\t\t\t\tonError?.(error);\n\t\t\t} catch (callbackError) {\n\t\t\t\tif (import.meta.env?.DEV) {\n\t\t\t\t\tconsole.warn('[Comments] onError callback failed.', callbackError);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[onError],\n\t);\n\n\tconst startReply = useCallback(\n\t\t(comment: CommentData<TUser, TMeta, TResource>) => {\n\t\t\tif (!comment.id) return;\n\t\t\tsetFormErrors({});\n\t\t\tsetComposerMode({\n\t\t\t\tkind: 'replying',\n\t\t\t\tcommentId: comment.id,\n\t\t\t\tauthorName: comment.user?.name,\n\t\t\t});\n\t\t},\n\t\t[],\n\t);\n\n\tconst startEdit = useCallback(\n\t\t(comment: CommentData<TUser, TMeta, TResource>) => {\n\t\t\tif (!comment.id) return;\n\t\t\tsetFormErrors({});\n\t\t\tsetComposerMode({ kind: 'editing', comment });\n\t\t},\n\t\t[],\n\t);\n\n\tconst cancelComposerMode = useCallback(() => {\n\t\tresetComposer();\n\t}, [resetComposer]);\n\n\tconst submit = useCallback(\n\t\tasync (values: CommentFormValues<TResource>) => {\n\t\t\tif (composerMode.kind === 'editing' && composerMode.comment.id) {\n\t\t\t\tif (!onUpdate) return;\n\t\t\t\tif (isSubmittingRef.current) return;\n\n\t\t\t\tconst payload = {\n\t\t\t\t\t...values,\n\t\t\t\t\teditingId: composerMode.comment.id,\n\t\t\t\t};\n\t\t\t\tsetSubmitting(true);\n\t\t\t\tsetFormErrors({});\n\t\t\t\ttry {\n\t\t\t\t\tawait onUpdate(composerMode.comment.id, payload, helpers);\n\t\t\t\t\tonAfterMutate?.('update', payload);\n\t\t\t\t} catch (error) {\n\t\t\t\t\treportError(error);\n\t\t\t\t} finally {\n\t\t\t\t\tsetSubmitting(false);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!onSubmit) return;\n\t\t\tif (isSubmittingRef.current) return;\n\n\t\t\tconst payload: CommentFormValues<TResource> =\n\t\t\t\tcomposerMode.kind === 'replying'\n\t\t\t\t\t? { ...values, replyToId: composerMode.commentId }\n\t\t\t\t\t: values;\n\n\t\t\tsetSubmitting(true);\n\t\t\tsetFormErrors({});\n\t\t\ttry {\n\t\t\t\tawait onSubmit(payload, helpers);\n\t\t\t\tonAfterMutate?.('create', payload);\n\t\t\t} catch (error) {\n\t\t\t\treportError(error);\n\t\t\t} finally {\n\t\t\t\tsetSubmitting(false);\n\t\t\t}\n\t\t},\n\t\t[\n\t\t\tcomposerMode,\n\t\t\thelpers,\n\t\t\tonAfterMutate,\n\t\t\tonSubmit,\n\t\t\tonUpdate,\n\t\t\treportError,\n\t\t\tsetSubmitting,\n\t\t],\n\t);\n\n\tconst deleteComment = useCallback(\n\t\tasync (id: string) => {\n\t\t\tif (!onDelete || !id) return;\n\t\t\ttry {\n\t\t\t\tawait onDelete(id);\n\t\t\t\tonAfterMutate?.('delete', { commentId: id });\n\t\t\t} catch (error) {\n\t\t\t\treportError(error);\n\t\t\t}\n\t\t},\n\t\t[onAfterMutate, onDelete, reportError],\n\t);\n\n\treturn {\n\t\tcomposerMode,\n\t\tisSubmitting,\n\t\tformErrors,\n\t\tresetKey,\n\t\tstartReply,\n\t\tstartEdit,\n\t\tcancelComposerMode,\n\t\tsubmit,\n\t\tdeleteComment,\n\t\tresetComposer,\n\t\thelpers,\n\t};\n}\n","/**\n * CommentAttachmentChip — small attachment pill used in the composer draft\n * and the timeline. Single inline row: icon + name · size, with progress /\n * error states overlaid on the same line. Editable mode reveals a remove\n * button; failed uploads expose a retry pill.\n */\nimport { File, FileText, Image as ImageIcon, Loader2, Paperclip, X } from 'lucide-react';\nimport type { FC, ReactNode } from 'react';\n\nimport { TextButton } from '../../../base/buttons';\nimport { FileSize, Percent, SecondaryValue } from '../../../primitives';\nimport { Text, TextLink } from '../../../typography';\nimport { useStrings, type StringsProp } from '../../../../lib/strings';\nimport { cn } from '../../../../lib/utils';\nimport { rowBlockPaddingClasses } from '../../../../lib/row-recipes';\nimport { fieldAffordanceRecipes } from '../../../../lib/field-affordance-recipes';\n\nimport type {\n\t\tCommentAttachment,\n\t\tCommentsAccessors,\n} from '../comments.types';\nimport {\n\t\tdefaultCommentsStrings,\n\t\ttype CommentsStrings,\n} from '../comments.strings';\nimport { interactionRecipes } from '../../../../lib/interaction-recipes';\nimport { toneRecipes } from '../../../../lib/tone-recipes';\n\nexport interface CommentAttachmentChipProps {\n\t\t/** The attachment this chip represents. */\n\t\tattachment: CommentAttachment;\n\t\t/** Editable mode shows a remove button. */\n\t\teditable?: boolean;\n\t\t/** Fired when an entry is removed. */\n\t\tonRemove?: (id: string) => void;\n\t\t/** Fired when the user retries after an entry failure. */\n\t\tonRetry?: (id: string) => void;\n\t\t/** Reads the fields this surface needs off your own shape. */\n\t\taccessors?: CommentsAccessors;\n\t\t/** Overrides this surface's own copy. */\n\t\tstrings?: StringsProp<CommentsStrings>;\n\t\t/** Compact chips have smaller text and tighter padding. */\n\t\tcompact?: boolean;\n\t\t/** Merged onto the outermost node. */\n\t\tclassName?: string;\n}\n\nfunction pickIcon(att: CommentAttachment) {\n\t\tif (att.mimeType?.startsWith('image/')) return ImageIcon;\n\t\tif (att.mimeType === 'application/pdf') return FileText;\n\t\tif (att.mimeType?.startsWith('text/')) return FileText;\n\t\tif (att.mimeType) return File;\n\t\treturn Paperclip;\n}\n\nexport const CommentAttachmentChip: FC<CommentAttachmentChipProps> = ({\n\t\tattachment,\n\t\teditable = false,\n\t\tonRemove,\n\t\tonRetry,\n\t\taccessors,\n\t\tstrings: stringsProp,\n\t\tcompact = false,\n\t\tclassName,\n}) => {\n\t\tconst strings = useStrings(defaultCommentsStrings, stringsProp);\n\n\t\tconst url = accessors?.getMediaUrl?.(attachment) ?? attachment.url;\n\t\tconst name =\n\t\t\t\taccessors?.getMediaName?.(attachment) ??\n\t\t\t\tattachment.name ??\n\t\t\t\tstrings.attachmentFallback;\n\t\tconst Icon = pickIcon(attachment);\n\n\t\tconst isUploading = attachment.status === 'uploading';\n\t\tconst isFailed = attachment.status === 'failed';\n\t\tconst meta: ReactNode = isUploading\n\t\t\t\t? (\n\t\t\t\t\t\t<SecondaryValue size=\"xs\" className=\"shrink-0\">\n\t\t\t\t\t\t\t\t{strings.attachmentUploadingLabel}\n\t\t\t\t\t\t\t\t{typeof attachment.progress === 'number' ? (\n\t\t\t\t\t\t\t\t\t\t<>\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<Percent\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue={Math.round(attachment.progress)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tscaled\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\talign=\"left\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"secondary\"\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\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t</SecondaryValue>\n\t\t\t\t)\n\t\t\t\t: isFailed\n\t\t\t\t\t? (\n\t\t\t\t\t\t\t<SecondaryValue size=\"xs\" className=\"shrink-0\">\n\t\t\t\t\t\t\t\t\t{attachment.error ?? strings.attachmentFailedLabel}\n\t\t\t\t\t\t\t</SecondaryValue>\n\t\t\t\t\t)\n\t\t\t\t\t: typeof attachment.size === 'number'\n\t\t\t\t\t\t? (\n\t\t\t\t\t\t\t<FileSize value={attachment.size} size=\"xs\" className=\"shrink-0\" />\n\t\t\t\t\t\t)\n\t\t\t\t\t\t: null;\n\n\t\tconst surface = cn(\n\t\t'comment-attachment-chip--component',\n\t\t\t\t'relative inline-flex min-w-0 max-w-[20rem] items-center gap-space-sm rounded-radius',\n\t\t\t\t'ring-1 ring-inset transition-colors',\n\t\t\t\tcompact ? 'px-control-xs' : 'px-control-sm',\n\t\t\t\trowBlockPaddingClasses.compact,\n\t\t\t\tisFailed\n\t\t\t\t\t\t? `${toneRecipes.destructive.tint} ${toneRecipes.destructive.halo}`\n\t\t\t\t\t\t: `bg-muted ring-border/60 ${interactionRecipes.rowHover}`,\n\t\t\t\tclassName,\n\t\t);\n\n\t\tconst iconNode = isUploading ? (\n\t\t\t\t<Loader2\n\t\t\t\t\t\tclassName={cn('shrink-0 animate-spin text-muted-foreground', 'size-icon-md')}\n\t\t\t\t\t\taria-hidden\n\t\t\t\t/>\n\t\t) : (\n\t\t\t\t<Icon\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t'shrink-0',\n\t\t\t\t\t\t\t\t'size-icon-md',\n\t\t\t\t\t\t\t\tisFailed ? 'text-destructive' : 'text-muted-foreground',\n\t\t\t\t\t\t)}\n\t\t\t\t\t\taria-hidden\n\t\t\t\t/>\n\t\t);\n\n\t\tconst labelRow = (\n\t\t\t\t<span className=\"inline-flex min-w-0 items-baseline gap-space-sm\">\n\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\t\ttag=\"span\"\n\t\t\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\t\t\tweight=\"medium\"\n\t\t\t\t\t\t\t\tclassName={cn('truncate', isFailed && 'text-destructive')}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{name}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t{meta}\n\t\t\t\t</span>\n\t\t);\n\n\t\tconst isInteractive = !!url && !isUploading && !isFailed;\n\n\t\treturn (\n\t\t\t\t<div className={surface}>\n\t\t\t\t\t\t{iconNode}\n\t\t\t\t\t\t{isInteractive ? (\n\t\t\t\t<TextLink\n\t\t\t\t\thref={url}\n\t\t\t\t\tsize=\"inherit\"\n\t\t\t\t\tunderline={false}\n\t\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\trel=\"noreferrer noopener\"\n\t\t\t\t\tclassName=\"inline-flex min-w-0 flex-1 items-baseline gap-space-sm hover:underline\"\n\t\t\t\t\t\t\t\t\t\taria-label={strings.attachmentDownloadLabel}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{labelRow}\n\t\t\t\t</TextLink>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\tlabelRow\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{isUploading && typeof attachment.progress === 'number' && (\n\t\t\t\t\t\t\t\t<div className={cn(toneRecipes.primary.line, 'absolute bottom-0 left-2 right-2 h-px overflow-hidden rounded-full')}>\n\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"bg-primary h-full transition-[width]\"\n\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\twidth: `${Math.min(100, Math.max(0, attachment.progress))}%`,\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\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{isFailed && onRetry && (\n\t\t\t\t\t\t\t\t<TextButton\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => onRetry(attachment.id)}\n\t\t\t\t\t\t\t\t\t\tclassName=\"shrink-0 text-destructive decoration-destructive/30 hover:decoration-destructive/60\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<Text tag=\"span\" size=\"xs\" weight=\"medium\" className=\"text-inherit\">{strings.attachmentRetryLabel}</Text>\n\t\t\t\t\t\t\t\t</TextButton>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{editable && onRemove && (\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\tonClick={() => onRemove(attachment.id)}\n\t\t\t\t\t\t\t\t\t\tclassName={cn(fieldAffordanceRecipes.target, fieldAffordanceRecipes.focus, fieldAffordanceRecipes.toggle)}\n\t\t\t\t\t\t\t\t\t\taria-label={strings.attachmentRemoveLabel}\n\t\t\t\t\t\t\t\t\t\ttitle={strings.attachmentRemoveLabel}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<X className={fieldAffordanceRecipes.icon} aria-hidden=\"true\" />\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t);\n};\n","/**\n * useAttachmentUpload — manages a list of in-flight + uploaded\n * `CommentAttachment`s for a comment composer.\n *\n * Pass the consumer-supplied `onUpload` callback directly via the\n * `attachments` prop on `<Comments>` (or `<CommentComposer>`). Aborts\n * in-flight uploads when an attachment is removed.\n */\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useStrings, type StringsProp } from '../../../../lib/strings';\nimport { defaultCommentsStrings, type CommentsStrings } from '../comments.strings';\n\nimport type {\n\tCommentAttachment,\n\tCommentsAttachmentsConfig,\n} from '../comments.types';\n\ninterface InFlightEntry {\n\tcontroller: AbortController;\n}\n\nconst defaultAttachmentUploadStrings = {\n\tattachmentTooLargeError: defaultCommentsStrings.attachmentTooLargeError,\n\tattachmentTooManyError: defaultCommentsStrings.attachmentTooManyError,\n\tattachmentFailedLabel: defaultCommentsStrings.attachmentFailedLabel,\n};\n\nexport interface UseAttachmentUploadOptions extends CommentsAttachmentsConfig {\n\t/** Initial attachments — useful when editing an existing comment. */\n\tinitialAttachments?: ReadonlyArray<CommentAttachment>;\n\t/** Fires when the list of uploaded attachments changes. */\n\tonValueChange?: (attachments: ReadonlyArray<CommentAttachment>) => void;\n\t/** Fires when a validation or upload error happens. */\n\tonError?: (error: string) => void;\n\t/** Validation and non-Error upload fallback copy; omitted keys use Comments defaults.\n\t * Error objects retain their caller-supplied message. */\n\tstrings?: StringsProp<Pick<CommentsStrings, 'attachmentTooLargeError' | 'attachmentTooManyError' | 'attachmentFailedLabel'>>;\n}\n\nexport interface UseAttachmentUploadReturn {\n\t/** All attachments — uploading + uploaded + failed. */\n\tattachments: ReadonlyArray<CommentAttachment>;\n\t/** Subset of attachments that finished uploading. Use this in the form payload. */\n\tuploadedAttachments: ReadonlyArray<CommentAttachment>;\n\t/** True while at least one upload is in flight. */\n\tisUploading: boolean;\n\t/** Add files. Validates against `maxSize` / `maxFiles` first. */\n\taddFiles: (files: ReadonlyArray<File> | FileList) => void;\n\t/** Remove an attachment by id (aborts in-flight uploads). */\n\tremoveAttachment: (id: string) => void;\n\t/** Retry a failed upload. */\n\tretryAttachment: (id: string) => void;\n\t/** Replace the list (used when editing or after submit). */\n\tsetAttachments: (attachments: ReadonlyArray<CommentAttachment>) => void;\n\t/** Clear the list and abort everything in flight. */\n\treset: () => void;\n}\n\nexport function useAttachmentUpload(\n\toptions: UseAttachmentUploadOptions = {},\n): UseAttachmentUploadReturn {\n\tconst {\n\t\tonUpload,\n\t\tmaxSize,\n\t\tmaxFiles,\n\t\t// `accept` is consumed by the surrounding `<input type=\"file\"\n\t\t// accept>` element, not here — destructuring is intentional\n\t\t// even though we don't reference it inside the hook.\n\t\tdisabled,\n\t\tinitialAttachments,\n\t\tonValueChange,\n\t\tonError,\n\t\tstrings: stringsProp,\n\t} = options;\n\tconst strings = useStrings(defaultAttachmentUploadStrings, stringsProp);\n\n\tconst [attachments, setAttachmentsState] = useState<CommentAttachment[]>(() =>\n\t\tinitialAttachments ? [...initialAttachments] : [],\n\t);\n\tconst inFlightRef = useRef<Map<string, InFlightEntry>>(new Map());\n\tconst fileCacheRef = useRef<Map<string, File>>(new Map());\n\tconst attachmentsRef = useRef(attachments);\n\t// Keep sequential picks and async updates current without calling consumers\n\t// from a React state updater (which StrictMode may evaluate more than once).\n\tconst commitAttachments = useCallback((next: ReadonlyArray<CommentAttachment>) => {\n\t\tconst list = [...next];\n\t\tattachmentsRef.current = list;\n\t\tsetAttachmentsState(list);\n\t}, []);\n\tconst onValueChangeRef = useRef(onValueChange);\n\tonValueChangeRef.current = onValueChange;\n\n\tconst updateAttachment = useCallback(\n\t\t(id: string, patch: Partial<CommentAttachment>) => {\n\t\t\tcommitAttachments(attachmentsRef.current.map((a) => (a.id === id ? { ...a, ...patch } : a)));\n\t\t},\n\t\t[commitAttachments],\n\t);\n\n\tconst setAttachments = useCallback(\n\t\t(next: ReadonlyArray<CommentAttachment>) => {\n\t\t\tcommitAttachments(next);\n\t\t},\n\t\t[commitAttachments],\n\t);\n\n\tconst beginUpload = useCallback(\n\t\t(id: string, file: File) => {\n\t\t\tif (!onUpload || !fileCacheRef.current.has(id)) return;\n\t\t\tconst controller = new AbortController();\n\t\t\tinFlightRef.current.set(id, { controller });\n\n\t\t\tupdateAttachment(id, {\n\t\t\t\tstatus: 'uploading',\n\t\t\t\tprogress: 0,\n\t\t\t\terror: undefined,\n\t\t\t});\n\n\t\t\tconst onProgress = (progress: number) => {\n\t\t\t\tif (controller.signal.aborted) return;\n\t\t\t\tupdateAttachment(id, { progress });\n\t\t\t};\n\n\t\t\tonUpload({ file, onProgress, signal: controller.signal })\n\t\t\t\t.then((uploaded) => {\n\t\t\t\t\tif (controller.signal.aborted) return;\n\t\t\t\t\tinFlightRef.current.delete(id);\n\t\t\t\t\tupdateAttachment(id, {\n\t\t\t\t\t\t...uploaded,\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tstatus: 'uploaded',\n\t\t\t\t\t\tprogress: 100,\n\t\t\t\t\t\terror: undefined,\n\t\t\t\t\t});\n\t\t\t\t})\n\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\tinFlightRef.current.delete(id);\n\t\t\t\t\tif (controller.signal.aborted) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst message =\n\t\t\t\t\t\terr instanceof Error ? err.message : strings.attachmentFailedLabel;\n\t\t\t\t\tupdateAttachment(id, {\n\t\t\t\t\t\tstatus: 'failed',\n\t\t\t\t\t\terror: message,\n\t\t\t\t\t});\n\t\t\t\t\tonError?.(message);\n\t\t\t\t});\n\t\t},\n\t\t[onError, onUpload, strings.attachmentFailedLabel, updateAttachment],\n\t);\n\n\tconst addFiles = useCallback(\n\t\t(filesInput: ReadonlyArray<File> | FileList) => {\n\t\t\tif (disabled || !onUpload) return;\n\t\t\tconst files = Array.from(filesInput);\n\t\t\tif (files.length === 0) return;\n\n\t\t\tconst next = [...attachmentsRef.current];\n\t\t\tconst pending: Array<{id: string; file: File}> = [];\n\t\t\tfor (const file of files) {\n\t\t\t\tif (\n\t\t\t\t\ttypeof maxFiles === 'number' &&\n\t\t\t\t\tnext.length >= maxFiles\n\t\t\t\t) {\n\t\t\t\t\tonError?.(strings.attachmentTooManyError);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\ttypeof maxSize === 'number' &&\n\t\t\t\t\tfile.size > maxSize\n\t\t\t\t) {\n\t\t\t\t\tonError?.(strings.attachmentTooLargeError);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst id =\n\t\t\t\t\ttypeof crypto !== 'undefined' && 'randomUUID' in crypto\n\t\t\t\t\t\t? crypto.randomUUID()\n\t\t\t\t\t\t: `att-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n\n\t\t\t\tfileCacheRef.current.set(id, file);\n\n\t\t\t\tnext.push({\n\t\t\t\t\tid,\n\t\t\t\t\tname: file.name,\n\t\t\t\t\tsize: file.size,\n\t\t\t\t\tmimeType: file.type,\n\t\t\t\t\tstatus: 'uploading',\n\t\t\t\t\tprogress: 0,\n\t\t\t\t});\n\n\t\t\t\tpending.push({id, file});\n\t\t\t}\n\t\t\tcommitAttachments(next);\n\t\t\tfor (const {id, file} of pending) queueMicrotask(() => beginUpload(id, file));\n\t\t},\n\t\t[beginUpload, commitAttachments, disabled, maxFiles, maxSize, onError, onUpload, strings.attachmentTooLargeError, strings.attachmentTooManyError],\n\t);\n\n\tconst removeAttachment = useCallback((id: string) => {\n\t\tconst entry = inFlightRef.current.get(id);\n\t\tif (entry) {\n\t\t\tentry.controller.abort();\n\t\t\tinFlightRef.current.delete(id);\n\t\t}\n\t\tfileCacheRef.current.delete(id);\n\t\tcommitAttachments(attachmentsRef.current.filter((a) => a.id !== id));\n\t}, [commitAttachments]);\n\n\tconst retryAttachment = useCallback(\n\t\t(id: string) => {\n\t\t\tconst file = fileCacheRef.current.get(id);\n\t\t\tif (!file) return;\n\t\t\tbeginUpload(id, file);\n\t\t},\n\t\t[beginUpload],\n\t);\n\n\tconst reset = useCallback(() => {\n\t\tfor (const entry of inFlightRef.current.values()) {\n\t\t\tentry.controller.abort();\n\t\t}\n\t\tinFlightRef.current.clear();\n\t\tfileCacheRef.current.clear();\n\t\tcommitAttachments([]);\n\t}, [commitAttachments]);\n\n\tuseEffect(() => {\n\t\tonValueChangeRef.current?.(attachments);\n\t}, [attachments]);\n\n\tuseEffect(() => {\n\t\tconst inFlight = inFlightRef.current;\n\t\tconst cache = fileCacheRef.current;\n\t\treturn () => {\n\t\t\tfor (const entry of inFlight.values()) {\n\t\t\t\tentry.controller.abort();\n\t\t\t}\n\t\t\tcache.clear();\n\t\t};\n\t}, []);\n\n\tconst uploadedAttachments = useMemo(\n\t\t() => attachments.filter((a) => a.status === 'uploaded' || !a.status),\n\t\t[attachments],\n\t);\n\n\tconst isUploading = useMemo(\n\t\t() => attachments.some((a) => a.status === 'uploading'),\n\t\t[attachments],\n\t);\n\n\treturn {\n\t\tattachments,\n\t\tuploadedAttachments,\n\t\tisUploading,\n\t\taddFiles,\n\t\tremoveAttachment,\n\t\tretryAttachment,\n\t\tsetAttachments,\n\t\treset,\n\t};\n}\n","import {compositionRhythm} from '../../../base/structure/composition.recipes';\n/**\n * CommentComposer — TipTap-backed rich text editor with inline reference\n * picker and attachment uploader. Default composer for `<Comments>`.\n *\n * Mention/reference handling is delegated to the shared\n * `features/mentions` module: `useMentions` drives picker state +\n * caret-trigger detection, `<MentionPicker>` renders the popover, and\n * `<MentionChip>` renders draft-list chips. The same primitives power\n * inline references in `features/activities`.\n */\nimport { AtSign, Loader2, Paperclip, X } from 'lucide-react';\nimport {\n\t\tforwardRef,\n\t\tuseEffect,\n\t\tuseImperativeHandle,\n\t\tuseMemo,\n\t\tuseRef,\n\t\tuseState,\n} from 'react';\nimport type { ReactNode } from 'react';\nimport type { ReactElement, RefAttributes } from 'react';\n\nimport { Button } from '../../../base/buttons';\nimport { Popover, PopoverTrigger } from '../../../base/popover';\nimport { Stack } from '../../../base/structure';\nimport { DisplayLabel, Text } from '../../../typography';\nimport {\n\t\tRichTextEditor,\n\t\ttype RichTextEditorHandle,\n\t\ttype RichTextEditorToolbarItem,\n} from '../../rich-text-editor/rich-text-editor';\nimport {\n\t\tMentionInlineSuggestions,\n\t\tMentionPicker,\n\t\tparseMentionsFromHtml,\n\t\tuseMentions,\n} from '../../mentions';\nimport { useResolvedStrings } from '../comments-provider';\nimport { interpolateString } from '../../../../lib/strings';\nimport { rowBlockPaddingClasses } from '../../../../lib/row-recipes';\nimport { cn } from '../../../../lib/utils';\nimport { fieldAffordanceRecipes } from '../../../../lib/field-affordance-recipes';\nimport type {\n\t\tCommentComposerProps,\n\t\tCommentFormValues,\n} from '../comments.types';\nimport { CommentAttachmentChip } from './comment-attachment-chip';\nimport { useAttachmentUpload } from '../hooks/use-attachment-upload';\n\nexport interface CommentComposerHandle {\n\t\tfocus(): void;\n\t\tclear(): void;\n\t\t/** Imperatively set the draft body. */\n\t\tsetBody(html: string): void;\n}\n\nfunction hasMeaningfulContent(html: string): boolean {\n\t\tif (!html || typeof html !== 'string') return false;\n\t\tconst text = html.replace(/<[^>]*>/g, '').trim();\n\t\treturn text.length > 0;\n}\n\nconst CommentComposerBase = forwardRef<\n\t\tCommentComposerHandle,\n\t\tCommentComposerProps\n>(function CommentComposer(\n\t\t{\n\t\t\t\tcontext,\n\t\t\t\tcanComment = true,\n\t\t\t\tsubmitting = false,\n\t\t\t\terrors,\n\t\t\t\tresetKey = 0,\n\t\t\t\tonSubmit,\n\t\t\t\tonCancel,\n\t\t\t\teditingComment,\n\t\t\t\treplyingTo,\n\t\t\t\tstrings: stringsProp,\n\t\t\t\tresources: resourcesProp,\n\t\t\t\tonResourceSearch: onResourceSearchProp,\n\t\t\t\tattachments: attachmentsProp,\n\t\t\t\tmaxAttachments: maxAttachmentsProp,\n\t\t\t\tallowAttachments: allowAttachmentsProp,\n\t\t\t\tinitialValues,\n\t\t\t\tautoFocus = false,\n\t\t\t\tinlineSubmit = true,\n\t\t\t\tplaceholder,\n\t\t},\n\t\tref,\n) {\n\t\tconst strings = useResolvedStrings(stringsProp);\n\t\tconst resources = resourcesProp;\n\t\tconst onResourceSearch = onResourceSearchProp;\n\t\tconst allowAttachments = allowAttachmentsProp ?? true;\n\t\tconst maxAttachments =\n\t\t\t\tattachmentsProp?.maxFiles ??\n\t\t\t\tmaxAttachmentsProp ??\n\t\t\t\t5;\n\t\tconst attachmentsConfig = useMemo(\n\t\t\t\t() => ({\n\t\t\t\t\t\t...attachmentsProp,\n\t\t\t\t\t\tmaxFiles: maxAttachments,\n\t\t\t\t\t\tdisabled: attachmentsProp?.disabled === true || !allowAttachments,\n\t\t\t\t}),\n\t\t\t\t[allowAttachments, attachmentsProp, maxAttachments],\n\t\t);\n\n\t\tconst editorRef = useRef<RichTextEditorHandle>(null);\n\t\tconst [body, setBody] = useState<string>(\n\t\t\t\t() => initialValues?.content ?? editingComment?.content ?? '',\n\t\t);\n\t\tconst [contentError, setContentError] = useState<string | null>(null);\n\t\tconst [attachmentError, setAttachmentError] = useState<string | null>(null);\n\n\t\t/**\n\t\t * Mentions state — picker + caret-trigger detection. The hook reads\n\t\t * the editor handle via the ref we pass; on suggestion select it\n\t\t * inserts the chip and replaces the trigger range automatically.\n\t\t */\n\t\tconst mentions = useMentions({\n\t\t\t\tresources,\n\t\t\t\tonResourceSearch,\n\t\t\t\teditorRef,\n\t\t\t\tinitialMentions:\n\t\t\t\t\t\tinitialValues?.references ?? editingComment?.references,\n\t\t});\n\n\t\tconst attachmentUpload = useAttachmentUpload({\n\t\t\t\t...attachmentsConfig,\n\t\t\t\tinitialAttachments: initialValues?.attachments ?? undefined,\n\t\t\t\tstrings,\n\t\t\t\tonError: setAttachmentError,\n\t\t});\n\t\tconst handleCancel = () => {\n\t\t\t\tattachmentUpload.reset();\n\t\t\t\tsetAttachmentError(null);\n\t\t\t\tonCancel?.();\n\t\t};\n\n\t\tuseImperativeHandle(\n\t\t\t\tref,\n\t\t\t\t() => ({\n\t\t\t\t\t\tfocus: () => editorRef.current?.focus(),\n\t\t\t\t\t\tclear: () => {\n\t\t\t\t\t\t\t\teditorRef.current?.clear();\n\t\t\t\t\t\t\t\tmentions.reset();\n\t\t\t\t\t\t\t\tattachmentUpload.reset();\n\t\t\t\t\t\t\t\tsetContentError(null);\n\t\t\t\t\t\t\t\tsetAttachmentError(null);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsetBody: (html) => {\n\t\t\t\t\t\t\t\teditorRef.current?.setHTML(html);\n\t\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t\t[attachmentUpload, mentions],\n\t\t);\n\n\t\t// Reset on context change / resetKey bump\n\t\tuseEffect(() => {\n\t\t\t\teditorRef.current?.setHTML(initialValues?.content ?? '');\n\t\t\t\tmentions.setMentions(initialValues?.references ?? []);\n\t\t\t\tattachmentUpload.reset();\n\t\t\t\tattachmentUpload.setAttachments(initialValues?.attachments ?? []);\n\t\t\t\tsetContentError(null);\n\t\t\t\tsetAttachmentError(null);\n\t\t\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t\t}, [context.id, context.type, resetKey]);\n\n\t\t// Sync editing comment payload\n\t\tuseEffect(() => {\n\t\t\t\tif (!editingComment) return;\n\t\t\t\teditorRef.current?.setHTML(editingComment.content ?? '');\n\t\t\t\tmentions.setMentions(editingComment.references ?? []);\n\t\t\t\tconst list = (editingComment.attachments ?? []).filter(\n\t\t\t\t\t\t(a): a is NonNullable<typeof a> => !!a,\n\t\t\t\t);\n\t\t\t\tattachmentUpload.reset();\n\t\t\t\tattachmentUpload.setAttachments(list);\n\t\t\t\tsetAttachmentError(null);\n\t\t\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t\t}, [editingComment?.id]);\n\n\t\t// Surface server-side errors\n\t\tuseEffect(() => {\n\t\t\t\tif (errors?.content) {\n\t\t\t\t\t\tsetContentError(errors.content);\n\t\t\t\t}\n\t\t}, [errors]);\n\n\t\tconst handleSubmit = (event?: React.FormEvent) => {\n\t\t\t\tevent?.preventDefault();\n\t\t\t\tif (submitting || attachmentUpload.isUploading) return;\n\t\t\t\tconst html = editorRef.current?.getHTML() ?? body;\n\t\t\t\tif (!hasMeaningfulContent(html)) {\n\t\t\t\t\t\tsetContentError(strings.invalidContent);\n\t\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsetContentError(null);\n\n\t\t\t\tconst values: CommentFormValues = {\n\t\t\t\t\t\tcontent: html,\n\t\t\t\t\t\tcommentableId: context.id,\n\t\t\t\t\t\tcommentableType: context.type,\n\t\t\t\t\t\tmoduleKey: context.moduleKey,\n\t\t\t\t\t\tcontentType: 'html',\n\t\t\t\t\t\treferences: mentions.mentions,\n\t\t\t\t\t\tattachments: attachmentUpload.uploadedAttachments,\n\t\t\t\t\t\treplyToId: replyingTo?.commentId ?? initialValues?.replyToId,\n\t\t\t\t\t\teditingId: editingComment?.id,\n\t\t\t\t};\n\n\t\t\t\tonSubmit(values);\n\t\t};\n\n\t\tconst fileInputRef = useRef<HTMLInputElement>(null);\n\t\tconst handleAttachmentClick = () => fileInputRef.current?.click();\n\t\tconst handleFiles = (files: FileList | null) => {\n\t\t\t\tif (!files?.length) return;\n\t\t\t\tsetAttachmentError(null);\n\t\t\t\tattachmentUpload.addFiles(files);\n\t\t};\n\n\t\tconst hasAttachments = attachmentUpload.attachments.length > 0;\n\t\tconst isEditing = !!editingComment;\n\t\tconst isReplying = !isEditing && !!replyingTo;\n\n\t\tconst submitLabel = submitting\n\t\t\t\t? strings.composerSubmitting\n\t\t\t\t: isEditing\n\t\t\t\t\t? strings.composerSave\n\t\t\t\t\t: strings.composerSubmit;\n\n\t\tconst eyebrow: ReactNode = isEditing ? (\n\t\t\t\t<ComposerEyebrow\n\t\t\t\t\t\tlabel={strings.composerEditingEyebrow}\n\t\t\t\t\t\tcloseLabel={strings.composerCancel}\n\t\t\t\t\t\tonClose={onCancel ? handleCancel : undefined}\n\t\t\t\t/>\n\t\t) : isReplying ? (\n\t\t\t\t<ComposerEyebrow\n\t\t\t\t\t\tlabel={makeReplyEyebrow(\n\t\t\t\t\t\t\t\tstrings.composerReplyingEyebrow,\n\t\t\t\t\t\t\t\treplyingTo.authorName,\n\t\t\t\t\t\t)}\n\t\t\t\t\t\tcloseLabel={strings.composerCancel}\n\t\t\t\t\t\tonClose={onCancel ? handleCancel : undefined}\n\t\t\t\t/>\n\t\t) : null;\n\n\t\tconst extraToolbarItems = useMemo<ReadonlyArray<RichTextEditorToolbarItem>>(() => {\n\t\t\t\tconst items: RichTextEditorToolbarItem[] = [];\n\t\t\t\tif (resources && Object.keys(resources).length > 0) {\n\t\t\t\t\t\titems.push({\n\t\t\t\t\t\t\t\tid: 'reference',\n\t\t\t\t\t\t\t\ticon: AtSign,\n\t\t\t\t\t\t\t\tlabel: strings.composerReferenceLabel,\n\t\t\t\t\t\t\t\tonClick: () => mentions.setPickerOpen(true),\n\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (attachmentsConfig?.onUpload && !attachmentsConfig.disabled) {\n\t\t\t\t\t\titems.push({\n\t\t\t\t\t\t\t\tid: 'attachment',\n\t\t\t\t\t\t\t\ticon: Paperclip,\n\t\t\t\t\t\t\t\tlabel: strings.composerAttachmentLabel,\n\t\t\t\t\t\t\t\tonClick: handleAttachmentClick,\n\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn items;\n\t\t\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t\t}, [\n\t\t\t\tresources,\n\t\t\t\tattachmentsConfig?.onUpload,\n\t\t\t\tattachmentsConfig?.disabled,\n\t\t\t\tstrings.composerReferenceLabel,\n\t\t\t\tstrings.composerAttachmentLabel,\n\t\t]);\n\n\t\tif (!canComment) return null;\n\n\t\tconst submitButton = (\n\t\t\t\t<Button tone=\"primary\"\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={() => handleSubmit()}\n\t\t\t\t\t\tdisabled={submitting || attachmentUpload.isUploading}\n\t\t\t\t\t\ticon={submitting ? Loader2 : undefined}\n\t\t\t\t>\n\t\t\t\t\t\t{submitLabel}\n\t\t\t\t</Button>\n\t\t);\n\n\t\tconst cancelButton = (isEditing || isReplying || onCancel) ? (\n\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\tonClick={handleCancel}\n\t\t\t\t\t\tdisabled={submitting}\n\t\t\t\t>\n\t\t\t\t\t\t{strings.composerCancel}\n\t\t\t\t</Button>\n\t\t) : null;\n\n\t\t// Mentions live as inline `<span class=\"rsc-mention\" contenteditable=\"false\">`\n\t\t// chips inside the editor body — they're visible, dismissible (single\n\t\t// backspace deletes the whole span), and the HTML→mentions sync keeps\n\t\t// `mentions.mentions` aligned automatically. Rendering them again as a\n\t\t// chip-list below the editor was redundant and confusing.\n\n\t\tconst attachmentChips = hasAttachments ? (\n\t\t\t\t<Stack direction=\"horizontal\" wrap align=\"center\" gap=\"sm\">\n\t\t\t\t\t\t{attachmentUpload.attachments.map((attachment) => (\n\t\t\t\t\t\t\t\t<CommentAttachmentChip\n\t\t\t\t\t\t\t\t\t\tkey={attachment.id}\n\t\t\t\t\t\t\t\t\t\tattachment={attachment}\n\t\t\t\t\t\t\t\t\t\teditable\n\t\t\t\t\t\t\t\t\t\tonRemove={(id) => { setAttachmentError(null); attachmentUpload.removeAttachment(id); }}\n\t\t\t\t\t\t\t\t\t\tonRetry={(id) => { setAttachmentError(null); attachmentUpload.retryAttachment(id); }}\n\t\t\t\t\t\t\t\t\t\tstrings={stringsProp}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t))}\n\t\t\t\t</Stack>\n\t\t) : null;\n\n\t\tconst footerSlot = hasAttachments ? attachmentChips : null;\n\n\t\tconst trailingSubmit =\n\t\t\t\tinlineSubmit !== false && !isEditing && !isReplying\n\t\t\t\t\t\t? submitButton\n\t\t\t\t\t\t: null;\n\t\tconst showFooterRow = inlineSubmit === false || isEditing || isReplying;\n\n\t\treturn (\n\t\t<Stack render={<form />} gap=\"md\" onSubmit={handleSubmit} className=\"comment-composer--component\">\n\t\t\t\t\t\t{eyebrow}\n\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\tref={fileInputRef}\n\t\t\t\t\t\t\t\ttype=\"file\"\n\t\t\t\t\t\t\t\tmultiple\n\t\t\t\t\t\t\t\thidden\n\t\t\t\t\t\t\t\taccept={attachmentsConfig?.accept}\n\t\t\t\t\t\t\t\tonChange={(e) => {\n\t\t\t\t\t\t\t\t\t\thandleFiles(e.target.files);\n\t\t\t\t\t\t\t\t\t\te.target.value = '';\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t{/* Manual button-click flow: regular popover anchored to the\n\t\t\t\t\t\t\t\thidden trigger. The inline-trigger flow uses the panel\n\t\t\t\t\t\t\t\trendered below — no focus stealing while the user types. */}\n\t\t\t\t\t\t{!mentions.triggerActive && (\n\t\t\t\t\t\t\t\t<Popover open={mentions.pickerOpen} onOpenChange={mentions.setPickerOpen}>\n\t\t\t\t\t\t\t\t\t\t<PopoverTrigger\n\t\t\t\t\t\t\t\t\t\t\t\trender={\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"sr-only\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttabIndex={-1}\n\t\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\t\t\t\t{strings.composerReferenceLabel}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</Button>\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\t\t\t\t\t\t\t\t\t\t<MentionPicker\n\t\t\t\t\t\t\t\t\t\t\t\topen={mentions.pickerOpen}\n\t\t\t\t\t\t\t\t\t\t\t\tactiveKind={mentions.activeKind}\n\t\t\t\t\t\t\t\t\t\t\t\tsetActiveKind={(kind) => { mentions.setActiveKind(kind); mentions.setManualKindOverride(true); }}\n\t\t\t\t\t\t\t\t\t\t\t\tkinds={mentions.kinds}\n\t\t\t\t\t\t\t\t\t\t\t\tresources={resources}\n\t\t\t\t\t\t\t\t\t\t\t\tquery={mentions.query}\n\t\t\t\t\t\t\t\t\t\t\t\tsetQuery={mentions.setQuery}\n\t\t\t\t\t\t\t\t\t\t\t\tsuggestions={mentions.suggestions}\n\t\t\t\t\t\t\t\t\t\t\t\tloading={mentions.isLoading}\n\t\t\t\t\t\t\t\t\t\t\t\tonSelect={mentions.pickSuggestion}\n\t\t\t\t\t\t\t\t\t\t\t\tstrings={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle: strings.composerReferenceMenuTitle,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsearchPlaceholder: strings.composerReferenceSearchPlaceholder,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tempty: strings.composerReferenceEmpty,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tloading: strings.composerReferenceLoading,\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\t\t\t\t\t\t\t\t</Popover>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t<div className=\"comment-composer--editor relative\" onBlur={mentions.handleBlur}>\n\t\t\t\t\t\t\t\t<RichTextEditor\n\t\t\t\t\t\t\t\t\t\tref={editorRef}\n\t\t\t\t\t\t\t\t\t\tvalue={body}\n\t\t\t\t\t\t\t\t\t\tonValueChange={(html) => {\n\t\t\t\t\t\t\t\t\t\t\t\tsetBody(html);\n\t\t\t\t\t\t\t\t\t\t\t\t// Sync the draft's mentions list with what's\n\t\t\t\t\t\t\t\t\t\t\t\t// actually present in the HTML — when the user\n\t\t\t\t\t\t\t\t\t\t\t\t// backspaces a chip span out of the body, the\n\t\t\t\t\t\t\t\t\t\t\t\t// chip-list below shrinks too. We merge with\n\t\t\t\t\t\t\t\t\t\t\t\t// the previously-known list so consumer-supplied\n\t\t\t\t\t\t\t\t\t\t\t\t// `href` / `data` payloads survive parsing.\n\t\t\t\t\t\t\t\t\t\t\t\tconst parsed = parseMentionsFromHtml<string>(html);\n\t\t\t\t\t\t\t\t\t\t\t\tconst previous = mentions.mentions;\n\t\t\t\t\t\t\t\t\t\t\t\tconst previousIds = previous.map((m) => m.id).join('|');\n\t\t\t\t\t\t\t\t\t\t\t\tconst currentIds = parsed.map((m) => m.id).join('|');\n\t\t\t\t\t\t\t\t\t\t\t\tif (previousIds !== currentIds) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst byId = new Map(previous.map((m) => [m.id, m]));\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst merged = parsed.map(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(p) => byId.get(p.id) ?? p,\n\t\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\t\tmentions.setMentions(merged);\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\t\t\t\t\t\t\t\t\t\tplaceholder={placeholder ?? strings.composerPlaceholder}\n\t\t\t\t\t\t\t\t\t\tstrings={{\n\t\t\t\t\t\t\t\t\t\t\t\teditorLabel: placeholder ?? strings.composerPlaceholder,\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\tbodyHeight=\"field\"\n\t\t\t\t\t\t\t\t\t\tautoFocus={autoFocus || isEditing || isReplying}\n\t\t\t\t\t\t\t\t\t\textraToolbarItems={extraToolbarItems}\n\t\t\t\t\t\t\t\t\t\ttoolbarTrailing={trailingSubmit}\n\t\t\t\t\t\t\t\t\t\tfooterSlot={footerSlot}\n\t\t\t\t\t\t\t\t\t\tonCaretChange={mentions.handleCaretChange}\n\t\t\t\t\t\t\t\t\t\tonEditorKeyDown={mentions.handleKeyDown}\n\t\t\t\t\t\t\t\t\t\tsuggestionPopup={mentions.suggestionPopup}\n\t\t\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t\t\t<MentionInlineSuggestions\n\t\t\t\t\t\t\t\t\t\topen={mentions.inlineOpen}\n\t\t\t\t\t\t\t\t\t\tlistboxId={mentions.listboxId}\n\t\t\t\t\t\t\t\t\t\tactiveIndex={mentions.activeIndex}\n\t\t\t\t\t\t\t\t\t\tactiveKind={mentions.activeKind}\n\t\t\t\t\t\t\t\t\t\tsetActiveKind={(kind) => { mentions.setActiveKind(kind); mentions.setManualKindOverride(true); }}\n\t\t\t\t\t\t\t\t\t\tkinds={mentions.kinds}\n\t\t\t\t\t\t\t\t\t\tresources={resources}\n\t\t\t\t\t\t\t\t\t\tquery={mentions.query}\n\t\t\t\t\t\t\t\t\t\tsuggestions={mentions.suggestions}\n\t\t\t\t\t\t\t\t\t\tsuggestionsByKind={mentions.suggestionsByKind}\n\t\t\t\t\t\t\t\t\t\tloading={mentions.isLoading}\n\t\t\t\t\t\t\t\t\t\tonSelect={mentions.pickSuggestion}\n\t\t\t\t\t\t\t\t\t\tstrings={{\n\t\t\t\t\t\t\t\t\t\t\t\ttitle: strings.composerReferenceMenuTitle,\n\t\t\t\t\t\t\t\t\t\t\t\tempty: strings.composerReferenceEmpty,\n\t\t\t\t\t\t\t\t\t\t\t\tloading: strings.composerReferenceLoading,\n\t\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</div>\n\n\t\t\t\t\t\t{attachmentError && (\n\t\t\t\t\t\t\t\t<Text role=\"alert\" size=\"xs\" type=\"error\" className=\"comment-composer--attachment-error\">\n\t\t\t\t\t\t\t\t\t\t{attachmentError}\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{contentError && (\n\t\t\t\t\t\t\t\t<Text size=\"xs\" type=\"error\">\n\t\t\t\t\t\t\t\t\t\t{contentError}\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{showFooterRow && (\n\t\t\t\t\t\t\t\t<Stack direction=\"horizontal\" align=\"center\" justify=\"end\" gap={compositionRhythm.commands} className=\"comment-composer--footer-actions\">\n\t\t\t\t\t\t\t\t\t\t{cancelButton}\n\t\t\t\t\t\t\t\t\t\t{submitButton}\n\t\t\t\t\t\t\t\t</Stack>\n\t\t\t\t\t\t)}\n\t\t</Stack>\n\t\t);\n});\n\n/** Preserve the consumer's resource-kind union through the forwarded-ref boundary. */\nexport const CommentComposer = CommentComposerBase as <\n\t\tTResource extends string = string,\n>(\n\t\tprops: CommentComposerProps<TResource> & RefAttributes<CommentComposerHandle>,\n) => ReactElement | null;\n\n/* ------------------------------------------------------------------ */\n/* ComposerEyebrow */\n/* ------------------------------------------------------------------ */\n\nfunction ComposerEyebrow({\n\t\tlabel,\n\t\tcloseLabel,\n\t\tonClose,\n}: {\n\t\tlabel: string;\n\t\tcloseLabel: string;\n\t\tonClose?: () => void;\n}) {\n\t\treturn (\n\t\t\t\t<div className={cn('comment-composer--eyebrow bg-muted/30 ring-border/60 flex min-w-0 items-center justify-between gap-space-sm rounded-radius px-row-x ring-1 ring-inset', rowBlockPaddingClasses.compact)}>\n\t\t\t\t\t\t<DisplayLabel>\n\t\t\t\t\t\t\t\t{label}\n\t\t\t\t\t\t</DisplayLabel>\n\t\t\t\t\t\t{onClose ? (\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\tonClick={onClose}\n\t\t\t\t\t\t\t\t\t\tclassName={cn(fieldAffordanceRecipes.target, fieldAffordanceRecipes.focus, fieldAffordanceRecipes.toggle)}\n\t\t\t\t\t\t\t\t\t\taria-label={closeLabel}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<X className={fieldAffordanceRecipes.icon} aria-hidden=\"true\" />\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t);\n}\n\n/** Helper export for templated reply eyebrow. */\nexport function makeReplyEyebrow(template: string, name?: string): string {\n\t\treturn interpolateString(template, { name }, { missing: 'empty' });\n}\n","/**\n * CommentEmpty — default empty state for the timeline. Replaceable via\n * the `emptySlot` prop on `<Comments>` / `<CommentTimeline>`.\n */\nimport { MessageCircle } from 'lucide-react';\nimport type { FC, ReactNode } from 'react';\n\nimport { EmptyState } from '../../../blocks/data-display';\nimport type { StringsProp } from '../../../../lib/strings';\nimport { cn } from '../../../../lib/utils';\n\nimport { useResolvedStrings } from '../comments-provider';\nimport type { CommentsStrings } from '../comments.strings';\n\nexport interface CommentEmptyProps {\n\t/** Overrides this surface's own copy. */\n\tstrings?: StringsProp<CommentsStrings>;\n\t/** Leading glyph. */\n\ticon?: ReactNode;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n}\n\nexport const CommentEmpty: FC<CommentEmptyProps> = ({\n\tstrings: stringsProp,\n\ticon,\n\tclassName,\n}) => {\n\tconst strings = useResolvedStrings(stringsProp);\n\n\treturn (\n\t\t<EmptyState\n\t\t\ttitle={strings.empty}\n\t\t\tdescription={strings.emptyHint || false}\n\t\t\tmedia={icon ?? <MessageCircle className=\"size-icon\" aria-hidden=\"true\" />}\n\t\t\tmediaVariant=\"icon-soft\"\n\t\t\tpadding=\"md\"\n\t\t\tclassName={cn('comment-empty--component', className)}\n\t\t/>\n\t);\n};\n","import type { ReactNode } from 'react';\nimport { Fragment, createElement } from 'react';\n\nimport { Text } from '../../../typography';\nimport { sanitizeHtml } from '../../../../lib/sanitize-html';\nimport { contentTypographyClassName } from '../../../typography/content-typography';\n\nimport { RichText } from '../../../typography/rich-text';\nimport { MentionContent } from '../../mentions';\n\nimport type {\n\tCommentData,\n\tCommentUser,\n\tCommentsConfig,\n\tCommentsSlots,\n} from '../comments.types';\n\nexport interface CommentContentProps<\n\tTUser extends CommentUser = CommentUser,\n\tTMeta = unknown,\n\tTResource extends string = string,\n> {\n\t/** The comment to render. */\n\tcomment: CommentData<TUser, TMeta, TResource>;\n\t/** Resource registry — passed through to `<MentionContent>`. */\n\tresources?: CommentsConfig<TUser, TMeta, TResource>['resources'];\n\t/** Replaces the default rendering of an inline reference. */\n\trenderReference?: CommentsSlots<\n\t\tTUser,\n\t\tTMeta,\n\t\tTResource\n\t>['renderReference'];\n\t/** Optional sanitizer override. The package safe allowlist is the default. */\n\tsanitizer?: (html: string) => string;\n}\n\nexport function CommentContent<\n\tTUser extends CommentUser = CommentUser,\n\tTMeta = unknown,\n\tTResource extends string = string,\n>(\n\tprops: CommentContentProps<TUser, TMeta, TResource>,\n): ReactNode {\n\tconst { comment, resources, renderReference, sanitizer } = props;\n\tconst contentType =\n\t\tcomment.contentType ??\n\t\t(comment as Record<string, unknown>).content_type ??\n\t\t'text';\n\n\tif (contentType === 'rich') {\n\t\tconst richContent = renderRichContent(comment.content);\n\t\treturn richContent ? (\n\t\t\t<div className=\"comment-content--component\">{richContent}</div>\n\t\t) : null;\n\t}\n\n\tif (contentType === 'html') {\n\t\treturn (\n\t\t\t<div className=\"comment-content--component\">\n\t\t\t\t<MentionContent<TResource>\n\t\t\t\t\tclassName=\"text-inherit\"\n\t\t\t\t\thtml={comment.content ?? ''}\n\t\t\t\t\tmentions={comment.references}\n\t\t\t\t\tresources={resources}\n\t\t\t\t\trenderMention={renderReference}\n\t\t\t\t\tsanitizer={sanitizer}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t);\n\t}\n\n\tconst plainContent = decodeQuotedString(comment.content ?? '');\n\n\treturn (\n\t\t<Text type=\"inherit\" className=\"comment-content--component whitespace-pre-line\">\n\t\t\t{plainContent}\n\t\t</Text>\n\t);\n}\n\n/* ------------------------------------------------------------------ */\n/* Rich-block renderer for Editor.js-style structured content */\n/* ------------------------------------------------------------------ */\n\nfunction renderRichContent(rawContent: string | null | undefined): ReactNode {\n\tif (!rawContent) return null;\n\n\ttry {\n\t\tconst parsed = JSON.parse(rawContent) as {\n\t\t\tblocks?: Array<{ id?: string; type: string; data?: Record<string, unknown> }>;\n\t\t};\n\n\t\tif (!parsed || !Array.isArray(parsed.blocks) || parsed.blocks.length === 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn (\n\t\t\t<Text tag=\"div\" type=\"inherit\" className={contentTypographyClassName}>\n\t\t\t\t{parsed.blocks.map((block, index) => (\n\t\t\t\t\t<Fragment key={block.id ?? `${block.type}-${index}`}>\n\t\t\t\t\t\t{renderRichBlock(block)}\n\t\t\t\t\t</Fragment>\n\t\t\t\t))}\n\t\t\t</Text>\n\t\t);\n\t} catch {\n\t\tconst decoded = decodeQuotedString(rawContent);\n\t\treturn (\n\t\t\t<Text type=\"inherit\" className=\"whitespace-pre-line\">\n\t\t\t\t{decoded}\n\t\t\t</Text>\n\t\t);\n\t}\n}\n\nfunction renderRichBlock(block: { type: string; data?: Record<string, unknown> }): ReactNode {\n\tconst data = block.data ?? {};\n\n\tswitch (block.type) {\n\t\tcase 'paragraph': {\n\t\t\tconst raw = String(data.text ?? '').trim();\n\t\t\tif (!raw) return null;\n\t\t\tconst html = sanitizeHtml(raw);\n\t\t\treturn html ? <p dangerouslySetInnerHTML={{ __html: html }} /> : null;\n\t\t}\n\t\tcase 'header': {\n\t\t\tconst text = stripHtml(String(data.text ?? ''));\n\t\t\tconst level = Number(data.level ?? 3);\n\t\t\tif (!text) return null;\n\t\t\tconst safeLevel = Math.min(Math.max(level, 1), 6);\n\t\t\treturn createElement(\n\t\t\t\t`h${safeLevel}`,\n\t\t\t\tnull,\n\t\t\t\ttext,\n\t\t\t);\n\t\t}\n\t\tcase 'list': {\n\t\t\tconst items = Array.isArray(data.items) ? data.items : [];\n\t\t\tconst sanitizedItems = items\n\t\t\t\t.map((item) => stripHtml(String(item ?? '')))\n\t\t\t\t.filter((item) => item.length > 0);\n\n\t\t\tif (sanitizedItems.length === 0) return null;\n\n\t\t\tif (data.style === 'ordered') {\n\t\t\t\treturn (\n\t\t\t\t\t<ol>\n\t\t\t\t\t\t{sanitizedItems.map((item, index) => (\n\t\t\t\t\t\t\t<li key={`${item}-${index}`}>\n\t\t\t\t\t\t\t\t<Text tag=\"span\" type=\"inherit\">{item}</Text>\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</ol>\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn (\n\t\t\t\t<ul>\n\t\t\t\t\t{sanitizedItems.map((item) => (\n\t\t\t\t\t\t<li key={item}>\n\t\t\t\t\t\t\t<Text tag=\"span\" type=\"inherit\">{item}</Text>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t))}\n\t\t\t\t</ul>\n\t\t\t);\n\t\t}\n\t\tcase 'quote': {\n\t\t\tconst text = String(data.text ?? '').trim();\n\t\t\tif (!text) return null;\n\t\t\tconst caption = stripHtml(String(data.caption ?? ''));\n\t\t\treturn (\n\t\t\t\t<blockquote className=\"italic\">\n\t\t\t\t\t<RichText tag=\"div\" html={text} type=\"secondary\" />\n\t\t\t\t\t{caption.length > 0 && (\n\t\t\t\t\t\t<cite className=\"mt-1 block not-italic\">\n\t\t\t\t\t\t\t<Text tag=\"span\" size=\"xs\" type=\"secondary\">\n\t\t\t\t\t\t\t\t— {caption}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t</cite>\n\t\t\t\t\t)}\n\t\t\t\t</blockquote>\n\t\t\t);\n\t\t}\n\t\tcase 'delimiter':\n\t\t\treturn (\n\t\t\t\t<hr\n\t\t\t\t\tclassName=\"border-dashed\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t/>\n\t\t\t);\n\t\tdefault: {\n\t\t\tconst text = stripHtml(String(data.text ?? ''));\n\t\t\tif (!text) return null;\n\t\t\treturn <p className=\"whitespace-pre-line\">{text}</p>;\n\t\t}\n\t}\n}\n\nfunction stripHtml(value: string): string {\n\treturn value.replace(/<[^>]*>/g, '').trim();\n}\n\nfunction decodeQuotedString(value: string | null | undefined): string {\n\tif (typeof value !== 'string') return '';\n\tconst trimmed = value.trim();\n\tif (trimmed === '') return '';\n\tif (trimmed.startsWith('{') || trimmed.startsWith('[')) return trimmed;\n\ttry {\n\t\tconst parsed = JSON.parse(trimmed);\n\t\tif (typeof parsed === 'string') return parsed;\n\t} catch {\n\t\t// ignore\n\t}\n\tif (trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n\t\treturn trimmed.slice(1, -1);\n\t}\n\treturn trimmed;\n}\n","import {\n\tCornerDownRight,\n\tPencil,\n\tPin,\n\tSmile,\n\tTrash2,\n} from 'lucide-react';\nimport type { FC } from 'react';\nimport { memo, useCallback, useMemo, useState } from 'react';\n\nimport {\n\tAvatar,\n\tAvatarFallback,\n\tAvatarImage,\n} from '../../../base/avatar';\nimport { Badge } from '../../../base/badge';\nimport { Button } from '../../../base/buttons';\nimport { ConfirmDialog, useOverlayVisibility } from '../../overlays';\nimport {\n\tTooltip,\n\tTooltipContent,\n\tTooltipProvider,\n\tTooltipTrigger,\n} from '../../../base/display/tooltip';\nimport { Number as NumberValue, RelativeTime } from '../../../primitives';\nimport { Text } from '../../../typography';\nimport { Stack } from '../../../base/structure';\nimport { cn } from '../../../../lib/utils';\nimport { fieldAffordanceRecipes } from '../../../../lib/field-affordance-recipes';\nimport { interpolateString } from '../../../../lib/strings';\nimport { defaultCommentsStrings } from '../comments.strings';\n\nimport {\n\tuseResolvedAccessors,\n\tuseResolvedStrings,\n} from '../comments-provider';\nimport type {\n\tCommentAttachment,\n\tCommentItemProps,\n\tCommentUser,\n} from '../comments.types';\nimport { CommentAttachmentChip } from './comment-attachment-chip';\nimport { CommentContent } from './comment-content';\n\nconst FALLBACK_INITIAL = '?';\n\nconst defaultGetMediaUrl = (m: CommentAttachment | null | undefined) => m?.url;\nconst defaultGetMediaName = (m: CommentAttachment | null | undefined) => m?.name;\nconst defaultGetStatusLabel = (s: string) =>\n\ts.charAt(0).toUpperCase() + s.slice(1).replace(/_/g, ' ');\n\nexport const CommentItem = memo(function CommentItem<\n\tTUser extends CommentUser = CommentUser,\n\tTMeta = unknown,\n\tTResource extends string = string,\n>({\n\tcomment,\n\tcanModerate,\n\tonDelete,\n\tonAttachmentRemove,\n\tonEdit,\n\tonPinToggle,\n\tonReact,\n\tonReply,\n\tallowReactions: allowReactionsProp,\n\tallowReplies: allowRepliesProp,\n\tsanitizer,\n\tstrings: stringsProp,\n\tgetMediaUrl,\n\tgetMediaName,\n\tgetStatusLabel,\n\tformatRelativeTime,\n\tresources,\n\trenderAttachment,\n\trenderReference,\n}: CommentItemProps<TUser, TMeta, TResource>) {\n\tconst strings = useResolvedStrings(stringsProp);\n\tconst allowReactions = allowReactionsProp ?? true;\n\tconst allowReplies = allowRepliesProp ?? true;\n\tconst accessors = useResolvedAccessors({\n\t\tgetMediaUrl,\n\t\tgetMediaName,\n\t\tgetStatusLabel,\n\t\tformatRelativeTime,\n\t});\n\n\tconst resolvedGetMediaUrl = accessors.getMediaUrl ?? defaultGetMediaUrl;\n\tconst resolvedGetMediaName = accessors.getMediaName ?? defaultGetMediaName;\n\tconst resolvedGetStatusLabel =\n\t\taccessors.getStatusLabel ?? defaultGetStatusLabel;\n\tconst resolvedFormatRelativeTime = accessors.formatRelativeTime;\n\n\tconst authorName = comment.user?.name ?? strings.fallbackAuthor;\n\tconst avatarUrl = comment.user?.avatar ?? undefined;\n\n\tconst fallbackInitial = useMemo(() => {\n\t\tif (!authorName) return FALLBACK_INITIAL;\n\t\tconst trimmed = authorName.trim();\n\t\treturn trimmed === ''\n\t\t\t? FALLBACK_INITIAL\n\t\t\t: trimmed.charAt(0).toUpperCase();\n\t}, [authorName]);\n\n\tconst tagList = useMemo(() => {\n\t\tif (Array.isArray(comment.tagsArray)) {\n\t\t\treturn comment.tagsArray.filter(\n\t\t\t\t(tag): tag is string => typeof tag === 'string',\n\t\t\t);\n\t\t}\n\t\tif (comment.tagsArray && typeof comment.tagsArray === 'object') {\n\t\t\treturn Object.values(comment.tagsArray).filter(\n\t\t\t\t(value): value is string => typeof value === 'string',\n\t\t\t);\n\t\t}\n\t\treturn [];\n\t}, [comment.tagsArray]);\n\n\tconst attachments = useMemo(() => {\n\t\tconst list = comment.attachments ?? [];\n\t\treturn list.filter(\n\t\t\t(a): a is CommentAttachment => !!a && typeof a === 'object',\n\t\t);\n\t}, [comment.attachments]);\n\n\tconst reactions = allowReactions ? (comment.reactions ?? []) : [];\n\n\tconst isPinned = comment.isPinned === true;\n\tconst isEdited = comment.isEdited === true;\n\tconst showStatus = comment.status && comment.status !== 'active';\n\tconst statusLabel =\n\t\tshowStatus && comment.status ? resolvedGetStatusLabel(comment.status) : null;\n\tconst canDeleteComment =\n\t\tcomment.canDelete === true || canModerate === true;\n\tconst canEditComment = comment.canEdit === true || canModerate === true;\n\tconst canReply = !!allowReplies && !!onReply && !!comment.id;\n\tconst canReact = !!allowReactions && !!onReact && !!comment.id;\n\tconst canPin = !!onPinToggle && !!canModerate;\n\tconst canEdit = !!canEditComment && !!onEdit && !!comment.id;\n\tconst canDelete = !!canDeleteComment && !!onDelete && !!comment.id;\n\tconst hasActions = canReply || canReact || canPin || canEdit || canDelete;\n\n\tconst attachmentConfirm = useOverlayVisibility();\n\tconst [pendingAttachmentId, setPendingAttachmentId] = useState<string | null>(null);\n\tconst requestAttachmentRemoval = useCallback(\n\t\t(attachmentId: string) => {\n\t\t\tsetPendingAttachmentId(attachmentId);\n\t\t\tattachmentConfirm.show();\n\t\t},\n\t\t[attachmentConfirm],\n\t);\n\n\tconst hasAttachments = attachments.length > 0;\n\n\treturn (\n\t\t<article\n\t\t\tclassName={cn(\n\t\t\t\t'comment-item--component group relative overflow-hidden rounded-surface border transition-colors',\n\t\t\t\t'border-border/60 bg-card text-card-foreground px-surface pt-surface',\n\t\t\t\t// A trailing row of ghost icon buttons already carries its own inset\n\t\t\t\t// around each glyph, so it supplies the rest of the bottom edge and the\n\t\t\t\t// card stays optically even instead of gaining an empty band.\n\t\t\t\thasActions ? 'pb-surface-xs' : 'pb-surface',\n\t\t\t)}\n\t\t\tdata-comment-id={comment.id}\n\t\t>\n\t\t\t<Stack direction=\"horizontal\" align=\"start\" gap=\"lg\" className=\"min-w-0\">\n\t\t\t\t<Avatar className=\"size-avatar shrink-0\">\n\t\t\t\t\t{!!avatarUrl && (\n\t\t\t\t\t\t<AvatarImage src={avatarUrl} alt={authorName} />\n\t\t\t\t\t)}\n\t\t\t\t\t<AvatarFallback className=\"bg-muted text-muted-foreground text-xs font-medium\">\n\t\t\t\t\t\t{fallbackInitial}\n\t\t\t\t\t</AvatarFallback>\n\t\t\t\t</Avatar>\n\n\t\t\t\t<div className=\"comment-item--body min-w-0 flex-1\">\n\t\t\t\t\t{/* The byline and its message are one copy unit: the Stack owns their gap. */}\n\t\t\t\t\t<Stack gap=\"xs\" className=\"comment-item--message min-w-0\">\n\t\t\t\t\t\t<Stack direction=\"horizontal\" align=\"baseline\" gap=\"md\" className=\"min-w-0\">\n\t\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\t\ttag=\"span\"\n\t\t\t\t\t\t\t\ttype=\"inherit\"\n\t\t\t\t\t\t\t\tweight=\"semibold\"\n\t\t\t\t\t\t\t\tclassName=\"truncate\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{authorName}\n\t\t\t\t\t\t\t</Text>\n\n\t\t\t\t\t\t\t{!!isPinned && (\n\t\t\t\t\t\t\t\t<TooltipProvider delayDuration={0}>\n\t\t\t\t\t\t\t\t\t<Tooltip>\n\t\t\t\t\t\t\t\t\t\t<TooltipTrigger render={<span className=\"inline-flex shrink-0 self-center\" />}>\n\t\t\t\t\t\t\t\t\t\t\t<Pin className=\"text-muted-foreground size-icon-sm\" aria-hidden />\n\t\t\t\t\t\t\t\t\t\t</TooltipTrigger>\n\t\t\t\t\t\t\t\t\t\t<TooltipContent\n\t\t\t\t\t\t\t\t\t\t\tside=\"top\"\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"text-xs\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{strings.pinned}\n\t\t\t\t\t\t\t\t\t\t</TooltipContent>\n\t\t\t\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t\t\t\t</TooltipProvider>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t<RelativeTime\n\t\t\t\t\t\t\t\tvalue={comment.createdAt}\n\t\t\t\t\t\t\t\tformatRelativeTime={resolvedFormatRelativeTime}\n\t\t\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\t\t\tclassName=\"shrink-0 tabular-nums\"\n\t\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t\t{!!isEdited && (\n\t\t\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\t\t\ttag=\"span\"\n\t\t\t\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\t\t\t\ttype=\"secondary\"\n\t\t\t\t\t\t\t\t\tclassName=\"shrink-0\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{strings.edited}\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t{!!showStatus && !!statusLabel && (\n\t\t\t\t\t\t\t\t<Badge size=\"sm\" tone=\"secondary\" className=\"self-center\">\n\t\t\t\t\t\t\t\t\t{statusLabel}\n\t\t\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</Stack>\n\n\t\t\t\t\t\t<div className=\"leading-relaxed\">\n\t\t\t\t\t\t\t<CommentContent\n\t\t\t\t\t\t\t\tcomment={comment}\n\t\t\t\t\t\t\t\tresources={resources}\n\t\t\t\t\t\t\t\trenderReference={renderReference}\n\t\t\t\t\t\t\t\tsanitizer={sanitizer}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</Stack>\n\n\t\t\t\t\t{tagList.length > 0 && (\n\t\t\t\t\t\t<div className=\"mt-space-md flex flex-wrap gap-space-sm\">\n\t\t\t\t\t\t\t{tagList.map((tag) => (\n\t\t\t\t\t\t\t\t<Badge key={tag} size=\"sm\" tone=\"secondary\">\n\t\t\t\t\t\t\t\t\t{tag}\n\t\t\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{hasAttachments && (\n\t\t\t\t\t\t<div className=\"mt-space-md flex flex-wrap gap-space-sm\">\n\t\t\t\t\t\t\t{attachments.map((attachment) => {\n\t\t\t\t\t\t\t\tif (renderAttachment) {\n\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t<div key={attachment.id ?? attachment.name}>\n\t\t\t\t\t\t\t\t\t\t\t{renderAttachment(attachment)}\n\t\t\t\t\t\t\t\t\t\t</div>\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/*\n\t\t\t\t\t\t\t\t * Posted attachments were read-only: no control, no\n\t\t\t\t\t\t\t\t * callback, nothing to remove. The control appears only\n\t\t\t\t\t\t\t\t * when the consumer supplies `onAttachmentRemove` and the\n\t\t\t\t\t\t\t\t * viewer may edit the comment, and detaching a published\n\t\t\t\t\t\t\t\t * file is irreversible, so it asks first.\n\t\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\t\tconst canRemoveAttachment =\n\t\t\t\t\t\t\t\t\t!!onAttachmentRemove && !!attachment.id && canDeleteComment;\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<CommentAttachmentChip\n\t\t\t\t\t\t\t\t\t\tkey={attachment.id ?? attachment.name}\n\t\t\t\t\t\t\t\t\t\tattachment={attachment}\n\t\t\t\t\t\t\t\t\t\teditable={canRemoveAttachment}\n\t\t\t\t\t\t\t\t\t\tonRemove={\n\t\t\t\t\t\t\t\t\t\t\tcanRemoveAttachment\n\t\t\t\t\t\t\t\t\t\t\t\t? () => requestAttachmentRemoval(attachment.id as string)\n\t\t\t\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\taccessors={{\n\t\t\t\t\t\t\t\t\t\t\tgetMediaUrl: resolvedGetMediaUrl,\n\t\t\t\t\t\t\t\t\t\t\tgetMediaName: resolvedGetMediaName,\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\tstrings={stringsProp}\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})}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{reactions.length > 0 && (\n\t\t\t\t\t\t<Stack direction=\"horizontal\" wrap align=\"center\" gap=\"xs\" className=\"mt-space-md\">\n\t\t\t\t\t\t\t{reactions.map((reaction) => (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\tkey={reaction.emoji}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\taria-label={interpolateString(strings.reactionLabel ?? defaultCommentsStrings.reactionLabel!, { emoji: reaction.emoji, count: reaction.count })}\n\t\t\t\t\t\t\t\t\taria-pressed={reaction.mine ?? false}\n\t\t\t\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t\t\t\tonReact && comment.id\n\t\t\t\t\t\t\t\t\t\t\t? onReact(comment.id, reaction.emoji)\n\t\t\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\ttitle={reaction.users?.join(', ')}\n\t\t\t\t\t\t\t\t\tclassName={cn(fieldAffordanceRecipes.inline, fieldAffordanceRecipes.focus)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Badge\n\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\ttone={reaction.mine ? 'info' : 'secondary'}\n\t\t\t\t\t\t\t\t\t\tclassName=\"cursor-pointer transition-colors\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\t\t\t\t\ttag=\"span\"\n\t\t\t\t\t\t\t\t\t\t\tsize=\"inherit\"\n\t\t\t\t\t\t\t\t\t\t\tlineHeight=\"none\"\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"text-inherit\"\n\t\t\t\t\t\t\t\t\t\t\taria-hidden\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{reaction.emoji}\n\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t\t<NumberValue\n\t\t\t\t\t\t\t\t\t\t\tvalue={reaction.count}\n\t\t\t\t\t\t\t\t\t\t\tsize=\"inherit\"\n\t\t\t\t\t\t\t\t\t\t\talign=\"left\"\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"tabular-nums text-current\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</Badge>\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</Stack>\n\t\t\t\t\t)}\n\n\t\t\t\t{/* Actions own a separate row so they never reserve message width. */}\n\t\t\t\t{hasActions && <div\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'comment-item--actions relative mt-space-xs ms-auto w-fit max-w-full flex-wrap opacity-100 transition-opacity',\n\t\t\t\t\t\t'group-hover:opacity-100 focus-within:opacity-100',\n\t\t\t\t\t\t'inline-flex items-center gap-space-2xs',\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t{canReply && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tsize=\"sm\" iconOnly\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\tonClick={() =>\n\t\t\t\t\t\t\t\tcomment.id && onReply(comment.id)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttitle={strings.replyLabel}\n\t\t\t\t\t\t\taria-label={strings.replyLabel}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<CornerDownRight className=\"size-icon-md\" />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t\t{canReact && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tsize=\"sm\" iconOnly\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\tonClick={() =>\n\t\t\t\t\t\t\t\tcomment.id && onReact(comment.id, '👍')\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttitle={strings.addReactionLabel}\n\t\t\t\t\t\t\taria-label={strings.addReactionLabel}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Smile className=\"size-icon-md\" />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t\t{canPin && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tsize=\"sm\" iconOnly\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\tonClick={() => onPinToggle(comment)}\n\t\t\t\t\t\t\ttitle={isPinned ? strings.unpinLabel : strings.pinLabel}\n\t\t\t\t\t\t\taria-label={isPinned ? strings.unpinLabel : strings.pinLabel}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Pin\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'size-icon-md',\n\t\t\t\t\t\t\t\t\tisPinned && 'text-foreground',\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t\t{canEdit && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tsize=\"sm\" iconOnly\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\ttitle={strings.editLabel}\n\t\t\t\t\t\t\taria-label={strings.editLabel}\n\t\t\t\t\t\t\tonClick={() => onEdit(comment)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Pencil className=\"size-icon-md\" />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t\t{canDelete && (\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tsize=\"sm\" iconOnly\n\t\t\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\t\t\t\tclassName=\"hover:text-destructive\"\n\t\t\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t\t\tonDelete(comment.id as string)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\ttitle={strings.deleteLabel}\n\t\t\t\t\t\t\t\taria-label={strings.deleteLabel}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Trash2 className=\"size-icon-md\" />\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t)}\n\t\t\t\t</div>}\n\t\t\t\t</div>\n\t\t\t</Stack>\n\t\t\t{!!onAttachmentRemove && (\n\t\t\t\t<ConfirmDialog\n\t\t\t\t\t{...attachmentConfirm.overlayProps}\n\t\t\t\t\tdestructive\n\t\t\t\t\ttitle={strings.confirmRemoveAttachmentTitle}\n\t\t\t\t\tdescription={strings.confirmRemoveAttachmentDescription}\n\t\t\t\t\tstrings={{ confirm: strings.attachmentRemoveLabel }}\n\t\t\t\t\tonConfirm={() => {\n\t\t\t\t\t\tif (pendingAttachmentId && comment.id) {\n\t\t\t\t\t\t\tvoid onAttachmentRemove(comment.id as string, pendingAttachmentId);\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</article>\n\t);\n}) as <\n\tTUser extends CommentUser = CommentUser,\n\tTMeta = unknown,\n\tTResource extends string = string,\n>(\n\tprops: CommentItemProps<TUser, TMeta, TResource>,\n) => ReturnType<FC>;\n","import type { FC } from 'react';\n\nimport { Stack } from '../../../base/structure';\nimport type { CommentTimelineProps, CommentUser } from '../comments.types';\nimport { CommentEmpty } from './comment-empty';\nimport { CommentItem } from './comment-item';\n\nexport const CommentTimeline = function CommentTimeline<\n\tTUser extends CommentUser = CommentUser,\n\tTMeta = unknown,\n\tTResource extends string = string,\n>({\n\tcomments,\n\tcanModerate,\n\tonDelete,\n\tonAttachmentRemove,\n\tonEdit,\n\tonPinToggle,\n\tonReact,\n\tonReply,\n\tallowReactions,\n\tallowReplies,\n\tsanitizer,\n\tstrings: stringsProp,\n\tgetMediaUrl,\n\tgetMediaName,\n\tgetStatusLabel,\n\tformatRelativeTime,\n\tresources,\n\trenderItem,\n\trenderAttachment,\n\trenderReference,\n\temptySlot,\n}: CommentTimelineProps<TUser, TMeta, TResource>) {\n\tif (!comments.length) {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{emptySlot ?? <CommentEmpty strings={stringsProp} />}\n\t\t\t</>\n\t\t);\n\t}\n\n\treturn (\n\t\t<Stack gap=\"sm\" className=\"comment-timeline--component\">\n\t\t\t{comments.map((comment, index) => {\n\t\t\t\tconst defaultItem = (\n\t\t\t\t\t<CommentItem<TUser, TMeta, TResource>\n\t\t\t\t\t\tcomment={comment}\n\t\t\t\t\t\tcanModerate={canModerate}\n\t\t\t\t\t\tonDelete={onDelete}\n\t\t\t\t\t\tonAttachmentRemove={onAttachmentRemove}\n\t\t\t\t\t\tonEdit={onEdit}\n\t\t\t\t\t\tonPinToggle={onPinToggle}\n\t\t\t\t\t\tonReact={onReact}\n\t\t\t\t\t\tonReply={onReply}\n\t\t\t\t\t\tallowReactions={allowReactions}\n\t\t\t\t\t\tallowReplies={allowReplies}\n\t\t\t\t\t\tsanitizer={sanitizer}\n\t\t\t\t\t\tstrings={stringsProp}\n\t\t\t\t\t\tgetMediaUrl={getMediaUrl}\n\t\t\t\t\t\tgetMediaName={getMediaName}\n\t\t\t\t\t\tgetStatusLabel={getStatusLabel}\n\t\t\t\t\t\tformatRelativeTime={formatRelativeTime}\n\t\t\t\t\t\tresources={resources}\n\t\t\t\t\t\trenderAttachment={renderAttachment}\n\t\t\t\t\t\trenderReference={renderReference}\n\t\t\t\t\t/>\n\t\t\t\t);\n\n\t\t\t\tif (renderItem) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div key={comment.id ?? `comment-${index}`}>\n\t\t\t\t\t\t\t{renderItem({\n\t\t\t\t\t\t\t\tcomment,\n\t\t\t\t\t\t\t\tcanModerate: canModerate ?? false,\n\t\t\t\t\t\t\t\tonDelete,\n\t\t\t\t\t\t\t\tonAttachmentRemove,\n\t\t\t\t\t\t\t\tonEdit,\n\t\t\t\t\t\t\t\tdefaultItem,\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn (\n\t\t\t\t\t<div key={comment.id ?? `comment-${index}`}>\n\t\t\t\t\t\t{defaultItem}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t})}\n\t\t</Stack>\n\t);\n} as <\n\tTUser extends CommentUser = CommentUser,\n\tTMeta = unknown,\n\tTResource extends string = string,\n>(\n\tprops: CommentTimelineProps<TUser, TMeta, TResource>,\n) => ReturnType<FC>;\n","/**\n * Comments — top-level entry for the Comments feature.\n *\n * Composes the composer + timeline + empty state behind a single API.\n * Generic in `<TUser, TMeta, TResource>` so consumers can type their\n * domain (user shape, custom meta payload, resource-kind union).\n *\n * Per-mount wiring (callbacks, resources, accessors) flows as direct\n * props. Library-wide display defaults (composer position, etc.) come\n * from `<UIProvider>` — see `@/lib/ui-provider`. Slots, render-props,\n * and the headless `useComments()` hook cover the composability\n * spectrum.\n *\n * Wrap the feature in `Card` at the call site when card chrome is desired.\n */\nimport { useCallback, useState } from 'react';\n\nimport { Stack } from '../../base/structure';\nimport { ConfirmDialog, useOverlayVisibility } from '../overlays';\nimport { Text } from '../../typography';\nimport { useCommentsConfig as useCommentsUIDefaults } from '../../../lib/ui-provider';\n\nimport { useResolvedStrings } from './comments-provider';\nimport type { CommentUser, CommentsProps } from './comments.types';\nimport { useComments } from './hooks/use-comments';\nimport { CommentComposer } from './partials/comment-composer';\nimport { CommentEmpty } from './partials/comment-empty';\nimport { CommentTimeline } from './partials/comment-timeline';\n\nimport { cn } from '../../../lib/utils';\nexport function Comments<\n\tTUser extends CommentUser = CommentUser,\n\tTMeta = unknown,\n\tTResource extends string = string,\n>(props: CommentsProps<TUser, TMeta, TResource>) {\n\tconst ui = useCommentsUIDefaults();\n\n\tconst composerPosition =\n\t\tprops.composerPosition ?? ui.composerPosition ?? 'top';\n\tconst maxAttachments = props.maxAttachments ?? 5;\n\tconst allowAttachments = props.allowAttachments ?? true;\n\tconst allowReactions = props.allowReactions ?? true;\n\tconst allowReplies = props.allowReplies ?? true;\n\n\tconst canComment = props.canComment ?? false;\n\tconst canModerate = props.canModerate ?? false;\n\n\tconst onPinToggle = props.onPinToggle;\n\n\tconst resources = props.resources;\n\tconst attachments = props.attachments;\n\n\tconst strings = useResolvedStrings(props.strings);\n\tconst title = props.title === undefined ? strings.title : props.title;\n\n\t/*\n\t * Deleting a comment is irreversible and the trigger is a bare icon button\n\t * next to Edit, so the confirmation is the component's job rather than every\n\t * consumer's. `confirmDelete={false}` opts out for apps that already confirm\n\t * upstream — otherwise they would ask twice.\n\t */\n\tconst confirmDelete = props.confirmDelete ?? true;\n\tconst deleteConfirm = useOverlayVisibility();\n\tconst [pendingDeleteId, setPendingDeleteId] = useState<string | null>(null);\n\n\tconst commentsState = useComments<TUser, TMeta, TResource>({\n\t\tonSubmit: props.onSubmit,\n\t\tonUpdate: props.onUpdate,\n\t\tonDelete: props.onDelete,\n\t\tonAfterMutate: props.onAfterMutate,\n\t\tonError: props.onError,\n\t});\n\n\tconst requestDelete = useCallback(\n\t\t(id: string) => {\n\t\t\tif (!confirmDelete) {\n\t\t\t\tvoid commentsState.deleteComment(id);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsetPendingDeleteId(id);\n\t\t\tdeleteConfirm.show();\n\t\t},\n\t\t[confirmDelete, commentsState, deleteConfirm],\n\t);\n\tconst startReply = commentsState.startReply;\n\tconst comments = props.comments;\n\tconst onReply = props.onReply;\n\n\tconst handleReply = useCallback(\n\t\t(commentId: string) => {\n\t\t\tconst comment = comments.find((item) => item.id === commentId);\n\t\t\tif (comment) startReply(comment);\n\t\t\tonReply?.(commentId);\n\t\t},\n\t\t[comments, onReply, startReply],\n\t);\n\n\tconst editingComment =\n\t\tcommentsState.composerMode.kind === 'editing'\n\t\t\t? commentsState.composerMode.comment\n\t\t\t: undefined;\n\tconst replyingTo =\n\t\tcommentsState.composerMode.kind === 'replying'\n\t\t\t? {\n\t\t\t\t\tcommentId: commentsState.composerMode.commentId,\n\t\t\t\t\tauthorName: commentsState.composerMode.authorName,\n\t\t\t\t}\n\t\t\t: undefined;\n\n\tconst composer = props.composerSlot ?? (\n\t\tcanComment ? (\n\t\t\t<CommentComposer<TResource>\n\t\t\t\tcontext={props.context}\n\t\t\t\tcanComment={canComment}\n\t\t\t\tsubmitting={commentsState.isSubmitting}\n\t\t\t\terrors={commentsState.formErrors}\n\t\t\t\tresetKey={commentsState.resetKey}\n\t\t\t\teditingComment={editingComment}\n\t\t\t\treplyingTo={replyingTo}\n\t\t\t\tonCancel={\n\t\t\t\t\tcommentsState.composerMode.kind === 'idle'\n\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t: commentsState.cancelComposerMode\n\t\t\t\t}\n\t\t\t\tonSubmit={commentsState.submit}\n\t\t\t\tstrings={props.strings}\n\t\t\t\tresources={resources}\n\t\t\t\tonResourceSearch={props.onResourceSearch}\n\t\t\t\tattachments={attachments}\n\t\t\t\tmaxAttachments={maxAttachments}\n\t\t\t\tallowAttachments={allowAttachments}\n\t\t\t/>\n\t\t) : null\n\t);\n\n\tconst timeline = (\n\t\t<CommentTimeline<TUser, TMeta, TResource>\n\t\t\tcomments={props.comments}\n\t\t\tcanModerate={canModerate}\n\t\t\tonDelete={props.onDelete ? requestDelete : undefined}\n\t\t\tonAttachmentRemove={props.onAttachmentRemove}\n\t\t\tonEdit={\n\t\t\t\tcanComment && props.onUpdate\n\t\t\t\t\t? commentsState.startEdit\n\t\t\t\t\t: undefined\n\t\t\t}\n\t\t\tonPinToggle={onPinToggle}\n\t\t\tonReact={props.onReact}\n\t\t\tonReply={canComment && allowReplies ? handleReply : undefined}\n\t\t\tallowReactions={allowReactions}\n\t\t\tallowReplies={allowReplies}\n\t\t\tsanitizer={props.sanitizer}\n\t\t\tstrings={props.strings}\n\t\t\tgetMediaUrl={props.getMediaUrl}\n\t\t\tgetMediaName={props.getMediaName}\n\t\t\tgetStatusLabel={props.getStatusLabel}\n\t\t\tformatRelativeTime={props.formatRelativeTime}\n\t\t\tresources={resources}\n\t\t\trenderItem={props.renderItem}\n\t\t\trenderAttachment={props.renderAttachment}\n\t\t\trenderReference={props.renderReference}\n\t\t\temptySlot={\n\t\t\t\tprops.emptySlot ?? <CommentEmpty strings={props.strings} />\n\t\t\t}\n\t\t/>\n\t);\n\n\tconst composerBlock = composer ? <div>{composer}</div> : null;\n\n\tconst inner = (\n\t\t<Stack gap=\"xl\" className=\"comments--body\">\n\t\t\t{props.headerSlot}\n\t\t\t{composerPosition === 'top' && composerBlock}\n\t\t\t{timeline}\n\t\t\t{composerPosition === 'bottom' && composerBlock}\n\t\t\t{props.footerSlot}\n\t\t</Stack>\n\t);\n\n\tif (props.bare) {\n\t\treturn inner;\n\t}\n\n\tconst ariaLabel = typeof title === 'string' ? title : undefined;\n\n\treturn (\n\t\t<Stack\n\t\t\trender={<section />}\n\t\t\tgap=\"lg\"\n\t\t\tdata-component=\"comments\"\n\t\t\tdata-slot=\"comments\"\n\t\t\tclassName={cn('comments--component', props.className)}\n\t\t\taria-label={ariaLabel}\n\t\t>\n\t\t\t{!!(title !== false && (title || strings.subtitle)) && (\n\t\t\t\t<Stack gap=\"normal\" className=\"comments--header\">\n\t\t\t\t\t{!!title && <Text weight=\"semibold\">{title}</Text>}\n\t\t\t\t\t{!!strings.subtitle && <Text type=\"secondary\">{strings.subtitle}</Text>}\n\t\t\t\t</Stack>\n\t\t\t)}\n\t\t\t{inner}\n\t\t\t{!!(confirmDelete && props.onDelete) && (\n\t\t\t\t<ConfirmDialog\n\t\t\t\t\t{...deleteConfirm.overlayProps}\n\t\t\t\t\tdestructive\n\t\t\t\t\ttitle={strings.confirmDeleteTitle}\n\t\t\t\t\tdescription={strings.confirmDeleteDescription}\n\t\t\t\t\tstrings={{ confirm: strings.confirmDeleteLabel }}\n\t\t\t\t\tonAsyncConfirm={async () => {\n\t\t\t\t\t\tif (pendingDeleteId) await commentsState.deleteComment(pendingDeleteId);\n\t\t\t\t\t}}\n\t\t\t\t\tonError={props.onError}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</Stack>\n\t);\n}\n"],"mappings":"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"}
@@ -21,6 +21,10 @@ export interface ChoiceOptionBase<TValue extends string = string> {
21
21
  disabled?: boolean;
22
22
  }
23
23
  export interface ChoiceGroupBaseProps {
24
+ /** Accessible name when no visible label is associated with the group. */
25
+ 'aria-label'?: string;
26
+ /** Id of a visible label that names the group. */
27
+ 'aria-labelledby'?: string;
24
28
  /** Supporting/error descriptions associated with the group. */
25
29
  'aria-describedby'?: string;
26
30
  /** Form field name (also used for hidden inputs and aria grouping). */
@@ -16,14 +16,15 @@ import * as React from 'react';
16
16
  import { type ChoiceGroupBaseProps, type ChoiceOptionBase } from './choice-types';
17
17
  export interface PillRadioGroupOption extends ChoiceOptionBase {
18
18
  }
19
- export interface PillRadioGroupProps extends Omit<ChoiceGroupBaseProps, 'name'> {
20
- /** Form field name, forwarded for native submits. */
21
- name: string;
22
- /** Current value. Controlled. */
23
- value: string | null | undefined;
19
+ export interface PillRadioGroupProps extends ChoiceGroupBaseProps {
20
+ /** Controlled selection. An explicit null or undefined clears the selection. */
21
+ value?: string | null | undefined;
22
+ /** Initial selection when value is omitted. */
23
+ defaultValue?: string;
24
24
  /** Choices offered. */
25
25
  options: PillRadioGroupOption[];
26
- onValueChange: (value: string | null) => void;
26
+ /** Reports a selection or null when cleared. */
27
+ onValueChange?: (value: string | null) => void;
27
28
  /** Allow deselecting (click active pill to clear). Default false. */
28
29
  allowClear?: boolean;
29
30
  /** Stretch pills to fill the container. */
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { type FormControlSize } from '../../../lib/ui-provider';
3
- interface ComboboxInputFieldProps {
3
+ interface ComboboxInputFieldProps extends Pick<React.ComponentPropsWithRef<'input'>, 'id' | 'ref' | 'aria-label' | 'aria-labelledby' | 'aria-describedby' | 'aria-invalid' | 'aria-required'> {
4
4
  placeholder: string;
5
5
  clearLabel: string;
6
6
  toggleLabel: string;
@@ -12,5 +12,5 @@ interface ComboboxInputFieldProps {
12
12
  className?: string;
13
13
  onBlur?: () => void;
14
14
  }
15
- export declare function ComboboxInputField({ placeholder, clearLabel, toggleLabel, size, error, required, disabled, clearable, className, onBlur, }: ComboboxInputFieldProps): React.ReactElement;
15
+ export declare function ComboboxInputField({ placeholder, clearLabel, toggleLabel, size, error, required, disabled, clearable, className, onBlur, 'aria-invalid': ariaInvalid, 'aria-required': ariaRequired, ...association }: ComboboxInputFieldProps): React.ReactElement;
16
16
  export {};
@@ -1,5 +1,7 @@
1
1
  import { type ButtonTone, type ButtonStyle } from '../buttons';
2
- import type { DatePickerProps, SingleDatePickerProps, MultipleDatePickerProps, RangeDatePickerProps, DatePickerStrings, PresetDateRange } from './datepicker.types';
2
+ import type { DatePickerProps, DatePickerBaseProps, SingleDatePickerProps, MultipleDatePickerProps, RangeDatePickerProps, DatePickerStrings, PresetDateRange } from './datepicker.types';
3
+ /** Per-mount visibility; a provider never owns an individual picker's open state. */
4
+ export declare function usePickerOpenState({ open, defaultOpen, onOpenChange, disabled }: Pick<DatePickerBaseProps, 'open' | 'defaultOpen' | 'onOpenChange' | 'disabled'>): readonly [boolean, (next: boolean) => void];
3
5
  export declare function resolvePickerButtonProps(tone?: ButtonTone, buttonStyle?: ButtonStyle): {
4
6
  tone: ButtonTone;
5
7
  buttonStyle: ButtonStyle;
@@ -1,6 +1,6 @@
1
1
  import type { AriaAttributes, FocusEventHandler, Ref } from 'react';
2
2
  import type { LucideIcon } from 'lucide-react';
3
- import type { DateRange, PropsSingle, PropsRange, PropsMulti, Locale } from 'react-day-picker';
3
+ import type { DateRange, PropsBase, PropsSingle, PropsRange, PropsMulti, Locale } from 'react-day-picker';
4
4
  import type { FormControlSize } from '../../../lib/ui-provider';
5
5
  import type { StringsProp } from '../../../lib/strings';
6
6
  import type { ActionPresentation } from '../../../lib/action-presentation';
@@ -66,6 +66,12 @@ export interface DatePickerStrings {
66
66
  year: string;
67
67
  }
68
68
  export interface DatePickerBaseProps {
69
+ /** Controlled popup visibility. Explicit values take precedence over defaultOpen. */
70
+ open?: boolean;
71
+ /** Initial popup visibility when uncontrolled. Defaults to false. */
72
+ defaultOpen?: boolean;
73
+ /** Reports trigger, dismissal and selection requests without changing a controlled value. */
74
+ onOpenChange?: (open: boolean) => void;
69
75
  /** Trigger ref for focus and form adapters; the forwarded ref remains the field root. */
70
76
  triggerRef?: Ref<HTMLButtonElement>;
71
77
  /** Native trigger blur callback. */
@@ -201,7 +207,7 @@ export interface SingleDatePickerProps extends DatePickerBaseProps {
201
207
  /** Dates to disable, as a list or a predicate. */
202
208
  disabledDates?: Date[] | ((date: Date) => boolean);
203
209
  /** Escape hatch forwarded to the underlying react-day-picker calendar. */
204
- calendarProps?: Omit<PropsSingle, 'mode' | 'selected' | 'onSelect'> & {
210
+ calendarProps?: Omit<PropsBase & PropsSingle, 'mode' | 'selected' | 'onSelect'> & {
205
211
  className?: string;
206
212
  };
207
213
  }
@@ -231,7 +237,7 @@ export interface MultipleDatePickerProps extends DatePickerBaseProps {
231
237
  /** Dates to disable, as a list or a predicate. */
232
238
  disabledDates?: Date[] | ((date: Date) => boolean);
233
239
  /** Escape hatch forwarded to the underlying react-day-picker calendar. */
234
- calendarProps?: Omit<PropsMulti, 'mode' | 'selected' | 'onSelect'> & {
240
+ calendarProps?: Omit<PropsBase & PropsMulti, 'mode' | 'selected' | 'onSelect'> & {
235
241
  className?: string;
236
242
  };
237
243
  }
@@ -265,7 +271,7 @@ export interface RangeDatePickerProps extends DatePickerBaseProps {
265
271
  /** Dates to disable, as a list or a predicate. */
266
272
  disabledDates?: Date[] | ((date: Date) => boolean);
267
273
  /** Escape hatch forwarded to the underlying react-day-picker calendar. */
268
- calendarProps?: Omit<PropsRange, 'mode' | 'selected' | 'onSelect'> & {
274
+ calendarProps?: Omit<PropsBase & PropsRange, 'mode' | 'selected' | 'onSelect'> & {
269
275
  className?: string;
270
276
  };
271
277
  }
@@ -1,4 +1,5 @@
1
1
  import * as React from 'react';
2
+ import { type FieldControlAttributes } from '../../../lib/field-control-attributes';
2
3
  import { type StringsProp } from '../../../lib/strings';
3
4
  import { type FormControlSize } from '../../../lib/ui-provider';
4
5
  export interface TimePickerStrings {
@@ -16,13 +17,14 @@ export interface TimePickerStrings {
16
17
  pm: string;
17
18
  }
18
19
  export declare const defaultTimePickerStrings: TimePickerStrings;
19
- export interface TimePickerProps {
20
+ export interface TimePickerProps extends FieldControlAttributes, Pick<React.AriaAttributes, 'aria-required'> {
20
21
  /**
21
22
  * Selected time as `'HH:mm'` or `'HH:mm:ss'`, always on a 24-hour clock
22
- * regardless of `format`. Controlled. `null` or omitted leaves every
23
- * segment blank.
23
+ * regardless of `format`. A controlled `null` leaves every segment blank.
24
24
  */
25
25
  value?: string | null;
26
+ /** Initial time when uncontrolled, in the same format as value. */
27
+ defaultValue?: string | null;
26
28
  /**
27
29
  * Fired with the next time in the same shape as `value` — `'HH:mm'` when
28
30
  * `precision` is `'minutes'`, `'HH:mm:ss'` when it is `'seconds'`. Fires
@@ -31,11 +33,23 @@ export interface TimePickerProps {
31
33
  * showing exactly what was typed until blur snaps them to that value.
32
34
  */
33
35
  onValueChange?: (value: string | null) => void;
36
+ /** Native form name. The submitted value uses a 24-hour clock. */
37
+ name?: string;
38
+ /** Requires a selected time when the browser validates the form. */
39
+ required?: boolean;
40
+ /** Runs when focus leaves the segments, trigger and popup. */
41
+ onBlur?: React.FocusEventHandler<HTMLElement>;
34
42
  /**
35
43
  * `'inline'` renders the segments directly; `'popover'` puts them behind a
36
44
  * field-shaped trigger showing the formatted time. Default: `'inline'`.
37
45
  */
38
46
  mode?: 'inline' | 'popover';
47
+ /** Controlled visibility in popover mode. */
48
+ open?: boolean;
49
+ /** Initial visibility in uncontrolled popover mode. */
50
+ defaultOpen?: boolean;
51
+ /** Reports requests to open or close the popup. */
52
+ onOpenChange?: (open: boolean) => void;
39
53
  /** Clock convention. `'12'` adds the AM/PM segment. Default: `'24'`. */
40
54
  format?: '12' | '24';
41
55
  /** Finest segment offered. Default: `'minutes'`. */
@@ -1,4 +1,7 @@
1
1
  import { type ComponentPropsWithoutRef, type ReactNode } from 'react';
2
+ import { type StringsProp } from '../../../lib/strings';
3
+ import { type ErrorStateStrings } from './state-display.strings';
4
+ export { defaultErrorStateStrings, type ErrorStateStrings } from './state-display.strings';
2
5
  type DivProps = ComponentPropsWithoutRef<'div'>;
3
6
  type StateDisplayVariant = 'inline' | 'panel';
4
7
  export type LoadingStateVariant = StateDisplayVariant;
@@ -21,6 +24,8 @@ export interface LoadingStateProps extends DivProps {
21
24
  export declare const LoadingState: import("react").ForwardRefExoticComponent<LoadingStateProps & import("react").RefAttributes<HTMLDivElement>>;
22
25
  export type ErrorStateVariant = StateDisplayVariant;
23
26
  export interface ErrorStateProps extends Omit<DivProps, 'title'> {
27
+ /** Default error copy. Explicit title, description and retryLabel props win. */
28
+ strings?: StringsProp<ErrorStateStrings>;
24
29
  /** Heading above the description. */
25
30
  title?: ReactNode;
26
31
  /** Supporting copy under the label. */
@@ -37,4 +42,3 @@ export interface ErrorStateProps extends Omit<DivProps, 'title'> {
37
42
  icon?: ReactNode;
38
43
  }
39
44
  export declare const ErrorState: import("react").ForwardRefExoticComponent<ErrorStateProps & import("react").RefAttributes<HTMLDivElement>>;
40
- export {};
@@ -0,0 +1,9 @@
1
+ export interface ErrorStateStrings {
2
+ /** Default heading when no error-specific title was supplied. */
3
+ title: string;
4
+ /** Default guidance when no error-specific description was supplied. */
5
+ description: string;
6
+ /** Label of the recovery action when `onRetry` is supplied. */
7
+ retry: string;
8
+ }
9
+ export declare const defaultErrorStateStrings: ErrorStateStrings;
@@ -8,7 +8,7 @@
8
8
  import * as React from 'react';
9
9
  import { type ComponentPropsWithoutRef, type ReactNode } from 'react';
10
10
  export interface FieldChromeProps {
11
- /** Caption rendered above the control, associated through `htmlFor`. */
11
+ /** Caption rendered above the control. Supplies a default accessible name to direct controls while preserving explicit names and native `htmlFor` association. */
12
12
  label?: ReactNode;
13
13
  /** Marks the field required and renders the required indicator by the label. */
14
14
  required?: boolean;
@@ -33,7 +33,12 @@ export interface FieldChromeProps {
33
33
  }
34
34
  export interface FormFieldProps extends FieldChromeProps, Omit<ComponentPropsWithoutRef<'div'>, 'children'> {
35
35
  children: ReactNode;
36
- /** Native ID of the labelled control. With compound children, assign it to the nested control; passive wrappers are left untouched. Direct controls receive an automatic ID when omitted. */
36
+ /**
37
+ * Native ID of the labelled control. Direct controls receive it when omitted.
38
+ * A matching ID in declared descendants leaves the outer child untouched.
39
+ * For a custom compound that creates unseen controls internally, use a passive
40
+ * host and assign this ID to its nested control; component bodies are not inspected.
41
+ */
37
42
  htmlFor?: string;
38
43
  /** ID for the resolved hint, helper, or error; controls can reference it explicitly. */
39
44
  supportingTextId?: string;
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { type StringsProp } from '../../../lib/strings';
3
3
  import type { FormControlSize } from '../../../lib/ui-provider';
4
+ import type { NumericCompositeFieldProps } from './numeric-composite-field';
4
5
  export interface CoordinatesObjectValue {
5
6
  lat?: string;
6
7
  lng?: string;
@@ -23,7 +24,9 @@ export interface CoordinatesInputStrings {
23
24
  lngAccessibleLabel: string;
24
25
  }
25
26
  export declare const defaultCoordinatesInputStrings: CoordinatesInputStrings;
26
- export interface CoordinatesInputProps {
27
+ export interface CoordinatesInputProps extends NumericCompositeFieldProps<CoordinatesValue> {
28
+ /** Native form name. Submits latitude and longitude separated by a comma, or an empty string. */
29
+ name?: string;
27
30
  /** Controlled value */
28
31
  value?: CoordinatesValue;
29
32
  /** Default value for uncontrolled mode */
@@ -32,9 +32,9 @@ export declare const defaultDecimalInputStrings: DecimalInputStrings;
32
32
  export interface DecimalInputProps extends Omit<InputProps, 'type' | 'inputMode' | 'strings'> {
33
33
  /** Maximum fractional digits accepted and used during normalization. */
34
34
  decimalPlaces?: number;
35
- /** Minimum accepted numeric value. */
35
+ /** Minimum used when normalising on blur or stepping. */
36
36
  min?: number;
37
- /** Maximum accepted numeric value. */
37
+ /** Maximum used when normalising on blur or stepping. Also limits unsigned text while typing. */
38
38
  max?: number;
39
39
  /** Whether a leading negative sign is accepted. */
40
40
  allowNegative?: boolean;
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { type StringsProp } from '../../../lib/strings';
3
3
  import { type FormControlSize } from '../../../lib/ui-provider';
4
+ import type { NumericCompositeFieldProps } from './numeric-composite-field';
4
5
  export interface DimensionObject {
5
6
  width?: string;
6
7
  height?: string;
@@ -18,7 +19,9 @@ export interface DimensionsInputStrings {
18
19
  depthPlaceholder: string;
19
20
  }
20
21
  export declare const defaultDimensionsInputStrings: DimensionsInputStrings;
21
- export interface DimensionsInputProps {
22
+ export interface DimensionsInputProps extends NumericCompositeFieldProps<DimensionValue> {
23
+ /** Native form name. Submits width, height and depth joined by x, or an empty string. */
24
+ name?: string;
22
25
  /** Current value (string "WxHxD" or object { width, height, depth }) */
23
26
  value?: DimensionValue;
24
27
  /** Default value for uncontrolled mode */
@@ -0,0 +1,12 @@
1
+ import type { AriaAttributes, FocusEventHandler } from 'react';
2
+ import type { FieldControlAttributes } from '../../../lib/field-control-attributes';
3
+ export interface NumericCompositeFieldProps<T> extends FieldControlAttributes, Pick<AriaAttributes, 'aria-required'> {
4
+ /** Reports the same value as the event-shaped change callback. */
5
+ onValueChange?: (value: T) => void;
6
+ /** Runs when focus leaves the field and its unit picker. */
7
+ onBlur?: FocusEventHandler<HTMLDivElement>;
8
+ /** Requires each numeric part when the browser validates the form. */
9
+ required?: boolean;
10
+ /** Shows the value and units without allowing edits. */
11
+ readOnly?: boolean;
12
+ }
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { type StringsProp } from '../../../lib/strings';
3
3
  import { type FormControlSize } from '../../../lib/ui-provider';
4
+ import type { NumericCompositeFieldProps } from './numeric-composite-field';
4
5
  export type WeightUnit = 'g' | 'kg' | 'lb' | 'oz';
5
6
  export interface WeightInputStrings {
6
7
  /** Above-field label for the unit selector. Empty string hides it. */
@@ -11,7 +12,11 @@ export interface WeightInputStrings {
11
12
  unitPlaceholder: string;
12
13
  }
13
14
  export declare const defaultWeightInputStrings: WeightInputStrings;
14
- export interface WeightInputProps {
15
+ export interface WeightInputProps extends NumericCompositeFieldProps<string> {
16
+ /** ID of the numeric value field. */
17
+ id?: string;
18
+ /** Native form name for the numeric value. Units remain separate. */
19
+ name?: string;
15
20
  /** Controlled value */
16
21
  value?: string;
17
22
  /** Default value for uncontrolled mode */