@flikk/ui 1.0.0-beta.10 → 1.0.0-beta.11

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 (42) hide show
  1. package/dist/components/ai/ApprovalCard/ApprovalCard.js +1 -0
  2. package/dist/components/ai/PromptInput/PromptInput.js +125 -7
  3. package/dist/components/ai/PromptInput/VoiceRecorder.js +77 -0
  4. package/dist/components/core/Accordion/Accordion.animations.d.ts +6 -1
  5. package/dist/components/core/Accordion/Accordion.animations.js +15 -1
  6. package/dist/components/core/Accordion/Accordion.theme.js +3 -3
  7. package/dist/components/core/Accordion/Accordion.types.d.ts +25 -0
  8. package/dist/components/core/Accordion/AccordionContent.js +1 -1
  9. package/dist/components/core/Accordion/AccordionTrigger.js +11 -6
  10. package/dist/components/core/Badge/Badge.theme.js +2 -2
  11. package/dist/components/core/Button/Button.js +21 -18
  12. package/dist/components/core/Button/Button.ripple.d.ts +5 -1
  13. package/dist/components/core/Button/Button.ripple.js +27 -17
  14. package/dist/components/core/Button/Button.theme.d.ts +1 -2
  15. package/dist/components/core/Button/Button.theme.js +6 -6
  16. package/dist/components/core/Button/index.d.ts +2 -0
  17. package/dist/components/core/Card/Card.theme.js +6 -6
  18. package/dist/components/core/Card/Card.types.d.ts +4 -9
  19. package/dist/components/core/Card/CardSubtitle.d.ts +1 -1
  20. package/dist/components/core/Card/CardTitle.d.ts +1 -1
  21. package/dist/components/core/Drawer/Drawer.js +1 -1
  22. package/dist/components/core/Drawer/Drawer.theme.d.ts +2 -0
  23. package/dist/components/core/Drawer/Drawer.theme.js +13 -11
  24. package/dist/components/core/Drawer/Drawer.types.d.ts +5 -5
  25. package/dist/components/core/Drawer/DrawerContent.js +1 -1
  26. package/dist/components/core/Drawer/DrawerHeader.js +1 -0
  27. package/dist/components/core/Drawer/DrawerTitle.js +1 -1
  28. package/dist/components/core/Drawer/index.d.ts +1 -1
  29. package/dist/components/core/Modal/ModalHeader.js +1 -0
  30. package/dist/components/core/index.js +1 -0
  31. package/dist/components/data-display/GanttChart/GanttToolbar.js +1 -0
  32. package/dist/components/data-display/Table/TableColumnManager.js +1 -0
  33. package/dist/components/data-display/Table/TableSelectionHeader.js +1 -1
  34. package/dist/components/forms/FileUpload/FileUpload.js +78 -0
  35. package/dist/components/forms/TimePicker/TimePickerContent.js +78 -1
  36. package/dist/components/forms/index.js +78 -0
  37. package/dist/components/layout/FormLayout/FormLayoutBody.js +79 -1
  38. package/dist/index.js +198 -191
  39. package/dist/styles.css +1 -1
  40. package/package.json +1 -1
  41. package/src/global.scss +1 -1
  42. package/dist/components/core/Button/Button.animations.d.ts +0 -5
@@ -4,6 +4,7 @@ import { approvalCardTheme } from './ApprovalCard.theme.js';
4
4
  import { Card } from '../../core/Card/Card.js';
5
5
  import { Badge } from '../../core/Badge/Badge.js';
6
6
  import { Button } from '../../core/Button/Button.js';
7
+ import 'react';
7
8
  import { cn } from '../../../utils/cn.js';
8
9
 
9
10
  const ApprovalCard = ({ title, subtitle, variant = "default", riskLevel = "medium", onApprove, onDeny, children, isApproving = false, className, }) => {
@@ -1,14 +1,43 @@
1
1
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
2
  import React__default, { useState, useRef, useId, useEffect, useCallback } from 'react';
3
3
  import { AnimatePresence, motion } from 'motion/react';
4
- import { cn } from '../../../utils/cn.js';
5
- import { CloudArrowUpIcon, MicrophoneIcon, PaperClipIcon, LinkIcon, DocumentIcon, XMarkIcon, PlusIcon, AdjustmentsHorizontalIcon, ChevronDownIcon, ArrowRightIcon } from '@heroicons/react/24/outline';
6
- import { StopIcon } from '@heroicons/react/24/solid';
7
- import { promptInputTheme } from './PromptInput.theme.js';
8
- import { VoiceRecorder } from './VoiceRecorder.js';
9
- import { dropzoneContainerVariants, dropzoneChildVariants, dropzoneActionIconVariants, textareaSwapVariants, iconSwapVariants } from './PromptInput.animations.js';
4
+ import '../../forms/Input/Input.js';
5
+ import '../../forms/Input/Input.theme.js';
6
+ import '../../forms/Select/Select.js';
7
+ import '../../forms/Select/Select.theme.js';
10
8
  import { Textarea } from '../../forms/Textarea/Textarea.js';
11
9
  import '../../forms/Textarea/Textarea.theme.js';
10
+ import '../../forms/FormLabel/FormLabel.js';
11
+ import '../../forms/Radio/Radio.js';
12
+ import '../../forms/Checkbox/Checkbox.js';
13
+ import '../../forms/Switch/Switch.js';
14
+ import '../../forms/DatePicker/DatePicker.js';
15
+ import '../../forms/DatePicker/DatePicker.theme.js';
16
+ import '../../forms/FileUpload/FileUpload.js';
17
+ import '../../forms/TimePicker/TimePicker.js';
18
+ import { CloudArrowUpIcon, MicrophoneIcon, PaperClipIcon, LinkIcon, DocumentIcon, XMarkIcon, PlusIcon, AdjustmentsHorizontalIcon, ChevronDownIcon, ArrowRightIcon } from '@heroicons/react/24/outline';
19
+ import { cn } from '../../../utils/cn.js';
20
+ import 'react-dom';
21
+ import '../../core/Accordion/Accordion.js';
22
+ import '../../core/AlertDialog/AlertDialog.js';
23
+ import '../../core/AspectRatio/AspectRatio.js';
24
+ import '../../core/Avatar/Avatar.js';
25
+ import '../../core/AvatarGroup/AvatarGroup.js';
26
+ import '../../core/Badge/Badge.js';
27
+ import '../../core/Breadcrumbs/Breadcrumbs.js';
28
+ import '../../core/Breadcrumbs/Breadcrumbs.theme.js';
29
+ import { Button } from '../../core/Button/Button.js';
30
+ import '../../core/ButtonGroup/ButtonGroup.js';
31
+ import '../../core/ButtonGroup/ButtonGroupSeparator.js';
32
+ import '../../core/ButtonGroup/ButtonGroupText.js';
33
+ import '../../core/Calendar/Calendar.js';
34
+ import '../../core/Calendar/CalendarMini/CalendarMini.js';
35
+ import '../../core/Card/Card.js';
36
+ import '../../core/CardStack/CardStack.js';
37
+ import '../../core/Carousel/Carousel.js';
38
+ import '../../core/CommandPalette/CommandPalette.js';
39
+ import '../../core/Separator/Separator.js';
40
+ import '../../core/Drawer/Drawer.js';
12
41
  import { Dropdown } from '../../core/Dropdown/Dropdown.js';
13
42
  import '../../core/Dropdown/DropdownTrigger.js';
14
43
  import '../../core/Dropdown/DropdownMenu.js';
@@ -16,7 +45,96 @@ import '../../core/Dropdown/DropdownItem.js';
16
45
  import '../../core/Dropdown/DropdownSection.js';
17
46
  import '../../core/Dropdown/DropdownSeparator.js';
18
47
  import '../../core/Dropdown/Dropdown.theme.js';
19
- import { Button } from '../../core/Button/Button.js';
48
+ import '../../core/Kbd/Kbd.js';
49
+ import '../../core/MenuItem/MenuItem.js';
50
+ import '../../core/Link/Link.js';
51
+ import '../../core/Loader/Loader.js';
52
+ import '../../core/Modal/Modal.js';
53
+ import '../../core/ModalStack/ModalStack.js';
54
+ import '../../core/PageHeading/PageHeading.js';
55
+ import '../../core/Pagination/Pagination.js';
56
+ import '../../core/Popover/Popover.js';
57
+ import '../../core/Popover/PopoverContext.js';
58
+ import '../../core/Progress/Progress.js';
59
+ import '../../core/Rating/Rating.js';
60
+ import '../../core/ScrollArea/ScrollArea.js';
61
+ import '../../core/ScrollArea/smooth/SmoothScrollEngine.js';
62
+ import '../../core/Segmented/Segmented.js';
63
+ import '../../core/Skeleton/Skeleton.js';
64
+ import '../../core/SlidingNumber/SlidingNumber.js';
65
+ import '../../core/Tabs/Tabs.js';
66
+ import '../../core/Tabs/TabsList.js';
67
+ import '../../core/Tabs/TabsTrigger.js';
68
+ import '../../core/Tabs/TabsContent.js';
69
+ import '../../core/Tabs/TabsContext.js';
70
+ import '../../core/Tooltip/Tooltip.js';
71
+ import '../../core/Tooltip/Tooltip.animations.js';
72
+ import '../../core/Tree/Tree.js';
73
+ import '../../core/Tag/Tag.js';
74
+ import '../../core/Alert/Alert.js';
75
+ import '../../core/Toast/Toast.js';
76
+ import '../../core/Toast/ToastProvider.js';
77
+ import { StopIcon } from '@heroicons/react/24/solid';
78
+ import '../../core/Spinner/Spinner.js';
79
+ import '../../core/Message/Message.js';
80
+ import '../../core/Message/TypeWriter.js';
81
+ import '../../core/Empty/Empty.js';
82
+ import '../../core/Masonry/Masonry.js';
83
+ import '../../core/DragDrop/DragDrop.js';
84
+ import '../../core/Sortable/Sortable.js';
85
+ import '../../core/NavItem/NavItem.js';
86
+ import '../../core/Sidebar/Sidebar.js';
87
+ import '../../core/Sidebar/SidebarHeader.js';
88
+ import '../../core/Sidebar/SidebarContent.js';
89
+ import '../../core/Sidebar/SidebarFooter.js';
90
+ import '../../core/Sidebar/SidebarNav.js';
91
+ import '../../core/Sidebar/SidebarNavGroup.js';
92
+ import '../../core/Sidebar/SidebarToggle.js';
93
+ import '../../core/Sidebar/SidebarContext.js';
94
+ import '../../core/OfflineIndicator/OfflineIndicator.js';
95
+ import '../../core/ContextMenu/ContextMenu.js';
96
+ import '../../core/ContextMenu/ContextMenu.theme.js';
97
+ import '../../core/Pill/Pill.js';
98
+ import '../../core/SocialIcon/SocialIcon.js';
99
+ import '../../forms/TimePicker/WheelColumn.js';
100
+ import '../../forms/TimePicker/TimePicker.theme.js';
101
+ import '../../forms/Slider/Slider.js';
102
+ import '../../forms/Slider/Slider.theme.js';
103
+ import '../../forms/Signature/Signature.js';
104
+ import '../../forms/Signature/Signature.theme.js';
105
+ import '../../forms/RichTextEditor/RichTextEditor.js';
106
+ import '../../forms/RichTextEditor/RichTextEditor.theme.js';
107
+ import '../../forms/InputOTP/InputOTP.js';
108
+ import '../../forms/InputOTP/InputOTP.theme.js';
109
+ import '../../forms/InputCreditCard/InputCreditCard.js';
110
+ import '../../forms/InputCreditCard/InputCreditCard.theme.js';
111
+ import '../../forms/InputAddress/InputAddress.js';
112
+ import '../../forms/InputAddress/InputAddress.theme.js';
113
+ import '../../forms/InputDate/InputDate.js';
114
+ import '../../forms/InputCounter/InputCounter.js';
115
+ import '../../forms/InputTag/InputTag.js';
116
+ import '../../forms/InputTag/InputTag.theme.js';
117
+ import '../../forms/Combobox/Combobox.js';
118
+ import '../../forms/Combobox/Combobox.theme.js';
119
+ import '../../forms/ColorPicker/ColorPicker.js';
120
+ import '../../forms/ColorPicker/ColorPickerTrigger.js';
121
+ import '../../forms/ColorPicker/ColorPickerContent.js';
122
+ import '../../forms/ColorPicker/ColorPicker2DCanvas.js';
123
+ import '../../forms/ColorPicker/ColorPickerSwatch.js';
124
+ import '../../forms/ColorPicker/ColorPickerSliders.js';
125
+ import '../../forms/ColorPicker/ColorPickerInput.js';
126
+ import '../../forms/ColorPicker/ColorPickerFormatSelector.js';
127
+ import '../../forms/ColorPicker/ColorPickerEyeDropper.js';
128
+ import '../../forms/ColorPicker/ColorPickerPresets.js';
129
+ import '../../forms/SelectableCard/SelectableCard.js';
130
+ import '../../forms/TransferList/TransferList.js';
131
+ import '../../forms/Mention/Mention.js';
132
+ import '../../forms/Mention/Mention.theme.js';
133
+ import '../../forms/CronInput/CronInput.js';
134
+ import '../../forms/CronInput/CronInput.theme.js';
135
+ import { promptInputTheme } from './PromptInput.theme.js';
136
+ import { VoiceRecorder } from './VoiceRecorder.js';
137
+ import { dropzoneContainerVariants, dropzoneChildVariants, dropzoneActionIconVariants, textareaSwapVariants, iconSwapVariants } from './PromptInput.animations.js';
20
138
 
21
139
  /**
22
140
  * Default model options for the model selector
@@ -3,7 +3,84 @@ import { useState, useRef, useCallback, useEffect } from 'react';
3
3
  import { motion } from 'motion/react';
4
4
  import { PlayIcon, PauseIcon, CheckIcon } from '@heroicons/react/24/outline';
5
5
  import { cn } from '../../../utils/cn.js';
6
+ import '../../core/Accordion/Accordion.js';
7
+ import '../../core/AlertDialog/AlertDialog.js';
8
+ import '../../core/AspectRatio/AspectRatio.js';
9
+ import '../../core/Avatar/Avatar.js';
10
+ import '../../core/AvatarGroup/AvatarGroup.js';
11
+ import '../../core/Badge/Badge.js';
12
+ import '../../core/Breadcrumbs/Breadcrumbs.js';
13
+ import '../../core/Breadcrumbs/Breadcrumbs.theme.js';
6
14
  import { Button } from '../../core/Button/Button.js';
15
+ import '../../core/ButtonGroup/ButtonGroup.js';
16
+ import '../../core/ButtonGroup/ButtonGroupSeparator.js';
17
+ import '../../core/ButtonGroup/ButtonGroupText.js';
18
+ import '../../core/Calendar/Calendar.js';
19
+ import '../../core/Calendar/CalendarMini/CalendarMini.js';
20
+ import '../../core/Card/Card.js';
21
+ import '../../core/CardStack/CardStack.js';
22
+ import '../../core/Carousel/Carousel.js';
23
+ import '../../core/CommandPalette/CommandPalette.js';
24
+ import '../../core/Separator/Separator.js';
25
+ import '../../core/Drawer/Drawer.js';
26
+ import '../../core/Dropdown/Dropdown.js';
27
+ import '../../core/Dropdown/DropdownTrigger.js';
28
+ import '../../core/Dropdown/DropdownMenu.js';
29
+ import '../../core/Dropdown/DropdownItem.js';
30
+ import '../../core/Dropdown/DropdownSection.js';
31
+ import '../../core/Dropdown/DropdownSeparator.js';
32
+ import '../../core/Dropdown/Dropdown.theme.js';
33
+ import '../../core/Kbd/Kbd.js';
34
+ import '../../core/MenuItem/MenuItem.js';
35
+ import '../../core/Link/Link.js';
36
+ import '../../core/Loader/Loader.js';
37
+ import '../../core/Modal/Modal.js';
38
+ import '../../core/ModalStack/ModalStack.js';
39
+ import '../../core/PageHeading/PageHeading.js';
40
+ import '../../core/Pagination/Pagination.js';
41
+ import '../../core/Popover/Popover.js';
42
+ import '../../core/Popover/PopoverContext.js';
43
+ import '../../core/Progress/Progress.js';
44
+ import '../../core/Rating/Rating.js';
45
+ import '../../core/ScrollArea/ScrollArea.js';
46
+ import '../../core/ScrollArea/smooth/SmoothScrollEngine.js';
47
+ import '../../core/Segmented/Segmented.js';
48
+ import '../../core/Skeleton/Skeleton.js';
49
+ import '../../core/SlidingNumber/SlidingNumber.js';
50
+ import '../../core/Tabs/Tabs.js';
51
+ import '../../core/Tabs/TabsList.js';
52
+ import '../../core/Tabs/TabsTrigger.js';
53
+ import '../../core/Tabs/TabsContent.js';
54
+ import '../../core/Tabs/TabsContext.js';
55
+ import '../../core/Tooltip/Tooltip.js';
56
+ import '../../core/Tooltip/Tooltip.animations.js';
57
+ import '../../core/Tree/Tree.js';
58
+ import '../../core/Tag/Tag.js';
59
+ import '../../core/Alert/Alert.js';
60
+ import '../../core/Toast/Toast.js';
61
+ import '../../core/Toast/ToastProvider.js';
62
+ import '@heroicons/react/24/solid';
63
+ import '../../core/Spinner/Spinner.js';
64
+ import '../../core/Message/Message.js';
65
+ import '../../core/Message/TypeWriter.js';
66
+ import '../../core/Empty/Empty.js';
67
+ import '../../core/Masonry/Masonry.js';
68
+ import '../../core/DragDrop/DragDrop.js';
69
+ import '../../core/Sortable/Sortable.js';
70
+ import '../../core/NavItem/NavItem.js';
71
+ import '../../core/Sidebar/Sidebar.js';
72
+ import '../../core/Sidebar/SidebarHeader.js';
73
+ import '../../core/Sidebar/SidebarContent.js';
74
+ import '../../core/Sidebar/SidebarFooter.js';
75
+ import '../../core/Sidebar/SidebarNav.js';
76
+ import '../../core/Sidebar/SidebarNavGroup.js';
77
+ import '../../core/Sidebar/SidebarToggle.js';
78
+ import '../../core/Sidebar/SidebarContext.js';
79
+ import '../../core/OfflineIndicator/OfflineIndicator.js';
80
+ import '../../core/ContextMenu/ContextMenu.js';
81
+ import '../../core/ContextMenu/ContextMenu.theme.js';
82
+ import '../../core/Pill/Pill.js';
83
+ import '../../core/SocialIcon/SocialIcon.js';
7
84
 
8
85
  /**
9
86
  * Format seconds into MM:SS display
@@ -1,8 +1,13 @@
1
- import { Variants } from 'motion/react';
1
+ import type { Variants } from 'motion/react';
2
2
  /**
3
3
  * Accordion animation variants for smooth, staggered open/close transitions
4
4
  */
5
5
  export declare const accordionAnimations: Variants;
6
+ /**
7
+ * Factory for trigger icon rotation variants.
8
+ * @param rotation - Degrees to rotate when open (e.g. 45 for PlusIcon, 180 for chevron)
9
+ */
10
+ export declare const createTriggerIconVariants: (rotation: number) => Variants;
6
11
  /**
7
12
  * Content animation variants for subtle slide-in effect after container expands
8
13
  */
@@ -19,6 +19,20 @@ const accordionAnimations = {
19
19
  }
20
20
  }
21
21
  };
22
+ /**
23
+ * Factory for trigger icon rotation variants.
24
+ * @param rotation - Degrees to rotate when open (e.g. 45 for PlusIcon, 180 for chevron)
25
+ */
26
+ const createTriggerIconVariants = (rotation) => ({
27
+ closed: {
28
+ rotate: 0,
29
+ transition: { duration: 0.2, ease: [0.4, 0.0, 0.2, 1] },
30
+ },
31
+ open: {
32
+ rotate: rotation,
33
+ transition: { duration: 0.2, ease: [0.4, 0.0, 0.2, 1] },
34
+ },
35
+ });
22
36
  /**
23
37
  * Content animation variants for subtle slide-in effect after container expands
24
38
  */
@@ -42,4 +56,4 @@ const accordionContentAnimations = {
42
56
  }
43
57
  };
44
58
 
45
- export { accordionAnimations, accordionContentAnimations };
59
+ export { accordionAnimations, accordionContentAnimations, createTriggerIconVariants };
@@ -4,13 +4,13 @@ const accordionTheme = {
4
4
  // Base container styles for stacked variant (unified card)
5
5
  baseStyleStacked: "w-full border border-[var(--color-border)] rounded-[var(--form-radius)] overflow-hidden",
6
6
  // Item styles for separated variant (individual cards with spacing)
7
- itemStyle: "border border-[var(--color-border)] rounded-[var(--form-radius)] bg-white dark:bg-[var(--color-background-secondary)] overflow-hidden mb-2 last-of-type:mb-0 data-[state=open]:shadow-xs",
7
+ itemStyle: "border border-[var(--color-border)] rounded-[var(--form-radius)] bg-white dark:bg-[var(--color-background-secondary)] overflow-hidden mb-2 last-of-type:mb-0",
8
8
  // Item styles for stacked variant (shared borders, no spacing)
9
9
  itemStyleStacked: "bg-white border-t border-[var(--color-border)] first-of-type:border-t-0",
10
10
  // Trigger styles (shared across variants)
11
- triggerStyle: "flex w-full gap-3 items-center justify-between px-4 py-2.5 text-left font-medium transition-all duration-200 cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary)] focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 text-[var(--color-text-primary)] [&[data-state=open]>svg]:rotate-180 cursor-pointer focus:outline-none transition-all flex justify-between",
11
+ triggerStyle: "flex w-full gap-3 items-center px-4 py-2.5 text-left font-medium transition-all duration-200 cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary)] focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 text-[var(--color-text-primary)]",
12
12
  // Content styles (shared across variants)
13
- contentStyle: "data-[state=closed]:max-h-0 data-[state=open]:max-h-[500px] accordion-content overflow-hidden",
13
+ contentStyle: "data-[state=closed]:max-h-0 data-[state=open]:max-h-[320px] accordion-content overflow-hidden",
14
14
  // Content inner wrapper styles
15
15
  contentInnerStyle: "p-4 pb-2.5 pt-0",
16
16
  };
@@ -54,6 +54,7 @@ export interface AccordionContextValue {
54
54
  baseStyle: string;
55
55
  triggerStyle: string;
56
56
  contentStyle: string;
57
+ contentInnerStyle: string;
57
58
  };
58
59
  }
59
60
  /**
@@ -89,6 +90,29 @@ export interface AccordionItemContextValue {
89
90
  export interface AccordionTriggerProps extends React.HTMLAttributes<HTMLButtonElement> {
90
91
  children: React.ReactNode;
91
92
  className?: string;
93
+ /**
94
+ * Optional leading icon rendered before children
95
+ */
96
+ iconStart?: React.ReactNode;
97
+ /**
98
+ * Indicator icon rendered after children. Defaults to PlusIcon.
99
+ * Set to `null` to hide the indicator entirely.
100
+ */
101
+ iconEnd?: React.ReactNode | null;
102
+ /**
103
+ * Rotation degrees applied to iconStart when open.
104
+ * Default: 0 (static, no rotation). Use 45 for a plus-to-X effect.
105
+ */
106
+ iconStartRotation?: number;
107
+ /**
108
+ * Rotation degrees applied to iconEnd when open.
109
+ * Default: 45 (for PlusIcon). Use 180 for chevrons, 90 for right-arrows, 0 for none.
110
+ */
111
+ iconEndRotation?: number;
112
+ /**
113
+ * @deprecated Use `iconEndRotation` instead. Alias for `iconEndRotation`.
114
+ */
115
+ iconRotation?: number;
92
116
  }
93
117
  /**
94
118
  * Content props
@@ -105,6 +129,7 @@ export interface AccordionThemeOverrides {
105
129
  baseStyleStacked?: string;
106
130
  triggerStyle?: string;
107
131
  contentStyle?: string;
132
+ contentInnerStyle?: string;
108
133
  itemStyle?: string;
109
134
  itemStyleStacked?: string;
110
135
  }
@@ -14,7 +14,7 @@ const AccordionContent = React__default.forwardRef(({ children, className, ...re
14
14
  const instantTransition = shouldReduceMotion ? { duration: 0 } : undefined;
15
15
  // Filter out conflicting props to avoid type issues
16
16
  const { onDrag, onDragEnd, onDragStart, onAnimationStart, onAnimationEnd, onTransitionEnd, onTransitionStart, ...safeProps } = rest;
17
- return (jsx(AnimatePresence, { initial: false, children: isOpen && (jsx(motion.div, { ref: ref, id: contentId, role: "region", "aria-labelledby": triggerId, className: cn(theme === null || theme === void 0 ? void 0 : theme.contentStyle, className), "data-state": isOpen ? "open" : "closed", "aria-hidden": !isOpen, initial: "collapsed", animate: "open", exit: "collapsed", variants: accordionAnimations, transition: instantTransition, ...safeProps, children: jsx(motion.div, { className: "p-4 pt-0", variants: accordionContentAnimations, initial: "collapsed", animate: "open", exit: "collapsed", transition: instantTransition, children: children }) })) }));
17
+ return (jsx(AnimatePresence, { initial: false, children: isOpen && (jsx(motion.div, { ref: ref, id: contentId, role: "region", "aria-labelledby": triggerId, className: theme === null || theme === void 0 ? void 0 : theme.contentStyle, "data-state": isOpen ? "open" : "closed", "aria-hidden": !isOpen, initial: "collapsed", animate: "open", exit: "collapsed", variants: accordionAnimations, transition: instantTransition, ...safeProps, children: jsx(motion.div, { className: cn(theme === null || theme === void 0 ? void 0 : theme.contentInnerStyle, className), variants: accordionContentAnimations, initial: "collapsed", animate: "open", exit: "collapsed", transition: instantTransition, children: children }) })) }));
18
18
  });
19
19
  AccordionContent.displayName = "AccordionContent";
20
20
 
@@ -1,18 +1,23 @@
1
- import { jsxs, jsx } from 'react/jsx-runtime';
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import React__default from 'react';
3
3
  import { cn } from '../../../utils/cn.js';
4
4
  import { useAccordionContext } from './Accordion.js';
5
5
  import { useAccordionItemContext } from './AccordionItem.js';
6
6
  import { motion } from 'motion/react';
7
7
  import { PlusIcon } from '@heroicons/react/24/outline';
8
+ import { createTriggerIconVariants } from './Accordion.animations.js';
8
9
 
9
- const AccordionTrigger = React__default.forwardRef(({ children, className, ...props }, ref) => {
10
+ const AccordionTrigger = React__default.forwardRef(({ children, className, iconStart, iconEnd, iconStartRotation = 0, iconEndRotation, iconRotation, ...props }, ref) => {
11
+ var _a;
10
12
  const { theme } = useAccordionContext();
11
13
  const { isOpen, toggle, triggerId, contentId } = useAccordionItemContext();
12
- return (jsxs("button", { ref: ref, type: "button", id: triggerId, className: cn(theme === null || theme === void 0 ? void 0 : theme.triggerStyle, className), "aria-expanded": isOpen, "aria-controls": contentId, "data-state": isOpen ? "open" : "closed", onClick: toggle, ...props, children: [children, jsx(motion.div, { animate: { rotate: isOpen ? 45 : 0 }, transition: {
13
- duration: 0.2,
14
- ease: [0.4, 0.0, 0.2, 1]
15
- }, className: "flex items-center justify-center", children: jsx(PlusIcon, { className: "size-4", strokeWidth: 2 }) })] }));
14
+ const resolvedEndRotation = (_a = iconEndRotation !== null && iconEndRotation !== void 0 ? iconEndRotation : iconRotation) !== null && _a !== void 0 ? _a : 45;
15
+ const renderIcon = iconEnd === null
16
+ ? null
17
+ : iconEnd !== undefined
18
+ ? iconEnd
19
+ : jsx(PlusIcon, { className: "size-4", strokeWidth: 2 });
20
+ return (jsxs("button", { ref: ref, type: "button", id: triggerId, className: cn(theme === null || theme === void 0 ? void 0 : theme.triggerStyle, className), "aria-expanded": isOpen, "aria-controls": contentId, "data-state": isOpen ? "open" : "closed", onClick: toggle, ...props, children: [iconStart && (iconStartRotation !== 0 ? (jsx(motion.div, { initial: false, animate: isOpen ? "open" : "closed", variants: createTriggerIconVariants(iconStartRotation), className: "flex items-center justify-center shrink-0", children: iconStart })) : (jsx("span", { className: "flex items-center justify-center shrink-0", children: iconStart }))), children, renderIcon && (jsx(motion.div, { initial: false, animate: isOpen ? "open" : "closed", variants: createTriggerIconVariants(resolvedEndRotation), className: "flex items-center justify-center shrink-0 ml-auto", children: renderIcon }))] }));
16
21
  });
17
22
  AccordionTrigger.displayName = "AccordionTrigger";
18
23
 
@@ -63,8 +63,8 @@ const badgeTheme = {
63
63
  },
64
64
  // Flat size structure (no nested objects)
65
65
  sizes: {
66
- sm: "text-xs md:text-sm px-1.5 py-0.5 gap-1",
67
- md: "text-sm md:text-base px-2 py-0.5 gap-1",
66
+ sm: "text-sm px-1.5 py-0.5 gap-1",
67
+ md: "text-base px-2 py-0.5 gap-1",
68
68
  },
69
69
  // Border radius per size (using CSS variable)
70
70
  radiusSizes: {
@@ -1,5 +1,5 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
- import React__default, { useCallback } from 'react';
2
+ import React__default, { useCallback, useRef } from 'react';
3
3
  import { useReducedMotion, motion } from 'motion/react';
4
4
  import { buttonTheme } from './Button.theme.js';
5
5
  import { cn } from '../../../utils/cn.js';
@@ -18,7 +18,7 @@ const BUTTON_TAP_ANIMATION = {
18
18
  },
19
19
  },
20
20
  };
21
- const Button = React__default.forwardRef(({ children, className = "", iconOnly = false, state = "default", size = "md", color, variant, block = false, onClick, enableRipple = true, rippleEffect = "default", rippleClassName, rippleScale = 10, showReflection = true, darkMode = false, ...props }, ref) => {
21
+ const Button = React__default.forwardRef(({ children, className = "", iconOnly = false, state = "default", size = "md", color, variant, block = false, onClick, enableRipple = true, rippleEffect = "default", rippleClassName, rippleScale = 10, showReflection = true, darkMode = false, disabled: disabledProp, "aria-label": ariaLabelProp, ...restProps }, ref) => {
22
22
  var _a, _b, _c, _d, _e, _f, _g;
23
23
  const shouldReduceMotion = useReducedMotion();
24
24
  const shouldDisableAnimations = !!shouldReduceMotion;
@@ -33,18 +33,18 @@ const Button = React__default.forwardRef(({ children, className = "", iconOnly =
33
33
  const resolvedVariant = variant || "filled";
34
34
  // Derived state flags (direct computation - faster than useMemo)
35
35
  const isLoading = state === "loading";
36
- const isDisabled = state === "disabled" || state === "loading";
36
+ const isDisabled = state === "disabled" || state === "loading" || !!disabledProp;
37
37
  const isError = state === "error";
38
38
  // Dev-time a11y warning for iconOnly buttons without aria-label
39
39
  if (process.env.NODE_ENV !== "production") {
40
- if (iconOnly && !props["aria-label"]) {
40
+ if (iconOnly && !ariaLabelProp) {
41
41
  // eslint-disable-next-line no-console
42
42
  console.warn("Button(iconOnly) requires 'aria-label' for accessibility.");
43
43
  }
44
44
  }
45
45
  // Safe onClick handler - respect both state="disabled" and disabled={true}
46
46
  const handleClick = useCallback((event) => {
47
- if (isDisabled || props.disabled)
47
+ if (isDisabled)
48
48
  return;
49
49
  // Create ripple effect if enabled
50
50
  if (enableRipple && !shouldReduceMotion) {
@@ -62,7 +62,6 @@ const Button = React__default.forwardRef(({ children, className = "", iconOnly =
62
62
  }, [
63
63
  onClick,
64
64
  isDisabled,
65
- props.disabled,
66
65
  enableRipple,
67
66
  shouldReduceMotion,
68
67
  createRipple,
@@ -71,7 +70,7 @@ const Button = React__default.forwardRef(({ children, className = "", iconOnly =
71
70
  const sizeClasses = ((_b = (_a = buttonTheme.sizes) === null || _a === void 0 ? void 0 : _a[size]) === null || _b === void 0 ? void 0 : _b[iconOnly ? "iconOnly" : resolvedVariant === "link" ? "link" : "default"]) || "";
72
71
  const colorClasses = ((_c = buttonTheme.variantColors[resolvedVariant]) === null || _c === void 0 ? void 0 : _c[resolvedColor]) || "";
73
72
  const variantClasses = ((_d = buttonTheme.variantStyles) === null || _d === void 0 ? void 0 : _d[resolvedVariant]) || "";
74
- const stateClasses = state === "disabled" || props.disabled
73
+ const stateClasses = isDisabled
75
74
  ? ((_e = buttonTheme.states) === null || _e === void 0 ? void 0 : _e.disabled) || ""
76
75
  : isError
77
76
  ? ((_f = buttonTheme.states) === null || _f === void 0 ? void 0 : _f.error) || ""
@@ -80,7 +79,7 @@ const Button = React__default.forwardRef(({ children, className = "", iconOnly =
80
79
  : "";
81
80
  const blockStyle = block ? buttonTheme.blockStyle : "";
82
81
  // Generate default aria-label for icon-only buttons if not provided (fallback only)
83
- const ariaLabel = iconOnly && !props["aria-label"] ? "Button" : props["aria-label"];
82
+ const ariaLabel = iconOnly && !ariaLabelProp ? "Button" : ariaLabelProp;
84
83
  // Determine animation props (user props will override due to spread order)
85
84
  const animationProps = shouldDisableAnimations
86
85
  ? {}
@@ -92,26 +91,30 @@ const Button = React__default.forwardRef(({ children, className = "", iconOnly =
92
91
  const spinnerClassName = resolvedVariant === "filled" && color !== "neutral"
93
92
  ? "border-t-white border-l-white"
94
93
  : "";
95
- // Merge refs - use ripple's buttonRef if ripple is enabled, otherwise use forwarded ref
96
- const mergedRef = React__default.useCallback((node) => {
94
+ // Track the latest forwarded ref to avoid mergedRef recreation on inline callback refs
95
+ const forwardedRef = useRef(ref);
96
+ forwardedRef.current = ref;
97
+ // Merge refs - stable callback that won't cause DOM detach/attach cycles
98
+ const mergedRef = useCallback((node) => {
97
99
  // Set ripple's buttonRef
98
100
  if (buttonRef) {
99
101
  buttonRef.current = node;
100
102
  }
101
103
  // Set forwarded ref
102
- if (typeof ref === "function") {
103
- ref(node);
104
+ const fRef = forwardedRef.current;
105
+ if (typeof fRef === "function") {
106
+ fRef(node);
104
107
  }
105
- else if (ref) {
106
- ref.current =
108
+ else if (fRef) {
109
+ fRef.current =
107
110
  node;
108
111
  }
109
- }, [ref, buttonRef]);
110
- return (jsxs(motion.button, { ref: mergedRef, type: "button", className: cn(buttonTheme.baseStyle, colorClasses, variantClasses, sizeClasses, blockStyle, stateClasses, darkMode && "dark", className), disabled: isDisabled, "data-state": state, "data-color": resolvedColor, "data-variant": resolvedVariant, "data-size": size, "data-icon-only": iconOnly ? "true" : "false", "data-block": block ? "true" : "false", "aria-disabled": isDisabled || undefined, "aria-invalid": isError || undefined, "aria-label": ariaLabel, "aria-describedby": undefined, onClick: handleClick, ...animationProps, ...props, children: [showReflection &&
112
+ }, [buttonRef]);
113
+ return (jsxs(motion.button, { ...restProps /* React drag events conflict with motion drag events */, ...animationProps, ref: mergedRef, type: "button", className: cn(buttonTheme.baseStyle, colorClasses, variantClasses, sizeClasses, blockStyle, stateClasses, darkMode && "dark", className), disabled: isDisabled, "data-state": state, "data-color": resolvedColor, "data-variant": resolvedVariant, "data-size": size, "data-icon-only": iconOnly ? "true" : "false", "data-block": block ? "true" : "false", "aria-disabled": isDisabled || undefined, "aria-invalid": isError || undefined, "aria-label": ariaLabel, onClick: handleClick, children: [showReflection &&
111
114
  resolvedVariant !== "link" &&
112
- resolvedVariant !== "outline" && (jsx("div", { className: "absolute top-0.25 right-0.25 left-0.25 h-3 bg-gradient-to-b border-t-[0.5px] border-white/40 rounded-t-[calc(var(--button-radius)-1.25px)] opacity-60" })), isLoading && (jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: jsx(Spinner, { size: "sm", color: color, className: spinnerClassName }) })), jsx("span", { className: cn("inline-flex items-center gap-2 whitespace-nowrap", isLoading && "opacity-0"), children: children }), enableRipple &&
115
+ resolvedVariant !== "outline" && (jsx("div", { className: "absolute top-0.25 right-0.25 left-0.25 h-3 bg-gradient-to-b from-white/25 to-transparent border-t-[0.5px] border-white/40 rounded-t-[calc(var(--button-radius)-1.25px)] opacity-60" })), isLoading && (jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: jsx(Spinner, { size: "sm", color: color, className: spinnerClassName }) })), jsx("span", { className: cn("inline-flex items-center gap-2 whitespace-nowrap", isLoading && "opacity-0"), children: children }), enableRipple &&
113
116
  ripples.map((ripple) => {
114
- const animation = getRippleAnimation(effect, ripple.layer || 1, rippleScale);
117
+ const animation = getRippleAnimation(effect, ripple, rippleScale);
115
118
  return (jsx(motion.span, { initial: animation.initial, animate: animation.animate, transition: animation.transition, className: cn("absolute rounded-full size-5 pointer-events-none ", animation.className, rippleClassName ||
116
119
  getRippleColorClass(resolvedVariant, resolvedColor)), style: {
117
120
  top: ripple.y - 10,
@@ -12,6 +12,10 @@ export interface Ripple {
12
12
  x: number;
13
13
  y: number;
14
14
  layer?: number;
15
+ /** Pre-computed random scale factor for particle effect (0-1 range) */
16
+ randomScale?: number;
17
+ /** Pre-computed random duration offset for particle effect (0-1 range) */
18
+ randomDuration?: number;
15
19
  }
16
20
  export interface RippleConfig {
17
21
  /** Scale multiplier for ripple expansion (default: 10) */
@@ -53,7 +57,7 @@ export declare function getRippleColorClass(variant?: string, color?: string): s
53
57
  /**
54
58
  * Get animation properties for specific ripple effect and layer
55
59
  */
56
- export declare function getRippleAnimation(effect: RippleEffectType, layer: number, baseScale: number): {
60
+ export declare function getRippleAnimation(effect: RippleEffectType, ripple: Ripple, baseScale: number): {
57
61
  initial: {
58
62
  scale: number;
59
63
  opacity: number;