@openconsole/shadcn 0.0.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/accordion.tsx +66 -0
- package/alert-dialog.tsx +196 -0
- package/alert.tsx +66 -0
- package/aspect-ratio.tsx +11 -0
- package/avatar.tsx +53 -0
- package/badge.tsx +46 -0
- package/breadcrumb.tsx +109 -0
- package/button-group.tsx +83 -0
- package/button.tsx +60 -0
- package/calendar.tsx +219 -0
- package/card.tsx +92 -0
- package/carousel.tsx +241 -0
- package/chart.tsx +374 -0
- package/checkbox.tsx +32 -0
- package/collapsible.tsx +33 -0
- package/command.tsx +184 -0
- package/context-menu.tsx +252 -0
- package/dialog.tsx +143 -0
- package/direction.tsx +22 -0
- package/drawer.tsx +135 -0
- package/dropdown-menu.tsx +257 -0
- package/empty.tsx +104 -0
- package/field.tsx +248 -0
- package/form.tsx +167 -0
- package/hooks/index.ts +1 -0
- package/hooks/use-mobile.ts +19 -0
- package/hover-card.tsx +44 -0
- package/icon.tsx +21 -0
- package/index.ts +59 -0
- package/input-group.tsx +170 -0
- package/input-otp.tsx +77 -0
- package/input.tsx +21 -0
- package/item.tsx +193 -0
- package/kbd.tsx +28 -0
- package/label.tsx +24 -0
- package/lib/index.ts +1 -0
- package/lib/utils.ts +6 -0
- package/menubar.tsx +276 -0
- package/native-select.tsx +62 -0
- package/navigation-menu.tsx +168 -0
- package/package.json +50 -0
- package/pagination.tsx +127 -0
- package/popover.tsx +89 -0
- package/progress.tsx +31 -0
- package/radio-group.tsx +45 -0
- package/resizable.tsx +53 -0
- package/scroll-area.tsx +58 -0
- package/select.tsx +187 -0
- package/separator.tsx +28 -0
- package/sheet.tsx +139 -0
- package/sidebar.tsx +724 -0
- package/skeleton.tsx +13 -0
- package/skill/SKILL.md +599 -0
- package/skill/customization.md +263 -0
- package/skill/rules/base-vs-radix.md +167 -0
- package/skill/rules/composition.md +240 -0
- package/skill/rules/forms.md +271 -0
- package/skill/rules/icons.md +136 -0
- package/skill/rules/styling.md +180 -0
- package/slider.tsx +63 -0
- package/sonner.tsx +40 -0
- package/spinner.tsx +16 -0
- package/switch.tsx +35 -0
- package/table.tsx +116 -0
- package/tabs.tsx +66 -0
- package/textarea.tsx +18 -0
- package/toggle-group.tsx +83 -0
- package/toggle.tsx +47 -0
- package/tooltip.tsx +61 -0
- package/tsconfig.json +12 -0
- package/tsconfig.tsbuildinfo +1 -0
package/item.tsx
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
3
|
+
import { Slot } from "radix-ui"
|
|
4
|
+
|
|
5
|
+
import { cn } from "./lib/utils"
|
|
6
|
+
import { Separator } from "./separator"
|
|
7
|
+
|
|
8
|
+
function ItemGroup({ className, ...props }: React.ComponentProps<"div">) {
|
|
9
|
+
return (
|
|
10
|
+
<div
|
|
11
|
+
role="list"
|
|
12
|
+
data-slot="item-group"
|
|
13
|
+
className={cn("group/item-group flex flex-col", className)}
|
|
14
|
+
{...props}
|
|
15
|
+
/>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function ItemSeparator({
|
|
20
|
+
className,
|
|
21
|
+
...props
|
|
22
|
+
}: React.ComponentProps<typeof Separator>) {
|
|
23
|
+
return (
|
|
24
|
+
<Separator
|
|
25
|
+
data-slot="item-separator"
|
|
26
|
+
orientation="horizontal"
|
|
27
|
+
className={cn("my-0", className)}
|
|
28
|
+
{...props}
|
|
29
|
+
/>
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const itemVariants = cva(
|
|
34
|
+
"group/item flex flex-wrap items-center rounded-md border border-transparent text-sm transition-colors duration-100 outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 [a]:transition-colors [a]:hover:bg-accent/50",
|
|
35
|
+
{
|
|
36
|
+
variants: {
|
|
37
|
+
variant: {
|
|
38
|
+
default: "bg-transparent",
|
|
39
|
+
outline: "border-border",
|
|
40
|
+
muted: "bg-muted/50",
|
|
41
|
+
},
|
|
42
|
+
size: {
|
|
43
|
+
default: "gap-4 p-4",
|
|
44
|
+
sm: "gap-2.5 px-4 py-3",
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
defaultVariants: {
|
|
48
|
+
variant: "default",
|
|
49
|
+
size: "default",
|
|
50
|
+
},
|
|
51
|
+
}
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
function Item({
|
|
55
|
+
className,
|
|
56
|
+
variant = "default",
|
|
57
|
+
size = "default",
|
|
58
|
+
asChild = false,
|
|
59
|
+
...props
|
|
60
|
+
}: React.ComponentProps<"div"> &
|
|
61
|
+
VariantProps<typeof itemVariants> & { asChild?: boolean }) {
|
|
62
|
+
const Comp = asChild ? Slot.Root : "div"
|
|
63
|
+
return (
|
|
64
|
+
<Comp
|
|
65
|
+
data-slot="item"
|
|
66
|
+
data-variant={variant}
|
|
67
|
+
data-size={size}
|
|
68
|
+
className={cn(itemVariants({ variant, size, className }))}
|
|
69
|
+
{...props}
|
|
70
|
+
/>
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const itemMediaVariants = cva(
|
|
75
|
+
"flex shrink-0 items-center justify-center gap-2 group-has-[[data-slot=item-description]]/item:translate-y-0.5 group-has-[[data-slot=item-description]]/item:self-start [&_svg]:pointer-events-none",
|
|
76
|
+
{
|
|
77
|
+
variants: {
|
|
78
|
+
variant: {
|
|
79
|
+
default: "bg-transparent",
|
|
80
|
+
icon: "size-8 rounded-sm border bg-muted [&_svg:not([class*='size-'])]:size-4",
|
|
81
|
+
image:
|
|
82
|
+
"size-10 overflow-hidden rounded-sm [&_img]:size-full [&_img]:object-cover",
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
defaultVariants: {
|
|
86
|
+
variant: "default",
|
|
87
|
+
},
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
function ItemMedia({
|
|
92
|
+
className,
|
|
93
|
+
variant = "default",
|
|
94
|
+
...props
|
|
95
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof itemMediaVariants>) {
|
|
96
|
+
return (
|
|
97
|
+
<div
|
|
98
|
+
data-slot="item-media"
|
|
99
|
+
data-variant={variant}
|
|
100
|
+
className={cn(itemMediaVariants({ variant, className }))}
|
|
101
|
+
{...props}
|
|
102
|
+
/>
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function ItemContent({ className, ...props }: React.ComponentProps<"div">) {
|
|
107
|
+
return (
|
|
108
|
+
<div
|
|
109
|
+
data-slot="item-content"
|
|
110
|
+
className={cn(
|
|
111
|
+
"flex flex-1 flex-col gap-1 [&+[data-slot=item-content]]:flex-none",
|
|
112
|
+
className
|
|
113
|
+
)}
|
|
114
|
+
{...props}
|
|
115
|
+
/>
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function ItemTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
120
|
+
return (
|
|
121
|
+
<div
|
|
122
|
+
data-slot="item-title"
|
|
123
|
+
className={cn(
|
|
124
|
+
"flex w-fit items-center gap-2 text-sm leading-snug font-medium",
|
|
125
|
+
className
|
|
126
|
+
)}
|
|
127
|
+
{...props}
|
|
128
|
+
/>
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function ItemDescription({ className, ...props }: React.ComponentProps<"p">) {
|
|
133
|
+
return (
|
|
134
|
+
<p
|
|
135
|
+
data-slot="item-description"
|
|
136
|
+
className={cn(
|
|
137
|
+
"line-clamp-2 text-sm leading-normal font-normal text-balance text-muted-foreground",
|
|
138
|
+
"[&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary",
|
|
139
|
+
className
|
|
140
|
+
)}
|
|
141
|
+
{...props}
|
|
142
|
+
/>
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function ItemActions({ className, ...props }: React.ComponentProps<"div">) {
|
|
147
|
+
return (
|
|
148
|
+
<div
|
|
149
|
+
data-slot="item-actions"
|
|
150
|
+
className={cn("flex items-center gap-2", className)}
|
|
151
|
+
{...props}
|
|
152
|
+
/>
|
|
153
|
+
)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function ItemHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
157
|
+
return (
|
|
158
|
+
<div
|
|
159
|
+
data-slot="item-header"
|
|
160
|
+
className={cn(
|
|
161
|
+
"flex basis-full items-center justify-between gap-2",
|
|
162
|
+
className
|
|
163
|
+
)}
|
|
164
|
+
{...props}
|
|
165
|
+
/>
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function ItemFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
170
|
+
return (
|
|
171
|
+
<div
|
|
172
|
+
data-slot="item-footer"
|
|
173
|
+
className={cn(
|
|
174
|
+
"flex basis-full items-center justify-between gap-2",
|
|
175
|
+
className
|
|
176
|
+
)}
|
|
177
|
+
{...props}
|
|
178
|
+
/>
|
|
179
|
+
)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export {
|
|
183
|
+
Item,
|
|
184
|
+
ItemMedia,
|
|
185
|
+
ItemContent,
|
|
186
|
+
ItemActions,
|
|
187
|
+
ItemGroup,
|
|
188
|
+
ItemSeparator,
|
|
189
|
+
ItemTitle,
|
|
190
|
+
ItemDescription,
|
|
191
|
+
ItemHeader,
|
|
192
|
+
ItemFooter,
|
|
193
|
+
}
|
package/kbd.tsx
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { cn } from "./lib/utils"
|
|
2
|
+
|
|
3
|
+
function Kbd({ className, ...props }: React.ComponentProps<"kbd">) {
|
|
4
|
+
return (
|
|
5
|
+
<kbd
|
|
6
|
+
data-slot="kbd"
|
|
7
|
+
className={cn(
|
|
8
|
+
"pointer-events-none inline-flex h-5 w-fit min-w-5 items-center justify-center gap-1 rounded-sm bg-muted px-1 font-sans text-xs font-medium text-muted-foreground select-none",
|
|
9
|
+
"[&_svg:not([class*='size-'])]:size-3",
|
|
10
|
+
"[[data-slot=tooltip-content]_&]:bg-background/20 [[data-slot=tooltip-content]_&]:text-background dark:[[data-slot=tooltip-content]_&]:bg-background/10",
|
|
11
|
+
className
|
|
12
|
+
)}
|
|
13
|
+
{...props}
|
|
14
|
+
/>
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function KbdGroup({ className, ...props }: React.ComponentProps<"div">) {
|
|
19
|
+
return (
|
|
20
|
+
<kbd
|
|
21
|
+
data-slot="kbd-group"
|
|
22
|
+
className={cn("inline-flex items-center gap-1", className)}
|
|
23
|
+
{...props}
|
|
24
|
+
/>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { Kbd, KbdGroup }
|
package/label.tsx
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import * as LabelPrimitive from "@radix-ui/react-label";
|
|
5
|
+
|
|
6
|
+
import { cn } from "./lib/utils";
|
|
7
|
+
|
|
8
|
+
function Label({
|
|
9
|
+
className,
|
|
10
|
+
...props
|
|
11
|
+
}: React.ComponentProps<typeof LabelPrimitive.Root>) {
|
|
12
|
+
return (
|
|
13
|
+
<LabelPrimitive.Root
|
|
14
|
+
data-slot="label"
|
|
15
|
+
className={cn(
|
|
16
|
+
"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
|
|
17
|
+
className,
|
|
18
|
+
)}
|
|
19
|
+
{...props}
|
|
20
|
+
/>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { Label };
|
package/lib/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./utils";
|
package/lib/utils.ts
ADDED
package/menubar.tsx
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
|
|
5
|
+
import { Menubar as MenubarPrimitive } from "radix-ui"
|
|
6
|
+
|
|
7
|
+
import { cn } from "./lib/utils"
|
|
8
|
+
|
|
9
|
+
function Menubar({
|
|
10
|
+
className,
|
|
11
|
+
...props
|
|
12
|
+
}: React.ComponentProps<typeof MenubarPrimitive.Root>) {
|
|
13
|
+
return (
|
|
14
|
+
<MenubarPrimitive.Root
|
|
15
|
+
data-slot="menubar"
|
|
16
|
+
className={cn(
|
|
17
|
+
"flex h-9 items-center gap-1 rounded-md border bg-background p-1 shadow-xs",
|
|
18
|
+
className
|
|
19
|
+
)}
|
|
20
|
+
{...props}
|
|
21
|
+
/>
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function MenubarMenu({
|
|
26
|
+
...props
|
|
27
|
+
}: React.ComponentProps<typeof MenubarPrimitive.Menu>) {
|
|
28
|
+
return <MenubarPrimitive.Menu data-slot="menubar-menu" {...props} />
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function MenubarGroup({
|
|
32
|
+
...props
|
|
33
|
+
}: React.ComponentProps<typeof MenubarPrimitive.Group>) {
|
|
34
|
+
return <MenubarPrimitive.Group data-slot="menubar-group" {...props} />
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function MenubarPortal({
|
|
38
|
+
...props
|
|
39
|
+
}: React.ComponentProps<typeof MenubarPrimitive.Portal>) {
|
|
40
|
+
return <MenubarPrimitive.Portal data-slot="menubar-portal" {...props} />
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function MenubarRadioGroup({
|
|
44
|
+
...props
|
|
45
|
+
}: React.ComponentProps<typeof MenubarPrimitive.RadioGroup>) {
|
|
46
|
+
return (
|
|
47
|
+
<MenubarPrimitive.RadioGroup data-slot="menubar-radio-group" {...props} />
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function MenubarTrigger({
|
|
52
|
+
className,
|
|
53
|
+
...props
|
|
54
|
+
}: React.ComponentProps<typeof MenubarPrimitive.Trigger>) {
|
|
55
|
+
return (
|
|
56
|
+
<MenubarPrimitive.Trigger
|
|
57
|
+
data-slot="menubar-trigger"
|
|
58
|
+
className={cn(
|
|
59
|
+
"flex items-center rounded-sm px-2 py-1 text-sm font-medium outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
|
|
60
|
+
className
|
|
61
|
+
)}
|
|
62
|
+
{...props}
|
|
63
|
+
/>
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function MenubarContent({
|
|
68
|
+
className,
|
|
69
|
+
align = "start",
|
|
70
|
+
alignOffset = -4,
|
|
71
|
+
sideOffset = 8,
|
|
72
|
+
...props
|
|
73
|
+
}: React.ComponentProps<typeof MenubarPrimitive.Content>) {
|
|
74
|
+
return (
|
|
75
|
+
<MenubarPortal>
|
|
76
|
+
<MenubarPrimitive.Content
|
|
77
|
+
data-slot="menubar-content"
|
|
78
|
+
align={align}
|
|
79
|
+
alignOffset={alignOffset}
|
|
80
|
+
sideOffset={sideOffset}
|
|
81
|
+
className={cn(
|
|
82
|
+
"z-50 min-w-[12rem] origin-(--radix-menubar-content-transform-origin) overflow-hidden rounded-md border bg-popover p-1 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]: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",
|
|
83
|
+
className
|
|
84
|
+
)}
|
|
85
|
+
{...props}
|
|
86
|
+
/>
|
|
87
|
+
</MenubarPortal>
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function MenubarItem({
|
|
92
|
+
className,
|
|
93
|
+
inset,
|
|
94
|
+
variant = "default",
|
|
95
|
+
...props
|
|
96
|
+
}: React.ComponentProps<typeof MenubarPrimitive.Item> & {
|
|
97
|
+
inset?: boolean
|
|
98
|
+
variant?: "default" | "destructive"
|
|
99
|
+
}) {
|
|
100
|
+
return (
|
|
101
|
+
<MenubarPrimitive.Item
|
|
102
|
+
data-slot="menubar-item"
|
|
103
|
+
data-inset={inset}
|
|
104
|
+
data-variant={variant}
|
|
105
|
+
className={cn(
|
|
106
|
+
"relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground data-[variant=destructive]:*:[svg]:text-destructive!",
|
|
107
|
+
className
|
|
108
|
+
)}
|
|
109
|
+
{...props}
|
|
110
|
+
/>
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function MenubarCheckboxItem({
|
|
115
|
+
className,
|
|
116
|
+
children,
|
|
117
|
+
checked,
|
|
118
|
+
...props
|
|
119
|
+
}: React.ComponentProps<typeof MenubarPrimitive.CheckboxItem>) {
|
|
120
|
+
return (
|
|
121
|
+
<MenubarPrimitive.CheckboxItem
|
|
122
|
+
data-slot="menubar-checkbox-item"
|
|
123
|
+
className={cn(
|
|
124
|
+
"relative flex cursor-default items-center gap-2 rounded-xs py-1.5 pr-2 pl-8 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",
|
|
125
|
+
className
|
|
126
|
+
)}
|
|
127
|
+
checked={checked}
|
|
128
|
+
{...props}
|
|
129
|
+
>
|
|
130
|
+
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
|
|
131
|
+
<MenubarPrimitive.ItemIndicator>
|
|
132
|
+
<CheckIcon className="size-4" />
|
|
133
|
+
</MenubarPrimitive.ItemIndicator>
|
|
134
|
+
</span>
|
|
135
|
+
{children}
|
|
136
|
+
</MenubarPrimitive.CheckboxItem>
|
|
137
|
+
)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function MenubarRadioItem({
|
|
141
|
+
className,
|
|
142
|
+
children,
|
|
143
|
+
...props
|
|
144
|
+
}: React.ComponentProps<typeof MenubarPrimitive.RadioItem>) {
|
|
145
|
+
return (
|
|
146
|
+
<MenubarPrimitive.RadioItem
|
|
147
|
+
data-slot="menubar-radio-item"
|
|
148
|
+
className={cn(
|
|
149
|
+
"relative flex cursor-default items-center gap-2 rounded-xs py-1.5 pr-2 pl-8 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",
|
|
150
|
+
className
|
|
151
|
+
)}
|
|
152
|
+
{...props}
|
|
153
|
+
>
|
|
154
|
+
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
|
|
155
|
+
<MenubarPrimitive.ItemIndicator>
|
|
156
|
+
<CircleIcon className="size-2 fill-current" />
|
|
157
|
+
</MenubarPrimitive.ItemIndicator>
|
|
158
|
+
</span>
|
|
159
|
+
{children}
|
|
160
|
+
</MenubarPrimitive.RadioItem>
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function MenubarLabel({
|
|
165
|
+
className,
|
|
166
|
+
inset,
|
|
167
|
+
...props
|
|
168
|
+
}: React.ComponentProps<typeof MenubarPrimitive.Label> & {
|
|
169
|
+
inset?: boolean
|
|
170
|
+
}) {
|
|
171
|
+
return (
|
|
172
|
+
<MenubarPrimitive.Label
|
|
173
|
+
data-slot="menubar-label"
|
|
174
|
+
data-inset={inset}
|
|
175
|
+
className={cn(
|
|
176
|
+
"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
|
|
177
|
+
className
|
|
178
|
+
)}
|
|
179
|
+
{...props}
|
|
180
|
+
/>
|
|
181
|
+
)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function MenubarSeparator({
|
|
185
|
+
className,
|
|
186
|
+
...props
|
|
187
|
+
}: React.ComponentProps<typeof MenubarPrimitive.Separator>) {
|
|
188
|
+
return (
|
|
189
|
+
<MenubarPrimitive.Separator
|
|
190
|
+
data-slot="menubar-separator"
|
|
191
|
+
className={cn("-mx-1 my-1 h-px bg-border", className)}
|
|
192
|
+
{...props}
|
|
193
|
+
/>
|
|
194
|
+
)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function MenubarShortcut({
|
|
198
|
+
className,
|
|
199
|
+
...props
|
|
200
|
+
}: React.ComponentProps<"span">) {
|
|
201
|
+
return (
|
|
202
|
+
<span
|
|
203
|
+
data-slot="menubar-shortcut"
|
|
204
|
+
className={cn(
|
|
205
|
+
"ml-auto text-xs tracking-widest text-muted-foreground",
|
|
206
|
+
className
|
|
207
|
+
)}
|
|
208
|
+
{...props}
|
|
209
|
+
/>
|
|
210
|
+
)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function MenubarSub({
|
|
214
|
+
...props
|
|
215
|
+
}: React.ComponentProps<typeof MenubarPrimitive.Sub>) {
|
|
216
|
+
return <MenubarPrimitive.Sub data-slot="menubar-sub" {...props} />
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function MenubarSubTrigger({
|
|
220
|
+
className,
|
|
221
|
+
inset,
|
|
222
|
+
children,
|
|
223
|
+
...props
|
|
224
|
+
}: React.ComponentProps<typeof MenubarPrimitive.SubTrigger> & {
|
|
225
|
+
inset?: boolean
|
|
226
|
+
}) {
|
|
227
|
+
return (
|
|
228
|
+
<MenubarPrimitive.SubTrigger
|
|
229
|
+
data-slot="menubar-sub-trigger"
|
|
230
|
+
data-inset={inset}
|
|
231
|
+
className={cn(
|
|
232
|
+
"flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-none select-none focus:bg-accent focus:text-accent-foreground data-[inset]:pl-8 data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
|
|
233
|
+
className
|
|
234
|
+
)}
|
|
235
|
+
{...props}
|
|
236
|
+
>
|
|
237
|
+
{children}
|
|
238
|
+
<ChevronRightIcon className="ml-auto h-4 w-4" />
|
|
239
|
+
</MenubarPrimitive.SubTrigger>
|
|
240
|
+
)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function MenubarSubContent({
|
|
244
|
+
className,
|
|
245
|
+
...props
|
|
246
|
+
}: React.ComponentProps<typeof MenubarPrimitive.SubContent>) {
|
|
247
|
+
return (
|
|
248
|
+
<MenubarPrimitive.SubContent
|
|
249
|
+
data-slot="menubar-sub-content"
|
|
250
|
+
className={cn(
|
|
251
|
+
"z-50 min-w-[8rem] origin-(--radix-menubar-content-transform-origin) overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg 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",
|
|
252
|
+
className
|
|
253
|
+
)}
|
|
254
|
+
{...props}
|
|
255
|
+
/>
|
|
256
|
+
)
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
export {
|
|
260
|
+
Menubar,
|
|
261
|
+
MenubarPortal,
|
|
262
|
+
MenubarMenu,
|
|
263
|
+
MenubarTrigger,
|
|
264
|
+
MenubarContent,
|
|
265
|
+
MenubarGroup,
|
|
266
|
+
MenubarSeparator,
|
|
267
|
+
MenubarLabel,
|
|
268
|
+
MenubarItem,
|
|
269
|
+
MenubarShortcut,
|
|
270
|
+
MenubarCheckboxItem,
|
|
271
|
+
MenubarRadioGroup,
|
|
272
|
+
MenubarRadioItem,
|
|
273
|
+
MenubarSub,
|
|
274
|
+
MenubarSubTrigger,
|
|
275
|
+
MenubarSubContent,
|
|
276
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { ChevronDownIcon } from "lucide-react"
|
|
3
|
+
|
|
4
|
+
import { cn } from "./lib/utils"
|
|
5
|
+
|
|
6
|
+
function NativeSelect({
|
|
7
|
+
className,
|
|
8
|
+
size = "default",
|
|
9
|
+
...props
|
|
10
|
+
}: Omit<React.ComponentProps<"select">, "size"> & { size?: "sm" | "default" }) {
|
|
11
|
+
return (
|
|
12
|
+
<div
|
|
13
|
+
className="group/native-select relative w-fit has-[select:disabled]:opacity-50"
|
|
14
|
+
data-slot="native-select-wrapper"
|
|
15
|
+
>
|
|
16
|
+
<select
|
|
17
|
+
data-slot="native-select"
|
|
18
|
+
data-size={size}
|
|
19
|
+
className={cn(
|
|
20
|
+
"h-9 w-full min-w-0 appearance-none rounded-md border border-input bg-transparent px-3 py-2 pr-9 text-sm shadow-xs transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed data-[size=sm]:h-8 data-[size=sm]:py-1 dark:bg-input/30 dark:hover:bg-input/50",
|
|
21
|
+
"focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50",
|
|
22
|
+
"aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40",
|
|
23
|
+
className
|
|
24
|
+
)}
|
|
25
|
+
{...props}
|
|
26
|
+
/>
|
|
27
|
+
<ChevronDownIcon
|
|
28
|
+
className="pointer-events-none absolute top-1/2 right-3.5 size-4 -translate-y-1/2 text-muted-foreground opacity-50 select-none"
|
|
29
|
+
aria-hidden="true"
|
|
30
|
+
data-slot="native-select-icon"
|
|
31
|
+
/>
|
|
32
|
+
</div>
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function NativeSelectOption({
|
|
37
|
+
className,
|
|
38
|
+
...props
|
|
39
|
+
}: React.ComponentProps<"option">) {
|
|
40
|
+
return (
|
|
41
|
+
<option
|
|
42
|
+
data-slot="native-select-option"
|
|
43
|
+
className={cn("bg-[Canvas] text-[CanvasText]", className)}
|
|
44
|
+
{...props}
|
|
45
|
+
/>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function NativeSelectOptGroup({
|
|
50
|
+
className,
|
|
51
|
+
...props
|
|
52
|
+
}: React.ComponentProps<"optgroup">) {
|
|
53
|
+
return (
|
|
54
|
+
<optgroup
|
|
55
|
+
data-slot="native-select-optgroup"
|
|
56
|
+
className={cn("bg-[Canvas] text-[CanvasText]", className)}
|
|
57
|
+
{...props}
|
|
58
|
+
/>
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export { NativeSelect, NativeSelectOptGroup, NativeSelectOption }
|