@tuturuuu/ui 0.0.4

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 (104) hide show
  1. package/.checksum +1 -0
  2. package/README.md +46 -0
  3. package/components.json +20 -0
  4. package/eslint.config.mjs +20 -0
  5. package/jsr.json +10 -0
  6. package/package.json +120 -0
  7. package/postcss.config.mjs +8 -0
  8. package/rollup.config.js +40 -0
  9. package/src/components/ui/accordion.tsx +70 -0
  10. package/src/components/ui/alert-dialog.tsx +156 -0
  11. package/src/components/ui/alert.tsx +58 -0
  12. package/src/components/ui/aspect-ratio.tsx +11 -0
  13. package/src/components/ui/avatar.tsx +52 -0
  14. package/src/components/ui/badge.tsx +49 -0
  15. package/src/components/ui/breadcrumb.tsx +108 -0
  16. package/src/components/ui/button.tsx +61 -0
  17. package/src/components/ui/calendar.tsx +212 -0
  18. package/src/components/ui/card.tsx +74 -0
  19. package/src/components/ui/carousel.tsx +240 -0
  20. package/src/components/ui/chart.tsx +365 -0
  21. package/src/components/ui/checkbox.tsx +31 -0
  22. package/src/components/ui/codeblock.tsx +161 -0
  23. package/src/components/ui/collapsible.tsx +33 -0
  24. package/src/components/ui/color-picker.tsx +143 -0
  25. package/src/components/ui/command.tsx +176 -0
  26. package/src/components/ui/context-menu.tsx +251 -0
  27. package/src/components/ui/custom/autosize-textarea.tsx +111 -0
  28. package/src/components/ui/custom/calendar/core.tsx +61 -0
  29. package/src/components/ui/custom/calendar/day-cell.tsx +74 -0
  30. package/src/components/ui/custom/calendar/month-header.tsx +59 -0
  31. package/src/components/ui/custom/calendar/month-view.tsx +110 -0
  32. package/src/components/ui/custom/calendar/utils.ts +76 -0
  33. package/src/components/ui/custom/calendar/year-calendar.tsx +64 -0
  34. package/src/components/ui/custom/calendar/year-view.tsx +58 -0
  35. package/src/components/ui/custom/combobox.tsx +197 -0
  36. package/src/components/ui/custom/common-footer.tsx +215 -0
  37. package/src/components/ui/custom/compared-date-range-picker.tsx +561 -0
  38. package/src/components/ui/custom/date-input.tsx +279 -0
  39. package/src/components/ui/custom/empty-card.tsx +39 -0
  40. package/src/components/ui/custom/feature-summary.tsx +135 -0
  41. package/src/components/ui/custom/file-uploader.tsx +349 -0
  42. package/src/components/ui/custom/input-field.tsx +29 -0
  43. package/src/components/ui/custom/loading-indicator.tsx +28 -0
  44. package/src/components/ui/custom/modifiable-dialog-trigger.tsx +83 -0
  45. package/src/components/ui/custom/month-picker.tsx +157 -0
  46. package/src/components/ui/custom/report-preview.tsx +175 -0
  47. package/src/components/ui/custom/search-bar.tsx +56 -0
  48. package/src/components/ui/custom/select-field.tsx +78 -0
  49. package/src/components/ui/custom/tables/data-table-column-header.tsx +72 -0
  50. package/src/components/ui/custom/tables/data-table-create-button.tsx +31 -0
  51. package/src/components/ui/custom/tables/data-table-faceted-filter.tsx +142 -0
  52. package/src/components/ui/custom/tables/data-table-pagination.tsx +243 -0
  53. package/src/components/ui/custom/tables/data-table-refresh-button.tsx +45 -0
  54. package/src/components/ui/custom/tables/data-table-toolbar.tsx +133 -0
  55. package/src/components/ui/custom/tables/data-table-view-options.tsx +112 -0
  56. package/src/components/ui/custom/tables/data-table.tsx +228 -0
  57. package/src/components/ui/custom/uploaded-files-card.tsx +50 -0
  58. package/src/components/ui/dialog.tsx +137 -0
  59. package/src/components/ui/drawer.tsx +131 -0
  60. package/src/components/ui/dropdown-menu.tsx +256 -0
  61. package/src/components/ui/form.tsx +167 -0
  62. package/src/components/ui/hover-card.tsx +41 -0
  63. package/src/components/ui/icons.tsx +506 -0
  64. package/src/components/ui/input-otp.tsx +78 -0
  65. package/src/components/ui/input.tsx +18 -0
  66. package/src/components/ui/label.tsx +23 -0
  67. package/src/components/ui/markdown.tsx +7 -0
  68. package/src/components/ui/menubar.tsx +275 -0
  69. package/src/components/ui/navigation-menu.tsx +169 -0
  70. package/src/components/ui/pagination.tsx +126 -0
  71. package/src/components/ui/popover.tsx +47 -0
  72. package/src/components/ui/progress.tsx +30 -0
  73. package/src/components/ui/radio-group.tsx +44 -0
  74. package/src/components/ui/resizable.tsx +55 -0
  75. package/src/components/ui/scroll-area.tsx +57 -0
  76. package/src/components/ui/select.tsx +180 -0
  77. package/src/components/ui/separator.tsx +27 -0
  78. package/src/components/ui/sheet.tsx +138 -0
  79. package/src/components/ui/sidebar.tsx +734 -0
  80. package/src/components/ui/skeleton.tsx +13 -0
  81. package/src/components/ui/slider.tsx +62 -0
  82. package/src/components/ui/sonner.tsx +29 -0
  83. package/src/components/ui/switch.tsx +30 -0
  84. package/src/components/ui/table.tsx +112 -0
  85. package/src/components/ui/tabs.tsx +68 -0
  86. package/src/components/ui/tag-input.tsx +141 -0
  87. package/src/components/ui/textarea.tsx +17 -0
  88. package/src/components/ui/time-picker-input.tsx +117 -0
  89. package/src/components/ui/time-picker-utils.tsx +146 -0
  90. package/src/components/ui/toast.tsx +128 -0
  91. package/src/components/ui/toaster.tsx +35 -0
  92. package/src/components/ui/toggle-group.tsx +72 -0
  93. package/src/components/ui/toggle.tsx +46 -0
  94. package/src/components/ui/tooltip.tsx +60 -0
  95. package/src/globals.css +252 -0
  96. package/src/hooks/use-callback-ref.ts +28 -0
  97. package/src/hooks/use-controllable-state.ts +68 -0
  98. package/src/hooks/use-copy-to-clipboard.ts +46 -0
  99. package/src/hooks/use-form.ts +23 -0
  100. package/src/hooks/use-forwarded-ref.ts +17 -0
  101. package/src/hooks/use-mobile.tsx +21 -0
  102. package/src/hooks/use-toast.ts +191 -0
  103. package/src/resolvers.ts +3 -0
  104. package/tsconfig.json +17 -0
@@ -0,0 +1,55 @@
1
+ 'use client';
2
+
3
+ import { cn } from '@tuturuuu/utils/format';
4
+ import { GripVerticalIcon } from 'lucide-react';
5
+ import * as React from 'react';
6
+ import * as ResizablePrimitive from 'react-resizable-panels';
7
+
8
+ function ResizablePanelGroup({
9
+ className,
10
+ ...props
11
+ }: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) {
12
+ return (
13
+ <ResizablePrimitive.PanelGroup
14
+ data-slot="resizable-panel-group"
15
+ className={cn(
16
+ 'flex h-full w-full data-[panel-group-direction=vertical]:flex-col',
17
+ className
18
+ )}
19
+ {...props}
20
+ />
21
+ );
22
+ }
23
+
24
+ function ResizablePanel({
25
+ ...props
26
+ }: React.ComponentProps<typeof ResizablePrimitive.Panel>) {
27
+ return <ResizablePrimitive.Panel data-slot="resizable-panel" {...props} />;
28
+ }
29
+
30
+ function ResizableHandle({
31
+ withHandle,
32
+ className,
33
+ ...props
34
+ }: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {
35
+ withHandle?: boolean;
36
+ }) {
37
+ return (
38
+ <ResizablePrimitive.PanelResizeHandle
39
+ data-slot="resizable-handle"
40
+ className={cn(
41
+ 'relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:outline-hidden data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:translate-x-0 data-[panel-group-direction=vertical]:after:-translate-y-1/2 [&[data-panel-group-direction=vertical]>div]:rotate-90',
42
+ className
43
+ )}
44
+ {...props}
45
+ >
46
+ {withHandle && (
47
+ <div className="z-10 flex h-4 w-3 items-center justify-center rounded-xs border bg-border">
48
+ <GripVerticalIcon className="size-2.5" />
49
+ </div>
50
+ )}
51
+ </ResizablePrimitive.PanelResizeHandle>
52
+ );
53
+ }
54
+
55
+ export { ResizableHandle, ResizablePanel, ResizablePanelGroup };
@@ -0,0 +1,57 @@
1
+ 'use client';
2
+
3
+ import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
4
+ import { cn } from '@tuturuuu/utils/format';
5
+ import * as React from 'react';
6
+
7
+ function ScrollArea({
8
+ className,
9
+ children,
10
+ ...props
11
+ }: React.ComponentProps<typeof ScrollAreaPrimitive.Root>) {
12
+ return (
13
+ <ScrollAreaPrimitive.Root
14
+ data-slot="scroll-area"
15
+ className={cn('relative', className)}
16
+ {...props}
17
+ >
18
+ <ScrollAreaPrimitive.Viewport
19
+ data-slot="scroll-area-viewport"
20
+ className="size-full rounded-[inherit] ring-ring/10 outline-ring/50 transition-[color,box-shadow] focus-visible:ring-4 focus-visible:outline-1 dark:ring-ring/20 dark:outline-ring/40"
21
+ >
22
+ {children}
23
+ </ScrollAreaPrimitive.Viewport>
24
+ <ScrollBar />
25
+ <ScrollAreaPrimitive.Corner />
26
+ </ScrollAreaPrimitive.Root>
27
+ );
28
+ }
29
+
30
+ function ScrollBar({
31
+ className,
32
+ orientation = 'vertical',
33
+ ...props
34
+ }: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>) {
35
+ return (
36
+ <ScrollAreaPrimitive.ScrollAreaScrollbar
37
+ data-slot="scroll-area-scrollbar"
38
+ orientation={orientation}
39
+ className={cn(
40
+ 'flex touch-none p-px transition-colors select-none',
41
+ orientation === 'vertical' &&
42
+ 'h-full w-2.5 border-l border-l-transparent',
43
+ orientation === 'horizontal' &&
44
+ 'h-2.5 flex-col border-t border-t-transparent',
45
+ className
46
+ )}
47
+ {...props}
48
+ >
49
+ <ScrollAreaPrimitive.ScrollAreaThumb
50
+ data-slot="scroll-area-thumb"
51
+ className="relative flex-1 rounded-full bg-border"
52
+ />
53
+ </ScrollAreaPrimitive.ScrollAreaScrollbar>
54
+ );
55
+ }
56
+
57
+ export { ScrollArea, ScrollBar };
@@ -0,0 +1,180 @@
1
+ 'use client';
2
+
3
+ import * as SelectPrimitive from '@radix-ui/react-select';
4
+ import { cn } from '@tuturuuu/utils/format';
5
+ import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from 'lucide-react';
6
+ import * as React from 'react';
7
+
8
+ function Select({
9
+ ...props
10
+ }: React.ComponentProps<typeof SelectPrimitive.Root>) {
11
+ return <SelectPrimitive.Root data-slot="select" {...props} />;
12
+ }
13
+
14
+ function SelectGroup({
15
+ ...props
16
+ }: React.ComponentProps<typeof SelectPrimitive.Group>) {
17
+ return <SelectPrimitive.Group data-slot="select-group" {...props} />;
18
+ }
19
+
20
+ function SelectValue({
21
+ ...props
22
+ }: React.ComponentProps<typeof SelectPrimitive.Value>) {
23
+ return <SelectPrimitive.Value data-slot="select-value" {...props} />;
24
+ }
25
+
26
+ function SelectTrigger({
27
+ className,
28
+ children,
29
+ ...props
30
+ }: React.ComponentProps<typeof SelectPrimitive.Trigger>) {
31
+ return (
32
+ <SelectPrimitive.Trigger
33
+ data-slot="select-trigger"
34
+ className={cn(
35
+ "flex h-9 w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-xs ring-ring/10 outline-ring/50 transition-[color,box-shadow] focus-visible:ring-4 focus-visible:outline-1 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:focus-visible:ring-0 data-[placeholder]:text-muted-foreground *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 dark:ring-ring/20 dark:outline-ring/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground [&>span]:line-clamp-1",
36
+ className
37
+ )}
38
+ {...props}
39
+ >
40
+ {children}
41
+ <SelectPrimitive.Icon asChild>
42
+ <ChevronDownIcon className="size-4 opacity-50" />
43
+ </SelectPrimitive.Icon>
44
+ </SelectPrimitive.Trigger>
45
+ );
46
+ }
47
+
48
+ function SelectContent({
49
+ className,
50
+ children,
51
+ position = 'popper',
52
+ ...props
53
+ }: React.ComponentProps<typeof SelectPrimitive.Content>) {
54
+ return (
55
+ <SelectPrimitive.Portal>
56
+ <SelectPrimitive.Content
57
+ data-slot="select-content"
58
+ className={cn(
59
+ 'relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95',
60
+ position === 'popper' &&
61
+ 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
62
+ className
63
+ )}
64
+ position={position}
65
+ {...props}
66
+ >
67
+ <SelectScrollUpButton />
68
+ <SelectPrimitive.Viewport
69
+ className={cn(
70
+ 'p-1',
71
+ position === 'popper' &&
72
+ 'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1'
73
+ )}
74
+ >
75
+ {children}
76
+ </SelectPrimitive.Viewport>
77
+ <SelectScrollDownButton />
78
+ </SelectPrimitive.Content>
79
+ </SelectPrimitive.Portal>
80
+ );
81
+ }
82
+
83
+ function SelectLabel({
84
+ className,
85
+ ...props
86
+ }: React.ComponentProps<typeof SelectPrimitive.Label>) {
87
+ return (
88
+ <SelectPrimitive.Label
89
+ data-slot="select-label"
90
+ className={cn('px-2 py-1.5 text-sm font-semibold', className)}
91
+ {...props}
92
+ />
93
+ );
94
+ }
95
+
96
+ function SelectItem({
97
+ className,
98
+ children,
99
+ ...props
100
+ }: React.ComponentProps<typeof SelectPrimitive.Item>) {
101
+ return (
102
+ <SelectPrimitive.Item
103
+ data-slot="select-item"
104
+ className={cn(
105
+ "relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
106
+ className
107
+ )}
108
+ {...props}
109
+ >
110
+ <span className="absolute right-2 flex size-3.5 items-center justify-center">
111
+ <SelectPrimitive.ItemIndicator>
112
+ <CheckIcon className="size-4" />
113
+ </SelectPrimitive.ItemIndicator>
114
+ </span>
115
+ <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
116
+ </SelectPrimitive.Item>
117
+ );
118
+ }
119
+
120
+ function SelectSeparator({
121
+ className,
122
+ ...props
123
+ }: React.ComponentProps<typeof SelectPrimitive.Separator>) {
124
+ return (
125
+ <SelectPrimitive.Separator
126
+ data-slot="select-separator"
127
+ className={cn('pointer-events-none -mx-1 my-1 h-px bg-border', className)}
128
+ {...props}
129
+ />
130
+ );
131
+ }
132
+
133
+ function SelectScrollUpButton({
134
+ className,
135
+ ...props
136
+ }: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {
137
+ return (
138
+ <SelectPrimitive.ScrollUpButton
139
+ data-slot="select-scroll-up-button"
140
+ className={cn(
141
+ 'flex cursor-default items-center justify-center py-1',
142
+ className
143
+ )}
144
+ {...props}
145
+ >
146
+ <ChevronUpIcon className="size-4" />
147
+ </SelectPrimitive.ScrollUpButton>
148
+ );
149
+ }
150
+
151
+ function SelectScrollDownButton({
152
+ className,
153
+ ...props
154
+ }: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {
155
+ return (
156
+ <SelectPrimitive.ScrollDownButton
157
+ data-slot="select-scroll-down-button"
158
+ className={cn(
159
+ 'flex cursor-default items-center justify-center py-1',
160
+ className
161
+ )}
162
+ {...props}
163
+ >
164
+ <ChevronDownIcon className="size-4" />
165
+ </SelectPrimitive.ScrollDownButton>
166
+ );
167
+ }
168
+
169
+ export {
170
+ Select,
171
+ SelectContent,
172
+ SelectGroup,
173
+ SelectItem,
174
+ SelectLabel,
175
+ SelectScrollDownButton,
176
+ SelectScrollUpButton,
177
+ SelectSeparator,
178
+ SelectTrigger,
179
+ SelectValue,
180
+ };
@@ -0,0 +1,27 @@
1
+ 'use client';
2
+
3
+ import * as SeparatorPrimitive from '@radix-ui/react-separator';
4
+ import { cn } from '@tuturuuu/utils/format';
5
+ import * as React from 'react';
6
+
7
+ function Separator({
8
+ className,
9
+ orientation = 'horizontal',
10
+ decorative = true,
11
+ ...props
12
+ }: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
13
+ return (
14
+ <SeparatorPrimitive.Root
15
+ data-slot="separator-root"
16
+ decorative={decorative}
17
+ orientation={orientation}
18
+ className={cn(
19
+ 'shrink-0 bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px',
20
+ className
21
+ )}
22
+ {...props}
23
+ />
24
+ );
25
+ }
26
+
27
+ export { Separator };
@@ -0,0 +1,138 @@
1
+ 'use client';
2
+
3
+ import * as SheetPrimitive from '@radix-ui/react-dialog';
4
+ import { cn } from '@tuturuuu/utils/format';
5
+ import { XIcon } from 'lucide-react';
6
+ import * as React from 'react';
7
+
8
+ function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
9
+ return <SheetPrimitive.Root data-slot="sheet" {...props} />;
10
+ }
11
+
12
+ function SheetTrigger({
13
+ ...props
14
+ }: React.ComponentProps<typeof SheetPrimitive.Trigger>) {
15
+ return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />;
16
+ }
17
+
18
+ function SheetClose({
19
+ ...props
20
+ }: React.ComponentProps<typeof SheetPrimitive.Close>) {
21
+ return <SheetPrimitive.Close data-slot="sheet-close" {...props} />;
22
+ }
23
+
24
+ function SheetPortal({
25
+ ...props
26
+ }: React.ComponentProps<typeof SheetPrimitive.Portal>) {
27
+ return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />;
28
+ }
29
+
30
+ function SheetOverlay({
31
+ className,
32
+ ...props
33
+ }: React.ComponentProps<typeof SheetPrimitive.Overlay>) {
34
+ return (
35
+ <SheetPrimitive.Overlay
36
+ data-slot="sheet-overlay"
37
+ className={cn(
38
+ 'fixed inset-0 z-50 bg-black/80 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0',
39
+ className
40
+ )}
41
+ {...props}
42
+ />
43
+ );
44
+ }
45
+
46
+ function SheetContent({
47
+ className,
48
+ children,
49
+ side = 'right',
50
+ ...props
51
+ }: React.ComponentProps<typeof SheetPrimitive.Content> & {
52
+ side?: 'top' | 'right' | 'bottom' | 'left';
53
+ }) {
54
+ return (
55
+ <SheetPortal>
56
+ <SheetOverlay />
57
+ <SheetPrimitive.Content
58
+ data-slot="sheet-content"
59
+ className={cn(
60
+ 'fixed z-50 flex flex-col gap-4 bg-background shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=closed]:animate-out data-[state=open]:duration-500 data-[state=open]:animate-in',
61
+ side === 'right' &&
62
+ 'inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm',
63
+ side === 'left' &&
64
+ 'inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm',
65
+ side === 'top' &&
66
+ 'inset-x-0 top-0 h-auto border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top',
67
+ side === 'bottom' &&
68
+ 'inset-x-0 bottom-0 h-auto border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom',
69
+ className
70
+ )}
71
+ {...props}
72
+ >
73
+ {children}
74
+ <SheetPrimitive.Close 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-secondary">
75
+ <XIcon className="size-4" />
76
+ <span className="sr-only">Close</span>
77
+ </SheetPrimitive.Close>
78
+ </SheetPrimitive.Content>
79
+ </SheetPortal>
80
+ );
81
+ }
82
+
83
+ function SheetHeader({ className, ...props }: React.ComponentProps<'div'>) {
84
+ return (
85
+ <div
86
+ data-slot="sheet-header"
87
+ className={cn('flex flex-col gap-1.5 p-4', className)}
88
+ {...props}
89
+ />
90
+ );
91
+ }
92
+
93
+ function SheetFooter({ className, ...props }: React.ComponentProps<'div'>) {
94
+ return (
95
+ <div
96
+ data-slot="sheet-footer"
97
+ className={cn('mt-auto flex flex-col gap-2 p-4', className)}
98
+ {...props}
99
+ />
100
+ );
101
+ }
102
+
103
+ function SheetTitle({
104
+ className,
105
+ ...props
106
+ }: React.ComponentProps<typeof SheetPrimitive.Title>) {
107
+ return (
108
+ <SheetPrimitive.Title
109
+ data-slot="sheet-title"
110
+ className={cn('font-semibold tracking-tight text-foreground', className)}
111
+ {...props}
112
+ />
113
+ );
114
+ }
115
+
116
+ function SheetDescription({
117
+ className,
118
+ ...props
119
+ }: React.ComponentProps<typeof SheetPrimitive.Description>) {
120
+ return (
121
+ <SheetPrimitive.Description
122
+ data-slot="sheet-description"
123
+ className={cn('text-sm text-muted-foreground', className)}
124
+ {...props}
125
+ />
126
+ );
127
+ }
128
+
129
+ export {
130
+ Sheet,
131
+ SheetClose,
132
+ SheetContent,
133
+ SheetDescription,
134
+ SheetFooter,
135
+ SheetHeader,
136
+ SheetTitle,
137
+ SheetTrigger,
138
+ };