@moontra/moonui-pro 2.0.22 → 2.1.0
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/index.mjs +215 -214
- package/package.json +4 -2
- package/src/__tests__/use-intersection-observer.test.tsx +216 -0
- package/src/__tests__/use-local-storage.test.tsx +174 -0
- package/src/__tests__/use-pro-access.test.tsx +183 -0
- package/src/components/advanced-chart/advanced-chart.test.tsx +281 -0
- package/src/components/advanced-chart/index.tsx +412 -0
- package/src/components/advanced-forms/index.tsx +431 -0
- package/src/components/animated-button/index.tsx +202 -0
- package/src/components/calendar/event-dialog.tsx +372 -0
- package/src/components/calendar/index.tsx +557 -0
- package/src/components/color-picker/index.tsx +434 -0
- package/src/components/dashboard/index.tsx +334 -0
- package/src/components/data-table/data-table.test.tsx +187 -0
- package/src/components/data-table/index.tsx +368 -0
- package/src/components/draggable-list/index.tsx +100 -0
- package/src/components/enhanced/button.tsx +360 -0
- package/src/components/enhanced/card.tsx +272 -0
- package/src/components/enhanced/dialog.tsx +248 -0
- package/src/components/enhanced/index.ts +3 -0
- package/src/components/error-boundary/index.tsx +111 -0
- package/src/components/file-upload/file-upload.test.tsx +242 -0
- package/src/components/file-upload/index.tsx +362 -0
- package/src/components/floating-action-button/index.tsx +209 -0
- package/src/components/github-stars/index.tsx +414 -0
- package/src/components/health-check/index.tsx +441 -0
- package/src/components/hover-card-3d/index.tsx +170 -0
- package/src/components/index.ts +76 -0
- package/src/components/kanban/index.tsx +436 -0
- package/src/components/lazy-component/index.tsx +342 -0
- package/src/components/magnetic-button/index.tsx +170 -0
- package/src/components/memory-efficient-data/index.tsx +352 -0
- package/src/components/optimized-image/index.tsx +427 -0
- package/src/components/performance-debugger/index.tsx +591 -0
- package/src/components/performance-monitor/index.tsx +775 -0
- package/src/components/pinch-zoom/index.tsx +172 -0
- package/src/components/rich-text-editor/index-old-backup.tsx +443 -0
- package/src/components/rich-text-editor/index.tsx +1537 -0
- package/src/components/rich-text-editor/slash-commands-extension.ts +220 -0
- package/src/components/rich-text-editor/slash-commands.css +35 -0
- package/src/components/rich-text-editor/table-styles.css +65 -0
- package/src/components/spotlight-card/index.tsx +194 -0
- package/src/components/swipeable-card/index.tsx +100 -0
- package/src/components/timeline/index.tsx +333 -0
- package/src/components/ui/animated-button.tsx +185 -0
- package/src/components/ui/avatar.tsx +135 -0
- package/src/components/ui/badge.tsx +225 -0
- package/src/components/ui/button.tsx +221 -0
- package/src/components/ui/card.tsx +141 -0
- package/src/components/ui/checkbox.tsx +256 -0
- package/src/components/ui/color-picker.tsx +95 -0
- package/src/components/ui/dialog.tsx +332 -0
- package/src/components/ui/dropdown-menu.tsx +200 -0
- package/src/components/ui/hover-card-3d.tsx +103 -0
- package/src/components/ui/index.ts +33 -0
- package/src/components/ui/input.tsx +219 -0
- package/src/components/ui/label.tsx +26 -0
- package/src/components/ui/magnetic-button.tsx +129 -0
- package/src/components/ui/popover.tsx +183 -0
- package/src/components/ui/select.tsx +273 -0
- package/src/components/ui/separator.tsx +140 -0
- package/src/components/ui/slider.tsx +351 -0
- package/src/components/ui/spotlight-card.tsx +119 -0
- package/src/components/ui/switch.tsx +83 -0
- package/src/components/ui/tabs.tsx +195 -0
- package/src/components/ui/textarea.tsx +25 -0
- package/src/components/ui/toast.tsx +313 -0
- package/src/components/ui/tooltip.tsx +152 -0
- package/src/components/virtual-list/index.tsx +369 -0
- package/src/hooks/use-chart.ts +205 -0
- package/src/hooks/use-data-table.ts +182 -0
- package/src/hooks/use-docs-pro-access.ts +13 -0
- package/src/hooks/use-license-check.ts +65 -0
- package/src/hooks/use-subscription.ts +19 -0
- package/src/index.ts +14 -0
- package/src/lib/micro-interactions.ts +255 -0
- package/src/lib/utils.ts +6 -0
- package/src/patterns/login-form/index.tsx +276 -0
- package/src/patterns/login-form/types.ts +67 -0
- package/src/setupTests.ts +41 -0
- package/src/styles/design-system.css +365 -0
- package/src/styles/index.css +4 -0
- package/src/styles/tailwind.css +6 -0
- package/src/styles/tokens.css +453 -0
- package/src/types/moonui.d.ts +22 -0
- package/src/use-intersection-observer.tsx +154 -0
- package/src/use-local-storage.tsx +71 -0
- package/src/use-paddle.ts +138 -0
- package/src/use-performance-optimizer.ts +379 -0
- package/src/use-pro-access.ts +141 -0
- package/src/use-scroll-animation.ts +221 -0
- package/src/use-subscription.ts +37 -0
- package/src/use-toast.ts +32 -0
- package/src/utils/chart-helpers.ts +257 -0
- package/src/utils/cn.ts +69 -0
- package/src/utils/data-processing.ts +151 -0
- package/src/utils/license-guard.tsx +177 -0
- package/src/utils/license-validator.tsx +183 -0
- package/src/utils/package-guard.ts +60 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
+
import { cn } from "../../lib/utils";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Premium Badge Component
|
|
7
|
+
*
|
|
8
|
+
* Durum, kategori ve etiketleme için yüksek kaliteli badge bileşeni.
|
|
9
|
+
* Dark ve light modda uyumlu, erişilebilir ve çeşitli varyantlar sunar.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const badgeVariants = cva(
|
|
13
|
+
["inline-flex items-center gap-1.5",
|
|
14
|
+
"font-medium transition-colors duration-200",
|
|
15
|
+
"border focus:outline-none",
|
|
16
|
+
"focus-visible:ring-2 focus-visible:ring-offset-1"],
|
|
17
|
+
{
|
|
18
|
+
variants: {
|
|
19
|
+
variant: {
|
|
20
|
+
primary: [
|
|
21
|
+
"border-transparent bg-primary text-primary-foreground",
|
|
22
|
+
"hover:bg-primary-hover dark:hover:bg-primary/90",
|
|
23
|
+
"focus-visible:ring-primary/30 dark:focus-visible:ring-primary/40",
|
|
24
|
+
"dark:bg-primary/90 dark:text-white dark:shadow-inner dark:shadow-primary/10",
|
|
25
|
+
],
|
|
26
|
+
secondary: [
|
|
27
|
+
"border-transparent bg-secondary text-secondary-foreground",
|
|
28
|
+
"hover:bg-gray-200 dark:hover:bg-gray-700/90",
|
|
29
|
+
"focus-visible:ring-gray-400/30 dark:focus-visible:ring-gray-500/40",
|
|
30
|
+
"dark:bg-gray-800 dark:text-gray-100 dark:shadow-inner dark:shadow-gray-950/10",
|
|
31
|
+
],
|
|
32
|
+
outline: [
|
|
33
|
+
"border-gray-200 dark:border-gray-700",
|
|
34
|
+
"bg-transparent text-foreground",
|
|
35
|
+
"hover:border-gray-300 dark:hover:border-gray-600",
|
|
36
|
+
"focus-visible:ring-gray-400/30 dark:focus-visible:ring-gray-500/40",
|
|
37
|
+
"dark:text-gray-200 dark:bg-transparent dark:backdrop-blur-sm",
|
|
38
|
+
],
|
|
39
|
+
destructive: [
|
|
40
|
+
"border-transparent bg-error text-white",
|
|
41
|
+
"hover:bg-error/90 dark:hover:bg-error/80",
|
|
42
|
+
"focus-visible:ring-error/30 dark:focus-visible:ring-error/25",
|
|
43
|
+
"dark:bg-error/90 dark:text-white dark:shadow-inner dark:shadow-error/10",
|
|
44
|
+
],
|
|
45
|
+
success: [
|
|
46
|
+
"border-transparent bg-success text-white",
|
|
47
|
+
"hover:bg-success/90 dark:hover:bg-success/80",
|
|
48
|
+
"focus-visible:ring-success/30 dark:focus-visible:ring-success/25",
|
|
49
|
+
"dark:bg-success/90 dark:text-white dark:shadow-inner dark:shadow-success/10",
|
|
50
|
+
],
|
|
51
|
+
warning: [
|
|
52
|
+
"border-transparent bg-warning text-white",
|
|
53
|
+
"hover:bg-warning/90 dark:hover:bg-warning/80",
|
|
54
|
+
"focus-visible:ring-warning/30 dark:focus-visible:ring-warning/25",
|
|
55
|
+
"dark:bg-warning/90 dark:text-gray-900 dark:shadow-inner dark:shadow-warning/10",
|
|
56
|
+
],
|
|
57
|
+
ghost: [
|
|
58
|
+
"border-transparent bg-transparent text-foreground",
|
|
59
|
+
"hover:bg-gray-100 dark:hover:bg-gray-800/80",
|
|
60
|
+
"focus-visible:ring-gray-400/30 dark:focus-visible:ring-gray-500/40",
|
|
61
|
+
"dark:text-gray-200 dark:backdrop-blur-sm",
|
|
62
|
+
"transition-colors duration-200",
|
|
63
|
+
],
|
|
64
|
+
pro: [
|
|
65
|
+
"border-transparent bg-gradient-to-r from-purple-600 to-pink-600 text-white",
|
|
66
|
+
"hover:from-purple-700 hover:to-pink-700",
|
|
67
|
+
"focus-visible:ring-purple-400/30 dark:focus-visible:ring-purple-500/40",
|
|
68
|
+
"shadow-md dark:shadow-lg dark:shadow-purple-500/10",
|
|
69
|
+
],
|
|
70
|
+
admin: [
|
|
71
|
+
"border-transparent bg-gradient-to-r from-purple-600 to-pink-600 text-white",
|
|
72
|
+
"hover:from-purple-700 hover:to-pink-700",
|
|
73
|
+
"focus-visible:ring-purple-400/30 dark:focus-visible:ring-purple-500/40",
|
|
74
|
+
"shadow-md dark:shadow-lg dark:shadow-purple-500/10",
|
|
75
|
+
],
|
|
76
|
+
},
|
|
77
|
+
size: {
|
|
78
|
+
sm: "h-5 px-2 text-xs",
|
|
79
|
+
md: "h-6 px-3 text-sm",
|
|
80
|
+
lg: "h-8 px-4 text-base",
|
|
81
|
+
},
|
|
82
|
+
radius: {
|
|
83
|
+
default: "rounded-full",
|
|
84
|
+
sm: "rounded-md",
|
|
85
|
+
lg: "rounded-xl",
|
|
86
|
+
none: "rounded-none",
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
defaultVariants: {
|
|
90
|
+
variant: "primary",
|
|
91
|
+
size: "md",
|
|
92
|
+
radius: "default",
|
|
93
|
+
},
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
export interface BadgeProps
|
|
98
|
+
extends React.HTMLAttributes<HTMLDivElement>,
|
|
99
|
+
Omit<VariantProps<typeof badgeVariants>, 'variant'> {
|
|
100
|
+
withDot?: boolean;
|
|
101
|
+
dotColor?: string;
|
|
102
|
+
removable?: boolean;
|
|
103
|
+
onRemove?: () => void;
|
|
104
|
+
leftIcon?: React.ReactNode;
|
|
105
|
+
rightIcon?: React.ReactNode;
|
|
106
|
+
variant?: 'primary' | 'secondary' | 'destructive' | 'outline' | 'success' | 'warning' | 'ghost' | 'pro' | 'admin';
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Premium Badge Component
|
|
111
|
+
*
|
|
112
|
+
* @param props - Badge bileşeni özellikleri
|
|
113
|
+
* @param props.variant - Badgenin görsel varyantı
|
|
114
|
+
* @param props.size - Badge boyutu
|
|
115
|
+
* @param props.radius - Köşe yuvarlama stili
|
|
116
|
+
* @param props.withDot - Başında nokta gösterimi
|
|
117
|
+
* @param props.dotColor - Noktanın rengi (özel)
|
|
118
|
+
* @param props.removable - Kaldırılabilir badge (X simgesi ile)
|
|
119
|
+
* @param props.onRemove - Kaldırma işlevi
|
|
120
|
+
* @param props.leftIcon - Badge'in solunda görüntülenecek ikon
|
|
121
|
+
* @param props.rightIcon - Badge'in sağında görüntülenecek ikon
|
|
122
|
+
*/
|
|
123
|
+
function Badge({
|
|
124
|
+
className,
|
|
125
|
+
variant,
|
|
126
|
+
size,
|
|
127
|
+
radius,
|
|
128
|
+
withDot,
|
|
129
|
+
dotColor,
|
|
130
|
+
removable,
|
|
131
|
+
onRemove,
|
|
132
|
+
leftIcon,
|
|
133
|
+
rightIcon,
|
|
134
|
+
children,
|
|
135
|
+
...props
|
|
136
|
+
}: BadgeProps) {
|
|
137
|
+
// Auto-assign icons and content for special variants
|
|
138
|
+
let autoLeftIcon = leftIcon;
|
|
139
|
+
let autoChildren = children;
|
|
140
|
+
|
|
141
|
+
if (variant === 'pro') {
|
|
142
|
+
// Auto Sparkles icon for pro
|
|
143
|
+
autoLeftIcon = leftIcon || (
|
|
144
|
+
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" className="w-3 h-3">
|
|
145
|
+
<path d="M12 0L13.09 8.26L22 9L13.09 9.74L12 18L10.91 9.74L2 9L10.91 8.26L12 0Z" fill="currentColor"/>
|
|
146
|
+
<path d="M19 5L19.5 7L21 7.5L19.5 8L19 10L18.5 8L17 7.5L18.5 7L19 5Z" fill="currentColor"/>
|
|
147
|
+
<path d="M19 15L19.5 17L21 17.5L19.5 18L19 20L18.5 18L17 17.5L18.5 17L19 15Z" fill="currentColor"/>
|
|
148
|
+
</svg>
|
|
149
|
+
);
|
|
150
|
+
autoChildren = children || 'Pro';
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (variant === 'admin') {
|
|
154
|
+
// Auto CheckCircle icon for admin
|
|
155
|
+
autoLeftIcon = leftIcon || (
|
|
156
|
+
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" className="w-3 h-3">
|
|
157
|
+
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" fill="currentColor"/>
|
|
158
|
+
</svg>
|
|
159
|
+
);
|
|
160
|
+
autoChildren = children || 'Admin Pro';
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return (
|
|
164
|
+
<div
|
|
165
|
+
className={cn(badgeVariants({ variant, size, radius }), className)}
|
|
166
|
+
data-removable={removable ? "" : undefined}
|
|
167
|
+
{...props}
|
|
168
|
+
>
|
|
169
|
+
{withDot && (
|
|
170
|
+
<span
|
|
171
|
+
className={cn(
|
|
172
|
+
"h-2 w-2 rounded-full",
|
|
173
|
+
dotColor ||
|
|
174
|
+
(variant === "destructive" ? "bg-white" :
|
|
175
|
+
variant === "success" ? "bg-white" :
|
|
176
|
+
variant === "warning" ? "bg-white" :
|
|
177
|
+
variant === "secondary" ? "bg-secondary-foreground" :
|
|
178
|
+
variant === "outline" ? "bg-foreground" :
|
|
179
|
+
variant === "ghost" ? "bg-foreground" :
|
|
180
|
+
variant === "pro" ? "bg-white" :
|
|
181
|
+
variant === "admin" ? "bg-white" :
|
|
182
|
+
"bg-primary-foreground")
|
|
183
|
+
)}
|
|
184
|
+
aria-hidden="true"
|
|
185
|
+
/>
|
|
186
|
+
)}
|
|
187
|
+
{autoLeftIcon && (
|
|
188
|
+
<span className="inline-flex shrink-0">
|
|
189
|
+
{autoLeftIcon}
|
|
190
|
+
</span>
|
|
191
|
+
)}
|
|
192
|
+
<span className="truncate">{autoChildren}</span>
|
|
193
|
+
{rightIcon && (
|
|
194
|
+
<span className="inline-flex shrink-0">
|
|
195
|
+
{rightIcon}
|
|
196
|
+
</span>
|
|
197
|
+
)}
|
|
198
|
+
{removable && onRemove && (
|
|
199
|
+
<button
|
|
200
|
+
type="button"
|
|
201
|
+
className="ml-1 -mr-1 h-3.5 w-3.5 rounded-full inline-flex items-center justify-center hover:bg-black/10 dark:hover:bg-white/10"
|
|
202
|
+
onClick={(e) => {
|
|
203
|
+
e.stopPropagation();
|
|
204
|
+
onRemove();
|
|
205
|
+
}}
|
|
206
|
+
aria-label="Remove badge"
|
|
207
|
+
>
|
|
208
|
+
<svg
|
|
209
|
+
width="8"
|
|
210
|
+
height="8"
|
|
211
|
+
viewBox="0 0 8 8"
|
|
212
|
+
fill="none"
|
|
213
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
214
|
+
className="opacity-70"
|
|
215
|
+
aria-hidden="true"
|
|
216
|
+
>
|
|
217
|
+
<path d="M0.799988 7.19999L7.19999 0.799988M0.799988 0.799988L7.19999 7.19999" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
|
|
218
|
+
</svg>
|
|
219
|
+
</button>
|
|
220
|
+
)}
|
|
221
|
+
</div>
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export { Badge, badgeVariants };
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
+
import { cn } from "../../lib/utils";
|
|
4
|
+
import { Loader2 } from "lucide-react";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Premium Button Component
|
|
8
|
+
*
|
|
9
|
+
* A world-class, accessible, and versatile button component.
|
|
10
|
+
* Pixel-perfect design with extensive variants and states.
|
|
11
|
+
*/
|
|
12
|
+
const buttonVariants = cva(
|
|
13
|
+
["inline-flex items-center justify-center gap-2 whitespace-nowrap",
|
|
14
|
+
"font-medium relative",
|
|
15
|
+
"transition-all duration-200 ease-out",
|
|
16
|
+
"premium-hover", /* Standart premium hover efekti */
|
|
17
|
+
"focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
|
|
18
|
+
"disabled:opacity-50 disabled:cursor-not-allowed disabled:pointer-events-none"],
|
|
19
|
+
{
|
|
20
|
+
variants: {
|
|
21
|
+
variant: {
|
|
22
|
+
primary: [
|
|
23
|
+
"bg-primary text-primary-foreground",
|
|
24
|
+
"hover:bg-primary-hover dark:hover:bg-primary/90",
|
|
25
|
+
"active:bg-primary-active dark:active:bg-primary/80",
|
|
26
|
+
"shadow-sm dark:shadow-primary/20 dark:shadow-md",
|
|
27
|
+
"focus-visible:ring-primary/50 dark:focus-visible:ring-primary/30",
|
|
28
|
+
"dark:bg-primary dark:text-white",
|
|
29
|
+
"transition-all duration-200",
|
|
30
|
+
],
|
|
31
|
+
secondary: [
|
|
32
|
+
"bg-secondary text-secondary-foreground",
|
|
33
|
+
"hover:bg-gray-200 dark:hover:bg-gray-700/90",
|
|
34
|
+
"active:bg-gray-300 dark:active:bg-gray-600/90",
|
|
35
|
+
"border border-transparent dark:border-gray-700",
|
|
36
|
+
"focus-visible:ring-gray-400/30 dark:focus-visible:ring-gray-500/40",
|
|
37
|
+
"dark:bg-gray-800 dark:text-gray-100",
|
|
38
|
+
"dark:shadow-sm dark:shadow-gray-900/20",
|
|
39
|
+
],
|
|
40
|
+
outline: [
|
|
41
|
+
"bg-background text-foreground",
|
|
42
|
+
"border border-gray-300 dark:border-gray-700",
|
|
43
|
+
"hover:border-gray-400 dark:hover:border-gray-500",
|
|
44
|
+
"hover:bg-gray-50 dark:hover:bg-gray-800/80",
|
|
45
|
+
"active:bg-gray-100 dark:active:bg-gray-800/90",
|
|
46
|
+
"focus-visible:ring-gray-400/30 dark:focus-visible:ring-gray-500/40",
|
|
47
|
+
"dark:text-gray-200 dark:bg-gray-900/50",
|
|
48
|
+
"dark:shadow-sm dark:shadow-gray-950/10",
|
|
49
|
+
],
|
|
50
|
+
ghost: [
|
|
51
|
+
"text-foreground",
|
|
52
|
+
"hover:bg-gray-100 dark:hover:bg-gray-800/90",
|
|
53
|
+
"active:bg-gray-200 dark:active:bg-gray-700/90",
|
|
54
|
+
"focus-visible:ring-gray-400/30 dark:focus-visible:ring-gray-500/40",
|
|
55
|
+
"dark:text-gray-200",
|
|
56
|
+
"transition-colors duration-200",
|
|
57
|
+
],
|
|
58
|
+
destructive: [
|
|
59
|
+
"bg-error text-white",
|
|
60
|
+
"hover:bg-error/90 dark:hover:bg-error/80",
|
|
61
|
+
"active:bg-error/80 dark:active:bg-error/70",
|
|
62
|
+
"shadow-sm dark:shadow-error/10 dark:shadow-md",
|
|
63
|
+
"focus-visible:ring-error/50 dark:focus-visible:ring-error/30",
|
|
64
|
+
"dark:text-white dark:border-error/20",
|
|
65
|
+
"transition-colors duration-200",
|
|
66
|
+
],
|
|
67
|
+
success: [
|
|
68
|
+
"bg-success text-white",
|
|
69
|
+
"hover:bg-success/90 dark:hover:bg-success/80",
|
|
70
|
+
"active:bg-success/80 dark:active:bg-success/70",
|
|
71
|
+
"shadow-sm dark:shadow-success/10 dark:shadow-md",
|
|
72
|
+
"focus-visible:ring-success/50 dark:focus-visible:ring-success/30",
|
|
73
|
+
"dark:text-white dark:border-success/20",
|
|
74
|
+
"transition-colors duration-200",
|
|
75
|
+
],
|
|
76
|
+
link: [
|
|
77
|
+
"text-primary bg-transparent",
|
|
78
|
+
"underline-offset-4 hover:underline",
|
|
79
|
+
"hover:text-primary-hover active:text-primary-active",
|
|
80
|
+
"p-0 h-auto",
|
|
81
|
+
"dark:text-blue-400 dark:hover:text-blue-300",
|
|
82
|
+
"dark:active:text-blue-500",
|
|
83
|
+
"transition-colors duration-200",
|
|
84
|
+
],
|
|
85
|
+
gradient: [
|
|
86
|
+
"bg-gradient-to-r from-blue-600 to-purple-600 text-white",
|
|
87
|
+
"hover:from-blue-700 hover:to-purple-700",
|
|
88
|
+
"active:from-blue-800 active:to-purple-800",
|
|
89
|
+
"shadow-lg shadow-purple-500/25",
|
|
90
|
+
"focus-visible:ring-purple-500/50",
|
|
91
|
+
"transition-all duration-300",
|
|
92
|
+
],
|
|
93
|
+
glow: [
|
|
94
|
+
"bg-primary text-primary-foreground",
|
|
95
|
+
"shadow-lg shadow-primary/50",
|
|
96
|
+
"hover:shadow-xl hover:shadow-primary/60",
|
|
97
|
+
"active:shadow-md active:shadow-primary/40",
|
|
98
|
+
"focus-visible:ring-primary/50",
|
|
99
|
+
"transition-all duration-300",
|
|
100
|
+
],
|
|
101
|
+
soft: [
|
|
102
|
+
"bg-primary/10 text-primary",
|
|
103
|
+
"hover:bg-primary/20",
|
|
104
|
+
"active:bg-primary/30",
|
|
105
|
+
"focus-visible:ring-primary/50",
|
|
106
|
+
"dark:bg-primary/20 dark:text-primary-foreground",
|
|
107
|
+
"dark:hover:bg-primary/30 dark:active:bg-primary/40",
|
|
108
|
+
"transition-colors duration-200",
|
|
109
|
+
],
|
|
110
|
+
glass: [
|
|
111
|
+
"bg-white/10 backdrop-blur-md text-foreground",
|
|
112
|
+
"border border-white/20",
|
|
113
|
+
"hover:bg-white/20 hover:border-white/30",
|
|
114
|
+
"active:bg-white/30",
|
|
115
|
+
"shadow-lg",
|
|
116
|
+
"focus-visible:ring-white/50",
|
|
117
|
+
"dark:bg-gray-800/10 dark:border-gray-700/20",
|
|
118
|
+
"dark:hover:bg-gray-800/20 dark:hover:border-gray-700/30",
|
|
119
|
+
"transition-all duration-200",
|
|
120
|
+
],
|
|
121
|
+
neon: [
|
|
122
|
+
"bg-transparent text-primary",
|
|
123
|
+
"border-2 border-primary",
|
|
124
|
+
"hover:bg-primary hover:text-primary-foreground",
|
|
125
|
+
"hover:shadow-[0_0_20px_rgba(var(--primary),0.5)]",
|
|
126
|
+
"active:shadow-[0_0_10px_rgba(var(--primary),0.3)]",
|
|
127
|
+
"focus-visible:ring-primary/50",
|
|
128
|
+
"transition-all duration-300",
|
|
129
|
+
],
|
|
130
|
+
},
|
|
131
|
+
size: {
|
|
132
|
+
xs: "h-7 px-2.5 text-xs rounded",
|
|
133
|
+
sm: "h-8 px-3 text-sm rounded",
|
|
134
|
+
md: "h-10 px-4 text-base rounded-md",
|
|
135
|
+
lg: "h-12 px-6 text-lg rounded-lg",
|
|
136
|
+
xl: "h-14 px-8 text-xl rounded-lg",
|
|
137
|
+
icon: "h-10 w-10 p-2 rounded-md",
|
|
138
|
+
"icon-sm": "h-8 w-8 p-1.5 rounded",
|
|
139
|
+
"icon-lg": "h-12 w-12 p-3 rounded-lg",
|
|
140
|
+
},
|
|
141
|
+
rounded: {
|
|
142
|
+
default: "",
|
|
143
|
+
full: "rounded-full",
|
|
144
|
+
none: "rounded-none",
|
|
145
|
+
},
|
|
146
|
+
fullWidth: {
|
|
147
|
+
true: "w-full",
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
defaultVariants: {
|
|
151
|
+
variant: "primary",
|
|
152
|
+
size: "md",
|
|
153
|
+
rounded: "default",
|
|
154
|
+
fullWidth: false,
|
|
155
|
+
},
|
|
156
|
+
}
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
// Button component props
|
|
160
|
+
export interface ButtonProps
|
|
161
|
+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
162
|
+
VariantProps<typeof buttonVariants> {
|
|
163
|
+
asChild?: boolean;
|
|
164
|
+
loading?: boolean;
|
|
165
|
+
leftIcon?: React.ReactNode;
|
|
166
|
+
rightIcon?: React.ReactNode;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Premium Button Component
|
|
171
|
+
*
|
|
172
|
+
* @param props - Button component properties
|
|
173
|
+
* @param props.variant - Visual variant (primary, secondary, ghost, etc.)
|
|
174
|
+
* @param props.size - Button size (xs, sm, md, lg, xl)
|
|
175
|
+
* @param props.loading - Loading state display
|
|
176
|
+
* @param props.leftIcon - Icon on the left side
|
|
177
|
+
* @param props.rightIcon - Icon on the right side
|
|
178
|
+
* @param props.fullWidth - Full width display
|
|
179
|
+
* @param props.rounded - Corner rounding style (default, full, none)
|
|
180
|
+
* @param props.asChild - For Radix UI polymorphic component
|
|
181
|
+
*/
|
|
182
|
+
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
183
|
+
({
|
|
184
|
+
className,
|
|
185
|
+
variant,
|
|
186
|
+
size,
|
|
187
|
+
rounded,
|
|
188
|
+
fullWidth,
|
|
189
|
+
asChild = false,
|
|
190
|
+
loading = false,
|
|
191
|
+
leftIcon,
|
|
192
|
+
rightIcon,
|
|
193
|
+
children,
|
|
194
|
+
disabled,
|
|
195
|
+
...props
|
|
196
|
+
}, ref) => {
|
|
197
|
+
// Radix UI'ın asChild pattern'i için - "as" prop yerine
|
|
198
|
+
const Comp = asChild ? "button" : "button";
|
|
199
|
+
|
|
200
|
+
return (
|
|
201
|
+
<Comp
|
|
202
|
+
className={cn(buttonVariants({ variant, size, rounded, fullWidth, className }))}
|
|
203
|
+
ref={ref}
|
|
204
|
+
disabled={disabled || loading}
|
|
205
|
+
data-loading={loading ? "" : undefined}
|
|
206
|
+
{...props}
|
|
207
|
+
>
|
|
208
|
+
{loading && (
|
|
209
|
+
<Loader2 className="w-4 h-4 animate-spin" aria-hidden="true" />
|
|
210
|
+
)}
|
|
211
|
+
{!loading && leftIcon}
|
|
212
|
+
{children}
|
|
213
|
+
{!loading && rightIcon}
|
|
214
|
+
</Comp>
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
Button.displayName = "Button";
|
|
220
|
+
|
|
221
|
+
export { Button, buttonVariants };
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
+
import { motion, type HTMLMotionProps } from "framer-motion";
|
|
4
|
+
import { cn } from "../../lib/utils";
|
|
5
|
+
import { microInteractionVariants, hoverAnimations, tapAnimations } from "../../lib/micro-interactions";
|
|
6
|
+
|
|
7
|
+
const cardVariants = cva(
|
|
8
|
+
"rounded-lg border bg-card text-card-foreground shadow-sm dark:shadow-gray-900/20 dark:border-gray-800 dark:bg-gray-900 dark:text-gray-100 transition-all duration-200",
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default: "",
|
|
13
|
+
outline: "border border-border shadow-none bg-transparent dark:border-gray-700 dark:bg-transparent dark:text-gray-200",
|
|
14
|
+
filled: "border-none bg-secondary dark:bg-gray-800 dark:text-gray-100 dark:shadow-inner dark:shadow-gray-950/10",
|
|
15
|
+
elevated: "border-none shadow-md dark:shadow-lg dark:shadow-gray-900/30 dark:bg-gray-850 dark:text-gray-100",
|
|
16
|
+
gradient: "border-none bg-gradient-to-br from-primary/5 to-primary/10 dark:from-primary/10 dark:to-primary/20",
|
|
17
|
+
glass: "border border-white/20 bg-white/10 backdrop-blur-md dark:border-gray-700/30 dark:bg-gray-800/10",
|
|
18
|
+
},
|
|
19
|
+
size: {
|
|
20
|
+
default: "p-6",
|
|
21
|
+
sm: "p-4",
|
|
22
|
+
lg: "p-8",
|
|
23
|
+
xl: "p-10",
|
|
24
|
+
},
|
|
25
|
+
radius: {
|
|
26
|
+
default: "rounded-lg",
|
|
27
|
+
sm: "rounded-md",
|
|
28
|
+
lg: "rounded-xl",
|
|
29
|
+
full: "rounded-3xl",
|
|
30
|
+
none: "rounded-none",
|
|
31
|
+
},
|
|
32
|
+
interactive: {
|
|
33
|
+
true: "cursor-pointer hover:shadow-lg hover:border-primary/20 dark:hover:border-primary/30 hover:-translate-y-0.5 active:translate-y-0 active:shadow-sm",
|
|
34
|
+
false: "",
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
defaultVariants: {
|
|
38
|
+
variant: "default",
|
|
39
|
+
size: "default",
|
|
40
|
+
radius: "default",
|
|
41
|
+
},
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
export interface CardProps
|
|
46
|
+
extends React.HTMLAttributes<HTMLDivElement>,
|
|
47
|
+
VariantProps<typeof cardVariants> {
|
|
48
|
+
asChild?: boolean;
|
|
49
|
+
microInteraction?: "lift" | "glow" | "scale" | "none";
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const Card = React.forwardRef<HTMLDivElement, CardProps>(
|
|
53
|
+
({ className, variant, size, radius, interactive, microInteraction = "lift", ...props }, ref) => {
|
|
54
|
+
// Interactive özelliği varsa motion.div, yoksa normal div kullan
|
|
55
|
+
if (interactive && microInteraction !== "none") {
|
|
56
|
+
const interactionProps = {
|
|
57
|
+
whileHover: microInteraction === "scale" ? hoverAnimations.scale :
|
|
58
|
+
microInteraction === "glow" ? hoverAnimations.glow :
|
|
59
|
+
hoverAnimations.lift,
|
|
60
|
+
whileTap: tapAnimations.scale,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<motion.div
|
|
65
|
+
ref={ref}
|
|
66
|
+
className={cn(cardVariants({ variant, size, radius, interactive, className }))}
|
|
67
|
+
{...interactionProps}
|
|
68
|
+
{...props}
|
|
69
|
+
/>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Non-interactive version
|
|
74
|
+
return (
|
|
75
|
+
<div
|
|
76
|
+
ref={ref}
|
|
77
|
+
className={cn(cardVariants({ variant, size, radius, interactive, className }))}
|
|
78
|
+
{...props}
|
|
79
|
+
/>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
);
|
|
83
|
+
Card.displayName = "Card";
|
|
84
|
+
|
|
85
|
+
const CardHeader = React.forwardRef<
|
|
86
|
+
HTMLDivElement,
|
|
87
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
88
|
+
>(({ className, ...props }, ref) => (
|
|
89
|
+
<div
|
|
90
|
+
ref={ref}
|
|
91
|
+
className={cn("flex flex-col space-y-1.5", className)}
|
|
92
|
+
{...props}
|
|
93
|
+
/>
|
|
94
|
+
));
|
|
95
|
+
CardHeader.displayName = "CardHeader";
|
|
96
|
+
|
|
97
|
+
const CardTitle = React.forwardRef<
|
|
98
|
+
HTMLHeadingElement,
|
|
99
|
+
React.HTMLAttributes<HTMLHeadingElement>
|
|
100
|
+
>(({ className, ...props }, ref) => (
|
|
101
|
+
<h3
|
|
102
|
+
ref={ref}
|
|
103
|
+
className={cn("text-lg font-semibold leading-none tracking-tight", className)}
|
|
104
|
+
{...props}
|
|
105
|
+
/>
|
|
106
|
+
));
|
|
107
|
+
CardTitle.displayName = "CardTitle";
|
|
108
|
+
|
|
109
|
+
const CardDescription = React.forwardRef<
|
|
110
|
+
HTMLParagraphElement,
|
|
111
|
+
React.HTMLAttributes<HTMLParagraphElement>
|
|
112
|
+
>(({ className, ...props }, ref) => (
|
|
113
|
+
<p
|
|
114
|
+
ref={ref}
|
|
115
|
+
className={cn("text-sm text-muted-foreground", className)}
|
|
116
|
+
{...props}
|
|
117
|
+
/>
|
|
118
|
+
));
|
|
119
|
+
CardDescription.displayName = "CardDescription";
|
|
120
|
+
|
|
121
|
+
const CardContent = React.forwardRef<
|
|
122
|
+
HTMLDivElement,
|
|
123
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
124
|
+
>(({ className, ...props }, ref) => (
|
|
125
|
+
<div ref={ref} className={cn("pt-0", className)} {...props} />
|
|
126
|
+
));
|
|
127
|
+
CardContent.displayName = "CardContent";
|
|
128
|
+
|
|
129
|
+
const CardFooter = React.forwardRef<
|
|
130
|
+
HTMLDivElement,
|
|
131
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
132
|
+
>(({ className, ...props }, ref) => (
|
|
133
|
+
<div
|
|
134
|
+
ref={ref}
|
|
135
|
+
className={cn("flex items-center pt-4", className)}
|
|
136
|
+
{...props}
|
|
137
|
+
/>
|
|
138
|
+
));
|
|
139
|
+
CardFooter.displayName = "CardFooter";
|
|
140
|
+
|
|
141
|
+
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };
|