flikkui 0.1.0-beta.2 → 0.1.0-beta.4
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/README.md +155 -0
- package/dist/components/charts/index.d.ts +2 -0
- package/dist/components/charts/shared/ChartLegend/ChartLegend.d.ts +7 -0
- package/dist/components/charts/shared/ChartLegend/ChartLegendContent.d.ts +7 -0
- package/dist/components/charts/shared/ChartLegend/index.d.ts +2 -0
- package/dist/components/core/AvatarGroup/AvatarGroup.animations.d.ts +1 -1
- package/dist/components/core/AvatarGroup/AvatarGroup.theme.d.ts +1 -0
- package/dist/components/core/Breadcrumbs/Breadcrumbs.js +8 -7
- package/dist/components/core/Button/Button.animations.d.ts +0 -12
- package/dist/components/core/Button/Button.animations.js +4 -19
- package/dist/components/core/Button/Button.js +40 -37
- package/dist/components/core/Button/Button.theme.d.ts +0 -4
- package/dist/components/core/Button/Button.theme.js +14 -9
- package/dist/components/core/Button/Button.types.d.ts +1 -1
- package/dist/components/core/Divider/Divider.types.d.ts +8 -2
- package/dist/components/core/Drawer/Drawer.types.d.ts +1 -1
- package/dist/components/core/Modal/Modal.types.d.ts +1 -1
- package/dist/components/core/Pagination/Pagination.types.d.ts +25 -13
- package/dist/components/core/Popover/Popover.animations.d.ts +34 -3
- package/dist/components/core/Popover/Popover.animations.js +19 -0
- package/dist/components/core/Popover/Popover.theme.js +2 -2
- package/dist/components/core/Popover/PopoverContent.js +5 -14
- package/dist/components/core/Segmented/Segmented.types.d.ts +17 -0
- package/dist/components/core/Tabs/Tabs.js +2 -8
- package/dist/components/core/Tabs/Tabs.theme.d.ts +8 -45
- package/dist/components/core/Tabs/Tabs.theme.js +14 -64
- package/dist/components/core/Tabs/Tabs.types.d.ts +4 -36
- package/dist/components/core/Tabs/TabsContent.js +3 -8
- package/dist/components/core/Tabs/TabsList.js +3 -10
- package/dist/components/core/Tabs/TabsTrigger.js +3 -15
- package/dist/components/core/Tabs/index.d.ts +1 -1
- package/dist/components/core/Tooltip/Tooltip.animations.d.ts +1 -1
- package/dist/components/core/Tooltip/Tooltip.d.ts +1 -1
- package/dist/components/core/Tooltip/Tooltip.theme.d.ts +0 -1
- package/dist/components/core/Tooltip/Tooltip.types.d.ts +15 -15
- package/dist/components/core/Tooltip/useTooltipPositioning.d.ts +12 -0
- package/dist/components/core/Tree/Tree.types.d.ts +8 -45
- package/dist/components/core/Tree/index.d.ts +1 -3
- package/dist/components/data-display/Table/Table.animations.d.ts +21 -0
- package/dist/components/data-display/Table/Table.types.d.ts +56 -13
- package/dist/components/data-display/Table/components/TableActionsMenu.d.ts +1 -1
- package/dist/components/data-display/Table/components/TableColumnManager/TableColumnManager.theme.d.ts +16 -0
- package/dist/components/data-display/Table/components/TablePagination/TablePagination.d.ts +17 -0
- package/dist/components/data-display/Table/components/TablePagination/TablePagination.types.d.ts +21 -0
- package/dist/components/data-display/Table/components/TablePagination/index.d.ts +2 -0
- package/dist/components/data-display/Table/index.d.ts +6 -3
- package/dist/components/feedback/Alert/Alert.types.d.ts +4 -0
- package/dist/components/feedback/ChatMessage/ChatMessage.types.d.ts +20 -14
- package/dist/components/feedback/Empty/Empty.theme.d.ts +4 -14
- package/dist/components/feedback/Empty/Empty.types.d.ts +8 -20
- package/dist/components/feedback/Empty/index.d.ts +2 -2
- package/dist/components/feedback/Notification/Notification.theme.d.ts +16 -1
- package/dist/components/feedback/Notification/Notification.types.d.ts +18 -40
- package/dist/components/feedback/Notification/index.d.ts +2 -2
- package/dist/components/feedback/Toast/Toast.animations.d.ts +31 -0
- package/dist/components/feedback/Toast/Toast.types.d.ts +1 -1
- package/dist/components/feedback/index.d.ts +3 -3
- package/dist/components/forms/Checkbox/Checkbox.js +10 -16
- package/dist/components/forms/Checkbox/Checkbox.theme.js +8 -6
- package/dist/components/forms/Checkbox/Checkbox.types.d.ts +13 -30
- package/dist/components/forms/FormLabel/FormLabel.d.ts +1 -2
- package/dist/components/forms/FormLabel/FormLabel.js +7 -14
- package/dist/components/forms/FormLabel/FormLabel.theme.d.ts +3 -4
- package/dist/components/forms/FormLabel/FormLabel.theme.js +6 -6
- package/dist/components/forms/FormLabel/FormLabel.types.d.ts +10 -18
- package/dist/components/forms/FormLabel/index.d.ts +3 -3
- package/dist/components/forms/Input/Input.d.ts +0 -1
- package/dist/components/forms/Input/Input.js +51 -85
- package/dist/components/forms/Input/Input.theme.d.ts +4 -4
- package/dist/components/forms/Input/Input.theme.js +26 -26
- package/dist/components/forms/Input/Input.types.d.ts +41 -64
- package/dist/components/forms/Input/index.d.ts +1 -1
- package/dist/components/forms/InputAddress/InputAddress.theme.d.ts +2 -2
- package/dist/components/forms/InputAddress/InputAddress.types.d.ts +3 -3
- package/dist/components/forms/InputCreditCard/InputCreditCard.theme.d.ts +3 -3
- package/dist/components/forms/InputCreditCard/InputCreditCard.types.d.ts +4 -4
- package/dist/components/forms/Radio/Radio.js +12 -18
- package/dist/components/forms/Radio/Radio.theme.d.ts +2 -18
- package/dist/components/forms/Radio/Radio.theme.js +10 -19
- package/dist/components/forms/Radio/Radio.types.d.ts +16 -32
- package/dist/components/forms/Select/Select.js +1 -9
- package/dist/components/forms/Signature/Signature.js +5 -4
- package/dist/components/forms/Signature/Signature.theme.js +1 -3
- package/dist/components/forms/Signature/Signature.types.d.ts +0 -4
- package/dist/components/layout/DragDrop/DragDrop.js +62 -0
- package/dist/components/layout/DragDrop/DragDrop.theme.js +8 -0
- package/dist/components/layout/Sortable/Sortable.animations.js +81 -0
- package/dist/components/layout/Sortable/Sortable.js +165 -0
- package/dist/components/layout/Sortable/Sortable.theme.js +7 -0
- package/dist/components/navigation/index.d.ts +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -1
- package/dist/node_modules/@heroicons/react/24/outline/esm/Bars3Icon.js +28 -0
- package/dist/node_modules/@heroicons/react/24/outline/esm/LockClosedIcon.js +28 -0
- package/dist/styles.css +1 -1
- package/dist/utils/debounce.d.ts +9 -0
- package/dist/utils/index.d.ts +1 -0
- package/package.json +4 -4
- package/dist/components/core/Popover/test-popover.d.ts +0 -3
- package/dist/components/core/Tabs/test-tabs.d.ts +0 -3
- package/dist/components/core/Tree/TreeIcon.d.ts +0 -3
- package/dist/components/core/Tree/TreeNode.d.ts +0 -6
- package/dist/components/forms/Input/Input.AdvancedStories.d.ts +0 -13
- package/dist/node_modules/framer-motion/dist/es/animation/hooks/animation-controls.js +0 -80
- package/dist/node_modules/framer-motion/dist/es/animation/hooks/use-animation.js +0 -41
package/README.md
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Flikkui
|
|
2
|
+
|
|
3
|
+
A modern React component library built with TypeScript, Tailwind CSS v4, and optional Framer Motion animations. Follows the shadcn philosophy where users can override any styling using className props while getting sensible defaults out of the box.
|
|
4
|
+
|
|
5
|
+
## 🚀 Quick Start
|
|
6
|
+
|
|
7
|
+
### 1. Install the package
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install flikkui@beta motion
|
|
11
|
+
# or
|
|
12
|
+
yarn add flikkui@beta motion
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### 2. Download the theme file
|
|
16
|
+
|
|
17
|
+
Download the theme file from [flikkui.dev/theme](https://flikkui.dev/theme) and save it as `flikkui-theme.css` in your project root.
|
|
18
|
+
|
|
19
|
+
Alternatively, you can copy this file: [flikkui-theme.css](./flikkui-theme.css)
|
|
20
|
+
|
|
21
|
+
### 3. Import the theme in your app
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
// In your main App.tsx, index.tsx, or _app.tsx
|
|
25
|
+
import './flikkui-theme.css' // Import the downloaded theme file
|
|
26
|
+
import App from './App'
|
|
27
|
+
|
|
28
|
+
// Your app code...
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### 4. Start using components
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
import { Button } from 'flikkui'
|
|
35
|
+
|
|
36
|
+
export function MyComponent() {
|
|
37
|
+
return (
|
|
38
|
+
<Button variant="primary">
|
|
39
|
+
Hello World
|
|
40
|
+
</Button>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## 🎨 Customization
|
|
46
|
+
|
|
47
|
+
Edit the `flikkui-theme.css` file to customize your design system:
|
|
48
|
+
|
|
49
|
+
```css
|
|
50
|
+
/* flikkui-theme.css */
|
|
51
|
+
@theme {
|
|
52
|
+
/* Change primary color */
|
|
53
|
+
--color-primary-base: oklch(0.666 0.223 48.717); /* Orange */
|
|
54
|
+
--color-primary-600: oklch(0.666 0.223 48.717);
|
|
55
|
+
--color-primary-700: oklch(0.555 0.192 47.355);
|
|
56
|
+
|
|
57
|
+
/* Larger buttons */
|
|
58
|
+
--button-min-h-md: 3rem;
|
|
59
|
+
--button-px-md: 1.25rem;
|
|
60
|
+
|
|
61
|
+
/* More rounded design */
|
|
62
|
+
--form-rounded: 1rem;
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
You can also override styles using className props (shadcn approach):
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
<Button className="bg-purple-600 hover:bg-purple-700 rounded-full">
|
|
70
|
+
Custom Button
|
|
71
|
+
</Button>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## 📚 Components
|
|
75
|
+
|
|
76
|
+
### Core Components
|
|
77
|
+
- **Button** - Multiple variants, states, optional animations
|
|
78
|
+
- **Avatar** - Image handling, fallbacks, status indicators
|
|
79
|
+
- **AvatarGroup** - Overlapping avatars with compound component pattern
|
|
80
|
+
- **Badge** - Variants, sizes, content flexibility
|
|
81
|
+
- **Accordion** - Compound component with animations
|
|
82
|
+
- **Modal** - Compound component with header, body, footer
|
|
83
|
+
- **Drawer** - Slide-out panels from edges
|
|
84
|
+
- **Popover** - Compound with portal rendering
|
|
85
|
+
- **Tooltip** - Positioning, animations, accessibility
|
|
86
|
+
- **Tabs** - Horizontal tabbed interface
|
|
87
|
+
|
|
88
|
+
### Form Components
|
|
89
|
+
- **Input** - Multiple types, masking, validation
|
|
90
|
+
- **Select** - Searchable, compound pattern
|
|
91
|
+
- **Checkbox** - Custom styling, controlled/uncontrolled
|
|
92
|
+
- **Radio** - Group management
|
|
93
|
+
- **Switch** - Toggle functionality
|
|
94
|
+
- **Textarea** - Resizable, validation
|
|
95
|
+
|
|
96
|
+
### Data Display
|
|
97
|
+
- **Table** - Dual API, sorting, filtering, selection
|
|
98
|
+
- **Spinner** - Loading states, sizes
|
|
99
|
+
|
|
100
|
+
### Charts
|
|
101
|
+
- **AreaChart** - Stacked, curved, null value handling
|
|
102
|
+
- **BarChart** - Horizontal/vertical, grouped, stacked
|
|
103
|
+
- **LineChart** - Multiple series, curved lines
|
|
104
|
+
- **DonutChart** - Progress, animations, gradients
|
|
105
|
+
- **Heatmap** - Interactive, customizable intensity
|
|
106
|
+
|
|
107
|
+
## 🔄 Migration from v0.1.0-beta.3
|
|
108
|
+
|
|
109
|
+
If you were using the previous version, update your imports:
|
|
110
|
+
|
|
111
|
+
```tsx
|
|
112
|
+
// Old (v0.1.0-beta.3)
|
|
113
|
+
import 'flikkui/styles.css'
|
|
114
|
+
|
|
115
|
+
// New (v0.1.0-beta.4+)
|
|
116
|
+
import './flikkui-theme.css' // Download this file first
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
This change gives you:
|
|
120
|
+
- ✅ 100% predictable styling
|
|
121
|
+
- ✅ Full control over your design system
|
|
122
|
+
- ✅ No more CSS cascade conflicts
|
|
123
|
+
- ✅ Easy theme customization
|
|
124
|
+
|
|
125
|
+
## 💡 Philosophy
|
|
126
|
+
|
|
127
|
+
Flikkui follows the **shadcn approach**:
|
|
128
|
+
- Components provide sensible defaults
|
|
129
|
+
- **className overrides always take precedence**
|
|
130
|
+
- Full TypeScript support with excellent DX
|
|
131
|
+
- Copy-paste friendly - customize anything
|
|
132
|
+
- CSS variables for consistent theming
|
|
133
|
+
|
|
134
|
+
## 🛠️ Tech Stack
|
|
135
|
+
|
|
136
|
+
- **React 18** with TypeScript (strict mode)
|
|
137
|
+
- **Tailwind CSS v4** with CSS variables
|
|
138
|
+
- **Framer Motion** (optional, for enhanced components)
|
|
139
|
+
- **Accessibility-first** - WCAG 2.1 AA compliance built-in
|
|
140
|
+
|
|
141
|
+
## 📖 Documentation
|
|
142
|
+
|
|
143
|
+
Visit [flikkui.dev](https://flikkui.dev) for:
|
|
144
|
+
- Component API documentation
|
|
145
|
+
- Interactive examples
|
|
146
|
+
- Theme customization guide
|
|
147
|
+
- Migration guides
|
|
148
|
+
|
|
149
|
+
## 📄 License
|
|
150
|
+
|
|
151
|
+
MIT
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
Made with ❤️ by [Espranza Innovations](https://espranza.net)
|
|
@@ -4,6 +4,7 @@ export { LineChart } from './LineChart';
|
|
|
4
4
|
export { AreaChart } from './AreaChart';
|
|
5
5
|
export { Heatmap } from './Heatmap';
|
|
6
6
|
export { ChartTooltip } from './shared/ChartTooltip';
|
|
7
|
+
export { ChartLegend, ChartLegendContent } from './shared/ChartLegend';
|
|
7
8
|
export { XAxis, YAxis } from './shared/ChartAxis';
|
|
8
9
|
export { ChartText } from './shared/ChartText';
|
|
9
10
|
export { ChartMarker } from './shared/ChartMarker';
|
|
@@ -17,6 +18,7 @@ export { generateColorPalette, getContrastColor } from './utils/color-utils';
|
|
|
17
18
|
export { processHeatmapData, calculateIntensity, createGridMatrix, getDefaultTooltipContent, formatAxisLabel, generateSampleData } from './Heatmap/utils/heatmapUtils';
|
|
18
19
|
export type { ChartDataPoint, ChartConfig, ChartVariant, CurveType, BaseChartProps, StandardChartDisplayProps, StandardVisualProps, BarChartSpecificProps, StandardAxisConfig, ChartThemeOverrides, CHART_DEFAULTS, } from './types/chart.types';
|
|
19
20
|
export type { ChartTooltipProps, ChartTooltipContentProps, } from './shared/ChartTooltip/ChartTooltip.types';
|
|
21
|
+
export type { ChartLegendProps, ChartLegendContentProps, } from './shared/ChartLegend/ChartLegend.types';
|
|
20
22
|
export type { BaseAxisProps, XAxisProps, YAxisProps, AxisTickProps, } from './shared/ChartAxis/ChartAxis.types';
|
|
21
23
|
export type { ChartTextProps, ChartTextTheme, } from './shared/ChartText/ChartText.types';
|
|
22
24
|
export type { ChartMarkerProps, ChartMarkerTheme, } from './shared/ChartMarker/ChartMarker.types';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ChartLegendProps } from './ChartLegend.types';
|
|
3
|
+
/**
|
|
4
|
+
* Basic ChartLegend component - minimal implementation
|
|
5
|
+
* TODO: Enhance with full legend functionality when needed
|
|
6
|
+
*/
|
|
7
|
+
export declare const ChartLegend: React.FC<ChartLegendProps>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ChartLegendContentProps } from './ChartLegend.types';
|
|
3
|
+
/**
|
|
4
|
+
* Basic ChartLegendContent component - minimal implementation
|
|
5
|
+
* TODO: Enhance with full legend content functionality when needed
|
|
6
|
+
*/
|
|
7
|
+
export declare const ChartLegendContent: React.FC<ChartLegendContentProps>;
|
|
@@ -5,7 +5,7 @@ import { AvatarGroupDirection } from "./AvatarGroup.types";
|
|
|
5
5
|
* Creates a creative sliding and focus effect where hovered avatars scale up
|
|
6
6
|
* while non-hovered avatars slide closer together and fade slightly
|
|
7
7
|
*/
|
|
8
|
-
export declare const getAvatarGroupVariants: (direction?: AvatarGroupDirection, shouldReduceMotion?: boolean | null) => Variants;
|
|
8
|
+
export declare const getAvatarGroupVariants: (direction?: AvatarGroupDirection, shouldReduceMotion?: boolean | null, enableAnimations?: boolean) => Variants;
|
|
9
9
|
/**
|
|
10
10
|
* Determines which animation state to use based on hover index
|
|
11
11
|
*/
|
|
@@ -52,9 +52,9 @@ var Breadcrumbs = function (_a) {
|
|
|
52
52
|
var renderEllipsis = function () {
|
|
53
53
|
if (hiddenItems.length === 0)
|
|
54
54
|
return null;
|
|
55
|
-
return (React__default.createElement(Popover, { isOpen: isEllipsisOpen, onOpenChange: setIsEllipsisOpen },
|
|
56
|
-
React__default.createElement(Popover.Trigger, {
|
|
57
|
-
React__default.createElement("button", {
|
|
55
|
+
return (React__default.createElement(Popover, { key: "ellipsis", isOpen: isEllipsisOpen, onOpenChange: setIsEllipsisOpen },
|
|
56
|
+
React__default.createElement(Popover.Trigger, { className: cn(theme.ellipsis), "aria-label": "Show ".concat(hiddenItems.length, " hidden breadcrumb items"), "aria-expanded": isEllipsisOpen },
|
|
57
|
+
React__default.createElement("button", { type: "button" }, "...")),
|
|
58
58
|
React__default.createElement(Popover.Content, { className: "p-2 min-w-48" },
|
|
59
59
|
React__default.createElement("div", { className: "space-y-1" }, hiddenItems.map(function (item, index) { return (React__default.createElement("div", { key: "hidden-".concat(index), className: "block" }, item.href ? (React__default.createElement("a", { href: item.href, className: cn("block px-2 py-1 text-sm rounded hover:bg-neutral-100 transition-colors", theme.link), onClick: function () { return setIsEllipsisOpen(false); } },
|
|
60
60
|
showIcons && item.icon && (React__default.createElement("span", { className: cn(theme.icon) }, item.icon)),
|
|
@@ -64,13 +64,14 @@ var Breadcrumbs = function (_a) {
|
|
|
64
64
|
};
|
|
65
65
|
// Build the breadcrumb elements
|
|
66
66
|
var breadcrumbElements = [];
|
|
67
|
+
var separatorIndex = 0; // Unique separator counter
|
|
67
68
|
if (shouldCollapse) {
|
|
68
69
|
// Add first item
|
|
69
70
|
breadcrumbElements.push(renderItem(visibleItems[0], 0, false));
|
|
70
|
-
breadcrumbElements.push(renderSeparator(
|
|
71
|
+
breadcrumbElements.push(renderSeparator(separatorIndex++));
|
|
71
72
|
// Add ellipsis
|
|
72
73
|
breadcrumbElements.push(renderEllipsis());
|
|
73
|
-
breadcrumbElements.push(renderSeparator(
|
|
74
|
+
breadcrumbElements.push(renderSeparator(separatorIndex++));
|
|
74
75
|
// Add last two items
|
|
75
76
|
var lastTwoItems_1 = visibleItems.slice(1);
|
|
76
77
|
lastTwoItems_1.forEach(function (item, index) {
|
|
@@ -78,7 +79,7 @@ var Breadcrumbs = function (_a) {
|
|
|
78
79
|
var isLast = actualIndex === lastTwoItems_1.length;
|
|
79
80
|
breadcrumbElements.push(renderItem(item, actualIndex, isLast));
|
|
80
81
|
if (!isLast) {
|
|
81
|
-
breadcrumbElements.push(renderSeparator(
|
|
82
|
+
breadcrumbElements.push(renderSeparator(separatorIndex++));
|
|
82
83
|
}
|
|
83
84
|
});
|
|
84
85
|
}
|
|
@@ -88,7 +89,7 @@ var Breadcrumbs = function (_a) {
|
|
|
88
89
|
var isLast = index === visibleItems.length - 1;
|
|
89
90
|
breadcrumbElements.push(renderItem(item, index, isLast));
|
|
90
91
|
if (!isLast) {
|
|
91
|
-
breadcrumbElements.push(renderSeparator(
|
|
92
|
+
breadcrumbElements.push(renderSeparator(separatorIndex++));
|
|
92
93
|
}
|
|
93
94
|
});
|
|
94
95
|
}
|
|
@@ -3,15 +3,3 @@ import { Variants } from "motion/react";
|
|
|
3
3
|
* Get button animation variants based on reduced motion preference
|
|
4
4
|
*/
|
|
5
5
|
export declare const getButtonVariants: (shouldReduceMotion: boolean | null) => Variants | undefined;
|
|
6
|
-
/**
|
|
7
|
-
* Get shake animation for error state
|
|
8
|
-
*/
|
|
9
|
-
export declare const getShakeAnimation: (shouldReduceMotion: boolean | null) => {
|
|
10
|
-
x: number | number[];
|
|
11
|
-
transition: {
|
|
12
|
-
duration: number;
|
|
13
|
-
times: number[];
|
|
14
|
-
restSpeed: number;
|
|
15
|
-
restDelta: number;
|
|
16
|
-
};
|
|
17
|
-
};
|
|
@@ -8,28 +8,13 @@ var getButtonVariants = function (shouldReduceMotion) {
|
|
|
8
8
|
tap: {
|
|
9
9
|
scale: 0.95,
|
|
10
10
|
transition: {
|
|
11
|
-
duration: 0.
|
|
11
|
+
duration: 0.1,
|
|
12
12
|
type: "spring",
|
|
13
|
-
stiffness:
|
|
14
|
-
damping:
|
|
13
|
+
stiffness: 400,
|
|
14
|
+
damping: 10,
|
|
15
15
|
},
|
|
16
16
|
},
|
|
17
17
|
};
|
|
18
18
|
};
|
|
19
|
-
/**
|
|
20
|
-
* Get shake animation for error state
|
|
21
|
-
*/
|
|
22
|
-
var getShakeAnimation = function (shouldReduceMotion) { return ({
|
|
23
|
-
x: (shouldReduceMotion !== null && shouldReduceMotion !== void 0 ? shouldReduceMotion : false)
|
|
24
|
-
? 0
|
|
25
|
-
: [0, -20, 20, -16, 16, -8, 8, -4, 4, 0],
|
|
26
|
-
transition: {
|
|
27
|
-
duration: 0.4,
|
|
28
|
-
times: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 1.0],
|
|
29
|
-
// Add a flag to prevent AbortError propagation
|
|
30
|
-
restSpeed: 0.01,
|
|
31
|
-
restDelta: 0.01,
|
|
32
|
-
},
|
|
33
|
-
}); };
|
|
34
19
|
|
|
35
|
-
export { getButtonVariants
|
|
20
|
+
export { getButtonVariants };
|
|
@@ -1,40 +1,32 @@
|
|
|
1
1
|
import { __rest, __assign } from '../../../node_modules/tslib/tslib.es6.js';
|
|
2
|
-
import React__default, { useMemo,
|
|
3
|
-
import {
|
|
2
|
+
import React__default, { useMemo, useCallback } from 'react';
|
|
3
|
+
import { getButtonVariants } from './Button.animations.js';
|
|
4
4
|
import { buttonTheme } from './Button.theme.js';
|
|
5
5
|
import { cn } from '../../../utils/cn.js';
|
|
6
6
|
import { useReducedMotion } from '../../../node_modules/framer-motion/dist/es/utils/reduced-motion/use-reduced-motion.js';
|
|
7
|
-
import { useAnimation } from '../../../node_modules/framer-motion/dist/es/animation/hooks/use-animation.js';
|
|
8
7
|
import { motion } from '../../../node_modules/framer-motion/dist/es/render/components/motion/proxy.js';
|
|
9
8
|
|
|
10
9
|
var Button = React__default.forwardRef(function (_a, ref) {
|
|
11
|
-
var _b, _c, _d, _e, _f;
|
|
12
|
-
var children = _a.children, _g = _a.className, className = _g === void 0 ? "" : _g, _h = _a.iconOnly, iconOnly = _h === void 0 ? false : _h, _j = _a.state, state = _j === void 0 ? "default" : _j, _k = _a.size, size = _k === void 0 ? "md" : _k, _l = _a.variant, variant = _l === void 0 ? "primary" : _l, _m = _a.block, block = _m === void 0 ? false : _m, onClick = _a.onClick, props = __rest(_a, ["children", "className", "iconOnly", "state", "size", "variant", "block", "onClick"]);
|
|
10
|
+
var children = _a.children, _b = _a.className, className = _b === void 0 ? "" : _b, _c = _a.iconOnly, iconOnly = _c === void 0 ? false : _c, _d = _a.state, state = _d === void 0 ? "default" : _d, _e = _a.size, size = _e === void 0 ? "md" : _e, _f = _a.variant, variant = _f === void 0 ? "primary" : _f, _g = _a.block, block = _g === void 0 ? false : _g, onClick = _a.onClick, props = __rest(_a, ["children", "className", "iconOnly", "state", "size", "variant", "block", "onClick"]);
|
|
13
11
|
var shouldReduceMotion = useReducedMotion();
|
|
14
|
-
|
|
12
|
+
// Check if we're in Storybook and should disable animations
|
|
13
|
+
var isInStorybook = typeof window !== 'undefined' && window.__STORYBOOK_DISABLE_ANIMATIONS__;
|
|
14
|
+
var shouldDisableAnimations = !!shouldReduceMotion || isInStorybook;
|
|
15
15
|
// Memoize derived state flags for performance
|
|
16
16
|
var derivedState = useMemo(function () { return ({
|
|
17
17
|
isDisabled: state === "disabled",
|
|
18
18
|
isError: state === "error",
|
|
19
19
|
}); }, [state]);
|
|
20
20
|
var isDisabled = derivedState.isDisabled, isError = derivedState.isError;
|
|
21
|
-
//
|
|
22
|
-
var buttonVariants = getButtonVariants(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
controls.set({ x: 0 });
|
|
29
|
-
// Use a timeout to prevent race conditions in Storybook
|
|
30
|
-
var timer_1 = setTimeout(function () {
|
|
31
|
-
controls.start(shakeAnimation).catch(function () {
|
|
32
|
-
// Silently catch animation interruption errors
|
|
33
|
-
});
|
|
34
|
-
}, 10);
|
|
35
|
-
return function () { return clearTimeout(timer_1); };
|
|
21
|
+
// Compute variants without a global cache (HMR-safe)
|
|
22
|
+
var buttonVariants = useMemo(function () { return getButtonVariants(shouldDisableAnimations); }, [shouldDisableAnimations]);
|
|
23
|
+
// Dev-time a11y warning for iconOnly buttons without aria-label
|
|
24
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
25
|
+
if (iconOnly && !props["aria-label"]) {
|
|
26
|
+
// eslint-disable-next-line no-console
|
|
27
|
+
console.warn("Button(iconOnly) requires 'aria-label' for accessibility.");
|
|
36
28
|
}
|
|
37
|
-
}
|
|
29
|
+
}
|
|
38
30
|
// Safe onClick handler
|
|
39
31
|
var handleClick = useCallback(function (event) {
|
|
40
32
|
if (isDisabled)
|
|
@@ -43,27 +35,38 @@ var Button = React__default.forwardRef(function (_a, ref) {
|
|
|
43
35
|
onClick === null || onClick === void 0 ? void 0 : onClick(event);
|
|
44
36
|
}
|
|
45
37
|
catch (error) {
|
|
38
|
+
// eslint-disable-next-line no-console
|
|
46
39
|
console.error("Error in button click handler:", error);
|
|
47
40
|
}
|
|
48
41
|
}, [onClick, isDisabled]);
|
|
49
|
-
//
|
|
50
|
-
var
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
42
|
+
// Memoize theme classes to prevent recalculation on every render
|
|
43
|
+
var themeClasses = useMemo(function () {
|
|
44
|
+
var _a, _b, _c, _d, _e;
|
|
45
|
+
var sizeClasses = ((_b = (_a = buttonTheme.sizes) === null || _a === void 0 ? void 0 : _a[size]) === null || _b === void 0 ? void 0 : _b[iconOnly ? "iconOnly" : "default"]) || "";
|
|
46
|
+
var variantClasses = ((_c = buttonTheme.variants) === null || _c === void 0 ? void 0 : _c[variant]) || "";
|
|
47
|
+
var stateClasses = isDisabled ? (((_d = buttonTheme.states) === null || _d === void 0 ? void 0 : _d.disabled) || "") :
|
|
48
|
+
isError ? (((_e = buttonTheme.states) === null || _e === void 0 ? void 0 : _e.error) || "") : "";
|
|
49
|
+
return {
|
|
50
|
+
sizeClasses: sizeClasses,
|
|
51
|
+
variantClasses: variantClasses,
|
|
52
|
+
stateClasses: stateClasses,
|
|
53
|
+
blockStyle: block ? buttonTheme.blockStyle : "",
|
|
54
|
+
};
|
|
55
|
+
}, [size, iconOnly, variant, isDisabled, isError, block]);
|
|
56
|
+
// Generate default aria-label for icon-only buttons if not provided (fallback only)
|
|
55
57
|
var ariaLabel = iconOnly && !props["aria-label"] ? "Button" : props["aria-label"];
|
|
58
|
+
// Determine animation props (user props will override due to spread order)
|
|
59
|
+
var animationProps = shouldDisableAnimations ? {} : {
|
|
60
|
+
whileTap: !isDisabled ? "tap" : undefined,
|
|
61
|
+
variants: buttonVariants,
|
|
62
|
+
};
|
|
56
63
|
return (React__default.createElement(motion.button, __assign({ ref: ref, type: "button", className: cn("relative", // Base class
|
|
57
|
-
buttonTheme.baseStyle, variantClasses, sizeClasses,
|
|
58
|
-
), disabled: isDisabled, "data-state": state, "data-variant": variant, "data-size": size, "data-icon-only": iconOnly ? "true" : "false", "data-block": block ? "true" : "false",
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
left: "1px",
|
|
62
|
-
right: "1px",
|
|
63
|
-
bottom: "1px",
|
|
64
|
-
borderRadius: "inherit",
|
|
64
|
+
buttonTheme.baseStyle, themeClasses.variantClasses, themeClasses.sizeClasses, themeClasses.blockStyle, themeClasses.stateClasses, className // User overrides take precedence
|
|
65
|
+
), disabled: isDisabled, "data-state": state, "data-variant": variant, "data-size": size, "data-icon-only": iconOnly ? "true" : "false", "data-block": block ? "true" : "false", "aria-disabled": isDisabled || undefined, "aria-invalid": isError || undefined, "aria-label": ariaLabel, "aria-describedby": undefined, onClick: handleClick }, animationProps, props),
|
|
66
|
+
React__default.createElement("div", { className: "absolute pointer-events-none top-px left-px right-px h-3 rounded-inherit bg-gradient-to-b from-white/15 via-transparent to-transparent", style: {
|
|
67
|
+
borderRadius: "calc(var(--button-rounded) - 2px)",
|
|
65
68
|
boxShadow: buttonTheme.highlightShadow,
|
|
66
|
-
} })
|
|
69
|
+
} }),
|
|
67
70
|
children));
|
|
68
71
|
});
|
|
69
72
|
// Set display name for dev tools and Storybook
|
|
@@ -12,10 +12,6 @@ interface ButtonTheme {
|
|
|
12
12
|
states: Partial<Record<ButtonState, string>>;
|
|
13
13
|
blockStyle: string;
|
|
14
14
|
highlightShadow: string;
|
|
15
|
-
animations: {
|
|
16
|
-
springTransition: string;
|
|
17
|
-
bounceTransition: string;
|
|
18
|
-
};
|
|
19
15
|
}
|
|
20
16
|
/**
|
|
21
17
|
* Default theme for the Button component
|
|
@@ -6,25 +6,29 @@ 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-base text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 border
|
|
10
|
-
secondary: "bg-white text-
|
|
11
|
-
ghost: "bg-neutral-50 text-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
primary: "bg-primary-base text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 border border-primary-700 hover:bg-primary-700 hover:ring-2 hover:ring-primary-base/40 hover:border-primary-600 hover:shadow-xl hover:shadow-primary-base/20",
|
|
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
|
+
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
|
+
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",
|
|
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-base text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-warning-600 border border-warning-700 hover:bg-warning-600 hover:ring-2 hover:ring-warning-base/40 hover:border-warning-700 hover:shadow-xl hover:shadow-warning-base/20",
|
|
16
|
+
danger: "bg-danger-base text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-danger-600 border border-danger-700 hover:bg-danger-600 hover:ring-2 hover:ring-danger-base/40 hover:border-danger-700 hover:shadow-xl hover:shadow-danger-base/20",
|
|
17
|
+
success: "bg-success-base text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-success-600 border border-success-600 hover:bg-success-600 hover:ring-2 hover:ring-success-base/30 hover:border-success-base hover:shadow-xl hover:shadow-success-base/20",
|
|
14
18
|
},
|
|
15
19
|
// Size variants
|
|
16
20
|
sizes: {
|
|
17
21
|
sm: {
|
|
18
22
|
default: "min-h-[var(--button-min-h-sm)] px-[var(--button-px-sm)] py-[var(--button-py-sm)] text-sm",
|
|
19
|
-
iconOnly: "
|
|
23
|
+
iconOnly: "size-[var(--button-icon-size-sm)] p-[var(--button-icon-p-sm)]",
|
|
20
24
|
},
|
|
21
25
|
md: {
|
|
22
26
|
default: "min-h-[var(--button-min-h-md)] px-[var(--button-px-md)] py-[var(--button-py-md)] text-sm",
|
|
23
|
-
iconOnly: "
|
|
27
|
+
iconOnly: "size-[var(--button-icon-size-md)] p-[var(--button-icon-p-md)]",
|
|
24
28
|
},
|
|
25
29
|
lg: {
|
|
26
30
|
default: "min-h-[var(--button-min-h-lg)] px-[var(--button-px-lg)] py-[var(--button-py-lg)] text-base",
|
|
27
|
-
iconOnly: "
|
|
31
|
+
iconOnly: "size-[var(--button-icon-size-lg)] p-[var(--button-icon-p-lg)]",
|
|
28
32
|
},
|
|
29
33
|
},
|
|
30
34
|
// State styles
|
|
@@ -36,6 +40,7 @@ var buttonTheme = {
|
|
|
36
40
|
// Block style
|
|
37
41
|
blockStyle: "w-full",
|
|
38
42
|
// Highlight shadow for primary variant - moved from hardcoded inline style
|
|
39
|
-
highlightShadow: "inset 0 .75px .25px 0 rgba(255, 255, 255, 0.25)"
|
|
43
|
+
highlightShadow: "inset 0 .75px .25px 0 rgba(255, 255, 255, 0.25)",
|
|
44
|
+
};
|
|
40
45
|
|
|
41
46
|
export { buttonTheme };
|
|
@@ -24,6 +24,6 @@ export interface ButtonProps extends HTMLMotionProps<"button"> {
|
|
|
24
24
|
/** Additional class names */
|
|
25
25
|
className?: string;
|
|
26
26
|
}
|
|
27
|
-
export type ButtonVariant = "primary" | "secondary" | "ghost" | "link" | "clear";
|
|
27
|
+
export type ButtonVariant = "primary" | "secondary" | "ghost" | "link" | "clear" | "outline" | "warning" | "danger" | "success";
|
|
28
28
|
export type ButtonSize = "sm" | "md" | "lg";
|
|
29
29
|
export type ButtonState = "default" | "disabled" | "error";
|
|
@@ -4,13 +4,19 @@ export interface DividerTheme {
|
|
|
4
4
|
baseStyle: string;
|
|
5
5
|
horizontal: string;
|
|
6
6
|
vertical: string;
|
|
7
|
-
margins:
|
|
7
|
+
margins: {
|
|
8
|
+
horizontal: Record<DividerMargin, string>;
|
|
9
|
+
vertical: Record<DividerMargin, string>;
|
|
10
|
+
};
|
|
8
11
|
}
|
|
9
12
|
export interface DividerThemeOverrides {
|
|
10
13
|
baseStyle?: string;
|
|
11
14
|
horizontal?: string;
|
|
12
15
|
vertical?: string;
|
|
13
|
-
margins?:
|
|
16
|
+
margins?: {
|
|
17
|
+
horizontal?: Partial<Record<DividerMargin, string>>;
|
|
18
|
+
vertical?: Partial<Record<DividerMargin, string>>;
|
|
19
|
+
};
|
|
14
20
|
}
|
|
15
21
|
export interface DividerProps extends HTMLAttributes<HTMLDivElement> {
|
|
16
22
|
/**
|
|
@@ -29,7 +29,7 @@ export interface DrawerContextValue {
|
|
|
29
29
|
showCloseButton: boolean;
|
|
30
30
|
theme: DrawerTheme;
|
|
31
31
|
}
|
|
32
|
-
export interface DrawerProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onClose'> {
|
|
32
|
+
export interface DrawerProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onClose' | 'onAnimationStart' | 'onDragStart'> {
|
|
33
33
|
isOpen: boolean;
|
|
34
34
|
onClose: () => void;
|
|
35
35
|
position?: DrawerPosition;
|
|
@@ -27,7 +27,7 @@ export interface ModalContextValue {
|
|
|
27
27
|
showCloseButton: boolean;
|
|
28
28
|
theme: ModalTheme;
|
|
29
29
|
}
|
|
30
|
-
export interface ModalProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onClose'> {
|
|
30
|
+
export interface ModalProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onClose' | 'onAnimationStart' | 'onDragStart'> {
|
|
31
31
|
isOpen: boolean;
|
|
32
32
|
onClose: () => void;
|
|
33
33
|
size?: ModalSize;
|
|
@@ -8,10 +8,6 @@ import React from "react";
|
|
|
8
8
|
* @property {boolean} showFirstLast - Whether to show first/last page buttons
|
|
9
9
|
* @property {boolean} showPrevNext - Whether to show previous/next buttons
|
|
10
10
|
* @property {number} siblingCount - Number of sibling pages to show around current page
|
|
11
|
-
* @property {string} previousLabel - Label for previous button
|
|
12
|
-
* @property {string} nextLabel - Label for next button
|
|
13
|
-
* @property {string} firstLabel - Label for first page button
|
|
14
|
-
* @property {string} lastLabel - Label for last page button
|
|
15
11
|
*/
|
|
16
12
|
export interface PaginationProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
17
13
|
/** The current active page number (1-based) */
|
|
@@ -28,18 +24,34 @@ export interface PaginationProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
28
24
|
showPrevNext?: boolean;
|
|
29
25
|
/** Number of sibling pages to show around current page */
|
|
30
26
|
siblingCount?: number;
|
|
31
|
-
/** Label for previous button */
|
|
32
|
-
previousLabel?: string;
|
|
33
|
-
/** Label for next button */
|
|
34
|
-
nextLabel?: string;
|
|
35
|
-
/** Label for first page button */
|
|
36
|
-
firstLabel?: string;
|
|
37
|
-
/** Label for last page button */
|
|
38
|
-
lastLabel?: string;
|
|
39
27
|
/** Additional class names */
|
|
40
28
|
className?: string;
|
|
29
|
+
/** Theme overrides */
|
|
30
|
+
theme?: PaginationThemeOverrides;
|
|
31
|
+
}
|
|
32
|
+
export type PaginationSize = "sm" | "md";
|
|
33
|
+
/**
|
|
34
|
+
* Theme overrides for the Pagination component
|
|
35
|
+
*/
|
|
36
|
+
export interface PaginationThemeOverrides {
|
|
37
|
+
/** Base container styles */
|
|
38
|
+
baseStyle?: string;
|
|
39
|
+
/** Base item styles */
|
|
40
|
+
itemBase?: string;
|
|
41
|
+
/** Variant styles */
|
|
42
|
+
variants?: {
|
|
43
|
+
page?: string;
|
|
44
|
+
ellipsis?: string;
|
|
45
|
+
};
|
|
46
|
+
/** Size variants */
|
|
47
|
+
sizes?: Partial<Record<PaginationSize, string>>;
|
|
48
|
+
/** State styles */
|
|
49
|
+
states?: {
|
|
50
|
+
active?: string;
|
|
51
|
+
disabled?: string;
|
|
52
|
+
hover?: string;
|
|
53
|
+
};
|
|
41
54
|
}
|
|
42
|
-
export type PaginationSize = "sm" | "md" | "lg";
|
|
43
55
|
/**
|
|
44
56
|
* Internal pagination item props
|
|
45
57
|
*/
|
|
@@ -1,5 +1,36 @@
|
|
|
1
|
-
import { Variants } from 'motion/react';
|
|
2
1
|
/**
|
|
3
|
-
*
|
|
2
|
+
* Animation variants for Popover component
|
|
4
3
|
*/
|
|
5
|
-
export declare const
|
|
4
|
+
export declare const popoverContentVariants: {
|
|
5
|
+
hidden: {
|
|
6
|
+
opacity: number;
|
|
7
|
+
scale: number;
|
|
8
|
+
};
|
|
9
|
+
visible: {
|
|
10
|
+
opacity: number;
|
|
11
|
+
scale: number;
|
|
12
|
+
};
|
|
13
|
+
exit: {
|
|
14
|
+
opacity: number;
|
|
15
|
+
scale: number;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
export declare const popoverBackdropVariants: {
|
|
19
|
+
hidden: {
|
|
20
|
+
opacity: number;
|
|
21
|
+
};
|
|
22
|
+
visible: {
|
|
23
|
+
opacity: number;
|
|
24
|
+
};
|
|
25
|
+
exit: {
|
|
26
|
+
opacity: number;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
export declare const popoverTransitions: {
|
|
30
|
+
content: {
|
|
31
|
+
duration: number;
|
|
32
|
+
};
|
|
33
|
+
backdrop: {
|
|
34
|
+
duration: number;
|
|
35
|
+
};
|
|
36
|
+
};
|