flikkui 0.1.0-beta.4 → 0.1.0-beta.5
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.
- package/dist/components/charts/AreaChart/AreaChart.js +434 -0
- package/dist/components/charts/AreaChart/AreaChart.types.js +7 -0
- package/dist/components/charts/BarChart/BarChart.js +402 -0
- package/dist/components/charts/BarChart/BarChart.types.js +7 -0
- package/dist/components/charts/ChartContainer.js +38 -0
- package/dist/components/charts/Heatmap/Heatmap.js +153 -0
- package/dist/components/charts/Heatmap/HeatmapCell.js +100 -0
- package/dist/components/charts/Heatmap/HeatmapLegend.js +20 -0
- package/dist/components/charts/Heatmap/utils/heatmapUtils.js +174 -0
- package/dist/components/charts/LineChart/LineChart.js +396 -0
- package/dist/components/charts/LineChart/LineChart.types.js +7 -0
- package/dist/components/charts/hooks/useChartAccessibility.js +127 -0
- package/dist/components/charts/hooks/useChartTheme.js +86 -0
- package/dist/components/charts/hooks/useChartValidation.js +59 -0
- package/dist/components/charts/hooks/useTooltipPosition.js +292 -0
- package/dist/components/charts/shared/ChartAxis/XAxis.js +30 -0
- package/dist/components/charts/shared/ChartAxis/YAxis.js +97 -0
- package/dist/components/charts/shared/ChartCrosshair/ChartCrosshair.js +35 -0
- package/dist/components/charts/shared/ChartCrosshair/ChartCrosshair.theme.js +11 -0
- package/dist/components/charts/shared/ChartErrorBoundary/ChartErrorBoundary.js +66 -0
- package/dist/components/charts/shared/ChartGrid/HorizontalGrid.js +22 -0
- package/dist/components/charts/shared/ChartLegend/ChartLegend.js +30 -0
- package/dist/components/charts/shared/ChartLegend/ChartLegendContent.js +22 -0
- package/dist/components/charts/shared/ChartMarker/ChartMarker.js +25 -0
- package/dist/components/charts/shared/ChartMarker/ChartMarker.theme.js +9 -0
- package/dist/components/charts/shared/ChartText/ChartText.js +33 -0
- package/dist/components/charts/shared/ChartText/ChartText.theme.js +9 -0
- package/dist/components/charts/shared/ChartTooltip/ChartTooltip.js +62 -0
- package/dist/components/charts/theme/chart.theme.js +73 -0
- package/dist/components/charts/types/chart.types.js +29 -0
- package/dist/components/charts/utils/chart-validation.js +292 -0
- package/dist/components/charts/utils/color-utils.js +175 -0
- package/dist/components/core/Accordion/Accordion.animations.js +45 -0
- package/dist/components/core/Accordion/Accordion.js +52 -0
- package/dist/components/core/Accordion/Accordion.theme.js +8 -0
- package/dist/components/core/Accordion/AccordionContent.js +25 -0
- package/dist/components/core/Accordion/AccordionItem.js +56 -0
- package/dist/components/core/Accordion/AccordionTrigger.js +32 -0
- package/dist/components/core/Accordion/index.js +5 -0
- package/dist/components/core/Avatar/Avatar.js +94 -0
- package/dist/components/core/Avatar/Avatar.theme.js +25 -0
- package/dist/components/core/AvatarGroup/AvatarGroup.animations.js +79 -0
- package/dist/components/core/AvatarGroup/AvatarGroup.js +67 -0
- package/dist/components/core/AvatarGroup/AvatarGroup.theme.js +23 -0
- package/dist/components/core/Badge/Badge.animations.js +109 -0
- package/dist/components/core/Badge/Badge.js +101 -0
- package/dist/components/core/Badge/Badge.theme.js +41 -0
- package/dist/components/core/Breadcrumbs/Breadcrumbs.theme.js +8 -8
- package/dist/components/core/Button/Button.theme.js +5 -5
- package/dist/components/core/Card/Card.js +46 -0
- package/dist/components/core/Card/Card.theme.js +5 -0
- package/dist/components/core/Divider/Divider.js +21 -0
- package/dist/components/core/Divider/Divider.theme.js +19 -0
- package/dist/components/core/Pagination/Pagination.js +113 -0
- package/dist/components/core/Pagination/Pagination.theme.js +27 -0
- package/dist/components/core/Segmented/Segmented.js +69 -0
- package/dist/components/core/Segmented/Segmented.theme.js +40 -0
- package/dist/components/core/Segmented/SegmentedContext.js +8 -0
- package/dist/components/core/Segmented/SegmentedItem.js +30 -0
- package/dist/components/core/Stepper/Stepper.js +57 -0
- package/dist/components/core/Stepper/Stepper.theme.js +9 -0
- package/dist/components/core/Stepper/components/ConnectorLine.js +42 -0
- package/dist/components/core/Stepper/components/IconCircle.js +44 -0
- package/dist/components/core/Stepper/components/ProgressIndicator.js +12 -0
- package/dist/components/core/Stepper/components/StepContent.js +36 -0
- package/dist/components/core/Stepper/components/StepperItem.js +22 -0
- package/dist/components/core/Tabs/Tabs.theme.js +2 -2
- package/dist/components/core/Tooltip/Tooltip.animations.js +46 -0
- package/dist/components/core/Tooltip/Tooltip.js +85 -0
- package/dist/components/core/Tooltip/Tooltip.theme.js +11 -0
- package/dist/components/core/Tooltip/useTooltipPositioning.js +59 -0
- package/dist/components/core/Tree/Tree.animations.js +38 -0
- package/dist/components/core/Tree/Tree.js +177 -0
- package/dist/components/core/Tree/Tree.theme.js +11 -0
- package/dist/components/data-display/Table/Table.js +177 -0
- package/dist/components/data-display/Table/Table.theme.js +28 -0
- package/dist/components/data-display/Table/Table.utils.js +28 -0
- package/dist/components/data-display/Table/components/DeclarativeComponents.js +123 -0
- package/dist/components/data-display/Table/components/TableActions/TableActions.js +56 -0
- package/dist/components/data-display/Table/components/TableActions/TableActionsMenu.js +29 -0
- package/dist/components/data-display/Table/components/TableColumnManager/TableColumnManager.js +85 -0
- package/dist/components/data-display/Table/components/TableColumnManager/TableColumnManager.theme.js +21 -0
- package/dist/components/data-display/Table/components/TablePagination/TablePagination.js +51 -0
- package/dist/components/data-display/Table/components/TableSelectionHeader/TableSelectionHeader.js +29 -0
- package/dist/components/data-display/Table/components/core/TableBody.js +32 -0
- package/dist/components/data-display/Table/components/core/TableCell.js +47 -0
- package/dist/components/data-display/Table/components/core/TableHeader.js +77 -0
- package/dist/components/data-display/Table/components/core/TableRow.js +46 -0
- package/dist/components/data-display/Table/index.js +20 -0
- package/dist/components/feedback/Alert/Alert.js +36 -0
- package/dist/components/feedback/Alert/Alert.theme.js +17 -0
- package/dist/components/feedback/ChatMessage/ChatMessage.js +26 -0
- package/dist/components/feedback/ChatMessage/ChatMessage.theme.js +16 -0
- package/dist/components/feedback/Empty/Empty.js +26 -0
- package/dist/components/feedback/Empty/Empty.theme.js +13 -0
- package/dist/components/feedback/Notification/Notification.js +41 -0
- package/dist/components/feedback/Notification/Notification.theme.js +49 -0
- package/dist/components/feedback/Spinner/Spinner.theme.js +3 -3
- package/dist/components/feedback/Toast/Toast.animations.js +58 -0
- package/dist/components/feedback/Toast/Toast.js +67 -0
- package/dist/components/feedback/Toast/Toast.theme.js +18 -0
- package/dist/components/feedback/Toast/ToastProvider.js +73 -0
- package/dist/components/feedback/Toast/useToast.js +91 -0
- package/dist/components/forms/Checkbox/Checkbox.theme.js +1 -1
- package/dist/components/forms/FormLabel/FormLabel.theme.js +2 -2
- package/dist/components/forms/Input/Input.theme.js +4 -4
- package/dist/components/forms/Radio/Radio.theme.js +2 -2
- package/dist/components/forms/Select/Select.js +1 -1
- package/dist/components/forms/Select/Select.theme.js +5 -5
- package/dist/components/forms/Switch/Switch.theme.js +1 -1
- package/dist/components/forms/TimePicker/TimePicker.theme.js +19 -19
- package/dist/components/forms/forms.theme.js +8 -8
- package/dist/components/navigation/NavItem/NavItem.js +93 -0
- package/dist/components/navigation/NavItem/NavItem.theme.js +27 -0
- package/dist/components/navigation/Sidebar/Sidebar.js +28 -0
- package/dist/components/navigation/Sidebar/Sidebar.theme.js +16 -0
- package/dist/components/navigation/Sidebar/SidebarContent.js +12 -0
- package/dist/components/navigation/Sidebar/SidebarContext.js +38 -0
- package/dist/components/navigation/Sidebar/SidebarFooter.js +11 -0
- package/dist/components/navigation/Sidebar/SidebarHeader.js +22 -0
- package/dist/components/navigation/Sidebar/SidebarNav.js +11 -0
- package/dist/components/navigation/Sidebar/SidebarNavGroup.js +19 -0
- package/dist/components/navigation/Sidebar/SidebarToggle.js +26 -0
- package/dist/icons/core/TickIcon.js +3 -1
- package/dist/index.d.ts +29 -4
- package/dist/index.js +64 -4
- package/dist/node_modules/@heroicons/react/20/solid/esm/ChevronDownIcon.js +26 -0
- package/dist/node_modules/@heroicons/react/24/outline/esm/ChevronDoubleLeftIcon.js +28 -0
- package/dist/node_modules/@heroicons/react/24/outline/esm/ChevronDoubleRightIcon.js +28 -0
- package/dist/node_modules/@heroicons/react/24/outline/esm/ChevronLeftIcon.js +28 -0
- package/dist/node_modules/@heroicons/react/24/outline/esm/Cog6ToothIcon.js +32 -0
- package/dist/node_modules/@heroicons/react/24/outline/esm/DocumentIcon.js +28 -0
- package/dist/node_modules/@heroicons/react/24/outline/esm/EllipsisVerticalIcon.js +28 -0
- package/dist/node_modules/@heroicons/react/24/outline/esm/PlusIcon.js +28 -0
- package/dist/node_modules/@heroicons/react/24/solid/esm/ArrowPathIcon.js +26 -0
- package/dist/node_modules/@heroicons/react/24/solid/esm/BellIcon.js +26 -0
- package/dist/node_modules/@heroicons/react/24/solid/esm/CheckCircleIcon.js +26 -0
- package/dist/node_modules/@heroicons/react/24/solid/esm/ExclamationTriangleIcon.js +26 -0
- package/dist/node_modules/@heroicons/react/24/solid/esm/InformationCircleIcon.js +26 -0
- package/dist/node_modules/@heroicons/react/24/solid/esm/XCircleIcon.js +26 -0
- package/dist/node_modules/@heroicons/react/24/solid/esm/XMarkIcon.js +26 -0
- package/dist/node_modules/tslib/tslib.es6.js +15 -1
- package/dist/utils/dateUtils.js +32 -0
- package/dist/utils/debounce.js +21 -0
- package/package.json +1 -1
- package/dist/styles.css +0 -2
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { __rest, __assign } from '../../../node_modules/tslib/tslib.es6.js';
|
|
2
|
+
import React__default, { useState, useMemo } from 'react';
|
|
3
|
+
import { Avatar } from '../Avatar/Avatar.js';
|
|
4
|
+
import { cn } from '../../../utils/cn.js';
|
|
5
|
+
import { avatarGroupTheme } from './AvatarGroup.theme.js';
|
|
6
|
+
import { getAnimationState, getAvatarGroupVariants } from './AvatarGroup.animations.js';
|
|
7
|
+
import { useReducedMotion } from '../../../node_modules/framer-motion/dist/es/utils/reduced-motion/use-reduced-motion.js';
|
|
8
|
+
import { motion } from '../../../node_modules/framer-motion/dist/es/render/components/motion/proxy.js';
|
|
9
|
+
|
|
10
|
+
var AvatarGroup = React__default.forwardRef(function (_a, ref) {
|
|
11
|
+
var _b = _a.avatars, avatars = _b === void 0 ? [] : _b, _c = _a.max, max = _c === void 0 ? 5 : _c, _d = _a.size, size = _d === void 0 ? "md" : _d, _e = _a.spacing, spacing = _e === void 0 ? "normal" : _e, _f = _a.direction, direction = _f === void 0 ? "row" : _f, overflowIndicator = _a.overflowIndicator, className = _a.className, _g = _a.ariaLabel, ariaLabel = _g === void 0 ? "Group of users" : _g, _h = _a.shouldAnimate, shouldAnimate = _h === void 0 ? true : _h, props = __rest(_a, ["avatars", "max", "size", "spacing", "direction", "overflowIndicator", "className", "ariaLabel", "shouldAnimate"]);
|
|
12
|
+
var _j = useState(null), hoveredIndex = _j[0], setHoveredIndex = _j[1];
|
|
13
|
+
var shouldReduceMotion = useReducedMotion();
|
|
14
|
+
var enableAnimations = shouldAnimate && !shouldReduceMotion;
|
|
15
|
+
// Memoize expensive calculations to prevent unnecessary re-renders
|
|
16
|
+
var memoizedData = useMemo(function () {
|
|
17
|
+
var visibleAvatars = avatars.slice(0, max);
|
|
18
|
+
var overflowCount = avatars.length > max ? avatars.length - max : 0;
|
|
19
|
+
var spacingClass = avatarGroupTheme.spacingStyles[spacing];
|
|
20
|
+
var spacingHoverClass = enableAnimations ? avatarGroupTheme.spacingHoverStyles[spacing] : '';
|
|
21
|
+
var directionClass = direction === "row-reverse" ? "flex-row-reverse" : "flex-row";
|
|
22
|
+
var totalPeople = avatars.length;
|
|
23
|
+
var groupDescription = avatars
|
|
24
|
+
.map(function (avatar) { return avatar.alt || "User"; })
|
|
25
|
+
.join(", ");
|
|
26
|
+
return {
|
|
27
|
+
visibleAvatars: visibleAvatars,
|
|
28
|
+
overflowCount: overflowCount,
|
|
29
|
+
spacingClass: spacingClass,
|
|
30
|
+
spacingHoverClass: spacingHoverClass,
|
|
31
|
+
directionClass: directionClass,
|
|
32
|
+
totalPeople: totalPeople,
|
|
33
|
+
groupDescription: groupDescription
|
|
34
|
+
};
|
|
35
|
+
}, [avatars, max, spacing, direction, enableAnimations]);
|
|
36
|
+
var visibleAvatars = memoizedData.visibleAvatars, overflowCount = memoizedData.overflowCount, spacingClass = memoizedData.spacingClass, spacingHoverClass = memoizedData.spacingHoverClass, directionClass = memoizedData.directionClass, totalPeople = memoizedData.totalPeople, groupDescription = memoizedData.groupDescription;
|
|
37
|
+
return (React__default.createElement("div", __assign({ ref: ref, className: cn(avatarGroupTheme.baseStyle, directionClass, className // User overrides take precedence
|
|
38
|
+
), role: "group", "aria-label": ariaLabel, "aria-description": "Contains ".concat(totalPeople, " users: ").concat(groupDescription), "data-size": size, "data-spacing": spacing, "data-direction": direction, "data-total": totalPeople, "data-visible": visibleAvatars.length, "data-overflow": overflowCount > 0 ? "true" : "false", onMouseLeave: function () { return enableAnimations && setHoveredIndex(null); } }, props),
|
|
39
|
+
visibleAvatars.map(function (avatarProps, index) {
|
|
40
|
+
// Create contextual label for individual avatars in a group
|
|
41
|
+
var position = index + 1;
|
|
42
|
+
var contextLabel = avatarProps.contextualLabel ||
|
|
43
|
+
" (".concat(position, " of ").concat(totalPeople, ")");
|
|
44
|
+
var MotionDiv = enableAnimations ? motion.div : "div";
|
|
45
|
+
var motionProps = enableAnimations ? {
|
|
46
|
+
variants: getAvatarGroupVariants(direction, shouldReduceMotion, enableAnimations),
|
|
47
|
+
animate: getAnimationState(index, hoveredIndex, enableAnimations),
|
|
48
|
+
onHoverStart: function () { return setHoveredIndex(index); },
|
|
49
|
+
whileHover: "hover"
|
|
50
|
+
} : {};
|
|
51
|
+
return (React__default.createElement(MotionDiv, __assign({ key: index, className: cn(
|
|
52
|
+
// First avatar doesn't need negative margin
|
|
53
|
+
index > 0 ? spacingClass : "z-10",
|
|
54
|
+
// Apply hover z-index only when animations enabled
|
|
55
|
+
index > 0 && spacingHoverClass), "data-position": position, "data-index": index }, motionProps),
|
|
56
|
+
React__default.createElement(Avatar, __assign({ size: size }, avatarProps, { contextualLabel: contextLabel,
|
|
57
|
+
// Ensure that groupPosition is not passed to avoid conflicts
|
|
58
|
+
groupPosition: undefined }))));
|
|
59
|
+
}),
|
|
60
|
+
overflowCount > 0 && (React__default.createElement("div", { className: cn(spacingClass, enableAnimations && "transition-transform duration-200 hover:scale-110"), "data-overflow-count": overflowCount }, overflowIndicator ? (overflowIndicator(overflowCount)) : (React__default.createElement(Avatar, { size: size, alt: "+".concat(overflowCount, " more"), fallback: React__default.createElement("span", null,
|
|
61
|
+
"+",
|
|
62
|
+
overflowCount), className: avatarGroupTheme.overflowAvatarStyle, role: "img", "aria-label": "+ ".concat(overflowCount, " more users") }))))));
|
|
63
|
+
});
|
|
64
|
+
// Set display name for dev tools and Storybook
|
|
65
|
+
AvatarGroup.displayName = "AvatarGroup";
|
|
66
|
+
|
|
67
|
+
export { AvatarGroup, AvatarGroup as default };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default theme for the AvatarGroup component
|
|
3
|
+
*/
|
|
4
|
+
var avatarGroupTheme = {
|
|
5
|
+
// Base styles for the avatar group
|
|
6
|
+
baseStyle: 'flex items-start',
|
|
7
|
+
// Spacing options - separated from hover effects
|
|
8
|
+
spacingStyles: {
|
|
9
|
+
tight: '-ml-5 z-10',
|
|
10
|
+
normal: '-ml-3 z-10',
|
|
11
|
+
loose: '-ml-2 z-10',
|
|
12
|
+
},
|
|
13
|
+
// Hover z-index effects - applied separately when animations enabled
|
|
14
|
+
spacingHoverStyles: {
|
|
15
|
+
tight: 'hover:z-20',
|
|
16
|
+
normal: 'hover:z-20',
|
|
17
|
+
loose: 'hover:z-20',
|
|
18
|
+
},
|
|
19
|
+
// Overflow avatar styles
|
|
20
|
+
overflowAvatarStyle: 'bg-neutral-100 text-neutral-800 font-semibold text-sm flex items-center justify-center hover:bg-neutral-200 transition-colors duration-200',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export { avatarGroupTheme };
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// Main badge variants with optimized transitions
|
|
2
|
+
var badgeVariants = {
|
|
3
|
+
initial: {
|
|
4
|
+
opacity: 1,
|
|
5
|
+
scale: 1,
|
|
6
|
+
},
|
|
7
|
+
animate: {
|
|
8
|
+
opacity: 1,
|
|
9
|
+
scale: 1,
|
|
10
|
+
transition: {
|
|
11
|
+
type: "spring",
|
|
12
|
+
stiffness: 500,
|
|
13
|
+
damping: 30,
|
|
14
|
+
mass: 1,
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
exit: {
|
|
18
|
+
opacity: 0,
|
|
19
|
+
scale: 0.2,
|
|
20
|
+
transition: {
|
|
21
|
+
type: "spring",
|
|
22
|
+
stiffness: 500,
|
|
23
|
+
damping: 25,
|
|
24
|
+
mass: 0.8,
|
|
25
|
+
duration: 0.3,
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
// Dot variants
|
|
30
|
+
var dotVariants = {
|
|
31
|
+
initial: {
|
|
32
|
+
opacity: 0,
|
|
33
|
+
scale: 0,
|
|
34
|
+
},
|
|
35
|
+
animate: {
|
|
36
|
+
opacity: 1,
|
|
37
|
+
scale: 1,
|
|
38
|
+
transition: {
|
|
39
|
+
type: "spring",
|
|
40
|
+
stiffness: 500,
|
|
41
|
+
damping: 30,
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
exit: {
|
|
45
|
+
opacity: 0,
|
|
46
|
+
scale: 0,
|
|
47
|
+
transition: {
|
|
48
|
+
duration: 0.15,
|
|
49
|
+
ease: "easeIn",
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
// Dismiss button variants - optimized for performance
|
|
54
|
+
var dismissButtonVariants = {
|
|
55
|
+
initial: {
|
|
56
|
+
opacity: 0.5,
|
|
57
|
+
},
|
|
58
|
+
hover: {
|
|
59
|
+
opacity: 1,
|
|
60
|
+
transition: { duration: 0.15, ease: "easeOut" },
|
|
61
|
+
},
|
|
62
|
+
tap: {
|
|
63
|
+
scale: 0.95,
|
|
64
|
+
transition: { duration: 0.1, ease: "easeOut" },
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
// Optimized dismiss animation sequence
|
|
68
|
+
// This uses Framer Motion's built-in sequencing capabilities
|
|
69
|
+
var dismissVariants = {
|
|
70
|
+
initial: {
|
|
71
|
+
opacity: 0,
|
|
72
|
+
scale: 0.8,
|
|
73
|
+
},
|
|
74
|
+
animate: {
|
|
75
|
+
opacity: 1,
|
|
76
|
+
scale: 1,
|
|
77
|
+
transition: {
|
|
78
|
+
type: "spring",
|
|
79
|
+
stiffness: 500,
|
|
80
|
+
damping: 30,
|
|
81
|
+
mass: 1,
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
// First stage of exit - slight pop
|
|
85
|
+
exit: {
|
|
86
|
+
opacity: 0,
|
|
87
|
+
scale: 0.2,
|
|
88
|
+
transition: {
|
|
89
|
+
opacity: {
|
|
90
|
+
duration: 0.3,
|
|
91
|
+
ease: "easeOut",
|
|
92
|
+
},
|
|
93
|
+
scale: {
|
|
94
|
+
type: "spring",
|
|
95
|
+
stiffness: 300,
|
|
96
|
+
damping: 20,
|
|
97
|
+
// Add a slight delay to create the pop effect
|
|
98
|
+
delay: 0.05,
|
|
99
|
+
},
|
|
100
|
+
duration: 0.4,
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
// Animation timing constants (in ms)
|
|
105
|
+
var animationTiming = {
|
|
106
|
+
dismissDelay: 400, // Total animation duration
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export { animationTiming, badgeVariants, dismissButtonVariants, dismissVariants, dotVariants };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { __rest, __assign } from '../../../node_modules/tslib/tslib.es6.js';
|
|
2
|
+
import React__default, { useState, useMemo, useCallback } from 'react';
|
|
3
|
+
import { cn } from '../../../utils/cn.js';
|
|
4
|
+
import { animationTiming, dismissVariants, badgeVariants, dotVariants, dismissButtonVariants } from './Badge.animations.js';
|
|
5
|
+
import { badgeTheme } from './Badge.theme.js';
|
|
6
|
+
import { AnimatePresence } from '../../../node_modules/framer-motion/dist/es/components/AnimatePresence/index.js';
|
|
7
|
+
import { motion } from '../../../node_modules/framer-motion/dist/es/render/components/motion/proxy.js';
|
|
8
|
+
|
|
9
|
+
// Helper to determine whether we should animate (Storybook can disable animations globally)
|
|
10
|
+
var getShouldAnimate = function () {
|
|
11
|
+
if (typeof window === 'undefined')
|
|
12
|
+
return true;
|
|
13
|
+
if (window.__STORYBOOK_DISABLE_ANIMATIONS__)
|
|
14
|
+
return false;
|
|
15
|
+
try {
|
|
16
|
+
return !window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
17
|
+
}
|
|
18
|
+
catch (_a) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Badge component for displaying status, labels, or counters.
|
|
24
|
+
*
|
|
25
|
+
* @component
|
|
26
|
+
* @example
|
|
27
|
+
* ```tsx
|
|
28
|
+
* <Badge variant="primary" size="md" pill>New Feature</Badge>
|
|
29
|
+
* <Badge variant="success" withDot>Ready</Badge>
|
|
30
|
+
* <Badge dismissible onDismiss={handleDismiss}>Removable</Badge>
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
var Badge = React__default.memo(React__default.forwardRef(function (_a, ref) {
|
|
34
|
+
var _b, _c, _d;
|
|
35
|
+
var children = _a.children, _e = _a.variant, variant = _e === void 0 ? 'default' : _e, _f = _a.size, size = _f === void 0 ? 'md' : _f, _g = _a.pill, pill = _g === void 0 ? false : _g, _h = _a.withDot, withDot = _h === void 0 ? false : _h, _j = _a.dismissible, dismissible = _j === void 0 ? false : _j, onDismiss = _a.onDismiss, className = _a.className, _k = _a.theme, customTheme = _k === void 0 ? {} : _k, props = __rest(_a, ["children", "variant", "size", "pill", "withDot", "dismissible", "onDismiss", "className", "theme"]);
|
|
36
|
+
// Add state to track visibility for animation
|
|
37
|
+
var _l = useState(true), isVisible = _l[0], setIsVisible = _l[1];
|
|
38
|
+
var shouldAnimate = useMemo(getShouldAnimate, []);
|
|
39
|
+
// Validate that onDismiss is provided when dismissible is true
|
|
40
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
41
|
+
if (dismissible && !onDismiss) {
|
|
42
|
+
console.warn('Badge: onDismiss prop is required when dismissible is true');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
var handleDismiss = useCallback(function (e) {
|
|
46
|
+
e.stopPropagation();
|
|
47
|
+
setIsVisible(false);
|
|
48
|
+
// Delay the onDismiss call until after the animation
|
|
49
|
+
setTimeout(function () {
|
|
50
|
+
onDismiss === null || onDismiss === void 0 ? void 0 : onDismiss(e);
|
|
51
|
+
}, animationTiming.dismissDelay);
|
|
52
|
+
}, [onDismiss]);
|
|
53
|
+
// Merge default theme with custom theme overrides
|
|
54
|
+
var theme = __assign(__assign(__assign({}, badgeTheme), customTheme), { variants: __assign(__assign({}, badgeTheme.variants), customTheme.variants), sizes: __assign(__assign({}, badgeTheme.sizes), customTheme.sizes), dotColors: __assign(__assign({}, badgeTheme.dotColors), customTheme.dotColors) });
|
|
55
|
+
// Get styles from theme
|
|
56
|
+
var variantStyles = ((_b = theme.variants) === null || _b === void 0 ? void 0 : _b[variant]) || '';
|
|
57
|
+
var sizeStyle = ((_c = theme.sizes) === null || _c === void 0 ? void 0 : _c[size]) || {};
|
|
58
|
+
var shapeStyle = pill ? 'rounded-full' : 'rounded-md';
|
|
59
|
+
var dotColorStyle = ((_d = theme.dotColors) === null || _d === void 0 ? void 0 : _d[variant]) || '';
|
|
60
|
+
// Button and icon size styles
|
|
61
|
+
var buttonSizeStyles = {
|
|
62
|
+
sm: 'size-3.5',
|
|
63
|
+
md: 'size-4',
|
|
64
|
+
lg: 'size-4.5',
|
|
65
|
+
};
|
|
66
|
+
var iconSizeStyles = {
|
|
67
|
+
sm: 'size-2.5',
|
|
68
|
+
md: 'size-3',
|
|
69
|
+
lg: 'size-3.5',
|
|
70
|
+
};
|
|
71
|
+
var baseStyles = cn(theme.baseStyle, 'badge inline-flex items-center font-medium ring-inset select-none whitespace-nowrap', shapeStyle, variantStyles, sizeStyle.base, pill ? sizeStyle.pill : sizeStyle.default, className);
|
|
72
|
+
// Create data attributes for styling hooks
|
|
73
|
+
var dataAttributes = {
|
|
74
|
+
'data-variant': variant,
|
|
75
|
+
'data-size': size,
|
|
76
|
+
'data-state': isVisible ? 'visible' : 'hidden',
|
|
77
|
+
'data-pill': pill ? 'true' : 'false',
|
|
78
|
+
'data-with-dot': withDot ? 'true' : 'false',
|
|
79
|
+
'data-dismissible': dismissible ? 'true' : 'false',
|
|
80
|
+
};
|
|
81
|
+
if (!shouldAnimate) {
|
|
82
|
+
// Strip motion-only props to satisfy HTMLAttributes typings
|
|
83
|
+
var _m = props; _m.initial; _m.animate; _m.exit; _m.variants; _m.whileHover; _m.whileTap; _m.layout; _m.transition; _m.style; _m.onUpdate; var restHtmlProps = __rest(_m, ["initial", "animate", "exit", "variants", "whileHover", "whileTap", "layout", "transition", "style", "onUpdate"]);
|
|
84
|
+
// Non-animated render for Storybook or reduced-motion environments
|
|
85
|
+
return (isVisible ? (React__default.createElement("span", __assign({ ref: ref, className: baseStyles }, dataAttributes, restHtmlProps),
|
|
86
|
+
withDot && (React__default.createElement("span", { className: cn('badge-dot rounded-full shrink-0 size-1.5', dotColorStyle), "aria-hidden": "true" })),
|
|
87
|
+
React__default.createElement("span", { className: "badge-content" }, children),
|
|
88
|
+
dismissible && (React__default.createElement("button", { type: "button", onClick: handleDismiss, className: cn('badge-dismiss-btn -ml-1 -mr-1 rounded-full p-0.5 cursor-pointer', buttonSizeStyles[size]), "aria-label": "Dismiss" },
|
|
89
|
+
React__default.createElement("svg", { className: cn('badge-dismiss-icon', iconSizeStyles[size]), viewBox: "0 0 16 16", fill: "currentColor" },
|
|
90
|
+
React__default.createElement("path", { d: "M12.72 3.293a1 1 0 00-1.415 0L8.002 6.586 4.709 3.293a1 1 0 00-1.415 1.414L6.587 8l-3.293 3.293a1 1 0 101.415 1.414L8.002 9.414l3.303 3.293a1 1 0 001.415-1.414L9.417 8l3.303-3.293a1 1 0 000-1.414z" })))))) : null);
|
|
91
|
+
}
|
|
92
|
+
return (React__default.createElement(AnimatePresence, { mode: "wait" }, isVisible && (React__default.createElement(motion.span, __assign({ ref: ref, className: baseStyles, variants: dismissible ? dismissVariants : badgeVariants, initial: "initial", animate: "animate", exit: "exit" }, dataAttributes, props),
|
|
93
|
+
withDot && (React__default.createElement(motion.span, { className: cn('badge-dot rounded-full shrink-0 size-1.5', dotColorStyle), variants: dotVariants, "aria-hidden": "true" })),
|
|
94
|
+
React__default.createElement("span", { className: "badge-content" }, children),
|
|
95
|
+
dismissible && (React__default.createElement(motion.button, { type: "button", onClick: handleDismiss, className: cn('badge-dismiss-btn -ml-1 -mr-1 rounded-full p-0.5 cursor-pointer', buttonSizeStyles[size]), "aria-label": "Dismiss", variants: dismissButtonVariants, initial: "initial", whileHover: "hover", whileTap: "tap" },
|
|
96
|
+
React__default.createElement("svg", { className: cn('badge-dismiss-icon', iconSizeStyles[size]), viewBox: "0 0 16 16", fill: "currentColor" },
|
|
97
|
+
React__default.createElement("path", { d: "M12.72 3.293a1 1 0 00-1.415 0L8.002 6.586 4.709 3.293a1 1 0 00-1.415 1.414L6.587 8l-3.293 3.293a1 1 0 101.415 1.414L8.002 9.414l3.303 3.293a1 1 0 001.415-1.414L9.417 8l3.303-3.293a1 1 0 000-1.414z" }))))))));
|
|
98
|
+
}));
|
|
99
|
+
Badge.displayName = 'Badge';
|
|
100
|
+
|
|
101
|
+
export { Badge };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default theme configuration for Badge component
|
|
3
|
+
*/
|
|
4
|
+
var badgeTheme = {
|
|
5
|
+
baseStyle: '',
|
|
6
|
+
variants: {
|
|
7
|
+
default: 'bg-white text-gray-600 ring-1 ring-gray-500/20',
|
|
8
|
+
primary: 'bg-[var(--color-primary-50)] text-primary ring-1 ring-primary/10',
|
|
9
|
+
secondary: 'bg-gray-100 text-gray-700 ring-1 ring-gray-900/10',
|
|
10
|
+
success: 'bg-[var(--color-success-50)] text-[var(--color-success-700)] ring-1 ring-success/20',
|
|
11
|
+
warning: 'bg-[var(--color-warning-50)] text-warning ring-1 ring-warning/20',
|
|
12
|
+
error: 'bg-[var(--color-danger-50)] text-danger ring-1 ring-danger/10',
|
|
13
|
+
},
|
|
14
|
+
sizes: {
|
|
15
|
+
sm: {
|
|
16
|
+
base: 'text-xs py-1 gap-1',
|
|
17
|
+
pill: 'px-2.5',
|
|
18
|
+
default: 'px-2',
|
|
19
|
+
},
|
|
20
|
+
md: {
|
|
21
|
+
base: 'text-sm py-1 gap-1.5',
|
|
22
|
+
pill: 'px-2.5',
|
|
23
|
+
default: 'px-2',
|
|
24
|
+
},
|
|
25
|
+
lg: {
|
|
26
|
+
base: 'text-sm py-1.5 gap-2',
|
|
27
|
+
pill: 'px-3',
|
|
28
|
+
default: 'px-2.5',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
dotColors: {
|
|
32
|
+
default: 'bg-gray-400',
|
|
33
|
+
primary: 'bg-primary',
|
|
34
|
+
secondary: 'bg-gray-500',
|
|
35
|
+
success: 'bg-success',
|
|
36
|
+
warning: 'bg-warning',
|
|
37
|
+
error: 'bg-danger',
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export { badgeTheme };
|
|
@@ -8,10 +8,10 @@ var breadcrumbsTheme = {
|
|
|
8
8
|
container: "flex items-center space-x-1",
|
|
9
9
|
nav: "flex items-center gap-3 space-x-1",
|
|
10
10
|
item: "flex items-cente",
|
|
11
|
-
link: "text-neutral-600 hover:text-neutral-900 transition-colors duration-150 font-medium",
|
|
12
|
-
current: "text-neutral-900 font-medium",
|
|
13
|
-
separator: "text-neutral-400 select-none",
|
|
14
|
-
ellipsis: "text-neutral-600 hover:text-neutral-900 transition-colors duration-150 cursor-pointer p-1 rounded hover:bg-neutral-100",
|
|
11
|
+
link: "text-[var(--color-neutral-600)] hover:text-[var(--color-neutral-900)] transition-colors duration-150 font-medium",
|
|
12
|
+
current: "text-[var(--color-neutral-900)] font-medium",
|
|
13
|
+
separator: "text-[var(--color-neutral-400)] select-none",
|
|
14
|
+
ellipsis: "text-[var(--color-neutral-600)] hover:text-[var(--color-neutral-900)] transition-colors duration-150 cursor-pointer p-1 rounded hover:bg-[var(--color-neutral-100)]",
|
|
15
15
|
icon: "mr-1.5 flex-shrink-0",
|
|
16
16
|
};
|
|
17
17
|
/**
|
|
@@ -20,10 +20,10 @@ var breadcrumbsTheme = {
|
|
|
20
20
|
var breadcrumbsVariants = {
|
|
21
21
|
default: {},
|
|
22
22
|
muted: {
|
|
23
|
-
link: "text-neutral-500 hover:text-neutral-700 transition-colors duration-150 font-normal",
|
|
24
|
-
current: "text-neutral-700 font-normal",
|
|
25
|
-
separator: "text-neutral-300",
|
|
26
|
-
ellipsis: "text-neutral-500 hover:text-neutral-700 transition-colors duration-150 cursor-pointer p-1 rounded hover:bg-neutral-50",
|
|
23
|
+
link: "text-[var(--color-neutral-500)] hover:text-[var(--color-neutral-700)] transition-colors duration-150 font-normal",
|
|
24
|
+
current: "text-[var(--color-neutral-700)] font-normal",
|
|
25
|
+
separator: "text-[var(--color-neutral-300)]",
|
|
26
|
+
ellipsis: "text-[var(--color-neutral-500)] hover:text-[var(--color-neutral-700)] transition-colors duration-150 cursor-pointer p-1 rounded hover:bg-[var(--color-neutral-50)]",
|
|
27
27
|
},
|
|
28
28
|
};
|
|
29
29
|
/**
|
|
@@ -6,15 +6,15 @@ var buttonTheme = {
|
|
|
6
6
|
baseStyle: "inline-flex items-center justify-center gap-2 font-semibold focus:outline-none rounded-[var(--button-rounded)] cursor-pointer transition-all duration-300 ease-in-out",
|
|
7
7
|
// Variant styles
|
|
8
8
|
variants: {
|
|
9
|
-
primary: "bg-primary
|
|
9
|
+
primary: "bg-primary text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--color-primary-600)] border border-[var(--color-primary-700)] hover:bg-[var(--color-primary-700)] hover:ring-2 hover:ring-primary/40 hover:border-[var(--color-primary-600)] hover:shadow-xl hover:shadow-primary/20",
|
|
10
10
|
secondary: "bg-white text-text-secondary focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 border border-border hover:bg-neutral-50 hover:ring-2 hover:ring-border/50 hover:shadow-xl hover:shadow-neutral-500/10",
|
|
11
11
|
ghost: "bg-neutral-50 text-text-secondary hover:bg-neutral-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 hover:ring-2 hover:ring-border/50",
|
|
12
12
|
outline: "bg-white text-text-secondary focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 border border-border hover:bg-neutral-50 hover:ring-2 hover:ring-border/50",
|
|
13
|
-
link: "bg-transparent text-primary-600 hover:text-primary-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600",
|
|
13
|
+
link: "bg-transparent text-[var(--color-primary-600)] hover:text-[var(--color-primary-700)] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--color-primary-600)]",
|
|
14
14
|
clear: "bg-transparent text-text-secondary hover:text-text-primary focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600",
|
|
15
|
-
warning: "bg-warning
|
|
16
|
-
danger: "bg-danger
|
|
17
|
-
success: "bg-success
|
|
15
|
+
warning: "bg-warning text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--color-warning-600)] border border-[var(--color-warning-700)] hover:bg-[var(--color-warning-600)] hover:ring-2 hover:ring-warning/40 hover:border-[var(--color-warning-700)] hover:shadow-xl hover:shadow-warning/20",
|
|
16
|
+
danger: "bg-danger text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--color-danger-600)] border border-[var(--color-danger-700)] hover:bg-[var(--color-danger-600)] hover:ring-2 hover:ring-danger/40 hover:border-[var(--color-danger-700)] hover:shadow-xl hover:shadow-danger/20",
|
|
17
|
+
success: "bg-success text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--color-success-600)] border border-[var(--color-success-600)] hover:bg-[var(--color-success-600)] hover:ring-2 hover:ring-success/30 hover:border-success hover:shadow-xl hover:shadow-success/20",
|
|
18
18
|
},
|
|
19
19
|
// Size variants
|
|
20
20
|
sizes: {
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { __rest, __assign } from '../../../node_modules/tslib/tslib.es6.js';
|
|
2
|
+
import React__default from 'react';
|
|
3
|
+
import { cn } from '../../../utils/cn.js';
|
|
4
|
+
import { cardTheme } from './Card.theme.js';
|
|
5
|
+
|
|
6
|
+
var CardRoot = React__default.forwardRef(function (_a, ref) {
|
|
7
|
+
var children = _a.children, className = _a.className, _b = _a.theme, customTheme = _b === void 0 ? {} : _b, props = __rest(_a, ["children", "className", "theme"]);
|
|
8
|
+
var theme = __assign(__assign({}, cardTheme), customTheme);
|
|
9
|
+
return (React__default.createElement("div", __assign({ ref: ref, className: cn(theme.baseStyle, className) }, props), children));
|
|
10
|
+
});
|
|
11
|
+
var CardHeader = React__default.forwardRef(function (_a, ref) {
|
|
12
|
+
var children = _a.children, className = _a.className, props = __rest(_a, ["children", "className"]);
|
|
13
|
+
return (React__default.createElement("div", __assign({ ref: ref, className: cn('flex flex-col space-y-1.5 p-6', className) }, props), children));
|
|
14
|
+
});
|
|
15
|
+
var CardTitle = React__default.forwardRef(function (_a, ref) {
|
|
16
|
+
var children = _a.children, className = _a.className, props = __rest(_a, ["children", "className"]);
|
|
17
|
+
return (React__default.createElement("h3", __assign({ ref: ref, className: cn('text-2xl font-semibold leading-none tracking-tight', className) }, props), children));
|
|
18
|
+
});
|
|
19
|
+
var CardDescription = React__default.forwardRef(function (_a, ref) {
|
|
20
|
+
var children = _a.children, className = _a.className, props = __rest(_a, ["children", "className"]);
|
|
21
|
+
return (React__default.createElement("p", __assign({ ref: ref, className: cn('text-sm text-gray-600', className) }, props), children));
|
|
22
|
+
});
|
|
23
|
+
var CardContent = React__default.forwardRef(function (_a, ref) {
|
|
24
|
+
var children = _a.children, className = _a.className, props = __rest(_a, ["children", "className"]);
|
|
25
|
+
return (React__default.createElement("div", __assign({ ref: ref, className: cn('p-6 pt-0', className) }, props), children));
|
|
26
|
+
});
|
|
27
|
+
var CardFooter = React__default.forwardRef(function (_a, ref) {
|
|
28
|
+
var children = _a.children, className = _a.className, props = __rest(_a, ["children", "className"]);
|
|
29
|
+
return (React__default.createElement("div", __assign({ ref: ref, className: cn('flex items-center p-6 pt-0', className) }, props), children));
|
|
30
|
+
});
|
|
31
|
+
CardRoot.displayName = 'Card';
|
|
32
|
+
CardHeader.displayName = 'CardHeader';
|
|
33
|
+
CardTitle.displayName = 'CardTitle';
|
|
34
|
+
CardDescription.displayName = 'CardDescription';
|
|
35
|
+
CardContent.displayName = 'CardContent';
|
|
36
|
+
CardFooter.displayName = 'CardFooter';
|
|
37
|
+
// Create compound component with proper typing
|
|
38
|
+
var Card = Object.assign(CardRoot, {
|
|
39
|
+
Header: CardHeader,
|
|
40
|
+
Title: CardTitle,
|
|
41
|
+
Description: CardDescription,
|
|
42
|
+
Content: CardContent,
|
|
43
|
+
Footer: CardFooter,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { __rest, __assign } from '../../../node_modules/tslib/tslib.es6.js';
|
|
2
|
+
import React__default from 'react';
|
|
3
|
+
import { cn } from '../../../utils/cn.js';
|
|
4
|
+
import { dividerTheme } from './Divider.theme.js';
|
|
5
|
+
|
|
6
|
+
var Divider = React__default.forwardRef(function (_a, ref) {
|
|
7
|
+
var _b, _c;
|
|
8
|
+
var _d = _a.vertical, vertical = _d === void 0 ? false : _d, _e = _a.margin, margin = _e === void 0 ? 'md' : _e, className = _a.className, _f = _a.theme, customTheme = _f === void 0 ? {} : _f, props = __rest(_a, ["vertical", "margin", "className", "theme"]);
|
|
9
|
+
var theme = __assign(__assign(__assign({}, dividerTheme), customTheme), { margins: {
|
|
10
|
+
horizontal: __assign(__assign({}, dividerTheme.margins.horizontal), (_b = customTheme.margins) === null || _b === void 0 ? void 0 : _b.horizontal),
|
|
11
|
+
vertical: __assign(__assign({}, dividerTheme.margins.vertical), (_c = customTheme.margins) === null || _c === void 0 ? void 0 : _c.vertical),
|
|
12
|
+
} });
|
|
13
|
+
var marginStyle = vertical
|
|
14
|
+
? theme.margins.vertical[margin] || ''
|
|
15
|
+
: theme.margins.horizontal[margin] || '';
|
|
16
|
+
var orientationStyle = vertical ? theme.vertical : theme.horizontal;
|
|
17
|
+
return (React__default.createElement("div", __assign({ ref: ref, className: cn(theme.baseStyle, orientationStyle, marginStyle, className), role: "separator", "aria-orientation": vertical ? 'vertical' : 'horizontal' }, props)));
|
|
18
|
+
});
|
|
19
|
+
Divider.displayName = 'Divider';
|
|
20
|
+
|
|
21
|
+
export { Divider };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
var dividerTheme = {
|
|
2
|
+
baseStyle: 'bg-gray-200 border-0',
|
|
3
|
+
horizontal: 'w-full h-px',
|
|
4
|
+
vertical: 'h-full w-px',
|
|
5
|
+
margins: {
|
|
6
|
+
horizontal: {
|
|
7
|
+
sm: 'my-2',
|
|
8
|
+
md: 'my-4',
|
|
9
|
+
lg: 'my-6',
|
|
10
|
+
},
|
|
11
|
+
vertical: {
|
|
12
|
+
sm: 'mx-2',
|
|
13
|
+
md: 'mx-4',
|
|
14
|
+
lg: 'mx-6',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export { dividerTheme };
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { __rest, __assign, __spreadArray } from '../../../node_modules/tslib/tslib.es6.js';
|
|
2
|
+
import React__default, { useMemo } from 'react';
|
|
3
|
+
import { paginationTheme } from './Pagination.theme.js';
|
|
4
|
+
import { cn } from '../../../utils/cn.js';
|
|
5
|
+
import Button from '../Button/Button.js';
|
|
6
|
+
import ForwardRef from '../../../node_modules/@heroicons/react/24/outline/esm/ChevronDoubleLeftIcon.js';
|
|
7
|
+
import ForwardRef$1 from '../../../node_modules/@heroicons/react/24/outline/esm/ChevronLeftIcon.js';
|
|
8
|
+
import ForwardRef$2 from '../../../node_modules/@heroicons/react/24/outline/esm/ChevronRightIcon.js';
|
|
9
|
+
import ForwardRef$3 from '../../../node_modules/@heroicons/react/24/outline/esm/ChevronDoubleRightIcon.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Internal PaginationItem component for page numbers and ellipsis
|
|
13
|
+
*/
|
|
14
|
+
var PaginationItem = React__default.forwardRef(function (_a, ref) {
|
|
15
|
+
var isActive = _a.isActive, isDisabled = _a.isDisabled, _b = _a.size, size = _b === void 0 ? "md" : _b, _c = _a.variant, variant = _c === void 0 ? "page" : _c, className = _a.className, children = _a.children, props = __rest(_a, ["isActive", "isDisabled", "size", "variant", "className", "children"]);
|
|
16
|
+
var baseClasses = paginationTheme.itemBase;
|
|
17
|
+
var variantClasses = paginationTheme.variants[variant];
|
|
18
|
+
var sizeClasses = paginationTheme.sizes[size];
|
|
19
|
+
var stateClasses = isActive
|
|
20
|
+
? paginationTheme.states.active
|
|
21
|
+
: isDisabled
|
|
22
|
+
? paginationTheme.states.disabled
|
|
23
|
+
: "";
|
|
24
|
+
return (React__default.createElement("button", __assign({ ref: ref, type: "button", disabled: isDisabled, className: cn(baseClasses, variantClasses, sizeClasses, stateClasses, className), "aria-current": isActive ? "page" : undefined }, props), children));
|
|
25
|
+
});
|
|
26
|
+
PaginationItem.displayName = "PaginationItem";
|
|
27
|
+
/**
|
|
28
|
+
* Generate pagination range with ellipsis
|
|
29
|
+
*/
|
|
30
|
+
var usePaginationRange = function (currentPage, totalPages, siblingCount) {
|
|
31
|
+
if (siblingCount === void 0) { siblingCount = 1; }
|
|
32
|
+
return useMemo(function () {
|
|
33
|
+
var DOTS = "...";
|
|
34
|
+
// Total page numbers to show: current + siblings + first + last + 2 dots
|
|
35
|
+
var totalPageNumbers = siblingCount + 5;
|
|
36
|
+
// If total pages is less than total page numbers, show all pages
|
|
37
|
+
if (totalPageNumbers >= totalPages) {
|
|
38
|
+
return Array.from({ length: totalPages }, function (_, i) { return i + 1; });
|
|
39
|
+
}
|
|
40
|
+
var leftSiblingIndex = Math.max(currentPage - siblingCount, 1);
|
|
41
|
+
var rightSiblingIndex = Math.min(currentPage + siblingCount, totalPages);
|
|
42
|
+
var shouldShowLeftDots = leftSiblingIndex > 2;
|
|
43
|
+
var shouldShowRightDots = rightSiblingIndex < totalPages - 2;
|
|
44
|
+
var firstPageIndex = 1;
|
|
45
|
+
var lastPageIndex = totalPages;
|
|
46
|
+
// No left dots, but right dots
|
|
47
|
+
if (!shouldShowLeftDots && shouldShowRightDots) {
|
|
48
|
+
var leftItemCount = 3 + 2 * siblingCount;
|
|
49
|
+
var leftRange = Array.from({ length: leftItemCount }, function (_, i) { return i + 1; });
|
|
50
|
+
return __spreadArray(__spreadArray([], leftRange, true), [DOTS, totalPages], false);
|
|
51
|
+
}
|
|
52
|
+
// Left dots, but no right dots
|
|
53
|
+
if (shouldShowLeftDots && !shouldShowRightDots) {
|
|
54
|
+
var rightItemCount_1 = 3 + 2 * siblingCount;
|
|
55
|
+
var rightRange = Array.from({ length: rightItemCount_1 }, function (_, i) { return totalPages - rightItemCount_1 + i + 1; });
|
|
56
|
+
return __spreadArray([firstPageIndex, DOTS], rightRange, true);
|
|
57
|
+
}
|
|
58
|
+
// Both left and right dots
|
|
59
|
+
if (shouldShowLeftDots && shouldShowRightDots) {
|
|
60
|
+
var middleRange = Array.from({ length: rightSiblingIndex - leftSiblingIndex + 1 }, function (_, i) { return leftSiblingIndex + i; });
|
|
61
|
+
return __spreadArray(__spreadArray([firstPageIndex, DOTS], middleRange, true), [DOTS, lastPageIndex], false);
|
|
62
|
+
}
|
|
63
|
+
return [];
|
|
64
|
+
}, [currentPage, totalPages, siblingCount]);
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Pagination component for navigating through pages
|
|
68
|
+
*/
|
|
69
|
+
var Pagination = React__default.forwardRef(function (_a, ref) {
|
|
70
|
+
var currentPage = _a.currentPage, totalPages = _a.totalPages, onPageChange = _a.onPageChange, _b = _a.size, size = _b === void 0 ? "md" : _b, _c = _a.showFirstLast, showFirstLast = _c === void 0 ? false : _c, _d = _a.showPrevNext, showPrevNext = _d === void 0 ? true : _d, _e = _a.siblingCount, siblingCount = _e === void 0 ? 1 : _e, className = _a.className, _f = _a.theme, customTheme = _f === void 0 ? {} : _f, props = __rest(_a, ["currentPage", "totalPages", "onPageChange", "size", "showFirstLast", "showPrevNext", "siblingCount", "className", "theme"]);
|
|
71
|
+
// Merge theme with custom overrides
|
|
72
|
+
var theme = __assign(__assign(__assign({}, paginationTheme), customTheme), { variants: __assign(__assign({}, paginationTheme.variants), (customTheme.variants || {})), sizes: __assign(__assign({}, paginationTheme.sizes), (customTheme.sizes || {})), states: __assign(__assign({}, paginationTheme.states), (customTheme.states || {})) });
|
|
73
|
+
var paginationRange = usePaginationRange(currentPage, totalPages, siblingCount);
|
|
74
|
+
// Don't render if there's only one page
|
|
75
|
+
if (totalPages <= 1) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
var handlePageChange = function (page) {
|
|
79
|
+
if (page >= 1 && page <= totalPages && page !== currentPage) {
|
|
80
|
+
onPageChange(page);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
var isFirstPage = currentPage === 1;
|
|
84
|
+
var isLastPage = currentPage === totalPages;
|
|
85
|
+
return (React__default.createElement("nav", __assign({ ref: ref, role: "navigation", "aria-label": "Pagination Navigation", className: cn(theme.baseStyle, className) }, props),
|
|
86
|
+
showFirstLast && (React__default.createElement(Button, { size: size, variant: "clear", disabled: isFirstPage, onClick: function () { return handlePageChange(1); }, "aria-label": "Go to first page" },
|
|
87
|
+
React__default.createElement(ForwardRef, { className: "w-4 h-4" }),
|
|
88
|
+
React__default.createElement("span", { className: "sr-only" }, "First"))),
|
|
89
|
+
showPrevNext && (React__default.createElement(Button, { size: size, variant: "clear", disabled: isFirstPage, onClick: function () { return handlePageChange(currentPage - 1); }, "aria-label": "Go to previous page (".concat(currentPage - 1, ")") },
|
|
90
|
+
React__default.createElement(ForwardRef$1, { className: "w-4 h-4" }),
|
|
91
|
+
React__default.createElement("span", { className: "sr-only" }, "Previous"))),
|
|
92
|
+
paginationRange.map(function (pageNumber, index) {
|
|
93
|
+
if (pageNumber === "...") {
|
|
94
|
+
return (React__default.createElement(PaginationItem, { key: "ellipsis-".concat(index), size: size, variant: "ellipsis", isDisabled: true, "aria-label": "More pages", role: "separator" },
|
|
95
|
+
React__default.createElement("span", { "aria-hidden": "true" }, "\u2026"),
|
|
96
|
+
React__default.createElement("span", { className: "sr-only" }, "More pages")));
|
|
97
|
+
}
|
|
98
|
+
var page = pageNumber;
|
|
99
|
+
var isActive = page === currentPage;
|
|
100
|
+
return (React__default.createElement(PaginationItem, { key: page, size: size, variant: "page", isActive: isActive, onClick: function () { return handlePageChange(page); }, "aria-label": isActive ? "Page ".concat(page, ", current page") : "Go to page ".concat(page) },
|
|
101
|
+
page,
|
|
102
|
+
isActive && React__default.createElement("span", { className: "sr-only" }, "(current)")));
|
|
103
|
+
}),
|
|
104
|
+
showPrevNext && (React__default.createElement(Button, { size: size, variant: "clear", disabled: isLastPage, onClick: function () { return handlePageChange(currentPage + 1); }, "aria-label": "Go to next page (".concat(currentPage + 1, ")") },
|
|
105
|
+
React__default.createElement(ForwardRef$2, { className: "w-4 h-4" }),
|
|
106
|
+
React__default.createElement("span", { className: "sr-only" }, "Next"))),
|
|
107
|
+
showFirstLast && (React__default.createElement(Button, { size: size, variant: "clear", disabled: isLastPage, onClick: function () { return handlePageChange(totalPages); }, "aria-label": "Go to last page" },
|
|
108
|
+
React__default.createElement(ForwardRef$3, { className: "w-4 h-4" }),
|
|
109
|
+
React__default.createElement("span", { className: "sr-only" }, "Last")))));
|
|
110
|
+
});
|
|
111
|
+
Pagination.displayName = "Pagination";
|
|
112
|
+
|
|
113
|
+
export { Pagination as default };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default theme for the Pagination component
|
|
3
|
+
*/
|
|
4
|
+
var paginationTheme = {
|
|
5
|
+
// Base container styles
|
|
6
|
+
baseStyle: "flex items-center justify-center gap-1",
|
|
7
|
+
// Base item styles
|
|
8
|
+
itemBase: "inline-flex items-center justify-center font-medium rounded-full transition-all duration-200 ease-in-out focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 cursor-pointer text-text-secondary hover:text-text-primary",
|
|
9
|
+
// Variant styles
|
|
10
|
+
variants: {
|
|
11
|
+
page: "hover:bg-neutral-50 hover:border-neutral-300",
|
|
12
|
+
ellipsis: "border-none cursor-default pointer-events-none",
|
|
13
|
+
},
|
|
14
|
+
// Size variants
|
|
15
|
+
sizes: {
|
|
16
|
+
sm: "h-8 min-w-[2rem] px-2 text-sm",
|
|
17
|
+
md: "h-10 min-w-[2.5rem] px-3 text-sm",
|
|
18
|
+
},
|
|
19
|
+
// State styles
|
|
20
|
+
states: {
|
|
21
|
+
active: "bg-primary-50 text-text-primary",
|
|
22
|
+
disabled: "opacity-50 cursor-not-allowed pointer-events-none",
|
|
23
|
+
hover: "hover:bg-neutral-50",
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export { paginationTheme };
|