@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.
Files changed (99) hide show
  1. package/dist/index.mjs +215 -214
  2. package/package.json +4 -2
  3. package/src/__tests__/use-intersection-observer.test.tsx +216 -0
  4. package/src/__tests__/use-local-storage.test.tsx +174 -0
  5. package/src/__tests__/use-pro-access.test.tsx +183 -0
  6. package/src/components/advanced-chart/advanced-chart.test.tsx +281 -0
  7. package/src/components/advanced-chart/index.tsx +412 -0
  8. package/src/components/advanced-forms/index.tsx +431 -0
  9. package/src/components/animated-button/index.tsx +202 -0
  10. package/src/components/calendar/event-dialog.tsx +372 -0
  11. package/src/components/calendar/index.tsx +557 -0
  12. package/src/components/color-picker/index.tsx +434 -0
  13. package/src/components/dashboard/index.tsx +334 -0
  14. package/src/components/data-table/data-table.test.tsx +187 -0
  15. package/src/components/data-table/index.tsx +368 -0
  16. package/src/components/draggable-list/index.tsx +100 -0
  17. package/src/components/enhanced/button.tsx +360 -0
  18. package/src/components/enhanced/card.tsx +272 -0
  19. package/src/components/enhanced/dialog.tsx +248 -0
  20. package/src/components/enhanced/index.ts +3 -0
  21. package/src/components/error-boundary/index.tsx +111 -0
  22. package/src/components/file-upload/file-upload.test.tsx +242 -0
  23. package/src/components/file-upload/index.tsx +362 -0
  24. package/src/components/floating-action-button/index.tsx +209 -0
  25. package/src/components/github-stars/index.tsx +414 -0
  26. package/src/components/health-check/index.tsx +441 -0
  27. package/src/components/hover-card-3d/index.tsx +170 -0
  28. package/src/components/index.ts +76 -0
  29. package/src/components/kanban/index.tsx +436 -0
  30. package/src/components/lazy-component/index.tsx +342 -0
  31. package/src/components/magnetic-button/index.tsx +170 -0
  32. package/src/components/memory-efficient-data/index.tsx +352 -0
  33. package/src/components/optimized-image/index.tsx +427 -0
  34. package/src/components/performance-debugger/index.tsx +591 -0
  35. package/src/components/performance-monitor/index.tsx +775 -0
  36. package/src/components/pinch-zoom/index.tsx +172 -0
  37. package/src/components/rich-text-editor/index-old-backup.tsx +443 -0
  38. package/src/components/rich-text-editor/index.tsx +1537 -0
  39. package/src/components/rich-text-editor/slash-commands-extension.ts +220 -0
  40. package/src/components/rich-text-editor/slash-commands.css +35 -0
  41. package/src/components/rich-text-editor/table-styles.css +65 -0
  42. package/src/components/spotlight-card/index.tsx +194 -0
  43. package/src/components/swipeable-card/index.tsx +100 -0
  44. package/src/components/timeline/index.tsx +333 -0
  45. package/src/components/ui/animated-button.tsx +185 -0
  46. package/src/components/ui/avatar.tsx +135 -0
  47. package/src/components/ui/badge.tsx +225 -0
  48. package/src/components/ui/button.tsx +221 -0
  49. package/src/components/ui/card.tsx +141 -0
  50. package/src/components/ui/checkbox.tsx +256 -0
  51. package/src/components/ui/color-picker.tsx +95 -0
  52. package/src/components/ui/dialog.tsx +332 -0
  53. package/src/components/ui/dropdown-menu.tsx +200 -0
  54. package/src/components/ui/hover-card-3d.tsx +103 -0
  55. package/src/components/ui/index.ts +33 -0
  56. package/src/components/ui/input.tsx +219 -0
  57. package/src/components/ui/label.tsx +26 -0
  58. package/src/components/ui/magnetic-button.tsx +129 -0
  59. package/src/components/ui/popover.tsx +183 -0
  60. package/src/components/ui/select.tsx +273 -0
  61. package/src/components/ui/separator.tsx +140 -0
  62. package/src/components/ui/slider.tsx +351 -0
  63. package/src/components/ui/spotlight-card.tsx +119 -0
  64. package/src/components/ui/switch.tsx +83 -0
  65. package/src/components/ui/tabs.tsx +195 -0
  66. package/src/components/ui/textarea.tsx +25 -0
  67. package/src/components/ui/toast.tsx +313 -0
  68. package/src/components/ui/tooltip.tsx +152 -0
  69. package/src/components/virtual-list/index.tsx +369 -0
  70. package/src/hooks/use-chart.ts +205 -0
  71. package/src/hooks/use-data-table.ts +182 -0
  72. package/src/hooks/use-docs-pro-access.ts +13 -0
  73. package/src/hooks/use-license-check.ts +65 -0
  74. package/src/hooks/use-subscription.ts +19 -0
  75. package/src/index.ts +14 -0
  76. package/src/lib/micro-interactions.ts +255 -0
  77. package/src/lib/utils.ts +6 -0
  78. package/src/patterns/login-form/index.tsx +276 -0
  79. package/src/patterns/login-form/types.ts +67 -0
  80. package/src/setupTests.ts +41 -0
  81. package/src/styles/design-system.css +365 -0
  82. package/src/styles/index.css +4 -0
  83. package/src/styles/tailwind.css +6 -0
  84. package/src/styles/tokens.css +453 -0
  85. package/src/types/moonui.d.ts +22 -0
  86. package/src/use-intersection-observer.tsx +154 -0
  87. package/src/use-local-storage.tsx +71 -0
  88. package/src/use-paddle.ts +138 -0
  89. package/src/use-performance-optimizer.ts +379 -0
  90. package/src/use-pro-access.ts +141 -0
  91. package/src/use-scroll-animation.ts +221 -0
  92. package/src/use-subscription.ts +37 -0
  93. package/src/use-toast.ts +32 -0
  94. package/src/utils/chart-helpers.ts +257 -0
  95. package/src/utils/cn.ts +69 -0
  96. package/src/utils/data-processing.ts +151 -0
  97. package/src/utils/license-guard.tsx +177 -0
  98. package/src/utils/license-validator.tsx +183 -0
  99. 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 };