@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.
- package/dist/index.mjs +771 -20
- package/package.json +2 -1
- 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 +531 -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 +11 -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-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 }
|