@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.
Files changed (65) hide show
  1. package/.turbo/turbo-lint.log +4 -0
  2. package/components.json +21 -0
  3. package/eslint.config.js +4 -0
  4. package/index.ts +2 -0
  5. package/package.json +67 -0
  6. package/postcss.config.mjs +6 -0
  7. package/src/components/accordion.tsx +84 -0
  8. package/src/components/alert-dialog.tsx +198 -0
  9. package/src/components/alert.tsx +77 -0
  10. package/src/components/aspect-ratio.tsx +11 -0
  11. package/src/components/avatar.tsx +109 -0
  12. package/src/components/badge.tsx +50 -0
  13. package/src/components/breadcrumb.tsx +118 -0
  14. package/src/components/button-group.tsx +84 -0
  15. package/src/components/button.tsx +68 -0
  16. package/src/components/calendar.tsx +223 -0
  17. package/src/components/card.tsx +102 -0
  18. package/src/components/carousel.tsx +241 -0
  19. package/src/components/chart.tsx +373 -0
  20. package/src/components/checkbox.tsx +32 -0
  21. package/src/components/collapsible.tsx +33 -0
  22. package/src/components/combobox.tsx +299 -0
  23. package/src/components/command.tsx +194 -0
  24. package/src/components/context-menu.tsx +272 -0
  25. package/src/components/dialog.tsx +171 -0
  26. package/src/components/direction.tsx +20 -0
  27. package/src/components/drawer.tsx +130 -0
  28. package/src/components/dropdown-menu.tsx +278 -0
  29. package/src/components/empty.tsx +102 -0
  30. package/src/components/field.tsx +237 -0
  31. package/src/components/hover-card.tsx +43 -0
  32. package/src/components/input-group.tsx +157 -0
  33. package/src/components/input.tsx +18 -0
  34. package/src/components/item.tsx +197 -0
  35. package/src/components/kbd.tsx +26 -0
  36. package/src/components/label.tsx +21 -0
  37. package/src/components/menubar.tsx +283 -0
  38. package/src/components/native-select.tsx +64 -0
  39. package/src/components/navigation-menu.tsx +166 -0
  40. package/src/components/pagination.tsx +131 -0
  41. package/src/components/popover.tsx +88 -0
  42. package/src/components/progress.tsx +30 -0
  43. package/src/components/radio-group.tsx +46 -0
  44. package/src/components/resizable.tsx +49 -0
  45. package/src/components/scroll-area.tsx +52 -0
  46. package/src/components/select.tsx +209 -0
  47. package/src/components/separator.tsx +25 -0
  48. package/src/components/sheet.tsx +152 -0
  49. package/src/components/sidebar.tsx +703 -0
  50. package/src/components/skeleton.tsx +13 -0
  51. package/src/components/slider.tsx +58 -0
  52. package/src/components/sonner.tsx +45 -0
  53. package/src/components/spinner.tsx +15 -0
  54. package/src/components/switch.tsx +32 -0
  55. package/src/components/table.tsx +115 -0
  56. package/src/components/tabs.tsx +89 -0
  57. package/src/components/textarea.tsx +17 -0
  58. package/src/components/toggle-group.tsx +86 -0
  59. package/src/components/toggle.tsx +48 -0
  60. package/src/components/tooltip.tsx +56 -0
  61. package/src/hooks/use-mobile.ts +19 -0
  62. package/src/lib/portal-container.ts +11 -0
  63. package/src/lib/utils.ts +8 -0
  64. package/src/theme.css +125 -0
  65. package/tsconfig.json +15 -0
@@ -0,0 +1,299 @@
1
+ import { Combobox as ComboboxPrimitive } from '@base-ui/react'
2
+ import { Button } from '@bupple/vss-ui/components/button'
3
+ import {
4
+ InputGroup,
5
+ InputGroupAddon,
6
+ InputGroupButton,
7
+ InputGroupInput,
8
+ } from '@bupple/vss-ui/components/input-group'
9
+ import { cn } from '@bupple/vss-ui/lib/utils'
10
+ import { CheckIcon, ChevronDownIcon, XIcon } from 'lucide-react'
11
+ import * as React from 'react'
12
+
13
+ const Combobox = ComboboxPrimitive.Root
14
+
15
+ function ComboboxValue({ ...props }: ComboboxPrimitive.Value.Props) {
16
+ return <ComboboxPrimitive.Value data-slot='combobox-value' {...props} />
17
+ }
18
+
19
+ function ComboboxTrigger({
20
+ className,
21
+ children,
22
+ ...props
23
+ }: ComboboxPrimitive.Trigger.Props) {
24
+ return (
25
+ <ComboboxPrimitive.Trigger
26
+ data-slot='combobox-trigger'
27
+ className={cn("[&_svg:not([class*='size-'])]:size-4", className)}
28
+ {...props}
29
+ >
30
+ {children}
31
+ <ChevronDownIcon className='pointer-events-none size-4 text-muted-foreground' />
32
+ </ComboboxPrimitive.Trigger>
33
+ )
34
+ }
35
+
36
+ function ComboboxClear({ className, ...props }: ComboboxPrimitive.Clear.Props) {
37
+ return (
38
+ <ComboboxPrimitive.Clear
39
+ data-slot='combobox-clear'
40
+ render={<InputGroupButton variant='ghost' size='icon-xs' />}
41
+ className={cn(className)}
42
+ {...props}
43
+ >
44
+ <XIcon className='pointer-events-none' />
45
+ </ComboboxPrimitive.Clear>
46
+ )
47
+ }
48
+
49
+ function ComboboxInput({
50
+ className,
51
+ children,
52
+ disabled = false,
53
+ showTrigger = true,
54
+ showClear = false,
55
+ ...props
56
+ }: ComboboxPrimitive.Input.Props & {
57
+ showTrigger?: boolean
58
+ showClear?: boolean
59
+ }) {
60
+ return (
61
+ <InputGroup className={cn('w-auto', className)}>
62
+ <ComboboxPrimitive.Input
63
+ render={<InputGroupInput disabled={disabled} />}
64
+ {...props}
65
+ />
66
+ <InputGroupAddon align='inline-end'>
67
+ {showTrigger && (
68
+ <InputGroupButton
69
+ size='icon-xs'
70
+ variant='ghost'
71
+ asChild
72
+ data-slot='input-group-button'
73
+ className='group-has-data-[slot=combobox-clear]/input-group:hidden data-pressed:bg-transparent'
74
+ disabled={disabled}
75
+ >
76
+ <ComboboxTrigger />
77
+ </InputGroupButton>
78
+ )}
79
+ {showClear && <ComboboxClear disabled={disabled} />}
80
+ </InputGroupAddon>
81
+ {children}
82
+ </InputGroup>
83
+ )
84
+ }
85
+
86
+ function ComboboxContent({
87
+ className,
88
+ side = 'bottom',
89
+ sideOffset = 6,
90
+ align = 'start',
91
+ alignOffset = 0,
92
+ anchor,
93
+ ...props
94
+ }: ComboboxPrimitive.Popup.Props &
95
+ Pick<
96
+ ComboboxPrimitive.Positioner.Props,
97
+ 'side' | 'align' | 'sideOffset' | 'alignOffset' | 'anchor'
98
+ >) {
99
+ return (
100
+ <ComboboxPrimitive.Portal>
101
+ <ComboboxPrimitive.Positioner
102
+ side={side}
103
+ sideOffset={sideOffset}
104
+ align={align}
105
+ alignOffset={alignOffset}
106
+ anchor={anchor}
107
+ className='isolate z-50'
108
+ >
109
+ <ComboboxPrimitive.Popup
110
+ data-slot='combobox-content'
111
+ data-chips={!!anchor}
112
+ className={cn(
113
+ 'group/combobox-content relative max-h-(--available-height) w-(--anchor-width) max-w-(--available-width) min-w-[calc(var(--anchor-width)+--spacing(7))] origin-(--transform-origin) overflow-hidden rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[chips=true]:min-w-(--anchor-width) data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-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-[slot=input-group]:m-1 *:data-[slot=input-group]:mb-0 *:data-[slot=input-group]:h-8 *:data-[slot=input-group]:border-input/30 *:data-[slot=input-group]:bg-input/30 *:data-[slot=input-group]:shadow-none 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',
114
+ className,
115
+ )}
116
+ {...props}
117
+ />
118
+ </ComboboxPrimitive.Positioner>
119
+ </ComboboxPrimitive.Portal>
120
+ )
121
+ }
122
+
123
+ function ComboboxList({ className, ...props }: ComboboxPrimitive.List.Props) {
124
+ return (
125
+ <ComboboxPrimitive.List
126
+ data-slot='combobox-list'
127
+ className={cn(
128
+ 'no-scrollbar max-h-[min(calc(--spacing(72)---spacing(9)),calc(var(--available-height)---spacing(9)))] scroll-py-1 overflow-y-auto overscroll-contain p-1 data-empty:p-0',
129
+ className,
130
+ )}
131
+ {...props}
132
+ />
133
+ )
134
+ }
135
+
136
+ function ComboboxItem({
137
+ className,
138
+ children,
139
+ ...props
140
+ }: ComboboxPrimitive.Item.Props) {
141
+ return (
142
+ <ComboboxPrimitive.Item
143
+ data-slot='combobox-item'
144
+ className={cn(
145
+ "relative flex w-full cursor-default items-center gap-2 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none data-highlighted:bg-accent data-highlighted:text-accent-foreground not-data-[variant=destructive]:data-highlighted:**: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",
146
+ className,
147
+ )}
148
+ {...props}
149
+ >
150
+ {children}
151
+ <ComboboxPrimitive.ItemIndicator
152
+ render={
153
+ <span className='pointer-events-none absolute right-2 flex size-4 items-center justify-center' />
154
+ }
155
+ >
156
+ <CheckIcon className='pointer-events-none' />
157
+ </ComboboxPrimitive.ItemIndicator>
158
+ </ComboboxPrimitive.Item>
159
+ )
160
+ }
161
+
162
+ function ComboboxGroup({ className, ...props }: ComboboxPrimitive.Group.Props) {
163
+ return (
164
+ <ComboboxPrimitive.Group
165
+ data-slot='combobox-group'
166
+ className={cn(className)}
167
+ {...props}
168
+ />
169
+ )
170
+ }
171
+
172
+ function ComboboxLabel({
173
+ className,
174
+ ...props
175
+ }: ComboboxPrimitive.GroupLabel.Props) {
176
+ return (
177
+ <ComboboxPrimitive.GroupLabel
178
+ data-slot='combobox-label'
179
+ className={cn('px-2 py-1.5 text-xs text-muted-foreground', className)}
180
+ {...props}
181
+ />
182
+ )
183
+ }
184
+
185
+ function ComboboxCollection({ ...props }: ComboboxPrimitive.Collection.Props) {
186
+ return (
187
+ <ComboboxPrimitive.Collection data-slot='combobox-collection' {...props} />
188
+ )
189
+ }
190
+
191
+ function ComboboxEmpty({ className, ...props }: ComboboxPrimitive.Empty.Props) {
192
+ return (
193
+ <ComboboxPrimitive.Empty
194
+ data-slot='combobox-empty'
195
+ className={cn(
196
+ 'hidden w-full justify-center py-2 text-center text-sm text-muted-foreground group-data-empty/combobox-content:flex',
197
+ className,
198
+ )}
199
+ {...props}
200
+ />
201
+ )
202
+ }
203
+
204
+ function ComboboxSeparator({
205
+ className,
206
+ ...props
207
+ }: ComboboxPrimitive.Separator.Props) {
208
+ return (
209
+ <ComboboxPrimitive.Separator
210
+ data-slot='combobox-separator'
211
+ className={cn('-mx-1 my-1 h-px bg-border', className)}
212
+ {...props}
213
+ />
214
+ )
215
+ }
216
+
217
+ function ComboboxChips({
218
+ className,
219
+ ...props
220
+ }: React.ComponentPropsWithRef<typeof ComboboxPrimitive.Chips> &
221
+ ComboboxPrimitive.Chips.Props) {
222
+ return (
223
+ <ComboboxPrimitive.Chips
224
+ data-slot='combobox-chips'
225
+ className={cn(
226
+ 'flex min-h-8 flex-wrap items-center gap-1 rounded-lg border border-input bg-transparent bg-clip-padding px-2.5 py-1 text-sm transition-colors focus-within:border-ring focus-within:ring-3 focus-within:ring-ring/50 has-aria-invalid:border-destructive has-aria-invalid:ring-3 has-aria-invalid:ring-destructive/20 has-data-[slot=combobox-chip]:px-1 dark:bg-input/30 dark:has-aria-invalid:border-destructive/50 dark:has-aria-invalid:ring-destructive/40',
227
+ className,
228
+ )}
229
+ {...props}
230
+ />
231
+ )
232
+ }
233
+
234
+ function ComboboxChip({
235
+ className,
236
+ children,
237
+ showRemove = true,
238
+ ...props
239
+ }: ComboboxPrimitive.Chip.Props & {
240
+ showRemove?: boolean
241
+ }) {
242
+ return (
243
+ <ComboboxPrimitive.Chip
244
+ data-slot='combobox-chip'
245
+ className={cn(
246
+ 'flex h-[calc(--spacing(5.25))] w-fit items-center justify-center gap-1 rounded-sm bg-muted px-1.5 text-xs font-medium whitespace-nowrap text-foreground has-disabled:pointer-events-none has-disabled:cursor-not-allowed has-disabled:opacity-50 has-data-[slot=combobox-chip-remove]:pr-0',
247
+ className,
248
+ )}
249
+ {...props}
250
+ >
251
+ {children}
252
+ {showRemove && (
253
+ <ComboboxPrimitive.ChipRemove
254
+ render={<Button variant='ghost' size='icon-xs' />}
255
+ className='-ml-1 opacity-50 hover:opacity-100'
256
+ data-slot='combobox-chip-remove'
257
+ >
258
+ <XIcon className='pointer-events-none' />
259
+ </ComboboxPrimitive.ChipRemove>
260
+ )}
261
+ </ComboboxPrimitive.Chip>
262
+ )
263
+ }
264
+
265
+ function ComboboxChipsInput({
266
+ className,
267
+ ...props
268
+ }: ComboboxPrimitive.Input.Props) {
269
+ return (
270
+ <ComboboxPrimitive.Input
271
+ data-slot='combobox-chip-input'
272
+ className={cn('min-w-16 flex-1 outline-none', className)}
273
+ {...props}
274
+ />
275
+ )
276
+ }
277
+
278
+ function useComboboxAnchor() {
279
+ return React.useRef<HTMLDivElement | null>(null)
280
+ }
281
+
282
+ export {
283
+ Combobox,
284
+ ComboboxInput,
285
+ ComboboxContent,
286
+ ComboboxList,
287
+ ComboboxItem,
288
+ ComboboxGroup,
289
+ ComboboxLabel,
290
+ ComboboxCollection,
291
+ ComboboxEmpty,
292
+ ComboboxSeparator,
293
+ ComboboxChips,
294
+ ComboboxChip,
295
+ ComboboxChipsInput,
296
+ ComboboxTrigger,
297
+ ComboboxValue,
298
+ useComboboxAnchor,
299
+ }
@@ -0,0 +1,194 @@
1
+ 'use client'
2
+
3
+ import {
4
+ Dialog,
5
+ DialogContent,
6
+ DialogDescription,
7
+ DialogHeader,
8
+ DialogTitle,
9
+ } from '@bupple/vss-ui/components/dialog'
10
+ import {
11
+ InputGroup,
12
+ InputGroupAddon,
13
+ } from '@bupple/vss-ui/components/input-group'
14
+ import { cn } from '@bupple/vss-ui/lib/utils'
15
+ import { Command as CommandPrimitive } from 'cmdk'
16
+ import { CheckIcon, SearchIcon } from 'lucide-react'
17
+ import * as React from 'react'
18
+
19
+ function Command({
20
+ className,
21
+ ...props
22
+ }: React.ComponentProps<typeof CommandPrimitive>) {
23
+ return (
24
+ <CommandPrimitive
25
+ data-slot='command'
26
+ className={cn(
27
+ 'flex size-full flex-col overflow-hidden rounded-xl! bg-popover p-1 text-popover-foreground',
28
+ className,
29
+ )}
30
+ {...props}
31
+ />
32
+ )
33
+ }
34
+
35
+ function CommandDialog({
36
+ title = 'Command Palette',
37
+ description = 'Search for a command to run...',
38
+ children,
39
+ className,
40
+ showCloseButton = false,
41
+ ...props
42
+ }: React.ComponentProps<typeof Dialog> & {
43
+ title?: string
44
+ description?: string
45
+ className?: string
46
+ showCloseButton?: boolean
47
+ }) {
48
+ return (
49
+ <Dialog {...props}>
50
+ <DialogHeader className='sr-only'>
51
+ <DialogTitle>{title}</DialogTitle>
52
+ <DialogDescription>{description}</DialogDescription>
53
+ </DialogHeader>
54
+ <DialogContent
55
+ className={cn(
56
+ 'top-1/3 translate-y-0 overflow-hidden rounded-xl! p-0',
57
+ className,
58
+ )}
59
+ showCloseButton={showCloseButton}
60
+ >
61
+ {children}
62
+ </DialogContent>
63
+ </Dialog>
64
+ )
65
+ }
66
+
67
+ function CommandInput({
68
+ className,
69
+ ...props
70
+ }: React.ComponentProps<typeof CommandPrimitive.Input>) {
71
+ return (
72
+ <div data-slot='command-input-wrapper' className='p-1 pb-0'>
73
+ <InputGroup className='h-8! rounded-lg! border-input/30 bg-input/30 shadow-none! *:data-[slot=input-group-addon]:pl-2!'>
74
+ <CommandPrimitive.Input
75
+ data-slot='command-input'
76
+ className={cn(
77
+ 'w-full text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50',
78
+ className,
79
+ )}
80
+ {...props}
81
+ />
82
+ <InputGroupAddon>
83
+ <SearchIcon className='size-4 shrink-0 opacity-50' />
84
+ </InputGroupAddon>
85
+ </InputGroup>
86
+ </div>
87
+ )
88
+ }
89
+
90
+ function CommandList({
91
+ className,
92
+ ...props
93
+ }: React.ComponentProps<typeof CommandPrimitive.List>) {
94
+ return (
95
+ <CommandPrimitive.List
96
+ data-slot='command-list'
97
+ className={cn(
98
+ 'no-scrollbar max-h-72 scroll-py-1 overflow-x-hidden overflow-y-auto outline-none',
99
+ className,
100
+ )}
101
+ {...props}
102
+ />
103
+ )
104
+ }
105
+
106
+ function CommandEmpty({
107
+ className,
108
+ ...props
109
+ }: React.ComponentProps<typeof CommandPrimitive.Empty>) {
110
+ return (
111
+ <CommandPrimitive.Empty
112
+ data-slot='command-empty'
113
+ className={cn('py-6 text-center text-sm', className)}
114
+ {...props}
115
+ />
116
+ )
117
+ }
118
+
119
+ function CommandGroup({
120
+ className,
121
+ ...props
122
+ }: React.ComponentProps<typeof CommandPrimitive.Group>) {
123
+ return (
124
+ <CommandPrimitive.Group
125
+ data-slot='command-group'
126
+ className={cn(
127
+ 'overflow-hidden p-1 text-foreground **:[[cmdk-group-heading]]:px-2 **:[[cmdk-group-heading]]:py-1.5 **:[[cmdk-group-heading]]:text-xs **:[[cmdk-group-heading]]:font-medium **:[[cmdk-group-heading]]:text-muted-foreground',
128
+ className,
129
+ )}
130
+ {...props}
131
+ />
132
+ )
133
+ }
134
+
135
+ function CommandSeparator({
136
+ className,
137
+ ...props
138
+ }: React.ComponentProps<typeof CommandPrimitive.Separator>) {
139
+ return (
140
+ <CommandPrimitive.Separator
141
+ data-slot='command-separator'
142
+ className={cn('-mx-1 h-px bg-border', className)}
143
+ {...props}
144
+ />
145
+ )
146
+ }
147
+
148
+ function CommandItem({
149
+ className,
150
+ children,
151
+ ...props
152
+ }: React.ComponentProps<typeof CommandPrimitive.Item>) {
153
+ return (
154
+ <CommandPrimitive.Item
155
+ data-slot='command-item'
156
+ className={cn(
157
+ "group/command-item relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none in-data-[slot=dialog-content]:rounded-lg! data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-selected:bg-muted data-selected:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-selected:*:[svg]:text-foreground",
158
+ className,
159
+ )}
160
+ {...props}
161
+ >
162
+ {children}
163
+ <CheckIcon className='ml-auto opacity-0 group-has-data-[slot=command-shortcut]/command-item:hidden group-data-[checked=true]/command-item:opacity-100' />
164
+ </CommandPrimitive.Item>
165
+ )
166
+ }
167
+
168
+ function CommandShortcut({
169
+ className,
170
+ ...props
171
+ }: React.ComponentProps<'span'>) {
172
+ return (
173
+ <span
174
+ data-slot='command-shortcut'
175
+ className={cn(
176
+ 'ml-auto text-xs tracking-widest text-muted-foreground group-data-selected/command-item:text-foreground',
177
+ className,
178
+ )}
179
+ {...props}
180
+ />
181
+ )
182
+ }
183
+
184
+ export {
185
+ Command,
186
+ CommandDialog,
187
+ CommandInput,
188
+ CommandList,
189
+ CommandEmpty,
190
+ CommandGroup,
191
+ CommandItem,
192
+ CommandShortcut,
193
+ CommandSeparator,
194
+ }