@flikk/ui 1.0.0-beta.14 → 1.0.0-beta.16

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 (279) hide show
  1. package/README.md +52 -0
  2. package/dist/components/ai/CodeBlock/CodeBlock.theme.js +1 -1
  3. package/dist/components/ai/PromptInput/PromptInput.js +3 -1
  4. package/dist/components/ai/PromptSuggestions/PromptSuggestion.theme.js +4 -4
  5. package/dist/components/ai/StreamingResponse/AnimatedText.js +3 -3
  6. package/dist/components/ai/StreamingResponse/MarkdownRenderer.js +22 -22
  7. package/dist/components/ai/StreamingResponse/StreamingCursor.js +1 -1
  8. package/dist/components/ai/StreamingResponse/StreamingResponse.animations.js +10 -10
  9. package/dist/components/ai/StreamingResponse/StreamingResponse.js +9 -3
  10. package/dist/components/ai/StreamingResponse/WordAnimationContext.d.ts +1 -1
  11. package/dist/components/ai/StreamingResponse/WordAnimationContext.js +11 -11
  12. package/dist/components/ai/index.d.ts +0 -7
  13. package/dist/components/ai/index.js +8 -6
  14. package/dist/components/charts/DonutChart/DonutChart.js +1 -1
  15. package/dist/components/charts/DonutChart/MultiSegmentDonutChart.js +1 -1
  16. package/dist/components/charts/shared/ChartLegend/ChartLegend.types.d.ts +13 -1
  17. package/dist/components/charts/shared/ChartLegend/ChartLegendContent.js +1 -1
  18. package/dist/components/charts/shared/ChartTooltip/ChartTooltip.types.d.ts +13 -2
  19. package/dist/components/core/Accordion/AccordionItem.js +1 -1
  20. package/dist/components/core/Accordion/AccordionTrigger.js +1 -1
  21. package/dist/components/core/Alert/Alert.animations.d.ts +11 -0
  22. package/dist/components/core/Alert/Alert.animations.js +44 -0
  23. package/dist/components/core/Alert/Alert.js +16 -3
  24. package/dist/components/core/Avatar/Avatar.js +12 -7
  25. package/dist/components/core/Avatar/Avatar.theme.d.ts +4 -6
  26. package/dist/components/core/Avatar/Avatar.theme.js +22 -12
  27. package/dist/components/core/Avatar/Avatar.types.d.ts +9 -0
  28. package/dist/components/core/AvatarGroup/AvatarGroup.animations.js +2 -2
  29. package/dist/components/core/AvatarGroup/AvatarGroup.js +1 -2
  30. package/dist/components/core/AvatarGroup/AvatarGroup.theme.js +1 -1
  31. package/dist/components/core/Badge/Badge.animations.js +1 -1
  32. package/dist/components/core/Badge/Badge.js +23 -47
  33. package/dist/components/core/Badge/Badge.theme.js +48 -62
  34. package/dist/components/core/Badge/Badge.types.d.ts +5 -29
  35. package/dist/components/core/Button/Button.js +2 -2
  36. package/dist/components/core/Button/Button.theme.js +2 -2
  37. package/dist/components/core/ButtonGroup/ButtonGroup.theme.js +6 -6
  38. package/dist/components/core/ButtonGroup/ButtonGroupText.js +1 -3
  39. package/dist/components/core/Calendar/Calendar.js +29 -3
  40. package/dist/components/core/Calendar/Calendar.theme.js +11 -7
  41. package/dist/components/core/Calendar/Calendar.types.d.ts +3 -0
  42. package/dist/components/core/Carousel/CarouselBody.js +0 -1
  43. package/dist/components/core/CommandPalette/CommandItem.js +1 -1
  44. package/dist/components/core/CommandPalette/CommandPalette.js +6 -4
  45. package/dist/components/core/CommandPalette/CommandPalette.theme.js +1 -0
  46. package/dist/components/core/CommandPalette/CommandPalette.types.d.ts +6 -0
  47. package/dist/components/core/ContextMenu/ContextMenu.js +5 -4
  48. package/dist/components/core/ContextMenu/ContextMenuTrigger.js +5 -6
  49. package/dist/components/core/Drawer/Drawer.d.ts +1 -1
  50. package/dist/components/core/Drawer/Drawer.js +25 -2
  51. package/dist/components/core/Drawer/Drawer.theme.js +2 -2
  52. package/dist/components/core/Drawer/Drawer.types.d.ts +6 -0
  53. package/dist/components/core/Dropdown/Dropdown.d.ts +1 -1
  54. package/dist/components/core/Dropdown/Dropdown.js +5 -1
  55. package/dist/components/core/Dropdown/Dropdown.types.d.ts +1 -0
  56. package/dist/components/core/Dropdown/DropdownItem.js +1 -1
  57. package/dist/components/core/Dropdown/DropdownMenu.js +4 -4
  58. package/dist/components/core/Dropdown/DropdownSection.js +1 -1
  59. package/dist/components/core/Dropdown/DropdownSeparator.js +1 -1
  60. package/dist/components/core/Dropdown/DropdownTrigger.d.ts +6 -1
  61. package/dist/components/core/Dropdown/DropdownTrigger.js +10 -8
  62. package/dist/components/core/Kbd/Kbd.theme.js +3 -3
  63. package/dist/components/core/Link/Link.js +3 -1
  64. package/dist/components/core/Message/Message.d.ts +9 -0
  65. package/dist/components/core/Message/Message.js +44 -3
  66. package/dist/components/core/Message/Message.theme.js +22 -0
  67. package/dist/components/core/Message/Message.types.d.ts +115 -0
  68. package/dist/components/core/Message/MessageAudio.d.ts +8 -0
  69. package/dist/components/core/Message/MessageAudio.js +11 -0
  70. package/dist/components/core/Message/MessageContext.d.ts +3 -1
  71. package/dist/components/core/Message/MessageDateDivider.d.ts +6 -0
  72. package/dist/components/core/Message/MessageDateDivider.js +10 -0
  73. package/dist/components/core/Message/MessageFile.d.ts +9 -0
  74. package/dist/components/core/Message/MessageFile.js +15 -0
  75. package/dist/components/core/Message/MessageImage.d.ts +11 -0
  76. package/dist/components/core/Message/MessageImage.js +13 -0
  77. package/dist/components/core/Message/MessageLink.d.ts +10 -0
  78. package/dist/components/core/Message/MessageLink.js +15 -0
  79. package/dist/components/core/Message/MessageReactions.d.ts +8 -0
  80. package/dist/components/core/Message/MessageReactions.js +12 -0
  81. package/dist/components/core/Message/MessageReply.d.ts +8 -0
  82. package/dist/components/core/Message/MessageReply.js +10 -0
  83. package/dist/components/core/Message/MessageSenderName.d.ts +6 -0
  84. package/dist/components/core/Message/MessageSenderName.js +10 -0
  85. package/dist/components/core/Message/MessageStatusIndicator.d.ts +9 -0
  86. package/dist/components/core/Message/MessageStatusIndicator.js +45 -0
  87. package/dist/components/core/Message/index.d.ts +19 -1
  88. package/dist/components/core/Modal/Modal.animations.d.ts +1 -0
  89. package/dist/components/core/Modal/Modal.animations.js +14 -11
  90. package/dist/components/core/Pagination/Pagination.theme.js +1 -1
  91. package/dist/components/core/Popover/Popover.d.ts +1 -1
  92. package/dist/components/core/Popover/PopoverBody.js +2 -2
  93. package/dist/components/core/Popover/PopoverTrigger.d.ts +1 -1
  94. package/dist/components/core/Popover/PopoverTrigger.js +11 -11
  95. package/dist/components/core/Progress/Progress.d.ts +9 -8
  96. package/dist/components/core/Progress/Progress.js +16 -16
  97. package/dist/components/core/Progress/Progress.theme.js +4 -15
  98. package/dist/components/core/Progress/Progress.types.d.ts +2 -20
  99. package/dist/components/core/Progress/index.d.ts +1 -1
  100. package/dist/components/core/ScrollArea/ScrollArea.js +49 -7
  101. package/dist/components/core/ScrollArea/ScrollArea.types.d.ts +12 -3
  102. package/dist/components/core/ScrollArea/index.d.ts +1 -1
  103. package/dist/components/core/Segmented/SegmentedItem.js +1 -1
  104. package/dist/components/core/Sidebar/Sidebar.js +2 -1
  105. package/dist/components/core/Sidebar/SidebarMobileTrigger.js +2 -1
  106. package/dist/components/core/Sidebar/SidebarToggle.js +2 -1
  107. package/dist/components/core/Sidebar/SidebarUserProfile.js +1 -1
  108. package/dist/components/core/SocialIcon/SocialIcon.js +1 -1
  109. package/dist/components/core/Sortable/Sortable.js +2 -2
  110. package/dist/components/core/Sortable/Sortable.theme.js +1 -1
  111. package/dist/components/core/Sortable/Sortable.types.d.ts +7 -5
  112. package/dist/components/core/Tabs/TabsBody.js +1 -1
  113. package/dist/components/core/Tabs/TabsTrigger.js +1 -1
  114. package/dist/components/core/Tag/Tag.js +2 -2
  115. package/dist/components/core/Toast/Toast.d.ts +2 -2
  116. package/dist/components/core/Toast/Toast.js +30 -21
  117. package/dist/components/core/Toast/Toast.theme.js +4 -9
  118. package/dist/components/core/Toast/Toast.types.d.ts +4 -21
  119. package/dist/components/core/Toast/index.d.ts +1 -1
  120. package/dist/components/core/Tooltip/Tooltip.js +1 -1
  121. package/dist/components/core/Tooltip/Tooltip.theme.js +1 -1
  122. package/dist/components/core/index.js +9 -0
  123. package/dist/components/data-display/GanttChart/GanttChart.types.d.ts +2 -2
  124. package/dist/components/data-display/Table/Table.types.d.ts +8 -8
  125. package/dist/components/effects/CustomCursor/CustomCursor.js +2 -2
  126. package/dist/components/effects/GlassSurface/GlassSurface.d.ts +1 -1
  127. package/dist/components/effects/GlassSurface/GlassSurface.js +17 -9
  128. package/dist/components/effects/GlassSurface/GlassSurface.types.d.ts +6 -0
  129. package/dist/components/effects/InteractiveCharacters/InteractiveCharacters.animations.d.ts +39 -0
  130. package/dist/components/effects/InteractiveCharacters/InteractiveCharacters.animations.js +98 -0
  131. package/dist/components/effects/InteractiveCharacters/InteractiveCharacters.d.ts +3 -0
  132. package/dist/components/effects/InteractiveCharacters/InteractiveCharacters.js +104 -0
  133. package/dist/components/effects/InteractiveCharacters/InteractiveCharacters.types.d.ts +30 -0
  134. package/dist/components/effects/InteractiveCharacters/characters/BlobCharacter.d.ts +3 -0
  135. package/dist/components/effects/InteractiveCharacters/characters/BlobCharacter.js +36 -0
  136. package/dist/components/effects/InteractiveCharacters/characters/SmallCharacter.d.ts +3 -0
  137. package/dist/components/effects/InteractiveCharacters/characters/SmallCharacter.js +36 -0
  138. package/dist/components/effects/InteractiveCharacters/characters/TallCharacter.d.ts +3 -0
  139. package/dist/components/effects/InteractiveCharacters/characters/TallCharacter.js +37 -0
  140. package/dist/components/effects/InteractiveCharacters/hooks/useBlink.d.ts +14 -0
  141. package/dist/components/effects/InteractiveCharacters/hooks/useBlink.js +41 -0
  142. package/dist/components/effects/InteractiveCharacters/hooks/useIdleAnimation.d.ts +25 -0
  143. package/dist/components/effects/InteractiveCharacters/hooks/useIdleAnimation.js +84 -0
  144. package/dist/components/effects/InteractiveCharacters/hooks/useMouseTracking.d.ts +18 -0
  145. package/dist/components/effects/InteractiveCharacters/hooks/useMouseTracking.js +35 -0
  146. package/dist/components/effects/InteractiveCharacters/index.d.ts +2 -0
  147. package/dist/components/effects/MorphingText/MorphingText.d.ts +1 -1
  148. package/dist/components/effects/MorphingText/MorphingText.js +6 -5
  149. package/dist/components/effects/Neumorphic/InsetCircleButton.d.ts +10 -0
  150. package/dist/components/effects/Neumorphic/InsetCircleButton.js +10 -0
  151. package/dist/components/effects/Neumorphic/InsetPill.d.ts +8 -0
  152. package/dist/components/effects/Neumorphic/InsetPill.js +7 -0
  153. package/dist/components/effects/Neumorphic/index.d.ts +4 -0
  154. package/dist/components/effects/NoiseOverlay/NoiseOverlay.d.ts +1 -1
  155. package/dist/components/effects/NoiseOverlay/NoiseOverlay.js +4 -4
  156. package/dist/components/effects/Overlay/Overlay.js +6 -4
  157. package/dist/components/effects/PageTransition/PageTransition.animations.d.ts +8 -0
  158. package/dist/components/effects/PageTransition/PageTransition.animations.js +53 -0
  159. package/dist/components/effects/PageTransition/PageTransition.d.ts +3 -0
  160. package/dist/components/effects/PageTransition/PageTransition.js +71 -0
  161. package/dist/components/effects/PageTransition/PageTransition.types.d.ts +15 -0
  162. package/dist/components/effects/PageTransition/index.d.ts +2 -0
  163. package/dist/components/effects/index.d.ts +6 -0
  164. package/dist/components/effects/index.js +4 -0
  165. package/dist/components/forms/Checkbox/Checkbox.animations.d.ts +14 -0
  166. package/dist/components/forms/Checkbox/Checkbox.animations.js +53 -0
  167. package/dist/components/forms/Checkbox/Checkbox.js +4 -2
  168. package/dist/components/forms/Checkbox/Checkbox.theme.js +3 -3
  169. package/dist/components/forms/ColorPicker/ColorPicker.types.d.ts +1 -1
  170. package/dist/components/forms/ColorPicker/ColorPickerBody.js +3 -3
  171. package/dist/components/forms/Combobox/Combobox.js +5 -3
  172. package/dist/components/forms/DatePicker/DatePickerBody.js +1 -1
  173. package/dist/components/forms/DateRangePicker/DateRangePicker.animations.d.ts +1 -0
  174. package/dist/components/forms/DateRangePicker/DateRangePicker.d.ts +37 -0
  175. package/dist/components/forms/DateRangePicker/DateRangePicker.js +110 -0
  176. package/dist/components/forms/DateRangePicker/DateRangePicker.theme.d.ts +5 -0
  177. package/dist/components/forms/DateRangePicker/DateRangePicker.theme.js +52 -0
  178. package/dist/components/forms/DateRangePicker/DateRangePicker.types.d.ts +154 -0
  179. package/dist/components/forms/DateRangePicker/DateRangePickerBody.d.ts +6 -0
  180. package/dist/components/forms/DateRangePicker/DateRangePickerBody.js +208 -0
  181. package/dist/components/forms/DateRangePicker/DateRangePickerPresets.d.ts +6 -0
  182. package/dist/components/forms/DateRangePicker/DateRangePickerPresets.js +41 -0
  183. package/dist/components/forms/DateRangePicker/DateRangePickerTrigger.d.ts +6 -0
  184. package/dist/components/forms/DateRangePicker/DateRangePickerTrigger.js +32 -0
  185. package/dist/components/forms/DateRangePicker/dateRangePresets.d.ts +5 -0
  186. package/dist/components/forms/DateRangePicker/dateRangePresets.js +59 -0
  187. package/dist/components/forms/DateRangePicker/index.d.ts +4 -0
  188. package/dist/components/forms/FileUpload/FileUploadProgress.animations.d.ts +36 -0
  189. package/dist/components/forms/FileUpload/FileUploadProgress.animations.js +22 -0
  190. package/dist/components/forms/FileUpload/FileUploadProgress.d.ts +3 -0
  191. package/dist/components/forms/FileUpload/FileUploadProgress.js +111 -0
  192. package/dist/components/forms/FileUpload/FileUploadProgress.theme.d.ts +19 -0
  193. package/dist/components/forms/FileUpload/FileUploadProgress.theme.js +27 -0
  194. package/dist/components/forms/FileUpload/FileUploadProgress.types.d.ts +33 -0
  195. package/dist/components/forms/FileUpload/index.d.ts +3 -0
  196. package/dist/components/forms/Input/Input.js +8 -13
  197. package/dist/components/forms/Input/Input.types.d.ts +6 -0
  198. package/dist/components/forms/InputAddress/InputAddress.theme.js +1 -1
  199. package/dist/components/forms/InputCounter/InputCounter.js +1 -1
  200. package/dist/components/forms/InputCreditCard/InputCreditCard.theme.js +1 -1
  201. package/dist/components/forms/InputOTP/InputOTP.theme.js +1 -1
  202. package/dist/components/forms/Radio/Radio.animations.d.ts +10 -0
  203. package/dist/components/forms/Radio/Radio.animations.js +33 -0
  204. package/dist/components/forms/Radio/Radio.js +11 -2
  205. package/dist/components/forms/Radio/Radio.theme.js +3 -3
  206. package/dist/components/forms/RichTextEditor/RichTextEditor.js +13 -4
  207. package/dist/components/forms/RichTextEditor/RichTextEditor.theme.js +2 -2
  208. package/dist/components/forms/RichTextEditor/RichTextEditor.types.d.ts +11 -0
  209. package/dist/components/forms/Select/Select.d.ts +1 -1
  210. package/dist/components/forms/Select/Select.js +7 -7
  211. package/dist/components/forms/Select/Select.types.d.ts +3 -3
  212. package/dist/components/forms/SelectableCard/SelectableCard.js +1 -1
  213. package/dist/components/forms/Slider/Slider.js +10 -3
  214. package/dist/components/forms/Slider/Slider.theme.js +3 -3
  215. package/dist/components/forms/Switch/Switch.js +10 -2
  216. package/dist/components/forms/Switch/Switch.theme.js +3 -3
  217. package/dist/components/forms/forms.theme.js +1 -1
  218. package/dist/components/forms/index.d.ts +6 -3
  219. package/dist/components/forms/index.js +8 -2
  220. package/dist/hooks/index.d.ts +1 -0
  221. package/dist/hooks/useMediaQuery.d.ts +5 -0
  222. package/dist/hooks/useMediaQuery.js +21 -0
  223. package/dist/index.js +21 -2
  224. package/dist/styles.css +1 -1
  225. package/dist/utils/dateUtils.js +56 -5
  226. package/dist/utils/formatUtils.d.ts +10 -0
  227. package/dist/utils/formatUtils.js +24 -0
  228. package/dist/utils/index.d.ts +1 -1
  229. package/package.json +12 -4
  230. package/src/global.scss +319 -39
  231. package/src/styles/theme.css +105 -16
  232. package/src/theme-plugin.css +13 -0
  233. package/dist/components/ai/ApprovalCard/ApprovalCard.d.ts +0 -3
  234. package/dist/components/ai/ApprovalCard/ApprovalCard.js +0 -16
  235. package/dist/components/ai/ApprovalCard/ApprovalCard.theme.d.ts +0 -13
  236. package/dist/components/ai/ApprovalCard/ApprovalCard.theme.js +0 -15
  237. package/dist/components/ai/ApprovalCard/ApprovalCard.types.d.ts +0 -43
  238. package/dist/components/ai/ApprovalCard/index.d.ts +0 -2
  239. package/dist/components/ai/MessageHistory/MessageHistory.d.ts +0 -18
  240. package/dist/components/ai/MessageHistory/MessageHistory.js +0 -98
  241. package/dist/components/ai/MessageHistory/MessageHistory.theme.d.ts +0 -2
  242. package/dist/components/ai/MessageHistory/MessageHistory.theme.js +0 -8
  243. package/dist/components/ai/MessageHistory/MessageHistory.types.d.ts +0 -94
  244. package/dist/components/ai/MessageHistory/index.d.ts +0 -3
  245. package/dist/components/ai/ThinkingIndicator/ThinkingIndicator.animations.d.ts +0 -10
  246. package/dist/components/ai/ThinkingIndicator/ThinkingIndicator.animations.js +0 -47
  247. package/dist/components/ai/ThinkingIndicator/ThinkingIndicator.d.ts +0 -20
  248. package/dist/components/ai/ThinkingIndicator/ThinkingIndicator.js +0 -55
  249. package/dist/components/ai/ThinkingIndicator/ThinkingIndicator.theme.d.ts +0 -2
  250. package/dist/components/ai/ThinkingIndicator/ThinkingIndicator.theme.js +0 -20
  251. package/dist/components/ai/ThinkingIndicator/ThinkingIndicator.types.d.ts +0 -67
  252. package/dist/components/ai/ThinkingIndicator/index.d.ts +0 -3
  253. package/dist/components/forms/TransferList/TransferList.animations.d.ts +0 -10
  254. package/dist/components/forms/TransferList/TransferList.animations.js +0 -32
  255. package/dist/components/forms/TransferList/TransferList.d.ts +0 -28
  256. package/dist/components/forms/TransferList/TransferList.js +0 -199
  257. package/dist/components/forms/TransferList/TransferList.theme.d.ts +0 -6
  258. package/dist/components/forms/TransferList/TransferList.theme.js +0 -60
  259. package/dist/components/forms/TransferList/TransferList.types.d.ts +0 -101
  260. package/dist/components/forms/TransferList/index.d.ts +0 -3
  261. package/dist/icons/Icon.d.ts +0 -24
  262. package/dist/icons/Icon.js +0 -30
  263. package/dist/icons/Index.d.ts +0 -16
  264. package/dist/icons/core/ChevronUpDown.d.ts +0 -1
  265. package/dist/icons/core/ChevronUpDown.js +0 -7
  266. package/dist/icons/core/DollarIcon.d.ts +0 -1
  267. package/dist/icons/core/DollarIcon.js +0 -5
  268. package/dist/icons/core/LockIcon.d.ts +0 -1
  269. package/dist/icons/core/LockIcon.js +0 -5
  270. package/dist/icons/core/MinusIcon.d.ts +0 -1
  271. package/dist/icons/core/MinusIcon.js +0 -7
  272. package/dist/icons/core/PlusIcon.d.ts +0 -1
  273. package/dist/icons/core/PlusIcon.js +0 -7
  274. package/dist/icons/core/SearchIcon.d.ts +0 -1
  275. package/dist/icons/core/SearchIcon.js +0 -7
  276. package/dist/icons/core/TickIcon.d.ts +0 -1
  277. package/dist/icons/core/TickIcon.js +0 -5
  278. package/dist/icons/core/User.d.ts +0 -1
  279. package/dist/utils/useClickOutside.d.ts +0 -1
@@ -0,0 +1,59 @@
1
+ import { toDate, addDays, getThisWeek, getLastWeek, getThisMonth, getLastMonth } from '../../../utils/dateUtils.js';
2
+
3
+ /**
4
+ * Default date range presets matching the reference design
5
+ */
6
+ const DEFAULT_DATE_RANGE_PRESETS = [
7
+ {
8
+ label: "Today",
9
+ getValue: () => {
10
+ const today = toDate(new Date());
11
+ return { start: today, end: today };
12
+ },
13
+ },
14
+ {
15
+ label: "Yesterday",
16
+ getValue: () => {
17
+ const yesterday = addDays(new Date(), -1);
18
+ return { start: yesterday, end: yesterday };
19
+ },
20
+ },
21
+ {
22
+ label: "This week",
23
+ getValue: () => getThisWeek(),
24
+ },
25
+ {
26
+ label: "Last week",
27
+ getValue: () => getLastWeek(),
28
+ },
29
+ {
30
+ label: "This month",
31
+ getValue: () => getThisMonth(),
32
+ },
33
+ {
34
+ label: "Last month",
35
+ getValue: () => getLastMonth(),
36
+ },
37
+ {
38
+ label: "Last 3 months",
39
+ getValue: () => {
40
+ const today = new Date();
41
+ today.setHours(23, 59, 59, 999);
42
+ const start = new Date(today.getFullYear(), today.getMonth() - 3, today.getDate());
43
+ start.setHours(0, 0, 0, 0);
44
+ return { start, end: today };
45
+ },
46
+ },
47
+ {
48
+ label: "Year to date",
49
+ getValue: () => {
50
+ const today = new Date();
51
+ today.setHours(23, 59, 59, 999);
52
+ const start = new Date(today.getFullYear(), 0, 1);
53
+ start.setHours(0, 0, 0, 0);
54
+ return { start, end: today };
55
+ },
56
+ },
57
+ ];
58
+
59
+ export { DEFAULT_DATE_RANGE_PRESETS };
@@ -0,0 +1,4 @@
1
+ export { DateRangePicker, DateRangePickerTrigger, DateRangePickerBody, DateRangePickerPresets, } from "./DateRangePicker";
2
+ export type { DateRangePickerProps, DateRangePickerTriggerProps, DateRangePickerBodyProps, DateRangePickerPresetsProps, DateRangePickerSize, DateRangePickerState, DateRangePickerPlacement, DateRangePickerTheme, DateRangePreset, } from "./DateRangePicker.types";
3
+ export { dateRangePickerTheme } from "./DateRangePicker.theme";
4
+ export { DEFAULT_DATE_RANGE_PRESETS } from "./dateRangePresets";
@@ -0,0 +1,36 @@
1
+ /** Spring config for the progress arc animation. */
2
+ export declare const PROGRESS_SPRING: {
3
+ type: "spring";
4
+ stiffness: number;
5
+ damping: number;
6
+ mass: number;
7
+ };
8
+ /** Crossfade transition for center content swaps. */
9
+ export declare const CROSSFADE: {
10
+ initial: {
11
+ opacity: number;
12
+ };
13
+ animate: {
14
+ opacity: number;
15
+ };
16
+ exit: {
17
+ opacity: number;
18
+ };
19
+ transition: {
20
+ duration: number;
21
+ };
22
+ };
23
+ /** Entrance animation for the remove button after completion. */
24
+ export declare const REMOVE_BUTTON_ENTER: {
25
+ initial: {
26
+ opacity: number;
27
+ scale: number;
28
+ };
29
+ animate: {
30
+ opacity: number;
31
+ scale: number;
32
+ };
33
+ transition: {
34
+ duration: number;
35
+ };
36
+ };
@@ -0,0 +1,22 @@
1
+ /** Spring config for the progress arc animation. */
2
+ const PROGRESS_SPRING = {
3
+ type: "spring",
4
+ stiffness: 100,
5
+ damping: 20,
6
+ mass: 0.5,
7
+ };
8
+ /** Crossfade transition for center content swaps. */
9
+ const CROSSFADE = {
10
+ initial: { opacity: 0 },
11
+ animate: { opacity: 1 },
12
+ exit: { opacity: 0 },
13
+ transition: { duration: 0.15 },
14
+ };
15
+ /** Entrance animation for the remove button after completion. */
16
+ const REMOVE_BUTTON_ENTER = {
17
+ initial: { opacity: 0, scale: 0.8 },
18
+ animate: { opacity: 1, scale: 1 },
19
+ transition: { duration: 0.2 },
20
+ };
21
+
22
+ export { CROSSFADE, PROGRESS_SPRING, REMOVE_BUTTON_ENTER };
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ import type { FileUploadProgressProps } from "./FileUploadProgress.types";
3
+ export declare const FileUploadProgress: React.ForwardRefExoticComponent<FileUploadProgressProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,111 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import React__default, { useState, useEffect } from 'react';
3
+ import { useReducedMotion, motion, AnimatePresence } from 'motion/react';
4
+ import { DocumentIcon, TrashIcon, XMarkIcon, ArrowPathIcon } from '@heroicons/react/24/outline';
5
+ import { FileTypeIcon } from '../../core/FileTypeIcon/FileTypeIcon.js';
6
+ import { fileTypes } from '../../core/FileTypeIcon/fileTypes.js';
7
+ import { cn } from '../../../utils/cn.js';
8
+ import { getFileExtension, formatFileSize } from '../../../utils/formatUtils.js';
9
+ import { Popover } from '../../core/Popover/Popover.js';
10
+ import '../../core/Popover/PopoverContext.js';
11
+ import '../../core/Popover/PopoverBody.js';
12
+ import { Button } from '../../core/Button/Button.js';
13
+ import { fileUploadProgressTheme } from './FileUploadProgress.theme.js';
14
+ import { REMOVE_BUTTON_ENTER, PROGRESS_SPRING, CROSSFADE } from './FileUploadProgress.animations.js';
15
+
16
+ const isKnownFileType = (ext) => {
17
+ return ext in fileTypes;
18
+ };
19
+ // SVG viewBox is 36×36 — small enough for crisp rendering, large enough for smooth arcs
20
+ const VIEWBOX = 36;
21
+ const CENTER = VIEWBOX / 2;
22
+ const RadialProgress = ({ progress, status, strokeWidth, trackColor, progressColor, centerTextStyle, statusIconColor, sizeClass, shouldReduceMotion, confirmRemove, completionDelay, onRemove, onRetry, }) => {
23
+ const [isHovered, setIsHovered] = useState(false);
24
+ const [confirmOpen, setConfirmOpen] = useState(false);
25
+ const [showRemove, setShowRemove] = useState(false);
26
+ const radius = (VIEWBOX - strokeWidth) / 2;
27
+ const circumference = 2 * Math.PI * radius;
28
+ const offset = circumference * (1 - progress / 100);
29
+ const isUploading = status === "uploading";
30
+ const isComplete = status === "complete";
31
+ const isError = status === "error";
32
+ // After completing, show tick briefly then transition to remove button
33
+ useEffect(() => {
34
+ if (isComplete) {
35
+ setShowRemove(false);
36
+ const timer = setTimeout(() => setShowRemove(true), completionDelay);
37
+ return () => clearTimeout(timer);
38
+ }
39
+ setShowRemove(false);
40
+ }, [isComplete, completionDelay]);
41
+ const handleClick = () => {
42
+ if (isError && onRetry) {
43
+ onRetry();
44
+ return;
45
+ }
46
+ if (onRemove) {
47
+ if (confirmRemove) {
48
+ setConfirmOpen(true);
49
+ }
50
+ else {
51
+ onRemove();
52
+ }
53
+ }
54
+ };
55
+ const handleConfirm = () => {
56
+ setConfirmOpen(false);
57
+ onRemove === null || onRemove === void 0 ? void 0 : onRemove();
58
+ };
59
+ const isClickable = (isError && onRetry) || onRemove;
60
+ const ariaLabel = isError && onRetry ? "Retry upload" : onRemove ? "Remove file" : undefined;
61
+ // Shared remove button used after completion tick
62
+ const removeButton = (jsx(motion.div, { initial: shouldReduceMotion ? false : REMOVE_BUTTON_ENTER.initial, animate: REMOVE_BUTTON_ENTER.animate, transition: REMOVE_BUTTON_ENTER.transition, className: "shrink-0", children: jsx(Button, { size: "sm", variant: "soft", color: "neutral", "aria-label": "Remove file", iconOnly: true, className: "rounded-full size-8", onClick: confirmRemove ? undefined : () => onRemove === null || onRemove === void 0 ? void 0 : onRemove(), children: jsx(TrashIcon, { className: "size-3.5", strokeWidth: 2 }) }) }, "remove-btn"));
63
+ const radialElement = (jsxs("div", { className: cn("relative shrink-0", sizeClass, isClickable && "cursor-pointer"), onMouseEnter: () => setIsHovered(true), onMouseLeave: () => {
64
+ if (!confirmOpen)
65
+ setIsHovered(false);
66
+ }, onClick: isClickable ? handleClick : undefined, role: isClickable ? "button" : undefined, tabIndex: isClickable ? 0 : undefined, "aria-label": ariaLabel, onKeyDown: isClickable
67
+ ? (e) => {
68
+ if (e.key === "Enter" || e.key === " ") {
69
+ e.preventDefault();
70
+ handleClick();
71
+ }
72
+ }
73
+ : undefined, children: [jsxs("svg", { viewBox: `0 0 ${VIEWBOX} ${VIEWBOX}`, className: "w-full h-full -rotate-90", children: [jsx("circle", { cx: CENTER, cy: CENTER, r: radius, fill: "none", stroke: trackColor, strokeWidth: strokeWidth }), jsx(motion.circle, { cx: CENTER, cy: CENTER, r: radius, fill: "none", stroke: progressColor, strokeWidth: strokeWidth, strokeLinecap: "round", strokeDasharray: circumference, initial: { strokeDashoffset: circumference }, animate: { strokeDashoffset: isComplete ? 0 : offset }, transition: shouldReduceMotion ? { duration: 0 } : PROGRESS_SPRING })] }), jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: jsxs(AnimatePresence, { mode: "wait", initial: false, children: [isUploading && !isHovered && (jsx(motion.span, { className: centerTextStyle, ...(shouldReduceMotion ? {} : CROSSFADE), children: progress }, "percent")), isUploading && isHovered && onRemove && (jsx(motion.span, { ...(shouldReduceMotion ? {} : CROSSFADE), children: jsx(XMarkIcon, { className: "size-4 text-[var(--color-text-muted)]", strokeWidth: 2.5 }) }, "close")), isComplete && !showRemove && (jsx(motion.span, { ...(shouldReduceMotion ? {} : CROSSFADE), children: jsx("svg", { viewBox: "0 0 24 24", fill: "none", className: cn("size-4", statusIconColor), children: jsx("path", { d: "M5 13l4.5 4.5L19 7", stroke: "currentColor", strokeWidth: 3.5, strokeLinecap: "round", strokeLinejoin: "round" }) }) }, "check")), isError && (jsx(motion.span, { ...(shouldReduceMotion ? {} : CROSSFADE), children: jsx(ArrowPathIcon, { className: cn("size-3.5", statusIconColor), strokeWidth: 2.5 }) }, "retry"))] }) })] }));
74
+ // Determine what to render: radial indicator or remove button
75
+ const showRemoveButton = isComplete && showRemove && onRemove;
76
+ const triggerElement = showRemoveButton ? removeButton : radialElement;
77
+ // No confirm popover needed — return the element directly
78
+ if (!confirmRemove || !onRemove)
79
+ return triggerElement;
80
+ return (jsxs(Popover, { isOpen: confirmOpen, onOpenChange: (open) => {
81
+ setConfirmOpen(open);
82
+ if (!open)
83
+ setIsHovered(false);
84
+ }, placement: "bottom-end", offset: isComplete ? 2 : 6, triggerType: "click", children: [jsx(Popover.Trigger, { children: triggerElement }), jsxs(Popover.Body, { portal: false, className: "flex items-center p-0.5 border-[0.5px] rounded-xl gap-0.5", children: [jsx("span", { className: "text-base font-medium text-[var(--color-text-secondary)] px-3", children: isComplete ? "Remove file?" : "Cancel upload?" }), jsx(Button, { size: "sm", color: "danger", variant: "filled", onClick: handleConfirm, children: "Yes" }), jsx(Button, { size: "sm", variant: "soft", color: "neutral", onClick: () => setConfirmOpen(false), children: "No" })] })] }));
85
+ };
86
+ // --- Main Component ---
87
+ const FileUploadProgress = React__default.forwardRef(({ items, onRemove, onRetry, showFileSize = true, confirmRemove = true, completionDelay = 1500, className, theme: themeOverrides, ...rest }, ref) => {
88
+ var _a;
89
+ const shouldReduceMotion = useReducedMotion();
90
+ const t = fileUploadProgressTheme;
91
+ if (items.length === 0)
92
+ return null;
93
+ const radialProgressColors = {
94
+ ...t.radialProgressColors,
95
+ ...themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.radialProgressColors,
96
+ };
97
+ const statusIconColors = {
98
+ ...t.statusIconColors,
99
+ ...themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.statusIconColors,
100
+ };
101
+ return (jsx("div", { ref: ref, className: cn((_a = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.containerStyle) !== null && _a !== void 0 ? _a : t.containerStyle, className), ...rest, children: items.map((item) => {
102
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
103
+ const clampedProgress = Math.min(100, Math.max(0, item.progress));
104
+ const ext = getFileExtension(item.file.name);
105
+ const hasFileTypeIcon = ext !== null && isKnownFileType(ext);
106
+ return (jsxs("div", { className: (_a = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.itemStyle) !== null && _a !== void 0 ? _a : t.itemStyle, children: [hasFileTypeIcon ? (jsx("span", { className: "shrink-0", children: jsx(FileTypeIcon, { type: ext, size: "lg" }) })) : (jsx("span", { className: cn((_b = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.iconContainerStyle) !== null && _b !== void 0 ? _b : t.iconContainerStyle, t.iconSize), children: jsx(DocumentIcon, { className: (_c = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.iconStyle) !== null && _c !== void 0 ? _c : t.iconStyle }) })), jsxs("div", { className: (_d = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.fileInfoStyle) !== null && _d !== void 0 ? _d : t.fileInfoStyle, children: [jsx("p", { className: (_e = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.fileNameStyle) !== null && _e !== void 0 ? _e : t.fileNameStyle, children: item.file.name }), showFileSize && (jsx("p", { className: (_f = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.fileSizeStyle) !== null && _f !== void 0 ? _f : t.fileSizeStyle, children: formatFileSize(item.file.size) })), item.status === "error" && item.error && (jsx("p", { className: (_g = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.errorTextStyle) !== null && _g !== void 0 ? _g : t.errorTextStyle, children: item.error }))] }), jsx(RadialProgress, { progress: clampedProgress, status: item.status, strokeWidth: t.radialStroke, trackColor: (_h = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.radialTrackColor) !== null && _h !== void 0 ? _h : t.radialTrackColor, progressColor: radialProgressColors[item.status], centerTextStyle: (_j = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.radialCenterTextStyle) !== null && _j !== void 0 ? _j : t.radialCenterTextStyle, statusIconColor: statusIconColors[item.status], sizeClass: t.radialSize, shouldReduceMotion: shouldReduceMotion, confirmRemove: confirmRemove, completionDelay: completionDelay, onRemove: onRemove ? () => onRemove(item.id) : undefined, onRetry: onRetry ? () => onRetry(item.id) : undefined })] }, item.id));
107
+ }) }));
108
+ });
109
+ FileUploadProgress.displayName = "FileUploadProgress";
110
+
111
+ export { FileUploadProgress };
@@ -0,0 +1,19 @@
1
+ import type { FileUploadProgressStatus } from "./FileUploadProgress.types";
2
+ export interface FileUploadProgressTheme {
3
+ containerStyle: string;
4
+ itemStyle: string;
5
+ iconContainerStyle: string;
6
+ iconStyle: string;
7
+ fileInfoStyle: string;
8
+ fileNameStyle: string;
9
+ fileSizeStyle: string;
10
+ radialTrackColor: string;
11
+ radialProgressColors: Record<FileUploadProgressStatus, string>;
12
+ radialCenterTextStyle: string;
13
+ statusIconColors: Record<FileUploadProgressStatus, string>;
14
+ errorTextStyle: string;
15
+ radialSize: string;
16
+ radialStroke: number;
17
+ iconSize: string;
18
+ }
19
+ export declare const fileUploadProgressTheme: FileUploadProgressTheme;
@@ -0,0 +1,27 @@
1
+ const fileUploadProgressTheme = {
2
+ containerStyle: "flex flex-col gap-3",
3
+ itemStyle: "w-full flex items-center gap-x-3",
4
+ iconContainerStyle: "flex items-center justify-center rounded-lg shrink-0 border border-[var(--color-border)] bg-[var(--color-background-secondary)]",
5
+ iconStyle: "shrink-0 size-5 text-[var(--color-text-muted)]",
6
+ fileInfoStyle: "flex-1 min-w-0",
7
+ fileNameStyle: "text-base font-medium text-[var(--color-text-primary)] truncate",
8
+ fileSizeStyle: "text-sm text-[var(--color-text-muted)]",
9
+ radialTrackColor: "var(--color-background-tertiary)",
10
+ radialProgressColors: {
11
+ uploading: "var(--color-primary)",
12
+ complete: "var(--color-success)",
13
+ error: "var(--color-danger)",
14
+ },
15
+ radialCenterTextStyle: "text-[10px] font-semibold tabular-nums text-[var(--color-text-secondary)]",
16
+ statusIconColors: {
17
+ uploading: "",
18
+ complete: "text-[var(--color-success)]",
19
+ error: "text-[var(--color-danger)]",
20
+ },
21
+ errorTextStyle: "text-xs text-[var(--color-danger)]",
22
+ iconSize: "size-10",
23
+ radialSize: "size-8",
24
+ radialStroke: 3,
25
+ };
26
+
27
+ export { fileUploadProgressTheme };
@@ -0,0 +1,33 @@
1
+ export type FileUploadProgressStatus = 'uploading' | 'complete' | 'error';
2
+ export interface FileUploadProgressItem {
3
+ id: string;
4
+ file: File;
5
+ progress: number;
6
+ status: FileUploadProgressStatus;
7
+ error?: string;
8
+ }
9
+ export interface FileUploadProgressThemeOverrides {
10
+ containerStyle?: string;
11
+ itemStyle?: string;
12
+ iconContainerStyle?: string;
13
+ iconStyle?: string;
14
+ fileInfoStyle?: string;
15
+ fileNameStyle?: string;
16
+ fileSizeStyle?: string;
17
+ radialTrackColor?: string;
18
+ radialProgressColors?: Partial<Record<FileUploadProgressStatus, string>>;
19
+ radialCenterTextStyle?: string;
20
+ statusIconColors?: Partial<Record<FileUploadProgressStatus, string>>;
21
+ errorTextStyle?: string;
22
+ }
23
+ export interface FileUploadProgressProps extends React.HTMLAttributes<HTMLDivElement> {
24
+ items: FileUploadProgressItem[];
25
+ onRemove?: (id: string) => void;
26
+ onRetry?: (id: string) => void;
27
+ showFileSize?: boolean;
28
+ confirmRemove?: boolean;
29
+ /** Delay in ms before the completion tick transitions to the remove button. Default: 1500 */
30
+ completionDelay?: number;
31
+ className?: string;
32
+ theme?: FileUploadProgressThemeOverrides;
33
+ }
@@ -1,3 +1,6 @@
1
1
  export { FileUpload } from './FileUpload';
2
2
  export { fileUploadTheme } from './FileUpload.theme';
3
3
  export type { FileUploadProps, FileUploadError, FileUploadThemeOverrides, UploadedFile } from './FileUpload.types';
4
+ export { FileUploadProgress } from './FileUploadProgress';
5
+ export { fileUploadProgressTheme } from './FileUploadProgress.theme';
6
+ export type { FileUploadProgressProps, FileUploadProgressItem, FileUploadProgressStatus, FileUploadProgressThemeOverrides, } from './FileUploadProgress.types';
@@ -4,12 +4,7 @@ import { FormLabel } from '../FormLabel/FormLabel.js';
4
4
  import { inputTheme } from './Input.theme.js';
5
5
  import { cn } from '../../../utils/cn.js';
6
6
  import { LockClosedIcon, EyeSlashIcon, EyeIcon } from '@heroicons/react/24/solid';
7
- import { PlusIcon } from '../../../icons/core/PlusIcon.js';
8
- import { MinusIcon } from '../../../icons/core/MinusIcon.js';
9
- import { SearchIcon } from '../../../icons/core/SearchIcon.js';
10
- import '../../../icons/core/LockIcon.js';
11
- import '../../../icons/core/DollarIcon.js';
12
- import '../../../icons/core/TickIcon.js';
7
+ import { MagnifyingGlassIcon, MinusIcon, PlusIcon } from '@heroicons/react/24/outline';
13
8
  import { validateMaskedInput, applyInputMask, getAdjustedCursorPosition } from './inputMasks.js';
14
9
 
15
10
  const PasswordToggleButton = ({ showPassword, onToggle, passwordToggleClasses, }) => {
@@ -31,10 +26,10 @@ const NumberButtons = ({ isDisabled, isAtMax, isAtMin, onIncrement, onDecrement,
31
26
  return (jsxs("div", { className: numberButtonsContainerClasses, children: [jsx("button", { type: "button", className: `${numberButtonClasses}`, onClick: (e) => {
32
27
  e.stopPropagation();
33
28
  onDecrement();
34
- }, disabled: isDisabled || isAtMin, "aria-label": "Decrease value", tabIndex: -1, children: jsx(MinusIcon, { size: "xs", className: decrementIconStyle, "aria-hidden": "true" }) }), jsx("button", { type: "button", className: `${numberButtonClasses}`, onClick: (e) => {
29
+ }, disabled: isDisabled || isAtMin, "aria-label": "Decrease value", tabIndex: -1, children: jsx(MinusIcon, { className: cn("size-4", decrementIconStyle), "aria-hidden": "true" }) }), jsx("button", { type: "button", className: `${numberButtonClasses}`, onClick: (e) => {
35
30
  e.stopPropagation();
36
31
  onIncrement();
37
- }, disabled: isDisabled || isAtMax, "aria-label": "Increase value", tabIndex: -1, children: jsx(PlusIcon, { size: "xs", className: incrementIconStyle, "aria-hidden": "true" }) })] }));
32
+ }, disabled: isDisabled || isAtMax, "aria-label": "Increase value", tabIndex: -1, children: jsx(PlusIcon, { className: cn("size-4", incrementIconStyle), "aria-hidden": "true" }) })] }));
38
33
  };
39
34
  const getActiveDots = (strength) => {
40
35
  switch (strength) {
@@ -72,7 +67,7 @@ const PasswordStrengthIndicator = ({ inline = false, passwordStrengthIndicator,
72
67
  // ============================================================================
73
68
  // Main Input Component
74
69
  // ============================================================================
75
- const Input = React__default.forwardRef(({ size = "md", state = "default", className = "", label, labelClassName = "", helperText, helperTextClassName = "", wrapperClassName = "", inputGroupClassName = "", iconStart, iconEnd, contentStart, contentEnd, keyboardShortcut, id, required, type = "text", passwordToggle = type === "password", passwordStrengthIndicator, showNumberControls = false, min, max, step = 1, onChange, onFocus, onBlur, value, currencyDecimalPlaces, ...props }, ref) => {
70
+ const Input = React__default.forwardRef(({ size = "md", state = "default", className = "", label, labelClassName = "", helperText, helperTextClassName = "", wrapperClassName = "", inputGroupClassName = "", iconStart, iconEnd, contentStart, contentEnd, keyboardShortcut, id, required, type = "text", passwordToggle = type === "password", passwordStrengthIndicator, showNumberControls = false, min, max, step = 1, onChange, onFocus, onBlur, value, currencyDecimalPlaces, darkMode = false, ...props }, ref) => {
76
71
  const [isFocused, setIsFocused] = useState(false);
77
72
  const [showPassword, setShowPassword] = useState(false);
78
73
  const generatedId = React__default.useId();
@@ -88,7 +83,7 @@ const Input = React__default.forwardRef(({ size = "md", state = "default", class
88
83
  const cursorPositionRef = useRef(null);
89
84
  // Default icons based on input type
90
85
  const defaultPasswordIcon = type === "password" && !iconStart ? (jsx(LockClosedIcon, { className: "size-5 text-[var(--color-text-muted)]" })) : null;
91
- const defaultSearchIcon = type === "search" && !iconStart ? (jsx(SearchIcon, { size: "sm", className: inputTheme.typeStyles.search.iconStyle })) : null;
86
+ const defaultSearchIcon = type === "search" && !iconStart ? (jsx(MagnifyingGlassIcon, { className: cn("size-5", inputTheme.typeStyles.search.iconStyle) })) : null;
92
87
  // Use the provided iconStart or the default icon based on input type
93
88
  const finalLeftIcon = iconStart || defaultPasswordIcon || defaultSearchIcon;
94
89
  // Derived state flags for internal use
@@ -275,14 +270,14 @@ const Input = React__default.forwardRef(({ size = "md", state = "default", class
275
270
  numberValue !== undefined &&
276
271
  typeof min === "number" &&
277
272
  numberValue <= min;
278
- return (jsxs("div", { className: cn(wrapperClasses, stateClass, wrapperClassName), children: [label && (typeof label === 'string' ? (jsxs("div", { className: "flex justify-between items-center", children: [jsx(FormLabel, { htmlFor: inputId, className: labelClassName, state: state, required: required, children: label }), showStrengthWithLabel && (jsx(PasswordStrengthIndicator, { inline: true, passwordStrengthIndicator: passwordStrengthIndicator }))] })) : (jsxs("div", { className: "flex justify-between items-center", children: [label, showStrengthWithLabel && (jsx(PasswordStrengthIndicator, { inline: true, passwordStrengthIndicator: passwordStrengthIndicator }))] }))), jsx("div", { children: jsxs("div", { className: cn(inputGroupClasses, stateClasses, isFocused && (isInvalid ? inputTheme.inputGroupFocusInvalidStyle : inputTheme.inputGroupFocusStyle), inputGroupClassName), onClick: handleInputGroupClick, role: "presentation", children: [hasContentStart && (jsx("div", { "data-slot": "content-start", className: cn(contentStyleClasses, contentStartStyle), children: contentStart })), jsxs("div", { className: "relative flex-1", children: [jsx("input", { ref: setInputRef, id: inputId, type: actualInputType, className: cn(baseClasses, sizeClasses, hasLeftIcon && iconStartPadding, (hasRightIcon || isPasswordField || displayNumberControls) &&
279
- iconEndPadding, className), disabled: isDisabled, "aria-invalid": isInvalid, required: required, min: min, max: max, step: step, value: value, onChange: handleInputChange, onFocus: (e) => {
273
+ return (jsxs("div", { className: cn(wrapperClasses, stateClass, darkMode && "dark", wrapperClassName), children: [label && (typeof label === 'string' ? (jsxs("div", { className: "flex justify-between items-center", children: [jsx(FormLabel, { htmlFor: inputId, className: labelClassName, state: state, required: required, children: label }), showStrengthWithLabel && (jsx(PasswordStrengthIndicator, { inline: true, passwordStrengthIndicator: passwordStrengthIndicator }))] })) : (jsxs("div", { className: "flex justify-between items-center", children: [label, showStrengthWithLabel && (jsx(PasswordStrengthIndicator, { inline: true, passwordStrengthIndicator: passwordStrengthIndicator }))] }))), jsx("div", { children: jsxs("div", { className: cn(inputGroupClasses, stateClasses, isFocused && (isInvalid ? inputTheme.inputGroupFocusInvalidStyle : inputTheme.inputGroupFocusStyle), inputGroupClassName), onClick: handleInputGroupClick, role: "presentation", children: [hasContentStart && (jsx("div", { "data-slot": "content-start", className: cn(contentStyleClasses, contentStartStyle), children: contentStart })), jsxs("div", { className: "relative flex-1", children: [jsx("input", { ref: setInputRef, id: inputId, type: actualInputType, className: cn(baseClasses, sizeClasses, hasLeftIcon && iconStartPadding, (hasRightIcon || isPasswordField || displayNumberControls) &&
274
+ iconEndPadding, className), disabled: isDisabled, "aria-invalid": isInvalid, "aria-describedby": helperText ? `${inputId}-helper` : undefined, required: required, min: min, max: max, step: step, value: value, onChange: handleInputChange, onFocus: (e) => {
280
275
  setIsFocused(true);
281
276
  onFocus === null || onFocus === void 0 ? void 0 : onFocus(e);
282
277
  }, onBlur: (e) => {
283
278
  setIsFocused(false);
284
279
  onBlur === null || onBlur === void 0 ? void 0 : onBlur(e);
285
- }, placeholder: props.placeholder, ...props }), hasLeftIcon && (jsx("div", { className: iconStartClasses, children: finalLeftIcon })), hasRightIcon && !isPasswordField && !displayNumberControls && (jsx("div", { className: iconEndClasses, children: iconEnd })), isPasswordField && (jsx(PasswordToggleButton, { showPassword: showPassword, onToggle: handleTogglePassword, passwordToggleClasses: passwordToggleClasses })), displayNumberControls && (jsx(NumberButtons, { isDisabled: isDisabled, isAtMax: isAtMax, isAtMin: isAtMin, onIncrement: handleIncrement, onDecrement: handleDecrement, numberButtonsContainerClasses: numberButtonsContainerClasses, numberButtonClasses: numberButtonClasses })), hasKeyboardShortcut && (jsx("div", { className: inputTheme.keyboardShortcutStyle, children: keyboardShortcut }))] }), hasContentEnd && (jsx("div", { "data-slot": "content-end", className: cn(contentStyleClasses, contentEndStyle), children: contentEnd }))] }) }), showStrengthBelow && jsx(PasswordStrengthIndicator, { inline: false, passwordStrengthIndicator: passwordStrengthIndicator }), helperText && (typeof helperText === 'string' ? (jsx("div", { className: cn(helperTextClasses, helperTextClassName), children: helperText })) : (helperText))] }));
280
+ }, placeholder: props.placeholder, ...props }), hasLeftIcon && (jsx("div", { className: iconStartClasses, children: finalLeftIcon })), hasRightIcon && !isPasswordField && !displayNumberControls && (jsx("div", { className: iconEndClasses, children: iconEnd })), isPasswordField && (jsx(PasswordToggleButton, { showPassword: showPassword, onToggle: handleTogglePassword, passwordToggleClasses: passwordToggleClasses })), displayNumberControls && (jsx(NumberButtons, { isDisabled: isDisabled, isAtMax: isAtMax, isAtMin: isAtMin, onIncrement: handleIncrement, onDecrement: handleDecrement, numberButtonsContainerClasses: numberButtonsContainerClasses, numberButtonClasses: numberButtonClasses })), hasKeyboardShortcut && (jsx("div", { className: inputTheme.keyboardShortcutStyle, children: keyboardShortcut }))] }), hasContentEnd && (jsx("div", { "data-slot": "content-end", className: cn(contentStyleClasses, contentEndStyle), children: contentEnd }))] }) }), showStrengthBelow && jsx(PasswordStrengthIndicator, { inline: false, passwordStrengthIndicator: passwordStrengthIndicator }), helperText && (typeof helperText === 'string' ? (jsx("div", { id: `${inputId}-helper`, className: cn(helperTextClasses, helperTextClassName), children: helperText })) : (helperText))] }));
286
281
  });
287
282
  Input.displayName = "Input";
288
283
 
@@ -61,6 +61,12 @@ export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElem
61
61
  passwordStrengthIndicator?: PasswordStrengthIndicator;
62
62
  /** Number of decimal places for currency inputs (default: 2). Only applies when type="currency" */
63
63
  currencyDecimalPlaces?: number;
64
+ /**
65
+ * Force dark mode styling for the component. Use when placing the component
66
+ * on a dark background while the page is in light mode.
67
+ * @default false
68
+ */
69
+ darkMode?: boolean;
64
70
  }
65
71
  export type InputSize = 'sm' | 'md' | 'lg';
66
72
  export type InputState = 'default' | 'disabled' | 'invalid';
@@ -23,7 +23,7 @@ const inputAddressTheme = {
23
23
  postalCodeInput: {
24
24
  ...inputTheme,
25
25
  },
26
- chevronStyles: 'pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-gray-500 sm:size-4',
26
+ chevronStyles: 'pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-[var(--color-text-muted)] sm:size-4',
27
27
  };
28
28
  /**
29
29
  * Styled theme matching the reference design
@@ -33,7 +33,7 @@ import { MinusIcon, PlusIcon } from '@heroicons/react/24/outline';
33
33
  * );
34
34
  * ```
35
35
  */
36
- const InputCounter = React__default.forwardRef(({ value, onChange, min, max, step = 1, disabled = false, decimalPlaces, formatNumber = (n) => n.toString(), className, buttonProps, theme, transition = { type: "spring", bounce: 0, stiffness: 300, damping: 30 }, "aria-label": ariaLabel = "Counter", ...props }, ref) => {
36
+ const InputCounter = React__default.forwardRef(({ value, onChange, min, max, step = 1, disabled = false, decimalPlaces, formatNumber = (n) => n.toString(), className, buttonProps, theme, transition = { type: "spring", bounce: 0, stiffness: 300, damping: 30 }, "aria-label": ariaLabel = "Counter", onAnimationStart, onAnimationEnd, onDrag, onDragStart, onDragEnd, ...props }, ref) => {
37
37
  const shouldReduceMotion = useReducedMotion();
38
38
  const shouldDisableAnimations = !!shouldReduceMotion;
39
39
  // Auto-detect decimal places from step if not explicitly provided
@@ -26,7 +26,7 @@ const inputCreditCardTheme = {
26
26
  cvcInput: {
27
27
  ...inputTheme,
28
28
  },
29
- chevronStyles: 'pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-gray-500 sm:size-4',
29
+ chevronStyles: 'pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-[var(--color-text-muted)] sm:size-4',
30
30
  };
31
31
  /**
32
32
  * Styled theme matching the reference design
@@ -10,7 +10,7 @@ const inputOTPTheme = {
10
10
  // OTP input container
11
11
  containerStyle: 'flex items-center gap-3',
12
12
  // Individual input field styles with design tokens
13
- inputStyle: 'text-center text-xl text-[var(--color-text-primary)] h-full',
13
+ inputStyle: 'text-center text-xl text-[var(--color-text-primary)] h-full !p-0',
14
14
  // Input group wrapper for grouped inputs (overrides default Input styling)
15
15
  inputGroupStyle: 'w-10 min-w-10 h-10 min-h-10 sm:w-12 sm:min-w-12 sm:h-12 sm:min-h-12',
16
16
  // Separator between input groups
@@ -0,0 +1,10 @@
1
+ import { Variants } from "motion/react";
2
+ /**
3
+ * Radio dot spring animation
4
+ * Scales in with a subtle bounce on select, fades out smoothly on deselect
5
+ */
6
+ export declare const radioDotVariants: Variants;
7
+ /**
8
+ * Reduced motion variants — instant opacity toggle, no scale
9
+ */
10
+ export declare const reducedMotionDotVariants: Variants;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Radio dot spring animation
3
+ * Scales in with a subtle bounce on select, fades out smoothly on deselect
4
+ */
5
+ const radioDotVariants = {
6
+ unchecked: {
7
+ scale: 0,
8
+ opacity: 0,
9
+ transition: {
10
+ duration: 0.15,
11
+ ease: "easeOut",
12
+ },
13
+ },
14
+ checked: {
15
+ scale: 1,
16
+ opacity: 1,
17
+ transition: {
18
+ type: "spring",
19
+ stiffness: 400,
20
+ damping: 15,
21
+ mass: 0.5,
22
+ },
23
+ },
24
+ };
25
+ /**
26
+ * Reduced motion variants — instant opacity toggle, no scale
27
+ */
28
+ const reducedMotionDotVariants = {
29
+ unchecked: { opacity: 0 },
30
+ checked: { opacity: 1 },
31
+ };
32
+
33
+ export { radioDotVariants, reducedMotionDotVariants };
@@ -1,10 +1,12 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
- import React__default, { useId } from 'react';
2
+ import React__default, { useId, useState } from 'react';
3
+ import { useReducedMotion, motion } from 'motion/react';
3
4
  import { radioTheme } from './Radio.theme.js';
4
5
  import { formLabelTheme } from '../FormLabel/FormLabel.theme.js';
5
6
  import { cn } from '../../../utils/cn.js';
6
7
  import { useRadioGroupContext } from './RadioContext.js';
7
8
  import { RadioGroup } from './RadioGroup.js';
9
+ import { reducedMotionDotVariants, radioDotVariants } from './Radio.animations.js';
8
10
 
9
11
  /**
10
12
  * Radio component for selecting one option from a group
@@ -12,6 +14,7 @@ import { RadioGroup } from './RadioGroup.js';
12
14
  const RadioComponent = React__default.forwardRef(({ id: idProp, name: nameProp, value, checked: checkedProp, defaultChecked, onChange, label, description, state: stateProp = "default", size: sizeProp = "md", className, ...restProps }, ref) => {
13
15
  var _a, _b, _c, _d;
14
16
  const autoId = useId();
17
+ const shouldReduceMotion = useReducedMotion();
15
18
  const groupContext = useRadioGroupContext();
16
19
  // Resolve props from group context or individual props
17
20
  const id = idProp !== null && idProp !== void 0 ? idProp : autoId;
@@ -23,9 +26,15 @@ const RadioComponent = React__default.forwardRef(({ id: idProp, name: nameProp,
23
26
  const isInGroup = groupContext !== undefined;
24
27
  const checked = isInGroup ? groupContext.value === value : checkedProp;
25
28
  const isControlled = checked !== undefined;
29
+ // Track internal state for uncontrolled radios (defaultChecked)
30
+ const [internalChecked, setInternalChecked] = useState(defaultChecked !== null && defaultChecked !== void 0 ? defaultChecked : false);
31
+ const isChecked = isControlled ? !!checked : internalChecked;
26
32
  const handleChange = (e) => {
27
33
  if (isDisabled)
28
34
  return;
35
+ if (!isControlled) {
36
+ setInternalChecked(e.target.checked);
37
+ }
29
38
  if (isInGroup) {
30
39
  groupContext.onChange(value);
31
40
  }
@@ -34,7 +43,7 @@ const RadioComponent = React__default.forwardRef(({ id: idProp, name: nameProp,
34
43
  const inputProps = isControlled
35
44
  ? { checked }
36
45
  : { defaultChecked };
37
- return (jsxs("div", { className: cn(radioTheme.baseStyle, className), ...restProps, children: [jsxs("div", { className: cn(radioTheme.inputContainerStyle, radioTheme.sizes[size]), children: [jsx("input", { ref: ref, type: "radio", id: id, name: name, value: value, ...inputProps, onChange: handleChange, disabled: isDisabled, "aria-describedby": description ? `${id}-description` : undefined, "data-state": isDisabled ? "disabled" : "default", className: cn("peer", radioTheme.inputStyle, radioTheme.sizes[size]) }), jsx("div", { className: cn(radioTheme.dotStyle, size === "sm" ? "size-2.5 top-0.25" : "size-3") })] }), (label || description) && (jsxs("label", { htmlFor: id, className: cn("cursor-pointer", isDisabled && "cursor-not-allowed"), children: [label && (typeof label === 'string' ? (jsx("span", { className: cn(formLabelTheme.baseStyle, formLabelTheme.stateStyles[state], "mb-0"), children: label })) : label), description && (typeof description === 'string' ? (jsx("div", { id: `${id}-description`, className: radioTheme.descriptionStyle, children: description })) : description)] }))] }));
46
+ return (jsxs("div", { className: cn(radioTheme.baseStyle, className), ...restProps, children: [jsxs("div", { className: cn(radioTheme.inputContainerStyle, radioTheme.sizes[size]), children: [jsx("input", { ref: ref, type: "radio", id: id, name: name, value: value, ...inputProps, onChange: handleChange, disabled: isDisabled, "aria-describedby": description ? `${id}-description` : undefined, "data-state": isDisabled ? "disabled" : "default", className: cn("peer", radioTheme.inputStyle, radioTheme.sizes[size]) }), jsx(motion.div, { className: cn(radioTheme.dotStyle, isDisabled && "saturate-0 opacity-80", size === "sm" ? "size-2.5" : "size-3"), initial: false, animate: isChecked ? "checked" : "unchecked", variants: shouldReduceMotion ? reducedMotionDotVariants : radioDotVariants })] }), (label || description) && (jsxs("label", { htmlFor: id, className: cn("cursor-pointer", isDisabled && "cursor-not-allowed"), children: [label && (typeof label === 'string' ? (jsx("span", { className: cn(formLabelTheme.baseStyle, formLabelTheme.stateStyles[state], "mb-0"), children: label })) : label), description && (typeof description === 'string' ? (jsx("div", { id: `${id}-description`, className: radioTheme.descriptionStyle, children: description })) : description)] }))] }));
38
47
  });
39
48
  RadioComponent.displayName = "Radio";
40
49
  const Radio = Object.assign(RadioComponent, { Group: RadioGroup });
@@ -9,11 +9,11 @@ const radioTheme = {
9
9
  // Default state - light
10
10
  "border-[var(--color-border)] bg-[var(--color-surface)] " +
11
11
  // Default state - dark
12
- "dark:bg-[var(--color-background-secondary)] " +
12
+ "dark:bg-[var(--color-background-tertiary)] " +
13
13
  // Checked state - light
14
14
  "checked:border-[var(--color-primary)] " +
15
15
  // Checked state - dark
16
- " " +
16
+ "checked:bg-[var(--color-neutral-200)] " +
17
17
  // Checked outline - light
18
18
  "checked:outline-2 checked:outline-[var(--color-primary-100)] checked:outline-offset-1 " +
19
19
  // Checked outline - dark
@@ -28,7 +28,7 @@ const radioTheme = {
28
28
  // Disabled state - dark
29
29
  "dark:disabled:bg-[var(--color-neutral-700)] dark:disabled:border-[var(--color-neutral-600)] " +
30
30
  "dark:data-[state=disabled]:bg-[var(--color-neutral-700)] dark:data-[state=disabled]:border-[var(--color-neutral-600)]",
31
- dotStyle: "absolute inset-0 m-auto pointer-events-none rounded-full bg-[var(--color-primary)] opacity-0 transition-all duration-400 peer-checked:opacity-100 peer-data-[state=disabled]:saturate-0 peer-data-[state=disabled]:peer-checked:opacity-80",
31
+ dotStyle: "absolute inset-0 m-auto pointer-events-none rounded-full bg-[var(--color-primary)]",
32
32
  descriptionStyle: "text-base text-[var(--color-text-secondary)]/80 mt-0.5",
33
33
  sizes: {
34
34
  sm: "size-5 mt-0.25",