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

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 (254) hide show
  1. package/dist/components/ai/CodeBlock/CodeBlock.theme.js +1 -1
  2. package/dist/components/ai/PromptInput/PromptInput.js +3 -1
  3. package/dist/components/ai/PromptSuggestions/PromptSuggestion.theme.js +4 -4
  4. package/dist/components/ai/StreamingResponse/StreamingResponse.js +6 -0
  5. package/dist/components/ai/ThinkingIndicator/ThinkingIndicator.js +3 -14
  6. package/dist/components/ai/index.d.ts +0 -5
  7. package/dist/components/ai/index.js +8 -4
  8. package/dist/components/charts/DonutChart/DonutChart.js +1 -1
  9. package/dist/components/charts/DonutChart/MultiSegmentDonutChart.js +1 -1
  10. package/dist/components/charts/shared/ChartLegend/ChartLegend.types.d.ts +13 -1
  11. package/dist/components/charts/shared/ChartLegend/ChartLegendContent.js +1 -1
  12. package/dist/components/charts/shared/ChartTooltip/ChartTooltip.types.d.ts +13 -2
  13. package/dist/components/core/Accordion/AccordionItem.js +1 -1
  14. package/dist/components/core/Accordion/AccordionTrigger.js +1 -1
  15. package/dist/components/core/Alert/Alert.animations.d.ts +11 -0
  16. package/dist/components/core/Alert/Alert.animations.js +44 -0
  17. package/dist/components/core/Alert/Alert.js +16 -3
  18. package/dist/components/core/Avatar/Avatar.js +12 -7
  19. package/dist/components/core/Avatar/Avatar.theme.d.ts +4 -6
  20. package/dist/components/core/Avatar/Avatar.theme.js +22 -12
  21. package/dist/components/core/Avatar/Avatar.types.d.ts +9 -0
  22. package/dist/components/core/AvatarGroup/AvatarGroup.animations.js +2 -2
  23. package/dist/components/core/AvatarGroup/AvatarGroup.js +1 -2
  24. package/dist/components/core/AvatarGroup/AvatarGroup.theme.js +1 -1
  25. package/dist/components/core/Badge/Badge.animations.js +1 -1
  26. package/dist/components/core/Badge/Badge.js +23 -47
  27. package/dist/components/core/Badge/Badge.theme.js +48 -62
  28. package/dist/components/core/Badge/Badge.types.d.ts +5 -29
  29. package/dist/components/core/Button/Button.js +2 -2
  30. package/dist/components/core/Button/Button.theme.js +2 -2
  31. package/dist/components/core/ButtonGroup/ButtonGroup.theme.js +6 -6
  32. package/dist/components/core/ButtonGroup/ButtonGroupText.js +1 -3
  33. package/dist/components/core/Calendar/Calendar.js +29 -3
  34. package/dist/components/core/Calendar/Calendar.theme.js +11 -7
  35. package/dist/components/core/Calendar/Calendar.types.d.ts +3 -0
  36. package/dist/components/core/Carousel/CarouselBody.js +0 -1
  37. package/dist/components/core/CommandPalette/CommandItem.js +1 -1
  38. package/dist/components/core/CommandPalette/CommandPalette.js +6 -4
  39. package/dist/components/core/CommandPalette/CommandPalette.theme.js +1 -0
  40. package/dist/components/core/CommandPalette/CommandPalette.types.d.ts +6 -0
  41. package/dist/components/core/ContextMenu/ContextMenu.js +5 -4
  42. package/dist/components/core/ContextMenu/ContextMenuTrigger.js +5 -6
  43. package/dist/components/core/Drawer/Drawer.d.ts +1 -1
  44. package/dist/components/core/Drawer/Drawer.js +25 -2
  45. package/dist/components/core/Drawer/Drawer.theme.js +2 -2
  46. package/dist/components/core/Drawer/Drawer.types.d.ts +6 -0
  47. package/dist/components/core/Dropdown/Dropdown.d.ts +1 -1
  48. package/dist/components/core/Dropdown/Dropdown.js +5 -1
  49. package/dist/components/core/Dropdown/Dropdown.types.d.ts +1 -0
  50. package/dist/components/core/Dropdown/DropdownItem.js +1 -1
  51. package/dist/components/core/Dropdown/DropdownMenu.js +4 -4
  52. package/dist/components/core/Dropdown/DropdownSection.js +1 -1
  53. package/dist/components/core/Dropdown/DropdownSeparator.js +1 -1
  54. package/dist/components/core/Dropdown/DropdownTrigger.d.ts +6 -1
  55. package/dist/components/core/Dropdown/DropdownTrigger.js +10 -8
  56. package/dist/components/core/Kbd/Kbd.theme.js +3 -3
  57. package/dist/components/core/Link/Link.js +3 -1
  58. package/dist/components/core/Message/Message.d.ts +9 -0
  59. package/dist/components/core/Message/Message.js +44 -3
  60. package/dist/components/core/Message/Message.theme.js +22 -0
  61. package/dist/components/core/Message/Message.types.d.ts +115 -0
  62. package/dist/components/core/Message/MessageAudio.d.ts +8 -0
  63. package/dist/components/core/Message/MessageAudio.js +11 -0
  64. package/dist/components/core/Message/MessageContext.d.ts +3 -1
  65. package/dist/components/core/Message/MessageDateDivider.d.ts +6 -0
  66. package/dist/components/core/Message/MessageDateDivider.js +10 -0
  67. package/dist/components/core/Message/MessageFile.d.ts +9 -0
  68. package/dist/components/core/Message/MessageFile.js +15 -0
  69. package/dist/components/core/Message/MessageImage.d.ts +11 -0
  70. package/dist/components/core/Message/MessageImage.js +13 -0
  71. package/dist/components/core/Message/MessageLink.d.ts +10 -0
  72. package/dist/components/core/Message/MessageLink.js +15 -0
  73. package/dist/components/core/Message/MessageReactions.d.ts +8 -0
  74. package/dist/components/core/Message/MessageReactions.js +12 -0
  75. package/dist/components/core/Message/MessageReply.d.ts +8 -0
  76. package/dist/components/core/Message/MessageReply.js +10 -0
  77. package/dist/components/core/Message/MessageSenderName.d.ts +6 -0
  78. package/dist/components/core/Message/MessageSenderName.js +10 -0
  79. package/dist/components/core/Message/MessageStatusIndicator.d.ts +9 -0
  80. package/dist/components/core/Message/MessageStatusIndicator.js +45 -0
  81. package/dist/components/core/Message/index.d.ts +19 -1
  82. package/dist/components/core/Modal/Modal.animations.d.ts +1 -0
  83. package/dist/components/core/Modal/Modal.animations.js +14 -11
  84. package/dist/components/core/Pagination/Pagination.theme.js +1 -1
  85. package/dist/components/core/Popover/Popover.d.ts +1 -1
  86. package/dist/components/core/Popover/PopoverBody.js +2 -2
  87. package/dist/components/core/Popover/PopoverTrigger.d.ts +1 -1
  88. package/dist/components/core/Popover/PopoverTrigger.js +11 -11
  89. package/dist/components/core/Progress/Progress.d.ts +9 -8
  90. package/dist/components/core/Progress/Progress.js +16 -16
  91. package/dist/components/core/Progress/Progress.theme.js +5 -16
  92. package/dist/components/core/Progress/Progress.types.d.ts +2 -20
  93. package/dist/components/core/Progress/index.d.ts +1 -1
  94. package/dist/components/core/ScrollArea/ScrollArea.js +49 -7
  95. package/dist/components/core/ScrollArea/ScrollArea.types.d.ts +12 -3
  96. package/dist/components/core/ScrollArea/index.d.ts +1 -1
  97. package/dist/components/core/Segmented/SegmentedItem.js +1 -1
  98. package/dist/components/core/Sidebar/Sidebar.js +2 -1
  99. package/dist/components/core/Sidebar/SidebarMobileTrigger.js +2 -1
  100. package/dist/components/core/Sidebar/SidebarToggle.js +2 -1
  101. package/dist/components/core/Sidebar/SidebarUserProfile.js +1 -1
  102. package/dist/components/core/SocialIcon/SocialIcon.js +1 -1
  103. package/dist/components/core/Sortable/Sortable.js +2 -2
  104. package/dist/components/core/Sortable/Sortable.theme.js +1 -1
  105. package/dist/components/core/Sortable/Sortable.types.d.ts +7 -5
  106. package/dist/components/core/Tabs/TabsBody.js +1 -1
  107. package/dist/components/core/Tabs/TabsTrigger.js +1 -1
  108. package/dist/components/core/Tag/Tag.js +2 -2
  109. package/dist/components/core/Toast/Toast.d.ts +2 -2
  110. package/dist/components/core/Toast/Toast.js +30 -21
  111. package/dist/components/core/Toast/Toast.theme.js +4 -9
  112. package/dist/components/core/Toast/Toast.types.d.ts +4 -21
  113. package/dist/components/core/Toast/index.d.ts +1 -1
  114. package/dist/components/core/Tooltip/Tooltip.js +1 -1
  115. package/dist/components/core/Tooltip/Tooltip.theme.js +1 -1
  116. package/dist/components/core/index.js +9 -0
  117. package/dist/components/data-display/GanttChart/GanttChart.types.d.ts +2 -2
  118. package/dist/components/data-display/Table/Table.types.d.ts +8 -8
  119. package/dist/components/effects/CustomCursor/CustomCursor.js +2 -2
  120. package/dist/components/effects/GlassSurface/GlassSurface.d.ts +1 -1
  121. package/dist/components/effects/GlassSurface/GlassSurface.js +12 -4
  122. package/dist/components/effects/InteractiveCharacters/InteractiveCharacters.animations.d.ts +39 -0
  123. package/dist/components/effects/InteractiveCharacters/InteractiveCharacters.animations.js +98 -0
  124. package/dist/components/effects/InteractiveCharacters/InteractiveCharacters.d.ts +3 -0
  125. package/dist/components/effects/InteractiveCharacters/InteractiveCharacters.js +104 -0
  126. package/dist/components/effects/InteractiveCharacters/InteractiveCharacters.types.d.ts +30 -0
  127. package/dist/components/effects/InteractiveCharacters/characters/BlobCharacter.d.ts +3 -0
  128. package/dist/components/effects/InteractiveCharacters/characters/BlobCharacter.js +36 -0
  129. package/dist/components/effects/InteractiveCharacters/characters/SmallCharacter.d.ts +3 -0
  130. package/dist/components/effects/InteractiveCharacters/characters/SmallCharacter.js +36 -0
  131. package/dist/components/effects/InteractiveCharacters/characters/TallCharacter.d.ts +3 -0
  132. package/dist/components/effects/InteractiveCharacters/characters/TallCharacter.js +37 -0
  133. package/dist/components/effects/InteractiveCharacters/hooks/useBlink.d.ts +14 -0
  134. package/dist/components/effects/InteractiveCharacters/hooks/useBlink.js +41 -0
  135. package/dist/components/effects/InteractiveCharacters/hooks/useIdleAnimation.d.ts +25 -0
  136. package/dist/components/effects/InteractiveCharacters/hooks/useIdleAnimation.js +84 -0
  137. package/dist/components/effects/InteractiveCharacters/hooks/useMouseTracking.d.ts +18 -0
  138. package/dist/components/effects/InteractiveCharacters/hooks/useMouseTracking.js +35 -0
  139. package/dist/components/effects/InteractiveCharacters/index.d.ts +2 -0
  140. package/dist/components/effects/MorphingText/MorphingText.d.ts +1 -1
  141. package/dist/components/effects/MorphingText/MorphingText.js +6 -5
  142. package/dist/components/effects/Neumorphic/InsetCircleButton.d.ts +9 -0
  143. package/dist/components/effects/Neumorphic/InsetCircleButton.js +10 -0
  144. package/dist/components/effects/Neumorphic/InsetPill.d.ts +7 -0
  145. package/dist/components/effects/Neumorphic/InsetPill.js +7 -0
  146. package/dist/components/effects/Neumorphic/index.d.ts +4 -0
  147. package/dist/components/effects/NoiseOverlay/NoiseOverlay.d.ts +1 -1
  148. package/dist/components/effects/NoiseOverlay/NoiseOverlay.js +4 -4
  149. package/dist/components/effects/Overlay/Overlay.js +6 -4
  150. package/dist/components/effects/PageTransition/PageTransition.animations.d.ts +8 -0
  151. package/dist/components/effects/PageTransition/PageTransition.animations.js +53 -0
  152. package/dist/components/effects/PageTransition/PageTransition.d.ts +3 -0
  153. package/dist/components/effects/PageTransition/PageTransition.js +71 -0
  154. package/dist/components/effects/PageTransition/PageTransition.types.d.ts +15 -0
  155. package/dist/components/effects/PageTransition/index.d.ts +2 -0
  156. package/dist/components/effects/index.d.ts +6 -0
  157. package/dist/components/effects/index.js +4 -0
  158. package/dist/components/forms/Checkbox/Checkbox.animations.d.ts +14 -0
  159. package/dist/components/forms/Checkbox/Checkbox.animations.js +53 -0
  160. package/dist/components/forms/Checkbox/Checkbox.js +4 -2
  161. package/dist/components/forms/Checkbox/Checkbox.theme.js +3 -3
  162. package/dist/components/forms/ColorPicker/ColorPicker.types.d.ts +1 -1
  163. package/dist/components/forms/ColorPicker/ColorPickerBody.js +3 -3
  164. package/dist/components/forms/Combobox/Combobox.js +5 -3
  165. package/dist/components/forms/DatePicker/DatePickerBody.js +1 -1
  166. package/dist/components/forms/DateRangePicker/DateRangePicker.animations.d.ts +1 -0
  167. package/dist/components/forms/DateRangePicker/DateRangePicker.d.ts +37 -0
  168. package/dist/components/forms/DateRangePicker/DateRangePicker.js +110 -0
  169. package/dist/components/forms/DateRangePicker/DateRangePicker.theme.d.ts +5 -0
  170. package/dist/components/forms/DateRangePicker/DateRangePicker.theme.js +52 -0
  171. package/dist/components/forms/DateRangePicker/DateRangePicker.types.d.ts +154 -0
  172. package/dist/components/forms/DateRangePicker/DateRangePickerBody.d.ts +6 -0
  173. package/dist/components/forms/DateRangePicker/DateRangePickerBody.js +208 -0
  174. package/dist/components/forms/DateRangePicker/DateRangePickerPresets.d.ts +6 -0
  175. package/dist/components/forms/DateRangePicker/DateRangePickerPresets.js +41 -0
  176. package/dist/components/forms/DateRangePicker/DateRangePickerTrigger.d.ts +6 -0
  177. package/dist/components/forms/DateRangePicker/DateRangePickerTrigger.js +32 -0
  178. package/dist/components/forms/DateRangePicker/dateRangePresets.d.ts +5 -0
  179. package/dist/components/forms/DateRangePicker/dateRangePresets.js +59 -0
  180. package/dist/components/forms/DateRangePicker/index.d.ts +4 -0
  181. package/dist/components/forms/FileUpload/FileUploadProgress.animations.d.ts +36 -0
  182. package/dist/components/forms/FileUpload/FileUploadProgress.animations.js +22 -0
  183. package/dist/components/forms/FileUpload/FileUploadProgress.d.ts +3 -0
  184. package/dist/components/forms/FileUpload/FileUploadProgress.js +111 -0
  185. package/dist/components/forms/FileUpload/FileUploadProgress.theme.d.ts +19 -0
  186. package/dist/components/forms/FileUpload/FileUploadProgress.theme.js +27 -0
  187. package/dist/components/forms/FileUpload/FileUploadProgress.types.d.ts +33 -0
  188. package/dist/components/forms/FileUpload/index.d.ts +3 -0
  189. package/dist/components/forms/Input/Input.js +8 -13
  190. package/dist/components/forms/Input/Input.types.d.ts +6 -0
  191. package/dist/components/forms/InputAddress/InputAddress.theme.js +1 -1
  192. package/dist/components/forms/InputCounter/InputCounter.js +1 -1
  193. package/dist/components/forms/InputCreditCard/InputCreditCard.theme.js +1 -1
  194. package/dist/components/forms/InputOTP/InputOTP.theme.js +1 -1
  195. package/dist/components/forms/Radio/Radio.animations.d.ts +10 -0
  196. package/dist/components/forms/Radio/Radio.animations.js +33 -0
  197. package/dist/components/forms/Radio/Radio.js +11 -2
  198. package/dist/components/forms/Radio/Radio.theme.js +3 -3
  199. package/dist/components/forms/RichTextEditor/RichTextEditor.js +13 -4
  200. package/dist/components/forms/RichTextEditor/RichTextEditor.theme.js +2 -2
  201. package/dist/components/forms/RichTextEditor/RichTextEditor.types.d.ts +11 -0
  202. package/dist/components/forms/Select/Select.d.ts +1 -1
  203. package/dist/components/forms/Select/Select.js +7 -7
  204. package/dist/components/forms/Select/Select.types.d.ts +3 -3
  205. package/dist/components/forms/SelectableCard/SelectableCard.js +1 -1
  206. package/dist/components/forms/Slider/Slider.theme.js +1 -1
  207. package/dist/components/forms/Switch/Switch.theme.js +3 -3
  208. package/dist/components/forms/forms.theme.js +1 -1
  209. package/dist/components/forms/index.d.ts +6 -0
  210. package/dist/components/forms/index.js +8 -0
  211. package/dist/hooks/index.d.ts +1 -0
  212. package/dist/hooks/useMediaQuery.d.ts +5 -0
  213. package/dist/hooks/useMediaQuery.js +21 -0
  214. package/dist/index.js +21 -0
  215. package/dist/styles.css +1 -1
  216. package/dist/utils/dateUtils.js +56 -5
  217. package/dist/utils/formatUtils.d.ts +10 -0
  218. package/dist/utils/formatUtils.js +24 -0
  219. package/dist/utils/index.d.ts +1 -1
  220. package/package.json +12 -4
  221. package/src/global.scss +319 -39
  222. package/src/styles/theme.css +105 -16
  223. package/src/theme-plugin.css +13 -0
  224. package/dist/components/ai/ApprovalCard/ApprovalCard.d.ts +0 -3
  225. package/dist/components/ai/ApprovalCard/ApprovalCard.js +0 -16
  226. package/dist/components/ai/ApprovalCard/ApprovalCard.theme.d.ts +0 -13
  227. package/dist/components/ai/ApprovalCard/ApprovalCard.theme.js +0 -15
  228. package/dist/components/ai/ApprovalCard/ApprovalCard.types.d.ts +0 -43
  229. package/dist/components/ai/ApprovalCard/index.d.ts +0 -2
  230. package/dist/components/ai/MessageHistory/MessageHistory.d.ts +0 -18
  231. package/dist/components/ai/MessageHistory/MessageHistory.js +0 -98
  232. package/dist/components/ai/MessageHistory/MessageHistory.theme.d.ts +0 -2
  233. package/dist/components/ai/MessageHistory/MessageHistory.theme.js +0 -8
  234. package/dist/components/ai/MessageHistory/MessageHistory.types.d.ts +0 -94
  235. package/dist/components/ai/MessageHistory/index.d.ts +0 -3
  236. package/dist/icons/Icon.d.ts +0 -24
  237. package/dist/icons/Icon.js +0 -30
  238. package/dist/icons/Index.d.ts +0 -16
  239. package/dist/icons/core/ChevronUpDown.d.ts +0 -1
  240. package/dist/icons/core/ChevronUpDown.js +0 -7
  241. package/dist/icons/core/DollarIcon.d.ts +0 -1
  242. package/dist/icons/core/DollarIcon.js +0 -5
  243. package/dist/icons/core/LockIcon.d.ts +0 -1
  244. package/dist/icons/core/LockIcon.js +0 -5
  245. package/dist/icons/core/MinusIcon.d.ts +0 -1
  246. package/dist/icons/core/MinusIcon.js +0 -7
  247. package/dist/icons/core/PlusIcon.d.ts +0 -1
  248. package/dist/icons/core/PlusIcon.js +0 -7
  249. package/dist/icons/core/SearchIcon.d.ts +0 -1
  250. package/dist/icons/core/SearchIcon.js +0 -7
  251. package/dist/icons/core/TickIcon.d.ts +0 -1
  252. package/dist/icons/core/TickIcon.js +0 -5
  253. package/dist/icons/core/User.d.ts +0 -1
  254. package/dist/utils/useClickOutside.d.ts +0 -1
@@ -0,0 +1,208 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import React__default, { useContext, useState, useEffect, useCallback, useMemo } from 'react';
3
+ import { AnimatePresence, motion } from 'motion/react';
4
+ import { createPortal } from 'react-dom';
5
+ import { Calendar } from '../../core/Calendar/Calendar.js';
6
+ import '../../core/Calendar/CalendarMini/CalendarMini.js';
7
+ import { Button } from '../../core/Button/Button.js';
8
+ import { cn } from '../../../utils/cn.js';
9
+ import { DateRangePickerContext } from './DateRangePicker.js';
10
+ import { DateRangePickerPresets } from './DateRangePickerPresets.js';
11
+ import { useSelectPortal } from '../../../hooks/useSelectPortal.js';
12
+ import { formatDateCustom } from '../../../utils/dateUtils.js';
13
+ import { createDropdownAnimations } from '../DatePicker/DatePicker.animations.js';
14
+ import { useIsClient } from '../../../hooks/useIsClient.js';
15
+ import { useMediaQuery } from '../../../hooks/useMediaQuery.js';
16
+
17
+ /**
18
+ * Hook to detect dark mode state from document
19
+ */
20
+ const useDarkMode = () => {
21
+ const [isDark, setIsDark] = useState(false);
22
+ useEffect(() => {
23
+ if (typeof document === "undefined")
24
+ return;
25
+ const checkDarkMode = () => {
26
+ const hasDarkClass = document.documentElement.classList.contains("dark") ||
27
+ document.body.classList.contains("dark") ||
28
+ document.querySelector(".dark") !== null;
29
+ setIsDark(hasDarkClass);
30
+ };
31
+ checkDarkMode();
32
+ const observer = new MutationObserver(checkDarkMode);
33
+ observer.observe(document.documentElement, {
34
+ attributes: true,
35
+ attributeFilter: ["class"],
36
+ });
37
+ observer.observe(document.body, {
38
+ attributes: true,
39
+ attributeFilter: ["class"],
40
+ });
41
+ return () => observer.disconnect();
42
+ }, []);
43
+ return isDark;
44
+ };
45
+ /**
46
+ * DateRangePicker Body Component — dual calendars + presets sidebar + footer
47
+ */
48
+ const DateRangePickerBody = ({ isOpen, className, onClose, portal = true, placement = "bottom-start", offset = 4, presets, showPresets = true, }) => {
49
+ const context = useContext(DateRangePickerContext);
50
+ if (!context) {
51
+ throw new Error("DateRangePickerBody must be used within a DateRangePicker");
52
+ }
53
+ const { theme, triggerRef, contentRef, selectedRange, minDate, maxDate, isDateDisabled, showToday, weekdays, months, handleRangeSelect, yearRange, } = context;
54
+ const hasPresets = showPresets && presets && presets.length > 0;
55
+ const isDarkMode = useDarkMode();
56
+ const isClient = useIsClient();
57
+ const isMobile = useMediaQuery("(max-width: 639px)");
58
+ // Temp range state — not committed until Apply is clicked
59
+ const [tempRange, setTempRange] = useState(selectedRange);
60
+ // Sync temp range when panel opens
61
+ useEffect(() => {
62
+ if (isOpen) {
63
+ setTempRange(selectedRange);
64
+ }
65
+ }, [isOpen, selectedRange]);
66
+ // Handle preset selection — update calendar view to show the range
67
+ const handlePresetSelect = useCallback((range) => {
68
+ if (range.start) {
69
+ setLeftCalendarDate(new Date(range.start.getFullYear(), range.start.getMonth(), 1));
70
+ }
71
+ }, []);
72
+ // Dual calendar state
73
+ const getInitialLeftDate = () => {
74
+ if (tempRange === null || tempRange === void 0 ? void 0 : tempRange.start) {
75
+ return new Date(tempRange.start.getFullYear(), tempRange.start.getMonth(), 1);
76
+ }
77
+ if (selectedRange === null || selectedRange === void 0 ? void 0 : selectedRange.start) {
78
+ return new Date(selectedRange.start.getFullYear(), selectedRange.start.getMonth(), 1);
79
+ }
80
+ return new Date();
81
+ };
82
+ const [leftCalendarDate, setLeftCalendarDate] = useState(getInitialLeftDate);
83
+ const rightCalendarDate = useMemo(() => {
84
+ const nextMonth = new Date(leftCalendarDate);
85
+ nextMonth.setMonth(nextMonth.getMonth() + 1);
86
+ return nextMonth;
87
+ }, [leftCalendarDate]);
88
+ const handleNavigatePrev = useCallback(() => {
89
+ setLeftCalendarDate((prev) => {
90
+ const newDate = new Date(prev);
91
+ newDate.setMonth(newDate.getMonth() - 1);
92
+ return newDate;
93
+ });
94
+ }, []);
95
+ const handleNavigateNext = useCallback(() => {
96
+ setLeftCalendarDate((prev) => {
97
+ const newDate = new Date(prev);
98
+ newDate.setMonth(newDate.getMonth() + 1);
99
+ return newDate;
100
+ });
101
+ }, []);
102
+ // Footer handlers
103
+ const handleApply = useCallback(() => {
104
+ if (tempRange) {
105
+ handleRangeSelect(tempRange);
106
+ }
107
+ onClose === null || onClose === void 0 ? void 0 : onClose();
108
+ }, [tempRange, handleRangeSelect, onClose]);
109
+ const handleCancel = useCallback(() => {
110
+ setTempRange(selectedRange);
111
+ onClose === null || onClose === void 0 ? void 0 : onClose();
112
+ }, [selectedRange, onClose]);
113
+ // Format range for footer display
114
+ const formatRangeDisplay = (range) => {
115
+ if (!(range === null || range === void 0 ? void 0 : range.start) && !(range === null || range === void 0 ? void 0 : range.end))
116
+ return "Select start and end dates";
117
+ if (!range.end)
118
+ return `${formatDateCustom(range.start, "DD/MM/YYYY")} - ...`;
119
+ return `${formatDateCustom(range.start, "DD/MM/YYYY")} - ${formatDateCustom(range.end, "DD/MM/YYYY")}`;
120
+ };
121
+ // Portal positioning
122
+ const { position, cssVariables, contentRef: portalContentRef, isFlipped, isReady, } = useSelectPortal({
123
+ triggerRef,
124
+ isOpen: isOpen || false,
125
+ placement,
126
+ offset,
127
+ autoWidth: true,
128
+ });
129
+ const animations = createDropdownAnimations(isFlipped);
130
+ // Combine refs
131
+ const combinedRef = React__default.useCallback((el) => {
132
+ if (contentRef &&
133
+ typeof contentRef === "object" &&
134
+ "current" in contentRef) {
135
+ contentRef.current =
136
+ el;
137
+ }
138
+ if (portalContentRef &&
139
+ typeof portalContentRef === "object" &&
140
+ "current" in portalContentRef) {
141
+ portalContentRef.current = el;
142
+ }
143
+ }, [contentRef, portalContentRef]);
144
+ // Click outside to close
145
+ useEffect(() => {
146
+ if (!isOpen)
147
+ return;
148
+ const handleClickOutside = (event) => {
149
+ var _a;
150
+ const target = event.target;
151
+ if ((_a = target.closest) === null || _a === void 0 ? void 0 : _a.call(target, '[role="listbox"]')) {
152
+ return;
153
+ }
154
+ const currentContentRef = portal
155
+ ? portalContentRef.current
156
+ : contentRef.current;
157
+ if (currentContentRef &&
158
+ !currentContentRef.contains(target) &&
159
+ triggerRef.current &&
160
+ !triggerRef.current.contains(target)) {
161
+ onClose === null || onClose === void 0 ? void 0 : onClose();
162
+ }
163
+ };
164
+ document.addEventListener("mousedown", handleClickOutside);
165
+ return () => {
166
+ document.removeEventListener("mousedown", handleClickOutside);
167
+ };
168
+ }, [isOpen, onClose, triggerRef, contentRef, portalContentRef, portal]);
169
+ // Escape key
170
+ useEffect(() => {
171
+ if (!isOpen)
172
+ return;
173
+ const handleKeyDown = (event) => {
174
+ if (event.key === "Escape") {
175
+ onClose === null || onClose === void 0 ? void 0 : onClose();
176
+ }
177
+ };
178
+ document.addEventListener("keydown", handleKeyDown);
179
+ return () => {
180
+ document.removeEventListener("keydown", handleKeyDown);
181
+ };
182
+ }, [isOpen, onClose]);
183
+ const contentElement = (jsx(AnimatePresence, { mode: "wait", children: isOpen && (jsxs(motion.div, { ref: combinedRef, className: cn(theme.bodyStyle, className), style: {
184
+ ...cssVariables,
185
+ ...(portal
186
+ ? {
187
+ top: `${position.top}px`,
188
+ left: `${position.left}px`,
189
+ minWidth: `${position.width}px`,
190
+ }
191
+ : {}),
192
+ }, variants: animations, initial: "initial", animate: isReady ? "visible" : "initial", exit: "exit", children: [hasPresets && presets && (jsx(DateRangePickerPresets, { presets: presets, tempRange: tempRange, setTempRange: setTempRange, onPresetSelect: handlePresetSelect })), jsxs("div", { className: "flex flex-col flex-1", children: [jsxs("div", { className: "flex flex-col sm:flex-row justify-between items-center sm:items-start gap-2 sm:gap-6 p-3 sm:p-4", children: [jsx("div", { className: "flex-1 min-w-fit", children: jsx(Calendar, { mode: "range", value: tempRange, onChange: (value) => {
193
+ setTempRange(value);
194
+ }, viewDate: leftCalendarDate, onViewDateChange: setLeftCalendarDate, onNavigatePrev: handleNavigatePrev, onNavigateNext: isMobile ? handleNavigateNext : null, minDate: minDate, maxDate: maxDate, isDateDisabled: isDateDisabled, showToday: showToday, selectTodayByDefault: false, weekdays: weekdays, months: months, yearRange: yearRange, showOtherMonthDays: false, headerMode: "static", size: "md" }) }), jsx("div", { className: "hidden sm:block flex-1 min-w-fit", children: jsx(Calendar, { mode: "range", value: tempRange, onChange: (value) => {
195
+ setTempRange(value);
196
+ }, viewDate: rightCalendarDate, onViewDateChange: (newDate) => {
197
+ const adjustedLeft = new Date(newDate);
198
+ adjustedLeft.setMonth(adjustedLeft.getMonth() - 1);
199
+ setLeftCalendarDate(adjustedLeft);
200
+ }, onNavigatePrev: null, onNavigateNext: handleNavigateNext, minDate: minDate, maxDate: maxDate, isDateDisabled: isDateDisabled, showToday: showToday, selectTodayByDefault: false, weekdays: weekdays, months: months, yearRange: yearRange, showOtherMonthDays: false, headerMode: "static", size: "md" }) })] }), jsxs("div", { className: "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2 px-3 sm:px-4 py-3 border-t border-[var(--color-border)]", children: [jsx("div", { className: "text-sm text-center sm:text-left text-[var(--color-text-muted)]", children: formatRangeDisplay(tempRange) }), jsxs("div", { className: "flex w-full sm:w-auto items-center gap-2", children: [jsx(Button, { variant: "outline", color: "neutral", size: "sm", className: "flex-1 sm:flex-initial", onClick: handleCancel, children: "Cancel" }), jsx(Button, { variant: "filled", size: "sm", className: "flex-1 sm:flex-initial", onClick: handleApply, disabled: !(tempRange === null || tempRange === void 0 ? void 0 : tempRange.start) || !(tempRange === null || tempRange === void 0 ? void 0 : tempRange.end), children: "Apply" })] })] })] })] })) }));
201
+ if (portal && isClient) {
202
+ return createPortal(jsx("div", { className: isDarkMode ? "dark" : undefined, children: contentElement }), document.body);
203
+ }
204
+ return contentElement;
205
+ };
206
+ DateRangePickerBody.displayName = "DateRangePicker.Body";
207
+
208
+ export { DateRangePickerBody };
@@ -0,0 +1,6 @@
1
+ import React from "react";
2
+ import { DateRangePickerPresetsProps } from "./DateRangePicker.types";
3
+ /**
4
+ * DateRangePicker Presets Component — shows preset buttons with checkmarks
5
+ */
6
+ export declare const DateRangePickerPresets: React.FC<DateRangePickerPresetsProps>;
@@ -0,0 +1,41 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { useContext } from 'react';
3
+ import { CheckIcon } from '@heroicons/react/24/outline';
4
+ import { DateRangePickerContext } from './DateRangePicker.js';
5
+ import { cn } from '../../../utils/cn.js';
6
+
7
+ /**
8
+ * DateRangePicker Presets Component — shows preset buttons with checkmarks
9
+ */
10
+ const DateRangePickerPresets = ({ presets, className, tempRange, setTempRange, onPresetSelect, }) => {
11
+ const context = useContext(DateRangePickerContext);
12
+ if (!context) {
13
+ throw new Error("DateRangePickerPresets must be used within a DateRangePicker");
14
+ }
15
+ const { theme } = context;
16
+ const isSameDate = (d1, d2) => {
17
+ if (!d1 || !d2)
18
+ return d1 === d2;
19
+ return (d1.getFullYear() === d2.getFullYear() &&
20
+ d1.getMonth() === d2.getMonth() &&
21
+ d1.getDate() === d2.getDate());
22
+ };
23
+ const isPresetActive = (preset) => {
24
+ if (!tempRange)
25
+ return false;
26
+ const presetRange = preset.getValue();
27
+ return (isSameDate(tempRange.start, presetRange.start) &&
28
+ isSameDate(tempRange.end, presetRange.end));
29
+ };
30
+ const handlePresetClick = (preset) => {
31
+ const range = preset.getValue();
32
+ setTempRange === null || setTempRange === void 0 ? void 0 : setTempRange(range);
33
+ onPresetSelect === null || onPresetSelect === void 0 ? void 0 : onPresetSelect(range);
34
+ };
35
+ return (jsx("div", { className: cn(theme.presetsContainerStyle, className), children: presets.map((preset, index) => {
36
+ const active = isPresetActive(preset);
37
+ return (jsxs("button", { type: "button", onClick: () => handlePresetClick(preset), className: theme.presetButtonStyle, "data-active": active, children: [jsx("span", { children: preset.label }), active && jsx(CheckIcon, { className: theme.presetCheckmarkStyle })] }, index));
38
+ }) }));
39
+ };
40
+
41
+ export { DateRangePickerPresets };
@@ -0,0 +1,6 @@
1
+ import React from "react";
2
+ import { DateRangePickerTriggerProps } from "./DateRangePicker.types";
3
+ /**
4
+ * DateRangePicker Trigger Component — styled like form input
5
+ */
6
+ export declare const DateRangePickerTrigger: React.FC<DateRangePickerTriggerProps>;
@@ -0,0 +1,32 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { useContext } from 'react';
3
+ import { CalendarIcon } from '@heroicons/react/24/outline';
4
+ import { cn } from '../../../utils/cn.js';
5
+ import { DateRangePickerContext } from './DateRangePicker.js';
6
+
7
+ /**
8
+ * DateRangePicker Trigger Component — styled like form input
9
+ */
10
+ const DateRangePickerTrigger = ({ id, disabled, isOpen, state = "default", size = "md", className, onClick, onFocus, onBlur, children, }) => {
11
+ var _a, _b, _c, _d;
12
+ const context = useContext(DateRangePickerContext);
13
+ if (!context) {
14
+ throw new Error("DateRangePickerTrigger must be used within a DateRangePicker");
15
+ }
16
+ const { theme, triggerRef } = context;
17
+ const baseStyle = theme.baseStyle || "";
18
+ const sizeStyle = ((_a = theme.triggerSizes) === null || _a === void 0 ? void 0 : _a[size]) || "";
19
+ const stateStyle = ((_b = theme.triggerStates) === null || _b === void 0 ? void 0 : _b[state]) || "";
20
+ const hoverStateStyle = ((_c = theme.triggerHoverStates) === null || _c === void 0 ? void 0 : _c[state]) || "";
21
+ const focusStateStyle = ((_d = theme.triggerFocusStates) === null || _d === void 0 ? void 0 : _d[state]) || "";
22
+ const iconEndStyle = theme.iconEndStyle || "";
23
+ const iconEndPadding = theme.iconEndPadding || "";
24
+ const triggerButtonStyle = theme.triggerButtonStyle || "";
25
+ const activeFocusState = isOpen
26
+ ? focusStateStyle ||
27
+ "outline-2 outline-primary-600 -outline-offset-1 ring-4 ring-[var(--color-primary)]/10"
28
+ : "";
29
+ return (jsx("div", { className: "relative w-full", children: jsxs("button", { ref: triggerRef, id: id, type: "button", className: cn(baseStyle, sizeStyle, stateStyle, hoverStateStyle, activeFocusState, iconEndPadding, triggerButtonStyle, "text-left", className), onClick: onClick, onFocus: onFocus, onBlur: onBlur, disabled: disabled, "aria-expanded": isOpen, "aria-haspopup": "dialog", "aria-label": "Open date range picker", children: [children, jsx("span", { className: iconEndStyle, children: jsx(CalendarIcon, { className: "h-4 w-4" }) })] }) }));
30
+ };
31
+
32
+ export { DateRangePickerTrigger };
@@ -0,0 +1,5 @@
1
+ import type { DateRangePreset } from "./DateRangePicker.types";
2
+ /**
3
+ * Default date range presets matching the reference design
4
+ */
5
+ export declare const DEFAULT_DATE_RANGE_PRESETS: DateRangePreset[];
@@ -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';