@bupple/vss-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/.turbo/turbo-lint.log +4 -0
- package/components.json +21 -0
- package/eslint.config.js +4 -0
- package/index.ts +2 -0
- package/package.json +67 -0
- package/postcss.config.mjs +6 -0
- package/src/components/accordion.tsx +84 -0
- package/src/components/alert-dialog.tsx +198 -0
- package/src/components/alert.tsx +77 -0
- package/src/components/aspect-ratio.tsx +11 -0
- package/src/components/avatar.tsx +109 -0
- package/src/components/badge.tsx +50 -0
- package/src/components/breadcrumb.tsx +118 -0
- package/src/components/button-group.tsx +84 -0
- package/src/components/button.tsx +68 -0
- package/src/components/calendar.tsx +223 -0
- package/src/components/card.tsx +102 -0
- package/src/components/carousel.tsx +241 -0
- package/src/components/chart.tsx +373 -0
- package/src/components/checkbox.tsx +32 -0
- package/src/components/collapsible.tsx +33 -0
- package/src/components/combobox.tsx +299 -0
- package/src/components/command.tsx +194 -0
- package/src/components/context-menu.tsx +272 -0
- package/src/components/dialog.tsx +171 -0
- package/src/components/direction.tsx +20 -0
- package/src/components/drawer.tsx +130 -0
- package/src/components/dropdown-menu.tsx +278 -0
- package/src/components/empty.tsx +102 -0
- package/src/components/field.tsx +237 -0
- package/src/components/hover-card.tsx +43 -0
- package/src/components/input-group.tsx +157 -0
- package/src/components/input.tsx +18 -0
- package/src/components/item.tsx +197 -0
- package/src/components/kbd.tsx +26 -0
- package/src/components/label.tsx +21 -0
- package/src/components/menubar.tsx +283 -0
- package/src/components/native-select.tsx +64 -0
- package/src/components/navigation-menu.tsx +166 -0
- package/src/components/pagination.tsx +131 -0
- package/src/components/popover.tsx +88 -0
- package/src/components/progress.tsx +30 -0
- package/src/components/radio-group.tsx +46 -0
- package/src/components/resizable.tsx +49 -0
- package/src/components/scroll-area.tsx +52 -0
- package/src/components/select.tsx +209 -0
- package/src/components/separator.tsx +25 -0
- package/src/components/sheet.tsx +152 -0
- package/src/components/sidebar.tsx +703 -0
- package/src/components/skeleton.tsx +13 -0
- package/src/components/slider.tsx +58 -0
- package/src/components/sonner.tsx +45 -0
- package/src/components/spinner.tsx +15 -0
- package/src/components/switch.tsx +32 -0
- package/src/components/table.tsx +115 -0
- package/src/components/tabs.tsx +89 -0
- package/src/components/textarea.tsx +17 -0
- package/src/components/toggle-group.tsx +86 -0
- package/src/components/toggle.tsx +48 -0
- package/src/components/tooltip.tsx +56 -0
- package/src/hooks/use-mobile.ts +19 -0
- package/src/lib/portal-container.ts +11 -0
- package/src/lib/utils.ts +8 -0
- package/src/theme.css +125 -0
- package/tsconfig.json +15 -0
package/components.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema.json",
|
|
3
|
+
"style": "radix-nova",
|
|
4
|
+
"rsc": false,
|
|
5
|
+
"tsx": true,
|
|
6
|
+
"tailwind": {
|
|
7
|
+
"config": "",
|
|
8
|
+
"css": "src/styles/globals.css",
|
|
9
|
+
"baseColor": "neutral",
|
|
10
|
+
"cssVariables": true,
|
|
11
|
+
"prefix": ""
|
|
12
|
+
},
|
|
13
|
+
"aliases": {
|
|
14
|
+
"components": "@/components",
|
|
15
|
+
"utils": "@/utils",
|
|
16
|
+
"ui": "@/components/ui",
|
|
17
|
+
"lib": "@/lib",
|
|
18
|
+
"hooks": "@/hooks"
|
|
19
|
+
},
|
|
20
|
+
"iconLibrary": "lucide"
|
|
21
|
+
}
|
package/eslint.config.js
ADDED
package/index.ts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bupple/vss-ui",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"sideEffects": [
|
|
6
|
+
"**/*.css"
|
|
7
|
+
],
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"access": "public",
|
|
10
|
+
"registry": "https://registry.npmjs.org"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./index.ts",
|
|
15
|
+
"default": "./index.ts"
|
|
16
|
+
},
|
|
17
|
+
"./theme.css": "./src/theme.css",
|
|
18
|
+
"./components/*": "./src/components/*.tsx",
|
|
19
|
+
"./hooks/*": "./src/hooks/*.ts",
|
|
20
|
+
"./lib/*": "./src/lib/*.ts"
|
|
21
|
+
},
|
|
22
|
+
"peerDependencies": {
|
|
23
|
+
"next-themes": ">=0.4.6",
|
|
24
|
+
"react": ">=18 <20",
|
|
25
|
+
"react-dom": ">=18 <20",
|
|
26
|
+
"tailwindcss": ">=4"
|
|
27
|
+
},
|
|
28
|
+
"peerDependenciesMeta": {
|
|
29
|
+
"react-dom": {
|
|
30
|
+
"optional": false
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@base-ui/react": "^1.3.0",
|
|
35
|
+
"@tanstack/react-table": "^8.21.3",
|
|
36
|
+
"class-variance-authority": "^0.7.1",
|
|
37
|
+
"clsx": "^2.1.1",
|
|
38
|
+
"cmdk": "^1.1.1",
|
|
39
|
+
"date-fns": "^3.6.0",
|
|
40
|
+
"embla-carousel-react": "^8.6.0",
|
|
41
|
+
"input-otp": "^1.4.2",
|
|
42
|
+
"lucide-react": "^0.575.0",
|
|
43
|
+
"next-themes": "^0.4.6",
|
|
44
|
+
"radix-ui": "^1.4.3",
|
|
45
|
+
"react-day-picker": "^9.14.0",
|
|
46
|
+
"react-resizable-panels": "^4.9.0",
|
|
47
|
+
"recharts": "3.8.0",
|
|
48
|
+
"sonner": "^2.0.7",
|
|
49
|
+
"tailwind-merge": "^3.4.0",
|
|
50
|
+
"tw-animate-css": "^1.4.0",
|
|
51
|
+
"vaul": "^1.1.2"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/node": "^22",
|
|
55
|
+
"@types/react": "^19",
|
|
56
|
+
"@types/react-dom": "^19",
|
|
57
|
+
"eslint": "^9.20.1",
|
|
58
|
+
"tailwindcss": "^4.1.18",
|
|
59
|
+
"typescript": "^5.9.3",
|
|
60
|
+
"@bupple/eslint-config": "0.0.0",
|
|
61
|
+
"@bupple/typescript-config": "0.0.0"
|
|
62
|
+
},
|
|
63
|
+
"scripts": {
|
|
64
|
+
"lint": "eslint .",
|
|
65
|
+
"type-check": "tsc --noEmit"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { cn } from '@bupple/vss-ui/lib/utils'
|
|
2
|
+
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-react'
|
|
3
|
+
import { Accordion as AccordionPrimitive } from 'radix-ui'
|
|
4
|
+
import * as React from 'react'
|
|
5
|
+
|
|
6
|
+
function Accordion({
|
|
7
|
+
className,
|
|
8
|
+
...props
|
|
9
|
+
}: React.ComponentProps<typeof AccordionPrimitive.Root>) {
|
|
10
|
+
return (
|
|
11
|
+
<AccordionPrimitive.Root
|
|
12
|
+
data-slot='accordion'
|
|
13
|
+
className={cn('flex w-full flex-col', className)}
|
|
14
|
+
{...props}
|
|
15
|
+
/>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function AccordionItem({
|
|
20
|
+
className,
|
|
21
|
+
...props
|
|
22
|
+
}: React.ComponentProps<typeof AccordionPrimitive.Item>) {
|
|
23
|
+
return (
|
|
24
|
+
<AccordionPrimitive.Item
|
|
25
|
+
data-slot='accordion-item'
|
|
26
|
+
className={cn('not-last:border-b', className)}
|
|
27
|
+
{...props}
|
|
28
|
+
/>
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function AccordionTrigger({
|
|
33
|
+
className,
|
|
34
|
+
children,
|
|
35
|
+
...props
|
|
36
|
+
}: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {
|
|
37
|
+
return (
|
|
38
|
+
<AccordionPrimitive.Header className='flex'>
|
|
39
|
+
<AccordionPrimitive.Trigger
|
|
40
|
+
data-slot='accordion-trigger'
|
|
41
|
+
className={cn(
|
|
42
|
+
'group/accordion-trigger relative flex flex-1 items-start justify-between rounded-lg border border-transparent py-2.5 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:after:border-ring disabled:pointer-events-none disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4 **:data-[slot=accordion-trigger-icon]:text-muted-foreground',
|
|
43
|
+
className,
|
|
44
|
+
)}
|
|
45
|
+
{...props}
|
|
46
|
+
>
|
|
47
|
+
{children}
|
|
48
|
+
<ChevronDownIcon
|
|
49
|
+
data-slot='accordion-trigger-icon'
|
|
50
|
+
className='pointer-events-none shrink-0 group-aria-expanded/accordion-trigger:hidden'
|
|
51
|
+
/>
|
|
52
|
+
<ChevronUpIcon
|
|
53
|
+
data-slot='accordion-trigger-icon'
|
|
54
|
+
className='pointer-events-none hidden shrink-0 group-aria-expanded/accordion-trigger:inline'
|
|
55
|
+
/>
|
|
56
|
+
</AccordionPrimitive.Trigger>
|
|
57
|
+
</AccordionPrimitive.Header>
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function AccordionContent({
|
|
62
|
+
className,
|
|
63
|
+
children,
|
|
64
|
+
...props
|
|
65
|
+
}: React.ComponentProps<typeof AccordionPrimitive.Content>) {
|
|
66
|
+
return (
|
|
67
|
+
<AccordionPrimitive.Content
|
|
68
|
+
data-slot='accordion-content'
|
|
69
|
+
className='overflow-hidden text-sm data-open:animate-accordion-down data-closed:animate-accordion-up'
|
|
70
|
+
{...props}
|
|
71
|
+
>
|
|
72
|
+
<div
|
|
73
|
+
className={cn(
|
|
74
|
+
'h-(--radix-accordion-content-height) pt-0 pb-2.5 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4',
|
|
75
|
+
className,
|
|
76
|
+
)}
|
|
77
|
+
>
|
|
78
|
+
{children}
|
|
79
|
+
</div>
|
|
80
|
+
</AccordionPrimitive.Content>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { Button } from '@bupple/vss-ui/components/button'
|
|
4
|
+
import { cn } from '@bupple/vss-ui/lib/utils'
|
|
5
|
+
import { AlertDialog as AlertDialogPrimitive } from 'radix-ui'
|
|
6
|
+
import * as React from 'react'
|
|
7
|
+
|
|
8
|
+
function AlertDialog({
|
|
9
|
+
...props
|
|
10
|
+
}: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {
|
|
11
|
+
return <AlertDialogPrimitive.Root data-slot='alert-dialog' {...props} />
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function AlertDialogTrigger({
|
|
15
|
+
...props
|
|
16
|
+
}: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {
|
|
17
|
+
return (
|
|
18
|
+
<AlertDialogPrimitive.Trigger data-slot='alert-dialog-trigger' {...props} />
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function AlertDialogPortal({
|
|
23
|
+
...props
|
|
24
|
+
}: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) {
|
|
25
|
+
return (
|
|
26
|
+
<AlertDialogPrimitive.Portal data-slot='alert-dialog-portal' {...props} />
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function AlertDialogOverlay({
|
|
31
|
+
className,
|
|
32
|
+
...props
|
|
33
|
+
}: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) {
|
|
34
|
+
return (
|
|
35
|
+
<AlertDialogPrimitive.Overlay
|
|
36
|
+
data-slot='alert-dialog-overlay'
|
|
37
|
+
className={cn(
|
|
38
|
+
'fixed inset-0 z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0',
|
|
39
|
+
className,
|
|
40
|
+
)}
|
|
41
|
+
{...props}
|
|
42
|
+
/>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function AlertDialogContent({
|
|
47
|
+
className,
|
|
48
|
+
size = 'default',
|
|
49
|
+
...props
|
|
50
|
+
}: React.ComponentProps<typeof AlertDialogPrimitive.Content> & {
|
|
51
|
+
size?: 'default' | 'sm'
|
|
52
|
+
}) {
|
|
53
|
+
return (
|
|
54
|
+
<AlertDialogPortal>
|
|
55
|
+
<AlertDialogOverlay />
|
|
56
|
+
<AlertDialogPrimitive.Content
|
|
57
|
+
data-slot='alert-dialog-content'
|
|
58
|
+
data-size={size}
|
|
59
|
+
className={cn(
|
|
60
|
+
'group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-sm 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',
|
|
61
|
+
className,
|
|
62
|
+
)}
|
|
63
|
+
{...props}
|
|
64
|
+
/>
|
|
65
|
+
</AlertDialogPortal>
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function AlertDialogHeader({
|
|
70
|
+
className,
|
|
71
|
+
...props
|
|
72
|
+
}: React.ComponentProps<'div'>) {
|
|
73
|
+
return (
|
|
74
|
+
<div
|
|
75
|
+
data-slot='alert-dialog-header'
|
|
76
|
+
className={cn(
|
|
77
|
+
'grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]',
|
|
78
|
+
className,
|
|
79
|
+
)}
|
|
80
|
+
{...props}
|
|
81
|
+
/>
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function AlertDialogFooter({
|
|
86
|
+
className,
|
|
87
|
+
...props
|
|
88
|
+
}: React.ComponentProps<'div'>) {
|
|
89
|
+
return (
|
|
90
|
+
<div
|
|
91
|
+
data-slot='alert-dialog-footer'
|
|
92
|
+
className={cn(
|
|
93
|
+
'-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end',
|
|
94
|
+
className,
|
|
95
|
+
)}
|
|
96
|
+
{...props}
|
|
97
|
+
/>
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function AlertDialogMedia({
|
|
102
|
+
className,
|
|
103
|
+
...props
|
|
104
|
+
}: React.ComponentProps<'div'>) {
|
|
105
|
+
return (
|
|
106
|
+
<div
|
|
107
|
+
data-slot='alert-dialog-media'
|
|
108
|
+
className={cn(
|
|
109
|
+
"mb-2 inline-flex size-10 items-center justify-center rounded-md bg-muted sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-6",
|
|
110
|
+
className,
|
|
111
|
+
)}
|
|
112
|
+
{...props}
|
|
113
|
+
/>
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function AlertDialogTitle({
|
|
118
|
+
className,
|
|
119
|
+
...props
|
|
120
|
+
}: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {
|
|
121
|
+
return (
|
|
122
|
+
<AlertDialogPrimitive.Title
|
|
123
|
+
data-slot='alert-dialog-title'
|
|
124
|
+
className={cn(
|
|
125
|
+
'text-base font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2',
|
|
126
|
+
className,
|
|
127
|
+
)}
|
|
128
|
+
{...props}
|
|
129
|
+
/>
|
|
130
|
+
)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function AlertDialogDescription({
|
|
134
|
+
className,
|
|
135
|
+
...props
|
|
136
|
+
}: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {
|
|
137
|
+
return (
|
|
138
|
+
<AlertDialogPrimitive.Description
|
|
139
|
+
data-slot='alert-dialog-description'
|
|
140
|
+
className={cn(
|
|
141
|
+
'text-sm text-balance text-muted-foreground md:text-pretty *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground',
|
|
142
|
+
className,
|
|
143
|
+
)}
|
|
144
|
+
{...props}
|
|
145
|
+
/>
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function AlertDialogAction({
|
|
150
|
+
className,
|
|
151
|
+
variant = 'default',
|
|
152
|
+
size = 'default',
|
|
153
|
+
...props
|
|
154
|
+
}: React.ComponentProps<typeof AlertDialogPrimitive.Action> &
|
|
155
|
+
Pick<React.ComponentProps<typeof Button>, 'variant' | 'size'>) {
|
|
156
|
+
return (
|
|
157
|
+
<Button variant={variant} size={size} asChild>
|
|
158
|
+
<AlertDialogPrimitive.Action
|
|
159
|
+
data-slot='alert-dialog-action'
|
|
160
|
+
className={cn(className)}
|
|
161
|
+
{...props}
|
|
162
|
+
/>
|
|
163
|
+
</Button>
|
|
164
|
+
)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function AlertDialogCancel({
|
|
168
|
+
className,
|
|
169
|
+
variant = 'outline',
|
|
170
|
+
size = 'default',
|
|
171
|
+
...props
|
|
172
|
+
}: React.ComponentProps<typeof AlertDialogPrimitive.Cancel> &
|
|
173
|
+
Pick<React.ComponentProps<typeof Button>, 'variant' | 'size'>) {
|
|
174
|
+
return (
|
|
175
|
+
<Button variant={variant} size={size} asChild>
|
|
176
|
+
<AlertDialogPrimitive.Cancel
|
|
177
|
+
data-slot='alert-dialog-cancel'
|
|
178
|
+
className={cn(className)}
|
|
179
|
+
{...props}
|
|
180
|
+
/>
|
|
181
|
+
</Button>
|
|
182
|
+
)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export {
|
|
186
|
+
AlertDialog,
|
|
187
|
+
AlertDialogAction,
|
|
188
|
+
AlertDialogCancel,
|
|
189
|
+
AlertDialogContent,
|
|
190
|
+
AlertDialogDescription,
|
|
191
|
+
AlertDialogFooter,
|
|
192
|
+
AlertDialogHeader,
|
|
193
|
+
AlertDialogMedia,
|
|
194
|
+
AlertDialogOverlay,
|
|
195
|
+
AlertDialogPortal,
|
|
196
|
+
AlertDialogTitle,
|
|
197
|
+
AlertDialogTrigger,
|
|
198
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { VariantProps } from 'class-variance-authority'
|
|
2
|
+
|
|
3
|
+
import { cn } from '@bupple/vss-ui/lib/utils'
|
|
4
|
+
import { cva } from 'class-variance-authority'
|
|
5
|
+
import * as React from 'react'
|
|
6
|
+
|
|
7
|
+
const alertVariants = cva(
|
|
8
|
+
"group/alert relative grid w-full gap-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4",
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default: 'bg-card text-card-foreground',
|
|
13
|
+
destructive:
|
|
14
|
+
'bg-card text-destructive *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
defaultVariants: {
|
|
18
|
+
variant: 'default',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
function Alert({
|
|
24
|
+
className,
|
|
25
|
+
variant,
|
|
26
|
+
...props
|
|
27
|
+
}: React.ComponentProps<'div'> & VariantProps<typeof alertVariants>) {
|
|
28
|
+
return (
|
|
29
|
+
<div
|
|
30
|
+
data-slot='alert'
|
|
31
|
+
role='alert'
|
|
32
|
+
className={cn(alertVariants({ variant }), className)}
|
|
33
|
+
{...props}
|
|
34
|
+
/>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function AlertTitle({ className, ...props }: React.ComponentProps<'div'>) {
|
|
39
|
+
return (
|
|
40
|
+
<div
|
|
41
|
+
data-slot='alert-title'
|
|
42
|
+
className={cn(
|
|
43
|
+
'font-medium group-has-[>svg]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground',
|
|
44
|
+
className,
|
|
45
|
+
)}
|
|
46
|
+
{...props}
|
|
47
|
+
/>
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function AlertDescription({
|
|
52
|
+
className,
|
|
53
|
+
...props
|
|
54
|
+
}: React.ComponentProps<'div'>) {
|
|
55
|
+
return (
|
|
56
|
+
<div
|
|
57
|
+
data-slot='alert-description'
|
|
58
|
+
className={cn(
|
|
59
|
+
'text-sm text-balance text-muted-foreground md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4',
|
|
60
|
+
className,
|
|
61
|
+
)}
|
|
62
|
+
{...props}
|
|
63
|
+
/>
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function AlertAction({ className, ...props }: React.ComponentProps<'div'>) {
|
|
68
|
+
return (
|
|
69
|
+
<div
|
|
70
|
+
data-slot='alert-action'
|
|
71
|
+
className={cn('absolute top-2 right-2', className)}
|
|
72
|
+
{...props}
|
|
73
|
+
/>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export { Alert, AlertTitle, AlertDescription, AlertAction }
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { AspectRatio as AspectRatioPrimitive } from 'radix-ui'
|
|
4
|
+
|
|
5
|
+
function AspectRatio({
|
|
6
|
+
...props
|
|
7
|
+
}: React.ComponentProps<typeof AspectRatioPrimitive.Root>) {
|
|
8
|
+
return <AspectRatioPrimitive.Root data-slot='aspect-ratio' {...props} />
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export { AspectRatio }
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { cn } from '@bupple/vss-ui/lib/utils'
|
|
2
|
+
import { Avatar as AvatarPrimitive } from 'radix-ui'
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
|
|
5
|
+
function Avatar({
|
|
6
|
+
className,
|
|
7
|
+
size = 'default',
|
|
8
|
+
...props
|
|
9
|
+
}: React.ComponentProps<typeof AvatarPrimitive.Root> & {
|
|
10
|
+
size?: 'default' | 'sm' | 'lg'
|
|
11
|
+
}) {
|
|
12
|
+
return (
|
|
13
|
+
<AvatarPrimitive.Root
|
|
14
|
+
data-slot='avatar'
|
|
15
|
+
data-size={size}
|
|
16
|
+
className={cn(
|
|
17
|
+
'group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6 dark:after:mix-blend-lighten',
|
|
18
|
+
className,
|
|
19
|
+
)}
|
|
20
|
+
{...props}
|
|
21
|
+
/>
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function AvatarImage({
|
|
26
|
+
className,
|
|
27
|
+
...props
|
|
28
|
+
}: React.ComponentProps<typeof AvatarPrimitive.Image>) {
|
|
29
|
+
return (
|
|
30
|
+
<AvatarPrimitive.Image
|
|
31
|
+
data-slot='avatar-image'
|
|
32
|
+
className={cn(
|
|
33
|
+
'aspect-square size-full rounded-full object-cover',
|
|
34
|
+
className,
|
|
35
|
+
)}
|
|
36
|
+
{...props}
|
|
37
|
+
/>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function AvatarFallback({
|
|
42
|
+
className,
|
|
43
|
+
...props
|
|
44
|
+
}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
|
|
45
|
+
return (
|
|
46
|
+
<AvatarPrimitive.Fallback
|
|
47
|
+
data-slot='avatar-fallback'
|
|
48
|
+
className={cn(
|
|
49
|
+
'flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs',
|
|
50
|
+
className,
|
|
51
|
+
)}
|
|
52
|
+
{...props}
|
|
53
|
+
/>
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function AvatarBadge({ className, ...props }: React.ComponentProps<'span'>) {
|
|
58
|
+
return (
|
|
59
|
+
<span
|
|
60
|
+
data-slot='avatar-badge'
|
|
61
|
+
className={cn(
|
|
62
|
+
'absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-primary text-primary-foreground bg-blend-color ring-2 ring-background select-none',
|
|
63
|
+
'group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden',
|
|
64
|
+
'group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2',
|
|
65
|
+
'group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2',
|
|
66
|
+
className,
|
|
67
|
+
)}
|
|
68
|
+
{...props}
|
|
69
|
+
/>
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function AvatarGroup({ className, ...props }: React.ComponentProps<'div'>) {
|
|
74
|
+
return (
|
|
75
|
+
<div
|
|
76
|
+
data-slot='avatar-group'
|
|
77
|
+
className={cn(
|
|
78
|
+
'group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background',
|
|
79
|
+
className,
|
|
80
|
+
)}
|
|
81
|
+
{...props}
|
|
82
|
+
/>
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function AvatarGroupCount({
|
|
87
|
+
className,
|
|
88
|
+
...props
|
|
89
|
+
}: React.ComponentProps<'div'>) {
|
|
90
|
+
return (
|
|
91
|
+
<div
|
|
92
|
+
data-slot='avatar-group-count'
|
|
93
|
+
className={cn(
|
|
94
|
+
'relative flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-sm text-muted-foreground ring-2 ring-background group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3',
|
|
95
|
+
className,
|
|
96
|
+
)}
|
|
97
|
+
{...props}
|
|
98
|
+
/>
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export {
|
|
103
|
+
Avatar,
|
|
104
|
+
AvatarImage,
|
|
105
|
+
AvatarFallback,
|
|
106
|
+
AvatarGroup,
|
|
107
|
+
AvatarGroupCount,
|
|
108
|
+
AvatarBadge,
|
|
109
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { VariantProps } from 'class-variance-authority'
|
|
2
|
+
|
|
3
|
+
import { cn } from '@bupple/vss-ui/lib/utils'
|
|
4
|
+
import { cva } from 'class-variance-authority'
|
|
5
|
+
import { Slot } from 'radix-ui'
|
|
6
|
+
import * as React from 'react'
|
|
7
|
+
|
|
8
|
+
const badgeVariants = cva(
|
|
9
|
+
'group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!',
|
|
10
|
+
{
|
|
11
|
+
variants: {
|
|
12
|
+
variant: {
|
|
13
|
+
default: 'bg-primary text-primary-foreground [a]:hover:bg-primary/80',
|
|
14
|
+
secondary:
|
|
15
|
+
'bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80',
|
|
16
|
+
destructive:
|
|
17
|
+
'bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20',
|
|
18
|
+
outline:
|
|
19
|
+
'border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground',
|
|
20
|
+
ghost:
|
|
21
|
+
'hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50',
|
|
22
|
+
link: 'text-primary underline-offset-4 hover:underline',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
defaultVariants: {
|
|
26
|
+
variant: 'default',
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
function Badge({
|
|
32
|
+
className,
|
|
33
|
+
variant = 'default',
|
|
34
|
+
asChild = false,
|
|
35
|
+
...props
|
|
36
|
+
}: React.ComponentProps<'span'> &
|
|
37
|
+
VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
|
|
38
|
+
const Comp = asChild ? Slot.Root : 'span'
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<Comp
|
|
42
|
+
data-slot='badge'
|
|
43
|
+
data-variant={variant}
|
|
44
|
+
className={cn(badgeVariants({ variant }), className)}
|
|
45
|
+
{...props}
|
|
46
|
+
/>
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { Badge, badgeVariants }
|