refactor(hub): migrate dashboard to shadcn components

Replace manual CSS classes with shadcn Card, CardHeader, CardTitle,
CardContent, and Badge components. Remove inline <style> block —
use Tailwind utility classes via shadcn theme tokens. Add Biome
formatting across all components.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
asepharyana
2026-07-23 12:19:43 +07:00
co-authored by Claude Opus 4.8
parent 18bf58be1a
commit d94524b70d
65 changed files with 1832 additions and 1492 deletions
File diff suppressed because one or more lines are too long
+26 -26
View File
@@ -1,25 +1,25 @@
"use client"
"use client";
import * as React from "react"
import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog"
import * as React from "react";
import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog";
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
function AlertDialog({ ...props }: AlertDialogPrimitive.Root.Props) {
return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />
return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />;
}
function AlertDialogTrigger({ ...props }: AlertDialogPrimitive.Trigger.Props) {
return (
<AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />
)
);
}
function AlertDialogPortal({ ...props }: AlertDialogPrimitive.Portal.Props) {
return (
<AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />
)
);
}
function AlertDialogOverlay({
@@ -31,11 +31,11 @@ function AlertDialogOverlay({
data-slot="alert-dialog-overlay"
className={cn(
"fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
className
className,
)}
{...props}
/>
)
);
}
function AlertDialogContent({
@@ -43,7 +43,7 @@ function AlertDialogContent({
size = "default",
...props
}: AlertDialogPrimitive.Popup.Props & {
size?: "default" | "sm"
size?: "default" | "sm";
}) {
return (
<AlertDialogPortal>
@@ -53,12 +53,12 @@ function AlertDialogContent({
data-size={size}
className={cn(
"group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
className
className,
)}
{...props}
/>
</AlertDialogPortal>
)
);
}
function AlertDialogHeader({
@@ -70,11 +70,11 @@ function AlertDialogHeader({
data-slot="alert-dialog-header"
className={cn(
"grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]",
className
className,
)}
{...props}
/>
)
);
}
function AlertDialogFooter({
@@ -86,11 +86,11 @@ function AlertDialogFooter({
data-slot="alert-dialog-footer"
className={cn(
"-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end",
className
className,
)}
{...props}
/>
)
);
}
function AlertDialogMedia({
@@ -102,11 +102,11 @@ function AlertDialogMedia({
data-slot="alert-dialog-media"
className={cn(
"mb-2 inline-flex size-10 items-center justify-center rounded-md bg-muted sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-6",
className
className,
)}
{...props}
/>
)
);
}
function AlertDialogTitle({
@@ -118,11 +118,11 @@ function AlertDialogTitle({
data-slot="alert-dialog-title"
className={cn(
"font-heading text-base font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2",
className
className,
)}
{...props}
/>
)
);
}
function AlertDialogDescription({
@@ -134,11 +134,11 @@ function AlertDialogDescription({
data-slot="alert-dialog-description"
className={cn(
"text-sm text-balance text-muted-foreground md:text-pretty *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
className
className,
)}
{...props}
/>
)
);
}
function AlertDialogAction({
@@ -151,7 +151,7 @@ function AlertDialogAction({
className={cn(className)}
{...props}
/>
)
);
}
function AlertDialogCancel({
@@ -168,7 +168,7 @@ function AlertDialogCancel({
render={<Button variant={variant} size={size} />}
{...props}
/>
)
);
}
export {
@@ -184,4 +184,4 @@ export {
AlertDialogPortal,
AlertDialogTitle,
AlertDialogTrigger,
}
};
+12 -12
View File
@@ -1,7 +1,7 @@
import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"
import * as React from "react";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";
const alertVariants = cva(
"group/alert relative grid w-full gap-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4",
@@ -16,8 +16,8 @@ const alertVariants = cva(
defaultVariants: {
variant: "default",
},
}
)
},
);
function Alert({
className,
@@ -31,7 +31,7 @@ function Alert({
className={cn(alertVariants({ variant }), className)}
{...props}
/>
)
);
}
function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
@@ -40,11 +40,11 @@ function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
data-slot="alert-title"
className={cn(
"font-medium group-has-[>svg]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground",
className
className,
)}
{...props}
/>
)
);
}
function AlertDescription({
@@ -56,11 +56,11 @@ function AlertDescription({
data-slot="alert-description"
className={cn(
"text-sm text-balance text-muted-foreground md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4",
className
className,
)}
{...props}
/>
)
);
}
function AlertAction({ className, ...props }: React.ComponentProps<"div">) {
@@ -70,7 +70,7 @@ function AlertAction({ className, ...props }: React.ComponentProps<"div">) {
className={cn("absolute top-2 right-2", className)}
{...props}
/>
)
);
}
export { Alert, AlertTitle, AlertDescription, AlertAction }
export { Alert, AlertTitle, AlertDescription, AlertAction };
+3 -3
View File
@@ -1,4 +1,4 @@
import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";
function AspectRatio({
ratio,
@@ -16,7 +16,7 @@ function AspectRatio({
className={cn("relative aspect-(--ratio)", className)}
{...props}
/>
)
);
}
export { AspectRatio }
export { AspectRatio };
+27 -27
View File
@@ -1,10 +1,10 @@
import * as React from "react"
import { mergeProps } from "@base-ui/react/merge-props"
import { useRender } from "@base-ui/react/use-render"
import { cva, type VariantProps } from "class-variance-authority"
import * as React from "react";
import { mergeProps } from "@base-ui/react/merge-props";
import { useRender } from "@base-ui/react/use-render";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
const attachmentVariants = cva(
"group/attachment relative flex w-fit max-w-full min-w-0 shrink-0 flex-wrap rounded-xl border bg-card text-card-foreground transition-colors focus-within:ring-1 focus-within:ring-ring/50 has-[>a,>button]:hover:bg-muted/50 data-[state=error]:border-destructive/30 data-[state=idle]:border-dashed",
@@ -21,8 +21,8 @@ const attachmentVariants = cva(
vertical: "w-24 flex-col has-data-[slot=attachment-content]:w-30",
},
},
}
)
},
);
function Attachment({
className,
@@ -32,7 +32,7 @@ function Attachment({
...props
}: React.ComponentProps<"div"> &
VariantProps<typeof attachmentVariants> & {
state?: "idle" | "uploading" | "processing" | "error" | "done"
state?: "idle" | "uploading" | "processing" | "error" | "done";
}) {
return (
<div
@@ -43,7 +43,7 @@ function Attachment({
className={cn(attachmentVariants({ size, orientation }), className)}
{...props}
/>
)
);
}
const attachmentMediaVariants = cva(
@@ -59,8 +59,8 @@ const attachmentMediaVariants = cva(
defaultVariants: {
variant: "icon",
},
}
)
},
);
function AttachmentMedia({
className,
@@ -74,7 +74,7 @@ function AttachmentMedia({
className={cn(attachmentMediaVariants({ variant }), className)}
{...props}
/>
)
);
}
function AttachmentContent({
@@ -86,11 +86,11 @@ function AttachmentContent({
data-slot="attachment-content"
className={cn(
"max-w-full min-w-0 flex-1 leading-tight group-data-[orientation=vertical]/attachment:px-1",
className
className,
)}
{...props}
/>
)
);
}
function AttachmentTitle({
@@ -102,11 +102,11 @@ function AttachmentTitle({
data-slot="attachment-title"
className={cn(
"block max-w-full min-w-0 truncate font-medium group-data-[state=processing]/attachment:shimmer group-data-[state=uploading]/attachment:shimmer",
className
className,
)}
{...props}
/>
)
);
}
function AttachmentDescription({
@@ -119,11 +119,11 @@ function AttachmentDescription({
className={cn(
"mt-0.5 block min-w-0 truncate text-xs text-muted-foreground group-data-[state=error]/attachment:text-destructive/80",
"max-w-full",
className
className,
)}
{...props}
/>
)
);
}
function AttachmentActions({
@@ -135,11 +135,11 @@ function AttachmentActions({
data-slot="attachment-actions"
className={cn(
"relative z-20 flex shrink-0 items-center group-data-[orientation=vertical]/attachment:absolute group-data-[orientation=vertical]/attachment:top-3 group-data-[orientation=vertical]/attachment:right-3 group-data-[orientation=vertical]/attachment:gap-1",
className
className,
)}
{...props}
/>
)
);
}
function AttachmentAction({
@@ -156,7 +156,7 @@ function AttachmentAction({
className={cn(className)}
{...props}
/>
)
);
}
function AttachmentTrigger({
@@ -172,13 +172,13 @@ function AttachmentTrigger({
type: render ? type : (type ?? "button"),
className: cn("absolute inset-0 z-10 outline-none", className),
},
props
props,
),
render,
state: {
slot: "attachment-trigger",
},
})
});
}
function AttachmentGroup({ className, ...props }: React.ComponentProps<"div">) {
@@ -187,11 +187,11 @@ function AttachmentGroup({ className, ...props }: React.ComponentProps<"div">) {
data-slot="attachment-group"
className={cn(
"flex min-w-0 scroll-fade-x snap-x snap-mandatory scroll-px-1 scrollbar-none gap-3 overflow-x-auto overscroll-x-contain py-1 *:data-[slot=attachment]:flex-none *:data-[slot=attachment]:snap-start",
className
className,
)}
{...props}
/>
)
);
}
export {
@@ -204,4 +204,4 @@ export {
AttachmentActions,
AttachmentAction,
AttachmentTrigger,
}
};
+18 -18
View File
@@ -1,16 +1,16 @@
"use client"
"use client";
import * as React from "react"
import { Avatar as AvatarPrimitive } from "@base-ui/react/avatar"
import * as React from "react";
import { Avatar as AvatarPrimitive } from "@base-ui/react/avatar";
import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";
function Avatar({
className,
size = "default",
...props
}: AvatarPrimitive.Root.Props & {
size?: "default" | "sm" | "lg"
size?: "default" | "sm" | "lg";
}) {
return (
<AvatarPrimitive.Root
@@ -18,11 +18,11 @@ function Avatar({
data-size={size}
className={cn(
"group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6 dark:after:mix-blend-lighten",
className
className,
)}
{...props}
/>
)
);
}
function AvatarImage({ className, ...props }: AvatarPrimitive.Image.Props) {
@@ -31,11 +31,11 @@ function AvatarImage({ className, ...props }: AvatarPrimitive.Image.Props) {
data-slot="avatar-image"
className={cn(
"aspect-square size-full rounded-full object-cover",
className
className,
)}
{...props}
/>
)
);
}
function AvatarFallback({
@@ -47,11 +47,11 @@ function AvatarFallback({
data-slot="avatar-fallback"
className={cn(
"flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs",
className
className,
)}
{...props}
/>
)
);
}
function AvatarBadge({ className, ...props }: React.ComponentProps<"span">) {
@@ -63,11 +63,11 @@ function AvatarBadge({ className, ...props }: React.ComponentProps<"span">) {
"group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden",
"group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2",
"group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2",
className
className,
)}
{...props}
/>
)
);
}
function AvatarGroup({ className, ...props }: React.ComponentProps<"div">) {
@@ -76,11 +76,11 @@ function AvatarGroup({ className, ...props }: React.ComponentProps<"div">) {
data-slot="avatar-group"
className={cn(
"group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background",
className
className,
)}
{...props}
/>
)
);
}
function AvatarGroupCount({
@@ -92,11 +92,11 @@ function AvatarGroupCount({
data-slot="avatar-group-count"
className={cn(
"relative flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-sm text-muted-foreground ring-2 ring-background group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3",
className
className,
)}
{...props}
/>
)
);
}
export {
@@ -106,4 +106,4 @@ export {
AvatarGroup,
AvatarGroupCount,
AvatarBadge,
}
};
+9 -9
View File
@@ -1,8 +1,8 @@
import { mergeProps } from "@base-ui/react/merge-props"
import { useRender } from "@base-ui/react/use-render"
import { cva, type VariantProps } from "class-variance-authority"
import { mergeProps } from "@base-ui/react/merge-props";
import { useRender } from "@base-ui/react/use-render";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";
const badgeVariants = cva(
"group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!",
@@ -24,8 +24,8 @@ const badgeVariants = cva(
defaultVariants: {
variant: "default",
},
}
)
},
);
function Badge({
className,
@@ -39,14 +39,14 @@ function Badge({
{
className: cn(badgeVariants({ variant }), className),
},
props
props,
),
render,
state: {
slot: "badge",
variant,
},
})
});
}
export { Badge, badgeVariants }
export { Badge, badgeVariants };
+18 -21
View File
@@ -1,9 +1,9 @@
import * as React from "react"
import { mergeProps } from "@base-ui/react/merge-props"
import { useRender } from "@base-ui/react/use-render"
import * as React from "react";
import { mergeProps } from "@base-ui/react/merge-props";
import { useRender } from "@base-ui/react/use-render";
import { cn } from "@/lib/utils"
import { ChevronRightIcon, MoreHorizontalIcon } from "lucide-react"
import { cn } from "@/lib/utils";
import { ChevronRightIcon, MoreHorizontalIcon } from "lucide-react";
function Breadcrumb({ className, ...props }: React.ComponentProps<"nav">) {
return (
@@ -13,7 +13,7 @@ function Breadcrumb({ className, ...props }: React.ComponentProps<"nav">) {
className={cn(className)}
{...props}
/>
)
);
}
function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
@@ -22,11 +22,11 @@ function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
data-slot="breadcrumb-list"
className={cn(
"flex flex-wrap items-center gap-1.5 text-sm wrap-break-word text-muted-foreground",
className
className,
)}
{...props}
/>
)
);
}
function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
@@ -36,7 +36,7 @@ function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
className={cn("inline-flex items-center gap-1", className)}
{...props}
/>
)
);
}
function BreadcrumbLink({
@@ -50,13 +50,13 @@ function BreadcrumbLink({
{
className: cn("transition-colors hover:text-foreground", className),
},
props
props,
),
render,
state: {
slot: "breadcrumb-link",
},
})
});
}
function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
@@ -69,7 +69,7 @@ function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
className={cn("font-normal text-foreground", className)}
{...props}
/>
)
);
}
function BreadcrumbSeparator({
@@ -85,11 +85,9 @@ function BreadcrumbSeparator({
className={cn("[&>svg]:size-3.5", className)}
{...props}
>
{children ?? (
<ChevronRightIcon />
)}
{children ?? <ChevronRightIcon />}
</li>
)
);
}
function BreadcrumbEllipsis({
@@ -103,15 +101,14 @@ function BreadcrumbEllipsis({
aria-hidden="true"
className={cn(
"flex size-5 items-center justify-center [&>svg]:size-4",
className
className,
)}
{...props}
>
<MoreHorizontalIcon
/>
<MoreHorizontalIcon />
<span className="sr-only">More</span>
</span>
)
);
}
export {
@@ -122,4 +119,4 @@ export {
BreadcrumbPage,
BreadcrumbSeparator,
BreadcrumbEllipsis,
}
};
+19 -19
View File
@@ -1,9 +1,9 @@
import * as React from "react"
import { mergeProps } from "@base-ui/react/merge-props"
import { useRender } from "@base-ui/react/use-render"
import { cva, type VariantProps } from "class-variance-authority"
import * as React from "react";
import { mergeProps } from "@base-ui/react/merge-props";
import { useRender } from "@base-ui/react/use-render";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";
function BubbleGroup({ className, ...props }: React.ComponentProps<"div">) {
return (
@@ -12,7 +12,7 @@ function BubbleGroup({ className, ...props }: React.ComponentProps<"div">) {
className={cn("flex min-w-0 flex-col gap-2", className)}
{...props}
/>
)
);
}
const bubbleVariants = cva(
@@ -39,8 +39,8 @@ const bubbleVariants = cva(
defaultVariants: {
variant: "default",
},
}
)
},
);
function Bubble({
variant = "default",
@@ -49,7 +49,7 @@ function Bubble({
...props
}: React.ComponentProps<"div"> &
VariantProps<typeof bubbleVariants> & {
align?: "start" | "end"
align?: "start" | "end";
}) {
return (
<div
@@ -59,7 +59,7 @@ function Bubble({
className={cn(bubbleVariants({ variant }), className)}
{...props}
/>
)
);
}
function BubbleContent({
@@ -73,16 +73,16 @@ function BubbleContent({
{
className: cn(
"w-fit max-w-full min-w-0 overflow-hidden rounded-xl border border-transparent px-3 py-2 text-sm leading-relaxed wrap-break-word group-data-[align=end]/bubble:self-end [button]:text-left [button,a]:transition-colors [button,a]:outline-none [button,a]:focus-visible:border-ring [button,a]:focus-visible:ring-3 [button,a]:focus-visible:ring-ring/50",
className
className,
),
},
props
props,
),
render,
state: {
slot: "bubble-content",
},
})
});
}
const bubbleReactionsVariants = cva(
@@ -102,8 +102,8 @@ const bubbleReactionsVariants = cva(
side: "bottom",
align: "end",
},
}
)
},
);
function BubbleReactions({
side = "bottom",
@@ -111,8 +111,8 @@ function BubbleReactions({
className,
...props
}: React.ComponentProps<"div"> & {
align?: "start" | "end"
side?: "top" | "bottom"
align?: "start" | "end";
side?: "top" | "bottom";
}) {
return (
<div
@@ -122,7 +122,7 @@ function BubbleReactions({
className={cn(bubbleReactionsVariants({ side, align }), className)}
{...props}
/>
)
);
}
export { BubbleGroup, Bubble, BubbleContent, BubbleReactions }
export { BubbleGroup, Bubble, BubbleContent, BubbleReactions };
+14 -14
View File
@@ -1,9 +1,9 @@
import { mergeProps } from "@base-ui/react/merge-props"
import { useRender } from "@base-ui/react/use-render"
import { cva, type VariantProps } from "class-variance-authority"
import { mergeProps } from "@base-ui/react/merge-props";
import { useRender } from "@base-ui/react/use-render";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils"
import { Separator } from "@/components/ui/separator"
import { cn } from "@/lib/utils";
import { Separator } from "@/components/ui/separator";
const buttonGroupVariants = cva(
"flex w-fit items-stretch *:focus-visible:relative *:focus-visible:z-10 has-[>[data-slot=button-group]]:gap-2 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-lg [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
@@ -19,8 +19,8 @@ const buttonGroupVariants = cva(
defaultVariants: {
orientation: "horizontal",
},
}
)
},
);
function ButtonGroup({
className,
@@ -35,7 +35,7 @@ function ButtonGroup({
className={cn(buttonGroupVariants({ orientation }), className)}
{...props}
/>
)
);
}
function ButtonGroupText({
@@ -49,16 +49,16 @@ function ButtonGroupText({
{
className: cn(
"flex items-center gap-2 rounded-lg border bg-muted px-2.5 text-sm font-medium [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
className
className,
),
},
props
props,
),
render,
state: {
slot: "button-group-text",
},
})
});
}
function ButtonGroupSeparator({
@@ -72,11 +72,11 @@ function ButtonGroupSeparator({
orientation={orientation}
className={cn(
"relative self-stretch bg-input data-horizontal:mx-px data-horizontal:w-auto data-vertical:my-px data-vertical:h-auto",
className
className,
)}
{...props}
/>
)
);
}
export {
@@ -84,4 +84,4 @@ export {
ButtonGroupSeparator,
ButtonGroupText,
buttonGroupVariants,
}
};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+15 -15
View File
@@ -1,6 +1,6 @@
import * as React from "react"
import * as React from "react";
import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";
function Card({
className,
@@ -13,11 +13,11 @@ function Card({
data-size={size}
className={cn(
"group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-xl bg-card py-(--card-spacing) text-sm text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
className
className,
)}
{...props}
/>
)
);
}
function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
@@ -26,11 +26,11 @@ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
data-slot="card-header"
className={cn(
"group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)",
className
className,
)}
{...props}
/>
)
);
}
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
@@ -39,11 +39,11 @@ function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
data-slot="card-title"
className={cn(
"font-heading text-base leading-snug font-medium group-data-[size=sm]/card:text-sm",
className
className,
)}
{...props}
/>
)
);
}
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
@@ -53,7 +53,7 @@ function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
)
);
}
function CardAction({ className, ...props }: React.ComponentProps<"div">) {
@@ -62,11 +62,11 @@ function CardAction({ className, ...props }: React.ComponentProps<"div">) {
data-slot="card-action"
className={cn(
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
className
className,
)}
{...props}
/>
)
);
}
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
@@ -76,7 +76,7 @@ function CardContent({ className, ...props }: React.ComponentProps<"div">) {
className={cn("px-(--card-spacing)", className)}
{...props}
/>
)
);
}
function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
@@ -85,11 +85,11 @@ function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
data-slot="card-footer"
className={cn(
"flex items-center rounded-b-xl border-t bg-muted/50 p-(--card-spacing)",
className
className,
)}
{...props}
/>
)
);
}
export {
@@ -100,4 +100,4 @@ export {
CardAction,
CardDescription,
CardContent,
}
};
+68 -68
View File
@@ -1,45 +1,45 @@
"use client"
"use client";
import * as React from "react"
import * as React from "react";
import useEmblaCarousel, {
type UseEmblaCarouselType,
} from "embla-carousel-react"
} from "embla-carousel-react";
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react"
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
type CarouselApi = UseEmblaCarouselType[1]
type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
type CarouselOptions = UseCarouselParameters[0]
type CarouselPlugin = UseCarouselParameters[1]
type CarouselApi = UseEmblaCarouselType[1];
type UseCarouselParameters = Parameters<typeof useEmblaCarousel>;
type CarouselOptions = UseCarouselParameters[0];
type CarouselPlugin = UseCarouselParameters[1];
type CarouselProps = {
opts?: CarouselOptions
plugins?: CarouselPlugin
orientation?: "horizontal" | "vertical"
setApi?: (api: CarouselApi) => void
}
opts?: CarouselOptions;
plugins?: CarouselPlugin;
orientation?: "horizontal" | "vertical";
setApi?: (api: CarouselApi) => void;
};
type CarouselContextProps = {
carouselRef: ReturnType<typeof useEmblaCarousel>[0]
api: ReturnType<typeof useEmblaCarousel>[1]
scrollPrev: () => void
scrollNext: () => void
canScrollPrev: boolean
canScrollNext: boolean
} & CarouselProps
carouselRef: ReturnType<typeof useEmblaCarousel>[0];
api: ReturnType<typeof useEmblaCarousel>[1];
scrollPrev: () => void;
scrollNext: () => void;
canScrollPrev: boolean;
canScrollNext: boolean;
} & CarouselProps;
const CarouselContext = React.createContext<CarouselContextProps | null>(null)
const CarouselContext = React.createContext<CarouselContextProps | null>(null);
function useCarousel() {
const context = React.useContext(CarouselContext)
const context = React.useContext(CarouselContext);
if (!context) {
throw new Error("useCarousel must be used within a <Carousel />")
throw new Error("useCarousel must be used within a <Carousel />");
}
return context
return context;
}
function Carousel({
@@ -56,53 +56,53 @@ function Carousel({
...opts,
axis: orientation === "horizontal" ? "x" : "y",
},
plugins
)
const [canScrollPrev, setCanScrollPrev] = React.useState(false)
const [canScrollNext, setCanScrollNext] = React.useState(false)
plugins,
);
const [canScrollPrev, setCanScrollPrev] = React.useState(false);
const [canScrollNext, setCanScrollNext] = React.useState(false);
const onSelect = React.useCallback((api: CarouselApi) => {
if (!api) return
setCanScrollPrev(api.canScrollPrev())
setCanScrollNext(api.canScrollNext())
}, [])
if (!api) return;
setCanScrollPrev(api.canScrollPrev());
setCanScrollNext(api.canScrollNext());
}, []);
const scrollPrev = React.useCallback(() => {
api?.scrollPrev()
}, [api])
api?.scrollPrev();
}, [api]);
const scrollNext = React.useCallback(() => {
api?.scrollNext()
}, [api])
api?.scrollNext();
}, [api]);
const handleKeyDown = React.useCallback(
(event: React.KeyboardEvent<HTMLDivElement>) => {
if (event.key === "ArrowLeft") {
event.preventDefault()
scrollPrev()
event.preventDefault();
scrollPrev();
} else if (event.key === "ArrowRight") {
event.preventDefault()
scrollNext()
event.preventDefault();
scrollNext();
}
},
[scrollPrev, scrollNext]
)
[scrollPrev, scrollNext],
);
React.useEffect(() => {
if (!api || !setApi) return
setApi(api)
}, [api, setApi])
if (!api || !setApi) return;
setApi(api);
}, [api, setApi]);
React.useEffect(() => {
if (!api) return
onSelect(api)
api.on("reInit", onSelect)
api.on("select", onSelect)
if (!api) return;
onSelect(api);
api.on("reInit", onSelect);
api.on("select", onSelect);
return () => {
api?.off("select", onSelect)
}
}, [api, onSelect])
api?.off("select", onSelect);
};
}, [api, onSelect]);
return (
<CarouselContext.Provider
@@ -129,11 +129,11 @@ function Carousel({
{children}
</div>
</CarouselContext.Provider>
)
);
}
function CarouselContent({ className, ...props }: React.ComponentProps<"div">) {
const { carouselRef, orientation } = useCarousel()
const { carouselRef, orientation } = useCarousel();
return (
<div
@@ -145,16 +145,16 @@ function CarouselContent({ className, ...props }: React.ComponentProps<"div">) {
className={cn(
"flex",
orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
className
className,
)}
{...props}
/>
</div>
)
);
}
function CarouselItem({ className, ...props }: React.ComponentProps<"div">) {
const { orientation } = useCarousel()
const { orientation } = useCarousel();
return (
<div
@@ -164,11 +164,11 @@ function CarouselItem({ className, ...props }: React.ComponentProps<"div">) {
className={cn(
"min-w-0 shrink-0 grow-0 basis-full",
orientation === "horizontal" ? "pl-4" : "pt-4",
className
className,
)}
{...props}
/>
)
);
}
function CarouselPrevious({
@@ -177,7 +177,7 @@ function CarouselPrevious({
size = "icon-sm",
...props
}: React.ComponentProps<typeof Button>) {
const { orientation, scrollPrev, canScrollPrev } = useCarousel()
const { orientation, scrollPrev, canScrollPrev } = useCarousel();
return (
<Button
@@ -189,7 +189,7 @@ function CarouselPrevious({
orientation === "horizontal"
? "inset-y-0 -left-12 my-auto"
: "-top-12 left-1/2 -translate-x-1/2 rotate-90",
className
className,
)}
disabled={!canScrollPrev}
onClick={scrollPrev}
@@ -198,7 +198,7 @@ function CarouselPrevious({
<ChevronLeftIcon />
<span className="sr-only">Previous slide</span>
</Button>
)
);
}
function CarouselNext({
@@ -207,7 +207,7 @@ function CarouselNext({
size = "icon-sm",
...props
}: React.ComponentProps<typeof Button>) {
const { orientation, scrollNext, canScrollNext } = useCarousel()
const { orientation, scrollNext, canScrollNext } = useCarousel();
return (
<Button
@@ -219,7 +219,7 @@ function CarouselNext({
orientation === "horizontal"
? "inset-y-0 -right-12 my-auto"
: "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
className
className,
)}
disabled={!canScrollNext}
onClick={scrollNext}
@@ -228,7 +228,7 @@ function CarouselNext({
<ChevronRightIcon />
<span className="sr-only">Next slide</span>
</Button>
)
);
}
export {
@@ -239,4 +239,4 @@ export {
CarouselPrevious,
CarouselNext,
useCarousel,
}
};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+6 -6
View File
@@ -1,21 +1,21 @@
"use client"
"use client";
import { Collapsible as CollapsiblePrimitive } from "@base-ui/react/collapsible"
import { Collapsible as CollapsiblePrimitive } from "@base-ui/react/collapsible";
function Collapsible({ ...props }: CollapsiblePrimitive.Root.Props) {
return <CollapsiblePrimitive.Root data-slot="collapsible" {...props} />
return <CollapsiblePrimitive.Root data-slot="collapsible" {...props} />;
}
function CollapsibleTrigger({ ...props }: CollapsiblePrimitive.Trigger.Props) {
return (
<CollapsiblePrimitive.Trigger data-slot="collapsible-trigger" {...props} />
)
);
}
function CollapsibleContent({ ...props }: CollapsiblePrimitive.Panel.Props) {
return (
<CollapsiblePrimitive.Panel data-slot="collapsible-content" {...props} />
)
);
}
export { Collapsible, CollapsibleTrigger, CollapsibleContent }
export { Collapsible, CollapsibleTrigger, CollapsibleContent };
File diff suppressed because one or more lines are too long
+29 -32
View File
@@ -1,21 +1,18 @@
"use client"
"use client";
import * as React from "react"
import { Command as CommandPrimitive } from "cmdk"
import * as React from "react";
import { Command as CommandPrimitive } from "cmdk";
import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog"
import {
InputGroup,
InputGroupAddon,
} from "@/components/ui/input-group"
import { SearchIcon, CheckIcon } from "lucide-react"
} from "@/components/ui/dialog";
import { InputGroup, InputGroupAddon } from "@/components/ui/input-group";
import { SearchIcon, CheckIcon } from "lucide-react";
function Command({
className,
@@ -26,11 +23,11 @@ function Command({
data-slot="command"
className={cn(
"flex size-full flex-col overflow-hidden rounded-xl! bg-popover p-1 text-popover-foreground",
className
className,
)}
{...props}
/>
)
);
}
function CommandDialog({
@@ -41,11 +38,11 @@ function CommandDialog({
showCloseButton = false,
...props
}: Omit<React.ComponentProps<typeof Dialog>, "children"> & {
title?: string
description?: string
className?: string
showCloseButton?: boolean
children: React.ReactNode
title?: string;
description?: string;
className?: string;
showCloseButton?: boolean;
children: React.ReactNode;
}) {
return (
<Dialog {...props}>
@@ -56,14 +53,14 @@ function CommandDialog({
<DialogContent
className={cn(
"top-1/3 translate-y-0 overflow-hidden rounded-xl! p-0",
className
className,
)}
showCloseButton={showCloseButton}
>
{children}
</DialogContent>
</Dialog>
)
);
}
function CommandInput({
@@ -77,7 +74,7 @@ function CommandInput({
data-slot="command-input"
className={cn(
"w-full text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
className
className,
)}
{...props}
/>
@@ -86,7 +83,7 @@ function CommandInput({
</InputGroupAddon>
</InputGroup>
</div>
)
);
}
function CommandList({
@@ -98,11 +95,11 @@ function CommandList({
data-slot="command-list"
className={cn(
"no-scrollbar max-h-72 scroll-py-1 overflow-x-hidden overflow-y-auto outline-none",
className
className,
)}
{...props}
/>
)
);
}
function CommandEmpty({
@@ -115,7 +112,7 @@ function CommandEmpty({
className={cn("py-6 text-center text-sm", className)}
{...props}
/>
)
);
}
function CommandGroup({
@@ -127,11 +124,11 @@ function CommandGroup({
data-slot="command-group"
className={cn(
"overflow-hidden p-1 text-foreground **:[[cmdk-group-heading]]:px-2 **:[[cmdk-group-heading]]:py-1.5 **:[[cmdk-group-heading]]:text-xs **:[[cmdk-group-heading]]:font-medium **:[[cmdk-group-heading]]:text-muted-foreground",
className
className,
)}
{...props}
/>
)
);
}
function CommandSeparator({
@@ -144,7 +141,7 @@ function CommandSeparator({
className={cn("-mx-1 h-px bg-border", className)}
{...props}
/>
)
);
}
function CommandItem({
@@ -157,14 +154,14 @@ function CommandItem({
data-slot="command-item"
className={cn(
"group/command-item relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none in-data-[slot=dialog-content]:rounded-lg! data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-selected:bg-muted data-selected:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-selected:*:[svg]:text-foreground",
className
className,
)}
{...props}
>
{children}
<CheckIcon className="ml-auto opacity-0 group-has-data-[slot=command-shortcut]/command-item:hidden group-data-[checked=true]/command-item:opacity-100" />
</CommandPrimitive.Item>
)
);
}
function CommandShortcut({
@@ -176,11 +173,11 @@ function CommandShortcut({
data-slot="command-shortcut"
className={cn(
"ml-auto text-xs tracking-widest text-muted-foreground group-data-selected/command-item:text-foreground",
className
className,
)}
{...props}
/>
)
);
}
export {
@@ -193,4 +190,4 @@ export {
CommandItem,
CommandShortcut,
CommandSeparator,
}
};
File diff suppressed because one or more lines are too long
+25 -26
View File
@@ -1,26 +1,26 @@
"use client"
"use client";
import * as React from "react"
import { Dialog as DialogPrimitive } from "@base-ui/react/dialog"
import * as React from "react";
import { Dialog as DialogPrimitive } from "@base-ui/react/dialog";
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import { XIcon } from "lucide-react"
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { XIcon } from "lucide-react";
function Dialog({ ...props }: DialogPrimitive.Root.Props) {
return <DialogPrimitive.Root data-slot="dialog" {...props} />
return <DialogPrimitive.Root data-slot="dialog" {...props} />;
}
function DialogTrigger({ ...props }: DialogPrimitive.Trigger.Props) {
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
}
function DialogPortal({ ...props }: DialogPrimitive.Portal.Props) {
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
}
function DialogClose({ ...props }: DialogPrimitive.Close.Props) {
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
}
function DialogOverlay({
@@ -32,11 +32,11 @@ function DialogOverlay({
data-slot="dialog-overlay"
className={cn(
"fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
className
className,
)}
{...props}
/>
)
);
}
function DialogContent({
@@ -45,7 +45,7 @@ function DialogContent({
showCloseButton = true,
...props
}: DialogPrimitive.Popup.Props & {
showCloseButton?: boolean
showCloseButton?: boolean;
}) {
return (
<DialogPortal>
@@ -54,7 +54,7 @@ function DialogContent({
data-slot="dialog-content"
className={cn(
"fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-sm text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
className
className,
)}
{...props}
>
@@ -70,14 +70,13 @@ function DialogContent({
/>
}
>
<XIcon
/>
<XIcon />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
)}
</DialogPrimitive.Popup>
</DialogPortal>
)
);
}
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
@@ -87,7 +86,7 @@ function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
className={cn("flex flex-col gap-2", className)}
{...props}
/>
)
);
}
function DialogFooter({
@@ -96,14 +95,14 @@ function DialogFooter({
children,
...props
}: React.ComponentProps<"div"> & {
showCloseButton?: boolean
showCloseButton?: boolean;
}) {
return (
<div
data-slot="dialog-footer"
className={cn(
"-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 sm:flex-row sm:justify-end",
className
className,
)}
{...props}
>
@@ -114,7 +113,7 @@ function DialogFooter({
</DialogPrimitive.Close>
)}
</div>
)
);
}
function DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {
@@ -123,11 +122,11 @@ function DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {
data-slot="dialog-title"
className={cn(
"font-heading text-base leading-none font-medium",
className
className,
)}
{...props}
/>
)
);
}
function DialogDescription({
@@ -139,11 +138,11 @@ function DialogDescription({
data-slot="dialog-description"
className={cn(
"text-sm text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
className
className,
)}
{...props}
/>
)
);
}
export {
@@ -157,4 +156,4 @@ export {
DialogPortal,
DialogTitle,
DialogTrigger,
}
};
+2 -2
View File
@@ -1,6 +1,6 @@
"use client"
"use client";
export {
DirectionProvider,
useDirection,
} from "@base-ui/react/direction-provider"
} from "@base-ui/react/direction-provider";
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+15 -15
View File
@@ -1,6 +1,6 @@
import { cva, type VariantProps } from "class-variance-authority"
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";
function Empty({ className, ...props }: React.ComponentProps<"div">) {
return (
@@ -8,11 +8,11 @@ function Empty({ className, ...props }: React.ComponentProps<"div">) {
data-slot="empty"
className={cn(
"flex w-full min-w-0 flex-1 flex-col items-center justify-center gap-4 rounded-xl border-dashed p-6 text-center text-balance",
className
className,
)}
{...props}
/>
)
);
}
function EmptyHeader({ className, ...props }: React.ComponentProps<"div">) {
@@ -22,7 +22,7 @@ function EmptyHeader({ className, ...props }: React.ComponentProps<"div">) {
className={cn("flex max-w-sm flex-col items-center gap-2", className)}
{...props}
/>
)
);
}
const emptyMediaVariants = cva(
@@ -37,8 +37,8 @@ const emptyMediaVariants = cva(
defaultVariants: {
variant: "default",
},
}
)
},
);
function EmptyMedia({
className,
@@ -52,7 +52,7 @@ function EmptyMedia({
className={cn(emptyMediaVariants({ variant, className }))}
{...props}
/>
)
);
}
function EmptyTitle({ className, ...props }: React.ComponentProps<"div">) {
@@ -61,11 +61,11 @@ function EmptyTitle({ className, ...props }: React.ComponentProps<"div">) {
data-slot="empty-title"
className={cn(
"font-heading text-sm font-medium tracking-tight",
className
className,
)}
{...props}
/>
)
);
}
function EmptyDescription({ className, ...props }: React.ComponentProps<"p">) {
@@ -74,11 +74,11 @@ function EmptyDescription({ className, ...props }: React.ComponentProps<"p">) {
data-slot="empty-description"
className={cn(
"text-sm/relaxed text-muted-foreground [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary",
className
className,
)}
{...props}
/>
)
);
}
function EmptyContent({ className, ...props }: React.ComponentProps<"div">) {
@@ -87,11 +87,11 @@ function EmptyContent({ className, ...props }: React.ComponentProps<"div">) {
data-slot="empty-content"
className={cn(
"flex w-full max-w-sm min-w-0 flex-col items-center gap-2.5 text-sm text-balance",
className
className,
)}
{...props}
/>
)
);
}
export {
@@ -101,4 +101,4 @@ export {
EmptyDescription,
EmptyContent,
EmptyMedia,
}
};
+37 -37
View File
@@ -1,11 +1,11 @@
"use client"
"use client";
import { useMemo } from "react"
import { cva, type VariantProps } from "class-variance-authority"
import { useMemo } from "react";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils"
import { Label } from "@/components/ui/label"
import { Separator } from "@/components/ui/separator"
import { cn } from "@/lib/utils";
import { Label } from "@/components/ui/label";
import { Separator } from "@/components/ui/separator";
function FieldSet({ className, ...props }: React.ComponentProps<"fieldset">) {
return (
@@ -13,11 +13,11 @@ function FieldSet({ className, ...props }: React.ComponentProps<"fieldset">) {
data-slot="field-set"
className={cn(
"flex flex-col gap-4 has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3",
className
className,
)}
{...props}
/>
)
);
}
function FieldLegend({
@@ -31,11 +31,11 @@ function FieldLegend({
data-variant={variant}
className={cn(
"mb-1.5 font-medium data-[variant=label]:text-sm data-[variant=legend]:text-base",
className
className,
)}
{...props}
/>
)
);
}
function FieldGroup({ className, ...props }: React.ComponentProps<"div">) {
@@ -44,11 +44,11 @@ function FieldGroup({ className, ...props }: React.ComponentProps<"div">) {
data-slot="field-group"
className={cn(
"group/field-group @container/field-group flex w-full flex-col gap-5 data-[slot=checkbox-group]:gap-3 *:data-[slot=field-group]:gap-4",
className
className,
)}
{...props}
/>
)
);
}
const fieldVariants = cva(
@@ -66,8 +66,8 @@ const fieldVariants = cva(
defaultVariants: {
orientation: "vertical",
},
}
)
},
);
function Field({
className,
@@ -82,7 +82,7 @@ function Field({
className={cn(fieldVariants({ orientation }), className)}
{...props}
/>
)
);
}
function FieldContent({ className, ...props }: React.ComponentProps<"div">) {
@@ -91,11 +91,11 @@ function FieldContent({ className, ...props }: React.ComponentProps<"div">) {
data-slot="field-content"
className={cn(
"group/field-content flex flex-1 flex-col gap-0.5 leading-snug",
className
className,
)}
{...props}
/>
)
);
}
function FieldLabel({
@@ -108,11 +108,11 @@ function FieldLabel({
className={cn(
"group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50 has-data-checked:border-primary/30 has-data-checked:bg-primary/5 has-[>[data-slot=field]]:rounded-lg has-[>[data-slot=field]]:border *:data-[slot=field]:p-2.5 dark:has-data-checked:border-primary/20 dark:has-data-checked:bg-primary/10",
"has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col",
className
className,
)}
{...props}
/>
)
);
}
function FieldTitle({ className, ...props }: React.ComponentProps<"div">) {
@@ -121,11 +121,11 @@ function FieldTitle({ className, ...props }: React.ComponentProps<"div">) {
data-slot="field-label"
className={cn(
"flex w-fit items-center gap-2 text-sm font-medium group-data-[disabled=true]/field:opacity-50",
className
className,
)}
{...props}
/>
)
);
}
function FieldDescription({ className, ...props }: React.ComponentProps<"p">) {
@@ -136,11 +136,11 @@ function FieldDescription({ className, ...props }: React.ComponentProps<"p">) {
"text-left text-sm leading-normal font-normal text-muted-foreground group-has-data-horizontal/field:text-balance [[data-variant=legend]+&]:-mt-1.5",
"last:mt-0 nth-last-2:-mt-1",
"[&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary",
className
className,
)}
{...props}
/>
)
);
}
function FieldSeparator({
@@ -148,7 +148,7 @@ function FieldSeparator({
className,
...props
}: React.ComponentProps<"div"> & {
children?: React.ReactNode
children?: React.ReactNode;
}) {
return (
<div
@@ -156,7 +156,7 @@ function FieldSeparator({
data-content={!!children}
className={cn(
"relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2",
className
className,
)}
{...props}
>
@@ -170,7 +170,7 @@ function FieldSeparator({
</span>
)}
</div>
)
);
}
function FieldError({
@@ -179,37 +179,37 @@ function FieldError({
errors,
...props
}: React.ComponentProps<"div"> & {
errors?: Array<{ message?: string } | undefined>
errors?: Array<{ message?: string } | undefined>;
}) {
const content = useMemo(() => {
if (children) {
return children
return children;
}
if (!errors?.length) {
return null
return null;
}
const uniqueErrors = [
...new Map(errors.map((error) => [error?.message, error])).values(),
]
];
if (uniqueErrors?.length == 1) {
return uniqueErrors[0]?.message
return uniqueErrors[0]?.message;
}
return (
<ul className="ml-4 flex list-disc flex-col gap-1">
{uniqueErrors.map(
(error, index) =>
error?.message && <li key={index}>{error.message}</li>
error?.message && <li key={index}>{error.message}</li>,
)}
</ul>
)
}, [children, errors])
);
}, [children, errors]);
if (!content) {
return null
return null;
}
return (
@@ -221,7 +221,7 @@ function FieldError({
>
{content}
</div>
)
);
}
export {
@@ -235,4 +235,4 @@ export {
FieldSet,
FieldContent,
FieldTitle,
}
};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+28 -28
View File
@@ -1,10 +1,10 @@
import * as React from "react"
import { mergeProps } from "@base-ui/react/merge-props"
import { useRender } from "@base-ui/react/use-render"
import { cva, type VariantProps } from "class-variance-authority"
import * as React from "react";
import { mergeProps } from "@base-ui/react/merge-props";
import { useRender } from "@base-ui/react/use-render";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils"
import { Separator } from "@/components/ui/separator"
import { cn } from "@/lib/utils";
import { Separator } from "@/components/ui/separator";
function ItemGroup({ className, ...props }: React.ComponentProps<"div">) {
return (
@@ -13,11 +13,11 @@ function ItemGroup({ className, ...props }: React.ComponentProps<"div">) {
data-slot="item-group"
className={cn(
"group/item-group flex w-full flex-col gap-4 has-data-[size=sm]:gap-2.5 has-data-[size=xs]:gap-2",
className
className,
)}
{...props}
/>
)
);
}
function ItemSeparator({
@@ -31,7 +31,7 @@ function ItemSeparator({
className={cn("my-2", className)}
{...props}
/>
)
);
}
const itemVariants = cva(
@@ -53,8 +53,8 @@ const itemVariants = cva(
variant: "default",
size: "default",
},
}
)
},
);
function Item({
className,
@@ -69,7 +69,7 @@ function Item({
{
className: cn(itemVariants({ variant, size, className })),
},
props
props,
),
render,
state: {
@@ -77,7 +77,7 @@ function Item({
variant,
size,
},
})
});
}
const itemMediaVariants = cva(
@@ -94,8 +94,8 @@ const itemMediaVariants = cva(
defaultVariants: {
variant: "default",
},
}
)
},
);
function ItemMedia({
className,
@@ -109,7 +109,7 @@ function ItemMedia({
className={cn(itemMediaVariants({ variant, className }))}
{...props}
/>
)
);
}
function ItemContent({ className, ...props }: React.ComponentProps<"div">) {
@@ -118,11 +118,11 @@ function ItemContent({ className, ...props }: React.ComponentProps<"div">) {
data-slot="item-content"
className={cn(
"flex flex-1 flex-col gap-1 group-data-[size=xs]/item:gap-0 [&+[data-slot=item-content]]:flex-none",
className
className,
)}
{...props}
/>
)
);
}
function ItemTitle({ className, ...props }: React.ComponentProps<"div">) {
@@ -131,11 +131,11 @@ function ItemTitle({ className, ...props }: React.ComponentProps<"div">) {
data-slot="item-title"
className={cn(
"line-clamp-1 flex w-fit items-center gap-2 text-sm leading-snug font-medium underline-offset-4",
className
className,
)}
{...props}
/>
)
);
}
function ItemDescription({ className, ...props }: React.ComponentProps<"p">) {
@@ -144,11 +144,11 @@ function ItemDescription({ className, ...props }: React.ComponentProps<"p">) {
data-slot="item-description"
className={cn(
"line-clamp-2 text-left text-sm leading-normal font-normal text-muted-foreground group-data-[size=xs]/item:text-xs [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary",
className
className,
)}
{...props}
/>
)
);
}
function ItemActions({ className, ...props }: React.ComponentProps<"div">) {
@@ -158,7 +158,7 @@ function ItemActions({ className, ...props }: React.ComponentProps<"div">) {
className={cn("flex items-center gap-2", className)}
{...props}
/>
)
);
}
function ItemHeader({ className, ...props }: React.ComponentProps<"div">) {
@@ -167,11 +167,11 @@ function ItemHeader({ className, ...props }: React.ComponentProps<"div">) {
data-slot="item-header"
className={cn(
"flex basis-full items-center justify-between gap-2",
className
className,
)}
{...props}
/>
)
);
}
function ItemFooter({ className, ...props }: React.ComponentProps<"div">) {
@@ -180,11 +180,11 @@ function ItemFooter({ className, ...props }: React.ComponentProps<"div">) {
data-slot="item-footer"
className={cn(
"flex basis-full items-center justify-between gap-2",
className
className,
)}
{...props}
/>
)
);
}
export {
@@ -198,4 +198,4 @@ export {
ItemDescription,
ItemHeader,
ItemFooter,
}
};
+5 -5
View File
@@ -1,4 +1,4 @@
import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";
function Kbd({ className, ...props }: React.ComponentProps<"kbd">) {
return (
@@ -6,11 +6,11 @@ function Kbd({ className, ...props }: React.ComponentProps<"kbd">) {
data-slot="kbd"
className={cn(
"pointer-events-none inline-flex h-5 w-fit min-w-5 items-center justify-center gap-1 rounded-sm bg-muted px-1 font-sans text-xs font-medium text-muted-foreground select-none in-data-[slot=tooltip-content]:bg-background/20 in-data-[slot=tooltip-content]:text-background dark:in-data-[slot=tooltip-content]:bg-background/10 [&_svg:not([class*='size-'])]:size-3",
className
className,
)}
{...props}
/>
)
);
}
function KbdGroup({ className, ...props }: React.ComponentProps<"div">) {
@@ -20,7 +20,7 @@ function KbdGroup({ className, ...props }: React.ComponentProps<"div">) {
className={cn("inline-flex items-center gap-1", className)}
{...props}
/>
)
);
}
export { Kbd, KbdGroup }
export { Kbd, KbdGroup };
+6 -6
View File
@@ -1,8 +1,8 @@
"use client"
"use client";
import * as React from "react"
import * as React from "react";
import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";
function Label({ className, ...props }: React.ComponentProps<"label">) {
return (
@@ -10,11 +10,11 @@ function Label({ className, ...props }: React.ComponentProps<"label">) {
data-slot="label"
className={cn(
"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
className
className,
)}
{...props}
/>
)
);
}
export { Label }
export { Label };
+14 -14
View File
@@ -1,9 +1,9 @@
import * as React from "react"
import { mergeProps } from "@base-ui/react/merge-props"
import { useRender } from "@base-ui/react/use-render"
import { cva, type VariantProps } from "class-variance-authority"
import * as React from "react";
import { mergeProps } from "@base-ui/react/merge-props";
import { useRender } from "@base-ui/react/use-render";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";
const markerVariants = cva(
"group/marker relative flex min-h-4 w-full items-center gap-2 text-left text-sm text-muted-foreground [&_svg:not([class*='size-'])]:size-4 [a]:underline [a]:underline-offset-3 [a]:hover:text-foreground",
@@ -16,8 +16,8 @@ const markerVariants = cva(
border: "border-b border-border pb-2",
},
},
}
)
},
);
function Marker({
className,
@@ -31,14 +31,14 @@ function Marker({
{
className: cn(markerVariants({ variant, className })),
},
props
props,
),
render,
state: {
slot: "marker",
variant,
},
})
});
}
function MarkerIcon({ className, ...props }: React.ComponentProps<"span">) {
@@ -48,11 +48,11 @@ function MarkerIcon({ className, ...props }: React.ComponentProps<"span">) {
aria-hidden="true"
className={cn(
"size-4 shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
className,
)}
{...props}
/>
)
);
}
function MarkerContent({ className, ...props }: React.ComponentProps<"span">) {
@@ -61,11 +61,11 @@ function MarkerContent({ className, ...props }: React.ComponentProps<"span">) {
data-slot="marker-content"
className={cn(
"min-w-0 wrap-break-word group-data-[variant=separator]/marker:flex-none group-data-[variant=separator]/marker:text-center *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
className
className,
)}
{...props}
/>
)
);
}
export { Marker, MarkerIcon, MarkerContent, markerVariants }
export { Marker, MarkerIcon, MarkerContent, markerVariants };
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+14 -14
View File
@@ -1,6 +1,6 @@
import * as React from "react"
import * as React from "react";
import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";
function MessageGroup({ className, ...props }: React.ComponentProps<"div">) {
return (
@@ -9,7 +9,7 @@ function MessageGroup({ className, ...props }: React.ComponentProps<"div">) {
className={cn("flex min-w-0 flex-col gap-2", className)}
{...props}
/>
)
);
}
function Message({
@@ -23,11 +23,11 @@ function Message({
data-align={align}
className={cn(
"group/message relative flex w-full min-w-0 gap-2 text-sm data-[align=end]:flex-row-reverse",
className
className,
)}
{...props}
/>
)
);
}
function MessageAvatar({ className, ...props }: React.ComponentProps<"div">) {
@@ -36,11 +36,11 @@ function MessageAvatar({ className, ...props }: React.ComponentProps<"div">) {
data-slot="message-avatar"
className={cn(
"flex w-fit min-w-8 shrink-0 items-center justify-center self-end overflow-hidden rounded-full bg-muted group-has-data-[slot=message-footer]/message:-translate-y-8",
className
className,
)}
{...props}
/>
)
);
}
function MessageContent({ className, ...props }: React.ComponentProps<"div">) {
@@ -49,11 +49,11 @@ function MessageContent({ className, ...props }: React.ComponentProps<"div">) {
data-slot="message-content"
className={cn(
"flex w-full min-w-0 flex-col gap-2.5 wrap-break-word group-data-[align=end]/message:*:data-slot:self-end",
className
className,
)}
{...props}
/>
)
);
}
function MessageHeader({ className, ...props }: React.ComponentProps<"div">) {
@@ -62,11 +62,11 @@ function MessageHeader({ className, ...props }: React.ComponentProps<"div">) {
data-slot="message-header"
className={cn(
"flex max-w-full min-w-0 items-center px-3 text-xs font-medium text-muted-foreground group-has-data-[variant=ghost]/message:px-0",
className
className,
)}
{...props}
/>
)
);
}
function MessageFooter({ className, ...props }: React.ComponentProps<"div">) {
@@ -75,11 +75,11 @@ function MessageFooter({ className, ...props }: React.ComponentProps<"div">) {
data-slot="message-footer"
className={cn(
"flex max-w-full min-w-0 items-center px-3 text-xs font-medium text-muted-foreground group-has-data-[variant=ghost]/message:px-0 group-data-[align=end]/message:justify-end",
className
className,
)}
{...props}
/>
)
);
}
export {
@@ -89,4 +89,4 @@ export {
MessageContent,
MessageFooter,
MessageHeader,
}
};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+20 -17
View File
@@ -1,8 +1,12 @@
import * as React from "react"
import * as React from "react";
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import { ChevronLeftIcon, ChevronRightIcon, MoreHorizontalIcon } from "lucide-react"
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import {
ChevronLeftIcon,
ChevronRightIcon,
MoreHorizontalIcon,
} from "lucide-react";
function Pagination({ className, ...props }: React.ComponentProps<"nav">) {
return (
@@ -13,7 +17,7 @@ function Pagination({ className, ...props }: React.ComponentProps<"nav">) {
className={cn("mx-auto flex w-full justify-center", className)}
{...props}
/>
)
);
}
function PaginationContent({
@@ -26,17 +30,17 @@ function PaginationContent({
className={cn("flex items-center gap-0.5", className)}
{...props}
/>
)
);
}
function PaginationItem({ ...props }: React.ComponentProps<"li">) {
return <li data-slot="pagination-item" {...props} />
return <li data-slot="pagination-item" {...props} />;
}
type PaginationLinkProps = {
isActive?: boolean
isActive?: boolean;
} & Pick<React.ComponentProps<typeof Button>, "size"> &
React.ComponentProps<"a">
React.ComponentProps<"a">;
function PaginationLink({
className,
@@ -59,7 +63,7 @@ function PaginationLink({
/>
}
/>
)
);
}
function PaginationPrevious({
@@ -77,7 +81,7 @@ function PaginationPrevious({
<ChevronLeftIcon data-icon="inline-start" />
<span className="hidden sm:block">{text}</span>
</PaginationLink>
)
);
}
function PaginationNext({
@@ -95,7 +99,7 @@ function PaginationNext({
<span className="hidden sm:block">{text}</span>
<ChevronRightIcon data-icon="inline-end" />
</PaginationLink>
)
);
}
function PaginationEllipsis({
@@ -108,15 +112,14 @@ function PaginationEllipsis({
data-slot="pagination-ellipsis"
className={cn(
"flex size-8 items-center justify-center [&_svg:not([class*='size-'])]:size-4",
className
className,
)}
{...props}
>
<MoreHorizontalIcon
/>
<MoreHorizontalIcon />
<span className="sr-only">More pages</span>
</span>
)
);
}
export {
@@ -127,4 +130,4 @@ export {
PaginationLink,
PaginationNext,
PaginationPrevious,
}
};
File diff suppressed because one or more lines are too long
+11 -11
View File
@@ -1,8 +1,8 @@
"use client"
"use client";
import { Progress as ProgressPrimitive } from "@base-ui/react/progress"
import { Progress as ProgressPrimitive } from "@base-ui/react/progress";
import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";
function Progress({
className,
@@ -22,7 +22,7 @@ function Progress({
<ProgressIndicator />
</ProgressTrack>
</ProgressPrimitive.Root>
)
);
}
function ProgressTrack({ className, ...props }: ProgressPrimitive.Track.Props) {
@@ -30,12 +30,12 @@ function ProgressTrack({ className, ...props }: ProgressPrimitive.Track.Props) {
<ProgressPrimitive.Track
className={cn(
"relative flex h-1 w-full items-center overflow-x-hidden rounded-full bg-muted",
className
className,
)}
data-slot="progress-track"
{...props}
/>
)
);
}
function ProgressIndicator({
@@ -48,7 +48,7 @@ function ProgressIndicator({
className={cn("h-full bg-primary transition-all", className)}
{...props}
/>
)
);
}
function ProgressLabel({ className, ...props }: ProgressPrimitive.Label.Props) {
@@ -58,7 +58,7 @@ function ProgressLabel({ className, ...props }: ProgressPrimitive.Label.Props) {
data-slot="progress-label"
{...props}
/>
)
);
}
function ProgressValue({ className, ...props }: ProgressPrimitive.Value.Props) {
@@ -66,12 +66,12 @@ function ProgressValue({ className, ...props }: ProgressPrimitive.Value.Props) {
<ProgressPrimitive.Value
className={cn(
"ml-auto text-sm text-muted-foreground tabular-nums",
className
className,
)}
data-slot="progress-value"
{...props}
/>
)
);
}
export {
@@ -80,4 +80,4 @@ export {
ProgressIndicator,
ProgressLabel,
ProgressValue,
}
};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+8 -8
View File
@@ -1,9 +1,9 @@
"use client"
"use client";
import * as React from "react"
import { ScrollArea as ScrollAreaPrimitive } from "@base-ui/react/scroll-area"
import * as React from "react";
import { ScrollArea as ScrollAreaPrimitive } from "@base-ui/react/scroll-area";
import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";
function ScrollArea({
className,
@@ -25,7 +25,7 @@ function ScrollArea({
<ScrollBar />
<ScrollAreaPrimitive.Corner />
</ScrollAreaPrimitive.Root>
)
);
}
function ScrollBar({
@@ -40,7 +40,7 @@ function ScrollBar({
orientation={orientation}
className={cn(
"flex touch-none p-px transition-colors select-none data-horizontal:h-2.5 data-horizontal:flex-col data-horizontal:border-t data-horizontal:border-t-transparent data-vertical:h-full data-vertical:w-2.5 data-vertical:border-l data-vertical:border-l-transparent",
className
className,
)}
{...props}
>
@@ -49,7 +49,7 @@ function ScrollBar({
className="relative flex-1 rounded-full bg-border"
/>
</ScrollAreaPrimitive.Scrollbar>
)
);
}
export { ScrollArea, ScrollBar }
export { ScrollArea, ScrollBar };
File diff suppressed because one or more lines are too long
+6 -6
View File
@@ -1,8 +1,8 @@
"use client"
"use client";
import { Separator as SeparatorPrimitive } from "@base-ui/react/separator"
import { Separator as SeparatorPrimitive } from "@base-ui/react/separator";
import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";
function Separator({
className,
@@ -15,11 +15,11 @@ function Separator({
orientation={orientation}
className={cn(
"shrink-0 bg-border data-horizontal:h-px data-horizontal:w-full data-vertical:w-px data-vertical:self-stretch",
className
className,
)}
{...props}
/>
)
);
}
export { Separator }
export { Separator };
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3 -3
View File
@@ -1,4 +1,4 @@
import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";
function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
return (
@@ -7,7 +7,7 @@ function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
className={cn("animate-pulse rounded-md bg-muted", className)}
{...props}
/>
)
);
}
export { Skeleton }
export { Skeleton };

Some files were not shown because too many files have changed in this diff Show More