@momentumworld/ui-react 0.17.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-2HQPCV2L.js +895 -0
- package/dist/chunk-2HQPCV2L.js.map +1 -0
- package/dist/form.d.ts +175 -0
- package/dist/form.js +356 -0
- package/dist/form.js.map +1 -0
- package/dist/index.d.ts +2162 -0
- package/dist/index.js +11640 -0
- package/dist/index.js.map +1 -0
- package/dist/input-JCZs61MO.d.ts +24 -0
- package/package.json +90 -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/layout/dashboard-topbar.tsx +221 -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-counter.tsx +109 -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/aurora-orb.tsx +163 -0
- package/src/components/ui/aurora-text.tsx +76 -0
- package/src/components/ui/autocomplete.tsx +296 -0
- package/src/components/ui/avatar-group.tsx +150 -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/chat-divider.tsx +67 -0
- package/src/components/ui/chat.tsx +494 -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/color-picker.tsx +389 -0
- package/src/components/ui/combobox.tsx +411 -0
- package/src/components/ui/command.tsx +264 -0
- package/src/components/ui/confetti.tsx +196 -0
- package/src/components/ui/context-menu.tsx +271 -0
- package/src/components/ui/context-meter.tsx +134 -0
- package/src/components/ui/credit-card.tsx +214 -0
- package/src/components/ui/data-table-paged.tsx +163 -0
- package/src/components/ui/date-picker.tsx +154 -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/fab.tsx +45 -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/help-tip.tsx +94 -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/markdown.tsx +188 -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/pipeline.tsx +102 -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/segmented-control.tsx +83 -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 +774 -0
- package/src/components/ui/skeleton.tsx +16 -0
- package/src/components/ui/slider.tsx +108 -0
- package/src/components/ui/smooth-scroll.tsx +206 -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 +242 -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/thinking-orb.tsx +6 -0
- package/src/components/ui/time-picker.tsx +308 -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 +143 -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 +329 -0
- package/src/types/helpers.ts +24 -0
- package/src/types/react.d.ts +7 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Dialog as DialogPrimitive } from "@base-ui/react/dialog";
|
|
4
|
+
import { XIcon } from "lucide-react";
|
|
5
|
+
import { Button } from "./button";
|
|
6
|
+
import { ScrollArea } from "./scroll-area";
|
|
7
|
+
import { cn } from "../../lib/utils/css";
|
|
8
|
+
|
|
9
|
+
const DialogCreateHandle = DialogPrimitive.createHandle;
|
|
10
|
+
|
|
11
|
+
const Dialog = DialogPrimitive.Root;
|
|
12
|
+
|
|
13
|
+
const DialogPortal = DialogPrimitive.Portal;
|
|
14
|
+
|
|
15
|
+
function DialogTrigger(props: DialogPrimitive.Trigger.Props) {
|
|
16
|
+
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function DialogClose(props: DialogPrimitive.Close.Props) {
|
|
20
|
+
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function DialogBackdrop({
|
|
24
|
+
className,
|
|
25
|
+
...props
|
|
26
|
+
}: DialogPrimitive.Backdrop.Props) {
|
|
27
|
+
return (
|
|
28
|
+
<DialogPrimitive.Backdrop
|
|
29
|
+
className={cn(
|
|
30
|
+
"fixed inset-0 z-50 bg-black/32 backdrop-blur-sm transition-all duration-200 data-ending-style:opacity-0 data-starting-style:opacity-0",
|
|
31
|
+
className,
|
|
32
|
+
)}
|
|
33
|
+
data-slot="dialog-backdrop"
|
|
34
|
+
{...props}
|
|
35
|
+
/>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function DialogViewport({
|
|
40
|
+
className,
|
|
41
|
+
...props
|
|
42
|
+
}: DialogPrimitive.Viewport.Props) {
|
|
43
|
+
return (
|
|
44
|
+
<DialogPrimitive.Viewport
|
|
45
|
+
className={cn(
|
|
46
|
+
"fixed inset-0 z-50 grid grid-rows-[1fr_auto_3fr] justify-items-center p-4",
|
|
47
|
+
className,
|
|
48
|
+
)}
|
|
49
|
+
data-slot="dialog-viewport"
|
|
50
|
+
{...props}
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function DialogPopup({
|
|
56
|
+
className,
|
|
57
|
+
children,
|
|
58
|
+
showCloseButton = true,
|
|
59
|
+
bottomStickOnMobile = true,
|
|
60
|
+
...props
|
|
61
|
+
}: DialogPrimitive.Popup.Props & {
|
|
62
|
+
showCloseButton?: boolean;
|
|
63
|
+
bottomStickOnMobile?: boolean;
|
|
64
|
+
}) {
|
|
65
|
+
return (
|
|
66
|
+
<DialogPortal>
|
|
67
|
+
<DialogBackdrop />
|
|
68
|
+
<DialogViewport
|
|
69
|
+
className={cn(
|
|
70
|
+
bottomStickOnMobile &&
|
|
71
|
+
"max-sm:grid-rows-[1fr_auto] max-sm:p-0 max-sm:pt-12",
|
|
72
|
+
)}
|
|
73
|
+
>
|
|
74
|
+
<DialogPrimitive.Popup
|
|
75
|
+
className={cn(
|
|
76
|
+
"-translate-y-[calc(1.25rem*var(--nested-dialogs))] relative row-start-2 flex max-h-full min-h-0 w-full min-w-0 max-w-lg scale-[calc(1-0.1*var(--nested-dialogs))] flex-col rounded-2xl border bg-popover not-dark:bg-clip-padding text-popover-foreground opacity-[calc(1-0.1*var(--nested-dialogs))] shadow-lg/5 transition-[scale,opacity,translate] duration-200 ease-in-out will-change-transform before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-2xl)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] data-nested:data-ending-style:translate-y-8 data-nested:data-starting-style:translate-y-8 data-nested-dialog-open:origin-top 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%)]",
|
|
77
|
+
bottomStickOnMobile &&
|
|
78
|
+
"max-sm:max-w-none max-sm:rounded-none max-sm:border-x-0 max-sm:border-t max-sm:border-b-0 max-sm:opacity-[calc(1-min(var(--nested-dialogs),1))] max-sm:data-ending-style:translate-y-4 max-sm:data-starting-style:translate-y-4 max-sm:before:hidden max-sm:before:rounded-none",
|
|
79
|
+
className,
|
|
80
|
+
)}
|
|
81
|
+
data-slot="dialog-popup"
|
|
82
|
+
{...props}
|
|
83
|
+
>
|
|
84
|
+
{children}
|
|
85
|
+
{showCloseButton && (
|
|
86
|
+
<DialogPrimitive.Close
|
|
87
|
+
aria-label="Close"
|
|
88
|
+
className="absolute end-2 top-2"
|
|
89
|
+
render={<Button size="icon" variant="ghost" />}
|
|
90
|
+
>
|
|
91
|
+
<XIcon />
|
|
92
|
+
</DialogPrimitive.Close>
|
|
93
|
+
)}
|
|
94
|
+
</DialogPrimitive.Popup>
|
|
95
|
+
</DialogViewport>
|
|
96
|
+
</DialogPortal>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
101
|
+
return (
|
|
102
|
+
<div
|
|
103
|
+
className={cn(
|
|
104
|
+
"flex flex-col gap-2 p-6 in-[[data-slot=dialog-popup]:has([data-slot=dialog-panel])]:pb-3 max-sm:pb-4",
|
|
105
|
+
className,
|
|
106
|
+
)}
|
|
107
|
+
data-slot="dialog-header"
|
|
108
|
+
{...props}
|
|
109
|
+
/>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function DialogFooter({
|
|
114
|
+
className,
|
|
115
|
+
variant = "default",
|
|
116
|
+
...props
|
|
117
|
+
}: React.ComponentProps<"div"> & {
|
|
118
|
+
variant?: "default" | "bare";
|
|
119
|
+
}) {
|
|
120
|
+
return (
|
|
121
|
+
<div
|
|
122
|
+
className={cn(
|
|
123
|
+
"flex flex-col-reverse gap-2 px-6 sm:flex-row sm:justify-end sm:rounded-b-[calc(var(--radius-2xl)-1px)]",
|
|
124
|
+
variant === "default" && "border-t bg-muted/72 py-4",
|
|
125
|
+
variant === "bare" &&
|
|
126
|
+
"in-[[data-slot=dialog-popup]:has([data-slot=dialog-panel])]:pt-3 pt-4 pb-6",
|
|
127
|
+
className,
|
|
128
|
+
)}
|
|
129
|
+
data-slot="dialog-footer"
|
|
130
|
+
{...props}
|
|
131
|
+
/>
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {
|
|
136
|
+
return (
|
|
137
|
+
<DialogPrimitive.Title
|
|
138
|
+
className={cn(
|
|
139
|
+
"font-heading font-semibold text-xl leading-none",
|
|
140
|
+
className,
|
|
141
|
+
)}
|
|
142
|
+
data-slot="dialog-title"
|
|
143
|
+
{...props}
|
|
144
|
+
/>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function DialogDescription({
|
|
149
|
+
className,
|
|
150
|
+
...props
|
|
151
|
+
}: DialogPrimitive.Description.Props) {
|
|
152
|
+
return (
|
|
153
|
+
<DialogPrimitive.Description
|
|
154
|
+
className={cn("text-muted-foreground text-sm", className)}
|
|
155
|
+
data-slot="dialog-description"
|
|
156
|
+
{...props}
|
|
157
|
+
/>
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function DialogPanel({
|
|
162
|
+
className,
|
|
163
|
+
scrollFade = true,
|
|
164
|
+
...props
|
|
165
|
+
}: React.ComponentProps<"div"> & { scrollFade?: boolean }) {
|
|
166
|
+
return (
|
|
167
|
+
<ScrollArea scrollFade={scrollFade}>
|
|
168
|
+
<div
|
|
169
|
+
className={cn(
|
|
170
|
+
"p-6 in-[[data-slot=dialog-popup]:has([data-slot=dialog-header])]:pt-1 in-[[data-slot=dialog-popup]:has([data-slot=dialog-footer]:not(.border-t))]:pb-1",
|
|
171
|
+
className,
|
|
172
|
+
)}
|
|
173
|
+
data-slot="dialog-panel"
|
|
174
|
+
{...props}
|
|
175
|
+
/>
|
|
176
|
+
</ScrollArea>
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export {
|
|
181
|
+
DialogCreateHandle,
|
|
182
|
+
Dialog,
|
|
183
|
+
DialogTrigger,
|
|
184
|
+
DialogPortal,
|
|
185
|
+
DialogClose,
|
|
186
|
+
DialogBackdrop,
|
|
187
|
+
DialogBackdrop as DialogOverlay,
|
|
188
|
+
DialogPopup,
|
|
189
|
+
DialogPopup as DialogContent,
|
|
190
|
+
DialogHeader,
|
|
191
|
+
DialogFooter,
|
|
192
|
+
DialogTitle,
|
|
193
|
+
DialogDescription,
|
|
194
|
+
DialogPanel,
|
|
195
|
+
DialogViewport,
|
|
196
|
+
};
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Drawer as DrawerPrimitive } from "vaul";
|
|
5
|
+
|
|
6
|
+
import { cn } from "../../lib/utils/css";
|
|
7
|
+
|
|
8
|
+
function Drawer(props: React.ComponentProps<typeof DrawerPrimitive.Root>) {
|
|
9
|
+
return <DrawerPrimitive.Root data-slot="drawer" {...props} />;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function DrawerTrigger(
|
|
13
|
+
props: React.ComponentProps<typeof DrawerPrimitive.Trigger>,
|
|
14
|
+
) {
|
|
15
|
+
return <DrawerPrimitive.Trigger data-slot="drawer-trigger" {...props} />;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function DrawerPortal(
|
|
19
|
+
props: React.ComponentProps<typeof DrawerPrimitive.Portal>,
|
|
20
|
+
) {
|
|
21
|
+
return <DrawerPrimitive.Portal data-slot="drawer-portal" {...props} />;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function DrawerClose(props: React.ComponentProps<typeof DrawerPrimitive.Close>) {
|
|
25
|
+
return <DrawerPrimitive.Close data-slot="drawer-close" {...props} />;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function DrawerOverlay({
|
|
29
|
+
className,
|
|
30
|
+
...props
|
|
31
|
+
}: React.ComponentProps<typeof DrawerPrimitive.Overlay>) {
|
|
32
|
+
return (
|
|
33
|
+
<DrawerPrimitive.Overlay
|
|
34
|
+
className={cn(
|
|
35
|
+
"fixed inset-0 z-50 bg-black/32 backdrop-blur-sm data-[state=closed]:animate-out data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
36
|
+
className,
|
|
37
|
+
)}
|
|
38
|
+
data-slot="drawer-overlay"
|
|
39
|
+
{...props}
|
|
40
|
+
/>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function DrawerContent({
|
|
45
|
+
className,
|
|
46
|
+
children,
|
|
47
|
+
...props
|
|
48
|
+
}: React.ComponentProps<typeof DrawerPrimitive.Content>) {
|
|
49
|
+
return (
|
|
50
|
+
<DrawerPortal>
|
|
51
|
+
<DrawerOverlay />
|
|
52
|
+
<DrawerPrimitive.Content
|
|
53
|
+
className={cn(
|
|
54
|
+
"group/drawer-content fixed z-50 flex h-auto flex-col bg-popover not-dark:bg-clip-padding text-popover-foreground shadow-lg/5 outline-none",
|
|
55
|
+
"data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[82vh] data-[vaul-drawer-direction=bottom]:rounded-t-2xl data-[vaul-drawer-direction=bottom]:border-t",
|
|
56
|
+
"data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[82vh] data-[vaul-drawer-direction=top]:rounded-b-2xl data-[vaul-drawer-direction=top]:border-b",
|
|
57
|
+
"data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-[calc(100%-(--spacing(12)))] data-[vaul-drawer-direction=right]:max-w-md data-[vaul-drawer-direction=right]:border-s",
|
|
58
|
+
"data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-[calc(100%-(--spacing(12)))] data-[vaul-drawer-direction=left]:max-w-md data-[vaul-drawer-direction=left]:border-e",
|
|
59
|
+
className,
|
|
60
|
+
)}
|
|
61
|
+
data-slot="drawer-content"
|
|
62
|
+
{...props}
|
|
63
|
+
>
|
|
64
|
+
{/* Grab handle — shown for bottom/top drawers. */}
|
|
65
|
+
<div className="mx-auto mt-3 hidden h-1.5 w-12 shrink-0 rounded-full bg-border group-data-[vaul-drawer-direction=bottom]/drawer-content:block group-data-[vaul-drawer-direction=top]/drawer-content:block" />
|
|
66
|
+
{children}
|
|
67
|
+
</DrawerPrimitive.Content>
|
|
68
|
+
</DrawerPortal>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function DrawerHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
73
|
+
return (
|
|
74
|
+
<div
|
|
75
|
+
className={cn(
|
|
76
|
+
"flex flex-col gap-1.5 p-6 group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center md:group-data-[vaul-drawer-direction=bottom]/drawer-content:text-left",
|
|
77
|
+
className,
|
|
78
|
+
)}
|
|
79
|
+
data-slot="drawer-header"
|
|
80
|
+
{...props}
|
|
81
|
+
/>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function DrawerFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
86
|
+
return (
|
|
87
|
+
<div
|
|
88
|
+
className={cn(
|
|
89
|
+
"mt-auto flex flex-col gap-2 border-t bg-muted/72 px-6 py-4",
|
|
90
|
+
className,
|
|
91
|
+
)}
|
|
92
|
+
data-slot="drawer-footer"
|
|
93
|
+
{...props}
|
|
94
|
+
/>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function DrawerTitle({
|
|
99
|
+
className,
|
|
100
|
+
...props
|
|
101
|
+
}: React.ComponentProps<typeof DrawerPrimitive.Title>) {
|
|
102
|
+
return (
|
|
103
|
+
<DrawerPrimitive.Title
|
|
104
|
+
className={cn("font-semibold text-xl leading-none", className)}
|
|
105
|
+
data-slot="drawer-title"
|
|
106
|
+
{...props}
|
|
107
|
+
/>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function DrawerDescription({
|
|
112
|
+
className,
|
|
113
|
+
...props
|
|
114
|
+
}: React.ComponentProps<typeof DrawerPrimitive.Description>) {
|
|
115
|
+
return (
|
|
116
|
+
<DrawerPrimitive.Description
|
|
117
|
+
className={cn("text-muted-foreground text-sm", className)}
|
|
118
|
+
data-slot="drawer-description"
|
|
119
|
+
{...props}
|
|
120
|
+
/>
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export {
|
|
125
|
+
Drawer,
|
|
126
|
+
DrawerPortal,
|
|
127
|
+
DrawerOverlay,
|
|
128
|
+
DrawerTrigger,
|
|
129
|
+
DrawerClose,
|
|
130
|
+
DrawerContent,
|
|
131
|
+
DrawerHeader,
|
|
132
|
+
DrawerFooter,
|
|
133
|
+
DrawerTitle,
|
|
134
|
+
DrawerDescription,
|
|
135
|
+
};
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
2
|
+
|
|
3
|
+
import { cn } from "../../lib/utils/css";
|
|
4
|
+
|
|
5
|
+
function Empty({ className, ...props }: React.ComponentProps<"div">) {
|
|
6
|
+
return (
|
|
7
|
+
<div
|
|
8
|
+
className={cn(
|
|
9
|
+
"flex min-w-0 flex-1 flex-col items-center justify-center gap-6 text-balance p-6 text-center md:p-12",
|
|
10
|
+
className,
|
|
11
|
+
)}
|
|
12
|
+
data-slot="empty"
|
|
13
|
+
{...props}
|
|
14
|
+
/>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function EmptyHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
19
|
+
return (
|
|
20
|
+
<div
|
|
21
|
+
className={cn(
|
|
22
|
+
"flex max-w-sm flex-col items-center text-center",
|
|
23
|
+
className,
|
|
24
|
+
)}
|
|
25
|
+
data-slot="empty-header"
|
|
26
|
+
{...props}
|
|
27
|
+
/>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const emptyMediaVariants = cva(
|
|
32
|
+
"flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
33
|
+
{
|
|
34
|
+
defaultVariants: {
|
|
35
|
+
variant: "default",
|
|
36
|
+
},
|
|
37
|
+
variants: {
|
|
38
|
+
variant: {
|
|
39
|
+
default: "bg-transparent",
|
|
40
|
+
icon: "relative flex size-9 shrink-0 items-center justify-center rounded-md border bg-card text-foreground shadow-sm/5 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-md)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)] [&_svg:not([class*='size-'])]:size-4.5",
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
function EmptyMedia({
|
|
47
|
+
className,
|
|
48
|
+
variant = "default",
|
|
49
|
+
...props
|
|
50
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof emptyMediaVariants>) {
|
|
51
|
+
return (
|
|
52
|
+
<div
|
|
53
|
+
className={cn("relative mb-6", className)}
|
|
54
|
+
data-slot="empty-media"
|
|
55
|
+
data-variant={variant}
|
|
56
|
+
{...props}
|
|
57
|
+
>
|
|
58
|
+
{variant === "icon" && (
|
|
59
|
+
<>
|
|
60
|
+
<div
|
|
61
|
+
aria-hidden="true"
|
|
62
|
+
className={cn(
|
|
63
|
+
emptyMediaVariants({ className, variant }),
|
|
64
|
+
"-translate-x-0.5 -rotate-10 pointer-events-none absolute bottom-px origin-bottom-left scale-84 shadow-none",
|
|
65
|
+
)}
|
|
66
|
+
/>
|
|
67
|
+
<div
|
|
68
|
+
aria-hidden="true"
|
|
69
|
+
className={cn(
|
|
70
|
+
emptyMediaVariants({ className, variant }),
|
|
71
|
+
"pointer-events-none absolute bottom-px origin-bottom-right translate-x-0.5 rotate-10 scale-84 shadow-none",
|
|
72
|
+
)}
|
|
73
|
+
/>
|
|
74
|
+
</>
|
|
75
|
+
)}
|
|
76
|
+
<div
|
|
77
|
+
className={cn(emptyMediaVariants({ className, variant }))}
|
|
78
|
+
{...props}
|
|
79
|
+
/>
|
|
80
|
+
</div>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function EmptyTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
85
|
+
return (
|
|
86
|
+
<div
|
|
87
|
+
className={cn("font-heading font-semibold text-xl", className)}
|
|
88
|
+
data-slot="empty-title"
|
|
89
|
+
{...props}
|
|
90
|
+
/>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function EmptyDescription({ className, ...props }: React.ComponentProps<"p">) {
|
|
95
|
+
return (
|
|
96
|
+
<div
|
|
97
|
+
className={cn(
|
|
98
|
+
"text-muted-foreground text-sm [&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4 [[data-slot=empty-title]+&]:mt-1",
|
|
99
|
+
className,
|
|
100
|
+
)}
|
|
101
|
+
data-slot="empty-description"
|
|
102
|
+
{...props}
|
|
103
|
+
/>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function EmptyContent({ className, ...props }: React.ComponentProps<"div">) {
|
|
108
|
+
return (
|
|
109
|
+
<div
|
|
110
|
+
className={cn(
|
|
111
|
+
"flex w-full min-w-0 max-w-sm flex-col items-center gap-4 text-balance text-sm",
|
|
112
|
+
className,
|
|
113
|
+
)}
|
|
114
|
+
data-slot="empty-content"
|
|
115
|
+
{...props}
|
|
116
|
+
/>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export {
|
|
121
|
+
Empty,
|
|
122
|
+
EmptyHeader,
|
|
123
|
+
EmptyTitle,
|
|
124
|
+
EmptyDescription,
|
|
125
|
+
EmptyContent,
|
|
126
|
+
EmptyMedia,
|
|
127
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
4
|
+
import type * as React from "react";
|
|
5
|
+
|
|
6
|
+
import { cn } from "../../lib/utils/css";
|
|
7
|
+
import { Button, type ButtonProps } from "./button";
|
|
8
|
+
|
|
9
|
+
const fabVariants = cva(
|
|
10
|
+
"fixed z-50 rounded-full shadow-lg transition-transform duration-150 hover:scale-105 active:scale-95 before:rounded-full",
|
|
11
|
+
{
|
|
12
|
+
defaultVariants: {
|
|
13
|
+
position: "bottom-right",
|
|
14
|
+
},
|
|
15
|
+
variants: {
|
|
16
|
+
position: {
|
|
17
|
+
"bottom-right": "right-4 bottom-4 sm:right-6 sm:bottom-6",
|
|
18
|
+
"bottom-left": "bottom-4 left-4 sm:bottom-6 sm:left-6",
|
|
19
|
+
"top-right": "top-4 right-4 sm:top-6 sm:right-6",
|
|
20
|
+
"top-left": "top-4 left-4 sm:top-6 sm:left-6",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
export interface FabProps extends ButtonProps {
|
|
27
|
+
position?: VariantProps<typeof fabVariants>["position"];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Floating action button — a fixed, round icon button used to summon overlays
|
|
32
|
+
* such as chat widgets. Composes `Button`, so all button variants/sizes apply.
|
|
33
|
+
*/
|
|
34
|
+
function Fab({ className, position, size = "icon-xl", ...props }: FabProps) {
|
|
35
|
+
return (
|
|
36
|
+
<Button
|
|
37
|
+
className={cn(fabVariants({ className, position }))}
|
|
38
|
+
data-slot="fab"
|
|
39
|
+
size={size}
|
|
40
|
+
{...props}
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export { Fab, fabVariants };
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
4
|
+
import type * as React from "react";
|
|
5
|
+
|
|
6
|
+
import { cn } from "../../lib/utils/css";
|
|
7
|
+
|
|
8
|
+
const featuredIconVariants = cva(
|
|
9
|
+
"relative inline-flex shrink-0 select-none items-center justify-center align-middle [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
10
|
+
{
|
|
11
|
+
compoundVariants: [
|
|
12
|
+
// The bordered themes are squared, with corners that scale with the size.
|
|
13
|
+
{
|
|
14
|
+
className: "rounded-md before:rounded-[calc(var(--radius-md)-3px)]",
|
|
15
|
+
size: "sm",
|
|
16
|
+
theme: ["modern", "modern-neue"],
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
className: "rounded-lg before:rounded-[calc(var(--radius-lg)-3px)]",
|
|
20
|
+
size: "md",
|
|
21
|
+
theme: ["modern", "modern-neue"],
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
className: "rounded-[10px] before:rounded-[7px]",
|
|
25
|
+
size: "lg",
|
|
26
|
+
theme: ["modern", "modern-neue"],
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
className: "rounded-xl before:rounded-[calc(var(--radius-xl)-3px)]",
|
|
30
|
+
size: "xl",
|
|
31
|
+
theme: ["modern", "modern-neue"],
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
defaultVariants: { color: "brand", size: "md", theme: "light" },
|
|
35
|
+
variants: {
|
|
36
|
+
// Colors are applied through the theme/color maps below — the variant
|
|
37
|
+
// exists so cva carries the prop type.
|
|
38
|
+
color: { brand: "", error: "", gray: "", success: "", warning: "" },
|
|
39
|
+
size: {
|
|
40
|
+
sm: "size-8 [&_svg:not([class*='size-'])]:size-4",
|
|
41
|
+
md: "size-10 [&_svg:not([class*='size-'])]:size-5",
|
|
42
|
+
lg: "size-12 [&_svg:not([class*='size-'])]:size-6",
|
|
43
|
+
xl: "size-14 [&_svg:not([class*='size-'])]:size-7",
|
|
44
|
+
},
|
|
45
|
+
theme: {
|
|
46
|
+
dark: "rounded-full text-white shadow-xs not-dark:inset-shadow-[0_1px_--theme(--color-white/16%)]",
|
|
47
|
+
gradient:
|
|
48
|
+
"rounded-full bg-linear-to-b from-white/24 to-white/0 text-white shadow-xs inset-shadow-[0_1px_--theme(--color-white/24%)]",
|
|
49
|
+
light: "rounded-full",
|
|
50
|
+
modern:
|
|
51
|
+
"border border-input bg-background shadow-xs not-dark:bg-clip-padding dark:bg-input/32",
|
|
52
|
+
"modern-neue":
|
|
53
|
+
"border border-input bg-background shadow-xs not-dark:bg-clip-padding dark:bg-input/32 before:pointer-events-none before:absolute before:inset-[3px] before:border before:border-border/72 before:shadow-xs",
|
|
54
|
+
outline:
|
|
55
|
+
"rounded-full before:pointer-events-none before:absolute before:inset-0 before:rounded-full before:border-2 before:border-current before:opacity-12 after:pointer-events-none after:absolute after:inset-[15%] after:rounded-full after:border-2 after:border-current after:opacity-32",
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
type FeaturedIconTheme = NonNullable<
|
|
62
|
+
VariantProps<typeof featuredIconVariants>["theme"]
|
|
63
|
+
>;
|
|
64
|
+
type FeaturedIconColor = NonNullable<
|
|
65
|
+
VariantProps<typeof featuredIconVariants>["color"]
|
|
66
|
+
>;
|
|
67
|
+
|
|
68
|
+
/** Per-theme color treatments, using the design-system tonal/solid tokens. */
|
|
69
|
+
const featuredIconColors: Record<
|
|
70
|
+
FeaturedIconTheme,
|
|
71
|
+
Record<FeaturedIconColor, string>
|
|
72
|
+
> = {
|
|
73
|
+
dark: {
|
|
74
|
+
brand: "bg-brand",
|
|
75
|
+
error: "bg-destructive",
|
|
76
|
+
gray: "bg-secondary-foreground text-background",
|
|
77
|
+
success: "bg-success",
|
|
78
|
+
warning: "bg-warning",
|
|
79
|
+
},
|
|
80
|
+
gradient: {
|
|
81
|
+
brand: "bg-brand",
|
|
82
|
+
error: "bg-destructive",
|
|
83
|
+
gray: "bg-secondary-foreground text-background",
|
|
84
|
+
success: "bg-success",
|
|
85
|
+
warning: "bg-warning",
|
|
86
|
+
},
|
|
87
|
+
light: {
|
|
88
|
+
brand: "bg-brand/12 text-sidebar-primary dark:bg-brand/20",
|
|
89
|
+
error: "bg-destructive/8 text-destructive-foreground dark:bg-destructive/16",
|
|
90
|
+
gray: "bg-secondary text-secondary-foreground",
|
|
91
|
+
success: "bg-success/8 text-success-foreground dark:bg-success/16",
|
|
92
|
+
warning: "bg-warning/8 text-warning-foreground dark:bg-warning/16",
|
|
93
|
+
},
|
|
94
|
+
modern: {
|
|
95
|
+
brand: "text-sidebar-primary",
|
|
96
|
+
error: "text-destructive-foreground",
|
|
97
|
+
gray: "text-foreground",
|
|
98
|
+
success: "text-success-foreground",
|
|
99
|
+
warning: "text-warning-foreground",
|
|
100
|
+
},
|
|
101
|
+
"modern-neue": {
|
|
102
|
+
brand: "text-sidebar-primary",
|
|
103
|
+
error: "text-destructive-foreground",
|
|
104
|
+
gray: "text-foreground",
|
|
105
|
+
success: "text-success-foreground",
|
|
106
|
+
warning: "text-warning-foreground",
|
|
107
|
+
},
|
|
108
|
+
outline: {
|
|
109
|
+
brand: "text-sidebar-primary",
|
|
110
|
+
error: "text-destructive-foreground",
|
|
111
|
+
gray: "text-muted-foreground",
|
|
112
|
+
success: "text-success-foreground",
|
|
113
|
+
warning: "text-warning-foreground",
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
interface FeaturedIconProps extends Omit<React.ComponentProps<"span">, "color"> {
|
|
118
|
+
theme?: FeaturedIconTheme;
|
|
119
|
+
color?: FeaturedIconColor;
|
|
120
|
+
size?: VariantProps<typeof featuredIconVariants>["size"];
|
|
121
|
+
/** Icon component rendered inside (e.g. a lucide icon). Or pass children. */
|
|
122
|
+
icon?: React.ElementType;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function FeaturedIcon({
|
|
126
|
+
className,
|
|
127
|
+
theme = "light",
|
|
128
|
+
color = "brand",
|
|
129
|
+
size,
|
|
130
|
+
icon: Icon,
|
|
131
|
+
children,
|
|
132
|
+
...props
|
|
133
|
+
}: FeaturedIconProps) {
|
|
134
|
+
return (
|
|
135
|
+
<span
|
|
136
|
+
className={cn(
|
|
137
|
+
featuredIconVariants({ color, size, theme }),
|
|
138
|
+
featuredIconColors[theme][color],
|
|
139
|
+
className,
|
|
140
|
+
)}
|
|
141
|
+
data-slot="featured-icon"
|
|
142
|
+
{...props}
|
|
143
|
+
>
|
|
144
|
+
{children ?? (Icon ? <Icon /> : null)}
|
|
145
|
+
</span>
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export { FeaturedIcon, featuredIconVariants };
|