@moontra/moonui-pro 2.0.21 → 2.0.23

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 (97) hide show
  1. package/dist/index.mjs +771 -20
  2. package/package.json +2 -1
  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 +531 -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 +11 -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-validator.tsx +183 -0
@@ -0,0 +1,200 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
5
+ import { Check, ChevronRight, Circle } from "lucide-react"
6
+
7
+ import { cn } from "../../lib/utils"
8
+
9
+ const DropdownMenu = DropdownMenuPrimitive.Root
10
+
11
+ const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
12
+
13
+ const DropdownMenuGroup = DropdownMenuPrimitive.Group
14
+
15
+ const DropdownMenuPortal = DropdownMenuPrimitive.Portal
16
+
17
+ const DropdownMenuSub = DropdownMenuPrimitive.Sub
18
+
19
+ const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
20
+
21
+ const DropdownMenuSubTrigger = React.forwardRef<
22
+ React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
23
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
24
+ inset?: boolean
25
+ }
26
+ >(({ className, inset, children, ...props }, ref) => (
27
+ <DropdownMenuPrimitive.SubTrigger
28
+ ref={ref}
29
+ className={cn(
30
+ "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",
31
+ inset && "pl-8",
32
+ className
33
+ )}
34
+ {...props}
35
+ >
36
+ {children}
37
+ <ChevronRight className="ml-auto h-4 w-4" />
38
+ </DropdownMenuPrimitive.SubTrigger>
39
+ ))
40
+ DropdownMenuSubTrigger.displayName =
41
+ DropdownMenuPrimitive.SubTrigger.displayName
42
+
43
+ const DropdownMenuSubContent = React.forwardRef<
44
+ React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
45
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
46
+ >(({ className, ...props }, ref) => (
47
+ <DropdownMenuPrimitive.SubContent
48
+ ref={ref}
49
+ className={cn(
50
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
51
+ className
52
+ )}
53
+ {...props}
54
+ />
55
+ ))
56
+ DropdownMenuSubContent.displayName =
57
+ DropdownMenuPrimitive.SubContent.displayName
58
+
59
+ const DropdownMenuContent = React.forwardRef<
60
+ React.ElementRef<typeof DropdownMenuPrimitive.Content>,
61
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
62
+ >(({ className, sideOffset = 4, ...props }, ref) => (
63
+ <DropdownMenuPrimitive.Portal>
64
+ <DropdownMenuPrimitive.Content
65
+ ref={ref}
66
+ sideOffset={sideOffset}
67
+ className={cn(
68
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
69
+ className
70
+ )}
71
+ {...props}
72
+ />
73
+ </DropdownMenuPrimitive.Portal>
74
+ ))
75
+ DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
76
+
77
+ const DropdownMenuItem = React.forwardRef<
78
+ React.ElementRef<typeof DropdownMenuPrimitive.Item>,
79
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
80
+ inset?: boolean
81
+ }
82
+ >(({ className, inset, ...props }, ref) => (
83
+ <DropdownMenuPrimitive.Item
84
+ ref={ref}
85
+ className={cn(
86
+ "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
87
+ inset && "pl-8",
88
+ className
89
+ )}
90
+ {...props}
91
+ />
92
+ ))
93
+ DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
94
+
95
+ const DropdownMenuCheckboxItem = React.forwardRef<
96
+ React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
97
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
98
+ >(({ className, children, checked, ...props }, ref) => (
99
+ <DropdownMenuPrimitive.CheckboxItem
100
+ ref={ref}
101
+ className={cn(
102
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
103
+ className
104
+ )}
105
+ checked={checked}
106
+ {...props}
107
+ >
108
+ <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
109
+ <DropdownMenuPrimitive.ItemIndicator>
110
+ <Check className="h-4 w-4" />
111
+ </DropdownMenuPrimitive.ItemIndicator>
112
+ </span>
113
+ {children}
114
+ </DropdownMenuPrimitive.CheckboxItem>
115
+ ))
116
+ DropdownMenuCheckboxItem.displayName =
117
+ DropdownMenuPrimitive.CheckboxItem.displayName
118
+
119
+ const DropdownMenuRadioItem = React.forwardRef<
120
+ React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
121
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
122
+ >(({ className, children, ...props }, ref) => (
123
+ <DropdownMenuPrimitive.RadioItem
124
+ ref={ref}
125
+ className={cn(
126
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
127
+ className
128
+ )}
129
+ {...props}
130
+ >
131
+ <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
132
+ <DropdownMenuPrimitive.ItemIndicator>
133
+ <Circle className="h-2 w-2 fill-current" />
134
+ </DropdownMenuPrimitive.ItemIndicator>
135
+ </span>
136
+ {children}
137
+ </DropdownMenuPrimitive.RadioItem>
138
+ ))
139
+ DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
140
+
141
+ const DropdownMenuLabel = React.forwardRef<
142
+ React.ElementRef<typeof DropdownMenuPrimitive.Label>,
143
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
144
+ inset?: boolean
145
+ }
146
+ >(({ className, inset, ...props }, ref) => (
147
+ <DropdownMenuPrimitive.Label
148
+ ref={ref}
149
+ className={cn(
150
+ "px-2 py-1.5 text-sm font-semibold",
151
+ inset && "pl-8",
152
+ className
153
+ )}
154
+ {...props}
155
+ />
156
+ ))
157
+ DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
158
+
159
+ const DropdownMenuSeparator = React.forwardRef<
160
+ React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
161
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
162
+ >(({ className, ...props }, ref) => (
163
+ <DropdownMenuPrimitive.Separator
164
+ ref={ref}
165
+ className={cn("-mx-1 my-1 h-px bg-muted", className)}
166
+ {...props}
167
+ />
168
+ ))
169
+ DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
170
+
171
+ const DropdownMenuShortcut = ({
172
+ className,
173
+ ...props
174
+ }: React.HTMLAttributes<HTMLSpanElement>) => {
175
+ return (
176
+ <span
177
+ className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
178
+ {...props}
179
+ />
180
+ )
181
+ }
182
+ DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
183
+
184
+ export {
185
+ DropdownMenu,
186
+ DropdownMenuTrigger,
187
+ DropdownMenuContent,
188
+ DropdownMenuItem,
189
+ DropdownMenuCheckboxItem,
190
+ DropdownMenuRadioItem,
191
+ DropdownMenuLabel,
192
+ DropdownMenuSeparator,
193
+ DropdownMenuShortcut,
194
+ DropdownMenuGroup,
195
+ DropdownMenuPortal,
196
+ DropdownMenuSub,
197
+ DropdownMenuSubContent,
198
+ DropdownMenuSubTrigger,
199
+ DropdownMenuRadioGroup,
200
+ }
@@ -0,0 +1,103 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import { motion, useMotionValue, useSpring, useTransform } from "framer-motion";
5
+ import { cn } from "@/lib/utils";
6
+
7
+ export interface HoverCard3DProps extends React.HTMLAttributes<HTMLDivElement> {
8
+ children: React.ReactNode;
9
+ rotateAmount?: number;
10
+ scale?: number;
11
+ perspective?: number;
12
+ springConfig?: {
13
+ stiffness?: number;
14
+ damping?: number;
15
+ };
16
+ }
17
+
18
+ const HoverCard3D = React.forwardRef<HTMLDivElement, HoverCard3DProps>(
19
+ (
20
+ {
21
+ children,
22
+ className,
23
+ rotateAmount = 15,
24
+ scale = 1.05,
25
+ perspective = 1000,
26
+ springConfig = { stiffness: 300, damping: 20 },
27
+ ...props
28
+ },
29
+ ref
30
+ ) => {
31
+ const cardRef = React.useRef<HTMLDivElement>(null);
32
+ const mouseX = useMotionValue(0);
33
+ const mouseY = useMotionValue(0);
34
+
35
+ const rotateX = useSpring(
36
+ useTransform(mouseY, [-0.5, 0.5], [rotateAmount, -rotateAmount]),
37
+ springConfig
38
+ );
39
+ const rotateY = useSpring(
40
+ useTransform(mouseX, [-0.5, 0.5], [-rotateAmount, rotateAmount]),
41
+ springConfig
42
+ );
43
+
44
+ const handleMouseMove = React.useCallback(
45
+ (e: React.MouseEvent<HTMLDivElement>) => {
46
+ if (!cardRef.current) return;
47
+
48
+ const rect = cardRef.current.getBoundingClientRect();
49
+ const width = rect.width;
50
+ const height = rect.height;
51
+ const x = e.clientX - rect.left;
52
+ const y = e.clientY - rect.top;
53
+
54
+ const xPct = x / width - 0.5;
55
+ const yPct = y / height - 0.5;
56
+
57
+ mouseX.set(xPct);
58
+ mouseY.set(yPct);
59
+ },
60
+ [mouseX, mouseY]
61
+ );
62
+
63
+ const handleMouseLeave = React.useCallback(() => {
64
+ mouseX.set(0);
65
+ mouseY.set(0);
66
+ }, [mouseX, mouseY]);
67
+
68
+ return (
69
+ <div
70
+ ref={ref}
71
+ className={cn("relative", className)}
72
+ style={{ perspective }}
73
+ {...props}
74
+ >
75
+ <motion.div
76
+ ref={cardRef}
77
+ className="w-full h-full transition-shadow duration-300 hover:shadow-xl"
78
+ style={{
79
+ rotateX,
80
+ rotateY,
81
+ transformStyle: "preserve-3d",
82
+ }}
83
+ onMouseMove={handleMouseMove}
84
+ onMouseLeave={handleMouseLeave}
85
+ whileHover={{ scale }}
86
+ transition={{ type: "spring", ...springConfig }}
87
+ >
88
+ <div
89
+ className="absolute inset-0 rounded-lg bg-gradient-to-br from-white/20 to-white/0 opacity-0 hover:opacity-100 transition-opacity duration-300"
90
+ style={{
91
+ transform: "translateZ(1px)",
92
+ }}
93
+ />
94
+ {children}
95
+ </motion.div>
96
+ </div>
97
+ );
98
+ }
99
+ );
100
+
101
+ HoverCard3D.displayName = "HoverCard3D";
102
+
103
+ export { HoverCard3D };
@@ -0,0 +1,33 @@
1
+ // Core UI Components
2
+ export * from './button';
3
+ export * from './card';
4
+ export * from './badge';
5
+ export * from './avatar';
6
+ export * from './dropdown-menu';
7
+ export * from './tooltip';
8
+ export * from './dialog';
9
+ export * from './input';
10
+ export * from './label';
11
+ export * from './select';
12
+ export * from './separator';
13
+ export * from './popover';
14
+ export * from './slider';
15
+ export * from './toast';
16
+ export * from './tabs';
17
+ export * from './switch';
18
+ export * from './checkbox';
19
+ export * from './color-picker';
20
+ export * from './textarea';
21
+
22
+ // Micro-interaction Components
23
+ export { AnimatedButton, animatedButtonVariants } from "./animated-button";
24
+ export type { AnimatedButtonProps } from "./animated-button";
25
+
26
+ export { MagneticButton, magneticButtonVariants } from "./magnetic-button";
27
+ export type { MagneticButtonProps } from "./magnetic-button";
28
+
29
+ export { HoverCard3D } from "./hover-card-3d";
30
+ export type { HoverCard3DProps } from "./hover-card-3d";
31
+
32
+ export { SpotlightCard } from "./spotlight-card";
33
+ export type { SpotlightCardProps } from "./spotlight-card";
@@ -0,0 +1,219 @@
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 Input Component
8
+ *
9
+ * Erişilebilir, estetik ve işlevsel input bileşeni.
10
+ * İkon desteği, hata gösterimi ve çeşitli varyantlar sunar.
11
+ */
12
+
13
+ const inputWrapperVariants = cva(
14
+ "group relative flex items-center w-full transition-colors",
15
+ {
16
+ variants: {
17
+ size: {
18
+ sm: "",
19
+ md: "",
20
+ lg: "",
21
+ },
22
+ },
23
+ defaultVariants: {
24
+ size: "md",
25
+ },
26
+ }
27
+ );
28
+
29
+ const inputVariants = cva(
30
+ [
31
+ "w-full bg-background transition-all duration-200",
32
+ "text-foreground placeholder:text-muted-foreground dark:placeholder:text-gray-500",
33
+ "disabled:cursor-not-allowed disabled:opacity-50",
34
+ "file:border-0 file:bg-transparent file:font-medium",
35
+ "focus-visible:outline-none dark:text-gray-200"
36
+ ],
37
+ {
38
+ variants: {
39
+ variant: {
40
+ standard: "border border-gray-300 dark:border-gray-700 rounded-md px-3 py-2 hover:border-gray-400 dark:hover:border-gray-600 focus-visible:ring-2 focus-visible:ring-primary/30 dark:focus-visible:ring-primary/20 focus-visible:border-primary dark:focus-visible:border-primary/80 dark:bg-gray-900/60 dark:shadow-inner dark:shadow-gray-950/10",
41
+ filled: "border border-transparent bg-gray-100 dark:bg-gray-800/90 rounded-md px-3 py-2 hover:bg-gray-200 dark:hover:bg-gray-700/90 focus-visible:ring-2 focus-visible:ring-primary/30 dark:focus-visible:ring-primary/20 dark:shadow-inner dark:shadow-gray-950/10",
42
+ ghost: "border-none bg-transparent shadow-none px-1 dark:text-gray-300 dark:placeholder:text-gray-500 hover:bg-gray-100/50 dark:hover:bg-gray-800/30 focus-visible:bg-transparent",
43
+ underline: "border-t-0 border-l-0 border-r-0 border-b border-gray-300 dark:border-gray-600 rounded-none px-0 py-2 hover:border-gray-400 dark:hover:border-gray-500 focus-visible:ring-0 focus-visible:border-b-2 focus-visible:border-primary dark:focus-visible:border-primary/80 dark:text-gray-300",
44
+ },
45
+ size: {
46
+ sm: "h-8 text-xs",
47
+ md: "h-10 text-sm",
48
+ lg: "h-12 text-base",
49
+ },
50
+ hasLeftIcon: {
51
+ true: "pl-10",
52
+ false: "",
53
+ },
54
+ hasRightIcon: {
55
+ true: "pr-10",
56
+ false: "",
57
+ },
58
+ hasRightButton: {
59
+ true: "pr-10",
60
+ false: "",
61
+ },
62
+ isError: {
63
+ true: "border-error focus-visible:ring-error/30 focus-visible:border-error hover:border-error/80 dark:hover:border-error/80",
64
+ false: "",
65
+ },
66
+ isSuccess: {
67
+ true: "border-success focus-visible:ring-success/30 focus-visible:border-success hover:border-success/80 dark:hover:border-success/80",
68
+ false: "",
69
+ },
70
+ isDisabled: {
71
+ true: "opacity-50 cursor-not-allowed bg-gray-50 dark:bg-gray-800/50 pointer-events-none",
72
+ false: "",
73
+ }
74
+ },
75
+ defaultVariants: {
76
+ variant: "standard",
77
+ size: "md",
78
+ isError: false,
79
+ isSuccess: false,
80
+ isDisabled: false,
81
+ hasLeftIcon: false,
82
+ hasRightIcon: false,
83
+ hasRightButton: false,
84
+ },
85
+ }
86
+ );
87
+
88
+ export interface InputProps
89
+ extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "size">,
90
+ Omit<VariantProps<typeof inputVariants>, "isDisabled" | "hasLeftIcon" | "hasRightIcon" | "hasRightButton"> {
91
+ /** Hata mesajı */
92
+ error?: string;
93
+ /** Başarı mesajı */
94
+ success?: string;
95
+ /** Yükleniyor durumu */
96
+ loading?: boolean;
97
+ /** Sol tarafta gösterilecek ikon */
98
+ leftIcon?: React.ReactNode;
99
+ /** Sağ tarafta gösterilecek ikon */
100
+ rightIcon?: React.ReactNode;
101
+ /** Sağ tarafta gösterilecek buton (password show/hide vb. için) */
102
+ rightButton?: React.ReactNode;
103
+ /** Mesajın görünürlüğü (true: her zaman görünür, false: sadece hata/başarı durumunda) */
104
+ alwaysShowMessage?: boolean;
105
+ /** Input wrapper için ek sınıflar */
106
+ wrapperClassName?: string;
107
+ /** Mesaj için ek sınıflar */
108
+ messageClassName?: string;
109
+ }
110
+
111
+ /**
112
+ * Premium Input Component
113
+ *
114
+ * @param props - Input bileşeni özellikleri
115
+ * @param props.variant - Görsel varyant (standard, filled, ghost, underline)
116
+ * @param props.size - Boyut (sm, md, lg)
117
+ * @param props.error - Hata mesajı
118
+ * @param props.success - Başarı mesajı
119
+ * @param props.loading - Yükleniyor durumu
120
+ * @param props.leftIcon - Sol tarafta gösterilecek ikon
121
+ * @param props.rightIcon - Sağ tarafta gösterilecek ikon
122
+ * @param props.rightButton - Sağ tarafta gösterilecek buton
123
+ * @param props.alwaysShowMessage - Mesajın her zaman görünür olması
124
+ */
125
+ const Input = React.forwardRef<HTMLInputElement, InputProps>(
126
+ ({
127
+ className,
128
+ wrapperClassName,
129
+ messageClassName,
130
+ variant,
131
+ size,
132
+ isError,
133
+ disabled,
134
+ error,
135
+ success,
136
+ loading,
137
+ leftIcon,
138
+ rightIcon,
139
+ rightButton,
140
+ alwaysShowMessage = false,
141
+ ...props
142
+ }, ref) => {
143
+ // Mesajı göster/gizle
144
+ const showMessage = alwaysShowMessage || error || success;
145
+ const messageType = error ? "error" : success ? "success" : "normal";
146
+
147
+ return (
148
+ <div className="space-y-1.5 w-full">
149
+ <div className={cn(inputWrapperVariants({ size }), wrapperClassName)}>
150
+ {leftIcon && (
151
+ <div className="absolute left-3 text-gray-500 flex items-center justify-center pointer-events-none">
152
+ {loading ? <Loader2 className="h-4 w-4 animate-spin" /> : leftIcon}
153
+ </div>
154
+ )}
155
+
156
+ <input
157
+ className={cn(
158
+ inputVariants({
159
+ variant,
160
+ size,
161
+ isError: !!error || isError,
162
+ isSuccess: !!success,
163
+ isDisabled: disabled || loading,
164
+ hasLeftIcon: !!leftIcon || loading,
165
+ hasRightIcon: !!rightIcon,
166
+ hasRightButton: !!rightButton,
167
+ }),
168
+ className
169
+ )}
170
+ ref={ref}
171
+ disabled={disabled || loading}
172
+ data-loading={loading ? "" : undefined}
173
+ data-error={!!error ? "" : undefined}
174
+ data-success={!!success ? "" : undefined}
175
+ aria-invalid={!!error || !!isError || undefined}
176
+ aria-describedby={error ? `${props.id || ''}-error` : success ? `${props.id || ''}-success` : undefined}
177
+ {...props}
178
+ />
179
+
180
+ {rightIcon && !loading && (
181
+ <div className="absolute right-3 text-gray-500 flex items-center justify-center pointer-events-none">
182
+ {rightIcon}
183
+ </div>
184
+ )}
185
+
186
+ {rightButton && (
187
+ <div className="absolute right-3">
188
+ {rightButton}
189
+ </div>
190
+ )}
191
+
192
+ {loading && !leftIcon && (
193
+ <div className="absolute left-3 text-gray-500 flex items-center justify-center pointer-events-none">
194
+ <Loader2 className="h-4 w-4 animate-spin" aria-hidden="true" />
195
+ </div>
196
+ )}
197
+ </div>
198
+
199
+ {showMessage && (
200
+ <p
201
+ className={cn(
202
+ "text-xs transition-all",
203
+ messageType === "error" && "text-error",
204
+ messageType === "success" && "text-success",
205
+ messageType === "normal" && "text-muted-foreground",
206
+ messageClassName
207
+ )}
208
+ id={error ? `${props.id || ''}-error` : success ? `${props.id || ''}-success` : undefined}
209
+ >
210
+ {error || success || ""}
211
+ </p>
212
+ )}
213
+ </div>
214
+ );
215
+ }
216
+ );
217
+ Input.displayName = "Input";
218
+
219
+ export { Input };
@@ -0,0 +1,26 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as LabelPrimitive from "@radix-ui/react-label"
5
+ import { cva, type VariantProps } from "class-variance-authority"
6
+
7
+ import { cn } from "../../lib/utils"
8
+
9
+ const labelVariants = cva(
10
+ "text-sm font-medium leading-none text-gray-900 dark:text-gray-200 peer-disabled:cursor-not-allowed peer-disabled:opacity-70 dark:peer-disabled:opacity-60 transition-colors duration-200"
11
+ )
12
+
13
+ const Label = React.forwardRef<
14
+ React.ElementRef<typeof LabelPrimitive.Root>,
15
+ React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
16
+ VariantProps<typeof labelVariants>
17
+ >(({ className, ...props }, ref) => (
18
+ <LabelPrimitive.Root
19
+ ref={ref}
20
+ className={cn(labelVariants(), className)}
21
+ {...props}
22
+ />
23
+ ))
24
+ Label.displayName = LabelPrimitive.Root.displayName
25
+
26
+ export { Label }