@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":"TextArea.cjs","sources":["../../../../src/components/TextArea/TextArea.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { IconButton } from \"../IconButton/IconButton\";\nimport { CheckOutlineIcon } from \"../Icons/CheckOutlineIcon\";\nimport { CloseIcon } from \"../Icons/CloseIcon\";\n\n/** Text area height in pixels. */\nexport type TextAreaSize = \"48\" | \"40\" | \"32\";\n\nexport interface TextAreaProps\n extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, \"size\"> {\n /** Label text displayed above the textarea. Also used as the accessible name. */\n label?: string;\n /** Helper text displayed below the textarea. Replaced by `errorMessage` when `error` is `true`. */\n helperText?: string;\n /** Minimum height of the text area in pixels. @default \"48\" */\n size?: TextAreaSize;\n /** Whether the text area is in an error state. @default false */\n error?: boolean;\n /** Error message displayed below the textarea. Shown instead of `helperText` when `error` is `true`. */\n errorMessage?: string;\n /** Whether the text area is validated. @default false */\n validated?: boolean;\n /** Whether the text area stretches to fill its container width. @default false */\n fullWidth?: boolean;\n /** Whether to show a clear button when text is present. @default false */\n showClearButton?: boolean;\n /** Callback fired when the clear button is clicked. Note: `onChange` is also called with an empty value when clearing. */\n onClear?: () => void;\n /** Minimum number of rows (lines) for the textarea. */\n minRows?: number;\n /** Maximum number of rows (lines) for the textarea. */\n maxRows?: number;\n /** Whether the textarea can be resized by the user. @default true */\n resizable?: boolean;\n}\n\nconst CONTAINER_MIN_HEIGHT: Record<TextAreaSize, string> = {\n \"48\": \"min-h-12\",\n \"40\": \"min-h-10\",\n \"32\": \"min-h-8\",\n};\n\nconst TEXTAREA_SIZE_CLASSES: Record<TextAreaSize, string> = {\n \"48\": \"py-3 typography-regular-body-lg autofill-body-lg\",\n \"40\": \"py-2 typography-regular-body-lg autofill-body-lg\",\n \"32\": \"py-2 typography-regular-body-md autofill-body-md\",\n};\n\nconst PADDING_HORIZONTAL: Record<TextAreaSize, string> = {\n \"48\": \"px-4\",\n \"40\": \"px-4\",\n \"32\": \"px-3\",\n};\n\nconst PADDING_RIGHT_WITH_CLEAR: Record<TextAreaSize, string> = {\n \"48\": \"pr-11\",\n \"40\": \"pr-11\",\n \"32\": \"pr-10\",\n};\n\nconst CLEAR_BUTTON_RIGHT: Record<TextAreaSize, string> = {\n \"48\": \"right-4 top-3\",\n \"40\": \"right-4 top-2\",\n \"32\": \"right-3 top-2\",\n};\n\nfunction getContainerClassName(size: TextAreaSize, error: boolean, disabled?: boolean) {\n return cn(\n \"relative rounded-sm border bg-neutral-alphas-50 has-focus-visible:shadow-focus-ring has-focus-visible:outline-none motion-safe:transition-colors\",\n error ? \"border-error-content\" : \"border-transparent\",\n !disabled && !error && \"hover:border-neutral-alphas-400\",\n CONTAINER_MIN_HEIGHT[size],\n disabled && \"opacity-50\",\n );\n}\n\nfunction getTextareaClassName(\n size: TextAreaSize,\n hasClearButton: boolean,\n hasMinRows: boolean,\n resizable: boolean,\n) {\n return cn(\n \"h-full w-full bg-transparent text-content-primary no-underline placeholder:text-content-secondary focus:outline-none disabled:cursor-not-allowed\",\n resizable ? \"resize-y\" : \"resize-none\",\n !hasMinRows && \"min-h-[80px]\",\n TEXTAREA_SIZE_CLASSES[size],\n PADDING_HORIZONTAL[size],\n hasClearButton ? PADDING_RIGHT_WITH_CLEAR[size] : \"\",\n );\n}\n\nfunction TextAreaHelperText({\n id,\n error,\n children,\n}: {\n id: string;\n error: boolean;\n children: React.ReactNode;\n}) {\n return (\n <p\n id={id}\n className={cn(\n \"typography-regular-body-sm px-2 pt-1 pb-0.5\",\n error ? \"text-error-content\" : \"text-content-secondary\",\n )}\n >\n {children}\n </p>\n );\n}\n\nfunction warnMissingAccessibleName(label?: string, ariaLabel?: string, ariaLabelledBy?: string) {\n if (process.env.NODE_ENV !== \"production\") {\n if (!label && !ariaLabel && !ariaLabelledBy) {\n console.warn(\n \"TextArea: no accessible name provided. Pass a `label`, `aria-label`, or `aria-labelledby` prop.\",\n );\n }\n }\n}\n\nfunction calculateMaxHeight(size: TextAreaSize, maxRows?: number): string | undefined {\n if (!maxRows) return undefined;\n\n // Line height is 24px for body-1 (sizes 48 and 40) and 20px for body-2 (size 32)\n const lineHeight = size === \"32\" ? 20 : 24;\n // py-2 = 8px, py-3 = 12px\n const verticalPadding = size === \"32\" ? 8 : size === \"40\" ? 8 : 12;\n\n return `${lineHeight * maxRows + verticalPadding * 2}px`;\n}\n\nfunction useTextAreaValue(\n value: React.TextareaHTMLAttributes<HTMLTextAreaElement>[\"value\"],\n defaultValue: React.TextareaHTMLAttributes<HTMLTextAreaElement>[\"defaultValue\"],\n showClearButton: boolean,\n onChange?: React.ChangeEventHandler<HTMLTextAreaElement>,\n onClear?: () => void,\n textareaRef?: React.RefObject<HTMLTextAreaElement | null>,\n) {\n const [internalValue, setInternalValue] = React.useState(defaultValue ?? \"\");\n const resolvedValue = value !== undefined ? value : internalValue;\n\n const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setInternalValue(e.target.value);\n onChange?.(e);\n };\n\n const handleClear = () => {\n setInternalValue(\"\");\n\n if (onChange && textareaRef?.current) {\n const syntheticEvent = {\n target: { ...textareaRef.current, value: \"\" },\n currentTarget: { ...textareaRef.current, value: \"\" },\n } as React.ChangeEvent<HTMLTextAreaElement>;\n onChange(syntheticEvent);\n }\n\n onClear?.();\n };\n\n return {\n resolvedValue,\n displayValue: showClearButton ? resolvedValue : value,\n resolvedDefaultValue: showClearButton ? undefined : defaultValue,\n handleChange,\n handleClear,\n };\n}\n\n/**\n * A multi-line text input with optional label, helper/error text, and clear button.\n *\n * Provide at least one of `label`, `aria-label`, or `aria-labelledby` for\n * accessibility — a console warning is emitted in development if none are set.\n *\n * @example\n * ```tsx\n * <TextArea\n * label=\"Description\"\n * placeholder=\"Enter your description...\"\n * showClearButton\n * error={!!descError}\n * errorMessage={descError}\n * />\n * ```\n */\nexport const TextArea = React.forwardRef<HTMLTextAreaElement, TextAreaProps>(\n (\n {\n label,\n helperText,\n size = \"48\",\n error = false,\n errorMessage,\n validated = false,\n className,\n id,\n disabled,\n fullWidth = false,\n showClearButton = false,\n onClear,\n value,\n defaultValue,\n onChange,\n minRows,\n maxRows,\n resizable = false,\n ...props\n },\n ref,\n ) => {\n const generatedId = React.useId();\n const inputId = id || generatedId;\n const helperTextId = `${inputId}-helper`;\n const bottomText = error && errorMessage ? errorMessage : helperText;\n const maxHeight = calculateMaxHeight(size, maxRows);\n\n const internalRef = React.useRef<HTMLTextAreaElement>(null);\n\n const { resolvedValue, displayValue, resolvedDefaultValue, handleChange, handleClear } =\n useTextAreaValue(value, defaultValue, showClearButton, onChange, onClear, internalRef);\n\n const mergedRef = (node: HTMLTextAreaElement | null) => {\n internalRef.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\n const showClear = showClearButton && resolvedValue !== \"\" && !disabled;\n const showValidated = validated && !showClear;\n const ariaDescribedBy = bottomText ? helperTextId : undefined;\n const textareaStyle = maxHeight ? { maxHeight } : undefined;\n\n warnMissingAccessibleName(label, props[\"aria-label\"], props[\"aria-labelledby\"]);\n\n return (\n <div\n className={cn(\"flex flex-col\", fullWidth && \"w-full\", className)}\n data-disabled={disabled ? \"\" : undefined}\n data-error={error ? \"\" : undefined}\n >\n {label && (\n <label\n htmlFor={inputId}\n className=\"typography-semibold-body-sm px-1 pt-1 pb-2 text-content-primary\"\n >\n {label}\n </label>\n )}\n\n <div className={getContainerClassName(size, error, disabled)}>\n <textarea\n ref={mergedRef}\n id={inputId}\n disabled={disabled}\n aria-describedby={ariaDescribedBy}\n aria-invalid={error || undefined}\n className={getTextareaClassName(size, showClear, !!minRows, resizable)}\n value={displayValue}\n defaultValue={resolvedDefaultValue}\n onChange={handleChange}\n rows={minRows}\n style={textareaStyle}\n {...props}\n />\n\n {showClear && (\n <IconButton\n variant=\"tertiary\"\n size=\"24\"\n icon={<CloseIcon />}\n aria-label=\"Clear text\"\n onClick={handleClear}\n className={cn(\n \"absolute flex size-5 items-center justify-center self-end\",\n CLEAR_BUTTON_RIGHT[size],\n )}\n />\n )}\n {showValidated && (\n <div\n className={cn(\n \"pointer-events-none absolute flex size-5 items-center justify-center\",\n CLEAR_BUTTON_RIGHT[size],\n )}\n >\n <CheckOutlineIcon className=\"text-success-content\" />\n </div>\n )}\n </div>\n\n {bottomText && (\n <TextAreaHelperText id={helperTextId} error={error}>\n {bottomText}\n </TextAreaHelperText>\n )}\n </div>\n );\n },\n);\n\nTextArea.displayName = \"TextArea\";\n"],"names":["cn","jsx","React","jsxs","IconButton","CloseIcon","CheckOutlineIcon"],"mappings":"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"}
1
+ {"version":3,"file":"TextArea.cjs","sources":["../../../../src/components/TextArea/TextArea.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { IconButton } from \"../IconButton/IconButton\";\nimport { CheckOutlineIcon } from \"../Icons/CheckOutlineIcon\";\nimport { CloseIcon } from \"../Icons/CloseIcon\";\n\n/** Text area height in pixels. */\nexport type TextAreaSize = \"48\" | \"40\" | \"32\";\n\nexport interface TextAreaProps\n extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, \"size\"> {\n /** Label text displayed above the textarea. Also used as the accessible name. */\n label?: string;\n /** Helper text displayed below the textarea. Replaced by `errorMessage` when `error` is `true`. */\n helperText?: string;\n /** Minimum height of the text area in pixels. @default \"48\" */\n size?: TextAreaSize;\n /** Whether the text area is in an error state. @default false */\n error?: boolean;\n /** Error message displayed below the textarea. Shown instead of `helperText` when `error` is `true`. */\n errorMessage?: string;\n /** Whether the text area is validated. @default false */\n validated?: boolean;\n /** Whether the text area stretches to fill its container width. @default false */\n fullWidth?: boolean;\n /** Whether to show a clear button when text is present. @default false */\n showClearButton?: boolean;\n /** Callback fired when the clear button is clicked. Note: `onChange` is also called with an empty value when clearing. */\n onClear?: () => void;\n /** Minimum number of rows (lines) for the textarea. */\n minRows?: number;\n /** Maximum number of rows (lines) for the textarea. */\n maxRows?: number;\n /** Whether the textarea can be resized by the user. @default true */\n resizable?: boolean;\n}\n\nconst CONTAINER_MIN_HEIGHT: Record<TextAreaSize, string> = {\n \"48\": \"min-h-12\",\n \"40\": \"min-h-10\",\n \"32\": \"min-h-8\",\n};\n\nconst TEXTAREA_SIZE_CLASSES: Record<TextAreaSize, string> = {\n \"48\": \"py-3 typography-body-default-16px-regular autofill-body-lg\",\n \"40\": \"py-2 typography-body-default-16px-regular autofill-body-lg\",\n \"32\": \"py-2 typography-body-small-14px-regular autofill-body-md\",\n};\n\nconst PADDING_HORIZONTAL: Record<TextAreaSize, string> = {\n \"48\": \"px-4\",\n \"40\": \"px-4\",\n \"32\": \"px-3\",\n};\n\nconst PADDING_RIGHT_WITH_CLEAR: Record<TextAreaSize, string> = {\n \"48\": \"pr-11\",\n \"40\": \"pr-11\",\n \"32\": \"pr-10\",\n};\n\nconst CLEAR_BUTTON_RIGHT: Record<TextAreaSize, string> = {\n \"48\": \"right-4 top-3\",\n \"40\": \"right-4 top-2\",\n \"32\": \"right-3 top-2\",\n};\n\nfunction getContainerClassName(size: TextAreaSize, error: boolean, disabled?: boolean) {\n return cn(\n \"relative rounded-sm border bg-neutral-alphas-50 has-focus-visible:shadow-focus-ring has-focus-visible:outline-none motion-safe:transition-colors\",\n error ? \"border-error-content\" : \"border-transparent\",\n !disabled && !error && \"hover:border-neutral-alphas-400\",\n CONTAINER_MIN_HEIGHT[size],\n disabled && \"opacity-50\",\n );\n}\n\nfunction getTextareaClassName(\n size: TextAreaSize,\n hasClearButton: boolean,\n hasMinRows: boolean,\n resizable: boolean,\n) {\n return cn(\n \"h-full w-full bg-transparent text-content-primary no-underline placeholder:text-content-secondary focus:outline-none disabled:cursor-not-allowed\",\n resizable ? \"resize-y\" : \"resize-none\",\n !hasMinRows && \"min-h-[80px]\",\n TEXTAREA_SIZE_CLASSES[size],\n PADDING_HORIZONTAL[size],\n hasClearButton ? PADDING_RIGHT_WITH_CLEAR[size] : \"\",\n );\n}\n\nfunction TextAreaHelperText({\n id,\n error,\n children,\n}: {\n id: string;\n error: boolean;\n children: React.ReactNode;\n}) {\n return (\n <p\n id={id}\n className={cn(\n \"typography-description-12px-regular px-2 pt-1 pb-0.5\",\n error ? \"text-error-content\" : \"text-content-secondary\",\n )}\n >\n {children}\n </p>\n );\n}\n\nfunction warnMissingAccessibleName(label?: string, ariaLabel?: string, ariaLabelledBy?: string) {\n if (process.env.NODE_ENV !== \"production\") {\n if (!label && !ariaLabel && !ariaLabelledBy) {\n console.warn(\n \"TextArea: no accessible name provided. Pass a `label`, `aria-label`, or `aria-labelledby` prop.\",\n );\n }\n }\n}\n\nfunction calculateMaxHeight(size: TextAreaSize, maxRows?: number): string | undefined {\n if (!maxRows) return undefined;\n\n // Line height is 24px for body-1 (sizes 48 and 40) and 20px for body-2 (size 32)\n const lineHeight = size === \"32\" ? 20 : 24;\n // py-2 = 8px, py-3 = 12px\n const verticalPadding = size === \"32\" ? 8 : size === \"40\" ? 8 : 12;\n\n return `${lineHeight * maxRows + verticalPadding * 2}px`;\n}\n\nfunction useTextAreaValue(\n value: React.TextareaHTMLAttributes<HTMLTextAreaElement>[\"value\"],\n defaultValue: React.TextareaHTMLAttributes<HTMLTextAreaElement>[\"defaultValue\"],\n showClearButton: boolean,\n onChange?: React.ChangeEventHandler<HTMLTextAreaElement>,\n onClear?: () => void,\n textareaRef?: React.RefObject<HTMLTextAreaElement | null>,\n) {\n const [internalValue, setInternalValue] = React.useState(defaultValue ?? \"\");\n const resolvedValue = value !== undefined ? value : internalValue;\n\n const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setInternalValue(e.target.value);\n onChange?.(e);\n };\n\n const handleClear = () => {\n setInternalValue(\"\");\n\n if (onChange && textareaRef?.current) {\n const syntheticEvent = {\n target: { ...textareaRef.current, value: \"\" },\n currentTarget: { ...textareaRef.current, value: \"\" },\n } as React.ChangeEvent<HTMLTextAreaElement>;\n onChange(syntheticEvent);\n }\n\n onClear?.();\n };\n\n return {\n resolvedValue,\n displayValue: showClearButton ? resolvedValue : value,\n resolvedDefaultValue: showClearButton ? undefined : defaultValue,\n handleChange,\n handleClear,\n };\n}\n\n/**\n * A multi-line text input with optional label, helper/error text, and clear button.\n *\n * Provide at least one of `label`, `aria-label`, or `aria-labelledby` for\n * accessibility — a console warning is emitted in development if none are set.\n *\n * @example\n * ```tsx\n * <TextArea\n * label=\"Description\"\n * placeholder=\"Enter your description...\"\n * showClearButton\n * error={!!descError}\n * errorMessage={descError}\n * />\n * ```\n */\nexport const TextArea = React.forwardRef<HTMLTextAreaElement, TextAreaProps>(\n (\n {\n label,\n helperText,\n size = \"48\",\n error = false,\n errorMessage,\n validated = false,\n className,\n id,\n disabled,\n fullWidth = false,\n showClearButton = false,\n onClear,\n value,\n defaultValue,\n onChange,\n minRows,\n maxRows,\n resizable = false,\n ...props\n },\n ref,\n ) => {\n const generatedId = React.useId();\n const inputId = id || generatedId;\n const helperTextId = `${inputId}-helper`;\n const bottomText = error && errorMessage ? errorMessage : helperText;\n const maxHeight = calculateMaxHeight(size, maxRows);\n\n const internalRef = React.useRef<HTMLTextAreaElement>(null);\n\n const { resolvedValue, displayValue, resolvedDefaultValue, handleChange, handleClear } =\n useTextAreaValue(value, defaultValue, showClearButton, onChange, onClear, internalRef);\n\n const mergedRef = (node: HTMLTextAreaElement | null) => {\n internalRef.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\n const showClear = showClearButton && resolvedValue !== \"\" && !disabled;\n const showValidated = validated && !showClear;\n const ariaDescribedBy = bottomText ? helperTextId : undefined;\n const textareaStyle = maxHeight ? { maxHeight } : undefined;\n\n warnMissingAccessibleName(label, props[\"aria-label\"], props[\"aria-labelledby\"]);\n\n return (\n <div\n className={cn(\"flex flex-col\", fullWidth && \"w-full\", className)}\n data-disabled={disabled ? \"\" : undefined}\n data-error={error ? \"\" : undefined}\n >\n {label && (\n <label\n htmlFor={inputId}\n className=\"typography-description-12px-semibold px-1 pt-1 pb-2 text-content-primary\"\n >\n {label}\n </label>\n )}\n\n <div className={getContainerClassName(size, error, disabled)}>\n <textarea\n ref={mergedRef}\n id={inputId}\n disabled={disabled}\n aria-describedby={ariaDescribedBy}\n aria-invalid={error || undefined}\n className={getTextareaClassName(size, showClear, !!minRows, resizable)}\n value={displayValue}\n defaultValue={resolvedDefaultValue}\n onChange={handleChange}\n rows={minRows}\n style={textareaStyle}\n {...props}\n />\n\n {showClear && (\n <IconButton\n variant=\"tertiary\"\n size=\"24\"\n icon={<CloseIcon />}\n aria-label=\"Clear text\"\n onClick={handleClear}\n className={cn(\n \"absolute flex size-5 items-center justify-center self-end\",\n CLEAR_BUTTON_RIGHT[size],\n )}\n />\n )}\n {showValidated && (\n <div\n className={cn(\n \"pointer-events-none absolute flex size-5 items-center justify-center\",\n CLEAR_BUTTON_RIGHT[size],\n )}\n >\n <CheckOutlineIcon className=\"text-success-content\" />\n </div>\n )}\n </div>\n\n {bottomText && (\n <TextAreaHelperText id={helperTextId} error={error}>\n {bottomText}\n </TextAreaHelperText>\n )}\n </div>\n );\n },\n);\n\nTextArea.displayName = \"TextArea\";\n"],"names":["cn","jsx","React","jsxs","IconButton","CloseIcon","CheckOutlineIcon"],"mappings":"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"}
@@ -29,9 +29,9 @@ const CONTAINER_HEIGHT = {
29
29
  "32": "h-8"
30
30
  };
31
31
  const INPUT_SIZE_CLASSES = {
32
- "48": "py-3 typography-regular-body-lg autofill-body-lg",
33
- "40": "py-2 typography-regular-body-lg autofill-body-lg",
34
- "32": "py-2 typography-regular-body-md autofill-body-md"
32
+ "48": "py-3 typography-body-default-16px-regular autofill-body-lg",
33
+ "40": "py-2 typography-body-default-16px-regular autofill-body-lg",
34
+ "32": "py-2 typography-body-small-14px-regular autofill-body-md"
35
35
  };
36
36
  const INPUT_PL = {
37
37
  "48": { default: "pl-4", withIcon: "pl-10" },
@@ -75,7 +75,7 @@ function TextFieldHelperText({
75
75
  {
76
76
  id,
77
77
  className: cn.cn(
78
- "typography-regular-body-sm px-2 pt-2 pb-0.5",
78
+ "typography-description-12px-regular px-2 pt-2 pb-0.5",
79
79
  error ? "text-error-content" : "text-content-secondary"
80
80
  ),
81
81
  children
@@ -123,7 +123,7 @@ const TextField = React__namespace.forwardRef(
123
123
  "label",
124
124
  {
125
125
  htmlFor: inputId,
126
- className: "typography-semibold-body-sm px-1 pt-1 pb-2 text-content-primary",
126
+ className: "typography-description-12px-semibold px-1 pt-1 pb-2 text-content-primary",
127
127
  children: label
128
128
  }
129
129
  ),
@@ -1 +1 @@
1
- {"version":3,"file":"TextField.cjs","sources":["../../../../src/components/TextField/TextField.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { CheckOutlineIcon } from \"@/index\";\nimport { cn } from \"../../utils/cn\";\n\n/** Text field height in pixels. */\nexport type TextFieldSize = \"48\" | \"40\" | \"32\";\n\nexport interface TextFieldProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\" | \"prefix\"> {\n /** Label text displayed above the input. Also used as the accessible name. */\n label?: string;\n /** Helper text displayed below the input. Replaced by `errorMessage` when `error` is `true`. */\n helperText?: string;\n /** Height of the text field in pixels. @default \"48\" */\n size?: TextFieldSize;\n /** Whether the text field is in an error state. @default false */\n error?: boolean;\n /** Error message displayed below the input. Shown instead of `helperText` when `error` is `true`. */\n errorMessage?: string;\n /** Whether the text field is validated. @default false */\n validated?: boolean;\n /** Icon element displayed at the left side of the input. */\n leftIcon?: React.ReactNode;\n /** Icon element displayed at the right side of the input. */\n rightIcon?: React.ReactNode;\n /** Whether the text field stretches to fill its container width. @default false */\n fullWidth?: boolean;\n}\n\nconst CONTAINER_HEIGHT: Record<TextFieldSize, string> = {\n \"48\": \"h-12\",\n \"40\": \"h-10\",\n \"32\": \"h-8\",\n};\n\nconst INPUT_SIZE_CLASSES: Record<TextFieldSize, string> = {\n \"48\": \"py-3 typography-regular-body-lg autofill-body-lg\",\n \"40\": \"py-2 typography-regular-body-lg autofill-body-lg\",\n \"32\": \"py-2 typography-regular-body-md autofill-body-md\",\n};\n\nconst INPUT_PL: Record<TextFieldSize, { default: string; withIcon: string }> = {\n \"48\": { default: \"pl-4\", withIcon: \"pl-10\" },\n \"40\": { default: \"pl-4\", withIcon: \"pl-10\" },\n \"32\": { default: \"pl-3\", withIcon: \"pl-9\" },\n};\n\nconst INPUT_PR: Record<TextFieldSize, { default: string; withIcon: string }> = {\n \"48\": { default: \"pr-4\", withIcon: \"pr-10\" },\n \"40\": { default: \"pr-4\", withIcon: \"pr-10\" },\n \"32\": { default: \"pr-3\", withIcon: \"pr-9\" },\n};\n\nconst ICON_INSET: Record<TextFieldSize, string> = {\n \"48\": \"px-4\",\n \"40\": \"px-4\",\n \"32\": \"px-3\",\n};\n\nfunction getContainerClassName(size: TextFieldSize, error: boolean, disabled?: boolean) {\n return cn(\n \"relative overflow-hidden rounded-sm border bg-neutral-alphas-50 has-focus-visible:shadow-focus-ring has-focus-visible:outline-none motion-safe:transition-colors\",\n error ? \"border-error-content\" : \"border-transparent\",\n !disabled && !error && \"hover:border-neutral-alphas-400\",\n CONTAINER_HEIGHT[size],\n disabled && \"opacity-50\",\n );\n}\n\nfunction getInputClassName(size: TextFieldSize, hasLeftIcon: boolean, hasRightIcon: boolean) {\n return cn(\n \"h-full w-full rounded-sm bg-transparent text-content-primary no-underline placeholder:text-content-secondary focus:outline-none disabled:cursor-not-allowed\",\n INPUT_SIZE_CLASSES[size],\n hasLeftIcon ? INPUT_PL[size].withIcon : INPUT_PL[size].default,\n hasRightIcon ? INPUT_PR[size].withIcon : INPUT_PR[size].default,\n );\n}\n\nfunction TextFieldHelperText({\n id,\n error,\n children,\n}: {\n id: string;\n error: boolean;\n children: React.ReactNode;\n}) {\n return (\n <p\n id={id}\n className={cn(\n \"typography-regular-body-sm px-2 pt-2 pb-0.5\",\n error ? \"text-error-content\" : \"text-content-secondary\",\n )}\n >\n {children}\n </p>\n );\n}\n\nfunction warnMissingAccessibleName(label?: string, ariaLabel?: string, ariaLabelledBy?: string) {\n if (process.env.NODE_ENV !== \"production\") {\n if (!label && !ariaLabel && !ariaLabelledBy) {\n console.warn(\n \"TextField: no accessible name provided. Pass a `label`, `aria-label`, or `aria-labelledby` prop.\",\n );\n }\n }\n}\n\n/**\n * A text input field with optional label, helper/error text, and icon slots.\n *\n * Provide at least one of `label`, `aria-label`, or `aria-labelledby` for\n * accessibility — a console warning is emitted in development if none are set.\n *\n * @example\n * ```tsx\n * <TextField\n * label=\"Email\"\n * placeholder=\"you@example.com\"\n * error={!!emailError}\n * errorMessage={emailError}\n * />\n * ```\n */\nexport const TextField = React.forwardRef<HTMLInputElement, TextFieldProps>(\n (\n {\n label,\n helperText,\n size = \"48\",\n error = false,\n errorMessage,\n validated = false,\n leftIcon,\n rightIcon,\n className,\n id,\n disabled,\n fullWidth = false,\n ...props\n },\n ref,\n ) => {\n const generatedId = React.useId();\n const inputId = id || generatedId;\n const helperTextId = `${inputId}-helper`;\n const bottomText = error && errorMessage ? errorMessage : helperText;\n\n warnMissingAccessibleName(label, props[\"aria-label\"], props[\"aria-labelledby\"]);\n\n return (\n <div\n className={cn(\"flex flex-col\", fullWidth && \"w-full\", className)}\n data-disabled={disabled ? \"\" : undefined}\n data-error={error ? \"\" : undefined}\n >\n {label && (\n <label\n htmlFor={inputId}\n className=\"typography-semibold-body-sm px-1 pt-1 pb-2 text-content-primary\"\n >\n {label}\n </label>\n )}\n\n <div className={getContainerClassName(size, error, disabled)}>\n <input\n ref={ref}\n id={inputId}\n disabled={disabled}\n aria-describedby={bottomText ? helperTextId : undefined}\n aria-invalid={error || undefined}\n className={cn(\n getInputClassName(size, !!leftIcon, !!(rightIcon || validated)),\n \"[&[type='search']::-webkit-search-cancel-button]:hidden [&[type='search']::-webkit-search-cancel-button]:appearance-none\",\n )}\n {...props}\n />\n\n {leftIcon && (\n <div\n className={cn(\n \"pointer-events-none absolute inset-y-0 left-0 flex items-center text-content-secondary\",\n ICON_INSET[size],\n )}\n >\n <div className=\"flex size-4 shrink-0 items-center justify-center\">{leftIcon}</div>\n </div>\n )}\n\n {(rightIcon || validated) && (\n <div\n className={cn(\n \"absolute inset-y-0 right-0 flex items-center gap-2 text-content-secondary\",\n ICON_INSET[size],\n )}\n >\n {rightIcon && (\n <div className=\"flex size-4 shrink-0 items-center justify-center\">{rightIcon}</div>\n )}\n {validated && (\n <div className=\"pointer-events-none flex size-4 shrink-0 items-center justify-center\">\n <CheckOutlineIcon className=\"text-success-content\" />\n </div>\n )}\n </div>\n )}\n </div>\n\n {bottomText && (\n <TextFieldHelperText id={helperTextId} error={error}>\n {bottomText}\n </TextFieldHelperText>\n )}\n </div>\n );\n },\n);\n\nTextField.displayName = \"TextField\";\n"],"names":["cn","jsx","React","jsxs","CheckOutlineIcon"],"mappings":"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"}
1
+ {"version":3,"file":"TextField.cjs","sources":["../../../../src/components/TextField/TextField.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { CheckOutlineIcon } from \"@/index\";\nimport { cn } from \"../../utils/cn\";\n\n/** Text field height in pixels. */\nexport type TextFieldSize = \"48\" | \"40\" | \"32\";\n\nexport interface TextFieldProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\" | \"prefix\"> {\n /** Label text displayed above the input. Also used as the accessible name. */\n label?: string;\n /** Helper text displayed below the input. Replaced by `errorMessage` when `error` is `true`. */\n helperText?: string;\n /** Height of the text field in pixels. @default \"48\" */\n size?: TextFieldSize;\n /** Whether the text field is in an error state. @default false */\n error?: boolean;\n /** Error message displayed below the input. Shown instead of `helperText` when `error` is `true`. */\n errorMessage?: string;\n /** Whether the text field is validated. @default false */\n validated?: boolean;\n /** Icon element displayed at the left side of the input. */\n leftIcon?: React.ReactNode;\n /** Icon element displayed at the right side of the input. */\n rightIcon?: React.ReactNode;\n /** Whether the text field stretches to fill its container width. @default false */\n fullWidth?: boolean;\n}\n\nconst CONTAINER_HEIGHT: Record<TextFieldSize, string> = {\n \"48\": \"h-12\",\n \"40\": \"h-10\",\n \"32\": \"h-8\",\n};\n\nconst INPUT_SIZE_CLASSES: Record<TextFieldSize, string> = {\n \"48\": \"py-3 typography-body-default-16px-regular autofill-body-lg\",\n \"40\": \"py-2 typography-body-default-16px-regular autofill-body-lg\",\n \"32\": \"py-2 typography-body-small-14px-regular autofill-body-md\",\n};\n\nconst INPUT_PL: Record<TextFieldSize, { default: string; withIcon: string }> = {\n \"48\": { default: \"pl-4\", withIcon: \"pl-10\" },\n \"40\": { default: \"pl-4\", withIcon: \"pl-10\" },\n \"32\": { default: \"pl-3\", withIcon: \"pl-9\" },\n};\n\nconst INPUT_PR: Record<TextFieldSize, { default: string; withIcon: string }> = {\n \"48\": { default: \"pr-4\", withIcon: \"pr-10\" },\n \"40\": { default: \"pr-4\", withIcon: \"pr-10\" },\n \"32\": { default: \"pr-3\", withIcon: \"pr-9\" },\n};\n\nconst ICON_INSET: Record<TextFieldSize, string> = {\n \"48\": \"px-4\",\n \"40\": \"px-4\",\n \"32\": \"px-3\",\n};\n\nfunction getContainerClassName(size: TextFieldSize, error: boolean, disabled?: boolean) {\n return cn(\n \"relative overflow-hidden rounded-sm border bg-neutral-alphas-50 has-focus-visible:shadow-focus-ring has-focus-visible:outline-none motion-safe:transition-colors\",\n error ? \"border-error-content\" : \"border-transparent\",\n !disabled && !error && \"hover:border-neutral-alphas-400\",\n CONTAINER_HEIGHT[size],\n disabled && \"opacity-50\",\n );\n}\n\nfunction getInputClassName(size: TextFieldSize, hasLeftIcon: boolean, hasRightIcon: boolean) {\n return cn(\n \"h-full w-full rounded-sm bg-transparent text-content-primary no-underline placeholder:text-content-secondary focus:outline-none disabled:cursor-not-allowed\",\n INPUT_SIZE_CLASSES[size],\n hasLeftIcon ? INPUT_PL[size].withIcon : INPUT_PL[size].default,\n hasRightIcon ? INPUT_PR[size].withIcon : INPUT_PR[size].default,\n );\n}\n\nfunction TextFieldHelperText({\n id,\n error,\n children,\n}: {\n id: string;\n error: boolean;\n children: React.ReactNode;\n}) {\n return (\n <p\n id={id}\n className={cn(\n \"typography-description-12px-regular px-2 pt-2 pb-0.5\",\n error ? \"text-error-content\" : \"text-content-secondary\",\n )}\n >\n {children}\n </p>\n );\n}\n\nfunction warnMissingAccessibleName(label?: string, ariaLabel?: string, ariaLabelledBy?: string) {\n if (process.env.NODE_ENV !== \"production\") {\n if (!label && !ariaLabel && !ariaLabelledBy) {\n console.warn(\n \"TextField: no accessible name provided. Pass a `label`, `aria-label`, or `aria-labelledby` prop.\",\n );\n }\n }\n}\n\n/**\n * A text input field with optional label, helper/error text, and icon slots.\n *\n * Provide at least one of `label`, `aria-label`, or `aria-labelledby` for\n * accessibility — a console warning is emitted in development if none are set.\n *\n * @example\n * ```tsx\n * <TextField\n * label=\"Email\"\n * placeholder=\"you@example.com\"\n * error={!!emailError}\n * errorMessage={emailError}\n * />\n * ```\n */\nexport const TextField = React.forwardRef<HTMLInputElement, TextFieldProps>(\n (\n {\n label,\n helperText,\n size = \"48\",\n error = false,\n errorMessage,\n validated = false,\n leftIcon,\n rightIcon,\n className,\n id,\n disabled,\n fullWidth = false,\n ...props\n },\n ref,\n ) => {\n const generatedId = React.useId();\n const inputId = id || generatedId;\n const helperTextId = `${inputId}-helper`;\n const bottomText = error && errorMessage ? errorMessage : helperText;\n\n warnMissingAccessibleName(label, props[\"aria-label\"], props[\"aria-labelledby\"]);\n\n return (\n <div\n className={cn(\"flex flex-col\", fullWidth && \"w-full\", className)}\n data-disabled={disabled ? \"\" : undefined}\n data-error={error ? \"\" : undefined}\n >\n {label && (\n <label\n htmlFor={inputId}\n className=\"typography-description-12px-semibold px-1 pt-1 pb-2 text-content-primary\"\n >\n {label}\n </label>\n )}\n\n <div className={getContainerClassName(size, error, disabled)}>\n <input\n ref={ref}\n id={inputId}\n disabled={disabled}\n aria-describedby={bottomText ? helperTextId : undefined}\n aria-invalid={error || undefined}\n className={cn(\n getInputClassName(size, !!leftIcon, !!(rightIcon || validated)),\n \"[&[type='search']::-webkit-search-cancel-button]:hidden [&[type='search']::-webkit-search-cancel-button]:appearance-none\",\n )}\n {...props}\n />\n\n {leftIcon && (\n <div\n className={cn(\n \"pointer-events-none absolute inset-y-0 left-0 flex items-center text-content-secondary\",\n ICON_INSET[size],\n )}\n >\n <div className=\"flex size-4 shrink-0 items-center justify-center\">{leftIcon}</div>\n </div>\n )}\n\n {(rightIcon || validated) && (\n <div\n className={cn(\n \"absolute inset-y-0 right-0 flex items-center gap-2 text-content-secondary\",\n ICON_INSET[size],\n )}\n >\n {rightIcon && (\n <div className=\"flex size-4 shrink-0 items-center justify-center\">{rightIcon}</div>\n )}\n {validated && (\n <div className=\"pointer-events-none flex size-4 shrink-0 items-center justify-center\">\n <CheckOutlineIcon className=\"text-success-content\" />\n </div>\n )}\n </div>\n )}\n </div>\n\n {bottomText && (\n <TextFieldHelperText id={helperTextId} error={error}>\n {bottomText}\n </TextFieldHelperText>\n )}\n </div>\n );\n },\n);\n\nTextField.displayName = \"TextField\";\n"],"names":["cn","jsx","React","jsxs","CheckOutlineIcon"],"mappings":"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"}
@@ -92,8 +92,8 @@ const Toast = React__namespace.forwardRef(
92
92
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-center gap-3", children: [
93
93
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "self-start", children: variant === "messageToast" ? avatarSrc && /* @__PURE__ */ jsxRuntime.jsx(Avatar.Avatar, { src: avatarSrc, alt: avatarAlt, fallback: avatarFallback }) : /* @__PURE__ */ jsxRuntime.jsx(VariantIcon, { variant }) }),
94
94
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col items-start", children: [
95
- title && /* @__PURE__ */ jsxRuntime.jsx(ToastPrimitive__namespace.Title, { className: "typography-semibold-body-md", children: title }),
96
- description && /* @__PURE__ */ jsxRuntime.jsx(ToastPrimitive__namespace.Description, { className: "typography-regular-body-md mt-1 opacity-90", children: description }),
95
+ title && /* @__PURE__ */ jsxRuntime.jsx(ToastPrimitive__namespace.Title, { className: "typography-body-small-14px-semibold", children: title }),
96
+ description && /* @__PURE__ */ jsxRuntime.jsx(ToastPrimitive__namespace.Description, { className: "typography-body-small-14px-regular mt-1 opacity-90", children: description }),
97
97
  children,
98
98
  onActionClick && /* @__PURE__ */ jsxRuntime.jsx(
99
99
  Button.Button,
@@ -1 +1 @@
1
- {"version":3,"file":"Toast.cjs","sources":["../../../../src/components/Toast/Toast.tsx"],"sourcesContent":["import * as ToastPrimitive from \"@radix-ui/react-toast\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Avatar } from \"../Avatar/Avatar\";\nimport { Button } from \"../Button/Button\";\nimport { IconButton } from \"../IconButton/IconButton\";\nimport { CloseIcon } from \"../Icons/CloseIcon\";\nimport { ErrorIcon } from \"../Icons/ErrorIcon\";\nimport { InfoIcon } from \"../Icons/InfoIcon\";\nimport { SuccessIcon } from \"../Icons/SuccessIcon\";\nimport { WarningIcon } from \"../Icons/WarningIcon\";\n\n/** Visual/semantic variant of the toast notification. */\nexport type ToastVariant = \"info\" | \"warning\" | \"success\" | \"error\" | \"messageToast\";\n\nexport interface ToastProps\n extends Omit<Omit<React.ComponentPropsWithoutRef<typeof ToastPrimitive.Root>, \"type\">, \"title\"> {\n /** Visual/semantic variant of the toast. @default \"info\" */\n variant?: ToastVariant;\n /** Title text displayed in bold at the top of the toast. */\n title?: string;\n /** Description or body content displayed below the title. */\n description?: React.ReactNode;\n /** Label for the optional action button. @default \"Action\" */\n actionLabel?: string;\n /** Click handler for the action button. When provided, the action button is rendered. */\n onActionClick?: () => void;\n /** Whether to show the close button. @default true */\n showClose?: boolean;\n /** Accessible label for the close button. @default \"Close notification\" */\n closeLabel?: string;\n /** Avatar image URL (used by the `messageToast` variant). */\n avatarSrc?: string;\n /** Alt text for the avatar image. */\n avatarAlt?: string;\n /** Fallback content for the avatar (e.g. initials). */\n avatarFallback?: string;\n}\n\n/** Props for the {@link ToastProvider}. Wraps Radix `Toast.Provider`. */\nexport interface ToastProviderProps extends ToastPrimitive.ToastProviderProps {}\n/** Props for the {@link ToastViewport}. Controls where toasts are rendered on screen. */\nexport interface ToastViewportProps\n extends React.ComponentPropsWithoutRef<typeof ToastPrimitive.Viewport> {}\n\n/** Provides toast context. Wrap your application (or a subtree) with this provider. */\nexport const ToastProvider: React.FC<ToastProviderProps> = ToastPrimitive.Provider;\n\n/** Fixed-position container that renders active toasts. Place once at the root of your app. */\nexport const ToastViewport = React.forwardRef<\n React.ElementRef<typeof ToastPrimitive.Viewport>,\n ToastViewportProps\n>(({ className, ...props }, ref) => (\n <ToastPrimitive.Viewport\n ref={ref}\n className={cn(\n \"pointer-events-none fixed right-0 bottom-0 z-100 flex max-h-screen w-full flex-col-reverse gap-3 p-4 md:max-w-[420px]\",\n className,\n )}\n {...props}\n />\n));\n\nToastViewport.displayName = \"ToastViewport\";\n\nconst VariantIcon = ({ variant }: { variant: ToastVariant }) => {\n switch (variant) {\n case \"info\":\n return <InfoIcon className=\"size-5 text-info-content\" />;\n case \"warning\":\n return <WarningIcon className=\"size-5 text-warning-content\" />;\n case \"success\":\n return <SuccessIcon className=\"size-5 text-success-content\" />;\n case \"error\":\n return <ErrorIcon className=\"size-5 text-error-content\" />;\n }\n};\n\n/**\n * A dismissible notification that appears temporarily. Supports `info`,\n * `warning`, `success`, `error`, and `messageToast` variants with optional\n * action button, close control, and avatar.\n *\n * Use inside a {@link ToastProvider} with a {@link ToastViewport}.\n *\n * @example\n * ```tsx\n * <Toast variant=\"success\" title=\"Saved\" description=\"Your changes are live.\" />\n * ```\n */\nexport const Toast = React.forwardRef<React.ComponentRef<typeof ToastPrimitive.Root>, ToastProps>(\n (\n {\n className,\n variant = \"info\",\n title,\n description,\n actionLabel,\n onActionClick,\n showClose = true,\n closeLabel = \"Close notification\",\n avatarSrc,\n avatarAlt,\n avatarFallback,\n children,\n ...props\n },\n ref,\n ) => {\n return (\n <ToastPrimitive.Root\n ref={ref}\n data-testid=\"toast\"\n className={cn(\n // Base styles\n \"group pointer-events-auto relative flex w-full flex-col items-start gap-3 overflow-hidden rounded-xs border-none bg-surface-primary-inverted p-4 text-content-primary-inverted shadow-lg transition-all\",\n // Dark mode\n \"dark:border-opacity-100\",\n // Animation\n \"data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-bottom-full data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-(--radix-toast-swipe-end-x) data-[swipe=move]:translate-x-(--radix-toast-swipe-move-x) data-[state=closed]:animate-out data-[state=open]:animate-in data-[swipe=end]:animate-out data-[swipe=move]:transition-none\",\n // Manual CSS overrides\n className,\n )}\n {...props}\n >\n <div className=\"flex w-full items-center gap-3\">\n <div className=\"self-start\">\n {variant === \"messageToast\" ? (\n avatarSrc && <Avatar src={avatarSrc} alt={avatarAlt} fallback={avatarFallback} />\n ) : (\n <VariantIcon variant={variant} />\n )}\n </div>\n <div className=\"flex flex-1 flex-col items-start\">\n {title && (\n <ToastPrimitive.Title className=\"typography-semibold-body-md\">\n {title}\n </ToastPrimitive.Title>\n )}\n {description && (\n <ToastPrimitive.Description className=\"typography-regular-body-md mt-1 opacity-90\">\n {description}\n </ToastPrimitive.Description>\n )}\n {children}\n {onActionClick && (\n <Button\n variant=\"secondary\"\n // These styles are basically inverted from the selected theme\n className=\"mt-4 border-content-primary-inverted text-content-primary-inverted\"\n size=\"32\"\n onClick={onActionClick}\n >\n {actionLabel ?? \"Action\"}\n </Button>\n )}\n </div>\n </div>\n {showClose && (\n <ToastPrimitive.Close asChild>\n <IconButton\n icon={<CloseIcon />}\n aria-label={closeLabel}\n // same as the button above\n className=\"absolute top-2 right-2 text-content-primary-inverted\"\n variant=\"tertiary\"\n size=\"24\"\n />\n </ToastPrimitive.Close>\n )}\n </ToastPrimitive.Root>\n );\n },\n);\n\nToast.displayName = \"Toast\";\n"],"names":["ToastPrimitive","React","jsx","cn","InfoIcon","WarningIcon","SuccessIcon","ErrorIcon","jsxs","Avatar","Button","IconButton","CloseIcon"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8CO,MAAM,gBAA8CA,0BAAe;AAGnE,MAAM,gBAAgBC,iBAAM,WAGjC,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QAC1BC,2BAAAA;AAAAA,EAACF,0BAAe;AAAA,EAAf;AAAA,IACC;AAAA,IACA,WAAWG,GAAAA;AAAAA,MACT;AAAA,MACA;AAAA,IAAA;AAAA,IAED,GAAG;AAAA,EAAA;AACN,CACD;AAED,cAAc,cAAc;AAE5B,MAAM,cAAc,CAAC,EAAE,cAAyC;AAC9D,UAAQ,SAAA;AAAA,IACN,KAAK;AACH,aAAOD,2BAAAA,IAACE,SAAAA,UAAA,EAAS,WAAU,2BAAA,CAA2B;AAAA,IACxD,KAAK;AACH,aAAOF,2BAAAA,IAACG,YAAAA,aAAA,EAAY,WAAU,8BAAA,CAA8B;AAAA,IAC9D,KAAK;AACH,aAAOH,2BAAAA,IAACI,YAAAA,aAAA,EAAY,WAAU,8BAAA,CAA8B;AAAA,IAC9D,KAAK;AACH,aAAOJ,2BAAAA,IAACK,UAAAA,WAAA,EAAU,WAAU,4BAAA,CAA4B;AAAA,EAAA;AAE9D;AAcO,MAAM,QAAQN,iBAAM;AAAA,EACzB,CACE;AAAA,IACE;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,WACEO,2BAAAA;AAAAA,MAACR,0BAAe;AAAA,MAAf;AAAA,QACC;AAAA,QACA,eAAY;AAAA,QACZ,WAAWG,GAAAA;AAAAA;AAAAA,UAET;AAAA;AAAA,UAEA;AAAA;AAAA,UAEA;AAAA;AAAA,UAEA;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEJ,UAAA;AAAA,UAAAK,2BAAAA,KAAC,OAAA,EAAI,WAAU,kCACb,UAAA;AAAA,YAAAN,2BAAAA,IAAC,SAAI,WAAU,cACZ,sBAAY,iBACX,4CAAcO,eAAA,EAAO,KAAK,WAAW,KAAK,WAAW,UAAU,eAAA,CAAgB,IAE/EP,2BAAAA,IAAC,aAAA,EAAY,SAAkB,EAAA,CAEnC;AAAA,YACAM,2BAAAA,KAAC,OAAA,EAAI,WAAU,oCACZ,UAAA;AAAA,cAAA,wCACER,0BAAe,OAAf,EAAqB,WAAU,+BAC7B,UAAA,OACH;AAAA,cAED,eACCE,2BAAAA,IAACF,0BAAe,aAAf,EAA2B,WAAU,8CACnC,UAAA,aACH;AAAA,cAED;AAAA,cACA,iBACCE,2BAAAA;AAAAA,gBAACQ,OAAAA;AAAAA,gBAAA;AAAA,kBACC,SAAQ;AAAA,kBAER,WAAU;AAAA,kBACV,MAAK;AAAA,kBACL,SAAS;AAAA,kBAER,UAAA,eAAe;AAAA,gBAAA;AAAA,cAAA;AAAA,YAClB,EAAA,CAEJ;AAAA,UAAA,GACF;AAAA,UACC,aACCR,2BAAAA,IAACF,0BAAe,OAAf,EAAqB,SAAO,MAC3B,UAAAE,2BAAAA;AAAAA,YAACS,WAAAA;AAAAA,YAAA;AAAA,cACC,qCAAOC,UAAAA,WAAA,EAAU;AAAA,cACjB,cAAY;AAAA,cAEZ,WAAU;AAAA,cACV,SAAQ;AAAA,cACR,MAAK;AAAA,YAAA;AAAA,UAAA,EACP,CACF;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,MAAM,cAAc;;;;"}
1
+ {"version":3,"file":"Toast.cjs","sources":["../../../../src/components/Toast/Toast.tsx"],"sourcesContent":["import * as ToastPrimitive from \"@radix-ui/react-toast\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Avatar } from \"../Avatar/Avatar\";\nimport { Button } from \"../Button/Button\";\nimport { IconButton } from \"../IconButton/IconButton\";\nimport { CloseIcon } from \"../Icons/CloseIcon\";\nimport { ErrorIcon } from \"../Icons/ErrorIcon\";\nimport { InfoIcon } from \"../Icons/InfoIcon\";\nimport { SuccessIcon } from \"../Icons/SuccessIcon\";\nimport { WarningIcon } from \"../Icons/WarningIcon\";\n\n/** Visual/semantic variant of the toast notification. */\nexport type ToastVariant = \"info\" | \"warning\" | \"success\" | \"error\" | \"messageToast\";\n\nexport interface ToastProps\n extends Omit<Omit<React.ComponentPropsWithoutRef<typeof ToastPrimitive.Root>, \"type\">, \"title\"> {\n /** Visual/semantic variant of the toast. @default \"info\" */\n variant?: ToastVariant;\n /** Title text displayed in bold at the top of the toast. */\n title?: string;\n /** Description or body content displayed below the title. */\n description?: React.ReactNode;\n /** Label for the optional action button. @default \"Action\" */\n actionLabel?: string;\n /** Click handler for the action button. When provided, the action button is rendered. */\n onActionClick?: () => void;\n /** Whether to show the close button. @default true */\n showClose?: boolean;\n /** Accessible label for the close button. @default \"Close notification\" */\n closeLabel?: string;\n /** Avatar image URL (used by the `messageToast` variant). */\n avatarSrc?: string;\n /** Alt text for the avatar image. */\n avatarAlt?: string;\n /** Fallback content for the avatar (e.g. initials). */\n avatarFallback?: string;\n}\n\n/** Props for the {@link ToastProvider}. Wraps Radix `Toast.Provider`. */\nexport interface ToastProviderProps extends ToastPrimitive.ToastProviderProps {}\n/** Props for the {@link ToastViewport}. Controls where toasts are rendered on screen. */\nexport interface ToastViewportProps\n extends React.ComponentPropsWithoutRef<typeof ToastPrimitive.Viewport> {}\n\n/** Provides toast context. Wrap your application (or a subtree) with this provider. */\nexport const ToastProvider: React.FC<ToastProviderProps> = ToastPrimitive.Provider;\n\n/** Fixed-position container that renders active toasts. Place once at the root of your app. */\nexport const ToastViewport = React.forwardRef<\n React.ElementRef<typeof ToastPrimitive.Viewport>,\n ToastViewportProps\n>(({ className, ...props }, ref) => (\n <ToastPrimitive.Viewport\n ref={ref}\n className={cn(\n \"pointer-events-none fixed right-0 bottom-0 z-100 flex max-h-screen w-full flex-col-reverse gap-3 p-4 md:max-w-[420px]\",\n className,\n )}\n {...props}\n />\n));\n\nToastViewport.displayName = \"ToastViewport\";\n\nconst VariantIcon = ({ variant }: { variant: ToastVariant }) => {\n switch (variant) {\n case \"info\":\n return <InfoIcon className=\"size-5 text-info-content\" />;\n case \"warning\":\n return <WarningIcon className=\"size-5 text-warning-content\" />;\n case \"success\":\n return <SuccessIcon className=\"size-5 text-success-content\" />;\n case \"error\":\n return <ErrorIcon className=\"size-5 text-error-content\" />;\n }\n};\n\n/**\n * A dismissible notification that appears temporarily. Supports `info`,\n * `warning`, `success`, `error`, and `messageToast` variants with optional\n * action button, close control, and avatar.\n *\n * Use inside a {@link ToastProvider} with a {@link ToastViewport}.\n *\n * @example\n * ```tsx\n * <Toast variant=\"success\" title=\"Saved\" description=\"Your changes are live.\" />\n * ```\n */\nexport const Toast = React.forwardRef<React.ComponentRef<typeof ToastPrimitive.Root>, ToastProps>(\n (\n {\n className,\n variant = \"info\",\n title,\n description,\n actionLabel,\n onActionClick,\n showClose = true,\n closeLabel = \"Close notification\",\n avatarSrc,\n avatarAlt,\n avatarFallback,\n children,\n ...props\n },\n ref,\n ) => {\n return (\n <ToastPrimitive.Root\n ref={ref}\n data-testid=\"toast\"\n className={cn(\n // Base styles\n \"group pointer-events-auto relative flex w-full flex-col items-start gap-3 overflow-hidden rounded-xs border-none bg-surface-primary-inverted p-4 text-content-primary-inverted shadow-lg transition-all\",\n // Dark mode\n \"dark:border-opacity-100\",\n // Animation\n \"data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-bottom-full data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-(--radix-toast-swipe-end-x) data-[swipe=move]:translate-x-(--radix-toast-swipe-move-x) data-[state=closed]:animate-out data-[state=open]:animate-in data-[swipe=end]:animate-out data-[swipe=move]:transition-none\",\n // Manual CSS overrides\n className,\n )}\n {...props}\n >\n <div className=\"flex w-full items-center gap-3\">\n <div className=\"self-start\">\n {variant === \"messageToast\" ? (\n avatarSrc && <Avatar src={avatarSrc} alt={avatarAlt} fallback={avatarFallback} />\n ) : (\n <VariantIcon variant={variant} />\n )}\n </div>\n <div className=\"flex flex-1 flex-col items-start\">\n {title && (\n <ToastPrimitive.Title className=\"typography-body-small-14px-semibold\">\n {title}\n </ToastPrimitive.Title>\n )}\n {description && (\n <ToastPrimitive.Description className=\"typography-body-small-14px-regular mt-1 opacity-90\">\n {description}\n </ToastPrimitive.Description>\n )}\n {children}\n {onActionClick && (\n <Button\n variant=\"secondary\"\n // These styles are basically inverted from the selected theme\n className=\"mt-4 border-content-primary-inverted text-content-primary-inverted\"\n size=\"32\"\n onClick={onActionClick}\n >\n {actionLabel ?? \"Action\"}\n </Button>\n )}\n </div>\n </div>\n {showClose && (\n <ToastPrimitive.Close asChild>\n <IconButton\n icon={<CloseIcon />}\n aria-label={closeLabel}\n // same as the button above\n className=\"absolute top-2 right-2 text-content-primary-inverted\"\n variant=\"tertiary\"\n size=\"24\"\n />\n </ToastPrimitive.Close>\n )}\n </ToastPrimitive.Root>\n );\n },\n);\n\nToast.displayName = \"Toast\";\n"],"names":["ToastPrimitive","React","jsx","cn","InfoIcon","WarningIcon","SuccessIcon","ErrorIcon","jsxs","Avatar","Button","IconButton","CloseIcon"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8CO,MAAM,gBAA8CA,0BAAe;AAGnE,MAAM,gBAAgBC,iBAAM,WAGjC,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QAC1BC,2BAAAA;AAAAA,EAACF,0BAAe;AAAA,EAAf;AAAA,IACC;AAAA,IACA,WAAWG,GAAAA;AAAAA,MACT;AAAA,MACA;AAAA,IAAA;AAAA,IAED,GAAG;AAAA,EAAA;AACN,CACD;AAED,cAAc,cAAc;AAE5B,MAAM,cAAc,CAAC,EAAE,cAAyC;AAC9D,UAAQ,SAAA;AAAA,IACN,KAAK;AACH,aAAOD,2BAAAA,IAACE,SAAAA,UAAA,EAAS,WAAU,2BAAA,CAA2B;AAAA,IACxD,KAAK;AACH,aAAOF,2BAAAA,IAACG,YAAAA,aAAA,EAAY,WAAU,8BAAA,CAA8B;AAAA,IAC9D,KAAK;AACH,aAAOH,2BAAAA,IAACI,YAAAA,aAAA,EAAY,WAAU,8BAAA,CAA8B;AAAA,IAC9D,KAAK;AACH,aAAOJ,2BAAAA,IAACK,UAAAA,WAAA,EAAU,WAAU,4BAAA,CAA4B;AAAA,EAAA;AAE9D;AAcO,MAAM,QAAQN,iBAAM;AAAA,EACzB,CACE;AAAA,IACE;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,WACEO,2BAAAA;AAAAA,MAACR,0BAAe;AAAA,MAAf;AAAA,QACC;AAAA,QACA,eAAY;AAAA,QACZ,WAAWG,GAAAA;AAAAA;AAAAA,UAET;AAAA;AAAA,UAEA;AAAA;AAAA,UAEA;AAAA;AAAA,UAEA;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEJ,UAAA;AAAA,UAAAK,2BAAAA,KAAC,OAAA,EAAI,WAAU,kCACb,UAAA;AAAA,YAAAN,2BAAAA,IAAC,SAAI,WAAU,cACZ,sBAAY,iBACX,4CAAcO,eAAA,EAAO,KAAK,WAAW,KAAK,WAAW,UAAU,eAAA,CAAgB,IAE/EP,2BAAAA,IAAC,aAAA,EAAY,SAAkB,EAAA,CAEnC;AAAA,YACAM,2BAAAA,KAAC,OAAA,EAAI,WAAU,oCACZ,UAAA;AAAA,cAAA,wCACER,0BAAe,OAAf,EAAqB,WAAU,uCAC7B,UAAA,OACH;AAAA,cAED,eACCE,2BAAAA,IAACF,0BAAe,aAAf,EAA2B,WAAU,sDACnC,UAAA,aACH;AAAA,cAED;AAAA,cACA,iBACCE,2BAAAA;AAAAA,gBAACQ,OAAAA;AAAAA,gBAAA;AAAA,kBACC,SAAQ;AAAA,kBAER,WAAU;AAAA,kBACV,MAAK;AAAA,kBACL,SAAS;AAAA,kBAER,UAAA,eAAe;AAAA,gBAAA;AAAA,cAAA;AAAA,YAClB,EAAA,CAEJ;AAAA,UAAA,GACF;AAAA,UACC,aACCR,2BAAAA,IAACF,0BAAe,OAAf,EAAqB,SAAO,MAC3B,UAAAE,2BAAAA;AAAAA,YAACS,WAAAA;AAAAA,YAAA;AAAA,cACC,qCAAOC,UAAAA,WAAA,EAAU;AAAA,cACjB,cAAY;AAAA,cAEZ,WAAU;AAAA,cACV,SAAQ;AAAA,cACR,MAAK;AAAA,YAAA;AAAA,UAAA,EACP,CACF;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,MAAM,cAAc;;;;"}
@@ -44,7 +44,7 @@ const TooltipContent = React__namespace.forwardRef(({ className, sideOffset = 8,
44
44
  collisionPadding: 8,
45
45
  style: { zIndex: "var(--fanvue-ui-portal-z-index, 50)", ...style },
46
46
  className: cn.cn(
47
- "typography-semibold-body-sm max-w-[320px] rounded-sm bg-surface-primary-inverted px-4 py-2 text-content-primary-inverted shadow-[0px_1px_4px_0px_rgba(0,0,0,0.06),0px_1px_3px_0px_rgba(0,0,0,0.05)]",
47
+ "typography-description-12px-semibold max-w-[320px] rounded-sm bg-surface-primary-inverted px-4 py-2 text-content-primary-inverted shadow-[0px_1px_4px_0px_rgba(0,0,0,0.06),0px_1px_3px_0px_rgba(0,0,0,0.05)]",
48
48
  className
49
49
  ),
50
50
  ...props
@@ -1 +1 @@
1
- {"version":3,"file":"Tooltip.cjs","sources":["../../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["import * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Props for the {@link TooltipProvider}. Wraps Radix `Tooltip.Provider`. */\nexport type TooltipProviderProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider>;\n\n/** Provides tooltip delay and skip-delay context. Wrap your app or a subtree. */\nexport const TooltipProvider = TooltipPrimitive.Provider;\n\n/** Props for the {@link Tooltip} root component. */\nexport interface TooltipProps extends React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root> {\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n defaultOpen?: boolean;\n}\n\n/** Root component that manages open/close state for a single tooltip. */\nexport const Tooltip = TooltipPrimitive.Root;\n\n/** Props for the {@link TooltipTrigger} component. */\nexport type TooltipTriggerProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Trigger>;\n\n/** The element that triggers the tooltip on hover/focus. */\nexport const TooltipTrigger = TooltipPrimitive.Trigger;\n\n/** Position of the tooltip relative to its trigger, combining side and alignment (MUI-style). */\nexport type TooltipPlacement =\n | \"top\"\n | \"top-start\"\n | \"top-end\"\n | \"bottom\"\n | \"bottom-start\"\n | \"bottom-end\"\n | \"left\"\n | \"left-start\"\n | \"left-end\"\n | \"right\"\n | \"right-start\"\n | \"right-end\";\n\nexport interface TooltipContentProps\n extends React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> {\n /**\n * Position of the tooltip relative to the trigger. Takes precedence over `side` and `align`.\n * @default \"top\"\n */\n placement?: TooltipPlacement;\n}\n\nexport const TooltipContent = React.forwardRef<\n React.ComponentRef<typeof TooltipPrimitive.Content>,\n TooltipContentProps\n>(({ className, sideOffset = 8, style, placement, side, align, ...props }, ref) => {\n let resolvedSide = side;\n let resolvedAlign: \"start\" | \"center\" | \"end\" = align ?? \"center\";\n if (placement) {\n const [parsedSide, parsedAlign] = placement.split(\"-\") as [\n \"top\" | \"right\" | \"bottom\" | \"left\",\n \"start\" | \"end\" | undefined,\n ];\n resolvedSide = parsedSide;\n resolvedAlign = parsedAlign ?? \"center\";\n }\n\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n ref={ref}\n side={resolvedSide}\n align={resolvedAlign}\n sideOffset={sideOffset}\n collisionPadding={8}\n style={{ zIndex: \"var(--fanvue-ui-portal-z-index, 50)\", ...style }}\n className={cn(\n \"typography-semibold-body-sm max-w-[320px] rounded-sm bg-surface-primary-inverted px-4 py-2 text-content-primary-inverted shadow-[0px_1px_4px_0px_rgba(0,0,0,0.06),0px_1px_3px_0px_rgba(0,0,0,0.05)]\",\n className,\n )}\n {...props}\n />\n </TooltipPrimitive.Portal>\n );\n});\nTooltipContent.displayName = \"TooltipContent\";\n"],"names":["TooltipPrimitive","React","jsx","cn"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAQO,MAAM,kBAAkBA,4BAAiB;AAUzC,MAAM,UAAUA,4BAAiB;AAMjC,MAAM,iBAAiBA,4BAAiB;AA0BxC,MAAM,iBAAiBC,iBAAM,WAGlC,CAAC,EAAE,WAAW,aAAa,GAAG,OAAO,WAAW,MAAM,OAAO,GAAG,MAAA,GAAS,QAAQ;AACjF,MAAI,eAAe;AACnB,MAAI,gBAA4C,SAAS;AACzD,MAAI,WAAW;AACb,UAAM,CAAC,YAAY,WAAW,IAAI,UAAU,MAAM,GAAG;AAIrD,mBAAe;AACf,oBAAgB,eAAe;AAAA,EACjC;AAEA,SACEC,2BAAAA,IAACF,4BAAiB,QAAjB,EACC,UAAAE,2BAAAA;AAAAA,IAACF,4BAAiB;AAAA,IAAjB;AAAA,MACC;AAAA,MACA,MAAM;AAAA,MACN,OAAO;AAAA,MACP;AAAA,MACA,kBAAkB;AAAA,MAClB,OAAO,EAAE,QAAQ,uCAAuC,GAAG,MAAA;AAAA,MAC3D,WAAWG,GAAAA;AAAAA,QACT;AAAA,QACA;AAAA,MAAA;AAAA,MAED,GAAG;AAAA,IAAA;AAAA,EAAA,GAER;AAEJ,CAAC;AACD,eAAe,cAAc;;;;;"}
1
+ {"version":3,"file":"Tooltip.cjs","sources":["../../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["import * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Props for the {@link TooltipProvider}. Wraps Radix `Tooltip.Provider`. */\nexport type TooltipProviderProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider>;\n\n/** Provides tooltip delay and skip-delay context. Wrap your app or a subtree. */\nexport const TooltipProvider = TooltipPrimitive.Provider;\n\n/** Props for the {@link Tooltip} root component. */\nexport interface TooltipProps extends React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root> {\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n defaultOpen?: boolean;\n}\n\n/** Root component that manages open/close state for a single tooltip. */\nexport const Tooltip = TooltipPrimitive.Root;\n\n/** Props for the {@link TooltipTrigger} component. */\nexport type TooltipTriggerProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Trigger>;\n\n/** The element that triggers the tooltip on hover/focus. */\nexport const TooltipTrigger = TooltipPrimitive.Trigger;\n\n/** Position of the tooltip relative to its trigger, combining side and alignment (MUI-style). */\nexport type TooltipPlacement =\n | \"top\"\n | \"top-start\"\n | \"top-end\"\n | \"bottom\"\n | \"bottom-start\"\n | \"bottom-end\"\n | \"left\"\n | \"left-start\"\n | \"left-end\"\n | \"right\"\n | \"right-start\"\n | \"right-end\";\n\nexport interface TooltipContentProps\n extends React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> {\n /**\n * Position of the tooltip relative to the trigger. Takes precedence over `side` and `align`.\n * @default \"top\"\n */\n placement?: TooltipPlacement;\n}\n\nexport const TooltipContent = React.forwardRef<\n React.ComponentRef<typeof TooltipPrimitive.Content>,\n TooltipContentProps\n>(({ className, sideOffset = 8, style, placement, side, align, ...props }, ref) => {\n let resolvedSide = side;\n let resolvedAlign: \"start\" | \"center\" | \"end\" = align ?? \"center\";\n if (placement) {\n const [parsedSide, parsedAlign] = placement.split(\"-\") as [\n \"top\" | \"right\" | \"bottom\" | \"left\",\n \"start\" | \"end\" | undefined,\n ];\n resolvedSide = parsedSide;\n resolvedAlign = parsedAlign ?? \"center\";\n }\n\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n ref={ref}\n side={resolvedSide}\n align={resolvedAlign}\n sideOffset={sideOffset}\n collisionPadding={8}\n style={{ zIndex: \"var(--fanvue-ui-portal-z-index, 50)\", ...style }}\n className={cn(\n \"typography-description-12px-semibold max-w-[320px] rounded-sm bg-surface-primary-inverted px-4 py-2 text-content-primary-inverted shadow-[0px_1px_4px_0px_rgba(0,0,0,0.06),0px_1px_3px_0px_rgba(0,0,0,0.05)]\",\n className,\n )}\n {...props}\n />\n </TooltipPrimitive.Portal>\n );\n});\nTooltipContent.displayName = \"TooltipContent\";\n"],"names":["TooltipPrimitive","React","jsx","cn"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAQO,MAAM,kBAAkBA,4BAAiB;AAUzC,MAAM,UAAUA,4BAAiB;AAMjC,MAAM,iBAAiBA,4BAAiB;AA0BxC,MAAM,iBAAiBC,iBAAM,WAGlC,CAAC,EAAE,WAAW,aAAa,GAAG,OAAO,WAAW,MAAM,OAAO,GAAG,MAAA,GAAS,QAAQ;AACjF,MAAI,eAAe;AACnB,MAAI,gBAA4C,SAAS;AACzD,MAAI,WAAW;AACb,UAAM,CAAC,YAAY,WAAW,IAAI,UAAU,MAAM,GAAG;AAIrD,mBAAe;AACf,oBAAgB,eAAe;AAAA,EACjC;AAEA,SACEC,2BAAAA,IAACF,4BAAiB,QAAjB,EACC,UAAAE,2BAAAA;AAAAA,IAACF,4BAAiB;AAAA,IAAjB;AAAA,MACC;AAAA,MACA,MAAM;AAAA,MACN,OAAO;AAAA,MACP;AAAA,MACA,kBAAkB;AAAA,MAClB,OAAO,EAAE,QAAQ,uCAAuC,GAAG,MAAA;AAAA,MAC3D,WAAWG,GAAAA;AAAAA,QACT;AAAA,QACA;AAAA,MAAA;AAAA,MAED,GAAG;AAAA,IAAA;AAAA,EAAA,GAER;AAEJ,CAAC;AACD,eAAe,cAAc;;;;;"}
@@ -19,7 +19,7 @@ const AccordionContent = React.forwardRef(({ className, children, noPadding, ...
19
19
  {
20
20
  className: cn(
21
21
  "overflow-wrap-anywhere min-w-0",
22
- "typography-regular-body-md text-content-secondary",
22
+ "typography-body-small-14px-regular text-content-secondary",
23
23
  !noPadding && "px-3 pt-2 pb-3"
24
24
  ),
25
25
  children
@@ -1 +1 @@
1
- {"version":3,"file":"AccordionContent.mjs","sources":["../../../src/components/Accordion/AccordionContent.tsx"],"sourcesContent":["import * as AccordionPrimitive from \"@radix-ui/react-accordion\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Props for the {@link AccordionContent} panel component. */\nexport type AccordionContentProps = React.ComponentPropsWithoutRef<\n typeof AccordionPrimitive.Content\n> & {\n /** Remove the default inner padding (`px-3 pb-3`). Useful when you need custom content layout. */\n noPadding?: boolean;\n};\n\n/** Renders the collapsible content panel for an {@link AccordionItem}. Animates open and closed. */\nexport const AccordionContent = React.forwardRef<\n React.ComponentRef<typeof AccordionPrimitive.Content>,\n AccordionContentProps\n>(({ className, children, noPadding, ...props }, ref) => (\n <AccordionPrimitive.Content\n ref={ref}\n className={cn(\n \"overflow-hidden\",\n \"motion-safe:data-[state=closed]:animate-accordion-collapse\",\n \"motion-safe:data-[state=open]:animate-accordion-expand\",\n className,\n )}\n {...props}\n >\n <div\n className={cn(\n \"overflow-wrap-anywhere min-w-0\",\n \"typography-regular-body-md text-content-secondary\",\n !noPadding && \"px-3 pt-2 pb-3\",\n )}\n >\n {children}\n </div>\n </AccordionPrimitive.Content>\n));\n\nAccordionContent.displayName = \"AccordionContent\";\n"],"names":[],"mappings":";;;;;AAaO,MAAM,mBAAmB,MAAM,WAGpC,CAAC,EAAE,WAAW,UAAU,WAAW,GAAG,SAAS,QAC/C;AAAA,EAAC,mBAAmB;AAAA,EAAnB;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,IAED,GAAG;AAAA,IAEJ,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA,CAAC,aAAa;AAAA,QAAA;AAAA,QAGf;AAAA,MAAA;AAAA,IAAA;AAAA,EACH;AACF,CACD;AAED,iBAAiB,cAAc;"}
1
+ {"version":3,"file":"AccordionContent.mjs","sources":["../../../src/components/Accordion/AccordionContent.tsx"],"sourcesContent":["import * as AccordionPrimitive from \"@radix-ui/react-accordion\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Props for the {@link AccordionContent} panel component. */\nexport type AccordionContentProps = React.ComponentPropsWithoutRef<\n typeof AccordionPrimitive.Content\n> & {\n /** Remove the default inner padding (`px-3 pb-3`). Useful when you need custom content layout. */\n noPadding?: boolean;\n};\n\n/** Renders the collapsible content panel for an {@link AccordionItem}. Animates open and closed. */\nexport const AccordionContent = React.forwardRef<\n React.ComponentRef<typeof AccordionPrimitive.Content>,\n AccordionContentProps\n>(({ className, children, noPadding, ...props }, ref) => (\n <AccordionPrimitive.Content\n ref={ref}\n className={cn(\n \"overflow-hidden\",\n \"motion-safe:data-[state=closed]:animate-accordion-collapse\",\n \"motion-safe:data-[state=open]:animate-accordion-expand\",\n className,\n )}\n {...props}\n >\n <div\n className={cn(\n \"overflow-wrap-anywhere min-w-0\",\n \"typography-body-small-14px-regular text-content-secondary\",\n !noPadding && \"px-3 pt-2 pb-3\",\n )}\n >\n {children}\n </div>\n </AccordionPrimitive.Content>\n));\n\nAccordionContent.displayName = \"AccordionContent\";\n"],"names":[],"mappings":";;;;;AAaO,MAAM,mBAAmB,MAAM,WAGpC,CAAC,EAAE,WAAW,UAAU,WAAW,GAAG,SAAS,QAC/C;AAAA,EAAC,mBAAmB;AAAA,EAAnB;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,IAED,GAAG;AAAA,IAEJ,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA,CAAC,aAAa;AAAA,QAAA;AAAA,QAGf;AAAA,MAAA;AAAA,IAAA;AAAA,EACH;AACF,CACD;AAED,iBAAiB,cAAc;"}
@@ -14,11 +14,11 @@ const AccordionTrigger = React.forwardRef(({ className, children, icon, ...props
14
14
  className: cn(
15
15
  "flex flex-1 items-center justify-between gap-3",
16
16
  "rounded-sm px-3 py-3",
17
- "typography-semibold-body-md text-content-primary",
17
+ "typography-body-small-14px-semibold text-content-primary",
18
18
  "cursor-pointer",
19
19
  "motion-safe:transition-colors motion-safe:duration-200 motion-safe:ease-in-out",
20
20
  "hover:bg-neutral-alphas-100",
21
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-interaction-focus focus-visible:ring-offset-2 focus-visible:ring-offset-bg-primary",
21
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-interaction-focus focus-visible:ring-offset-2 focus-visible:ring-offset-background-primary",
22
22
  "data-disabled:pointer-events-none data-disabled:opacity-50",
23
23
  className
24
24
  ),
@@ -1 +1 @@
1
- {"version":3,"file":"AccordionTrigger.mjs","sources":["../../../src/components/Accordion/AccordionTrigger.tsx"],"sourcesContent":["import * as AccordionPrimitive from \"@radix-ui/react-accordion\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { ChevronDownIcon } from \"../Icons/ChevronDownIcon\";\n\n/** Props for the {@link AccordionTrigger} button component. */\nexport type AccordionTriggerProps = React.ComponentPropsWithoutRef<\n typeof AccordionPrimitive.Trigger\n> & {\n /** Custom icon element. Defaults to `ChevronDownIcon`. Pass `null` to suppress the icon entirely. */\n icon?: React.ReactNode | null;\n};\n\n/** An interactive button that toggles the visibility of its associated {@link AccordionContent} panel. */\nexport const AccordionTrigger = React.forwardRef<\n React.ComponentRef<typeof AccordionPrimitive.Trigger>,\n AccordionTriggerProps\n>(({ className, children, icon, ...props }, ref) => {\n const showIcon = icon !== null;\n const iconElement =\n icon === undefined ? (\n <ChevronDownIcon className=\"size-4 shrink-0 text-content-secondary\" />\n ) : (\n icon\n );\n\n return (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n ref={ref}\n className={cn(\n \"flex flex-1 items-center justify-between gap-3\",\n \"rounded-sm px-3 py-3\",\n \"typography-semibold-body-md text-content-primary\",\n \"cursor-pointer\",\n \"motion-safe:transition-colors motion-safe:duration-200 motion-safe:ease-in-out\",\n \"hover:bg-neutral-alphas-100\",\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 \"data-disabled:pointer-events-none data-disabled:opacity-50\",\n className,\n )}\n {...props}\n >\n <span className=\"min-w-0 flex-1 truncate text-left\">{children}</span>\n {showIcon && (\n <span className=\"shrink-0 motion-safe:transition-transform motion-safe:duration-200 [[data-state=open]>&]:rotate-180\">\n {iconElement}\n </span>\n )}\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n );\n});\n\nAccordionTrigger.displayName = \"AccordionTrigger\";\n"],"names":[],"mappings":";;;;;;AAcO,MAAM,mBAAmB,MAAM,WAGpC,CAAC,EAAE,WAAW,UAAU,MAAM,GAAG,MAAA,GAAS,QAAQ;AAClD,QAAM,WAAW,SAAS;AAC1B,QAAM,cACJ,SAAS,6BACN,iBAAA,EAAgB,WAAU,0CAAyC,IAEpE;AAGJ,SACE,oBAAC,mBAAmB,QAAnB,EAA0B,WAAU,QACnC,UAAA;AAAA,IAAC,mBAAmB;AAAA,IAAnB;AAAA,MACC;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,MAED,GAAG;AAAA,MAEJ,UAAA;AAAA,QAAA,oBAAC,QAAA,EAAK,WAAU,qCAAqC,SAAA,CAAS;AAAA,QAC7D,YACC,oBAAC,QAAA,EAAK,WAAU,uGACb,UAAA,YAAA,CACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,GAGN;AAEJ,CAAC;AAED,iBAAiB,cAAc;"}
1
+ {"version":3,"file":"AccordionTrigger.mjs","sources":["../../../src/components/Accordion/AccordionTrigger.tsx"],"sourcesContent":["import * as AccordionPrimitive from \"@radix-ui/react-accordion\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { ChevronDownIcon } from \"../Icons/ChevronDownIcon\";\n\n/** Props for the {@link AccordionTrigger} button component. */\nexport type AccordionTriggerProps = React.ComponentPropsWithoutRef<\n typeof AccordionPrimitive.Trigger\n> & {\n /** Custom icon element. Defaults to `ChevronDownIcon`. Pass `null` to suppress the icon entirely. */\n icon?: React.ReactNode | null;\n};\n\n/** An interactive button that toggles the visibility of its associated {@link AccordionContent} panel. */\nexport const AccordionTrigger = React.forwardRef<\n React.ComponentRef<typeof AccordionPrimitive.Trigger>,\n AccordionTriggerProps\n>(({ className, children, icon, ...props }, ref) => {\n const showIcon = icon !== null;\n const iconElement =\n icon === undefined ? (\n <ChevronDownIcon className=\"size-4 shrink-0 text-content-secondary\" />\n ) : (\n icon\n );\n\n return (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n ref={ref}\n className={cn(\n \"flex flex-1 items-center justify-between gap-3\",\n \"rounded-sm px-3 py-3\",\n \"typography-body-small-14px-semibold text-content-primary\",\n \"cursor-pointer\",\n \"motion-safe:transition-colors motion-safe:duration-200 motion-safe:ease-in-out\",\n \"hover:bg-neutral-alphas-100\",\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 \"data-disabled:pointer-events-none data-disabled:opacity-50\",\n className,\n )}\n {...props}\n >\n <span className=\"min-w-0 flex-1 truncate text-left\">{children}</span>\n {showIcon && (\n <span className=\"shrink-0 motion-safe:transition-transform motion-safe:duration-200 [[data-state=open]>&]:rotate-180\">\n {iconElement}\n </span>\n )}\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n );\n});\n\nAccordionTrigger.displayName = \"AccordionTrigger\";\n"],"names":[],"mappings":";;;;;;AAcO,MAAM,mBAAmB,MAAM,WAGpC,CAAC,EAAE,WAAW,UAAU,MAAM,GAAG,MAAA,GAAS,QAAQ;AAClD,QAAM,WAAW,SAAS;AAC1B,QAAM,cACJ,SAAS,6BACN,iBAAA,EAAgB,WAAU,0CAAyC,IAEpE;AAGJ,SACE,oBAAC,mBAAmB,QAAnB,EAA0B,WAAU,QACnC,UAAA;AAAA,IAAC,mBAAmB;AAAA,IAAnB;AAAA,MACC;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,MAED,GAAG;AAAA,MAEJ,UAAA;AAAA,QAAA,oBAAC,QAAA,EAAK,WAAU,qCAAqC,SAAA,CAAS;AAAA,QAC7D,YACC,oBAAC,QAAA,EAAK,WAAU,uGACb,UAAA,YAAA,CACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,GAGN;AAEJ,CAAC;AAED,iBAAiB,cAAc;"}
@@ -56,8 +56,8 @@ const Alert = React.forwardRef(
56
56
  children: [
57
57
  resolvedIcon && /* @__PURE__ */ jsx("span", { className: "flex shrink-0 items-start h-full", "aria-hidden": "true", children: resolvedIcon }),
58
58
  /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-2", children: [
59
- title && /* @__PURE__ */ jsx("div", { className: "typography-semibold-body-md text-content-primary", children: title }),
60
- /* @__PURE__ */ jsx("div", { className: "typography-regular-body-md text-content-primary", children })
59
+ title && /* @__PURE__ */ jsx("div", { className: "typography-body-small-14px-semibold text-content-primary", children: title }),
60
+ /* @__PURE__ */ jsx("div", { className: "typography-body-small-14px-regular text-content-primary", children })
61
61
  ] }),
62
62
  closable && /* @__PURE__ */ jsx(
63
63
  Button,
@@ -1 +1 @@
1
- {"version":3,"file":"Alert.mjs","sources":["../../../src/components/Alert/Alert.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../Button/Button\";\nimport { CheckCircleIcon } from \"../Icons/CheckCircleIcon\";\nimport { CrossIcon } from \"../Icons/CrossIcon\";\nimport { ErrorCircleIcon } from \"../Icons/ErrorCircleIcon\";\nimport { InfoCircleIcon } from \"../Icons/InfoCircleIcon\";\nimport { WarningTriangleIcon } from \"../Icons/WarningTriangleIcon\";\n\n/** Visual style variant of the alert. */\nexport type AlertVariant = \"info\" | \"success\" | \"warning\" | \"error\";\n\nconst DEFAULT_ICONS: Record<AlertVariant, React.ReactNode> = {\n info: <InfoCircleIcon />,\n success: <CheckCircleIcon />,\n warning: <WarningTriangleIcon />,\n error: <ErrorCircleIcon />,\n};\n\nexport interface AlertProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Visual style variant of the alert. @default \"info\" */\n variant?: AlertVariant;\n /** Optional title text displayed in bold above the description. */\n title?: string;\n /** Custom icon override. Pass `null` to hide the icon entirely. Each variant shows a default icon when left `undefined`. */\n icon?: React.ReactNode | null;\n /** Whether to show the close button. @default false */\n closable?: boolean;\n /** Callback fired when the close button is clicked. */\n onClose?: () => void;\n /** Accessible label for the close button. @default \"Close alert\" */\n closeLabel?: string;\n}\n\nconst CLOSE_BUTTON_CLASSES: Record<AlertVariant, string> = {\n info: \"hover:bg-info-content/10 active:bg-info-content/20 text-info-content motion-safe:transition-colors motion-safe:duration-150\",\n success:\n \"hover:bg-success-content/10 active:bg-success-content/20 text-success-content motion-safe:transition-colors motion-safe:duration-150\",\n warning:\n \"hover:bg-warning-content/10 active:bg-warning-content/20 text-warning-content motion-safe:transition-colors motion-safe:duration-150\",\n error:\n \"hover:bg-error-content/10 active:bg-error-content/20 text-error-content motion-safe:transition-colors motion-safe:duration-150\",\n};\n\n/**\n * Displays a contextual feedback message to the user.\n *\n * Supports `info`, `success`, `warning`, and `error` variants with a default\n * icon per variant, optional title, description, and dismiss button.\n *\n * Each variant renders a default icon automatically. Pass a custom `icon` to\n * override, or `icon={null}` to hide the icon entirely.\n *\n * @example\n * ```tsx\n * <Alert variant=\"success\" title=\"Saved\" closable onClose={handleClose}>\n * Your changes have been saved.\n * </Alert>\n * ```\n */\nexport const Alert = React.forwardRef<HTMLDivElement, AlertProps>(\n (\n {\n className,\n variant = \"info\",\n title,\n icon,\n closable = false,\n onClose,\n closeLabel = \"Close alert\",\n children,\n ...props\n },\n ref,\n ) => {\n const resolvedIcon = icon === null ? null : (icon ?? DEFAULT_ICONS[variant]);\n\n return (\n <div\n ref={ref}\n role=\"alert\"\n data-testid=\"alert\"\n className={cn(\n \"grid gap-x-3 rounded-xs p-4 text-sm leading-[18px]\",\n resolvedIcon && closable && \"grid-cols-[auto_1fr_auto]\",\n resolvedIcon && !closable && \"grid-cols-[auto_1fr]\",\n !resolvedIcon && closable && \"grid-cols-[1fr_auto]\",\n !resolvedIcon && !closable && \"grid-cols-[1fr]\",\n title && children ? \"items-start\" : \"items-center\",\n variant === \"info\" && \"bg-info-surface text-info-content\",\n variant === \"success\" && \"bg-success-surface text-success-content\",\n variant === \"warning\" && \"bg-warning-surface text-warning-content\",\n variant === \"error\" && \"bg-error-surface text-error-content\",\n className,\n )}\n {...props}\n >\n {resolvedIcon && (\n <span className=\"flex shrink-0 items-start h-full\" aria-hidden=\"true\">\n {resolvedIcon}\n </span>\n )}\n\n <div className=\"flex min-w-0 flex-col gap-2\">\n {title && <div className=\"typography-semibold-body-md text-content-primary\">{title}</div>}\n <div className=\"typography-regular-body-md text-content-primary\">{children}</div>\n </div>\n\n {closable && (\n <Button\n variant=\"tertiary\"\n size=\"24\"\n onClick={onClose}\n className={cn(\"self-start px-0\", CLOSE_BUTTON_CLASSES[variant])}\n aria-label={closeLabel}\n >\n <CrossIcon />\n </Button>\n )}\n </div>\n );\n },\n);\n\nAlert.displayName = \"Alert\";\n"],"names":[],"mappings":";;;;;;;;;;AAYA,MAAM,gBAAuD;AAAA,EAC3D,0BAAO,gBAAA,EAAe;AAAA,EACtB,6BAAU,iBAAA,EAAgB;AAAA,EAC1B,6BAAU,qBAAA,EAAoB;AAAA,EAC9B,2BAAQ,iBAAA,CAAA,CAAgB;AAC1B;AAiBA,MAAM,uBAAqD;AAAA,EACzD,MAAM;AAAA,EACN,SACE;AAAA,EACF,SACE;AAAA,EACF,OACE;AACJ;AAkBO,MAAM,QAAQ,MAAM;AAAA,EACzB,CACE;AAAA,IACE;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA,aAAa;AAAA,IACb;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,eAAe,SAAS,OAAO,OAAQ,QAAQ,cAAc,OAAO;AAE1E,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,MAAK;AAAA,QACL,eAAY;AAAA,QACZ,WAAW;AAAA,UACT;AAAA,UACA,gBAAgB,YAAY;AAAA,UAC5B,gBAAgB,CAAC,YAAY;AAAA,UAC7B,CAAC,gBAAgB,YAAY;AAAA,UAC7B,CAAC,gBAAgB,CAAC,YAAY;AAAA,UAC9B,SAAS,WAAW,gBAAgB;AAAA,UACpC,YAAY,UAAU;AAAA,UACtB,YAAY,aAAa;AAAA,UACzB,YAAY,aAAa;AAAA,UACzB,YAAY,WAAW;AAAA,UACvB;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA,oCACE,QAAA,EAAK,WAAU,oCAAmC,eAAY,QAC5D,UAAA,cACH;AAAA,UAGF,qBAAC,OAAA,EAAI,WAAU,+BACZ,UAAA;AAAA,YAAA,SAAS,oBAAC,OAAA,EAAI,WAAU,oDAAoD,UAAA,OAAM;AAAA,YACnF,oBAAC,OAAA,EAAI,WAAU,mDAAmD,SAAA,CAAS;AAAA,UAAA,GAC7E;AAAA,UAEC,YACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,SAAS;AAAA,cACT,WAAW,GAAG,mBAAmB,qBAAqB,OAAO,CAAC;AAAA,cAC9D,cAAY;AAAA,cAEZ,8BAAC,WAAA,CAAA,CAAU;AAAA,YAAA;AAAA,UAAA;AAAA,QACb;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,MAAM,cAAc;"}
1
+ {"version":3,"file":"Alert.mjs","sources":["../../../src/components/Alert/Alert.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../Button/Button\";\nimport { CheckCircleIcon } from \"../Icons/CheckCircleIcon\";\nimport { CrossIcon } from \"../Icons/CrossIcon\";\nimport { ErrorCircleIcon } from \"../Icons/ErrorCircleIcon\";\nimport { InfoCircleIcon } from \"../Icons/InfoCircleIcon\";\nimport { WarningTriangleIcon } from \"../Icons/WarningTriangleIcon\";\n\n/** Visual style variant of the alert. */\nexport type AlertVariant = \"info\" | \"success\" | \"warning\" | \"error\";\n\nconst DEFAULT_ICONS: Record<AlertVariant, React.ReactNode> = {\n info: <InfoCircleIcon />,\n success: <CheckCircleIcon />,\n warning: <WarningTriangleIcon />,\n error: <ErrorCircleIcon />,\n};\n\nexport interface AlertProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Visual style variant of the alert. @default \"info\" */\n variant?: AlertVariant;\n /** Optional title text displayed in bold above the description. */\n title?: string;\n /** Custom icon override. Pass `null` to hide the icon entirely. Each variant shows a default icon when left `undefined`. */\n icon?: React.ReactNode | null;\n /** Whether to show the close button. @default false */\n closable?: boolean;\n /** Callback fired when the close button is clicked. */\n onClose?: () => void;\n /** Accessible label for the close button. @default \"Close alert\" */\n closeLabel?: string;\n}\n\nconst CLOSE_BUTTON_CLASSES: Record<AlertVariant, string> = {\n info: \"hover:bg-info-content/10 active:bg-info-content/20 text-info-content motion-safe:transition-colors motion-safe:duration-150\",\n success:\n \"hover:bg-success-content/10 active:bg-success-content/20 text-success-content motion-safe:transition-colors motion-safe:duration-150\",\n warning:\n \"hover:bg-warning-content/10 active:bg-warning-content/20 text-warning-content motion-safe:transition-colors motion-safe:duration-150\",\n error:\n \"hover:bg-error-content/10 active:bg-error-content/20 text-error-content motion-safe:transition-colors motion-safe:duration-150\",\n};\n\n/**\n * Displays a contextual feedback message to the user.\n *\n * Supports `info`, `success`, `warning`, and `error` variants with a default\n * icon per variant, optional title, description, and dismiss button.\n *\n * Each variant renders a default icon automatically. Pass a custom `icon` to\n * override, or `icon={null}` to hide the icon entirely.\n *\n * @example\n * ```tsx\n * <Alert variant=\"success\" title=\"Saved\" closable onClose={handleClose}>\n * Your changes have been saved.\n * </Alert>\n * ```\n */\nexport const Alert = React.forwardRef<HTMLDivElement, AlertProps>(\n (\n {\n className,\n variant = \"info\",\n title,\n icon,\n closable = false,\n onClose,\n closeLabel = \"Close alert\",\n children,\n ...props\n },\n ref,\n ) => {\n const resolvedIcon = icon === null ? null : (icon ?? DEFAULT_ICONS[variant]);\n\n return (\n <div\n ref={ref}\n role=\"alert\"\n data-testid=\"alert\"\n className={cn(\n \"grid gap-x-3 rounded-xs p-4 text-sm leading-[18px]\",\n resolvedIcon && closable && \"grid-cols-[auto_1fr_auto]\",\n resolvedIcon && !closable && \"grid-cols-[auto_1fr]\",\n !resolvedIcon && closable && \"grid-cols-[1fr_auto]\",\n !resolvedIcon && !closable && \"grid-cols-[1fr]\",\n title && children ? \"items-start\" : \"items-center\",\n variant === \"info\" && \"bg-info-surface text-info-content\",\n variant === \"success\" && \"bg-success-surface text-success-content\",\n variant === \"warning\" && \"bg-warning-surface text-warning-content\",\n variant === \"error\" && \"bg-error-surface text-error-content\",\n className,\n )}\n {...props}\n >\n {resolvedIcon && (\n <span className=\"flex shrink-0 items-start h-full\" aria-hidden=\"true\">\n {resolvedIcon}\n </span>\n )}\n\n <div className=\"flex min-w-0 flex-col gap-2\">\n {title && (\n <div className=\"typography-body-small-14px-semibold text-content-primary\">{title}</div>\n )}\n <div className=\"typography-body-small-14px-regular text-content-primary\">{children}</div>\n </div>\n\n {closable && (\n <Button\n variant=\"tertiary\"\n size=\"24\"\n onClick={onClose}\n className={cn(\"self-start px-0\", CLOSE_BUTTON_CLASSES[variant])}\n aria-label={closeLabel}\n >\n <CrossIcon />\n </Button>\n )}\n </div>\n );\n },\n);\n\nAlert.displayName = \"Alert\";\n"],"names":[],"mappings":";;;;;;;;;;AAYA,MAAM,gBAAuD;AAAA,EAC3D,0BAAO,gBAAA,EAAe;AAAA,EACtB,6BAAU,iBAAA,EAAgB;AAAA,EAC1B,6BAAU,qBAAA,EAAoB;AAAA,EAC9B,2BAAQ,iBAAA,CAAA,CAAgB;AAC1B;AAiBA,MAAM,uBAAqD;AAAA,EACzD,MAAM;AAAA,EACN,SACE;AAAA,EACF,SACE;AAAA,EACF,OACE;AACJ;AAkBO,MAAM,QAAQ,MAAM;AAAA,EACzB,CACE;AAAA,IACE;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA,aAAa;AAAA,IACb;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,eAAe,SAAS,OAAO,OAAQ,QAAQ,cAAc,OAAO;AAE1E,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,MAAK;AAAA,QACL,eAAY;AAAA,QACZ,WAAW;AAAA,UACT;AAAA,UACA,gBAAgB,YAAY;AAAA,UAC5B,gBAAgB,CAAC,YAAY;AAAA,UAC7B,CAAC,gBAAgB,YAAY;AAAA,UAC7B,CAAC,gBAAgB,CAAC,YAAY;AAAA,UAC9B,SAAS,WAAW,gBAAgB;AAAA,UACpC,YAAY,UAAU;AAAA,UACtB,YAAY,aAAa;AAAA,UACzB,YAAY,aAAa;AAAA,UACzB,YAAY,WAAW;AAAA,UACvB;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA,oCACE,QAAA,EAAK,WAAU,oCAAmC,eAAY,QAC5D,UAAA,cACH;AAAA,UAGF,qBAAC,OAAA,EAAI,WAAU,+BACZ,UAAA;AAAA,YAAA,SACC,oBAAC,OAAA,EAAI,WAAU,4DAA4D,UAAA,OAAM;AAAA,YAEnF,oBAAC,OAAA,EAAI,WAAU,2DAA2D,SAAA,CAAS;AAAA,UAAA,GACrF;AAAA,UAEC,YACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,SAAS;AAAA,cACT,WAAW,GAAG,mBAAmB,qBAAqB,OAAO,CAAC;AAAA,cAC9D,cAAY;AAAA,cAEZ,8BAAC,WAAA,CAAA,CAAU;AAAA,YAAA;AAAA,UAAA;AAAA,QACb;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,MAAM,cAAc;"}
@@ -151,7 +151,7 @@ const AudioUpload = React.forwardRef(
151
151
  /* @__PURE__ */ jsx(
152
152
  "div",
153
153
  {
154
- className: "flex size-[72px] items-center justify-center rounded-full bg-buttons-primary",
154
+ className: "flex size-[72px] items-center justify-center rounded-full bg-buttons-primary-default",
155
155
  "aria-hidden": "true",
156
156
  children: /* @__PURE__ */ jsx(MicrophoneIcon, { className: "size-5 text-content-primary-inverted" })
157
157
  }
@@ -161,7 +161,7 @@ const AudioUpload = React.forwardRef(
161
161
  {
162
162
  role: "timer",
163
163
  "aria-label": "Recording time",
164
- className: "typography-regular-body-lg text-content-primary",
164
+ className: "typography-body-default-16px-regular text-content-primary",
165
165
  children: [
166
166
  formattedElapsed,
167
167
  " / ",
@@ -184,7 +184,7 @@ const AudioUpload = React.forwardRef(
184
184
  ref: stopButtonRef,
185
185
  type: "button",
186
186
  onClick: handleStopClick,
187
- className: "mt-1 flex size-11 items-center justify-center rounded-full bg-error-content text-content-on-brand-inverted transition-colors hover:bg-error-content/80 focus:shadow-focus-ring focus-visible:outline-none",
187
+ className: "mt-1 flex size-11 items-center justify-center rounded-full bg-error-content text-content-always-white transition-colors hover:bg-error-content/80 focus:shadow-focus-ring focus-visible:outline-none",
188
188
  "aria-label": stopButtonAriaLabel,
189
189
  children: /* @__PURE__ */ jsx(StopIcon, { className: "size-5" })
190
190
  }
@@ -236,12 +236,12 @@ const AudioUpload = React.forwardRef(
236
236
  className: "flex cursor-pointer flex-col items-center gap-2 rounded-xs px-2 py-1 peer-focus-visible:shadow-focus-ring",
237
237
  children: [
238
238
  /* @__PURE__ */ jsx(UploadCloudIcon, { className: "size-5 text-content-primary" }),
239
- /* @__PURE__ */ jsx("span", { className: "typography-semibold-body-lg text-center text-content-primary", children: uploadTitle }),
239
+ /* @__PURE__ */ jsx("span", { className: "typography-body-default-16px-semibold text-center text-content-primary", children: uploadTitle }),
240
240
  /* @__PURE__ */ jsx(
241
241
  "span",
242
242
  {
243
243
  id: descriptionId,
244
- className: "typography-regular-body-md text-center text-content-primary",
244
+ className: "typography-body-small-14px-regular text-center text-content-primary",
245
245
  children: uploadDescription
246
246
  }
247
247
  )
@@ -249,7 +249,7 @@ const AudioUpload = React.forwardRef(
249
249
  }
250
250
  ),
251
251
  allowRecording && isRecordingSupported && /* @__PURE__ */ jsxs(Fragment, { children: [
252
- /* @__PURE__ */ jsx("p", { className: "typography-regular-body-md text-center text-content-primary", children: separatorText }),
252
+ /* @__PURE__ */ jsx("p", { className: "typography-body-small-14px-regular text-center text-content-primary", children: separatorText }),
253
253
  /* @__PURE__ */ jsx(
254
254
  Button,
255
255
  {
@@ -1 +1 @@
1
- {"version":3,"file":"AudioUpload.mjs","sources":["../../../src/components/AudioUpload/AudioUpload.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport { Button } from \"../Button/Button\";\nimport { MicrophoneIcon } from \"../Icons/MicrophoneIcon\";\nimport { StopIcon } from \"../Icons/StopIcon\";\nimport { UploadCloudIcon } from \"../Icons/UploadCloudIcon\";\nimport { AudioWaveform } from \"./AudioWaveform\";\nimport { type AudioValidationError, formatAudioTime, validateAudioFile } from \"./audioUtils\";\nimport {\n DEFAULT_ACCEPTED_TYPES,\n DEFAULT_MAX_FILE_SIZE,\n DEFAULT_MAX_RECORDING_DURATION,\n DEFAULT_MIN_RECORDING_DURATION,\n} from \"./constants\";\nimport { useAudioRecorder } from \"./useAudioRecorder\";\n\n/** A file that was rejected during drop or browse, along with the reasons. */\nexport interface AudioFileRejection {\n /** The rejected file. */\n file: File;\n /** One or more validation errors explaining why the file was rejected. */\n errors: AudioValidationError[];\n}\n\nexport interface AudioUploadProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"onDrop\"> {\n /** Maximum file size in bytes. @default 10_485_760 (10MB) */\n maxFileSize?: number;\n /** Accepted audio MIME types. @default DEFAULT_ACCEPTED_TYPES */\n accept?: readonly string[];\n /** Maximum number of files per drop. @default 1 */\n maxFiles?: number;\n /** Whether to show the record audio button. @default true */\n allowRecording?: boolean;\n /** Maximum recording duration in seconds. @default 30 */\n maxRecordingDuration?: number;\n /** Minimum recording duration in seconds. @default 5 */\n minRecordingDuration?: number;\n\n /** Called when valid files are accepted via drop or browse */\n onFilesAccepted?: (files: File[]) => void;\n /** Called when files are rejected (wrong type, too large, etc.) */\n onFilesRejected?: (rejections: AudioFileRejection[]) => void;\n /** Called when a recording completes and meets minimum duration */\n onRecordingComplete?: (blob: Blob, durationMs: number) => void;\n /** Called when recording is stopped but does not meet minimum duration */\n onRecordingTooShort?: (durationMs: number, minDurationMs: number) => void;\n /** Called when microphone permission is denied or unavailable */\n onPermissionError?: (error: Error) => void;\n /** Called when an unexpected recording error occurs */\n onRecordingError?: (error: Error) => void;\n\n /** Upload area title text. @default \"Click to upload, or drag & drop\" */\n uploadTitle?: string;\n /** Upload area description text. @default \"Audio files only, up to 10MB each\" */\n uploadDescription?: string;\n /** Separator text between upload and record. @default \"or\" */\n separatorText?: string;\n /** Record button label. @default \"Record audio\" */\n recordButtonLabel?: string;\n /** Stop recording button aria-label. @default \"Stop recording\" */\n stopButtonAriaLabel?: string;\n\n /** Whether the component is disabled. @default false */\n disabled?: boolean;\n}\n\nfunction partitionFiles(\n files: File[],\n maxFileSize: number,\n accept: readonly string[],\n maxFiles: number,\n): { accepted: File[]; rejected: AudioFileRejection[] } {\n const accepted: File[] = [];\n const rejected: AudioFileRejection[] = [];\n\n for (const file of files) {\n const errors = validateAudioFile(file, { maxFileSize, acceptedTypes: accept });\n if (errors.length > 0) {\n rejected.push({ file, errors });\n } else {\n accepted.push(file);\n }\n }\n\n if (maxFiles > 0 && accepted.length > maxFiles) {\n const excess = accepted.splice(maxFiles);\n for (const file of excess) {\n rejected.push({\n file,\n errors: [{ code: \"too-many-files\", message: `Too many files. Maximum is ${maxFiles}` }],\n });\n }\n }\n\n return { accepted, rejected };\n}\n\n/**\n * Audio file upload with drag-and-drop and optional in-browser recording.\n * Supports file validation, multiple files, and real-time waveform visualization during recording.\n *\n * @example\n * ```tsx\n * <AudioUpload\n * onFilesAccepted={(files) => console.log(files)}\n * onRecordingComplete={(blob, duration) => console.log(blob, duration)}\n * />\n * ```\n */\nexport const AudioUpload = React.forwardRef<HTMLDivElement, AudioUploadProps>(\n (\n {\n className,\n maxFileSize = DEFAULT_MAX_FILE_SIZE,\n accept = DEFAULT_ACCEPTED_TYPES,\n maxFiles = 1,\n allowRecording = true,\n maxRecordingDuration = DEFAULT_MAX_RECORDING_DURATION,\n minRecordingDuration = DEFAULT_MIN_RECORDING_DURATION,\n onFilesAccepted,\n onFilesRejected,\n onRecordingComplete,\n onRecordingTooShort,\n onPermissionError,\n onRecordingError,\n uploadTitle = \"Click to upload, or drag & drop\",\n uploadDescription = \"Audio files only, up to 10MB each\",\n separatorText = \"or\",\n recordButtonLabel = \"Record audio\",\n stopButtonAriaLabel = \"Stop recording\",\n disabled = false,\n ...props\n },\n ref,\n ) => {\n const inputId = React.useId();\n const descriptionId = React.useId();\n const [isDragActive, setIsDragActive] = React.useState(false);\n const stopButtonRef = React.useRef<HTMLButtonElement>(null);\n\n const {\n isRecording,\n elapsedMs,\n startRecording,\n stopRecording,\n analyserNode,\n isSupported: isRecordingSupported,\n } = useAudioRecorder({\n maxDuration: maxRecordingDuration,\n minDuration: minRecordingDuration,\n onComplete: onRecordingComplete,\n onTooShort: onRecordingTooShort,\n onPermissionError,\n onError: onRecordingError,\n });\n\n const acceptString = accept.join(\",\");\n\n // Move focus to stop button when recording starts\n React.useEffect(() => {\n if (isRecording) {\n stopButtonRef.current?.focus();\n }\n }, [isRecording]);\n\n const validateAndAcceptFiles = React.useCallback(\n (files: FileList | File[]) => {\n const { accepted, rejected } = partitionFiles(\n Array.from(files),\n maxFileSize,\n accept,\n maxFiles,\n );\n if (accepted.length > 0) onFilesAccepted?.(accepted);\n if (rejected.length > 0) onFilesRejected?.(rejected);\n },\n [maxFileSize, accept, maxFiles, onFilesAccepted, onFilesRejected],\n );\n\n const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragActive(false);\n\n if (disabled) return;\n\n const { files } = e.dataTransfer;\n if (files.length > 0) {\n validateAndAcceptFiles(files);\n }\n };\n\n const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n e.stopPropagation();\n if (!disabled) {\n setIsDragActive(true);\n }\n };\n\n const handleDragLeave = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragActive(false);\n };\n\n const handleFileInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const { files } = e.target;\n if (files && files.length > 0) {\n validateAndAcceptFiles(files);\n }\n // Reset input so same file can be selected again\n e.target.value = \"\";\n };\n\n const handleRecordClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n startRecording();\n };\n\n const handleStopClick = () => {\n stopRecording();\n };\n\n if (isRecording) {\n const formattedElapsed = formatAudioTime(elapsedMs);\n\n return (\n // biome-ignore lint/a11y/useSemanticElements: <fieldset> would break the public HTMLDivElement ref/props API\n <div\n ref={ref}\n role=\"group\"\n aria-label=\"Audio recording in progress\"\n data-testid=\"audio-upload\"\n data-state=\"recording\"\n className={cn(\n \"flex flex-col items-center justify-center gap-2 rounded-md bg-surface-secondary px-4 py-3\",\n className,\n )}\n {...props}\n >\n <div className=\"flex flex-1 flex-col items-center gap-2\">\n <div\n className=\"flex size-[72px] items-center justify-center rounded-full bg-buttons-primary\"\n aria-hidden=\"true\"\n >\n <MicrophoneIcon className=\"size-5 text-content-primary-inverted\" />\n </div>\n\n <p\n role=\"timer\"\n aria-label=\"Recording time\"\n className=\"typography-regular-body-lg text-content-primary\"\n >\n {formattedElapsed} / {formatAudioTime(maxRecordingDuration * 1000)}\n </p>\n </div>\n\n <div className=\"flex w-full items-center gap-2.5\" aria-hidden=\"true\">\n <AudioWaveform\n analyserNode={analyserNode}\n isRecording={isRecording}\n className=\"flex-1\"\n />\n </div>\n\n <button\n ref={stopButtonRef}\n type=\"button\"\n onClick={handleStopClick}\n className=\"mt-1 flex size-11 items-center justify-center rounded-full bg-error-content text-content-on-brand-inverted transition-colors hover:bg-error-content/80 focus:shadow-focus-ring focus-visible:outline-none\"\n aria-label={stopButtonAriaLabel}\n >\n <StopIcon className=\"size-5\" />\n </button>\n </div>\n );\n }\n\n return (\n // biome-ignore lint/a11y/useSemanticElements: <fieldset> would break the public HTMLDivElement ref/props API\n <div\n ref={ref}\n role=\"group\"\n aria-label=\"Audio upload\"\n data-testid=\"audio-upload\"\n data-state=\"idle\"\n aria-disabled={disabled || undefined}\n onDrop={handleDrop}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n className={cn(\n \"flex flex-col items-center justify-center gap-2 rounded-md bg-surface-secondary px-4 py-3 transition-colors\",\n isDragActive && \"bg-brand-primary-muted ring-2 ring-brand-primary-default\",\n disabled && \"pointer-events-none opacity-50\",\n className,\n )}\n {...props}\n >\n <input\n id={inputId}\n type=\"file\"\n accept={acceptString}\n multiple={maxFiles > 1}\n onChange={handleFileInputChange}\n className=\"peer sr-only\"\n disabled={disabled}\n aria-describedby={descriptionId}\n />\n\n <label\n htmlFor={inputId}\n className=\"flex cursor-pointer flex-col items-center gap-2 rounded-xs px-2 py-1 peer-focus-visible:shadow-focus-ring\"\n >\n <UploadCloudIcon className=\"size-5 text-content-primary\" />\n\n <span className=\"typography-semibold-body-lg text-center text-content-primary\">\n {uploadTitle}\n </span>\n\n <span\n id={descriptionId}\n className=\"typography-regular-body-md text-center text-content-primary\"\n >\n {uploadDescription}\n </span>\n </label>\n\n {allowRecording && isRecordingSupported && (\n <>\n <p className=\"typography-regular-body-md text-center text-content-primary\">\n {separatorText}\n </p>\n\n <Button\n variant=\"brand\"\n size=\"40\"\n leftIcon={<MicrophoneIcon className=\"size-5\" />}\n onClick={handleRecordClick}\n disabled={disabled}\n type=\"button\"\n >\n {recordButtonLabel}\n </Button>\n </>\n )}\n </div>\n );\n },\n);\n\nAudioUpload.displayName = \"AudioUpload\";\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AudioUpload.mjs","sources":["../../../src/components/AudioUpload/AudioUpload.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport { Button } from \"../Button/Button\";\nimport { MicrophoneIcon } from \"../Icons/MicrophoneIcon\";\nimport { StopIcon } from \"../Icons/StopIcon\";\nimport { UploadCloudIcon } from \"../Icons/UploadCloudIcon\";\nimport { AudioWaveform } from \"./AudioWaveform\";\nimport { type AudioValidationError, formatAudioTime, validateAudioFile } from \"./audioUtils\";\nimport {\n DEFAULT_ACCEPTED_TYPES,\n DEFAULT_MAX_FILE_SIZE,\n DEFAULT_MAX_RECORDING_DURATION,\n DEFAULT_MIN_RECORDING_DURATION,\n} from \"./constants\";\nimport { useAudioRecorder } from \"./useAudioRecorder\";\n\n/** A file that was rejected during drop or browse, along with the reasons. */\nexport interface AudioFileRejection {\n /** The rejected file. */\n file: File;\n /** One or more validation errors explaining why the file was rejected. */\n errors: AudioValidationError[];\n}\n\nexport interface AudioUploadProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"onDrop\"> {\n /** Maximum file size in bytes. @default 10_485_760 (10MB) */\n maxFileSize?: number;\n /** Accepted audio MIME types. @default DEFAULT_ACCEPTED_TYPES */\n accept?: readonly string[];\n /** Maximum number of files per drop. @default 1 */\n maxFiles?: number;\n /** Whether to show the record audio button. @default true */\n allowRecording?: boolean;\n /** Maximum recording duration in seconds. @default 30 */\n maxRecordingDuration?: number;\n /** Minimum recording duration in seconds. @default 5 */\n minRecordingDuration?: number;\n\n /** Called when valid files are accepted via drop or browse */\n onFilesAccepted?: (files: File[]) => void;\n /** Called when files are rejected (wrong type, too large, etc.) */\n onFilesRejected?: (rejections: AudioFileRejection[]) => void;\n /** Called when a recording completes and meets minimum duration */\n onRecordingComplete?: (blob: Blob, durationMs: number) => void;\n /** Called when recording is stopped but does not meet minimum duration */\n onRecordingTooShort?: (durationMs: number, minDurationMs: number) => void;\n /** Called when microphone permission is denied or unavailable */\n onPermissionError?: (error: Error) => void;\n /** Called when an unexpected recording error occurs */\n onRecordingError?: (error: Error) => void;\n\n /** Upload area title text. @default \"Click to upload, or drag & drop\" */\n uploadTitle?: string;\n /** Upload area description text. @default \"Audio files only, up to 10MB each\" */\n uploadDescription?: string;\n /** Separator text between upload and record. @default \"or\" */\n separatorText?: string;\n /** Record button label. @default \"Record audio\" */\n recordButtonLabel?: string;\n /** Stop recording button aria-label. @default \"Stop recording\" */\n stopButtonAriaLabel?: string;\n\n /** Whether the component is disabled. @default false */\n disabled?: boolean;\n}\n\nfunction partitionFiles(\n files: File[],\n maxFileSize: number,\n accept: readonly string[],\n maxFiles: number,\n): { accepted: File[]; rejected: AudioFileRejection[] } {\n const accepted: File[] = [];\n const rejected: AudioFileRejection[] = [];\n\n for (const file of files) {\n const errors = validateAudioFile(file, { maxFileSize, acceptedTypes: accept });\n if (errors.length > 0) {\n rejected.push({ file, errors });\n } else {\n accepted.push(file);\n }\n }\n\n if (maxFiles > 0 && accepted.length > maxFiles) {\n const excess = accepted.splice(maxFiles);\n for (const file of excess) {\n rejected.push({\n file,\n errors: [{ code: \"too-many-files\", message: `Too many files. Maximum is ${maxFiles}` }],\n });\n }\n }\n\n return { accepted, rejected };\n}\n\n/**\n * Audio file upload with drag-and-drop and optional in-browser recording.\n * Supports file validation, multiple files, and real-time waveform visualization during recording.\n *\n * @example\n * ```tsx\n * <AudioUpload\n * onFilesAccepted={(files) => console.log(files)}\n * onRecordingComplete={(blob, duration) => console.log(blob, duration)}\n * />\n * ```\n */\nexport const AudioUpload = React.forwardRef<HTMLDivElement, AudioUploadProps>(\n (\n {\n className,\n maxFileSize = DEFAULT_MAX_FILE_SIZE,\n accept = DEFAULT_ACCEPTED_TYPES,\n maxFiles = 1,\n allowRecording = true,\n maxRecordingDuration = DEFAULT_MAX_RECORDING_DURATION,\n minRecordingDuration = DEFAULT_MIN_RECORDING_DURATION,\n onFilesAccepted,\n onFilesRejected,\n onRecordingComplete,\n onRecordingTooShort,\n onPermissionError,\n onRecordingError,\n uploadTitle = \"Click to upload, or drag & drop\",\n uploadDescription = \"Audio files only, up to 10MB each\",\n separatorText = \"or\",\n recordButtonLabel = \"Record audio\",\n stopButtonAriaLabel = \"Stop recording\",\n disabled = false,\n ...props\n },\n ref,\n ) => {\n const inputId = React.useId();\n const descriptionId = React.useId();\n const [isDragActive, setIsDragActive] = React.useState(false);\n const stopButtonRef = React.useRef<HTMLButtonElement>(null);\n\n const {\n isRecording,\n elapsedMs,\n startRecording,\n stopRecording,\n analyserNode,\n isSupported: isRecordingSupported,\n } = useAudioRecorder({\n maxDuration: maxRecordingDuration,\n minDuration: minRecordingDuration,\n onComplete: onRecordingComplete,\n onTooShort: onRecordingTooShort,\n onPermissionError,\n onError: onRecordingError,\n });\n\n const acceptString = accept.join(\",\");\n\n // Move focus to stop button when recording starts\n React.useEffect(() => {\n if (isRecording) {\n stopButtonRef.current?.focus();\n }\n }, [isRecording]);\n\n const validateAndAcceptFiles = React.useCallback(\n (files: FileList | File[]) => {\n const { accepted, rejected } = partitionFiles(\n Array.from(files),\n maxFileSize,\n accept,\n maxFiles,\n );\n if (accepted.length > 0) onFilesAccepted?.(accepted);\n if (rejected.length > 0) onFilesRejected?.(rejected);\n },\n [maxFileSize, accept, maxFiles, onFilesAccepted, onFilesRejected],\n );\n\n const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragActive(false);\n\n if (disabled) return;\n\n const { files } = e.dataTransfer;\n if (files.length > 0) {\n validateAndAcceptFiles(files);\n }\n };\n\n const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n e.stopPropagation();\n if (!disabled) {\n setIsDragActive(true);\n }\n };\n\n const handleDragLeave = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragActive(false);\n };\n\n const handleFileInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const { files } = e.target;\n if (files && files.length > 0) {\n validateAndAcceptFiles(files);\n }\n // Reset input so same file can be selected again\n e.target.value = \"\";\n };\n\n const handleRecordClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n startRecording();\n };\n\n const handleStopClick = () => {\n stopRecording();\n };\n\n if (isRecording) {\n const formattedElapsed = formatAudioTime(elapsedMs);\n\n return (\n // biome-ignore lint/a11y/useSemanticElements: <fieldset> would break the public HTMLDivElement ref/props API\n <div\n ref={ref}\n role=\"group\"\n aria-label=\"Audio recording in progress\"\n data-testid=\"audio-upload\"\n data-state=\"recording\"\n className={cn(\n \"flex flex-col items-center justify-center gap-2 rounded-md bg-surface-secondary px-4 py-3\",\n className,\n )}\n {...props}\n >\n <div className=\"flex flex-1 flex-col items-center gap-2\">\n <div\n className=\"flex size-[72px] items-center justify-center rounded-full bg-buttons-primary-default\"\n aria-hidden=\"true\"\n >\n <MicrophoneIcon className=\"size-5 text-content-primary-inverted\" />\n </div>\n\n <p\n role=\"timer\"\n aria-label=\"Recording time\"\n className=\"typography-body-default-16px-regular text-content-primary\"\n >\n {formattedElapsed} / {formatAudioTime(maxRecordingDuration * 1000)}\n </p>\n </div>\n\n <div className=\"flex w-full items-center gap-2.5\" aria-hidden=\"true\">\n <AudioWaveform\n analyserNode={analyserNode}\n isRecording={isRecording}\n className=\"flex-1\"\n />\n </div>\n\n <button\n ref={stopButtonRef}\n type=\"button\"\n onClick={handleStopClick}\n className=\"mt-1 flex size-11 items-center justify-center rounded-full bg-error-content text-content-always-white transition-colors hover:bg-error-content/80 focus:shadow-focus-ring focus-visible:outline-none\"\n aria-label={stopButtonAriaLabel}\n >\n <StopIcon className=\"size-5\" />\n </button>\n </div>\n );\n }\n\n return (\n // biome-ignore lint/a11y/useSemanticElements: <fieldset> would break the public HTMLDivElement ref/props API\n <div\n ref={ref}\n role=\"group\"\n aria-label=\"Audio upload\"\n data-testid=\"audio-upload\"\n data-state=\"idle\"\n aria-disabled={disabled || undefined}\n onDrop={handleDrop}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n className={cn(\n \"flex flex-col items-center justify-center gap-2 rounded-md bg-surface-secondary px-4 py-3 transition-colors\",\n isDragActive && \"bg-brand-primary-muted ring-2 ring-brand-primary-default\",\n disabled && \"pointer-events-none opacity-50\",\n className,\n )}\n {...props}\n >\n <input\n id={inputId}\n type=\"file\"\n accept={acceptString}\n multiple={maxFiles > 1}\n onChange={handleFileInputChange}\n className=\"peer sr-only\"\n disabled={disabled}\n aria-describedby={descriptionId}\n />\n\n <label\n htmlFor={inputId}\n className=\"flex cursor-pointer flex-col items-center gap-2 rounded-xs px-2 py-1 peer-focus-visible:shadow-focus-ring\"\n >\n <UploadCloudIcon className=\"size-5 text-content-primary\" />\n\n <span className=\"typography-body-default-16px-semibold text-center text-content-primary\">\n {uploadTitle}\n </span>\n\n <span\n id={descriptionId}\n className=\"typography-body-small-14px-regular text-center text-content-primary\"\n >\n {uploadDescription}\n </span>\n </label>\n\n {allowRecording && isRecordingSupported && (\n <>\n <p className=\"typography-body-small-14px-regular text-center text-content-primary\">\n {separatorText}\n </p>\n\n <Button\n variant=\"brand\"\n size=\"40\"\n leftIcon={<MicrophoneIcon className=\"size-5\" />}\n onClick={handleRecordClick}\n disabled={disabled}\n type=\"button\"\n >\n {recordButtonLabel}\n </Button>\n </>\n )}\n </div>\n );\n },\n);\n\nAudioUpload.displayName = \"AudioUpload\";\n"],"names":[],"mappings":"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"}
@@ -16,9 +16,9 @@ const CONTAINER_HEIGHT = {
16
16
  "32": "min-h-8"
17
17
  };
18
18
  const INPUT_SIZE_CLASSES = {
19
- "48": "typography-regular-body-lg",
20
- "40": "typography-regular-body-lg",
21
- "32": "typography-regular-body-md"
19
+ "48": "typography-body-default-16px-regular",
20
+ "40": "typography-body-default-16px-regular",
21
+ "32": "typography-body-small-14px-regular"
22
22
  };
23
23
  const PADDING_CLASSES = {
24
24
  "48": "px-4 py-1.5 gap-3",
@@ -73,7 +73,7 @@ const Autocomplete = React.forwardRef((props, ref) => {
73
73
  "label",
74
74
  {
75
75
  htmlFor: ac.inputId,
76
- className: "typography-semibold-body-sm px-1 pt-1 pb-2 text-content-primary",
76
+ className: "typography-description-12px-semibold px-1 pt-1 pb-2 text-content-primary",
77
77
  children: label
78
78
  }
79
79
  ),
@@ -165,7 +165,7 @@ const Autocomplete = React.forwardRef((props, ref) => {
165
165
  onCloseAutoFocus: (e) => e.preventDefault(),
166
166
  style: { zIndex: "var(--fanvue-ui-portal-z-index, 50)" },
167
167
  className: cn(
168
- "w-max min-w-(--radix-popper-anchor-width) max-w-(--radix-popover-content-available-width) overflow-hidden rounded-sm border border-neutral-alphas-200 bg-bg-primary text-content-primary shadow-[0_4px_16px_rgba(0,0,0,0.10)]",
168
+ "w-max min-w-(--radix-popper-anchor-width) max-w-(--radix-popover-content-available-width) overflow-hidden rounded-sm border border-neutral-alphas-200 bg-background-primary text-content-primary shadow-[0_4px_16px_rgba(0,0,0,0.10)]",
169
169
  "data-[state=closed]:animate-out data-[state=open]:animate-in",
170
170
  "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
171
171
  "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
@@ -209,7 +209,7 @@ const Autocomplete = React.forwardRef((props, ref) => {
209
209
  {
210
210
  id: ac.helperTextId,
211
211
  className: cn(
212
- "typography-regular-body-sm px-2 pt-1 pb-0.5",
212
+ "typography-description-12px-regular px-2 pt-1 pb-0.5",
213
213
  error ? "text-error-content" : "text-content-secondary"
214
214
  ),
215
215
  children: bottomText