@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,222 @@
1
+ import * as React from "react";
2
+ import { CheckIcon, CaretRightIcon, CircleIcon } from "@phosphor-icons/react";
3
+ import { ContextMenu as ContextMenuPrimitive } from "radix-ui";
4
+
5
+ import { cn } from "./cn";
6
+
7
+ function ContextMenu({ ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Root>) {
8
+ return <ContextMenuPrimitive.Root data-slot="context-menu" {...props} />;
9
+ }
10
+
11
+ function ContextMenuTrigger({
12
+ ...props
13
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Trigger>) {
14
+ return <ContextMenuPrimitive.Trigger data-slot="context-menu-trigger" {...props} />;
15
+ }
16
+
17
+ function ContextMenuGroup({ ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Group>) {
18
+ return <ContextMenuPrimitive.Group data-slot="context-menu-group" {...props} />;
19
+ }
20
+
21
+ function ContextMenuPortal({ ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Portal>) {
22
+ return <ContextMenuPrimitive.Portal data-slot="context-menu-portal" {...props} />;
23
+ }
24
+
25
+ function ContextMenuSub({ ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Sub>) {
26
+ return <ContextMenuPrimitive.Sub data-slot="context-menu-sub" {...props} />;
27
+ }
28
+
29
+ function ContextMenuRadioGroup({
30
+ ...props
31
+ }: React.ComponentProps<typeof ContextMenuPrimitive.RadioGroup>) {
32
+ return <ContextMenuPrimitive.RadioGroup data-slot="context-menu-radio-group" {...props} />;
33
+ }
34
+
35
+ function ContextMenuSubTrigger({
36
+ className,
37
+ inset,
38
+ children,
39
+ ...props
40
+ }: React.ComponentProps<typeof ContextMenuPrimitive.SubTrigger> & {
41
+ inset?: boolean;
42
+ }) {
43
+ return (
44
+ <ContextMenuPrimitive.SubTrigger
45
+ data-slot="context-menu-sub-trigger"
46
+ data-inset={inset}
47
+ className={cn(
48
+ "flex cursor-default items-center 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",
49
+ className,
50
+ )}
51
+ {...props}
52
+ >
53
+ {children}
54
+ <CaretRightIcon className="ml-auto" />
55
+ </ContextMenuPrimitive.SubTrigger>
56
+ );
57
+ }
58
+
59
+ function ContextMenuSubContent({
60
+ className,
61
+ ...props
62
+ }: React.ComponentProps<typeof ContextMenuPrimitive.SubContent>) {
63
+ return (
64
+ <ContextMenuPrimitive.SubContent
65
+ data-slot="context-menu-sub-content"
66
+ className={cn(
67
+ "z-50 min-w-[8rem] origin-(--radix-context-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",
68
+ className,
69
+ )}
70
+ {...props}
71
+ />
72
+ );
73
+ }
74
+
75
+ function ContextMenuContent({
76
+ className,
77
+ ...props
78
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Content>) {
79
+ return (
80
+ <ContextMenuPrimitive.Portal>
81
+ <ContextMenuPrimitive.Content
82
+ data-slot="context-menu-content"
83
+ className={cn(
84
+ "z-50 max-h-(--radix-context-menu-content-available-height) min-w-[8rem] origin-(--radix-context-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",
85
+ className,
86
+ )}
87
+ {...props}
88
+ />
89
+ </ContextMenuPrimitive.Portal>
90
+ );
91
+ }
92
+
93
+ function ContextMenuItem({
94
+ className,
95
+ inset,
96
+ variant = "default",
97
+ ...props
98
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Item> & {
99
+ inset?: boolean;
100
+ variant?: "default" | "destructive";
101
+ }) {
102
+ return (
103
+ <ContextMenuPrimitive.Item
104
+ data-slot="context-menu-item"
105
+ data-inset={inset}
106
+ data-variant={variant}
107
+ className={cn(
108
+ "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!",
109
+ className,
110
+ )}
111
+ {...props}
112
+ />
113
+ );
114
+ }
115
+
116
+ function ContextMenuCheckboxItem({
117
+ className,
118
+ children,
119
+ checked,
120
+ ...props
121
+ }: React.ComponentProps<typeof ContextMenuPrimitive.CheckboxItem>) {
122
+ return (
123
+ <ContextMenuPrimitive.CheckboxItem
124
+ data-slot="context-menu-checkbox-item"
125
+ className={cn(
126
+ "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",
127
+ className,
128
+ )}
129
+ checked={checked}
130
+ {...props}
131
+ >
132
+ <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
133
+ <ContextMenuPrimitive.ItemIndicator>
134
+ <CheckIcon className="size-4" />
135
+ </ContextMenuPrimitive.ItemIndicator>
136
+ </span>
137
+ {children}
138
+ </ContextMenuPrimitive.CheckboxItem>
139
+ );
140
+ }
141
+
142
+ function ContextMenuRadioItem({
143
+ className,
144
+ children,
145
+ ...props
146
+ }: React.ComponentProps<typeof ContextMenuPrimitive.RadioItem>) {
147
+ return (
148
+ <ContextMenuPrimitive.RadioItem
149
+ data-slot="context-menu-radio-item"
150
+ className={cn(
151
+ "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",
152
+ className,
153
+ )}
154
+ {...props}
155
+ >
156
+ <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
157
+ <ContextMenuPrimitive.ItemIndicator>
158
+ <CircleIcon className="size-2 fill-current" />
159
+ </ContextMenuPrimitive.ItemIndicator>
160
+ </span>
161
+ {children}
162
+ </ContextMenuPrimitive.RadioItem>
163
+ );
164
+ }
165
+
166
+ function ContextMenuLabel({
167
+ className,
168
+ inset,
169
+ ...props
170
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Label> & {
171
+ inset?: boolean;
172
+ }) {
173
+ return (
174
+ <ContextMenuPrimitive.Label
175
+ data-slot="context-menu-label"
176
+ data-inset={inset}
177
+ className={cn("px-2 py-1.5 text-sm font-medium text-foreground data-[inset]:pl-8", className)}
178
+ {...props}
179
+ />
180
+ );
181
+ }
182
+
183
+ function ContextMenuSeparator({
184
+ className,
185
+ ...props
186
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Separator>) {
187
+ return (
188
+ <ContextMenuPrimitive.Separator
189
+ data-slot="context-menu-separator"
190
+ className={cn("-mx-1 my-1 h-px bg-border", className)}
191
+ {...props}
192
+ />
193
+ );
194
+ }
195
+
196
+ function ContextMenuShortcut({ className, ...props }: React.ComponentProps<"span">) {
197
+ return (
198
+ <span
199
+ data-slot="context-menu-shortcut"
200
+ className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)}
201
+ {...props}
202
+ />
203
+ );
204
+ }
205
+
206
+ export {
207
+ ContextMenu,
208
+ ContextMenuTrigger,
209
+ ContextMenuContent,
210
+ ContextMenuItem,
211
+ ContextMenuCheckboxItem,
212
+ ContextMenuRadioItem,
213
+ ContextMenuLabel,
214
+ ContextMenuSeparator,
215
+ ContextMenuShortcut,
216
+ ContextMenuGroup,
217
+ ContextMenuPortal,
218
+ ContextMenuSub,
219
+ ContextMenuSubContent,
220
+ ContextMenuSubTrigger,
221
+ ContextMenuRadioGroup,
222
+ };
package/src/dialog.tsx ADDED
@@ -0,0 +1,142 @@
1
+ import * as React from "react";
2
+ import { XIcon } from "@phosphor-icons/react";
3
+ import { Dialog as DialogPrimitive } from "radix-ui";
4
+
5
+ import { cn } from "./cn";
6
+ import { Button } from "./button";
7
+
8
+ function Dialog({ ...props }: React.ComponentProps<typeof DialogPrimitive.Root>) {
9
+ return <DialogPrimitive.Root data-slot="dialog" {...props} />;
10
+ }
11
+
12
+ function DialogTrigger({ ...props }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
13
+ return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
14
+ }
15
+
16
+ function DialogPortal({ ...props }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
17
+ return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
18
+ }
19
+
20
+ function DialogClose({ ...props }: React.ComponentProps<typeof DialogPrimitive.Close>) {
21
+ return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
22
+ }
23
+
24
+ function DialogOverlay({
25
+ className,
26
+ ...props
27
+ }: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
28
+ return (
29
+ <DialogPrimitive.Overlay
30
+ data-slot="dialog-overlay"
31
+ className={cn(
32
+ "fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0",
33
+ className,
34
+ )}
35
+ {...props}
36
+ />
37
+ );
38
+ }
39
+
40
+ function DialogContent({
41
+ className,
42
+ children,
43
+ showCloseButton = true,
44
+ ...props
45
+ }: React.ComponentProps<typeof DialogPrimitive.Content> & {
46
+ showCloseButton?: boolean;
47
+ }) {
48
+ return (
49
+ <DialogPortal data-slot="dialog-portal">
50
+ <DialogOverlay />
51
+ <DialogPrimitive.Content
52
+ data-slot="dialog-content"
53
+ className={cn(
54
+ "fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-background p-6 shadow-lg duration-200 outline-none 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 sm:max-w-lg",
55
+ className,
56
+ )}
57
+ {...props}
58
+ >
59
+ {children}
60
+ {showCloseButton && (
61
+ <DialogPrimitive.Close
62
+ data-slot="dialog-close"
63
+ className="absolute top-4 right-4 rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
64
+ >
65
+ <XIcon />
66
+ <span className="sr-only">Close</span>
67
+ </DialogPrimitive.Close>
68
+ )}
69
+ </DialogPrimitive.Content>
70
+ </DialogPortal>
71
+ );
72
+ }
73
+
74
+ function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
75
+ return (
76
+ <div
77
+ data-slot="dialog-header"
78
+ className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
79
+ {...props}
80
+ />
81
+ );
82
+ }
83
+
84
+ function DialogFooter({
85
+ className,
86
+ showCloseButton = false,
87
+ children,
88
+ ...props
89
+ }: React.ComponentProps<"div"> & {
90
+ showCloseButton?: boolean;
91
+ }) {
92
+ return (
93
+ <div
94
+ data-slot="dialog-footer"
95
+ className={cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className)}
96
+ {...props}
97
+ >
98
+ {children}
99
+ {showCloseButton && (
100
+ <DialogPrimitive.Close asChild>
101
+ <Button variant="outline">Close</Button>
102
+ </DialogPrimitive.Close>
103
+ )}
104
+ </div>
105
+ );
106
+ }
107
+
108
+ function DialogTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>) {
109
+ return (
110
+ <DialogPrimitive.Title
111
+ data-slot="dialog-title"
112
+ className={cn("text-lg leading-none font-semibold", className)}
113
+ {...props}
114
+ />
115
+ );
116
+ }
117
+
118
+ function DialogDescription({
119
+ className,
120
+ ...props
121
+ }: React.ComponentProps<typeof DialogPrimitive.Description>) {
122
+ return (
123
+ <DialogPrimitive.Description
124
+ data-slot="dialog-description"
125
+ className={cn("text-sm text-muted-foreground", className)}
126
+ {...props}
127
+ />
128
+ );
129
+ }
130
+
131
+ export {
132
+ Dialog,
133
+ DialogClose,
134
+ DialogContent,
135
+ DialogDescription,
136
+ DialogFooter,
137
+ DialogHeader,
138
+ DialogOverlay,
139
+ DialogPortal,
140
+ DialogTitle,
141
+ DialogTrigger,
142
+ };
@@ -0,0 +1,18 @@
1
+ import * as React from "react";
2
+ import { Direction } from "radix-ui";
3
+
4
+ function DirectionProvider({
5
+ dir,
6
+ direction,
7
+ children,
8
+ }: React.ComponentProps<typeof Direction.DirectionProvider> & {
9
+ direction?: React.ComponentProps<typeof Direction.DirectionProvider>["dir"];
10
+ }) {
11
+ return (
12
+ <Direction.DirectionProvider dir={direction ?? dir}>{children}</Direction.DirectionProvider>
13
+ );
14
+ }
15
+
16
+ const useDirection = Direction.useDirection;
17
+
18
+ export { DirectionProvider, useDirection };
package/src/drawer.tsx ADDED
@@ -0,0 +1,122 @@
1
+ import * as React from "react";
2
+ import { Drawer as DrawerPrimitive } from "vaul";
3
+
4
+ import { cn } from "./cn";
5
+
6
+ function Drawer({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Root>) {
7
+ return <DrawerPrimitive.Root data-slot="drawer" {...props} />;
8
+ }
9
+
10
+ function DrawerTrigger({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Trigger>) {
11
+ return <DrawerPrimitive.Trigger data-slot="drawer-trigger" {...props} />;
12
+ }
13
+
14
+ function DrawerPortal({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Portal>) {
15
+ return <DrawerPrimitive.Portal data-slot="drawer-portal" {...props} />;
16
+ }
17
+
18
+ function DrawerClose({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Close>) {
19
+ return <DrawerPrimitive.Close data-slot="drawer-close" {...props} />;
20
+ }
21
+
22
+ function DrawerOverlay({
23
+ className,
24
+ ...props
25
+ }: React.ComponentProps<typeof DrawerPrimitive.Overlay>) {
26
+ return (
27
+ <DrawerPrimitive.Overlay
28
+ data-slot="drawer-overlay"
29
+ className={cn(
30
+ "fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0",
31
+ className,
32
+ )}
33
+ {...props}
34
+ />
35
+ );
36
+ }
37
+
38
+ function DrawerContent({
39
+ className,
40
+ children,
41
+ ...props
42
+ }: React.ComponentProps<typeof DrawerPrimitive.Content>) {
43
+ return (
44
+ <DrawerPortal data-slot="drawer-portal">
45
+ <DrawerOverlay />
46
+ <DrawerPrimitive.Content
47
+ data-slot="drawer-content"
48
+ className={cn(
49
+ "group/drawer-content fixed z-50 flex h-auto flex-col bg-background",
50
+ "data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-lg data-[vaul-drawer-direction=top]:border-b",
51
+ "data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-lg data-[vaul-drawer-direction=bottom]:border-t",
52
+ "data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=right]:sm:max-w-sm",
53
+ "data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=left]:sm:max-w-sm",
54
+ className,
55
+ )}
56
+ {...props}
57
+ >
58
+ <div className="mx-auto mt-4 hidden h-2 w-[100px] shrink-0 rounded-full bg-muted group-data-[vaul-drawer-direction=bottom]/drawer-content:block" />
59
+ {children}
60
+ </DrawerPrimitive.Content>
61
+ </DrawerPortal>
62
+ );
63
+ }
64
+
65
+ function DrawerHeader({ className, ...props }: React.ComponentProps<"div">) {
66
+ return (
67
+ <div
68
+ data-slot="drawer-header"
69
+ className={cn(
70
+ "flex flex-col gap-0.5 p-4 group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center group-data-[vaul-drawer-direction=top]/drawer-content:text-center md:gap-1.5 md:text-left",
71
+ className,
72
+ )}
73
+ {...props}
74
+ />
75
+ );
76
+ }
77
+
78
+ function DrawerFooter({ className, ...props }: React.ComponentProps<"div">) {
79
+ return (
80
+ <div
81
+ data-slot="drawer-footer"
82
+ className={cn("mt-auto flex flex-col gap-2 p-4", className)}
83
+ {...props}
84
+ />
85
+ );
86
+ }
87
+
88
+ function DrawerTitle({ className, ...props }: React.ComponentProps<typeof DrawerPrimitive.Title>) {
89
+ return (
90
+ <DrawerPrimitive.Title
91
+ data-slot="drawer-title"
92
+ className={cn("font-semibold text-foreground", className)}
93
+ {...props}
94
+ />
95
+ );
96
+ }
97
+
98
+ function DrawerDescription({
99
+ className,
100
+ ...props
101
+ }: React.ComponentProps<typeof DrawerPrimitive.Description>) {
102
+ return (
103
+ <DrawerPrimitive.Description
104
+ data-slot="drawer-description"
105
+ className={cn("text-sm text-muted-foreground", className)}
106
+ {...props}
107
+ />
108
+ );
109
+ }
110
+
111
+ export {
112
+ Drawer,
113
+ DrawerPortal,
114
+ DrawerOverlay,
115
+ DrawerTrigger,
116
+ DrawerClose,
117
+ DrawerContent,
118
+ DrawerHeader,
119
+ DrawerFooter,
120
+ DrawerTitle,
121
+ DrawerDescription,
122
+ };