@cntyclub/ui-react 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-HDGMSYQS.js +26461 -0
- package/dist/chunk-HDGMSYQS.js.map +1 -0
- package/dist/chunk-PR4QN5HX.js +39 -0
- package/dist/chunk-PR4QN5HX.js.map +1 -0
- package/dist/form.d.ts +175 -0
- package/dist/form.js +5207 -0
- package/dist/form.js.map +1 -0
- package/dist/index.d.ts +1462 -0
- package/dist/index.js +81862 -0
- package/dist/index.js.map +1 -0
- package/dist/input-CZvh825j.d.ts +24 -0
- package/dist/qr-code-styling-3Y6LZH6V.js +1123 -0
- package/dist/qr-code-styling-3Y6LZH6V.js.map +1 -0
- package/package.json +79 -0
- package/src/components/form/checkbox-group-field.tsx +101 -0
- package/src/components/form/date-field.tsx +79 -0
- package/src/components/form/date-range-field.tsx +106 -0
- package/src/components/form/form-context.ts +10 -0
- package/src/components/form/form.tsx +54 -0
- package/src/components/form/number-field.tsx +69 -0
- package/src/components/form/select-field.tsx +76 -0
- package/src/components/form/submit-button.tsx +28 -0
- package/src/components/form/text-field.tsx +107 -0
- package/src/components/layout/dashboard-header.tsx +54 -0
- package/src/components/layout/dashboard-panel.tsx +34 -0
- package/src/components/theme-provider.tsx +403 -0
- package/src/components/ui/accordion.tsx +69 -0
- package/src/components/ui/alert-dialog.tsx +169 -0
- package/src/components/ui/alert.tsx +80 -0
- package/src/components/ui/animated-theme-toggler.tsx +265 -0
- package/src/components/ui/app-store-buttons.tsx +182 -0
- package/src/components/ui/aspect-ratio.tsx +23 -0
- package/src/components/ui/autocomplete.tsx +296 -0
- package/src/components/ui/avatar-group.tsx +95 -0
- package/src/components/ui/avatar.tsx +285 -0
- package/src/components/ui/badge-group.tsx +160 -0
- package/src/components/ui/badge.tsx +172 -0
- package/src/components/ui/breadcrumb.tsx +112 -0
- package/src/components/ui/button.tsx +77 -0
- package/src/components/ui/calendar.tsx +137 -0
- package/src/components/ui/card.tsx +244 -0
- package/src/components/ui/carousel.tsx +258 -0
- package/src/components/ui/chart.tsx +379 -0
- package/src/components/ui/checkbox-group.tsx +16 -0
- package/src/components/ui/checkbox.tsx +82 -0
- package/src/components/ui/collapsible.tsx +45 -0
- package/src/components/ui/combobox.tsx +411 -0
- package/src/components/ui/command.tsx +264 -0
- package/src/components/ui/context-menu.tsx +271 -0
- package/src/components/ui/credit-card.tsx +214 -0
- package/src/components/ui/dialog.tsx +196 -0
- package/src/components/ui/drawer.tsx +135 -0
- package/src/components/ui/empty.tsx +127 -0
- package/src/components/ui/featured-icon.tsx +149 -0
- package/src/components/ui/field.tsx +88 -0
- package/src/components/ui/fieldset.tsx +29 -0
- package/src/components/ui/form.tsx +17 -0
- package/src/components/ui/frame.tsx +82 -0
- package/src/components/ui/generic-empty.tsx +142 -0
- package/src/components/ui/group.tsx +97 -0
- package/src/components/ui/horizontal-scroll-fader.tsx +228 -0
- package/src/components/ui/input-group.tsx +102 -0
- package/src/components/ui/input-otp.tsx +96 -0
- package/src/components/ui/input.tsx +66 -0
- package/src/components/ui/item.tsx +198 -0
- package/src/components/ui/kbd.tsx +30 -0
- package/src/components/ui/label.tsx +28 -0
- package/src/components/ui/menu.tsx +312 -0
- package/src/components/ui/menubar.tsx +93 -0
- package/src/components/ui/meter.tsx +67 -0
- package/src/components/ui/multi-select.tsx +308 -0
- package/src/components/ui/navigation-menu.tsx +143 -0
- package/src/components/ui/number-field.tsx +160 -0
- package/src/components/ui/pagination-controls.tsx +74 -0
- package/src/components/ui/pagination.tsx +149 -0
- package/src/components/ui/popover.tsx +119 -0
- package/src/components/ui/preview-card.tsx +55 -0
- package/src/components/ui/progress.tsx +289 -0
- package/src/components/ui/qr-code.tsx +150 -0
- package/src/components/ui/radio-group.tsx +103 -0
- package/src/components/ui/resizable.tsx +56 -0
- package/src/components/ui/scroll-area.tsx +90 -0
- package/src/components/ui/scroller.tsx +38 -0
- package/src/components/ui/section-header.tsx +118 -0
- package/src/components/ui/select.tsx +181 -0
- package/src/components/ui/separator.tsx +23 -0
- package/src/components/ui/sheet.tsx +224 -0
- package/src/components/ui/sidebar.tsx +744 -0
- package/src/components/ui/skeleton.tsx +16 -0
- package/src/components/ui/slider.tsx +108 -0
- package/src/components/ui/smooth-scroll.tsx +143 -0
- package/src/components/ui/social-button.tsx +247 -0
- package/src/components/ui/spinner-on-demand.tsx +32 -0
- package/src/components/ui/spinner.tsx +18 -0
- package/src/components/ui/stat.tsx +187 -0
- package/src/components/ui/stepper.tsx +167 -0
- package/src/components/ui/switch.tsx +56 -0
- package/src/components/ui/table.tsx +126 -0
- package/src/components/ui/tabs.tsx +90 -0
- package/src/components/ui/tag.tsx +229 -0
- package/src/components/ui/target-countdown.tsx +46 -0
- package/src/components/ui/text-editor.tsx +313 -0
- package/src/components/ui/textarea.tsx +51 -0
- package/src/components/ui/timeline.tsx +116 -0
- package/src/components/ui/toast.tsx +268 -0
- package/src/components/ui/toggle-group.tsx +101 -0
- package/src/components/ui/toggle.tsx +45 -0
- package/src/components/ui/toolbar.tsx +89 -0
- package/src/components/ui/tooltip.tsx +102 -0
- package/src/components/ui/vertical-scroll-fader.tsx +250 -0
- package/src/components/ui/video-player.tsx +275 -0
- package/src/components/upload/avatar-upload-base.tsx +131 -0
- package/src/components/upload/image-upload-base.tsx +112 -0
- package/src/form.ts +17 -0
- package/src/index.ts +125 -0
- package/src/lib/hooks/use-callback-ref.ts +15 -0
- package/src/lib/hooks/use-first-render.ts +11 -0
- package/src/lib/hooks/use-hover.ts +53 -0
- package/src/lib/hooks/use-is-tab-active.ts +17 -0
- package/src/lib/hooks/use-media-query.ts +164 -0
- package/src/lib/utils/css.ts +6 -0
- package/src/styles.css +300 -0
- package/src/types/helpers.ts +24 -0
- package/src/types/react.d.ts +7 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
|
|
5
|
+
import { cn } from "../../lib/utils/css";
|
|
6
|
+
|
|
7
|
+
function Timeline({ className, ...props }: React.ComponentProps<"ol">) {
|
|
8
|
+
return (
|
|
9
|
+
<ol
|
|
10
|
+
className={cn(
|
|
11
|
+
"flex flex-col [&>li:last-child_[data-slot=timeline-connector]]:hidden",
|
|
12
|
+
className,
|
|
13
|
+
)}
|
|
14
|
+
data-slot="timeline"
|
|
15
|
+
{...props}
|
|
16
|
+
/>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function TimelineItem({ className, ...props }: React.ComponentProps<"li">) {
|
|
21
|
+
return (
|
|
22
|
+
<li
|
|
23
|
+
className={cn("group/timeline-item flex gap-4", className)}
|
|
24
|
+
data-slot="timeline-item"
|
|
25
|
+
{...props}
|
|
26
|
+
/>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** The marker column: a dot and the connecting line beneath it. */
|
|
31
|
+
function TimelineDot({
|
|
32
|
+
className,
|
|
33
|
+
children,
|
|
34
|
+
...props
|
|
35
|
+
}: React.ComponentProps<"div">) {
|
|
36
|
+
return (
|
|
37
|
+
<div
|
|
38
|
+
className="flex w-7 shrink-0 flex-col items-center"
|
|
39
|
+
data-slot="timeline-marker"
|
|
40
|
+
>
|
|
41
|
+
<div
|
|
42
|
+
className={cn(
|
|
43
|
+
"mt-0.5 flex size-3 shrink-0 items-center justify-center rounded-full border-2 border-primary bg-background [&_svg]:size-3.5 has-[svg]:mt-0 has-[svg]:size-7 has-[svg]:border-transparent has-[svg]:bg-primary has-[svg]:text-primary-foreground",
|
|
44
|
+
className,
|
|
45
|
+
)}
|
|
46
|
+
data-slot="timeline-dot"
|
|
47
|
+
{...props}
|
|
48
|
+
>
|
|
49
|
+
{children}
|
|
50
|
+
</div>
|
|
51
|
+
<div
|
|
52
|
+
className="my-1 w-0.5 flex-1 rounded-full bg-border"
|
|
53
|
+
data-slot="timeline-connector"
|
|
54
|
+
/>
|
|
55
|
+
</div>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function TimelineContent({ className, ...props }: React.ComponentProps<"div">) {
|
|
60
|
+
return (
|
|
61
|
+
<div
|
|
62
|
+
className={cn(
|
|
63
|
+
"flex flex-1 flex-col gap-1 pb-8 group-last/timeline-item:pb-0",
|
|
64
|
+
className,
|
|
65
|
+
)}
|
|
66
|
+
data-slot="timeline-content"
|
|
67
|
+
{...props}
|
|
68
|
+
/>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function TimelineTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
73
|
+
return (
|
|
74
|
+
<div
|
|
75
|
+
className={cn("font-medium text-sm leading-tight", className)}
|
|
76
|
+
data-slot="timeline-title"
|
|
77
|
+
{...props}
|
|
78
|
+
/>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function TimelineTime({ className, ...props }: React.ComponentProps<"div">) {
|
|
83
|
+
return (
|
|
84
|
+
<div
|
|
85
|
+
className={cn(
|
|
86
|
+
"font-medium text-muted-foreground text-xs tabular-nums",
|
|
87
|
+
className,
|
|
88
|
+
)}
|
|
89
|
+
data-slot="timeline-time"
|
|
90
|
+
{...props}
|
|
91
|
+
/>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function TimelineDescription({
|
|
96
|
+
className,
|
|
97
|
+
...props
|
|
98
|
+
}: React.ComponentProps<"div">) {
|
|
99
|
+
return (
|
|
100
|
+
<div
|
|
101
|
+
className={cn("text-muted-foreground text-sm", className)}
|
|
102
|
+
data-slot="timeline-description"
|
|
103
|
+
{...props}
|
|
104
|
+
/>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export {
|
|
109
|
+
Timeline,
|
|
110
|
+
TimelineItem,
|
|
111
|
+
TimelineDot,
|
|
112
|
+
TimelineContent,
|
|
113
|
+
TimelineTitle,
|
|
114
|
+
TimelineTime,
|
|
115
|
+
TimelineDescription,
|
|
116
|
+
};
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Toast } from "@base-ui/react/toast";
|
|
4
|
+
import {
|
|
5
|
+
CircleAlertIcon,
|
|
6
|
+
CircleCheckIcon,
|
|
7
|
+
InfoIcon,
|
|
8
|
+
LoaderCircleIcon,
|
|
9
|
+
TriangleAlertIcon,
|
|
10
|
+
} from "lucide-react";
|
|
11
|
+
import { buttonVariants } from "./button";
|
|
12
|
+
import { cn } from "../../lib/utils/css";
|
|
13
|
+
|
|
14
|
+
const toastManager = Toast.createToastManager();
|
|
15
|
+
const anchoredToastManager = Toast.createToastManager();
|
|
16
|
+
|
|
17
|
+
const TOAST_ICONS = {
|
|
18
|
+
error: CircleAlertIcon,
|
|
19
|
+
info: InfoIcon,
|
|
20
|
+
loading: LoaderCircleIcon,
|
|
21
|
+
success: CircleCheckIcon,
|
|
22
|
+
warning: TriangleAlertIcon,
|
|
23
|
+
} as const;
|
|
24
|
+
|
|
25
|
+
type ToastPosition =
|
|
26
|
+
| "top-left"
|
|
27
|
+
| "top-center"
|
|
28
|
+
| "top-right"
|
|
29
|
+
| "bottom-left"
|
|
30
|
+
| "bottom-center"
|
|
31
|
+
| "bottom-right";
|
|
32
|
+
|
|
33
|
+
interface ToastProviderProps extends Toast.Provider.Props {
|
|
34
|
+
position?: ToastPosition;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function ToastProvider({
|
|
38
|
+
children,
|
|
39
|
+
position = "bottom-right",
|
|
40
|
+
...props
|
|
41
|
+
}: ToastProviderProps) {
|
|
42
|
+
return (
|
|
43
|
+
<Toast.Provider toastManager={toastManager} {...props}>
|
|
44
|
+
{children}
|
|
45
|
+
<Toasts position={position} />
|
|
46
|
+
</Toast.Provider>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function Toasts({ position = "bottom-right" }: { position: ToastPosition }) {
|
|
51
|
+
const { toasts } = Toast.useToastManager();
|
|
52
|
+
const isTop = position.startsWith("top");
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<Toast.Portal data-slot="toast-portal">
|
|
56
|
+
<Toast.Viewport
|
|
57
|
+
className={cn(
|
|
58
|
+
"fixed z-60 mx-auto flex w-[calc(100%-var(--toast-inset)*2)] max-w-90 [--toast-inset:--spacing(4)] sm:[--toast-inset:--spacing(8)]",
|
|
59
|
+
// Vertical positioning
|
|
60
|
+
"data-[position*=top]:top-(--toast-inset)",
|
|
61
|
+
"data-[position*=bottom]:bottom-(--toast-inset)",
|
|
62
|
+
// Horizontal positioning
|
|
63
|
+
"data-[position*=left]:left-(--toast-inset)",
|
|
64
|
+
"data-[position*=right]:right-(--toast-inset)",
|
|
65
|
+
"data-[position*=center]:-translate-x-1/2 data-[position*=center]:left-1/2",
|
|
66
|
+
)}
|
|
67
|
+
data-position={position}
|
|
68
|
+
data-slot="toast-viewport"
|
|
69
|
+
>
|
|
70
|
+
{toasts.map((toast) => {
|
|
71
|
+
const Icon = toast.type
|
|
72
|
+
? TOAST_ICONS[toast.type as keyof typeof TOAST_ICONS]
|
|
73
|
+
: null;
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<Toast.Root
|
|
77
|
+
className={cn(
|
|
78
|
+
"absolute z-[calc(9999-var(--toast-index))] h-(--toast-calc-height) w-full select-none rounded-lg border bg-popover not-dark:bg-clip-padding text-popover-foreground shadow-lg/5 [transition:transform_.5s_cubic-bezier(.22,1,.36,1),opacity_.5s,height_.15s] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
|
79
|
+
// Base positioning using data-position
|
|
80
|
+
"data-[position*=right]:right-0 data-[position*=right]:left-auto",
|
|
81
|
+
"data-[position*=left]:right-auto data-[position*=left]:left-0",
|
|
82
|
+
"data-[position*=center]:right-0 data-[position*=center]:left-0",
|
|
83
|
+
"data-[position*=top]:top-0 data-[position*=top]:bottom-auto data-[position*=top]:origin-top",
|
|
84
|
+
"data-[position*=bottom]:top-auto data-[position*=bottom]:bottom-0 data-[position*=bottom]:origin-bottom",
|
|
85
|
+
// Gap fill for hover
|
|
86
|
+
"after:absolute after:left-0 after:h-[calc(var(--toast-gap)+1px)] after:w-full",
|
|
87
|
+
"data-[position*=top]:after:top-full",
|
|
88
|
+
"data-[position*=bottom]:after:bottom-full",
|
|
89
|
+
// Define some variables
|
|
90
|
+
"[--toast-calc-height:var(--toast-frontmost-height,var(--toast-height))] [--toast-gap:--spacing(3)] [--toast-peek:--spacing(3)] [--toast-scale:calc(max(0,1-(var(--toast-index)*.1)))] [--toast-shrink:calc(1-var(--toast-scale))]",
|
|
91
|
+
// Define offset-y variable
|
|
92
|
+
"data-[position*=top]:[--toast-calc-offset-y:calc(var(--toast-offset-y)+var(--toast-index)*var(--toast-gap)+var(--toast-swipe-movement-y))]",
|
|
93
|
+
"data-[position*=bottom]:[--toast-calc-offset-y:calc(var(--toast-offset-y)*-1+var(--toast-index)*var(--toast-gap)*-1+var(--toast-swipe-movement-y))]",
|
|
94
|
+
// Default state transform
|
|
95
|
+
"data-[position*=top]:transform-[translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--toast-swipe-movement-y)+(var(--toast-index)*var(--toast-peek))+(var(--toast-shrink)*var(--toast-calc-height))))_scale(var(--toast-scale))]",
|
|
96
|
+
"data-[position*=bottom]:transform-[translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--toast-swipe-movement-y)-(var(--toast-index)*var(--toast-peek))-(var(--toast-shrink)*var(--toast-calc-height))))_scale(var(--toast-scale))]",
|
|
97
|
+
// Limited state
|
|
98
|
+
"data-limited:opacity-0",
|
|
99
|
+
// Expanded state
|
|
100
|
+
"data-expanded:h-(--toast-height)",
|
|
101
|
+
"data-position:data-expanded:transform-[translateX(var(--toast-swipe-movement-x))_translateY(var(--toast-calc-offset-y))]",
|
|
102
|
+
// Starting and ending animations
|
|
103
|
+
"data-[position*=top]:data-starting-style:transform-[translateY(calc(-100%-var(--toast-inset)))]",
|
|
104
|
+
"data-[position*=bottom]:data-starting-style:transform-[translateY(calc(100%+var(--toast-inset)))]",
|
|
105
|
+
"data-ending-style:opacity-0",
|
|
106
|
+
// Ending animations (direction-aware)
|
|
107
|
+
"data-ending-style:not-data-limited:not-data-swipe-direction:transform-[translateY(calc(100%+var(--toast-inset)))]",
|
|
108
|
+
"data-ending-style:data-[swipe-direction=left]:transform-[translateX(calc(var(--toast-swipe-movement-x)-100%-var(--toast-inset)))_translateY(var(--toast-calc-offset-y))]",
|
|
109
|
+
"data-ending-style:data-[swipe-direction=right]:transform-[translateX(calc(var(--toast-swipe-movement-x)+100%+var(--toast-inset)))_translateY(var(--toast-calc-offset-y))]",
|
|
110
|
+
"data-ending-style:data-[swipe-direction=up]:transform-[translateY(calc(var(--toast-swipe-movement-y)-100%-var(--toast-inset)))]",
|
|
111
|
+
"data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(var(--toast-swipe-movement-y)+100%+var(--toast-inset)))]",
|
|
112
|
+
// Ending animations (expanded)
|
|
113
|
+
"data-expanded:data-ending-style:data-[swipe-direction=left]:transform-[translateX(calc(var(--toast-swipe-movement-x)-100%-var(--toast-inset)))_translateY(var(--toast-calc-offset-y))]",
|
|
114
|
+
"data-expanded:data-ending-style:data-[swipe-direction=right]:transform-[translateX(calc(var(--toast-swipe-movement-x)+100%+var(--toast-inset)))_translateY(var(--toast-calc-offset-y))]",
|
|
115
|
+
"data-expanded:data-ending-style:data-[swipe-direction=up]:transform-[translateY(calc(var(--toast-swipe-movement-y)-100%-var(--toast-inset)))]",
|
|
116
|
+
"data-expanded:data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(var(--toast-swipe-movement-y)+100%+var(--toast-inset)))]",
|
|
117
|
+
)}
|
|
118
|
+
data-position={position}
|
|
119
|
+
key={toast.id}
|
|
120
|
+
swipeDirection={
|
|
121
|
+
position.includes("center")
|
|
122
|
+
? [isTop ? "up" : "down"]
|
|
123
|
+
: position.includes("left")
|
|
124
|
+
? ["left", isTop ? "up" : "down"]
|
|
125
|
+
: ["right", isTop ? "up" : "down"]
|
|
126
|
+
}
|
|
127
|
+
toast={toast}
|
|
128
|
+
>
|
|
129
|
+
<Toast.Content className="pointer-events-auto flex items-center justify-between gap-1.5 overflow-hidden px-3.5 py-3 text-sm transition-opacity duration-250 data-behind:not-data-expanded:pointer-events-none data-behind:opacity-0 data-expanded:opacity-100">
|
|
130
|
+
<div className="flex gap-2">
|
|
131
|
+
{Icon && (
|
|
132
|
+
<div
|
|
133
|
+
className="[&>svg]:h-lh [&>svg]:w-4 [&_svg]:pointer-events-none [&_svg]:shrink-0"
|
|
134
|
+
data-slot="toast-icon"
|
|
135
|
+
>
|
|
136
|
+
<Icon className="in-data-[type=loading]:animate-spin in-data-[type=error]:text-destructive in-data-[type=info]:text-info in-data-[type=success]:text-success in-data-[type=warning]:text-warning in-data-[type=loading]:opacity-80" />
|
|
137
|
+
</div>
|
|
138
|
+
)}
|
|
139
|
+
|
|
140
|
+
<div className="flex flex-col gap-0.5">
|
|
141
|
+
<Toast.Title
|
|
142
|
+
className="font-medium"
|
|
143
|
+
data-slot="toast-title"
|
|
144
|
+
/>
|
|
145
|
+
<Toast.Description
|
|
146
|
+
className="text-muted-foreground"
|
|
147
|
+
data-slot="toast-description"
|
|
148
|
+
/>
|
|
149
|
+
</div>
|
|
150
|
+
</div>
|
|
151
|
+
{toast.actionProps && (
|
|
152
|
+
<Toast.Action
|
|
153
|
+
className={buttonVariants({ size: "xs" })}
|
|
154
|
+
data-slot="toast-action"
|
|
155
|
+
>
|
|
156
|
+
{toast.actionProps.children}
|
|
157
|
+
</Toast.Action>
|
|
158
|
+
)}
|
|
159
|
+
</Toast.Content>
|
|
160
|
+
</Toast.Root>
|
|
161
|
+
);
|
|
162
|
+
})}
|
|
163
|
+
</Toast.Viewport>
|
|
164
|
+
</Toast.Portal>
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function AnchoredToastProvider({ children, ...props }: Toast.Provider.Props) {
|
|
169
|
+
return (
|
|
170
|
+
<Toast.Provider toastManager={anchoredToastManager} {...props}>
|
|
171
|
+
{children}
|
|
172
|
+
<AnchoredToasts />
|
|
173
|
+
</Toast.Provider>
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function AnchoredToasts() {
|
|
178
|
+
const { toasts } = Toast.useToastManager();
|
|
179
|
+
|
|
180
|
+
return (
|
|
181
|
+
<Toast.Portal data-slot="toast-portal-anchored">
|
|
182
|
+
<Toast.Viewport
|
|
183
|
+
className="outline-none"
|
|
184
|
+
data-slot="toast-viewport-anchored"
|
|
185
|
+
>
|
|
186
|
+
{toasts.map((toast) => {
|
|
187
|
+
const Icon = toast.type
|
|
188
|
+
? TOAST_ICONS[toast.type as keyof typeof TOAST_ICONS]
|
|
189
|
+
: null;
|
|
190
|
+
const tooltipStyle =
|
|
191
|
+
(toast.data as { tooltipStyle?: boolean })?.tooltipStyle ?? false;
|
|
192
|
+
const positionerProps = toast.positionerProps;
|
|
193
|
+
|
|
194
|
+
if (!positionerProps?.anchor) {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return (
|
|
199
|
+
<Toast.Positioner
|
|
200
|
+
className="z-50 max-w-[min(--spacing(64),var(--available-width))]"
|
|
201
|
+
data-slot="toast-positioner"
|
|
202
|
+
key={toast.id}
|
|
203
|
+
sideOffset={positionerProps.sideOffset ?? 4}
|
|
204
|
+
toast={toast}
|
|
205
|
+
>
|
|
206
|
+
<Toast.Root
|
|
207
|
+
className={cn(
|
|
208
|
+
"relative text-balance border bg-popover not-dark:bg-clip-padding text-popover-foreground text-xs transition-[scale,opacity] before:pointer-events-none before:absolute before:inset-0 before:shadow-[0_1px_--theme(--color-black/6%)] data-ending-style:scale-98 data-starting-style:scale-98 data-ending-style:opacity-0 data-starting-style:opacity-0 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
|
209
|
+
tooltipStyle
|
|
210
|
+
? "rounded-md shadow-md/5 before:rounded-[calc(var(--radius-md)-1px)]"
|
|
211
|
+
: "rounded-lg shadow-lg/5 before:rounded-[calc(var(--radius-lg)-1px)]",
|
|
212
|
+
)}
|
|
213
|
+
data-slot="toast-popup"
|
|
214
|
+
toast={toast}
|
|
215
|
+
>
|
|
216
|
+
{tooltipStyle ? (
|
|
217
|
+
<Toast.Content className="pointer-events-auto px-2 py-1">
|
|
218
|
+
<Toast.Title data-slot="toast-title" />
|
|
219
|
+
</Toast.Content>
|
|
220
|
+
) : (
|
|
221
|
+
<Toast.Content className="pointer-events-auto flex items-center justify-between gap-1.5 overflow-hidden px-3.5 py-3 text-sm">
|
|
222
|
+
<div className="flex gap-2">
|
|
223
|
+
{Icon && (
|
|
224
|
+
<div
|
|
225
|
+
className="[&>svg]:h-lh [&>svg]:w-4 [&_svg]:pointer-events-none [&_svg]:shrink-0"
|
|
226
|
+
data-slot="toast-icon"
|
|
227
|
+
>
|
|
228
|
+
<Icon className="in-data-[type=loading]:animate-spin in-data-[type=error]:text-destructive in-data-[type=info]:text-info in-data-[type=success]:text-success in-data-[type=warning]:text-warning in-data-[type=loading]:opacity-80" />
|
|
229
|
+
</div>
|
|
230
|
+
)}
|
|
231
|
+
|
|
232
|
+
<div className="flex flex-col gap-0.5">
|
|
233
|
+
<Toast.Title
|
|
234
|
+
className="font-medium"
|
|
235
|
+
data-slot="toast-title"
|
|
236
|
+
/>
|
|
237
|
+
<Toast.Description
|
|
238
|
+
className="text-muted-foreground"
|
|
239
|
+
data-slot="toast-description"
|
|
240
|
+
/>
|
|
241
|
+
</div>
|
|
242
|
+
</div>
|
|
243
|
+
{toast.actionProps && (
|
|
244
|
+
<Toast.Action
|
|
245
|
+
className={buttonVariants({ size: "xs" })}
|
|
246
|
+
data-slot="toast-action"
|
|
247
|
+
>
|
|
248
|
+
{toast.actionProps.children}
|
|
249
|
+
</Toast.Action>
|
|
250
|
+
)}
|
|
251
|
+
</Toast.Content>
|
|
252
|
+
)}
|
|
253
|
+
</Toast.Root>
|
|
254
|
+
</Toast.Positioner>
|
|
255
|
+
);
|
|
256
|
+
})}
|
|
257
|
+
</Toast.Viewport>
|
|
258
|
+
</Toast.Portal>
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export {
|
|
263
|
+
ToastProvider,
|
|
264
|
+
type ToastPosition,
|
|
265
|
+
toastManager,
|
|
266
|
+
AnchoredToastProvider,
|
|
267
|
+
anchoredToastManager,
|
|
268
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type { Toggle as TogglePrimitive } from "@base-ui/react/toggle";
|
|
4
|
+
import { ToggleGroup as ToggleGroupPrimitive } from "@base-ui/react/toggle-group";
|
|
5
|
+
import type { VariantProps } from "class-variance-authority";
|
|
6
|
+
import * as React from "react";
|
|
7
|
+
import { Separator } from "./separator";
|
|
8
|
+
import {
|
|
9
|
+
Toggle as ToggleComponent,
|
|
10
|
+
type toggleVariants,
|
|
11
|
+
} from "./toggle";
|
|
12
|
+
import { cn } from "../../lib/utils/css";
|
|
13
|
+
|
|
14
|
+
const ToggleGroupContext = React.createContext<
|
|
15
|
+
VariantProps<typeof toggleVariants>
|
|
16
|
+
>({
|
|
17
|
+
size: "default",
|
|
18
|
+
variant: "default",
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
function ToggleGroup({
|
|
22
|
+
className,
|
|
23
|
+
variant = "default",
|
|
24
|
+
size = "default",
|
|
25
|
+
orientation = "horizontal",
|
|
26
|
+
children,
|
|
27
|
+
...props
|
|
28
|
+
}: ToggleGroupPrimitive.Props & VariantProps<typeof toggleVariants>) {
|
|
29
|
+
return (
|
|
30
|
+
<ToggleGroupPrimitive
|
|
31
|
+
className={cn(
|
|
32
|
+
"flex w-fit *:focus-visible:z-10 dark:*:[[data-slot=separator]:has(+[data-slot=toggle]:hover)]:before:bg-input/64 dark:*:[[data-slot=separator]:has(+[data-slot=toggle][data-pressed])]:before:bg-input dark:*:[[data-slot=toggle]:hover+[data-slot=separator]]:before:bg-input/64 dark:*:[[data-slot=toggle][data-pressed]+[data-slot=separator]]:before:bg-input",
|
|
33
|
+
orientation === "horizontal"
|
|
34
|
+
? "*:pointer-coarse:after:min-w-auto"
|
|
35
|
+
: "*:pointer-coarse:after:min-h-auto",
|
|
36
|
+
variant === "default"
|
|
37
|
+
? "gap-0.5"
|
|
38
|
+
: orientation === "horizontal"
|
|
39
|
+
? "*:not-first:not-data-[slot=separator]:before:-start-[0.5px] *:not-last:not-data-[slot=separator]:before:-end-[0.5px] *:not-first:rounded-s-none *:not-last:rounded-e-none *:not-first:border-s-0 *:not-last:border-e-0 *:not-first:before:rounded-s-none *:not-last:before:rounded-e-none"
|
|
40
|
+
: "*:not-first:not-data-[slot=separator]:before:-top-[0.5px] *:not-last:not-data-[slot=separator]:before:-bottom-[0.5px] flex-col *:not-first:rounded-t-none *:not-last:rounded-b-none *:not-first:border-t-0 *:not-last:border-b-0 *:not-first:before:rounded-t-none *:not-last:before:rounded-b-none *:data-[slot=toggle]:not-last:before:hidden dark:*:last:before:hidden dark:*:first:before:block",
|
|
41
|
+
className,
|
|
42
|
+
)}
|
|
43
|
+
data-size={size}
|
|
44
|
+
data-slot="toggle-group"
|
|
45
|
+
data-variant={variant}
|
|
46
|
+
orientation={orientation}
|
|
47
|
+
{...props}
|
|
48
|
+
>
|
|
49
|
+
<ToggleGroupContext.Provider value={{ size, variant }}>
|
|
50
|
+
{children}
|
|
51
|
+
</ToggleGroupContext.Provider>
|
|
52
|
+
</ToggleGroupPrimitive>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function Toggle({
|
|
57
|
+
className,
|
|
58
|
+
children,
|
|
59
|
+
variant,
|
|
60
|
+
size,
|
|
61
|
+
...props
|
|
62
|
+
}: TogglePrimitive.Props & VariantProps<typeof toggleVariants>) {
|
|
63
|
+
const context = React.useContext(ToggleGroupContext);
|
|
64
|
+
|
|
65
|
+
const resolvedVariant = context.variant || variant;
|
|
66
|
+
const resolvedSize = context.size || size;
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<ToggleComponent
|
|
70
|
+
className={className}
|
|
71
|
+
data-size={resolvedSize}
|
|
72
|
+
data-variant={resolvedVariant}
|
|
73
|
+
size={resolvedSize}
|
|
74
|
+
variant={resolvedVariant}
|
|
75
|
+
{...props}
|
|
76
|
+
>
|
|
77
|
+
{children}
|
|
78
|
+
</ToggleComponent>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function ToggleGroupSeparator({
|
|
83
|
+
className,
|
|
84
|
+
orientation = "vertical",
|
|
85
|
+
...props
|
|
86
|
+
}: {
|
|
87
|
+
className?: string;
|
|
88
|
+
} & React.ComponentProps<typeof Separator>) {
|
|
89
|
+
return (
|
|
90
|
+
<Separator
|
|
91
|
+
className={cn(
|
|
92
|
+
"pointer-events-none relative bg-input before:absolute before:inset-0 dark:before:bg-input/32",
|
|
93
|
+
className,
|
|
94
|
+
)}
|
|
95
|
+
orientation={orientation}
|
|
96
|
+
{...props}
|
|
97
|
+
/>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export { ToggleGroup, Toggle, Toggle as ToggleGroupItem, ToggleGroupSeparator };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Toggle as TogglePrimitive } from "@base-ui/react/toggle";
|
|
4
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
5
|
+
|
|
6
|
+
import { cn } from "../../lib/utils/css";
|
|
7
|
+
|
|
8
|
+
const toggleVariants = cva(
|
|
9
|
+
"[&_svg]:-mx-0.5 relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center gap-2 whitespace-nowrap rounded-lg border font-medium text-base text-foreground outline-none transition-[box-shadow,background-color] duration-100 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 hover:bg-accent focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-64 data-pressed:bg-input/64 data-pressed:text-accent-foreground sm:text-sm [&_svg:not([class*='opacity-'])]:opacity-80 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:transition-transform [&_svg]:duration-150 [&_svg]:ease-[cubic-bezier(0.34,1.56,0.64,1)] data-pressed:[&_svg]:scale-115",
|
|
10
|
+
{
|
|
11
|
+
defaultVariants: {
|
|
12
|
+
size: "default",
|
|
13
|
+
variant: "default",
|
|
14
|
+
},
|
|
15
|
+
variants: {
|
|
16
|
+
size: {
|
|
17
|
+
default: "h-9 min-w-9 px-[calc(--spacing(2)-1px)] sm:h-8 sm:min-w-8",
|
|
18
|
+
lg: "h-10 min-w-10 px-[calc(--spacing(2.5)-1px)] sm:h-9 sm:min-w-9",
|
|
19
|
+
sm: "h-8 min-w-8 px-[calc(--spacing(1.5)-1px)] sm:h-7 sm:min-w-7",
|
|
20
|
+
},
|
|
21
|
+
variant: {
|
|
22
|
+
default: "border-transparent",
|
|
23
|
+
outline:
|
|
24
|
+
"border-input bg-background not-dark:bg-clip-padding shadow-xs/5 not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/6%)] dark:bg-input/32 dark:data-pressed:bg-input dark:hover:bg-input/64 dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] dark:not-disabled:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/2%)] [:disabled,:active,[data-pressed]]:shadow-none",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
function Toggle({
|
|
31
|
+
className,
|
|
32
|
+
variant,
|
|
33
|
+
size,
|
|
34
|
+
...props
|
|
35
|
+
}: TogglePrimitive.Props & VariantProps<typeof toggleVariants>) {
|
|
36
|
+
return (
|
|
37
|
+
<TogglePrimitive
|
|
38
|
+
className={cn(toggleVariants({ className, size, variant }))}
|
|
39
|
+
data-slot="toggle"
|
|
40
|
+
{...props}
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export { Toggle, toggleVariants };
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Toolbar as ToolbarPrimitive } from "@base-ui/react/toolbar";
|
|
4
|
+
|
|
5
|
+
import { cn } from "../../lib/utils/css";
|
|
6
|
+
|
|
7
|
+
function Toolbar({ className, ...props }: ToolbarPrimitive.Root.Props) {
|
|
8
|
+
return (
|
|
9
|
+
<ToolbarPrimitive.Root
|
|
10
|
+
className={cn(
|
|
11
|
+
"relative flex gap-2 rounded-xl border bg-card not-dark:bg-clip-padding p-1 text-card-foreground",
|
|
12
|
+
className,
|
|
13
|
+
)}
|
|
14
|
+
data-slot="toolbar"
|
|
15
|
+
{...props}
|
|
16
|
+
/>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function ToolbarButton({ className, ...props }: ToolbarPrimitive.Button.Props) {
|
|
21
|
+
return (
|
|
22
|
+
<ToolbarPrimitive.Button
|
|
23
|
+
className={cn(
|
|
24
|
+
"transition-[box-shadow,background-color,color,filter] duration-150 ease-out [:active:not(:disabled)]:brightness-95",
|
|
25
|
+
className,
|
|
26
|
+
)}
|
|
27
|
+
data-slot="toolbar-button"
|
|
28
|
+
{...props}
|
|
29
|
+
/>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function ToolbarLink({ className, ...props }: ToolbarPrimitive.Link.Props) {
|
|
34
|
+
return (
|
|
35
|
+
<ToolbarPrimitive.Link
|
|
36
|
+
className={cn(
|
|
37
|
+
"transition-[color,opacity] duration-150 ease-out",
|
|
38
|
+
className,
|
|
39
|
+
)}
|
|
40
|
+
data-slot="toolbar-link"
|
|
41
|
+
{...props}
|
|
42
|
+
/>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function ToolbarInput({ className, ...props }: ToolbarPrimitive.Input.Props) {
|
|
47
|
+
return (
|
|
48
|
+
<ToolbarPrimitive.Input
|
|
49
|
+
className={cn(className)}
|
|
50
|
+
data-slot="toolbar-input"
|
|
51
|
+
{...props}
|
|
52
|
+
/>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function ToolbarGroup({ className, ...props }: ToolbarPrimitive.Group.Props) {
|
|
57
|
+
return (
|
|
58
|
+
<ToolbarPrimitive.Group
|
|
59
|
+
className={cn("flex items-center gap-1", className)}
|
|
60
|
+
data-slot="toolbar-group"
|
|
61
|
+
{...props}
|
|
62
|
+
/>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function ToolbarSeparator({
|
|
67
|
+
className,
|
|
68
|
+
...props
|
|
69
|
+
}: ToolbarPrimitive.Separator.Props) {
|
|
70
|
+
return (
|
|
71
|
+
<ToolbarPrimitive.Separator
|
|
72
|
+
className={cn(
|
|
73
|
+
"shrink-0 bg-border data-[orientation=horizontal]:my-0.5 data-[orientation=vertical]:my-1.5 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px data-[orientation=vertical]:not-[[class^='h-']]:not-[[class*='_h-']]:self-stretch",
|
|
74
|
+
className,
|
|
75
|
+
)}
|
|
76
|
+
data-slot="toolbar-separator"
|
|
77
|
+
{...props}
|
|
78
|
+
/>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export {
|
|
83
|
+
Toolbar,
|
|
84
|
+
ToolbarGroup,
|
|
85
|
+
ToolbarSeparator,
|
|
86
|
+
ToolbarButton,
|
|
87
|
+
ToolbarLink,
|
|
88
|
+
ToolbarInput,
|
|
89
|
+
};
|