@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,38 @@
|
|
|
1
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
2
|
+
import { cn } from "../../lib/utils/css";
|
|
3
|
+
import type { AsChildProps } from "../../types/helpers";
|
|
4
|
+
|
|
5
|
+
const scrollerClassName =
|
|
6
|
+
"absolute top-1/2 z-10 -translate-y-1/2 data-closed:opacity-0";
|
|
7
|
+
|
|
8
|
+
const LeftScroller = ({
|
|
9
|
+
className,
|
|
10
|
+
asChild,
|
|
11
|
+
...props
|
|
12
|
+
}: AsChildProps<"button">) => {
|
|
13
|
+
const Comp = asChild ? Slot : "button";
|
|
14
|
+
return (
|
|
15
|
+
<Comp
|
|
16
|
+
{...(asChild ? {} : { type: "button" })}
|
|
17
|
+
className={cn(scrollerClassName, "left-0", className)}
|
|
18
|
+
{...props}
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const RightScroller = ({
|
|
24
|
+
className,
|
|
25
|
+
asChild,
|
|
26
|
+
...props
|
|
27
|
+
}: AsChildProps<"button">) => {
|
|
28
|
+
const Comp = asChild ? Slot : "button";
|
|
29
|
+
return (
|
|
30
|
+
<Comp
|
|
31
|
+
{...(asChild ? {} : { type: "button" })}
|
|
32
|
+
className={cn(scrollerClassName, "right-0", className)}
|
|
33
|
+
{...props}
|
|
34
|
+
/>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export { LeftScroller, RightScroller };
|
|
@@ -0,0 +1,118 @@
|
|
|
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 sectionHeaderTitleVariants = cva(
|
|
9
|
+
"min-w-0 font-semibold text-foreground tracking-tight",
|
|
10
|
+
{
|
|
11
|
+
defaultVariants: { size: "default" },
|
|
12
|
+
variants: {
|
|
13
|
+
size: {
|
|
14
|
+
sm: "text-sm",
|
|
15
|
+
default: "text-base",
|
|
16
|
+
lg: "text-lg",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
const sectionHeaderDescriptionVariants = cva(
|
|
23
|
+
"text-muted-foreground leading-relaxed",
|
|
24
|
+
{
|
|
25
|
+
defaultVariants: { size: "default" },
|
|
26
|
+
variants: {
|
|
27
|
+
size: {
|
|
28
|
+
sm: "text-xs",
|
|
29
|
+
default: "text-sm",
|
|
30
|
+
lg: "text-sm",
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
interface SectionHeaderProps
|
|
37
|
+
extends Omit<React.ComponentProps<"div">, "title">,
|
|
38
|
+
VariantProps<typeof sectionHeaderTitleVariants> {
|
|
39
|
+
title?: React.ReactNode;
|
|
40
|
+
description?: React.ReactNode;
|
|
41
|
+
/** Right-aligned actions (buttons, counts, menus). */
|
|
42
|
+
actions?: React.ReactNode;
|
|
43
|
+
/** A leading node — e.g. a `<FeaturedIcon />` or a count badge. */
|
|
44
|
+
icon?: React.ReactNode;
|
|
45
|
+
/** Adds a bottom hairline + padding, so the header sits above a list/grid. */
|
|
46
|
+
border?: boolean;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* A titled section heading: title + optional description on the left, optional
|
|
51
|
+
* actions on the right, with an optional leading icon. One altitude below the
|
|
52
|
+
* page-level `DashboardHeader` — use it to introduce a card body, a list, or a
|
|
53
|
+
* settings group.
|
|
54
|
+
*/
|
|
55
|
+
function SectionHeader({
|
|
56
|
+
className,
|
|
57
|
+
title,
|
|
58
|
+
description,
|
|
59
|
+
actions,
|
|
60
|
+
icon,
|
|
61
|
+
size,
|
|
62
|
+
border,
|
|
63
|
+
children,
|
|
64
|
+
...props
|
|
65
|
+
}: SectionHeaderProps) {
|
|
66
|
+
return (
|
|
67
|
+
<div
|
|
68
|
+
className={cn(
|
|
69
|
+
"flex items-start justify-between gap-3",
|
|
70
|
+
border && "border-b pb-4",
|
|
71
|
+
className,
|
|
72
|
+
)}
|
|
73
|
+
data-slot="section-header"
|
|
74
|
+
{...props}
|
|
75
|
+
>
|
|
76
|
+
<div className="flex min-w-0 items-start gap-3">
|
|
77
|
+
{icon ? (
|
|
78
|
+
<div className="shrink-0" data-slot="section-header-icon">
|
|
79
|
+
{icon}
|
|
80
|
+
</div>
|
|
81
|
+
) : null}
|
|
82
|
+
<div className="min-w-0 space-y-0.5">
|
|
83
|
+
{title ? (
|
|
84
|
+
<div
|
|
85
|
+
className={cn(sectionHeaderTitleVariants({ size }))}
|
|
86
|
+
data-slot="section-header-title"
|
|
87
|
+
>
|
|
88
|
+
{title}
|
|
89
|
+
</div>
|
|
90
|
+
) : null}
|
|
91
|
+
{description ? (
|
|
92
|
+
<p
|
|
93
|
+
className={cn(sectionHeaderDescriptionVariants({ size }))}
|
|
94
|
+
data-slot="section-header-description"
|
|
95
|
+
>
|
|
96
|
+
{description}
|
|
97
|
+
</p>
|
|
98
|
+
) : null}
|
|
99
|
+
{children}
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
{actions ? (
|
|
103
|
+
<div
|
|
104
|
+
className="flex shrink-0 items-center gap-2"
|
|
105
|
+
data-slot="section-header-actions"
|
|
106
|
+
>
|
|
107
|
+
{actions}
|
|
108
|
+
</div>
|
|
109
|
+
) : null}
|
|
110
|
+
</div>
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export {
|
|
115
|
+
SectionHeader,
|
|
116
|
+
sectionHeaderTitleVariants,
|
|
117
|
+
sectionHeaderDescriptionVariants,
|
|
118
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type * as React from "react";
|
|
4
|
+
|
|
5
|
+
import { ToggleGroup, ToggleGroupItem } from "./toggle-group";
|
|
6
|
+
import { cn } from "../../lib/utils/css";
|
|
7
|
+
|
|
8
|
+
interface SegmentedControlOption<T extends string> {
|
|
9
|
+
value: T;
|
|
10
|
+
label: React.ReactNode;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface SegmentedControlProps<T extends string> {
|
|
14
|
+
/** The currently-selected option value. */
|
|
15
|
+
value: T;
|
|
16
|
+
/** Called with the newly-selected value (never with an empty selection). */
|
|
17
|
+
onValueChange: (value: T) => void;
|
|
18
|
+
/** The mutually-exclusive options, left to right. */
|
|
19
|
+
options: SegmentedControlOption<T>[];
|
|
20
|
+
size?: "sm" | "default" | "lg";
|
|
21
|
+
variant?: "default" | "outline";
|
|
22
|
+
className?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Per-size segment padding. The base toggle sizes are icon-button tight
|
|
27
|
+
* (~5px), which crowds text labels like "Past 3 months"; a segmented control
|
|
28
|
+
* reads as text tabs, so it wants room to breathe on both axes.
|
|
29
|
+
*/
|
|
30
|
+
const SEGMENT_SIZE: Record<NonNullable<SegmentedControlProps<string>["size"]>, string> = {
|
|
31
|
+
sm: "h-8 px-3.5 sm:h-7",
|
|
32
|
+
default: "h-9 px-4 sm:h-8",
|
|
33
|
+
lg: "h-10 px-5 sm:h-9",
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* A single-select segmented control — a compact row of mutually-exclusive
|
|
38
|
+
* options (e.g. a time-range switch: Past month / Past 3 months / Overall).
|
|
39
|
+
*
|
|
40
|
+
* A thin, typed wrapper over {@link ToggleGroup} that keeps exactly one option
|
|
41
|
+
* selected — the active segment can't be toggled off into an empty state — and
|
|
42
|
+
* hides Base UI's array-value plumbing. Pass `options`, `value`, and
|
|
43
|
+
* `onValueChange`; the value is a string union you control.
|
|
44
|
+
*/
|
|
45
|
+
function SegmentedControl<T extends string>({
|
|
46
|
+
value,
|
|
47
|
+
onValueChange,
|
|
48
|
+
options,
|
|
49
|
+
size = "sm",
|
|
50
|
+
variant = "outline",
|
|
51
|
+
className,
|
|
52
|
+
}: SegmentedControlProps<T>) {
|
|
53
|
+
return (
|
|
54
|
+
<ToggleGroup
|
|
55
|
+
className={cn(className)}
|
|
56
|
+
data-slot="segmented-control"
|
|
57
|
+
value={[value]}
|
|
58
|
+
onValueChange={(groupValue) => {
|
|
59
|
+
const next = Array.isArray(groupValue) ? groupValue[0] : groupValue;
|
|
60
|
+
// Ignore the empty-array case so a segment always stays selected.
|
|
61
|
+
if (next != null) onValueChange(next as T);
|
|
62
|
+
}}
|
|
63
|
+
size={size}
|
|
64
|
+
variant={variant}
|
|
65
|
+
>
|
|
66
|
+
{options.map((option) => (
|
|
67
|
+
<ToggleGroupItem
|
|
68
|
+
key={option.value}
|
|
69
|
+
value={option.value}
|
|
70
|
+
className={SEGMENT_SIZE[size]}
|
|
71
|
+
>
|
|
72
|
+
{option.label}
|
|
73
|
+
</ToggleGroupItem>
|
|
74
|
+
))}
|
|
75
|
+
</ToggleGroup>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export {
|
|
80
|
+
SegmentedControl,
|
|
81
|
+
type SegmentedControlOption,
|
|
82
|
+
type SegmentedControlProps,
|
|
83
|
+
};
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Select as SelectPrimitive } from "@base-ui/react/select";
|
|
4
|
+
import {
|
|
5
|
+
ChevronDownIcon,
|
|
6
|
+
ChevronsUpDownIcon,
|
|
7
|
+
ChevronUpIcon,
|
|
8
|
+
} from "lucide-react";
|
|
9
|
+
|
|
10
|
+
import { cn } from "../../lib/utils/css";
|
|
11
|
+
|
|
12
|
+
const Select = SelectPrimitive.Root;
|
|
13
|
+
|
|
14
|
+
function SelectTrigger({
|
|
15
|
+
className,
|
|
16
|
+
size = "default",
|
|
17
|
+
children,
|
|
18
|
+
...props
|
|
19
|
+
}: SelectPrimitive.Trigger.Props & {
|
|
20
|
+
size?: "sm" | "default" | "lg";
|
|
21
|
+
}) {
|
|
22
|
+
return (
|
|
23
|
+
<SelectPrimitive.Trigger
|
|
24
|
+
className={cn(
|
|
25
|
+
"relative inline-flex min-h-9 w-full min-w-36 select-none items-center justify-center gap-2 rounded-lg border border-input bg-background not-dark:bg-clip-padding px-[calc(--spacing(3)-1px)] text-left text-base text-foreground shadow-xs/5 outline-none ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-data-disabled:not-focus-visible:not-aria-invalid:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 focus-visible:border-ring focus-visible:ring-[3px] aria-invalid:border-destructive/36 focus-visible:aria-invalid:border-destructive/64 focus-visible:aria-invalid:ring-destructive/16 data-disabled:pointer-events-none data-disabled:opacity-64 sm:min-h-8 sm:text-sm dark:aria-invalid:ring-destructive/24 dark:not-data-disabled:not-focus-visible:not-aria-invalid:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [&_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 [[data-disabled],:focus-visible,[aria-invalid],[data-pressed]]:shadow-none",
|
|
26
|
+
size === "sm" &&
|
|
27
|
+
"min-h-8 gap-1.5 px-[calc(--spacing(2.5)-1px)] sm:min-h-7",
|
|
28
|
+
size === "lg" && "min-h-10 sm:min-h-9",
|
|
29
|
+
className,
|
|
30
|
+
)}
|
|
31
|
+
data-slot="select-trigger"
|
|
32
|
+
{...props}
|
|
33
|
+
>
|
|
34
|
+
{children}
|
|
35
|
+
<SelectPrimitive.Icon data-slot="select-icon">
|
|
36
|
+
<ChevronsUpDownIcon className="-me-1 size-4.5 opacity-80 sm:size-4" />
|
|
37
|
+
</SelectPrimitive.Icon>
|
|
38
|
+
</SelectPrimitive.Trigger>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function SelectValue({ className, ...props }: SelectPrimitive.Value.Props) {
|
|
43
|
+
return (
|
|
44
|
+
<SelectPrimitive.Value
|
|
45
|
+
className={cn(
|
|
46
|
+
"flex-1 truncate data-placeholder:text-muted-foreground",
|
|
47
|
+
className,
|
|
48
|
+
)}
|
|
49
|
+
data-slot="select-value"
|
|
50
|
+
{...props}
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function SelectPopup({
|
|
56
|
+
className,
|
|
57
|
+
children,
|
|
58
|
+
sideOffset = 4,
|
|
59
|
+
alignItemWithTrigger = true,
|
|
60
|
+
...props
|
|
61
|
+
}: SelectPrimitive.Popup.Props & {
|
|
62
|
+
sideOffset?: SelectPrimitive.Positioner.Props["sideOffset"];
|
|
63
|
+
alignItemWithTrigger?: SelectPrimitive.Positioner.Props["alignItemWithTrigger"];
|
|
64
|
+
}) {
|
|
65
|
+
return (
|
|
66
|
+
<SelectPrimitive.Portal>
|
|
67
|
+
<SelectPrimitive.Positioner
|
|
68
|
+
alignItemWithTrigger={alignItemWithTrigger}
|
|
69
|
+
className="z-50 select-none"
|
|
70
|
+
data-slot="select-positioner"
|
|
71
|
+
sideOffset={sideOffset}
|
|
72
|
+
>
|
|
73
|
+
<SelectPrimitive.Popup
|
|
74
|
+
className="origin-(--transform-origin) text-foreground transition-[transform,scale,opacity] duration-150 ease-out data-ending-style:scale-95 data-ending-style:opacity-0 data-starting-style:scale-95 data-starting-style:opacity-0"
|
|
75
|
+
data-slot="select-popup"
|
|
76
|
+
{...props}
|
|
77
|
+
>
|
|
78
|
+
<SelectPrimitive.ScrollUpArrow
|
|
79
|
+
className="top-0 z-50 flex h-6 w-full cursor-default items-center justify-center before:pointer-events-none before:absolute before:inset-x-px before:top-px before:h-[200%] before:rounded-t-[calc(var(--radius-lg)-1px)] before:bg-linear-to-b before:from-50% before:from-popover"
|
|
80
|
+
data-slot="select-scroll-up-arrow"
|
|
81
|
+
>
|
|
82
|
+
<ChevronUpIcon className="relative size-4.5 sm:size-4" />
|
|
83
|
+
</SelectPrimitive.ScrollUpArrow>
|
|
84
|
+
<div className="relative h-full rounded-lg border bg-popover not-dark:bg-clip-padding shadow-lg/5 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%)]">
|
|
85
|
+
<SelectPrimitive.List
|
|
86
|
+
className={cn(
|
|
87
|
+
"max-h-(--available-height) min-w-(--anchor-width) overflow-y-auto p-1",
|
|
88
|
+
className,
|
|
89
|
+
)}
|
|
90
|
+
data-slot="select-list"
|
|
91
|
+
>
|
|
92
|
+
{children}
|
|
93
|
+
</SelectPrimitive.List>
|
|
94
|
+
</div>
|
|
95
|
+
<SelectPrimitive.ScrollDownArrow
|
|
96
|
+
className="bottom-0 z-50 flex h-6 w-full cursor-default items-center justify-center before:pointer-events-none before:absolute before:inset-x-px before:bottom-px before:h-[200%] before:rounded-b-[calc(var(--radius-lg)-1px)] before:bg-linear-to-t before:from-50% before:from-popover"
|
|
97
|
+
data-slot="select-scroll-down-arrow"
|
|
98
|
+
>
|
|
99
|
+
<ChevronDownIcon className="relative size-4.5 sm:size-4" />
|
|
100
|
+
</SelectPrimitive.ScrollDownArrow>
|
|
101
|
+
</SelectPrimitive.Popup>
|
|
102
|
+
</SelectPrimitive.Positioner>
|
|
103
|
+
</SelectPrimitive.Portal>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function SelectItem({
|
|
108
|
+
className,
|
|
109
|
+
children,
|
|
110
|
+
...props
|
|
111
|
+
}: SelectPrimitive.Item.Props) {
|
|
112
|
+
return (
|
|
113
|
+
<SelectPrimitive.Item
|
|
114
|
+
className={cn(
|
|
115
|
+
"grid min-h-8 in-data-[side=none]:min-w-[calc(var(--anchor-width)+1.25rem)] cursor-default grid-cols-[1rem_1fr] items-center gap-2 rounded-sm py-1 ps-2 pe-4 text-base outline-none data-disabled:pointer-events-none data-highlighted:bg-accent data-highlighted:text-accent-foreground data-disabled:opacity-64 sm:min-h-7 sm:text-sm [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
116
|
+
className,
|
|
117
|
+
)}
|
|
118
|
+
data-slot="select-item"
|
|
119
|
+
{...props}
|
|
120
|
+
>
|
|
121
|
+
<SelectPrimitive.ItemIndicator className="col-start-1">
|
|
122
|
+
{/** biome-ignore lint/a11y/noSvgWithoutTitle: Imported from library */}
|
|
123
|
+
<svg
|
|
124
|
+
fill="none"
|
|
125
|
+
height="24"
|
|
126
|
+
stroke="currentColor"
|
|
127
|
+
strokeLinecap="round"
|
|
128
|
+
strokeLinejoin="round"
|
|
129
|
+
strokeWidth="2"
|
|
130
|
+
viewBox="0 0 24 24"
|
|
131
|
+
width="24"
|
|
132
|
+
xmlns="http://www.w3.org/1500/svg"
|
|
133
|
+
>
|
|
134
|
+
<path d="M5.252 12.7 10.2 18.63 18.748 5.37" />
|
|
135
|
+
</svg>
|
|
136
|
+
</SelectPrimitive.ItemIndicator>
|
|
137
|
+
<SelectPrimitive.ItemText className="col-start-2 min-w-0">
|
|
138
|
+
{children}
|
|
139
|
+
</SelectPrimitive.ItemText>
|
|
140
|
+
</SelectPrimitive.Item>
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function SelectSeparator({
|
|
145
|
+
className,
|
|
146
|
+
...props
|
|
147
|
+
}: SelectPrimitive.Separator.Props) {
|
|
148
|
+
return (
|
|
149
|
+
<SelectPrimitive.Separator
|
|
150
|
+
className={cn("mx-2 my-1 h-px bg-border", className)}
|
|
151
|
+
data-slot="select-separator"
|
|
152
|
+
{...props}
|
|
153
|
+
/>
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function SelectGroup(props: SelectPrimitive.Group.Props) {
|
|
158
|
+
return <SelectPrimitive.Group data-slot="select-group" {...props} />;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function SelectGroupLabel(props: SelectPrimitive.GroupLabel.Props) {
|
|
162
|
+
return (
|
|
163
|
+
<SelectPrimitive.GroupLabel
|
|
164
|
+
className="px-2 py-1.5 font-medium text-muted-foreground text-xs"
|
|
165
|
+
data-slot="select-group-label"
|
|
166
|
+
{...props}
|
|
167
|
+
/>
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export {
|
|
172
|
+
Select,
|
|
173
|
+
SelectTrigger,
|
|
174
|
+
SelectValue,
|
|
175
|
+
SelectPopup,
|
|
176
|
+
SelectPopup as SelectContent,
|
|
177
|
+
SelectItem,
|
|
178
|
+
SelectSeparator,
|
|
179
|
+
SelectGroup,
|
|
180
|
+
SelectGroupLabel,
|
|
181
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Separator as SeparatorPrimitive } from "@base-ui/react/separator";
|
|
2
|
+
|
|
3
|
+
import { cn } from "../../lib/utils/css";
|
|
4
|
+
|
|
5
|
+
function Separator({
|
|
6
|
+
className,
|
|
7
|
+
orientation = "horizontal",
|
|
8
|
+
...props
|
|
9
|
+
}: SeparatorPrimitive.Props) {
|
|
10
|
+
return (
|
|
11
|
+
<SeparatorPrimitive
|
|
12
|
+
className={cn(
|
|
13
|
+
"shrink-0 bg-border 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",
|
|
14
|
+
className,
|
|
15
|
+
)}
|
|
16
|
+
data-slot="separator"
|
|
17
|
+
orientation={orientation}
|
|
18
|
+
{...props}
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { Separator };
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Dialog as SheetPrimitive } from "@base-ui/react/dialog";
|
|
4
|
+
import { cva } from "class-variance-authority";
|
|
5
|
+
import { XIcon } from "lucide-react";
|
|
6
|
+
import { Button } from "./button";
|
|
7
|
+
import { ScrollArea } from "./scroll-area";
|
|
8
|
+
import { cn } from "../../lib/utils/css";
|
|
9
|
+
|
|
10
|
+
const Sheet = SheetPrimitive.Root;
|
|
11
|
+
|
|
12
|
+
const SheetPortal = SheetPrimitive.Portal;
|
|
13
|
+
|
|
14
|
+
function SheetTrigger(props: SheetPrimitive.Trigger.Props) {
|
|
15
|
+
return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function SheetClose(props: SheetPrimitive.Close.Props) {
|
|
19
|
+
return <SheetPrimitive.Close data-slot="sheet-close" {...props} />;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function SheetBackdrop({ className, ...props }: SheetPrimitive.Backdrop.Props) {
|
|
23
|
+
return (
|
|
24
|
+
<SheetPrimitive.Backdrop
|
|
25
|
+
className={cn(
|
|
26
|
+
"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",
|
|
27
|
+
className,
|
|
28
|
+
)}
|
|
29
|
+
data-slot="sheet-backdrop"
|
|
30
|
+
{...props}
|
|
31
|
+
/>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const sheetViewportVariants = cva("fixed inset-0 z-50 grid", {
|
|
36
|
+
variants: {
|
|
37
|
+
side: {
|
|
38
|
+
bottom: "grid grid-rows-[1fr_auto] pt-12",
|
|
39
|
+
top: "grid grid-rows-[auto_1fr] pb-12",
|
|
40
|
+
left: "flex justify-start",
|
|
41
|
+
right: "flex justify-end",
|
|
42
|
+
},
|
|
43
|
+
variant: {
|
|
44
|
+
default: "",
|
|
45
|
+
inset: "sm:p-4",
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
function SheetViewport({
|
|
51
|
+
className,
|
|
52
|
+
side,
|
|
53
|
+
variant = "default",
|
|
54
|
+
...props
|
|
55
|
+
}: SheetPrimitive.Viewport.Props & {
|
|
56
|
+
side?: "right" | "left" | "top" | "bottom";
|
|
57
|
+
variant?: "default" | "inset";
|
|
58
|
+
}) {
|
|
59
|
+
return (
|
|
60
|
+
<SheetPrimitive.Viewport
|
|
61
|
+
className={cn(sheetViewportVariants({ side, variant }), className)}
|
|
62
|
+
data-slot="sheet-viewport"
|
|
63
|
+
{...props}
|
|
64
|
+
/>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export const sheetPopupVariants = cva(
|
|
69
|
+
"relative flex max-h-full min-h-0 w-full min-w-0 flex-col bg-popover not-dark:bg-clip-padding text-popover-foreground shadow-lg/5 transition-[opacity,translate] duration-200 ease-in-out will-change-transform before:pointer-events-none before:absolute before:inset-0 before:shadow-[0_1px_--theme(--color-black/6%)] data-ending-style:opacity-0 data-starting-style:opacity-0 max-sm:before:hidden dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
|
70
|
+
{
|
|
71
|
+
defaultVariants: {
|
|
72
|
+
variant: "default",
|
|
73
|
+
},
|
|
74
|
+
variants: {
|
|
75
|
+
side: {
|
|
76
|
+
bottom:
|
|
77
|
+
"row-start-2 border-t data-ending-style:translate-y-8 data-starting-style:translate-y-8",
|
|
78
|
+
top: "data-ending-style:-translate-y-8 data-starting-style:-translate-y-8 border-b",
|
|
79
|
+
left: "data-ending-style:-translate-x-8 data-starting-style:-translate-x-8 w-[calc(100%-(--spacing(12)))] max-w-md border-e",
|
|
80
|
+
right:
|
|
81
|
+
"col-start-2 w-[calc(100%-(--spacing(12)))] max-w-md border-s data-ending-style:translate-x-8 data-starting-style:translate-x-8",
|
|
82
|
+
},
|
|
83
|
+
variant: {
|
|
84
|
+
default: "",
|
|
85
|
+
inset:
|
|
86
|
+
"before:hidden sm:rounded-2xl sm:border sm:before:rounded-[calc(var(--radius-2xl)-1px)] sm:**:data-[slot=sheet-footer]:rounded-b-[calc(var(--radius-2xl)-1px)]",
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
function SheetPopup({
|
|
93
|
+
className,
|
|
94
|
+
children,
|
|
95
|
+
showCloseButton = true,
|
|
96
|
+
side = "right",
|
|
97
|
+
variant = "default",
|
|
98
|
+
...props
|
|
99
|
+
}: SheetPrimitive.Popup.Props & {
|
|
100
|
+
showCloseButton?: boolean;
|
|
101
|
+
side?: "right" | "left" | "top" | "bottom";
|
|
102
|
+
variant?: "default" | "inset";
|
|
103
|
+
}) {
|
|
104
|
+
return (
|
|
105
|
+
<SheetPortal>
|
|
106
|
+
<SheetBackdrop />
|
|
107
|
+
<SheetViewport side={side} variant={variant}>
|
|
108
|
+
<SheetPrimitive.Popup
|
|
109
|
+
className={cn(sheetPopupVariants({ side, variant }), className)}
|
|
110
|
+
data-slot="sheet-popup"
|
|
111
|
+
{...props}
|
|
112
|
+
>
|
|
113
|
+
{children}
|
|
114
|
+
{showCloseButton && (
|
|
115
|
+
<SheetPrimitive.Close
|
|
116
|
+
aria-label="Close"
|
|
117
|
+
className="absolute end-2 top-2"
|
|
118
|
+
render={<Button size="icon" variant="ghost" />}
|
|
119
|
+
>
|
|
120
|
+
<XIcon />
|
|
121
|
+
</SheetPrimitive.Close>
|
|
122
|
+
)}
|
|
123
|
+
</SheetPrimitive.Popup>
|
|
124
|
+
</SheetViewport>
|
|
125
|
+
</SheetPortal>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
130
|
+
return (
|
|
131
|
+
<div
|
|
132
|
+
className={cn(
|
|
133
|
+
"flex flex-col gap-2 p-6 in-[[data-slot=sheet-popup]:has([data-slot=sheet-panel])]:pb-3 max-sm:pb-4",
|
|
134
|
+
className,
|
|
135
|
+
)}
|
|
136
|
+
data-slot="sheet-header"
|
|
137
|
+
{...props}
|
|
138
|
+
/>
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function SheetFooter({
|
|
143
|
+
className,
|
|
144
|
+
variant = "default",
|
|
145
|
+
...props
|
|
146
|
+
}: React.ComponentProps<"div"> & {
|
|
147
|
+
variant?: "default" | "bare";
|
|
148
|
+
}) {
|
|
149
|
+
return (
|
|
150
|
+
<div
|
|
151
|
+
className={cn(
|
|
152
|
+
"flex flex-col-reverse gap-2 px-6 sm:flex-row sm:justify-end",
|
|
153
|
+
variant === "default" && "border-t bg-muted/72 py-4",
|
|
154
|
+
variant === "bare" &&
|
|
155
|
+
"in-[[data-slot=sheet-popup]:has([data-slot=sheet-panel])]:pt-3 pt-4 pb-6",
|
|
156
|
+
className,
|
|
157
|
+
)}
|
|
158
|
+
data-slot="sheet-footer"
|
|
159
|
+
{...props}
|
|
160
|
+
/>
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function SheetTitle({ className, ...props }: SheetPrimitive.Title.Props) {
|
|
165
|
+
return (
|
|
166
|
+
<SheetPrimitive.Title
|
|
167
|
+
className={cn(
|
|
168
|
+
"font-heading font-semibold text-xl leading-none",
|
|
169
|
+
className,
|
|
170
|
+
)}
|
|
171
|
+
data-slot="sheet-title"
|
|
172
|
+
{...props}
|
|
173
|
+
/>
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function SheetDescription({
|
|
178
|
+
className,
|
|
179
|
+
...props
|
|
180
|
+
}: SheetPrimitive.Description.Props) {
|
|
181
|
+
return (
|
|
182
|
+
<SheetPrimitive.Description
|
|
183
|
+
className={cn("text-muted-foreground text-sm", className)}
|
|
184
|
+
data-slot="sheet-description"
|
|
185
|
+
{...props}
|
|
186
|
+
/>
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function SheetPanel({
|
|
191
|
+
className,
|
|
192
|
+
scrollFade = true,
|
|
193
|
+
...props
|
|
194
|
+
}: React.ComponentProps<"div"> & { scrollFade?: boolean }) {
|
|
195
|
+
return (
|
|
196
|
+
<ScrollArea scrollFade={scrollFade}>
|
|
197
|
+
<div
|
|
198
|
+
className={cn(
|
|
199
|
+
"p-6 in-[[data-slot=sheet-popup]:has([data-slot=sheet-header])]:pt-1 in-[[data-slot=sheet-popup]:has([data-slot=sheet-footer]:not(.border-t))]:pb-1",
|
|
200
|
+
className,
|
|
201
|
+
)}
|
|
202
|
+
data-slot="sheet-panel"
|
|
203
|
+
{...props}
|
|
204
|
+
/>
|
|
205
|
+
</ScrollArea>
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export {
|
|
210
|
+
Sheet,
|
|
211
|
+
SheetTrigger,
|
|
212
|
+
SheetPortal,
|
|
213
|
+
SheetClose,
|
|
214
|
+
SheetBackdrop,
|
|
215
|
+
SheetViewport,
|
|
216
|
+
SheetBackdrop as SheetOverlay,
|
|
217
|
+
SheetPopup,
|
|
218
|
+
SheetPopup as SheetContent,
|
|
219
|
+
SheetHeader,
|
|
220
|
+
SheetFooter,
|
|
221
|
+
SheetTitle,
|
|
222
|
+
SheetDescription,
|
|
223
|
+
SheetPanel,
|
|
224
|
+
};
|