create-kuckit-app 0.2.0 → 0.3.0
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.
- package/package.json +1 -1
- package/templates/base/AGENTS.md +203 -0
- package/templates/base/apps/server/AGENTS.md +64 -8
- package/templates/base/apps/web/AGENTS.md +82 -8
- package/templates/base/apps/web/src/components/KuckitModuleRoute.tsx +119 -0
- package/templates/base/apps/web/src/components/dashboard/app-sidebar.tsx +120 -0
- package/templates/base/apps/web/src/components/dashboard/dashboard-layout.tsx +46 -0
- package/templates/base/apps/web/src/components/dashboard/dashboard-overview.tsx +24 -0
- package/templates/base/apps/web/src/components/dashboard/index.ts +2 -0
- package/templates/base/apps/web/src/components/dashboard/nav-user.tsx +77 -0
- package/templates/base/apps/web/src/components/ui/avatar.tsx +39 -0
- package/templates/base/apps/web/src/components/ui/breadcrumb.tsx +102 -0
- package/templates/base/apps/web/src/components/ui/collapsible.tsx +21 -0
- package/templates/base/apps/web/src/components/ui/separator.tsx +26 -0
- package/templates/base/apps/web/src/components/ui/sheet.tsx +130 -0
- package/templates/base/apps/web/src/components/ui/sidebar.tsx +694 -0
- package/templates/base/apps/web/src/components/ui/skeleton.tsx +13 -0
- package/templates/base/apps/web/src/components/ui/tooltip.tsx +55 -0
- package/templates/base/apps/web/src/hooks/use-mobile.ts +19 -0
- package/templates/base/apps/web/src/lib/utils.ts +6 -0
- package/templates/base/apps/web/src/modules.client.ts +4 -3
- package/templates/base/apps/web/src/providers/KuckitProvider.tsx +1 -25
- package/templates/base/apps/web/src/routes/$.tsx +14 -0
- package/templates/base/apps/web/src/routes/dashboard/$.tsx +9 -0
- package/templates/base/apps/web/src/routes/dashboard/index.tsx +6 -0
- package/templates/base/apps/web/src/routes/dashboard.tsx +25 -0
- package/templates/base/apps/web/tsconfig.json +5 -1
- package/templates/base/apps/web/vite.config.ts +6 -0
- package/templates/base/packages/api/AGENTS.md +44 -5
- package/templates/base/packages/auth/AGENTS.md +17 -1
- package/templates/base/packages/db/AGENTS.md +16 -1
- package/templates/base/packages/items-module/AGENTS.md +99 -1
- package/templates/base/packages/items-module/src/ui/ItemsPage.tsx +50 -68
- package/templates/base/apps/web/src/lib/kuckit-router.ts +0 -42
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { useServices } from '@/providers/ServicesProvider'
|
|
2
|
+
|
|
3
|
+
export function DashboardOverview() {
|
|
4
|
+
const { authClient } = useServices()
|
|
5
|
+
const { data: session } = authClient.useSession()
|
|
6
|
+
|
|
7
|
+
return (
|
|
8
|
+
<div className="space-y-6">
|
|
9
|
+
<div>
|
|
10
|
+
<h1 className="text-3xl font-bold tracking-tight">Dashboard</h1>
|
|
11
|
+
<p className="text-muted-foreground">Welcome back, {session?.user?.name || 'User'}</p>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
|
15
|
+
<div className="rounded-lg border bg-card p-6">
|
|
16
|
+
<h3 className="font-semibold">Getting Started</h3>
|
|
17
|
+
<p className="text-sm text-muted-foreground">
|
|
18
|
+
Your Kuckit application is ready. Start building!
|
|
19
|
+
</p>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { ChevronsUpDown, LogOut, User } from 'lucide-react'
|
|
2
|
+
import { useNavigate } from '@tanstack/react-router'
|
|
3
|
+
import { useServices } from '@/providers/ServicesProvider'
|
|
4
|
+
import {
|
|
5
|
+
DropdownMenu,
|
|
6
|
+
DropdownMenuContent,
|
|
7
|
+
DropdownMenuItem,
|
|
8
|
+
DropdownMenuSeparator,
|
|
9
|
+
DropdownMenuTrigger,
|
|
10
|
+
} from '@/components/ui/dropdown-menu'
|
|
11
|
+
import {
|
|
12
|
+
SidebarMenu,
|
|
13
|
+
SidebarMenuButton,
|
|
14
|
+
SidebarMenuItem,
|
|
15
|
+
useSidebar,
|
|
16
|
+
} from '@/components/ui/sidebar'
|
|
17
|
+
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
|
|
18
|
+
|
|
19
|
+
export function NavUser() {
|
|
20
|
+
const { isMobile } = useSidebar()
|
|
21
|
+
const navigate = useNavigate()
|
|
22
|
+
const { authClient } = useServices()
|
|
23
|
+
const { data: session } = authClient.useSession()
|
|
24
|
+
|
|
25
|
+
const user = session?.user
|
|
26
|
+
const initials =
|
|
27
|
+
user?.name
|
|
28
|
+
?.split(' ')
|
|
29
|
+
.map((n) => n[0])
|
|
30
|
+
.join('')
|
|
31
|
+
.toUpperCase() || 'U'
|
|
32
|
+
|
|
33
|
+
const handleLogout = async () => {
|
|
34
|
+
await authClient.signOut()
|
|
35
|
+
navigate({ to: '/' })
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<SidebarMenu>
|
|
40
|
+
<SidebarMenuItem>
|
|
41
|
+
<DropdownMenu>
|
|
42
|
+
<DropdownMenuTrigger asChild>
|
|
43
|
+
<SidebarMenuButton size="lg" className="data-[state=open]:bg-sidebar-accent">
|
|
44
|
+
<Avatar className="h-8 w-8 rounded-lg">
|
|
45
|
+
<AvatarImage src={user?.image || undefined} alt={user?.name || ''} />
|
|
46
|
+
<AvatarFallback className="rounded-lg bg-gradient-to-br from-primary to-primary/80 text-primary-foreground">
|
|
47
|
+
{initials}
|
|
48
|
+
</AvatarFallback>
|
|
49
|
+
</Avatar>
|
|
50
|
+
<div className="grid flex-1 text-left text-sm leading-tight">
|
|
51
|
+
<span className="truncate font-semibold">{user?.name || 'User'}</span>
|
|
52
|
+
<span className="truncate text-xs text-muted-foreground">{user?.email || ''}</span>
|
|
53
|
+
</div>
|
|
54
|
+
<ChevronsUpDown className="ml-auto size-4" />
|
|
55
|
+
</SidebarMenuButton>
|
|
56
|
+
</DropdownMenuTrigger>
|
|
57
|
+
<DropdownMenuContent
|
|
58
|
+
className="w-[--radix-dropdown-menu-trigger-width] min-w-56 rounded-lg"
|
|
59
|
+
side={isMobile ? 'bottom' : 'right'}
|
|
60
|
+
align="end"
|
|
61
|
+
sideOffset={4}
|
|
62
|
+
>
|
|
63
|
+
<DropdownMenuItem onClick={() => navigate({ to: '/dashboard/settings' })}>
|
|
64
|
+
<User className="mr-2 h-4 w-4" />
|
|
65
|
+
Settings
|
|
66
|
+
</DropdownMenuItem>
|
|
67
|
+
<DropdownMenuSeparator />
|
|
68
|
+
<DropdownMenuItem onClick={handleLogout}>
|
|
69
|
+
<LogOut className="mr-2 h-4 w-4" />
|
|
70
|
+
Log out
|
|
71
|
+
</DropdownMenuItem>
|
|
72
|
+
</DropdownMenuContent>
|
|
73
|
+
</DropdownMenu>
|
|
74
|
+
</SidebarMenuItem>
|
|
75
|
+
</SidebarMenu>
|
|
76
|
+
)
|
|
77
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import * as AvatarPrimitive from '@radix-ui/react-avatar'
|
|
3
|
+
|
|
4
|
+
import { cn } from '@/lib/utils'
|
|
5
|
+
|
|
6
|
+
function Avatar({ className, ...props }: React.ComponentProps<typeof AvatarPrimitive.Root>) {
|
|
7
|
+
return (
|
|
8
|
+
<AvatarPrimitive.Root
|
|
9
|
+
data-slot="avatar"
|
|
10
|
+
className={cn('relative flex size-8 shrink-0 overflow-hidden rounded-full', className)}
|
|
11
|
+
{...props}
|
|
12
|
+
/>
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function AvatarImage({ className, ...props }: React.ComponentProps<typeof AvatarPrimitive.Image>) {
|
|
17
|
+
return (
|
|
18
|
+
<AvatarPrimitive.Image
|
|
19
|
+
data-slot="avatar-image"
|
|
20
|
+
className={cn('aspect-square size-full', className)}
|
|
21
|
+
{...props}
|
|
22
|
+
/>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function AvatarFallback({
|
|
27
|
+
className,
|
|
28
|
+
...props
|
|
29
|
+
}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
|
|
30
|
+
return (
|
|
31
|
+
<AvatarPrimitive.Fallback
|
|
32
|
+
data-slot="avatar-fallback"
|
|
33
|
+
className={cn('bg-muted flex size-full items-center justify-center rounded-full', className)}
|
|
34
|
+
{...props}
|
|
35
|
+
/>
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export { Avatar, AvatarImage, AvatarFallback }
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import { Slot } from '@radix-ui/react-slot'
|
|
3
|
+
import { ChevronRight, MoreHorizontal } from 'lucide-react'
|
|
4
|
+
|
|
5
|
+
import { cn } from '@/lib/utils'
|
|
6
|
+
|
|
7
|
+
function Breadcrumb({ ...props }: React.ComponentProps<'nav'>) {
|
|
8
|
+
return <nav aria-label="breadcrumb" data-slot="breadcrumb" {...props} />
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function BreadcrumbList({ className, ...props }: React.ComponentProps<'ol'>) {
|
|
12
|
+
return (
|
|
13
|
+
<ol
|
|
14
|
+
data-slot="breadcrumb-list"
|
|
15
|
+
className={cn(
|
|
16
|
+
'text-muted-foreground flex flex-wrap items-center gap-1.5 text-sm break-words sm:gap-2.5',
|
|
17
|
+
className
|
|
18
|
+
)}
|
|
19
|
+
{...props}
|
|
20
|
+
/>
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function BreadcrumbItem({ className, ...props }: React.ComponentProps<'li'>) {
|
|
25
|
+
return (
|
|
26
|
+
<li
|
|
27
|
+
data-slot="breadcrumb-item"
|
|
28
|
+
className={cn('inline-flex items-center gap-1.5', className)}
|
|
29
|
+
{...props}
|
|
30
|
+
/>
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function BreadcrumbLink({
|
|
35
|
+
asChild,
|
|
36
|
+
className,
|
|
37
|
+
...props
|
|
38
|
+
}: React.ComponentProps<'a'> & {
|
|
39
|
+
asChild?: boolean
|
|
40
|
+
}) {
|
|
41
|
+
const Comp = asChild ? Slot : 'a'
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<Comp
|
|
45
|
+
data-slot="breadcrumb-link"
|
|
46
|
+
className={cn('hover:text-foreground transition-colors', className)}
|
|
47
|
+
{...props}
|
|
48
|
+
/>
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function BreadcrumbPage({ className, ...props }: React.ComponentProps<'span'>) {
|
|
53
|
+
return (
|
|
54
|
+
<span
|
|
55
|
+
data-slot="breadcrumb-page"
|
|
56
|
+
role="link"
|
|
57
|
+
aria-disabled="true"
|
|
58
|
+
aria-current="page"
|
|
59
|
+
className={cn('text-foreground font-normal', className)}
|
|
60
|
+
{...props}
|
|
61
|
+
/>
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function BreadcrumbSeparator({ children, className, ...props }: React.ComponentProps<'li'>) {
|
|
66
|
+
return (
|
|
67
|
+
<li
|
|
68
|
+
data-slot="breadcrumb-separator"
|
|
69
|
+
role="presentation"
|
|
70
|
+
aria-hidden="true"
|
|
71
|
+
className={cn('[&>svg]:size-3.5', className)}
|
|
72
|
+
{...props}
|
|
73
|
+
>
|
|
74
|
+
{children ?? <ChevronRight />}
|
|
75
|
+
</li>
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function BreadcrumbEllipsis({ className, ...props }: React.ComponentProps<'span'>) {
|
|
80
|
+
return (
|
|
81
|
+
<span
|
|
82
|
+
data-slot="breadcrumb-ellipsis"
|
|
83
|
+
role="presentation"
|
|
84
|
+
aria-hidden="true"
|
|
85
|
+
className={cn('flex size-9 items-center justify-center', className)}
|
|
86
|
+
{...props}
|
|
87
|
+
>
|
|
88
|
+
<MoreHorizontal className="size-4" />
|
|
89
|
+
<span className="sr-only">More</span>
|
|
90
|
+
</span>
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export {
|
|
95
|
+
Breadcrumb,
|
|
96
|
+
BreadcrumbList,
|
|
97
|
+
BreadcrumbItem,
|
|
98
|
+
BreadcrumbLink,
|
|
99
|
+
BreadcrumbPage,
|
|
100
|
+
BreadcrumbSeparator,
|
|
101
|
+
BreadcrumbEllipsis,
|
|
102
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as CollapsiblePrimitive from '@radix-ui/react-collapsible'
|
|
4
|
+
|
|
5
|
+
function Collapsible({ ...props }: React.ComponentProps<typeof CollapsiblePrimitive.Root>) {
|
|
6
|
+
return <CollapsiblePrimitive.Root data-slot="collapsible" {...props} />
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function CollapsibleTrigger({
|
|
10
|
+
...props
|
|
11
|
+
}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleTrigger>) {
|
|
12
|
+
return <CollapsiblePrimitive.CollapsibleTrigger data-slot="collapsible-trigger" {...props} />
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function CollapsibleContent({
|
|
16
|
+
...props
|
|
17
|
+
}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleContent>) {
|
|
18
|
+
return <CollapsiblePrimitive.CollapsibleContent data-slot="collapsible-content" {...props} />
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { Collapsible, CollapsibleTrigger, CollapsibleContent }
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import * as SeparatorPrimitive from '@radix-ui/react-separator'
|
|
3
|
+
|
|
4
|
+
import { cn } from '@/lib/utils'
|
|
5
|
+
|
|
6
|
+
function Separator({
|
|
7
|
+
className,
|
|
8
|
+
orientation = 'horizontal',
|
|
9
|
+
decorative = true,
|
|
10
|
+
...props
|
|
11
|
+
}: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
|
|
12
|
+
return (
|
|
13
|
+
<SeparatorPrimitive.Root
|
|
14
|
+
data-slot="separator"
|
|
15
|
+
decorative={decorative}
|
|
16
|
+
orientation={orientation}
|
|
17
|
+
className={cn(
|
|
18
|
+
'bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px',
|
|
19
|
+
className
|
|
20
|
+
)}
|
|
21
|
+
{...props}
|
|
22
|
+
/>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { Separator }
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import * as SheetPrimitive from '@radix-ui/react-dialog'
|
|
5
|
+
import { XIcon } from 'lucide-react'
|
|
6
|
+
|
|
7
|
+
import { cn } from '@/lib/utils'
|
|
8
|
+
|
|
9
|
+
function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
|
|
10
|
+
return <SheetPrimitive.Root data-slot="sheet" {...props} />
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function SheetTrigger({ ...props }: React.ComponentProps<typeof SheetPrimitive.Trigger>) {
|
|
14
|
+
return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function SheetClose({ ...props }: React.ComponentProps<typeof SheetPrimitive.Close>) {
|
|
18
|
+
return <SheetPrimitive.Close data-slot="sheet-close" {...props} />
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function SheetPortal({ ...props }: React.ComponentProps<typeof SheetPrimitive.Portal>) {
|
|
22
|
+
return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function SheetOverlay({
|
|
26
|
+
className,
|
|
27
|
+
...props
|
|
28
|
+
}: React.ComponentProps<typeof SheetPrimitive.Overlay>) {
|
|
29
|
+
return (
|
|
30
|
+
<SheetPrimitive.Overlay
|
|
31
|
+
data-slot="sheet-overlay"
|
|
32
|
+
className={cn(
|
|
33
|
+
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50',
|
|
34
|
+
className
|
|
35
|
+
)}
|
|
36
|
+
{...props}
|
|
37
|
+
/>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function SheetContent({
|
|
42
|
+
className,
|
|
43
|
+
children,
|
|
44
|
+
side = 'right',
|
|
45
|
+
...props
|
|
46
|
+
}: React.ComponentProps<typeof SheetPrimitive.Content> & {
|
|
47
|
+
side?: 'top' | 'right' | 'bottom' | 'left'
|
|
48
|
+
}) {
|
|
49
|
+
return (
|
|
50
|
+
<SheetPortal>
|
|
51
|
+
<SheetOverlay />
|
|
52
|
+
<SheetPrimitive.Content
|
|
53
|
+
data-slot="sheet-content"
|
|
54
|
+
className={cn(
|
|
55
|
+
'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500',
|
|
56
|
+
side === 'right' &&
|
|
57
|
+
'data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm',
|
|
58
|
+
side === 'left' &&
|
|
59
|
+
'data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm',
|
|
60
|
+
side === 'top' &&
|
|
61
|
+
'data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b',
|
|
62
|
+
side === 'bottom' &&
|
|
63
|
+
'data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t',
|
|
64
|
+
className
|
|
65
|
+
)}
|
|
66
|
+
{...props}
|
|
67
|
+
>
|
|
68
|
+
{children}
|
|
69
|
+
<SheetPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none">
|
|
70
|
+
<XIcon className="size-4" />
|
|
71
|
+
<span className="sr-only">Close</span>
|
|
72
|
+
</SheetPrimitive.Close>
|
|
73
|
+
</SheetPrimitive.Content>
|
|
74
|
+
</SheetPortal>
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function SheetHeader({ className, ...props }: React.ComponentProps<'div'>) {
|
|
79
|
+
return (
|
|
80
|
+
<div
|
|
81
|
+
data-slot="sheet-header"
|
|
82
|
+
className={cn('flex flex-col gap-1.5 p-4', className)}
|
|
83
|
+
{...props}
|
|
84
|
+
/>
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function SheetFooter({ className, ...props }: React.ComponentProps<'div'>) {
|
|
89
|
+
return (
|
|
90
|
+
<div
|
|
91
|
+
data-slot="sheet-footer"
|
|
92
|
+
className={cn('mt-auto flex flex-col gap-2 p-4', className)}
|
|
93
|
+
{...props}
|
|
94
|
+
/>
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function SheetTitle({ className, ...props }: React.ComponentProps<typeof SheetPrimitive.Title>) {
|
|
99
|
+
return (
|
|
100
|
+
<SheetPrimitive.Title
|
|
101
|
+
data-slot="sheet-title"
|
|
102
|
+
className={cn('text-foreground font-semibold', className)}
|
|
103
|
+
{...props}
|
|
104
|
+
/>
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function SheetDescription({
|
|
109
|
+
className,
|
|
110
|
+
...props
|
|
111
|
+
}: React.ComponentProps<typeof SheetPrimitive.Description>) {
|
|
112
|
+
return (
|
|
113
|
+
<SheetPrimitive.Description
|
|
114
|
+
data-slot="sheet-description"
|
|
115
|
+
className={cn('text-muted-foreground text-sm', className)}
|
|
116
|
+
{...props}
|
|
117
|
+
/>
|
|
118
|
+
)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export {
|
|
122
|
+
Sheet,
|
|
123
|
+
SheetTrigger,
|
|
124
|
+
SheetClose,
|
|
125
|
+
SheetContent,
|
|
126
|
+
SheetHeader,
|
|
127
|
+
SheetFooter,
|
|
128
|
+
SheetTitle,
|
|
129
|
+
SheetDescription,
|
|
130
|
+
}
|