@fanvue/ui 2.21.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (227) hide show
  1. package/dist/cjs/components/Accordion/AccordionContent.cjs +1 -1
  2. package/dist/cjs/components/Accordion/AccordionContent.cjs.map +1 -1
  3. package/dist/cjs/components/Accordion/AccordionTrigger.cjs +2 -2
  4. package/dist/cjs/components/Accordion/AccordionTrigger.cjs.map +1 -1
  5. package/dist/cjs/components/Alert/Alert.cjs +2 -2
  6. package/dist/cjs/components/Alert/Alert.cjs.map +1 -1
  7. package/dist/cjs/components/AudioUpload/AudioUpload.cjs +6 -6
  8. package/dist/cjs/components/AudioUpload/AudioUpload.cjs.map +1 -1
  9. package/dist/cjs/components/Autocomplete/Autocomplete.cjs +6 -6
  10. package/dist/cjs/components/Autocomplete/Autocomplete.cjs.map +1 -1
  11. package/dist/cjs/components/Autocomplete/AutocompleteDropdownContent.cjs +4 -4
  12. package/dist/cjs/components/Autocomplete/AutocompleteDropdownContent.cjs.map +1 -1
  13. package/dist/cjs/components/Autocomplete/AutocompleteOptionItem.cjs +1 -1
  14. package/dist/cjs/components/Autocomplete/AutocompleteOptionItem.cjs.map +1 -1
  15. package/dist/cjs/components/Autocomplete/AutocompleteTag.cjs +1 -1
  16. package/dist/cjs/components/Autocomplete/AutocompleteTag.cjs.map +1 -1
  17. package/dist/cjs/components/Badge/Badge.cjs +12 -12
  18. package/dist/cjs/components/Badge/Badge.cjs.map +1 -1
  19. package/dist/cjs/components/Banner/Banner.cjs +11 -11
  20. package/dist/cjs/components/Banner/Banner.cjs.map +1 -1
  21. package/dist/cjs/components/BottomNavigation/BottomNavigation.cjs +2 -2
  22. package/dist/cjs/components/BottomNavigation/BottomNavigation.cjs.map +1 -1
  23. package/dist/cjs/components/BottomNavigation/BottomNavigationAction.cjs +2 -2
  24. package/dist/cjs/components/BottomNavigation/BottomNavigationAction.cjs.map +1 -1
  25. package/dist/cjs/components/Breadcrumb/Breadcrumb.cjs +2 -2
  26. package/dist/cjs/components/Breadcrumb/Breadcrumb.cjs.map +1 -1
  27. package/dist/cjs/components/Button/Button.cjs +9 -9
  28. package/dist/cjs/components/Button/Button.cjs.map +1 -1
  29. package/dist/cjs/components/Card/Card.cjs +2 -2
  30. package/dist/cjs/components/Card/Card.cjs.map +1 -1
  31. package/dist/cjs/components/Chart/ChartCard.cjs +4 -4
  32. package/dist/cjs/components/Chart/ChartCard.cjs.map +1 -1
  33. package/dist/cjs/components/Chart/ChartPieLegend.cjs +2 -2
  34. package/dist/cjs/components/Chart/ChartPieLegend.cjs.map +1 -1
  35. package/dist/cjs/components/Chart/ChartSeriesToggle.cjs +1 -1
  36. package/dist/cjs/components/Chart/ChartSeriesToggle.cjs.map +1 -1
  37. package/dist/cjs/components/ChatInput/ChatInput.cjs +4 -4
  38. package/dist/cjs/components/ChatInput/ChatInput.cjs.map +1 -1
  39. package/dist/cjs/components/Checkbox/Checkbox.cjs +3 -3
  40. package/dist/cjs/components/Checkbox/Checkbox.cjs.map +1 -1
  41. package/dist/cjs/components/Chip/Chip.cjs +3 -3
  42. package/dist/cjs/components/Chip/Chip.cjs.map +1 -1
  43. package/dist/cjs/components/Count/Count.cjs +7 -7
  44. package/dist/cjs/components/Count/Count.cjs.map +1 -1
  45. package/dist/cjs/components/CreatorCard/CreatorCard.cjs +4 -4
  46. package/dist/cjs/components/CreatorCard/CreatorCard.cjs.map +1 -1
  47. package/dist/cjs/components/CreatorCover/CreatorCover.cjs +5 -5
  48. package/dist/cjs/components/CreatorCover/CreatorCover.cjs.map +1 -1
  49. package/dist/cjs/components/CreatorTile/CreatorTile.cjs +2 -2
  50. package/dist/cjs/components/CreatorTile/CreatorTile.cjs.map +1 -1
  51. package/dist/cjs/components/DatePicker/DatePicker.cjs +5 -5
  52. package/dist/cjs/components/DatePicker/DatePicker.cjs.map +1 -1
  53. package/dist/cjs/components/Dialog/Dialog.cjs +4 -4
  54. package/dist/cjs/components/Dialog/Dialog.cjs.map +1 -1
  55. package/dist/cjs/components/Divider/Divider.cjs +1 -1
  56. package/dist/cjs/components/Divider/Divider.cjs.map +1 -1
  57. package/dist/cjs/components/Drawer/Drawer.cjs +3 -3
  58. package/dist/cjs/components/Drawer/Drawer.cjs.map +1 -1
  59. package/dist/cjs/components/DropdownMenu/DropdownMenu.cjs +13 -13
  60. package/dist/cjs/components/DropdownMenu/DropdownMenu.cjs.map +1 -1
  61. package/dist/cjs/components/EmptyState/EmptyState.cjs +6 -6
  62. package/dist/cjs/components/EmptyState/EmptyState.cjs.map +1 -1
  63. package/dist/cjs/components/IconButton/IconButton.cjs +6 -6
  64. package/dist/cjs/components/IconButton/IconButton.cjs.map +1 -1
  65. package/dist/cjs/components/InfoBox/InfoBox.cjs +4 -4
  66. package/dist/cjs/components/InfoBox/InfoBox.cjs.map +1 -1
  67. package/dist/cjs/components/InlineEdit/InlineEdit.cjs +1 -1
  68. package/dist/cjs/components/InlineEdit/InlineEdit.cjs.map +1 -1
  69. package/dist/cjs/components/Logo/Logo.cjs +2 -2
  70. package/dist/cjs/components/Logo/Logo.cjs.map +1 -1
  71. package/dist/cjs/components/MobileStepper/MobileStepper.cjs +1 -1
  72. package/dist/cjs/components/MobileStepper/MobileStepper.cjs.map +1 -1
  73. package/dist/cjs/components/Pagination/Pagination.cjs +1 -1
  74. package/dist/cjs/components/Pagination/Pagination.cjs.map +1 -1
  75. package/dist/cjs/components/Pill/Pill.cjs +5 -5
  76. package/dist/cjs/components/Pill/Pill.cjs.map +1 -1
  77. package/dist/cjs/components/ProgressBar/ProgressBar.cjs +5 -5
  78. package/dist/cjs/components/ProgressBar/ProgressBar.cjs.map +1 -1
  79. package/dist/cjs/components/Radio/Radio.cjs +3 -3
  80. package/dist/cjs/components/Radio/Radio.cjs.map +1 -1
  81. package/dist/cjs/components/Select/Select.cjs +11 -8
  82. package/dist/cjs/components/Select/Select.cjs.map +1 -1
  83. package/dist/cjs/components/Skeleton/Skeleton.cjs +1 -1
  84. package/dist/cjs/components/Skeleton/Skeleton.cjs.map +1 -1
  85. package/dist/cjs/components/Slider/SliderLayout.cjs +12 -5
  86. package/dist/cjs/components/Slider/SliderLayout.cjs.map +1 -1
  87. package/dist/cjs/components/Slider/SliderThumb.cjs +3 -3
  88. package/dist/cjs/components/Slider/SliderThumb.cjs.map +1 -1
  89. package/dist/cjs/components/Snackbar/Snackbar.cjs +6 -6
  90. package/dist/cjs/components/Snackbar/Snackbar.cjs.map +1 -1
  91. package/dist/cjs/components/Stepper/StepperStep.cjs +9 -9
  92. package/dist/cjs/components/Stepper/StepperStep.cjs.map +1 -1
  93. package/dist/cjs/components/Switch/Switch.cjs +1 -1
  94. package/dist/cjs/components/Switch/Switch.cjs.map +1 -1
  95. package/dist/cjs/components/SwitchField/SwitchField.cjs +2 -2
  96. package/dist/cjs/components/SwitchField/SwitchField.cjs.map +1 -1
  97. package/dist/cjs/components/SwitchToggle/SwitchToggle.cjs +1 -1
  98. package/dist/cjs/components/SwitchToggle/SwitchToggle.cjs.map +1 -1
  99. package/dist/cjs/components/Table/Table.cjs +7 -7
  100. package/dist/cjs/components/Table/Table.cjs.map +1 -1
  101. package/dist/cjs/components/Table/TablePagination.cjs +2 -2
  102. package/dist/cjs/components/Table/TablePagination.cjs.map +1 -1
  103. package/dist/cjs/components/Tabs/TabsTrigger.cjs +2 -2
  104. package/dist/cjs/components/Tabs/TabsTrigger.cjs.map +1 -1
  105. package/dist/cjs/components/TextArea/TextArea.cjs +5 -5
  106. package/dist/cjs/components/TextArea/TextArea.cjs.map +1 -1
  107. package/dist/cjs/components/TextField/TextField.cjs +5 -5
  108. package/dist/cjs/components/TextField/TextField.cjs.map +1 -1
  109. package/dist/cjs/components/Toast/Toast.cjs +2 -2
  110. package/dist/cjs/components/Toast/Toast.cjs.map +1 -1
  111. package/dist/cjs/components/Tooltip/Tooltip.cjs +1 -1
  112. package/dist/cjs/components/Tooltip/Tooltip.cjs.map +1 -1
  113. package/dist/components/Accordion/AccordionContent.mjs +1 -1
  114. package/dist/components/Accordion/AccordionContent.mjs.map +1 -1
  115. package/dist/components/Accordion/AccordionTrigger.mjs +2 -2
  116. package/dist/components/Accordion/AccordionTrigger.mjs.map +1 -1
  117. package/dist/components/Alert/Alert.mjs +2 -2
  118. package/dist/components/Alert/Alert.mjs.map +1 -1
  119. package/dist/components/AudioUpload/AudioUpload.mjs +6 -6
  120. package/dist/components/AudioUpload/AudioUpload.mjs.map +1 -1
  121. package/dist/components/Autocomplete/Autocomplete.mjs +6 -6
  122. package/dist/components/Autocomplete/Autocomplete.mjs.map +1 -1
  123. package/dist/components/Autocomplete/AutocompleteDropdownContent.mjs +4 -4
  124. package/dist/components/Autocomplete/AutocompleteDropdownContent.mjs.map +1 -1
  125. package/dist/components/Autocomplete/AutocompleteOptionItem.mjs +1 -1
  126. package/dist/components/Autocomplete/AutocompleteOptionItem.mjs.map +1 -1
  127. package/dist/components/Autocomplete/AutocompleteTag.mjs +1 -1
  128. package/dist/components/Autocomplete/AutocompleteTag.mjs.map +1 -1
  129. package/dist/components/Badge/Badge.mjs +12 -12
  130. package/dist/components/Badge/Badge.mjs.map +1 -1
  131. package/dist/components/Banner/Banner.mjs +11 -11
  132. package/dist/components/Banner/Banner.mjs.map +1 -1
  133. package/dist/components/BottomNavigation/BottomNavigation.mjs +2 -2
  134. package/dist/components/BottomNavigation/BottomNavigation.mjs.map +1 -1
  135. package/dist/components/BottomNavigation/BottomNavigationAction.mjs +2 -2
  136. package/dist/components/BottomNavigation/BottomNavigationAction.mjs.map +1 -1
  137. package/dist/components/Breadcrumb/Breadcrumb.mjs +2 -2
  138. package/dist/components/Breadcrumb/Breadcrumb.mjs.map +1 -1
  139. package/dist/components/Button/Button.mjs +9 -9
  140. package/dist/components/Button/Button.mjs.map +1 -1
  141. package/dist/components/Card/Card.mjs +2 -2
  142. package/dist/components/Card/Card.mjs.map +1 -1
  143. package/dist/components/Chart/ChartCard.mjs +4 -4
  144. package/dist/components/Chart/ChartCard.mjs.map +1 -1
  145. package/dist/components/Chart/ChartPieLegend.mjs +2 -2
  146. package/dist/components/Chart/ChartPieLegend.mjs.map +1 -1
  147. package/dist/components/Chart/ChartSeriesToggle.mjs +1 -1
  148. package/dist/components/Chart/ChartSeriesToggle.mjs.map +1 -1
  149. package/dist/components/ChatInput/ChatInput.mjs +4 -4
  150. package/dist/components/ChatInput/ChatInput.mjs.map +1 -1
  151. package/dist/components/Checkbox/Checkbox.mjs +3 -3
  152. package/dist/components/Checkbox/Checkbox.mjs.map +1 -1
  153. package/dist/components/Chip/Chip.mjs +3 -3
  154. package/dist/components/Chip/Chip.mjs.map +1 -1
  155. package/dist/components/Count/Count.mjs +7 -7
  156. package/dist/components/Count/Count.mjs.map +1 -1
  157. package/dist/components/CreatorCard/CreatorCard.mjs +4 -4
  158. package/dist/components/CreatorCard/CreatorCard.mjs.map +1 -1
  159. package/dist/components/CreatorCover/CreatorCover.mjs +5 -5
  160. package/dist/components/CreatorCover/CreatorCover.mjs.map +1 -1
  161. package/dist/components/CreatorTile/CreatorTile.mjs +2 -2
  162. package/dist/components/CreatorTile/CreatorTile.mjs.map +1 -1
  163. package/dist/components/DatePicker/DatePicker.mjs +5 -5
  164. package/dist/components/DatePicker/DatePicker.mjs.map +1 -1
  165. package/dist/components/Dialog/Dialog.mjs +4 -4
  166. package/dist/components/Dialog/Dialog.mjs.map +1 -1
  167. package/dist/components/Divider/Divider.mjs +1 -1
  168. package/dist/components/Divider/Divider.mjs.map +1 -1
  169. package/dist/components/Drawer/Drawer.mjs +3 -3
  170. package/dist/components/Drawer/Drawer.mjs.map +1 -1
  171. package/dist/components/DropdownMenu/DropdownMenu.mjs +13 -13
  172. package/dist/components/DropdownMenu/DropdownMenu.mjs.map +1 -1
  173. package/dist/components/EmptyState/EmptyState.mjs +6 -6
  174. package/dist/components/EmptyState/EmptyState.mjs.map +1 -1
  175. package/dist/components/IconButton/IconButton.mjs +6 -6
  176. package/dist/components/IconButton/IconButton.mjs.map +1 -1
  177. package/dist/components/InfoBox/InfoBox.mjs +4 -4
  178. package/dist/components/InfoBox/InfoBox.mjs.map +1 -1
  179. package/dist/components/InlineEdit/InlineEdit.mjs +1 -1
  180. package/dist/components/InlineEdit/InlineEdit.mjs.map +1 -1
  181. package/dist/components/Logo/Logo.mjs +2 -2
  182. package/dist/components/Logo/Logo.mjs.map +1 -1
  183. package/dist/components/MobileStepper/MobileStepper.mjs +1 -1
  184. package/dist/components/MobileStepper/MobileStepper.mjs.map +1 -1
  185. package/dist/components/Pagination/Pagination.mjs +1 -1
  186. package/dist/components/Pagination/Pagination.mjs.map +1 -1
  187. package/dist/components/Pill/Pill.mjs +5 -5
  188. package/dist/components/Pill/Pill.mjs.map +1 -1
  189. package/dist/components/ProgressBar/ProgressBar.mjs +5 -5
  190. package/dist/components/ProgressBar/ProgressBar.mjs.map +1 -1
  191. package/dist/components/Radio/Radio.mjs +3 -3
  192. package/dist/components/Radio/Radio.mjs.map +1 -1
  193. package/dist/components/Select/Select.mjs +11 -8
  194. package/dist/components/Select/Select.mjs.map +1 -1
  195. package/dist/components/Skeleton/Skeleton.mjs +1 -1
  196. package/dist/components/Skeleton/Skeleton.mjs.map +1 -1
  197. package/dist/components/Slider/SliderLayout.mjs +12 -5
  198. package/dist/components/Slider/SliderLayout.mjs.map +1 -1
  199. package/dist/components/Slider/SliderThumb.mjs +3 -3
  200. package/dist/components/Slider/SliderThumb.mjs.map +1 -1
  201. package/dist/components/Snackbar/Snackbar.mjs +6 -6
  202. package/dist/components/Snackbar/Snackbar.mjs.map +1 -1
  203. package/dist/components/Stepper/StepperStep.mjs +9 -9
  204. package/dist/components/Stepper/StepperStep.mjs.map +1 -1
  205. package/dist/components/Switch/Switch.mjs +1 -1
  206. package/dist/components/Switch/Switch.mjs.map +1 -1
  207. package/dist/components/SwitchField/SwitchField.mjs +2 -2
  208. package/dist/components/SwitchField/SwitchField.mjs.map +1 -1
  209. package/dist/components/SwitchToggle/SwitchToggle.mjs +1 -1
  210. package/dist/components/SwitchToggle/SwitchToggle.mjs.map +1 -1
  211. package/dist/components/Table/Table.mjs +7 -7
  212. package/dist/components/Table/Table.mjs.map +1 -1
  213. package/dist/components/Table/TablePagination.mjs +2 -2
  214. package/dist/components/Table/TablePagination.mjs.map +1 -1
  215. package/dist/components/Tabs/TabsTrigger.mjs +2 -2
  216. package/dist/components/Tabs/TabsTrigger.mjs.map +1 -1
  217. package/dist/components/TextArea/TextArea.mjs +5 -5
  218. package/dist/components/TextArea/TextArea.mjs.map +1 -1
  219. package/dist/components/TextField/TextField.mjs +5 -5
  220. package/dist/components/TextField/TextField.mjs.map +1 -1
  221. package/dist/components/Toast/Toast.mjs +2 -2
  222. package/dist/components/Toast/Toast.mjs.map +1 -1
  223. package/dist/components/Tooltip/Tooltip.mjs +1 -1
  224. package/dist/components/Tooltip/Tooltip.mjs.map +1 -1
  225. package/dist/styles/base.css +2 -2
  226. package/dist/styles/theme.css +626 -195
  227. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"BottomNavigationAction.mjs","sources":["../../../src/components/BottomNavigation/BottomNavigationAction.tsx"],"sourcesContent":["import { Slot, Slottable } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { useBottomNavigationContext } from \"./BottomNavigation\";\n\nexport interface BottomNavigationActionProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"value\"> {\n /** Unique value that identifies this action. */\n value: string;\n /** Icon element displayed in the action. */\n icon: React.ReactElement;\n /** Accessible label applied as `aria-label`. */\n label?: string;\n /** Optional badge element (e.g. {@link Count}) rendered at the top-end corner of the icon. */\n badge?: React.ReactNode;\n /** Merge props onto a child element instead of rendering a `<button>`. @default false */\n asChild?: boolean;\n}\n\nexport const BottomNavigationAction = React.forwardRef<\n HTMLButtonElement,\n BottomNavigationActionProps\n>(({ className, value, icon, label, badge, onClick, asChild = false, children, ...props }, ref) => {\n const {\n value: selectedValue,\n onValueChange,\n hasInformationArchitectureNav,\n } = useBottomNavigationContext();\n\n const isActive = selectedValue === value;\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n onValueChange?.(value);\n onClick?.(e);\n };\n\n const Comp = asChild ? Slot : \"button\";\n\n if (hasInformationArchitectureNav) {\n return (\n <Comp\n ref={ref}\n {...(!asChild && { type: \"button\" as const })}\n aria-current={isActive ? (\"page\" as const) : undefined}\n data-state={isActive ? \"active\" : \"inactive\"}\n onClick={handleClick}\n {...props}\n className={cn(\n \"relative flex min-w-0 flex-1 cursor-pointer flex-col items-center justify-center gap-1\",\n isActive ? \"text-icons-primary\" : \"text-icons-tertiary\",\n \"motion-safe:transition-colors motion-safe:duration-150 motion-safe:ease-in-out\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-interaction-focus focus-visible:ring-offset-2 focus-visible:ring-offset-bg-primary\",\n className,\n )}\n >\n {asChild && <Slottable>{children}</Slottable>}\n <span className=\"relative inline-flex\">\n <span className=\"flex items-center justify-center [&>svg]:size-6\" aria-hidden=\"true\">\n {icon}\n </span>\n {badge && <span className=\"absolute -end-1 -top-2.5\">{badge}</span>}\n </span>\n {label && (\n <span\n className={cn(\n \"typography-medium-caption-xs max-w-full truncate text-center motion-safe:transition-colors motion-safe:duration-150 motion-safe:ease-in-out\",\n isActive ? \"text-content-primary\" : \"text-content-tertiary\",\n )}\n >\n {label}\n </span>\n )}\n </Comp>\n );\n }\n\n return (\n <Comp\n ref={ref}\n {...(!asChild && { type: \"button\" as const })}\n aria-current={isActive ? \"page\" : undefined}\n aria-label={label}\n data-state={isActive ? \"active\" : \"inactive\"}\n className={cn(\n \"relative flex min-w-0 flex-1 cursor-pointer flex-col items-center justify-center gap-0.5 overflow-hidden px-2 py-2\",\n \"text-content-primary\",\n \"motion-safe:transition-colors motion-safe:duration-150 motion-safe:ease-in-out\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-interaction-focus focus-visible:ring-offset-2 focus-visible:ring-offset-bg-primary\",\n className,\n )}\n onClick={handleClick}\n {...props}\n >\n {asChild && <Slottable>{children}</Slottable>}\n <span className=\"relative inline-flex\">\n <span className=\"flex items-center justify-center [&>svg]:size-7\" aria-hidden=\"true\">\n {icon}\n </span>\n {badge && <span className=\"absolute -end-1 -top-2.5\">{badge}</span>}\n </span>\n </Comp>\n );\n});\n\nBottomNavigationAction.displayName = \"BottomNavigationAction\";\n"],"names":[],"mappings":";;;;;;AAmBO,MAAM,yBAAyB,MAAM,WAG1C,CAAC,EAAE,WAAW,OAAO,MAAM,OAAO,OAAO,SAAS,UAAU,OAAO,UAAU,GAAG,MAAA,GAAS,QAAQ;AACjG,QAAM;AAAA,IACJ,OAAO;AAAA,IACP;AAAA,IACA;AAAA,EAAA,IACE,2BAAA;AAEJ,QAAM,WAAW,kBAAkB;AAEnC,QAAM,cAAc,CAAC,MAA2C;AAC9D,oBAAgB,KAAK;AACrB,cAAU,CAAC;AAAA,EACb;AAEA,QAAM,OAAO,UAAU,OAAO;AAE9B,MAAI,+BAA+B;AACjC,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACC,GAAI,CAAC,WAAW,EAAE,MAAM,SAAA;AAAA,QACzB,gBAAc,WAAY,SAAmB;AAAA,QAC7C,cAAY,WAAW,WAAW;AAAA,QAClC,SAAS;AAAA,QACR,GAAG;AAAA,QACJ,WAAW;AAAA,UACT;AAAA,UACA,WAAW,uBAAuB;AAAA,UAClC;AAAA,UACA;AAAA,UACA;AAAA,QAAA;AAAA,QAGD,UAAA;AAAA,UAAA,WAAW,oBAAC,aAAW,SAAA,CAAS;AAAA,UACjC,qBAAC,QAAA,EAAK,WAAU,wBACd,UAAA;AAAA,YAAA,oBAAC,QAAA,EAAK,WAAU,mDAAkD,eAAY,QAC3E,UAAA,MACH;AAAA,YACC,SAAS,oBAAC,QAAA,EAAK,WAAU,4BAA4B,UAAA,MAAA,CAAM;AAAA,UAAA,GAC9D;AAAA,UACC,SACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAW;AAAA,gBACT;AAAA,gBACA,WAAW,yBAAyB;AAAA,cAAA;AAAA,cAGrC,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AAEA,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACC,GAAI,CAAC,WAAW,EAAE,MAAM,SAAA;AAAA,MACzB,gBAAc,WAAW,SAAS;AAAA,MAClC,cAAY;AAAA,MACZ,cAAY,WAAW,WAAW;AAAA,MAClC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,SAAS;AAAA,MACR,GAAG;AAAA,MAEH,UAAA;AAAA,QAAA,WAAW,oBAAC,aAAW,SAAA,CAAS;AAAA,QACjC,qBAAC,QAAA,EAAK,WAAU,wBACd,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAK,WAAU,mDAAkD,eAAY,QAC3E,UAAA,MACH;AAAA,UACC,SAAS,oBAAC,QAAA,EAAK,WAAU,4BAA4B,UAAA,MAAA,CAAM;AAAA,QAAA,EAAA,CAC9D;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN,CAAC;AAED,uBAAuB,cAAc;"}
1
+ {"version":3,"file":"BottomNavigationAction.mjs","sources":["../../../src/components/BottomNavigation/BottomNavigationAction.tsx"],"sourcesContent":["import { Slot, Slottable } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { useBottomNavigationContext } from \"./BottomNavigation\";\n\nexport interface BottomNavigationActionProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"value\"> {\n /** Unique value that identifies this action. */\n value: string;\n /** Icon element displayed in the action. */\n icon: React.ReactElement;\n /** Accessible label applied as `aria-label`. */\n label?: string;\n /** Optional badge element (e.g. {@link Count}) rendered at the top-end corner of the icon. */\n badge?: React.ReactNode;\n /** Merge props onto a child element instead of rendering a `<button>`. @default false */\n asChild?: boolean;\n}\n\nexport const BottomNavigationAction = React.forwardRef<\n HTMLButtonElement,\n BottomNavigationActionProps\n>(({ className, value, icon, label, badge, onClick, asChild = false, children, ...props }, ref) => {\n const {\n value: selectedValue,\n onValueChange,\n hasInformationArchitectureNav,\n } = useBottomNavigationContext();\n\n const isActive = selectedValue === value;\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n onValueChange?.(value);\n onClick?.(e);\n };\n\n const Comp = asChild ? Slot : \"button\";\n\n if (hasInformationArchitectureNav) {\n return (\n <Comp\n ref={ref}\n {...(!asChild && { type: \"button\" as const })}\n aria-current={isActive ? (\"page\" as const) : undefined}\n data-state={isActive ? \"active\" : \"inactive\"}\n onClick={handleClick}\n {...props}\n className={cn(\n \"relative flex min-w-0 flex-1 cursor-pointer flex-col items-center justify-center gap-1\",\n isActive ? \"text-icons-primary\" : \"text-icons-tertiary\",\n \"motion-safe:transition-colors motion-safe:duration-150 motion-safe:ease-in-out\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-interaction-focus focus-visible:ring-offset-2 focus-visible:ring-offset-background-primary\",\n className,\n )}\n >\n {asChild && <Slottable>{children}</Slottable>}\n <span className=\"relative inline-flex\">\n <span className=\"flex items-center justify-center [&>svg]:size-6\" aria-hidden=\"true\">\n {icon}\n </span>\n {badge && <span className=\"absolute -end-1 -top-2.5\">{badge}</span>}\n </span>\n {label && (\n <span\n className={cn(\n \"typography-medium-caption-xs max-w-full truncate text-center motion-safe:transition-colors motion-safe:duration-150 motion-safe:ease-in-out\",\n isActive ? \"text-content-primary\" : \"text-content-tertiary\",\n )}\n >\n {label}\n </span>\n )}\n </Comp>\n );\n }\n\n return (\n <Comp\n ref={ref}\n {...(!asChild && { type: \"button\" as const })}\n aria-current={isActive ? \"page\" : undefined}\n aria-label={label}\n data-state={isActive ? \"active\" : \"inactive\"}\n className={cn(\n \"relative flex min-w-0 flex-1 cursor-pointer flex-col items-center justify-center gap-0.5 overflow-hidden px-2 py-2\",\n \"text-content-primary\",\n \"motion-safe:transition-colors motion-safe:duration-150 motion-safe:ease-in-out\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-interaction-focus focus-visible:ring-offset-2 focus-visible:ring-offset-background-primary\",\n className,\n )}\n onClick={handleClick}\n {...props}\n >\n {asChild && <Slottable>{children}</Slottable>}\n <span className=\"relative inline-flex\">\n <span className=\"flex items-center justify-center [&>svg]:size-7\" aria-hidden=\"true\">\n {icon}\n </span>\n {badge && <span className=\"absolute -end-1 -top-2.5\">{badge}</span>}\n </span>\n </Comp>\n );\n});\n\nBottomNavigationAction.displayName = \"BottomNavigationAction\";\n"],"names":[],"mappings":";;;;;;AAmBO,MAAM,yBAAyB,MAAM,WAG1C,CAAC,EAAE,WAAW,OAAO,MAAM,OAAO,OAAO,SAAS,UAAU,OAAO,UAAU,GAAG,MAAA,GAAS,QAAQ;AACjG,QAAM;AAAA,IACJ,OAAO;AAAA,IACP;AAAA,IACA;AAAA,EAAA,IACE,2BAAA;AAEJ,QAAM,WAAW,kBAAkB;AAEnC,QAAM,cAAc,CAAC,MAA2C;AAC9D,oBAAgB,KAAK;AACrB,cAAU,CAAC;AAAA,EACb;AAEA,QAAM,OAAO,UAAU,OAAO;AAE9B,MAAI,+BAA+B;AACjC,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACC,GAAI,CAAC,WAAW,EAAE,MAAM,SAAA;AAAA,QACzB,gBAAc,WAAY,SAAmB;AAAA,QAC7C,cAAY,WAAW,WAAW;AAAA,QAClC,SAAS;AAAA,QACR,GAAG;AAAA,QACJ,WAAW;AAAA,UACT;AAAA,UACA,WAAW,uBAAuB;AAAA,UAClC;AAAA,UACA;AAAA,UACA;AAAA,QAAA;AAAA,QAGD,UAAA;AAAA,UAAA,WAAW,oBAAC,aAAW,SAAA,CAAS;AAAA,UACjC,qBAAC,QAAA,EAAK,WAAU,wBACd,UAAA;AAAA,YAAA,oBAAC,QAAA,EAAK,WAAU,mDAAkD,eAAY,QAC3E,UAAA,MACH;AAAA,YACC,SAAS,oBAAC,QAAA,EAAK,WAAU,4BAA4B,UAAA,MAAA,CAAM;AAAA,UAAA,GAC9D;AAAA,UACC,SACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAW;AAAA,gBACT;AAAA,gBACA,WAAW,yBAAyB;AAAA,cAAA;AAAA,cAGrC,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AAEA,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACC,GAAI,CAAC,WAAW,EAAE,MAAM,SAAA;AAAA,MACzB,gBAAc,WAAW,SAAS;AAAA,MAClC,cAAY;AAAA,MACZ,cAAY,WAAW,WAAW;AAAA,MAClC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,SAAS;AAAA,MACR,GAAG;AAAA,MAEH,UAAA;AAAA,QAAA,WAAW,oBAAC,aAAW,SAAA,CAAS;AAAA,QACjC,qBAAC,QAAA,EAAK,WAAU,wBACd,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAK,WAAU,mDAAkD,eAAY,QAC3E,UAAA,MACH;AAAA,UACC,SAAS,oBAAC,QAAA,EAAK,WAAU,4BAA4B,UAAA,MAAA,CAAM;AAAA,QAAA,EAAA,CAC9D;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN,CAAC;AAED,uBAAuB,cAAc;"}
@@ -34,7 +34,7 @@ const BreadcrumbLink = React.forwardRef(
34
34
  {
35
35
  ref,
36
36
  className: cn(
37
- "typography-regular-body-sm rounded-[2px] text-content-secondary underline-offset-2 transition-colors hover:text-content-primary hover:underline focus-visible:shadow-focus-ring focus-visible:outline-none",
37
+ "typography-description-12px-regular rounded-[2px] text-content-secondary underline-offset-2 transition-colors hover:text-content-primary hover:underline focus-visible:shadow-focus-ring focus-visible:outline-none",
38
38
  className
39
39
  ),
40
40
  ...props
@@ -49,7 +49,7 @@ const BreadcrumbPage = React.forwardRef(
49
49
  {
50
50
  ref,
51
51
  "aria-current": "page",
52
- className: cn("typography-semibold-body-sm text-content-primary", className),
52
+ className: cn("typography-description-12px-semibold text-content-primary", className),
53
53
  ...props
54
54
  }
55
55
  )
@@ -1 +1 @@
1
- {"version":3,"file":"Breadcrumb.mjs","sources":["../../../src/components/Breadcrumb/Breadcrumb.tsx"],"sourcesContent":["import { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { ChevronRightIcon } from \"../Icons/ChevronRightIcon\";\n\nexport interface BreadcrumbProps extends React.ComponentPropsWithoutRef<\"nav\"> {\n /** Accessible label for the breadcrumb navigation landmark. @default \"breadcrumb\" */\n \"aria-label\"?: string;\n}\n\n/**\n * Root navigation wrapper for the breadcrumb trail.\n *\n * @example\n * ```tsx\n * <Breadcrumb>\n * <BreadcrumbList>\n * <BreadcrumbItem><BreadcrumbLink href=\"/\">Home</BreadcrumbLink></BreadcrumbItem>\n * <BreadcrumbSeparator />\n * <BreadcrumbItem><BreadcrumbPage>Current Page</BreadcrumbPage></BreadcrumbItem>\n * </BreadcrumbList>\n * </Breadcrumb>\n * ```\n */\nexport const Breadcrumb = React.forwardRef<HTMLElement, BreadcrumbProps>(\n ({ \"aria-label\": ariaLabel = \"breadcrumb\", ...props }, ref) => (\n <nav ref={ref} aria-label={ariaLabel} {...props} />\n ),\n);\n\nBreadcrumb.displayName = \"Breadcrumb\";\n\nexport interface BreadcrumbListProps extends React.ComponentPropsWithoutRef<\"ol\"> {\n /** Custom separator element rendered between items. @default ChevronRightIcon */\n separator?: React.ReactNode;\n}\n\n/**\n * Ordered list container for breadcrumb items. Automatically injects a\n * separator between each child item.\n */\nexport const BreadcrumbList = React.forwardRef<HTMLOListElement, BreadcrumbListProps>(\n ({ className, children, separator, ...props }, ref) => {\n const items = React.Children.toArray(children);\n const withSeparators = items.flatMap((child, index) => {\n const childKey = React.isValidElement(child) ? child.key : index;\n return index === 0\n ? [child]\n : [\n <BreadcrumbSeparator key={`sep-before-${childKey}`}>{separator}</BreadcrumbSeparator>,\n child,\n ];\n });\n\n return (\n <ol ref={ref} className={cn(\"flex flex-wrap items-center gap-2\", className)} {...props}>\n {withSeparators}\n </ol>\n );\n },\n);\n\nBreadcrumbList.displayName = \"BreadcrumbList\";\n\nexport interface BreadcrumbItemProps extends React.ComponentPropsWithoutRef<\"li\"> {}\n\n/**\n * List item wrapper for a single breadcrumb entry or separator.\n */\nexport const BreadcrumbItem = React.forwardRef<HTMLLIElement, BreadcrumbItemProps>(\n ({ className, ...props }, ref) => (\n <li ref={ref} className={cn(\"inline-flex items-center gap-2\", className)} {...props} />\n ),\n);\n\nBreadcrumbItem.displayName = \"BreadcrumbItem\";\n\nexport interface BreadcrumbLinkProps extends React.ComponentPropsWithoutRef<\"a\"> {\n /** Render the link as a child element (e.g. a router `Link`). @default false */\n asChild?: boolean;\n}\n\n/**\n * Anchor element for a non-current breadcrumb step. Supports `asChild` for\n * router-aware link components.\n */\nexport const BreadcrumbLink = React.forwardRef<HTMLAnchorElement, BreadcrumbLinkProps>(\n ({ asChild = false, className, ...props }, ref) => {\n const Comp = asChild ? Slot : \"a\";\n return (\n <Comp\n ref={ref}\n className={cn(\n \"typography-regular-body-sm rounded-[2px] text-content-secondary underline-offset-2 transition-colors hover:text-content-primary hover:underline focus-visible:shadow-focus-ring focus-visible:outline-none\",\n className,\n )}\n {...props}\n />\n );\n },\n);\n\nBreadcrumbLink.displayName = \"BreadcrumbLink\";\n\nexport interface BreadcrumbPageProps extends React.ComponentPropsWithoutRef<\"span\"> {}\n\n/**\n * Non-interactive label representing the current page in the breadcrumb trail.\n */\nexport const BreadcrumbPage = React.forwardRef<HTMLSpanElement, BreadcrumbPageProps>(\n ({ className, ...props }, ref) => (\n <span\n ref={ref}\n aria-current=\"page\"\n className={cn(\"typography-semibold-body-sm text-content-primary\", className)}\n {...props}\n />\n ),\n);\n\nBreadcrumbPage.displayName = \"BreadcrumbPage\";\n\nexport interface BreadcrumbSeparatorProps extends React.ComponentPropsWithoutRef<\"li\"> {}\n\n/**\n * Visual separator rendered between breadcrumb items.\n * Renders a right-pointing chevron icon and is hidden from assistive technology.\n */\nexport const BreadcrumbSeparator = React.forwardRef<HTMLLIElement, BreadcrumbSeparatorProps>(\n ({ className, children, ...props }, ref) => (\n <li\n ref={ref}\n aria-hidden=\"true\"\n className={cn(\"flex items-center text-content-secondary\", className)}\n {...props}\n >\n {children ?? <ChevronRightIcon className=\"size-4\" />}\n </li>\n ),\n);\n\nBreadcrumbSeparator.displayName = \"BreadcrumbSeparator\";\n"],"names":[],"mappings":";;;;;;AAwBO,MAAM,aAAa,MAAM;AAAA,EAC9B,CAAC,EAAE,cAAc,YAAY,cAAc,GAAG,MAAA,GAAS,4BACpD,OAAA,EAAI,KAAU,cAAY,WAAY,GAAG,MAAA,CAAO;AAErD;AAEA,WAAW,cAAc;AAWlB,MAAM,iBAAiB,MAAM;AAAA,EAClC,CAAC,EAAE,WAAW,UAAU,WAAW,GAAG,MAAA,GAAS,QAAQ;AACrD,UAAM,QAAQ,MAAM,SAAS,QAAQ,QAAQ;AAC7C,UAAM,iBAAiB,MAAM,QAAQ,CAAC,OAAO,UAAU;AACrD,YAAM,WAAW,MAAM,eAAe,KAAK,IAAI,MAAM,MAAM;AAC3D,aAAO,UAAU,IACb,CAAC,KAAK,IACN;AAAA,QACE,oBAAC,qBAAA,EAAoD,UAAA,UAAA,GAA3B,cAAc,QAAQ,EAAe;AAAA,QAC/D;AAAA,MAAA;AAAA,IAER,CAAC;AAED,WACE,oBAAC,MAAA,EAAG,KAAU,WAAW,GAAG,qCAAqC,SAAS,GAAI,GAAG,OAC9E,UAAA,eAAA,CACH;AAAA,EAEJ;AACF;AAEA,eAAe,cAAc;AAOtB,MAAM,iBAAiB,MAAM;AAAA,EAClC,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QACxB,oBAAC,MAAA,EAAG,KAAU,WAAW,GAAG,kCAAkC,SAAS,GAAI,GAAG,MAAA,CAAO;AAEzF;AAEA,eAAe,cAAc;AAWtB,MAAM,iBAAiB,MAAM;AAAA,EAClC,CAAC,EAAE,UAAU,OAAO,WAAW,GAAG,MAAA,GAAS,QAAQ;AACjD,UAAM,OAAO,UAAU,OAAO;AAC9B,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW;AAAA,UACT;AAAA,UACA;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,MAAA;AAAA,IAAA;AAAA,EAGV;AACF;AAEA,eAAe,cAAc;AAOtB,MAAM,iBAAiB,MAAM;AAAA,EAClC,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QACxB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,gBAAa;AAAA,MACb,WAAW,GAAG,oDAAoD,SAAS;AAAA,MAC1E,GAAG;AAAA,IAAA;AAAA,EAAA;AAGV;AAEA,eAAe,cAAc;AAQtB,MAAM,sBAAsB,MAAM;AAAA,EACvC,CAAC,EAAE,WAAW,UAAU,GAAG,MAAA,GAAS,QAClC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,eAAY;AAAA,MACZ,WAAW,GAAG,4CAA4C,SAAS;AAAA,MAClE,GAAG;AAAA,MAEH,UAAA,YAAY,oBAAC,kBAAA,EAAiB,WAAU,SAAA,CAAS;AAAA,IAAA;AAAA,EAAA;AAGxD;AAEA,oBAAoB,cAAc;"}
1
+ {"version":3,"file":"Breadcrumb.mjs","sources":["../../../src/components/Breadcrumb/Breadcrumb.tsx"],"sourcesContent":["import { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { ChevronRightIcon } from \"../Icons/ChevronRightIcon\";\n\nexport interface BreadcrumbProps extends React.ComponentPropsWithoutRef<\"nav\"> {\n /** Accessible label for the breadcrumb navigation landmark. @default \"breadcrumb\" */\n \"aria-label\"?: string;\n}\n\n/**\n * Root navigation wrapper for the breadcrumb trail.\n *\n * @example\n * ```tsx\n * <Breadcrumb>\n * <BreadcrumbList>\n * <BreadcrumbItem><BreadcrumbLink href=\"/\">Home</BreadcrumbLink></BreadcrumbItem>\n * <BreadcrumbSeparator />\n * <BreadcrumbItem><BreadcrumbPage>Current Page</BreadcrumbPage></BreadcrumbItem>\n * </BreadcrumbList>\n * </Breadcrumb>\n * ```\n */\nexport const Breadcrumb = React.forwardRef<HTMLElement, BreadcrumbProps>(\n ({ \"aria-label\": ariaLabel = \"breadcrumb\", ...props }, ref) => (\n <nav ref={ref} aria-label={ariaLabel} {...props} />\n ),\n);\n\nBreadcrumb.displayName = \"Breadcrumb\";\n\nexport interface BreadcrumbListProps extends React.ComponentPropsWithoutRef<\"ol\"> {\n /** Custom separator element rendered between items. @default ChevronRightIcon */\n separator?: React.ReactNode;\n}\n\n/**\n * Ordered list container for breadcrumb items. Automatically injects a\n * separator between each child item.\n */\nexport const BreadcrumbList = React.forwardRef<HTMLOListElement, BreadcrumbListProps>(\n ({ className, children, separator, ...props }, ref) => {\n const items = React.Children.toArray(children);\n const withSeparators = items.flatMap((child, index) => {\n const childKey = React.isValidElement(child) ? child.key : index;\n return index === 0\n ? [child]\n : [\n <BreadcrumbSeparator key={`sep-before-${childKey}`}>{separator}</BreadcrumbSeparator>,\n child,\n ];\n });\n\n return (\n <ol ref={ref} className={cn(\"flex flex-wrap items-center gap-2\", className)} {...props}>\n {withSeparators}\n </ol>\n );\n },\n);\n\nBreadcrumbList.displayName = \"BreadcrumbList\";\n\nexport interface BreadcrumbItemProps extends React.ComponentPropsWithoutRef<\"li\"> {}\n\n/**\n * List item wrapper for a single breadcrumb entry or separator.\n */\nexport const BreadcrumbItem = React.forwardRef<HTMLLIElement, BreadcrumbItemProps>(\n ({ className, ...props }, ref) => (\n <li ref={ref} className={cn(\"inline-flex items-center gap-2\", className)} {...props} />\n ),\n);\n\nBreadcrumbItem.displayName = \"BreadcrumbItem\";\n\nexport interface BreadcrumbLinkProps extends React.ComponentPropsWithoutRef<\"a\"> {\n /** Render the link as a child element (e.g. a router `Link`). @default false */\n asChild?: boolean;\n}\n\n/**\n * Anchor element for a non-current breadcrumb step. Supports `asChild` for\n * router-aware link components.\n */\nexport const BreadcrumbLink = React.forwardRef<HTMLAnchorElement, BreadcrumbLinkProps>(\n ({ asChild = false, className, ...props }, ref) => {\n const Comp = asChild ? Slot : \"a\";\n return (\n <Comp\n ref={ref}\n className={cn(\n \"typography-description-12px-regular rounded-[2px] text-content-secondary underline-offset-2 transition-colors hover:text-content-primary hover:underline focus-visible:shadow-focus-ring focus-visible:outline-none\",\n className,\n )}\n {...props}\n />\n );\n },\n);\n\nBreadcrumbLink.displayName = \"BreadcrumbLink\";\n\nexport interface BreadcrumbPageProps extends React.ComponentPropsWithoutRef<\"span\"> {}\n\n/**\n * Non-interactive label representing the current page in the breadcrumb trail.\n */\nexport const BreadcrumbPage = React.forwardRef<HTMLSpanElement, BreadcrumbPageProps>(\n ({ className, ...props }, ref) => (\n <span\n ref={ref}\n aria-current=\"page\"\n className={cn(\"typography-description-12px-semibold text-content-primary\", className)}\n {...props}\n />\n ),\n);\n\nBreadcrumbPage.displayName = \"BreadcrumbPage\";\n\nexport interface BreadcrumbSeparatorProps extends React.ComponentPropsWithoutRef<\"li\"> {}\n\n/**\n * Visual separator rendered between breadcrumb items.\n * Renders a right-pointing chevron icon and is hidden from assistive technology.\n */\nexport const BreadcrumbSeparator = React.forwardRef<HTMLLIElement, BreadcrumbSeparatorProps>(\n ({ className, children, ...props }, ref) => (\n <li\n ref={ref}\n aria-hidden=\"true\"\n className={cn(\"flex items-center text-content-secondary\", className)}\n {...props}\n >\n {children ?? <ChevronRightIcon className=\"size-4\" />}\n </li>\n ),\n);\n\nBreadcrumbSeparator.displayName = \"BreadcrumbSeparator\";\n"],"names":[],"mappings":";;;;;;AAwBO,MAAM,aAAa,MAAM;AAAA,EAC9B,CAAC,EAAE,cAAc,YAAY,cAAc,GAAG,MAAA,GAAS,4BACpD,OAAA,EAAI,KAAU,cAAY,WAAY,GAAG,MAAA,CAAO;AAErD;AAEA,WAAW,cAAc;AAWlB,MAAM,iBAAiB,MAAM;AAAA,EAClC,CAAC,EAAE,WAAW,UAAU,WAAW,GAAG,MAAA,GAAS,QAAQ;AACrD,UAAM,QAAQ,MAAM,SAAS,QAAQ,QAAQ;AAC7C,UAAM,iBAAiB,MAAM,QAAQ,CAAC,OAAO,UAAU;AACrD,YAAM,WAAW,MAAM,eAAe,KAAK,IAAI,MAAM,MAAM;AAC3D,aAAO,UAAU,IACb,CAAC,KAAK,IACN;AAAA,QACE,oBAAC,qBAAA,EAAoD,UAAA,UAAA,GAA3B,cAAc,QAAQ,EAAe;AAAA,QAC/D;AAAA,MAAA;AAAA,IAER,CAAC;AAED,WACE,oBAAC,MAAA,EAAG,KAAU,WAAW,GAAG,qCAAqC,SAAS,GAAI,GAAG,OAC9E,UAAA,eAAA,CACH;AAAA,EAEJ;AACF;AAEA,eAAe,cAAc;AAOtB,MAAM,iBAAiB,MAAM;AAAA,EAClC,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QACxB,oBAAC,MAAA,EAAG,KAAU,WAAW,GAAG,kCAAkC,SAAS,GAAI,GAAG,MAAA,CAAO;AAEzF;AAEA,eAAe,cAAc;AAWtB,MAAM,iBAAiB,MAAM;AAAA,EAClC,CAAC,EAAE,UAAU,OAAO,WAAW,GAAG,MAAA,GAAS,QAAQ;AACjD,UAAM,OAAO,UAAU,OAAO;AAC9B,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW;AAAA,UACT;AAAA,UACA;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,MAAA;AAAA,IAAA;AAAA,EAGV;AACF;AAEA,eAAe,cAAc;AAOtB,MAAM,iBAAiB,MAAM;AAAA,EAClC,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QACxB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,gBAAa;AAAA,MACb,WAAW,GAAG,6DAA6D,SAAS;AAAA,MACnF,GAAG;AAAA,IAAA;AAAA,EAAA;AAGV;AAEA,eAAe,cAAc;AAQtB,MAAM,sBAAsB,MAAM;AAAA,EACvC,CAAC,EAAE,WAAW,UAAU,GAAG,MAAA,GAAS,QAClC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,eAAY;AAAA,MACZ,WAAW,GAAG,4CAA4C,SAAS;AAAA,MAClE,GAAG;AAAA,MAEH,UAAA,YAAY,oBAAC,kBAAA,EAAiB,WAAU,SAAA,CAAS;AAAA,IAAA;AAAA,EAAA;AAGxD;AAEA,oBAAoB,cAAc;"}
@@ -5,10 +5,10 @@ import * as React from "react";
5
5
  import { cn } from "../../utils/cn.mjs";
6
6
  import { SpinnerIcon } from "../Icons/SpinnerIcon.mjs";
7
7
  const SIZE_CLASSES = {
8
- "48": "h-12 px-4 py-3 typography-semibold-body-lg",
9
- "40": "h-10 px-4 py-2 typography-semibold-body-lg",
10
- "32": "h-8 px-3 py-2 typography-semibold-body-md",
11
- "24": "h-6 px-2 py-1 typography-semibold-body-md"
8
+ "48": "h-12 px-4 py-3 typography-body-default-16px-semibold",
9
+ "40": "h-10 px-4 py-2 typography-body-default-16px-semibold",
10
+ "32": "h-8 px-3 py-2 typography-body-small-14px-semibold",
11
+ "24": "h-6 px-2 py-1 typography-body-small-14px-semibold"
12
12
  };
13
13
  const ICON_SIZE_CLASS = {
14
14
  "48": "size-5",
@@ -23,13 +23,13 @@ const ICON_WRAPPER_CLASS = {
23
23
  "24": "[&>svg]:size-3.5"
24
24
  };
25
25
  const VARIANT_CLASSES = {
26
- primary: "bg-buttons-primary text-content-primary-inverted hover:bg-buttons-primary-hover hover:text-content-primary-inverted active:bg-buttons-primary-hover active:text-content-primary-inverted",
26
+ primary: "bg-buttons-primary-default text-content-primary-inverted hover:bg-buttons-primary-hover hover:text-content-primary-inverted active:bg-buttons-primary-hover active:text-content-primary-inverted",
27
27
  secondary: "border-content-primary border bg-transparent text-content-primary hover:bg-brand-primary-muted active:bg-brand-primary-muted",
28
28
  tertiary: "bg-transparent text-content-primary hover:bg-brand-primary-muted active:bg-brand-primary-muted",
29
29
  link: "bg-transparent text-content-primary underline decoration-solid hover:bg-brand-primary-muted active:bg-brand-primary-muted",
30
- brand: "bg-buttons-brand text-content-on-brand hover:bg-buttons-brand-hover hover:text-content-on-brand active:bg-buttons-brand-hover active:text-content-on-brand",
31
- destructive: "bg-error-content text-content-on-brand-inverted hover:bg-brand-primary-muted hover:text-content-primary active:bg-brand-primary-muted active:text-content-primary",
32
- white: "bg-content-on-brand-inverted text-content-on-brand hover:bg-brand-primary-muted hover:text-content-primary active:bg-brand-primary-muted active:text-content-primary",
30
+ brand: "bg-buttons-brand-default text-content-always-black hover:bg-buttons-brand-hover hover:text-content-always-black active:bg-buttons-brand-hover active:text-content-always-black",
31
+ destructive: "bg-error-content text-content-always-white hover:bg-brand-primary-muted hover:text-content-primary active:bg-brand-primary-muted active:text-content-primary",
32
+ white: "bg-content-always-white text-content-always-black hover:bg-brand-primary-muted hover:text-content-primary active:bg-brand-primary-muted active:text-content-primary",
33
33
  tertiaryDestructive: "bg-transparent text-error-content hover:bg-error-surface active:bg-error-surface",
34
34
  text: "bg-transparent text-content-primary hover:underline active:underline"
35
35
  };
@@ -95,7 +95,7 @@ function renderContent({
95
95
  }
96
96
  ),
97
97
  (price || discount) && /* @__PURE__ */ jsxs("div", { children: [
98
- discount && /* @__PURE__ */ jsx("span", { className: "typography-regular-body-lg line-through", "aria-hidden": "true", children: discount }),
98
+ discount && /* @__PURE__ */ jsx("span", { className: "typography-body-default-16px-regular line-through", "aria-hidden": "true", children: discount }),
99
99
  price && /* @__PURE__ */ jsx("span", { className: "ml-2", "aria-hidden": "true", children: price })
100
100
  ] })
101
101
  ] });
@@ -1 +1 @@
1
- {"version":3,"file":"Button.mjs","sources":["../../../src/components/Button/Button.tsx"],"sourcesContent":["import { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { SpinnerIcon } from \"../Icons/SpinnerIcon\";\n\n/** Visual style variant of the button. */\nexport type ButtonVariant =\n | \"primary\"\n | \"secondary\"\n | \"tertiary\"\n | \"link\"\n | \"brand\"\n | \"destructive\"\n | \"white\"\n | \"tertiaryDestructive\"\n | \"text\";\n\n/** Button height in pixels. */\nexport type ButtonSize = \"48\" | \"40\" | \"32\" | \"24\";\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Visual style variant of the button. @default \"primary\" */\n variant?: ButtonVariant;\n /** Height of the button in pixels. @default \"40\" */\n size?: ButtonSize;\n /** Icon element displayed before the label. */\n leftIcon?: React.ReactNode;\n /** Icon element displayed after the label. */\n rightIcon?: React.ReactNode;\n /** When `true`, replaces the label with a spinner and disables interaction. @default false */\n loading?: boolean;\n /** Merge props onto a child element instead of rendering a `<button>`. @default false */\n asChild?: boolean;\n /** Old price shown with a strikethrough before the current price. */\n discount?: string;\n /** Current price shown inside the button after the label and icons. */\n price?: string;\n /** When `true`, the button will take the full width of its container. @default false */\n fullWidth?: boolean;\n}\n\nconst SIZE_CLASSES: Record<ButtonSize, string> = {\n \"48\": \"h-12 px-4 py-3 typography-semibold-body-lg\",\n \"40\": \"h-10 px-4 py-2 typography-semibold-body-lg\",\n \"32\": \"h-8 px-3 py-2 typography-semibold-body-md\",\n \"24\": \"h-6 px-2 py-1 typography-semibold-body-md\",\n};\n\nconst ICON_SIZE_CLASS: Record<ButtonSize, string> = {\n \"48\": \"size-5\",\n \"40\": \"size-5\",\n \"32\": \"size-4\",\n \"24\": \"size-3.5\",\n};\n\n/** Targets only direct SVG children so non-icon content (e.g. Pill) can size naturally. */\nconst ICON_WRAPPER_CLASS: Record<ButtonSize, string> = {\n \"48\": \"[&>svg]:size-5\",\n \"40\": \"[&>svg]:size-5\",\n \"32\": \"[&>svg]:size-4\",\n \"24\": \"[&>svg]:size-3.5\",\n};\n\nconst VARIANT_CLASSES: Record<ButtonVariant, string> = {\n primary:\n \"bg-buttons-primary text-content-primary-inverted hover:bg-buttons-primary-hover hover:text-content-primary-inverted active:bg-buttons-primary-hover active:text-content-primary-inverted\",\n secondary:\n \"border-content-primary border bg-transparent text-content-primary hover:bg-brand-primary-muted active:bg-brand-primary-muted\",\n tertiary:\n \"bg-transparent text-content-primary hover:bg-brand-primary-muted active:bg-brand-primary-muted\",\n link: \"bg-transparent text-content-primary underline decoration-solid hover:bg-brand-primary-muted active:bg-brand-primary-muted\",\n brand:\n \"bg-buttons-brand text-content-on-brand hover:bg-buttons-brand-hover hover:text-content-on-brand active:bg-buttons-brand-hover active:text-content-on-brand\",\n destructive:\n \"bg-error-content text-content-on-brand-inverted hover:bg-brand-primary-muted hover:text-content-primary active:bg-brand-primary-muted active:text-content-primary\",\n white:\n \"bg-content-on-brand-inverted text-content-on-brand hover:bg-brand-primary-muted hover:text-content-primary active:bg-brand-primary-muted active:text-content-primary\",\n tertiaryDestructive:\n \"bg-transparent text-error-content hover:bg-error-surface active:bg-error-surface\",\n text: \"bg-transparent text-content-primary hover:underline active:underline\",\n};\n\n/** Recursively extract text content from React nodes for accessible labels */\nfunction getTextContent(node: React.ReactNode): string | undefined {\n if (typeof node === \"string\") return node;\n if (typeof node === \"number\") return String(node);\n if (React.isValidElement(node)) {\n return getTextContent((node.props as { children?: React.ReactNode }).children);\n }\n if (Array.isArray(node)) {\n const text = node.map(getTextContent).filter(Boolean).join(\"\");\n return text || undefined;\n }\n return undefined;\n}\n\nconst LoadingSpinner = ({ size }: { size: ButtonSize }) => {\n return (\n <span className=\"animate-spin\" aria-hidden=\"true\">\n <SpinnerIcon className={ICON_SIZE_CLASS[size]}>\n <title>Loading</title>\n </SpinnerIcon>\n </span>\n );\n};\n\nfunction renderContent({\n loading,\n asChild,\n children,\n size,\n leftIcon,\n rightIcon,\n iconSizeClass,\n discount,\n price,\n}: {\n loading: boolean;\n asChild: boolean;\n children: React.ReactNode;\n size: ButtonSize;\n leftIcon: React.ReactNode;\n rightIcon: React.ReactNode;\n iconSizeClass: string;\n discount?: string;\n price?: string;\n fullWidth?: boolean;\n}) {\n if (loading) {\n // When asChild, clone the child element with spinner content instead of\n // wrapping in sr-only span (which would nest interactive elements)\n if (asChild && React.isValidElement(children)) {\n return React.cloneElement(\n children as React.ReactElement<{ children?: React.ReactNode }>,\n undefined,\n <LoadingSpinner size={size} />,\n );\n }\n return (\n <>\n <LoadingSpinner size={size} />\n <span className=\"sr-only\">{children}</span>\n </>\n );\n }\n\n if (asChild) return children;\n\n return (\n <>\n {leftIcon && (\n <span\n className={cn(\"flex shrink-0 items-center justify-center\", iconSizeClass)}\n aria-hidden=\"true\"\n >\n {leftIcon}\n </span>\n )}\n {React.Children.map(children, (child) =>\n typeof child === \"string\" ? (\n child.trim() ? (\n <span className=\"min-w-0 truncate\">{child}</span>\n ) : null\n ) : typeof child === \"number\" ? (\n <span className=\"min-w-0 truncate\">{child}</span>\n ) : (\n child\n ),\n )}\n {rightIcon && (\n <span\n className={cn(\"flex shrink-0 items-center justify-center\", iconSizeClass)}\n aria-hidden=\"true\"\n >\n {rightIcon}\n </span>\n )}\n {(price || discount) && (\n <div>\n {discount && (\n <span className=\"typography-regular-body-lg line-through\" aria-hidden=\"true\">\n {discount}\n </span>\n )}\n {price && (\n <span className=\"ml-2\" aria-hidden=\"true\">\n {price}\n </span>\n )}\n </div>\n )}\n </>\n );\n}\n\n/**\n * A versatile button component with multiple visual variants, sizes, icon\n * slots, loading state, and optional pricing display.\n *\n * @example\n * ```tsx\n * <Button variant=\"brand\" size=\"40\" leftIcon={<StarIcon />}>\n * Subscribe\n * </Button>\n * ```\n */\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n variant = \"primary\",\n size = \"40\",\n leftIcon,\n rightIcon,\n loading = false,\n asChild = false,\n disabled,\n children,\n discount,\n price,\n fullWidth = false,\n ...props\n },\n ref,\n ) => {\n const Comp = asChild ? Slot : \"button\";\n const isDisabled = disabled || loading;\n const iconSizeClass = ICON_WRAPPER_CLASS[size];\n\n const buttonSpecificProps = !asChild\n ? {\n type: \"button\" as const,\n \"data-testid\": \"button\",\n disabled: isDisabled,\n }\n : isDisabled\n ? { \"aria-disabled\": true }\n : {};\n\n // When asChild + loading, extract text from children for aria-label since we\n // can't wrap element children in an sr-only span (creates invalid nested markup)\n const loadingLabelProps = loading && asChild ? { \"aria-label\": getTextContent(children) } : {};\n\n const content = renderContent({\n loading,\n asChild,\n children,\n size,\n leftIcon,\n rightIcon,\n iconSizeClass,\n discount,\n price,\n });\n\n return (\n <Comp\n ref={ref}\n {...buttonSpecificProps}\n aria-busy={loading}\n {...loadingLabelProps}\n className={cn(\n // Base styles\n \"inline-flex min-w-0 cursor-pointer items-center gap-2 whitespace-nowrap rounded-full transition-colors\",\n // Focus ring\n \"focus-visible:shadow-focus-ring focus-visible:outline-none\",\n // Disabled state\n \"disabled:pointer-events-none disabled:opacity-50\",\n \"aria-disabled:pointer-events-none aria-disabled:opacity-50\",\n `${price ? \"justify-between\" : \"justify-center\"}`,\n fullWidth && \"w-full\",\n // Size styles\n SIZE_CLASSES[size],\n // Variant styles\n VARIANT_CLASSES[variant],\n // Manual CSS overrides\n className,\n )}\n {...props}\n >\n {content}\n </Comp>\n );\n },\n);\n\nButton.displayName = \"Button\";\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Button.mjs","sources":["../../../src/components/Button/Button.tsx"],"sourcesContent":["import { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { SpinnerIcon } from \"../Icons/SpinnerIcon\";\n\n/** Visual style variant of the button. */\nexport type ButtonVariant =\n | \"primary\"\n | \"secondary\"\n | \"tertiary\"\n | \"link\"\n | \"brand\"\n | \"destructive\"\n | \"white\"\n | \"tertiaryDestructive\"\n | \"text\";\n\n/** Button height in pixels. */\nexport type ButtonSize = \"48\" | \"40\" | \"32\" | \"24\";\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Visual style variant of the button. @default \"primary\" */\n variant?: ButtonVariant;\n /** Height of the button in pixels. @default \"40\" */\n size?: ButtonSize;\n /** Icon element displayed before the label. */\n leftIcon?: React.ReactNode;\n /** Icon element displayed after the label. */\n rightIcon?: React.ReactNode;\n /** When `true`, replaces the label with a spinner and disables interaction. @default false */\n loading?: boolean;\n /** Merge props onto a child element instead of rendering a `<button>`. @default false */\n asChild?: boolean;\n /** Old price shown with a strikethrough before the current price. */\n discount?: string;\n /** Current price shown inside the button after the label and icons. */\n price?: string;\n /** When `true`, the button will take the full width of its container. @default false */\n fullWidth?: boolean;\n}\n\nconst SIZE_CLASSES: Record<ButtonSize, string> = {\n \"48\": \"h-12 px-4 py-3 typography-body-default-16px-semibold\",\n \"40\": \"h-10 px-4 py-2 typography-body-default-16px-semibold\",\n \"32\": \"h-8 px-3 py-2 typography-body-small-14px-semibold\",\n \"24\": \"h-6 px-2 py-1 typography-body-small-14px-semibold\",\n};\n\nconst ICON_SIZE_CLASS: Record<ButtonSize, string> = {\n \"48\": \"size-5\",\n \"40\": \"size-5\",\n \"32\": \"size-4\",\n \"24\": \"size-3.5\",\n};\n\n/** Targets only direct SVG children so non-icon content (e.g. Pill) can size naturally. */\nconst ICON_WRAPPER_CLASS: Record<ButtonSize, string> = {\n \"48\": \"[&>svg]:size-5\",\n \"40\": \"[&>svg]:size-5\",\n \"32\": \"[&>svg]:size-4\",\n \"24\": \"[&>svg]:size-3.5\",\n};\n\nconst VARIANT_CLASSES: Record<ButtonVariant, string> = {\n primary:\n \"bg-buttons-primary-default text-content-primary-inverted hover:bg-buttons-primary-hover hover:text-content-primary-inverted active:bg-buttons-primary-hover active:text-content-primary-inverted\",\n secondary:\n \"border-content-primary border bg-transparent text-content-primary hover:bg-brand-primary-muted active:bg-brand-primary-muted\",\n tertiary:\n \"bg-transparent text-content-primary hover:bg-brand-primary-muted active:bg-brand-primary-muted\",\n link: \"bg-transparent text-content-primary underline decoration-solid hover:bg-brand-primary-muted active:bg-brand-primary-muted\",\n brand:\n \"bg-buttons-brand-default text-content-always-black hover:bg-buttons-brand-hover hover:text-content-always-black active:bg-buttons-brand-hover active:text-content-always-black\",\n destructive:\n \"bg-error-content text-content-always-white hover:bg-brand-primary-muted hover:text-content-primary active:bg-brand-primary-muted active:text-content-primary\",\n white:\n \"bg-content-always-white text-content-always-black hover:bg-brand-primary-muted hover:text-content-primary active:bg-brand-primary-muted active:text-content-primary\",\n tertiaryDestructive:\n \"bg-transparent text-error-content hover:bg-error-surface active:bg-error-surface\",\n text: \"bg-transparent text-content-primary hover:underline active:underline\",\n};\n\n/** Recursively extract text content from React nodes for accessible labels */\nfunction getTextContent(node: React.ReactNode): string | undefined {\n if (typeof node === \"string\") return node;\n if (typeof node === \"number\") return String(node);\n if (React.isValidElement(node)) {\n return getTextContent((node.props as { children?: React.ReactNode }).children);\n }\n if (Array.isArray(node)) {\n const text = node.map(getTextContent).filter(Boolean).join(\"\");\n return text || undefined;\n }\n return undefined;\n}\n\nconst LoadingSpinner = ({ size }: { size: ButtonSize }) => {\n return (\n <span className=\"animate-spin\" aria-hidden=\"true\">\n <SpinnerIcon className={ICON_SIZE_CLASS[size]}>\n <title>Loading</title>\n </SpinnerIcon>\n </span>\n );\n};\n\nfunction renderContent({\n loading,\n asChild,\n children,\n size,\n leftIcon,\n rightIcon,\n iconSizeClass,\n discount,\n price,\n}: {\n loading: boolean;\n asChild: boolean;\n children: React.ReactNode;\n size: ButtonSize;\n leftIcon: React.ReactNode;\n rightIcon: React.ReactNode;\n iconSizeClass: string;\n discount?: string;\n price?: string;\n fullWidth?: boolean;\n}) {\n if (loading) {\n // When asChild, clone the child element with spinner content instead of\n // wrapping in sr-only span (which would nest interactive elements)\n if (asChild && React.isValidElement(children)) {\n return React.cloneElement(\n children as React.ReactElement<{ children?: React.ReactNode }>,\n undefined,\n <LoadingSpinner size={size} />,\n );\n }\n return (\n <>\n <LoadingSpinner size={size} />\n <span className=\"sr-only\">{children}</span>\n </>\n );\n }\n\n if (asChild) return children;\n\n return (\n <>\n {leftIcon && (\n <span\n className={cn(\"flex shrink-0 items-center justify-center\", iconSizeClass)}\n aria-hidden=\"true\"\n >\n {leftIcon}\n </span>\n )}\n {React.Children.map(children, (child) =>\n typeof child === \"string\" ? (\n child.trim() ? (\n <span className=\"min-w-0 truncate\">{child}</span>\n ) : null\n ) : typeof child === \"number\" ? (\n <span className=\"min-w-0 truncate\">{child}</span>\n ) : (\n child\n ),\n )}\n {rightIcon && (\n <span\n className={cn(\"flex shrink-0 items-center justify-center\", iconSizeClass)}\n aria-hidden=\"true\"\n >\n {rightIcon}\n </span>\n )}\n {(price || discount) && (\n <div>\n {discount && (\n <span className=\"typography-body-default-16px-regular line-through\" aria-hidden=\"true\">\n {discount}\n </span>\n )}\n {price && (\n <span className=\"ml-2\" aria-hidden=\"true\">\n {price}\n </span>\n )}\n </div>\n )}\n </>\n );\n}\n\n/**\n * A versatile button component with multiple visual variants, sizes, icon\n * slots, loading state, and optional pricing display.\n *\n * @example\n * ```tsx\n * <Button variant=\"brand\" size=\"40\" leftIcon={<StarIcon />}>\n * Subscribe\n * </Button>\n * ```\n */\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n variant = \"primary\",\n size = \"40\",\n leftIcon,\n rightIcon,\n loading = false,\n asChild = false,\n disabled,\n children,\n discount,\n price,\n fullWidth = false,\n ...props\n },\n ref,\n ) => {\n const Comp = asChild ? Slot : \"button\";\n const isDisabled = disabled || loading;\n const iconSizeClass = ICON_WRAPPER_CLASS[size];\n\n const buttonSpecificProps = !asChild\n ? {\n type: \"button\" as const,\n \"data-testid\": \"button\",\n disabled: isDisabled,\n }\n : isDisabled\n ? { \"aria-disabled\": true }\n : {};\n\n // When asChild + loading, extract text from children for aria-label since we\n // can't wrap element children in an sr-only span (creates invalid nested markup)\n const loadingLabelProps = loading && asChild ? { \"aria-label\": getTextContent(children) } : {};\n\n const content = renderContent({\n loading,\n asChild,\n children,\n size,\n leftIcon,\n rightIcon,\n iconSizeClass,\n discount,\n price,\n });\n\n return (\n <Comp\n ref={ref}\n {...buttonSpecificProps}\n aria-busy={loading}\n {...loadingLabelProps}\n className={cn(\n // Base styles\n \"inline-flex min-w-0 cursor-pointer items-center gap-2 whitespace-nowrap rounded-full transition-colors\",\n // Focus ring\n \"focus-visible:shadow-focus-ring focus-visible:outline-none\",\n // Disabled state\n \"disabled:pointer-events-none disabled:opacity-50\",\n \"aria-disabled:pointer-events-none aria-disabled:opacity-50\",\n `${price ? \"justify-between\" : \"justify-center\"}`,\n fullWidth && \"w-full\",\n // Size styles\n SIZE_CLASSES[size],\n // Variant styles\n VARIANT_CLASSES[variant],\n // Manual CSS overrides\n className,\n )}\n {...props}\n >\n {content}\n </Comp>\n );\n },\n);\n\nButton.displayName = \"Button\";\n"],"names":[],"mappings":"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"}
@@ -43,7 +43,7 @@ const CardTitle = React.forwardRef(
43
43
  "h3",
44
44
  {
45
45
  ref,
46
- className: cn("typography-semibold-body-lg text-content-primary", className),
46
+ className: cn("typography-body-default-16px-semibold text-content-primary", className),
47
47
  ...props,
48
48
  children
49
49
  }
@@ -57,7 +57,7 @@ const CardDescription = React.forwardRef(
57
57
  "p",
58
58
  {
59
59
  ref,
60
- className: cn("typography-regular-body-sm text-content-secondary", className),
60
+ className: cn("typography-description-12px-regular text-content-secondary", className),
61
61
  ...props,
62
62
  children
63
63
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Card.mjs","sources":["../../../src/components/Card/Card.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Visual style variant of the card. */\nexport type CardVariant = \"outlined\" | \"elevated\" | \"filled\" | \"ghost\";\n\nexport interface CardProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Visual style variant of the card. @default \"outlined\" */\n variant?: CardVariant;\n /** When `true`, the card will take the full width of its container. @default true */\n fullWidth?: boolean;\n /** When `true`, removes all internal padding. @default false */\n noPadding?: boolean;\n}\n\nexport interface CardHeaderProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Icon element displayed at the trailing end of the header. */\n action?: React.ReactNode;\n}\n\nexport interface CardTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {}\n\nexport interface CardDescriptionProps extends React.HTMLAttributes<HTMLParagraphElement> {}\n\nexport interface CardContentProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport interface CardFooterProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nconst VARIANT_CLASSES: Record<CardVariant, string> = {\n outlined: \"border border-neutral-alphas-200 bg-surface-primary shadow-sm\",\n elevated: \"border border-neutral-alphas-200 bg-surface-primary shadow-md\",\n filled: \"bg-surface-secondary\",\n ghost: \"bg-transparent\",\n};\n\n/**\n * A composable card component with multiple visual variants. Use with\n * {@link CardHeader}, {@link CardTitle}, {@link CardDescription},\n * {@link CardContent}, and {@link CardFooter} for structured layouts.\n *\n * @example\n * ```tsx\n * <Card variant=\"outlined\">\n * <CardHeader action={<HomeIcon className=\"size-5\" />}>\n * <CardTitle>Card title</CardTitle>\n * <CardDescription>Card description text</CardDescription>\n * </CardHeader>\n * <CardContent>Content goes here</CardContent>\n * <CardFooter>\n * <Button variant=\"secondary\">Label</Button>\n * <Button variant=\"primary\">Label</Button>\n * </CardFooter>\n * </Card>\n * ```\n */\nexport const Card = React.forwardRef<HTMLDivElement, CardProps>(\n (\n { className, variant = \"outlined\", fullWidth = true, noPadding = false, children, ...props },\n ref,\n ) => {\n return (\n <div\n ref={ref}\n className={cn(\n \"flex flex-col overflow-hidden rounded-md\",\n !noPadding && \"p-4\",\n fullWidth && \"w-full\",\n VARIANT_CLASSES[variant],\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n },\n);\nCard.displayName = \"Card\";\n\n/**\n * Header section of a {@link Card}. Renders a flex row with text content\n * on the left and an optional trailing action element (e.g. icon) on the right.\n */\nexport const CardHeader = React.forwardRef<HTMLDivElement, CardHeaderProps>(\n ({ className, action, children, ...props }, ref) => {\n return (\n <div ref={ref} className={cn(\"flex items-start gap-3\", className)} {...props}>\n <div className=\"min-w-0 flex-1\">{children}</div>\n {action && <div className=\"shrink-0\">{action}</div>}\n </div>\n );\n },\n);\nCardHeader.displayName = \"CardHeader\";\n\n/** Title element rendered inside a {@link CardHeader}. */\nexport const CardTitle = React.forwardRef<HTMLHeadingElement, CardTitleProps>(\n ({ className, children, ...props }, ref) => {\n return (\n <h3\n ref={ref}\n className={cn(\"typography-semibold-body-lg text-content-primary\", className)}\n {...props}\n >\n {children}\n </h3>\n );\n },\n);\nCardTitle.displayName = \"CardTitle\";\n\n/** Description text rendered below the {@link CardTitle} inside a {@link CardHeader}. */\nexport const CardDescription = React.forwardRef<HTMLParagraphElement, CardDescriptionProps>(\n ({ className, children, ...props }, ref) => {\n return (\n <p\n ref={ref}\n className={cn(\"typography-regular-body-sm text-content-secondary\", className)}\n {...props}\n >\n {children}\n </p>\n );\n },\n);\nCardDescription.displayName = \"CardDescription\";\n\n/** Flexible content area of a {@link Card}. Adds vertical padding between header and footer. */\nexport const CardContent = React.forwardRef<HTMLDivElement, CardContentProps>(\n ({ className, children, ...props }, ref) => {\n return (\n <div ref={ref} className={cn(\"flex-1 py-4\", className)} {...props}>\n {children}\n </div>\n );\n },\n);\nCardContent.displayName = \"CardContent\";\n\n/** Footer section of a {@link Card}. Renders children in a horizontal row with a gap. */\nexport const CardFooter = React.forwardRef<HTMLDivElement, CardFooterProps>(\n ({ className, children, ...props }, ref) => {\n return (\n <div ref={ref} className={cn(\"flex items-center gap-3\", className)} {...props}>\n {children}\n </div>\n );\n },\n);\nCardFooter.displayName = \"CardFooter\";\n"],"names":[],"mappings":";;;;AA4BA,MAAM,kBAA+C;AAAA,EACnD,UAAU;AAAA,EACV,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,OAAO;AACT;AAsBO,MAAM,OAAO,MAAM;AAAA,EACxB,CACE,EAAE,WAAW,UAAU,YAAY,YAAY,MAAM,YAAY,OAAO,UAAU,GAAG,MAAA,GACrF,QACG;AACH,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW;AAAA,UACT;AAAA,UACA,CAAC,aAAa;AAAA,UACd,aAAa;AAAA,UACb,gBAAgB,OAAO;AAAA,UACvB;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AACA,KAAK,cAAc;AAMZ,MAAM,aAAa,MAAM;AAAA,EAC9B,CAAC,EAAE,WAAW,QAAQ,UAAU,GAAG,MAAA,GAAS,QAAQ;AAClD,WACE,qBAAC,SAAI,KAAU,WAAW,GAAG,0BAA0B,SAAS,GAAI,GAAG,OACrE,UAAA;AAAA,MAAA,oBAAC,OAAA,EAAI,WAAU,kBAAkB,SAAA,CAAS;AAAA,MACzC,UAAU,oBAAC,OAAA,EAAI,WAAU,YAAY,UAAA,OAAA,CAAO;AAAA,IAAA,GAC/C;AAAA,EAEJ;AACF;AACA,WAAW,cAAc;AAGlB,MAAM,YAAY,MAAM;AAAA,EAC7B,CAAC,EAAE,WAAW,UAAU,GAAG,MAAA,GAAS,QAAQ;AAC1C,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW,GAAG,oDAAoD,SAAS;AAAA,QAC1E,GAAG;AAAA,QAEH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AACA,UAAU,cAAc;AAGjB,MAAM,kBAAkB,MAAM;AAAA,EACnC,CAAC,EAAE,WAAW,UAAU,GAAG,MAAA,GAAS,QAAQ;AAC1C,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW,GAAG,qDAAqD,SAAS;AAAA,QAC3E,GAAG;AAAA,QAEH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AACA,gBAAgB,cAAc;AAGvB,MAAM,cAAc,MAAM;AAAA,EAC/B,CAAC,EAAE,WAAW,UAAU,GAAG,MAAA,GAAS,QAAQ;AAC1C,WACE,oBAAC,OAAA,EAAI,KAAU,WAAW,GAAG,eAAe,SAAS,GAAI,GAAG,OACzD,SAAA,CACH;AAAA,EAEJ;AACF;AACA,YAAY,cAAc;AAGnB,MAAM,aAAa,MAAM;AAAA,EAC9B,CAAC,EAAE,WAAW,UAAU,GAAG,MAAA,GAAS,QAAQ;AAC1C,WACE,oBAAC,OAAA,EAAI,KAAU,WAAW,GAAG,2BAA2B,SAAS,GAAI,GAAG,OACrE,SAAA,CACH;AAAA,EAEJ;AACF;AACA,WAAW,cAAc;"}
1
+ {"version":3,"file":"Card.mjs","sources":["../../../src/components/Card/Card.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Visual style variant of the card. */\nexport type CardVariant = \"outlined\" | \"elevated\" | \"filled\" | \"ghost\";\n\nexport interface CardProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Visual style variant of the card. @default \"outlined\" */\n variant?: CardVariant;\n /** When `true`, the card will take the full width of its container. @default true */\n fullWidth?: boolean;\n /** When `true`, removes all internal padding. @default false */\n noPadding?: boolean;\n}\n\nexport interface CardHeaderProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Icon element displayed at the trailing end of the header. */\n action?: React.ReactNode;\n}\n\nexport interface CardTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {}\n\nexport interface CardDescriptionProps extends React.HTMLAttributes<HTMLParagraphElement> {}\n\nexport interface CardContentProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport interface CardFooterProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nconst VARIANT_CLASSES: Record<CardVariant, string> = {\n outlined: \"border border-neutral-alphas-200 bg-surface-primary shadow-sm\",\n elevated: \"border border-neutral-alphas-200 bg-surface-primary shadow-md\",\n filled: \"bg-surface-secondary\",\n ghost: \"bg-transparent\",\n};\n\n/**\n * A composable card component with multiple visual variants. Use with\n * {@link CardHeader}, {@link CardTitle}, {@link CardDescription},\n * {@link CardContent}, and {@link CardFooter} for structured layouts.\n *\n * @example\n * ```tsx\n * <Card variant=\"outlined\">\n * <CardHeader action={<HomeIcon className=\"size-5\" />}>\n * <CardTitle>Card title</CardTitle>\n * <CardDescription>Card description text</CardDescription>\n * </CardHeader>\n * <CardContent>Content goes here</CardContent>\n * <CardFooter>\n * <Button variant=\"secondary\">Label</Button>\n * <Button variant=\"primary\">Label</Button>\n * </CardFooter>\n * </Card>\n * ```\n */\nexport const Card = React.forwardRef<HTMLDivElement, CardProps>(\n (\n { className, variant = \"outlined\", fullWidth = true, noPadding = false, children, ...props },\n ref,\n ) => {\n return (\n <div\n ref={ref}\n className={cn(\n \"flex flex-col overflow-hidden rounded-md\",\n !noPadding && \"p-4\",\n fullWidth && \"w-full\",\n VARIANT_CLASSES[variant],\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n },\n);\nCard.displayName = \"Card\";\n\n/**\n * Header section of a {@link Card}. Renders a flex row with text content\n * on the left and an optional trailing action element (e.g. icon) on the right.\n */\nexport const CardHeader = React.forwardRef<HTMLDivElement, CardHeaderProps>(\n ({ className, action, children, ...props }, ref) => {\n return (\n <div ref={ref} className={cn(\"flex items-start gap-3\", className)} {...props}>\n <div className=\"min-w-0 flex-1\">{children}</div>\n {action && <div className=\"shrink-0\">{action}</div>}\n </div>\n );\n },\n);\nCardHeader.displayName = \"CardHeader\";\n\n/** Title element rendered inside a {@link CardHeader}. */\nexport const CardTitle = React.forwardRef<HTMLHeadingElement, CardTitleProps>(\n ({ className, children, ...props }, ref) => {\n return (\n <h3\n ref={ref}\n className={cn(\"typography-body-default-16px-semibold text-content-primary\", className)}\n {...props}\n >\n {children}\n </h3>\n );\n },\n);\nCardTitle.displayName = \"CardTitle\";\n\n/** Description text rendered below the {@link CardTitle} inside a {@link CardHeader}. */\nexport const CardDescription = React.forwardRef<HTMLParagraphElement, CardDescriptionProps>(\n ({ className, children, ...props }, ref) => {\n return (\n <p\n ref={ref}\n className={cn(\"typography-description-12px-regular text-content-secondary\", className)}\n {...props}\n >\n {children}\n </p>\n );\n },\n);\nCardDescription.displayName = \"CardDescription\";\n\n/** Flexible content area of a {@link Card}. Adds vertical padding between header and footer. */\nexport const CardContent = React.forwardRef<HTMLDivElement, CardContentProps>(\n ({ className, children, ...props }, ref) => {\n return (\n <div ref={ref} className={cn(\"flex-1 py-4\", className)} {...props}>\n {children}\n </div>\n );\n },\n);\nCardContent.displayName = \"CardContent\";\n\n/** Footer section of a {@link Card}. Renders children in a horizontal row with a gap. */\nexport const CardFooter = React.forwardRef<HTMLDivElement, CardFooterProps>(\n ({ className, children, ...props }, ref) => {\n return (\n <div ref={ref} className={cn(\"flex items-center gap-3\", className)} {...props}>\n {children}\n </div>\n );\n },\n);\nCardFooter.displayName = \"CardFooter\";\n"],"names":[],"mappings":";;;;AA4BA,MAAM,kBAA+C;AAAA,EACnD,UAAU;AAAA,EACV,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,OAAO;AACT;AAsBO,MAAM,OAAO,MAAM;AAAA,EACxB,CACE,EAAE,WAAW,UAAU,YAAY,YAAY,MAAM,YAAY,OAAO,UAAU,GAAG,MAAA,GACrF,QACG;AACH,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW;AAAA,UACT;AAAA,UACA,CAAC,aAAa;AAAA,UACd,aAAa;AAAA,UACb,gBAAgB,OAAO;AAAA,UACvB;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AACA,KAAK,cAAc;AAMZ,MAAM,aAAa,MAAM;AAAA,EAC9B,CAAC,EAAE,WAAW,QAAQ,UAAU,GAAG,MAAA,GAAS,QAAQ;AAClD,WACE,qBAAC,SAAI,KAAU,WAAW,GAAG,0BAA0B,SAAS,GAAI,GAAG,OACrE,UAAA;AAAA,MAAA,oBAAC,OAAA,EAAI,WAAU,kBAAkB,SAAA,CAAS;AAAA,MACzC,UAAU,oBAAC,OAAA,EAAI,WAAU,YAAY,UAAA,OAAA,CAAO;AAAA,IAAA,GAC/C;AAAA,EAEJ;AACF;AACA,WAAW,cAAc;AAGlB,MAAM,YAAY,MAAM;AAAA,EAC7B,CAAC,EAAE,WAAW,UAAU,GAAG,MAAA,GAAS,QAAQ;AAC1C,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW,GAAG,8DAA8D,SAAS;AAAA,QACpF,GAAG;AAAA,QAEH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AACA,UAAU,cAAc;AAGjB,MAAM,kBAAkB,MAAM;AAAA,EACnC,CAAC,EAAE,WAAW,UAAU,GAAG,MAAA,GAAS,QAAQ;AAC1C,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW,GAAG,8DAA8D,SAAS;AAAA,QACpF,GAAG;AAAA,QAEH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AACA,gBAAgB,cAAc;AAGvB,MAAM,cAAc,MAAM;AAAA,EAC/B,CAAC,EAAE,WAAW,UAAU,GAAG,MAAA,GAAS,QAAQ;AAC1C,WACE,oBAAC,OAAA,EAAI,KAAU,WAAW,GAAG,eAAe,SAAS,GAAI,GAAG,OACzD,SAAA,CACH;AAAA,EAEJ;AACF;AACA,YAAY,cAAc;AAGnB,MAAM,aAAa,MAAM;AAAA,EAC9B,CAAC,EAAE,WAAW,UAAU,GAAG,MAAA,GAAS,QAAQ;AAC1C,WACE,oBAAC,OAAA,EAAI,KAAU,WAAW,GAAG,2BAA2B,SAAS,GAAI,GAAG,OACrE,SAAA,CACH;AAAA,EAEJ;AACF;AACA,WAAW,cAAc;"}
@@ -31,7 +31,7 @@ const ChartCard = React.forwardRef(
31
31
  /* @__PURE__ */ jsx(Skeleton, { animation: "wave", variant: "rounded", className: "h-3 w-24" })
32
32
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
33
33
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
34
- /* @__PURE__ */ jsx("span", { className: "typography-semibold-body-md text-content-primary", children: title }),
34
+ /* @__PURE__ */ jsx("span", { className: "typography-body-small-14px-semibold text-content-primary", children: title }),
35
35
  tooltip && /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
36
36
  /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
37
37
  IconButton,
@@ -46,19 +46,19 @@ const ChartCard = React.forwardRef(
46
46
  ] }) })
47
47
  ] }),
48
48
  subtitle && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
49
- /* @__PURE__ */ jsx("span", { className: "typography-bold-heading-sm text-content-primary", children: subtitle }),
49
+ /* @__PURE__ */ jsx("span", { className: "typography-header-heading-sm text-content-primary", children: subtitle }),
50
50
  trendChip && /* @__PURE__ */ jsx(
51
51
  "span",
52
52
  {
53
53
  className: cn(
54
- "typography-semibold-body-sm rounded-full px-2 py-0.5",
54
+ "typography-description-12px-semibold rounded-full px-2 py-0.5",
55
55
  TREND_CLASSES[trendChip.trend]
56
56
  ),
57
57
  children: trendChip.label
58
58
  }
59
59
  )
60
60
  ] }),
61
- dateInfo && /* @__PURE__ */ jsx("span", { className: "typography-regular-body-sm text-content-tertiary", children: dateInfo })
61
+ dateInfo && /* @__PURE__ */ jsx("span", { className: "typography-description-12px-regular text-content-tertiary", children: dateInfo })
62
62
  ] }),
63
63
  /* @__PURE__ */ jsx("div", { className: "mt-auto", children })
64
64
  ] }) });
@@ -1 +1 @@
1
- {"version":3,"file":"ChartCard.mjs","sources":["../../../src/components/Chart/ChartCard.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Card } from \"../Card/Card\";\nimport { IconButton } from \"../IconButton/IconButton\";\nimport { InfoCircleIcon } from \"../Icons/InfoCircleIcon\";\nimport { Skeleton } from \"../Skeleton/Skeleton\";\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from \"../Tooltip/Tooltip\";\n\n/** Props for {@link ChartCard}. */\nexport interface ChartCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"title\"> {\n /** Card title text. Pass translated string for i18n. */\n title: React.ReactNode;\n /** Large subtitle value (e.g. formatted price or count). */\n subtitle?: React.ReactNode;\n /** Tooltip text shown next to the title. Pass translated string for i18n. */\n tooltip?: React.ReactNode;\n /** Accessible label for the info tooltip trigger. Override for i18n. @default \"More info\" */\n tooltipAriaLabel?: string;\n /** Date range or period label shown below the subtitle. */\n dateInfo?: React.ReactNode;\n /** Trend indicator chip config. */\n trendChip?: {\n /** Display label (e.g. \"12.5%\"). */\n label: React.ReactNode;\n /** Whether the trend is positive (green) or negative (red). */\n trend: \"positive\" | \"negative\";\n };\n /** Show loading skeleton instead of content. @default false */\n loading?: boolean;\n /** Chart content rendered below the header. */\n children?: React.ReactNode;\n}\n\nconst TREND_CLASSES: Record<\"positive\" | \"negative\", string> = {\n positive: \"bg-success-surface text-success-content\",\n negative: \"bg-error-surface text-error-content\",\n};\n\n/**\n * Wraps any chart with a structured header containing title, subtitle,\n * optional trend chip, date range label, info tooltip, and a loading\n * skeleton state.\n *\n * @example\n * ```tsx\n * <ChartCard\n * title=\"Revenue\"\n * subtitle=\"$4,523\"\n * trendChip={{ label: \"+12.5%\", trend: \"positive\" }}\n * dateInfo=\"Jan 1 – Mar 17\"\n * tooltip=\"Total revenue for the selected period.\"\n * >\n * <MyLineChart />\n * </ChartCard>\n * ```\n */\nexport const ChartCard = React.forwardRef<HTMLDivElement, ChartCardProps>(\n (\n {\n className,\n title,\n subtitle,\n tooltip,\n tooltipAriaLabel = \"More info\",\n dateInfo,\n trendChip,\n loading = false,\n children,\n ...props\n },\n ref,\n ) => {\n return (\n <Card ref={ref} variant=\"outlined\" noPadding className={className} {...props}>\n <div className=\"flex flex-col gap-2 p-4\">\n {loading ? (\n <>\n <Skeleton animation=\"wave\" variant=\"rounded\" className=\"h-4 w-32\" />\n <Skeleton animation=\"wave\" variant=\"rounded\" className=\"h-7 w-44\" />\n <Skeleton animation=\"wave\" variant=\"rounded\" className=\"h-3 w-24\" />\n </>\n ) : (\n <>\n <div className=\"flex items-center gap-1.5\">\n <span className=\"typography-semibold-body-md text-content-primary\">{title}</span>\n {tooltip && (\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n <IconButton\n variant=\"tertiary\"\n size=\"24\"\n aria-label={tooltipAriaLabel}\n icon={<InfoCircleIcon className=\"size-4 text-content-tertiary\" />}\n />\n </TooltipTrigger>\n <TooltipContent>{tooltip}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n )}\n </div>\n {subtitle && (\n <div className=\"flex items-center gap-2\">\n <span className=\"typography-bold-heading-sm text-content-primary\">\n {subtitle}\n </span>\n {trendChip && (\n <span\n className={cn(\n \"typography-semibold-body-sm rounded-full px-2 py-0.5\",\n TREND_CLASSES[trendChip.trend],\n )}\n >\n {trendChip.label}\n </span>\n )}\n </div>\n )}\n {dateInfo && (\n <span className=\"typography-regular-body-sm text-content-tertiary\">{dateInfo}</span>\n )}\n </>\n )}\n <div className=\"mt-auto\">{children}</div>\n </div>\n </Card>\n );\n },\n);\nChartCard.displayName = \"ChartCard\";\n"],"names":[],"mappings":";;;;;;;;;AAiCA,MAAM,gBAAyD;AAAA,EAC7D,UAAU;AAAA,EACV,UAAU;AACZ;AAoBO,MAAM,YAAY,MAAM;AAAA,EAC7B,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,mBAAmB;AAAA,IACnB;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,WACE,oBAAC,MAAA,EAAK,KAAU,SAAQ,YAAW,WAAS,MAAC,WAAuB,GAAG,OACrE,UAAA,qBAAC,OAAA,EAAI,WAAU,2BACZ,UAAA;AAAA,MAAA,UACC,qBAAA,UAAA,EACE,UAAA;AAAA,QAAA,oBAAC,YAAS,WAAU,QAAO,SAAQ,WAAU,WAAU,YAAW;AAAA,4BACjE,UAAA,EAAS,WAAU,QAAO,SAAQ,WAAU,WAAU,YAAW;AAAA,4BACjE,UAAA,EAAS,WAAU,QAAO,SAAQ,WAAU,WAAU,WAAA,CAAW;AAAA,MAAA,EAAA,CACpE,IAEA,qBAAA,UAAA,EACE,UAAA;AAAA,QAAA,qBAAC,OAAA,EAAI,WAAU,6BACb,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAK,WAAU,oDAAoD,UAAA,OAAM;AAAA,UACzE,WACC,oBAAC,iBAAA,EACC,UAAA,qBAAC,SAAA,EACC,UAAA;AAAA,YAAA,oBAAC,gBAAA,EAAe,SAAO,MACrB,UAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,SAAQ;AAAA,gBACR,MAAK;AAAA,gBACL,cAAY;AAAA,gBACZ,MAAM,oBAAC,gBAAA,EAAe,WAAU,+BAAA,CAA+B;AAAA,cAAA;AAAA,YAAA,GAEnE;AAAA,YACA,oBAAC,kBAAgB,UAAA,QAAA,CAAQ;AAAA,UAAA,EAAA,CAC3B,EAAA,CACF;AAAA,QAAA,GAEJ;AAAA,QACC,YACC,qBAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAK,WAAU,mDACb,UAAA,UACH;AAAA,UACC,aACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAW;AAAA,gBACT;AAAA,gBACA,cAAc,UAAU,KAAK;AAAA,cAAA;AAAA,cAG9B,UAAA,UAAU;AAAA,YAAA;AAAA,UAAA;AAAA,QACb,GAEJ;AAAA,QAED,YACC,oBAAC,QAAA,EAAK,WAAU,oDAAoD,UAAA,SAAA,CAAS;AAAA,MAAA,GAEjF;AAAA,MAEF,oBAAC,OAAA,EAAI,WAAU,WAAW,SAAA,CAAS;AAAA,IAAA,EAAA,CACrC,EAAA,CACF;AAAA,EAEJ;AACF;AACA,UAAU,cAAc;"}
1
+ {"version":3,"file":"ChartCard.mjs","sources":["../../../src/components/Chart/ChartCard.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Card } from \"../Card/Card\";\nimport { IconButton } from \"../IconButton/IconButton\";\nimport { InfoCircleIcon } from \"../Icons/InfoCircleIcon\";\nimport { Skeleton } from \"../Skeleton/Skeleton\";\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from \"../Tooltip/Tooltip\";\n\n/** Props for {@link ChartCard}. */\nexport interface ChartCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"title\"> {\n /** Card title text. Pass translated string for i18n. */\n title: React.ReactNode;\n /** Large subtitle value (e.g. formatted price or count). */\n subtitle?: React.ReactNode;\n /** Tooltip text shown next to the title. Pass translated string for i18n. */\n tooltip?: React.ReactNode;\n /** Accessible label for the info tooltip trigger. Override for i18n. @default \"More info\" */\n tooltipAriaLabel?: string;\n /** Date range or period label shown below the subtitle. */\n dateInfo?: React.ReactNode;\n /** Trend indicator chip config. */\n trendChip?: {\n /** Display label (e.g. \"12.5%\"). */\n label: React.ReactNode;\n /** Whether the trend is positive (green) or negative (red). */\n trend: \"positive\" | \"negative\";\n };\n /** Show loading skeleton instead of content. @default false */\n loading?: boolean;\n /** Chart content rendered below the header. */\n children?: React.ReactNode;\n}\n\nconst TREND_CLASSES: Record<\"positive\" | \"negative\", string> = {\n positive: \"bg-success-surface text-success-content\",\n negative: \"bg-error-surface text-error-content\",\n};\n\n/**\n * Wraps any chart with a structured header containing title, subtitle,\n * optional trend chip, date range label, info tooltip, and a loading\n * skeleton state.\n *\n * @example\n * ```tsx\n * <ChartCard\n * title=\"Revenue\"\n * subtitle=\"$4,523\"\n * trendChip={{ label: \"+12.5%\", trend: \"positive\" }}\n * dateInfo=\"Jan 1 – Mar 17\"\n * tooltip=\"Total revenue for the selected period.\"\n * >\n * <MyLineChart />\n * </ChartCard>\n * ```\n */\nexport const ChartCard = React.forwardRef<HTMLDivElement, ChartCardProps>(\n (\n {\n className,\n title,\n subtitle,\n tooltip,\n tooltipAriaLabel = \"More info\",\n dateInfo,\n trendChip,\n loading = false,\n children,\n ...props\n },\n ref,\n ) => {\n return (\n <Card ref={ref} variant=\"outlined\" noPadding className={className} {...props}>\n <div className=\"flex flex-col gap-2 p-4\">\n {loading ? (\n <>\n <Skeleton animation=\"wave\" variant=\"rounded\" className=\"h-4 w-32\" />\n <Skeleton animation=\"wave\" variant=\"rounded\" className=\"h-7 w-44\" />\n <Skeleton animation=\"wave\" variant=\"rounded\" className=\"h-3 w-24\" />\n </>\n ) : (\n <>\n <div className=\"flex items-center gap-1.5\">\n <span className=\"typography-body-small-14px-semibold text-content-primary\">\n {title}\n </span>\n {tooltip && (\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n <IconButton\n variant=\"tertiary\"\n size=\"24\"\n aria-label={tooltipAriaLabel}\n icon={<InfoCircleIcon className=\"size-4 text-content-tertiary\" />}\n />\n </TooltipTrigger>\n <TooltipContent>{tooltip}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n )}\n </div>\n {subtitle && (\n <div className=\"flex items-center gap-2\">\n <span className=\"typography-header-heading-sm text-content-primary\">\n {subtitle}\n </span>\n {trendChip && (\n <span\n className={cn(\n \"typography-description-12px-semibold rounded-full px-2 py-0.5\",\n TREND_CLASSES[trendChip.trend],\n )}\n >\n {trendChip.label}\n </span>\n )}\n </div>\n )}\n {dateInfo && (\n <span className=\"typography-description-12px-regular text-content-tertiary\">\n {dateInfo}\n </span>\n )}\n </>\n )}\n <div className=\"mt-auto\">{children}</div>\n </div>\n </Card>\n );\n },\n);\nChartCard.displayName = \"ChartCard\";\n"],"names":[],"mappings":";;;;;;;;;AAiCA,MAAM,gBAAyD;AAAA,EAC7D,UAAU;AAAA,EACV,UAAU;AACZ;AAoBO,MAAM,YAAY,MAAM;AAAA,EAC7B,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,mBAAmB;AAAA,IACnB;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,WACE,oBAAC,MAAA,EAAK,KAAU,SAAQ,YAAW,WAAS,MAAC,WAAuB,GAAG,OACrE,UAAA,qBAAC,OAAA,EAAI,WAAU,2BACZ,UAAA;AAAA,MAAA,UACC,qBAAA,UAAA,EACE,UAAA;AAAA,QAAA,oBAAC,YAAS,WAAU,QAAO,SAAQ,WAAU,WAAU,YAAW;AAAA,4BACjE,UAAA,EAAS,WAAU,QAAO,SAAQ,WAAU,WAAU,YAAW;AAAA,4BACjE,UAAA,EAAS,WAAU,QAAO,SAAQ,WAAU,WAAU,WAAA,CAAW;AAAA,MAAA,EAAA,CACpE,IAEA,qBAAA,UAAA,EACE,UAAA;AAAA,QAAA,qBAAC,OAAA,EAAI,WAAU,6BACb,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAK,WAAU,4DACb,UAAA,OACH;AAAA,UACC,WACC,oBAAC,iBAAA,EACC,UAAA,qBAAC,SAAA,EACC,UAAA;AAAA,YAAA,oBAAC,gBAAA,EAAe,SAAO,MACrB,UAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,SAAQ;AAAA,gBACR,MAAK;AAAA,gBACL,cAAY;AAAA,gBACZ,MAAM,oBAAC,gBAAA,EAAe,WAAU,+BAAA,CAA+B;AAAA,cAAA;AAAA,YAAA,GAEnE;AAAA,YACA,oBAAC,kBAAgB,UAAA,QAAA,CAAQ;AAAA,UAAA,EAAA,CAC3B,EAAA,CACF;AAAA,QAAA,GAEJ;AAAA,QACC,YACC,qBAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAK,WAAU,qDACb,UAAA,UACH;AAAA,UACC,aACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAW;AAAA,gBACT;AAAA,gBACA,cAAc,UAAU,KAAK;AAAA,cAAA;AAAA,cAG9B,UAAA,UAAU;AAAA,YAAA;AAAA,UAAA;AAAA,QACb,GAEJ;AAAA,QAED,YACC,oBAAC,QAAA,EAAK,WAAU,6DACb,UAAA,SAAA,CACH;AAAA,MAAA,GAEJ;AAAA,MAEF,oBAAC,OAAA,EAAI,WAAU,WAAW,SAAA,CAAS;AAAA,IAAA,EAAA,CACrC,EAAA,CACF;AAAA,EAEJ;AACF;AACA,UAAU,cAAc;"}
@@ -14,8 +14,8 @@ const ChartPieLegend = React.forwardRef(
14
14
  style: { backgroundColor: item.color }
15
15
  }
16
16
  ),
17
- /* @__PURE__ */ jsx("span", { className: "typography-regular-body-sm min-w-0 flex-1 truncate text-content-secondary", children: item.label }),
18
- /* @__PURE__ */ jsx("span", { className: "typography-semibold-body-md text-content-primary tabular-nums", children: item.formattedValue ?? item.value.toLocaleString() })
17
+ /* @__PURE__ */ jsx("span", { className: "typography-description-12px-regular min-w-0 flex-1 truncate text-content-secondary", children: item.label }),
18
+ /* @__PURE__ */ jsx("span", { className: "typography-body-small-14px-semibold text-content-primary tabular-nums", children: item.formattedValue ?? item.value.toLocaleString() })
19
19
  ] }),
20
20
  /* @__PURE__ */ jsx(
21
21
  "div",
@@ -1 +1 @@
1
- {"version":3,"file":"ChartPieLegend.mjs","sources":["../../../src/components/Chart/ChartPieLegend.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** A single item in a {@link ChartPieLegend}. */\nexport interface ChartPieLegendItem {\n /** Display label. Pass translated string for i18n. */\n label: React.ReactNode;\n /** Numeric value for this slice. Used to calculate the proportional bar width. */\n value: number;\n /** Formatted display value (e.g. \"$4,500\"). If omitted, `value.toLocaleString()` is used. */\n formattedValue?: React.ReactNode;\n /** Slice color (CSS value). */\n color: string;\n /** Optional icon to show instead of the color dot. */\n icon?: React.ReactNode;\n}\n\n/** Props for {@link ChartPieLegend}. */\nexport interface ChartPieLegendProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Legend items to display. */\n items: ChartPieLegendItem[];\n}\n\n/**\n * A side legend for pie/donut charts that shows each slice's label,\n * formatted value, and a proportional progress bar.\n *\n * @example\n * ```tsx\n * <ChartPieLegend\n * items={[\n * { label: \"Subscriptions\", value: 4500, formattedValue: \"$4,500\", color: \"var(--color-special-chart-teal)\" },\n * { label: \"Messages\", value: 2100, formattedValue: \"$2,100\", color: \"var(--color-special-chart-sky)\" },\n * { label: \"Tips\", value: 1200, formattedValue: \"$1,200\", color: \"var(--color-special-chart-orange)\" },\n * ]}\n * />\n * ```\n */\nexport const ChartPieLegend = React.forwardRef<HTMLDivElement, ChartPieLegendProps>(\n ({ items, className, ...props }, ref) => {\n const total = items.reduce((sum, item) => sum + item.value, 0);\n\n return (\n <div ref={ref} className={cn(\"flex flex-col gap-3\", className)} {...props}>\n {items.map((item) => (\n <div key={`${item.color}-${item.value}`} className=\"flex flex-col gap-1.5\">\n <div className=\"flex items-center gap-2\">\n {item.icon ?? (\n <span\n className=\"size-2 shrink-0 rounded-full\"\n style={{ backgroundColor: item.color }}\n />\n )}\n <span className=\"typography-regular-body-sm min-w-0 flex-1 truncate text-content-secondary\">\n {item.label}\n </span>\n <span className=\"typography-semibold-body-md text-content-primary tabular-nums\">\n {item.formattedValue ?? item.value.toLocaleString()}\n </span>\n </div>\n <div\n className=\"h-1.5 rounded-full\"\n style={{\n backgroundColor: item.color,\n width: total > 0 ? `${(item.value / total) * 100}%` : \"0%\",\n }}\n />\n </div>\n ))}\n </div>\n );\n },\n);\n\nChartPieLegend.displayName = \"ChartPieLegend\";\n"],"names":[],"mappings":";;;;AAsCO,MAAM,iBAAiB,MAAM;AAAA,EAClC,CAAC,EAAE,OAAO,WAAW,GAAG,MAAA,GAAS,QAAQ;AACvC,UAAM,QAAQ,MAAM,OAAO,CAAC,KAAK,SAAS,MAAM,KAAK,OAAO,CAAC;AAE7D,+BACG,OAAA,EAAI,KAAU,WAAW,GAAG,uBAAuB,SAAS,GAAI,GAAG,OACjE,gBAAM,IAAI,CAAC,SACV,qBAAC,OAAA,EAAwC,WAAU,yBACjD,UAAA;AAAA,MAAA,qBAAC,OAAA,EAAI,WAAU,2BACZ,UAAA;AAAA,QAAA,KAAK,QACJ;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO,EAAE,iBAAiB,KAAK,MAAA;AAAA,UAAM;AAAA,QAAA;AAAA,QAGzC,oBAAC,QAAA,EAAK,WAAU,6EACb,eAAK,OACR;AAAA,QACA,oBAAC,UAAK,WAAU,iEACb,eAAK,kBAAkB,KAAK,MAAM,eAAA,EAAe,CACpD;AAAA,MAAA,GACF;AAAA,MACA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAU;AAAA,UACV,OAAO;AAAA,YACL,iBAAiB,KAAK;AAAA,YACtB,OAAO,QAAQ,IAAI,GAAI,KAAK,QAAQ,QAAS,GAAG,MAAM;AAAA,UAAA;AAAA,QACxD;AAAA,MAAA;AAAA,IACF,KArBQ,GAAG,KAAK,KAAK,IAAI,KAAK,KAAK,EAsBrC,CACD,GACH;AAAA,EAEJ;AACF;AAEA,eAAe,cAAc;"}
1
+ {"version":3,"file":"ChartPieLegend.mjs","sources":["../../../src/components/Chart/ChartPieLegend.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** A single item in a {@link ChartPieLegend}. */\nexport interface ChartPieLegendItem {\n /** Display label. Pass translated string for i18n. */\n label: React.ReactNode;\n /** Numeric value for this slice. Used to calculate the proportional bar width. */\n value: number;\n /** Formatted display value (e.g. \"$4,500\"). If omitted, `value.toLocaleString()` is used. */\n formattedValue?: React.ReactNode;\n /** Slice color (CSS value). */\n color: string;\n /** Optional icon to show instead of the color dot. */\n icon?: React.ReactNode;\n}\n\n/** Props for {@link ChartPieLegend}. */\nexport interface ChartPieLegendProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Legend items to display. */\n items: ChartPieLegendItem[];\n}\n\n/**\n * A side legend for pie/donut charts that shows each slice's label,\n * formatted value, and a proportional progress bar.\n *\n * @example\n * ```tsx\n * <ChartPieLegend\n * items={[\n * { label: \"Subscriptions\", value: 4500, formattedValue: \"$4,500\", color: \"var(--color-special-chart-teal)\" },\n * { label: \"Messages\", value: 2100, formattedValue: \"$2,100\", color: \"var(--color-special-chart-sky)\" },\n * { label: \"Tips\", value: 1200, formattedValue: \"$1,200\", color: \"var(--color-special-chart-orange)\" },\n * ]}\n * />\n * ```\n */\nexport const ChartPieLegend = React.forwardRef<HTMLDivElement, ChartPieLegendProps>(\n ({ items, className, ...props }, ref) => {\n const total = items.reduce((sum, item) => sum + item.value, 0);\n\n return (\n <div ref={ref} className={cn(\"flex flex-col gap-3\", className)} {...props}>\n {items.map((item) => (\n <div key={`${item.color}-${item.value}`} className=\"flex flex-col gap-1.5\">\n <div className=\"flex items-center gap-2\">\n {item.icon ?? (\n <span\n className=\"size-2 shrink-0 rounded-full\"\n style={{ backgroundColor: item.color }}\n />\n )}\n <span className=\"typography-description-12px-regular min-w-0 flex-1 truncate text-content-secondary\">\n {item.label}\n </span>\n <span className=\"typography-body-small-14px-semibold text-content-primary tabular-nums\">\n {item.formattedValue ?? item.value.toLocaleString()}\n </span>\n </div>\n <div\n className=\"h-1.5 rounded-full\"\n style={{\n backgroundColor: item.color,\n width: total > 0 ? `${(item.value / total) * 100}%` : \"0%\",\n }}\n />\n </div>\n ))}\n </div>\n );\n },\n);\n\nChartPieLegend.displayName = \"ChartPieLegend\";\n"],"names":[],"mappings":";;;;AAsCO,MAAM,iBAAiB,MAAM;AAAA,EAClC,CAAC,EAAE,OAAO,WAAW,GAAG,MAAA,GAAS,QAAQ;AACvC,UAAM,QAAQ,MAAM,OAAO,CAAC,KAAK,SAAS,MAAM,KAAK,OAAO,CAAC;AAE7D,+BACG,OAAA,EAAI,KAAU,WAAW,GAAG,uBAAuB,SAAS,GAAI,GAAG,OACjE,gBAAM,IAAI,CAAC,SACV,qBAAC,OAAA,EAAwC,WAAU,yBACjD,UAAA;AAAA,MAAA,qBAAC,OAAA,EAAI,WAAU,2BACZ,UAAA;AAAA,QAAA,KAAK,QACJ;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO,EAAE,iBAAiB,KAAK,MAAA;AAAA,UAAM;AAAA,QAAA;AAAA,QAGzC,oBAAC,QAAA,EAAK,WAAU,sFACb,eAAK,OACR;AAAA,QACA,oBAAC,UAAK,WAAU,yEACb,eAAK,kBAAkB,KAAK,MAAM,eAAA,EAAe,CACpD;AAAA,MAAA,GACF;AAAA,MACA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAU;AAAA,UACV,OAAO;AAAA,YACL,iBAAiB,KAAK;AAAA,YACtB,OAAO,QAAQ,IAAI,GAAI,KAAK,QAAQ,QAAS,GAAG,MAAM;AAAA,UAAA;AAAA,QACxD;AAAA,MAAA;AAAA,IACF,KArBQ,GAAG,KAAK,KAAK,IAAI,KAAK,KAAK,EAsBrC,CACD,GACH;AAAA,EAEJ;AACF;AAEA,eAAe,cAAc;"}
@@ -21,7 +21,7 @@ const ChartSeriesToggle = React.forwardRef(
21
21
  type: "button",
22
22
  "aria-pressed": isActive,
23
23
  className: cn(
24
- "typography-regular-body-sm flex items-center gap-2 rounded-full border px-3 py-1.5 text-content-primary transition-opacity hover:opacity-100",
24
+ "typography-description-12px-regular flex items-center gap-2 rounded-full border px-3 py-1.5 text-content-primary transition-opacity hover:opacity-100",
25
25
  isActive ? "border-neutral-alphas-200 bg-surface-primary" : "border-transparent bg-transparent opacity-50"
26
26
  ),
27
27
  onClick: () => toggle(item.key),
@@ -1 +1 @@
1
- {"version":3,"file":"ChartSeriesToggle.mjs","sources":["../../../src/components/Chart/ChartSeriesToggle.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** A single toggleable series in a {@link ChartSeriesToggle}. */\nexport interface ChartSeriesToggleItem {\n /** Unique key matching the data series key and ChartConfig key. */\n key: string;\n /** Human-readable label. Pass translated string for i18n. */\n label: React.ReactNode;\n /** Series color (CSS value). Shown as indicator dot. */\n color: string;\n}\n\n/** Props for {@link ChartSeriesToggle}. */\nexport interface ChartSeriesToggleProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Available series that can be toggled. */\n items: ChartSeriesToggleItem[];\n /** Set of currently visible series keys. */\n value: Set<string>;\n /** Called when a series is toggled. Receives the updated Set. */\n onValueChange: (value: Set<string>) => void;\n}\n\n/**\n * Renders a grid of toggleable chips that control which series are visible\n * on a multi-series chart. Each toggle shows a color indicator dot and a label.\n *\n * @example\n * ```tsx\n * const [visible, setVisible] = useState(new Set([\"subscription\", \"message\", \"tip\"]));\n *\n * <ChartSeriesToggle\n * items={[\n * { key: \"subscription\", label: \"Subscription\", color: \"var(--color-special-chart-teal)\" },\n * { key: \"message\", label: \"Message\", color: \"var(--color-special-chart-sky)\" },\n * { key: \"tip\", label: \"Tip\", color: \"var(--color-special-chart-orange)\" },\n * ]}\n * value={visible}\n * onValueChange={setVisible}\n * />\n * ```\n */\nexport const ChartSeriesToggle = React.forwardRef<HTMLDivElement, ChartSeriesToggleProps>(\n ({ className, items, value, onValueChange, ...props }, ref) => {\n const toggle = (key: string) => {\n const next = new Set(value);\n if (next.has(key)) {\n next.delete(key);\n } else {\n next.add(key);\n }\n onValueChange(next);\n };\n\n return (\n <div ref={ref} className={cn(\"grid grid-cols-2 gap-2 sm:grid-cols-3\", className)} {...props}>\n {items.map((item) => {\n const isActive = value.has(item.key);\n return (\n <button\n key={item.key}\n type=\"button\"\n aria-pressed={isActive}\n className={cn(\n \"typography-regular-body-sm flex items-center gap-2 rounded-full border px-3 py-1.5 text-content-primary transition-opacity hover:opacity-100\",\n isActive\n ? \"border-neutral-alphas-200 bg-surface-primary\"\n : \"border-transparent bg-transparent opacity-50\",\n )}\n onClick={() => toggle(item.key)}\n >\n <span\n className=\"size-2 shrink-0 rounded-full\"\n style={{ backgroundColor: item.color }}\n />\n <span>{item.label}</span>\n </button>\n );\n })}\n </div>\n );\n },\n);\n\nChartSeriesToggle.displayName = \"ChartSeriesToggle\";\n"],"names":[],"mappings":";;;;AA0CO,MAAM,oBAAoB,MAAM;AAAA,EACrC,CAAC,EAAE,WAAW,OAAO,OAAO,eAAe,GAAG,MAAA,GAAS,QAAQ;AAC7D,UAAM,SAAS,CAAC,QAAgB;AAC9B,YAAM,OAAO,IAAI,IAAI,KAAK;AAC1B,UAAI,KAAK,IAAI,GAAG,GAAG;AACjB,aAAK,OAAO,GAAG;AAAA,MACjB,OAAO;AACL,aAAK,IAAI,GAAG;AAAA,MACd;AACA,oBAAc,IAAI;AAAA,IACpB;AAEA,WACE,oBAAC,OAAA,EAAI,KAAU,WAAW,GAAG,yCAAyC,SAAS,GAAI,GAAG,OACnF,UAAA,MAAM,IAAI,CAAC,SAAS;AACnB,YAAM,WAAW,MAAM,IAAI,KAAK,GAAG;AACnC,aACE;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,MAAK;AAAA,UACL,gBAAc;AAAA,UACd,WAAW;AAAA,YACT;AAAA,YACA,WACI,iDACA;AAAA,UAAA;AAAA,UAEN,SAAS,MAAM,OAAO,KAAK,GAAG;AAAA,UAE9B,UAAA;AAAA,YAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO,EAAE,iBAAiB,KAAK,MAAA;AAAA,cAAM;AAAA,YAAA;AAAA,YAEvC,oBAAC,QAAA,EAAM,UAAA,KAAK,MAAA,CAAM;AAAA,UAAA;AAAA,QAAA;AAAA,QAfb,KAAK;AAAA,MAAA;AAAA,IAkBhB,CAAC,EAAA,CACH;AAAA,EAEJ;AACF;AAEA,kBAAkB,cAAc;"}
1
+ {"version":3,"file":"ChartSeriesToggle.mjs","sources":["../../../src/components/Chart/ChartSeriesToggle.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** A single toggleable series in a {@link ChartSeriesToggle}. */\nexport interface ChartSeriesToggleItem {\n /** Unique key matching the data series key and ChartConfig key. */\n key: string;\n /** Human-readable label. Pass translated string for i18n. */\n label: React.ReactNode;\n /** Series color (CSS value). Shown as indicator dot. */\n color: string;\n}\n\n/** Props for {@link ChartSeriesToggle}. */\nexport interface ChartSeriesToggleProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Available series that can be toggled. */\n items: ChartSeriesToggleItem[];\n /** Set of currently visible series keys. */\n value: Set<string>;\n /** Called when a series is toggled. Receives the updated Set. */\n onValueChange: (value: Set<string>) => void;\n}\n\n/**\n * Renders a grid of toggleable chips that control which series are visible\n * on a multi-series chart. Each toggle shows a color indicator dot and a label.\n *\n * @example\n * ```tsx\n * const [visible, setVisible] = useState(new Set([\"subscription\", \"message\", \"tip\"]));\n *\n * <ChartSeriesToggle\n * items={[\n * { key: \"subscription\", label: \"Subscription\", color: \"var(--color-special-chart-teal)\" },\n * { key: \"message\", label: \"Message\", color: \"var(--color-special-chart-sky)\" },\n * { key: \"tip\", label: \"Tip\", color: \"var(--color-special-chart-orange)\" },\n * ]}\n * value={visible}\n * onValueChange={setVisible}\n * />\n * ```\n */\nexport const ChartSeriesToggle = React.forwardRef<HTMLDivElement, ChartSeriesToggleProps>(\n ({ className, items, value, onValueChange, ...props }, ref) => {\n const toggle = (key: string) => {\n const next = new Set(value);\n if (next.has(key)) {\n next.delete(key);\n } else {\n next.add(key);\n }\n onValueChange(next);\n };\n\n return (\n <div ref={ref} className={cn(\"grid grid-cols-2 gap-2 sm:grid-cols-3\", className)} {...props}>\n {items.map((item) => {\n const isActive = value.has(item.key);\n return (\n <button\n key={item.key}\n type=\"button\"\n aria-pressed={isActive}\n className={cn(\n \"typography-description-12px-regular flex items-center gap-2 rounded-full border px-3 py-1.5 text-content-primary transition-opacity hover:opacity-100\",\n isActive\n ? \"border-neutral-alphas-200 bg-surface-primary\"\n : \"border-transparent bg-transparent opacity-50\",\n )}\n onClick={() => toggle(item.key)}\n >\n <span\n className=\"size-2 shrink-0 rounded-full\"\n style={{ backgroundColor: item.color }}\n />\n <span>{item.label}</span>\n </button>\n );\n })}\n </div>\n );\n },\n);\n\nChartSeriesToggle.displayName = \"ChartSeriesToggle\";\n"],"names":[],"mappings":";;;;AA0CO,MAAM,oBAAoB,MAAM;AAAA,EACrC,CAAC,EAAE,WAAW,OAAO,OAAO,eAAe,GAAG,MAAA,GAAS,QAAQ;AAC7D,UAAM,SAAS,CAAC,QAAgB;AAC9B,YAAM,OAAO,IAAI,IAAI,KAAK;AAC1B,UAAI,KAAK,IAAI,GAAG,GAAG;AACjB,aAAK,OAAO,GAAG;AAAA,MACjB,OAAO;AACL,aAAK,IAAI,GAAG;AAAA,MACd;AACA,oBAAc,IAAI;AAAA,IACpB;AAEA,WACE,oBAAC,OAAA,EAAI,KAAU,WAAW,GAAG,yCAAyC,SAAS,GAAI,GAAG,OACnF,UAAA,MAAM,IAAI,CAAC,SAAS;AACnB,YAAM,WAAW,MAAM,IAAI,KAAK,GAAG;AACnC,aACE;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,MAAK;AAAA,UACL,gBAAc;AAAA,UACd,WAAW;AAAA,YACT;AAAA,YACA,WACI,iDACA;AAAA,UAAA;AAAA,UAEN,SAAS,MAAM,OAAO,KAAK,GAAG;AAAA,UAE9B,UAAA;AAAA,YAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO,EAAE,iBAAiB,KAAK,MAAA;AAAA,cAAM;AAAA,YAAA;AAAA,YAEvC,oBAAC,QAAA,EAAM,UAAA,KAAK,MAAA,CAAM;AAAA,UAAA;AAAA,QAAA;AAAA,QAfb,KAAK;AAAA,MAAA;AAAA,IAkBhB,CAAC,EAAA,CACH;AAAA,EAEJ;AACF;AAEA,kBAAkB,cAAc;"}
@@ -20,7 +20,7 @@ function ChatInputDefaultAttachmentThumbnails({
20
20
  return attachments.map((item) => /* @__PURE__ */ jsxs(
21
21
  "div",
22
22
  {
23
- className: "relative size-16 shrink-0 overflow-hidden rounded-sm border border-neutral-200 bg-bg-secondary",
23
+ className: "relative size-16 shrink-0 overflow-hidden rounded-sm border border-neutral-200 bg-background-secondary",
24
24
  children: [
25
25
  /* @__PURE__ */ jsx("img", { src: item.src, alt: "", className: "size-full object-cover" }),
26
26
  /* @__PURE__ */ jsx(
@@ -173,7 +173,7 @@ const ChatInput = React.forwardRef(
173
173
  className: cn(
174
174
  "w-full resize-none bg-transparent px-4",
175
175
  hasAttachmentStrip ? "pt-0" : "pt-4",
176
- "typography-regular-body-md text-content-primary",
176
+ "typography-body-small-14px-regular text-content-primary",
177
177
  "placeholder:text-content-tertiary",
178
178
  "focus:outline-none disabled:cursor-not-allowed",
179
179
  "overflow-y-auto"
@@ -254,7 +254,7 @@ function InlineSelect({ options, value, onChange, disabled, selectedOption }) {
254
254
  disabled,
255
255
  onClick: () => setOpen((prev) => !prev),
256
256
  className: cn(
257
- "typography-semibold-body-sm text-content-primary",
257
+ "typography-description-12px-semibold text-content-primary",
258
258
  "flex items-center gap-1 rounded-md px-2 py-2",
259
259
  "hover:bg-neutral-alphas-50 focus-visible:shadow-focus-ring focus-visible:outline-none",
260
260
  "disabled:cursor-not-allowed disabled:opacity-50",
@@ -287,7 +287,7 @@ function InlineSelect({ options, value, onChange, disabled, selectedOption }) {
287
287
  tabIndex: 0,
288
288
  "aria-selected": option.value === value,
289
289
  className: cn(
290
- "typography-regular-body-md flex cursor-pointer items-center gap-2 rounded-xs px-3 py-1.5",
290
+ "typography-body-small-14px-regular flex cursor-pointer items-center gap-2 rounded-xs px-3 py-1.5",
291
291
  "text-content-primary hover:bg-neutral-alphas-50",
292
292
  "focus-visible:shadow-focus-ring focus-visible:outline-none",
293
293
  option.value === value && "bg-neutral-alphas-50"
@@ -1 +1 @@
1
- {"version":3,"file":"ChatInput.mjs","sources":["../../../src/components/ChatInput/ChatInput.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { IconButton } from \"../IconButton/IconButton\";\nimport { AddIcon } from \"../Icons/AddIcon\";\nimport { ArrowUpIcon } from \"../Icons/ArrowUpIcon\";\nimport { ChevronDownIcon } from \"../Icons/ChevronDownIcon\";\nimport { CloseIcon } from \"../Icons/CloseIcon\";\n\n/** A single image thumbnail in the built-in attachment strip. */\nexport interface ChatInputAttachmentItem {\n /** Stable id passed to {@link ChatInputProps.onAttachmentRemove} and used as React `key`. */\n id: string;\n /** Image URL for the thumbnail. */\n src: string;\n /** Optional value passed to the remove control `aria-label`. */\n ariaLabel?: string;\n}\n\n/** A single option for the inline model/dropdown selector. */\nexport interface ChatInputSelectOption {\n /** Unique value for this option. */\n value: string;\n /** Display label. */\n label: string;\n /** Optional icon rendered to the left of the label. */\n icon?: React.ReactNode;\n}\n\n/**\n * Props for {@link ChatInput}. Standard textarea HTML attributes are forwarded to the inner\n * `<textarea>` except `className` (applied to the outer container), `rows` (use `minRows`), and\n * `onSubmit` (replaced by the chat message submit callback).\n */\nexport interface ChatInputProps\n extends Omit<\n React.TextareaHTMLAttributes<HTMLTextAreaElement>,\n \"className\" | \"rows\" | \"onSubmit\"\n > {\n /** Minimum number of visible rows. @default 1 */\n minRows?: number;\n /** Maximum number of visible rows before scrolling. @default 6 */\n maxRows?: number;\n /** Whether a submission is in progress (disables submit, shows visual feedback). @default false */\n loading?: boolean;\n /**\n * Callback fired when the user submits (clicks the send button or presses Enter without Shift).\n * Receives the current trimmed text value.\n */\n onSubmit?: (value: string) => void;\n /**\n * When `true`, renders an \"attach file\" button in the bottom-left toolbar.\n * @default false\n */\n showFileButton?: boolean;\n /** Callback fired when the attach-file button is clicked. Only relevant when `showFileButton` is `true`. */\n onFileClick?: () => void;\n /** Accessible label for the attach-file button. @default \"Attach file\" */\n fileButtonAriaLabel?: string;\n /** Accessible label for the submit button. @default \"Send message\" */\n submitAriaLabel?: string;\n /** Icon element for the submit button. @default `<ArrowUpIcon />` */\n submitIcon?: React.ReactNode;\n /**\n * Optional content rendered in the bottom-right toolbar, to the left of the submit button.\n * When provided, takes precedence over the built-in `selectOptions` dropdown.\n */\n toolbarRight?: React.ReactNode;\n /**\n * Options for the built-in inline dropdown selector (e.g. model picker).\n * Ignored when `toolbarRight` is provided.\n */\n selectOptions?: ChatInputSelectOption[];\n /** Currently selected value for the built-in dropdown. Should match one of `selectOptions[].value`. */\n selectValue?: string;\n /** Callback fired when the user picks a different dropdown option. */\n onSelectChange?: (value: string) => void;\n /**\n * Image attachments shown in the built-in thumbnail strip. Ignored when {@link ChatInputProps.attachmentPreviews}\n * is provided (including `null`).\n */\n attachments?: ChatInputAttachmentItem[];\n /**\n * Called when the user removes a built-in thumbnail. The remove button is disabled when this is\n * omitted or the input is {@link ChatInputProps.disabled}.\n */\n onAttachmentRemove?: (id: string) => void;\n /**\n * Replaces the built-in attachment strip entirely. When set to any value other than `undefined`\n * (including `null` or `[]`), {@link ChatInputProps.attachments} is ignored.\n */\n attachmentPreviews?: React.ReactNode;\n /** Additional className applied to the outermost container. */\n className?: string;\n}\n\nconst LINE_HEIGHT = 18;\nconst TEXTAREA_PY = 12;\n\nfunction calculateHeight(rows: number): number {\n return LINE_HEIGHT * rows + TEXTAREA_PY * 2;\n}\n\ninterface ChatInputDefaultAttachmentThumbnailsProps {\n attachments: ChatInputAttachmentItem[];\n onAttachmentRemove?: (id: string) => void;\n disabled?: boolean;\n}\n\nfunction ChatInputDefaultAttachmentThumbnails({\n attachments,\n onAttachmentRemove,\n disabled = false,\n}: ChatInputDefaultAttachmentThumbnailsProps) {\n return attachments.map((item) => (\n <div\n key={item.id}\n className=\"relative size-16 shrink-0 overflow-hidden rounded-sm border border-neutral-200 bg-bg-secondary\"\n >\n <img src={item.src} alt=\"\" className=\"size-full object-cover\" />\n <IconButton\n variant=\"tertiary\"\n size=\"24\"\n aria-label={item.ariaLabel ? `Remove ${item.ariaLabel}` : \"Remove attachment\"}\n icon={<CloseIcon className=\"!size-3\" />}\n disabled={disabled || !onAttachmentRemove}\n onClick={() => onAttachmentRemove?.(item.id)}\n className=\"absolute top-0.5 right-0.5 size-5 bg-neutral-900/40 p-1 text-white hover:bg-neutral-900/55\"\n />\n </div>\n ));\n}\n\n/**\n * A chat-style multi-line input with an integrated toolbar containing an\n * optional file-attach button, optional right-side controls (e.g. a model\n * selector), and a submit button — all inside a single bordered container.\n *\n * Designed to behave like modern AI chat inputs: auto-grows with content,\n * submits on Enter (Shift+Enter for newlines), and keeps controls inline.\n *\n * @example\n * ```tsx\n * <ChatInput\n * placeholder=\"Type a message...\"\n * onSubmit={(text) => send(text)}\n * />\n * ```\n *\n * @example\n * ```tsx\n * <ChatInput\n * placeholder=\"Ask the agent...\"\n * showFileButton\n * onFileClick={() => openFilePicker()}\n * selectOptions={[\n * { value: \"fanvue-ai\", label: \"Fanvue AI\", icon: <AIIcon className=\"size-4\" /> },\n * { value: \"example\", label: \"Example\", icon: <BulbIcon className=\"size-4\" /> },\n * ]}\n * selectValue=\"fanvue-ai\"\n * onSelectChange={(v) => setModel(v)}\n * onSubmit={(text) => send(text)}\n * />\n * ```\n *\n * @example\n * ```tsx\n * <ChatInput\n * showFileButton\n * onFileClick={() => openPicker()}\n * attachments={files}\n * onAttachmentRemove={(id) => setFiles((prev) => prev.filter((f) => f.id !== id))}\n * />\n * ```\n *\n * @example\n * ```tsx\n * <ChatInput\n * showFileButton\n * onFileClick={() => openPicker()}\n * attachmentPreviews={<CustomVideoStrip items={items} />}\n * />\n * ```\n */\nexport const ChatInput = React.forwardRef<HTMLTextAreaElement, ChatInputProps>(\n (\n {\n className,\n minRows = 1,\n maxRows = 6,\n disabled = false,\n loading = false,\n value,\n defaultValue,\n placeholder,\n maxLength,\n \"aria-label\": ariaLabel,\n onChange,\n onKeyDown,\n onSubmit,\n showFileButton = false,\n onFileClick,\n fileButtonAriaLabel = \"Attach file\",\n submitAriaLabel = \"Send message\",\n submitIcon,\n toolbarRight,\n selectOptions,\n selectValue,\n onSelectChange,\n attachments,\n onAttachmentRemove,\n attachmentPreviews,\n style,\n ...textareaProps\n },\n ref,\n ) => {\n const internalRef = React.useRef<HTMLTextAreaElement>(null);\n const [internalValue, setInternalValue] = React.useState(defaultValue ?? \"\");\n const resolvedValue = value !== undefined ? value : internalValue;\n const isControlled = value !== undefined;\n\n const mergedRef = React.useCallback(\n (node: HTMLTextAreaElement | null) => {\n (internalRef as React.MutableRefObject<HTMLTextAreaElement | null>).current = node;\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n (ref as React.MutableRefObject<HTMLTextAreaElement | null>).current = node;\n }\n },\n [ref],\n );\n\n const adjustHeight = React.useCallback(() => {\n const textarea = internalRef.current;\n if (!textarea) return;\n\n const minHeight = calculateHeight(minRows);\n const maxHeight = calculateHeight(maxRows);\n\n textarea.style.height = `${minHeight}px`;\n const desired = Math.min(Math.max(textarea.scrollHeight, minHeight), maxHeight);\n textarea.style.height = `${desired}px`;\n }, [minRows, maxRows]);\n\n React.useEffect(() => {\n adjustHeight();\n }, [resolvedValue, adjustHeight]);\n\n const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n if (!isControlled) {\n setInternalValue(e.target.value);\n }\n onChange?.(e);\n };\n\n const canSubmit = !!String(resolvedValue).trim() && !disabled && !loading;\n\n const handleSubmit = () => {\n const text = String(resolvedValue).trim();\n if (!text || !canSubmit) return;\n onSubmit?.(text);\n if (!isControlled) {\n setInternalValue(\"\");\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n handleSubmit();\n }\n onKeyDown?.(e);\n };\n\n const minHeight = calculateHeight(minRows);\n const maxHeight = calculateHeight(maxRows);\n\n const useCustomAttachmentPreviews = attachmentPreviews !== undefined;\n const customAttachmentStrip = useCustomAttachmentPreviews ? attachmentPreviews : null;\n const defaultAttachmentStrip =\n !useCustomAttachmentPreviews && !!attachments?.length ? (\n <ChatInputDefaultAttachmentThumbnails\n attachments={attachments ?? []}\n disabled={disabled}\n onAttachmentRemove={onAttachmentRemove}\n />\n ) : null;\n const resolvedAttachmentStrip = customAttachmentStrip ?? defaultAttachmentStrip;\n const hasAttachmentStrip = resolvedAttachmentStrip != null;\n\n const selectedOption =\n selectOptions?.find((o) => o.value === selectValue) ?? selectOptions?.[0];\n const resolvedToolbarRight =\n toolbarRight ??\n (selectOptions && selectOptions.length > 0 ? (\n <InlineSelect\n options={selectOptions}\n value={selectValue}\n onChange={onSelectChange}\n disabled={disabled}\n selectedOption={selectedOption}\n />\n ) : null);\n\n return (\n <div\n className={cn(\n \"relative flex flex-col gap-6 rounded-lg border border-border-primary bg-surface-primary\",\n \"has-focus-visible:outline-none\",\n \"motion-safe:transition-colors\",\n disabled && \"opacity-50\",\n className,\n )}\n >\n <div className=\"flex flex-col\">\n {hasAttachmentStrip ? (\n <div className=\"flex gap-2 overflow-x-auto px-4 pt-4 pb-2 [scrollbar-width:thin]\">\n {resolvedAttachmentStrip}\n </div>\n ) : null}\n <textarea\n {...textareaProps}\n ref={mergedRef}\n value={isControlled ? value : internalValue}\n placeholder={placeholder}\n maxLength={maxLength}\n disabled={disabled}\n aria-label={ariaLabel ?? placeholder}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n rows={minRows}\n className={cn(\n \"w-full resize-none bg-transparent px-4\",\n hasAttachmentStrip ? \"pt-0\" : \"pt-4\",\n \"typography-regular-body-md text-content-primary\",\n \"placeholder:text-content-tertiary\",\n \"focus:outline-none disabled:cursor-not-allowed\",\n \"overflow-y-auto\",\n )}\n style={{\n minHeight: `${minHeight}px`,\n maxHeight: `${maxHeight}px`,\n ...style,\n }}\n />\n </div>\n\n <div className=\"flex items-center justify-between gap-2 px-4 pb-4\">\n <div className=\"flex items-center gap-1\">\n {showFileButton && (\n <IconButton\n variant=\"tertiary\"\n size=\"32\"\n icon={<AddIcon />}\n aria-label={fileButtonAriaLabel}\n onClick={onFileClick}\n disabled={disabled}\n className=\"sm:border sm:border-border-primary max-sm:-ml-2\"\n />\n )}\n </div>\n\n <div className=\"flex items-center gap-1\">\n {resolvedToolbarRight}\n <IconButton\n variant=\"primary\"\n size=\"32\"\n icon={submitIcon ?? <ArrowUpIcon />}\n aria-label={submitAriaLabel}\n onClick={handleSubmit}\n disabled={!canSubmit}\n className=\"disabled:bg-surface-secondary disabled:opacity-100 disabled:text-icons-primary\"\n />\n </div>\n </div>\n </div>\n );\n },\n);\n\nChatInput.displayName = \"ChatInput\";\n\ninterface InlineSelectProps {\n options: ChatInputSelectOption[];\n value?: string;\n onChange?: (value: string) => void;\n disabled?: boolean;\n selectedOption?: ChatInputSelectOption;\n}\n\nfunction InlineSelect({ options, value, onChange, disabled, selectedOption }: InlineSelectProps) {\n const [open, setOpen] = React.useState(false);\n const containerRef = React.useRef<HTMLDivElement>(null);\n\n React.useEffect(() => {\n if (!open) return;\n const handleClick = (e: MouseEvent) => {\n if (containerRef.current && !containerRef.current.contains(e.target as Node)) {\n setOpen(false);\n }\n };\n document.addEventListener(\"mousedown\", handleClick);\n return () => document.removeEventListener(\"mousedown\", handleClick);\n }, [open]);\n\n React.useEffect(() => {\n if (!open) return;\n const handleKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") setOpen(false);\n };\n document.addEventListener(\"keydown\", handleKey);\n return () => document.removeEventListener(\"keydown\", handleKey);\n }, [open]);\n\n return (\n <div ref={containerRef} className=\"relative\">\n <button\n type=\"button\"\n role=\"combobox\"\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n aria-label=\"Select model\"\n disabled={disabled}\n onClick={() => setOpen((prev) => !prev)}\n className={cn(\n \"typography-semibold-body-sm text-content-primary\",\n \"flex items-center gap-1 rounded-md px-2 py-2\",\n \"hover:bg-neutral-alphas-50 focus-visible:shadow-focus-ring focus-visible:outline-none\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n \"motion-safe:transition-colors\",\n )}\n >\n {selectedOption?.icon && (\n <span className=\"flex shrink-0 items-center [&>svg]:size-4\">{selectedOption.icon}</span>\n )}\n {selectedOption?.label ?? options[0]?.label ?? \"Select\"}\n <ChevronDownIcon\n className={cn(\"size-4 motion-safe:transition-transform\", open && \"rotate-180\")}\n />\n </button>\n\n {open && (\n <div\n role=\"listbox\"\n className={cn(\n \"absolute right-0 bottom-full z-10 mb-1 min-w-[140px]\",\n \"overflow-hidden rounded-xs border border-border-primary bg-surface-primary p-1 shadow-lg\",\n )}\n >\n {options.map((option) => (\n <div\n key={option.value}\n role=\"option\"\n tabIndex={0}\n aria-selected={option.value === value}\n className={cn(\n \"typography-regular-body-md flex cursor-pointer items-center gap-2 rounded-xs px-3 py-1.5\",\n \"text-content-primary hover:bg-neutral-alphas-50\",\n \"focus-visible:shadow-focus-ring focus-visible:outline-none\",\n option.value === value && \"bg-neutral-alphas-50\",\n )}\n onClick={() => {\n onChange?.(option.value);\n setOpen(false);\n }}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onChange?.(option.value);\n setOpen(false);\n }\n }}\n >\n {option.icon && (\n <span className=\"flex shrink-0 items-center [&>svg]:size-4\">{option.icon}</span>\n )}\n {option.label}\n </div>\n ))}\n </div>\n )}\n </div>\n );\n}\n"],"names":["minHeight","maxHeight"],"mappings":"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"}
1
+ {"version":3,"file":"ChatInput.mjs","sources":["../../../src/components/ChatInput/ChatInput.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { IconButton } from \"../IconButton/IconButton\";\nimport { AddIcon } from \"../Icons/AddIcon\";\nimport { ArrowUpIcon } from \"../Icons/ArrowUpIcon\";\nimport { ChevronDownIcon } from \"../Icons/ChevronDownIcon\";\nimport { CloseIcon } from \"../Icons/CloseIcon\";\n\n/** A single image thumbnail in the built-in attachment strip. */\nexport interface ChatInputAttachmentItem {\n /** Stable id passed to {@link ChatInputProps.onAttachmentRemove} and used as React `key`. */\n id: string;\n /** Image URL for the thumbnail. */\n src: string;\n /** Optional value passed to the remove control `aria-label`. */\n ariaLabel?: string;\n}\n\n/** A single option for the inline model/dropdown selector. */\nexport interface ChatInputSelectOption {\n /** Unique value for this option. */\n value: string;\n /** Display label. */\n label: string;\n /** Optional icon rendered to the left of the label. */\n icon?: React.ReactNode;\n}\n\n/**\n * Props for {@link ChatInput}. Standard textarea HTML attributes are forwarded to the inner\n * `<textarea>` except `className` (applied to the outer container), `rows` (use `minRows`), and\n * `onSubmit` (replaced by the chat message submit callback).\n */\nexport interface ChatInputProps\n extends Omit<\n React.TextareaHTMLAttributes<HTMLTextAreaElement>,\n \"className\" | \"rows\" | \"onSubmit\"\n > {\n /** Minimum number of visible rows. @default 1 */\n minRows?: number;\n /** Maximum number of visible rows before scrolling. @default 6 */\n maxRows?: number;\n /** Whether a submission is in progress (disables submit, shows visual feedback). @default false */\n loading?: boolean;\n /**\n * Callback fired when the user submits (clicks the send button or presses Enter without Shift).\n * Receives the current trimmed text value.\n */\n onSubmit?: (value: string) => void;\n /**\n * When `true`, renders an \"attach file\" button in the bottom-left toolbar.\n * @default false\n */\n showFileButton?: boolean;\n /** Callback fired when the attach-file button is clicked. Only relevant when `showFileButton` is `true`. */\n onFileClick?: () => void;\n /** Accessible label for the attach-file button. @default \"Attach file\" */\n fileButtonAriaLabel?: string;\n /** Accessible label for the submit button. @default \"Send message\" */\n submitAriaLabel?: string;\n /** Icon element for the submit button. @default `<ArrowUpIcon />` */\n submitIcon?: React.ReactNode;\n /**\n * Optional content rendered in the bottom-right toolbar, to the left of the submit button.\n * When provided, takes precedence over the built-in `selectOptions` dropdown.\n */\n toolbarRight?: React.ReactNode;\n /**\n * Options for the built-in inline dropdown selector (e.g. model picker).\n * Ignored when `toolbarRight` is provided.\n */\n selectOptions?: ChatInputSelectOption[];\n /** Currently selected value for the built-in dropdown. Should match one of `selectOptions[].value`. */\n selectValue?: string;\n /** Callback fired when the user picks a different dropdown option. */\n onSelectChange?: (value: string) => void;\n /**\n * Image attachments shown in the built-in thumbnail strip. Ignored when {@link ChatInputProps.attachmentPreviews}\n * is provided (including `null`).\n */\n attachments?: ChatInputAttachmentItem[];\n /**\n * Called when the user removes a built-in thumbnail. The remove button is disabled when this is\n * omitted or the input is {@link ChatInputProps.disabled}.\n */\n onAttachmentRemove?: (id: string) => void;\n /**\n * Replaces the built-in attachment strip entirely. When set to any value other than `undefined`\n * (including `null` or `[]`), {@link ChatInputProps.attachments} is ignored.\n */\n attachmentPreviews?: React.ReactNode;\n /** Additional className applied to the outermost container. */\n className?: string;\n}\n\nconst LINE_HEIGHT = 18;\nconst TEXTAREA_PY = 12;\n\nfunction calculateHeight(rows: number): number {\n return LINE_HEIGHT * rows + TEXTAREA_PY * 2;\n}\n\ninterface ChatInputDefaultAttachmentThumbnailsProps {\n attachments: ChatInputAttachmentItem[];\n onAttachmentRemove?: (id: string) => void;\n disabled?: boolean;\n}\n\nfunction ChatInputDefaultAttachmentThumbnails({\n attachments,\n onAttachmentRemove,\n disabled = false,\n}: ChatInputDefaultAttachmentThumbnailsProps) {\n return attachments.map((item) => (\n <div\n key={item.id}\n className=\"relative size-16 shrink-0 overflow-hidden rounded-sm border border-neutral-200 bg-background-secondary\"\n >\n <img src={item.src} alt=\"\" className=\"size-full object-cover\" />\n <IconButton\n variant=\"tertiary\"\n size=\"24\"\n aria-label={item.ariaLabel ? `Remove ${item.ariaLabel}` : \"Remove attachment\"}\n icon={<CloseIcon className=\"!size-3\" />}\n disabled={disabled || !onAttachmentRemove}\n onClick={() => onAttachmentRemove?.(item.id)}\n className=\"absolute top-0.5 right-0.5 size-5 bg-neutral-900/40 p-1 text-white hover:bg-neutral-900/55\"\n />\n </div>\n ));\n}\n\n/**\n * A chat-style multi-line input with an integrated toolbar containing an\n * optional file-attach button, optional right-side controls (e.g. a model\n * selector), and a submit button — all inside a single bordered container.\n *\n * Designed to behave like modern AI chat inputs: auto-grows with content,\n * submits on Enter (Shift+Enter for newlines), and keeps controls inline.\n *\n * @example\n * ```tsx\n * <ChatInput\n * placeholder=\"Type a message...\"\n * onSubmit={(text) => send(text)}\n * />\n * ```\n *\n * @example\n * ```tsx\n * <ChatInput\n * placeholder=\"Ask the agent...\"\n * showFileButton\n * onFileClick={() => openFilePicker()}\n * selectOptions={[\n * { value: \"fanvue-ai\", label: \"Fanvue AI\", icon: <AIIcon className=\"size-4\" /> },\n * { value: \"example\", label: \"Example\", icon: <BulbIcon className=\"size-4\" /> },\n * ]}\n * selectValue=\"fanvue-ai\"\n * onSelectChange={(v) => setModel(v)}\n * onSubmit={(text) => send(text)}\n * />\n * ```\n *\n * @example\n * ```tsx\n * <ChatInput\n * showFileButton\n * onFileClick={() => openPicker()}\n * attachments={files}\n * onAttachmentRemove={(id) => setFiles((prev) => prev.filter((f) => f.id !== id))}\n * />\n * ```\n *\n * @example\n * ```tsx\n * <ChatInput\n * showFileButton\n * onFileClick={() => openPicker()}\n * attachmentPreviews={<CustomVideoStrip items={items} />}\n * />\n * ```\n */\nexport const ChatInput = React.forwardRef<HTMLTextAreaElement, ChatInputProps>(\n (\n {\n className,\n minRows = 1,\n maxRows = 6,\n disabled = false,\n loading = false,\n value,\n defaultValue,\n placeholder,\n maxLength,\n \"aria-label\": ariaLabel,\n onChange,\n onKeyDown,\n onSubmit,\n showFileButton = false,\n onFileClick,\n fileButtonAriaLabel = \"Attach file\",\n submitAriaLabel = \"Send message\",\n submitIcon,\n toolbarRight,\n selectOptions,\n selectValue,\n onSelectChange,\n attachments,\n onAttachmentRemove,\n attachmentPreviews,\n style,\n ...textareaProps\n },\n ref,\n ) => {\n const internalRef = React.useRef<HTMLTextAreaElement>(null);\n const [internalValue, setInternalValue] = React.useState(defaultValue ?? \"\");\n const resolvedValue = value !== undefined ? value : internalValue;\n const isControlled = value !== undefined;\n\n const mergedRef = React.useCallback(\n (node: HTMLTextAreaElement | null) => {\n (internalRef as React.MutableRefObject<HTMLTextAreaElement | null>).current = node;\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n (ref as React.MutableRefObject<HTMLTextAreaElement | null>).current = node;\n }\n },\n [ref],\n );\n\n const adjustHeight = React.useCallback(() => {\n const textarea = internalRef.current;\n if (!textarea) return;\n\n const minHeight = calculateHeight(minRows);\n const maxHeight = calculateHeight(maxRows);\n\n textarea.style.height = `${minHeight}px`;\n const desired = Math.min(Math.max(textarea.scrollHeight, minHeight), maxHeight);\n textarea.style.height = `${desired}px`;\n }, [minRows, maxRows]);\n\n React.useEffect(() => {\n adjustHeight();\n }, [resolvedValue, adjustHeight]);\n\n const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n if (!isControlled) {\n setInternalValue(e.target.value);\n }\n onChange?.(e);\n };\n\n const canSubmit = !!String(resolvedValue).trim() && !disabled && !loading;\n\n const handleSubmit = () => {\n const text = String(resolvedValue).trim();\n if (!text || !canSubmit) return;\n onSubmit?.(text);\n if (!isControlled) {\n setInternalValue(\"\");\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n handleSubmit();\n }\n onKeyDown?.(e);\n };\n\n const minHeight = calculateHeight(minRows);\n const maxHeight = calculateHeight(maxRows);\n\n const useCustomAttachmentPreviews = attachmentPreviews !== undefined;\n const customAttachmentStrip = useCustomAttachmentPreviews ? attachmentPreviews : null;\n const defaultAttachmentStrip =\n !useCustomAttachmentPreviews && !!attachments?.length ? (\n <ChatInputDefaultAttachmentThumbnails\n attachments={attachments ?? []}\n disabled={disabled}\n onAttachmentRemove={onAttachmentRemove}\n />\n ) : null;\n const resolvedAttachmentStrip = customAttachmentStrip ?? defaultAttachmentStrip;\n const hasAttachmentStrip = resolvedAttachmentStrip != null;\n\n const selectedOption =\n selectOptions?.find((o) => o.value === selectValue) ?? selectOptions?.[0];\n const resolvedToolbarRight =\n toolbarRight ??\n (selectOptions && selectOptions.length > 0 ? (\n <InlineSelect\n options={selectOptions}\n value={selectValue}\n onChange={onSelectChange}\n disabled={disabled}\n selectedOption={selectedOption}\n />\n ) : null);\n\n return (\n <div\n className={cn(\n \"relative flex flex-col gap-6 rounded-lg border border-border-primary bg-surface-primary\",\n \"has-focus-visible:outline-none\",\n \"motion-safe:transition-colors\",\n disabled && \"opacity-50\",\n className,\n )}\n >\n <div className=\"flex flex-col\">\n {hasAttachmentStrip ? (\n <div className=\"flex gap-2 overflow-x-auto px-4 pt-4 pb-2 [scrollbar-width:thin]\">\n {resolvedAttachmentStrip}\n </div>\n ) : null}\n <textarea\n {...textareaProps}\n ref={mergedRef}\n value={isControlled ? value : internalValue}\n placeholder={placeholder}\n maxLength={maxLength}\n disabled={disabled}\n aria-label={ariaLabel ?? placeholder}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n rows={minRows}\n className={cn(\n \"w-full resize-none bg-transparent px-4\",\n hasAttachmentStrip ? \"pt-0\" : \"pt-4\",\n \"typography-body-small-14px-regular text-content-primary\",\n \"placeholder:text-content-tertiary\",\n \"focus:outline-none disabled:cursor-not-allowed\",\n \"overflow-y-auto\",\n )}\n style={{\n minHeight: `${minHeight}px`,\n maxHeight: `${maxHeight}px`,\n ...style,\n }}\n />\n </div>\n\n <div className=\"flex items-center justify-between gap-2 px-4 pb-4\">\n <div className=\"flex items-center gap-1\">\n {showFileButton && (\n <IconButton\n variant=\"tertiary\"\n size=\"32\"\n icon={<AddIcon />}\n aria-label={fileButtonAriaLabel}\n onClick={onFileClick}\n disabled={disabled}\n className=\"sm:border sm:border-border-primary max-sm:-ml-2\"\n />\n )}\n </div>\n\n <div className=\"flex items-center gap-1\">\n {resolvedToolbarRight}\n <IconButton\n variant=\"primary\"\n size=\"32\"\n icon={submitIcon ?? <ArrowUpIcon />}\n aria-label={submitAriaLabel}\n onClick={handleSubmit}\n disabled={!canSubmit}\n className=\"disabled:bg-surface-secondary disabled:opacity-100 disabled:text-icons-primary\"\n />\n </div>\n </div>\n </div>\n );\n },\n);\n\nChatInput.displayName = \"ChatInput\";\n\ninterface InlineSelectProps {\n options: ChatInputSelectOption[];\n value?: string;\n onChange?: (value: string) => void;\n disabled?: boolean;\n selectedOption?: ChatInputSelectOption;\n}\n\nfunction InlineSelect({ options, value, onChange, disabled, selectedOption }: InlineSelectProps) {\n const [open, setOpen] = React.useState(false);\n const containerRef = React.useRef<HTMLDivElement>(null);\n\n React.useEffect(() => {\n if (!open) return;\n const handleClick = (e: MouseEvent) => {\n if (containerRef.current && !containerRef.current.contains(e.target as Node)) {\n setOpen(false);\n }\n };\n document.addEventListener(\"mousedown\", handleClick);\n return () => document.removeEventListener(\"mousedown\", handleClick);\n }, [open]);\n\n React.useEffect(() => {\n if (!open) return;\n const handleKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") setOpen(false);\n };\n document.addEventListener(\"keydown\", handleKey);\n return () => document.removeEventListener(\"keydown\", handleKey);\n }, [open]);\n\n return (\n <div ref={containerRef} className=\"relative\">\n <button\n type=\"button\"\n role=\"combobox\"\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n aria-label=\"Select model\"\n disabled={disabled}\n onClick={() => setOpen((prev) => !prev)}\n className={cn(\n \"typography-description-12px-semibold text-content-primary\",\n \"flex items-center gap-1 rounded-md px-2 py-2\",\n \"hover:bg-neutral-alphas-50 focus-visible:shadow-focus-ring focus-visible:outline-none\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n \"motion-safe:transition-colors\",\n )}\n >\n {selectedOption?.icon && (\n <span className=\"flex shrink-0 items-center [&>svg]:size-4\">{selectedOption.icon}</span>\n )}\n {selectedOption?.label ?? options[0]?.label ?? \"Select\"}\n <ChevronDownIcon\n className={cn(\"size-4 motion-safe:transition-transform\", open && \"rotate-180\")}\n />\n </button>\n\n {open && (\n <div\n role=\"listbox\"\n className={cn(\n \"absolute right-0 bottom-full z-10 mb-1 min-w-[140px]\",\n \"overflow-hidden rounded-xs border border-border-primary bg-surface-primary p-1 shadow-lg\",\n )}\n >\n {options.map((option) => (\n <div\n key={option.value}\n role=\"option\"\n tabIndex={0}\n aria-selected={option.value === value}\n className={cn(\n \"typography-body-small-14px-regular flex cursor-pointer items-center gap-2 rounded-xs px-3 py-1.5\",\n \"text-content-primary hover:bg-neutral-alphas-50\",\n \"focus-visible:shadow-focus-ring focus-visible:outline-none\",\n option.value === value && \"bg-neutral-alphas-50\",\n )}\n onClick={() => {\n onChange?.(option.value);\n setOpen(false);\n }}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onChange?.(option.value);\n setOpen(false);\n }\n }}\n >\n {option.icon && (\n <span className=\"flex shrink-0 items-center [&>svg]:size-4\">{option.icon}</span>\n )}\n {option.label}\n </div>\n ))}\n </div>\n )}\n </div>\n );\n}\n"],"names":["minHeight","maxHeight"],"mappings":"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"}
@@ -84,7 +84,7 @@ const Checkbox = React.forwardRef(
84
84
  "hover:ring-2 hover:ring-brand-primary-default group-hover:ring-2 group-hover:ring-brand-primary-default",
85
85
  "not-disabled:active:ring-2 not-disabled:active:ring-brand-primary-default",
86
86
  // Focus state
87
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-interaction-focus focus-visible:ring-offset-2 focus-visible:ring-offset-bg-primary",
87
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-interaction-focus focus-visible:ring-offset-2 focus-visible:ring-offset-background-primary",
88
88
  // Disabled state
89
89
  "disabled:cursor-not-allowed disabled:border-neutral-alphas-600 disabled:ring-0 disabled:group-hover:ring-0",
90
90
  "disabled:data-[state=checked]:border-neutral-alphas-600 disabled:data-[state=checked]:bg-neutral-alphas-600 disabled:data-[state=checked]:text-content-tertiary",
@@ -128,7 +128,7 @@ const Checkbox = React.forwardRef(
128
128
  className: cn(
129
129
  "cursor-pointer select-none text-content-primary",
130
130
  "group-has-disabled:cursor-not-allowed group-has-disabled:text-content-tertiary",
131
- useSmallLabelTypography ? "typography-semibold-body-md" : "typography-semibold-body-lg"
131
+ useSmallLabelTypography ? "typography-body-small-14px-semibold" : "typography-body-default-16px-semibold"
132
132
  ),
133
133
  children: label
134
134
  }
@@ -141,7 +141,7 @@ const Checkbox = React.forwardRef(
141
141
  className: cn(
142
142
  "ml-7 text-content-secondary",
143
143
  "in-[.is-disabled]:cursor-not-allowed in-[.is-disabled]:text-content-tertiary",
144
- useSmallLabelTypography ? "typography-regular-body-sm" : "typography-regular-body-md"
144
+ useSmallLabelTypography ? "typography-description-12px-regular" : "typography-body-small-14px-regular"
145
145
  ),
146
146
  children: helperText
147
147
  }