@m5kdev/web-ui 0.1.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/LICENSE +621 -0
- package/README.md +17 -0
- package/package.json +169 -0
- package/src/animations/card.motion.ts +9 -0
- package/src/components/AvatarUpload.tsx +133 -0
- package/src/components/Button.tsx +14 -0
- package/src/components/Calendar.css +684 -0
- package/src/components/Calendar.tsx +32 -0
- package/src/components/CardsSelect.tsx +155 -0
- package/src/components/CollapsibleSidebarMenuItem.tsx +57 -0
- package/src/components/ColorPicker.tsx +56 -0
- package/src/components/CopyButton.tsx +45 -0
- package/src/components/CropDialog.tsx +154 -0
- package/src/components/DialogProvider.tsx +105 -0
- package/src/components/ErrorFallback.tsx +17 -0
- package/src/components/FileDropzone.tsx +120 -0
- package/src/components/MultiSelectDropdown.tsx +233 -0
- package/src/components/Orb.tsx +288 -0
- package/src/components/PageAlert.tsx +121 -0
- package/src/components/SelectChips.tsx +40 -0
- package/src/components/SidebarItem.tsx +26 -0
- package/src/components/Steps.tsx +340 -0
- package/src/components/TablerIconPicker.tsx +4260 -0
- package/src/components/app-header.tsx +40 -0
- package/src/components/blur-card.tsx +132 -0
- package/src/components/features-section-demo-1.tsx +127 -0
- package/src/components/features-section-demo-2.tsx +102 -0
- package/src/components/features-section-demo-3.tsx +272 -0
- package/src/components/mode-toggle.tsx +31 -0
- package/src/components/nav-main.tsx +69 -0
- package/src/components/pricing-cards.tsx +133 -0
- package/src/components/shared/ButtonCopy.tsx +50 -0
- package/src/components/team-switcher.tsx +83 -0
- package/src/components/theme-provider.tsx +74 -0
- package/src/components/typewriter.tsx +90 -0
- package/src/components/ui/alert-dialog.tsx +133 -0
- package/src/components/ui/alert.tsx +60 -0
- package/src/components/ui/avatar.tsx +47 -0
- package/src/components/ui/badge.tsx +33 -0
- package/src/components/ui/bento-grid.tsx +54 -0
- package/src/components/ui/bento-grid2.tsx +66 -0
- package/src/components/ui/breadcrumb.tsx +101 -0
- package/src/components/ui/button.tsx +50 -0
- package/src/components/ui/card.tsx +55 -0
- package/src/components/ui/checkbox.tsx +26 -0
- package/src/components/ui/collapsible.tsx +9 -0
- package/src/components/ui/dialog.tsx +119 -0
- package/src/components/ui/dropdown-menu.tsx +186 -0
- package/src/components/ui/floating-navbar.tsx +78 -0
- package/src/components/ui/form.tsx +167 -0
- package/src/components/ui/image.tsx +55 -0
- package/src/components/ui/input.tsx +22 -0
- package/src/components/ui/label.tsx +19 -0
- package/src/components/ui/pagination.tsx +105 -0
- package/src/components/ui/progress.tsx +23 -0
- package/src/components/ui/resizable-navbar.tsx +260 -0
- package/src/components/ui/segment-control.tsx +143 -0
- package/src/components/ui/select.tsx +153 -0
- package/src/components/ui/separator.tsx +24 -0
- package/src/components/ui/sheet.tsx +121 -0
- package/src/components/ui/sidebar.tsx +736 -0
- package/src/components/ui/skeleton.tsx +7 -0
- package/src/components/ui/slider.tsx +23 -0
- package/src/components/ui/sonner.tsx +27 -0
- package/src/components/ui/spinner.tsx +45 -0
- package/src/components/ui/switch.tsx +27 -0
- package/src/components/ui/table.tsx +90 -0
- package/src/components/ui/tabs.tsx +52 -0
- package/src/components/ui/textarea.tsx +18 -0
- package/src/components/ui/timeline.tsx +95 -0
- package/src/components/ui/toast.tsx +126 -0
- package/src/components/ui/tooltip.tsx +55 -0
- package/src/components/ui/typewriter-effect.tsx +181 -0
- package/src/hooks/use-mobile.ts +19 -0
- package/src/hooks/useDialog.ts +25 -0
- package/src/icons/GoogleIcon.tsx +32 -0
- package/src/icons/LinkedInIcon.tsx +30 -0
- package/src/icons/MicrosoftIcon.tsx +21 -0
- package/src/lib/chatwoot.ts +51 -0
- package/src/lib/utils.ts +6 -0
- package/src/modules/app/components/AppLoader.tsx +9 -0
- package/src/modules/app/components/AppShell.tsx +21 -0
- package/src/modules/app/components/AppSidebar.tsx +26 -0
- package/src/modules/app/components/AppSidebarContent.tsx +73 -0
- package/src/modules/app/components/AppSidebarHeader.tsx +57 -0
- package/src/modules/app/components/AppSidebarInvites.tsx +32 -0
- package/src/modules/app/components/AppSidebarUser.tsx +128 -0
- package/src/modules/auth/components/AdminUserManagement.tsx +1136 -0
- package/src/modules/auth/components/AdminWaitlist.tsx +358 -0
- package/src/modules/auth/components/AuthLayout.tsx +13 -0
- package/src/modules/auth/components/AuthProviders.tsx +105 -0
- package/src/modules/auth/components/AuthRouter.tsx +29 -0
- package/src/modules/auth/components/ClaimAccountRoute.tsx +242 -0
- package/src/modules/auth/components/ErrorAuthRoute.tsx +121 -0
- package/src/modules/auth/components/ForgotPasswordForm.tsx +58 -0
- package/src/modules/auth/components/ForgotPasswordRoute.tsx +27 -0
- package/src/modules/auth/components/InviteFriends.tsx +273 -0
- package/src/modules/auth/components/LastUsedBadge.tsx +22 -0
- package/src/modules/auth/components/LoginForm.tsx +104 -0
- package/src/modules/auth/components/LoginRoute.tsx +31 -0
- package/src/modules/auth/components/LogoutRoute.tsx +21 -0
- package/src/modules/auth/components/OrganizationAcceptInvitationRoute.tsx +161 -0
- package/src/modules/auth/components/OrganizationMembersRoute.tsx +730 -0
- package/src/modules/auth/components/OrganizationSettingsRoute.tsx +280 -0
- package/src/modules/auth/components/OrganizationSwitcher.tsx +148 -0
- package/src/modules/auth/components/ProfileRoute.tsx +104 -0
- package/src/modules/auth/components/RangeNuqsDatePicker.tsx +365 -0
- package/src/modules/auth/components/ResetPasswordForm.tsx +103 -0
- package/src/modules/auth/components/ResetPasswordRoute.tsx +27 -0
- package/src/modules/auth/components/SignupFormRoute.tsx +189 -0
- package/src/modules/auth/components/SignupRoute.tsx +53 -0
- package/src/modules/auth/components/UserPreferences.tsx +144 -0
- package/src/modules/auth/components/WaitlistCard.tsx +78 -0
- package/src/modules/auth/components/WaitlistCodeValidation.tsx +79 -0
- package/src/modules/billing/components/BillingBetaPage.tsx +124 -0
- package/src/modules/billing/components/BillingInvoicePage.tsx +180 -0
- package/src/modules/billing/components/BillingPlanSelect.tsx +14 -0
- package/src/modules/billing/components/BillingRouter.tsx +20 -0
- package/src/modules/billing/components/BillingSinglePlanSelect.tsx +172 -0
- package/src/modules/table/components/ColumnOrderAndVisibility.tsx +127 -0
- package/src/modules/table/components/NuqsTable.tsx +396 -0
- package/src/modules/table/components/TableFiltering.tsx +520 -0
- package/src/modules/table/components/TablePagination.tsx +59 -0
- package/src/modules/table/components/table.types.ts +11 -0
- package/src/modules/table/filterTransformers.ts +323 -0
- package/src/types.ts +4 -0
- package/src/vite-env.d.ts +1 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
2
|
+
import type * as React from "react";
|
|
3
|
+
|
|
4
|
+
import { cn } from "#utils";
|
|
5
|
+
|
|
6
|
+
const alertVariants = cva(
|
|
7
|
+
"relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
|
|
8
|
+
{
|
|
9
|
+
variants: {
|
|
10
|
+
variant: {
|
|
11
|
+
default: "bg-card text-card-foreground",
|
|
12
|
+
destructive:
|
|
13
|
+
"text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
defaultVariants: {
|
|
17
|
+
variant: "default",
|
|
18
|
+
},
|
|
19
|
+
}
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
function Alert({
|
|
23
|
+
className,
|
|
24
|
+
variant,
|
|
25
|
+
...props
|
|
26
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) {
|
|
27
|
+
return (
|
|
28
|
+
<div
|
|
29
|
+
data-slot="alert"
|
|
30
|
+
role="alert"
|
|
31
|
+
className={cn(alertVariants({ variant }), className)}
|
|
32
|
+
{...props}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
38
|
+
return (
|
|
39
|
+
<div
|
|
40
|
+
data-slot="alert-title"
|
|
41
|
+
className={cn("col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight", className)}
|
|
42
|
+
{...props}
|
|
43
|
+
/>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function AlertDescription({ className, ...props }: React.ComponentProps<"div">) {
|
|
48
|
+
return (
|
|
49
|
+
<div
|
|
50
|
+
data-slot="alert-description"
|
|
51
|
+
className={cn(
|
|
52
|
+
"text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed",
|
|
53
|
+
className
|
|
54
|
+
)}
|
|
55
|
+
{...props}
|
|
56
|
+
/>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export { Alert, AlertTitle, AlertDescription };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
|
|
6
|
+
import { cn } from "#utils";
|
|
7
|
+
|
|
8
|
+
const Avatar = React.forwardRef<
|
|
9
|
+
React.ElementRef<typeof AvatarPrimitive.Root>,
|
|
10
|
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
|
|
11
|
+
>(({ className, ...props }, ref) => (
|
|
12
|
+
<AvatarPrimitive.Root
|
|
13
|
+
ref={ref}
|
|
14
|
+
className={cn("relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", className)}
|
|
15
|
+
{...props}
|
|
16
|
+
/>
|
|
17
|
+
));
|
|
18
|
+
Avatar.displayName = AvatarPrimitive.Root.displayName;
|
|
19
|
+
|
|
20
|
+
const AvatarImage = React.forwardRef<
|
|
21
|
+
React.ElementRef<typeof AvatarPrimitive.Image>,
|
|
22
|
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
|
|
23
|
+
>(({ className, ...props }, ref) => (
|
|
24
|
+
<AvatarPrimitive.Image
|
|
25
|
+
ref={ref}
|
|
26
|
+
className={cn("aspect-square h-full w-full", className)}
|
|
27
|
+
{...props}
|
|
28
|
+
/>
|
|
29
|
+
));
|
|
30
|
+
AvatarImage.displayName = AvatarPrimitive.Image.displayName;
|
|
31
|
+
|
|
32
|
+
const AvatarFallback = React.forwardRef<
|
|
33
|
+
React.ElementRef<typeof AvatarPrimitive.Fallback>,
|
|
34
|
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
|
|
35
|
+
>(({ className, ...props }, ref) => (
|
|
36
|
+
<AvatarPrimitive.Fallback
|
|
37
|
+
ref={ref}
|
|
38
|
+
className={cn(
|
|
39
|
+
"flex h-full w-full items-center justify-center rounded-full bg-muted",
|
|
40
|
+
className
|
|
41
|
+
)}
|
|
42
|
+
{...props}
|
|
43
|
+
/>
|
|
44
|
+
));
|
|
45
|
+
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
|
|
46
|
+
|
|
47
|
+
export { Avatar, AvatarImage, AvatarFallback };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
2
|
+
import type * as React from "react";
|
|
3
|
+
|
|
4
|
+
import { cn } from "#utils";
|
|
5
|
+
|
|
6
|
+
const badgeVariants = cva(
|
|
7
|
+
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
8
|
+
{
|
|
9
|
+
variants: {
|
|
10
|
+
variant: {
|
|
11
|
+
default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
|
|
12
|
+
secondary:
|
|
13
|
+
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
14
|
+
destructive:
|
|
15
|
+
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
|
|
16
|
+
outline: "text-foreground",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
defaultVariants: {
|
|
20
|
+
variant: "default",
|
|
21
|
+
},
|
|
22
|
+
}
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
export interface BadgeProps
|
|
26
|
+
extends React.HTMLAttributes<HTMLDivElement>,
|
|
27
|
+
VariantProps<typeof badgeVariants> {}
|
|
28
|
+
|
|
29
|
+
function Badge({ className, variant, ...props }: BadgeProps) {
|
|
30
|
+
return <div className={cn(badgeVariants({ variant }), className)} {...props} />;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export { Badge, badgeVariants };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { cn } from "#utils";
|
|
2
|
+
|
|
3
|
+
export const BentoGrid = ({
|
|
4
|
+
className,
|
|
5
|
+
children,
|
|
6
|
+
}: {
|
|
7
|
+
className?: string;
|
|
8
|
+
children?: React.ReactNode;
|
|
9
|
+
}) => {
|
|
10
|
+
return (
|
|
11
|
+
<div
|
|
12
|
+
className={cn(
|
|
13
|
+
"mx-auto grid max-w-7xl grid-cols-1 gap-4 md:auto-rows-[20rem] md:grid-cols-4",
|
|
14
|
+
className
|
|
15
|
+
)}
|
|
16
|
+
>
|
|
17
|
+
{children}
|
|
18
|
+
</div>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const BentoGridItem = ({
|
|
23
|
+
className,
|
|
24
|
+
title,
|
|
25
|
+
description,
|
|
26
|
+
header,
|
|
27
|
+
icon,
|
|
28
|
+
}: {
|
|
29
|
+
className?: string;
|
|
30
|
+
title?: string | React.ReactNode;
|
|
31
|
+
description?: string | React.ReactNode;
|
|
32
|
+
header?: React.ReactNode;
|
|
33
|
+
icon?: React.ReactNode;
|
|
34
|
+
}) => {
|
|
35
|
+
return (
|
|
36
|
+
<div
|
|
37
|
+
className={cn(
|
|
38
|
+
"group/bento shadow-input row-span-1 flex flex-col justify-between space-y-4 rounded-xl border border-neutral-200 bg-white p-4 transition duration-200 hover:shadow-xl dark:border-white/[0.2] dark:bg-black dark:shadow-none",
|
|
39
|
+
className
|
|
40
|
+
)}
|
|
41
|
+
>
|
|
42
|
+
{header}
|
|
43
|
+
<div className="transition duration-200 group-hover/bento:translate-x-2">
|
|
44
|
+
{icon}
|
|
45
|
+
<div className="mt-2 mb-2 font-sans font-bold text-neutral-600 dark:text-neutral-200 text-lg">
|
|
46
|
+
{title}
|
|
47
|
+
</div>
|
|
48
|
+
<div className="font-sans text-sm font-normal text-neutral-600 dark:text-neutral-300">
|
|
49
|
+
{description}
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
);
|
|
54
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { IconArrowRight } from "@tabler/icons-react";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
import { Button } from "#components/ui/button";
|
|
5
|
+
import { cn } from "#utils";
|
|
6
|
+
|
|
7
|
+
const BentoGrid = ({ children, className }: { children: ReactNode; className?: string }) => {
|
|
8
|
+
return (
|
|
9
|
+
<div className={cn("grid w-full auto-rows-[22rem] grid-cols-3 gap-4", className)}>
|
|
10
|
+
{children}
|
|
11
|
+
</div>
|
|
12
|
+
);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const BentoCard = ({
|
|
16
|
+
name,
|
|
17
|
+
className,
|
|
18
|
+
background,
|
|
19
|
+
Icon,
|
|
20
|
+
description,
|
|
21
|
+
href,
|
|
22
|
+
cta,
|
|
23
|
+
}: {
|
|
24
|
+
name: string;
|
|
25
|
+
className: string;
|
|
26
|
+
background: ReactNode;
|
|
27
|
+
Icon: any;
|
|
28
|
+
description: string;
|
|
29
|
+
href: string;
|
|
30
|
+
cta: string;
|
|
31
|
+
}) => (
|
|
32
|
+
<div
|
|
33
|
+
key={name}
|
|
34
|
+
className={cn(
|
|
35
|
+
"group relative flex flex-col justify-between overflow-hidden rounded-xl h-60",
|
|
36
|
+
// light styles
|
|
37
|
+
"bg-white [box-shadow:0_0_0_1px_rgba(0,0,0,.03),0_2px_4px_rgba(0,0,0,.05),0_12px_24px_rgba(0,0,0,.05)]",
|
|
38
|
+
// dark styles
|
|
39
|
+
"transform-gpu dark:bg-black dark:[border:1px_solid_rgba(255,255,255,.1)] dark:[box-shadow:0_-20px_80px_-20px_#ffffff1f_inset]",
|
|
40
|
+
className
|
|
41
|
+
)}
|
|
42
|
+
>
|
|
43
|
+
<div>{background}</div>
|
|
44
|
+
<div className="pointer-events-none z-10 flex transform-gpu flex-col gap-1 p-6 transition-all duration-300 group-hover:-translate-y-10">
|
|
45
|
+
<Icon className="h-12 w-12 origin-left transform-gpu text-neutral-700 transition-all duration-300 ease-in-out group-hover:scale-75" />
|
|
46
|
+
<h3 className="text-xl font-semibold text-neutral-700 dark:text-neutral-300">{name}</h3>
|
|
47
|
+
<p className="max-w-lg text-neutral-400">{description}</p>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<div
|
|
51
|
+
className={cn(
|
|
52
|
+
"pointer-events-none absolute bottom-0 flex w-full translate-y-10 transform-gpu flex-row items-center p-4 opacity-0 transition-all duration-300 group-hover:translate-y-0 group-hover:opacity-100"
|
|
53
|
+
)}
|
|
54
|
+
>
|
|
55
|
+
<Button variant="ghost" asChild size="sm" className="pointer-events-auto">
|
|
56
|
+
<a href={href}>
|
|
57
|
+
{cta}
|
|
58
|
+
<IconArrowRight className="ml-2 h-4 w-4" />
|
|
59
|
+
</a>
|
|
60
|
+
</Button>
|
|
61
|
+
</div>
|
|
62
|
+
<div className="pointer-events-none absolute inset-0 transform-gpu transition-all duration-300 group-hover:bg-black/[.03] group-hover:dark:bg-neutral-800/10" />
|
|
63
|
+
</div>
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
export { BentoCard, BentoGrid };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
2
|
+
import { ChevronRight, MoreHorizontal } from "lucide-react";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
|
|
5
|
+
import { cn } from "#utils";
|
|
6
|
+
|
|
7
|
+
const Breadcrumb = React.forwardRef<
|
|
8
|
+
HTMLElement,
|
|
9
|
+
React.ComponentPropsWithoutRef<"nav"> & {
|
|
10
|
+
separator?: React.ReactNode;
|
|
11
|
+
}
|
|
12
|
+
>(({ ...props }, ref) => <nav ref={ref} aria-label="breadcrumb" {...props} />);
|
|
13
|
+
Breadcrumb.displayName = "Breadcrumb";
|
|
14
|
+
|
|
15
|
+
const BreadcrumbList = React.forwardRef<HTMLOListElement, React.ComponentPropsWithoutRef<"ol">>(
|
|
16
|
+
({ className, ...props }, ref) => (
|
|
17
|
+
<ol
|
|
18
|
+
ref={ref}
|
|
19
|
+
className={cn(
|
|
20
|
+
"flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5",
|
|
21
|
+
className
|
|
22
|
+
)}
|
|
23
|
+
{...props}
|
|
24
|
+
/>
|
|
25
|
+
)
|
|
26
|
+
);
|
|
27
|
+
BreadcrumbList.displayName = "BreadcrumbList";
|
|
28
|
+
|
|
29
|
+
const BreadcrumbItem = React.forwardRef<HTMLLIElement, React.ComponentPropsWithoutRef<"li">>(
|
|
30
|
+
({ className, ...props }, ref) => (
|
|
31
|
+
<li ref={ref} className={cn("inline-flex items-center gap-1.5", className)} {...props} />
|
|
32
|
+
)
|
|
33
|
+
);
|
|
34
|
+
BreadcrumbItem.displayName = "BreadcrumbItem";
|
|
35
|
+
|
|
36
|
+
const BreadcrumbLink = React.forwardRef<
|
|
37
|
+
HTMLAnchorElement,
|
|
38
|
+
React.ComponentPropsWithoutRef<"a"> & {
|
|
39
|
+
asChild?: boolean;
|
|
40
|
+
}
|
|
41
|
+
>(({ asChild, className, ...props }, ref) => {
|
|
42
|
+
const Comp = asChild ? Slot : "a";
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<Comp
|
|
46
|
+
ref={ref}
|
|
47
|
+
className={cn("transition-colors hover:text-foreground", className)}
|
|
48
|
+
{...props}
|
|
49
|
+
/>
|
|
50
|
+
);
|
|
51
|
+
});
|
|
52
|
+
BreadcrumbLink.displayName = "BreadcrumbLink";
|
|
53
|
+
|
|
54
|
+
const BreadcrumbPage = React.forwardRef<HTMLSpanElement, React.ComponentPropsWithoutRef<"span">>(
|
|
55
|
+
({ className, ...props }, ref) => (
|
|
56
|
+
<span
|
|
57
|
+
ref={ref}
|
|
58
|
+
// role="link"
|
|
59
|
+
aria-disabled="true"
|
|
60
|
+
aria-current="page"
|
|
61
|
+
className={cn("font-normal text-foreground", className)}
|
|
62
|
+
{...props}
|
|
63
|
+
/>
|
|
64
|
+
)
|
|
65
|
+
);
|
|
66
|
+
BreadcrumbPage.displayName = "BreadcrumbPage";
|
|
67
|
+
|
|
68
|
+
const BreadcrumbSeparator = ({ children, className, ...props }: React.ComponentProps<"li">) => (
|
|
69
|
+
<li
|
|
70
|
+
role="presentation"
|
|
71
|
+
aria-hidden="true"
|
|
72
|
+
className={cn("[&>svg]:w-3.5 [&>svg]:h-3.5", className)}
|
|
73
|
+
{...props}
|
|
74
|
+
>
|
|
75
|
+
{children ?? <ChevronRight />}
|
|
76
|
+
</li>
|
|
77
|
+
);
|
|
78
|
+
BreadcrumbSeparator.displayName = "BreadcrumbSeparator";
|
|
79
|
+
|
|
80
|
+
const BreadcrumbEllipsis = ({ className, ...props }: React.ComponentProps<"span">) => (
|
|
81
|
+
<span
|
|
82
|
+
role="presentation"
|
|
83
|
+
aria-hidden="true"
|
|
84
|
+
className={cn("flex h-9 w-9 items-center justify-center", className)}
|
|
85
|
+
{...props}
|
|
86
|
+
>
|
|
87
|
+
<MoreHorizontal className="h-4 w-4" />
|
|
88
|
+
<span className="sr-only">More</span>
|
|
89
|
+
</span>
|
|
90
|
+
);
|
|
91
|
+
BreadcrumbEllipsis.displayName = "BreadcrumbElipssis";
|
|
92
|
+
|
|
93
|
+
export {
|
|
94
|
+
Breadcrumb,
|
|
95
|
+
BreadcrumbList,
|
|
96
|
+
BreadcrumbItem,
|
|
97
|
+
BreadcrumbLink,
|
|
98
|
+
BreadcrumbPage,
|
|
99
|
+
BreadcrumbSeparator,
|
|
100
|
+
BreadcrumbEllipsis,
|
|
101
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
|
|
5
|
+
import { cn } from "#utils";
|
|
6
|
+
|
|
7
|
+
const buttonVariants = cva(
|
|
8
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
|
|
13
|
+
destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
|
14
|
+
outline:
|
|
15
|
+
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
|
16
|
+
secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
|
17
|
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
18
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
19
|
+
},
|
|
20
|
+
size: {
|
|
21
|
+
default: "h-9 px-4 py-2",
|
|
22
|
+
sm: "h-8 rounded-md px-3 text-xs",
|
|
23
|
+
lg: "h-10 rounded-md px-8",
|
|
24
|
+
icon: "h-9 w-9",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
defaultVariants: {
|
|
28
|
+
variant: "default",
|
|
29
|
+
size: "default",
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
export interface ButtonProps
|
|
35
|
+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
36
|
+
VariantProps<typeof buttonVariants> {
|
|
37
|
+
asChild?: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
41
|
+
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
42
|
+
const Comp = asChild ? Slot : "button";
|
|
43
|
+
return (
|
|
44
|
+
<Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} />
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
Button.displayName = "Button";
|
|
49
|
+
|
|
50
|
+
export { Button, buttonVariants };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
import { cn } from "#utils";
|
|
4
|
+
|
|
5
|
+
const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
6
|
+
({ className, ...props }, ref) => (
|
|
7
|
+
<div
|
|
8
|
+
ref={ref}
|
|
9
|
+
className={cn("rounded-xl border bg-card text-card-foreground shadow", className)}
|
|
10
|
+
{...props}
|
|
11
|
+
/>
|
|
12
|
+
)
|
|
13
|
+
);
|
|
14
|
+
Card.displayName = "Card";
|
|
15
|
+
|
|
16
|
+
const CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
17
|
+
({ className, ...props }, ref) => (
|
|
18
|
+
<div ref={ref} className={cn("flex flex-col space-y-1.5 p-6", className)} {...props} />
|
|
19
|
+
)
|
|
20
|
+
);
|
|
21
|
+
CardHeader.displayName = "CardHeader";
|
|
22
|
+
|
|
23
|
+
const CardTitle = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
24
|
+
({ className, ...props }, ref) => (
|
|
25
|
+
<div
|
|
26
|
+
ref={ref}
|
|
27
|
+
className={cn("font-semibold leading-none tracking-tight", className)}
|
|
28
|
+
{...props}
|
|
29
|
+
/>
|
|
30
|
+
)
|
|
31
|
+
);
|
|
32
|
+
CardTitle.displayName = "CardTitle";
|
|
33
|
+
|
|
34
|
+
const CardDescription = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
35
|
+
({ className, ...props }, ref) => (
|
|
36
|
+
<div ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} />
|
|
37
|
+
)
|
|
38
|
+
);
|
|
39
|
+
CardDescription.displayName = "CardDescription";
|
|
40
|
+
|
|
41
|
+
const CardContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
42
|
+
({ className, ...props }, ref) => (
|
|
43
|
+
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
|
|
44
|
+
)
|
|
45
|
+
);
|
|
46
|
+
CardContent.displayName = "CardContent";
|
|
47
|
+
|
|
48
|
+
const CardFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
49
|
+
({ className, ...props }, ref) => (
|
|
50
|
+
<div ref={ref} className={cn("flex items-center p-6 pt-0", className)} {...props} />
|
|
51
|
+
)
|
|
52
|
+
);
|
|
53
|
+
CardFooter.displayName = "CardFooter";
|
|
54
|
+
|
|
55
|
+
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
|
|
2
|
+
import { Check } from "lucide-react";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
|
|
5
|
+
import { cn } from "#utils";
|
|
6
|
+
|
|
7
|
+
const Checkbox = React.forwardRef<
|
|
8
|
+
React.ElementRef<typeof CheckboxPrimitive.Root>,
|
|
9
|
+
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
|
|
10
|
+
>(({ className, ...props }, ref) => (
|
|
11
|
+
<CheckboxPrimitive.Root
|
|
12
|
+
ref={ref}
|
|
13
|
+
className={cn(
|
|
14
|
+
"peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
|
|
15
|
+
className
|
|
16
|
+
)}
|
|
17
|
+
{...props}
|
|
18
|
+
>
|
|
19
|
+
<CheckboxPrimitive.Indicator className={cn("flex items-center justify-center text-current")}>
|
|
20
|
+
<Check className="h-4 w-4" />
|
|
21
|
+
</CheckboxPrimitive.Indicator>
|
|
22
|
+
</CheckboxPrimitive.Root>
|
|
23
|
+
));
|
|
24
|
+
Checkbox.displayName = CheckboxPrimitive.Root.displayName;
|
|
25
|
+
|
|
26
|
+
export { Checkbox };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
|
|
2
|
+
|
|
3
|
+
const Collapsible = CollapsiblePrimitive.Root;
|
|
4
|
+
|
|
5
|
+
const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger;
|
|
6
|
+
|
|
7
|
+
const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent;
|
|
8
|
+
|
|
9
|
+
export { Collapsible, CollapsibleTrigger, CollapsibleContent };
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
2
|
+
import { XIcon } from "lucide-react";
|
|
3
|
+
import type * as React from "react";
|
|
4
|
+
|
|
5
|
+
import { cn } from "#utils";
|
|
6
|
+
|
|
7
|
+
function Dialog({ ...props }: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
|
8
|
+
return <DialogPrimitive.Root data-slot="dialog" {...props} />;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function DialogTrigger({ ...props }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
|
12
|
+
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function DialogPortal({ ...props }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
|
16
|
+
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function DialogClose({ ...props }: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
|
20
|
+
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function DialogOverlay({
|
|
24
|
+
className,
|
|
25
|
+
...props
|
|
26
|
+
}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
|
|
27
|
+
return (
|
|
28
|
+
<DialogPrimitive.Overlay
|
|
29
|
+
data-slot="dialog-overlay"
|
|
30
|
+
className={cn(
|
|
31
|
+
"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/80",
|
|
32
|
+
className
|
|
33
|
+
)}
|
|
34
|
+
{...props}
|
|
35
|
+
/>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function DialogContent({
|
|
40
|
+
className,
|
|
41
|
+
children,
|
|
42
|
+
...props
|
|
43
|
+
}: React.ComponentProps<typeof DialogPrimitive.Content>) {
|
|
44
|
+
return (
|
|
45
|
+
<DialogPortal data-slot="dialog-portal">
|
|
46
|
+
<DialogOverlay />
|
|
47
|
+
<DialogPrimitive.Content
|
|
48
|
+
data-slot="dialog-content"
|
|
49
|
+
className={cn(
|
|
50
|
+
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
|
|
51
|
+
className
|
|
52
|
+
)}
|
|
53
|
+
{...props}
|
|
54
|
+
>
|
|
55
|
+
{children}
|
|
56
|
+
<DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground 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 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4">
|
|
57
|
+
<XIcon />
|
|
58
|
+
<span className="sr-only">Close</span>
|
|
59
|
+
</DialogPrimitive.Close>
|
|
60
|
+
</DialogPrimitive.Content>
|
|
61
|
+
</DialogPortal>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
66
|
+
return (
|
|
67
|
+
<div
|
|
68
|
+
data-slot="dialog-header"
|
|
69
|
+
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
|
|
70
|
+
{...props}
|
|
71
|
+
/>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
76
|
+
return (
|
|
77
|
+
<div
|
|
78
|
+
data-slot="dialog-footer"
|
|
79
|
+
className={cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className)}
|
|
80
|
+
{...props}
|
|
81
|
+
/>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function DialogTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>) {
|
|
86
|
+
return (
|
|
87
|
+
<DialogPrimitive.Title
|
|
88
|
+
data-slot="dialog-title"
|
|
89
|
+
className={cn("text-lg leading-none font-semibold", className)}
|
|
90
|
+
{...props}
|
|
91
|
+
/>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function DialogDescription({
|
|
96
|
+
className,
|
|
97
|
+
...props
|
|
98
|
+
}: React.ComponentProps<typeof DialogPrimitive.Description>) {
|
|
99
|
+
return (
|
|
100
|
+
<DialogPrimitive.Description
|
|
101
|
+
data-slot="dialog-description"
|
|
102
|
+
className={cn("text-muted-foreground text-sm", className)}
|
|
103
|
+
{...props}
|
|
104
|
+
/>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export {
|
|
109
|
+
Dialog,
|
|
110
|
+
DialogClose,
|
|
111
|
+
DialogContent,
|
|
112
|
+
DialogDescription,
|
|
113
|
+
DialogFooter,
|
|
114
|
+
DialogHeader,
|
|
115
|
+
DialogOverlay,
|
|
116
|
+
DialogPortal,
|
|
117
|
+
DialogTitle,
|
|
118
|
+
DialogTrigger,
|
|
119
|
+
};
|