@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,160 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { NumberField as NumberFieldPrimitive } from "@base-ui/react/number-field";
|
|
4
|
+
import { MinusIcon, PlusIcon } from "lucide-react";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
import { Label } from "./label";
|
|
7
|
+
import { cn } from "../../lib/utils/css";
|
|
8
|
+
|
|
9
|
+
const NumberFieldContext = React.createContext<{
|
|
10
|
+
fieldId: string;
|
|
11
|
+
} | null>(null);
|
|
12
|
+
|
|
13
|
+
function NumberField({
|
|
14
|
+
id,
|
|
15
|
+
className,
|
|
16
|
+
size = "default",
|
|
17
|
+
...props
|
|
18
|
+
}: NumberFieldPrimitive.Root.Props & {
|
|
19
|
+
size?: "sm" | "default" | "lg";
|
|
20
|
+
}) {
|
|
21
|
+
const generatedId = React.useId();
|
|
22
|
+
const fieldId = id ?? generatedId;
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<NumberFieldContext.Provider value={{ fieldId }}>
|
|
26
|
+
<NumberFieldPrimitive.Root
|
|
27
|
+
className={cn("flex w-full flex-col items-start gap-2", className)}
|
|
28
|
+
data-size={size}
|
|
29
|
+
data-slot="number-field"
|
|
30
|
+
id={fieldId}
|
|
31
|
+
{...props}
|
|
32
|
+
/>
|
|
33
|
+
</NumberFieldContext.Provider>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function NumberFieldGroup({
|
|
38
|
+
className,
|
|
39
|
+
...props
|
|
40
|
+
}: NumberFieldPrimitive.Group.Props) {
|
|
41
|
+
return (
|
|
42
|
+
<NumberFieldPrimitive.Group
|
|
43
|
+
className={cn(
|
|
44
|
+
"relative flex w-full justify-between rounded-lg border border-input bg-background not-dark:bg-clip-padding text-base text-foreground shadow-xs/5 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-within:not-aria-invalid:before:shadow-[0_1px_--theme(--color-black/6%)] focus-within:border-ring focus-within:ring-[3px] has-aria-invalid:border-destructive/36 focus-within:has-aria-invalid:border-destructive/64 focus-within:has-aria-invalid:ring-destructive/48 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm dark:bg-input/32 dark:has-aria-invalid:ring-destructive/24 dark:not-data-disabled:not-focus-within:not-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/6%)] [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0 [[data-disabled],:focus-within,[aria-invalid]]:shadow-none",
|
|
45
|
+
className,
|
|
46
|
+
)}
|
|
47
|
+
data-slot="number-field-group"
|
|
48
|
+
{...props}
|
|
49
|
+
/>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function NumberFieldDecrement({
|
|
54
|
+
className,
|
|
55
|
+
...props
|
|
56
|
+
}: NumberFieldPrimitive.Decrement.Props) {
|
|
57
|
+
return (
|
|
58
|
+
<NumberFieldPrimitive.Decrement
|
|
59
|
+
className={cn(
|
|
60
|
+
"relative flex shrink-0 cursor-pointer items-center justify-center rounded-s-[calc(var(--radius-lg)-1px)] in-data-[size=sm]:px-[calc(--spacing(2.5)-1px)] px-[calc(--spacing(3)-1px)] transition-colors pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 hover:bg-accent",
|
|
61
|
+
className,
|
|
62
|
+
)}
|
|
63
|
+
data-slot="number-field-decrement"
|
|
64
|
+
{...props}
|
|
65
|
+
>
|
|
66
|
+
<MinusIcon />
|
|
67
|
+
</NumberFieldPrimitive.Decrement>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function NumberFieldIncrement({
|
|
72
|
+
className,
|
|
73
|
+
...props
|
|
74
|
+
}: NumberFieldPrimitive.Increment.Props) {
|
|
75
|
+
return (
|
|
76
|
+
<NumberFieldPrimitive.Increment
|
|
77
|
+
className={cn(
|
|
78
|
+
"relative flex shrink-0 cursor-pointer items-center justify-center rounded-e-[calc(var(--radius-lg)-1px)] in-data-[size=sm]:px-[calc(--spacing(2.5)-1px)] px-[calc(--spacing(3)-1px)] transition-colors pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 hover:bg-accent",
|
|
79
|
+
className,
|
|
80
|
+
)}
|
|
81
|
+
data-slot="number-field-increment"
|
|
82
|
+
{...props}
|
|
83
|
+
>
|
|
84
|
+
<PlusIcon />
|
|
85
|
+
</NumberFieldPrimitive.Increment>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function NumberFieldInput({
|
|
90
|
+
className,
|
|
91
|
+
...props
|
|
92
|
+
}: NumberFieldPrimitive.Input.Props) {
|
|
93
|
+
return (
|
|
94
|
+
<NumberFieldPrimitive.Input
|
|
95
|
+
className={cn(
|
|
96
|
+
"h-8.5 in-data-[size=lg]:h-9.5 in-data-[size=sm]:h-7.5 w-full min-w-0 grow bg-transparent in-data-[size=sm]:px-[calc(--spacing(2.5)-1px)] px-[calc(--spacing(3)-1px)] text-center tabular-nums in-data-[size=lg]:leading-9.5 in-data-[size=sm]:leading-7.5 leading-8.5 outline-none sm:h-7.5 sm:in-data-[size=lg]:h-8.5 sm:in-data-[size=sm]:h-6.5 sm:in-data-[size=lg]:leading-8.5 sm:in-data-[size=sm]:leading-8.5 sm:leading-7.5",
|
|
97
|
+
className,
|
|
98
|
+
)}
|
|
99
|
+
data-slot="number-field-input"
|
|
100
|
+
{...props}
|
|
101
|
+
/>
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function NumberFieldScrubArea({
|
|
106
|
+
className,
|
|
107
|
+
label,
|
|
108
|
+
...props
|
|
109
|
+
}: NumberFieldPrimitive.ScrubArea.Props & {
|
|
110
|
+
label: string;
|
|
111
|
+
}) {
|
|
112
|
+
const context = React.useContext(NumberFieldContext);
|
|
113
|
+
|
|
114
|
+
if (!context) {
|
|
115
|
+
throw new Error(
|
|
116
|
+
"NumberFieldScrubArea must be used within a NumberField component for accessibility.",
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
<NumberFieldPrimitive.ScrubArea
|
|
122
|
+
className={cn("flex cursor-ew-resize", className)}
|
|
123
|
+
data-slot="number-field-scrub-area"
|
|
124
|
+
{...props}
|
|
125
|
+
>
|
|
126
|
+
<Label className="cursor-ew-resize" htmlFor={context.fieldId}>
|
|
127
|
+
{label}
|
|
128
|
+
</Label>
|
|
129
|
+
<NumberFieldPrimitive.ScrubAreaCursor className="drop-shadow-[0_1px_1px_#0008] filter">
|
|
130
|
+
<CursorGrowIcon />
|
|
131
|
+
</NumberFieldPrimitive.ScrubAreaCursor>
|
|
132
|
+
</NumberFieldPrimitive.ScrubArea>
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function CursorGrowIcon(props: React.ComponentProps<"svg">) {
|
|
137
|
+
return (
|
|
138
|
+
// biome-ignore lint/a11y/noSvgWithoutTitle: Imported from library
|
|
139
|
+
<svg
|
|
140
|
+
fill="black"
|
|
141
|
+
height="14"
|
|
142
|
+
stroke="white"
|
|
143
|
+
viewBox="0 0 24 14"
|
|
144
|
+
width="26"
|
|
145
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
146
|
+
{...props}
|
|
147
|
+
>
|
|
148
|
+
<path d="M19.5 5.5L6.49737 5.51844V2L1 6.9999L6.5 12L6.49737 8.5L19.5 8.5V12L25 6.9999L19.5 2V5.5Z" />
|
|
149
|
+
</svg>
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export {
|
|
154
|
+
NumberField,
|
|
155
|
+
NumberFieldScrubArea,
|
|
156
|
+
NumberFieldDecrement,
|
|
157
|
+
NumberFieldIncrement,
|
|
158
|
+
NumberFieldGroup,
|
|
159
|
+
NumberFieldInput,
|
|
160
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Pagination,
|
|
3
|
+
PaginationContent,
|
|
4
|
+
PaginationEllipsis,
|
|
5
|
+
PaginationItem,
|
|
6
|
+
PaginationLink,
|
|
7
|
+
type PaginationLinkProps,
|
|
8
|
+
PaginationNext,
|
|
9
|
+
PaginationPrevious,
|
|
10
|
+
} from "./pagination";
|
|
11
|
+
|
|
12
|
+
export function PaginationControls(props: {
|
|
13
|
+
page: number;
|
|
14
|
+
pageCount: number;
|
|
15
|
+
renderPageLink: (page: number) => PaginationLinkProps["render"];
|
|
16
|
+
}) {
|
|
17
|
+
const { page, pageCount, renderPageLink } = props;
|
|
18
|
+
|
|
19
|
+
if (pageCount <= 1) return null;
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<Pagination>
|
|
23
|
+
<PaginationContent>
|
|
24
|
+
{/* Prev/Next are always rendered (disabled at the bounds) so they fade
|
|
25
|
+
between states instead of popping in and out. */}
|
|
26
|
+
<PaginationItem>
|
|
27
|
+
<PaginationPrevious
|
|
28
|
+
disabled={page <= 1}
|
|
29
|
+
render={page > 1 ? renderPageLink(page - 1) : <span />}
|
|
30
|
+
/>
|
|
31
|
+
</PaginationItem>
|
|
32
|
+
|
|
33
|
+
{page > 1 && (
|
|
34
|
+
<PaginationItem>
|
|
35
|
+
<PaginationLink render={renderPageLink(1)}>1</PaginationLink>
|
|
36
|
+
</PaginationItem>
|
|
37
|
+
)}
|
|
38
|
+
|
|
39
|
+
{page > 2 && (
|
|
40
|
+
<PaginationItem>
|
|
41
|
+
<PaginationEllipsis />
|
|
42
|
+
</PaginationItem>
|
|
43
|
+
)}
|
|
44
|
+
|
|
45
|
+
<PaginationItem>
|
|
46
|
+
<PaginationLink render={renderPageLink(page)} isActive>
|
|
47
|
+
{page}
|
|
48
|
+
</PaginationLink>
|
|
49
|
+
</PaginationItem>
|
|
50
|
+
|
|
51
|
+
{pageCount > page + 1 && (
|
|
52
|
+
<PaginationItem>
|
|
53
|
+
<PaginationEllipsis />
|
|
54
|
+
</PaginationItem>
|
|
55
|
+
)}
|
|
56
|
+
|
|
57
|
+
{pageCount > page && (
|
|
58
|
+
<PaginationItem>
|
|
59
|
+
<PaginationLink render={renderPageLink(pageCount)}>
|
|
60
|
+
{pageCount}
|
|
61
|
+
</PaginationLink>
|
|
62
|
+
</PaginationItem>
|
|
63
|
+
)}
|
|
64
|
+
|
|
65
|
+
<PaginationItem>
|
|
66
|
+
<PaginationNext
|
|
67
|
+
disabled={page >= pageCount}
|
|
68
|
+
render={page < pageCount ? renderPageLink(page + 1) : <span />}
|
|
69
|
+
/>
|
|
70
|
+
</PaginationItem>
|
|
71
|
+
</PaginationContent>
|
|
72
|
+
</Pagination>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { mergeProps } from "@base-ui/react/merge-props";
|
|
4
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
5
|
+
import {
|
|
6
|
+
ChevronLeftIcon,
|
|
7
|
+
ChevronRightIcon,
|
|
8
|
+
MoreHorizontalIcon,
|
|
9
|
+
} from "lucide-react";
|
|
10
|
+
import type * as React from "react";
|
|
11
|
+
import { type Button, buttonVariants } from "./button";
|
|
12
|
+
import { cn } from "../../lib/utils/css";
|
|
13
|
+
|
|
14
|
+
function Pagination({ className, ...props }: React.ComponentProps<"nav">) {
|
|
15
|
+
return (
|
|
16
|
+
<nav
|
|
17
|
+
aria-label="pagination"
|
|
18
|
+
className={cn("mx-auto flex w-full justify-center", className)}
|
|
19
|
+
data-slot="pagination"
|
|
20
|
+
{...props}
|
|
21
|
+
/>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function PaginationContent({
|
|
26
|
+
className,
|
|
27
|
+
...props
|
|
28
|
+
}: React.ComponentProps<"ul">) {
|
|
29
|
+
return (
|
|
30
|
+
<ul
|
|
31
|
+
className={cn("flex flex-row items-center gap-1", className)}
|
|
32
|
+
data-slot="pagination-content"
|
|
33
|
+
{...props}
|
|
34
|
+
/>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function PaginationItem({ className, ...props }: React.ComponentProps<"li">) {
|
|
39
|
+
return (
|
|
40
|
+
<li
|
|
41
|
+
className={cn(
|
|
42
|
+
"animate-in fade-in-0 zoom-in-95 duration-200 ease-out",
|
|
43
|
+
className,
|
|
44
|
+
)}
|
|
45
|
+
data-slot="pagination-item"
|
|
46
|
+
{...props}
|
|
47
|
+
/>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type PaginationLinkProps = {
|
|
52
|
+
isActive?: boolean;
|
|
53
|
+
disabled?: boolean;
|
|
54
|
+
size?: React.ComponentProps<typeof Button>["size"];
|
|
55
|
+
} & useRender.ComponentProps<"a">;
|
|
56
|
+
|
|
57
|
+
function PaginationLink({
|
|
58
|
+
className,
|
|
59
|
+
isActive,
|
|
60
|
+
disabled,
|
|
61
|
+
size = "icon",
|
|
62
|
+
render,
|
|
63
|
+
...props
|
|
64
|
+
}: PaginationLinkProps) {
|
|
65
|
+
const defaultProps = {
|
|
66
|
+
"aria-current": isActive ? ("page" as const) : undefined,
|
|
67
|
+
"aria-disabled": disabled || undefined,
|
|
68
|
+
className: cn(
|
|
69
|
+
buttonVariants({
|
|
70
|
+
size,
|
|
71
|
+
variant: isActive ? "outline" : "ghost",
|
|
72
|
+
}),
|
|
73
|
+
"transition-[opacity,box-shadow,filter] duration-200 ease-out",
|
|
74
|
+
disabled && "pointer-events-none opacity-50",
|
|
75
|
+
className,
|
|
76
|
+
),
|
|
77
|
+
"data-active": isActive,
|
|
78
|
+
"data-disabled": disabled || undefined,
|
|
79
|
+
"data-slot": "pagination-link",
|
|
80
|
+
tabIndex: disabled ? -1 : undefined,
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
return useRender({
|
|
84
|
+
defaultTagName: "a",
|
|
85
|
+
props: mergeProps<"a">(defaultProps, props),
|
|
86
|
+
render,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function PaginationPrevious({
|
|
91
|
+
className,
|
|
92
|
+
...props
|
|
93
|
+
}: React.ComponentProps<typeof PaginationLink>) {
|
|
94
|
+
return (
|
|
95
|
+
<PaginationLink
|
|
96
|
+
aria-label="Go to previous page"
|
|
97
|
+
className={cn("max-sm:aspect-square max-sm:p-0", className)}
|
|
98
|
+
size="default"
|
|
99
|
+
{...props}
|
|
100
|
+
>
|
|
101
|
+
<ChevronLeftIcon className="sm:-ms-1" />
|
|
102
|
+
<span className="max-sm:hidden">Previous</span>
|
|
103
|
+
</PaginationLink>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function PaginationNext({
|
|
108
|
+
className,
|
|
109
|
+
...props
|
|
110
|
+
}: React.ComponentProps<typeof PaginationLink>) {
|
|
111
|
+
return (
|
|
112
|
+
<PaginationLink
|
|
113
|
+
aria-label="Go to next page"
|
|
114
|
+
className={cn("max-sm:aspect-square max-sm:p-0", className)}
|
|
115
|
+
size="default"
|
|
116
|
+
{...props}
|
|
117
|
+
>
|
|
118
|
+
<span className="max-sm:hidden">Next</span>
|
|
119
|
+
<ChevronRightIcon className="sm:-me-1" />
|
|
120
|
+
</PaginationLink>
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function PaginationEllipsis({
|
|
125
|
+
className,
|
|
126
|
+
...props
|
|
127
|
+
}: React.ComponentProps<"span">) {
|
|
128
|
+
return (
|
|
129
|
+
<span
|
|
130
|
+
aria-hidden
|
|
131
|
+
className={cn("flex min-w-7 justify-center", className)}
|
|
132
|
+
data-slot="pagination-ellipsis"
|
|
133
|
+
{...props}
|
|
134
|
+
>
|
|
135
|
+
<MoreHorizontalIcon className="size-5 sm:size-4" />
|
|
136
|
+
<span className="sr-only">More pages</span>
|
|
137
|
+
</span>
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export {
|
|
142
|
+
Pagination,
|
|
143
|
+
PaginationContent,
|
|
144
|
+
PaginationLink,
|
|
145
|
+
PaginationItem,
|
|
146
|
+
PaginationPrevious,
|
|
147
|
+
PaginationNext,
|
|
148
|
+
PaginationEllipsis,
|
|
149
|
+
};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Popover as PopoverPrimitive } from "@base-ui/react/popover";
|
|
4
|
+
|
|
5
|
+
import { cn } from "../../lib/utils/css";
|
|
6
|
+
|
|
7
|
+
const PopoverCreateHandle = PopoverPrimitive.createHandle;
|
|
8
|
+
|
|
9
|
+
const Popover = PopoverPrimitive.Root;
|
|
10
|
+
|
|
11
|
+
function PopoverTrigger({
|
|
12
|
+
className,
|
|
13
|
+
children,
|
|
14
|
+
...props
|
|
15
|
+
}: PopoverPrimitive.Trigger.Props) {
|
|
16
|
+
return (
|
|
17
|
+
<PopoverPrimitive.Trigger
|
|
18
|
+
className={className}
|
|
19
|
+
data-slot="popover-trigger"
|
|
20
|
+
{...props}
|
|
21
|
+
>
|
|
22
|
+
{children}
|
|
23
|
+
</PopoverPrimitive.Trigger>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function PopoverPopup({
|
|
28
|
+
children,
|
|
29
|
+
className,
|
|
30
|
+
side = "bottom",
|
|
31
|
+
align = "center",
|
|
32
|
+
sideOffset = 4,
|
|
33
|
+
alignOffset = 0,
|
|
34
|
+
tooltipStyle = false,
|
|
35
|
+
anchor,
|
|
36
|
+
...props
|
|
37
|
+
}: PopoverPrimitive.Popup.Props & {
|
|
38
|
+
side?: PopoverPrimitive.Positioner.Props["side"];
|
|
39
|
+
align?: PopoverPrimitive.Positioner.Props["align"];
|
|
40
|
+
sideOffset?: PopoverPrimitive.Positioner.Props["sideOffset"];
|
|
41
|
+
alignOffset?: PopoverPrimitive.Positioner.Props["alignOffset"];
|
|
42
|
+
tooltipStyle?: boolean;
|
|
43
|
+
anchor?: PopoverPrimitive.Positioner.Props["anchor"];
|
|
44
|
+
}) {
|
|
45
|
+
return (
|
|
46
|
+
<PopoverPrimitive.Portal>
|
|
47
|
+
<PopoverPrimitive.Positioner
|
|
48
|
+
align={align}
|
|
49
|
+
alignOffset={alignOffset}
|
|
50
|
+
anchor={anchor}
|
|
51
|
+
className="z-50 h-(--positioner-height) w-(--positioner-width) max-w-(--available-width) transition-[top,left,right,bottom,transform] data-instant:transition-none"
|
|
52
|
+
data-slot="popover-positioner"
|
|
53
|
+
side={side}
|
|
54
|
+
sideOffset={sideOffset}
|
|
55
|
+
>
|
|
56
|
+
<PopoverPrimitive.Popup
|
|
57
|
+
className={cn(
|
|
58
|
+
"relative flex h-(--popup-height,auto) w-(--popup-width,auto) origin-(--transform-origin) rounded-lg border bg-popover not-dark:bg-clip-padding text-popover-foreground shadow-lg/5 outline-none transition-[width,height,scale,opacity] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] has-data-[slot=calendar]:rounded-xl has-data-[slot=calendar]:before:rounded-[calc(var(--radius-xl)-1px)] data-ending-style:scale-98 data-ending-style:opacity-0 data-starting-style:scale-98 data-starting-style:opacity-0 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
|
59
|
+
tooltipStyle &&
|
|
60
|
+
"w-fit text-balance rounded-md text-xs shadow-md/5 before:rounded-[calc(var(--radius-md)-1px)]",
|
|
61
|
+
className,
|
|
62
|
+
)}
|
|
63
|
+
data-slot="popover-popup"
|
|
64
|
+
{...props}
|
|
65
|
+
>
|
|
66
|
+
<PopoverPrimitive.Viewport
|
|
67
|
+
className={cn(
|
|
68
|
+
"relative size-full max-h-(--available-height) overflow-clip px-(--viewport-inline-padding) py-4 [--viewport-inline-padding:--spacing(4)] has-data-[slot=calendar]:p-2 data-instant:transition-none **:data-current:data-ending-style:opacity-0 **:data-current:data-starting-style:opacity-0 **:data-previous:data-ending-style:opacity-0 **:data-previous:data-starting-style:opacity-0 **:data-current:w-[calc(var(--popup-width)-2*var(--viewport-inline-padding)-2px)] **:data-previous:w-[calc(var(--popup-width)-2*var(--viewport-inline-padding)-2px)] **:data-current:opacity-100 **:data-previous:opacity-100 **:data-current:transition-opacity **:data-previous:transition-opacity",
|
|
69
|
+
tooltipStyle
|
|
70
|
+
? "py-1 [--viewport-inline-padding:--spacing(2)]"
|
|
71
|
+
: "not-data-transitioning:overflow-y-auto",
|
|
72
|
+
)}
|
|
73
|
+
data-slot="popover-viewport"
|
|
74
|
+
>
|
|
75
|
+
{children}
|
|
76
|
+
</PopoverPrimitive.Viewport>
|
|
77
|
+
</PopoverPrimitive.Popup>
|
|
78
|
+
</PopoverPrimitive.Positioner>
|
|
79
|
+
</PopoverPrimitive.Portal>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function PopoverClose({ ...props }: PopoverPrimitive.Close.Props) {
|
|
84
|
+
return <PopoverPrimitive.Close data-slot="popover-close" {...props} />;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function PopoverTitle({ className, ...props }: PopoverPrimitive.Title.Props) {
|
|
88
|
+
return (
|
|
89
|
+
<PopoverPrimitive.Title
|
|
90
|
+
className={cn("font-semibold text-lg leading-none", className)}
|
|
91
|
+
data-slot="popover-title"
|
|
92
|
+
{...props}
|
|
93
|
+
/>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function PopoverDescription({
|
|
98
|
+
className,
|
|
99
|
+
...props
|
|
100
|
+
}: PopoverPrimitive.Description.Props) {
|
|
101
|
+
return (
|
|
102
|
+
<PopoverPrimitive.Description
|
|
103
|
+
className={cn("text-muted-foreground text-sm", className)}
|
|
104
|
+
data-slot="popover-description"
|
|
105
|
+
{...props}
|
|
106
|
+
/>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export {
|
|
111
|
+
PopoverCreateHandle,
|
|
112
|
+
Popover,
|
|
113
|
+
PopoverTrigger,
|
|
114
|
+
PopoverPopup,
|
|
115
|
+
PopoverPopup as PopoverContent,
|
|
116
|
+
PopoverTitle,
|
|
117
|
+
PopoverDescription,
|
|
118
|
+
PopoverClose,
|
|
119
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { PreviewCard as PreviewCardPrimitive } from "@base-ui/react/preview-card";
|
|
4
|
+
|
|
5
|
+
import { cn } from "../../lib/utils/css";
|
|
6
|
+
|
|
7
|
+
const PreviewCard = PreviewCardPrimitive.Root;
|
|
8
|
+
|
|
9
|
+
function PreviewCardTrigger({ ...props }: PreviewCardPrimitive.Trigger.Props) {
|
|
10
|
+
return (
|
|
11
|
+
<PreviewCardPrimitive.Trigger data-slot="preview-card-trigger" {...props} />
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function PreviewCardPopup({
|
|
16
|
+
className,
|
|
17
|
+
children,
|
|
18
|
+
align = "center",
|
|
19
|
+
sideOffset = 4,
|
|
20
|
+
...props
|
|
21
|
+
}: PreviewCardPrimitive.Popup.Props & {
|
|
22
|
+
align?: PreviewCardPrimitive.Positioner.Props["align"];
|
|
23
|
+
sideOffset?: PreviewCardPrimitive.Positioner.Props["sideOffset"];
|
|
24
|
+
}) {
|
|
25
|
+
return (
|
|
26
|
+
<PreviewCardPrimitive.Portal>
|
|
27
|
+
<PreviewCardPrimitive.Positioner
|
|
28
|
+
align={align}
|
|
29
|
+
className="z-50"
|
|
30
|
+
data-slot="preview-card-positioner"
|
|
31
|
+
sideOffset={sideOffset}
|
|
32
|
+
>
|
|
33
|
+
<PreviewCardPrimitive.Popup
|
|
34
|
+
className={cn(
|
|
35
|
+
"relative flex w-64 origin-(--transform-origin) text-balance rounded-lg border bg-popover not-dark:bg-clip-padding p-4 text-popover-foreground text-sm shadow-lg/5 transition-[scale,opacity] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] 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%)]",
|
|
36
|
+
className,
|
|
37
|
+
)}
|
|
38
|
+
data-slot="preview-card-content"
|
|
39
|
+
{...props}
|
|
40
|
+
>
|
|
41
|
+
{children}
|
|
42
|
+
</PreviewCardPrimitive.Popup>
|
|
43
|
+
</PreviewCardPrimitive.Positioner>
|
|
44
|
+
</PreviewCardPrimitive.Portal>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export {
|
|
49
|
+
PreviewCard,
|
|
50
|
+
PreviewCard as HoverCard,
|
|
51
|
+
PreviewCardTrigger,
|
|
52
|
+
PreviewCardTrigger as HoverCardTrigger,
|
|
53
|
+
PreviewCardPopup,
|
|
54
|
+
PreviewCardPopup as HoverCardContent,
|
|
55
|
+
};
|