@theruntime/components 0.0.0 → 0.0.1

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 (91) hide show
  1. package/LICENSE +21 -0
  2. package/package.json +113 -4
  3. package/src/accordion.tsx +62 -0
  4. package/src/alert-dialog.tsx +177 -0
  5. package/src/alert.tsx +60 -0
  6. package/src/aspect-ratio.tsx +7 -0
  7. package/src/attachment.tsx +192 -0
  8. package/src/avatar.tsx +94 -0
  9. package/src/badge.tsx +46 -0
  10. package/src/breadcrumb.tsx +102 -0
  11. package/src/bubble.tsx +125 -0
  12. package/src/button-group.tsx +82 -0
  13. package/src/button.tsx +62 -0
  14. package/src/calendar.tsx +178 -0
  15. package/src/card.tsx +75 -0
  16. package/src/carousel.tsx +228 -0
  17. package/src/chart/container.tsx +72 -0
  18. package/src/chart/context.tsx +39 -0
  19. package/src/chart/index.ts +4 -0
  20. package/src/chart/legend.tsx +63 -0
  21. package/src/chart/payload.ts +31 -0
  22. package/src/chart/tooltip.tsx +149 -0
  23. package/src/checkbox.tsx +27 -0
  24. package/src/cn.ts +36 -0
  25. package/src/collapsible.tsx +19 -0
  26. package/src/combobox/chips.tsx +71 -0
  27. package/src/combobox/content.tsx +123 -0
  28. package/src/combobox/index.ts +13 -0
  29. package/src/combobox/input.tsx +39 -0
  30. package/src/combobox/trigger.tsx +44 -0
  31. package/src/command.tsx +153 -0
  32. package/src/context-menu.tsx +222 -0
  33. package/src/dialog.tsx +142 -0
  34. package/src/direction.tsx +18 -0
  35. package/src/drawer.tsx +122 -0
  36. package/src/dropdown-menu.tsx +226 -0
  37. package/src/empty.tsx +94 -0
  38. package/src/field.tsx +232 -0
  39. package/src/form.tsx +153 -0
  40. package/src/hover-card.tsx +36 -0
  41. package/src/index.ts +90 -0
  42. package/src/input-group.tsx +156 -0
  43. package/src/input-otp.tsx +68 -0
  44. package/src/input.tsx +21 -0
  45. package/src/item.tsx +172 -0
  46. package/src/kbd.tsx +28 -0
  47. package/src/label.tsx +19 -0
  48. package/src/marker.tsx +66 -0
  49. package/src/menubar.tsx +250 -0
  50. package/src/message-scroller.tsx +128 -0
  51. package/src/message.tsx +85 -0
  52. package/src/native-select.tsx +56 -0
  53. package/src/navigation-menu.tsx +161 -0
  54. package/src/pagination.tsx +106 -0
  55. package/src/popover.tsx +72 -0
  56. package/src/progress.tsx +26 -0
  57. package/src/questionnaire/actions.tsx +118 -0
  58. package/src/questionnaire/choices.tsx +113 -0
  59. package/src/questionnaire/index.ts +21 -0
  60. package/src/questionnaire/root.tsx +75 -0
  61. package/src/radio-group.tsx +43 -0
  62. package/src/resizable.tsx +45 -0
  63. package/src/scroll-area.tsx +54 -0
  64. package/src/select.tsx +173 -0
  65. package/src/separator.tsx +26 -0
  66. package/src/sheet.tsx +132 -0
  67. package/src/shell/app-tab.tsx +67 -0
  68. package/src/shell/entry-row.tsx +137 -0
  69. package/src/shell/field.tsx +83 -0
  70. package/src/shell/group-head.tsx +19 -0
  71. package/src/shell/scope-chip.tsx +32 -0
  72. package/src/shell/suggest-panel.tsx +92 -0
  73. package/src/sidebar/context.tsx +128 -0
  74. package/src/sidebar/index.ts +23 -0
  75. package/src/sidebar/menu.tsx +239 -0
  76. package/src/sidebar/sections.tsx +118 -0
  77. package/src/sidebar/sidebar.tsx +183 -0
  78. package/src/skeleton.tsx +13 -0
  79. package/src/slider.tsx +56 -0
  80. package/src/sonner.tsx +41 -0
  81. package/src/spinner.tsx +16 -0
  82. package/src/styles.css +149 -0
  83. package/src/switch.tsx +33 -0
  84. package/src/table.tsx +90 -0
  85. package/src/tabs.tsx +79 -0
  86. package/src/textarea.tsx +18 -0
  87. package/src/toggle-group.tsx +81 -0
  88. package/src/toggle.tsx +44 -0
  89. package/src/tooltip.tsx +51 -0
  90. package/src/use-mobile.ts +21 -0
  91. package/README.md +0 -3
@@ -0,0 +1,250 @@
1
+ import * as React from "react";
2
+ import { CheckIcon, CaretRightIcon, CircleIcon } from "@phosphor-icons/react";
3
+ import { Menubar as MenubarPrimitive } from "radix-ui";
4
+
5
+ import { cn } from "./cn";
6
+
7
+ function Menubar({ className, ...props }: React.ComponentProps<typeof MenubarPrimitive.Root>) {
8
+ return (
9
+ <MenubarPrimitive.Root
10
+ data-slot="menubar"
11
+ className={cn(
12
+ "flex h-9 items-center gap-1 rounded-md border bg-background p-1 shadow-xs",
13
+ className,
14
+ )}
15
+ {...props}
16
+ />
17
+ );
18
+ }
19
+
20
+ function MenubarMenu({ ...props }: React.ComponentProps<typeof MenubarPrimitive.Menu>) {
21
+ return <MenubarPrimitive.Menu data-slot="menubar-menu" {...props} />;
22
+ }
23
+
24
+ function MenubarGroup({ ...props }: React.ComponentProps<typeof MenubarPrimitive.Group>) {
25
+ return <MenubarPrimitive.Group data-slot="menubar-group" {...props} />;
26
+ }
27
+
28
+ function MenubarPortal({ ...props }: React.ComponentProps<typeof MenubarPrimitive.Portal>) {
29
+ return <MenubarPrimitive.Portal data-slot="menubar-portal" {...props} />;
30
+ }
31
+
32
+ function MenubarRadioGroup({ ...props }: React.ComponentProps<typeof MenubarPrimitive.RadioGroup>) {
33
+ return <MenubarPrimitive.RadioGroup data-slot="menubar-radio-group" {...props} />;
34
+ }
35
+
36
+ function MenubarTrigger({
37
+ className,
38
+ ...props
39
+ }: React.ComponentProps<typeof MenubarPrimitive.Trigger>) {
40
+ return (
41
+ <MenubarPrimitive.Trigger
42
+ data-slot="menubar-trigger"
43
+ className={cn(
44
+ "flex items-center rounded-sm px-2 py-1 text-sm font-medium outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
45
+ className,
46
+ )}
47
+ {...props}
48
+ />
49
+ );
50
+ }
51
+
52
+ function MenubarContent({
53
+ className,
54
+ align = "start",
55
+ alignOffset = -4,
56
+ sideOffset = 8,
57
+ ...props
58
+ }: React.ComponentProps<typeof MenubarPrimitive.Content>) {
59
+ return (
60
+ <MenubarPortal>
61
+ <MenubarPrimitive.Content
62
+ data-slot="menubar-content"
63
+ align={align}
64
+ alignOffset={alignOffset}
65
+ sideOffset={sideOffset}
66
+ className={cn(
67
+ "z-50 min-w-[12rem] origin-(--radix-menubar-content-transform-origin) overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
68
+ className,
69
+ )}
70
+ {...props}
71
+ />
72
+ </MenubarPortal>
73
+ );
74
+ }
75
+
76
+ function MenubarItem({
77
+ className,
78
+ inset,
79
+ variant = "default",
80
+ ...props
81
+ }: React.ComponentProps<typeof MenubarPrimitive.Item> & {
82
+ inset?: boolean;
83
+ variant?: "default" | "destructive";
84
+ }) {
85
+ return (
86
+ <MenubarPrimitive.Item
87
+ data-slot="menubar-item"
88
+ data-inset={inset}
89
+ data-variant={variant}
90
+ className={cn(
91
+ "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!",
92
+ className,
93
+ )}
94
+ {...props}
95
+ />
96
+ );
97
+ }
98
+
99
+ function MenubarCheckboxItem({
100
+ className,
101
+ children,
102
+ checked,
103
+ ...props
104
+ }: React.ComponentProps<typeof MenubarPrimitive.CheckboxItem>) {
105
+ return (
106
+ <MenubarPrimitive.CheckboxItem
107
+ data-slot="menubar-checkbox-item"
108
+ className={cn(
109
+ "relative flex cursor-default items-center gap-2 rounded-xs py-1.5 pr-2 pl-8 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
110
+ className,
111
+ )}
112
+ checked={checked}
113
+ {...props}
114
+ >
115
+ <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
116
+ <MenubarPrimitive.ItemIndicator>
117
+ <CheckIcon className="size-4" />
118
+ </MenubarPrimitive.ItemIndicator>
119
+ </span>
120
+ {children}
121
+ </MenubarPrimitive.CheckboxItem>
122
+ );
123
+ }
124
+
125
+ function MenubarRadioItem({
126
+ className,
127
+ children,
128
+ ...props
129
+ }: React.ComponentProps<typeof MenubarPrimitive.RadioItem>) {
130
+ return (
131
+ <MenubarPrimitive.RadioItem
132
+ data-slot="menubar-radio-item"
133
+ className={cn(
134
+ "relative flex cursor-default items-center gap-2 rounded-xs py-1.5 pr-2 pl-8 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
135
+ className,
136
+ )}
137
+ {...props}
138
+ >
139
+ <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
140
+ <MenubarPrimitive.ItemIndicator>
141
+ <CircleIcon className="size-2 fill-current" />
142
+ </MenubarPrimitive.ItemIndicator>
143
+ </span>
144
+ {children}
145
+ </MenubarPrimitive.RadioItem>
146
+ );
147
+ }
148
+
149
+ function MenubarLabel({
150
+ className,
151
+ inset,
152
+ ...props
153
+ }: React.ComponentProps<typeof MenubarPrimitive.Label> & {
154
+ inset?: boolean;
155
+ }) {
156
+ return (
157
+ <MenubarPrimitive.Label
158
+ data-slot="menubar-label"
159
+ data-inset={inset}
160
+ className={cn("px-2 py-1.5 text-sm font-medium data-[inset]:pl-8", className)}
161
+ {...props}
162
+ />
163
+ );
164
+ }
165
+
166
+ function MenubarSeparator({
167
+ className,
168
+ ...props
169
+ }: React.ComponentProps<typeof MenubarPrimitive.Separator>) {
170
+ return (
171
+ <MenubarPrimitive.Separator
172
+ data-slot="menubar-separator"
173
+ className={cn("-mx-1 my-1 h-px bg-border", className)}
174
+ {...props}
175
+ />
176
+ );
177
+ }
178
+
179
+ function MenubarShortcut({ className, ...props }: React.ComponentProps<"span">) {
180
+ return (
181
+ <span
182
+ data-slot="menubar-shortcut"
183
+ className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)}
184
+ {...props}
185
+ />
186
+ );
187
+ }
188
+
189
+ function MenubarSub({ ...props }: React.ComponentProps<typeof MenubarPrimitive.Sub>) {
190
+ return <MenubarPrimitive.Sub data-slot="menubar-sub" {...props} />;
191
+ }
192
+
193
+ function MenubarSubTrigger({
194
+ className,
195
+ inset,
196
+ children,
197
+ ...props
198
+ }: React.ComponentProps<typeof MenubarPrimitive.SubTrigger> & {
199
+ inset?: boolean;
200
+ }) {
201
+ return (
202
+ <MenubarPrimitive.SubTrigger
203
+ data-slot="menubar-sub-trigger"
204
+ data-inset={inset}
205
+ className={cn(
206
+ "flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-none select-none focus:bg-accent focus:text-accent-foreground data-[inset]:pl-8 data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
207
+ className,
208
+ )}
209
+ {...props}
210
+ >
211
+ {children}
212
+ <CaretRightIcon className="ml-auto h-4 w-4" />
213
+ </MenubarPrimitive.SubTrigger>
214
+ );
215
+ }
216
+
217
+ function MenubarSubContent({
218
+ className,
219
+ ...props
220
+ }: React.ComponentProps<typeof MenubarPrimitive.SubContent>) {
221
+ return (
222
+ <MenubarPrimitive.SubContent
223
+ data-slot="menubar-sub-content"
224
+ className={cn(
225
+ "z-50 min-w-[8rem] origin-(--radix-menubar-content-transform-origin) overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
226
+ className,
227
+ )}
228
+ {...props}
229
+ />
230
+ );
231
+ }
232
+
233
+ export {
234
+ Menubar,
235
+ MenubarPortal,
236
+ MenubarMenu,
237
+ MenubarTrigger,
238
+ MenubarContent,
239
+ MenubarGroup,
240
+ MenubarSeparator,
241
+ MenubarLabel,
242
+ MenubarItem,
243
+ MenubarShortcut,
244
+ MenubarCheckboxItem,
245
+ MenubarRadioGroup,
246
+ MenubarRadioItem,
247
+ MenubarSub,
248
+ MenubarSubTrigger,
249
+ MenubarSubContent,
250
+ };
@@ -0,0 +1,128 @@
1
+ import * as React from "react";
2
+ import {
3
+ MessageScroller as MessageScrollerPrimitive,
4
+ useMessageScroller,
5
+ useMessageScrollerScrollable,
6
+ useMessageScrollerVisibility,
7
+ } from "@shadcn/react/message-scroller";
8
+ import { ArrowDownIcon } from "@phosphor-icons/react";
9
+
10
+ import { cn } from "./cn";
11
+ import { Button } from "./button";
12
+
13
+ function MessageScrollerProvider(
14
+ props: React.ComponentProps<typeof MessageScrollerPrimitive.Provider>,
15
+ ) {
16
+ return <MessageScrollerPrimitive.Provider {...props} />;
17
+ }
18
+
19
+ function MessageScroller({
20
+ className,
21
+ ...props
22
+ }: React.ComponentProps<typeof MessageScrollerPrimitive.Root>) {
23
+ return (
24
+ <MessageScrollerPrimitive.Root
25
+ data-slot="message-scroller"
26
+ className={cn(
27
+ "group/message-scroller relative flex size-full min-h-0 flex-col overflow-hidden",
28
+ className,
29
+ )}
30
+ {...props}
31
+ />
32
+ );
33
+ }
34
+
35
+ function MessageScrollerViewport({
36
+ className,
37
+ ...props
38
+ }: React.ComponentProps<typeof MessageScrollerPrimitive.Viewport>) {
39
+ return (
40
+ <MessageScrollerPrimitive.Viewport
41
+ data-slot="message-scroller-viewport"
42
+ className={cn(
43
+ "size-full min-h-0 min-w-0 scroll-fade-b scrollbar-thin scrollbar-gutter-stable overflow-y-auto overscroll-contain contain-content data-autoscrolling:scrollbar-none",
44
+ className,
45
+ )}
46
+ {...props}
47
+ />
48
+ );
49
+ }
50
+
51
+ function MessageScrollerContent({
52
+ className,
53
+ ...props
54
+ }: React.ComponentProps<typeof MessageScrollerPrimitive.Content>) {
55
+ return (
56
+ <MessageScrollerPrimitive.Content
57
+ data-slot="message-scroller-content"
58
+ className={cn("flex h-max min-h-full flex-col gap-8", className)}
59
+ {...props}
60
+ />
61
+ );
62
+ }
63
+
64
+ function MessageScrollerItem({
65
+ className,
66
+ scrollAnchor = false,
67
+ ...props
68
+ }: React.ComponentProps<typeof MessageScrollerPrimitive.Item>) {
69
+ return (
70
+ <MessageScrollerPrimitive.Item
71
+ data-slot="message-scroller-item"
72
+ scrollAnchor={scrollAnchor}
73
+ className={cn(
74
+ "min-w-0 shrink-0 [contain-intrinsic-size:auto_10rem] [content-visibility:auto]",
75
+ className,
76
+ )}
77
+ {...props}
78
+ />
79
+ );
80
+ }
81
+
82
+ function MessageScrollerButton({
83
+ direction = "end",
84
+ className,
85
+ children,
86
+ render,
87
+ variant = "secondary",
88
+ size = "icon-sm",
89
+ ...props
90
+ }: React.ComponentProps<typeof MessageScrollerPrimitive.Button> &
91
+ Pick<React.ComponentProps<typeof Button>, "variant" | "size">) {
92
+ return (
93
+ <MessageScrollerPrimitive.Button
94
+ data-slot="message-scroller-button"
95
+ data-direction={direction}
96
+ data-variant={variant}
97
+ data-size={size}
98
+ direction={direction}
99
+ className={cn(
100
+ "absolute inset-s-1/2 -translate-x-1/2 border-border bg-background text-foreground transition-[translate,scale,opacity] duration-200 hover:bg-muted hover:text-foreground data-[active=false]:pointer-events-none data-[active=false]:scale-95 data-[active=false]:opacity-0 data-[active=false]:duration-400 data-[active=false]:ease-[cubic-bezier(0.7,0,0.84,0)] data-[active=true]:translate-y-0 data-[active=true]:scale-100 data-[active=true]:opacity-100 data-[active=true]:ease-[cubic-bezier(0.23,1,0.32,1)] data-[direction=end]:bottom-4 data-[direction=end]:data-[active=false]:translate-y-full data-[direction=start]:top-4 data-[direction=start]:data-[active=false]:-translate-y-full rtl:translate-x-1/2 data-[direction=start]:[&_svg]:rotate-180",
101
+ className,
102
+ )}
103
+ render={render ?? <Button variant={variant} size={size} />}
104
+ {...props}
105
+ >
106
+ {children ?? (
107
+ <>
108
+ <ArrowDownIcon />
109
+ <span className="sr-only">
110
+ {direction === "end" ? "Scroll to end" : "Scroll to start"}
111
+ </span>
112
+ </>
113
+ )}
114
+ </MessageScrollerPrimitive.Button>
115
+ );
116
+ }
117
+
118
+ export {
119
+ MessageScrollerProvider,
120
+ MessageScroller,
121
+ MessageScrollerViewport,
122
+ MessageScrollerContent,
123
+ MessageScrollerItem,
124
+ MessageScrollerButton,
125
+ useMessageScroller,
126
+ useMessageScrollerScrollable,
127
+ useMessageScrollerVisibility,
128
+ };
@@ -0,0 +1,85 @@
1
+ import * as React from "react";
2
+
3
+ import { cn } from "./cn";
4
+
5
+ function MessageGroup({ className, ...props }: React.ComponentProps<"div">) {
6
+ return (
7
+ <div
8
+ data-slot="message-group"
9
+ className={cn("flex min-w-0 flex-col gap-2", className)}
10
+ {...props}
11
+ />
12
+ );
13
+ }
14
+
15
+ function Message({
16
+ className,
17
+ align = "start",
18
+ ...props
19
+ }: React.ComponentProps<"div"> & { align?: "start" | "end" }) {
20
+ return (
21
+ <div
22
+ data-slot="message"
23
+ data-align={align}
24
+ className={cn(
25
+ "group/message relative flex w-full min-w-0 gap-2 text-sm data-[align=end]:flex-row-reverse",
26
+ className,
27
+ )}
28
+ {...props}
29
+ />
30
+ );
31
+ }
32
+
33
+ function MessageAvatar({ className, ...props }: React.ComponentProps<"div">) {
34
+ return (
35
+ <div
36
+ data-slot="message-avatar"
37
+ className={cn(
38
+ "flex w-fit min-w-8 shrink-0 items-center justify-center self-end overflow-hidden rounded-full bg-muted group-has-data-[slot=message-footer]/message:-translate-y-8",
39
+ className,
40
+ )}
41
+ {...props}
42
+ />
43
+ );
44
+ }
45
+
46
+ function MessageContent({ className, ...props }: React.ComponentProps<"div">) {
47
+ return (
48
+ <div
49
+ data-slot="message-content"
50
+ className={cn(
51
+ "flex w-full min-w-0 flex-col gap-2.5 wrap-break-word group-data-[align=end]/message:*:data-slot:self-end",
52
+ className,
53
+ )}
54
+ {...props}
55
+ />
56
+ );
57
+ }
58
+
59
+ function MessageHeader({ className, ...props }: React.ComponentProps<"div">) {
60
+ return (
61
+ <div
62
+ data-slot="message-header"
63
+ className={cn(
64
+ "flex max-w-full min-w-0 items-center px-3 text-xs font-medium text-muted-foreground group-has-data-[variant=ghost]/message:px-0",
65
+ className,
66
+ )}
67
+ {...props}
68
+ />
69
+ );
70
+ }
71
+
72
+ function MessageFooter({ className, ...props }: React.ComponentProps<"div">) {
73
+ return (
74
+ <div
75
+ data-slot="message-footer"
76
+ className={cn(
77
+ "flex max-w-full min-w-0 items-center px-3 text-xs font-medium text-muted-foreground group-has-data-[variant=ghost]/message:px-0 group-data-[align=end]/message:justify-end",
78
+ className,
79
+ )}
80
+ {...props}
81
+ />
82
+ );
83
+ }
84
+
85
+ export { MessageGroup, Message, MessageAvatar, MessageContent, MessageFooter, MessageHeader };
@@ -0,0 +1,56 @@
1
+ import * as React from "react";
2
+ import { CaretDownIcon } from "@phosphor-icons/react";
3
+
4
+ import { cn } from "./cn";
5
+
6
+ function NativeSelect({
7
+ className,
8
+ size = "default",
9
+ ...props
10
+ }: Omit<React.ComponentProps<"select">, "size"> & { size?: "sm" | "default" }) {
11
+ return (
12
+ <div
13
+ className="group/native-select relative w-fit has-[select:disabled]:opacity-50"
14
+ data-slot="native-select-wrapper"
15
+ >
16
+ <select
17
+ data-slot="native-select"
18
+ data-size={size}
19
+ className={cn(
20
+ "h-9 w-full min-w-0 appearance-none rounded-md border border-input bg-transparent px-3 py-2 pr-9 text-sm shadow-xs transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed data-[size=sm]:h-8 data-[size=sm]:py-1 dark:bg-input/30 dark:hover:bg-input/50",
21
+ "focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50",
22
+ "aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40",
23
+ className,
24
+ )}
25
+ {...props}
26
+ />
27
+ <CaretDownIcon
28
+ className="pointer-events-none absolute top-1/2 right-3.5 size-4 -translate-y-1/2 text-muted-foreground opacity-50 select-none"
29
+ aria-hidden="true"
30
+ data-slot="native-select-icon"
31
+ />
32
+ </div>
33
+ );
34
+ }
35
+
36
+ function NativeSelectOption({ className, ...props }: React.ComponentProps<"option">) {
37
+ return (
38
+ <option
39
+ data-slot="native-select-option"
40
+ className={cn("bg-[Canvas] text-[CanvasText]", className)}
41
+ {...props}
42
+ />
43
+ );
44
+ }
45
+
46
+ function NativeSelectOptGroup({ className, ...props }: React.ComponentProps<"optgroup">) {
47
+ return (
48
+ <optgroup
49
+ data-slot="native-select-optgroup"
50
+ className={cn("bg-[Canvas] text-[CanvasText]", className)}
51
+ {...props}
52
+ />
53
+ );
54
+ }
55
+
56
+ export { NativeSelect, NativeSelectOptGroup, NativeSelectOption };
@@ -0,0 +1,161 @@
1
+ import * as React from "react";
2
+ import { cva } from "class-variance-authority";
3
+ import { CaretDownIcon } from "@phosphor-icons/react";
4
+ import { NavigationMenu as NavigationMenuPrimitive } from "radix-ui";
5
+
6
+ import { cn } from "./cn";
7
+
8
+ function NavigationMenu({
9
+ className,
10
+ children,
11
+ viewport = true,
12
+ ...props
13
+ }: React.ComponentProps<typeof NavigationMenuPrimitive.Root> & {
14
+ viewport?: boolean;
15
+ }) {
16
+ return (
17
+ <NavigationMenuPrimitive.Root
18
+ data-slot="navigation-menu"
19
+ data-viewport={viewport}
20
+ className={cn(
21
+ "group/navigation-menu relative flex max-w-max flex-1 items-center justify-center",
22
+ className,
23
+ )}
24
+ {...props}
25
+ >
26
+ {children}
27
+ {viewport && <NavigationMenuViewport />}
28
+ </NavigationMenuPrimitive.Root>
29
+ );
30
+ }
31
+
32
+ function NavigationMenuList({
33
+ className,
34
+ ...props
35
+ }: React.ComponentProps<typeof NavigationMenuPrimitive.List>) {
36
+ return (
37
+ <NavigationMenuPrimitive.List
38
+ data-slot="navigation-menu-list"
39
+ className={cn("group flex flex-1 list-none items-center justify-center gap-1", className)}
40
+ {...props}
41
+ />
42
+ );
43
+ }
44
+
45
+ function NavigationMenuItem({
46
+ className,
47
+ ...props
48
+ }: React.ComponentProps<typeof NavigationMenuPrimitive.Item>) {
49
+ return (
50
+ <NavigationMenuPrimitive.Item
51
+ data-slot="navigation-menu-item"
52
+ className={cn("relative", className)}
53
+ {...props}
54
+ />
55
+ );
56
+ }
57
+
58
+ const navigationMenuTriggerStyle = cva(
59
+ "group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-[color,box-shadow] outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=open]:bg-accent/50 data-[state=open]:text-accent-foreground data-[state=open]:hover:bg-accent data-[state=open]:focus:bg-accent",
60
+ );
61
+
62
+ function NavigationMenuTrigger({
63
+ className,
64
+ children,
65
+ ...props
66
+ }: React.ComponentProps<typeof NavigationMenuPrimitive.Trigger>) {
67
+ return (
68
+ <NavigationMenuPrimitive.Trigger
69
+ data-slot="navigation-menu-trigger"
70
+ className={cn(navigationMenuTriggerStyle(), "group", className)}
71
+ {...props}
72
+ >
73
+ {children}{" "}
74
+ <CaretDownIcon
75
+ className="relative top-[1px] ml-1 size-3 transition duration-300 group-data-[state=open]:rotate-180"
76
+ aria-hidden="true"
77
+ />
78
+ </NavigationMenuPrimitive.Trigger>
79
+ );
80
+ }
81
+
82
+ function NavigationMenuContent({
83
+ className,
84
+ ...props
85
+ }: React.ComponentProps<typeof NavigationMenuPrimitive.Content>) {
86
+ return (
87
+ <NavigationMenuPrimitive.Content
88
+ data-slot="navigation-menu-content"
89
+ className={cn(
90
+ "top-0 left-0 w-full p-2 pr-2.5 data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 data-[motion^=from-]:animate-in data-[motion^=from-]:fade-in data-[motion^=to-]:animate-out data-[motion^=to-]:fade-out md:absolute md:w-auto",
91
+ "group-data-[viewport=false]/navigation-menu:top-full group-data-[viewport=false]/navigation-menu:mt-1.5 group-data-[viewport=false]/navigation-menu:overflow-hidden group-data-[viewport=false]/navigation-menu:rounded-md group-data-[viewport=false]/navigation-menu:border group-data-[viewport=false]/navigation-menu:bg-popover group-data-[viewport=false]/navigation-menu:text-popover-foreground group-data-[viewport=false]/navigation-menu:shadow group-data-[viewport=false]/navigation-menu:duration-200 **:data-[slot=navigation-menu-link]:focus:ring-0 **:data-[slot=navigation-menu-link]:focus:outline-none group-data-[viewport=false]/navigation-menu:data-[state=closed]:animate-out group-data-[viewport=false]/navigation-menu:data-[state=closed]:fade-out-0 group-data-[viewport=false]/navigation-menu:data-[state=closed]:zoom-out-95 group-data-[viewport=false]/navigation-menu:data-[state=open]:animate-in group-data-[viewport=false]/navigation-menu:data-[state=open]:fade-in-0 group-data-[viewport=false]/navigation-menu:data-[state=open]:zoom-in-95",
92
+ className,
93
+ )}
94
+ {...props}
95
+ />
96
+ );
97
+ }
98
+
99
+ function NavigationMenuViewport({
100
+ className,
101
+ ...props
102
+ }: React.ComponentProps<typeof NavigationMenuPrimitive.Viewport>) {
103
+ return (
104
+ <div className={cn("absolute top-full left-0 isolate z-50 flex justify-center")}>
105
+ <NavigationMenuPrimitive.Viewport
106
+ data-slot="navigation-menu-viewport"
107
+ className={cn(
108
+ "origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:zoom-in-90 md:w-[var(--radix-navigation-menu-viewport-width)]",
109
+ className,
110
+ )}
111
+ {...props}
112
+ />
113
+ </div>
114
+ );
115
+ }
116
+
117
+ function NavigationMenuLink({
118
+ className,
119
+ ...props
120
+ }: React.ComponentProps<typeof NavigationMenuPrimitive.Link>) {
121
+ return (
122
+ <NavigationMenuPrimitive.Link
123
+ data-slot="navigation-menu-link"
124
+ className={cn(
125
+ "flex flex-col gap-1 rounded-sm p-2 text-sm transition-all outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1 data-[active=true]:bg-accent/50 data-[active=true]:text-accent-foreground data-[active=true]:hover:bg-accent data-[active=true]:focus:bg-accent [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground",
126
+ className,
127
+ )}
128
+ {...props}
129
+ />
130
+ );
131
+ }
132
+
133
+ function NavigationMenuIndicator({
134
+ className,
135
+ ...props
136
+ }: React.ComponentProps<typeof NavigationMenuPrimitive.Indicator>) {
137
+ return (
138
+ <NavigationMenuPrimitive.Indicator
139
+ data-slot="navigation-menu-indicator"
140
+ className={cn(
141
+ "top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:animate-in data-[state=visible]:fade-in",
142
+ className,
143
+ )}
144
+ {...props}
145
+ >
146
+ <div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" />
147
+ </NavigationMenuPrimitive.Indicator>
148
+ );
149
+ }
150
+
151
+ export {
152
+ NavigationMenu,
153
+ NavigationMenuList,
154
+ NavigationMenuItem,
155
+ NavigationMenuContent,
156
+ NavigationMenuTrigger,
157
+ NavigationMenuLink,
158
+ NavigationMenuIndicator,
159
+ NavigationMenuViewport,
160
+ navigationMenuTriggerStyle,
161
+ };