@openconsole/shadcn 0.0.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +380 -0
- package/accordion.tsx +66 -66
- package/alert-dialog.tsx +196 -196
- package/alert.tsx +66 -66
- package/aspect-ratio.tsx +11 -11
- package/avatar.tsx +53 -53
- package/badge.tsx +46 -46
- package/breadcrumb.tsx +109 -109
- package/button-group.tsx +83 -83
- package/button.tsx +60 -60
- package/calendar.tsx +219 -219
- package/card.tsx +92 -92
- package/carousel.tsx +241 -241
- package/chart.tsx +374 -374
- package/checkbox.tsx +32 -32
- package/collapsible.tsx +33 -33
- package/command.tsx +184 -184
- package/context-menu.tsx +252 -252
- package/dialog.tsx +143 -143
- package/direction.tsx +22 -22
- package/drawer.tsx +135 -135
- package/dropdown-menu.tsx +257 -257
- package/empty.tsx +104 -104
- package/field.tsx +248 -248
- package/form.tsx +167 -167
- package/hooks/index.ts +1 -1
- package/hooks/use-mobile.ts +19 -19
- package/hover-card.tsx +44 -44
- package/icon.tsx +21 -21
- package/index.ts +59 -59
- package/input-group.tsx +170 -170
- package/input-otp.tsx +77 -77
- package/input.tsx +21 -21
- package/item.tsx +193 -193
- package/kbd.tsx +28 -28
- package/label.tsx +24 -24
- package/lib/index.ts +1 -1
- package/lib/utils.ts +6 -6
- package/menubar.tsx +276 -276
- package/native-select.tsx +62 -62
- package/navigation-menu.tsx +168 -168
- package/package.json +10 -2
- package/pagination.tsx +127 -127
- package/popover.tsx +89 -89
- package/progress.tsx +31 -31
- package/radio-group.tsx +45 -45
- package/resizable.tsx +53 -53
- package/scroll-area.tsx +58 -58
- package/select.tsx +187 -187
- package/separator.tsx +28 -28
- package/sheet.tsx +139 -139
- package/sidebar.tsx +724 -724
- package/skeleton.tsx +13 -13
- package/slider.tsx +63 -63
- package/sonner.tsx +40 -40
- package/spinner.tsx +16 -16
- package/styles.css +122 -0
- package/switch.tsx +35 -35
- package/table.tsx +116 -116
- package/tabs.tsx +66 -66
- package/textarea.tsx +18 -18
- package/toggle-group.tsx +83 -83
- package/toggle.tsx +47 -47
- package/tooltip.tsx +61 -61
- package/tsconfig.json +12 -12
- package/tsconfig.tsbuildinfo +1 -1
- package/skill/SKILL.md +0 -599
- package/skill/customization.md +0 -263
- package/skill/rules/base-vs-radix.md +0 -167
- package/skill/rules/composition.md +0 -240
- package/skill/rules/forms.md +0 -271
- package/skill/rules/icons.md +0 -136
- package/skill/rules/styling.md +0 -180
package/form.tsx
CHANGED
|
@@ -1,167 +1,167 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
import { Label as LabelPrimitive, Slot } from "radix-ui";
|
|
5
|
-
import {
|
|
6
|
-
Controller,
|
|
7
|
-
FormProvider,
|
|
8
|
-
useFormContext,
|
|
9
|
-
useFormState,
|
|
10
|
-
type ControllerProps,
|
|
11
|
-
type FieldPath,
|
|
12
|
-
type FieldValues,
|
|
13
|
-
} from "react-hook-form";
|
|
14
|
-
|
|
15
|
-
import { cn } from "./lib/utils";
|
|
16
|
-
import { Label } from "./label";
|
|
17
|
-
|
|
18
|
-
const Form = FormProvider;
|
|
19
|
-
|
|
20
|
-
type FormFieldContextValue<
|
|
21
|
-
TFieldValues extends FieldValues = FieldValues,
|
|
22
|
-
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
|
|
23
|
-
> = {
|
|
24
|
-
name: TName;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const FormFieldContext = React.createContext<FormFieldContextValue | null>(
|
|
28
|
-
null,
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
const FormField = <
|
|
32
|
-
TFieldValues extends FieldValues = FieldValues,
|
|
33
|
-
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
|
|
34
|
-
>({
|
|
35
|
-
...props
|
|
36
|
-
}: ControllerProps<TFieldValues, TName>) => {
|
|
37
|
-
return (
|
|
38
|
-
<FormFieldContext.Provider value={{ name: props.name }}>
|
|
39
|
-
<Controller {...props} />
|
|
40
|
-
</FormFieldContext.Provider>
|
|
41
|
-
);
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
type FormItemContextValue = {
|
|
45
|
-
id: string;
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
const FormItemContext = React.createContext<FormItemContextValue | null>(null);
|
|
49
|
-
|
|
50
|
-
const useFormField = () => {
|
|
51
|
-
const fieldContext = React.useContext(FormFieldContext);
|
|
52
|
-
const itemContext = React.useContext(FormItemContext);
|
|
53
|
-
if (!fieldContext) {
|
|
54
|
-
throw new Error("useFormField should be used within <FormField>");
|
|
55
|
-
}
|
|
56
|
-
if (!itemContext) {
|
|
57
|
-
throw new Error("useFormField should be used within <FormItem>");
|
|
58
|
-
}
|
|
59
|
-
const { getFieldState } = useFormContext();
|
|
60
|
-
const formState = useFormState({ name: fieldContext.name });
|
|
61
|
-
const fieldState = getFieldState(fieldContext.name, formState);
|
|
62
|
-
|
|
63
|
-
const { id } = itemContext;
|
|
64
|
-
|
|
65
|
-
return {
|
|
66
|
-
id,
|
|
67
|
-
name: fieldContext.name,
|
|
68
|
-
formItemId: `${id}-form-item`,
|
|
69
|
-
formDescriptionId: `${id}-form-item-description`,
|
|
70
|
-
formMessageId: `${id}-form-item-message`,
|
|
71
|
-
...fieldState,
|
|
72
|
-
};
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
function FormItem({ className, ...props }: React.ComponentProps<"div">) {
|
|
76
|
-
const id = React.useId();
|
|
77
|
-
|
|
78
|
-
return (
|
|
79
|
-
<FormItemContext.Provider value={{ id }}>
|
|
80
|
-
<div
|
|
81
|
-
data-slot="form-item"
|
|
82
|
-
className={cn("grid gap-2", className)}
|
|
83
|
-
{...props}
|
|
84
|
-
/>
|
|
85
|
-
</FormItemContext.Provider>
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function FormLabel({
|
|
90
|
-
className,
|
|
91
|
-
...props
|
|
92
|
-
}: React.ComponentProps<typeof LabelPrimitive.Root>) {
|
|
93
|
-
const { error, formItemId } = useFormField();
|
|
94
|
-
|
|
95
|
-
return (
|
|
96
|
-
<Label
|
|
97
|
-
data-slot="form-label"
|
|
98
|
-
data-error={!!error}
|
|
99
|
-
className={cn("data-[error=true]:text-destructive", className)}
|
|
100
|
-
htmlFor={formItemId}
|
|
101
|
-
{...props}
|
|
102
|
-
/>
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function FormControl({ ...props }: React.ComponentProps<typeof Slot.Root>) {
|
|
107
|
-
const { error, formItemId, formDescriptionId, formMessageId } =
|
|
108
|
-
useFormField();
|
|
109
|
-
|
|
110
|
-
return (
|
|
111
|
-
<Slot.Root
|
|
112
|
-
data-slot="form-control"
|
|
113
|
-
id={formItemId}
|
|
114
|
-
aria-describedby={
|
|
115
|
-
!error
|
|
116
|
-
? `${formDescriptionId}`
|
|
117
|
-
: `${formDescriptionId} ${formMessageId}`
|
|
118
|
-
}
|
|
119
|
-
aria-invalid={!!error}
|
|
120
|
-
{...props}
|
|
121
|
-
/>
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function FormDescription({ className, ...props }: React.ComponentProps<"p">) {
|
|
126
|
-
const { formDescriptionId } = useFormField();
|
|
127
|
-
|
|
128
|
-
return (
|
|
129
|
-
<p
|
|
130
|
-
data-slot="form-description"
|
|
131
|
-
id={formDescriptionId}
|
|
132
|
-
className={cn("text-sm text-muted-foreground", className)}
|
|
133
|
-
{...props}
|
|
134
|
-
/>
|
|
135
|
-
);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
function FormMessage({ className, ...props }: React.ComponentProps<"p">) {
|
|
139
|
-
const { error, formMessageId } = useFormField();
|
|
140
|
-
const body = error ? String(error?.message ?? "") : props.children;
|
|
141
|
-
|
|
142
|
-
if (!body) {
|
|
143
|
-
return null;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return (
|
|
147
|
-
<p
|
|
148
|
-
data-slot="form-message"
|
|
149
|
-
id={formMessageId}
|
|
150
|
-
className={cn("text-sm text-destructive", className)}
|
|
151
|
-
{...props}
|
|
152
|
-
>
|
|
153
|
-
{body}
|
|
154
|
-
</p>
|
|
155
|
-
);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
export {
|
|
159
|
-
useFormField,
|
|
160
|
-
Form,
|
|
161
|
-
FormItem,
|
|
162
|
-
FormLabel,
|
|
163
|
-
FormControl,
|
|
164
|
-
FormDescription,
|
|
165
|
-
FormMessage,
|
|
166
|
-
FormField,
|
|
167
|
-
};
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Label as LabelPrimitive, Slot } from "radix-ui";
|
|
5
|
+
import {
|
|
6
|
+
Controller,
|
|
7
|
+
FormProvider,
|
|
8
|
+
useFormContext,
|
|
9
|
+
useFormState,
|
|
10
|
+
type ControllerProps,
|
|
11
|
+
type FieldPath,
|
|
12
|
+
type FieldValues,
|
|
13
|
+
} from "react-hook-form";
|
|
14
|
+
|
|
15
|
+
import { cn } from "./lib/utils";
|
|
16
|
+
import { Label } from "./label";
|
|
17
|
+
|
|
18
|
+
const Form = FormProvider;
|
|
19
|
+
|
|
20
|
+
type FormFieldContextValue<
|
|
21
|
+
TFieldValues extends FieldValues = FieldValues,
|
|
22
|
+
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
|
|
23
|
+
> = {
|
|
24
|
+
name: TName;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const FormFieldContext = React.createContext<FormFieldContextValue | null>(
|
|
28
|
+
null,
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const FormField = <
|
|
32
|
+
TFieldValues extends FieldValues = FieldValues,
|
|
33
|
+
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
|
|
34
|
+
>({
|
|
35
|
+
...props
|
|
36
|
+
}: ControllerProps<TFieldValues, TName>) => {
|
|
37
|
+
return (
|
|
38
|
+
<FormFieldContext.Provider value={{ name: props.name }}>
|
|
39
|
+
<Controller {...props} />
|
|
40
|
+
</FormFieldContext.Provider>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
type FormItemContextValue = {
|
|
45
|
+
id: string;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const FormItemContext = React.createContext<FormItemContextValue | null>(null);
|
|
49
|
+
|
|
50
|
+
const useFormField = () => {
|
|
51
|
+
const fieldContext = React.useContext(FormFieldContext);
|
|
52
|
+
const itemContext = React.useContext(FormItemContext);
|
|
53
|
+
if (!fieldContext) {
|
|
54
|
+
throw new Error("useFormField should be used within <FormField>");
|
|
55
|
+
}
|
|
56
|
+
if (!itemContext) {
|
|
57
|
+
throw new Error("useFormField should be used within <FormItem>");
|
|
58
|
+
}
|
|
59
|
+
const { getFieldState } = useFormContext();
|
|
60
|
+
const formState = useFormState({ name: fieldContext.name });
|
|
61
|
+
const fieldState = getFieldState(fieldContext.name, formState);
|
|
62
|
+
|
|
63
|
+
const { id } = itemContext;
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
id,
|
|
67
|
+
name: fieldContext.name,
|
|
68
|
+
formItemId: `${id}-form-item`,
|
|
69
|
+
formDescriptionId: `${id}-form-item-description`,
|
|
70
|
+
formMessageId: `${id}-form-item-message`,
|
|
71
|
+
...fieldState,
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
function FormItem({ className, ...props }: React.ComponentProps<"div">) {
|
|
76
|
+
const id = React.useId();
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<FormItemContext.Provider value={{ id }}>
|
|
80
|
+
<div
|
|
81
|
+
data-slot="form-item"
|
|
82
|
+
className={cn("grid gap-2", className)}
|
|
83
|
+
{...props}
|
|
84
|
+
/>
|
|
85
|
+
</FormItemContext.Provider>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function FormLabel({
|
|
90
|
+
className,
|
|
91
|
+
...props
|
|
92
|
+
}: React.ComponentProps<typeof LabelPrimitive.Root>) {
|
|
93
|
+
const { error, formItemId } = useFormField();
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<Label
|
|
97
|
+
data-slot="form-label"
|
|
98
|
+
data-error={!!error}
|
|
99
|
+
className={cn("data-[error=true]:text-destructive", className)}
|
|
100
|
+
htmlFor={formItemId}
|
|
101
|
+
{...props}
|
|
102
|
+
/>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function FormControl({ ...props }: React.ComponentProps<typeof Slot.Root>) {
|
|
107
|
+
const { error, formItemId, formDescriptionId, formMessageId } =
|
|
108
|
+
useFormField();
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<Slot.Root
|
|
112
|
+
data-slot="form-control"
|
|
113
|
+
id={formItemId}
|
|
114
|
+
aria-describedby={
|
|
115
|
+
!error
|
|
116
|
+
? `${formDescriptionId}`
|
|
117
|
+
: `${formDescriptionId} ${formMessageId}`
|
|
118
|
+
}
|
|
119
|
+
aria-invalid={!!error}
|
|
120
|
+
{...props}
|
|
121
|
+
/>
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function FormDescription({ className, ...props }: React.ComponentProps<"p">) {
|
|
126
|
+
const { formDescriptionId } = useFormField();
|
|
127
|
+
|
|
128
|
+
return (
|
|
129
|
+
<p
|
|
130
|
+
data-slot="form-description"
|
|
131
|
+
id={formDescriptionId}
|
|
132
|
+
className={cn("text-sm text-muted-foreground", className)}
|
|
133
|
+
{...props}
|
|
134
|
+
/>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function FormMessage({ className, ...props }: React.ComponentProps<"p">) {
|
|
139
|
+
const { error, formMessageId } = useFormField();
|
|
140
|
+
const body = error ? String(error?.message ?? "") : props.children;
|
|
141
|
+
|
|
142
|
+
if (!body) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return (
|
|
147
|
+
<p
|
|
148
|
+
data-slot="form-message"
|
|
149
|
+
id={formMessageId}
|
|
150
|
+
className={cn("text-sm text-destructive", className)}
|
|
151
|
+
{...props}
|
|
152
|
+
>
|
|
153
|
+
{body}
|
|
154
|
+
</p>
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export {
|
|
159
|
+
useFormField,
|
|
160
|
+
Form,
|
|
161
|
+
FormItem,
|
|
162
|
+
FormLabel,
|
|
163
|
+
FormControl,
|
|
164
|
+
FormDescription,
|
|
165
|
+
FormMessage,
|
|
166
|
+
FormField,
|
|
167
|
+
};
|
package/hooks/index.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from "./use-mobile";
|
|
1
|
+
export * from "./use-mobile";
|
package/hooks/use-mobile.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
|
|
3
|
-
const MOBILE_BREAKPOINT = 768;
|
|
4
|
-
|
|
5
|
-
export function useIsMobile() {
|
|
6
|
-
const [isMobile, setIsMobile] = React.useState<boolean>(false);
|
|
7
|
-
|
|
8
|
-
React.useEffect(() => {
|
|
9
|
-
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
|
10
|
-
const onChange = (event: MediaQueryListEvent | MediaQueryList) => {
|
|
11
|
-
setIsMobile(event.matches);
|
|
12
|
-
};
|
|
13
|
-
onChange(mql);
|
|
14
|
-
mql.addEventListener("change", onChange);
|
|
15
|
-
return () => mql.removeEventListener("change", onChange);
|
|
16
|
-
}, []);
|
|
17
|
-
|
|
18
|
-
return isMobile;
|
|
19
|
-
}
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
const MOBILE_BREAKPOINT = 768;
|
|
4
|
+
|
|
5
|
+
export function useIsMobile() {
|
|
6
|
+
const [isMobile, setIsMobile] = React.useState<boolean>(false);
|
|
7
|
+
|
|
8
|
+
React.useEffect(() => {
|
|
9
|
+
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
|
10
|
+
const onChange = (event: MediaQueryListEvent | MediaQueryList) => {
|
|
11
|
+
setIsMobile(event.matches);
|
|
12
|
+
};
|
|
13
|
+
onChange(mql);
|
|
14
|
+
mql.addEventListener("change", onChange);
|
|
15
|
+
return () => mql.removeEventListener("change", onChange);
|
|
16
|
+
}, []);
|
|
17
|
+
|
|
18
|
+
return isMobile;
|
|
19
|
+
}
|
package/hover-card.tsx
CHANGED
|
@@ -1,44 +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
|
-
"z-50 w-64 origin-(--radix-hover-card-content-transform-origin) rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-hidden 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",
|
|
36
|
-
className
|
|
37
|
-
)}
|
|
38
|
-
{...props}
|
|
39
|
-
/>
|
|
40
|
-
</HoverCardPrimitive.Portal>
|
|
41
|
-
)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export { HoverCard, HoverCardTrigger, HoverCardContent }
|
|
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
|
+
"z-50 w-64 origin-(--radix-hover-card-content-transform-origin) rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-hidden 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",
|
|
36
|
+
className
|
|
37
|
+
)}
|
|
38
|
+
{...props}
|
|
39
|
+
/>
|
|
40
|
+
</HoverCardPrimitive.Portal>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export { HoverCard, HoverCardTrigger, HoverCardContent }
|
package/icon.tsx
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { icons as lucideIcons, type LucideProps } from "lucide-react";
|
|
4
|
-
|
|
5
|
-
interface IconProps extends LucideProps {
|
|
6
|
-
/** lucide-react icon name in PascalCase (e.g. "LayoutDashboard"). */
|
|
7
|
-
name?: string;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Render a lucide-react icon by name.
|
|
12
|
-
*
|
|
13
|
-
* Sider data keeps icon references as plain strings so it stays serializable
|
|
14
|
-
* across the React Server / Client boundary. The actual component lookup
|
|
15
|
-
* happens here, inside the client.
|
|
16
|
-
*/
|
|
17
|
-
export function Icon({ name, ...props }: IconProps) {
|
|
18
|
-
if (!name) return null;
|
|
19
|
-
const LucideIcon = lucideIcons[name as keyof typeof lucideIcons];
|
|
20
|
-
return LucideIcon ? <LucideIcon {...props} /> : null;
|
|
21
|
-
}
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { icons as lucideIcons, type LucideProps } from "lucide-react";
|
|
4
|
+
|
|
5
|
+
interface IconProps extends LucideProps {
|
|
6
|
+
/** lucide-react icon name in PascalCase (e.g. "LayoutDashboard"). */
|
|
7
|
+
name?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Render a lucide-react icon by name.
|
|
12
|
+
*
|
|
13
|
+
* Sider data keeps icon references as plain strings so it stays serializable
|
|
14
|
+
* across the React Server / Client boundary. The actual component lookup
|
|
15
|
+
* happens here, inside the client.
|
|
16
|
+
*/
|
|
17
|
+
export function Icon({ name, ...props }: IconProps) {
|
|
18
|
+
if (!name) return null;
|
|
19
|
+
const LucideIcon = lucideIcons[name as keyof typeof lucideIcons];
|
|
20
|
+
return LucideIcon ? <LucideIcon {...props} /> : null;
|
|
21
|
+
}
|
package/index.ts
CHANGED
|
@@ -1,59 +1,59 @@
|
|
|
1
|
-
export * from "./lib";
|
|
2
|
-
export * from "./hooks";
|
|
3
|
-
|
|
4
|
-
export * from "./accordion";
|
|
5
|
-
export * from "./alert";
|
|
6
|
-
export * from "./alert-dialog";
|
|
7
|
-
export * from "./aspect-ratio";
|
|
8
|
-
export * from "./avatar";
|
|
9
|
-
export * from "./badge";
|
|
10
|
-
export * from "./breadcrumb";
|
|
11
|
-
export * from "./button";
|
|
12
|
-
export * from "./button-group";
|
|
13
|
-
export * from "./calendar";
|
|
14
|
-
export * from "./card";
|
|
15
|
-
export * from "./carousel";
|
|
16
|
-
export * from "./chart";
|
|
17
|
-
export * from "./checkbox";
|
|
18
|
-
export * from "./collapsible";
|
|
19
|
-
export * from "./command";
|
|
20
|
-
export * from "./context-menu";
|
|
21
|
-
export * from "./dialog";
|
|
22
|
-
export * from "./direction";
|
|
23
|
-
export * from "./drawer";
|
|
24
|
-
export * from "./dropdown-menu";
|
|
25
|
-
export * from "./empty";
|
|
26
|
-
export * from "./field";
|
|
27
|
-
export * from "./form";
|
|
28
|
-
export * from "./hover-card";
|
|
29
|
-
export * from "./icon";
|
|
30
|
-
export * from "./input";
|
|
31
|
-
export * from "./input-group";
|
|
32
|
-
export * from "./input-otp";
|
|
33
|
-
export * from "./item";
|
|
34
|
-
export * from "./kbd";
|
|
35
|
-
export * from "./label";
|
|
36
|
-
export * from "./menubar";
|
|
37
|
-
export * from "./native-select";
|
|
38
|
-
export * from "./navigation-menu";
|
|
39
|
-
export * from "./pagination";
|
|
40
|
-
export * from "./popover";
|
|
41
|
-
export * from "./progress";
|
|
42
|
-
export * from "./radio-group";
|
|
43
|
-
export * from "./resizable";
|
|
44
|
-
export * from "./scroll-area";
|
|
45
|
-
export * from "./select";
|
|
46
|
-
export * from "./separator";
|
|
47
|
-
export * from "./sheet";
|
|
48
|
-
export * from "./sidebar";
|
|
49
|
-
export * from "./skeleton";
|
|
50
|
-
export * from "./slider";
|
|
51
|
-
export * from "./sonner";
|
|
52
|
-
export * from "./spinner";
|
|
53
|
-
export * from "./switch";
|
|
54
|
-
export * from "./table";
|
|
55
|
-
export * from "./tabs";
|
|
56
|
-
export * from "./textarea";
|
|
57
|
-
export * from "./toggle";
|
|
58
|
-
export * from "./toggle-group";
|
|
59
|
-
export * from "./tooltip";
|
|
1
|
+
export * from "./lib";
|
|
2
|
+
export * from "./hooks";
|
|
3
|
+
|
|
4
|
+
export * from "./accordion";
|
|
5
|
+
export * from "./alert";
|
|
6
|
+
export * from "./alert-dialog";
|
|
7
|
+
export * from "./aspect-ratio";
|
|
8
|
+
export * from "./avatar";
|
|
9
|
+
export * from "./badge";
|
|
10
|
+
export * from "./breadcrumb";
|
|
11
|
+
export * from "./button";
|
|
12
|
+
export * from "./button-group";
|
|
13
|
+
export * from "./calendar";
|
|
14
|
+
export * from "./card";
|
|
15
|
+
export * from "./carousel";
|
|
16
|
+
export * from "./chart";
|
|
17
|
+
export * from "./checkbox";
|
|
18
|
+
export * from "./collapsible";
|
|
19
|
+
export * from "./command";
|
|
20
|
+
export * from "./context-menu";
|
|
21
|
+
export * from "./dialog";
|
|
22
|
+
export * from "./direction";
|
|
23
|
+
export * from "./drawer";
|
|
24
|
+
export * from "./dropdown-menu";
|
|
25
|
+
export * from "./empty";
|
|
26
|
+
export * from "./field";
|
|
27
|
+
export * from "./form";
|
|
28
|
+
export * from "./hover-card";
|
|
29
|
+
export * from "./icon";
|
|
30
|
+
export * from "./input";
|
|
31
|
+
export * from "./input-group";
|
|
32
|
+
export * from "./input-otp";
|
|
33
|
+
export * from "./item";
|
|
34
|
+
export * from "./kbd";
|
|
35
|
+
export * from "./label";
|
|
36
|
+
export * from "./menubar";
|
|
37
|
+
export * from "./native-select";
|
|
38
|
+
export * from "./navigation-menu";
|
|
39
|
+
export * from "./pagination";
|
|
40
|
+
export * from "./popover";
|
|
41
|
+
export * from "./progress";
|
|
42
|
+
export * from "./radio-group";
|
|
43
|
+
export * from "./resizable";
|
|
44
|
+
export * from "./scroll-area";
|
|
45
|
+
export * from "./select";
|
|
46
|
+
export * from "./separator";
|
|
47
|
+
export * from "./sheet";
|
|
48
|
+
export * from "./sidebar";
|
|
49
|
+
export * from "./skeleton";
|
|
50
|
+
export * from "./slider";
|
|
51
|
+
export * from "./sonner";
|
|
52
|
+
export * from "./spinner";
|
|
53
|
+
export * from "./switch";
|
|
54
|
+
export * from "./table";
|
|
55
|
+
export * from "./tabs";
|
|
56
|
+
export * from "./textarea";
|
|
57
|
+
export * from "./toggle";
|
|
58
|
+
export * from "./toggle-group";
|
|
59
|
+
export * from "./tooltip";
|