torch-glare 1.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 (68) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +207 -0
  3. package/cli/bin/addComponent.js +278 -0
  4. package/cli/bin/addHooks.js +75 -0
  5. package/cli/bin/addLayout.js +71 -0
  6. package/cli/bin/addProvider.js +71 -0
  7. package/cli/bin/addUtils.js +74 -0
  8. package/cli/bin/cli.js +73 -0
  9. package/cli/bin/init/init.js +15 -0
  10. package/cli/bin/init/tailwindInit.js +174 -0
  11. package/cli/bin/update.js +147 -0
  12. package/lib/components/ActionButton.tsx +63 -0
  13. package/lib/components/ActionsGroup.tsx +34 -0
  14. package/lib/components/AlertDialog.tsx +211 -0
  15. package/lib/components/Badge.tsx +116 -0
  16. package/lib/components/BadgeField.tsx +192 -0
  17. package/lib/components/Button.tsx +277 -0
  18. package/lib/components/Card.tsx +63 -0
  19. package/lib/components/Checkbox.tsx +104 -0
  20. package/lib/components/CountBadge.tsx +54 -0
  21. package/lib/components/DatePicker.tsx +464 -0
  22. package/lib/components/Drawer.tsx +118 -0
  23. package/lib/components/DropdownMenu.tsx +399 -0
  24. package/lib/components/FieldHint.tsx +76 -0
  25. package/lib/components/ImageAttachment.tsx +171 -0
  26. package/lib/components/InnerLabelField.tsx +155 -0
  27. package/lib/components/Input.tsx +179 -0
  28. package/lib/components/InputField.tsx +147 -0
  29. package/lib/components/Label.tsx +107 -0
  30. package/lib/components/LabelField.tsx +75 -0
  31. package/lib/components/LabeledCheckBox.tsx +65 -0
  32. package/lib/components/LabeledRadio.tsx +45 -0
  33. package/lib/components/LinkButton.tsx +90 -0
  34. package/lib/components/LoginButton.tsx +56 -0
  35. package/lib/components/PasswordLevel.tsx +58 -0
  36. package/lib/components/Popover.tsx +274 -0
  37. package/lib/components/ProfileMenu.tsx +90 -0
  38. package/lib/components/Radio.tsx +69 -0
  39. package/lib/components/RadioCard.tsx +70 -0
  40. package/lib/components/RingLoading.tsx +190 -0
  41. package/lib/components/SearchField.tsx +49 -0
  42. package/lib/components/Select.tsx +417 -0
  43. package/lib/components/SlideDatePicker.tsx +120 -0
  44. package/lib/components/SpinLoading.tsx +190 -0
  45. package/lib/components/Switcher.tsx +56 -0
  46. package/lib/components/TabFormItem.tsx +158 -0
  47. package/lib/components/Table.tsx +395 -0
  48. package/lib/components/Textarea.tsx +108 -0
  49. package/lib/components/Tooltip.tsx +111 -0
  50. package/lib/components/TransparentLabel.tsx +72 -0
  51. package/lib/components/TreeDropDown.tsx +69 -0
  52. package/lib/hooks/MobileSlidePicker/components/Picker.tsx +218 -0
  53. package/lib/hooks/MobileSlidePicker/components/PickerColumn.tsx +238 -0
  54. package/lib/hooks/MobileSlidePicker/components/PickerItem.tsx +64 -0
  55. package/lib/hooks/MobileSlidePicker/index.ts +10 -0
  56. package/lib/hooks/useActiveTreeItem.tsx +61 -0
  57. package/lib/hooks/useClickOutside.tsx +20 -0
  58. package/lib/hooks/useResize.tsx +78 -0
  59. package/lib/layouts/CLayout.tsx +326 -0
  60. package/lib/layouts/FieldSection.tsx +64 -0
  61. package/lib/layouts/TreeSubLayout.tsx +187 -0
  62. package/lib/providers/ThemeProvider.tsx +99 -0
  63. package/lib/utils/cn.ts +6 -0
  64. package/lib/utils/convertImageFileToDataUrl.ts +17 -0
  65. package/lib/utils/resize.ts +35 -0
  66. package/lib/utils/types.ts +12 -0
  67. package/package.json +28 -0
  68. package/torch-glare.js +24 -0
@@ -0,0 +1,464 @@
1
+ import DatePicker from "react-datepicker";
2
+ import "react-datepicker/dist/react-datepicker.css";
3
+ import { HTMLAttributes, InputHTMLAttributes, ReactNode, useEffect, useRef, useState } from "react";
4
+ import { getYear, getMonth, isSameDay } from "date-fns";
5
+ import { Button } from "./Button";
6
+ import { cn } from "../utils/cn";
7
+ import { cva } from "class-variance-authority";
8
+ import { Themes } from "../utils/types";
9
+
10
+ function range(start: number, end: number, step: number) {
11
+ return Array.from({ length: Math.ceil((end - start) / step) }, (_, i) => start + i * step);
12
+ }
13
+
14
+ interface PickerProps {
15
+ selected?: Date
16
+ placeholderText?: string
17
+ customInput?: any
18
+ onChange: any
19
+ dateFormat?: any
20
+ theme?: Themes
21
+ className?: string
22
+ [key: string]: any
23
+ }
24
+
25
+ export const Datepicker = ({ theme = "dark", onChange, className, dateFormat, customInput, placeholderText, selected, ...props }: PickerProps) => {
26
+
27
+ const [startDate, setStartDate] = useState<Date | any>(selected || new Date(Date.now()));
28
+ useEffect(() => {
29
+ onChange && onChange(startDate)
30
+ }, [])
31
+ return (
32
+ <div className={cn("w-full", className)} data-theme={theme} >
33
+ <DatePicker
34
+ {...props}
35
+ dateFormat={dateFormat}
36
+ customInput={customInput}
37
+ onChange={(date: any) => {
38
+ setStartDate(date)
39
+ onChange && onChange(date)
40
+ }}
41
+ wrapperClassName="w-full"
42
+ selected={startDate}
43
+ placeholderText={placeholderText}
44
+ weekDayClassName={() => "hidden"}
45
+ dayClassName={(date) => {
46
+ const isCurrentMonth = getMonth(date) === getMonth(startDate || new Date());
47
+ const isSelected = startDate && isSameDay(date, startDate);
48
+ return cn(
49
+ "w-[29px] h-[29px] bg-transparent rounded-[6px] border border-transparent !text-content-system-global-disabled text-[10px] leading-0 hover:border-border-system-action-secondary-hover hover:!bg-background-system-action-primary-hover",
50
+ {
51
+ "!bg-background-system-body-secondary !text-content-system-global-primary": isCurrentMonth,
52
+ "!border-border-system-action-secondary-hover !bg-background-system-action-secondary-hover hover:!bg-background-system-action-secondary-hover": isSelected,
53
+ }
54
+ );
55
+ }}
56
+ calendarClassName="custom-datepicker border-none bg-background-system-body-base rounded-[12px] shadow-[0px_0px_18px_0px_rgba(0,0,0,0.75)]"
57
+ renderCustomHeader={({
58
+ date,
59
+ changeYear,
60
+ changeMonth,
61
+ prevMonthButtonDisabled,
62
+ nextMonthButtonDisabled,
63
+ }) => <CustomDatePickerHeader
64
+ date={date}
65
+ changeMonth={changeMonth}
66
+ changeYear={changeYear}
67
+ prevMonthButtonDisabled={prevMonthButtonDisabled}
68
+ nextMonthButtonDisabled={nextMonthButtonDisabled}
69
+ onChange={onChange}
70
+ setStartDate={setStartDate}
71
+ />}
72
+ />
73
+
74
+ {/* Add a <style> tag to override the header styles */}
75
+ <style>
76
+ {`
77
+ .custom-datepicker {
78
+ background-color: var(--background-system-body-base) !important;
79
+ border: none !important;
80
+ }
81
+ .react-datepicker__day-names{
82
+ display:none !important;
83
+ }
84
+ .custom-datepicker .react-datepicker__header {
85
+ padding: 0 !important;
86
+ border: none !important;
87
+ background-color: transparent !important;
88
+ }
89
+
90
+ .react-datepicker__triangle{
91
+ fill:var(--background-system-body-base) !important;
92
+ color:var(--background-system-body-base) !important;
93
+ stroke:var(--background-system-body-base) !important;
94
+ }
95
+
96
+ `}
97
+ </style>
98
+ </div>
99
+ );
100
+ }
101
+
102
+
103
+
104
+ interface CustomDatePickerHeaderProps {
105
+ date: Date;
106
+ changeYear: (year: number) => void;
107
+ changeMonth: (month: number) => void;
108
+ prevMonthButtonDisabled: boolean;
109
+ nextMonthButtonDisabled: boolean;
110
+ onChange: (date: Date) => void;
111
+ setStartDate: any
112
+ }
113
+
114
+ export const CustomDatePickerHeader = ({
115
+ date,
116
+ changeYear,
117
+ changeMonth,
118
+ prevMonthButtonDisabled,
119
+ nextMonthButtonDisabled,
120
+ onChange,
121
+ setStartDate
122
+ }: CustomDatePickerHeaderProps) => {
123
+ const months = [
124
+ "January", "February", "March", "April", "May", "June",
125
+ "July", "August", "September", "October", "November", "December",
126
+ ];
127
+ const years = range(1900, getYear(new Date()) * 1.05, 1);
128
+
129
+ const setChangeMonth = (monthIndex: number) => {
130
+ const newDate = new Date(date);
131
+ newDate.setMonth(monthIndex);
132
+ onChange && onChange(newDate);
133
+ setStartDate(newDate); // Update the state
134
+ };
135
+
136
+ const setChangeYear = (year: number) => {
137
+ const newDate = new Date(date);
138
+ newDate.setFullYear(year);
139
+ onChange && onChange(newDate);
140
+ setStartDate(newDate); // Update the state
141
+ };
142
+
143
+ return (
144
+ <div dir="ltr" className="w-full flex justify-center items-center flex-col bg-background-system-body-base h-full px-[6px] pt-[6px] rounded-[12px]">
145
+ <div className="flex justify-between items-center flex-1 w-full">
146
+ <Button
147
+ variant={"PrimeStyle"}
148
+ className="hover:border-border-system-action-secondary-hover hover:!bg-background-system-action-primary-hover focus:!border-transparent"
149
+ buttonType={"icon"}
150
+ size={"M"}
151
+ onClick={() => {
152
+ const newDate = new Date(date);
153
+ if (newDate.getMonth() === 0) {
154
+ // If current month is January, go to December of the previous year
155
+ newDate.setFullYear(newDate.getFullYear() - 1);
156
+ newDate.setMonth(11); // December
157
+ } else {
158
+ // Otherwise, just decrease the month
159
+ newDate.setMonth(newDate.getMonth() - 1);
160
+ }
161
+ setStartDate(newDate);
162
+ changeMonth(newDate.getMonth());
163
+ changeYear(newDate.getFullYear());
164
+ setChangeMonth(newDate.getMonth())
165
+ }}
166
+ disabled={prevMonthButtonDisabled}
167
+ type="button"
168
+ >
169
+ <i className="ri-arrow-left-s-line"></i>
170
+ </Button>
171
+
172
+ <div className="flex gap-1 justify-center items-center">
173
+ <OptionsValue
174
+ inputClassName="w-[22px]"
175
+ value={months[getMonth(date)].substring(0, 3)}
176
+ options={months.map((month, i) => (
177
+ <OptionsItem
178
+ key={month}
179
+ selected={getMonth(date) === i}
180
+ onClick={() => {
181
+ changeMonth(months.indexOf(month));
182
+ setChangeMonth(months.indexOf(month));
183
+ }}
184
+ >
185
+ {`${month} - ${i + 1}`}
186
+ </OptionsItem>
187
+ ))}
188
+ />
189
+
190
+ <OptionsValue
191
+ value={getYear(date)}
192
+ options={years.map((year) => (
193
+ <OptionsItem
194
+ id={year.toString()}
195
+ selected={getYear(date) === year}
196
+ key={year}
197
+ onClick={() => {
198
+ changeYear(year);
199
+ setChangeYear(year);
200
+ }}
201
+ >
202
+ {year}
203
+ </OptionsItem>
204
+ ))}
205
+ />
206
+ </div>
207
+
208
+ <Button
209
+ type="button"
210
+ variant={"PrimeStyle"}
211
+ className="hover:border-border-system-action-secondary-hover hover:!bg-background-system-action-primary-hover focus:!border-transparent"
212
+ buttonType={"icon"}
213
+ size={"M"}
214
+ onClick={() => {
215
+ const newDate = new Date(date);
216
+ if (newDate.getMonth() === 11) {
217
+ // If current month is December, go to January of the next year
218
+ newDate.setFullYear(newDate.getFullYear() + 1);
219
+ newDate.setMonth(0); // January
220
+ } else {
221
+ // Otherwise, just increase the month
222
+ newDate.setMonth(newDate.getMonth() + 1);
223
+ }
224
+ setStartDate(newDate);
225
+ changeMonth(newDate.getMonth());
226
+ setChangeMonth(newDate.getMonth())
227
+ changeYear(newDate.getFullYear());
228
+ }}
229
+ disabled={nextMonthButtonDisabled}
230
+ >
231
+ <i className="ri-arrow-right-s-line"></i>
232
+ </Button>
233
+ </div>
234
+
235
+ <div className="flex justify-center items-center w-full gap-[19px] mt-[10px] [&>p]:text-content-presentation-global-highlight-darkback typography-body-small-medium">
236
+ {
237
+ ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((e) => {
238
+ return <p>{e}</p>
239
+
240
+ })
241
+ }
242
+ </div>
243
+ </div>
244
+ );
245
+ };
246
+
247
+
248
+ export const MenuItemStyles = cva(
249
+ [
250
+ "text-content-presentation-action-light-primary",
251
+ "outline-none",
252
+ "border",
253
+ "border-transparent",
254
+ "flex",
255
+ "gap-[8px]",
256
+ "items-center",
257
+ "justify-start",
258
+ "text-overflow",
259
+ "overflow-hidden",
260
+ "px-[12px]",
261
+ "rounded-[4px]",
262
+ "transition-all",
263
+ "ease-in-out",
264
+ "duration-300",
265
+ ],
266
+ {
267
+ variants: {
268
+ variant: {
269
+ SystemStyle: [
270
+ "bg-background-system-body-primary",
271
+ "text-content-system-global-primary",
272
+ "hover:!bg-background-system-action-secondary-hover",
273
+ "hover:!text-content-system-action-primary-hover",
274
+ "hover:!border-border-system-action-primary-hover",
275
+ "focus:bg-background-System-Action-Primary-Selected",
276
+ "focus:border-transparent",
277
+ "active:border-transparent",
278
+ "active:bg-background-System-Action-Primary-Selected",
279
+ "disabled:bg-background-system-body-secondary",
280
+ "disabled:text-content-system-global-disabled",
281
+ ],
282
+ },
283
+ size: {
284
+ S: ["typography-body-small-regular", "h-[24px]"],
285
+ M: ["typography-body-medium-regular", "h-[32px]"],
286
+ },
287
+
288
+ disabled: {
289
+ true: [
290
+ "text-content-presentation-state-disabled",
291
+ "bg-white-00",
292
+ ],
293
+ },
294
+
295
+ selected: {
296
+ true: [
297
+ "bg-background-presentation-action-selected",
298
+ "text-content-presentation-action-light-primary",
299
+ ],
300
+ },
301
+
302
+ defaultVariants: {
303
+ variant: "Default",
304
+ size: "M",
305
+ active: false,
306
+ disabled: false,
307
+ },
308
+ }
309
+ }
310
+ );
311
+ export const dropdownMenuStyles = cva(
312
+ [
313
+ "p-1",
314
+ "rounded-[8px]",
315
+ "border",
316
+ "max-h-[200px]",
317
+ "outline-none",
318
+ "overflow-scroll",
319
+ "data-[state=open]:animate-in",
320
+ "data-[state=closed]:animate-out",
321
+ "data-[state=closed]:fade-out-0",
322
+ "data-[state=open]:fade-in-0",
323
+ "overflow-x-hidden",
324
+ "scrollbar-hide",
325
+ ],
326
+ {
327
+ variants: {
328
+ variant: {
329
+ SystemStyle: [
330
+ "border-border-system-global-secondary",
331
+ "bg-background-system-body-primary",
332
+ "shadow-[0px_0px_18px_0px_rgba(0,0,0,0.75)]",
333
+ ]
334
+ },
335
+ defaultVariants: {
336
+ variant: "SystemStyle",
337
+ },
338
+ },
339
+ }
340
+ );
341
+
342
+
343
+
344
+ const OptionsDropDown = ({ className, ...props }: any) => {
345
+ return (
346
+ <a className={cn("absolute min-w-[100px] z-[20] top-[27px] left-0", dropdownMenuStyles({ variant: "SystemStyle" }), className)}>
347
+ {props.children}
348
+ </a>
349
+ )
350
+ }
351
+
352
+ interface OptionsItemProps
353
+ extends HTMLAttributes<HTMLLIElement> {
354
+ selected: boolean
355
+ }
356
+
357
+ const OptionsItem = ({ selected, ...props }: OptionsItemProps) => {
358
+
359
+ const ref = useRef<HTMLLIElement>(null);
360
+
361
+ // Scroll to the selected item when the dropdown is opened
362
+ useEffect(() => {
363
+ if (selected && ref.current) {
364
+ ref.current.scrollIntoView({ behavior: "auto", block: "center" });
365
+ }
366
+ }, [selected]);
367
+
368
+ return (
369
+ <li {...props} ref={ref} className={cn(" whitespace-nowrap", MenuItemStyles({ variant: "SystemStyle", selected: selected, size: "S" }))}>
370
+ {props.children}
371
+ </li>
372
+ )
373
+ }
374
+
375
+ interface OptionsValueProps
376
+ extends InputHTMLAttributes<HTMLInputElement> {
377
+ options: ReactNode
378
+ inputClassName?: string
379
+ }
380
+
381
+ const OptionsValue = ({ inputClassName, options, ...props }: OptionsValueProps) => {
382
+ const [active, setActive] = useState(false);
383
+ const sectionRef = useRef<HTMLDivElement>(null);
384
+
385
+ useEffect(() => {
386
+ const handleOutsideClick = (event: MouseEvent) => {
387
+ if (
388
+ sectionRef.current &&
389
+ !sectionRef.current.contains(event.target as Node)
390
+ ) {
391
+ setActive(false);
392
+ } else {
393
+ setActive(true);
394
+ }
395
+ };
396
+
397
+ document.addEventListener("mousedown", handleOutsideClick);
398
+ document.addEventListener("pointerdown", handleOutsideClick);
399
+ return () => {
400
+ document.removeEventListener("mousedown", handleOutsideClick);
401
+ document.removeEventListener("pointerdown", handleOutsideClick);
402
+ };
403
+ }, []);
404
+ return (
405
+ <div
406
+ ref={sectionRef}
407
+ className={cn([
408
+ "relative flex justify-between items-center",
409
+ "bg-black-alpha-20",
410
+ "text-white",
411
+ "border-[#2C2D2E]",
412
+ "hover:border-[#9748FF]",
413
+ "hover:bg-purple-alpha-10",
414
+ "typography-body-small-regular leading-0",
415
+ "border",
416
+ "transition-all duration-200 ease-in-out",
417
+ "h-[26px]",
418
+ "w-fit",
419
+ "rounded-[6px]",
420
+ "outline-none",
421
+ "pl-[8px]",
422
+ ])}>
423
+ <input {...props} className={cn([
424
+ "bg-transparent",
425
+ "text-white",
426
+ "h-[24px]",
427
+ "border-none",
428
+ "max-w-[30px]",
429
+ "outline-none",
430
+ "typography-body-small-regular leading-0",
431
+ ], inputClassName)} {...props} readOnly />
432
+ <i className="ri-arrow-down-s-fill text-[12px] text-[#9748FF] px-1"></i>
433
+ {
434
+ options && active &&
435
+ <OptionsDropDown >
436
+ {options}
437
+ </OptionsDropDown>
438
+ }
439
+ </div>
440
+ )
441
+ }
442
+
443
+
444
+ // using with react-hook-form
445
+ /*
446
+ <form onSubmit={handleSubmit(onSubmit)}>
447
+ <Controller
448
+ name="dateOfBirth"
449
+ control={control}
450
+ render={() => (
451
+ <Datepicker
452
+ customInput={<InputField />}
453
+ placeholderText="Select date"
454
+ onChange={(e: any) => {
455
+ setValue("dateOfBirth", e, {
456
+ shouldDirty: true
457
+ });
458
+ }}
459
+ />
460
+ )}
461
+ />
462
+ <button>submit</button>
463
+ </form>
464
+ */
@@ -0,0 +1,118 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { Drawer as DrawerPrimitive } from "vaul"
5
+
6
+ import { cn } from "../utils/cn"
7
+
8
+ const Drawer = ({
9
+ shouldScaleBackground = true,
10
+ ...props
11
+ }: React.ComponentProps<typeof DrawerPrimitive.Root>) => (
12
+ <DrawerPrimitive.Root
13
+ shouldScaleBackground={shouldScaleBackground}
14
+ {...props}
15
+ />
16
+ )
17
+ Drawer.displayName = "Drawer"
18
+
19
+ const DrawerTrigger = DrawerPrimitive.Trigger
20
+
21
+ const DrawerPortal = DrawerPrimitive.Portal
22
+
23
+ const DrawerClose = DrawerPrimitive.Close
24
+
25
+ const DrawerOverlay = React.forwardRef<
26
+ React.ElementRef<typeof DrawerPrimitive.Overlay>,
27
+ React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Overlay>
28
+ >(({ className, ...props }, ref) => (
29
+ <DrawerPrimitive.Overlay
30
+ ref={ref}
31
+ className={cn("fixed inset-0 z-50 bg-black/80", className)}
32
+ {...props}
33
+ />
34
+ ))
35
+ DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName
36
+
37
+ const DrawerContent = React.forwardRef<
38
+ React.ElementRef<typeof DrawerPrimitive.Content>,
39
+ React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Content>
40
+ >(({ className, children, ...props }, ref) => (
41
+ <DrawerPortal>
42
+ <DrawerOverlay />
43
+ <DrawerPrimitive.Content
44
+ ref={ref}
45
+ className={cn(
46
+ "fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] bg-background-system-body-primary m-1 border-border-system-global-primary",
47
+ className
48
+ )}
49
+ {...props}
50
+ >
51
+ <div className="mx-auto mt-4 h-2 w-[100px] rounded-full bg-muted" />
52
+ {children}
53
+ </DrawerPrimitive.Content>
54
+ </DrawerPortal>
55
+ ))
56
+ DrawerContent.displayName = "DrawerContent"
57
+
58
+ const DrawerHeader = ({
59
+ className,
60
+ ...props
61
+ }: React.HTMLAttributes<HTMLDivElement>) => (
62
+ <div
63
+ className={cn("grid gap-1.5 p-4 text-center sm:text-left", className)}
64
+ {...props}
65
+ />
66
+ )
67
+ DrawerHeader.displayName = "DrawerHeader"
68
+
69
+ const DrawerFooter = ({
70
+ className,
71
+ ...props
72
+ }: React.HTMLAttributes<HTMLDivElement>) => (
73
+ <div
74
+ className={cn("mt-auto flex flex-col gap-2 p-4", className)}
75
+ {...props}
76
+ />
77
+ )
78
+ DrawerFooter.displayName = "DrawerFooter"
79
+
80
+ const DrawerTitle = React.forwardRef<
81
+ React.ElementRef<typeof DrawerPrimitive.Title>,
82
+ React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Title>
83
+ >(({ className, ...props }, ref) => (
84
+ <DrawerPrimitive.Title
85
+ ref={ref}
86
+ className={cn(
87
+ "text-lg font-semibold leading-none tracking-tight",
88
+ className
89
+ )}
90
+ {...props}
91
+ />
92
+ ))
93
+ DrawerTitle.displayName = DrawerPrimitive.Title.displayName
94
+
95
+ const DrawerDescription = React.forwardRef<
96
+ React.ElementRef<typeof DrawerPrimitive.Description>,
97
+ React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Description>
98
+ >(({ className, ...props }, ref) => (
99
+ <DrawerPrimitive.Description
100
+ ref={ref}
101
+ className={cn("text-sm text-muted-foreground", className)}
102
+ {...props}
103
+ />
104
+ ))
105
+ DrawerDescription.displayName = DrawerPrimitive.Description.displayName
106
+
107
+ export {
108
+ Drawer,
109
+ DrawerPortal,
110
+ DrawerOverlay,
111
+ DrawerTrigger,
112
+ DrawerClose,
113
+ DrawerContent,
114
+ DrawerHeader,
115
+ DrawerFooter,
116
+ DrawerTitle,
117
+ DrawerDescription,
118
+ }