@clip-how/ui 0.1.6

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.
@@ -0,0 +1,175 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react";
5
+ import { Select as SelectPrimitive } from "radix-ui";
6
+
7
+ import { cn } from "../lib/utils";
8
+
9
+ function Select({ ...props }: React.ComponentProps<typeof SelectPrimitive.Root>) {
10
+ return <SelectPrimitive.Root data-slot="select" {...props} />;
11
+ }
12
+
13
+ function SelectGroup({ ...props }: React.ComponentProps<typeof SelectPrimitive.Group>) {
14
+ return <SelectPrimitive.Group data-slot="select-group" {...props} />;
15
+ }
16
+
17
+ function SelectValue({ ...props }: React.ComponentProps<typeof SelectPrimitive.Value>) {
18
+ return <SelectPrimitive.Value data-slot="select-value" {...props} />;
19
+ }
20
+
21
+ function SelectTrigger({
22
+ className,
23
+ size = "default",
24
+ children,
25
+ ...props
26
+ }: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
27
+ size?: "sm" | "default";
28
+ }) {
29
+ return (
30
+ <SelectPrimitive.Trigger
31
+ data-slot="select-trigger"
32
+ data-size={size}
33
+ className={cn(
34
+ "flex w-fit items-center justify-between gap-2 rounded-xl border border-input bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[placeholder]:text-muted-foreground data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground",
35
+ className,
36
+ )}
37
+ {...props}
38
+ >
39
+ {children}
40
+ <SelectPrimitive.Icon asChild>
41
+ <ChevronDownIcon className="size-4 opacity-50" />
42
+ </SelectPrimitive.Icon>
43
+ </SelectPrimitive.Trigger>
44
+ );
45
+ }
46
+
47
+ function SelectContent({
48
+ className,
49
+ children,
50
+ position = "item-aligned",
51
+ align = "center",
52
+ ...props
53
+ }: React.ComponentProps<typeof SelectPrimitive.Content>) {
54
+ return (
55
+ <SelectPrimitive.Portal>
56
+ <SelectPrimitive.Content
57
+ data-slot="select-content"
58
+ className={cn(
59
+ "relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg border bg-popover text-popover-foreground shadow-md 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 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
60
+ position === "popper" &&
61
+ "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
62
+ className,
63
+ )}
64
+ position={position}
65
+ align={align}
66
+ {...props}
67
+ >
68
+ <SelectScrollUpButton />
69
+ <SelectPrimitive.Viewport
70
+ className={cn(
71
+ "p-1",
72
+ position === "popper" &&
73
+ "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1",
74
+ )}
75
+ >
76
+ {children}
77
+ </SelectPrimitive.Viewport>
78
+ <SelectScrollDownButton />
79
+ </SelectPrimitive.Content>
80
+ </SelectPrimitive.Portal>
81
+ );
82
+ }
83
+
84
+ function SelectLabel({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.Label>) {
85
+ return (
86
+ <SelectPrimitive.Label
87
+ data-slot="select-label"
88
+ className={cn("px-2 py-1.5 text-xs text-muted-foreground", className)}
89
+ {...props}
90
+ />
91
+ );
92
+ }
93
+
94
+ function SelectItem({
95
+ className,
96
+ children,
97
+ ...props
98
+ }: React.ComponentProps<typeof SelectPrimitive.Item>) {
99
+ return (
100
+ <SelectPrimitive.Item
101
+ data-slot="select-item"
102
+ className={cn(
103
+ "relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
104
+ className,
105
+ )}
106
+ {...props}
107
+ >
108
+ <span
109
+ data-slot="select-item-indicator"
110
+ className="absolute right-2 flex size-3.5 items-center justify-center"
111
+ >
112
+ <SelectPrimitive.ItemIndicator>
113
+ <CheckIcon className="size-4" />
114
+ </SelectPrimitive.ItemIndicator>
115
+ </span>
116
+ <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
117
+ </SelectPrimitive.Item>
118
+ );
119
+ }
120
+
121
+ function SelectSeparator({
122
+ className,
123
+ ...props
124
+ }: React.ComponentProps<typeof SelectPrimitive.Separator>) {
125
+ return (
126
+ <SelectPrimitive.Separator
127
+ data-slot="select-separator"
128
+ className={cn("pointer-events-none -mx-1 my-1 h-px bg-border", className)}
129
+ {...props}
130
+ />
131
+ );
132
+ }
133
+
134
+ function SelectScrollUpButton({
135
+ className,
136
+ ...props
137
+ }: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {
138
+ return (
139
+ <SelectPrimitive.ScrollUpButton
140
+ data-slot="select-scroll-up-button"
141
+ className={cn("flex cursor-default items-center justify-center py-1", className)}
142
+ {...props}
143
+ >
144
+ <ChevronUpIcon className="size-4" />
145
+ </SelectPrimitive.ScrollUpButton>
146
+ );
147
+ }
148
+
149
+ function SelectScrollDownButton({
150
+ className,
151
+ ...props
152
+ }: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {
153
+ return (
154
+ <SelectPrimitive.ScrollDownButton
155
+ data-slot="select-scroll-down-button"
156
+ className={cn("flex cursor-default items-center justify-center py-1", className)}
157
+ {...props}
158
+ >
159
+ <ChevronDownIcon className="size-4" />
160
+ </SelectPrimitive.ScrollDownButton>
161
+ );
162
+ }
163
+
164
+ export {
165
+ Select,
166
+ SelectContent,
167
+ SelectGroup,
168
+ SelectItem,
169
+ SelectLabel,
170
+ SelectScrollDownButton,
171
+ SelectScrollUpButton,
172
+ SelectSeparator,
173
+ SelectTrigger,
174
+ SelectValue,
175
+ };
@@ -0,0 +1,28 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import { Separator as SeparatorPrimitive } from "radix-ui";
5
+
6
+ import { cn } from "../lib/utils";
7
+
8
+ function Separator({
9
+ className,
10
+ orientation = "horizontal",
11
+ decorative = true,
12
+ ...props
13
+ }: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
14
+ return (
15
+ <SeparatorPrimitive.Root
16
+ data-slot="separator"
17
+ decorative={decorative}
18
+ orientation={orientation}
19
+ className={cn(
20
+ "shrink-0 bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
21
+ className,
22
+ )}
23
+ {...props}
24
+ />
25
+ );
26
+ }
27
+
28
+ export { Separator };
@@ -0,0 +1,134 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import { XIcon } from "lucide-react";
5
+ import { Dialog as SheetPrimitive } from "radix-ui";
6
+
7
+ import { cn } from "../lib/utils";
8
+
9
+ function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
10
+ return <SheetPrimitive.Root data-slot="sheet" {...props} />;
11
+ }
12
+
13
+ function SheetTrigger({ ...props }: React.ComponentProps<typeof SheetPrimitive.Trigger>) {
14
+ return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />;
15
+ }
16
+
17
+ function SheetClose({ ...props }: React.ComponentProps<typeof SheetPrimitive.Close>) {
18
+ return <SheetPrimitive.Close data-slot="sheet-close" {...props} />;
19
+ }
20
+
21
+ function SheetPortal({ ...props }: React.ComponentProps<typeof SheetPrimitive.Portal>) {
22
+ return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />;
23
+ }
24
+
25
+ function SheetOverlay({
26
+ className,
27
+ ...props
28
+ }: React.ComponentProps<typeof SheetPrimitive.Overlay>) {
29
+ return (
30
+ <SheetPrimitive.Overlay
31
+ data-slot="sheet-overlay"
32
+ className={cn(
33
+ "fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0",
34
+ className,
35
+ )}
36
+ {...props}
37
+ />
38
+ );
39
+ }
40
+
41
+ function SheetContent({
42
+ className,
43
+ children,
44
+ side = "right",
45
+ showCloseButton = true,
46
+ ...props
47
+ }: React.ComponentProps<typeof SheetPrimitive.Content> & {
48
+ side?: "top" | "right" | "bottom" | "left";
49
+ showCloseButton?: boolean;
50
+ }) {
51
+ return (
52
+ <SheetPortal>
53
+ <SheetOverlay />
54
+ <SheetPrimitive.Content
55
+ data-slot="sheet-content"
56
+ className={cn(
57
+ "fixed z-50 flex flex-col gap-4 bg-background shadow-lg transition ease-in-out data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:animate-in data-[state=open]:duration-500",
58
+ side === "right" &&
59
+ "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
60
+ side === "left" &&
61
+ "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
62
+ side === "top" &&
63
+ "inset-x-0 top-0 h-auto border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
64
+ side === "bottom" &&
65
+ "inset-x-0 bottom-0 h-auto border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
66
+ className,
67
+ )}
68
+ {...props}
69
+ >
70
+ {children}
71
+ {showCloseButton && (
72
+ <SheetPrimitive.Close className="absolute top-4 right-4 rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none data-[state=open]:bg-secondary">
73
+ <XIcon className="size-4" />
74
+ <span className="sr-only">Close</span>
75
+ </SheetPrimitive.Close>
76
+ )}
77
+ </SheetPrimitive.Content>
78
+ </SheetPortal>
79
+ );
80
+ }
81
+
82
+ function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
83
+ return (
84
+ <div
85
+ data-slot="sheet-header"
86
+ className={cn("flex flex-col gap-1.5 p-4", className)}
87
+ {...props}
88
+ />
89
+ );
90
+ }
91
+
92
+ function SheetFooter({ className, ...props }: React.ComponentProps<"div">) {
93
+ return (
94
+ <div
95
+ data-slot="sheet-footer"
96
+ className={cn("mt-auto flex flex-col gap-2 p-4", className)}
97
+ {...props}
98
+ />
99
+ );
100
+ }
101
+
102
+ function SheetTitle({ className, ...props }: React.ComponentProps<typeof SheetPrimitive.Title>) {
103
+ return (
104
+ <SheetPrimitive.Title
105
+ data-slot="sheet-title"
106
+ className={cn("font-semibold text-foreground", className)}
107
+ {...props}
108
+ />
109
+ );
110
+ }
111
+
112
+ function SheetDescription({
113
+ className,
114
+ ...props
115
+ }: React.ComponentProps<typeof SheetPrimitive.Description>) {
116
+ return (
117
+ <SheetPrimitive.Description
118
+ data-slot="sheet-description"
119
+ className={cn("text-sm text-muted-foreground", className)}
120
+ {...props}
121
+ />
122
+ );
123
+ }
124
+
125
+ export {
126
+ Sheet,
127
+ SheetTrigger,
128
+ SheetClose,
129
+ SheetContent,
130
+ SheetHeader,
131
+ SheetFooter,
132
+ SheetTitle,
133
+ SheetDescription,
134
+ };
@@ -0,0 +1,13 @@
1
+ import { cn } from "../lib/utils";
2
+
3
+ function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
4
+ return (
5
+ <div
6
+ data-slot="skeleton"
7
+ className={cn("animate-pulse rounded-md bg-accent", className)}
8
+ {...props}
9
+ />
10
+ );
11
+ }
12
+
13
+ export { Skeleton };
@@ -0,0 +1,40 @@
1
+ "use client";
2
+
3
+ import {
4
+ CircleCheckIcon,
5
+ InfoIcon,
6
+ Loader2Icon,
7
+ OctagonXIcon,
8
+ TriangleAlertIcon,
9
+ } from "lucide-react";
10
+ import { useTheme } from "next-themes";
11
+ import { Toaster as Sonner, type ToasterProps } from "sonner";
12
+
13
+ const Toaster = ({ ...props }: ToasterProps) => {
14
+ const { theme = "system" } = useTheme();
15
+
16
+ return (
17
+ <Sonner
18
+ theme={theme as ToasterProps["theme"]}
19
+ className="toaster group"
20
+ icons={{
21
+ success: <CircleCheckIcon className="size-4" />,
22
+ info: <InfoIcon className="size-4" />,
23
+ warning: <TriangleAlertIcon className="size-4" />,
24
+ error: <OctagonXIcon className="size-4" />,
25
+ loading: <Loader2Icon className="size-4 animate-spin" />,
26
+ }}
27
+ style={
28
+ {
29
+ "--normal-bg": "var(--popover)",
30
+ "--normal-text": "var(--popover-foreground)",
31
+ "--normal-border": "var(--border)",
32
+ "--border-radius": "var(--radius)",
33
+ } as React.CSSProperties
34
+ }
35
+ {...props}
36
+ />
37
+ );
38
+ };
39
+
40
+ export { Toaster };
@@ -0,0 +1,28 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import * as SwitchPrimitives from "@radix-ui/react-switch";
5
+ import { cn } from "../lib/utils";
6
+
7
+ const Switch = React.forwardRef<
8
+ React.ComponentRef<typeof SwitchPrimitives.Root>,
9
+ React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>
10
+ >(({ className, ...props }, ref) => (
11
+ <SwitchPrimitives.Root
12
+ className={cn(
13
+ "peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
14
+ className,
15
+ )}
16
+ {...props}
17
+ ref={ref}
18
+ >
19
+ <SwitchPrimitives.Thumb
20
+ className={cn(
21
+ "pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0",
22
+ )}
23
+ />
24
+ </SwitchPrimitives.Root>
25
+ ));
26
+ Switch.displayName = SwitchPrimitives.Root.displayName;
27
+
28
+ export { Switch };
@@ -0,0 +1,92 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+
5
+ import { cn } from "../lib/utils";
6
+
7
+ function Table({ className, ...props }: React.ComponentProps<"table">) {
8
+ return (
9
+ <div data-slot="table-container" className="relative w-full overflow-x-auto">
10
+ <table
11
+ data-slot="table"
12
+ className={cn("w-full caption-bottom text-sm", className)}
13
+ {...props}
14
+ />
15
+ </div>
16
+ );
17
+ }
18
+
19
+ function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
20
+ return <thead data-slot="table-header" className={cn("[&_tr]:border-b", className)} {...props} />;
21
+ }
22
+
23
+ function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
24
+ return (
25
+ <tbody
26
+ data-slot="table-body"
27
+ className={cn("[&_tr:last-child]:border-0", className)}
28
+ {...props}
29
+ />
30
+ );
31
+ }
32
+
33
+ function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
34
+ return (
35
+ <tfoot
36
+ data-slot="table-footer"
37
+ className={cn("border-t bg-muted/50 font-medium [&>tr]:last:border-b-0", className)}
38
+ {...props}
39
+ />
40
+ );
41
+ }
42
+
43
+ function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
44
+ return (
45
+ <tr
46
+ data-slot="table-row"
47
+ className={cn(
48
+ "border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
49
+ className,
50
+ )}
51
+ {...props}
52
+ />
53
+ );
54
+ }
55
+
56
+ function TableHead({ className, ...props }: React.ComponentProps<"th">) {
57
+ return (
58
+ <th
59
+ data-slot="table-head"
60
+ className={cn(
61
+ "h-10 px-2 text-left align-middle text-xs font-semibold uppercase tracking-wider whitespace-nowrap text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
62
+ className,
63
+ )}
64
+ {...props}
65
+ />
66
+ );
67
+ }
68
+
69
+ function TableCell({ className, ...props }: React.ComponentProps<"td">) {
70
+ return (
71
+ <td
72
+ data-slot="table-cell"
73
+ className={cn(
74
+ "p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
75
+ className,
76
+ )}
77
+ {...props}
78
+ />
79
+ );
80
+ }
81
+
82
+ function TableCaption({ className, ...props }: React.ComponentProps<"caption">) {
83
+ return (
84
+ <caption
85
+ data-slot="table-caption"
86
+ className={cn("mt-4 text-sm text-muted-foreground", className)}
87
+ {...props}
88
+ />
89
+ );
90
+ }
91
+
92
+ export { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption };
@@ -0,0 +1,81 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import { cva, type VariantProps } from "class-variance-authority";
5
+ import { Tabs as TabsPrimitive } from "radix-ui";
6
+
7
+ import { cn } from "../lib/utils";
8
+
9
+ function Tabs({
10
+ className,
11
+ orientation = "horizontal",
12
+ ...props
13
+ }: React.ComponentProps<typeof TabsPrimitive.Root>) {
14
+ return (
15
+ <TabsPrimitive.Root
16
+ data-slot="tabs"
17
+ data-orientation={orientation}
18
+ orientation={orientation}
19
+ className={cn("group/tabs flex gap-2 data-[orientation=horizontal]:flex-col", className)}
20
+ {...props}
21
+ />
22
+ );
23
+ }
24
+
25
+ const tabsListVariants = cva(
26
+ "group/tabs-list inline-flex w-fit items-center justify-center flex-wrap gap-2 rounded-lg p-[3px] text-muted-foreground group-data-[orientation=horizontal]/tabs:h-auto group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col data-[variant=line]:rounded-none",
27
+ {
28
+ variants: {
29
+ variant: {
30
+ default: "bg-muted",
31
+ line: "gap-1 bg-transparent",
32
+ },
33
+ },
34
+ defaultVariants: {
35
+ variant: "default",
36
+ },
37
+ },
38
+ );
39
+
40
+ function TabsList({
41
+ className,
42
+ variant = "default",
43
+ ...props
44
+ }: React.ComponentProps<typeof TabsPrimitive.List> & VariantProps<typeof tabsListVariants>) {
45
+ return (
46
+ <TabsPrimitive.List
47
+ data-slot="tabs-list"
48
+ data-variant={variant}
49
+ className={cn(tabsListVariants({ variant }), className)}
50
+ {...props}
51
+ />
52
+ );
53
+ }
54
+
55
+ function TabsTrigger({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
56
+ return (
57
+ <TabsPrimitive.Trigger
58
+ data-slot="tabs-trigger"
59
+ className={cn(
60
+ "relative inline-flex h-9 items-center justify-center gap-1.5 rounded-md border border-transparent px-3 py-1.5 text-sm font-medium whitespace-nowrap text-foreground/60 transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50 group-data-[variant=default]/tabs-list:data-[state=active]:shadow-sm group-data-[variant=line]/tabs-list:data-[state=active]:shadow-none dark:text-muted-foreground dark:hover:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
61
+ "group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:border-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent",
62
+ "data-[state=active]:bg-background data-[state=active]:text-foreground dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 dark:data-[state=active]:text-foreground",
63
+ "after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-[state=active]:after:opacity-100",
64
+ className,
65
+ )}
66
+ {...props}
67
+ />
68
+ );
69
+ }
70
+
71
+ function TabsContent({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Content>) {
72
+ return (
73
+ <TabsPrimitive.Content
74
+ data-slot="tabs-content"
75
+ className={cn("flex-1 outline-none", className)}
76
+ {...props}
77
+ />
78
+ );
79
+ }
80
+
81
+ export { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants };
@@ -0,0 +1,18 @@
1
+ import * as React from "react";
2
+
3
+ import { cn } from "../lib/utils";
4
+
5
+ function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
6
+ return (
7
+ <textarea
8
+ data-slot="textarea"
9
+ className={cn(
10
+ "flex field-sizing-content min-h-16 w-full resize-none rounded-xl border border-input bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:aria-invalid:ring-destructive/40",
11
+ className,
12
+ )}
13
+ {...props}
14
+ />
15
+ );
16
+ }
17
+
18
+ export { Textarea };
@@ -0,0 +1,53 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import { Tooltip as TooltipPrimitive } from "radix-ui";
5
+
6
+ import { cn } from "../lib/utils";
7
+
8
+ function TooltipProvider({
9
+ delayDuration = 0,
10
+ ...props
11
+ }: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
12
+ return (
13
+ <TooltipPrimitive.Provider
14
+ data-slot="tooltip-provider"
15
+ delayDuration={delayDuration}
16
+ {...props}
17
+ />
18
+ );
19
+ }
20
+
21
+ function Tooltip({ ...props }: React.ComponentProps<typeof TooltipPrimitive.Root>) {
22
+ return <TooltipPrimitive.Root data-slot="tooltip" {...props} />;
23
+ }
24
+
25
+ function TooltipTrigger({ ...props }: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
26
+ return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />;
27
+ }
28
+
29
+ function TooltipContent({
30
+ className,
31
+ sideOffset = 0,
32
+ children,
33
+ ...props
34
+ }: React.ComponentProps<typeof TooltipPrimitive.Content>) {
35
+ return (
36
+ <TooltipPrimitive.Portal>
37
+ <TooltipPrimitive.Content
38
+ data-slot="tooltip-content"
39
+ sideOffset={sideOffset}
40
+ className={cn(
41
+ "z-50 w-fit origin-(--radix-tooltip-content-transform-origin) animate-in rounded-md bg-foreground px-3 py-1.5 text-xs text-balance text-background fade-in-0 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 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
42
+ className,
43
+ )}
44
+ {...props}
45
+ >
46
+ {children}
47
+ <TooltipPrimitive.Arrow className="z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground" />
48
+ </TooltipPrimitive.Content>
49
+ </TooltipPrimitive.Portal>
50
+ );
51
+ }
52
+
53
+ export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
package/lib/utils.ts ADDED
@@ -0,0 +1,12 @@
1
+ import { clsx, type ClassValue } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ /**
5
+ * Tailwind-aware class concatenation. The one helper every shadcn
6
+ * component imports via `import { cn } from "@/lib/utils"`. By living
7
+ * here it stays in lockstep with the component primitives that depend
8
+ * on it — bump them together if their semantics ever diverge.
9
+ */
10
+ export function cn(...inputs: ClassValue[]) {
11
+ return twMerge(clsx(inputs));
12
+ }