@bearmenu/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/dist/chunk-2CUFS5LF.js +80 -0
- package/dist/chunk-3GWWZKX7.js +33 -0
- package/dist/chunk-3VMDCCCX.js +10 -0
- package/dist/chunk-4AVS6CV4.js +89 -0
- package/dist/chunk-4JOV7FXW.js +17 -0
- package/dist/chunk-4KOMHDZD.js +89 -0
- package/dist/chunk-4UO73SKC.js +26 -0
- package/dist/chunk-7H54PTVH.js +116 -0
- package/dist/chunk-CW24PLDW.js +24 -0
- package/dist/chunk-EBAMCZDW.js +112 -0
- package/dist/chunk-ERMIA7NP.js +106 -0
- package/dist/chunk-ESO2EM3L.js +46 -0
- package/dist/chunk-EUHEIWHZ.js +32 -0
- package/dist/chunk-FEK5XGZW.js +8 -0
- package/dist/chunk-NKHH23YK.js +31 -0
- package/dist/chunk-R47NEOSI.js +78 -0
- package/dist/chunk-UXAYXRFN.js +69 -0
- package/dist/chunk-X6GATUI2.js +19 -0
- package/dist/components/accordion.d.ts +9 -0
- package/dist/components/accordion.js +53 -0
- package/dist/components/alert-dialog.d.ts +23 -0
- package/dist/components/alert-dialog.js +98 -0
- package/dist/components/alert.d.ts +11 -0
- package/dist/components/alert.js +52 -0
- package/dist/components/aspect-ratio.d.ts +6 -0
- package/dist/components/aspect-ratio.js +2 -0
- package/dist/components/avatar.d.ts +8 -0
- package/dist/components/avatar.js +47 -0
- package/dist/components/badge.d.ts +13 -0
- package/dist/components/badge.js +3 -0
- package/dist/components/breadcrumb.d.ts +14 -0
- package/dist/components/breadcrumb.js +96 -0
- package/dist/components/button.d.ts +16 -0
- package/dist/components/button.js +4 -0
- package/dist/components/calendar.d.ts +11 -0
- package/dist/components/calendar.js +56 -0
- package/dist/components/card.d.ts +13 -0
- package/dist/components/card.js +4 -0
- package/dist/components/carousel.d.ts +24 -0
- package/dist/components/carousel.js +198 -0
- package/dist/components/checkbox.d.ts +6 -0
- package/dist/components/checkbox.js +25 -0
- package/dist/components/collapsible.d.ts +8 -0
- package/dist/components/collapsible.js +26 -0
- package/dist/components/command.d.ts +84 -0
- package/dist/components/command.js +4 -0
- package/dist/components/currency-input.d.ts +17 -0
- package/dist/components/currency-input.js +121 -0
- package/dist/components/dialog.d.ts +22 -0
- package/dist/components/dialog.js +3 -0
- package/dist/components/drawer.d.ts +27 -0
- package/dist/components/drawer.js +85 -0
- package/dist/components/dropdown-menu.d.ts +28 -0
- package/dist/components/dropdown-menu.js +211 -0
- package/dist/components/empty-state.d.ts +22 -0
- package/dist/components/empty-state.js +81 -0
- package/dist/components/form.d.ts +28 -0
- package/dist/components/form.js +97 -0
- package/dist/components/haptic-button.d.ts +12 -0
- package/dist/components/haptic-button.js +17 -0
- package/dist/components/input-otp.d.ts +14 -0
- package/dist/components/input-otp.js +62 -0
- package/dist/components/input.d.ts +6 -0
- package/dist/components/input.js +3 -0
- package/dist/components/label.d.ts +8 -0
- package/dist/components/label.js +3 -0
- package/dist/components/lazy-markdown.d.ts +11 -0
- package/dist/components/lazy-markdown.js +13 -0
- package/dist/components/link-button.d.ts +30 -0
- package/dist/components/link-button.js +17 -0
- package/dist/components/markdown-renderer.d.ts +11 -0
- package/dist/components/markdown-renderer.js +10 -0
- package/dist/components/multi-select-combobox.d.ts +23 -0
- package/dist/components/multi-select-combobox.js +114 -0
- package/dist/components/pagination.d.ts +18 -0
- package/dist/components/pagination.js +101 -0
- package/dist/components/popover.d.ts +8 -0
- package/dist/components/popover.js +3 -0
- package/dist/components/progress.d.ts +6 -0
- package/dist/components/progress.js +30 -0
- package/dist/components/radio-group.d.ts +7 -0
- package/dist/components/radio-group.js +30 -0
- package/dist/components/rating.d.ts +15 -0
- package/dist/components/rating.js +120 -0
- package/dist/components/scroll-area.d.ts +7 -0
- package/dist/components/scroll-area.js +44 -0
- package/dist/components/search-bar.d.ts +17 -0
- package/dist/components/search-bar.js +92 -0
- package/dist/components/searchable-select.d.ts +22 -0
- package/dist/components/searchable-select.js +104 -0
- package/dist/components/select.d.ts +15 -0
- package/dist/components/select.js +129 -0
- package/dist/components/separator.d.ts +6 -0
- package/dist/components/separator.js +25 -0
- package/dist/components/sheet.d.ts +29 -0
- package/dist/components/sheet.js +96 -0
- package/dist/components/skeleton-card.d.ts +13 -0
- package/dist/components/skeleton-card.js +154 -0
- package/dist/components/skeleton.d.ts +6 -0
- package/dist/components/skeleton.js +3 -0
- package/dist/components/slider.d.ts +6 -0
- package/dist/components/slider.js +24 -0
- package/dist/components/sliding-panels.d.ts +19 -0
- package/dist/components/sliding-panels.js +75 -0
- package/dist/components/sonner.d.ts +6 -0
- package/dist/components/sonner.js +23 -0
- package/dist/components/sticky-container.d.ts +44 -0
- package/dist/components/sticky-container.js +39 -0
- package/dist/components/switch.d.ts +6 -0
- package/dist/components/switch.js +31 -0
- package/dist/components/table.d.ts +12 -0
- package/dist/components/table.js +81 -0
- package/dist/components/tabs.d.ts +12 -0
- package/dist/components/tabs.js +55 -0
- package/dist/components/text.d.ts +31 -0
- package/dist/components/text.js +3 -0
- package/dist/components/textarea.d.ts +6 -0
- package/dist/components/textarea.js +23 -0
- package/dist/components/toast.d.ts +18 -0
- package/dist/components/toast.js +3 -0
- package/dist/components/toaster.d.ts +5 -0
- package/dist/components/toaster.js +25 -0
- package/dist/components/toggle-group.d.ts +12 -0
- package/dist/components/toggle-group.js +72 -0
- package/dist/components/toggle.d.ts +13 -0
- package/dist/components/toggle.js +3 -0
- package/dist/components/tooltip.d.ts +9 -0
- package/dist/components/tooltip.js +26 -0
- package/dist/components/use-mobile.d.ts +3 -0
- package/dist/components/use-mobile.js +19 -0
- package/dist/components/use-toast.d.ts +42 -0
- package/dist/components/use-toast.js +2 -0
- package/dist/hooks/use-haptic.d.ts +22 -0
- package/dist/hooks/use-haptic.js +2 -0
- package/dist/hooks/use-mobile.d.ts +3 -0
- package/dist/hooks/use-mobile.js +19 -0
- package/dist/hooks/use-mounted-theme.d.ts +6 -0
- package/dist/hooks/use-mounted-theme.js +18 -0
- package/dist/hooks/use-sticky.d.ts +18 -0
- package/dist/hooks/use-sticky.js +2 -0
- package/dist/lib/utils.d.ts +5 -0
- package/dist/lib/utils.js +2 -0
- package/package.json +203 -0
- package/src/components/accordion.tsx +57 -0
- package/src/components/alert-dialog.tsx +116 -0
- package/src/components/alert.tsx +57 -0
- package/src/components/aspect-ratio.tsx +9 -0
- package/src/components/avatar.tsx +49 -0
- package/src/components/badge.tsx +38 -0
- package/src/components/breadcrumb.tsx +102 -0
- package/src/components/button.tsx +94 -0
- package/src/components/calendar.tsx +60 -0
- package/src/components/card.tsx +67 -0
- package/src/components/carousel.tsx +230 -0
- package/src/components/checkbox.tsx +27 -0
- package/src/components/collapsible.tsx +28 -0
- package/src/components/command.tsx +148 -0
- package/src/components/currency-input.tsx +158 -0
- package/src/components/dialog.tsx +103 -0
- package/src/components/drawer.tsx +99 -0
- package/src/components/dropdown-menu.tsx +228 -0
- package/src/components/empty-state.tsx +118 -0
- package/src/components/form.tsx +152 -0
- package/src/components/haptic-button.tsx +19 -0
- package/src/components/input-otp.tsx +70 -0
- package/src/components/input.tsx +23 -0
- package/src/components/label.tsx +20 -0
- package/src/components/lazy-markdown.tsx +20 -0
- package/src/components/link-button.tsx +40 -0
- package/src/components/markdown-renderer.tsx +20 -0
- package/src/components/multi-select-combobox.tsx +148 -0
- package/src/components/pagination.tsx +106 -0
- package/src/components/popover.tsx +30 -0
- package/src/components/progress.tsx +27 -0
- package/src/components/radio-group.tsx +37 -0
- package/src/components/rating.tsx +136 -0
- package/src/components/scroll-area.tsx +45 -0
- package/src/components/search-bar.tsx +113 -0
- package/src/components/searchable-select.tsx +134 -0
- package/src/components/select.tsx +152 -0
- package/src/components/separator.tsx +25 -0
- package/src/components/sheet.tsx +121 -0
- package/src/components/skeleton-card.tsx +282 -0
- package/src/components/skeleton.tsx +17 -0
- package/src/components/slider.tsx +24 -0
- package/src/components/sliding-panels.tsx +99 -0
- package/src/components/sonner.tsx +25 -0
- package/src/components/sticky-container.tsx +88 -0
- package/src/components/switch.tsx +28 -0
- package/src/components/table.tsx +90 -0
- package/src/components/tabs.tsx +72 -0
- package/src/components/text.test.tsx +192 -0
- package/src/components/text.tsx +114 -0
- package/src/components/textarea.tsx +22 -0
- package/src/components/toast.tsx +129 -0
- package/src/components/toaster.tsx +31 -0
- package/src/components/toggle-group.tsx +69 -0
- package/src/components/toggle.tsx +46 -0
- package/src/components/tooltip.tsx +29 -0
- package/src/components/use-mobile.tsx +19 -0
- package/src/components/use-toast.ts +180 -0
- package/src/globals.css +409 -0
- package/src/hooks/use-haptic.ts +118 -0
- package/src/hooks/use-mobile.ts +19 -0
- package/src/hooks/use-mounted-theme.ts +20 -0
- package/src/hooks/use-sticky.ts +47 -0
- package/src/lib/utils.ts +6 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
3
|
+
import { ChevronRight, MoreHorizontal } from "lucide-react";
|
|
4
|
+
|
|
5
|
+
import { cn } from "../lib/utils";
|
|
6
|
+
|
|
7
|
+
function Breadcrumb({ ...props }: React.ComponentProps<"nav">) {
|
|
8
|
+
return <nav aria-label="breadcrumb" data-slot="breadcrumb" {...props} />;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
|
|
12
|
+
return (
|
|
13
|
+
<ol
|
|
14
|
+
data-slot="breadcrumb-list"
|
|
15
|
+
className={cn(
|
|
16
|
+
"text-muted-foreground flex flex-wrap items-center gap-1.5 text-sm break-words sm:gap-2.5",
|
|
17
|
+
className
|
|
18
|
+
)}
|
|
19
|
+
{...props}
|
|
20
|
+
/>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
|
|
25
|
+
return (
|
|
26
|
+
<li
|
|
27
|
+
data-slot="breadcrumb-item"
|
|
28
|
+
className={cn("inline-flex items-center gap-1.5", className)}
|
|
29
|
+
{...props}
|
|
30
|
+
/>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function BreadcrumbLink({
|
|
35
|
+
asChild,
|
|
36
|
+
className,
|
|
37
|
+
...props
|
|
38
|
+
}: React.ComponentProps<"a"> & {
|
|
39
|
+
asChild?: boolean;
|
|
40
|
+
}) {
|
|
41
|
+
const Comp = asChild ? Slot : "a";
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<Comp
|
|
45
|
+
data-slot="breadcrumb-link"
|
|
46
|
+
className={cn("hover:text-foreground transition-colors", className)}
|
|
47
|
+
{...props}
|
|
48
|
+
/>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
|
|
53
|
+
return (
|
|
54
|
+
<span
|
|
55
|
+
data-slot="breadcrumb-page"
|
|
56
|
+
role="link"
|
|
57
|
+
aria-disabled="true"
|
|
58
|
+
aria-current="page"
|
|
59
|
+
className={cn("text-foreground font-normal", className)}
|
|
60
|
+
{...props}
|
|
61
|
+
/>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function BreadcrumbSeparator({ children, className, ...props }: React.ComponentProps<"li">) {
|
|
66
|
+
return (
|
|
67
|
+
<li
|
|
68
|
+
data-slot="breadcrumb-separator"
|
|
69
|
+
role="presentation"
|
|
70
|
+
aria-hidden="true"
|
|
71
|
+
className={cn("[&>svg]:size-3.5", className)}
|
|
72
|
+
{...props}
|
|
73
|
+
>
|
|
74
|
+
{children ?? <ChevronRight />}
|
|
75
|
+
</li>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function BreadcrumbEllipsis({ className, ...props }: React.ComponentProps<"span">) {
|
|
80
|
+
return (
|
|
81
|
+
<span
|
|
82
|
+
data-slot="breadcrumb-ellipsis"
|
|
83
|
+
role="presentation"
|
|
84
|
+
aria-hidden="true"
|
|
85
|
+
className={cn("flex size-9 items-center justify-center", className)}
|
|
86
|
+
{...props}
|
|
87
|
+
>
|
|
88
|
+
<MoreHorizontal className="size-4" />
|
|
89
|
+
<span className="sr-only">More</span>
|
|
90
|
+
</span>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export {
|
|
95
|
+
Breadcrumb,
|
|
96
|
+
BreadcrumbList,
|
|
97
|
+
BreadcrumbItem,
|
|
98
|
+
BreadcrumbLink,
|
|
99
|
+
BreadcrumbPage,
|
|
100
|
+
BreadcrumbSeparator,
|
|
101
|
+
BreadcrumbEllipsis,
|
|
102
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
3
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
4
|
+
import { cn } from "../lib/utils";
|
|
5
|
+
import { useHaptic } from "../hooks/use-haptic";
|
|
6
|
+
|
|
7
|
+
const buttonVariants = cva(
|
|
8
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-3xl text-sm font-medium transition-all duration-300 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 cursor-pointer [@media(pointer:coarse)]:active:scale-95",
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default:
|
|
13
|
+
"bg-primary backdrop-blur-sm text-primary-foreground shadow-lg hover:bg-primary/85 border border-primary/20 transition-colors duration-200",
|
|
14
|
+
destructive:
|
|
15
|
+
"bg-destructive text-destructive-foreground shadow-lg hover:bg-destructive/90 hover:shadow-destructive/20 backdrop-blur-sm border border-destructive/20",
|
|
16
|
+
outline:
|
|
17
|
+
"border border-border bg-card/70 backdrop-blur-md hover:bg-accent hover:text-accent-foreground hover:border-accent-foreground/20 hover:shadow-lg glass-hover",
|
|
18
|
+
secondary:
|
|
19
|
+
"bg-secondary text-secondary-foreground shadow-lg hover:bg-secondary/90 hover:shadow-secondary/20 backdrop-blur-sm border border-secondary/20",
|
|
20
|
+
ghost: "hover:bg-foreground/10 hover:text-foreground transition-colors duration-200",
|
|
21
|
+
link: "text-primary underline-offset-4 hover:underline hover:text-primary/80",
|
|
22
|
+
glass: "glass glass-hover text-foreground hover:text-accent-foreground",
|
|
23
|
+
brown:
|
|
24
|
+
"bg-[#482E1F] text-white shadow-lg hover:bg-[#352317] hover:shadow-[#482E1F]/20 backdrop-blur-sm border border-[#482E1F]/30 transition-all duration-300",
|
|
25
|
+
antagonist:
|
|
26
|
+
"bg-primary-foreground text-primary shadow-lg hover:bg-primary-foreground/90 hover:shadow-primary-foreground/20 backdrop-blur-sm border border-primary-foreground/20 transition-all duration-300",
|
|
27
|
+
},
|
|
28
|
+
size: {
|
|
29
|
+
default: "h-11 px-6 py-2",
|
|
30
|
+
sm: "h-9 rounded-lg px-4",
|
|
31
|
+
lg: "h-12 rounded-xl px-8",
|
|
32
|
+
icon: "h-11 w-11",
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
defaultVariants: {
|
|
36
|
+
variant: "default",
|
|
37
|
+
size: "default",
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
export interface ButtonProps
|
|
43
|
+
extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
44
|
+
asChild?: boolean;
|
|
45
|
+
haptic?: boolean;
|
|
46
|
+
hapticStyle?: "light" | "medium" | "heavy";
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
50
|
+
(
|
|
51
|
+
{
|
|
52
|
+
className,
|
|
53
|
+
variant,
|
|
54
|
+
size,
|
|
55
|
+
asChild = false,
|
|
56
|
+
haptic = true,
|
|
57
|
+
hapticStyle = "light",
|
|
58
|
+
onClick,
|
|
59
|
+
...props
|
|
60
|
+
},
|
|
61
|
+
ref
|
|
62
|
+
) => {
|
|
63
|
+
const Comp = asChild ? Slot : "button";
|
|
64
|
+
const { trigger } = useHaptic();
|
|
65
|
+
const [isMounted, setIsMounted] = React.useState(false);
|
|
66
|
+
|
|
67
|
+
// Track mounted state to prevent hydration issues
|
|
68
|
+
React.useEffect(() => {
|
|
69
|
+
setIsMounted(true);
|
|
70
|
+
}, []);
|
|
71
|
+
|
|
72
|
+
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
|
73
|
+
// Only trigger haptic feedback after component has mounted to prevent hydration issues
|
|
74
|
+
if (haptic && isMounted) {
|
|
75
|
+
trigger(hapticStyle);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Call the original onClick handler
|
|
79
|
+
onClick?.(event);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<Comp
|
|
84
|
+
className={cn(buttonVariants({ variant, size, className }))}
|
|
85
|
+
ref={ref}
|
|
86
|
+
onClick={handleClick}
|
|
87
|
+
{...props}
|
|
88
|
+
/>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
);
|
|
92
|
+
Button.displayName = "Button";
|
|
93
|
+
|
|
94
|
+
export { Button, buttonVariants };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type * as React from "react";
|
|
4
|
+
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
5
|
+
import { DayPicker } from "react-day-picker";
|
|
6
|
+
import { cn } from "../lib/utils";
|
|
7
|
+
import { buttonVariants } from "./button";
|
|
8
|
+
|
|
9
|
+
export type CalendarProps = React.ComponentProps<typeof DayPicker>;
|
|
10
|
+
|
|
11
|
+
function Calendar({ className, classNames, showOutsideDays = true, ...props }: CalendarProps) {
|
|
12
|
+
return (
|
|
13
|
+
<DayPicker
|
|
14
|
+
showOutsideDays={showOutsideDays}
|
|
15
|
+
className={cn("p-3", className)}
|
|
16
|
+
classNames={{
|
|
17
|
+
months: "flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0",
|
|
18
|
+
month: "space-y-4",
|
|
19
|
+
caption: "flex justify-center pt-1 relative items-center",
|
|
20
|
+
caption_label: "text-sm font-medium",
|
|
21
|
+
nav: "space-x-1 flex items-center",
|
|
22
|
+
nav_button: cn(
|
|
23
|
+
buttonVariants({ variant: "outline" }),
|
|
24
|
+
"h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100 glass-hover"
|
|
25
|
+
),
|
|
26
|
+
nav_button_previous: "absolute left-1",
|
|
27
|
+
nav_button_next: "absolute right-1",
|
|
28
|
+
table: "w-full border-collapse space-y-1",
|
|
29
|
+
head_row: "flex",
|
|
30
|
+
head_cell: "text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]",
|
|
31
|
+
row: "flex w-full mt-2",
|
|
32
|
+
cell: "h-9 w-9 text-center text-sm p-0 relative [&:has([aria-selected].day-range-end)]:rounded-r-md [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20",
|
|
33
|
+
day: cn(
|
|
34
|
+
buttonVariants({ variant: "ghost" }),
|
|
35
|
+
"h-9 w-9 p-0 font-normal aria-selected:opacity-100 glass-hover"
|
|
36
|
+
),
|
|
37
|
+
day_range_end: "day-range-end",
|
|
38
|
+
day_selected:
|
|
39
|
+
"bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground glass-glow",
|
|
40
|
+
day_today: "bg-accent text-accent-foreground",
|
|
41
|
+
day_outside:
|
|
42
|
+
"day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30",
|
|
43
|
+
day_disabled: "text-muted-foreground opacity-50",
|
|
44
|
+
day_range_middle: "aria-selected:bg-accent aria-selected:text-accent-foreground",
|
|
45
|
+
day_hidden: "invisible",
|
|
46
|
+
...classNames,
|
|
47
|
+
}}
|
|
48
|
+
components={{
|
|
49
|
+
Chevron: (props) => {
|
|
50
|
+
if (props.orientation === "left") return <ChevronLeft className="h-4 w-4" />;
|
|
51
|
+
return <ChevronRight className="h-4 w-4" />;
|
|
52
|
+
},
|
|
53
|
+
}}
|
|
54
|
+
{...props}
|
|
55
|
+
/>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
Calendar.displayName = "Calendar";
|
|
59
|
+
|
|
60
|
+
export { Calendar };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cn } from "../lib/utils";
|
|
3
|
+
import { textVariants } from "./text";
|
|
4
|
+
|
|
5
|
+
type CardVariant = "glass" | "surface";
|
|
6
|
+
|
|
7
|
+
const Card = React.forwardRef<
|
|
8
|
+
HTMLDivElement,
|
|
9
|
+
React.HTMLAttributes<HTMLDivElement> & { variant?: CardVariant }
|
|
10
|
+
>(({ className, variant = "glass", ...props }, ref) => (
|
|
11
|
+
<div
|
|
12
|
+
ref={ref}
|
|
13
|
+
className={cn(
|
|
14
|
+
variant === "glass"
|
|
15
|
+
? "glass rounded-[22px] border border-transparent text-card-foreground transition-[transform,border-color] duration-300 [@media(hover:hover)]:hover:-translate-y-0.5 hover:border-primary/40"
|
|
16
|
+
: "bg-surface rounded-[22px] border border-border text-card-foreground transition-all duration-200 hover:border-primary/40 hover:-translate-y-0.5",
|
|
17
|
+
className
|
|
18
|
+
)}
|
|
19
|
+
{...props}
|
|
20
|
+
/>
|
|
21
|
+
));
|
|
22
|
+
Card.displayName = "Card";
|
|
23
|
+
|
|
24
|
+
const CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
25
|
+
({ className, ...props }, ref) => (
|
|
26
|
+
<div ref={ref} className={cn("flex flex-col space-y-1.5 p-6", className)} {...props} />
|
|
27
|
+
)
|
|
28
|
+
);
|
|
29
|
+
CardHeader.displayName = "CardHeader";
|
|
30
|
+
|
|
31
|
+
const CardTitle = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
32
|
+
({ className, ...props }, ref) => (
|
|
33
|
+
<div
|
|
34
|
+
ref={ref}
|
|
35
|
+
className={cn(textVariants({ variant: "h4", wrap: "balance" }), className)}
|
|
36
|
+
{...props}
|
|
37
|
+
/>
|
|
38
|
+
)
|
|
39
|
+
);
|
|
40
|
+
CardTitle.displayName = "CardTitle";
|
|
41
|
+
|
|
42
|
+
const CardDescription = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
43
|
+
({ className, ...props }, ref) => (
|
|
44
|
+
<div
|
|
45
|
+
ref={ref}
|
|
46
|
+
className={cn("text-sm", textVariants({ color: "muted", wrap: "pretty" }), className)}
|
|
47
|
+
{...props}
|
|
48
|
+
/>
|
|
49
|
+
)
|
|
50
|
+
);
|
|
51
|
+
CardDescription.displayName = "CardDescription";
|
|
52
|
+
|
|
53
|
+
const CardContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
54
|
+
({ className, ...props }, ref) => (
|
|
55
|
+
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
|
|
56
|
+
)
|
|
57
|
+
);
|
|
58
|
+
CardContent.displayName = "CardContent";
|
|
59
|
+
|
|
60
|
+
const CardFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
61
|
+
({ className, ...props }, ref) => (
|
|
62
|
+
<div ref={ref} className={cn("flex items-center p-6 pt-0", className)} {...props} />
|
|
63
|
+
)
|
|
64
|
+
);
|
|
65
|
+
CardFooter.displayName = "CardFooter";
|
|
66
|
+
|
|
67
|
+
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import useEmblaCarousel, { type UseEmblaCarouselType } from "embla-carousel-react";
|
|
5
|
+
import { ArrowLeft, ArrowRight } from "lucide-react";
|
|
6
|
+
|
|
7
|
+
import { cn } from "../lib/utils";
|
|
8
|
+
import { Button } from "./button";
|
|
9
|
+
|
|
10
|
+
type CarouselApi = UseEmblaCarouselType[1];
|
|
11
|
+
type UseCarouselParameters = Parameters<typeof useEmblaCarousel>;
|
|
12
|
+
type CarouselOptions = UseCarouselParameters[0];
|
|
13
|
+
type CarouselPlugin = UseCarouselParameters[1];
|
|
14
|
+
|
|
15
|
+
type CarouselProps = {
|
|
16
|
+
opts?: CarouselOptions;
|
|
17
|
+
plugins?: CarouselPlugin;
|
|
18
|
+
orientation?: "horizontal" | "vertical";
|
|
19
|
+
setApi?: (api: CarouselApi) => void;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
type CarouselContextProps = {
|
|
23
|
+
carouselRef: ReturnType<typeof useEmblaCarousel>[0];
|
|
24
|
+
api: ReturnType<typeof useEmblaCarousel>[1];
|
|
25
|
+
scrollPrev: () => void;
|
|
26
|
+
scrollNext: () => void;
|
|
27
|
+
canScrollPrev: boolean;
|
|
28
|
+
canScrollNext: boolean;
|
|
29
|
+
} & CarouselProps;
|
|
30
|
+
|
|
31
|
+
const CarouselContext = React.createContext<CarouselContextProps | null>(null);
|
|
32
|
+
|
|
33
|
+
function useCarousel() {
|
|
34
|
+
const context = React.useContext(CarouselContext);
|
|
35
|
+
|
|
36
|
+
if (!context) {
|
|
37
|
+
throw new Error("useCarousel must be used within a <Carousel />");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return context;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function Carousel({
|
|
44
|
+
orientation = "horizontal",
|
|
45
|
+
opts,
|
|
46
|
+
setApi,
|
|
47
|
+
plugins,
|
|
48
|
+
className,
|
|
49
|
+
children,
|
|
50
|
+
...props
|
|
51
|
+
}: React.ComponentProps<"div"> & CarouselProps) {
|
|
52
|
+
const [carouselRef, api] = useEmblaCarousel(
|
|
53
|
+
{
|
|
54
|
+
...opts,
|
|
55
|
+
axis: orientation === "horizontal" ? "x" : "y",
|
|
56
|
+
},
|
|
57
|
+
plugins
|
|
58
|
+
);
|
|
59
|
+
const [canScrollPrev, setCanScrollPrev] = React.useState(false);
|
|
60
|
+
const [canScrollNext, setCanScrollNext] = React.useState(false);
|
|
61
|
+
|
|
62
|
+
const onSelect = React.useCallback((api: CarouselApi) => {
|
|
63
|
+
if (!api) return;
|
|
64
|
+
setCanScrollPrev(api.canScrollPrev());
|
|
65
|
+
setCanScrollNext(api.canScrollNext());
|
|
66
|
+
}, []);
|
|
67
|
+
|
|
68
|
+
const scrollPrev = React.useCallback(() => {
|
|
69
|
+
api?.scrollPrev();
|
|
70
|
+
}, [api]);
|
|
71
|
+
|
|
72
|
+
const scrollNext = React.useCallback(() => {
|
|
73
|
+
api?.scrollNext();
|
|
74
|
+
}, [api]);
|
|
75
|
+
|
|
76
|
+
const handleKeyDown = React.useCallback(
|
|
77
|
+
(event: React.KeyboardEvent<HTMLDivElement>) => {
|
|
78
|
+
if (event.key === "ArrowLeft") {
|
|
79
|
+
event.preventDefault();
|
|
80
|
+
scrollPrev();
|
|
81
|
+
} else if (event.key === "ArrowRight") {
|
|
82
|
+
event.preventDefault();
|
|
83
|
+
scrollNext();
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
[scrollPrev, scrollNext]
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
React.useEffect(() => {
|
|
90
|
+
if (!api || !setApi) return;
|
|
91
|
+
setApi(api);
|
|
92
|
+
}, [api, setApi]);
|
|
93
|
+
|
|
94
|
+
React.useEffect(() => {
|
|
95
|
+
if (!api) return;
|
|
96
|
+
onSelect(api);
|
|
97
|
+
api.on("reInit", onSelect);
|
|
98
|
+
api.on("select", onSelect);
|
|
99
|
+
|
|
100
|
+
return () => {
|
|
101
|
+
api?.off("select", onSelect);
|
|
102
|
+
};
|
|
103
|
+
}, [api, onSelect]);
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<CarouselContext.Provider
|
|
107
|
+
value={{
|
|
108
|
+
carouselRef,
|
|
109
|
+
api: api,
|
|
110
|
+
opts,
|
|
111
|
+
orientation: orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
|
|
112
|
+
scrollPrev,
|
|
113
|
+
scrollNext,
|
|
114
|
+
canScrollPrev,
|
|
115
|
+
canScrollNext,
|
|
116
|
+
}}
|
|
117
|
+
>
|
|
118
|
+
<div
|
|
119
|
+
onKeyDownCapture={handleKeyDown}
|
|
120
|
+
className={cn("relative", className)}
|
|
121
|
+
role="region"
|
|
122
|
+
aria-roledescription="carousel"
|
|
123
|
+
data-slot="carousel"
|
|
124
|
+
{...props}
|
|
125
|
+
>
|
|
126
|
+
{children}
|
|
127
|
+
</div>
|
|
128
|
+
</CarouselContext.Provider>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function CarouselContent({ className, ...props }: React.ComponentProps<"div">) {
|
|
133
|
+
const { carouselRef, orientation } = useCarousel();
|
|
134
|
+
|
|
135
|
+
return (
|
|
136
|
+
<div ref={carouselRef} className="overflow-hidden" data-slot="carousel-content">
|
|
137
|
+
<div
|
|
138
|
+
className={cn("flex", orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col", className)}
|
|
139
|
+
{...props}
|
|
140
|
+
/>
|
|
141
|
+
</div>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function CarouselItem({ className, ...props }: React.ComponentProps<"div">) {
|
|
146
|
+
const { orientation } = useCarousel();
|
|
147
|
+
|
|
148
|
+
return (
|
|
149
|
+
<div
|
|
150
|
+
role="group"
|
|
151
|
+
aria-roledescription="slide"
|
|
152
|
+
data-slot="carousel-item"
|
|
153
|
+
className={cn(
|
|
154
|
+
"min-w-0 shrink-0 grow-0 basis-full",
|
|
155
|
+
orientation === "horizontal" ? "pl-4" : "pt-4",
|
|
156
|
+
className
|
|
157
|
+
)}
|
|
158
|
+
{...props}
|
|
159
|
+
/>
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function CarouselPrevious({
|
|
164
|
+
className,
|
|
165
|
+
variant = "outline",
|
|
166
|
+
size = "icon",
|
|
167
|
+
...props
|
|
168
|
+
}: React.ComponentProps<typeof Button>) {
|
|
169
|
+
const { orientation, scrollPrev, canScrollPrev } = useCarousel();
|
|
170
|
+
|
|
171
|
+
return (
|
|
172
|
+
<Button
|
|
173
|
+
data-slot="carousel-previous"
|
|
174
|
+
variant={variant}
|
|
175
|
+
size={size}
|
|
176
|
+
className={cn(
|
|
177
|
+
"absolute size-8 rounded-full",
|
|
178
|
+
orientation === "horizontal"
|
|
179
|
+
? "top-1/2 -left-12 -translate-y-1/2"
|
|
180
|
+
: "-top-12 left-1/2 -translate-x-1/2 rotate-90",
|
|
181
|
+
className
|
|
182
|
+
)}
|
|
183
|
+
disabled={!canScrollPrev}
|
|
184
|
+
onClick={scrollPrev}
|
|
185
|
+
{...props}
|
|
186
|
+
>
|
|
187
|
+
<ArrowLeft />
|
|
188
|
+
<span className="sr-only">Previous slide</span>
|
|
189
|
+
</Button>
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function CarouselNext({
|
|
194
|
+
className,
|
|
195
|
+
variant = "outline",
|
|
196
|
+
size = "icon",
|
|
197
|
+
...props
|
|
198
|
+
}: React.ComponentProps<typeof Button>) {
|
|
199
|
+
const { orientation, scrollNext, canScrollNext } = useCarousel();
|
|
200
|
+
|
|
201
|
+
return (
|
|
202
|
+
<Button
|
|
203
|
+
data-slot="carousel-next"
|
|
204
|
+
variant={variant}
|
|
205
|
+
size={size}
|
|
206
|
+
className={cn(
|
|
207
|
+
"absolute size-8 rounded-full",
|
|
208
|
+
orientation === "horizontal"
|
|
209
|
+
? "top-1/2 -right-12 -translate-y-1/2"
|
|
210
|
+
: "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
|
|
211
|
+
className
|
|
212
|
+
)}
|
|
213
|
+
disabled={!canScrollNext}
|
|
214
|
+
onClick={scrollNext}
|
|
215
|
+
{...props}
|
|
216
|
+
>
|
|
217
|
+
<ArrowRight />
|
|
218
|
+
<span className="sr-only">Next slide</span>
|
|
219
|
+
</Button>
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export {
|
|
224
|
+
type CarouselApi,
|
|
225
|
+
Carousel,
|
|
226
|
+
CarouselContent,
|
|
227
|
+
CarouselItem,
|
|
228
|
+
CarouselPrevious,
|
|
229
|
+
CarouselNext,
|
|
230
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
|
|
5
|
+
import { Check } from "lucide-react";
|
|
6
|
+
import { cn } from "../lib/utils";
|
|
7
|
+
|
|
8
|
+
const Checkbox = React.forwardRef<
|
|
9
|
+
React.ElementRef<typeof CheckboxPrimitive.Root>,
|
|
10
|
+
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
|
|
11
|
+
>(({ className, ...props }, ref) => (
|
|
12
|
+
<CheckboxPrimitive.Root
|
|
13
|
+
ref={ref}
|
|
14
|
+
className={cn(
|
|
15
|
+
"peer h-5 w-5 shrink-0 rounded-md border border-border glass transition-all duration-300 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[state=checked]:border-primary data-[state=checked]:shadow-lg data-[state=checked]:shadow-primary/20 hover:border-accent/50 hover:shadow-md",
|
|
16
|
+
className
|
|
17
|
+
)}
|
|
18
|
+
{...props}
|
|
19
|
+
>
|
|
20
|
+
<CheckboxPrimitive.Indicator className={cn("flex items-center justify-center text-current")}>
|
|
21
|
+
<Check className="h-3.5 w-3.5 animate-in zoom-in-50 duration-200" />
|
|
22
|
+
</CheckboxPrimitive.Indicator>
|
|
23
|
+
</CheckboxPrimitive.Root>
|
|
24
|
+
));
|
|
25
|
+
Checkbox.displayName = CheckboxPrimitive.Root.displayName;
|
|
26
|
+
|
|
27
|
+
export { Checkbox };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
|
|
5
|
+
import { cn } from "../lib/utils";
|
|
6
|
+
|
|
7
|
+
const Collapsible = CollapsiblePrimitive.Root;
|
|
8
|
+
|
|
9
|
+
const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger;
|
|
10
|
+
|
|
11
|
+
const CollapsibleContent = React.forwardRef<
|
|
12
|
+
React.ElementRef<typeof CollapsiblePrimitive.CollapsibleContent>,
|
|
13
|
+
React.ComponentPropsWithoutRef<typeof CollapsiblePrimitive.CollapsibleContent>
|
|
14
|
+
>(({ className, children, ...props }, ref) => (
|
|
15
|
+
<CollapsiblePrimitive.CollapsibleContent
|
|
16
|
+
ref={ref}
|
|
17
|
+
className={cn(
|
|
18
|
+
"transition-all data-[state=closed]:overflow-hidden data-[state=open]:overflow-visible data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down",
|
|
19
|
+
className
|
|
20
|
+
)}
|
|
21
|
+
{...props}
|
|
22
|
+
>
|
|
23
|
+
{children}
|
|
24
|
+
</CollapsiblePrimitive.CollapsibleContent>
|
|
25
|
+
));
|
|
26
|
+
CollapsibleContent.displayName = CollapsiblePrimitive.CollapsibleContent.displayName;
|
|
27
|
+
|
|
28
|
+
export { Collapsible, CollapsibleTrigger, CollapsibleContent };
|