@greatapps/greatauth-ui 0.2.1 → 0.3.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@greatapps/greatauth-ui",
3
- "version": "0.2.1",
3
+ "version": "0.3.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -34,11 +34,14 @@
34
34
  "react": "^19",
35
35
  "react-dom": "^19",
36
36
  "next": ">=15",
37
- "lucide-react": "*",
37
+ "lucide-react": "^0.577.0",
38
38
  "better-auth": "^1.4",
39
39
  "next-themes": "*",
40
40
  "radix-ui": "^1.4",
41
- "cmdk": "^1"
41
+ "cmdk": "^1",
42
+ "sonner": "^2.0.7",
43
+ "vaul": "^1.1.2",
44
+ "input-otp": "^1.4.2"
42
45
  },
43
46
  "dependencies": {
44
47
  "clsx": "^2",
@@ -0,0 +1,81 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { Accordion as AccordionPrimitive } from "radix-ui"
5
+
6
+ import { cn } from "../../lib/utils"
7
+ import { ChevronDown, ChevronUp } from "lucide-react"
8
+
9
+ function Accordion({
10
+ className,
11
+ ...props
12
+ }: React.ComponentProps<typeof AccordionPrimitive.Root>) {
13
+ return (
14
+ <AccordionPrimitive.Root
15
+ data-slot="accordion"
16
+ className={cn("flex w-full flex-col", className)}
17
+ {...props}
18
+ />
19
+ )
20
+ }
21
+
22
+ function AccordionItem({
23
+ className,
24
+ ...props
25
+ }: React.ComponentProps<typeof AccordionPrimitive.Item>) {
26
+ return (
27
+ <AccordionPrimitive.Item
28
+ data-slot="accordion-item"
29
+ className={cn("not-last:border-b", className)}
30
+ {...props}
31
+ />
32
+ )
33
+ }
34
+
35
+ function AccordionTrigger({
36
+ className,
37
+ children,
38
+ ...props
39
+ }: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {
40
+ return (
41
+ <AccordionPrimitive.Header className="flex">
42
+ <AccordionPrimitive.Trigger
43
+ data-slot="accordion-trigger"
44
+ className={cn(
45
+ "focus-visible:ring-ring/50 focus-visible:border-ring focus-visible:after:border-ring **:data-[slot=accordion-trigger-icon]:text-muted-foreground rounded-md py-4 text-left text-sm font-medium hover:underline focus-visible:ring-3 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4 group/accordion-trigger relative flex flex-1 items-start justify-between border border-transparent transition-all outline-none disabled:pointer-events-none disabled:opacity-50",
46
+ className
47
+ )}
48
+ {...props}
49
+ >
50
+ {children}
51
+ <ChevronDown data-slot="accordion-trigger-icon" className="pointer-events-none shrink-0 group-aria-expanded/accordion-trigger:hidden" />
52
+ <ChevronUp data-slot="accordion-trigger-icon" className="pointer-events-none hidden shrink-0 group-aria-expanded/accordion-trigger:inline" />
53
+ </AccordionPrimitive.Trigger>
54
+ </AccordionPrimitive.Header>
55
+ )
56
+ }
57
+
58
+ function AccordionContent({
59
+ className,
60
+ children,
61
+ ...props
62
+ }: React.ComponentProps<typeof AccordionPrimitive.Content>) {
63
+ return (
64
+ <AccordionPrimitive.Content
65
+ data-slot="accordion-content"
66
+ className="data-open:animate-accordion-down data-closed:animate-accordion-up text-sm overflow-hidden"
67
+ {...props}
68
+ >
69
+ <div
70
+ className={cn(
71
+ "pt-0 pb-4 [&_a]:hover:text-foreground h-(--radix-accordion-content-height) [&_a]:underline [&_a]:underline-offset-3 [&_p:not(:last-child)]:mb-4",
72
+ className
73
+ )}
74
+ >
75
+ {children}
76
+ </div>
77
+ </AccordionPrimitive.Content>
78
+ )
79
+ }
80
+
81
+ export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
@@ -0,0 +1,11 @@
1
+ "use client"
2
+
3
+ import { AspectRatio as AspectRatioPrimitive } from "radix-ui"
4
+
5
+ function AspectRatio({
6
+ ...props
7
+ }: React.ComponentProps<typeof AspectRatioPrimitive.Root>) {
8
+ return <AspectRatioPrimitive.Root data-slot="aspect-ratio" {...props} />
9
+ }
10
+
11
+ export { AspectRatio }
@@ -0,0 +1,33 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { Checkbox as CheckboxPrimitive } from "radix-ui"
5
+
6
+ import { cn } from "../../lib/utils"
7
+ import { Check } from "lucide-react"
8
+
9
+ function Checkbox({
10
+ className,
11
+ ...props
12
+ }: React.ComponentProps<typeof CheckboxPrimitive.Root>) {
13
+ return (
14
+ <CheckboxPrimitive.Root
15
+ data-slot="checkbox"
16
+ className={cn(
17
+ "border-input dark:bg-input/30 data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary data-checked:border-primary aria-invalid:aria-checked:border-primary aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 flex size-4 items-center justify-center rounded-[4px] border shadow-xs transition-shadow group-has-disabled/field:opacity-50 focus-visible:ring-3 aria-invalid:ring-3 peer relative shrink-0 outline-none after:absolute after:-inset-x-3 after:-inset-y-2 disabled:cursor-not-allowed disabled:opacity-50",
18
+ className
19
+ )}
20
+ {...props}
21
+ >
22
+ <CheckboxPrimitive.Indicator
23
+ data-slot="checkbox-indicator"
24
+ className="[&>svg]:size-3.5 grid place-content-center text-current transition-none"
25
+ >
26
+ <Check
27
+ />
28
+ </CheckboxPrimitive.Indicator>
29
+ </CheckboxPrimitive.Root>
30
+ )
31
+ }
32
+
33
+ export { Checkbox }
@@ -0,0 +1,255 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { ContextMenu as ContextMenuPrimitive } from "radix-ui"
5
+
6
+ import { cn } from "../../lib/utils"
7
+ import { ChevronRight, Check } from "lucide-react"
8
+
9
+ function ContextMenu({
10
+ ...props
11
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Root>) {
12
+ return <ContextMenuPrimitive.Root data-slot="context-menu" {...props} />
13
+ }
14
+
15
+ function ContextMenuTrigger({
16
+ className,
17
+ ...props
18
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Trigger>) {
19
+ return (
20
+ <ContextMenuPrimitive.Trigger
21
+ data-slot="context-menu-trigger"
22
+ className={cn("select-none", className)}
23
+ {...props}
24
+ />
25
+ )
26
+ }
27
+
28
+ function ContextMenuGroup({
29
+ ...props
30
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Group>) {
31
+ return (
32
+ <ContextMenuPrimitive.Group data-slot="context-menu-group" {...props} />
33
+ )
34
+ }
35
+
36
+ function ContextMenuPortal({
37
+ ...props
38
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Portal>) {
39
+ return (
40
+ <ContextMenuPrimitive.Portal data-slot="context-menu-portal" {...props} />
41
+ )
42
+ }
43
+
44
+ function ContextMenuSub({
45
+ ...props
46
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Sub>) {
47
+ return <ContextMenuPrimitive.Sub data-slot="context-menu-sub" {...props} />
48
+ }
49
+
50
+ function ContextMenuRadioGroup({
51
+ ...props
52
+ }: React.ComponentProps<typeof ContextMenuPrimitive.RadioGroup>) {
53
+ return (
54
+ <ContextMenuPrimitive.RadioGroup
55
+ data-slot="context-menu-radio-group"
56
+ {...props}
57
+ />
58
+ )
59
+ }
60
+
61
+ function ContextMenuContent({
62
+ className,
63
+ ...props
64
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Content> & {
65
+ side?: "top" | "right" | "bottom" | "left"
66
+ }) {
67
+ return (
68
+ <ContextMenuPrimitive.Portal>
69
+ <ContextMenuPrimitive.Content
70
+ data-slot="context-menu-content"
71
+ className={cn("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 ring-foreground/10 bg-popover text-popover-foreground min-w-36 rounded-md p-1 shadow-md ring-1 duration-100 z-50 max-h-(--radix-context-menu-content-available-height) origin-(--radix-context-menu-content-transform-origin) overflow-x-hidden overflow-y-auto", className )}
72
+ {...props}
73
+ />
74
+ </ContextMenuPrimitive.Portal>
75
+ )
76
+ }
77
+
78
+ function ContextMenuItem({
79
+ className,
80
+ inset,
81
+ variant = "default",
82
+ ...props
83
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Item> & {
84
+ inset?: boolean
85
+ variant?: "default" | "destructive"
86
+ }) {
87
+ return (
88
+ <ContextMenuPrimitive.Item
89
+ data-slot="context-menu-item"
90
+ data-inset={inset}
91
+ data-variant={variant}
92
+ className={cn(
93
+ "focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive focus:*:[svg]:text-accent-foreground gap-2 rounded-sm px-2 py-1.5 text-sm data-inset:pl-8 [&_svg:not([class*='size-'])]:size-4 group/context-menu-item relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
94
+ className
95
+ )}
96
+ {...props}
97
+ />
98
+ )
99
+ }
100
+
101
+ function ContextMenuSubTrigger({
102
+ className,
103
+ inset,
104
+ children,
105
+ ...props
106
+ }: React.ComponentProps<typeof ContextMenuPrimitive.SubTrigger> & {
107
+ inset?: boolean
108
+ }) {
109
+ return (
110
+ <ContextMenuPrimitive.SubTrigger
111
+ data-slot="context-menu-sub-trigger"
112
+ data-inset={inset}
113
+ className={cn(
114
+ "focus:bg-accent focus:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground rounded-sm px-2 py-1.5 text-sm data-inset:pl-8 [&_svg:not([class*='size-'])]:size-4 flex cursor-default items-center outline-hidden select-none [&_svg]:pointer-events-none [&_svg]:shrink-0",
115
+ className
116
+ )}
117
+ {...props}
118
+ >
119
+ {children}
120
+ <ChevronRight className="ml-auto" />
121
+ </ContextMenuPrimitive.SubTrigger>
122
+ )
123
+ }
124
+
125
+ function ContextMenuSubContent({
126
+ className,
127
+ ...props
128
+ }: React.ComponentProps<typeof ContextMenuPrimitive.SubContent>) {
129
+ return (
130
+ <ContextMenuPrimitive.SubContent
131
+ data-slot="context-menu-sub-content"
132
+ className={cn("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 bg-popover text-popover-foreground min-w-32 rounded-md border p-1 shadow-lg duration-100 z-50 origin-(--radix-context-menu-content-transform-origin) overflow-hidden", className )}
133
+ {...props}
134
+ />
135
+ )
136
+ }
137
+
138
+ function ContextMenuCheckboxItem({
139
+ className,
140
+ children,
141
+ checked,
142
+ inset,
143
+ ...props
144
+ }: React.ComponentProps<typeof ContextMenuPrimitive.CheckboxItem> & {
145
+ inset?: boolean
146
+ }) {
147
+ return (
148
+ <ContextMenuPrimitive.CheckboxItem
149
+ data-slot="context-menu-checkbox-item"
150
+ data-inset={inset}
151
+ className={cn(
152
+ "focus:bg-accent focus:text-accent-foreground gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm data-inset:pl-8 [&_svg:not([class*='size-'])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
153
+ className
154
+ )}
155
+ checked={checked}
156
+ {...props}
157
+ >
158
+ <span className="absolute right-2 pointer-events-none">
159
+ <ContextMenuPrimitive.ItemIndicator>
160
+ <Check />
161
+ </ContextMenuPrimitive.ItemIndicator>
162
+ </span>
163
+ {children}
164
+ </ContextMenuPrimitive.CheckboxItem>
165
+ )
166
+ }
167
+
168
+ function ContextMenuRadioItem({
169
+ className,
170
+ children,
171
+ inset,
172
+ ...props
173
+ }: React.ComponentProps<typeof ContextMenuPrimitive.RadioItem> & {
174
+ inset?: boolean
175
+ }) {
176
+ return (
177
+ <ContextMenuPrimitive.RadioItem
178
+ data-slot="context-menu-radio-item"
179
+ data-inset={inset}
180
+ className={cn(
181
+ "focus:bg-accent focus:text-accent-foreground gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm data-inset:pl-8 [&_svg:not([class*='size-'])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
182
+ className
183
+ )}
184
+ {...props}
185
+ >
186
+ <span className="absolute right-2 pointer-events-none">
187
+ <ContextMenuPrimitive.ItemIndicator>
188
+ <Check />
189
+ </ContextMenuPrimitive.ItemIndicator>
190
+ </span>
191
+ {children}
192
+ </ContextMenuPrimitive.RadioItem>
193
+ )
194
+ }
195
+
196
+ function ContextMenuLabel({
197
+ className,
198
+ inset,
199
+ ...props
200
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Label> & {
201
+ inset?: boolean
202
+ }) {
203
+ return (
204
+ <ContextMenuPrimitive.Label
205
+ data-slot="context-menu-label"
206
+ data-inset={inset}
207
+ className={cn("text-muted-foreground px-2 py-1.5 text-xs font-medium data-inset:pl-8", className)}
208
+ {...props}
209
+ />
210
+ )
211
+ }
212
+
213
+ function ContextMenuSeparator({
214
+ className,
215
+ ...props
216
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Separator>) {
217
+ return (
218
+ <ContextMenuPrimitive.Separator
219
+ data-slot="context-menu-separator"
220
+ className={cn("bg-border -mx-1 my-1 h-px", className)}
221
+ {...props}
222
+ />
223
+ )
224
+ }
225
+
226
+ function ContextMenuShortcut({
227
+ className,
228
+ ...props
229
+ }: React.ComponentProps<"span">) {
230
+ return (
231
+ <span
232
+ data-slot="context-menu-shortcut"
233
+ className={cn("text-muted-foreground group-focus/context-menu-item:text-accent-foreground ml-auto text-xs tracking-widest", className)}
234
+ {...props}
235
+ />
236
+ )
237
+ }
238
+
239
+ export {
240
+ ContextMenu,
241
+ ContextMenuTrigger,
242
+ ContextMenuContent,
243
+ ContextMenuItem,
244
+ ContextMenuCheckboxItem,
245
+ ContextMenuRadioItem,
246
+ ContextMenuLabel,
247
+ ContextMenuSeparator,
248
+ ContextMenuShortcut,
249
+ ContextMenuGroup,
250
+ ContextMenuPortal,
251
+ ContextMenuSub,
252
+ ContextMenuSubContent,
253
+ ContextMenuSubTrigger,
254
+ ContextMenuRadioGroup,
255
+ }
@@ -0,0 +1,125 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { Drawer as DrawerPrimitive } from "vaul"
5
+
6
+ import { cn } from "../../lib/utils"
7
+
8
+ function Drawer({
9
+ ...props
10
+ }: React.ComponentProps<typeof DrawerPrimitive.Root>) {
11
+ return <DrawerPrimitive.Root data-slot="drawer" {...props} />
12
+ }
13
+
14
+ function DrawerTrigger({
15
+ ...props
16
+ }: React.ComponentProps<typeof DrawerPrimitive.Trigger>) {
17
+ return <DrawerPrimitive.Trigger data-slot="drawer-trigger" {...props} />
18
+ }
19
+
20
+ function DrawerPortal({
21
+ ...props
22
+ }: React.ComponentProps<typeof DrawerPrimitive.Portal>) {
23
+ return <DrawerPrimitive.Portal data-slot="drawer-portal" {...props} />
24
+ }
25
+
26
+ function DrawerClose({
27
+ ...props
28
+ }: React.ComponentProps<typeof DrawerPrimitive.Close>) {
29
+ return <DrawerPrimitive.Close data-slot="drawer-close" {...props} />
30
+ }
31
+
32
+ function DrawerOverlay({
33
+ className,
34
+ ...props
35
+ }: React.ComponentProps<typeof DrawerPrimitive.Overlay>) {
36
+ return (
37
+ <DrawerPrimitive.Overlay
38
+ data-slot="drawer-overlay"
39
+ className={cn("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/10 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 z-50", className)}
40
+ {...props}
41
+ />
42
+ )
43
+ }
44
+
45
+ function DrawerContent({
46
+ className,
47
+ children,
48
+ ...props
49
+ }: React.ComponentProps<typeof DrawerPrimitive.Content>) {
50
+ return (
51
+ <DrawerPortal data-slot="drawer-portal">
52
+ <DrawerOverlay />
53
+ <DrawerPrimitive.Content
54
+ data-slot="drawer-content"
55
+ className={cn(
56
+ "bg-background flex h-auto flex-col text-sm data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-xl data-[vaul-drawer-direction=bottom]:border-t data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:rounded-r-xl data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:rounded-l-xl data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-xl data-[vaul-drawer-direction=top]:border-b data-[vaul-drawer-direction=left]:sm:max-w-sm data-[vaul-drawer-direction=right]:sm:max-w-sm group/drawer-content fixed z-50",
57
+ className
58
+ )}
59
+ {...props}
60
+ >
61
+ <div className="bg-muted mt-4 h-1.5 w-[100px] rounded-full mx-auto hidden shrink-0 group-data-[vaul-drawer-direction=bottom]/drawer-content:block" />
62
+ {children}
63
+ </DrawerPrimitive.Content>
64
+ </DrawerPortal>
65
+ )
66
+ }
67
+
68
+ function DrawerHeader({ className, ...props }: React.ComponentProps<"div">) {
69
+ return (
70
+ <div
71
+ data-slot="drawer-header"
72
+ className={cn("gap-0.5 p-4 group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center group-data-[vaul-drawer-direction=top]/drawer-content:text-center md:gap-1.5 md:text-left flex flex-col", className)}
73
+ {...props}
74
+ />
75
+ )
76
+ }
77
+
78
+ function DrawerFooter({ className, ...props }: React.ComponentProps<"div">) {
79
+ return (
80
+ <div
81
+ data-slot="drawer-footer"
82
+ className={cn("gap-2 p-4 mt-auto flex flex-col", className)}
83
+ {...props}
84
+ />
85
+ )
86
+ }
87
+
88
+ function DrawerTitle({
89
+ className,
90
+ ...props
91
+ }: React.ComponentProps<typeof DrawerPrimitive.Title>) {
92
+ return (
93
+ <DrawerPrimitive.Title
94
+ data-slot="drawer-title"
95
+ className={cn("text-foreground font-medium", className)}
96
+ {...props}
97
+ />
98
+ )
99
+ }
100
+
101
+ function DrawerDescription({
102
+ className,
103
+ ...props
104
+ }: React.ComponentProps<typeof DrawerPrimitive.Description>) {
105
+ return (
106
+ <DrawerPrimitive.Description
107
+ data-slot="drawer-description"
108
+ className={cn("text-muted-foreground text-sm", className)}
109
+ {...props}
110
+ />
111
+ )
112
+ }
113
+
114
+ export {
115
+ Drawer,
116
+ DrawerPortal,
117
+ DrawerOverlay,
118
+ DrawerTrigger,
119
+ DrawerClose,
120
+ DrawerContent,
121
+ DrawerHeader,
122
+ DrawerFooter,
123
+ DrawerTitle,
124
+ DrawerDescription,
125
+ }
@@ -0,0 +1,44 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { HoverCard as HoverCardPrimitive } from "radix-ui"
5
+
6
+ import { cn } from "../../lib/utils"
7
+
8
+ function HoverCard({
9
+ ...props
10
+ }: React.ComponentProps<typeof HoverCardPrimitive.Root>) {
11
+ return <HoverCardPrimitive.Root data-slot="hover-card" {...props} />
12
+ }
13
+
14
+ function HoverCardTrigger({
15
+ ...props
16
+ }: React.ComponentProps<typeof HoverCardPrimitive.Trigger>) {
17
+ return (
18
+ <HoverCardPrimitive.Trigger data-slot="hover-card-trigger" {...props} />
19
+ )
20
+ }
21
+
22
+ function HoverCardContent({
23
+ className,
24
+ align = "center",
25
+ sideOffset = 4,
26
+ ...props
27
+ }: React.ComponentProps<typeof HoverCardPrimitive.Content>) {
28
+ return (
29
+ <HoverCardPrimitive.Portal data-slot="hover-card-portal">
30
+ <HoverCardPrimitive.Content
31
+ data-slot="hover-card-content"
32
+ align={align}
33
+ sideOffset={sideOffset}
34
+ className={cn(
35
+ "data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 ring-foreground/10 bg-popover text-popover-foreground w-64 rounded-lg p-4 text-sm shadow-md ring-1 duration-100 z-50 origin-(--radix-hover-card-content-transform-origin) outline-hidden",
36
+ className
37
+ )}
38
+ {...props}
39
+ />
40
+ </HoverCardPrimitive.Portal>
41
+ )
42
+ }
43
+
44
+ export { HoverCard, HoverCardTrigger, HoverCardContent }
@@ -0,0 +1,86 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { OTPInput, OTPInputContext } from "input-otp"
5
+
6
+ import { cn } from "../../lib/utils"
7
+ import { Minus } from "lucide-react"
8
+
9
+ function InputOTP({
10
+ className,
11
+ containerClassName,
12
+ ...props
13
+ }: React.ComponentProps<typeof OTPInput> & {
14
+ containerClassName?: string
15
+ }) {
16
+ return (
17
+ <OTPInput
18
+ data-slot="input-otp"
19
+ containerClassName={cn(
20
+ "cn-input-otp flex items-center has-disabled:opacity-50",
21
+ containerClassName
22
+ )}
23
+ spellCheck={false}
24
+ className={cn(
25
+ "disabled:cursor-not-allowed",
26
+ className
27
+ )}
28
+ {...props}
29
+ />
30
+ )
31
+ }
32
+
33
+ function InputOTPGroup({ className, ...props }: React.ComponentProps<"div">) {
34
+ return (
35
+ <div
36
+ data-slot="input-otp-group"
37
+ className={cn("has-aria-invalid:ring-destructive/20 dark:has-aria-invalid:ring-destructive/40 has-aria-invalid:border-destructive rounded-md has-aria-invalid:ring-3 flex items-center", className)}
38
+ {...props}
39
+ />
40
+ )
41
+ }
42
+
43
+ function InputOTPSlot({
44
+ index,
45
+ className,
46
+ ...props
47
+ }: React.ComponentProps<"div"> & {
48
+ index: number
49
+ }) {
50
+ const inputOTPContext = React.useContext(OTPInputContext)
51
+ const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {}
52
+
53
+ return (
54
+ <div
55
+ data-slot="input-otp-slot"
56
+ data-active={isActive}
57
+ className={cn(
58
+ "dark:bg-input/30 border-input data-[active=true]:border-ring data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:ring-destructive/20 dark:data-[active=true]:aria-invalid:ring-destructive/40 aria-invalid:border-destructive data-[active=true]:aria-invalid:border-destructive size-9 border-y border-r text-sm shadow-xs transition-all outline-none first:rounded-l-md first:border-l last:rounded-r-md data-[active=true]:ring-3 relative flex items-center justify-center data-[active=true]:z-10",
59
+ className
60
+ )}
61
+ {...props}
62
+ >
63
+ {char}
64
+ {hasFakeCaret && (
65
+ <div className="pointer-events-none absolute inset-0 flex items-center justify-center">
66
+ <div className="animate-caret-blink bg-foreground h-4 w-px duration-1000" />
67
+ </div>
68
+ )}
69
+ </div>
70
+ )
71
+ }
72
+
73
+ function InputOTPSeparator({ ...props }: React.ComponentProps<"div">) {
74
+ return (
75
+ <div
76
+ data-slot="input-otp-separator"
77
+ className="[&_svg:not([class*='size-'])]:size-4 flex items-center"
78
+ role="separator"
79
+ {...props}
80
+ >
81
+ <Minus />
82
+ </div>
83
+ )
84
+ }
85
+
86
+ export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator }