parthenon-ui 1.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/package.json +74 -0
- package/src/components/.gitkeep +0 -0
- package/src/components/avatar.tsx +109 -0
- package/src/components/badge.tsx +52 -0
- package/src/components/button.tsx +122 -0
- package/src/components/card.tsx +108 -0
- package/src/components/checkbox.tsx +37 -0
- package/src/components/collapsible.tsx +21 -0
- package/src/components/color-picker.tsx +270 -0
- package/src/components/command.tsx +195 -0
- package/src/components/context-menu.tsx +270 -0
- package/src/components/dialog.tsx +169 -0
- package/src/components/dropdown-menu.tsx +279 -0
- package/src/components/empty.tsx +104 -0
- package/src/components/index.ts +27 -0
- package/src/components/input-group.tsx +155 -0
- package/src/components/input.tsx +27 -0
- package/src/components/label.tsx +18 -0
- package/src/components/popover.tsx +88 -0
- package/src/components/scroll-area.tsx +55 -0
- package/src/components/select.tsx +201 -0
- package/src/components/separator.tsx +23 -0
- package/src/components/sheet.tsx +138 -0
- package/src/components/sidebar.tsx +729 -0
- package/src/components/skeleton.tsx +13 -0
- package/src/components/sonner.tsx +59 -0
- package/src/components/switch.tsx +51 -0
- package/src/components/table.tsx +375 -0
- package/src/components/tabs.tsx +80 -0
- package/src/components/textarea.tsx +18 -0
- package/src/components/tooltip.tsx +64 -0
- package/src/hooks/.gitkeep +0 -0
- package/src/hooks/use-mobile.ts +19 -0
- package/src/lib/.gitkeep +0 -0
- package/src/lib/utils.ts +6 -0
- package/src/styles/globals.css +654 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { Menu as MenuPrimitive } from "@base-ui/react/menu"
|
|
3
|
+
|
|
4
|
+
import { cn } from "@workspace/ui/lib/utils"
|
|
5
|
+
import { HugeiconsIcon } from "@hugeicons/react"
|
|
6
|
+
import { ArrowRight01Icon, Tick02Icon } from "@hugeicons/core-free-icons"
|
|
7
|
+
|
|
8
|
+
function DropdownMenu({ children, ...props }: MenuPrimitive.Root.Props) {
|
|
9
|
+
return (
|
|
10
|
+
<MenuPrimitive.Root data-slot="dropdown-menu" {...props}>
|
|
11
|
+
{children}
|
|
12
|
+
</MenuPrimitive.Root>
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function DropdownMenuPortal({ ...props }: MenuPrimitive.Portal.Props) {
|
|
17
|
+
return <MenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function DropdownMenuTrigger({ ...props }: MenuPrimitive.Trigger.Props) {
|
|
21
|
+
return <MenuPrimitive.Trigger data-slot="dropdown-menu-trigger" {...props} />
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function DropdownMenuContent({
|
|
25
|
+
align = "start",
|
|
26
|
+
alignOffset = 0,
|
|
27
|
+
side = "bottom",
|
|
28
|
+
sideOffset = 4,
|
|
29
|
+
className,
|
|
30
|
+
...props
|
|
31
|
+
}: MenuPrimitive.Popup.Props &
|
|
32
|
+
Pick<
|
|
33
|
+
MenuPrimitive.Positioner.Props,
|
|
34
|
+
"align" | "alignOffset" | "side" | "sideOffset"
|
|
35
|
+
>) {
|
|
36
|
+
return (
|
|
37
|
+
<MenuPrimitive.Portal>
|
|
38
|
+
<MenuPrimitive.Positioner
|
|
39
|
+
className="z-[100] outline-none"
|
|
40
|
+
align={align}
|
|
41
|
+
alignOffset={alignOffset}
|
|
42
|
+
side={side}
|
|
43
|
+
sideOffset={sideOffset}
|
|
44
|
+
>
|
|
45
|
+
<MenuPrimitive.Popup
|
|
46
|
+
data-slot="dropdown-menu-content"
|
|
47
|
+
className={cn(
|
|
48
|
+
"z-[100] max-h-(--available-height) w-(--anchor-width) min-w-48 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-2xl bg-popover p-1 text-popover-foreground shadow-2xl ring-1 ring-foreground/5 duration-100 outline-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-start-2 data-[side=inline-start]:slide-in-from-end-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 dark:ring-foreground/10 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:overflow-hidden data-closed:fade-out-0 data-closed:zoom-out-95",
|
|
49
|
+
className
|
|
50
|
+
)}
|
|
51
|
+
{...props}
|
|
52
|
+
/>
|
|
53
|
+
</MenuPrimitive.Positioner>
|
|
54
|
+
</MenuPrimitive.Portal>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props) {
|
|
59
|
+
return <MenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function DropdownMenuLabel({
|
|
63
|
+
className,
|
|
64
|
+
inset,
|
|
65
|
+
...props
|
|
66
|
+
}: MenuPrimitive.GroupLabel.Props & {
|
|
67
|
+
inset?: boolean
|
|
68
|
+
}) {
|
|
69
|
+
return (
|
|
70
|
+
<MenuPrimitive.GroupLabel
|
|
71
|
+
data-slot="dropdown-menu-label"
|
|
72
|
+
data-inset={inset}
|
|
73
|
+
className={cn(
|
|
74
|
+
"px-3 py-2.5 text-xs text-muted-foreground data-inset:ps-9.5",
|
|
75
|
+
className
|
|
76
|
+
)}
|
|
77
|
+
{...props}
|
|
78
|
+
/>
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function DropdownMenuItem({
|
|
83
|
+
className,
|
|
84
|
+
inset,
|
|
85
|
+
variant = "default",
|
|
86
|
+
...props
|
|
87
|
+
}: MenuPrimitive.Item.Props & {
|
|
88
|
+
inset?: boolean
|
|
89
|
+
variant?: "default" | "destructive"
|
|
90
|
+
}) {
|
|
91
|
+
return (
|
|
92
|
+
<MenuPrimitive.Item
|
|
93
|
+
data-slot="dropdown-menu-item"
|
|
94
|
+
data-inset={inset}
|
|
95
|
+
data-variant={variant}
|
|
96
|
+
className={cn(
|
|
97
|
+
"group/dropdown-menu-item relative flex cursor-default items-center gap-2.5 rounded-xl px-3 py-2 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:ps-9.5 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 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive",
|
|
98
|
+
className
|
|
99
|
+
)}
|
|
100
|
+
{...props}
|
|
101
|
+
/>
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function DropdownMenuSub({ ...props }: MenuPrimitive.SubmenuRoot.Props) {
|
|
106
|
+
return <MenuPrimitive.SubmenuRoot data-slot="dropdown-menu-sub" {...props} />
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function DropdownMenuSubTrigger({
|
|
110
|
+
className,
|
|
111
|
+
inset,
|
|
112
|
+
children,
|
|
113
|
+
...props
|
|
114
|
+
}: MenuPrimitive.SubmenuTrigger.Props & {
|
|
115
|
+
inset?: boolean
|
|
116
|
+
}) {
|
|
117
|
+
return (
|
|
118
|
+
<MenuPrimitive.SubmenuTrigger
|
|
119
|
+
data-slot="dropdown-menu-sub-trigger"
|
|
120
|
+
data-inset={inset}
|
|
121
|
+
className={cn(
|
|
122
|
+
"flex cursor-default items-center gap-2 rounded-xl px-3 py-2 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:ps-9.5 data-popup-open:bg-accent data-popup-open:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
123
|
+
className
|
|
124
|
+
)}
|
|
125
|
+
{...props}
|
|
126
|
+
>
|
|
127
|
+
{children}
|
|
128
|
+
<HugeiconsIcon
|
|
129
|
+
icon={ArrowRight01Icon}
|
|
130
|
+
strokeWidth={2}
|
|
131
|
+
className="rtl:rotate-180 ms-auto"
|
|
132
|
+
/>
|
|
133
|
+
</MenuPrimitive.SubmenuTrigger>
|
|
134
|
+
)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function DropdownMenuSubContent({
|
|
138
|
+
align = "start",
|
|
139
|
+
alignOffset = -3,
|
|
140
|
+
side = "inline-end",
|
|
141
|
+
sideOffset = 0,
|
|
142
|
+
className,
|
|
143
|
+
...props
|
|
144
|
+
}: React.ComponentProps<typeof DropdownMenuContent>) {
|
|
145
|
+
return (
|
|
146
|
+
<DropdownMenuContent
|
|
147
|
+
data-slot="dropdown-menu-sub-content"
|
|
148
|
+
className={cn(
|
|
149
|
+
"w-auto min-w-36 rounded-2xl bg-popover p-1 text-popover-foreground shadow-2xl ring-1 ring-foreground/5 duration-100 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-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
|
150
|
+
className
|
|
151
|
+
)}
|
|
152
|
+
align={align}
|
|
153
|
+
alignOffset={alignOffset}
|
|
154
|
+
side={side}
|
|
155
|
+
sideOffset={sideOffset}
|
|
156
|
+
{...props}
|
|
157
|
+
/>
|
|
158
|
+
)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function DropdownMenuCheckboxItem({
|
|
162
|
+
className,
|
|
163
|
+
children,
|
|
164
|
+
checked,
|
|
165
|
+
inset,
|
|
166
|
+
...props
|
|
167
|
+
}: MenuPrimitive.CheckboxItem.Props & {
|
|
168
|
+
inset?: boolean
|
|
169
|
+
}) {
|
|
170
|
+
return (
|
|
171
|
+
<MenuPrimitive.CheckboxItem
|
|
172
|
+
data-slot="dropdown-menu-checkbox-item"
|
|
173
|
+
data-inset={inset}
|
|
174
|
+
className={cn(
|
|
175
|
+
"relative flex cursor-default items-center gap-2.5 rounded-xl py-2 pe-8 ps-3 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:ps-9.5 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
176
|
+
className
|
|
177
|
+
)}
|
|
178
|
+
checked={checked}
|
|
179
|
+
{...props}
|
|
180
|
+
>
|
|
181
|
+
<span
|
|
182
|
+
className="pointer-events-none absolute end-2 flex items-center justify-center"
|
|
183
|
+
data-slot="dropdown-menu-checkbox-item-indicator"
|
|
184
|
+
>
|
|
185
|
+
<MenuPrimitive.CheckboxItemIndicator>
|
|
186
|
+
<HugeiconsIcon icon={Tick02Icon} strokeWidth={2} />
|
|
187
|
+
</MenuPrimitive.CheckboxItemIndicator>
|
|
188
|
+
</span>
|
|
189
|
+
{children}
|
|
190
|
+
</MenuPrimitive.CheckboxItem>
|
|
191
|
+
)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function DropdownMenuRadioGroup({ ...props }: MenuPrimitive.RadioGroup.Props) {
|
|
195
|
+
return (
|
|
196
|
+
<MenuPrimitive.RadioGroup
|
|
197
|
+
data-slot="dropdown-menu-radio-group"
|
|
198
|
+
{...props}
|
|
199
|
+
/>
|
|
200
|
+
)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function DropdownMenuRadioItem({
|
|
204
|
+
className,
|
|
205
|
+
children,
|
|
206
|
+
inset,
|
|
207
|
+
...props
|
|
208
|
+
}: MenuPrimitive.RadioItem.Props & {
|
|
209
|
+
inset?: boolean
|
|
210
|
+
}) {
|
|
211
|
+
return (
|
|
212
|
+
<MenuPrimitive.RadioItem
|
|
213
|
+
data-slot="dropdown-menu-radio-item"
|
|
214
|
+
data-inset={inset}
|
|
215
|
+
className={cn(
|
|
216
|
+
"relative flex cursor-default items-center gap-2.5 rounded-xl py-2 pe-8 ps-3 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:ps-9.5 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
217
|
+
className
|
|
218
|
+
)}
|
|
219
|
+
{...props}
|
|
220
|
+
>
|
|
221
|
+
<span
|
|
222
|
+
className="pointer-events-none absolute end-2 flex items-center justify-center"
|
|
223
|
+
data-slot="dropdown-menu-radio-item-indicator"
|
|
224
|
+
>
|
|
225
|
+
<MenuPrimitive.RadioItemIndicator>
|
|
226
|
+
<HugeiconsIcon icon={Tick02Icon} strokeWidth={2} />
|
|
227
|
+
</MenuPrimitive.RadioItemIndicator>
|
|
228
|
+
</span>
|
|
229
|
+
{children}
|
|
230
|
+
</MenuPrimitive.RadioItem>
|
|
231
|
+
)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function DropdownMenuSeparator({
|
|
235
|
+
className,
|
|
236
|
+
...props
|
|
237
|
+
}: MenuPrimitive.Separator.Props) {
|
|
238
|
+
return (
|
|
239
|
+
<MenuPrimitive.Separator
|
|
240
|
+
data-slot="dropdown-menu-separator"
|
|
241
|
+
className={cn("-mx-1 my-1 h-px bg-border/50", className)}
|
|
242
|
+
{...props}
|
|
243
|
+
/>
|
|
244
|
+
)
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function DropdownMenuShortcut({
|
|
248
|
+
className,
|
|
249
|
+
...props
|
|
250
|
+
}: React.ComponentProps<"span">) {
|
|
251
|
+
return (
|
|
252
|
+
<span
|
|
253
|
+
data-slot="dropdown-menu-shortcut"
|
|
254
|
+
className={cn(
|
|
255
|
+
"ms-auto text-xs tracking-widest text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground",
|
|
256
|
+
className
|
|
257
|
+
)}
|
|
258
|
+
{...props}
|
|
259
|
+
/>
|
|
260
|
+
)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export {
|
|
264
|
+
DropdownMenu,
|
|
265
|
+
DropdownMenuPortal,
|
|
266
|
+
DropdownMenuTrigger,
|
|
267
|
+
DropdownMenuContent,
|
|
268
|
+
DropdownMenuGroup,
|
|
269
|
+
DropdownMenuLabel,
|
|
270
|
+
DropdownMenuItem,
|
|
271
|
+
DropdownMenuCheckboxItem,
|
|
272
|
+
DropdownMenuRadioGroup,
|
|
273
|
+
DropdownMenuRadioItem,
|
|
274
|
+
DropdownMenuSeparator,
|
|
275
|
+
DropdownMenuShortcut,
|
|
276
|
+
DropdownMenuSub,
|
|
277
|
+
DropdownMenuSubTrigger,
|
|
278
|
+
DropdownMenuSubContent,
|
|
279
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
2
|
+
|
|
3
|
+
import { cn } from "@workspace/ui/lib/utils"
|
|
4
|
+
|
|
5
|
+
function Empty({ className, ...props }: React.ComponentProps<"div">) {
|
|
6
|
+
return (
|
|
7
|
+
<div
|
|
8
|
+
data-slot="empty"
|
|
9
|
+
className={cn(
|
|
10
|
+
"flex w-full min-w-0 flex-1 flex-col items-center justify-center gap-4 rounded-lg border-dashed p-12 text-center text-balance",
|
|
11
|
+
className
|
|
12
|
+
)}
|
|
13
|
+
{...props}
|
|
14
|
+
/>
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function EmptyHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
19
|
+
return (
|
|
20
|
+
<div
|
|
21
|
+
data-slot="empty-header"
|
|
22
|
+
className={cn("flex max-w-sm flex-col items-center gap-2", className)}
|
|
23
|
+
{...props}
|
|
24
|
+
/>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const emptyMediaVariants = cva(
|
|
29
|
+
"mb-2 flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
30
|
+
{
|
|
31
|
+
variants: {
|
|
32
|
+
variant: {
|
|
33
|
+
default: "bg-transparent",
|
|
34
|
+
icon: "flex size-10 shrink-0 items-center justify-center rounded-lg bg-muted text-foreground [&_svg:not([class*='size-'])]:size-6",
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
defaultVariants: {
|
|
38
|
+
variant: "default",
|
|
39
|
+
},
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
function EmptyMedia({
|
|
44
|
+
className,
|
|
45
|
+
variant = "default",
|
|
46
|
+
...props
|
|
47
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof emptyMediaVariants>) {
|
|
48
|
+
return (
|
|
49
|
+
<div
|
|
50
|
+
data-slot="empty-icon"
|
|
51
|
+
data-variant={variant}
|
|
52
|
+
className={cn(emptyMediaVariants({ variant, className }))}
|
|
53
|
+
{...props}
|
|
54
|
+
/>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function EmptyTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
59
|
+
return (
|
|
60
|
+
<div
|
|
61
|
+
data-slot="empty-title"
|
|
62
|
+
className={cn(
|
|
63
|
+
"font-heading text-lg font-medium tracking-tight",
|
|
64
|
+
className
|
|
65
|
+
)}
|
|
66
|
+
{...props}
|
|
67
|
+
/>
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function EmptyDescription({ className, ...props }: React.ComponentProps<"p">) {
|
|
72
|
+
return (
|
|
73
|
+
<div
|
|
74
|
+
data-slot="empty-description"
|
|
75
|
+
className={cn(
|
|
76
|
+
"text-sm/relaxed text-muted-foreground [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary",
|
|
77
|
+
className
|
|
78
|
+
)}
|
|
79
|
+
{...props}
|
|
80
|
+
/>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function EmptyContent({ className, ...props }: React.ComponentProps<"div">) {
|
|
85
|
+
return (
|
|
86
|
+
<div
|
|
87
|
+
data-slot="empty-content"
|
|
88
|
+
className={cn(
|
|
89
|
+
"flex w-full max-w-sm min-w-0 flex-col items-center gap-4 text-sm text-balance",
|
|
90
|
+
className
|
|
91
|
+
)}
|
|
92
|
+
{...props}
|
|
93
|
+
/>
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export {
|
|
98
|
+
Empty,
|
|
99
|
+
EmptyHeader,
|
|
100
|
+
EmptyTitle,
|
|
101
|
+
EmptyDescription,
|
|
102
|
+
EmptyContent,
|
|
103
|
+
EmptyMedia,
|
|
104
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export * from "./avatar";
|
|
2
|
+
export * from "./badge";
|
|
3
|
+
export * from "./button";
|
|
4
|
+
export * from "./card";
|
|
5
|
+
export * from "./checkbox";
|
|
6
|
+
export * from "./collapsible";
|
|
7
|
+
export * from "./command";
|
|
8
|
+
export * from "./context-menu";
|
|
9
|
+
export * from "./dialog";
|
|
10
|
+
export * from "./dropdown-menu";
|
|
11
|
+
export * from "./empty";
|
|
12
|
+
export * from "./input-group";
|
|
13
|
+
export * from "./input";
|
|
14
|
+
export * from "./label";
|
|
15
|
+
export * from "./popover";
|
|
16
|
+
export * from "./scroll-area";
|
|
17
|
+
export * from "./select";
|
|
18
|
+
export * from "./separator";
|
|
19
|
+
export * from "./sheet";
|
|
20
|
+
export * from "./sidebar";
|
|
21
|
+
export * from "./skeleton";
|
|
22
|
+
export * from "./sonner";
|
|
23
|
+
export * from "./switch";
|
|
24
|
+
export * from "./table";
|
|
25
|
+
export * from "./tabs";
|
|
26
|
+
export * from "./textarea";
|
|
27
|
+
export * from "./tooltip";
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
3
|
+
|
|
4
|
+
import { cn } from "@workspace/ui/lib/utils"
|
|
5
|
+
import { Button } from "@workspace/ui/components/button"
|
|
6
|
+
import { Input } from "@workspace/ui/components/input"
|
|
7
|
+
import { Textarea } from "@workspace/ui/components/textarea"
|
|
8
|
+
|
|
9
|
+
function InputGroup({ className, ...props }: React.ComponentProps<"div">) {
|
|
10
|
+
return (
|
|
11
|
+
<div
|
|
12
|
+
data-slot="input-group"
|
|
13
|
+
role="group"
|
|
14
|
+
className={cn(
|
|
15
|
+
"group/input-group relative flex h-9 w-full min-w-0 items-center rounded-4xl border border-input bg-input/30 transition-colors outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-data-[align=block-end]:rounded-2xl has-data-[align=block-start]:rounded-2xl has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-[3px] has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-[3px] has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[textarea]:rounded-xl has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pe-1.5 has-[>[data-align=inline-start]]:[&>input]:ps-1.5",
|
|
16
|
+
className
|
|
17
|
+
)}
|
|
18
|
+
{...props}
|
|
19
|
+
/>
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const inputGroupAddonVariants = cva(
|
|
24
|
+
"flex h-auto cursor-text items-center justify-center gap-2 py-2 text-sm font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 **:data-[slot=kbd]:rounded-4xl **:data-[slot=kbd]:bg-muted-foreground/10 **:data-[slot=kbd]:px-1.5 [&>svg:not([class*='size-'])]:size-4",
|
|
25
|
+
{
|
|
26
|
+
variants: {
|
|
27
|
+
align: {
|
|
28
|
+
"inline-start":
|
|
29
|
+
"order-first ps-3 has-[>button]:-ms-1 has-[>kbd]:ms-[-0.15rem]",
|
|
30
|
+
"inline-end":
|
|
31
|
+
"order-last pe-3 has-[>button]:-me-1 has-[>kbd]:me-[-0.15rem]",
|
|
32
|
+
"block-start":
|
|
33
|
+
"order-first w-full justify-start px-3 pt-3 group-has-[>input]/input-group:pt-3 [.border-b]:pb-3",
|
|
34
|
+
"block-end":
|
|
35
|
+
"order-last w-full justify-start px-3 pb-3 group-has-[>input]/input-group:pb-3 [.border-t]:pt-3",
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
defaultVariants: {
|
|
39
|
+
align: "inline-start",
|
|
40
|
+
},
|
|
41
|
+
}
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
function InputGroupAddon({
|
|
45
|
+
className,
|
|
46
|
+
align = "inline-start",
|
|
47
|
+
...props
|
|
48
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>) {
|
|
49
|
+
return (
|
|
50
|
+
<div
|
|
51
|
+
role="group"
|
|
52
|
+
data-slot="input-group-addon"
|
|
53
|
+
data-align={align}
|
|
54
|
+
className={cn(inputGroupAddonVariants({ align }), className)}
|
|
55
|
+
onClick={(e) => {
|
|
56
|
+
if ((e.target as HTMLElement).closest("button")) {
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
e.currentTarget.parentElement?.querySelector("input")?.focus()
|
|
60
|
+
}}
|
|
61
|
+
{...props}
|
|
62
|
+
/>
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const inputGroupButtonVariants = cva(
|
|
67
|
+
"flex items-center gap-2 rounded-4xl text-sm shadow-none",
|
|
68
|
+
{
|
|
69
|
+
variants: {
|
|
70
|
+
size: {
|
|
71
|
+
xs: "h-6 gap-1 px-1.5 [&>svg:not([class*='size-'])]:size-3.5",
|
|
72
|
+
sm: "",
|
|
73
|
+
"icon-xs": "size-6 p-0 has-[>svg]:p-0",
|
|
74
|
+
"icon-sm": "size-8 p-0 has-[>svg]:p-0",
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
defaultVariants: {
|
|
78
|
+
size: "xs",
|
|
79
|
+
},
|
|
80
|
+
}
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
function InputGroupButton({
|
|
84
|
+
className,
|
|
85
|
+
type = "button",
|
|
86
|
+
variant = "ghost",
|
|
87
|
+
size = "xs",
|
|
88
|
+
...props
|
|
89
|
+
}: Omit<React.ComponentProps<typeof Button>, "size" | "type"> &
|
|
90
|
+
VariantProps<typeof inputGroupButtonVariants> & {
|
|
91
|
+
type?: "button" | "submit" | "reset"
|
|
92
|
+
}) {
|
|
93
|
+
return (
|
|
94
|
+
<Button
|
|
95
|
+
type={type}
|
|
96
|
+
data-size={size}
|
|
97
|
+
variant={variant}
|
|
98
|
+
className={cn(inputGroupButtonVariants({ size }), className)}
|
|
99
|
+
{...props}
|
|
100
|
+
/>
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function InputGroupText({ className, ...props }: React.ComponentProps<"span">) {
|
|
105
|
+
return (
|
|
106
|
+
<span
|
|
107
|
+
className={cn(
|
|
108
|
+
"flex items-center gap-2 text-sm text-muted-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
|
|
109
|
+
className
|
|
110
|
+
)}
|
|
111
|
+
{...props}
|
|
112
|
+
/>
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function InputGroupInput({
|
|
117
|
+
className,
|
|
118
|
+
...props
|
|
119
|
+
}: React.ComponentProps<"input">) {
|
|
120
|
+
return (
|
|
121
|
+
<Input
|
|
122
|
+
data-slot="input-group-control"
|
|
123
|
+
className={cn(
|
|
124
|
+
"flex-1 rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 aria-invalid:ring-0 dark:bg-transparent",
|
|
125
|
+
className
|
|
126
|
+
)}
|
|
127
|
+
{...props}
|
|
128
|
+
/>
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function InputGroupTextarea({
|
|
133
|
+
className,
|
|
134
|
+
...props
|
|
135
|
+
}: React.ComponentProps<"textarea">) {
|
|
136
|
+
return (
|
|
137
|
+
<Textarea
|
|
138
|
+
data-slot="input-group-control"
|
|
139
|
+
className={cn(
|
|
140
|
+
"flex-1 resize-none rounded-none border-0 bg-transparent py-2 shadow-none ring-0 focus-visible:ring-0 aria-invalid:ring-0 dark:bg-transparent",
|
|
141
|
+
className
|
|
142
|
+
)}
|
|
143
|
+
{...props}
|
|
144
|
+
/>
|
|
145
|
+
)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export {
|
|
149
|
+
InputGroup,
|
|
150
|
+
InputGroupAddon,
|
|
151
|
+
InputGroupButton,
|
|
152
|
+
InputGroupText,
|
|
153
|
+
InputGroupInput,
|
|
154
|
+
InputGroupTextarea,
|
|
155
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { Input as InputPrimitive } from "@base-ui/react/input"
|
|
3
|
+
|
|
4
|
+
import { cn } from "@workspace/ui/lib/utils"
|
|
5
|
+
|
|
6
|
+
function Input({ className, type, ...props }: React.ComponentProps<"input">) {
|
|
7
|
+
return (
|
|
8
|
+
<div className="relative">
|
|
9
|
+
<InputPrimitive
|
|
10
|
+
type={type}
|
|
11
|
+
data-slot="input"
|
|
12
|
+
className={cn(
|
|
13
|
+
"h-9 w-full min-w-0 rounded-4xl border border-input bg-input/30 px-3 py-1 text-base transition-all duration-150 outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground",
|
|
14
|
+
"shadow-[0_1px_1px_0_rgba(0,0,0,0.24),0_2px_3px_0_rgba(0,0,0,0.20),inset_0_1px_1px_0_rgba(255,255,255,0.07),0_0_0_1px_var(--input)]",
|
|
15
|
+
"before:absolute before:inset-0 before:rounded-4xl before:bg-linear-[180deg,rgba(255,255,255,0.1)_0%,rgba(255,255,255,0)_100%] before:content-[''] before:pointer-events-none",
|
|
16
|
+
"focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:shadow-[0_1px_1px_0_rgba(0,0,0,0.24),0_2px_3px_0_rgba(0,0,0,0.20),inset_0_1px_1px_0_rgba(255,255,255,0.07),0_0_0_1px_var(--ring)]",
|
|
17
|
+
"focus-visible:before:bg-linear-[180deg,rgba(255,255,255,0)_0%,rgba(255,255,255,0.1)_100%]",
|
|
18
|
+
"disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-[3px] aria-invalid:ring-destructive/20 md:text-sm dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
|
|
19
|
+
className
|
|
20
|
+
)}
|
|
21
|
+
{...props}
|
|
22
|
+
/>
|
|
23
|
+
</div>
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export { Input }
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
import { cn } from "@workspace/ui/lib/utils"
|
|
4
|
+
|
|
5
|
+
function Label({ className, ...props }: React.ComponentProps<"label">) {
|
|
6
|
+
return (
|
|
7
|
+
<label
|
|
8
|
+
data-slot="label"
|
|
9
|
+
className={cn(
|
|
10
|
+
"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",
|
|
11
|
+
className
|
|
12
|
+
)}
|
|
13
|
+
{...props}
|
|
14
|
+
/>
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { Label }
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { Popover as PopoverPrimitive } from "@base-ui/react/popover"
|
|
3
|
+
|
|
4
|
+
import { cn } from "@workspace/ui/lib/utils"
|
|
5
|
+
|
|
6
|
+
function Popover({ ...props }: PopoverPrimitive.Root.Props) {
|
|
7
|
+
return <PopoverPrimitive.Root data-slot="popover" {...props} />
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function PopoverTrigger({ ...props }: PopoverPrimitive.Trigger.Props) {
|
|
11
|
+
return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function PopoverContent({
|
|
15
|
+
className,
|
|
16
|
+
align = "center",
|
|
17
|
+
alignOffset = 0,
|
|
18
|
+
side = "bottom",
|
|
19
|
+
sideOffset = 4,
|
|
20
|
+
...props
|
|
21
|
+
}: PopoverPrimitive.Popup.Props &
|
|
22
|
+
Pick<
|
|
23
|
+
PopoverPrimitive.Positioner.Props,
|
|
24
|
+
"align" | "alignOffset" | "side" | "sideOffset"
|
|
25
|
+
>) {
|
|
26
|
+
return (
|
|
27
|
+
<PopoverPrimitive.Portal>
|
|
28
|
+
<PopoverPrimitive.Positioner
|
|
29
|
+
align={align}
|
|
30
|
+
alignOffset={alignOffset}
|
|
31
|
+
side={side}
|
|
32
|
+
sideOffset={sideOffset}
|
|
33
|
+
className="isolate z-50"
|
|
34
|
+
>
|
|
35
|
+
<PopoverPrimitive.Popup
|
|
36
|
+
data-slot="popover-content"
|
|
37
|
+
className={cn(
|
|
38
|
+
"z-50 flex w-72 origin-(--transform-origin) flex-col gap-4 rounded-2xl bg-popover p-4 text-sm text-popover-foreground shadow-2xl ring-1 ring-foreground/5 outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-start-2 data-[side=inline-start]:slide-in-from-end-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-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
|
39
|
+
className
|
|
40
|
+
)}
|
|
41
|
+
{...props}
|
|
42
|
+
/>
|
|
43
|
+
</PopoverPrimitive.Positioner>
|
|
44
|
+
</PopoverPrimitive.Portal>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function PopoverHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
49
|
+
return (
|
|
50
|
+
<div
|
|
51
|
+
data-slot="popover-header"
|
|
52
|
+
className={cn("flex flex-col gap-1 text-sm", className)}
|
|
53
|
+
{...props}
|
|
54
|
+
/>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function PopoverTitle({ className, ...props }: PopoverPrimitive.Title.Props) {
|
|
59
|
+
return (
|
|
60
|
+
<PopoverPrimitive.Title
|
|
61
|
+
data-slot="popover-title"
|
|
62
|
+
className={cn("text-base font-medium", className)}
|
|
63
|
+
{...props}
|
|
64
|
+
/>
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function PopoverDescription({
|
|
69
|
+
className,
|
|
70
|
+
...props
|
|
71
|
+
}: PopoverPrimitive.Description.Props) {
|
|
72
|
+
return (
|
|
73
|
+
<PopoverPrimitive.Description
|
|
74
|
+
data-slot="popover-description"
|
|
75
|
+
className={cn("text-muted-foreground", className)}
|
|
76
|
+
{...props}
|
|
77
|
+
/>
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export {
|
|
82
|
+
Popover,
|
|
83
|
+
PopoverContent,
|
|
84
|
+
PopoverDescription,
|
|
85
|
+
PopoverHeader,
|
|
86
|
+
PopoverTitle,
|
|
87
|
+
PopoverTrigger,
|
|
88
|
+
}
|