@flikk/ui 1.0.0-beta.24 → 1.0.0-beta.26

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 (135) hide show
  1. package/dist/components/ai/CodeBlock/CodeBlock.theme.js +2 -2
  2. package/dist/components/ai/PromptInput/PromptInput.js +1 -0
  3. package/dist/components/ai/PromptInput/VoiceRecorder.js +1 -0
  4. package/dist/components/ai/StreamingResponse/MarkdownRenderer.js +1 -1
  5. package/dist/components/ai/TokenCounter/TokenCounter.theme.js +1 -1
  6. package/dist/components/charts/BarChart/BarChart.js +2 -2
  7. package/dist/components/charts/StackedBarChart/StackedBarChart.js +1 -1
  8. package/dist/components/charts/shared/BarRenderer/BarRenderer.js +2 -2
  9. package/dist/components/core/Accordion/Accordion.theme.js +2 -2
  10. package/dist/components/core/Breadcrumbs/Breadcrumbs.js +1 -1
  11. package/dist/components/core/Breadcrumbs/Breadcrumbs.theme.js +2 -2
  12. package/dist/components/core/Button/Button.js +1 -1
  13. package/dist/components/core/Button/Button.theme.js +4 -4
  14. package/dist/components/core/Calendar/Calendar.js +1 -1
  15. package/dist/components/core/Calendar/CalendarMini/CalendarMini.js +4 -2
  16. package/dist/components/core/Calendar/CalendarMini/CalendarMini.theme.js +2 -2
  17. package/dist/components/core/ContextMenu/ContextMenu.theme.js +1 -1
  18. package/dist/components/core/Drawer/Drawer.theme.js +2 -2
  19. package/dist/components/core/Dropdown/Dropdown.theme.js +2 -2
  20. package/dist/components/core/Empty/Empty.js +1 -1
  21. package/dist/components/core/Empty/Empty.theme.js +1 -1
  22. package/dist/components/core/ImagePlaceholder/ImagePlaceholder.d.ts +14 -0
  23. package/dist/components/core/ImagePlaceholder/ImagePlaceholder.js +28 -0
  24. package/dist/components/core/ImagePlaceholder/ImagePlaceholder.theme.d.ts +6 -0
  25. package/dist/components/core/ImagePlaceholder/ImagePlaceholder.theme.js +8 -0
  26. package/dist/components/core/ImagePlaceholder/ImagePlaceholder.types.d.ts +32 -0
  27. package/dist/components/core/ImagePlaceholder/index.d.ts +2 -0
  28. package/dist/components/core/Link/Link.js +1 -1
  29. package/dist/components/core/Message/Message.theme.js +1 -1
  30. package/dist/components/core/Modal/Modal.theme.js +1 -1
  31. package/dist/components/core/NavItem/NavItem.d.ts +1 -1
  32. package/dist/components/core/NavItem/NavItem.js +171 -68
  33. package/dist/components/core/NavItem/NavItem.theme.js +20 -12
  34. package/dist/components/core/NavItem/NavItem.types.d.ts +17 -39
  35. package/dist/components/core/Pagination/Pagination.theme.js +3 -3
  36. package/dist/components/core/Popover/Popover.theme.js +1 -1
  37. package/dist/components/core/Progress/Progress.theme.js +1 -1
  38. package/dist/components/core/ScrollArea/ScrollArea.js +2 -2
  39. package/dist/components/core/ScrollArea/ScrollArea.theme.js +1 -1
  40. package/dist/components/core/Segmented/Segmented.js +8 -6
  41. package/dist/components/core/Segmented/Segmented.theme.js +3 -3
  42. package/dist/components/core/Sidebar/Sidebar.d.ts +1 -1
  43. package/dist/components/core/Sidebar/Sidebar.js +42 -13
  44. package/dist/components/core/Sidebar/Sidebar.theme.js +5 -7
  45. package/dist/components/core/Sidebar/Sidebar.types.d.ts +33 -4
  46. package/dist/components/core/Sidebar/SidebarContent.js +6 -6
  47. package/dist/components/core/Sidebar/SidebarContext.d.ts +17 -16
  48. package/dist/components/core/Sidebar/SidebarContext.js +42 -19
  49. package/dist/components/core/Sidebar/SidebarFooter.js +4 -6
  50. package/dist/components/core/Sidebar/SidebarHeader.js +4 -9
  51. package/dist/components/core/Sidebar/SidebarLogo.js +3 -7
  52. package/dist/components/core/Sidebar/SidebarNav.js +4 -3
  53. package/dist/components/core/Sidebar/SidebarNavGroup.js +4 -7
  54. package/dist/components/core/Sidebar/SidebarToggle.js +6 -1
  55. package/dist/components/core/Sidebar/SidebarUserProfile.js +33 -17
  56. package/dist/components/core/Sidebar/index.d.ts +2 -3
  57. package/dist/components/core/Skeleton/Skeleton.theme.js +1 -1
  58. package/dist/components/core/Spinner/Spinner.theme.js +1 -1
  59. package/dist/components/core/Tabs/Tabs.js +6 -1
  60. package/dist/components/core/Tabs/Tabs.types.d.ts +2 -0
  61. package/dist/components/core/Tabs/TabsBody.js +5 -3
  62. package/dist/components/core/Tag/Tag.theme.js +1 -1
  63. package/dist/components/core/index.d.ts +1 -0
  64. package/dist/components/core/index.js +2 -2
  65. package/dist/components/data-display/GanttChart/GanttTableGroupRow.js +1 -1
  66. package/dist/components/data-display/KPI/KPI.js +13 -3
  67. package/dist/components/data-display/KPI/KPI.theme.js +3 -3
  68. package/dist/components/data-display/Metric/Metric.theme.js +3 -3
  69. package/dist/components/data-display/Table/Table.js +4 -3
  70. package/dist/components/data-display/Table/Table.theme.js +11 -1
  71. package/dist/components/data-display/Table/Table.types.d.ts +15 -0
  72. package/dist/components/data-display/Table/TableColumnManager.js +1 -1
  73. package/dist/components/data-display/Table/index.d.ts +2 -2
  74. package/dist/components/data-display/Timeline/Timeline.animations.d.ts +0 -7
  75. package/dist/components/data-display/Timeline/Timeline.animations.js +1 -27
  76. package/dist/components/data-display/Timeline/Timeline.js +3 -4
  77. package/dist/components/data-display/Timeline/Timeline.types.d.ts +0 -13
  78. package/dist/components/data-display/Timeline/TimelineContent.js +3 -7
  79. package/dist/components/data-display/Timeline/TimelineItem.js +4 -17
  80. package/dist/components/data-display/Timeline/index.d.ts +2 -2
  81. package/dist/components/effects/Aurora/Aurora.js +79 -40
  82. package/dist/components/effects/InteractiveCharacters/InteractiveCharacters.js +3 -3
  83. package/dist/components/effects/InteractiveCharacters/characters/BlobCharacter.js +13 -4
  84. package/dist/components/effects/InteractiveCharacters/characters/SmallCharacter.js +13 -4
  85. package/dist/components/effects/InteractiveCharacters/characters/TallCharacter.js +14 -4
  86. package/dist/components/effects/MorphingText/MorphingText.js +40 -7
  87. package/dist/components/effects/StripePattern/StripePattern.d.ts +18 -0
  88. package/dist/components/effects/StripePattern/StripePattern.js +54 -0
  89. package/dist/components/effects/StripePattern/StripePattern.types.d.ts +53 -0
  90. package/dist/components/effects/StripePattern/index.d.ts +2 -0
  91. package/dist/components/effects/index.d.ts +9 -0
  92. package/dist/components/effects/index.js +4 -0
  93. package/dist/components/forms/Checkbox/Checkbox.theme.js +1 -1
  94. package/dist/components/forms/CronInput/CronInput.theme.js +16 -16
  95. package/dist/components/forms/DatePicker/DatePickerTrigger.js +1 -1
  96. package/dist/components/forms/DateRangePicker/DateRangePicker.theme.js +1 -1
  97. package/dist/components/forms/DateRangePicker/DateRangePickerTrigger.js +1 -1
  98. package/dist/components/forms/FileUpload/FileUpload.js +1 -1
  99. package/dist/components/forms/FileUpload/FileUploadProgress.js +27 -20
  100. package/dist/components/forms/FileUpload/FileUploadProgress.theme.js +2 -2
  101. package/dist/components/forms/Input/Input.theme.js +9 -11
  102. package/dist/components/forms/Mention/Mention.theme.js +3 -3
  103. package/dist/components/forms/Radio/Radio.theme.js +1 -1
  104. package/dist/components/forms/RichTextEditor/RichTextEditor.d.ts +18 -0
  105. package/dist/components/forms/RichTextEditor/RichTextEditor.js +1231 -236
  106. package/dist/components/forms/RichTextEditor/RichTextEditor.theme.d.ts +53 -1
  107. package/dist/components/forms/RichTextEditor/RichTextEditor.theme.js +99 -25
  108. package/dist/components/forms/RichTextEditor/RichTextEditor.types.d.ts +42 -3
  109. package/dist/components/forms/RichTextEditor/index.d.ts +2 -2
  110. package/dist/components/forms/Select/Select.js +2 -2
  111. package/dist/components/forms/Slider/Slider.theme.js +1 -1
  112. package/dist/components/forms/Switch/Switch.theme.js +1 -1
  113. package/dist/components/forms/TimePicker/TimePicker.theme.js +2 -2
  114. package/dist/components/forms/TimePicker/TimePickerContent.js +1 -0
  115. package/dist/components/forms/TimePicker/TimePickerTrigger.js +1 -1
  116. package/dist/components/forms/forms.theme.js +12 -12
  117. package/dist/components/forms/index.js +1 -0
  118. package/dist/components/layout/FormLayout/FormLayout.js +6 -4
  119. package/dist/components/layout/FormLayout/FormLayout.types.d.ts +3 -3
  120. package/dist/components/layout/FormLayout/FormLayoutSection.js +6 -1
  121. package/dist/components/layout/PageLayout/PageLayout.d.ts +2 -2
  122. package/dist/components/layout/PageLayout/PageLayout.js +23 -5
  123. package/dist/components/layout/PageLayout/PageLayout.theme.d.ts +2 -1
  124. package/dist/components/layout/PageLayout/PageLayout.theme.js +35 -6
  125. package/dist/components/layout/PageLayout/PageLayout.types.d.ts +45 -0
  126. package/dist/components/layout/PageLayout/PageLayoutContent.js +6 -4
  127. package/dist/components/layout/PageLayout/PageLayoutHeader.js +3 -3
  128. package/dist/components/layout/PageLayout/PageLayoutSidebar.js +5 -3
  129. package/dist/components/layout/PageLayout/index.d.ts +1 -1
  130. package/dist/index.js +2 -2
  131. package/dist/styles.css +1 -1
  132. package/package.json +1 -1
  133. package/src/styles/theme.css +127 -92
  134. package/dist/components/core/Sidebar/SidebarSubmenu.d.ts +0 -7
  135. package/dist/components/core/Sidebar/SidebarSubmenu.js +0 -12
@@ -4,10 +4,9 @@ export { SidebarContent } from "./SidebarContent";
4
4
  export { SidebarFooter } from "./SidebarFooter";
5
5
  export { SidebarNav } from "./SidebarNav";
6
6
  export { SidebarNavGroup } from "./SidebarNavGroup";
7
- export { SidebarSubmenu } from "./SidebarSubmenu";
8
7
  export { SidebarToggle } from "./SidebarToggle";
9
8
  export { SidebarMobileTrigger } from "./SidebarMobileTrigger";
10
9
  export { SidebarUserProfile } from "./SidebarUserProfile";
11
10
  export { SidebarLogo } from "./SidebarLogo";
12
- export { useSidebarContext } from "./SidebarContext";
13
- export type { SidebarProps, SidebarHeaderProps, SidebarContentProps, SidebarFooterProps, SidebarNavProps, SidebarNavGroupProps, SidebarToggleProps, SidebarMobileTriggerProps, SidebarUserProfileProps, SidebarUserStatus, SidebarSide, SidebarVariant, SidebarContextValue, SidebarTheme, SidebarThemeOverrides, SidebarLogoProps, } from "./Sidebar.types";
11
+ export { SidebarProvider, useSidebarContext } from "./SidebarContext";
12
+ export type { SidebarProps, SidebarHeaderProps, SidebarContentProps, SidebarFooterProps, SidebarNavProps, SidebarNavGroupProps, SidebarToggleProps, SidebarMobileTriggerProps, SidebarUserProfileProps, SidebarUserStatus, SidebarSide, SidebarVariant, SidebarDensity, SidebarContextValue, SidebarProviderProps, SidebarTheme, SidebarThemeOverrides, SidebarLogoProps, } from "./Sidebar.types";
@@ -4,7 +4,7 @@
4
4
  */
5
5
  const skeletonTheme = {
6
6
  // Base styles with background color and animation
7
- baseStyle: "bg-[var(--color-background-tertiary)] overflow-hidden",
7
+ baseStyle: "bg-[var(--color-surface-sunken)] overflow-hidden",
8
8
  // Shape variants
9
9
  variants: {
10
10
  text: "h-4 rounded",
@@ -15,7 +15,7 @@ const spinnerTheme = {
15
15
  // Color variants
16
16
  colors: {
17
17
  ...semanticSpinnerColors,
18
- dark: "border-[var(--color-background-quinary)] border-t-transparent",
18
+ dark: "border-[var(--color-surface-sunken)] border-t-transparent",
19
19
  },
20
20
  // Animation class with drop shadow
21
21
  animation: "animate-[spin_1s_linear_infinite] rounded-full",
@@ -14,6 +14,9 @@ import { TabsBody } from './TabsBody.js';
14
14
  */
15
15
  const TabsComponent = React__default.forwardRef(({ value, defaultValue, onValueChange, orientation = "horizontal", size = "md", disabled = false, children, className, darkMode = false, ...props }, ref) => {
16
16
  const [currentValue, setCurrentValue] = useState(value || defaultValue || "");
17
+ // Track whether the user has switched tabs yet, so content only animates
18
+ // on an actual tab change and not on mount / page load.
19
+ const [hasSwitched, setHasSwitched] = useState(false);
17
20
  // Unique instance prefix to scope all DOM IDs to this Tabs instance
18
21
  const instanceId = useId();
19
22
  // Track trigger elements for underline positioning
@@ -42,6 +45,7 @@ const TabsComponent = React__default.forwardRef(({ value, defaultValue, onValueC
42
45
  // Safe value change handler with error handling
43
46
  const handleValueChange = useCallback((newValue) => {
44
47
  try {
48
+ setHasSwitched(true);
45
49
  if (!isControlled) {
46
50
  setCurrentValue(newValue);
47
51
  }
@@ -71,7 +75,8 @@ const TabsComponent = React__default.forwardRef(({ value, defaultValue, onValueC
71
75
  registerTrigger,
72
76
  unregisterTrigger,
73
77
  instanceId,
74
- }), [activeValue, handleValueChange, orientation, size, disabled, registerTrigger, unregisterTrigger, instanceId]);
78
+ hasSwitched,
79
+ }), [activeValue, handleValueChange, orientation, size, disabled, registerTrigger, unregisterTrigger, instanceId, hasSwitched]);
75
80
  // Memoize theme classes for performance
76
81
  const themeClasses = useMemo(() => ({
77
82
  baseStyle: tabsTheme.baseStyle,
@@ -141,4 +141,6 @@ export interface TabsContextValue {
141
141
  unregisterTrigger: (value: string) => void;
142
142
  /** Unique prefix scoping DOM IDs to this Tabs instance */
143
143
  instanceId: string;
144
+ /** Whether the user has switched tabs yet (false until the first change). Used to suppress content animation on mount. */
145
+ hasSwitched: boolean;
144
146
  }
@@ -10,7 +10,7 @@ import { getTabsBodyVariants } from './Tabs.animations.js';
10
10
  * TabsBody component displays content panels for tabs with directional fade animations
11
11
  */
12
12
  const TabsBody = React__default.forwardRef(({ value, forceMount = false, children, className, ...props }, ref) => {
13
- const { value: selectedValue, orientation, instanceId } = useTabsContext();
13
+ const { value: selectedValue, orientation, instanceId, hasSwitched } = useTabsContext();
14
14
  const shouldReduceMotion = useReducedMotion();
15
15
  // Check if we're in Storybook and should disable animations
16
16
  const isInStorybook = typeof window !== 'undefined' && window.__STORYBOOK_DISABLE_ANIMATIONS__;
@@ -32,9 +32,11 @@ const TabsBody = React__default.forwardRef(({ value, forceMount = false, childre
32
32
  if (!shouldRender) {
33
33
  return null;
34
34
  }
35
- // Determine animation props (user props will override due to spread order)
35
+ // Determine animation props (user props will override due to spread order).
36
+ // Until the user switches tabs, the panel snaps in (initial=false) so it does
37
+ // not animate on mount / page load — only actual tab changes animate.
36
38
  const animationProps = shouldDisableAnimations ? {} : {
37
- initial: "initial",
39
+ initial: hasSwitched ? "initial" : false,
38
40
  animate: "animate",
39
41
  exit: "exit",
40
42
  variants: contentVariants,
@@ -16,7 +16,7 @@ const tagTheme = {
16
16
  },
17
17
  disabledStyle: "opacity-50 cursor-not-allowed",
18
18
  removeButtonStyle: "inline-flex items-center justify-center rounded-full p-1 " +
19
- "hover:bg-[var(--color-background-quaternary)] " +
19
+ "hover:bg-[var(--color-surface-hover)] " +
20
20
  "text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)] " +
21
21
  "transition-all duration-300 cursor-pointer focus:outline-none " +
22
22
  "focus-visible:ring-2 focus-visible:ring-[var(--color-primary)]",
@@ -47,3 +47,4 @@ export * from "./OfflineIndicator";
47
47
  export * from "./ContextMenu";
48
48
  export * from "./Pill";
49
49
  export * from "./Icon";
50
+ export * from "./ImagePlaceholder";
@@ -96,12 +96,11 @@ export { SidebarContent } from './Sidebar/SidebarContent.js';
96
96
  export { SidebarFooter } from './Sidebar/SidebarFooter.js';
97
97
  export { SidebarNav } from './Sidebar/SidebarNav.js';
98
98
  export { SidebarNavGroup } from './Sidebar/SidebarNavGroup.js';
99
- export { SidebarSubmenu } from './Sidebar/SidebarSubmenu.js';
100
99
  export { SidebarToggle } from './Sidebar/SidebarToggle.js';
101
100
  export { SidebarMobileTrigger } from './Sidebar/SidebarMobileTrigger.js';
102
101
  export { SidebarUserProfile } from './Sidebar/SidebarUserProfile.js';
103
102
  export { SidebarLogo } from './Sidebar/SidebarLogo.js';
104
- export { useSidebarContext } from './Sidebar/SidebarContext.js';
103
+ export { SidebarProvider, useSidebarContext } from './Sidebar/SidebarContext.js';
105
104
  export { OfflineIndicator } from './OfflineIndicator/OfflineIndicator.js';
106
105
  export { offlineIndicatorTheme } from './OfflineIndicator/OfflineIndicator.theme.js';
107
106
  export { ContextMenu } from './ContextMenu/ContextMenu.js';
@@ -110,6 +109,7 @@ export { Pill } from './Pill/Pill.js';
110
109
  export { pillTheme } from './Pill/Pill.theme.js';
111
110
  export { Icon } from './Icon/Icon.js';
112
111
  export { fileTypes } from './Icon/data/fileTypes.js';
112
+ export { ImagePlaceholder } from './ImagePlaceholder/ImagePlaceholder.js';
113
113
  export { AnimatePresence } from 'motion/react';
114
114
  export { CardBody } from './Card/CardBody.js';
115
115
  export { CardFooter } from './Card/CardFooter.js';
@@ -14,7 +14,7 @@ const GanttTableGroupRow = React__default.memo(({ row, }) => {
14
14
  e.preventDefault();
15
15
  toggleGroup(row.group.id);
16
16
  }
17
- }, role: "button", tabIndex: 0, "aria-expanded": !isCollapsed, "aria-label": `${row.group.title} — ${row.completedCount} of ${row.taskCount} completed`, children: [jsxs("div", { className: "flex items-center gap-2 px-3 flex-1 min-w-0", children: [jsx(motion.div, { variants: chevronVariants, animate: isCollapsed ? "collapsed" : "open", children: jsx(ChevronRightIcon, { className: "size-4 text-[var(--color-text-muted)]" }) }), jsx("div", { className: "size-2.5 rounded-full shrink-0", style: { backgroundColor: row.group.color } }), jsx("span", { className: "font-medium text-[var(--color-text-primary)] truncate", children: row.group.title }), jsxs("span", { className: "text-sm text-[var(--color-text-muted)] shrink-0", children: [row.completedCount, "/", row.taskCount] })] }), onTaskAdd && !readonly && (jsx("button", { className: "p-1 mr-2 rounded hover:bg-[var(--color-background-tertiary)] text-[var(--color-text-muted)] opacity-0 group-hover:opacity-100 focus:opacity-100 transition-opacity", "aria-label": `Add task to ${row.group.title}`, onClick: (e) => {
17
+ }, role: "button", tabIndex: 0, "aria-expanded": !isCollapsed, "aria-label": `${row.group.title} — ${row.completedCount} of ${row.taskCount} completed`, children: [jsxs("div", { className: "flex items-center gap-2 px-3 flex-1 min-w-0", children: [jsx(motion.div, { variants: chevronVariants, animate: isCollapsed ? "collapsed" : "open", children: jsx(ChevronRightIcon, { className: "size-4 text-[var(--color-text-muted)]" }) }), jsx("div", { className: "size-2.5 rounded-full shrink-0", style: { backgroundColor: row.group.color } }), jsx("span", { className: "font-medium text-[var(--color-text-primary)] truncate", children: row.group.title }), jsxs("span", { className: "text-sm text-[var(--color-text-muted)] shrink-0", children: [row.completedCount, "/", row.taskCount] })] }), onTaskAdd && !readonly && (jsx("button", { className: "p-1 mr-2 rounded hover:bg-[var(--color-surface-hover)] text-[var(--color-text-muted)] opacity-0 group-hover:opacity-100 focus:opacity-100 transition-opacity", "aria-label": `Add task to ${row.group.title}`, onClick: (e) => {
18
18
  e.stopPropagation();
19
19
  onTaskAdd(row.group.id);
20
20
  }, children: jsx(PlusIcon, { className: "size-4" }) }))] }));
@@ -24,7 +24,13 @@ const KPI = React__default.forwardRef(({ value, label, trend, trendLabel, progre
24
24
  const sign = trend > 0 ? "+" : "";
25
25
  return `${sign}${trend}%`;
26
26
  }, [trend, trendLabel]);
27
- const trendDirection = trend === undefined ? null : trend > 0 ? "up" : trend < 0 ? "down" : "neutral";
27
+ const trendDirection = trend === undefined
28
+ ? null
29
+ : trend > 0
30
+ ? "up"
31
+ : trend < 0
32
+ ? "down"
33
+ : "neutral";
28
34
  // Calculate filled bar count from progress
29
35
  const filledBars = useMemo(() => {
30
36
  if (progress === undefined)
@@ -32,7 +38,10 @@ const KPI = React__default.forwardRef(({ value, label, trend, trendLabel, progre
32
38
  return Math.round((Math.min(Math.max(progress, 0), 100) / 100) * barCount);
33
39
  }, [progress, barCount]);
34
40
  const barSize = kpiTheme.barSizes[size];
35
- return (jsxs("div", { ref: ref, className: cn(theme.baseStyle, className), ...props, children: [jsxs("div", { className: "flex items-start justify-between", children: [jsxs("div", { className: "flex items-baseline gap-2", children: [jsx("span", { className: cn(theme.valueSizes[size]), children: value }), label && (typeof label === 'string' ? (jsxs("span", { className: cn(theme.labelStyle, theme.labelSizes[size]), children: [icon && (jsx("span", { className: "inline-flex items-center mr-1", children: icon })), label] })) : label)] }), formattedTrend && trendDirection && (typeof formattedTrend === 'string' ? (jsxs("span", { className: cn("inline-flex items-center gap-0.5 font-medium", theme.trendSizes[size], trendDirection === "up" && theme.trendPositive, trendDirection === "down" && theme.trendNegative, trendDirection === "neutral" && theme.trendNeutral), children: [formattedTrend, trendDirection === "up" && jsx(ArrowUpRightIcon, { className: "size-4" }), trendDirection === "down" && jsx(ArrowDownRightIcon, { className: "size-4" })] })) : formattedTrend)] }), progress !== undefined && (jsx("div", { className: cn("flex items-end", barSize.gap), role: "img", "aria-label": `Progress: ${progress}%`, children: Array.from({ length: barCount }, (_, i) => {
41
+ return (jsxs("div", { ref: ref, className: cn(theme.baseStyle, className), ...props, children: [jsxs("div", { className: "flex items-start justify-between", children: [jsxs("div", { className: "flex items-baseline gap-2", children: [jsx("span", { className: cn(theme.valueSizes[size]), children: value }), label &&
42
+ (typeof label === "string" ? (jsxs("span", { className: cn(theme.labelStyle, theme.labelSizes[size]), children: [icon && (jsx("span", { className: "inline-flex items-center mr-1", children: icon })), label] })) : (label))] }), formattedTrend &&
43
+ trendDirection &&
44
+ (typeof formattedTrend === "string" ? (jsxs("span", { className: cn("inline-flex items-center gap-0.5 font-medium", theme.trendSizes[size], trendDirection === "up" && theme.trendPositive, trendDirection === "down" && theme.trendNegative, trendDirection === "neutral" && theme.trendNeutral), children: [formattedTrend, trendDirection === "up" && (jsx(ArrowUpRightIcon, { className: "size-4" })), trendDirection === "down" && (jsx(ArrowDownRightIcon, { className: "size-4" }))] })) : (formattedTrend))] }), progress !== undefined && (jsx("div", { className: cn("flex items-end", barSize.gap), role: "img", "aria-label": `Progress: ${progress}%`, children: Array.from({ length: barCount }, (_, i) => {
36
45
  const isFilled = i < filledBars;
37
46
  const fadeDistance = filledBars - i;
38
47
  const fillOpacity = isFilled && fadeDistance <= 3
@@ -43,7 +52,8 @@ const KPI = React__default.forwardRef(({ value, label, trend, trendLabel, progre
43
52
  ease: "easeOut",
44
53
  delay: i * 0.03,
45
54
  } })) }, i));
46
- }) })), subtitle && (typeof subtitle === 'string' ? (jsx("span", { className: cn(theme.subtitleStyle, size === "sm" ? "text-sm" : "text-base"), children: subtitle })) : subtitle)] }));
55
+ }) })), subtitle &&
56
+ (typeof subtitle === "string" ? (jsx("span", { className: cn(theme.subtitleStyle), children: subtitle })) : (subtitle))] }));
47
57
  });
48
58
  KPI.displayName = "KPI";
49
59
 
@@ -7,7 +7,7 @@ const kpiTheme = {
7
7
  md: "text-2xl font-bold text-[var(--color-text-primary)]",
8
8
  lg: "text-3xl font-bold text-[var(--color-text-primary)]",
9
9
  },
10
- labelStyle: "text-[var(--color-text-muted)]",
10
+ labelStyle: "text-[var(--color-text-primary)] font-medium",
11
11
  labelSizes: {
12
12
  sm: "text-xs",
13
13
  md: "text-sm",
@@ -25,13 +25,13 @@ const kpiTheme = {
25
25
  ...semanticBgColors,
26
26
  neutral: "bg-[var(--color-text-secondary)]",
27
27
  },
28
- barEmptyColor: "bg-[var(--color-background-tertiary)]",
28
+ barEmptyColor: "bg-[var(--color-surface-sunken)]",
29
29
  barSizes: {
30
30
  sm: { height: "h-4", width: "w-[3px]", gap: "gap-[2px]" },
31
31
  md: { height: "h-6", width: "w-[3px]", gap: "gap-[3px]" },
32
32
  lg: { height: "h-8", width: "w-1", gap: "gap-1" },
33
33
  },
34
- subtitleStyle: "text-[var(--color-text-muted)]",
34
+ subtitleStyle: "text-[var(--color-text-secondary)] text-sm",
35
35
  };
36
36
 
37
37
  export { kpiTheme };
@@ -60,7 +60,7 @@ const metricTheme = {
60
60
  contentPadding: "p-4",
61
61
  iconContainer: "size-14",
62
62
  label: "text-sm",
63
- value: "text-xl",
63
+ value: "text-2xl",
64
64
  subtitle: "text-xs mt-0.5",
65
65
  },
66
66
  lg: {
@@ -68,12 +68,12 @@ const metricTheme = {
68
68
  contentPadding: "p-5",
69
69
  iconContainer: "size-16",
70
70
  label: "text-base",
71
- value: "text-2xl",
71
+ value: "text-3xl",
72
72
  subtitle: "text-sm mt-1",
73
73
  },
74
74
  },
75
75
  // Common element styles
76
- labelStyle: "font-semibold text-[var(--color-text-secondary)] mb-1",
76
+ labelStyle: "font-semibold text-[var(--color-text-primary)] mb-1",
77
77
  valueStyle: "font-bold text-[var(--color-text-primary)] tracking-tight",
78
78
  subtitleStyle: "text-[var(--color-text-secondary)]/80",
79
79
  iconContainerStyle: "rounded-full flex items-center justify-center flex-shrink-0 p-3.5",
@@ -37,8 +37,8 @@ const TableContext = createContext({
37
37
  * - Theme customization with className overrides
38
38
  */
39
39
  function TableComponent(props) {
40
- var _a;
41
- const { data, columns, rowKey, variant = "default", theme: themeOverrides, className = "", freezeHeader = false, freezeFirstColumn = false, freezeLastColumn = false, sortable = false, sortConfig = [], onSortChange, filterable = false, filterConfig = [], onFilterChange, filterLogic: controlledFilterLogic, enableBuiltInFilter = false, expandable = false, expandedRowRender, expandedRows = [], onExpandedRowsChange, selectable = false, selectionType = "checkbox", selectedRows = [], onSelectionChange, bulkActions = [], showColumnManager = false, visibleColumns: initialVisibleColumns, onVisibleColumnsChange, onColumnReorder, pagination, children, caption, } = props;
40
+ var _a, _b;
41
+ const { data, columns, rowKey, variant = "default", padding = "default", theme: themeOverrides, className = "", freezeHeader = false, freezeFirstColumn = false, freezeLastColumn = false, sortable = false, sortConfig = [], onSortChange, filterable = false, filterConfig = [], onFilterChange, filterLogic: controlledFilterLogic, enableBuiltInFilter = false, expandable = false, expandedRowRender, expandedRows = [], onExpandedRowsChange, selectable = false, selectionType = "checkbox", selectedRows = [], onSelectionChange, bulkActions = [], showColumnManager = false, visibleColumns: initialVisibleColumns, onVisibleColumnsChange, onColumnReorder, pagination, children, caption, } = props;
42
42
  // Column management hook
43
43
  const { visibleColumns, columnOrder, visibleColumnsList, handleToggleColumn, handleColumnReorder, handleResetToDefault, } = useTableColumns({
44
44
  columns,
@@ -104,6 +104,7 @@ function TableComponent(props) {
104
104
  // Get base classes from theme
105
105
  const baseClasses = theme.baseStyle || "";
106
106
  const variantClasses = ((_a = theme.variants) === null || _a === void 0 ? void 0 : _a[variant]) || "";
107
+ const paddingClasses = ((_b = theme.paddingStyles) === null || _b === void 0 ? void 0 : _b[padding]) || "";
107
108
  // Memoize context value to prevent unnecessary re-renders in consumers
108
109
  const contextValue = useMemo(() => ({
109
110
  theme,
@@ -148,7 +149,7 @@ function TableComponent(props) {
148
149
  selectedRows,
149
150
  onSelectionChange,
150
151
  ]);
151
- return (jsx(TableContext.Provider, { value: contextValue, children: jsxs("div", { className: "relative", children: [!isDeclarativeAPI && columns && ((filterable && onFilterChange) || showColumnManager) && (jsxs("div", { className: theme.columnManagerContainer, children: [filterable && onFilterChange && (jsx(TableFilter, { columns: columns, filterConfig: filterConfig, onFilterChange: onFilterChange, filterLogic: filterLogic, onFilterLogicChange: handleFilterLogicChange, data: data })), showColumnManager && (jsx(TableColumnManager, { columns: columns, visibleColumns: visibleColumns, columnOrder: columnOrder, onToggleColumn: handleToggleColumn, onResetToDefault: handleResetToDefault, onColumnReorder: onColumnReorder ? handleColumnReorder : undefined }))] })), !isDeclarativeAPI && selectable && selectedRows.length > 0 && (jsx(TableSelectionHeader, { selectedCount: selectedRows.length, totalCount: paginatedData.length, selectedRows: selectedRows, bulkActions: bulkActions, onClearSelection: handleClearSelection })), jsx("div", { className: "overflow-x-auto", ref: scrollContainerRef, children: jsxs("table", { className: cn(baseClasses, variantClasses, className), role: "table", "aria-label": isDeclarativeAPI ? "Data table" : `Data table with ${paginatedData.length} rows`, "aria-rowcount": pagination ? pagination.totalItems : data === null || data === void 0 ? void 0 : data.length, "aria-colcount": visibleColumnsList.length, children: [caption && (jsx("caption", { className: "sr-only", children: caption })), isDeclarativeAPI ? (children) : (jsxs(Fragment, { children: [jsx(TableHeader, { columns: visibleColumnsList, sortConfig: sortConfig, onSortChange: onSortChange, filterConfig: filterConfig, onFilterChange: onFilterChange, freezeHeader: freezeHeader, freezeFirstColumn: freezeFirstColumn, freezeLastColumn: freezeLastColumn, expandable: expandable, expandedRowRender: expandedRowRender, selectable: selectable, selectionType: selectionType, selectedRows: selectedRows, onSelectionChange: onSelectionChange, totalRowCount: paginatedData.length, theme: theme, data: paginatedData, rowKey: rowKey }), jsx(TableBody, { data: paginatedData, columns: visibleColumnsList, rowKey: rowKey, expandedRowRender: expandedRowRender, expandedRows: expandedRows, onExpandedRowsChange: onExpandedRowsChange, selectable: selectable, selectionType: selectionType, selectedRows: selectedRows, onSelectionChange: onSelectionChange, freezeFirstColumn: freezeFirstColumn, freezeLastColumn: freezeLastColumn, theme: theme })] }))] }) })] }) }));
152
+ return (jsx(TableContext.Provider, { value: contextValue, children: jsxs("div", { className: "relative", children: [!isDeclarativeAPI && columns && ((filterable && onFilterChange) || showColumnManager) && (jsxs("div", { className: theme.columnManagerContainer, children: [filterable && onFilterChange && (jsx(TableFilter, { columns: columns, filterConfig: filterConfig, onFilterChange: onFilterChange, filterLogic: filterLogic, onFilterLogicChange: handleFilterLogicChange, data: data })), showColumnManager && (jsx(TableColumnManager, { columns: columns, visibleColumns: visibleColumns, columnOrder: columnOrder, onToggleColumn: handleToggleColumn, onResetToDefault: handleResetToDefault, onColumnReorder: onColumnReorder ? handleColumnReorder : undefined }))] })), !isDeclarativeAPI && selectable && selectedRows.length > 0 && (jsx(TableSelectionHeader, { selectedCount: selectedRows.length, totalCount: paginatedData.length, selectedRows: selectedRows, bulkActions: bulkActions, onClearSelection: handleClearSelection })), jsx("div", { className: "overflow-x-auto", ref: scrollContainerRef, children: jsxs("table", { className: cn(baseClasses, variantClasses, paddingClasses, className), role: "table", "aria-label": isDeclarativeAPI ? "Data table" : `Data table with ${paginatedData.length} rows`, "aria-rowcount": pagination ? pagination.totalItems : data === null || data === void 0 ? void 0 : data.length, "aria-colcount": visibleColumnsList.length, children: [caption && (jsx("caption", { className: "sr-only", children: caption })), isDeclarativeAPI ? (children) : (jsxs(Fragment, { children: [jsx(TableHeader, { columns: visibleColumnsList, sortConfig: sortConfig, onSortChange: onSortChange, filterConfig: filterConfig, onFilterChange: onFilterChange, freezeHeader: freezeHeader, freezeFirstColumn: freezeFirstColumn, freezeLastColumn: freezeLastColumn, expandable: expandable, expandedRowRender: expandedRowRender, selectable: selectable, selectionType: selectionType, selectedRows: selectedRows, onSelectionChange: onSelectionChange, totalRowCount: paginatedData.length, theme: theme, data: paginatedData, rowKey: rowKey }), jsx(TableBody, { data: paginatedData, columns: visibleColumnsList, rowKey: rowKey, expandedRowRender: expandedRowRender, expandedRows: expandedRows, onExpandedRowsChange: onExpandedRowsChange, selectable: selectable, selectionType: selectionType, selectedRows: selectedRows, onSelectionChange: onSelectionChange, freezeFirstColumn: freezeFirstColumn, freezeLastColumn: freezeLastColumn, theme: theme })] }))] }) })] }) }));
152
153
  }
153
154
  TableComponent.displayName = "Table";
154
155
  const Table = TableComponent;
@@ -20,6 +20,16 @@ const tableTheme = {
20
20
  compact: "border-[var(--color-border)] dark:border-[var(--color-neutral-700)] " +
21
21
  "[&_td]:px-3 [&_td]:py-1 [&_th]:px-3 [&_th]:py-1",
22
22
  },
23
+ // Edge-padding modes — applied at the table root via descendant selectors so they
24
+ // work for both the data-driven and declarative APIs. `flush` zeroes the
25
+ // first/last cell side padding (overrides the default `first:pl-4 last:pr-4`).
26
+ // Descendant selectors (.table th:first-child) outrank per-cell first:pl-4 by
27
+ // one specificity point so this wins without !important.
28
+ paddingStyles: {
29
+ default: "",
30
+ flush: "[&_th:first-child]:pl-0 [&_th:last-child]:pr-0 " +
31
+ "[&_td:first-child]:pl-0 [&_td:last-child]:pr-0",
32
+ },
23
33
  // Header styles
24
34
  // Light: primary text, light border | Dark: neutral-200 text, neutral-700 border
25
35
  headerStyle: "text-left font-semibold sticky top-0 border-b first:pl-4 last:pr-4 " +
@@ -32,7 +42,7 @@ const tableTheme = {
32
42
  // Light: neutral-50 hover | Dark: neutral-800 hover
33
43
  rowStyle: "group transition-all duration-300 relative " +
34
44
  "hover:bg-[var(--color-neutral-50)] " +
35
- "dark:hover:bg-[var(--color-background-tertiary)]",
45
+ "dark:hover:bg-[var(--color-surface-hover)]",
36
46
  // Selected row styles — background is applied per-cell (in TableCell) so that
37
47
  // sticky/frozen columns repaint correctly. The row only carries the left indicator.
38
48
  selectedRowStyle: "shadow-[inset_3px_0_0_0_var(--color-primary)]",
@@ -18,6 +18,13 @@ export interface BulkAction {
18
18
  }
19
19
  /** Table visual variants for different styling approaches */
20
20
  export type TableVariant = 'default' | 'striped' | 'bordered' | 'compact';
21
+ /**
22
+ * Edge padding behavior for table cells.
23
+ * - `default`: First/last cells receive extra side padding (matches inner cells).
24
+ * - `flush`: First/last cells have zero side padding so values align flush with the table's container edges.
25
+ * Useful for invoice-style layouts where the table sits inside a padded card.
26
+ */
27
+ export type TablePadding = 'default' | 'flush';
21
28
  /** Text alignment options for table cells and headers */
22
29
  export type TableAlignment = 'left' | 'center' | 'right';
23
30
  /** Selection control types for row selection */
@@ -95,6 +102,8 @@ export interface FilterConfig {
95
102
  export interface TableThemeOverrides {
96
103
  baseStyle?: string;
97
104
  variants?: Partial<Record<TableVariant, string>>;
105
+ /** Edge-padding mode classes applied at the table root via descendant selectors */
106
+ paddingStyles?: Partial<Record<TablePadding, string>>;
98
107
  headerStyle?: string;
99
108
  cellStyle?: string;
100
109
  rowStyle?: string;
@@ -148,6 +157,12 @@ export interface TableProps<T = unknown> {
148
157
  rowKey?: keyof T | ((row: T, index: number) => string | number);
149
158
  /** Visual variant for different table styles */
150
159
  variant?: TableVariant;
160
+ /**
161
+ * Edge padding behavior. `flush` removes left padding from the first cell and right padding
162
+ * from the last cell so column values align flush with the table's container edges.
163
+ * @default "default"
164
+ */
165
+ padding?: TablePadding;
151
166
  /** Theme overrides for custom styling */
152
167
  theme?: TableThemeOverrides;
153
168
  /** Additional CSS classes for customization */
@@ -18,7 +18,7 @@ function TableColumnManagerComponent({ columns, visibleColumns, columnOrder, onT
18
18
  const displayName = typeof column.header === 'string' ? column.header : column.id;
19
19
  return (jsx(Checkbox, { id: `column-checkbox-${column.id}`, name: `column-${column.id}`, value: column.id, checked: isVisible, onChange: () => onToggleColumn(column.id), "aria-label": `Toggle visibility for ${displayName} column`, label: displayName, state: isLocked ? 'disabled' : 'default' }));
20
20
  };
21
- return (jsxs(Popover, { placement: "bottom-end", offset: 8, children: [jsx(Popover.Trigger, { children: jsxs(Button, { color: "neutral", variant: "filled", "aria-label": "Manage column visibility", children: [jsx(Cog6ToothIcon, { className: "size-5", "aria-hidden": "true" }), "Manage Columns"] }) }), jsx(Popover.Body, { className: "p-0", children: jsxs("div", { className: "w-64 p-3 overflow-hidden", role: "dialog", "aria-labelledby": "column-manager-title", "aria-describedby": "column-manager-description", "aria-modal": "true", children: [jsx("div", { id: "column-manager-title", className: "text-sm uppercase font-bold mb-3 text-[var(--color-text-placeholder)]", children: "Manage Columns" }), jsx("div", { id: "column-manager-description", className: "sr-only", children: "Use checkboxes to control which columns are visible in the table. Locked columns cannot be hidden." }), jsx("div", { className: "space-y-0.5", role: "group", "aria-label": "Column visibility options", children: onColumnReorder ? (jsx(Sortable, { onReorder: onColumnReorder, showDragHandle: true, className: "space-y-0.5", children: orderedColumns.map((column) => (jsx(SortableItem, { id: column.id, disabled: column.locked === true, className: `hover:bg-[var(--color-background-tertiary)] rounded-lg p-1.5 transition-colors ${column.locked ? 'bg-[var(--color-background-secondary)]' : ''}`, children: renderColumnItem(column) }, column.id))) })) : (orderedColumns.map((column) => (jsx("div", { className: `hover:bg-[var(--color-background-tertiary)] rounded-lg p-1.5 transition-colors ${column.locked ? 'bg-[var(--color-background-secondary)]' : ''}`, children: renderColumnItem(column) }, column.id)))) }), jsx("div", { className: "mt-3 flex justify-end", children: jsx(Button, { color: "neutral", variant: "filled", className: "w-full", onClick: onResetToDefault, children: "Reset to Default" }) })] }) })] }));
21
+ return (jsxs(Popover, { placement: "bottom-end", offset: 8, children: [jsx(Popover.Trigger, { children: jsxs(Button, { color: "neutral", variant: "filled", "aria-label": "Manage column visibility", children: [jsx(Cog6ToothIcon, { className: "size-5", "aria-hidden": "true" }), "Manage Columns"] }) }), jsx(Popover.Body, { className: "p-0", children: jsxs("div", { className: "w-64 p-3 overflow-hidden", role: "dialog", "aria-labelledby": "column-manager-title", "aria-describedby": "column-manager-description", "aria-modal": "true", children: [jsx("div", { id: "column-manager-title", className: "text-sm uppercase font-bold mb-3 text-[var(--color-text-placeholder)]", children: "Manage Columns" }), jsx("div", { id: "column-manager-description", className: "sr-only", children: "Use checkboxes to control which columns are visible in the table. Locked columns cannot be hidden." }), jsx("div", { className: "space-y-0.5", role: "group", "aria-label": "Column visibility options", children: onColumnReorder ? (jsx(Sortable, { onReorder: onColumnReorder, showDragHandle: true, className: "space-y-0.5", children: orderedColumns.map((column) => (jsx(SortableItem, { id: column.id, disabled: column.locked === true, className: `hover:bg-[var(--color-surface-hover)] rounded-lg p-1.5 transition-colors ${column.locked ? 'bg-[var(--color-background-secondary)]' : ''}`, children: renderColumnItem(column) }, column.id))) })) : (orderedColumns.map((column) => (jsx("div", { className: `hover:bg-[var(--color-surface-hover)] rounded-lg p-1.5 transition-colors ${column.locked ? 'bg-[var(--color-background-secondary)]' : ''}`, children: renderColumnItem(column) }, column.id)))) }), jsx("div", { className: "mt-3 flex justify-end", children: jsx(Button, { color: "neutral", variant: "filled", className: "w-full", onClick: onResetToDefault, children: "Reset to Default" }) })] }) })] }));
22
22
  }
23
23
  const TableColumnManager = TableColumnManagerComponent;
24
24
 
@@ -1,4 +1,4 @@
1
- import { TableProps, Column, SortConfig, FilterConfig, FilterOperator, FilterType, FilterLogic, FilterOption, TableThemeOverrides, TableVariant, TableAlignment, SelectionType, TableHeaderProps, TableBodyProps, TableRowProps, TableCellProps, TableHeaderCellProps, BulkAction, ActionItem, ActionVariant, ActionPriority, TableActionsProps, TableActionsMenuProps, TablePaginationProps, TableSelectionHeaderProps, TableColumnManagerProps, TableFilterProps } from './Table.types';
1
+ import { TableProps, Column, SortConfig, FilterConfig, FilterOperator, FilterType, FilterLogic, FilterOption, TableThemeOverrides, TableVariant, TablePadding, TableAlignment, SelectionType, TableHeaderProps, TableBodyProps, TableRowProps, TableCellProps, TableHeaderCellProps, BulkAction, ActionItem, ActionVariant, ActionPriority, TableActionsProps, TableActionsMenuProps, TablePaginationProps, TableSelectionHeaderProps, TableColumnManagerProps, TableFilterProps } from './Table.types';
2
2
  import { TableActions } from './TableActions';
3
3
  import { TableActionsMenu } from './TableActionsMenu';
4
4
  import { TablePagination } from './TablePagination';
@@ -16,7 +16,7 @@ interface TableCompound {
16
16
  }
17
17
  declare const Table: TableCompound;
18
18
  export { Table };
19
- export type { TableProps, Column, SortConfig, FilterConfig, FilterOperator, FilterType, FilterLogic, FilterOption, TableThemeOverrides, TableVariant, TableAlignment, SelectionType, TableHeaderProps, TableBodyProps, TableRowProps, TableCellProps, TableHeaderCellProps, BulkAction, ActionItem, ActionVariant, ActionPriority, TableActionsProps, TableActionsMenuProps, TablePaginationProps, TableSelectionHeaderProps, TableColumnManagerProps, TableFilterProps, };
19
+ export type { TableProps, Column, SortConfig, FilterConfig, FilterOperator, FilterType, FilterLogic, FilterOption, TableThemeOverrides, TableVariant, TablePadding, TableAlignment, SelectionType, TableHeaderProps, TableBodyProps, TableRowProps, TableCellProps, TableHeaderCellProps, BulkAction, ActionItem, ActionVariant, ActionPriority, TableActionsProps, TableActionsMenuProps, TablePaginationProps, TableSelectionHeaderProps, TableColumnManagerProps, TableFilterProps, };
20
20
  export { TableActions, TableActionsMenu, TablePagination, TableFilter };
21
21
  export { inferFilterType, getOperatorsForFilterType, getDefaultOperator, isUnaryOperator, isBetweenOperator, filterData, operatorLabels, } from './Table.filterUtils';
22
22
  export { useTableColumns, useTableSelection, useTableExpansion, useTablePagination, useTableFilter, } from './hooks';
@@ -4,13 +4,6 @@ import { Variants } from "motion/react";
4
4
  * Provides a fade + slide effect when items enter the viewport
5
5
  */
6
6
  export declare const timelineItemVariants: Variants;
7
- /**
8
- * Get directional slide variants based on alignment side
9
- * Items slide in from the opposite direction of their placement
10
- *
11
- * @param side - 'left' slides from left, 'right' slides from right
12
- */
13
- export declare const getDirectionalVariants: (side: "left" | "right") => Variants;
14
7
  /**
15
8
  * Horizontal layout item entry animation
16
9
  * Items fade in from below
@@ -20,32 +20,6 @@ const timelineItemVariants = {
20
20
  },
21
21
  },
22
22
  };
23
- /**
24
- * Get directional slide variants based on alignment side
25
- * Items slide in from the opposite direction of their placement
26
- *
27
- * @param side - 'left' slides from left, 'right' slides from right
28
- */
29
- const getDirectionalVariants = (side) => ({
30
- hidden: {
31
- opacity: 0,
32
- x: side === "left" ? -30 : 30,
33
- y: 10,
34
- transition: {
35
- duration: 0.3,
36
- ease: "easeOut",
37
- },
38
- },
39
- visible: {
40
- opacity: 1,
41
- x: 0,
42
- y: 0,
43
- transition: {
44
- duration: 0.5,
45
- ease: [0.04, 0.62, 0.23, 0.98],
46
- },
47
- },
48
- });
49
23
  /**
50
24
  * Horizontal layout item entry animation
51
25
  * Items fade in from below
@@ -89,4 +63,4 @@ const timelineMarkerVariants = {
89
63
  },
90
64
  };
91
65
 
92
- export { getDirectionalVariants, timelineHorizontalItemVariants, timelineItemVariants, timelineMarkerVariants };
66
+ export { timelineHorizontalItemVariants, timelineItemVariants, timelineMarkerVariants };
@@ -14,7 +14,7 @@ const useTimelineContext = () => {
14
14
  throw new Error("Timeline compound components must be used within <Timeline>");
15
15
  return ctx;
16
16
  };
17
- const TimelineRoot = React__default.forwardRef(({ children, className, layout = "vertical", align = "left", theme: themeOverrides, ...props }, ref) => {
17
+ const TimelineRoot = React__default.forwardRef(({ children, className, layout = "vertical", theme: themeOverrides, ...props }, ref) => {
18
18
  // Merge theme with any overrides
19
19
  const theme = useMemo(() => ({
20
20
  ...timelineTheme,
@@ -29,12 +29,11 @@ const TimelineRoot = React__default.forwardRef(({ children, className, layout =
29
29
  // Context value to be provided to children
30
30
  const contextValue = useMemo(() => ({
31
31
  layout,
32
- align,
33
32
  theme,
34
33
  totalItems,
35
- }), [layout, align, theme, totalItems]);
34
+ }), [layout, theme, totalItems]);
36
35
  const isHorizontal = layout === "horizontal";
37
- return (jsx(TimelineContext.Provider, { value: contextValue, children: jsx("div", { ref: ref, className: cn(isHorizontal ? theme.baseStyleHorizontal : theme.baseStyle, className), "data-layout": layout, "data-align": align, role: "list", "aria-label": "Timeline", ...props, children: children }) }));
36
+ return (jsx(TimelineContext.Provider, { value: contextValue, children: jsx("div", { ref: ref, className: cn(isHorizontal ? theme.baseStyleHorizontal : theme.baseStyle, className), "data-layout": layout, role: "list", "aria-label": "Timeline", ...props, children: children }) }));
38
37
  });
39
38
  TimelineRoot.displayName = "Timeline";
40
39
  // Attach compound subcomponents
@@ -3,13 +3,6 @@ import React from "react";
3
3
  * Layout orientation for the Timeline
4
4
  */
5
5
  export type TimelineLayout = "vertical" | "horizontal";
6
- /**
7
- * Alignment mode for vertical timeline items
8
- * - left: all items on the left side of the line
9
- * - right: all items on the right side of the line
10
- * - alternate: items alternate between left and right
11
- */
12
- export type TimelineAlign = "left" | "right" | "alternate";
13
6
  /**
14
7
  * Status of an individual timeline item
15
8
  * - completed: item is finished (success color)
@@ -41,11 +34,6 @@ export interface TimelineProps extends React.HTMLAttributes<HTMLDivElement> {
41
34
  * @default 'vertical'
42
35
  */
43
36
  layout?: TimelineLayout;
44
- /**
45
- * Alignment of items relative to the timeline line (vertical only)
46
- * @default 'left'
47
- */
48
- align?: TimelineAlign;
49
37
  /**
50
38
  * Theme overrides for customizing styles
51
39
  */
@@ -60,7 +48,6 @@ export interface TimelineProps extends React.HTMLAttributes<HTMLDivElement> {
60
48
  */
61
49
  export interface TimelineContextValue {
62
50
  layout: TimelineLayout;
63
- align: TimelineAlign;
64
51
  theme: TimelineThemeOverrides & {
65
52
  baseStyle: string;
66
53
  baseStyleHorizontal: string;
@@ -5,16 +5,12 @@ import { useTimelineContext } from './Timeline.js';
5
5
  import { useTimelineItemContext } from './TimelineItem.js';
6
6
 
7
7
  const TimelineContent = React__default.forwardRef(({ children, className, ...props }, ref) => {
8
- const { theme, layout, align } = useTimelineContext();
9
- const { isLast, index } = useTimelineItemContext();
8
+ const { theme, layout } = useTimelineContext();
9
+ const { isLast } = useTimelineItemContext();
10
10
  const isHorizontal = layout === "horizontal";
11
- // For alternate layout, determine text alignment
12
- const isAlternateRight = align === "alternate" && index % 2 !== 0;
13
11
  return (jsx("div", { ref: ref, className: cn(isHorizontal ? theme.contentStyleHorizontal : theme.contentStyle,
14
12
  // Remove bottom padding on last item
15
- !isHorizontal && isLast && "pb-0",
16
- // Align text based on side in alternate mode
17
- !isHorizontal && isAlternateRight && "text-right", !isHorizontal && align === "right" && "text-right", className), ...props, children: children }));
13
+ !isHorizontal && isLast && "pb-0", className), ...props, children: children }));
18
14
  });
19
15
  TimelineContent.displayName = "TimelineContent";
20
16
 
@@ -3,7 +3,7 @@ import React__default, { createContext, useRef, useState, useEffect, useContext
3
3
  import { useReducedMotion, motion } from 'motion/react';
4
4
  import { cn } from '../../../utils/cn.js';
5
5
  import { useTimelineContext } from './Timeline.js';
6
- import { timelineHorizontalItemVariants, getDirectionalVariants, timelineItemVariants } from './Timeline.animations.js';
6
+ import { timelineHorizontalItemVariants, timelineItemVariants } from './Timeline.animations.js';
7
7
 
8
8
  // Create context for TimelineItem
9
9
  const TimelineItemContext = createContext(undefined);
@@ -15,7 +15,7 @@ const useTimelineItemContext = () => {
15
15
  return ctx;
16
16
  };
17
17
  const TimelineItem = React__default.forwardRef(({ children, className, status = "pending", ...props }, ref) => {
18
- const { layout, align, theme, totalItems } = useTimelineContext();
18
+ const { layout, theme, totalItems } = useTimelineContext();
19
19
  const shouldReduceMotion = useReducedMotion();
20
20
  const itemRef = useRef(null);
21
21
  const [isVisible, setIsVisible] = useState(false);
@@ -48,21 +48,12 @@ const TimelineItem = React__default.forwardRef(({ children, className, status =
48
48
  const isFirst = index === 0;
49
49
  const isLast = index === totalItems - 1;
50
50
  const isHorizontal = layout === "horizontal";
51
- // Determine which side this item is on for alternate layout
52
- const itemSide = align === "alternate"
53
- ? index % 2 === 0
54
- ? "left"
55
- : "right"
56
- : align;
57
- // Select animation variants based on layout and alignment
51
+ // Select animation variants based on layout
58
52
  const getVariants = () => {
59
53
  if (shouldReduceMotion)
60
54
  return undefined;
61
55
  if (isHorizontal)
62
56
  return timelineHorizontalItemVariants;
63
- if (align === "alternate") {
64
- return getDirectionalVariants(itemSide);
65
- }
66
57
  return timelineItemVariants;
67
58
  };
68
59
  // Context value for Marker and Content
@@ -72,14 +63,10 @@ const TimelineItem = React__default.forwardRef(({ children, className, status =
72
63
  isFirst,
73
64
  isLast,
74
65
  };
75
- // Build className based on layout
76
- const isAlternateRight = align === "alternate" && index % 2 !== 0;
77
66
  // Filter out conflicting motion props from rest
78
67
  const { onDrag, onDragEnd, onDragStart, onAnimationStart, onAnimationEnd, ...safeProps } = props;
79
68
  const variants = getVariants();
80
- return (jsx(TimelineItemContext.Provider, { value: contextValue, children: jsx(motion.div, { ref: ref || itemRef, className: cn(isHorizontal ? theme.itemStyleHorizontal : theme.itemStyle,
81
- // For right-aligned or alternate-right, reverse the flex direction
82
- !isHorizontal && align === "right" && "flex-row-reverse", !isHorizontal && isAlternateRight && "flex-row-reverse", className), "data-status": status, "data-side": itemSide, "data-layout": layout, role: "listitem", initial: variants ? "hidden" : undefined, animate: variants && isVisible ? "visible" : variants ? "hidden" : undefined, variants: variants, ...safeProps, children: children }) }));
69
+ return (jsx(TimelineItemContext.Provider, { value: contextValue, children: jsx(motion.div, { ref: ref || itemRef, className: cn(isHorizontal ? theme.itemStyleHorizontal : theme.itemStyle, className), "data-status": status, "data-layout": layout, role: "listitem", initial: variants ? "hidden" : undefined, animate: variants && isVisible ? "visible" : variants ? "hidden" : undefined, variants: variants, ...safeProps, children: children }) }));
83
70
  });
84
71
  TimelineItem.displayName = "TimelineItem";
85
72
 
@@ -1,4 +1,4 @@
1
1
  import { Timeline } from "./Timeline";
2
- import { TimelineProps, TimelineItemProps, TimelineMarkerProps, TimelineContentProps, TimelineContextValue, TimelineItemContextValue, TimelineThemeOverrides, TimelineLayout, TimelineAlign, TimelineItemStatus } from "./Timeline.types";
2
+ import { TimelineProps, TimelineItemProps, TimelineMarkerProps, TimelineContentProps, TimelineContextValue, TimelineItemContextValue, TimelineThemeOverrides, TimelineLayout, TimelineItemStatus } from "./Timeline.types";
3
3
  export { Timeline };
4
- export type { TimelineProps, TimelineItemProps, TimelineMarkerProps, TimelineContentProps, TimelineContextValue, TimelineItemContextValue, TimelineThemeOverrides, TimelineLayout, TimelineAlign, TimelineItemStatus, };
4
+ export type { TimelineProps, TimelineItemProps, TimelineMarkerProps, TimelineContentProps, TimelineContextValue, TimelineItemContextValue, TimelineThemeOverrides, TimelineLayout, TimelineItemStatus, };