@cosmicdrift/kumiko-renderer-web 0.64.0 → 0.66.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 (52) hide show
  1. package/package.json +6 -4
  2. package/src/__tests__/date-input.test.tsx +2 -1
  3. package/src/__tests__/form-action-bar.test.tsx +50 -15
  4. package/src/__tests__/nav-tree.test.tsx +250 -16
  5. package/src/__tests__/primitives.test.tsx +9 -6
  6. package/src/__tests__/render-edit.test.tsx +6 -6
  7. package/src/__tests__/test-utils.tsx +21 -0
  8. package/src/__tests__/toast.test.tsx +4 -3
  9. package/src/__tests__/workspace-shell.test.tsx +21 -66
  10. package/src/app/__tests__/qualify-nav-provider-key.test.ts +27 -0
  11. package/src/app/client-plugin.tsx +12 -27
  12. package/src/app/create-app.tsx +31 -19
  13. package/src/app/nav-providers-context.tsx +56 -0
  14. package/src/index.ts +8 -0
  15. package/src/layout/app-layout.tsx +9 -2
  16. package/src/layout/default-app-shell.tsx +116 -33
  17. package/src/layout/nav-tree.tsx +491 -125
  18. package/src/layout/sidebar-brand.tsx +40 -0
  19. package/src/layout/sidebar-user.tsx +46 -0
  20. package/src/layout/sidebar.tsx +1 -1
  21. package/src/layout/target-resolver-stub.tsx +3 -5
  22. package/src/layout/workspace-shell.tsx +32 -34
  23. package/src/primitives/date-field.tsx +3 -1
  24. package/src/primitives/file-upload.tsx +118 -0
  25. package/src/primitives/index.tsx +314 -175
  26. package/src/primitives/timestamp-input.tsx +3 -1
  27. package/src/primitives/toast.tsx +8 -4
  28. package/src/styles.css +76 -50
  29. package/src/ui/avatar.tsx +110 -0
  30. package/src/ui/badge.tsx +49 -0
  31. package/src/ui/breadcrumb.tsx +110 -0
  32. package/src/ui/button.tsx +65 -0
  33. package/src/ui/card.tsx +93 -0
  34. package/src/ui/checkbox.tsx +33 -0
  35. package/src/ui/collapsible.tsx +34 -0
  36. package/src/ui/dropdown-menu.tsx +258 -0
  37. package/src/ui/input.tsx +22 -0
  38. package/src/ui/label.tsx +25 -0
  39. package/src/ui/select.tsx +191 -0
  40. package/src/ui/separator.tsx +29 -0
  41. package/src/ui/sheet.tsx +144 -0
  42. package/src/ui/sidebar.tsx +727 -0
  43. package/src/ui/skeleton.tsx +14 -0
  44. package/src/ui/table.tsx +117 -0
  45. package/src/ui/textarea.tsx +19 -0
  46. package/src/ui/tooltip.tsx +58 -0
  47. package/src/ui/use-mobile.ts +20 -0
  48. package/src/__tests__/visual-tree-integration.test.tsx +0 -314
  49. package/src/app/tree-providers-context.tsx +0 -68
  50. package/src/layout/__tests__/visual-tree.test.tsx +0 -303
  51. package/src/layout/tree-node-renderer.tsx +0 -386
  52. package/src/layout/visual-tree.tsx +0 -398
@@ -0,0 +1,33 @@
1
+ // @ts-nocheck — vendored shadcn, regenerate via scripts/sync-shadcn.ts
2
+ "use client"
3
+
4
+ import * as React from "react"
5
+ import { CheckIcon } from "lucide-react"
6
+ import { Checkbox as CheckboxPrimitive } from "radix-ui"
7
+
8
+ import { cn } from "../lib/cn"
9
+
10
+ function Checkbox({
11
+ className,
12
+ ...props
13
+ }: React.ComponentProps<typeof CheckboxPrimitive.Root>) {
14
+ return (
15
+ <CheckboxPrimitive.Root
16
+ data-slot="checkbox"
17
+ className={cn(
18
+ "peer size-4 shrink-0 rounded-[4px] border border-input shadow-xs transition-shadow outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:bg-input/30 dark:aria-invalid:ring-destructive/40 dark:data-[state=checked]:bg-primary",
19
+ className
20
+ )}
21
+ {...props}
22
+ >
23
+ <CheckboxPrimitive.Indicator
24
+ data-slot="checkbox-indicator"
25
+ className="grid place-content-center text-current transition-none"
26
+ >
27
+ <CheckIcon className="size-3.5" />
28
+ </CheckboxPrimitive.Indicator>
29
+ </CheckboxPrimitive.Root>
30
+ )
31
+ }
32
+
33
+ export { Checkbox }
@@ -0,0 +1,34 @@
1
+ // @ts-nocheck — vendored shadcn, regenerate via scripts/sync-shadcn.ts
2
+ "use client"
3
+
4
+ import { Collapsible as CollapsiblePrimitive } from "radix-ui"
5
+
6
+ function Collapsible({
7
+ ...props
8
+ }: React.ComponentProps<typeof CollapsiblePrimitive.Root>) {
9
+ return <CollapsiblePrimitive.Root data-slot="collapsible" {...props} />
10
+ }
11
+
12
+ function CollapsibleTrigger({
13
+ ...props
14
+ }: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleTrigger>) {
15
+ return (
16
+ <CollapsiblePrimitive.CollapsibleTrigger
17
+ data-slot="collapsible-trigger"
18
+ {...props}
19
+ />
20
+ )
21
+ }
22
+
23
+ function CollapsibleContent({
24
+ ...props
25
+ }: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleContent>) {
26
+ return (
27
+ <CollapsiblePrimitive.CollapsibleContent
28
+ data-slot="collapsible-content"
29
+ {...props}
30
+ />
31
+ )
32
+ }
33
+
34
+ export { Collapsible, CollapsibleTrigger, CollapsibleContent }
@@ -0,0 +1,258 @@
1
+ // @ts-nocheck — vendored shadcn, regenerate via scripts/sync-shadcn.ts
2
+ "use client"
3
+
4
+ import * as React from "react"
5
+ import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
6
+ import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui"
7
+
8
+ import { cn } from "../lib/cn"
9
+
10
+ function DropdownMenu({
11
+ ...props
12
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {
13
+ return <DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} />
14
+ }
15
+
16
+ function DropdownMenuPortal({
17
+ ...props
18
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {
19
+ return (
20
+ <DropdownMenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />
21
+ )
22
+ }
23
+
24
+ function DropdownMenuTrigger({
25
+ ...props
26
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {
27
+ return (
28
+ <DropdownMenuPrimitive.Trigger
29
+ data-slot="dropdown-menu-trigger"
30
+ {...props}
31
+ />
32
+ )
33
+ }
34
+
35
+ function DropdownMenuContent({
36
+ className,
37
+ sideOffset = 4,
38
+ ...props
39
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {
40
+ return (
41
+ <DropdownMenuPrimitive.Portal>
42
+ <DropdownMenuPrimitive.Content
43
+ data-slot="dropdown-menu-content"
44
+ sideOffset={sideOffset}
45
+ className={cn(
46
+ "z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto 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]: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",
47
+ className
48
+ )}
49
+ {...props}
50
+ />
51
+ </DropdownMenuPrimitive.Portal>
52
+ )
53
+ }
54
+
55
+ function DropdownMenuGroup({
56
+ ...props
57
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {
58
+ return (
59
+ <DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
60
+ )
61
+ }
62
+
63
+ function DropdownMenuItem({
64
+ className,
65
+ inset,
66
+ variant = "default",
67
+ ...props
68
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
69
+ inset?: boolean
70
+ variant?: "default" | "destructive"
71
+ }) {
72
+ return (
73
+ <DropdownMenuPrimitive.Item
74
+ data-slot="dropdown-menu-item"
75
+ data-inset={inset}
76
+ data-variant={variant}
77
+ className={cn(
78
+ "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!",
79
+ className
80
+ )}
81
+ {...props}
82
+ />
83
+ )
84
+ }
85
+
86
+ function DropdownMenuCheckboxItem({
87
+ className,
88
+ children,
89
+ checked,
90
+ ...props
91
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {
92
+ return (
93
+ <DropdownMenuPrimitive.CheckboxItem
94
+ data-slot="dropdown-menu-checkbox-item"
95
+ className={cn(
96
+ "relative flex cursor-default items-center gap-2 rounded-sm 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",
97
+ className
98
+ )}
99
+ checked={checked}
100
+ {...props}
101
+ >
102
+ <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
103
+ <DropdownMenuPrimitive.ItemIndicator>
104
+ <CheckIcon className="size-4" />
105
+ </DropdownMenuPrimitive.ItemIndicator>
106
+ </span>
107
+ {children}
108
+ </DropdownMenuPrimitive.CheckboxItem>
109
+ )
110
+ }
111
+
112
+ function DropdownMenuRadioGroup({
113
+ ...props
114
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) {
115
+ return (
116
+ <DropdownMenuPrimitive.RadioGroup
117
+ data-slot="dropdown-menu-radio-group"
118
+ {...props}
119
+ />
120
+ )
121
+ }
122
+
123
+ function DropdownMenuRadioItem({
124
+ className,
125
+ children,
126
+ ...props
127
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {
128
+ return (
129
+ <DropdownMenuPrimitive.RadioItem
130
+ data-slot="dropdown-menu-radio-item"
131
+ className={cn(
132
+ "relative flex cursor-default items-center gap-2 rounded-sm 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",
133
+ className
134
+ )}
135
+ {...props}
136
+ >
137
+ <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
138
+ <DropdownMenuPrimitive.ItemIndicator>
139
+ <CircleIcon className="size-2 fill-current" />
140
+ </DropdownMenuPrimitive.ItemIndicator>
141
+ </span>
142
+ {children}
143
+ </DropdownMenuPrimitive.RadioItem>
144
+ )
145
+ }
146
+
147
+ function DropdownMenuLabel({
148
+ className,
149
+ inset,
150
+ ...props
151
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {
152
+ inset?: boolean
153
+ }) {
154
+ return (
155
+ <DropdownMenuPrimitive.Label
156
+ data-slot="dropdown-menu-label"
157
+ data-inset={inset}
158
+ className={cn(
159
+ "px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
160
+ className
161
+ )}
162
+ {...props}
163
+ />
164
+ )
165
+ }
166
+
167
+ function DropdownMenuSeparator({
168
+ className,
169
+ ...props
170
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {
171
+ return (
172
+ <DropdownMenuPrimitive.Separator
173
+ data-slot="dropdown-menu-separator"
174
+ className={cn("-mx-1 my-1 h-px bg-border", className)}
175
+ {...props}
176
+ />
177
+ )
178
+ }
179
+
180
+ function DropdownMenuShortcut({
181
+ className,
182
+ ...props
183
+ }: React.ComponentProps<"span">) {
184
+ return (
185
+ <span
186
+ data-slot="dropdown-menu-shortcut"
187
+ className={cn(
188
+ "ml-auto text-xs tracking-widest text-muted-foreground",
189
+ className
190
+ )}
191
+ {...props}
192
+ />
193
+ )
194
+ }
195
+
196
+ function DropdownMenuSub({
197
+ ...props
198
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {
199
+ return <DropdownMenuPrimitive.Sub data-slot="dropdown-menu-sub" {...props} />
200
+ }
201
+
202
+ function DropdownMenuSubTrigger({
203
+ className,
204
+ inset,
205
+ children,
206
+ ...props
207
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {
208
+ inset?: boolean
209
+ }) {
210
+ return (
211
+ <DropdownMenuPrimitive.SubTrigger
212
+ data-slot="dropdown-menu-sub-trigger"
213
+ data-inset={inset}
214
+ className={cn(
215
+ "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-[inset]:pl-8 data-[state=open]:bg-accent data-[state=open]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground",
216
+ className
217
+ )}
218
+ {...props}
219
+ >
220
+ {children}
221
+ <ChevronRightIcon className="ml-auto size-4" />
222
+ </DropdownMenuPrimitive.SubTrigger>
223
+ )
224
+ }
225
+
226
+ function DropdownMenuSubContent({
227
+ className,
228
+ ...props
229
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {
230
+ return (
231
+ <DropdownMenuPrimitive.SubContent
232
+ data-slot="dropdown-menu-sub-content"
233
+ className={cn(
234
+ "z-50 min-w-[8rem] origin-(--radix-dropdown-menu-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",
235
+ className
236
+ )}
237
+ {...props}
238
+ />
239
+ )
240
+ }
241
+
242
+ export {
243
+ DropdownMenu,
244
+ DropdownMenuPortal,
245
+ DropdownMenuTrigger,
246
+ DropdownMenuContent,
247
+ DropdownMenuGroup,
248
+ DropdownMenuLabel,
249
+ DropdownMenuItem,
250
+ DropdownMenuCheckboxItem,
251
+ DropdownMenuRadioGroup,
252
+ DropdownMenuRadioItem,
253
+ DropdownMenuSeparator,
254
+ DropdownMenuShortcut,
255
+ DropdownMenuSub,
256
+ DropdownMenuSubTrigger,
257
+ DropdownMenuSubContent,
258
+ }
@@ -0,0 +1,22 @@
1
+ // @ts-nocheck — vendored shadcn, regenerate via scripts/sync-shadcn.ts
2
+ import * as React from "react"
3
+
4
+ import { cn } from "../lib/cn"
5
+
6
+ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
7
+ return (
8
+ <input
9
+ type={type}
10
+ data-slot="input"
11
+ className={cn(
12
+ "h-9 w-full min-w-0 rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground 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 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:bg-input/30",
13
+ "focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50",
14
+ "aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40",
15
+ className
16
+ )}
17
+ {...props}
18
+ />
19
+ )
20
+ }
21
+
22
+ export { Input }
@@ -0,0 +1,25 @@
1
+ // @ts-nocheck — vendored shadcn, regenerate via scripts/sync-shadcn.ts
2
+ "use client"
3
+
4
+ import * as React from "react"
5
+ import { Label as LabelPrimitive } from "radix-ui"
6
+
7
+ import { cn } from "../lib/cn"
8
+
9
+ function Label({
10
+ className,
11
+ ...props
12
+ }: React.ComponentProps<typeof LabelPrimitive.Root>) {
13
+ return (
14
+ <LabelPrimitive.Root
15
+ data-slot="label"
16
+ className={cn(
17
+ "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",
18
+ className
19
+ )}
20
+ {...props}
21
+ />
22
+ )
23
+ }
24
+
25
+ export { Label }
@@ -0,0 +1,191 @@
1
+ // @ts-nocheck — vendored shadcn, regenerate via scripts/sync-shadcn.ts
2
+ "use client"
3
+
4
+ import * as React from "react"
5
+ import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react"
6
+ import { Select as SelectPrimitive } from "radix-ui"
7
+
8
+ import { cn } from "../lib/cn"
9
+
10
+ function Select({
11
+ ...props
12
+ }: React.ComponentProps<typeof SelectPrimitive.Root>) {
13
+ return <SelectPrimitive.Root data-slot="select" {...props} />
14
+ }
15
+
16
+ function SelectGroup({
17
+ ...props
18
+ }: React.ComponentProps<typeof SelectPrimitive.Group>) {
19
+ return <SelectPrimitive.Group data-slot="select-group" {...props} />
20
+ }
21
+
22
+ function SelectValue({
23
+ ...props
24
+ }: React.ComponentProps<typeof SelectPrimitive.Value>) {
25
+ return <SelectPrimitive.Value data-slot="select-value" {...props} />
26
+ }
27
+
28
+ function SelectTrigger({
29
+ className,
30
+ size = "default",
31
+ children,
32
+ ...props
33
+ }: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
34
+ size?: "sm" | "default"
35
+ }) {
36
+ return (
37
+ <SelectPrimitive.Trigger
38
+ data-slot="select-trigger"
39
+ data-size={size}
40
+ className={cn(
41
+ "flex w-fit items-center justify-between gap-2 rounded-md border border-input bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[placeholder]:text-muted-foreground data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground",
42
+ className
43
+ )}
44
+ {...props}
45
+ >
46
+ {children}
47
+ <SelectPrimitive.Icon asChild>
48
+ <ChevronDownIcon className="size-4 opacity-50" />
49
+ </SelectPrimitive.Icon>
50
+ </SelectPrimitive.Trigger>
51
+ )
52
+ }
53
+
54
+ function SelectContent({
55
+ className,
56
+ children,
57
+ position = "item-aligned",
58
+ align = "center",
59
+ ...props
60
+ }: React.ComponentProps<typeof SelectPrimitive.Content>) {
61
+ return (
62
+ <SelectPrimitive.Portal>
63
+ <SelectPrimitive.Content
64
+ data-slot="select-content"
65
+ className={cn(
66
+ "relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border bg-popover 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]: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",
67
+ position === "popper" &&
68
+ "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
69
+ className
70
+ )}
71
+ position={position}
72
+ align={align}
73
+ {...props}
74
+ >
75
+ <SelectScrollUpButton />
76
+ <SelectPrimitive.Viewport
77
+ className={cn(
78
+ "p-1",
79
+ position === "popper" &&
80
+ "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"
81
+ )}
82
+ >
83
+ {children}
84
+ </SelectPrimitive.Viewport>
85
+ <SelectScrollDownButton />
86
+ </SelectPrimitive.Content>
87
+ </SelectPrimitive.Portal>
88
+ )
89
+ }
90
+
91
+ function SelectLabel({
92
+ className,
93
+ ...props
94
+ }: React.ComponentProps<typeof SelectPrimitive.Label>) {
95
+ return (
96
+ <SelectPrimitive.Label
97
+ data-slot="select-label"
98
+ className={cn("px-2 py-1.5 text-xs text-muted-foreground", className)}
99
+ {...props}
100
+ />
101
+ )
102
+ }
103
+
104
+ function SelectItem({
105
+ className,
106
+ children,
107
+ ...props
108
+ }: React.ComponentProps<typeof SelectPrimitive.Item>) {
109
+ return (
110
+ <SelectPrimitive.Item
111
+ data-slot="select-item"
112
+ className={cn(
113
+ "relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 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 [&_svg:not([class*='text-'])]:text-muted-foreground *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
114
+ className
115
+ )}
116
+ {...props}
117
+ >
118
+ <span
119
+ data-slot="select-item-indicator"
120
+ className="absolute right-2 flex size-3.5 items-center justify-center"
121
+ >
122
+ <SelectPrimitive.ItemIndicator>
123
+ <CheckIcon className="size-4" />
124
+ </SelectPrimitive.ItemIndicator>
125
+ </span>
126
+ <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
127
+ </SelectPrimitive.Item>
128
+ )
129
+ }
130
+
131
+ function SelectSeparator({
132
+ className,
133
+ ...props
134
+ }: React.ComponentProps<typeof SelectPrimitive.Separator>) {
135
+ return (
136
+ <SelectPrimitive.Separator
137
+ data-slot="select-separator"
138
+ className={cn("pointer-events-none -mx-1 my-1 h-px bg-border", className)}
139
+ {...props}
140
+ />
141
+ )
142
+ }
143
+
144
+ function SelectScrollUpButton({
145
+ className,
146
+ ...props
147
+ }: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {
148
+ return (
149
+ <SelectPrimitive.ScrollUpButton
150
+ data-slot="select-scroll-up-button"
151
+ className={cn(
152
+ "flex cursor-default items-center justify-center py-1",
153
+ className
154
+ )}
155
+ {...props}
156
+ >
157
+ <ChevronUpIcon className="size-4" />
158
+ </SelectPrimitive.ScrollUpButton>
159
+ )
160
+ }
161
+
162
+ function SelectScrollDownButton({
163
+ className,
164
+ ...props
165
+ }: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {
166
+ return (
167
+ <SelectPrimitive.ScrollDownButton
168
+ data-slot="select-scroll-down-button"
169
+ className={cn(
170
+ "flex cursor-default items-center justify-center py-1",
171
+ className
172
+ )}
173
+ {...props}
174
+ >
175
+ <ChevronDownIcon className="size-4" />
176
+ </SelectPrimitive.ScrollDownButton>
177
+ )
178
+ }
179
+
180
+ export {
181
+ Select,
182
+ SelectContent,
183
+ SelectGroup,
184
+ SelectItem,
185
+ SelectLabel,
186
+ SelectScrollDownButton,
187
+ SelectScrollUpButton,
188
+ SelectSeparator,
189
+ SelectTrigger,
190
+ SelectValue,
191
+ }
@@ -0,0 +1,29 @@
1
+ // @ts-nocheck — vendored shadcn, regenerate via scripts/sync-shadcn.ts
2
+ "use client"
3
+
4
+ import * as React from "react"
5
+ import { Separator as SeparatorPrimitive } from "radix-ui"
6
+
7
+ import { cn } from "../lib/cn"
8
+
9
+ function Separator({
10
+ className,
11
+ orientation = "horizontal",
12
+ decorative = true,
13
+ ...props
14
+ }: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
15
+ return (
16
+ <SeparatorPrimitive.Root
17
+ data-slot="separator"
18
+ decorative={decorative}
19
+ orientation={orientation}
20
+ className={cn(
21
+ "shrink-0 bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
22
+ className
23
+ )}
24
+ {...props}
25
+ />
26
+ )
27
+ }
28
+
29
+ export { Separator }