themelia-react-ui 2.0.0 → 2.0.1

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 (625) hide show
  1. package/CHANGELOG.md +351 -0
  2. package/README.md +26 -13
  3. package/dist/{accordion-CQXVcd7Q.js → accordion-B6a3vVgA.js} +84 -82
  4. package/dist/accordion-B6a3vVgA.js.map +1 -0
  5. package/dist/action-menu-TzCoSlwL.js +280 -0
  6. package/dist/action-menu-TzCoSlwL.js.map +1 -0
  7. package/dist/{affordance-geometry.generated-CCIXb2A1.js → affordance-geometry.generated-B5iu-Mkr.js} +3 -2
  8. package/dist/affordance-geometry.generated-B5iu-Mkr.js.map +1 -0
  9. package/dist/{ai-artifact-2PQ2fItc.js → ai-artifact-BMJdv-6q.js} +379 -376
  10. package/dist/ai-artifact-BMJdv-6q.js.map +1 -0
  11. package/dist/{app-shell-BE_j8-AT.js → app-shell-ZK5RWdo6.js} +4 -4
  12. package/dist/{app-shell-BE_j8-AT.js.map → app-shell-ZK5RWdo6.js.map} +1 -1
  13. package/dist/attachment-BtfhGm8i.js +245 -0
  14. package/dist/attachment-BtfhGm8i.js.map +1 -0
  15. package/dist/{auth-M3vGMgDR.js → auth-CYxKfo69.js} +237 -235
  16. package/dist/auth-CYxKfo69.js.map +1 -0
  17. package/dist/{avatar-djdaaQ_s.js → avatar-BBnEJIx8.js} +66 -65
  18. package/dist/avatar-BBnEJIx8.js.map +1 -0
  19. package/dist/badge-MrKVNzW9.js +93 -0
  20. package/dist/badge-MrKVNzW9.js.map +1 -0
  21. package/dist/base/accordion.js +1 -1
  22. package/dist/base/action-menu.js +1 -1
  23. package/dist/base/attachment.js +1 -1
  24. package/dist/base/avatar.js +1 -1
  25. package/dist/base/badge.js +1 -1
  26. package/dist/base/batch-action-bar.js +3 -0
  27. package/dist/base/buttons.js +2 -3
  28. package/dist/base/cards.js +2 -2
  29. package/dist/base/carousel.js +13 -13
  30. package/dist/base/carousel.js.map +1 -1
  31. package/dist/base/cascader.js +103 -115
  32. package/dist/base/cascader.js.map +1 -1
  33. package/dist/base/chart.js +1 -1
  34. package/dist/base/choice-inputs.js +3 -3
  35. package/dist/base/code-block.js +1 -1
  36. package/dist/base/combobox.js +1 -1
  37. package/dist/base/command.js +1 -1
  38. package/dist/base/copyable.js +1 -1
  39. package/dist/base/date-pickers.js +2 -2
  40. package/dist/base/display.js +7 -7
  41. package/dist/base/feedback.js +3 -3
  42. package/dist/base/forms-numeric.js +1 -1
  43. package/dist/base/forms.js +2 -2
  44. package/dist/base/inline-edit.js +17 -17
  45. package/dist/base/inline-edit.js.map +1 -1
  46. package/dist/base/item.js +1 -1
  47. package/dist/base/media-gallery.js +1 -1
  48. package/dist/base/metadata-list.js +3 -0
  49. package/dist/base/navigation.js +7 -7
  50. package/dist/base/popover-menu.js +1 -1
  51. package/dist/base/popover.js +1 -1
  52. package/dist/base/qr-code.js +1 -1
  53. package/dist/base/repeaters.js +171 -170
  54. package/dist/base/repeaters.js.map +1 -1
  55. package/dist/base/sheet.js +1 -1
  56. package/dist/base/sidebar.js +1 -1
  57. package/dist/base/signature-pad.js +147 -137
  58. package/dist/base/signature-pad.js.map +1 -1
  59. package/dist/base/skeleton.js +1 -1
  60. package/dist/base/spinner.js +1 -1
  61. package/dist/base/structure.js +1 -1
  62. package/dist/base/table.js +1 -1
  63. package/dist/base/text-inputs.js +2 -2
  64. package/dist/base/toaster.js +2 -2
  65. package/dist/base/tree.js +1 -1
  66. package/dist/base/upload-queue.js +1 -1
  67. package/dist/base/upload.js +3 -3
  68. package/dist/base/value-inputs.js +2 -2
  69. package/dist/batch-action-bar-BZGDG-Si.js +104 -0
  70. package/dist/batch-action-bar-BZGDG-Si.js.map +1 -0
  71. package/dist/blocks/admin.js +173 -171
  72. package/dist/blocks/admin.js.map +1 -1
  73. package/dist/blocks/ai.js +266 -263
  74. package/dist/blocks/ai.js.map +1 -1
  75. package/dist/blocks/analytics/usage-card.js +1 -1
  76. package/dist/blocks/analytics.js +440 -438
  77. package/dist/blocks/analytics.js.map +1 -1
  78. package/dist/blocks/collaboration.js +1 -1
  79. package/dist/blocks/commerce/receipt.js +1 -1
  80. package/dist/blocks/commerce.js +1945 -1266
  81. package/dist/blocks/commerce.js.map +1 -1
  82. package/dist/blocks/data-display.js +3 -2
  83. package/dist/blocks/onboarding.js +50 -49
  84. package/dist/blocks/onboarding.js.map +1 -1
  85. package/dist/blocks/planning.js +25 -25
  86. package/dist/blocks/planning.js.map +1 -1
  87. package/dist/blocks/timelines.js +1 -1
  88. package/dist/breadcrumbs-D5t7I023.js +129 -0
  89. package/dist/breadcrumbs-D5t7I023.js.map +1 -0
  90. package/dist/{button-R9CCoH7A.js → button-QYwiyhD2.js} +15 -14
  91. package/dist/button-QYwiyhD2.js.map +1 -0
  92. package/dist/{button-BS3KDg00.js → buttons-SbIcm1HJ.js} +200 -213
  93. package/dist/buttons-SbIcm1HJ.js.map +1 -0
  94. package/dist/{cards-QoJ4syG9.js → cards-CiiHpKYd.js} +8 -8
  95. package/dist/cards-CiiHpKYd.js.map +1 -0
  96. package/dist/{chart-DwYRKKc-.js → chart-QfrARkXl.js} +5 -5
  97. package/dist/{chart-DwYRKKc-.js.map → chart-QfrARkXl.js.map} +1 -1
  98. package/dist/checkbox-DhB6K0bK.js +36 -0
  99. package/dist/checkbox-DhB6K0bK.js.map +1 -0
  100. package/dist/choice-inputs-t6w3ATNz.js +766 -0
  101. package/dist/choice-inputs-t6w3ATNz.js.map +1 -0
  102. package/dist/code-block-Dgbu-CU3.js +185 -0
  103. package/dist/code-block-Dgbu-CU3.js.map +1 -0
  104. package/dist/{collapsible-oMUGM4tr.js → collapsible-D8AEGU1-.js} +4 -4
  105. package/dist/{collapsible-oMUGM4tr.js.map → collapsible-D8AEGU1-.js.map} +1 -1
  106. package/dist/{collection-content-Ys-OZOkY.js → collection-content-uK16Grv0.js} +3 -3
  107. package/dist/{collection-content-Ys-OZOkY.js.map → collection-content-uK16Grv0.js.map} +1 -1
  108. package/dist/{combobox-6dvVny2q.js → combobox-2Ic8N9bL.js} +74 -68
  109. package/dist/combobox-2Ic8N9bL.js.map +1 -0
  110. package/dist/{combobox-CB7039j7.js → combobox-DLl0bfiq.js} +307 -305
  111. package/dist/combobox-DLl0bfiq.js.map +1 -0
  112. package/dist/{command-kPMPjIxJ.js → command-kNR20o7x.js} +7 -7
  113. package/dist/{command-kPMPjIxJ.js.map → command-kNR20o7x.js.map} +1 -1
  114. package/dist/{comments-You0Bzbr.js → comments-BpDuCUUu.js} +341 -339
  115. package/dist/comments-BpDuCUUu.js.map +1 -0
  116. package/dist/components/base/action-menu/action-menu.d.ts +21 -4
  117. package/dist/components/base/action-menu/action-menu.recipes.d.ts +21 -0
  118. package/dist/components/base/action-menu/index.d.ts +1 -0
  119. package/dist/components/base/badge/badge.recipes.d.ts +4 -4
  120. package/dist/components/base/batch-action-bar/batch-action-bar.d.ts +50 -0
  121. package/dist/components/base/batch-action-bar/batch-action-bar.strings.d.ts +20 -0
  122. package/dist/components/base/batch-action-bar/index.d.ts +8 -0
  123. package/dist/components/base/buttons/button-group.recipes.d.ts +1 -1
  124. package/dist/components/base/buttons/button.recipes.d.ts +2 -2
  125. package/dist/components/base/choice-inputs/checkbox.d.ts +2 -2
  126. package/dist/components/base/choice-inputs/choice-types.d.ts +18 -6
  127. package/dist/components/base/display/alert-dialog.d.ts +6 -5
  128. package/dist/components/base/display/dialog.d.ts +4 -8
  129. package/dist/components/base/display/icon-badge/icon-badge.d.ts +1 -1
  130. package/dist/components/base/forms/form-sizing.d.ts +15 -12
  131. package/dist/components/base/metadata-list/index.d.ts +12 -0
  132. package/dist/components/{blocks/data-display/metadata → base/metadata-list}/metadata-list.d.ts +28 -25
  133. package/dist/components/{blocks/data-display/metadata → base/metadata-list}/metadata-value.d.ts +2 -2
  134. package/dist/components/base/navigation/index.d.ts +1 -1
  135. package/dist/components/base/navigation/page-header/index.d.ts +1 -0
  136. package/dist/components/base/navigation/page-header/page-header-commands.d.ts +73 -0
  137. package/dist/components/base/navigation/page-header/page-header.d.ts +26 -3
  138. package/dist/components/base/sheet/sheet.d.ts +4 -8
  139. package/dist/components/base/signature-pad/signature-pad.types.d.ts +5 -1
  140. package/dist/components/base/signature-pad/signature-pad.utils.d.ts +11 -3
  141. package/dist/components/base/text-inputs/field-clear-button.d.ts +6 -0
  142. package/dist/components/base/upload/upload.recipes.d.ts +25 -3
  143. package/dist/components/base/value-inputs/index.d.ts +5 -5
  144. package/dist/components/base/value-inputs/tags-input.d.ts +36 -12
  145. package/dist/components/blocks/commerce/address-card/address-card.d.ts +1 -1
  146. package/dist/components/blocks/commerce/address-card/types.d.ts +2 -1
  147. package/dist/components/blocks/commerce/cart-summary/cart-summary.d.ts +3 -1
  148. package/dist/components/blocks/commerce/cart-summary/index.d.ts +2 -2
  149. package/dist/components/blocks/commerce/cart-summary/types.d.ts +6 -1
  150. package/dist/components/blocks/commerce/discount-stack/discount-stack.d.ts +3 -1
  151. package/dist/components/blocks/commerce/discount-stack/index.d.ts +2 -2
  152. package/dist/components/blocks/commerce/discount-stack/types.d.ts +16 -4
  153. package/dist/components/blocks/commerce/fulfillment-group/fulfillment-group.d.ts +5 -0
  154. package/dist/components/blocks/commerce/fulfillment-group/index.d.ts +2 -0
  155. package/dist/components/blocks/commerce/fulfillment-group/types.d.ts +43 -0
  156. package/dist/components/blocks/commerce/index.d.ts +13 -5
  157. package/dist/components/blocks/commerce/invoice-header/invoice-header.d.ts +1 -1
  158. package/dist/components/blocks/commerce/invoice-header/types.d.ts +4 -2
  159. package/dist/components/blocks/commerce/invoice-mini/invoice-mini.d.ts +1 -1
  160. package/dist/components/blocks/commerce/invoice-mini/types.d.ts +2 -1
  161. package/dist/components/blocks/commerce/order-customer/index.d.ts +2 -0
  162. package/dist/components/blocks/commerce/order-customer/order-customer.d.ts +5 -0
  163. package/dist/components/blocks/commerce/order-customer/types.d.ts +48 -0
  164. package/dist/components/blocks/commerce/order-header/index.d.ts +2 -0
  165. package/dist/components/blocks/commerce/order-header/order-header.d.ts +5 -0
  166. package/dist/components/blocks/commerce/order-header/types.d.ts +37 -0
  167. package/dist/components/blocks/commerce/order-line-item/index.d.ts +2 -0
  168. package/dist/components/blocks/commerce/order-line-item/order-line-item.d.ts +5 -0
  169. package/dist/components/blocks/commerce/order-line-item/types.d.ts +46 -0
  170. package/dist/components/blocks/commerce/order-summary/index.d.ts +2 -0
  171. package/dist/components/blocks/commerce/order-summary/order-summary.d.ts +5 -0
  172. package/dist/components/blocks/commerce/order-summary/types.d.ts +42 -0
  173. package/dist/components/blocks/commerce/order-transactions/index.d.ts +2 -0
  174. package/dist/components/blocks/commerce/order-transactions/order-transactions.d.ts +5 -0
  175. package/dist/components/blocks/commerce/order-transactions/types.d.ts +46 -0
  176. package/dist/components/blocks/commerce/payment-method/index.d.ts +2 -2
  177. package/dist/components/blocks/commerce/payment-method/payment-method.d.ts +9 -1
  178. package/dist/components/blocks/commerce/payment-method/types.d.ts +12 -1
  179. package/dist/components/blocks/commerce/refund-status/index.d.ts +2 -2
  180. package/dist/components/blocks/commerce/refund-status/refund-status.d.ts +3 -1
  181. package/dist/components/blocks/commerce/refund-status/types.d.ts +6 -3
  182. package/dist/components/blocks/commerce/shared/address-lines.d.ts +21 -0
  183. package/dist/components/blocks/commerce/shared/line-thumbnail.d.ts +9 -0
  184. package/dist/components/blocks/commerce/shared/order-status.d.ts +51 -0
  185. package/dist/components/blocks/commerce/shipment-tracking/shipment-tracking.d.ts +1 -1
  186. package/dist/components/blocks/commerce/shipment-tracking/types.d.ts +27 -6
  187. package/dist/components/blocks/commerce/summary-panel/amount-row.d.ts +2 -0
  188. package/dist/components/blocks/commerce/summary-panel/index.d.ts +3 -0
  189. package/dist/components/blocks/commerce/summary-panel/summary-panel.d.ts +2 -0
  190. package/dist/components/blocks/commerce/summary-panel/types.d.ts +26 -0
  191. package/dist/components/blocks/commerce/tax-breakdown/tax-breakdown.d.ts +1 -1
  192. package/dist/components/blocks/commerce/tax-breakdown/types.d.ts +2 -1
  193. package/dist/components/blocks/data-display/metadata/index.d.ts +30 -4
  194. package/dist/components/features/activities/partials/activity-row.d.ts +6 -2
  195. package/dist/components/features/activities/partials/tone-tokens.d.ts +0 -6
  196. package/dist/components/features/global-search/partials/global-search-group-heading.d.ts +15 -0
  197. package/dist/components/features/global-search/partials/tone-palettes.d.ts +0 -5
  198. package/dist/components/features/kanban/kanban.d.ts +1 -1
  199. package/dist/components/features/kanban/kanban.strings.d.ts +1 -1
  200. package/dist/components/features/kanban/kanban.types.d.ts +2 -2
  201. package/dist/components/features/media-library/hooks/use-media-library.d.ts +1 -1
  202. package/dist/components/features/media-library/index.d.ts +1 -1
  203. package/dist/components/features/media-library/media-library.d.ts +1 -1
  204. package/dist/components/features/media-library/media-library.strings.d.ts +4 -0
  205. package/dist/components/features/media-library/media-library.types.d.ts +74 -1
  206. package/dist/components/features/media-library/partials/media-library-partials.d.ts +3 -3
  207. package/dist/components/features/mentions/partials/mention-kind-toggles.d.ts +16 -0
  208. package/dist/components/features/overlays/alert-dialog.d.ts +1 -1
  209. package/dist/components/features/overlays/dialog.d.ts +1 -1
  210. package/dist/components/features/overlays/index.d.ts +1 -1
  211. package/dist/components/features/overlays/overlay-tone-icon.d.ts +3 -3
  212. package/dist/components/features/overlays/overlays.types.d.ts +20 -0
  213. package/dist/components/features/products/components/product-contract-overview.d.ts +5 -0
  214. package/dist/components/features/products/components/product-details-card.d.ts +5 -0
  215. package/dist/components/features/products/components/product-operations-card.d.ts +5 -0
  216. package/dist/components/features/products/components/product-option-action-menu.d.ts +5 -0
  217. package/dist/components/features/products/components/product-options-summary.d.ts +5 -0
  218. package/dist/components/features/products/components/product-policies-card.d.ts +5 -0
  219. package/dist/components/features/products/components/product-quote-preview-card.d.ts +5 -0
  220. package/dist/components/features/products/components/product-readiness-card.d.ts +5 -0
  221. package/dist/components/features/products/components/product-structure-card.d.ts +5 -0
  222. package/dist/components/features/products/components/product-variant-action-menu.d.ts +23 -1
  223. package/dist/components/features/products/products.types.d.ts +9 -2
  224. package/dist/components/features/resource/index.d.ts +1 -1
  225. package/dist/components/features/resource/resource.d.ts +1 -1
  226. package/dist/components/features/resource/resource.types.d.ts +34 -6
  227. package/dist/components/features/rich-text-editor/index.d.ts +2 -1
  228. package/dist/components/features/rich-text-editor/partials/image-nodes.d.ts +13 -0
  229. package/dist/components/features/rich-text-editor/partials/image-uploads.d.ts +66 -0
  230. package/dist/components/features/rich-text-editor/partials/inline-reference-node.d.ts +19 -0
  231. package/dist/components/features/rich-text-editor/rich-text-editor.recipes.d.ts +1 -1
  232. package/dist/components/features/rich-text-editor/rich-text-editor.strings.d.ts +14 -0
  233. package/dist/components/features/rich-text-editor/rich-text-editor.types.d.ts +45 -0
  234. package/dist/components/features/rich-text-editor/use-rich-text-images.d.ts +18 -0
  235. package/dist/components/features/sync/index.d.ts +26 -3
  236. package/dist/components/features/table/data-table.d.ts +1 -1
  237. package/dist/components/features/table/table.types.d.ts +32 -7
  238. package/dist/components/layout/page/index.d.ts +1 -1
  239. package/dist/components/layout/page/page.types.d.ts +33 -36
  240. package/dist/components/layout/page/partials/page-actions.d.ts +1 -0
  241. package/dist/components/layout/page/partials/page-header.d.ts +1 -1
  242. package/dist/components/layout/settings/settings.d.ts +16 -2
  243. package/dist/components/layout/workspace/workspace.types.d.ts +21 -4
  244. package/dist/components/typography/rich-text/index.d.ts +1 -1
  245. package/dist/components/typography/rich-text/rich-text-tree.d.ts +19 -0
  246. package/dist/components/typography/rich-text/rich-text.d.ts +16 -0
  247. package/dist/components/typography/text-link.d.ts +4 -3
  248. package/dist/components/ui/checkbox.d.ts +4 -3
  249. package/dist/components/ui/overlay.recipes.d.ts +0 -9
  250. package/dist/components/ui/switch.d.ts +2 -2
  251. package/dist/{containers-D_L4mTVb.js → containers-DmWiJa2I.js} +36 -35
  252. package/dist/containers-DmWiJa2I.js.map +1 -0
  253. package/dist/{copyable-DDjTeW_j.js → copyable-B3Gwgdqc.js} +6 -6
  254. package/dist/{copyable-DDjTeW_j.js.map → copyable-B3Gwgdqc.js.map} +1 -1
  255. package/dist/data-display-DafIvCl5.js +960 -0
  256. package/dist/data-display-DafIvCl5.js.map +1 -0
  257. package/dist/{date-uf3z37Nm.js → date-BgK3bTdo.js} +5 -5
  258. package/dist/{date-uf3z37Nm.js.map → date-BgK3bTdo.js.map} +1 -1
  259. package/dist/date-picker-CF-DtUpF.js +1529 -0
  260. package/dist/date-picker-CF-DtUpF.js.map +1 -0
  261. package/dist/{date-pickers-CnFCb0n2.js → date-pickers-BmzxJl5l.js} +19 -19
  262. package/dist/{date-pickers-CnFCb0n2.js.map → date-pickers-BmzxJl5l.js.map} +1 -1
  263. package/dist/{display-DrdvPwF0.js → display-DsQTVzMz.js} +88 -87
  264. package/dist/display-DsQTVzMz.js.map +1 -0
  265. package/dist/{dropdown-menu-CURh59jb.js → dropdown-menu-E2qmdC7o.js} +7 -7
  266. package/dist/{dropdown-menu-CURh59jb.js.map → dropdown-menu-E2qmdC7o.js.map} +1 -1
  267. package/dist/features/activities.js +414 -501
  268. package/dist/features/activities.js.map +1 -1
  269. package/dist/features/ai-chat.js +170 -169
  270. package/dist/features/ai-chat.js.map +1 -1
  271. package/dist/features/async-preview.js +8 -8
  272. package/dist/features/async-preview.js.map +1 -1
  273. package/dist/features/combobox.js +1 -1
  274. package/dist/features/comments.js +1 -1
  275. package/dist/features/data-view.js +139 -138
  276. package/dist/features/data-view.js.map +1 -1
  277. package/dist/features/email-composer/engine.js +1 -1
  278. package/dist/features/email-composer.js +73 -71
  279. package/dist/features/email-composer.js.map +1 -1
  280. package/dist/features/event-calendar.js +278 -275
  281. package/dist/features/event-calendar.js.map +1 -1
  282. package/dist/features/filters.js +1 -1
  283. package/dist/features/global-search.js +307 -310
  284. package/dist/features/global-search.js.map +1 -1
  285. package/dist/features/kanban.js +95 -97
  286. package/dist/features/kanban.js.map +1 -1
  287. package/dist/features/map.js +56 -57
  288. package/dist/features/map.js.map +1 -1
  289. package/dist/features/media-library.js +918 -825
  290. package/dist/features/media-library.js.map +1 -1
  291. package/dist/features/mentions.js +1 -1
  292. package/dist/features/overlays.js +1 -1
  293. package/dist/features/products.js +1115 -1122
  294. package/dist/features/products.js.map +1 -1
  295. package/dist/features/questionnaire.js +202 -194
  296. package/dist/features/questionnaire.js.map +1 -1
  297. package/dist/features/resource-assignment.js +25 -25
  298. package/dist/features/resource-assignment.js.map +1 -1
  299. package/dist/features/resource.js +77 -69
  300. package/dist/features/resource.js.map +1 -1
  301. package/dist/features/rich-text-editor.js +30 -11
  302. package/dist/features/rich-text-editor.js.map +1 -1
  303. package/dist/features/schema-form.js +33 -33
  304. package/dist/features/schema-form.js.map +1 -1
  305. package/dist/features/suggestions.js +3 -3
  306. package/dist/features/sync.js +3 -3
  307. package/dist/features/table.js +1 -1
  308. package/dist/features/theme-tweaker.js +397 -396
  309. package/dist/features/theme-tweaker.js.map +1 -1
  310. package/dist/{feedback-C7nR0UtT.js → feedback-qNuMBtRH.js} +84 -83
  311. package/dist/feedback-qNuMBtRH.js.map +1 -0
  312. package/dist/{field-affordance-recipes-CkOCdE2y.js → field-affordance-recipes-qQeIf4lG.js} +8 -6
  313. package/dist/field-affordance-recipes-qQeIf4lG.js.map +1 -0
  314. package/dist/field-state-recipes-BVA2CWHo.js +12 -0
  315. package/dist/field-state-recipes-BVA2CWHo.js.map +1 -0
  316. package/dist/{filters-Da-gNPsE.js → filters-BkHH53uv.js} +565 -563
  317. package/dist/filters-BkHH53uv.js.map +1 -0
  318. package/dist/focus-recipes-B653VaLq.js +12 -0
  319. package/dist/focus-recipes-B653VaLq.js.map +1 -0
  320. package/dist/{form-field-VZRULhUK.js → form-field-DUt4UxSV.js} +4 -4
  321. package/dist/{form-field-VZRULhUK.js.map → form-field-DUt4UxSV.js.map} +1 -1
  322. package/dist/{form-sizing-uWP4lzVh.js → form-sizing-By94KzXE.js} +19 -15
  323. package/dist/form-sizing-By94KzXE.js.map +1 -0
  324. package/dist/{forms-DDeEnXSY.js → forms-Bzha-Y3B.js} +22 -22
  325. package/dist/{forms-DDeEnXSY.js.map → forms-Bzha-Y3B.js.map} +1 -1
  326. package/dist/{forms-numeric-D3CO60IF.js → forms-numeric-C0bvjRPZ.js} +265 -264
  327. package/dist/forms-numeric-C0bvjRPZ.js.map +1 -0
  328. package/dist/{header-2ycNqGOR.js → header-BOefOKd1.js} +47 -51
  329. package/dist/header-BOefOKd1.js.map +1 -0
  330. package/dist/{hooks-DQ5SPwZw.js → hooks-9k_TtmKh.js} +2 -2
  331. package/dist/{hooks-DQ5SPwZw.js.map → hooks-9k_TtmKh.js.map} +1 -1
  332. package/dist/{http-CdEIHyQf.js → http-D_6rOnzU.js} +2 -2
  333. package/dist/{http-CdEIHyQf.js.map → http-D_6rOnzU.js.map} +1 -1
  334. package/dist/icon-badge-CAuKupo9.js +55 -0
  335. package/dist/icon-badge-CAuKupo9.js.map +1 -0
  336. package/dist/index.js +7 -7
  337. package/dist/input-DWhBBBww.js +262 -0
  338. package/dist/input-DWhBBBww.js.map +1 -0
  339. package/dist/{input-BoLm9Hks.js → input-Ddi_LSYv.js} +3 -3
  340. package/dist/{input-BoLm9Hks.js.map → input-Ddi_LSYv.js.map} +1 -1
  341. package/dist/interaction-recipes-CHr0dJUs.js +24 -0
  342. package/dist/interaction-recipes-CHr0dJUs.js.map +1 -0
  343. package/dist/{item-xzh8Df65.js → item-DEmDiTlD.js} +98 -97
  344. package/dist/item-DEmDiTlD.js.map +1 -0
  345. package/dist/layer-recipes-CCpklYME.js +13 -0
  346. package/dist/layer-recipes-CCpklYME.js.map +1 -0
  347. package/dist/layout/app-shell.js +1 -1
  348. package/dist/layout/auth.js +1 -1
  349. package/dist/layout/containers.js +1 -1
  350. package/dist/layout/header.js +1 -1
  351. package/dist/layout/hooks.js +1 -1
  352. package/dist/layout/navigation.js +1 -1
  353. package/dist/layout/page.js +1 -1
  354. package/dist/layout/settings.js +1 -1
  355. package/dist/layout/sidebar.js +2 -2
  356. package/dist/layout/workspace.js +1 -1
  357. package/dist/layout.js +10 -10
  358. package/dist/lib/affordance-geometry.generated.d.ts +1 -0
  359. package/dist/lib/field-affordance-recipes.d.ts +6 -1
  360. package/dist/lib/field-state-recipes.d.ts +9 -8
  361. package/dist/lib/focus-recipes.d.ts +24 -0
  362. package/dist/lib/interaction-recipes.d.ts +35 -0
  363. package/dist/lib/layer-recipes.d.ts +19 -0
  364. package/dist/lib/motion-recipes.d.ts +1 -0
  365. package/dist/lib/overlay-anatomy-recipes.d.ts +1 -0
  366. package/dist/lib/safe-image-src.d.ts +10 -0
  367. package/dist/lib/sanitize-html.d.ts +15 -3
  368. package/dist/lib/surface-recipes.d.ts +47 -7
  369. package/dist/lib/token-merge.generated.d.ts +9 -6
  370. package/dist/lib/tone-recipes.d.ts +79 -0
  371. package/dist/lib/ui-provider/hooks.d.ts +2 -1
  372. package/dist/lib/ui-provider/index.d.ts +2 -2
  373. package/dist/lib/ui-provider/types.d.ts +9 -0
  374. package/dist/lib/utils.js +1 -1
  375. package/dist/media-gallery-DcTtAaeC.js +203 -0
  376. package/dist/media-gallery-DcTtAaeC.js.map +1 -0
  377. package/dist/mentions-D-uyCh01.js +568 -0
  378. package/dist/mentions-D-uyCh01.js.map +1 -0
  379. package/dist/{message-YfFmbXNP.js → message-CdHgIWKf.js} +5 -5
  380. package/dist/{message-YfFmbXNP.js.map → message-CdHgIWKf.js.map} +1 -1
  381. package/dist/metadata-list-X5rYAKSB.js +394 -0
  382. package/dist/metadata-list-X5rYAKSB.js.map +1 -0
  383. package/dist/{motion-recipes-B6jKXEcN.js → motion-recipes-ChBg4HBq.js} +3 -2
  384. package/dist/{motion-recipes-B6jKXEcN.js.map → motion-recipes-ChBg4HBq.js.map} +1 -1
  385. package/dist/navigation-D3KwXmaq.js +145 -0
  386. package/dist/navigation-D3KwXmaq.js.map +1 -0
  387. package/dist/navigation-HJf5zxlH.js +268 -0
  388. package/dist/navigation-HJf5zxlH.js.map +1 -0
  389. package/dist/{navigation-row-recipes-DlU-4QYO.js → navigation-row-recipes-BVowojQw.js} +2 -2
  390. package/dist/{navigation-row-recipes-DlU-4QYO.js.map → navigation-row-recipes-BVowojQw.js.map} +1 -1
  391. package/dist/{number-CKRBYmZK.js → number-DMhe-Vsk.js} +5 -5
  392. package/dist/{number-CKRBYmZK.js.map → number-DMhe-Vsk.js.map} +1 -1
  393. package/dist/overflow-tab-bar-sQHXLlwQ.js +280 -0
  394. package/dist/overflow-tab-bar-sQHXLlwQ.js.map +1 -0
  395. package/dist/overlay.recipes-8GHqmlb4.js +6 -0
  396. package/dist/overlay.recipes-8GHqmlb4.js.map +1 -0
  397. package/dist/overlays-I0axtYA6.js +999 -0
  398. package/dist/overlays-I0axtYA6.js.map +1 -0
  399. package/dist/page-B5dTH9gE.js +224 -0
  400. package/dist/page-B5dTH9gE.js.map +1 -0
  401. package/dist/page-header-commands-DjzFEq3E.js +126 -0
  402. package/dist/page-header-commands-DjzFEq3E.js.map +1 -0
  403. package/dist/{pagination-Cm0jqa3I.js → pagination-3bPA_a6K.js} +15 -15
  404. package/dist/{pagination-Cm0jqa3I.js.map → pagination-3bPA_a6K.js.map} +1 -1
  405. package/dist/{popover-Dcv_9jxr.js → popover-Di55PyAI.js} +8 -8
  406. package/dist/popover-Di55PyAI.js.map +1 -0
  407. package/dist/{popover-menu-DnRFKnHP.js → popover-menu-B71Tn2Qz.js} +6 -6
  408. package/dist/{popover-menu-DnRFKnHP.js.map → popover-menu-B71Tn2Qz.js.map} +1 -1
  409. package/dist/{popover.recipes-wmbvL8Ah.js → popover.recipes-Bdyhj2db.js} +2 -2
  410. package/dist/{popover.recipes-wmbvL8Ah.js.map → popover.recipes-Bdyhj2db.js.map} +1 -1
  411. package/dist/{primitives-BHrwQXFC.js → primitives-B-CkiEMU.js} +5 -5
  412. package/dist/{primitives-BHrwQXFC.js.map → primitives-B-CkiEMU.js.map} +1 -1
  413. package/dist/primitives.js +4 -4
  414. package/dist/{progress-Br9WTFya.js → progress-rnS8-uAW.js} +9 -9
  415. package/dist/{progress-Br9WTFya.js.map → progress-rnS8-uAW.js.map} +1 -1
  416. package/dist/{receipt-CV89q1fs.js → receipt-D0oswZ0p.js} +6 -6
  417. package/dist/{receipt-CV89q1fs.js.map → receipt-D0oswZ0p.js.map} +1 -1
  418. package/dist/rich-text-DvGulsNJ.js +78 -0
  419. package/dist/rich-text-DvGulsNJ.js.map +1 -0
  420. package/dist/rich-text-editor-sMU_Scqm.js +1204 -0
  421. package/dist/rich-text-editor-sMU_Scqm.js.map +1 -0
  422. package/dist/rich-text-editor.recipes-CadiF_Uu.js +88 -0
  423. package/dist/rich-text-editor.recipes-CadiF_Uu.js.map +1 -0
  424. package/dist/rich-text-editor.strings-CB59ekH2.js +38 -0
  425. package/dist/rich-text-editor.strings-CB59ekH2.js.map +1 -0
  426. package/dist/safe-image-src-C6kQSMBZ.js +17 -0
  427. package/dist/safe-image-src-C6kQSMBZ.js.map +1 -0
  428. package/dist/sanitize-html-DsQmI48u.js +92 -0
  429. package/dist/sanitize-html-DsQmI48u.js.map +1 -0
  430. package/dist/scroll-area-Bt_vXY2b.js +48 -0
  431. package/dist/scroll-area-Bt_vXY2b.js.map +1 -0
  432. package/dist/{separator-Do5GWDYi.js → separator-C8DlRGwF.js} +3 -3
  433. package/dist/{separator-Do5GWDYi.js.map → separator-C8DlRGwF.js.map} +1 -1
  434. package/dist/{separator-BMEvwnSX.js → separator-CYHnjsAb.js} +2 -2
  435. package/dist/{separator-BMEvwnSX.js.map → separator-CYHnjsAb.js.map} +1 -1
  436. package/dist/services/actions/action-adapters.d.ts +18 -0
  437. package/dist/services/actions/index.d.ts +1 -1
  438. package/dist/services/actions.js +16 -4
  439. package/dist/services/actions.js.map +1 -1
  440. package/dist/settings-CQW3b-Cu.js +170 -0
  441. package/dist/settings-CQW3b-Cu.js.map +1 -0
  442. package/dist/sheet-4SEvVYzA.js +210 -0
  443. package/dist/sheet-4SEvVYzA.js.map +1 -0
  444. package/dist/{sidebar-Crc9M9JV.js → sidebar-C7WWR29L.js} +180 -179
  445. package/dist/sidebar-C7WWR29L.js.map +1 -0
  446. package/dist/{sidebar-Cb8WzOvE.js → sidebar-d7Dg80ln.js} +16 -16
  447. package/dist/sidebar-d7Dg80ln.js.map +1 -0
  448. package/dist/{skeleton-DVMXr15h.js → skeleton-Cz890JZF.js} +9 -9
  449. package/dist/{skeleton-DVMXr15h.js.map → skeleton-Cz890JZF.js.map} +1 -1
  450. package/dist/smart-card-lFKxn5Hu.js +595 -0
  451. package/dist/smart-card-lFKxn5Hu.js.map +1 -0
  452. package/dist/{spinner-CmTAbEp0.js → spinner-fa3h1Aif.js} +7 -7
  453. package/dist/{spinner-CmTAbEp0.js.map → spinner-fa3h1Aif.js.map} +1 -1
  454. package/dist/{structure-hzCW-XsV.js → structure-DC2dygdA.js} +2 -2
  455. package/dist/{structure-hzCW-XsV.js.map → structure-DC2dygdA.js.map} +1 -1
  456. package/dist/style.css +1 -1
  457. package/dist/surface-recipes-BKRVW8Os.js +43 -0
  458. package/dist/surface-recipes-BKRVW8Os.js.map +1 -0
  459. package/dist/{table-D6zKeYQX.js → table-CIKyLUsy.js} +59 -58
  460. package/dist/table-CIKyLUsy.js.map +1 -0
  461. package/dist/table-CrcLN9Io.js +1458 -0
  462. package/dist/table-CrcLN9Io.js.map +1 -0
  463. package/dist/{tabs-Dk8E_knt.js → tabs-DwBJfjxX.js} +58 -57
  464. package/dist/tabs-DwBJfjxX.js.map +1 -0
  465. package/dist/{text-inputs-BFpku0Qd.js → text-inputs-aaK9wcDT.js} +74 -79
  466. package/dist/text-inputs-aaK9wcDT.js.map +1 -0
  467. package/dist/theme.css +3 -3
  468. package/dist/{timelines-CxuAFIc2.js → timelines-C_SBwHNP.js} +153 -150
  469. package/dist/timelines-C_SBwHNP.js.map +1 -0
  470. package/dist/tone-recipes-CPoExcTE.js +70 -0
  471. package/dist/tone-recipes-CPoExcTE.js.map +1 -0
  472. package/dist/tooltip-CsfgrfS7.js +111 -0
  473. package/dist/tooltip-CsfgrfS7.js.map +1 -0
  474. package/dist/{tree-BotPlyiD.js → tree-BiKhg8AY.js} +68 -66
  475. package/dist/tree-BiKhg8AY.js.map +1 -0
  476. package/dist/typography/rich-text.js +1 -1
  477. package/dist/typography-DTRkE9zL.js +117 -0
  478. package/dist/typography-DTRkE9zL.js.map +1 -0
  479. package/dist/typography.js +1 -1
  480. package/dist/{ui-provider-D2_TeLqw.js → ui-provider-1D_NSYzO.js} +11 -3
  481. package/dist/ui-provider-1D_NSYzO.js.map +1 -0
  482. package/dist/ui-provider.js +3 -3
  483. package/dist/{upload-B0WHW7ak.js → upload-BO8-CLN6.js} +209 -209
  484. package/dist/upload-BO8-CLN6.js.map +1 -0
  485. package/dist/{upload-queue-BHZ_wBfd.js → upload-queue-EOC8g1gf.js} +109 -111
  486. package/dist/upload-queue-EOC8g1gf.js.map +1 -0
  487. package/dist/upload.recipes-BbxTqrCT.js +61 -0
  488. package/dist/upload.recipes-BbxTqrCT.js.map +1 -0
  489. package/dist/{usage-card-U0YBLTNT.js → usage-card-obRaBskq.js} +46 -46
  490. package/dist/{usage-card-U0YBLTNT.js.map → usage-card-obRaBskq.js.map} +1 -1
  491. package/dist/{utils-Cospvlj1.js → utils-l5LpDw2z.js} +56 -24
  492. package/dist/utils-l5LpDw2z.js.map +1 -0
  493. package/dist/value-inputs-TAYMX111.js +947 -0
  494. package/dist/value-inputs-TAYMX111.js.map +1 -0
  495. package/dist/{value-typography-Deb3yQZg.js → value-typography-b8wpz1eX.js} +2 -2
  496. package/dist/{value-typography-Deb3yQZg.js.map → value-typography-b8wpz1eX.js.map} +1 -1
  497. package/dist/workspace-DH0v0KcB.js +407 -0
  498. package/dist/workspace-DH0v0KcB.js.map +1 -0
  499. package/docs/consumer-skill/SKILL.md +19 -20
  500. package/docs/consumer-skill/examples/app-layout.tsx +1 -1
  501. package/docs/consumer-skill/examples/composition.tsx +3 -3
  502. package/docs/consumer-skill/examples/detail.tsx +59 -12
  503. package/docs/consumer-skill/examples/edit.tsx +1 -1
  504. package/docs/consumer-skill/examples/receipt.tsx +2 -2
  505. package/docs/consumer-skill/examples/scoped-directory.tsx +1 -1
  506. package/docs/consumer-skill/examples/website.tsx +1 -1
  507. package/docs/consumer-skill/references/agents-md.md +33 -0
  508. package/docs/consumer-skill/references/analytics.md +1 -1
  509. package/docs/consumer-skill/references/composition.md +51 -8
  510. package/docs/consumer-skill/references/design-contract.md +12 -3
  511. package/docs/consumer-skill/references/installation.md +11 -1
  512. package/docs/consumer-skill/references/public-api.json +847 -447
  513. package/docs/consumer-skill/references/review.md +25 -5
  514. package/docs/consumer-skill/references/theming.md +8 -4
  515. package/docs/consumer-skill/references/tokens.json +1 -1
  516. package/docs/consumer-skill/references/workflows.md +29 -10
  517. package/docs/consumer-skill/scripts/composition-policy.mjs +41 -11
  518. package/docs/consumer-skill/scripts/surface-policy.mjs +139 -5
  519. package/package.json +10 -2
  520. package/dist/accordion-CQXVcd7Q.js.map +0 -1
  521. package/dist/action-menu-BTpyPWJ2.js +0 -264
  522. package/dist/action-menu-BTpyPWJ2.js.map +0 -1
  523. package/dist/affordance-geometry.generated-CCIXb2A1.js.map +0 -1
  524. package/dist/ai-artifact-2PQ2fItc.js.map +0 -1
  525. package/dist/attachment-q69dlt5Y.js +0 -244
  526. package/dist/attachment-q69dlt5Y.js.map +0 -1
  527. package/dist/auth-M3vGMgDR.js.map +0 -1
  528. package/dist/avatar-djdaaQ_s.js.map +0 -1
  529. package/dist/badge-0tATj-tW.js +0 -92
  530. package/dist/badge-0tATj-tW.js.map +0 -1
  531. package/dist/breadcrumbs-BG_FfMK4.js +0 -128
  532. package/dist/breadcrumbs-BG_FfMK4.js.map +0 -1
  533. package/dist/button-BS3KDg00.js.map +0 -1
  534. package/dist/button-R9CCoH7A.js.map +0 -1
  535. package/dist/buttons-DS0ZIwJ_.js +0 -99
  536. package/dist/buttons-DS0ZIwJ_.js.map +0 -1
  537. package/dist/cards-QoJ4syG9.js.map +0 -1
  538. package/dist/checkbox-B7ygNTYp.js +0 -35
  539. package/dist/checkbox-B7ygNTYp.js.map +0 -1
  540. package/dist/choice-inputs-DrJ17tpL.js +0 -752
  541. package/dist/choice-inputs-DrJ17tpL.js.map +0 -1
  542. package/dist/code-block-CD0B7M93.js +0 -183
  543. package/dist/code-block-CD0B7M93.js.map +0 -1
  544. package/dist/combobox-6dvVny2q.js.map +0 -1
  545. package/dist/combobox-CB7039j7.js.map +0 -1
  546. package/dist/comments-You0Bzbr.js.map +0 -1
  547. package/dist/components/layout/page/partials/page-header-commands.d.ts +0 -13
  548. package/dist/containers-D_L4mTVb.js.map +0 -1
  549. package/dist/data-display-3xWQUnMA.js +0 -1335
  550. package/dist/data-display-3xWQUnMA.js.map +0 -1
  551. package/dist/date-picker-DrDFj8Lo.js +0 -1527
  552. package/dist/date-picker-DrDFj8Lo.js.map +0 -1
  553. package/dist/display-DrdvPwF0.js.map +0 -1
  554. package/dist/feedback-C7nR0UtT.js.map +0 -1
  555. package/dist/field-affordance-recipes-CkOCdE2y.js.map +0 -1
  556. package/dist/field-state-recipes-C-MFBX_8.js +0 -11
  557. package/dist/field-state-recipes-C-MFBX_8.js.map +0 -1
  558. package/dist/filters-Da-gNPsE.js.map +0 -1
  559. package/dist/form-sizing-uWP4lzVh.js.map +0 -1
  560. package/dist/forms-numeric-D3CO60IF.js.map +0 -1
  561. package/dist/header-2ycNqGOR.js.map +0 -1
  562. package/dist/icon-badge-DKlaKXoo.js +0 -53
  563. package/dist/icon-badge-DKlaKXoo.js.map +0 -1
  564. package/dist/input-DhQdBnV3.js +0 -255
  565. package/dist/input-DhQdBnV3.js.map +0 -1
  566. package/dist/item-xzh8Df65.js.map +0 -1
  567. package/dist/media-gallery-DQUQ0m3O.js +0 -201
  568. package/dist/media-gallery-DQUQ0m3O.js.map +0 -1
  569. package/dist/mentions-DwnO1hh4.js +0 -564
  570. package/dist/mentions-DwnO1hh4.js.map +0 -1
  571. package/dist/navigation-Cbp5V8gG.js +0 -264
  572. package/dist/navigation-Cbp5V8gG.js.map +0 -1
  573. package/dist/navigation-Cs1npsPm.js +0 -300
  574. package/dist/navigation-Cs1npsPm.js.map +0 -1
  575. package/dist/overlay.recipes-CNO2S9V6.js +0 -34
  576. package/dist/overlay.recipes-CNO2S9V6.js.map +0 -1
  577. package/dist/overlays-DhZO7N-I.js +0 -994
  578. package/dist/overlays-DhZO7N-I.js.map +0 -1
  579. package/dist/page-C6R_8jFt.js +0 -325
  580. package/dist/page-C6R_8jFt.js.map +0 -1
  581. package/dist/page-header-hUTzcRZX.js +0 -112
  582. package/dist/page-header-hUTzcRZX.js.map +0 -1
  583. package/dist/popover-Dcv_9jxr.js.map +0 -1
  584. package/dist/rich-text-editor-CF8QYt5p.js +0 -574
  585. package/dist/rich-text-editor-CF8QYt5p.js.map +0 -1
  586. package/dist/rich-text-editor.recipes-CnrbmTS1.js +0 -81
  587. package/dist/rich-text-editor.recipes-CnrbmTS1.js.map +0 -1
  588. package/dist/rich-text-editor.strings-BpnIQgMl.js +0 -25
  589. package/dist/rich-text-editor.strings-BpnIQgMl.js.map +0 -1
  590. package/dist/rich-text-j-FGAeZW.js +0 -32
  591. package/dist/rich-text-j-FGAeZW.js.map +0 -1
  592. package/dist/sanitize-html-BG9FGe-j.js +0 -64
  593. package/dist/sanitize-html-BG9FGe-j.js.map +0 -1
  594. package/dist/scroll-area-DRdr16Pt.js +0 -47
  595. package/dist/scroll-area-DRdr16Pt.js.map +0 -1
  596. package/dist/settings-DHk0L2MF.js +0 -161
  597. package/dist/settings-DHk0L2MF.js.map +0 -1
  598. package/dist/sheet-DRFNY1_D.js +0 -207
  599. package/dist/sheet-DRFNY1_D.js.map +0 -1
  600. package/dist/sidebar-Cb8WzOvE.js.map +0 -1
  601. package/dist/sidebar-Crc9M9JV.js.map +0 -1
  602. package/dist/smart-card-Bek-TwUp.js +0 -599
  603. package/dist/smart-card-Bek-TwUp.js.map +0 -1
  604. package/dist/surface-recipes-DOdoBXGm.js +0 -28
  605. package/dist/surface-recipes-DOdoBXGm.js.map +0 -1
  606. package/dist/table-D6zKeYQX.js.map +0 -1
  607. package/dist/table-Dn4XSrSB.js +0 -1444
  608. package/dist/table-Dn4XSrSB.js.map +0 -1
  609. package/dist/tabs-Dk8E_knt.js.map +0 -1
  610. package/dist/text-inputs-BFpku0Qd.js.map +0 -1
  611. package/dist/timelines-CxuAFIc2.js.map +0 -1
  612. package/dist/tree-BotPlyiD.js.map +0 -1
  613. package/dist/typography-CAr3dQhX.js +0 -116
  614. package/dist/typography-CAr3dQhX.js.map +0 -1
  615. package/dist/ui-provider-D2_TeLqw.js.map +0 -1
  616. package/dist/upload-B0WHW7ak.js.map +0 -1
  617. package/dist/upload-queue-BHZ_wBfd.js.map +0 -1
  618. package/dist/use-file-drop-target-BX7GnhoQ.js +0 -39
  619. package/dist/use-file-drop-target-BX7GnhoQ.js.map +0 -1
  620. package/dist/utils-Cospvlj1.js.map +0 -1
  621. package/dist/value-inputs-CjfzGMsN.js +0 -854
  622. package/dist/value-inputs-CjfzGMsN.js.map +0 -1
  623. package/dist/workspace-YoFjXi6i.js +0 -394
  624. package/dist/workspace-YoFjXi6i.js.map +0 -1
  625. /package/dist/components/{blocks/data-display/metadata → base/metadata-list}/metadata-list.strings.d.ts +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"file":"timelines-CxuAFIc2.js","names":["Text","Stack","SecondaryValue","MonoValue","Percent","Badge","ContentBlock","DOT_PX","ICON_PX","STATUS_TONE","Timeline","cn","className","items","tone","item","Icon","isLast","i","dotSize","statusStyles","Check","Loader2","Circle","StepsCard","steps","titleColor","step","HorizontalDot","status","stepNumber","StepsHorizontal","title","description","idx","lineColor","footerText","defaultChangelogTimelineStrings","KIND_ICON","Plus","Minus","Wrench","GitCommit","ChangelogTimeline","stringsProp","strings","useStrings","labelByKind","entries","entry","defaultMilestonesTimelineStrings","STATUS_TO_TIMELINE","STATUS_ICON","Clock","X","STATUS_BADGE","MilestonesTimeline","labelByStatus","milestones","m"],"sources":["../src/components/blocks/timelines/shared/timeline.tsx","../src/components/blocks/timelines/steps-card/steps-card.tsx","../src/components/blocks/timelines/changelog/types.ts","../src/components/blocks/timelines/changelog/changelog-timeline.tsx","../src/components/blocks/timelines/milestones/types.ts","../src/components/blocks/timelines/milestones/milestones-timeline.tsx"],"sourcesContent":["/**\n * Timeline — shared base primitive for the blocks timeline family.\n *\n * Renders a vertical, dot-and-line list of events. Each item supports an\n * icon (Lucide component), a status that maps to dot tone, a title row, an\n * optional description block, an optional timestamp, and free-form content\n * via `children`. Use this primitive directly for new timeline variants\n * instead of reinventing the dot/line geometry — see `ChangeLogTimeline`,\n * `MilestonesTimeline`, and the existing OrderTimeline / PaymentTimeline /\n * ActivityStream consumers for examples.\n */\nimport type { LucideIcon } from 'lucide-react';\nimport type { ReactNode } from 'react';\n\nimport { SecondaryValue } from '../../../primitives';\nimport { Text } from '../../../typography';\nimport { Stack } from '../../../base/structure';\nimport type { ComponentScale } from '../../../../lib/component-vocabulary';\nimport { cn } from '../../../../lib/utils';\n\nexport type TimelineStatus =\n\t| 'completed'\n\t| 'current'\n\t| 'pending'\n\t| 'success'\n\t| 'warning'\n\t| 'error'\n\t| 'neutral';\n\nexport type TimelineDotSize = ComponentScale;\n\nexport interface TimelineItem {\n\t/** Stable identity for this entry. */\n\tid: string;\n\t/** Surface title. */\n\ttitle: ReactNode;\n\t/** Supporting copy shown under the label. */\n\tdescription?: ReactNode;\n\t/** Formatted time for the entry. */\n\ttimestamp?: ReactNode;\n\t/** Leading glyph. */\n\ticon?: LucideIcon;\n\tstatus?: TimelineStatus;\n\tchildren?: ReactNode;\n}\n\nexport interface TimelineProps {\n\titems: TimelineItem[];\n\tdotSize?: TimelineDotSize;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n}\n\nconst DOT_PX: Record<TimelineDotSize, string> = {\n\tsm: 'size-2.5',\n\tmd: 'size-icon-md',\n\tlg: 'size-icon-lg',\n};\n\nconst ICON_PX: Record<TimelineDotSize, string> = {\n\tsm: 'size-2',\n\tmd: 'size-2.5',\n\tlg: 'size-icon-sm',\n};\n\nconst STATUS_TONE: Record<TimelineStatus, { bg: string; text: string; ring: string; line: string }> = {\n\tcompleted: { bg: 'bg-success', text: 'text-success-foreground', ring: 'ring-success/20', line: 'bg-success/40' },\n\tcurrent: { bg: 'bg-primary', text: 'text-primary-foreground', ring: 'ring-primary/30', line: 'bg-primary/40' },\n\tpending: { bg: 'bg-muted', text: 'text-muted-foreground', ring: 'ring-border', line: 'bg-border' },\n\tsuccess: { bg: 'bg-success', text: 'text-success-foreground', ring: 'ring-success/20', line: 'bg-success/40' },\n\twarning: { bg: 'bg-warning', text: 'text-warning-foreground', ring: 'ring-warning/30', line: 'bg-warning/40' },\n\terror: { bg: 'bg-destructive', text: 'text-destructive-foreground', ring: 'ring-destructive/30', line: 'bg-destructive/40' },\n\tneutral: { bg: 'bg-card', text: 'text-foreground', ring: 'ring-border', line: 'bg-border' },\n};\n\nexport function Timeline({ items, dotSize = 'md', className }: TimelineProps) {\n\treturn (\n\t\t<ol className={cn('timeline--component', 'relative m-0 p-0 list-none space-y-space-xl', className)}>\n\t\t\t{items.map((item, i) => {\n\t\t\t\tconst status = item.status ?? 'neutral';\n\t\t\t\tconst tone = STATUS_TONE[status];\n\t\t\t\tconst Icon = item.icon;\n\t\t\t\tconst isLast = i === items.length - 1;\n\n\t\t\t\treturn (\n\t\t\t\t\t<li key={item.id} className=\"relative flex gap-space-lg\">\n\t\t\t\t\t\t{/* Connector line — fills available space below dot until last */}\n\t\t\t\t\t\t{!isLast && (\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'absolute left-[7px] top-4 bottom-[-1rem] w-px',\n\t\t\t\t\t\t\t\t\ttone.line,\n\t\t\t\t\t\t\t\t\tdotSize === 'lg' && 'left-[10px]',\n\t\t\t\t\t\t\t\t\tdotSize === 'sm' && 'left-[5px]',\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t<div className=\"relative z-[1] mt-0.5 flex shrink-0 items-start\">\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'inline-flex items-center justify-center rounded-full ring-2',\n\t\t\t\t\t\t\t\t\ttone.bg,\n\t\t\t\t\t\t\t\t\ttone.text,\n\t\t\t\t\t\t\t\t\ttone.ring,\n\t\t\t\t\t\t\t\t\tDOT_PX[dotSize],\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{!!Icon && <Icon className={ICON_PX[dotSize]} />}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<div className=\"min-w-0 flex-1 pb-space-md\">\n\t\t\t\t\t\t\t<Stack gap=\"dense\">\n\t\t\t\t\t\t\t<div className=\"flex items-baseline justify-between gap-space-md\">\n\t\t\t\t\t\t\t\t<Text weight=\"medium\" className=\"leading-tight\">\n\t\t\t\t\t\t\t\t\t{item.title}\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t{!!item.timestamp && (\n\t\t\t\t\t\t\t\t\t<SecondaryValue size=\"xs\" className=\"shrink-0 tabular-nums\">\n\t\t\t\t\t\t\t\t\t\t{item.timestamp}\n\t\t\t\t\t\t\t\t\t</SecondaryValue>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t{!!item.description && (\n\t\t\t\t\t\t\t\t<Text size=\"xs\" type=\"secondary\">\n\t\t\t\t\t\t\t\t\t{item.description}\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</Stack>\n\t\t\t\t\t\t\t{!!item.children && <div className=\"mt-space-md\">{item.children}</div>}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</li>\n\t\t\t\t);\n\t\t\t})}\n\t\t</ol>\n\t);\n}\n\nTimeline.displayName = 'Timeline';\n","import { Stack } from '../../../base/structure';\nimport { Text } from '../../../typography/text';\nimport { Badge } from '../../../base/badge';\nimport { ContentBlock } from '../../../base/display';\nimport { cn } from '../../../../lib/utils';\nimport { Check, Circle, Loader2 } from 'lucide-react';\nimport { Timeline, type TimelineItem } from '../shared';\nimport { type StepStatus, type StepsCardProps, type StepsHorizontalProps } from './types';\n\nconst statusStyles: Record<StepStatus, {\n\tdot: string;\n\tline: string;\n\ttitle: string;\n\tIcon: typeof Check;\n}> = {\n\tcompleted: {\n\t\tdot: 'bg-success text-success-foreground',\n\t\tline: 'bg-success',\n\t\ttitle: 'text-foreground',\n\t\tIcon: Check,\n\t},\n\tcurrent: {\n\t\tdot: 'bg-primary text-primary-foreground ring-4 ring-primary/20',\n\t\tline: 'bg-border',\n\t\ttitle: 'text-foreground',\n\t\tIcon: Loader2,\n\t},\n\tupcoming: {\n\t\tdot: 'bg-muted text-muted-foreground',\n\t\tline: 'bg-border',\n\t\ttitle: 'text-muted-foreground',\n\t\tIcon: Circle,\n\t},\n};\n\n/* ─── Vertical StepsCard (original) ────────────────────────────────────────── */\n\nexport function StepsCard({ title, description, steps, footerText, className }: StepsCardProps) {\n\tconst items: TimelineItem[] = steps.map((step) => {\n\t\tconst { Icon, title: titleColor } = statusStyles[step.status];\n\t\treturn {\n\t\t\tid: step.id,\n\t\t\ttitle: (\n\t\t\t\t<span className=\"inline-flex flex-wrap items-center gap-space-sm\">\n\t\t\t\t\t<Text tag=\"span\" size=\"inherit\" weight=\"semibold\" className={titleColor}>\n\t\t\t\t\t\t{step.title}\n\t\t\t\t\t</Text>\n\t\t\t\t\t{step.badge ? (\n\t\t\t\t\t\t<Badge tone={step.badgeTone ?? 'secondary'}>{step.badge}</Badge>\n\t\t\t\t\t) : null}\n\t\t\t\t</span>\n\t\t\t),\n\t\t\tdescription: step.description,\n\t\t\ttimestamp: step.timestamp,\n\t\t\ticon: Icon,\n\t\t\tstatus: step.status === 'upcoming' ? 'pending' : step.status,\n\t\t\tchildren: step.content,\n\t\t};\n\t});\n\n\treturn (\n\t\t<ContentBlock\n\t\t\tdata-component=\"steps-card\"\n\t\t\tdata-slot=\"steps-card\"\n\t\t\ttitle={title}\n\t\t\tdescription={description}\n\t\t\tfooterText={footerText}\n\t\t\tclassName={cn('steps-card--component', className)}\n\t\t>\n\t\t\t<Timeline items={items} dotSize=\"lg\" />\n\t\t</ContentBlock>\n\t);\n}\n\nStepsCard.displayName = 'StepsCard';\n\n/*──────────────────────────────────────────────────────────────────────────────\n * STEPS HORIZONTAL — Horizontal step bar with connecting lines\n *────────────────────────────────────────────────────────────────────────────*/\n\nfunction HorizontalDot({ status, stepNumber }: { status: StepStatus; stepNumber: number }) {\n\tif (status === 'completed') {\n\t\treturn (\n\t\t\t<div className=\"relative z-10 flex h-8 w-8 shrink-0 items-center justify-center rounded-radius bg-success text-success-foreground\">\n\t\t\t\t<Check className=\"h-4 w-4\" />\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (status === 'current') {\n\t\treturn (\n\t\t\t<div className=\"relative z-10 flex h-8 w-8 shrink-0 items-center justify-center rounded-radius bg-primary text-primary-foreground\">\n\t\t\t\t<Text weight=\"bold\" className=\"text-primary-foreground\">\n\t\t\t\t\t{stepNumber}\n\t\t\t\t</Text>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div className=\"relative z-10 flex h-8 w-8 shrink-0 items-center justify-center rounded-radius border-2 border-muted text-muted-foreground\">\n\t\t\t<Text weight=\"medium\" className=\"text-muted-foreground\">\n\t\t\t\t{stepNumber}\n\t\t\t</Text>\n\t\t</div>\n\t);\n}\n\nexport function StepsHorizontal({ title, description, steps, footerText, className }: StepsHorizontalProps) {\n\treturn (\n\t\t<div\n\t\t\tdata-component=\"steps-horizontal\"\n\t\t\tdata-slot=\"steps-horizontal\"\n\t\t\tclassName={cn('steps-horizontal--component @container/steps-horizontal grid min-w-0 gap-space-md', className)}\n\t\t>\n\t\t\t{!!(title || description) && (\n\t\t\t\t<div className=\"steps-horizontal--header grid min-w-0 gap-normal\">\n\t\t\t\t\t{!!title && <Text weight=\"semibold\">{title}</Text>}\n\t\t\t\t\t{!!description && <Text type=\"secondary\">{description}</Text>}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<div className=\"space-y-space-lg @xl/steps-horizontal:hidden\">\n\t\t\t\t{steps.map((step, idx) => {\n\t\t\t\t\tconst isLast = idx === steps.length - 1;\n\t\t\t\t\tconst lineColor = step.status === 'completed' ? 'bg-success' : 'bg-border';\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div key={step.id} className=\"flex gap-space-lg\">\n\t\t\t\t\t\t\t<div className=\"flex flex-col items-center\">\n\t\t\t\t\t\t\t\t<HorizontalDot status={step.status} stepNumber={idx + 1} />\n\t\t\t\t\t\t\t\t{!isLast && <div className={cn('mt-1 w-0.5 flex-1 min-h-5', lineColor)} />}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<Stack gap=\"dense\" className={cn('min-w-0 flex-1 pb-space-md', isLast && 'pb-0')}>\n\t\t\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\t\t\tweight=\"semibold\"\n\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t'leading-snug',\n\t\t\t\t\t\t\t\t\t\tstep.status === 'upcoming' ? 'text-muted-foreground' : 'text-foreground',\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{step.title}\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t{!!step.description && (\n\t\t\t\t\t\t\t\t\t<Text size=\"xs\" type=\"secondary\" className=\"line-clamp-2\">\n\t\t\t\t\t\t\t\t\t\t{step.description}\n\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</Stack>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</div>\n\n\t\t\t{/* Horizontal scroll wrapper — when total step width exceeds the\n\t\t\t\tcard, this lets users scroll instead of clipping labels. */}\n\t\t\t<div className=\"hidden overflow-x-auto @xl/steps-horizontal:block\">\n\t\t\t\t<div className=\"flex min-w-fit items-start\">\n\t\t\t\t\t{steps.map((step, idx) => {\n\t\t\t\t\t\tconst isLast = idx === steps.length - 1;\n\t\t\t\t\t\tconst lineColor = step.status === 'completed' ? 'bg-success' : 'bg-border';\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<div key={step.id} className=\"flex min-w-28 flex-1 items-start\">\n\t\t\t\t\t\t\t\t<div className=\"flex w-full flex-col items-center\">\n\t\t\t\t\t\t\t\t\t<div className=\"flex w-full items-center\">\n\t\t\t\t\t\t\t\t\t\t{idx > 0 && (\n\t\t\t\t\t\t\t\t\t\t\t<div className={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t'h-0.5 flex-1',\n\t\t\t\t\t\t\t\t\t\t\t\tsteps[idx - 1].status === 'completed' ? 'bg-success' : 'bg-border',\n\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{idx === 0 && <div className=\"flex-1\" />}\n\n\t\t\t\t\t\t\t\t\t\t<HorizontalDot status={step.status} stepNumber={idx + 1} />\n\n\t\t\t\t\t\t\t\t\t\t{!isLast && (\n\t\t\t\t\t\t\t\t\t\t\t<div className={cn('h-0.5 flex-1', lineColor)} />\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t{!!isLast && <div className=\"flex-1\" />}\n\t\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t\t{/* Labels below dot — clamped to 2 lines so long step\n\t\t\t\t\t\t\t\t\t\tnames break gracefully instead of pushing the\n\t\t\t\t\t\t\t\t\t\trow taller. */}\n\t\t\t\t\t\t\t\t\t<Stack gap=\"dense\" className=\"mt-space-md flex w-full flex-col items-center px-space-xs text-center\">\n\t\t\t\t\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\t\t\t\t\tweight=\"semibold\"\n\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t'leading-snug line-clamp-2',\n\t\t\t\t\t\t\t\t\t\t\t\tstep.status === 'upcoming' ? 'text-muted-foreground' : 'text-foreground',\n\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\t{step.title}\n\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t\t{!!step.description && (\n\t\t\t\t\t\t\t\t\t\t\t<Text size=\"xs\" type=\"secondary\" className=\"leading-snug line-clamp-2\">\n\t\t\t\t\t\t\t\t\t\t\t\t{step.description}\n\t\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</Stack>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t{!!footerText && <Text size=\"xs\" type=\"secondary\">{footerText}</Text>}\n\t\t</div>\n\t);\n}\n\nStepsHorizontal.displayName = 'StepsHorizontal';\n","import type { ReactNode } from 'react';\nimport type { StringsProp } from '../../../../lib/strings';\n\nexport type ChangelogEntryKind = 'added' | 'removed' | 'modified' | 'fixed';\n\nexport interface ChangelogEntry {\n\t/** Stable identity for this entry. */\n\tid: string;\n\tkind: ChangelogEntryKind;\n\t/** Surface title. */\n\ttitle: ReactNode;\n\t/** Supporting copy shown under the label. */\n\tdescription?: ReactNode;\n\tversion?: string;\n\t/** Formatted time for the entry. */\n\ttimestamp?: string;\n\t/** Who produced the entry. */\n\tauthor?: string;\n}\n\nexport interface ChangelogTimelineStrings {\n\t/** Surface title. */\n\ttitle: string;\n\tadded: string;\n\tremoved: string;\n\tmodified: string;\n\tfixed: string;\n}\n\nexport const defaultChangelogTimelineStrings: ChangelogTimelineStrings = {\n\ttitle: 'Changelog',\n\tadded: 'Added',\n\tremoved: 'Removed',\n\tmodified: 'Modified',\n\tfixed: 'Fixed',\n};\n\nexport interface ChangelogTimelineProps {\n\tentries: ChangelogEntry[];\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n\t/** Overrides this surface's own copy. */\n\tstrings?: StringsProp<ChangelogTimelineStrings>;\n}\n","/**\n * ChangelogTimeline — code/release changelog rendered through the shared\n * `Timeline` primitive. Each entry's kind (added / removed / modified /\n * fixed) is a neutral chip plus the marker glyph: a kind is a category, not a\n * status, so it carries no colour. An optional version label and timestamp\n * follow. Strings overridable for i18n.\n */\nimport { GitCommit, Minus, Plus, Wrench } from 'lucide-react';\nimport { Badge } from '../../../base/badge';\nimport { MonoValue } from '../../../primitives';\nimport { Text } from '../../../typography';\nimport { Stack } from '../../../base/structure';\nimport { useStrings } from '../../../../lib/strings';\n\nimport {\n\tTimeline,\n\ttype TimelineItem,\n} from '../shared';\nimport {\n\tdefaultChangelogTimelineStrings,\n\ttype ChangelogEntry,\n\ttype ChangelogEntryKind,\n\ttype ChangelogTimelineProps,\n} from './types';\n\nimport { cn } from '../../../../lib/utils';\nconst KIND_ICON = {\n\tadded: Plus,\n\tremoved: Minus,\n\tmodified: Wrench,\n\tfixed: GitCommit,\n} as const;\n\nexport function ChangelogTimeline({\n\tentries,\n\tclassName,\n\tstrings: stringsProp,\n}: ChangelogTimelineProps) {\n\tconst strings = useStrings(defaultChangelogTimelineStrings, stringsProp);\n\tconst labelByKind: Record<ChangelogEntryKind, string> = {\n\t\tadded: strings.added,\n\t\tremoved: strings.removed,\n\t\tmodified: strings.modified,\n\t\tfixed: strings.fixed,\n\t};\n\n\tconst items: TimelineItem[] = entries.map((entry: ChangelogEntry) => ({\n\t\tid: entry.id,\n\t\ttitle: (\n\t\t\t<span className=\"inline-flex flex-wrap items-center gap-space-sm\">\n\t\t\t\t<Badge>\n\t\t\t\t\t{labelByKind[entry.kind]}\n\t\t\t\t</Badge>\n\t\t\t\t<Text tag=\"span\" size=\"inherit\" weight=\"medium\" lineHeight=\"tight\">\n\t\t\t\t\t{entry.title}\n\t\t\t\t</Text>\n\t\t\t\t{!!entry.version && (\n\t\t\t\t\t<MonoValue size=\"xs\" className=\"text-muted-foreground\">\n\t\t\t\t\t\t{entry.version}\n\t\t\t\t\t</MonoValue>\n\t\t\t\t)}\n\t\t\t</span>\n\t\t),\n\t\tdescription: entry.author ? (\n\t\t\t<Stack render={<span />} direction=\"horizontal\" gap=\"md\" className=\"inline-flex\">\n\t\t\t\t{entry.description}\n\t\t\t\t<Text tag=\"span\" size=\"xs\" type=\"discrete\">\n\t\t\t\t\t— {entry.author}\n\t\t\t\t</Text>\n\t\t\t</Stack>\n\t\t) : (\n\t\t\tentry.description\n\t\t),\n\t\ttimestamp: entry.timestamp,\n\t\ticon: KIND_ICON[entry.kind],\n\t\tstatus: 'neutral',\n\t}));\n\n\treturn (\n\t\t<div\n\t\t\tdata-component=\"changelog-timeline\"\n\t\t\tdata-slot=\"changelog-timeline\"\n\t\t\tclassName={cn('changelog-timeline--component', className)}\n\t\t>\n\t\t\t<Timeline items={items} dotSize=\"md\" />\n\t\t</div>\n\t);\n}\n\nChangelogTimeline.displayName = 'ChangelogTimeline';\n","import type { ReactNode } from 'react';\nimport type { StringsProp } from '../../../../lib/strings';\n\nexport type MilestoneStatus = 'completed' | 'in_progress' | 'upcoming' | 'blocked';\n\nexport interface MilestoneItem {\n\t/** Stable identity for this entry. */\n\tid: string;\n\t/** Surface title. */\n\ttitle: ReactNode;\n\t/** Supporting copy shown under the label. */\n\tdescription?: ReactNode;\n\tdueDate?: string;\n\tstatus: MilestoneStatus;\n\t/** 0–100; only used when status is `in_progress`. */\n\tprogress?: number;\n}\n\nexport interface MilestonesTimelineStrings {\n\t/** Surface title. */\n\ttitle: string;\n\tcompleted: string;\n\tin_progress: string;\n\tupcoming: string;\n\tblocked: string;\n\tdueOn: string;\n}\n\nexport const defaultMilestonesTimelineStrings: MilestonesTimelineStrings = {\n\ttitle: 'Milestones',\n\tcompleted: 'Completed',\n\tin_progress: 'In progress',\n\tupcoming: 'Upcoming',\n\tblocked: 'Blocked',\n\tdueOn: 'Due',\n};\n\nexport interface MilestonesTimelineProps {\n\tmilestones: MilestoneItem[];\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n\t/** Overrides this surface's own copy. */\n\tstrings?: StringsProp<MilestonesTimelineStrings>;\n}\n","/**\n * MilestonesTimeline — project / goal milestones rendered through the\n * shared `Timeline` primitive. Each milestone has a status (completed /\n * in-progress / upcoming / blocked) that drives the dot tone, and an\n * optional `progress` percent that renders an inline progress bar when the\n * milestone is in flight. Strings overridable for i18n.\n */\nimport { Check, Circle, Clock, X } from 'lucide-react';\nimport { Badge } from '../../../base/badge';\nimport { Percent } from '../../../primitives';\nimport { Text } from '../../../typography';\nimport { useStrings } from '../../../../lib/strings';\nimport { cn } from '../../../../lib/utils';\n\nimport {\n\tTimeline,\n\ttype TimelineItem,\n\ttype TimelineStatus,\n} from '../shared';\nimport {\n\tdefaultMilestonesTimelineStrings,\n\ttype MilestoneItem,\n\ttype MilestoneStatus,\n\ttype MilestonesTimelineProps,\n} from './types';\n\nconst STATUS_TO_TIMELINE: Record<MilestoneStatus, TimelineStatus> = {\n\tcompleted: 'completed',\n\tin_progress: 'current',\n\tupcoming: 'pending',\n\tblocked: 'error',\n};\n\nconst STATUS_ICON = {\n\tcompleted: Check,\n\tin_progress: Clock,\n\tupcoming: Circle,\n\tblocked: X,\n} as const;\n\n// In progress is a status (info); primary is reserved for the main command.\nconst STATUS_BADGE: Record<MilestoneStatus, 'success' | 'info' | 'secondary' | 'destructive'> = {\n\tcompleted: 'success',\n\tin_progress: 'info',\n\tupcoming: 'secondary',\n\tblocked: 'destructive',\n};\n\nexport function MilestonesTimeline({\n\tmilestones,\n\tclassName,\n\tstrings: stringsProp,\n}: MilestonesTimelineProps) {\n\tconst strings = useStrings(defaultMilestonesTimelineStrings, stringsProp);\n\tconst labelByStatus: Record<MilestoneStatus, string> = {\n\t\tcompleted: strings.completed,\n\t\tin_progress: strings.in_progress,\n\t\tupcoming: strings.upcoming,\n\t\tblocked: strings.blocked,\n\t};\n\n\tconst items: TimelineItem[] = milestones.map((m: MilestoneItem) => ({\n\t\tid: m.id,\n\t\ttitle: (\n\t\t\t<span className=\"inline-flex flex-wrap items-center gap-space-sm\">\n\t\t\t\t<Text tag=\"span\" size=\"inherit\" weight=\"medium\" lineHeight=\"tight\">\n\t\t\t\t\t{m.title}\n\t\t\t\t</Text>\n\t\t\t\t<Badge tone={STATUS_BADGE[m.status]}>\n\t\t\t\t\t{labelByStatus[m.status]}\n\t\t\t\t</Badge>\n\t\t\t</span>\n\t\t),\n\t\tdescription: m.description,\n\t\ttimestamp: m.dueDate ? `${strings.dueOn} ${m.dueDate}` : undefined,\n\t\ticon: STATUS_ICON[m.status],\n\t\tstatus: STATUS_TO_TIMELINE[m.status],\n\t\tchildren:\n\t\t\tm.status === 'in_progress' && typeof m.progress === 'number' ? (\n\t\t\t\t<div className=\"space-y-space-xs\">\n\t\t\t\t\t<div className=\"h-1.5 w-full overflow-hidden rounded-full bg-muted\">\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={cn('h-full rounded-full bg-primary transition-[width] duration-300')}\n\t\t\t\t\t\t\tstyle={{ width: `${Math.max(0, Math.min(100, m.progress))}%` }}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t\t<Percent value={Math.round(m.progress)} scaled size=\"xs\" type=\"secondary\" align=\"left\" />\n\t\t\t\t</div>\n\t\t\t) : undefined,\n\t}));\n\n\treturn (\n\t\t<div\n\t\t\tdata-component=\"milestones-timeline\"\n\t\t\tdata-slot=\"milestones-timeline\"\n\t\t\tclassName={cn('milestones-timeline--component', className)}\n\t\t>\n\t\t\t<Timeline items={items} dotSize=\"md\" />\n\t\t</div>\n\t);\n}\n\nMilestonesTimeline.displayName = 'MilestonesTimeline';\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"tree-BotPlyiD.js","names":["DisclosureButton","useTypographyConfig","Text","textSizes","Button","ICON_DESCENDANT_SIZE_CLASSNAMES","rowBlockPaddingClasses","CollectionContent","navigationRowDensityRecipes","navigationRowInlineClasses","navigationChildInsetClasses","indexHierarchy","index","visit","node","nodes","entry","path","disabled","items","visibleHierarchy","open","expanded","isBranch","Tree","props","localExpanded","setLocalExpanded","useState","defaultExpandedValues","localSelected","setLocalSelected","defaultSelectedValues","expandedValues","selected","selectedValues","useMemo","visible","focused","setFocused","visibleValues","visibleAncestor","focusValue","refs","useRef","focusedElement","search","recipe","density","rich","rowLayout","previous","focus","value","toggle","next","onExpandedValuesChange","select","branchActivation","selectionMode","onSelectedValuesChange","keyboard","onKeyDown","event","position","rtl","forward","backward","item","now","term","letter","rows","blocked","branch","checked","element","level","cn","defaultTextSize","strings","ChevronDown","ChevronRight","renderLabel","Check","showGuides","indent","className","empty"],"sources":["../src/components/base/tree/hierarchy.ts","../src/components/base/tree/tree.tsx"],"sourcesContent":["import type { TreeNode } from './tree.types';\nexport interface HierarchyEntry<T> { node: TreeNode<T>; parent: string | null; path: TreeNode<T>[]; disabled: boolean }\n/** One canonical traversal for tree focus, cascader paths and local search. */\nexport function indexHierarchy<T>(items: readonly TreeNode<T>[]): Map<string, HierarchyEntry<T>> {\n const index = new Map<string, HierarchyEntry<T>>();\n function visit(nodes: readonly TreeNode<T>[], path: TreeNode<T>[], disabled: boolean) {\n for (const node of nodes) {\n if (index.has(node.value)) throw new Error(`Hierarchy values must be unique: ${node.value}`);\n const entry = { node, parent: path.at(-1)?.value ?? null, path: [...path, node], disabled: disabled || !!node.disabled };\n index.set(node.value, entry);\n visit(node.children ?? [], entry.path, entry.disabled);\n }\n }\n visit(items, [], false);\n return index;\n}\nexport function visibleHierarchy<T>(index: Map<string, HierarchyEntry<T>>, expanded: readonly string[]) {\n const open = new Set(expanded);\n return [...index.values()].filter(entry => entry.path.slice(0, -1).every(node => open.has(node.value)));\n}\nexport function isBranch(node: TreeNode) { return !!(node.hasChildren || node.children?.length); }\n","import { useLayoutEffect, useMemo, useRef, useState, type KeyboardEvent } from 'react';\nimport { Check, ChevronDown, ChevronRight } from 'lucide-react';\nimport { Button as DisclosureButton } from '../../ui/button';\nimport { CollectionContent } from '../popover/collection-content';\nimport { Text } from '../../typography';\nimport { cn } from '../../../lib/utils';\nimport { useTypographyConfig } from '../../../lib/ui-provider';\nimport { textSizes } from '../../typography/text.styles';\nimport { ICON_DESCENDANT_SIZE_CLASSNAMES } from '../display/icon-size';\nimport { navigationChildInsetClasses, navigationRowDensityRecipes, navigationRowInlineClasses } from '../../../lib/navigation-row-recipes';\nimport { rowBlockPaddingClasses } from '../../../lib/row-recipes';\nimport { indexHierarchy, isBranch, visibleHierarchy } from './hierarchy';\nimport type { TreeNode, TreeProps } from './tree.types';\n\n/** Accessible data-driven hierarchy. Focus moves independently from selection. */\nexport function Tree<T = unknown>({items, expandedValues, defaultExpandedValues = [], onExpandedValuesChange, selectedValues, defaultSelectedValues = [], onSelectedValuesChange, selectionMode = 'single', branchActivation = 'select', disabled = false, density = 'compact', rowLayout = 'line', indent, showGuides = true, empty = 'No items', strings, renderLabel, className, onKeyDown, ...props}: TreeProps<T>) {\n const [localExpanded, setLocalExpanded] = useState<readonly string[]>(defaultExpandedValues);\n const [localSelected, setLocalSelected] = useState<readonly string[]>(defaultSelectedValues);\n const expanded = expandedValues ?? localExpanded;\n const selected = selectedValues ?? localSelected;\n const index = useMemo(() => indexHierarchy(items), [items]);\n const visible = visibleHierarchy(index, expanded).filter(entry => !entry.disabled);\n const [focused, setFocused] = useState<string | null>(null);\n const visibleValues = new Set(visible.map(entry => entry.node.value));\n const visibleAncestor = focused === null ? undefined : index.get(focused)?.path.slice(0, -1).reverse().find(node => visibleValues.has(node.value))?.value;\n const focusValue = focused !== null && visibleValues.has(focused) ? focused : visibleAncestor ?? visible.find(entry => selected.includes(entry.node.value))?.node.value ?? visible[0]?.node.value;\n const refs = useRef(new Map<string, HTMLDivElement>());\n const focusedElement = useRef<HTMLDivElement | null>(null);\n const search = useRef({ text: '', time: 0 });\n const { defaultTextSize } = useTypographyConfig();\n const recipe = navigationRowDensityRecipes[density];\n const rich = rowLayout === 'rich';\n useLayoutEffect(() => {\n const previous = focusedElement.current;\n if (disabled || focusValue === undefined || !previous) return;\n // Keep focus inside a changing hierarchy, but do not reclaim it from another control.\n if (previous === document.activeElement || (!previous.isConnected && document.activeElement === document.body)) refs.current.get(focusValue)?.focus();\n }, [focusValue, disabled]);\n function focus(value: string | undefined) { if (value !== undefined) { setFocused(value); refs.current.get(value)?.focus(); } }\n function toggle(node: TreeNode<T>) {\n if (disabled || index.get(node.value)?.disabled) return;\n const next = expanded.includes(node.value) ? expanded.filter(value => value !== node.value) : [...expanded, node.value];\n if (expandedValues === undefined) setLocalExpanded(next);\n onExpandedValuesChange?.(next, node);\n }\n function select(node: TreeNode<T>) {\n if (disabled || index.get(node.value)?.disabled) return;\n if (branchActivation === 'toggle' && isBranch(node)) { toggle(node); return; }\n if (selectionMode === 'none') return;\n const next = selectionMode === 'multiple' ? selected.includes(node.value) ? selected.filter(value => value !== node.value) : [...selected, node.value] : [node.value];\n if (selectedValues === undefined) setLocalSelected(next);\n onSelectedValuesChange?.(next, node);\n }\n function keyboard(event: KeyboardEvent<HTMLDivElement>) {\n onKeyDown?.(event);\n if (event.defaultPrevented || disabled || (event.target as HTMLElement).closest('button') || (event.target as HTMLElement).closest('[role=tree]') !== event.currentTarget) return;\n const position = visible.findIndex(entry => entry.node.value === focused);\n const entry = index.get(focused ?? focusValue ?? '');\n if (!entry) return;\n const rtl = getComputedStyle(event.currentTarget).direction === 'rtl';\n const forward = rtl ? 'ArrowLeft' : 'ArrowRight';\n const backward = rtl ? 'ArrowRight' : 'ArrowLeft';\n if (event.key === 'ArrowDown') focus(visible[Math.min(position + 1, visible.length - 1)]?.node.value);\n else if (event.key === 'ArrowUp') focus(visible[Math.max(position - 1, 0)]?.node.value);\n else if (event.key === 'Home') focus(visible[0]?.node.value);\n else if (event.key === 'End') focus(visible.at(-1)?.node.value);\n else if (event.key === forward && isBranch(entry.node)) {\n if (!expanded.includes(entry.node.value)) toggle(entry.node);\n else focus(entry.node.children?.find(node => !index.get(node.value)?.disabled)?.value);\n } else if (event.key === backward) {\n if (isBranch(entry.node) && expanded.includes(entry.node.value)) toggle(entry.node);\n else focus(entry.parent ?? undefined);\n } else if (event.key === 'Enter' || event.key === ' ') select(entry.node);\n else if (event.key === '*') {\n const next = [...new Set([...expanded, ...[...index.values()].filter(item => item.parent === entry.parent && !item.disabled && isBranch(item.node)).map(item => item.node.value)])];\n if (expandedValues === undefined) setLocalExpanded(next);\n onExpandedValuesChange?.(next, entry.node);\n } else if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {\n const now = Date.now();\n search.current.text = (now - search.current.time < 500 ? search.current.text : '') + event.key.toLocaleLowerCase();\n search.current.time = now;\n const term = [...search.current.text].every(letter => letter === event.key.toLocaleLowerCase()) ? event.key.toLocaleLowerCase() : search.current.text;\n const rotated = [...visible.slice(position + 1), ...visible.slice(0, position + 1)];\n focus(rotated.find(item => item.node.label.toLocaleLowerCase().startsWith(term))?.node.value);\n } else return;\n event.preventDefault();\n }\n function rows(nodes: readonly TreeNode<T>[], level: number) { return nodes.map((node, position) => {\n const blocked = disabled || !!index.get(node.value)?.disabled;\n const branch = isBranch(node);\n const open = expanded.includes(node.value);\n const checked = selected.includes(node.value);\n return <div key={node.value} data-tree-value={node.value} className=\"tree--branch min-w-0 outline-none [&:focus-visible>.tree--item]:ring-2 [&:focus-visible>.tree--item]:ring-ring\" ref={element => { if (element) refs.current.set(node.value, element); else refs.current.delete(node.value); }}\n role=\"treeitem\" aria-label={node.label} aria-level={level} aria-posinset={position + 1} aria-setsize={nodes.length}\n title={!rich && typeof node.description === 'string' ? node.description : undefined}\n aria-description={!rich && typeof node.description === 'string' ? node.description : undefined}\n aria-expanded={branch ? open : undefined} aria-selected={selectionMode !== 'none' && !(branch && branchActivation === 'toggle') ? checked : undefined} aria-disabled={blocked || undefined}\n tabIndex={!blocked && focusValue === node.value ? 0 : -1}\n onFocus={event => { if (event.target === event.currentTarget) { focusedElement.current = event.currentTarget; setFocused(node.value); } }}\n onClick={event => { if (!blocked && (event.target as HTMLElement).closest('[role=treeitem]') === event.currentTarget) { focus(node.value); select(node); } }}>\n <div data-selected={checked || undefined} data-disabled={blocked || undefined}\n className={cn('tree--item flex w-full items-center cursor-default outline-none hover:bg-accent/50 hover:text-accent-foreground focus-visible:ring-2 focus-visible:ring-ring data-selected:bg-accent data-selected:hover:bg-accent data-selected:text-accent-foreground data-disabled:opacity-50', navigationRowInlineClasses, rich ? rowBlockPaddingClasses[density] : level === 1 ? recipe.height : recipe.childHeight, textSizes[defaultTextSize ?? 'sm'])}\n >\n <span className=\"tree--caret relative size-icon-sm shrink-0\">\n {branch && <DisclosureButton variant=\"ghost\" size=\"icon-xs\" className=\"tree--disclosure absolute start-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-inner rtl:translate-x-1/2\" tabIndex={-1} disabled={blocked} aria-label={open ? strings?.collapse?.(node.label) ?? `Collapse ${node.label}` : strings?.expand?.(node.label) ?? `Expand ${node.label}`} onClick={event => {event.stopPropagation(); focus(node.value); toggle(node);}}>\n {open ? <ChevronDown aria-hidden=\"true\" className=\"size-icon-sm\" /> : <ChevronRight aria-hidden=\"true\" className=\"size-icon-sm rtl:rotate-180\" />}\n </DisclosureButton>}\n </span>\n <CollectionContent label={renderLabel?.(node) ?? node.label} description={rich ? node.description : undefined} leading={node.icon} leadingClassName={ICON_DESCENDANT_SIZE_CLASSNAMES.md} leadingDecorative wrap={rich}\n bodyClassName={rich ? undefined : 'overflow-hidden'}\n trailing={node.trailing != null || (checked && selectionMode === 'multiple') ? <span className=\"inline-flex shrink-0 items-center gap-space-sm\">{node.trailing}{checked && selectionMode === 'multiple' && <Check aria-hidden=\"true\" className=\"size-icon shrink-0\" />}</span> : undefined} />\n </div>\n {branch && open && !!node.children?.length && <div role=\"group\" className={cn('tree--group flex flex-col border-s', navigationChildInsetClasses, recipe.childGap, showGuides ? 'border-border' : 'border-transparent')}\n style={indent === undefined ? undefined : { marginInlineStart: Math.max(0, indent) / 2, paddingInlineStart: Math.max(0, indent) / 2 }}>{rows(node.children, level + 1)}</div>}\n </div>;\n }); }\n return <div {...props} role=\"tree\" data-row-layout={rowLayout} aria-multiselectable={selectionMode === 'multiple' || undefined} aria-disabled={disabled || undefined} onKeyDown={keyboard} className={cn('tree--component flex min-w-0 flex-col', recipe.gap, className)}>\n {items.length ? rows(items, 1) : <Text type=\"secondary\">{empty}</Text>}\n </div>;\n}\n"],"mappings":"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"}
@@ -1,116 +0,0 @@
1
- "use client";
2
- import { _ as e, p as t, s as n } from "./ui-provider-D2_TeLqw.js";
3
- import { t as r } from "./utils-Cospvlj1.js";
4
- import { o as i, r as a, t as o } from "./text.styles-g4He6UIW.js";
5
- import { createContext as s, forwardRef as c, useContext as l } from "react";
6
- import { jsx as u, jsxs as d } from "react/jsx-runtime";
7
- //#region src/components/typography/running-text.ts
8
- var f = s(!1);
9
- function p() {
10
- return l(f);
11
- }
12
- //#endregion
13
- //#region src/components/typography/text.tsx
14
- var m = c(function({ content: e, children: n, type: a = "main", size: o, weight: s, align: c, lineHeight: l, numeric: d, invert: p = !1, tag: m = "p", className: h, ...g }, _) {
15
- let { defaultTextSize: v } = t(), y = n ?? e;
16
- return y == null || y === "" ? null : /* @__PURE__ */ u(m, {
17
- "data-typography": "text",
18
- ...g,
19
- ref: _,
20
- className: r("text--component", i({
21
- type: p ? "inverse" : a,
22
- size: o ?? v,
23
- weight: s,
24
- align: c,
25
- lineHeight: l,
26
- numeric: d
27
- }), h),
28
- children: /* @__PURE__ */ u(f.Provider, {
29
- value: !0,
30
- children: y
31
- })
32
- });
33
- });
34
- //#endregion
35
- //#region src/components/typography/heading.tsx
36
- function h({ tag: e = "h3", size: t = "base", subHeading: n, subHeadingClassName: i, subHeadingSize: s, containerClassName: c, align: l = "left", divider: p = !1, className: h, children: g, ref: _, ...v }) {
37
- return /* @__PURE__ */ d("div", {
38
- className: r("heading--component flex min-w-0 flex-col gap-dense", a[l], c),
39
- children: [g != null && /* @__PURE__ */ u(e, {
40
- ...v,
41
- ref: _,
42
- "data-typography": "heading",
43
- className: r("heading--title m-0 font-heading", o[t], "font-semibold text-foreground text-balance break-words", a[l], p && "border-b border-border pb-space-md", h),
44
- children: /* @__PURE__ */ u(f.Provider, {
45
- value: !0,
46
- children: g
47
- })
48
- }), n != null && /* @__PURE__ */ u(m, {
49
- type: "secondary",
50
- size: s,
51
- align: l,
52
- className: i,
53
- children: n
54
- })]
55
- });
56
- }
57
- //#endregion
58
- //#region src/components/typography/display-label.tsx
59
- function g({ tag: e = "span", tone: t = "default", className: n, ...i }) {
60
- return /* @__PURE__ */ u(m, {
61
- ...i,
62
- tag: e,
63
- size: "sm",
64
- type: "main",
65
- weight: "medium",
66
- lineHeight: "tight",
67
- "data-typography": "display-label",
68
- className: r("display-label--component", t === "inverse" && "text-inverse-muted", n)
69
- });
70
- }
71
- //#endregion
72
- //#region src/components/typography/label.tsx
73
- var _ = {
74
- sm: "text-xs",
75
- md: "text-sm",
76
- lg: "text-base"
77
- };
78
- function v({ content: t, children: i, size: a, className: o, ref: s, ...c }) {
79
- let { defaultScale: l } = n();
80
- return /* @__PURE__ */ u("label", {
81
- ...c,
82
- ref: s,
83
- "data-typography": "label",
84
- className: r("label--component font-sans font-medium leading-none text-foreground peer-disabled:cursor-not-allowed peer-disabled:opacity-50", _[e(a, l)], o),
85
- children: /* @__PURE__ */ u(f.Provider, {
86
- value: !0,
87
- children: i ?? t
88
- })
89
- });
90
- }
91
- //#endregion
92
- //#region src/components/typography/text-link.tsx
93
- var y = "w-fit max-w-full rounded-radius-xs outline-none box-decoration-clone transition-colors motion-reduce:transition-none focus-visible:ring-2 focus-visible:ring-ring", b = "underline decoration-current underline-offset-[0.2em]";
94
- function x({ type: e = "main", size: n, weight: a, align: o, lineHeight: s, underline: c = !0, className: l, ref: d, children: m, ...h }) {
95
- let { defaultTextSize: g } = t(), _ = p();
96
- return /* @__PURE__ */ u("a", {
97
- ...h,
98
- ref: d,
99
- "data-typography": "link",
100
- className: r("text-link--component", y, i({
101
- type: e,
102
- size: n ?? (_ ? "inherit" : g),
103
- weight: a ?? (_ ? "inherit" : void 0),
104
- align: o,
105
- lineHeight: s ?? (_ ? "inherit" : void 0)
106
- }), c ? `${b} hover:decoration-transparent` : "no-underline", l),
107
- children: /* @__PURE__ */ u(f.Provider, {
108
- value: !0,
109
- children: m
110
- })
111
- });
112
- }
113
- //#endregion
114
- export { g as a, f as c, v as i, p as l, y as n, h as o, b as r, m as s, x as t };
115
-
116
- //# sourceMappingURL=typography-CAr3dQhX.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"typography-CAr3dQhX.js","names":["resolveComponentScale","useTypographyConfig","useDensityConfig","cn","textVariants","textAlignments","headingSizes","RunningTextContext","createContext","useInRunningText","useContext","Text","forwardRef","Tag","props","value","children","content","invert","type","size","defaultTextSize","className","Heading","align","containerClassName","divider","subHeading","subHeadingSize","subHeadingClassName","DisplayLabel","tone","sizes","Label","defaultScale","inlineLinkClassName","linkUnderlineClassName","TextLink","inText","weight","lineHeight","underline"],"sources":["../src/components/typography/running-text.ts","../src/components/typography/text.tsx","../src/components/typography/heading.tsx","../src/components/typography/display-label.tsx","../src/components/typography/label.tsx","../src/components/typography/text-link.tsx"],"sourcesContent":["import { createContext, useContext } from 'react';\n\n/**\n * True below an element that renders running text: `Text`, `Heading`,\n * `DisplayLabel`, `Label`, `TextLink` and the inline value primitives.\n *\n * Inline value primitives read it to tell a value inside a sentence from a\n * standalone value. Inside running text their unset size, colour, weight and\n * leading inherit from the surrounding text; standalone values keep their role\n * defaults. Explicit props always win.\n */\nexport const RunningTextContext = createContext(false);\n\n/** Whether the caller renders inside running text owned by a typography role. */\nexport function useInRunningText(): boolean {\n\treturn useContext(RunningTextContext);\n}\n","import { forwardRef, type ComponentPropsWithoutRef, type ReactNode } from 'react';\nimport { useTypographyConfig, type TextSize } from '../../lib/ui-provider';\nimport { cn } from '../../lib/utils';\nimport { RunningTextContext } from './running-text';\nimport { textVariants, type textTypes, type textWeights, type textAlignments, type textLineHeights } from './text.styles';\n\nexport interface TextProps extends Omit<ComponentPropsWithoutRef<'p'>, 'children'> {\n /** Plain text fallback; children take precedence, including zero and empty strings. */\n content?: string;\n children?: ReactNode;\n /** Colour role. Defaults to `main`; `inherit` keeps the surrounding text colour. */\n type?: keyof typeof textTypes;\n /** Text size. Defaults to the provider `typography.defaultTextSize` (`sm`). */\n size?: TextSize;\n /** Font weight. Defaults to `regular`; `inherit` keeps the surrounding weight. */\n weight?: keyof typeof textWeights;\n /** Text alignment. Defaults to `left`; `left` and `right` follow the reading direction. */\n align?: keyof typeof textAlignments;\n /** Line height. Defaults to `normal`; `inherit` keeps the surrounding leading. */\n lineHeight?: keyof typeof textLineHeights;\n /** Renders the inverse colour role on inverse surfaces. Defaults to `false`. */\n invert?: boolean;\n /**\n * Monospace with tabular figures, for identifiers and code-like values. Numbers,\n * amounts and dates use the number primitives (tabular sans figures) instead.\n * Defaults to `false`.\n */\n numeric?: boolean;\n /** Rendered element. Defaults to `p`. */\n tag?: 'div' | 'p' | 'span';\n}\n\nexport const Text = forwardRef<HTMLElement, TextProps>(function Text({\n content, children, type = 'main', size, weight, align, lineHeight,\n numeric, invert = false, tag: Tag = 'p', className, ...props\n}, ref) {\n const {defaultTextSize} = useTypographyConfig();\n const value = children ?? content;\n if (value === undefined || value === null || value === '') return null;\n return <Tag data-typography=\"text\" {...props} ref={ref as never} className={cn('text--component', textVariants({type: invert ? 'inverse' : type, size: size ?? defaultTextSize, weight, align, lineHeight, numeric}), className)}>\n <RunningTextContext.Provider value>{value}</RunningTextContext.Provider>\n </Tag>;\n});\n","import type { HTMLAttributes, ReactNode, Ref } from 'react';\nimport type { TextSize } from '../../lib/ui-provider';\nimport { cn } from '../../lib/utils';\nimport { RunningTextContext } from './running-text';\nimport { headingSizes, textAlignments } from './text.styles';\nimport { Text } from './text';\n\nexport type HeadingTag = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';\nexport type HeadingSize = keyof typeof headingSizes;\nexport interface HeadingProps extends HTMLAttributes<HTMLHeadingElement> {\n ref?: Ref<HTMLHeadingElement>;\n /** Semantic outline level. Defaults to `h3`; it never changes the visual size. */\n tag?: HeadingTag;\n /**\n * Visual emphasis, independent of `tag`. Defaults to the compact admin `base`.\n * `xl` and larger tighten tracking; `2xl` and larger also tighten leading.\n */\n size?: HeadingSize;\n /** Secondary line under the title, rendered as secondary `Text`. */\n subHeading?: ReactNode;\n subHeadingClassName?: string;\n /** Text size of `subHeading`; defaults to the provider text size. */\n subHeadingSize?: TextSize;\n containerClassName?: string;\n /** Text alignment for the title and sub-heading. Defaults to `left`. */\n align?: keyof typeof textAlignments;\n /** Adds a bottom rule under the title. Defaults to `false`. */\n divider?: boolean;\n}\n\n/** Semantic heading levels share Themelia's restrained admin heading scale. */\nexport function Heading({tag: Tag = 'h3', size = 'base', subHeading, subHeadingClassName, subHeadingSize, containerClassName, align = 'left', divider = false, className, children, ref, ...props}: HeadingProps) {\n return <div className={cn('heading--component flex min-w-0 flex-col gap-dense', textAlignments[align], containerClassName)}>\n {children != null && <Tag {...props} ref={ref} data-typography=\"heading\" className={cn('heading--title m-0 font-heading', headingSizes[size], 'font-semibold text-foreground text-balance break-words', textAlignments[align], divider && 'border-b border-border pb-space-md', className)}><RunningTextContext.Provider value>{children}</RunningTextContext.Provider></Tag>}\n {subHeading != null && <Text type=\"secondary\" size={subHeadingSize} align={align} className={subHeadingClassName}>{subHeading}</Text>}\n </div>;\n}\n","import { Text, type TextProps } from './text';\nimport { cn } from '../../lib/utils';\n\nexport interface DisplayLabelProps extends Omit<TextProps, 'size' | 'type' | 'weight' | 'lineHeight'> {tone?: 'default' | 'inverse'}\nexport function DisplayLabel({tag = 'span', tone = 'default', className, ...props}: DisplayLabelProps) {\n return <Text {...props} tag={tag} size=\"sm\" type=\"main\" weight=\"medium\" lineHeight=\"tight\" data-typography=\"display-label\" className={cn('display-label--component', tone === 'inverse' && 'text-inverse-muted', className)} />;\n}\n","import type { LabelHTMLAttributes, ReactNode, Ref } from 'react';\nimport type { ComponentScale } from '../../lib/component-vocabulary';\nimport { useDensityConfig } from '../../lib/ui-provider';\nimport { resolveComponentScale } from '../../lib/ui-provider/scale';\nimport { cn } from '../../lib/utils';\nimport { RunningTextContext } from './running-text';\n\nexport interface LabelProps extends Omit<LabelHTMLAttributes<HTMLLabelElement>, 'content'> {\n /** Fallback content; children take precedence. */\n content?: ReactNode;\n /** Control scale the caption belongs to (`sm` → xs, `md` → sm, `lg` → base). Defaults to the provider density scale. */\n size?: ComponentScale;\n ref?: Ref<HTMLLabelElement>;\n}\nconst sizes = {sm: 'text-xs', md: 'text-sm', lg: 'text-base'} as const;\n/** Form caption for a control; medium weight, foreground, no incidental margins. */\nexport function Label({content, children, size, className, ref, ...props}: LabelProps) {\n const {defaultScale} = useDensityConfig();\n return <label {...props} ref={ref} data-typography=\"label\" className={cn('label--component font-sans font-medium leading-none text-foreground peer-disabled:cursor-not-allowed peer-disabled:opacity-50', sizes[resolveComponentScale(size, defaultScale)], className)}>\n <RunningTextContext.Provider value>{children ?? content}</RunningTextContext.Provider>\n </label>;\n}\n","import type { AnchorHTMLAttributes, Ref } from 'react';\nimport { useTypographyConfig } from '../../lib/ui-provider';\nimport { cn } from '../../lib/utils';\nimport { RunningTextContext, useInRunningText } from './running-text';\nimport { textVariants } from './text.styles';\nimport type { TextProps } from './text';\n\n/**\n * Inline-link mechanics shared by `TextLink` and the link primitives. As a flex\n * or grid item the link hugs its text, so neither the hit area nor the focus\n * ring stretches across the row. The full-strength ring uses the small radius\n * role and follows every line of a wrapped link. Links keep one colour whether\n * or not they were visited: the role colour is explicit.\n */\nexport const inlineLinkClassName = 'w-fit max-w-full rounded-radius-xs outline-none box-decoration-clone transition-colors motion-reduce:transition-none focus-visible:ring-2 focus-visible:ring-ring';\n\n/** Underline geometry shared with content links: proportional to the text size. */\nexport const linkUnderlineClassName = 'underline decoration-current underline-offset-[0.2em]';\n\nexport interface TextLinkProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'type'>, Pick<TextProps, 'type' | 'size' | 'weight' | 'align' | 'lineHeight'> {\n /** Text size. Defaults to the provider text size; inside running text, the surrounding size. */\n size?: TextProps['size'];\n /**\n * Underlined at rest, clearing on hover. Defaults to `true`; keep it for links\n * whose colour matches the surrounding text. `false` renders no underline and\n * leaves the hover treatment to the composition (a row, chip or menu).\n */\n underline?: boolean;\n ref?: Ref<HTMLAnchorElement>;\n}\n\n/**\n * Native anchor sibling of `Text`: the same roles plus link focus and hover\n * states. Inside running text an unset size, weight and leading follow the\n * sentence; the colour role stays, so the link still reads as a link.\n */\nexport function TextLink({type = 'main', size, weight, align, lineHeight, underline = true, className, ref, children, ...props}: TextLinkProps) {\n const {defaultTextSize} = useTypographyConfig();\n const inText = useInRunningText();\n return <a {...props} ref={ref} data-typography=\"link\" className={cn('text-link--component', inlineLinkClassName, textVariants({type, size: size ?? (inText ? 'inherit' : defaultTextSize), weight: weight ?? (inText ? 'inherit' : undefined), align, lineHeight: lineHeight ?? (inText ? 'inherit' : undefined)}), underline ? `${linkUnderlineClassName} hover:decoration-transparent` : 'no-underline', className)}>\n <RunningTextContext.Provider value>{children}</RunningTextContext.Provider>\n </a>;\n}\n"],"mappings":";;;;;;;AAWA,IAAaO,IAAqBC,EAAc,EAAK;AAGrD,SAAgBC,IAA4B;CAC3C,OAAOC,EAAWH,CAAkB;AACrC;;;ACgBA,IAAaI,IAAOC,EAAmC,SAAc,EACnE,YAAS,aAAU,UAAO,QAAQ,SAAM,WAAQ,UAAO,eACvD,YAAS,YAAS,IAAO,KAAKC,IAAM,KAAK,cAAW,GAAGC,KACtD,GAAK;CACN,IAAM,EAAC,uBAAmBb,EAAoB,GACxCc,IAAQC,KAAYC;CAE1B,OADIF,KAAiC,QAAQA,MAAU,KAAW,OAC3D,kBAACF,GAAD;EAAK,mBAAgB;EAAO,GAAIC;EAAY;EAAc,WAAWX,EAAG,mBAAmBC,EAAa;GAAC,MAAMc,IAAS,YAAYC;GAAM,MAAMC,KAAQC;GAAiB;GAAQ;GAAO;GAAY;EAAO,CAAC,GAAGC,CAAS;EAC7N,UAAA,kBAACf,EAAmB,UAApB;GAA6B,OAAA;GAAO,UAAAQ;EAAmC,CAAA;CACpE,CAAA;AACP,CAAC;;;ACXD,SAAgBQ,EAAQ,EAAC,KAAKV,IAAM,MAAM,UAAO,QAAQ,eAAY,wBAAqB,mBAAgB,uBAAoB,WAAQ,QAAQ,aAAU,IAAO,cAAW,aAAU,QAAK,GAAGC,KAAsB;CAChN,OAAO,kBAAC,OAAD;EAAK,WAAWX,EAAG,sDAAsDE,EAAemB,IAAQC,CAAkB;EAAlH,UAAA,CACJT,KAAY,QAAQ,kBAACH,GAAD;GAAK,GAAIC;GAAY;GAAK,mBAAgB;GAAU,WAAWX,EAAG,mCAAmCG,EAAac,IAAO,0DAA0Df,EAAemB,IAAQE,KAAW,sCAAsCJ,CAAS;GAAG,UAAA,kBAACf,EAAmB,UAApB;IAA6B,OAAA;IAAO;GAAsC,CAAA;EAAM,CAAA,GAC3WoB,KAAc,QAAQ,kBAAChB,GAAD;GAAM,MAAK;GAAY,MAAMiB;GAAuB;GAAO,WAAWC;GAAsB,UAAAF;EAAiB,CAAA,CACjI;;AACP;;;AChCA,SAAgBG,EAAa,EAAC,SAAM,QAAQ,UAAO,WAAW,cAAW,GAAGhB,KAA2B;CACrG,OAAO,kBAACH,GAAD;EAAM,GAAIG;EAAY;EAAK,MAAK;EAAK,MAAK;EAAO,QAAO;EAAS,YAAW;EAAQ,mBAAgB;EAAgB,WAAWX,EAAG,4BAA4B4B,MAAS,aAAa,sBAAsBT,CAAS;CAAI,CAAA;AAChO;;;ACQA,IAAMU,IAAQ;CAAC,IAAI;CAAW,IAAI;CAAW,IAAI;AAAW;AAE5D,SAAgBC,EAAM,EAAC,YAAS,aAAU,SAAM,cAAW,QAAK,GAAGnB,KAAoB;CACrF,IAAM,EAAC,oBAAgBZ,EAAiB;CACxC,OAAO,kBAAC,SAAD;EAAO,GAAIY;EAAY;EAAK,mBAAgB;EAAQ,WAAWX,EAAG,iIAAiI6B,EAAMhC,EAAsBoB,GAAMc,CAAY,IAAIZ,CAAS;EACnQ,UAAA,kBAACf,EAAmB,UAApB;GAA6B,OAAA;GAAO,UAAAS,KAAYC;EAAqC,CAAA;CAChF,CAAA;AACT;;;ACPA,IAAakB,IAAsB,qKAGtBC,IAAyB;AAmBtC,SAAgBC,EAAS,EAAC,UAAO,QAAQ,SAAM,WAAQ,UAAO,eAAY,eAAY,IAAM,cAAW,QAAK,aAAU,GAAGvB,KAAuB;CAC9I,IAAM,EAAC,uBAAmBb,EAAoB,GACxCqC,IAAS7B,EAAiB;CAChC,OAAO,kBAAC,KAAD;EAAG,GAAIK;EAAY;EAAK,mBAAgB;EAAO,WAAWX,EAAG,wBAAwBgC,GAAqB/B,EAAa;GAAC;GAAM,MAAMgB,MAASkB,IAAS,YAAYjB;GAAkB,QAAQkB,MAAWD,IAAS,YAAY,KAAA;GAAY;GAAO,YAAYE,MAAeF,IAAS,YAAY,KAAA;EAAU,CAAC,GAAGG,IAAY,GAAGL,EAAuB,iCAAiC,gBAAgBd,CAAS;EAClZ,UAAA,kBAACf,EAAmB,UAApB;GAA6B,OAAA;GAAO;EAAsC,CAAA;CACzE,CAAA;AACL"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ui-provider-D2_TeLqw.js","names":["DEFAULT_UI_CONFIG","isComponentScale","COMPONENT_SCALES","value","resolveComponentScale","propScale","providerScale","fallback","resolveUIConfig","config","base","createUIStore","createStore","UIStoreContext","createContext","fallbackUIStore","useUIStore","contextualStore","useContext","useStore","selector","UIProvider","parentStore","storeRef","useRef","useEffect","useDensityConfig","s","useFormattingConfig","useMoneyConfig","useDatesConfig","useCommentsConfig","useTypographyConfig","useItemConfig","useButtonConfig","useBadgeConfig","useCardConfig","useToastConfig","useSpinnerConfig","DirectionProvider"],"sources":["../src/lib/ui-provider/defaults.ts","../src/lib/ui-provider/scale.ts","../src/lib/ui-provider/store.ts","../src/lib/ui-provider/provider.tsx","../src/lib/ui-provider/hooks.ts"],"sourcesContent":["/**\n * Hardcoded library-wide defaults.\n *\n * These are the values the store ships with — every component reading via\n * `useFooConfig()` gets these even when no `<UIProvider>` is mounted.\n *\n * Each `<UIProvider>` creates an isolated mount-once store synchronously, so\n * these defaults work for browser rendering, SSR, and multiple React roots.\n * Components outside a provider read the no-provider fallback store.\n */\nimport type { ResolvedUIConfig } from './types';\n\nexport const DEFAULT_UI_CONFIG: ResolvedUIConfig = {\n\tdensity: {\n\t\tdefaultScale: 'md',\n\t},\n\tformatting: {\n\t\tlocale: 'en-US',\n\t},\n\tmoney: {\n\t\tdefaultCurrency: 'USD',\n\t\tdualPricingEnabled: false,\n\t\tdisplayMode: 'default_only',\n\t\tdualPricingDisplay: 'lines',\n\t\tformatMode: 'with_code',\n\t},\n\tdates: {\n\t\tweekStartsOn: 1,\n\t\tformat: 'dd MMM yyyy',\n\t},\n\tcomments: {\n\t\tcomposerPosition: 'top',\n\t},\n\ttypography: {\n\t\tdefaultTextSize: 'sm',\n\t},\n\titem: {\n\t\tdefaultVariant: 'default',\n\t},\n\tbutton: {\n\t\t// The neutral button; the one main command opts into tone=\"primary\".\n\t\tdefaultTone: 'secondary',\n\t\tdefaultButtonStyle: 'outline',\n\t},\n\tbadge: {\n\t\tdefaultTone: 'neutral',\n\t},\n\tcard: {\n\t\tdefaultSurface: 'framed',\n\t\tdefaultHeaderDivider: false,\n\t\tdefaultFooterDivider: false,\n\t},\n\ttoast: {\n\t\tduration: 5000,\n\t\tposition: 'bottom-center',\n\t\ttheme: 'dark',\n\t\tcloseButton: true,\n\t\trichColors: false,\n\t\tvisibleToasts: 4,\n\t},\n\tspinner: {\n\t\tdefaultVariant: 'default',\n\t},\n};\n","import {\n\tCOMPONENT_SCALES,\n\ttype ComponentScale,\n} from '../component-vocabulary';\n\n/** Runtime guard for serialized or otherwise untyped component scale values. */\nexport function isComponentScale(value: unknown): value is ComponentScale {\n\treturn COMPONENT_SCALES.includes(value as ComponentScale);\n}\n\n/** Resolve direct, provider, and local scale defaults in precedence order. */\nexport function resolveComponentScale(\n\tpropScale: ComponentScale | undefined,\n\tproviderScale: ComponentScale | undefined,\n\tfallback: ComponentScale = 'md',\n): ComponentScale {\n\tif (isComponentScale(propScale)) return propScale;\n\tif (isComponentScale(providerScale)) return providerScale;\n\treturn isComponentScale(fallback) ? fallback : 'md';\n}\n","/**\n * Store plumbing for `<UIProvider>`.\n *\n * Each provider owns a vanilla Zustand store. This keeps independent React\n * roots and concurrent SSR requests isolated while retaining slice-scoped\n * subscriptions. A fallback store keeps components functional when no\n * provider is mounted and preserves the historical test bootstrap helpers.\n */\nimport { createContext, useContext } from 'react';\nimport { useStore } from 'zustand';\nimport { createStore, type StoreApi } from 'zustand/vanilla';\n\nimport { DEFAULT_UI_CONFIG } from './defaults';\nimport { resolveComponentScale } from './scale';\nimport type { ResolvedUIConfig, UIConfig } from './types';\n\nexport type UIStore = StoreApi<ResolvedUIConfig>;\n\n/**\n * Merge a partial config over a resolved base: the package defaults for a\n * root provider, or the parent provider's resolved defaults when nested.\n */\nexport function resolveUIConfig(\n\tconfig: UIConfig = {},\n\tbase: ResolvedUIConfig = DEFAULT_UI_CONFIG,\n): ResolvedUIConfig {\n\treturn {\n\t\tdensity: {\n\t\t\tdefaultScale: resolveComponentScale(\n\t\t\t\tconfig.density?.defaultScale,\n\t\t\t\tbase.density.defaultScale,\n\t\t\t),\n\t\t},\n\t\tformatting: { ...base.formatting, ...config.formatting },\n\t\tmoney: { ...base.money, ...config.money },\n\t\tdates: { ...base.dates, ...config.dates },\n\t\tcomments: { ...base.comments, ...config.comments },\n\t\ttypography: { ...base.typography, ...config.typography },\n\t\titem: { ...base.item, ...config.item },\n\t\tbutton: { ...base.button, ...config.button },\n\t\tbadge: { ...base.badge, ...config.badge },\n\t\tcard: { ...base.card, ...config.card },\n\t\ttoast: { ...base.toast, ...config.toast },\n\t\tspinner: { ...base.spinner, ...config.spinner },\n\t};\n}\n\nexport function createUIStore(config: UIConfig = {}, base?: ResolvedUIConfig): UIStore {\n\treturn createStore<ResolvedUIConfig>(() => resolveUIConfig(config, base));\n}\n\nexport const UIStoreContext = createContext<UIStore | null>(null);\n\nconst fallbackUIStore = createUIStore();\n\nexport function useUIStore<T>(selector: (state: ResolvedUIConfig) => T): T {\n\tconst contextualStore = useContext(UIStoreContext);\n\treturn useStore(contextualStore ?? fallbackUIStore, selector);\n}\n\n/** Test-only helper for components rendered without a provider. */\nexport function applyUIConfig(config: UIConfig): void {\n\tfallbackUIStore.setState((state) => {\n\t\tconst next = { ...state };\n\t\tconst nextSlices = next as unknown as Record<keyof UIConfig, object>;\n\t\tconst currentSlices = state as unknown as Record<keyof UIConfig, object>;\n\n\t\tfor (const key of Object.keys(config) as Array<keyof UIConfig>) {\n\t\t\tconst override = config[key];\n\t\t\tif (!override) continue;\n\t\t\tnextSlices[key] = { ...currentSlices[key], ...override };\n\t\t}\n\n\t\treturn next;\n\t});\n}\n\n/** Test-only reset for the no-provider fallback store. */\nexport function resetUIConfig(): void {\n\tfallbackUIStore.setState(resolveUIConfig(), true);\n}\n","/**\n * `<UIProvider>` — an isolated, mount-once display-default boundary.\n *\n * The store is created synchronously on the first render, so server output,\n * hydration, and the first browser render all observe the same configuration.\n * Independent roots and SSR requests never share mutable provider state. A\n * nested provider starts from its parent's resolved defaults and overrides\n * only the keys it sets.\n */\nimport { useContext, useEffect, useRef, type ReactNode } from 'react';\n\nimport { createUIStore, UIStoreContext, type UIStore } from './store';\nimport type { UIConfig } from './types';\n\nexport interface UIProviderProps {\n\t/**\n\t * Partial display-default tree merged over the nearest parent provider's\n\t * defaults, or over `DEFAULT_UI_CONFIG` at the root.\n\t */\n\tconfig?: UIConfig;\n\tchildren: ReactNode;\n}\n\nexport function UIProvider({ config, children }: UIProviderProps) {\n\tconst parentStore = useContext(UIStoreContext);\n\tconst storeRef = useRef<UIStore | null>(null);\n\tconst initialConfigRef = useRef<UIConfig | undefined>(config);\n\n\tif (storeRef.current === null) {\n\t\t// Both providers are mount-once, so the parent snapshot stays exact.\n\t\tstoreRef.current = createUIStore(config, parentStore?.getState());\n\t}\n\n\tuseEffect(() => {\n\t\tif (import.meta.env?.DEV && initialConfigRef.current !== config) {\n\t\t\tconsole.warn(\n\t\t\t\t'[UIProvider] `config` is mount-once. Subsequent prop identity ' +\n\t\t\t\t\t'changes are ignored; use direct component props for per-mount state.',\n\t\t\t);\n\t\t}\n\t}, [config]);\n\n\treturn (\n\t\t<UIStoreContext.Provider value={storeRef.current}>\n\t\t\t{children}\n\t\t</UIStoreContext.Provider>\n\t);\n}\n","/**\n * Slice selector hooks.\n *\n * Each hook reads exactly one slice from the store. Components that only\n * care about `money` will not re-render when `dates` changes, etc.\n *\n * Every selector returns a guaranteed-populated slice (the store is\n * initialized with `DEFAULT_UI_CONFIG`), so component code can write:\n *\n * const { defaultCurrency } = useMoneyConfig();\n * const currency = props.currency ?? defaultCurrency;\n *\n * — no need to chain optional-access through the slice.\n */\nimport { useUIStore } from './store';\nimport type {\n\tButtonConfigSlice,\n\tBadgeConfigSlice,\n\tCardConfigSlice,\n\tCommentsDefaultsConfig,\n\tDatesConfig,\n\tDensityConfigSlice,\n\tFormattingConfigSlice,\n\tItemConfigSlice,\n\tMoneyConfig,\n\tSpinnerConfigSlice,\n\tToastConfig,\n\tTypographyConfigSlice,\n} from './types';\n\nexport const useDensityConfig = (): DensityConfigSlice =>\n\tuseUIStore((s) => s.density);\n\nexport const useFormattingConfig = (): FormattingConfigSlice =>\n\tuseUIStore((s) => s.formatting);\n\nexport const useMoneyConfig = (): MoneyConfig =>\n\tuseUIStore((s) => s.money);\n\nexport const useDatesConfig = (): DatesConfig =>\n\tuseUIStore((s) => s.dates);\n\nexport const useCommentsConfig = (): CommentsDefaultsConfig =>\n\tuseUIStore((s) => s.comments);\n\nexport const useTypographyConfig = (): TypographyConfigSlice =>\n\tuseUIStore((s) => s.typography);\n\nexport const useItemConfig = (): ItemConfigSlice =>\n\tuseUIStore((s) => s.item);\n\nexport const useButtonConfig = (): ButtonConfigSlice =>\n\tuseUIStore((s) => s.button);\n\nexport const useBadgeConfig = (): BadgeConfigSlice =>\n\tuseUIStore((s) => s.badge);\n\nexport const useCardConfig = (): CardConfigSlice =>\n\tuseUIStore((s) => s.card);\n\nexport const useToastConfig = (): ToastConfig =>\n\tuseUIStore((s) => s.toast);\n\nexport const useSpinnerConfig = (): SpinnerConfigSlice =>\n\tuseUIStore((s) => s.spinner);\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"upload-B0WHW7ak.js","names":["React","resolveComponentScale","useFormattingConfig","useDensityConfig","cn","Text","Button","AlertDescription","Alert","AlertTitle","formatFileSize","FileSize","fieldAffordanceRecipes","ItemGroup","useFileDropTarget","Dropzone","FilePickerInput","uploadDropTargetRecipes","AttachmentFileIcon","AttachmentTitle","AttachmentDescription","AttachmentActions","AttachmentMedia","AttachmentContent","Attachment","React$1","React","defaultFileUploadStrings","fileName","accept","minimum","maximum","fileFingerprint","file","fileMatchesAccept","fileType","part","rule","validateOneFile","options","strings","minSizeBytes","formatSize","maxSizeBytes","validateFile","result","validateFileSelection","nextFiles","append","current","fingerprints","accepted","rejections","incoming","validationRejection","fingerprint","maxFiles","hasOwnValue","props","normalizeMaximum","value","fileKey","index","assignInputRef","node","forwardedRef","SelectedFileRow","replaceLabel","removeLabel","showReplace","UploadIcon","onReplace","Trash2Icon","onRemove","FileUploadImpl","sizeProp","stringsProp","_value","_defaultValue","_onValueChange","_selectionMode","_maxFiles","ariaDescribedBy","nativeAriaInvalid","nativeInputProps","useStrings","size","defaultScale","controlled","uncontrolledFiles","setUncontrolledFiles","useState","setRejections","inputRef","useRef","rootRef","continueFocus","pickerWasFocused","generatedId","useId","files","useMemo","target","multipleProps","multiple","errorId","describedBy","hasInvalidState","invalid","commitFiles","useCallback","nextFile","bytes","locale","handleFiles","disabled","onRejectedFiles","clearNativeInput","handleRemove","fileIndex","openPicker","inputProps","picker","className","dropTargetProps","isDragging","TriangleAlert","rejection","FileUpload","forwardRef","FILE_SIZE_UNITS","defaultFormatSize","unitIndex","idCounter","generateId","getExtension","getFingerprint","createMeta","extension","rules","allowed","toErrorMap","useFiles","setFilesState","filesRef","processFiles","incomingFiles","previousFiles","replace","meta","nextRejections","id","MAX_FILE_SIZE_MB","ASPECT_RATIO_CLASSES","defaultImageUploadStrings","count","getImageUploadRejectionMessage","code","details","ImageUploadImpl","inputId","allowedExtensions","parsed","item","subtype","ext","setFiles","removeAll","selected","selectOrChangeButtonLabel","filePreviewUrl","setFilePreviewUrl","acceptedExtensionsLabel","url","previewUrl","initialPreviewUrl","hasPreview","previewAlt","aspectClass","aspectRatio","imgFitClass","fit","computedMaxWidth","maxWidth","wrapperStyle","layout","inlinePreviewStyle","acceptedFile","onValueChange","handleInput","event","triggerFileDialog","remove","ImageIcon","ImageUpload","defaultAvatarUploadStrings","getAvatarUploadRejectionMessage","SIZE_PX","AvatarUploadImpl","sizes","s","list","initials","Camera","X","AvatarUpload"],"sources":["../src/components/base/upload/file-upload.strings.ts","../src/components/base/upload/file-upload.validation.ts","../src/components/base/upload/file-upload.tsx","../src/hooks/use-files.ts","../src/components/base/upload/image-upload.tsx","../src/components/base/upload/avatar-upload.tsx"],"sourcesContent":["export interface FileUploadStrings {\n\tinstruction: string;\n\thelper: string;\n\tbrowse: string;\n\treplace: string;\n\tremove: string;\n\tdragOver: string;\n\terrorsHeading: string;\n\treplaceFileAria: (fileName: string) => string;\n\tremoveFileAria: (fileName: string) => string;\n\tinvalidType: (fileName: string, accept: string) => string;\n\tfileTooSmall: (fileName: string, minimum: string) => string;\n\tfileTooLarge: (fileName: string, maximum: string) => string;\n\ttooManyFiles: (fileName: string, maximum: number) => string;\n\tduplicateFile: (fileName: string) => string;\n\tcustomValidationFailed: (fileName: string) => string;\n}\n\nexport const defaultFileUploadStrings: FileUploadStrings = {\n\tinstruction: 'Drag files here or click to browse',\n\thelper: '',\n\tbrowse: 'Browse files',\n\treplace: 'Replace file',\n\tremove: 'Remove file',\n\tdragOver: 'Release to select',\n\terrorsHeading: 'Some files could not be selected',\n\treplaceFileAria: (fileName) => `Replace ${fileName}`,\n\tremoveFileAria: (fileName) => `Remove ${fileName}`,\n\tinvalidType: (fileName, accept) => `${fileName} is not an accepted file type (${accept}).`,\n\tfileTooSmall: (fileName, minimum) => `${fileName} is smaller than the minimum size of ${minimum}.`,\n\tfileTooLarge: (fileName, maximum) => `${fileName} is larger than the maximum size of ${maximum}.`,\n\ttooManyFiles: (fileName, maximum) => `${fileName} exceeds the limit of ${maximum} files.`,\n\tduplicateFile: (fileName) => `${fileName} has already been selected.`,\n\tcustomValidationFailed: (fileName) => `${fileName} did not pass validation.`,\n};\n\n","import type {\n\tFileUploadRejection,\n\tFileUploadValidator,\n} from './file-upload.types';\nimport type { FileUploadStrings } from './file-upload.strings';\n\ninterface ValidateFileSelectionOptions {\n\tincoming: File[];\n\tcurrent: File[];\n\taccept?: string;\n\tminSizeBytes?: number;\n\tmaxSizeBytes?: number;\n\tmaxFiles: number;\n\tappend: boolean;\n\tvalidateFile?: FileUploadValidator;\n\tformatSize: (bytes: number) => string;\n\tstrings: FileUploadStrings;\n}\n\nexport interface FileSelectionResult {\n\taccepted: File[];\n\tnextFiles: File[];\n\trejections: FileUploadRejection[];\n}\n\nfunction fileFingerprint(file: File) {\n\treturn `${file.name}\\u0000${file.size}\\u0000${file.type}\\u0000${file.lastModified}`;\n}\n\nfunction fileMatchesAccept(file: File, accept?: string) {\n\tif (!accept?.trim()) return true;\n\n\tconst fileName = file.name.toLowerCase();\n\tconst fileType = file.type.toLowerCase();\n\treturn accept\n\t\t.split(',')\n\t\t.map((part) => part.trim().toLowerCase())\n\t\t.filter(Boolean)\n\t\t.some((rule) => {\n\t\t\tif (rule.startsWith('.')) return fileName.endsWith(rule);\n\t\t\tif (rule.endsWith('/*')) return fileType.startsWith(rule.slice(0, -1));\n\t\t\treturn fileType === rule;\n\t\t});\n}\n\nfunction validateOneFile(\n\tfile: File,\n\toptions: Pick<\n\t\tValidateFileSelectionOptions,\n\t\t'accept' | 'minSizeBytes' | 'maxSizeBytes' | 'validateFile' | 'formatSize' | 'strings'\n\t>,\n): FileUploadRejection | undefined {\n\tconst { accept, minSizeBytes, maxSizeBytes, validateFile, formatSize, strings } = options;\n\n\tif (!fileMatchesAccept(file, accept)) {\n\t\treturn {\n\t\t\tfile,\n\t\t\tcode: 'invalid-type',\n\t\t\tmessage: strings.invalidType(file.name, accept ?? ''),\n\t\t};\n\t}\n\tif (minSizeBytes !== undefined && file.size < minSizeBytes) {\n\t\treturn {\n\t\t\tfile,\n\t\t\tcode: 'too-small',\n\t\t\tmessage: strings.fileTooSmall(file.name, formatSize(minSizeBytes)),\n\t\t};\n\t}\n\tif (maxSizeBytes !== undefined && file.size > maxSizeBytes) {\n\t\treturn {\n\t\t\tfile,\n\t\t\tcode: 'too-large',\n\t\t\tmessage: strings.fileTooLarge(file.name, formatSize(maxSizeBytes)),\n\t\t};\n\t}\n\tif (validateFile) {\n\t\tlet result: boolean | string;\n\t\ttry {\n\t\t\tresult = validateFile(file);\n\t\t} catch {\n\t\t\tresult = false;\n\t\t}\n\t\tif (result !== true) {\n\t\t\treturn {\n\t\t\t\tfile,\n\t\t\t\tcode: 'custom',\n\t\t\t\tmessage: typeof result === 'string'\n\t\t\t\t\t? result\n\t\t\t\t\t: strings.customValidationFailed(file.name),\n\t\t\t};\n\t\t}\n\t}\n\n\treturn undefined;\n}\n\nexport function validateFileSelection({\n\tincoming,\n\tcurrent,\n\taccept,\n\tminSizeBytes,\n\tmaxSizeBytes,\n\tmaxFiles,\n\tappend,\n\tvalidateFile,\n\tformatSize,\n\tstrings,\n}: ValidateFileSelectionOptions): FileSelectionResult {\n\tconst nextFiles = append ? [...current] : [];\n\tconst fingerprints = new Set(nextFiles.map(fileFingerprint));\n\tconst accepted: File[] = [];\n\tconst rejections: FileUploadRejection[] = [];\n\n\tfor (const file of incoming) {\n\t\tconst validationRejection = validateOneFile(file, {\n\t\t\taccept,\n\t\t\tminSizeBytes,\n\t\t\tmaxSizeBytes,\n\t\t\tvalidateFile,\n\t\t\tformatSize,\n\t\t\tstrings,\n\t\t});\n\t\tif (validationRejection) {\n\t\t\trejections.push(validationRejection);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst fingerprint = fileFingerprint(file);\n\t\tif (fingerprints.has(fingerprint)) {\n\t\t\trejections.push({\n\t\t\t\tfile,\n\t\t\t\tcode: 'duplicate',\n\t\t\t\tmessage: strings.duplicateFile(file.name),\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (nextFiles.length >= maxFiles) {\n\t\t\trejections.push({\n\t\t\t\tfile,\n\t\t\t\tcode: 'too-many',\n\t\t\t\tmessage: strings.tooManyFiles(file.name, maxFiles),\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\taccepted.push(file);\n\t\tnextFiles.push(file);\n\t\tfingerprints.add(fingerprint);\n\t}\n\n\treturn { accepted, nextFiles, rejections };\n}\n","/**\n * FileUpload — controlled or uncontrolled local-file selection with validation.\n * The component never transfers files; consumers own upload/network behavior.\n */\nimport {\n\tforwardRef,\n\tuseCallback,\n\tuseLayoutEffect,\n\tuseId,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n\ttype ForwardedRef,\n\ttype MutableRefObject,\n} from 'react';\nimport {\n\tTrash2Icon,\n\tTriangleAlert,\n\tUploadIcon,\n} from 'lucide-react';\n\nimport { Button } from '../buttons';\nimport { Alert, AlertDescription, AlertTitle } from '../feedback';\nimport {\n\tItemGroup,\n} from '../item';\nimport { Attachment, AttachmentMedia, AttachmentContent, AttachmentTitle, AttachmentDescription, AttachmentActions, AttachmentFileIcon } from '../attachment';\nimport { FileSize, formatFileSize } from '../../primitives';\nimport { Text } from '../../typography';\nimport { useStrings } from '../../../lib/strings';\nimport { useFormattingConfig, useDensityConfig, type ComponentScale } from '../../../lib/ui-provider';\nimport { resolveComponentScale } from '../../../lib/ui-provider/scale';\nimport { cn } from '../../../lib/utils';\n\nimport { Dropzone } from './dropzone';\nimport {\n\tFilePickerInput,\n\ttype FilePickerNativeInputProps,\n} from './file-picker-input';\nimport {\n\tdefaultFileUploadStrings,\n\ttype FileUploadStrings,\n} from './file-upload.strings';\nimport type {\n\tFileUploadRejection,\n\tMultipleFileUploadProps,\n\tSingleFileUploadProps,\n} from './file-upload.types';\nimport { validateFileSelection } from './file-upload.validation';\nimport { useFileDropTarget } from './use-file-drop-target';\n\n/** Public discriminated single/multiple contract, declared here for docgen discoverability. */\nexport type FileUploadProps = SingleFileUploadProps | MultipleFileUploadProps;\n\nfunction hasOwnValue(props: FileUploadProps) {\n\treturn Object.prototype.hasOwnProperty.call(props, 'value');\n}\n\nfunction normalizeMaximum(value: number | undefined) {\n\tif (value === undefined) return Number.MAX_SAFE_INTEGER;\n\tif (!Number.isFinite(value)) return Number.MAX_SAFE_INTEGER;\n\treturn Math.max(1, Math.floor(value));\n}\n\nfunction fileKey(file: File, index: number) {\n\treturn `${file.name}-${file.size}-${file.type}-${file.lastModified}-${index}`;\n}\n\nfunction assignInputRef(\n\tnode: HTMLInputElement | null,\n\tlocalRef: MutableRefObject<HTMLInputElement | null>,\n\tforwardedRef: ForwardedRef<HTMLInputElement>,\n) {\n\tlocalRef.current = node;\n\tif (typeof forwardedRef === 'function') forwardedRef(node);\n\telse if (forwardedRef) forwardedRef.current = node;\n}\n\ninterface SelectedFileRowProps {\n\tfile: File;\n\tindex: number;\n\tdisabled: boolean;\n\tsize: ComponentScale;\n\tlocale?: string;\n\tstrings: FileUploadStrings;\n\tshowReplace: boolean;\n\tonReplace: () => void;\n\tonRemove: (index: number) => void;\n}\n\nfunction SelectedFileRow({\n\tfile,\n\tindex,\n\tdisabled,\n\tsize,\n\tlocale,\n\tstrings,\n\tshowReplace,\n\tonReplace,\n\tonRemove,\n}: SelectedFileRowProps) {\n\tconst replaceLabel = strings.replaceFileAria(file.name);\n\tconst removeLabel = strings.removeFileAria(file.name);\n\n\treturn (\n\t\t<Attachment\n\t\t\tvariant=\"outline\"\n\t\t\tsize={size}\n\t\t\tclassName=\"file-upload--file flex-nowrap bg-card text-card-foreground\"\n\t\t>\n\t\t\t<AttachmentMedia variant=\"icon\" className=\"file-upload--file-media self-center group-has-data-[slot=item-description]/item:self-center\">\n\t\t\t\t<AttachmentFileIcon name={file.name} />\n\t\t\t</AttachmentMedia>\n\t\t\t<AttachmentContent className=\"file-upload--file-content min-w-0\">\n\t\t\t\t<AttachmentTitle className=\"file-upload--file-name truncate\" title={file.name}>\n\t\t\t\t\t{file.name}\n\t\t\t\t</AttachmentTitle>\n\t\t\t\t<AttachmentDescription className=\"file-upload--file-size\" clamp={1}>\n\t\t\t\t\t<FileSize\n\t\t\t\t\t\tvalue={file.size}\n\t\t\t\t\t\tlocale={locale}\n\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\talign=\"left\"\n\t\t\t\t\t\ttype=\"secondary\"\n\t\t\t\t\t/>\n\t\t\t\t</AttachmentDescription>\n\t\t\t</AttachmentContent>\n\t\t\t<AttachmentActions className=\"file-upload--actions gap-space-xs\">\n\t\t\t\t{showReplace && (\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\t\tsize=\"sm\" iconOnly\n\t\t\t\t\t\ticon={UploadIcon}\n\t\t\t\t\t\taria-label={replaceLabel}\n\t\t\t\t\t\ttitle={replaceLabel}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tonClick={onReplace}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Text tag=\"span\" size=\"inherit\" className=\"sr-only\">\n\t\t\t\t\t\t\t{strings.replace}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t</Button>\n\t\t\t\t)}\n\t\t\t\t<Button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\ttone=\"destructive\"\n\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\tsize=\"sm\" iconOnly\n\t\t\t\t\ticon={Trash2Icon}\n\t\t\t\t\taria-label={removeLabel}\n\t\t\t\t\ttitle={removeLabel}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tonClick={() => onRemove(index)}\n\t\t\t\t>\n\t\t\t\t\t<Text tag=\"span\" size=\"inherit\" className=\"sr-only\">\n\t\t\t\t\t\t{strings.remove}\n\t\t\t\t\t</Text>\n\t\t\t\t</Button>\n\t\t\t</AttachmentActions>\n\t\t</Attachment>\n\t);\n}\n\nfunction FileUploadImpl(\n\tprops: FileUploadProps,\n\tforwardedRef: ForwardedRef<HTMLInputElement>,\n) {\n\tconst {\n\t\taccept,\n\t\tdisabled = false,\n\t\tinvalid = false,\n\t\tsize: sizeProp,\n\t\tminSizeBytes,\n\t\tmaxSizeBytes,\n\t\tvalidateFile,\n\t\tonRejectedFiles,\n\t\tclassName,\n\t\tstrings: stringsProp,\n\t\tmultiple = false,\n\t\tvalue: _value,\n\t\tdefaultValue: _defaultValue,\n\t\tonValueChange: _onValueChange,\n\t\tselectionMode: _selectionMode,\n\t\tmaxFiles: _maxFiles,\n\t\t'aria-describedby': ariaDescribedBy,\n\t\t'aria-invalid': nativeAriaInvalid,\n\t\t...nativeInputProps\n\t} = props;\n\tconst strings = useStrings(defaultFileUploadStrings, stringsProp);\n\tconst { defaultScale } = useDensityConfig();\n\tconst { locale } = useFormattingConfig();\n\tconst size = resolveComponentScale(sizeProp, defaultScale);\n\tconst controlled = hasOwnValue(props);\n\tconst [uncontrolledFiles, setUncontrolledFiles] = useState<File[]>(() => {\n\t\tif (props.multiple) return [...(props.defaultValue ?? [])];\n\t\treturn props.defaultValue ? [props.defaultValue] : [];\n\t});\n\tconst [rejections, setRejections] = useState<FileUploadRejection[]>([]);\n\tconst inputRef = useRef<HTMLInputElement | null>(null);\n\tconst rootRef = useRef<HTMLDivElement | null>(null);\n\tconst continueFocus = useRef(false);\n\tconst pickerWasFocused = useRef(false);\n\tconst generatedId = useId();\n\n\tconst files = useMemo(() => {\n\t\tif (!controlled) return uncontrolledFiles;\n\t\tif (props.multiple) return props.value ?? [];\n\t\treturn props.value ? [props.value] : [];\n\t}, [controlled, props.multiple, props.value, uncontrolledFiles]);\n\tuseLayoutEffect(() => {\n\t\tif (!continueFocus.current) return;\n\t\tconst target = rootRef.current?.querySelector<HTMLElement>('.file-upload--actions button, .file-upload--dropzone input[type=file], .file-upload--dropzone button');\n\t\tif (target) {\n\t\t\ttarget.focus();\n\t\t\tcontinueFocus.current = false;\n\t\t}\n\t}, [files]);\n\tconst multipleProps = props.multiple ? props as MultipleFileUploadProps : undefined;\n\tconst maxFiles = multiple ? normalizeMaximum(multipleProps?.maxFiles) : 1;\n\tconst append = multiple && (multipleProps?.selectionMode ?? 'append') === 'append';\n\tconst errorId = `${nativeInputProps.id ?? `file-upload-${generatedId}`}-errors`;\n\tconst describedBy = [ariaDescribedBy, rejections.length > 0 ? errorId : undefined]\n\t\t.filter(Boolean)\n\t\t.join(' ') || undefined;\n\tconst hasInvalidState = invalid || rejections.length > 0;\n\n\tconst commitFiles = useCallback((nextFiles: File[]) => {\n\t\tif (!controlled) setUncontrolledFiles(nextFiles);\n\t\tif (props.multiple) {\n\t\t\tprops.onValueChange?.(nextFiles);\n\t\t} else {\n\t\t\tconst nextFile = nextFiles[0];\n\t\t\tprops.onValueChange?.(nextFile);\n\t\t}\n\t}, [controlled, props]);\n\n\tconst formatSize = useCallback((bytes: number) => (\n\t\tformatFileSize(bytes, { locale }) ?? `${bytes} B`\n\t), [locale]);\n\n\tconst handleFiles = useCallback((incoming: File[]) => {\n\t\tif (disabled || incoming.length === 0) return false;\n\t\tconst result = validateFileSelection({\n\t\t\tincoming,\n\t\t\tcurrent: files,\n\t\t\taccept,\n\t\t\tminSizeBytes,\n\t\t\tmaxSizeBytes,\n\t\t\tmaxFiles,\n\t\t\tappend,\n\t\t\tvalidateFile,\n\t\t\tformatSize,\n\t\t\tstrings,\n\t\t});\n\n\t\tsetRejections(result.rejections);\n\t\tif (result.rejections.length > 0) onRejectedFiles?.(result.rejections);\n\t\tif (result.accepted.length === 0) return false;\n\t\tcontinueFocus.current = !multiple && (pickerWasFocused.current || Boolean(rootRef.current?.contains(document.activeElement)));\n\t\tpickerWasFocused.current = false;\n\t\tcommitFiles(result.nextFiles);\n\t\treturn result.rejections.length === 0;\n\t}, [\n\t\taccept,\n\t\tappend,\n\t\tcommitFiles,\n\t\tdisabled,\n\t\tmultiple,\n\t\tfiles,\n\t\tformatSize,\n\t\tmaxFiles,\n\t\tmaxSizeBytes,\n\t\tminSizeBytes,\n\t\tonRejectedFiles,\n\t\tstrings,\n\t\tvalidateFile,\n\t]);\n\n\tconst clearNativeInput = useCallback(() => {\n\t\tif (inputRef.current) inputRef.current.value = '';\n\t}, []);\n\n\tconst handleRemove = useCallback((index: number) => {\n\t\tif (disabled) return;\n\t\tsetRejections([]);\n\t\tclearNativeInput();\n\t\tcontinueFocus.current = Boolean(rootRef.current?.contains(document.activeElement));\n\t\tcommitFiles(files.filter((_, fileIndex) => fileIndex !== index));\n\t}, [clearNativeInput, commitFiles, disabled, files]);\n\n\tconst openPicker = useCallback(() => {\n\t\tif (!disabled) {\n\t\t\tpickerWasFocused.current = Boolean(rootRef.current?.contains(document.activeElement));\n\t\t\tinputRef.current?.click();\n\t\t}\n\t}, [disabled]);\n\n\tconst { isDragging, dropTargetProps } = useFileDropTarget({\n\t\tdisabled,\n\t\tonFiles: handleFiles,\n\t});\n\n\tconst inputProps: FilePickerNativeInputProps = {\n\t\t...(nativeInputProps as FilePickerNativeInputProps),\n\t\taccept,\n\t\tmultiple,\n\t\tdisabled,\n\t\t'aria-describedby': describedBy,\n\t\t'aria-invalid': hasInvalidState ? true : nativeAriaInvalid,\n\t};\n\n\tconst picker = (\n\t\t<Dropzone\n\t\t\tref={(node) => assignInputRef(node, inputRef, forwardedRef)}\n\t\t\tonDrop={handleFiles}\n\t\t\taccept={accept}\n\t\t\tmultiple={multiple}\n\t\t\tdisabled={disabled}\n\t\t\tinvalid={hasInvalidState}\n\t\t\tsize={size}\n\t\t\tclassName=\"file-upload--dropzone\"\n\t\t\tinputProps={inputProps}\n\t\t\tstrings={{\n\t\t\t\tinstruction: strings.instruction,\n\t\t\t\thelper: strings.helper,\n\t\t\t\tdragOver: strings.dragOver,\n\t\t\t}}\n\t\t>\n\t\t\t<Button\n\t\t\t\ttype=\"button\"\n\t\t\t\ttone=\"secondary\"\n\t\t\t\tbuttonStyle=\"outline\"\n\t\t\t\tsize={size}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tonClick={openPicker}\n\t\t\t>\n\t\t\t\t{strings.browse}\n\t\t\t</Button>\n\t\t</Dropzone>\n\t);\n\n\treturn (\n\t\t<div\n\t\t\tref={rootRef}\n\t\t\tdata-disabled={disabled || undefined}\n\t\t\tdata-invalid={hasInvalidState || undefined}\n\t\t\tclassName={cn('file-upload--component grid gap-space-md', className)}\n\t\t>\n\t\t\t{(multiple || files.length === 0) && picker}\n\n\t\t\t{!multiple && files[0] && (\n\t\t\t\t<div\n\t\t\t\t\t{...dropTargetProps}\n\t\t\t\t\tdata-dragging={isDragging || undefined}\n\t\t\t\t\tdata-invalid={hasInvalidState || undefined}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'file-upload--selected rounded-radius transition-shadow',\n\t\t\t\t\t\thasInvalidState && '[&_.file-upload--file]:border-destructive',\n\t\t\t\t\t\t!disabled && isDragging && (\n\t\t\t\t\t\t\thasInvalidState\n\t\t\t\t\t\t\t\t? 'ring-2 ring-destructive/50 ring-offset-2'\n\t\t\t\t\t\t\t\t: 'ring-2 ring-primary/50 ring-offset-2'\n\t\t\t\t\t\t),\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<FilePickerInput\n\t\t\t\t\t\t{...inputProps}\n\t\t\t\t\t\tref={(node) => assignInputRef(node, inputRef, forwardedRef)}\n\t\t\t\t\t\ttabIndex={-1}\n\t\t\t\t\t\tclassName=\"file-upload--input\"\n\t\t\t\t\t\tonFiles={handleFiles}\n\t\t\t\t\t/>\n\t\t\t\t\t<SelectedFileRow\n\t\t\t\t\t\tfile={files[0]}\n\t\t\t\t\t\tindex={0}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tsize={size}\n\t\t\t\t\t\tlocale={locale}\n\t\t\t\t\t\tstrings={strings}\n\t\t\t\t\t\tshowReplace\n\t\t\t\t\t\tonReplace={openPicker}\n\t\t\t\t\t\tonRemove={handleRemove}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{multiple && files.length > 0 && (\n\t\t\t\t<ItemGroup className=\"file-upload--files\">\n\t\t\t\t\t{files.map((file, index) => (\n\t\t\t\t\t\t<SelectedFileRow\n\t\t\t\t\t\t\tkey={fileKey(file, index)}\n\t\t\t\t\t\t\tfile={file}\n\t\t\t\t\t\t\tindex={index}\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\tsize={size}\n\t\t\t\t\t\t\tlocale={locale}\n\t\t\t\t\t\t\tstrings={strings}\n\t\t\t\t\t\t\tshowReplace={false}\n\t\t\t\t\t\t\tonReplace={openPicker}\n\t\t\t\t\t\t\tonRemove={handleRemove}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t</ItemGroup>\n\t\t\t)}\n\n\t\t\t{rejections.length > 0 && (\n\t\t\t\t<Alert\n\t\t\t\t\tid={errorId}\n\t\t\t\t\ttone=\"destructive\"\n\t\t\t\t\taria-live=\"polite\"\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'file-upload--errors',\n\t\t\t\t\t\tsize === 'sm' && 'p-surface-xs',\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<TriangleAlert aria-hidden=\"true\" />\n\t\t\t\t\t<AlertTitle>{strings.errorsHeading}</AlertTitle>\n\t\t\t\t\t<AlertDescription>\n\t\t\t\t\t\t<ul className=\"m-0 p-0 list-none grid gap-space-2xs\">\n\t\t\t\t\t\t\t{rejections.map((rejection, index) => (\n\t\t\t\t\t\t\t\t<li\n\t\t\t\t\t\t\t\t\tkey={`${rejection.code}-${fileKey(rejection.file, index)}`}\n\t\t\t\t\t\t\t\t\tclassName=\"file-upload--error\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Text tag=\"span\" size=\"xs\" type=\"error\">\n\t\t\t\t\t\t\t\t\t\t{rejection.message}\n\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t</AlertDescription>\n\t\t\t\t</Alert>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\n/** Selects and validates local File values without performing network uploads. */\nexport const FileUpload = forwardRef<HTMLInputElement, FileUploadProps>(FileUploadImpl);\nFileUpload.displayName = 'FileUpload';\n\nexport { defaultFileUploadStrings };\nexport type { FileUploadStrings };\nexport type {\n\tFileUploadRejection,\n\tFileUploadRejectionCode,\n\tFileUploadCommonProps,\n\tFileUploadSelectionMode,\n\tFileUploadValidator,\n\tMultipleFileUploadProps,\n\tSingleFileUploadProps,\n} from './file-upload.types';\n","import { useCallback, useRef, useState } from 'react';\n\nexport type FileRejectionCode =\n\t| 'invalid-type'\n\t| 'too-small'\n\t| 'too-large'\n\t| 'too-many'\n\t| 'duplicate'\n\t| 'custom';\n\nexport interface FileRejectionDetails {\n\textension?: string;\n\tminimumBytes?: number;\n\tmaximumBytes?: number;\n\tmaximumFiles?: number;\n\t/** Consumer-provided custom copy. The hook never manufactures a message. */\n\tcustomMessage?: string;\n}\n\nexport interface FileRejection {\n\tfile: File;\n\tcode: FileRejectionCode;\n\tdetails: FileRejectionDetails;\n}\n\nexport interface FileValidationRules {\n\tmaxSize?: number;\n\tminSize?: number;\n\tallowedExtensions?: string[];\n\tmaxFiles?: number;\n\tcustomValidator?: (file: File) => boolean | string;\n}\n\nexport interface FileMeta {\n\tid: string;\n\tfile: File;\n\tname: string;\n\tsize: number;\n\tformattedSize: string;\n\ttype: string;\n\textension: string;\n\tlastModified: number;\n}\n\nexport interface FileProcessingResult {\n\taccepted: FileMeta[];\n\tfiles: FileMeta[];\n\trejections: FileRejection[];\n}\n\nexport interface UseFilesReturn {\n\tfiles: FileMeta[];\n\taddFiles: (incoming: FileList | File[]) => FileProcessingResult;\n\tsetFiles: (incoming: FileList | File[]) => FileProcessingResult;\n\tremove: (id: string) => void;\n\tremoveAll: () => void;\n\tformatSize: (bytes: number) => string;\n\t/** Compatibility lookup keyed by file name. Values are typed details, never copy. */\n\tvalidationErrors: Record<string, FileRejection>;\n\trejections: FileRejection[];\n}\n\nconst FILE_SIZE_UNITS = ['B', 'KB', 'MB', 'GB', 'TB'] as const;\n\nfunction defaultFormatSize(bytes: number): string {\n\tif (!Number.isFinite(bytes) || bytes <= 0) return '0 B';\n\tconst unitIndex = Math.min(\n\t\tMath.floor(Math.log(bytes) / Math.log(1024)),\n\t\tFILE_SIZE_UNITS.length - 1,\n\t);\n\tconst value = bytes / 1024 ** unitIndex;\n\tconst formattedValue = unitIndex === 0\n\t\t? value.toFixed(0)\n\t\t: Number(value.toFixed(1)).toString();\n\treturn `${formattedValue} ${FILE_SIZE_UNITS[unitIndex]}`;\n}\n\nlet idCounter = 0;\nfunction generateId(): string {\n\tconst timestamp = Date.now().toString(36);\n\tconst count = (idCounter++).toString(36);\n\treturn `${timestamp}-${count}`;\n}\n\nfunction getExtension(file: File) {\n\treturn file.name.split('.').pop()?.toLowerCase() ?? '';\n}\n\nfunction getFingerprint(file: File) {\n\treturn `${file.name}\\u0000${file.size}\\u0000${file.type}\\u0000${file.lastModified}`;\n}\n\nfunction createMeta(file: File): FileMeta {\n\treturn {\n\t\tid: generateId(),\n\t\tfile,\n\t\tname: file.name,\n\t\tsize: file.size,\n\t\tformattedSize: defaultFormatSize(file.size),\n\t\ttype: file.type,\n\t\textension: getExtension(file),\n\t\tlastModified: file.lastModified,\n\t};\n}\n\nfunction validateFile(\n\tfile: File,\n\trules?: FileValidationRules,\n): FileRejection | undefined {\n\tconst extension = getExtension(file);\n\tif (rules?.minSize !== undefined && file.size < rules.minSize) {\n\t\treturn {\n\t\t\tfile,\n\t\t\tcode: 'too-small',\n\t\t\tdetails: { minimumBytes: rules.minSize },\n\t\t};\n\t}\n\tif (rules?.maxSize !== undefined && file.size > rules.maxSize) {\n\t\treturn {\n\t\t\tfile,\n\t\t\tcode: 'too-large',\n\t\t\tdetails: { maximumBytes: rules.maxSize },\n\t\t};\n\t}\n\tif (\n\t\trules?.allowedExtensions &&\n\t\t!rules.allowedExtensions.some((allowed) => allowed.toLowerCase().replace(/^\\./, '') === extension)\n\t) {\n\t\treturn {\n\t\t\tfile,\n\t\t\tcode: 'invalid-type',\n\t\t\tdetails: { extension },\n\t\t};\n\t}\n\tif (rules?.customValidator) {\n\t\tlet result: boolean | string;\n\t\ttry {\n\t\t\tresult = rules.customValidator(file);\n\t\t} catch {\n\t\t\tresult = false;\n\t\t}\n\t\tif (result !== true) {\n\t\t\treturn {\n\t\t\t\tfile,\n\t\t\t\tcode: 'custom',\n\t\t\t\tdetails: {\n\t\t\t\t\tcustomMessage: typeof result === 'string' && result.length > 0\n\t\t\t\t\t\t? result\n\t\t\t\t\t\t: undefined,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction toErrorMap(rejections: FileRejection[]) {\n\treturn Object.fromEntries(rejections.map((rejection) => [rejection.file.name, rejection]));\n}\n\nexport function useFiles(rules?: FileValidationRules): UseFilesReturn {\n\tconst [files, setFilesState] = useState<FileMeta[]>([]);\n\tconst filesRef = useRef<FileMeta[]>([]);\n\tconst [rejections, setRejections] = useState<FileRejection[]>([]);\n\n\tconst formatSize = useCallback(defaultFormatSize, []);\n\n\tconst processFiles = useCallback((incoming: FileList | File[], replace: boolean) => {\n\t\tconst incomingFiles = Array.isArray(incoming) ? incoming : Array.from(incoming);\n\t\tconst previousFiles = filesRef.current;\n\t\tlet nextFiles = replace ? [] : [...previousFiles];\n\t\tconst fingerprints = new Set(nextFiles.map((meta) => getFingerprint(meta.file)));\n\t\tconst accepted: FileMeta[] = [];\n\t\tconst nextRejections: FileRejection[] = [];\n\n\t\tfor (const file of incomingFiles) {\n\t\t\tconst fingerprint = getFingerprint(file);\n\t\t\tif (fingerprints.has(fingerprint)) {\n\t\t\t\tnextRejections.push({ file, code: 'duplicate', details: {} });\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst rejection = validateFile(file, rules);\n\t\t\tif (rejection) {\n\t\t\t\tnextRejections.push(rejection);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (rules?.maxFiles !== undefined && nextFiles.length >= rules.maxFiles) {\n\t\t\t\tnextRejections.push({\n\t\t\t\t\tfile,\n\t\t\t\t\tcode: 'too-many',\n\t\t\t\t\tdetails: { maximumFiles: rules.maxFiles },\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst meta = createMeta(file);\n\t\t\taccepted.push(meta);\n\t\t\tnextFiles.push(meta);\n\t\t\tfingerprints.add(fingerprint);\n\t\t}\n\t\tif (replace && accepted.length === 0 && nextRejections.length > 0) {\n\t\t\tnextFiles = previousFiles;\n\t\t}\n\n\t\tfilesRef.current = nextFiles;\n\t\tsetFilesState(nextFiles);\n\t\tsetRejections(nextRejections);\n\t\treturn { accepted, files: nextFiles, rejections: nextRejections };\n\t}, [rules]);\n\n\tconst addFiles = useCallback(\n\t\t(incoming: FileList | File[]) => processFiles(incoming, false),\n\t\t[processFiles],\n\t);\n\tconst setFiles = useCallback(\n\t\t(incoming: FileList | File[]) => processFiles(incoming, true),\n\t\t[processFiles],\n\t);\n\tconst remove = useCallback((id: string) => {\n\t\tconst nextFiles = filesRef.current.filter((file) => file.id !== id);\n\t\tfilesRef.current = nextFiles;\n\t\tsetFilesState(nextFiles);\n\t}, []);\n\tconst removeAll = useCallback(() => {\n\t\tfilesRef.current = [];\n\t\tsetFilesState([]);\n\t\tsetRejections([]);\n\t}, []);\n\n\treturn {\n\t\tfiles,\n\t\taddFiles,\n\t\tsetFiles,\n\t\tremove,\n\t\tremoveAll,\n\t\tformatSize,\n\t\tvalidationErrors: toErrorMap(rejections),\n\t\trejections,\n\t};\n}\n","/**\n * ImageUpload — preview-first image picker. Drops in a file → renders an img\n * preview with a configurable aspect ratio and fit mode. Layout can be\n * stacked (preview on top, controls below) or inline (preview alongside\n * controls). Reflects controlled `value` and reports change via `onValueChange`.\n * Strings overridable for i18n.\n */\nimport { ImageIcon } from 'lucide-react';\nimport React, { useEffect, useId, useMemo, useRef, useState, useCallback } from 'react';\nimport { Button } from '../buttons';\nimport { Text } from '../../typography';\nimport { useFiles, type FileRejection } from '../../../hooks/use-files';\nimport { useStrings, type StringsProp } from '../../../lib/strings';\nimport { cn } from '../../../lib/utils';\nimport { useFileDropTarget } from './use-file-drop-target';\nimport { uploadDropTargetRecipes } from './upload.recipes';\n\nconst MAX_FILE_SIZE_MB = 2;\n\ntype ImageUploadAspectRatio = 'square' | 'standard' | 'widescreen' | 'portrait';\ntype ImageUploadLayout = 'stacked' | 'inline';\ntype ImageUploadFit = 'cover' | 'contain';\n\nconst ASPECT_RATIO_CLASSES: Record<ImageUploadAspectRatio, string> = {\n\t\tsquare: 'aspect-square',\n\t\tstandard: 'aspect-[4/3]',\n\t\twidescreen: 'aspect-[16/9]',\n\t\tportrait: 'aspect-[9/16]',\n};\n\nexport interface ImageUploadStrings {\n\t\tselect: string;\n\t\tchange: string;\n\t\tremove: string;\n\t\tnoSelection: string;\n\t\tkeepCurrent: string;\n\t/** Accessible description for an existing preview without a selected file name. */\n\tpreviewAlt?: string;\n\t\t/** Template for the supports-text. `{ext}` is the comma-separated allowed\n\t\t * extensions; `{size}` is the max-size MB number. */\n\t\tsupportsTemplate: string;\n\tinvalidType: (fileName: string, extension: string) => string;\n\ttooSmall: (fileName: string, minimum: string) => string;\n\ttooLarge: (fileName: string, maximum: string) => string;\n\ttooMany: (fileName: string, maximum: number) => string;\n\tduplicate: (fileName: string) => string;\n\tcustomValidationFailed: (fileName: string) => string;\n\t\t/** Summary line when `multiple` is set and more than one file is selected.\n\t\t * Receives the count of files beyond the displayed one — e.g. `count=3`\n\t\t * for \"+ 3 more files\". Override to swap the English plural-`s` rule\n\t\t * (`'+ ' + count + ' more file' + (count === 1 ? '' : 's')`) for the\n\t\t * consumer locale. */\n\t\tmoreFiles: (count: number) => string;\n}\n\nexport const defaultImageUploadStrings: ImageUploadStrings = {\n\t\tselect: 'Select image',\n\t\tchange: 'Change image',\n\t\tremove: 'Remove',\n\t\tnoSelection: 'No file selected yet.',\n\t\tkeepCurrent: 'Current image stays until you upload a new one.',\n\tpreviewAlt: 'Selected image',\n\t\tsupportsTemplate: 'Supports {ext} files up to {size} MB.',\n\tinvalidType: (fileName, extension) => `${fileName} uses an unsupported .${extension || 'unknown'} file type.`,\n\ttooSmall: (fileName, minimum) => `${fileName} is smaller than ${minimum}.`,\n\ttooLarge: (fileName, maximum) => `${fileName} is larger than ${maximum}.`,\n\ttooMany: (fileName, maximum) => `${fileName} exceeds the limit of ${maximum} images.`,\n\tduplicate: (fileName) => `${fileName} is already selected.`,\n\tcustomValidationFailed: (fileName) => `${fileName} did not pass validation.`,\n\t\tmoreFiles: (count) => `+ ${count} more file${count === 1 ? '' : 's'}`,\n};\n\nfunction getImageUploadRejectionMessage(\n\trejection: FileRejection,\n\tstrings: ImageUploadStrings,\n\tformatSize: (bytes: number) => string,\n) {\n\tconst { file, code, details } = rejection;\n\tswitch (code) {\n\t\tcase 'invalid-type':\n\t\t\treturn strings.invalidType(file.name, details.extension ?? '');\n\t\tcase 'too-small':\n\t\t\treturn strings.tooSmall(file.name, formatSize(details.minimumBytes ?? 0));\n\t\tcase 'too-large':\n\t\t\treturn strings.tooLarge(file.name, formatSize(details.maximumBytes ?? 0));\n\t\tcase 'too-many':\n\t\t\treturn strings.tooMany(file.name, details.maximumFiles ?? 1);\n\t\tcase 'duplicate':\n\t\t\treturn strings.duplicate(file.name);\n\t\tcase 'custom':\n\t\t\treturn details.customMessage ?? strings.customValidationFailed(file.name);\n\t}\n}\n\nexport interface ImageUploadProps {\n\t\t/** Accepted MIME types or extensions, as the native `accept` attribute. */\n\t\taccept?: string;\n\t\t/** Allows more than one file to be chosen. */\n\t\tmultiple?: boolean;\n\t\t/** Selected files. Controlled. */\n\t\tvalue?: File;\n\t\tonValueChange?: (file?: File) => void;\n\t\t/** Disables the control and blocks drops. */\n\t\tdisabled?: boolean;\n\t\t/** Image shown before anything is chosen — an existing upload. */\n\t\tinitialPreviewUrl?: string;\n\t\t/** Aspect ratio the preview is cropped to. */\n\t\taspectRatio?: ImageUploadAspectRatio;\n\t\t/** How the preview fills its frame — cover or contain. */\n\t\tfit?: ImageUploadFit;\n\t\t/** Caps the preview's width. */\n\t\tmaxWidth?: number | string;\n\t\t/** Arrangement of the preview and drop target. */\n\t\tlayout?: ImageUploadLayout;\n\t\t/** Applies the invalid styling. */\n\t\tinvalid?: boolean;\n\t\t/** Override default strings (button labels, helper text, supports template). */\n\t\tstrings?: StringsProp<ImageUploadStrings>;\n}\n\nfunction ImageUploadImpl(\n\t\t{\n\t\taccept = '.png,.jpg,.jpeg,.gif,.svg',\n\t\tmultiple = false,\n\t\tvalue,\n\t\tonValueChange,\n\t\tdisabled,\n\t\tinitialPreviewUrl,\n\t\taspectRatio = 'square',\n\t\tfit = 'cover',\n\t\tmaxWidth,\n\t\tlayout = 'stacked',\n\t\tinvalid,\n\t\tstrings: stringsProp,\n}: ImageUploadProps,\n\t\tforwardedRef: React.ForwardedRef<HTMLInputElement>,\n) {\n\t\tconst strings = useStrings(defaultImageUploadStrings, stringsProp);\n\t\tconst inputId = useId();\n\t\tconst inputRef = useRef<HTMLInputElement | null>(null);\n\n\t\tconst allowedExtensions = useMemo(() => {\n\t\t\t\tif (!accept) {\n\t\t\t\t\t\treturn ['png', 'jpg', 'jpeg', 'gif', 'svg'];\n\t\t\t\t}\n\n\t\t\t\tconst parsed = accept\n\t\t\t\t\t\t.split(',')\n\t\t\t\t\t\t.map((item) => item.trim())\n\t\t\t\t\t\t.map((item) => {\n\t\t\t\t\t\t\t\tif (!item) return null;\n\t\t\t\t\t\t\t\tif (item.startsWith('.')) {\n\t\t\t\t\t\t\t\t\t\treturn item.slice(1).toLowerCase();\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (item.includes('/')) {\n\t\t\t\t\t\t\t\t\t\tconst subtype = item.split('/')[1] ?? '';\n\t\t\t\t\t\t\t\t\t\tif (subtype === '*' || subtype.length === 0) {\n\t\t\t\t\t\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\treturn subtype.replace(/\\+.*/, '').toLowerCase();\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\treturn item.toLowerCase();\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.filter((ext): ext is string => Boolean(ext));\n\n\t\t\t\tif (parsed.length === 0) {\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\treturn Array.from(new Set(parsed));\n\t\t}, [accept]);\n\n\t\tconst fileRules = useMemo(\n\t\t\t\t() => ({\n\t\t\t\t\t\tmaxFiles: multiple ? undefined : 1,\n\t\t\tmaxSize: MAX_FILE_SIZE_MB * 1024 * 1024,\n\t\t\t\t\t\tallowedExtensions,\n\t\t\t\t}),\n\t\t\t\t[multiple, allowedExtensions]\n\t\t);\n\n\t\tconst { files, setFiles, remove, removeAll, formatSize, rejections } = useFiles(fileRules);\n\n\t\t// Reflect controlled value into local preview if provided\n\t\tuseEffect(() => {\n\t\t\t\tif (value) {\n\t\t\t\t\t\tsetFiles([value]);\n\t\t\t\t} else {\n\t\t\t\t\t\tremoveAll();\n\t\t\t\t\t\tif (inputRef.current) {\n\t\t\t\t\t\t\t\tinputRef.current.value = '';\n\t\t\t\t\t\t}\n\t\t\t\t}\n\t\t}, [value, setFiles, removeAll]);\n\n\t\tconst selected = files[0];\n\tconst selectOrChangeButtonLabel = selected ? strings.change : strings.select;\n\t\tconst [filePreviewUrl, setFilePreviewUrl] = useState<string | undefined>(undefined);\n\n\t\tconst acceptedExtensionsLabel = useMemo(() => {\n\t\t\t\tif (!allowedExtensions || allowedExtensions.length === 0) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\treturn allowedExtensions.map((ext) => ext.toUpperCase()).join(', ');\n\t\t}, [allowedExtensions]);\n\n\t\tuseEffect(() => {\n\t\t\t\tconst file = selected?.file ?? value;\n\t\t\t\tif (!file) {\n\t\t\t\t\t\tsetFilePreviewUrl(undefined);\n\t\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst url = URL.createObjectURL(file);\n\t\t\t\tsetFilePreviewUrl(url);\n\t\t\t\treturn () => URL.revokeObjectURL(url);\n\t\t}, [selected, value]);\n\n\t\tconst previewUrl = filePreviewUrl ?? initialPreviewUrl;\n\t\tconst hasPreview = Boolean(previewUrl);\n\tconst previewAlt = selected?.name ?? strings.previewAlt ?? defaultImageUploadStrings.previewAlt;\n\t\tconst aspectClass = ASPECT_RATIO_CLASSES[aspectRatio] ?? ASPECT_RATIO_CLASSES.square;\n\t\tconst imgFitClass = fit === 'contain' ? 'object-contain p-space-sm' : 'object-cover';\n\t\t// Default max-width caps the preview at a sensible thumbnail size — without\n\t\t// this, an `aspect-square` preview inside a wide form column becomes a\n\t\t// huge square (`w-full` × 1:1 ratio = container width tall). Consumers\n\t\t// can override via the `maxWidth` prop.\n\t\tconst computedMaxWidth = maxWidth ? (typeof maxWidth === 'number' ? `${maxWidth}px` : maxWidth) : '240px';\n\t\tconst wrapperStyle = layout === 'inline' ? undefined : { maxWidth: computedMaxWidth };\n\t\tconst inlinePreviewStyle =\n\t\t\t\tlayout === 'inline'\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\tmaxWidth: maxWidth ? computedMaxWidth : '185px',\n\t\t\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: undefined;\n\n\t\tconst handleFiles = useCallback((incoming: File[]) => {\n\t\t\tif (disabled || incoming.length === 0) return;\n\t\t\tconst result = setFiles(incoming);\n\t\t\tconst acceptedFile = result.accepted[0]?.file;\n\t\t\tif (acceptedFile) onValueChange?.(acceptedFile);\n\t\t}, [disabled, setFiles, onValueChange]);\n\t\tconst handleInput = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {\n\t\t\thandleFiles(Array.from(event.target.files ?? []));\n\t\t}, [handleFiles]);\n\t\tconst { isDragging, dropTargetProps } = useFileDropTarget({ disabled, onFiles: handleFiles });\n\n\t\tconst triggerFileDialog = useCallback(() => {\n\t\t\t\tif (disabled) return;\n\t\t\t\tinputRef.current?.click();\n\t\t}, [disabled]);\n\n\t\tconst handleRemove = useCallback(() => {\n\t\t\t\tif (selected) {\n\t\t\t\t\t\tremove(selected.id);\n\t\t\t\t}\n\t\t\t\tonValueChange?.(undefined);\n\t\t\t\tif (inputRef.current) {\n\t\t\t\t\t\tinputRef.current.value = '';\n\t\t\t\t}\n\t\t}, [selected, remove, onValueChange]);\n\n\t\treturn (\n\t\t\t\t<div className={cn('image-upload--component', 'grid gap-space-md')} style={wrapperStyle}>\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\tref={(node) => { inputRef.current = node; if (typeof forwardedRef === \"function\") forwardedRef(node); else if (forwardedRef) forwardedRef.current = node; }}\n\t\t\t\t\t\t\t\tid={inputId}\n\t\t\t\t\t\t\t\ttype=\"file\"\n\t\t\t\t\t\t\t\tclassName=\"sr-only\"\n\t\t\t\t\t\t\t\t// The visible button is the keyboard affordance; an invisible\n\t\t\t\t\t\t\t\t// second Tab stop would have no focus indicator.\n\t\t\t\t\t\t\t\ttabIndex={-1}\n\t\t\t\t\t\t\t\taria-label={selectOrChangeButtonLabel}\n\t\t\t\t\t\t\t\taccept={accept}\n\t\t\t\t\t\t\t\tmultiple={multiple}\n\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\tonChange={handleInput}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<div className={cn(layout === 'inline' ? 'flex flex-wrap items-start gap-space-xl' : 'grid gap-space-md')}>\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t{...dropTargetProps}\n\t\t\t\t\t\t\t\t\t\tdata-dragging={isDragging || undefined}\n\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t'relative overflow-hidden rounded-radius border transition-colors',\n\t\t\t\t\t\t\t\t\t\t\t\tlayout === 'inline' ? 'flex-shrink-0 w-full' : 'w-full',\n\t\t\t\t\t\t\t\t\t\t\t\taspectClass,\n\t\t\t\t\t\t\t\t\t\t\t\thasPreview\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? 'border-border bg-muted'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Same dashed control boundary as Dropzone and AvatarUpload.\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t'border-dashed bg-background text-muted-foreground',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tuploadDropTargetRecipes.idle,\n\t\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\tinvalid && uploadDropTargetRecipes.invalid,\n\t\t\t\t\t\t\t\t\t\t\t\t!disabled && isDragging && uploadDropTargetRecipes.dragging\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\tstyle={inlinePreviewStyle}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{hasPreview && previewUrl ? (\n\t\t\t\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsrc={previewUrl}\n\t\t\t\t\t\t\t\t\t\t\t\talt={previewAlt}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={cn('absolute inset-0 box-border h-full w-full', imgFitClass)}\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\t\t<div className=\"absolute inset-0 flex items-center justify-center\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<ImageIcon aria-hidden className=\"size-icon-lg\" />\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div className={cn('grid gap-space-sm', layout === 'inline' && 'flex-1 min-w-0 basis-40')}>\n\t\t\t\t\t\t\t\t\t\t<div className=\"flex flex-wrap items-center gap-space-md\">\n\t <Button\n\t type=\"button\"\n\t tone=\"secondary\"\n\t buttonStyle=\"outline\"\n\t onClick={triggerFileDialog}\n\t disabled={disabled}\n\t >\n\t {selectOrChangeButtonLabel}\n\t </Button>\n\t\t\t\t\t\t\t\t\t\t\t\t{!selected && !!hasPreview && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<Text size=\"xs\" type=\"secondary\">{strings.keepCurrent}</Text>\n\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t\t\t{!!acceptedExtensionsLabel && (\n\t\t\t\t\t\t\t\t\t\t\t\t<Text size=\"xs\" type=\"secondary\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{strings.supportsTemplate\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.replace('{ext}', acceptedExtensionsLabel)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.replace('{size}', String(MAX_FILE_SIZE_MB))}\n\t\t\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t\t{!!selected && (\n\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"grid gap-space-2xs\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<Text weight=\"medium\" title={selected.name} className=\"truncate\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{selected.name}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<Text size=\"xs\" type=\"secondary\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{selected.formattedSize}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{!!multiple && files.length > 1 && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<Text size=\"xs\" type=\"secondary\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{strings.moreFiles(files.length - 1)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</Text>\n\t\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<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=\"destructive\"\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\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={handleRemove}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"justify-self-start\"\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.remove}\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</div>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t\t{!selected && !hasPreview && (\n\t\t\t\t\t\t\t\t\t\t\t\t<Text size=\"xs\" type=\"secondary\">{strings.noSelection}</Text>\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</div>\n\n\t\t\t\t\t\t{/* Validation errors */}\n\t\t\t\t\t\t{rejections.length > 0 && (\n\t\t\t\t\t\t\t\t<div className=\"image-upload--errors grid gap-space-2xs\" role=\"alert\" aria-live=\"polite\">\n\t\t\t\t\t\t\t\t\t\t{rejections.map((rejection, index) => (\n\t\t\t\t\t\t\t\t\t\t\t\t<Text key={`${rejection.file.name}-${rejection.code}-${index}`} size=\"xs\" type=\"error\">\n\t\t\t\t\t\t\t{getImageUploadRejectionMessage(rejection, strings, formatSize)}\n\t\t\t\t\t\t\t\t\t\t\t\t</Text>\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\t\t\t\t</div>\n\t\t);\n}\n\nconst ImageUpload = React.forwardRef<HTMLInputElement, ImageUploadProps>(ImageUploadImpl);\nImageUpload.displayName = 'ImageUpload';\n\nexport { ImageUpload };\n","import * as React from 'react';\n/**\n * AvatarUpload — round avatar picker. Click or drag a file onto the circle to\n * upload; an X button (visible on hover) clears the selection. Honours\n * controlled `value` (a `File`), and reflects an existing `initialPreviewUrl`\n * when no file is staged. Use for profile photos / org logos where the\n * preview is small and the only meaningful interaction is replace + clear.\n *\n * Pair with a separate \"remove from server\" handler if your data model\n * needs to delete a previously persisted image (this component only manages\n * the local staged file).\n *\n * Strings overridable for i18n.\n */\nimport { useCallback, useEffect, useId, useMemo, useRef, useState} from 'react';\nimport type { ChangeEvent, ForwardedRef} from 'react';\nimport { Camera, X } from 'lucide-react';\nimport { Text } from '../../typography';\nimport { useFiles, type FileRejection } from '../../../hooks/use-files';\nimport { useStrings, type StringsProp } from '../../../lib/strings';\nimport { useDensityConfig, type ComponentScale } from '../../../lib/ui-provider';\nimport { resolveComponentScale } from '../../../lib/ui-provider/scale';\nimport { cn } from '../../../lib/utils';\nimport { fieldAffordanceRecipes } from '../../../lib/field-affordance-recipes';\nimport { useFileDropTarget } from './use-file-drop-target';\nimport { uploadDropTargetRecipes } from './upload.recipes';\n\nexport type AvatarUploadSize = ComponentScale;\n\nexport interface AvatarUploadStrings {\n\tchange: string;\n\tremove: string;\n\thint: string;\n\tdragOver: string;\n\tinvalidType: (fileName: string, extension: string) => string;\n\ttooSmall: (fileName: string, minimum: string) => string;\n\ttooLarge: (fileName: string, maximum: string) => string;\n\ttooMany: (fileName: string, maximum: number) => string;\n\tduplicate: (fileName: string) => string;\n\tcustomValidationFailed: (fileName: string) => string;\n}\n\nexport const defaultAvatarUploadStrings: AvatarUploadStrings = {\n\tchange: 'Change photo',\n\tremove: 'Remove photo',\n\thint: 'Click or drop an image',\n\tdragOver: 'Drop image to upload',\n\tinvalidType: (fileName, extension) => `${fileName} uses an unsupported .${extension || 'unknown'} file type.`,\n\ttooSmall: (fileName, minimum) => `${fileName} is smaller than ${minimum}.`,\n\ttooLarge: (fileName, maximum) => `${fileName} is larger than ${maximum}.`,\n\ttooMany: (fileName, maximum) => `${fileName} exceeds the limit of ${maximum} images.`,\n\tduplicate: (fileName) => `${fileName} is already selected.`,\n\tcustomValidationFailed: (fileName) => `${fileName} did not pass validation.`,\n};\n\nfunction getAvatarUploadRejectionMessage(\n\trejection: FileRejection,\n\tstrings: AvatarUploadStrings,\n\tformatSize: (bytes: number) => string,\n) {\n\tconst { file, code, details } = rejection;\n\tswitch (code) {\n\t\tcase 'invalid-type':\n\t\t\treturn strings.invalidType(file.name, details.extension ?? '');\n\t\tcase 'too-small':\n\t\t\treturn strings.tooSmall(file.name, formatSize(details.minimumBytes ?? 0));\n\t\tcase 'too-large':\n\t\t\treturn strings.tooLarge(file.name, formatSize(details.maximumBytes ?? 0));\n\t\tcase 'too-many':\n\t\t\treturn strings.tooMany(file.name, details.maximumFiles ?? 1);\n\t\tcase 'duplicate':\n\t\t\treturn strings.duplicate(file.name);\n\t\tcase 'custom':\n\t\t\treturn details.customMessage ?? strings.customValidationFailed(file.name);\n\t}\n}\n\nexport interface AvatarUploadProps {\n\t/** Selected file. Controlled. */\n\tvalue?: File;\n\tonValueChange?: (file?: File) => void;\n\t/** Image shown before anything is chosen — an existing avatar. */\n\tinitialPreviewUrl?: string;\n\t/** Accepted MIME types or extensions. */\n\taccept?: string;\n\t/** Disables the control and blocks drops. */\n\tdisabled?: boolean;\n\t/** Applies the invalid styling. */\n\tinvalid?: boolean;\n\t/** Diameter preset for the avatar. */\n\tsize?: AvatarUploadSize;\n\tclassName?: string;\n\t/** Overrides the upload and remove copy. */\n\tstrings?: StringsProp<AvatarUploadStrings>;\n\t/** Initials shown when no preview is available. */\n\tinitials?: string;\n}\n\nconst SIZE_PX: Record<AvatarUploadSize, { box: string; icon: string; remove: string }> = {\n\tsm: { box: 'size-upload-avatar-small', icon: 'size-icon', remove: 'size-control-clear' },\n\tmd: { box: 'size-upload-avatar', icon: 'size-icon-lg', remove: 'size-action' },\n\tlg: { box: 'size-upload-avatar-large', icon: 'size-icon-lg', remove: 'size-action-lg' },\n};\n\nfunction AvatarUploadImpl(\n\t{\n\tvalue,\n\tonValueChange,\n\tinitialPreviewUrl,\n\taccept = '.png,.jpg,.jpeg,.gif,.webp',\n\tdisabled = false,\n\tinvalid = false,\n\tsize: sizeProp,\n\tclassName,\n\tstrings: stringsProp,\n\tinitials,\n}: AvatarUploadProps,\n\tforwardedRef: ForwardedRef<HTMLInputElement>,\n) {\n\tconst { defaultScale } = useDensityConfig();\n\tconst size = resolveComponentScale(sizeProp, defaultScale);\n\tconst strings = useStrings(defaultAvatarUploadStrings, stringsProp);\n\tconst inputId = useId();\n\tconst inputRef = useRef<HTMLInputElement | null>(null);\n\tconst sizes = SIZE_PX[size];\n\n\tconst { files, setFiles, removeAll, formatSize, rejections } = useFiles({\n\t\tmaxFiles: 1,\n\t\tallowedExtensions: useMemo(\n\t\t\t() =>\n\t\t\t\taccept\n\t\t\t\t\t.split(',')\n\t\t\t\t\t.map((s) => s.trim().replace(/^\\./, '').toLowerCase())\n\t\t\t\t\t.filter(Boolean),\n\t\t\t[accept],\n\t\t),\n\t});\n\n\tuseEffect(() => {\n\t\tif (value) setFiles([value]);\n\t\telse removeAll();\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [value]);\n\n\tconst selected = files[0];\n\tconst [filePreviewUrl, setFilePreviewUrl] = useState<string | undefined>(undefined);\n\n\tuseEffect(() => {\n\t\tconst file = selected?.file ?? value;\n\t\tif (!file) {\n\t\t\tsetFilePreviewUrl(undefined);\n\t\t\treturn;\n\t\t}\n\t\tconst url = URL.createObjectURL(file);\n\t\tsetFilePreviewUrl(url);\n\t\treturn () => URL.revokeObjectURL(url);\n\t}, [selected, value]);\n\n\tconst previewUrl = filePreviewUrl ?? initialPreviewUrl;\n\tconst hasPreview = Boolean(previewUrl);\n\n\tconst handleInput = useCallback(\n\t\t(e: ChangeEvent<HTMLInputElement>) => {\n\t\t\tconst list = e.target.files;\n\t\t\tif (!list || list.length === 0) return;\n\t\t\tconst result = setFiles(list);\n\t\t\tconst acceptedFile = result.accepted[0]?.file;\n\t\t\tif (acceptedFile) onValueChange?.(acceptedFile);\n\t\t\tif (inputRef.current) inputRef.current.value = '';\n\t\t},\n\t\t[onValueChange, setFiles],\n\t);\n\n\tconst handleRemove = useCallback(() => {\n\t\tremoveAll();\n\t\tonValueChange?.(undefined);\n\t\tif (inputRef.current) inputRef.current.value = '';\n\t}, [onValueChange, removeAll]);\n\n\tconst handleFiles = useCallback((incoming: File[]) => {\n\t\tconst result = setFiles(incoming);\n\t\tconst acceptedFile = result.accepted[0]?.file;\n\t\tif (acceptedFile) onValueChange?.(acceptedFile);\n\t}, [onValueChange, setFiles]);\n\tconst { isDragging, dropTargetProps } = useFileDropTarget({ disabled, onFiles: handleFiles });\n\n\treturn (\n\t\t// Intrinsic width, aligned to the field's start edge even inside a stretching stack.\n\t\t<div className={cn('avatar-upload--component', 'inline-flex w-fit flex-col items-center gap-space-md self-start', className)}>\n\t\t\t<div\n\t\t\t\t{...dropTargetProps}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'group relative flex shrink-0 items-center justify-center rounded-full',\n\t\t\t\t\t'border transition-colors duration-150 outline-none',\n\t\t\t\t\t// Keyboard focus only: a pointer click on the file input draws no ring.\n\t\t\t\t\t'has-[input:focus-visible]:ring-2 has-[input:focus-visible]:ring-ring',\n\t\t\t\t\thasPreview\n\t\t\t\t\t\t? 'border-border bg-muted'\n\t\t\t\t\t\t: cn(\n\t\t\t\t\t\t\t\t// The empty drop target shares the upload family's dashed control boundary.\n\t\t\t\t\t\t\t\t'border-dashed bg-muted',\n\t\t\t\t\t\t\t\t!disabled && 'hover:border-primary hover:bg-primary/5',\n\t\t\t\t\t\t\t\tuploadDropTargetRecipes.idle,\n\t\t\t\t\t\t\t),\n\t\t\t\t\tinvalid && uploadDropTargetRecipes.invalid,\n\t\t\t\t\tdisabled && 'cursor-not-allowed opacity-50',\n\t\t\t\t\t!disabled && isDragging && uploadDropTargetRecipes.dragging,\n\t\t\t\t\tsizes.box,\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<input\n\t\t\t\t\tid={inputId}\n\t\t\t\t\tref={(node) => { inputRef.current = node; if (typeof forwardedRef === \"function\") forwardedRef(node); else if (forwardedRef) forwardedRef.current = node; }}\n\t\t\t\t\ttype=\"file\"\n\t\t\t\t\tclassName=\"absolute inset-0 z-10 size-full cursor-pointer opacity-0 disabled:cursor-not-allowed\"\n\t\t\t\t\taria-label={strings.change}\n\t\t\t\t\taria-invalid={invalid || undefined}\n\t\t\t\t\taccept={accept}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tonChange={handleInput}\n\t\t\t\t/>\n\n\t\t\t\t{/* Only the visual preview is circularly clipped; removal and focus\n\t\t\t\t remain outside that clip as space and density scale independently. */}\n\t\t\t\t<div className=\"pointer-events-none absolute inset-0 flex items-center justify-center overflow-hidden rounded-full\">\n\t\t\t\t\t{hasPreview && previewUrl ? (\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tsrc={previewUrl}\n\t\t\t\t\t\t\talt={strings.change}\n\t\t\t\t\t\t\tclassName=\"absolute inset-0 size-full object-cover\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : initials ? (\n\t\t\t\t\t\t<Text size={size === 'sm' ? 'sm' : size === 'lg' ? 'lg' : 'base'} weight=\"medium\" lineHeight=\"none\">\n\t\t\t\t\t\t\t{initials}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<Camera className={cn(sizes.icon, 'text-muted-foreground')} aria-hidden=\"true\" />\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* Hover overlay: a plain inverse scrim, dark in both themes, keeps the\n\t\t\t\t\t glyph legible over any photo without blurring it. */}\n\t\t\t\t\t{!disabled && hasPreview && (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName=\"absolute inset-0 hidden items-center justify-center bg-inverse-background/60 text-inverse-foreground group-hover:flex\"\n\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Camera className={sizes.icon} />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\n\t\t\t\t{/* Remove pill */}\n\t\t\t\t{!disabled && hasPreview && (\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\taria-label={strings.remove}\n\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\thandleRemove();\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\tfieldAffordanceRecipes.target,\n\t\t\t\t\t\t\tfieldAffordanceRecipes.focus,\n\t\t\t\t\t\t\t'absolute end-0.5 top-0.5 z-20 bg-card text-foreground shadow ring-1 ring-border',\n\t\t\t\t\t\t\t'opacity-100 transition-opacity sm:opacity-0 sm:group-hover:opacity-100 group-focus-within:opacity-100 focus-visible:opacity-100',\n\t\t\t\t\t\t\tsizes.remove,\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<X className={fieldAffordanceRecipes.icon} />\n\t\t\t\t\t</button>\n\t\t\t\t)}\n\n\t\t\t\t{!disabled && !hasPreview && isDragging && (\n\t\t\t\t\t<Text size=\"xs\" weight=\"medium\" className=\"absolute inset-x-0 bottom-1.5 text-center text-primary-accent\">\n\t\t\t\t\t\t{strings.dragOver}\n\t\t\t\t\t</Text>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{!hasPreview && (\n\t\t\t\t<Text size=\"xs\" type=\"secondary\">\n\t\t\t\t\t{strings.hint}\n\t\t\t\t</Text>\n\t\t\t)}\n\t\t\t{rejections.length > 0 && (\n\t\t\t\t<div className=\"avatar-upload--errors grid gap-space-2xs\" role=\"alert\" aria-live=\"polite\">\n\t\t\t\t\t{rejections.map((rejection, index) => (\n\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\tkey={`${rejection.file.name}-${rejection.code}-${index}`}\n\t\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\t\ttype=\"error\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{getAvatarUploadRejectionMessage(rejection, strings, formatSize)}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nconst AvatarUpload = React.forwardRef<HTMLInputElement, AvatarUploadProps>(AvatarUploadImpl);\nAvatarUpload.displayName = 'AvatarUpload';\n\nexport { AvatarUpload };\n"],"mappings":"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"}