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

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 (165) hide show
  1. package/dist/components/ai/ApprovalCard/ApprovalCard.js +2 -1
  2. package/dist/components/ai/MessageHistory/MessageHistory.js +1 -0
  3. package/dist/components/ai/StreamingResponse/StreamingResponse.js +1 -0
  4. package/dist/components/ai/index.js +1 -0
  5. package/dist/components/core/Accordion/Accordion.animations.d.ts +6 -1
  6. package/dist/components/core/Accordion/Accordion.animations.js +15 -1
  7. package/dist/components/core/Accordion/Accordion.d.ts +1 -1
  8. package/dist/components/core/Accordion/Accordion.js +2 -2
  9. package/dist/components/core/Accordion/Accordion.theme.d.ts +2 -2
  10. package/dist/components/core/Accordion/Accordion.theme.js +6 -6
  11. package/dist/components/core/Accordion/Accordion.types.d.ts +34 -4
  12. package/dist/components/core/Accordion/AccordionBody.d.ts +3 -0
  13. package/dist/components/core/Accordion/{AccordionContent.js → AccordionBody.js} +4 -4
  14. package/dist/components/core/Accordion/AccordionItem.js +1 -1
  15. package/dist/components/core/Accordion/AccordionTrigger.js +20 -6
  16. package/dist/components/core/Accordion/index.d.ts +2 -2
  17. package/dist/components/core/Alert/Alert.js +5 -1
  18. package/dist/components/core/Alert/Alert.types.d.ts +3 -3
  19. package/dist/components/core/Badge/Badge.theme.js +2 -2
  20. package/dist/components/core/Breadcrumbs/Breadcrumbs.js +7 -3
  21. package/dist/components/core/Breadcrumbs/Breadcrumbs.types.d.ts +1 -1
  22. package/dist/components/core/Button/Button.js +22 -25
  23. package/dist/components/core/Button/Button.ripple.d.ts +5 -1
  24. package/dist/components/core/Button/Button.ripple.js +27 -17
  25. package/dist/components/core/Button/Button.theme.d.ts +1 -2
  26. package/dist/components/core/Button/Button.theme.js +7 -7
  27. package/dist/components/core/Button/index.d.ts +2 -0
  28. package/dist/components/core/Calendar/Calendar.js +3 -3
  29. package/dist/components/core/Card/Card.d.ts +2 -2
  30. package/dist/components/core/Card/Card.js +3 -3
  31. package/dist/components/core/Card/Card.theme.js +6 -6
  32. package/dist/components/core/Card/Card.types.d.ts +8 -13
  33. package/dist/components/core/Card/CardBody.d.ts +3 -0
  34. package/dist/components/core/Card/CardBody.js +11 -0
  35. package/dist/components/core/Card/CardSubtitle.d.ts +1 -1
  36. package/dist/components/core/Card/CardTitle.d.ts +1 -1
  37. package/dist/components/core/Card/index.d.ts +2 -2
  38. package/dist/components/core/Carousel/Carousel.js +4 -4
  39. package/dist/components/core/Carousel/Carousel.types.d.ts +4 -4
  40. package/dist/components/core/Carousel/CarouselBody.d.ts +4 -0
  41. package/dist/components/core/Carousel/{CarouselContent.js → CarouselBody.js} +3 -3
  42. package/dist/components/core/Carousel/index.d.ts +2 -1
  43. package/dist/components/core/ContextMenu/ContextMenu.d.ts +2 -2
  44. package/dist/components/core/ContextMenu/ContextMenu.js +6 -6
  45. package/dist/components/core/ContextMenu/ContextMenu.types.d.ts +2 -2
  46. package/dist/components/core/ContextMenu/ContextMenuBody.d.ts +6 -0
  47. package/dist/components/core/ContextMenu/{ContextMenuContent.js → ContextMenuBody.js} +4 -4
  48. package/dist/components/core/ContextMenu/ContextMenuSubBody.d.ts +6 -0
  49. package/dist/components/core/ContextMenu/{ContextMenuSubContent.js → ContextMenuSubBody.js} +4 -4
  50. package/dist/components/core/ContextMenu/index.d.ts +1 -1
  51. package/dist/components/core/Drawer/Drawer.d.ts +2 -2
  52. package/dist/components/core/Drawer/Drawer.js +28 -9
  53. package/dist/components/core/Drawer/Drawer.theme.d.ts +2 -0
  54. package/dist/components/core/Drawer/Drawer.theme.js +12 -10
  55. package/dist/components/core/Drawer/Drawer.types.d.ts +8 -6
  56. package/dist/components/core/Drawer/DrawerBody.d.ts +5 -0
  57. package/dist/components/core/Drawer/{DrawerContent.js → DrawerBody.js} +3 -3
  58. package/dist/components/core/Drawer/DrawerHeader.js +1 -0
  59. package/dist/components/core/Drawer/DrawerTitle.js +1 -1
  60. package/dist/components/core/Drawer/index.d.ts +2 -1
  61. package/dist/components/core/Dropdown/Dropdown.types.d.ts +3 -3
  62. package/dist/components/core/Dropdown/DropdownSection.js +3 -1
  63. package/dist/components/core/MenuItem/MenuItem.js +3 -1
  64. package/dist/components/core/MenuItem/MenuItem.types.d.ts +1 -1
  65. package/dist/components/core/Message/Message.d.ts +1 -1
  66. package/dist/components/core/Message/Message.js +2 -2
  67. package/dist/components/core/Message/Message.types.d.ts +1 -1
  68. package/dist/components/core/Message/MessageBody.d.ts +8 -0
  69. package/dist/components/core/Message/{MessageContent.js → MessageBody.js} +3 -3
  70. package/dist/components/core/Message/index.d.ts +2 -0
  71. package/dist/components/core/Modal/Modal.js +5 -1
  72. package/dist/components/core/Modal/Modal.theme.js +1 -1
  73. package/dist/components/core/Modal/Modal.types.d.ts +5 -2
  74. package/dist/components/core/Modal/ModalHeader.js +1 -0
  75. package/dist/components/core/ModalStack/ModalStackModal.js +1 -0
  76. package/dist/components/core/PageHeading/PageHeading.types.d.ts +1 -1
  77. package/dist/components/core/PageHeading/PageHeadingBackButton.js +3 -1
  78. package/dist/components/core/Popover/Popover.d.ts +1 -1
  79. package/dist/components/core/Popover/Popover.js +4 -4
  80. package/dist/components/core/Popover/Popover.theme.d.ts +1 -1
  81. package/dist/components/core/Popover/Popover.theme.js +2 -2
  82. package/dist/components/core/Popover/Popover.types.d.ts +3 -3
  83. package/dist/components/core/Popover/PopoverBody.d.ts +7 -0
  84. package/dist/components/core/Popover/{PopoverContent.js → PopoverBody.js} +5 -5
  85. package/dist/components/core/Popover/index.d.ts +4 -3
  86. package/dist/components/core/Tabs/Tabs.animations.d.ts +2 -2
  87. package/dist/components/core/Tabs/Tabs.animations.js +3 -3
  88. package/dist/components/core/Tabs/Tabs.d.ts +1 -1
  89. package/dist/components/core/Tabs/Tabs.js +3 -3
  90. package/dist/components/core/Tabs/Tabs.theme.d.ts +1 -1
  91. package/dist/components/core/Tabs/Tabs.theme.js +2 -2
  92. package/dist/components/core/Tabs/Tabs.types.d.ts +9 -9
  93. package/dist/components/core/Tabs/TabsBody.d.ts +6 -0
  94. package/dist/components/core/Tabs/{TabsContent.js → TabsBody.js} +8 -8
  95. package/dist/components/core/Tabs/index.d.ts +2 -2
  96. package/dist/components/core/Toast/Toast.js +5 -1
  97. package/dist/components/core/Toast/Toast.types.d.ts +9 -9
  98. package/dist/components/core/index.js +7 -2
  99. package/dist/components/data-display/Feed/Feed.js +10 -2
  100. package/dist/components/data-display/Feed/Feed.types.d.ts +4 -4
  101. package/dist/components/data-display/GanttChart/GanttTaskContextMenu.js +1 -1
  102. package/dist/components/data-display/GanttChart/GanttToolbar.js +1 -0
  103. package/dist/components/data-display/KPI/KPI.js +2 -2
  104. package/dist/components/data-display/KPI/KPI.types.d.ts +3 -3
  105. package/dist/components/data-display/Metric/Metric.js +2 -2
  106. package/dist/components/data-display/Metric/Metric.types.d.ts +3 -3
  107. package/dist/components/data-display/Table/TableColumnManager.js +3 -1
  108. package/dist/components/data-display/Table/TableFilter.js +2 -1
  109. package/dist/components/data-display/Table/TableSelectionHeader.js +1 -1
  110. package/dist/components/forms/Checkbox/Checkbox.js +1 -1
  111. package/dist/components/forms/Checkbox/Checkbox.types.d.ts +5 -5
  112. package/dist/components/forms/Checkbox/CheckboxGroup.js +2 -2
  113. package/dist/components/forms/ColorPicker/ColorPicker.d.ts +1 -1
  114. package/dist/components/forms/ColorPicker/ColorPicker.js +2 -2
  115. package/dist/components/forms/ColorPicker/ColorPicker.types.d.ts +2 -2
  116. package/dist/components/forms/ColorPicker/ColorPickerBody.d.ts +7 -0
  117. package/dist/components/forms/ColorPicker/{ColorPickerContent.js → ColorPickerBody.js} +5 -5
  118. package/dist/components/forms/ColorPicker/index.d.ts +2 -2
  119. package/dist/components/forms/DatePicker/DatePicker.d.ts +7 -3
  120. package/dist/components/forms/DatePicker/DatePicker.js +6 -5
  121. package/dist/components/forms/DatePicker/DatePicker.theme.js +3 -3
  122. package/dist/components/forms/DatePicker/DatePicker.types.d.ts +9 -4
  123. package/dist/components/forms/DatePicker/DatePickerBody.d.ts +7 -0
  124. package/dist/components/forms/DatePicker/{DatePickerContent.js → DatePickerBody.js} +10 -9
  125. package/dist/components/forms/DatePicker/index.d.ts +2 -2
  126. package/dist/components/forms/Input/Input.js +2 -2
  127. package/dist/components/forms/Input/Input.types.d.ts +4 -4
  128. package/dist/components/forms/Radio/Radio.js +1 -1
  129. package/dist/components/forms/Radio/Radio.types.d.ts +5 -5
  130. package/dist/components/forms/Radio/RadioGroup.js +1 -1
  131. package/dist/components/forms/Select/Select.js +2 -2
  132. package/dist/components/forms/Select/Select.types.d.ts +4 -4
  133. package/dist/components/forms/Switch/Switch.js +1 -1
  134. package/dist/components/forms/Switch/Switch.types.d.ts +4 -4
  135. package/dist/components/forms/Textarea/Textarea.js +2 -2
  136. package/dist/components/forms/Textarea/Textarea.types.d.ts +4 -4
  137. package/dist/components/forms/index.d.ts +2 -2
  138. package/dist/components/forms/index.js +2 -2
  139. package/dist/components/layout/FormLayout/FormLayout.d.ts +0 -2
  140. package/dist/components/layout/FormLayout/FormLayout.js +12 -6
  141. package/dist/components/layout/FormLayout/FormLayout.theme.js +2 -5
  142. package/dist/components/layout/FormLayout/FormLayout.types.d.ts +8 -26
  143. package/dist/components/layout/FormLayout/FormLayoutSection.js +3 -2
  144. package/dist/components/layout/FormLayout/index.d.ts +1 -1
  145. package/dist/index.js +9 -4
  146. package/dist/styles.css +1 -1
  147. package/package.json +1 -1
  148. package/src/global.scss +1 -1
  149. package/dist/components/core/Accordion/AccordionContent.d.ts +0 -3
  150. package/dist/components/core/Button/Button.animations.d.ts +0 -5
  151. package/dist/components/core/Card/CardContent.d.ts +0 -3
  152. package/dist/components/core/Card/CardContent.js +0 -11
  153. package/dist/components/core/Carousel/CarouselContent.d.ts +0 -4
  154. package/dist/components/core/ContextMenu/ContextMenuContent.d.ts +0 -6
  155. package/dist/components/core/ContextMenu/ContextMenuSubContent.d.ts +0 -6
  156. package/dist/components/core/Drawer/DrawerContent.d.ts +0 -5
  157. package/dist/components/core/Message/MessageContent.d.ts +0 -8
  158. package/dist/components/core/Popover/PopoverContent.d.ts +0 -7
  159. package/dist/components/core/Tabs/TabsContent.d.ts +0 -6
  160. package/dist/components/forms/ColorPicker/ColorPickerContent.d.ts +0 -7
  161. package/dist/components/forms/DatePicker/DatePickerContent.d.ts +0 -7
  162. package/dist/components/layout/FormLayout/FormLayoutBody.d.ts +0 -3
  163. package/dist/components/layout/FormLayout/FormLayoutBody.js +0 -13
  164. package/dist/components/layout/FormLayout/FormLayoutHeader.d.ts +0 -3
  165. package/dist/components/layout/FormLayout/FormLayoutHeader.js +0 -12
@@ -4,12 +4,13 @@ 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, }) => {
10
11
  const riskColor = approvalCardTheme.badgeColors[riskLevel];
11
12
  const riskIcon = riskLevel === "critical" || riskLevel === "high" ? (jsx(ExclamationTriangleIcon, { className: "" })) : (jsx(CheckCircleIcon, { className: "" }));
12
- return (jsxs(Card, { className: cn(approvalCardTheme.baseStyle, approvalCardTheme.variants[variant], className), children: [jsx(Card.Header, { children: jsx("div", { className: "flex flex-col items-start", children: jsxs(Badge, { variant: "outline", color: riskColor, size: "sm", iconStart: riskIcon, className: "font-semibold shadow", children: [riskLevel.toUpperCase(), " RISK"] }) }) }), jsxs(Card.Content, { className: "space-y-3", children: [jsxs("div", { className: "space-y-1", children: [jsx(Card.Title, { className: "", children: title }), subtitle && (jsx("p", { className: "text-sm md:text-base text-[var(--color-text-secondary)]/80", children: subtitle }))] }), children && (jsx("div", { className: "bg-[var(--color-background-secondary)] rounded-md p-3 text-sm font-mono border border-[var(--color-border)] overflow-x-auto", children: children }))] }), jsxs(Card.Footer, { className: "justify-end gap-2 mt-3", children: [jsx(Button, { variant: "outline", color: "neutral", size: "sm", onClick: onDeny, children: "Deny" }), jsx(Button, { color: riskColor, size: "sm", state: isApproving ? "loading" : "default", onClick: onApprove, children: "Approve" })] })] }));
13
+ return (jsxs(Card, { className: cn(approvalCardTheme.baseStyle, approvalCardTheme.variants[variant], className), children: [jsx(Card.Header, { children: jsx("div", { className: "flex flex-col items-start", children: jsxs(Badge, { variant: "outline", color: riskColor, size: "sm", iconStart: riskIcon, className: "font-semibold shadow", children: [riskLevel.toUpperCase(), " RISK"] }) }) }), jsxs(Card.Body, { className: "space-y-3", children: [jsxs("div", { className: "space-y-1", children: [jsx(Card.Title, { className: "", children: title }), subtitle && (jsx("p", { className: "text-sm md:text-base text-[var(--color-text-secondary)]/80", children: subtitle }))] }), children && (jsx("div", { className: "bg-[var(--color-background-secondary)] rounded-md p-3 text-sm font-mono border border-[var(--color-border)] overflow-x-auto", children: children }))] }), jsxs(Card.Footer, { className: "justify-end gap-2 mt-3", children: [jsx(Button, { variant: "outline", color: "neutral", size: "sm", onClick: onDeny, children: "Deny" }), jsx(Button, { color: riskColor, size: "sm", state: isApproving ? "loading" : "default", onClick: onApprove, children: "Approve" })] })] }));
13
14
  };
14
15
 
15
16
  export { ApprovalCard };
@@ -3,6 +3,7 @@ import React__default, { useRef, useCallback, useEffect, useMemo } from 'react';
3
3
  import { messageHistoryTheme } from './MessageHistory.theme.js';
4
4
  import { Message } from '../../core/Message/Message.js';
5
5
  import '../../core/Message/TypeWriter.js';
6
+ import '../../core/Message/MessageBody.js';
6
7
  import { cn } from '../../../utils/cn.js';
7
8
 
8
9
  /**
@@ -3,6 +3,7 @@ import { useRef, useEffect } from 'react';
3
3
  import { useStreamingSSE } from '../../../hooks/useStreamingSSE.js';
4
4
  import { Message } from '../../core/Message/Message.js';
5
5
  import { TypeWriter } from '../../core/Message/TypeWriter.js';
6
+ import '../../core/Message/MessageBody.js';
6
7
  import { ErrorDisplay } from './ErrorDisplay.js';
7
8
  import { MarkdownRenderer } from './MarkdownRenderer.js';
8
9
  import { AnimatedText } from './AnimatedText.js';
@@ -1,6 +1,7 @@
1
1
  export { Message } from '../core/Message/Message.js';
2
2
  export { messageTheme } from '../core/Message/Message.theme.js';
3
3
  import '../core/Message/TypeWriter.js';
4
+ import '../core/Message/MessageBody.js';
4
5
  export { MessageHistory } from './MessageHistory/MessageHistory.js';
5
6
  export { messageHistoryTheme } from './MessageHistory/MessageHistory.theme.js';
6
7
  export { PromptInput } from './PromptInput/PromptInput.js';
@@ -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 };
@@ -7,5 +7,5 @@ export declare const Accordion: {
7
7
  } & {
8
8
  Item: React.ForwardRefExoticComponent<import("./Accordion.types").AccordionItemProps & React.RefAttributes<HTMLDivElement>>;
9
9
  Trigger: React.ForwardRefExoticComponent<import("./Accordion.types").AccordionTriggerProps & React.RefAttributes<HTMLButtonElement>>;
10
- Content: React.ForwardRefExoticComponent<import("./Accordion.types").AccordionContentProps & React.RefAttributes<HTMLDivElement>>;
10
+ Body: React.ForwardRefExoticComponent<import("./Accordion.types").AccordionBodyProps & React.RefAttributes<HTMLDivElement>>;
11
11
  };
@@ -3,7 +3,7 @@ import { useContext, createContext, useState, useCallback } from 'react';
3
3
  import { cn } from '../../../utils/cn.js';
4
4
  import { accordionTheme } from './Accordion.theme.js';
5
5
  import { AccordionTrigger } from './AccordionTrigger.js';
6
- import { AccordionContent } from './AccordionContent.js';
6
+ import { AccordionBody } from './AccordionBody.js';
7
7
  import { AccordionItem } from './AccordionItem.js';
8
8
 
9
9
  // Create context for the main Accordion component
@@ -50,7 +50,7 @@ AccordionRoot.displayName = "Accordion";
50
50
  const Accordion = Object.assign(AccordionRoot, {
51
51
  Item: AccordionItem,
52
52
  Trigger: AccordionTrigger,
53
- Content: AccordionContent,
53
+ Body: AccordionBody,
54
54
  });
55
55
 
56
56
  export { Accordion, useAccordionContext };
@@ -2,8 +2,8 @@ export interface AccordionTheme {
2
2
  baseStyle: string;
3
3
  baseStyleStacked: string;
4
4
  triggerStyle: string;
5
- contentStyle: string;
6
- contentInnerStyle: string;
5
+ bodyStyle: string;
6
+ bodyInnerStyle: string;
7
7
  itemStyle: string;
8
8
  itemStyleStacked: string;
9
9
  }
@@ -4,15 +4,15 @@ 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",
12
- // Content styles (shared across variants)
13
- contentStyle: "data-[state=closed]:max-h-0 data-[state=open]:max-h-[500px] accordion-content overflow-hidden",
14
- // Content inner wrapper styles
15
- contentInnerStyle: "p-4 pb-2.5 pt-0",
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
+ // Body styles (shared across variants)
13
+ bodyStyle: "data-[state=closed]:max-h-0 data-[state=open]:max-h-[320px] accordion-content overflow-hidden",
14
+ // Body inner wrapper styles
15
+ bodyInnerStyle: "p-4 pb-2.5 pt-0",
16
16
  };
17
17
 
18
18
  export { accordionTheme };
@@ -53,7 +53,8 @@ export interface AccordionContextValue {
53
53
  theme: AccordionThemeOverrides & {
54
54
  baseStyle: string;
55
55
  triggerStyle: string;
56
- contentStyle: string;
56
+ bodyStyle: string;
57
+ bodyInnerStyle: string;
57
58
  };
58
59
  }
59
60
  /**
@@ -89,11 +90,39 @@ export interface AccordionItemContextValue {
89
90
  export interface AccordionTriggerProps extends React.HTMLAttributes<HTMLButtonElement> {
90
91
  children: React.ReactNode;
91
92
  className?: string;
93
+ /**
94
+ * Override the default indicator (chevron) icon.
95
+ * Set to `null` to hide it entirely — equivalent to `showChevron={false}`.
96
+ */
97
+ chevron?: React.ReactNode | null;
98
+ /**
99
+ * Rotation degrees applied to the chevron icon when open.
100
+ * Default: 45 (for PlusIcon). Use 180 for a chevron-down, 90 for a right-arrow, 0 for none.
101
+ */
102
+ chevronRotation?: number;
103
+ /**
104
+ * Position of the chevron icon.
105
+ * - `"right"` (default): pushed to the far right after children.
106
+ * - `"left"`: appears before children.
107
+ * No effect when `chevron` is explicitly provided.
108
+ * @default "right"
109
+ */
110
+ chevronPosition?: "left" | "right";
111
+ /**
112
+ * Set to `false` to hide the chevron icon entirely.
113
+ * Equivalent to passing `chevron={null}`.
114
+ * @default true
115
+ */
116
+ showChevron?: boolean;
117
+ /**
118
+ * @deprecated Use `chevronRotation` instead.
119
+ */
120
+ iconRotation?: number;
92
121
  }
93
122
  /**
94
- * Content props
123
+ * Body props
95
124
  */
96
- export interface AccordionContentProps extends React.HTMLAttributes<HTMLDivElement> {
125
+ export interface AccordionBodyProps extends React.HTMLAttributes<HTMLDivElement> {
97
126
  children: React.ReactNode;
98
127
  className?: string;
99
128
  }
@@ -104,7 +133,8 @@ export interface AccordionThemeOverrides {
104
133
  baseStyle?: string;
105
134
  baseStyleStacked?: string;
106
135
  triggerStyle?: string;
107
- contentStyle?: string;
136
+ bodyStyle?: string;
137
+ bodyInnerStyle?: string;
108
138
  itemStyle?: string;
109
139
  itemStyleStacked?: string;
110
140
  }
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ import { AccordionBodyProps } from "./Accordion.types";
3
+ export declare const AccordionBody: React.ForwardRefExoticComponent<AccordionBodyProps & React.RefAttributes<HTMLDivElement>>;
@@ -6,7 +6,7 @@ import { useAccordionItemContext } from './AccordionItem.js';
6
6
  import { useReducedMotion, AnimatePresence, motion } from 'motion/react';
7
7
  import { accordionAnimations, accordionContentAnimations } from './Accordion.animations.js';
8
8
 
9
- const AccordionContent = React__default.forwardRef(({ children, className, ...rest }, ref) => {
9
+ const AccordionBody = React__default.forwardRef(({ children, className, ...rest }, ref) => {
10
10
  const { theme } = useAccordionContext();
11
11
  const { isOpen, contentId, triggerId } = useAccordionItemContext();
12
12
  const shouldReduceMotion = useReducedMotion();
@@ -14,8 +14,8 @@ 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.bodyStyle, "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.bodyInnerStyle, className), variants: accordionContentAnimations, initial: "collapsed", animate: "open", exit: "collapsed", transition: instantTransition, children: children }) })) }));
18
18
  });
19
- AccordionContent.displayName = "AccordionContent";
19
+ AccordionBody.displayName = "Accordion.Body";
20
20
 
21
- export { AccordionContent };
21
+ export { AccordionBody };
@@ -9,7 +9,7 @@ const AccordionItemContext = createContext(undefined);
9
9
  const useAccordionItemContext = () => {
10
10
  const ctx = useContext(AccordionItemContext);
11
11
  if (!ctx)
12
- throw new Error("Accordion.Trigger and Accordion.Content must be used within Accordion.Item");
12
+ throw new Error("Accordion.Trigger and Accordion.Body must be used within Accordion.Item");
13
13
  return ctx;
14
14
  };
15
15
  const AccordionItem = React__default.forwardRef(({ children, className, value, ...props }, ref) => {
@@ -1,18 +1,32 @@
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, chevron, chevronRotation, iconRotation, chevronPosition = "right", showChevron = true, ...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 resolvedChevronRotation = (_a = chevronRotation !== null && chevronRotation !== void 0 ? chevronRotation : iconRotation) !== null && _a !== void 0 ? _a : 45;
15
+ // Resolve the indicator icon, respecting showChevron and chevron overrides
16
+ const defaultChevronIcon = jsx(PlusIcon, { className: "size-4", strokeWidth: 2 });
17
+ const resolvedChevron = !showChevron || chevron === null
18
+ ? null
19
+ : chevron !== undefined
20
+ ? chevron
21
+ : chevronPosition === "left"
22
+ ? null // rendered in the left slot instead
23
+ : defaultChevronIcon;
24
+ // When chevronPosition="left", render the default animated chevron before children
25
+ const useDefaultOnLeft = showChevron && chevron === null
26
+ ? false
27
+ : showChevron && chevronPosition === "left" && chevron === undefined;
28
+ const animatedChevron = (rotation, extraClass) => (jsx(motion.div, { initial: false, animate: isOpen ? "open" : "closed", variants: createTriggerIconVariants(rotation), className: cn("flex items-center justify-center shrink-0", extraClass), children: defaultChevronIcon }));
29
+ 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: [useDefaultOnLeft && animatedChevron(resolvedChevronRotation), children, resolvedChevron && (jsx(motion.div, { initial: false, animate: isOpen ? "open" : "closed", variants: createTriggerIconVariants(resolvedChevronRotation), className: "flex items-center justify-center shrink-0 ml-auto", children: resolvedChevron }))] }));
16
30
  });
17
31
  AccordionTrigger.displayName = "AccordionTrigger";
18
32
 
@@ -1,4 +1,4 @@
1
1
  import { Accordion } from "./Accordion";
2
- import { AccordionProps, AccordionTriggerProps, AccordionContentProps, AccordionItemProps, AccordionContextValue, AccordionItemContextValue, AccordionThemeOverrides } from "./Accordion.types";
2
+ import { AccordionProps, AccordionTriggerProps, AccordionBodyProps, AccordionItemProps, AccordionContextValue, AccordionItemContextValue, AccordionThemeOverrides } from "./Accordion.types";
3
3
  export { Accordion };
4
- export type { AccordionProps, AccordionItemProps, AccordionTriggerProps, AccordionContentProps, AccordionContextValue, AccordionItemContextValue, AccordionThemeOverrides, };
4
+ export type { AccordionProps, AccordionItemProps, AccordionTriggerProps, AccordionBodyProps, AccordionContextValue, AccordionItemContextValue, AccordionThemeOverrides, };
@@ -33,7 +33,11 @@ const Alert = React__default.forwardRef(({ variant = "default", color = "primary
33
33
  const IconComponent = defaultIcons[color];
34
34
  return (jsx("div", { className: "flex-shrink-0 w-6 h-6 mt-1", "aria-hidden": "true", children: jsx(IconComponent, { className: cn("w-6 h-6", iconColor) }) }));
35
35
  };
36
- const alertNode = (jsxs("div", { ref: ref, className: cn(alertTheme.baseStyle, alertTheme.variants[variant], className), role: "alert", "aria-live": "assertive", "aria-atomic": "true", ...props, children: [renderIconOrAvatar(), jsxs("div", { className: `flex-1 min-w-0 ${showDismiss ? "mr-5" : ""}`, children: [title && (jsx("div", { className: cn("font-semibold text-[var(--color-text-primary)]"), children: title })), subtitle && (jsx("div", { className: "text-[var(--color-text-secondary)]/90 mt-1", children: subtitle })), children && jsx("div", { className: "mt-2", children: children }), actions && (jsx("div", { className: "flex items-center gap-2 mt-6", children: actions }))] }), showDismiss && (jsx(Button, { variant: "link", color: "neutral", size: "sm", iconOnly: true, onClick: handleDismiss, "aria-label": "Dismiss alert", className: "rounded-full absolute top-2 right-2 flex-shrink-0", children: jsx(XMarkIcon, { className: "size-4", strokeWidth: 2 }) }))] }));
36
+ const alertNode = (jsxs("div", { ref: ref, className: cn(alertTheme.baseStyle, alertTheme.variants[variant], className), role: "alert", "aria-live": "assertive", "aria-atomic": "true", ...props, children: [renderIconOrAvatar(), jsxs("div", { className: `flex-1 min-w-0 ${showDismiss ? "mr-5" : ""}`, children: [title && (typeof title === 'string'
37
+ ? jsx("div", { className: cn("font-semibold text-[var(--color-text-primary)]"), children: title })
38
+ : title), subtitle && (typeof subtitle === 'string'
39
+ ? jsx("div", { className: "text-[var(--color-text-secondary)]/90 mt-1", children: subtitle })
40
+ : subtitle), children && jsx("div", { className: "mt-2", children: children }), actions && (jsx("div", { className: "flex items-center gap-2 mt-6", children: actions }))] }), showDismiss && (jsx(Button, { variant: "link", color: "neutral", size: "sm", iconOnly: true, onClick: handleDismiss, "aria-label": "Dismiss alert", className: "rounded-full absolute top-2 right-2 flex-shrink-0", children: jsx(XMarkIcon, { className: "size-4", strokeWidth: 2 }) }))] }));
37
41
  if (darkMode) {
38
42
  return jsx("div", { className: "dark", children: alertNode });
39
43
  }
@@ -23,15 +23,15 @@ export interface AlertTheme {
23
23
  dismissible: string;
24
24
  };
25
25
  }
26
- export interface AlertProps extends HTMLAttributes<HTMLDivElement> {
26
+ export interface AlertProps extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
27
27
  /** Visual variant */
28
28
  variant?: AlertVariant;
29
29
  /** Semantic color */
30
30
  color?: AlertColor;
31
31
  /** The main title/message of the alert */
32
- title?: string;
32
+ title?: ReactNode;
33
33
  /** Additional subtitle text */
34
- subtitle?: string;
34
+ subtitle?: ReactNode;
35
35
  /** Whether the alert can be dismissed */
36
36
  dismissible?: boolean;
37
37
  /**
@@ -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: {
@@ -42,8 +42,10 @@ const Breadcrumbs = ({ items, separator, maxItems = 4, variant = "default", clas
42
42
  // Render individual breadcrumb item
43
43
  const renderItem = (item, index, isLast) => {
44
44
  const isCurrentPage = isLast || !item.href;
45
- const itemContent = (jsxs(Fragment, { children: [showIcons && item.iconStart && (jsx("span", { className: "mr-1.5 flex-shrink-0", children: item.iconStart })), item.label] }));
46
- return (jsx("span", { className: "flex items-center text-base", children: isCurrentPage ? (jsx("span", { className: cn("flex items-center", theme.current), "aria-current": "page", children: itemContent })) : (jsx("a", { href: item.href, className: cn("flex items-center", theme.link), "aria-label": `Navigate to ${item.label}`, children: itemContent })) }, `${item.label}-${index}`));
45
+ const itemContent = (jsxs(Fragment, { children: [showIcons && item.iconStart && (jsx("span", { className: "mr-1.5 flex-shrink-0", children: item.iconStart })), typeof item.label === 'string'
46
+ ? jsx("span", { children: item.label })
47
+ : item.label] }));
48
+ return (jsx("span", { className: "flex items-center text-base", children: isCurrentPage ? (jsx("span", { className: cn("flex items-center", theme.current), "aria-current": "page", children: itemContent })) : (jsx("a", { href: item.href, className: cn("flex items-center", theme.link), "aria-label": typeof item.label === 'string' ? `Navigate to ${item.label}` : undefined, children: itemContent })) }, `breadcrumb-${index}`));
47
49
  };
48
50
  // Render separator
49
51
  const renderSeparator = (index) => {
@@ -60,7 +62,9 @@ const Breadcrumbs = ({ items, separator, maxItems = 4, variant = "default", clas
60
62
  window.location.href = selectedItem.href;
61
63
  }
62
64
  };
63
- return (jsxs(Dropdown, { isOpen: isEllipsisOpen, onOpenChange: setIsEllipsisOpen, onAction: handleEllipsisAction, placement: "bottom-start", offset: 8, children: [jsx(Dropdown.Trigger, { children: jsx("button", { type: "button", className: cn(theme.ellipsis), "aria-label": `Navigate to one of ${hiddenItems.length} hidden breadcrumbs`, children: "..." }) }), jsx(Dropdown.Menu, { "aria-label": "Hidden breadcrumb items", children: hiddenItems.map((item, index) => (jsx(Dropdown.Item, { itemKey: `hidden-${index}`, startContent: showIcons && item.iconStart, children: item.label }, `hidden-${index}`))) })] }, "ellipsis"));
65
+ return (jsxs(Dropdown, { isOpen: isEllipsisOpen, onOpenChange: setIsEllipsisOpen, onAction: handleEllipsisAction, placement: "bottom-start", offset: 8, children: [jsx(Dropdown.Trigger, { children: jsx("button", { type: "button", className: cn(theme.ellipsis), "aria-label": `Navigate to one of ${hiddenItems.length} hidden breadcrumbs`, children: "..." }) }), jsx(Dropdown.Menu, { "aria-label": "Hidden breadcrumb items", children: hiddenItems.map((item, index) => (jsx(Dropdown.Item, { itemKey: `hidden-${index}`, startContent: showIcons && item.iconStart, children: typeof item.label === 'string'
66
+ ? jsx("span", { children: item.label })
67
+ : item.label }, `hidden-${index}`))) })] }, "ellipsis"));
64
68
  };
65
69
  // Build the breadcrumb elements
66
70
  const breadcrumbElements = [];
@@ -4,7 +4,7 @@ import React from "react";
4
4
  */
5
5
  export interface BreadcrumbItem {
6
6
  /** The display text for the breadcrumb item */
7
- label: string;
7
+ label: React.ReactNode;
8
8
  /** Optional href for navigation. If not provided, item is treated as current page */
9
9
  href?: string;
10
10
  /** Optional icon to display at the start (before the label) */
@@ -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) {
@@ -59,19 +59,12 @@ const Button = React__default.forwardRef(({ children, className = "", iconOnly =
59
59
  console.error("Error in button click handler:", error);
60
60
  }
61
61
  }
62
- }, [
63
- onClick,
64
- isDisabled,
65
- props.disabled,
66
- enableRipple,
67
- shouldReduceMotion,
68
- createRipple,
69
- ]);
62
+ }, [onClick, isDisabled, enableRipple, shouldReduceMotion, createRipple]);
70
63
  // Compute theme classes (direct computation - faster than useMemo)
71
64
  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
65
  const colorClasses = ((_c = buttonTheme.variantColors[resolvedVariant]) === null || _c === void 0 ? void 0 : _c[resolvedColor]) || "";
73
66
  const variantClasses = ((_d = buttonTheme.variantStyles) === null || _d === void 0 ? void 0 : _d[resolvedVariant]) || "";
74
- const stateClasses = state === "disabled" || props.disabled
67
+ const stateClasses = isDisabled
75
68
  ? ((_e = buttonTheme.states) === null || _e === void 0 ? void 0 : _e.disabled) || ""
76
69
  : isError
77
70
  ? ((_f = buttonTheme.states) === null || _f === void 0 ? void 0 : _f.error) || ""
@@ -80,7 +73,7 @@ const Button = React__default.forwardRef(({ children, className = "", iconOnly =
80
73
  : "";
81
74
  const blockStyle = block ? buttonTheme.blockStyle : "";
82
75
  // Generate default aria-label for icon-only buttons if not provided (fallback only)
83
- const ariaLabel = iconOnly && !props["aria-label"] ? "Button" : props["aria-label"];
76
+ const ariaLabel = iconOnly && !ariaLabelProp ? "Button" : ariaLabelProp;
84
77
  // Determine animation props (user props will override due to spread order)
85
78
  const animationProps = shouldDisableAnimations
86
79
  ? {}
@@ -92,26 +85,30 @@ const Button = React__default.forwardRef(({ children, className = "", iconOnly =
92
85
  const spinnerClassName = resolvedVariant === "filled" && color !== "neutral"
93
86
  ? "border-t-white border-l-white"
94
87
  : "";
95
- // Merge refs - use ripple's buttonRef if ripple is enabled, otherwise use forwarded ref
96
- const mergedRef = React__default.useCallback((node) => {
88
+ // Track the latest forwarded ref to avoid mergedRef recreation on inline callback refs
89
+ const forwardedRef = useRef(ref);
90
+ forwardedRef.current = ref;
91
+ // Merge refs - stable callback that won't cause DOM detach/attach cycles
92
+ const mergedRef = useCallback((node) => {
97
93
  // Set ripple's buttonRef
98
94
  if (buttonRef) {
99
95
  buttonRef.current = node;
100
96
  }
101
97
  // Set forwarded ref
102
- if (typeof ref === "function") {
103
- ref(node);
98
+ const fRef = forwardedRef.current;
99
+ if (typeof fRef === "function") {
100
+ fRef(node);
104
101
  }
105
- else if (ref) {
106
- ref.current =
102
+ else if (fRef) {
103
+ fRef.current =
107
104
  node;
108
105
  }
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 &&
106
+ }, [buttonRef]);
107
+ 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
108
  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 &&
109
+ resolvedVariant !== "outline" && (jsx("div", { className: "absolute top-0.25 right-0.25 left-0.25 h-3 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
110
  ripples.map((ripple) => {
114
- const animation = getRippleAnimation(effect, ripple.layer || 1, rippleScale);
111
+ const animation = getRippleAnimation(effect, ripple, rippleScale);
115
112
  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
113
  getRippleColorClass(resolvedVariant, resolvedColor)), style: {
117
114
  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;