@olympusoss/canvas 2.6.19

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 (128) hide show
  1. package/package.json +179 -0
  2. package/src/components/atoms/README.md +11 -0
  3. package/src/components/atoms/aspect-ratio.tsx +32 -0
  4. package/src/components/atoms/avatar.tsx +98 -0
  5. package/src/components/atoms/badge.tsx +44 -0
  6. package/src/components/atoms/brand-mark.tsx +74 -0
  7. package/src/components/atoms/button.tsx +104 -0
  8. package/src/components/atoms/checkbox.tsx +63 -0
  9. package/src/components/atoms/flex-box.tsx +105 -0
  10. package/src/components/atoms/icon.tsx +34 -0
  11. package/src/components/atoms/input.tsx +91 -0
  12. package/src/components/atoms/label.tsx +41 -0
  13. package/src/components/atoms/logo.tsx +89 -0
  14. package/src/components/atoms/progress.tsx +55 -0
  15. package/src/components/atoms/radio-group.tsx +122 -0
  16. package/src/components/atoms/scroll-area.tsx +106 -0
  17. package/src/components/atoms/section.tsx +48 -0
  18. package/src/components/atoms/separator.tsx +45 -0
  19. package/src/components/atoms/skeleton.tsx +17 -0
  20. package/src/components/atoms/slider.tsx +93 -0
  21. package/src/components/atoms/switch.tsx +60 -0
  22. package/src/components/atoms/textarea.tsx +78 -0
  23. package/src/components/atoms/toggle.tsx +80 -0
  24. package/src/components/charts/activity-heatmap.tsx +96 -0
  25. package/src/components/charts/axes.tsx +21 -0
  26. package/src/components/charts/chart-container.tsx +195 -0
  27. package/src/components/charts/chart-legend.tsx +67 -0
  28. package/src/components/charts/chart-tooltip.tsx +161 -0
  29. package/src/components/charts/chart-types.tsx +49 -0
  30. package/src/components/charts/containers.tsx +11 -0
  31. package/src/components/charts/data.tsx +16 -0
  32. package/src/components/charts/details.tsx +25 -0
  33. package/src/components/charts/gauge.tsx +106 -0
  34. package/src/components/charts/grids.tsx +8 -0
  35. package/src/components/charts/index.ts +62 -0
  36. package/src/components/charts/labeled-bar-list.tsx +85 -0
  37. package/src/components/charts/references.tsx +8 -0
  38. package/src/components/charts/service-health-list.tsx +73 -0
  39. package/src/components/charts/sparkline.tsx +52 -0
  40. package/src/components/charts/stacked-bar.tsx +104 -0
  41. package/src/components/charts/text.tsx +10 -0
  42. package/src/components/charts/world-heat-map-inner.tsx +317 -0
  43. package/src/components/charts/world-heat-map.tsx +184 -0
  44. package/src/components/molecules/README.md +12 -0
  45. package/src/components/molecules/action-bar.tsx +73 -0
  46. package/src/components/molecules/activity-item.tsx +74 -0
  47. package/src/components/molecules/alert.tsx +80 -0
  48. package/src/components/molecules/animated-background.tsx +92 -0
  49. package/src/components/molecules/brand-lockup.tsx +48 -0
  50. package/src/components/molecules/breadcrumb.tsx +161 -0
  51. package/src/components/molecules/button-group.tsx +104 -0
  52. package/src/components/molecules/calendar.tsx +216 -0
  53. package/src/components/molecules/card.tsx +101 -0
  54. package/src/components/molecules/code-block.tsx +48 -0
  55. package/src/components/molecules/empty-state.tsx +55 -0
  56. package/src/components/molecules/error-state.tsx +42 -0
  57. package/src/components/molecules/field-display.tsx +35 -0
  58. package/src/components/molecules/input-otp.tsx +74 -0
  59. package/src/components/molecules/loading-state.tsx +36 -0
  60. package/src/components/molecules/notification-item.tsx +67 -0
  61. package/src/components/molecules/notification-list.tsx +45 -0
  62. package/src/components/molecules/number-badge.tsx +53 -0
  63. package/src/components/molecules/page-header.tsx +88 -0
  64. package/src/components/molecules/page-tabs.tsx +94 -0
  65. package/src/components/molecules/pagination.tsx +150 -0
  66. package/src/components/molecules/phone-input.tsx +200 -0
  67. package/src/components/molecules/search-bar.tsx +64 -0
  68. package/src/components/molecules/secret-field.tsx +158 -0
  69. package/src/components/molecules/section-card.tsx +91 -0
  70. package/src/components/molecules/stat-card.tsx +96 -0
  71. package/src/components/molecules/status-badge.tsx +42 -0
  72. package/src/components/molecules/stepper.tsx +96 -0
  73. package/src/components/molecules/table.tsx +157 -0
  74. package/src/components/molecules/toggle-group.tsx +145 -0
  75. package/src/components/molecules/tooltip.tsx +150 -0
  76. package/src/components/molecules/user-avatar-chip.tsx +71 -0
  77. package/src/components/organisms/README.md +14 -0
  78. package/src/components/organisms/accordion.tsx +149 -0
  79. package/src/components/organisms/alert-dialog.tsx +269 -0
  80. package/src/components/organisms/carousel.tsx +244 -0
  81. package/src/components/organisms/collapsible.tsx +69 -0
  82. package/src/components/organisms/command.tsx +143 -0
  83. package/src/components/organisms/context-menu.tsx +333 -0
  84. package/src/components/organisms/dashboard-grid.tsx +360 -0
  85. package/src/components/organisms/data-table.tsx +330 -0
  86. package/src/components/organisms/dialog.tsx +304 -0
  87. package/src/components/organisms/drawer.tsx +100 -0
  88. package/src/components/organisms/dropdown-menu.tsx +434 -0
  89. package/src/components/organisms/editors/code-editor.tsx +144 -0
  90. package/src/components/organisms/editors/index.ts +4 -0
  91. package/src/components/organisms/editors/markdown-editor.tsx +153 -0
  92. package/src/components/organisms/editors/markdown-renderer.ts +27 -0
  93. package/src/components/organisms/editors/prose-canvas-classes.ts +45 -0
  94. package/src/components/organisms/editors/rich-text-editor.tsx +126 -0
  95. package/src/components/organisms/editors/toolbar/md-toolbar.tsx +129 -0
  96. package/src/components/organisms/editors/toolbar/rte-toolbar.tsx +211 -0
  97. package/src/components/organisms/editors/toolbar/toolbar-shell.tsx +45 -0
  98. package/src/components/organisms/editors/use-codemirror-theme.ts +61 -0
  99. package/src/components/organisms/error-boundary.tsx +61 -0
  100. package/src/components/organisms/form.tsx +174 -0
  101. package/src/components/organisms/hover-card.tsx +114 -0
  102. package/src/components/organisms/menubar.tsx +491 -0
  103. package/src/components/organisms/navbar.tsx +101 -0
  104. package/src/components/organisms/navigation-menu.tsx +234 -0
  105. package/src/components/organisms/popover.tsx +144 -0
  106. package/src/components/organisms/resizable.tsx +39 -0
  107. package/src/components/organisms/schema-form.tsx +232 -0
  108. package/src/components/organisms/select.tsx +303 -0
  109. package/src/components/organisms/sheet.tsx +256 -0
  110. package/src/components/organisms/sidebar.tsx +1037 -0
  111. package/src/components/organisms/sonner.tsx +96 -0
  112. package/src/components/organisms/tabs.tsx +132 -0
  113. package/src/components/organisms/theme-provider.tsx +101 -0
  114. package/src/hooks/use-mobile.tsx +19 -0
  115. package/src/index.ts +547 -0
  116. package/src/lib/portal-container.tsx +35 -0
  117. package/src/lib/utils.ts +6 -0
  118. package/src/native.ts +23 -0
  119. package/src/tokens/colors.ts +91 -0
  120. package/src/tokens/index.ts +3 -0
  121. package/src/tokens/spacing.ts +55 -0
  122. package/src/tokens/typography.ts +27 -0
  123. package/styles/canvas.css +55 -0
  124. package/styles/dashboard-grid.css +47 -0
  125. package/styles/leaflet.css +13 -0
  126. package/styles/tokens.css +234 -0
  127. package/tailwind.config.ts +70 -0
  128. package/tsconfig.json +23 -0
@@ -0,0 +1,304 @@
1
+ "use client";
2
+
3
+ import * as DialogPrimitive from "@radix-ui/react-dialog";
4
+ import { X } from "lucide-react";
5
+ import * as React from "react";
6
+
7
+ import { cn } from "../../lib/utils";
8
+
9
+ /* ────────────────────────────────────────────────────────────────
10
+ * Public prop interfaces — every prop documented for the docs site
11
+ * and TS hover-info. Mirrors the full Radix Dialog API surface.
12
+ * ──────────────────────────────────────────────────────────────── */
13
+
14
+ export interface DialogProps extends React.ComponentProps<typeof DialogPrimitive.Root> {
15
+ /**
16
+ * Controlled open state. Pair with `onOpenChange`. Omit for uncontrolled
17
+ * usage and pass `defaultOpen` instead.
18
+ */
19
+ open?: boolean;
20
+ /**
21
+ * Initial open state for uncontrolled usage. Ignored if `open` is also
22
+ * passed.
23
+ * @default false
24
+ */
25
+ defaultOpen?: boolean;
26
+ /**
27
+ * Fires whenever the user opens or closes the dialog (escape key, scrim
28
+ * click, X button, programmatic close).
29
+ */
30
+ onOpenChange?: (open: boolean) => void;
31
+ /**
32
+ * When true, blocks focus from leaving the dialog (focus trap) and
33
+ * renders the scrim overlay over the rest of the page.
34
+ * @default true
35
+ */
36
+ modal?: boolean;
37
+ /** Trigger + Content + any other Radix sub-pieces. */
38
+ children?: React.ReactNode;
39
+ }
40
+
41
+ const Dialog = DialogPrimitive.Root as React.FC<DialogProps>;
42
+
43
+ export interface DialogTriggerProps
44
+ extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Trigger> {
45
+ /**
46
+ * Render as a Radix Slot — forwards props onto the immediate child
47
+ * element instead of rendering a wrapper `<button>`.
48
+ * @default false
49
+ */
50
+ asChild?: boolean;
51
+ /** The button (or slot) that opens the dialog. */
52
+ children?: React.ReactNode;
53
+ /** Tailwind / CSS classes merged onto the trigger via `cn()`. */
54
+ className?: string;
55
+ }
56
+
57
+ const DialogTrigger = DialogPrimitive.Trigger as React.ForwardRefExoticComponent<
58
+ DialogTriggerProps & React.RefAttributes<HTMLButtonElement>
59
+ >;
60
+
61
+ export interface DialogPortalProps
62
+ extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Portal> {
63
+ /**
64
+ * The DOM element to portal the dialog content into. Defaults to
65
+ * `document.body`. Useful when canvas is embedded inside an iframe and
66
+ * the dialog should mount in the iframe's document instead of the parent.
67
+ */
68
+ container?: HTMLElement | null;
69
+ /**
70
+ * Force the portal to mount its children even when the dialog is
71
+ * closed. Useful when animation libraries need the DOM nodes to persist
72
+ * between open/close.
73
+ * @default false
74
+ */
75
+ forceMount?: true;
76
+ /** Overlay + Content + Close. */
77
+ children?: React.ReactNode;
78
+ }
79
+
80
+ const DialogPortal = DialogPrimitive.Portal as React.FC<DialogPortalProps>;
81
+
82
+ export interface DialogCloseProps
83
+ extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Close> {
84
+ /**
85
+ * Render as a Radix Slot — forwards props onto the immediate child
86
+ * element instead of rendering a wrapper `<button>`.
87
+ * @default false
88
+ */
89
+ asChild?: boolean;
90
+ /** The button (or slot) that closes the dialog. */
91
+ children?: React.ReactNode;
92
+ /** Tailwind / CSS classes merged onto the close button via `cn()`. */
93
+ className?: string;
94
+ }
95
+
96
+ const DialogClose = DialogPrimitive.Close as React.ForwardRefExoticComponent<
97
+ DialogCloseProps & React.RefAttributes<HTMLButtonElement>
98
+ >;
99
+
100
+ export interface DialogOverlayProps
101
+ extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay> {
102
+ /**
103
+ * Render as a Radix Slot — forwards props onto the immediate child
104
+ * element instead of rendering a wrapper `<div>`.
105
+ * @default false
106
+ */
107
+ asChild?: boolean;
108
+ /**
109
+ * Force the overlay to mount even when the dialog is closed. Pair with
110
+ * a CSS animation that fades in/out based on `data-state`.
111
+ * @default false
112
+ */
113
+ forceMount?: true;
114
+ /** Tailwind / CSS classes merged onto the overlay via `cn()`. Defaults to a black/80% scrim. */
115
+ className?: string;
116
+ }
117
+
118
+ const DialogOverlay = React.forwardRef<
119
+ React.ElementRef<typeof DialogPrimitive.Overlay>,
120
+ DialogOverlayProps
121
+ >(({ className, ...props }, ref) => (
122
+ <DialogPrimitive.Overlay
123
+ ref={ref}
124
+ className={cn(
125
+ "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
126
+ className,
127
+ )}
128
+ {...props}
129
+ />
130
+ ));
131
+ DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
132
+
133
+ export interface DialogContentProps
134
+ extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> {
135
+ /**
136
+ * Render as a Radix Slot — forwards props onto the immediate child
137
+ * element instead of rendering a wrapper `<div>`.
138
+ * @default false
139
+ */
140
+ asChild?: boolean;
141
+ /**
142
+ * Force the content to mount even when the dialog is closed. Pair with
143
+ * a CSS animation that fades in/out based on `data-state`.
144
+ * @default false
145
+ */
146
+ forceMount?: true;
147
+ /**
148
+ * Fires when focus enters the dialog after it opens. Call
149
+ * `event.preventDefault()` to prevent the default focus-first-element
150
+ * behaviour.
151
+ */
152
+ onOpenAutoFocus?: (event: Event) => void;
153
+ /**
154
+ * Fires when focus leaves the dialog after it closes. Call
155
+ * `event.preventDefault()` to prevent focus from returning to the trigger.
156
+ */
157
+ onCloseAutoFocus?: (event: Event) => void;
158
+ /**
159
+ * Fires when the Escape key is pressed inside the dialog. Call
160
+ * `event.preventDefault()` to keep the dialog open.
161
+ */
162
+ onEscapeKeyDown?: (event: KeyboardEvent) => void;
163
+ /**
164
+ * Fires when a pointer event happens outside the dialog. Call
165
+ * `event.preventDefault()` to keep the dialog open.
166
+ */
167
+ onPointerDownOutside?: (event: CustomEvent<{ originalEvent: PointerEvent }>) => void;
168
+ /**
169
+ * Fires on any interaction (focus, pointer) outside the dialog. Call
170
+ * `event.preventDefault()` to keep the dialog open. Superset of the
171
+ * `onPointerDownOutside` and focus-out events.
172
+ */
173
+ onInteractOutside?: (event: Event) => void;
174
+ /** Title + Description + body content + Footer. */
175
+ children?: React.ReactNode;
176
+ /**
177
+ * Tailwind / CSS classes merged onto the content panel via `cn()`.
178
+ * Default styling: centered, max-w-lg, white card with shadow.
179
+ */
180
+ className?: string;
181
+ }
182
+
183
+ const DialogContent = React.forwardRef<
184
+ React.ElementRef<typeof DialogPrimitive.Content>,
185
+ DialogContentProps
186
+ >(({ className, children, ...props }, ref) => (
187
+ <DialogPortal>
188
+ <DialogOverlay />
189
+ <DialogPrimitive.Content
190
+ ref={ref}
191
+ className={cn(
192
+ "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
193
+ className,
194
+ )}
195
+ {...props}
196
+ >
197
+ {children}
198
+ <DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
199
+ <X className="h-4 w-4" />
200
+ <span className="sr-only">Close</span>
201
+ </DialogPrimitive.Close>
202
+ </DialogPrimitive.Content>
203
+ </DialogPortal>
204
+ ));
205
+ DialogContent.displayName = DialogPrimitive.Content.displayName;
206
+
207
+ export interface DialogHeaderProps extends React.HTMLAttributes<HTMLDivElement> {
208
+ /**
209
+ * Title + optional description for the dialog. Stacked column on mobile,
210
+ * left-aligned by default on desktop.
211
+ */
212
+ children?: React.ReactNode;
213
+ /** Tailwind / CSS classes merged onto the header via `cn()`. */
214
+ className?: string;
215
+ }
216
+
217
+ const DialogHeader = ({ className, ...props }: DialogHeaderProps) => (
218
+ <div className={cn("flex flex-col space-y-1.5 text-center sm:text-left", className)} {...props} />
219
+ );
220
+ DialogHeader.displayName = "DialogHeader";
221
+
222
+ export interface DialogFooterProps extends React.HTMLAttributes<HTMLDivElement> {
223
+ /**
224
+ * Action buttons for the dialog. Reverses to a column on mobile so the
225
+ * primary action sits on top.
226
+ */
227
+ children?: React.ReactNode;
228
+ /** Tailwind / CSS classes merged onto the footer via `cn()`. */
229
+ className?: string;
230
+ }
231
+
232
+ const DialogFooter = ({ className, ...props }: DialogFooterProps) => (
233
+ <div
234
+ className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)}
235
+ {...props}
236
+ />
237
+ );
238
+ DialogFooter.displayName = "DialogFooter";
239
+
240
+ export interface DialogTitleProps
241
+ extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title> {
242
+ /**
243
+ * Render as a Radix Slot — forwards props onto the immediate child
244
+ * element. Use to swap the heading level (e.g. `<h3>` instead of the
245
+ * default `<h2>`).
246
+ * @default false
247
+ */
248
+ asChild?: boolean;
249
+ /** Title text. Required for screen-reader users. */
250
+ children?: React.ReactNode;
251
+ /** Tailwind / CSS classes merged onto the title via `cn()`. */
252
+ className?: string;
253
+ }
254
+
255
+ const DialogTitle = React.forwardRef<
256
+ React.ElementRef<typeof DialogPrimitive.Title>,
257
+ DialogTitleProps
258
+ >(({ className, ...props }, ref) => (
259
+ <DialogPrimitive.Title
260
+ ref={ref}
261
+ className={cn("text-lg font-semibold leading-none tracking-tight", className)}
262
+ {...props}
263
+ />
264
+ ));
265
+ DialogTitle.displayName = DialogPrimitive.Title.displayName;
266
+
267
+ export interface DialogDescriptionProps
268
+ extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description> {
269
+ /**
270
+ * Render as a Radix Slot — forwards props onto the immediate child
271
+ * element instead of the default `<p>`.
272
+ * @default false
273
+ */
274
+ asChild?: boolean;
275
+ /** Description text shown below the title. */
276
+ children?: React.ReactNode;
277
+ /** Tailwind / CSS classes merged onto the description via `cn()`. */
278
+ className?: string;
279
+ }
280
+
281
+ const DialogDescription = React.forwardRef<
282
+ React.ElementRef<typeof DialogPrimitive.Description>,
283
+ DialogDescriptionProps
284
+ >(({ className, ...props }, ref) => (
285
+ <DialogPrimitive.Description
286
+ ref={ref}
287
+ className={cn("text-sm text-muted-foreground", className)}
288
+ {...props}
289
+ />
290
+ ));
291
+ DialogDescription.displayName = DialogPrimitive.Description.displayName;
292
+
293
+ export {
294
+ Dialog,
295
+ DialogClose,
296
+ DialogContent,
297
+ DialogDescription,
298
+ DialogFooter,
299
+ DialogHeader,
300
+ DialogOverlay,
301
+ DialogPortal,
302
+ DialogTitle,
303
+ DialogTrigger,
304
+ };
@@ -0,0 +1,100 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import { Drawer as DrawerPrimitive } from "vaul";
5
+
6
+ import { cn } from "../../lib/utils";
7
+
8
+ const Drawer = ({
9
+ shouldScaleBackground = true,
10
+ ...props
11
+ }: React.ComponentProps<typeof DrawerPrimitive.Root>) => (
12
+ <DrawerPrimitive.Root shouldScaleBackground={shouldScaleBackground} {...props} />
13
+ );
14
+ Drawer.displayName = "Drawer";
15
+
16
+ const DrawerTrigger = DrawerPrimitive.Trigger;
17
+
18
+ const DrawerPortal = DrawerPrimitive.Portal;
19
+
20
+ const DrawerClose = DrawerPrimitive.Close;
21
+
22
+ const DrawerOverlay = React.forwardRef<
23
+ React.ElementRef<typeof DrawerPrimitive.Overlay>,
24
+ React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Overlay>
25
+ >(({ className, ...props }, ref) => (
26
+ <DrawerPrimitive.Overlay
27
+ ref={ref}
28
+ className={cn("fixed inset-0 z-50 bg-black/80", className)}
29
+ {...props}
30
+ />
31
+ ));
32
+ DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName;
33
+
34
+ const DrawerContent = React.forwardRef<
35
+ React.ElementRef<typeof DrawerPrimitive.Content>,
36
+ React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Content>
37
+ >(({ className, children, ...props }, ref) => (
38
+ <DrawerPortal>
39
+ <DrawerOverlay />
40
+ <DrawerPrimitive.Content
41
+ ref={ref}
42
+ className={cn(
43
+ "fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background",
44
+ className,
45
+ )}
46
+ {...props}
47
+ >
48
+ <div className="mx-auto mt-4 h-2 w-[100px] rounded-full bg-muted" />
49
+ {children}
50
+ </DrawerPrimitive.Content>
51
+ </DrawerPortal>
52
+ ));
53
+ DrawerContent.displayName = "DrawerContent";
54
+
55
+ const DrawerHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
56
+ <div className={cn("grid gap-1.5 p-4 text-center sm:text-left", className)} {...props} />
57
+ );
58
+ DrawerHeader.displayName = "DrawerHeader";
59
+
60
+ const DrawerFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
61
+ <div className={cn("mt-auto flex flex-col gap-2 p-4", className)} {...props} />
62
+ );
63
+ DrawerFooter.displayName = "DrawerFooter";
64
+
65
+ const DrawerTitle = React.forwardRef<
66
+ React.ElementRef<typeof DrawerPrimitive.Title>,
67
+ React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Title>
68
+ >(({ className, ...props }, ref) => (
69
+ <DrawerPrimitive.Title
70
+ ref={ref}
71
+ className={cn("text-lg font-semibold leading-none tracking-tight", className)}
72
+ {...props}
73
+ />
74
+ ));
75
+ DrawerTitle.displayName = DrawerPrimitive.Title.displayName;
76
+
77
+ const DrawerDescription = React.forwardRef<
78
+ React.ElementRef<typeof DrawerPrimitive.Description>,
79
+ React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Description>
80
+ >(({ className, ...props }, ref) => (
81
+ <DrawerPrimitive.Description
82
+ ref={ref}
83
+ className={cn("text-sm text-muted-foreground", className)}
84
+ {...props}
85
+ />
86
+ ));
87
+ DrawerDescription.displayName = DrawerPrimitive.Description.displayName;
88
+
89
+ export {
90
+ Drawer,
91
+ DrawerClose,
92
+ DrawerContent,
93
+ DrawerDescription,
94
+ DrawerFooter,
95
+ DrawerHeader,
96
+ DrawerOverlay,
97
+ DrawerPortal,
98
+ DrawerTitle,
99
+ DrawerTrigger,
100
+ };