@boyernick/standard-ui-react 0.1.1-canary.3 → 0.1.1-canary.4
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/package.json +1 -1
- package/src/badge.tsx +73 -9
- package/src/breadcrumb.tsx +39 -21
- package/src/button.tsx +1 -1
- package/src/calendar.tsx +22 -11
- package/src/card.tsx +57 -14
- package/src/carousel.tsx +163 -6
- package/src/date-picker.tsx +169 -0
- package/src/icons.tsx +27 -0
- package/src/index.ts +18 -0
- package/src/menu.tsx +3 -3
package/package.json
CHANGED
package/src/badge.tsx
CHANGED
|
@@ -1,28 +1,92 @@
|
|
|
1
1
|
import { cva, type VariantProps } from "class-variance-authority"
|
|
2
|
-
import type { HTMLAttributes } from "react"
|
|
2
|
+
import type { HTMLAttributes, ReactNode } from "react"
|
|
3
3
|
import { cn } from "./lib/cn"
|
|
4
4
|
|
|
5
5
|
const badgeVariants = cva(
|
|
6
|
-
"
|
|
6
|
+
"inline-flex shrink-0 items-center justify-center whitespace-nowrap align-middle [&>[data-badge-label]]:min-w-0 [&>[data-badge-label]]:truncate [&>[data-badge-slot]]:inline-flex [&>[data-badge-slot]]:shrink-0 [&>[data-badge-slot]]:items-center [&>[data-badge-slot]]:justify-center [&>[data-badge-slot]>svg]:size-full",
|
|
7
7
|
{
|
|
8
8
|
variants: {
|
|
9
9
|
variant: {
|
|
10
|
-
default: "bg-background-tertiary
|
|
11
|
-
outline: "border border-border-primary
|
|
12
|
-
|
|
10
|
+
default: "bg-background-tertiary text-fg-primary",
|
|
11
|
+
outline: "border border-border-primary text-fg-secondary",
|
|
12
|
+
info: "bg-status-info-background text-status-info",
|
|
13
|
+
success: "bg-status-success-background text-status-success",
|
|
14
|
+
warning: "bg-status-warning-background text-status-warning",
|
|
15
|
+
critical: "bg-status-critical-background text-status-critical",
|
|
16
|
+
destructive: "bg-status-critical-background text-status-critical",
|
|
17
|
+
},
|
|
18
|
+
size: {
|
|
19
|
+
xxs: "text-2xs-strong h-4 gap-0.5 px-1.5 [&>[data-badge-slot]]:size-2.5",
|
|
20
|
+
xs: "text-2xs-strong h-5 gap-1 px-1.5 [&>[data-badge-slot]]:size-3",
|
|
21
|
+
sm: "text-xs-strong h-6 gap-1 px-2 [&>[data-badge-slot]]:size-3.5",
|
|
22
|
+
md: "text-xs-strong h-7 gap-1.5 px-2.5 [&>[data-badge-slot]]:size-3.5",
|
|
23
|
+
lg: "text-sm-strong h-8 gap-1.5 px-3 [&>[data-badge-slot]]:size-4",
|
|
24
|
+
},
|
|
25
|
+
rounded: {
|
|
26
|
+
true: "rounded-full",
|
|
27
|
+
false: "rounded-sm",
|
|
28
|
+
},
|
|
29
|
+
iconOnly: {
|
|
30
|
+
true: "p-0",
|
|
31
|
+
false: "",
|
|
13
32
|
},
|
|
14
33
|
},
|
|
34
|
+
compoundVariants: [
|
|
35
|
+
{ iconOnly: true, size: "xxs", class: "size-4" },
|
|
36
|
+
{ iconOnly: true, size: "xs", class: "size-5" },
|
|
37
|
+
{ iconOnly: true, size: "sm", class: "size-6" },
|
|
38
|
+
{ iconOnly: true, size: "md", class: "size-7" },
|
|
39
|
+
{ iconOnly: true, size: "lg", class: "size-8" },
|
|
40
|
+
],
|
|
15
41
|
defaultVariants: {
|
|
16
42
|
variant: "default",
|
|
43
|
+
size: "sm",
|
|
44
|
+
rounded: false,
|
|
45
|
+
iconOnly: false,
|
|
17
46
|
},
|
|
18
47
|
},
|
|
19
48
|
)
|
|
20
49
|
|
|
21
|
-
export type BadgeProps = HTMLAttributes<HTMLSpanElement> &
|
|
22
|
-
VariantProps<typeof badgeVariants>
|
|
50
|
+
export type BadgeProps = Omit<HTMLAttributes<HTMLSpanElement>, "prefix"> &
|
|
51
|
+
VariantProps<typeof badgeVariants> & {
|
|
52
|
+
/** Square badge sized to the height of `size`. */
|
|
53
|
+
iconOnly?: boolean
|
|
54
|
+
/** Pill shape (`rounded-full`) instead of the default light radius. */
|
|
55
|
+
rounded?: boolean
|
|
56
|
+
/** Icon or element before the label. */
|
|
57
|
+
prefix?: ReactNode
|
|
58
|
+
/** Icon or element after the label. */
|
|
59
|
+
suffix?: ReactNode
|
|
60
|
+
}
|
|
23
61
|
|
|
24
|
-
export const Badge = ({
|
|
25
|
-
|
|
62
|
+
export const Badge = ({
|
|
63
|
+
className,
|
|
64
|
+
variant,
|
|
65
|
+
size,
|
|
66
|
+
rounded,
|
|
67
|
+
iconOnly,
|
|
68
|
+
prefix,
|
|
69
|
+
suffix,
|
|
70
|
+
children,
|
|
71
|
+
...props
|
|
72
|
+
}: BadgeProps) => (
|
|
73
|
+
<span
|
|
74
|
+
className={cn(
|
|
75
|
+
badgeVariants({ variant, size, rounded, iconOnly }),
|
|
76
|
+
className,
|
|
77
|
+
)}
|
|
78
|
+
{...props}
|
|
79
|
+
>
|
|
80
|
+
{iconOnly ? (
|
|
81
|
+
<span data-badge-slot="icon">{children}</span>
|
|
82
|
+
) : (
|
|
83
|
+
<>
|
|
84
|
+
{prefix ? <span data-badge-slot="prefix">{prefix}</span> : null}
|
|
85
|
+
{children != null ? <span data-badge-label>{children}</span> : null}
|
|
86
|
+
{suffix ? <span data-badge-slot="suffix">{suffix}</span> : null}
|
|
87
|
+
</>
|
|
88
|
+
)}
|
|
89
|
+
</span>
|
|
26
90
|
)
|
|
27
91
|
|
|
28
92
|
export { badgeVariants }
|
package/src/breadcrumb.tsx
CHANGED
|
@@ -1,16 +1,30 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
2
|
+
import type { ComponentProps, ReactNode } from "react"
|
|
3
|
+
import { IconChevronRightSmall } from "./icons"
|
|
4
|
+
import { cn } from "./lib/cn"
|
|
5
|
+
import { motion } from "./lib/motion"
|
|
6
|
+
|
|
7
|
+
export type BreadcrumbProps = ComponentProps<"nav">
|
|
8
|
+
export type BreadcrumbListProps = ComponentProps<"ol">
|
|
9
|
+
export type BreadcrumbItemProps = ComponentProps<"li">
|
|
10
|
+
export type BreadcrumbLinkProps = ComponentProps<"a">
|
|
11
|
+
export type BreadcrumbPageProps = ComponentProps<"span">
|
|
12
|
+
|
|
13
|
+
const breadcrumbSeparatorVariants = cva("text-fg-tertiary", {
|
|
14
|
+
variants: {
|
|
15
|
+
variant: {
|
|
16
|
+
chevron: "[&_svg]:size-3.5",
|
|
17
|
+
slash: "px-0.5",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
defaultVariants: {
|
|
21
|
+
variant: "chevron",
|
|
22
|
+
},
|
|
23
|
+
})
|
|
5
24
|
|
|
6
|
-
export type BreadcrumbProps = ComponentProps<"nav">;
|
|
7
|
-
export type BreadcrumbListProps = ComponentProps<"ol">;
|
|
8
|
-
export type BreadcrumbItemProps = ComponentProps<"li">;
|
|
9
|
-
export type BreadcrumbLinkProps = ComponentProps<"a">;
|
|
10
|
-
export type BreadcrumbPageProps = ComponentProps<"span">;
|
|
11
25
|
export type BreadcrumbSeparatorProps = ComponentProps<"li"> & {
|
|
12
|
-
children?: ReactNode
|
|
13
|
-
}
|
|
26
|
+
children?: ReactNode
|
|
27
|
+
} & VariantProps<typeof breadcrumbSeparatorVariants>
|
|
14
28
|
|
|
15
29
|
export const Breadcrumb = ({ className, ...props }: BreadcrumbProps) => (
|
|
16
30
|
<nav
|
|
@@ -18,27 +32,27 @@ export const Breadcrumb = ({ className, ...props }: BreadcrumbProps) => (
|
|
|
18
32
|
className={cn("text-sm text-fg-secondary", className)}
|
|
19
33
|
{...props}
|
|
20
34
|
/>
|
|
21
|
-
)
|
|
35
|
+
)
|
|
22
36
|
|
|
23
37
|
export const BreadcrumbList = ({
|
|
24
38
|
className,
|
|
25
39
|
...props
|
|
26
40
|
}: BreadcrumbListProps) => (
|
|
27
41
|
<ol
|
|
28
|
-
className={cn("flex flex-wrap items-center gap-
|
|
42
|
+
className={cn("flex flex-wrap items-center gap-0.5", className)}
|
|
29
43
|
{...props}
|
|
30
44
|
/>
|
|
31
|
-
)
|
|
45
|
+
)
|
|
32
46
|
|
|
33
47
|
export const BreadcrumbItem = ({
|
|
34
48
|
className,
|
|
35
49
|
...props
|
|
36
50
|
}: BreadcrumbItemProps) => (
|
|
37
51
|
<li
|
|
38
|
-
className={cn("inline-flex items-center gap-1.5", className)}
|
|
52
|
+
className={cn("inline-flex items-center gap-1.5 px-1", className)}
|
|
39
53
|
{...props}
|
|
40
54
|
/>
|
|
41
|
-
)
|
|
55
|
+
)
|
|
42
56
|
|
|
43
57
|
export const BreadcrumbLink = ({
|
|
44
58
|
className,
|
|
@@ -52,7 +66,7 @@ export const BreadcrumbLink = ({
|
|
|
52
66
|
)}
|
|
53
67
|
{...props}
|
|
54
68
|
/>
|
|
55
|
-
)
|
|
69
|
+
)
|
|
56
70
|
|
|
57
71
|
export const BreadcrumbPage = ({
|
|
58
72
|
className,
|
|
@@ -63,19 +77,23 @@ export const BreadcrumbPage = ({
|
|
|
63
77
|
className={cn("font-medium text-fg-primary", className)}
|
|
64
78
|
{...props}
|
|
65
79
|
/>
|
|
66
|
-
)
|
|
80
|
+
)
|
|
67
81
|
|
|
68
82
|
export const BreadcrumbSeparator = ({
|
|
69
83
|
className,
|
|
70
84
|
children,
|
|
85
|
+
variant,
|
|
71
86
|
...props
|
|
72
87
|
}: BreadcrumbSeparatorProps) => (
|
|
73
88
|
<li
|
|
74
89
|
role="presentation"
|
|
75
90
|
aria-hidden
|
|
76
|
-
className={cn(
|
|
91
|
+
className={cn(breadcrumbSeparatorVariants({ variant }), className)}
|
|
77
92
|
{...props}
|
|
78
93
|
>
|
|
79
|
-
{children ??
|
|
94
|
+
{children ??
|
|
95
|
+
(variant === "slash" ? "/" : <IconChevronRightSmall aria-hidden />)}
|
|
80
96
|
</li>
|
|
81
|
-
)
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
export { breadcrumbSeparatorVariants }
|
package/src/button.tsx
CHANGED
package/src/calendar.tsx
CHANGED
|
@@ -8,9 +8,9 @@ import { motion } from "./lib/motion"
|
|
|
8
8
|
export type CalendarProps = DayPickerProps
|
|
9
9
|
|
|
10
10
|
const navButtonClassName = cn(
|
|
11
|
-
"inline-flex size-
|
|
11
|
+
"inline-flex size-6 items-center justify-center rounded-md border border-transparent text-fg-tertiary",
|
|
12
12
|
motion.colors,
|
|
13
|
-
"hover:bg-background-tertiary hover:text-fg-primary outline-none focus-visible:border-ring focus-visible:
|
|
13
|
+
"hover:bg-background-tertiary hover:text-fg-primary outline-none focus-visible:border-ring focus-visible:bg-background-tertiary focus-visible:text-fg-primary focus-visible:ring-2 focus-visible:ring-ring/20 disabled:cursor-not-allowed disabled:opacity-50",
|
|
14
14
|
)
|
|
15
15
|
|
|
16
16
|
const CalendarChevron = ({
|
|
@@ -40,34 +40,45 @@ export const Calendar = ({
|
|
|
40
40
|
className,
|
|
41
41
|
classNames,
|
|
42
42
|
showOutsideDays = true,
|
|
43
|
+
weekStartsOn = 1,
|
|
43
44
|
components,
|
|
44
45
|
...props
|
|
45
46
|
}: CalendarProps) => (
|
|
46
47
|
<DayPicker
|
|
47
48
|
showOutsideDays={showOutsideDays}
|
|
48
|
-
|
|
49
|
+
weekStartsOn={weekStartsOn}
|
|
50
|
+
className={cn(
|
|
51
|
+
"w-64 rounded-xl border border-border-primary bg-surface p-3",
|
|
52
|
+
className,
|
|
53
|
+
)}
|
|
49
54
|
classNames={{
|
|
50
55
|
months: "relative flex flex-col gap-4 sm:flex-row",
|
|
51
|
-
month: "flex w-full flex-col
|
|
52
|
-
month_caption: "
|
|
56
|
+
month: "flex w-full flex-col",
|
|
57
|
+
month_caption: "flex h-8 items-start justify-start",
|
|
53
58
|
caption_label: "text-sm-strong text-fg-primary",
|
|
54
|
-
nav: "absolute
|
|
59
|
+
nav: "absolute top-0 right-0 flex items-center",
|
|
55
60
|
button_previous: navButtonClassName,
|
|
56
61
|
button_next: navButtonClassName,
|
|
57
62
|
month_grid: "w-full border-collapse",
|
|
58
63
|
weekdays: "flex",
|
|
59
64
|
weekday:
|
|
60
|
-
"flex
|
|
61
|
-
weeks: "flex flex-col",
|
|
62
|
-
week: "
|
|
65
|
+
"flex w-8 items-center justify-center pb-1 text-xs font-normal text-fg-tertiary select-none",
|
|
66
|
+
weeks: "flex flex-col gap-1",
|
|
67
|
+
week: "flex w-full",
|
|
63
68
|
day: "relative p-0 text-center",
|
|
64
69
|
day_button: cn(
|
|
65
|
-
"inline-flex size-8 items-center justify-center rounded-
|
|
70
|
+
"inline-flex size-8 items-center justify-center rounded-lg text-sm text-fg-primary tabular-nums",
|
|
66
71
|
motion.colors,
|
|
67
|
-
"hover:bg-background-tertiary outline-none focus-visible:
|
|
72
|
+
"hover:bg-background-tertiary outline-none focus-visible:z-10 focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 aria-selected:opacity-100",
|
|
68
73
|
),
|
|
69
74
|
selected:
|
|
70
75
|
"[&>button]:bg-brand-primary [&>button]:text-brand-foreground [&>button]:ring-0 [&>button]:hover:bg-brand-primary-hover [&>button]:hover:text-brand-foreground",
|
|
76
|
+
range_start:
|
|
77
|
+
"rounded-l-lg bg-brand-primary/10 last:rounded-r-lg [&>button]:relative [&>button]:z-[1]",
|
|
78
|
+
range_middle:
|
|
79
|
+
"bg-brand-primary/10 first:rounded-l-lg last:rounded-r-lg [&>button]:!rounded-none [&>button]:!bg-transparent [&>button]:!text-fg-primary [&>button]:hover:!bg-brand-primary/15",
|
|
80
|
+
range_end:
|
|
81
|
+
"rounded-r-lg bg-brand-primary/10 first:rounded-l-lg [&>button]:relative [&>button]:z-[1]",
|
|
71
82
|
today:
|
|
72
83
|
"[&>button]:font-medium [&>button]:ring-1 [&>button]:ring-inset [&>button]:ring-border-secondary",
|
|
73
84
|
outside: "[&>button]:text-fg-quaternary",
|
package/src/card.tsx
CHANGED
|
@@ -1,32 +1,59 @@
|
|
|
1
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
1
2
|
import type { HTMLAttributes } from "react"
|
|
2
3
|
import { cn } from "./lib/cn"
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
const cardVariants = cva("flex flex-col rounded-xl bg-surface text-fg-primary", {
|
|
6
|
+
variants: {
|
|
7
|
+
variant: {
|
|
8
|
+
elevated: "shadow-lg",
|
|
9
|
+
outline: "border border-border-primary",
|
|
10
|
+
ghost: "",
|
|
11
|
+
},
|
|
12
|
+
padding: {
|
|
13
|
+
md: "gap-6 py-6",
|
|
14
|
+
none: "",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
defaultVariants: {
|
|
18
|
+
variant: "elevated",
|
|
19
|
+
padding: "md",
|
|
20
|
+
},
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
export type CardProps = HTMLAttributes<HTMLDivElement> &
|
|
24
|
+
VariantProps<typeof cardVariants>
|
|
5
25
|
export type CardHeaderProps = HTMLAttributes<HTMLDivElement>
|
|
6
26
|
export type CardTitleProps = HTMLAttributes<HTMLHeadingElement>
|
|
7
27
|
export type CardDescriptionProps = HTMLAttributes<HTMLParagraphElement>
|
|
28
|
+
export type CardActionProps = HTMLAttributes<HTMLDivElement>
|
|
8
29
|
export type CardContentProps = HTMLAttributes<HTMLDivElement>
|
|
9
30
|
export type CardFooterProps = HTMLAttributes<HTMLDivElement>
|
|
10
31
|
|
|
11
|
-
export const Card = ({ className, ...props }: CardProps) => (
|
|
32
|
+
export const Card = ({ className, variant, padding, ...props }: CardProps) => (
|
|
12
33
|
<div
|
|
13
|
-
className={cn(
|
|
14
|
-
"flex flex-col overflow-hidden rounded-xl border border-border-primary bg-surface",
|
|
15
|
-
className,
|
|
16
|
-
)}
|
|
17
34
|
{...props}
|
|
35
|
+
data-slot="card"
|
|
36
|
+
className={cn(cardVariants({ variant, padding }), className)}
|
|
18
37
|
/>
|
|
19
38
|
)
|
|
20
39
|
|
|
21
40
|
export const CardHeader = ({ className, ...props }: CardHeaderProps) => (
|
|
22
41
|
<div
|
|
23
|
-
className={cn("flex flex-col gap-1 px-5 pt-5 pb-3", className)}
|
|
24
42
|
{...props}
|
|
43
|
+
data-slot="card-header"
|
|
44
|
+
className={cn(
|
|
45
|
+
"grid auto-rows-min items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto]",
|
|
46
|
+
className,
|
|
47
|
+
)}
|
|
25
48
|
/>
|
|
26
49
|
)
|
|
27
50
|
|
|
28
51
|
export const CardTitle = ({ className, ...props }: CardTitleProps) => (
|
|
29
|
-
<h3
|
|
52
|
+
<h3
|
|
53
|
+
{...props}
|
|
54
|
+
data-slot="card-title"
|
|
55
|
+
className={cn("text-sm-strong leading-none text-fg-primary", className)}
|
|
56
|
+
/>
|
|
30
57
|
)
|
|
31
58
|
|
|
32
59
|
export const CardDescription = ({
|
|
@@ -34,21 +61,37 @@ export const CardDescription = ({
|
|
|
34
61
|
...props
|
|
35
62
|
}: CardDescriptionProps) => (
|
|
36
63
|
<p
|
|
37
|
-
className={cn("text-sm leading-relaxed text-fg-secondary", className)}
|
|
38
64
|
{...props}
|
|
65
|
+
data-slot="card-description"
|
|
66
|
+
className={cn("text-sm text-fg-secondary", className)}
|
|
67
|
+
/>
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
export const CardAction = ({ className, ...props }: CardActionProps) => (
|
|
71
|
+
<div
|
|
72
|
+
{...props}
|
|
73
|
+
data-slot="card-action"
|
|
74
|
+
className={cn(
|
|
75
|
+
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
|
|
76
|
+
className,
|
|
77
|
+
)}
|
|
39
78
|
/>
|
|
40
79
|
)
|
|
41
80
|
|
|
42
81
|
export const CardContent = ({ className, ...props }: CardContentProps) => (
|
|
43
|
-
<div
|
|
82
|
+
<div
|
|
83
|
+
{...props}
|
|
84
|
+
data-slot="card-content"
|
|
85
|
+
className={cn("px-6", className)}
|
|
86
|
+
/>
|
|
44
87
|
)
|
|
45
88
|
|
|
46
89
|
export const CardFooter = ({ className, ...props }: CardFooterProps) => (
|
|
47
90
|
<div
|
|
48
|
-
className={cn(
|
|
49
|
-
"flex items-center gap-2 border-t border-border-primary px-5 py-4",
|
|
50
|
-
className,
|
|
51
|
-
)}
|
|
52
91
|
{...props}
|
|
92
|
+
data-slot="card-footer"
|
|
93
|
+
className={cn("flex items-center gap-2 px-6", className)}
|
|
53
94
|
/>
|
|
54
95
|
)
|
|
96
|
+
|
|
97
|
+
export { cardVariants }
|
package/src/carousel.tsx
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
useCallback,
|
|
9
9
|
useContext,
|
|
10
10
|
useEffect,
|
|
11
|
+
useRef,
|
|
11
12
|
useSyncExternalStore,
|
|
12
13
|
type ComponentProps,
|
|
13
14
|
type KeyboardEvent,
|
|
@@ -21,6 +22,9 @@ type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
|
|
|
21
22
|
type CarouselOptions = UseCarouselParameters[0]
|
|
22
23
|
type CarouselPlugin = UseCarouselParameters[1]
|
|
23
24
|
|
|
25
|
+
const TRACKPAD_SWIPE_THRESHOLD = 24
|
|
26
|
+
const TRACKPAD_GESTURE_END_DELAY = 140
|
|
27
|
+
|
|
24
28
|
type CarouselContextValue = {
|
|
25
29
|
carouselRef: ReturnType<typeof useEmblaCarousel>[0]
|
|
26
30
|
api: CarouselApi
|
|
@@ -46,6 +50,8 @@ export type CarouselProps = ComponentProps<"div"> & {
|
|
|
46
50
|
plugins?: CarouselPlugin
|
|
47
51
|
orientation?: "horizontal" | "vertical"
|
|
48
52
|
setApi?: (api: CarouselApi) => void
|
|
53
|
+
/** Adds directional edge fades wherever more slides are available. */
|
|
54
|
+
fade?: boolean
|
|
49
55
|
}
|
|
50
56
|
|
|
51
57
|
export type CarouselContentProps = ComponentProps<"div">
|
|
@@ -53,16 +59,54 @@ export type CarouselItemProps = ComponentProps<"div">
|
|
|
53
59
|
export type CarouselPreviousProps = ComponentProps<typeof Button>
|
|
54
60
|
export type CarouselNextProps = ComponentProps<typeof Button>
|
|
55
61
|
|
|
62
|
+
const CarouselEdgeFades = () => {
|
|
63
|
+
const { orientation, canScrollPrev, canScrollNext } = useCarousel()
|
|
64
|
+
const horizontal = orientation === "horizontal"
|
|
65
|
+
const sharedClassName =
|
|
66
|
+
"pointer-events-none absolute z-10 opacity-0 transition-opacity duration-[var(--duration-lg)] ease-enter data-[visible=true]:opacity-100 motion-reduce:transition-none"
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<>
|
|
70
|
+
<div
|
|
71
|
+
aria-hidden="true"
|
|
72
|
+
data-slot={horizontal ? "carousel-fade-left" : "carousel-fade-top"}
|
|
73
|
+
data-visible={canScrollPrev}
|
|
74
|
+
className={cn(
|
|
75
|
+
sharedClassName,
|
|
76
|
+
horizontal
|
|
77
|
+
? "-top-px -bottom-px -left-px w-20 bg-linear-to-r from-surface via-surface/60 via-40% to-transparent"
|
|
78
|
+
: "-top-px -right-px -left-px h-20 bg-linear-to-b from-surface via-surface/60 via-40% to-transparent",
|
|
79
|
+
)}
|
|
80
|
+
/>
|
|
81
|
+
<div
|
|
82
|
+
aria-hidden="true"
|
|
83
|
+
data-slot={horizontal ? "carousel-fade-right" : "carousel-fade-bottom"}
|
|
84
|
+
data-visible={canScrollNext}
|
|
85
|
+
className={cn(
|
|
86
|
+
sharedClassName,
|
|
87
|
+
horizontal
|
|
88
|
+
? "-top-px -right-px -bottom-px w-20 bg-linear-to-l from-surface via-surface/60 via-40% to-transparent"
|
|
89
|
+
: "-right-px -bottom-px -left-px h-20 bg-linear-to-t from-surface via-surface/60 via-40% to-transparent",
|
|
90
|
+
)}
|
|
91
|
+
/>
|
|
92
|
+
</>
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
|
|
56
96
|
export const Carousel = ({
|
|
57
97
|
orientation = "horizontal",
|
|
98
|
+
fade = false,
|
|
58
99
|
opts,
|
|
59
100
|
setApi,
|
|
60
101
|
plugins,
|
|
61
102
|
className,
|
|
62
103
|
children,
|
|
63
104
|
onKeyDownCapture,
|
|
105
|
+
tabIndex,
|
|
106
|
+
ref: forwardedRef,
|
|
64
107
|
...props
|
|
65
108
|
}: CarouselProps) => {
|
|
109
|
+
const carouselRootRef = useRef<HTMLDivElement | null>(null)
|
|
66
110
|
const [carouselRef, api] = useEmblaCarousel(
|
|
67
111
|
{
|
|
68
112
|
...opts,
|
|
@@ -107,6 +151,35 @@ export const Carousel = ({
|
|
|
107
151
|
api?.scrollNext()
|
|
108
152
|
}, [api])
|
|
109
153
|
|
|
154
|
+
const canScrollPrevRef = useRef(canScrollPrev)
|
|
155
|
+
const canScrollNextRef = useRef(canScrollNext)
|
|
156
|
+
const scrollPrevRef = useRef(scrollPrev)
|
|
157
|
+
const scrollNextRef = useRef(scrollNext)
|
|
158
|
+
|
|
159
|
+
useEffect(() => {
|
|
160
|
+
canScrollPrevRef.current = canScrollPrev
|
|
161
|
+
canScrollNextRef.current = canScrollNext
|
|
162
|
+
scrollPrevRef.current = scrollPrev
|
|
163
|
+
scrollNextRef.current = scrollNext
|
|
164
|
+
}, [canScrollNext, canScrollPrev, scrollNext, scrollPrev])
|
|
165
|
+
|
|
166
|
+
const trackpadDelta = useRef(0)
|
|
167
|
+
const trackpadGestureHandled = useRef(false)
|
|
168
|
+
const trackpadGestureTimeout = useRef<ReturnType<typeof setTimeout> | null>(
|
|
169
|
+
null,
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
const scheduleTrackpadGestureEnd = useCallback(() => {
|
|
173
|
+
if (trackpadGestureTimeout.current) {
|
|
174
|
+
clearTimeout(trackpadGestureTimeout.current)
|
|
175
|
+
}
|
|
176
|
+
trackpadGestureTimeout.current = setTimeout(() => {
|
|
177
|
+
trackpadDelta.current = 0
|
|
178
|
+
trackpadGestureHandled.current = false
|
|
179
|
+
trackpadGestureTimeout.current = null
|
|
180
|
+
}, TRACKPAD_GESTURE_END_DELAY)
|
|
181
|
+
}, [])
|
|
182
|
+
|
|
110
183
|
const handleKeyDown = useCallback(
|
|
111
184
|
(event: KeyboardEvent<HTMLDivElement>) => {
|
|
112
185
|
onKeyDownCapture?.(event)
|
|
@@ -122,6 +195,72 @@ export const Carousel = ({
|
|
|
122
195
|
[onKeyDownCapture, scrollNext, scrollPrev],
|
|
123
196
|
)
|
|
124
197
|
|
|
198
|
+
const handleWheel = useCallback(
|
|
199
|
+
(event: globalThis.WheelEvent) => {
|
|
200
|
+
if (event.defaultPrevented || orientation !== "horizontal") return
|
|
201
|
+
|
|
202
|
+
const deltaMultiplier =
|
|
203
|
+
event.deltaMode === 1 ? 16 : event.deltaMode === 2 ? 100 : 1
|
|
204
|
+
const horizontalDelta = event.deltaX * deltaMultiplier
|
|
205
|
+
const verticalDelta = event.deltaY * deltaMultiplier
|
|
206
|
+
|
|
207
|
+
if (
|
|
208
|
+
Math.abs(horizontalDelta) <= Math.abs(verticalDelta) ||
|
|
209
|
+
Math.abs(horizontalDelta) < 1
|
|
210
|
+
) {
|
|
211
|
+
return
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (trackpadGestureHandled.current) {
|
|
215
|
+
event.preventDefault()
|
|
216
|
+
scheduleTrackpadGestureEnd()
|
|
217
|
+
return
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const canScrollInDirection =
|
|
221
|
+
horizontalDelta > 0
|
|
222
|
+
? canScrollNextRef.current
|
|
223
|
+
: canScrollPrevRef.current
|
|
224
|
+
if (!canScrollInDirection) return
|
|
225
|
+
|
|
226
|
+
event.preventDefault()
|
|
227
|
+
trackpadDelta.current += horizontalDelta
|
|
228
|
+
scheduleTrackpadGestureEnd()
|
|
229
|
+
|
|
230
|
+
if (Math.abs(trackpadDelta.current) < TRACKPAD_SWIPE_THRESHOLD) return
|
|
231
|
+
|
|
232
|
+
trackpadGestureHandled.current = true
|
|
233
|
+
trackpadDelta.current = 0
|
|
234
|
+
if (horizontalDelta > 0) scrollNextRef.current()
|
|
235
|
+
else scrollPrevRef.current()
|
|
236
|
+
},
|
|
237
|
+
[orientation, scheduleTrackpadGestureEnd],
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
useEffect(() => {
|
|
241
|
+
const root = carouselRootRef.current
|
|
242
|
+
if (!root) return
|
|
243
|
+
|
|
244
|
+
root.addEventListener("wheel", handleWheel, { passive: false })
|
|
245
|
+
return () => {
|
|
246
|
+
root.removeEventListener("wheel", handleWheel)
|
|
247
|
+
if (trackpadGestureTimeout.current) {
|
|
248
|
+
clearTimeout(trackpadGestureTimeout.current)
|
|
249
|
+
}
|
|
250
|
+
trackpadDelta.current = 0
|
|
251
|
+
trackpadGestureHandled.current = false
|
|
252
|
+
}
|
|
253
|
+
}, [handleWheel])
|
|
254
|
+
|
|
255
|
+
const setCarouselRootRef = useCallback(
|
|
256
|
+
(node: HTMLDivElement | null) => {
|
|
257
|
+
carouselRootRef.current = node
|
|
258
|
+
if (typeof forwardedRef === "function") forwardedRef(node)
|
|
259
|
+
else if (forwardedRef) forwardedRef.current = node
|
|
260
|
+
},
|
|
261
|
+
[forwardedRef],
|
|
262
|
+
)
|
|
263
|
+
|
|
125
264
|
useEffect(() => {
|
|
126
265
|
if (!api || !setApi) return
|
|
127
266
|
setApi(api)
|
|
@@ -140,14 +279,23 @@ export const Carousel = ({
|
|
|
140
279
|
}}
|
|
141
280
|
>
|
|
142
281
|
<div
|
|
282
|
+
ref={setCarouselRootRef}
|
|
143
283
|
role="region"
|
|
144
284
|
aria-roledescription="carousel"
|
|
145
285
|
data-slot="carousel"
|
|
146
|
-
|
|
286
|
+
data-fade={fade || undefined}
|
|
287
|
+
className={cn(
|
|
288
|
+
"relative",
|
|
289
|
+
fade &&
|
|
290
|
+
"rounded-xl outline-none focus-visible:ring-[3px] focus-visible:ring-offset-1 focus-visible:ring-offset-background-primary focus-visible:ring-ring/20",
|
|
291
|
+
className,
|
|
292
|
+
)}
|
|
147
293
|
onKeyDownCapture={handleKeyDown}
|
|
294
|
+
tabIndex={tabIndex ?? (fade ? 0 : undefined)}
|
|
148
295
|
{...props}
|
|
149
296
|
>
|
|
150
297
|
{children}
|
|
298
|
+
{fade ? <CarouselEdgeFades /> : null}
|
|
151
299
|
</div>
|
|
152
300
|
</CarouselContext.Provider>
|
|
153
301
|
)
|
|
@@ -160,7 +308,16 @@ export const CarouselContent = ({
|
|
|
160
308
|
const { carouselRef, orientation } = useCarousel()
|
|
161
309
|
|
|
162
310
|
return (
|
|
163
|
-
<div
|
|
311
|
+
<div
|
|
312
|
+
ref={carouselRef}
|
|
313
|
+
className={cn(
|
|
314
|
+
"overflow-hidden",
|
|
315
|
+
orientation === "horizontal"
|
|
316
|
+
? "touch-pan-y overscroll-x-contain"
|
|
317
|
+
: "touch-pan-x overscroll-y-contain",
|
|
318
|
+
)}
|
|
319
|
+
data-slot="carousel-viewport"
|
|
320
|
+
>
|
|
164
321
|
<div
|
|
165
322
|
data-slot="carousel-content"
|
|
166
323
|
className={cn(
|
|
@@ -194,7 +351,7 @@ export const CarouselItem = ({ className, ...props }: CarouselItemProps) => {
|
|
|
194
351
|
|
|
195
352
|
export const CarouselPrevious = ({
|
|
196
353
|
className,
|
|
197
|
-
variant = "
|
|
354
|
+
variant = "ghost",
|
|
198
355
|
size = "md",
|
|
199
356
|
...props
|
|
200
357
|
}: CarouselPreviousProps) => {
|
|
@@ -211,7 +368,7 @@ export const CarouselPrevious = ({
|
|
|
211
368
|
aria-label="Previous slide"
|
|
212
369
|
data-slot="carousel-previous"
|
|
213
370
|
className={cn(
|
|
214
|
-
"absolute size-9",
|
|
371
|
+
"absolute size-9 border-0 focus-visible:border-0",
|
|
215
372
|
orientation === "horizontal"
|
|
216
373
|
? "top-1/2 -left-12 -translate-y-1/2 active:!-translate-y-1/2"
|
|
217
374
|
: "-top-12 left-1/2 -translate-x-1/2 rotate-90 active:!-translate-x-1/2 active:!translate-y-0",
|
|
@@ -227,7 +384,7 @@ export const CarouselPrevious = ({
|
|
|
227
384
|
|
|
228
385
|
export const CarouselNext = ({
|
|
229
386
|
className,
|
|
230
|
-
variant = "
|
|
387
|
+
variant = "ghost",
|
|
231
388
|
size = "md",
|
|
232
389
|
...props
|
|
233
390
|
}: CarouselNextProps) => {
|
|
@@ -244,7 +401,7 @@ export const CarouselNext = ({
|
|
|
244
401
|
aria-label="Next slide"
|
|
245
402
|
data-slot="carousel-next"
|
|
246
403
|
className={cn(
|
|
247
|
-
"absolute size-9",
|
|
404
|
+
"absolute size-9 border-0 focus-visible:border-0",
|
|
248
405
|
orientation === "horizontal"
|
|
249
406
|
? "top-1/2 -right-12 -translate-y-1/2 active:!-translate-y-1/2"
|
|
250
407
|
: "-bottom-12 left-1/2 -translate-x-1/2 rotate-90 active:!-translate-x-1/2 active:!translate-y-0",
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { useState, type ReactNode } from "react"
|
|
4
|
+
import type { DateRange, PropsBase } from "react-day-picker"
|
|
5
|
+
import { Button } from "./button"
|
|
6
|
+
import { Calendar } from "./calendar"
|
|
7
|
+
import { IconCalendar1 } from "./icons"
|
|
8
|
+
import { cn } from "./lib/cn"
|
|
9
|
+
import {
|
|
10
|
+
Popover,
|
|
11
|
+
PopoverPopup,
|
|
12
|
+
PopoverPortal,
|
|
13
|
+
PopoverPositioner,
|
|
14
|
+
PopoverTrigger,
|
|
15
|
+
} from "./popover"
|
|
16
|
+
|
|
17
|
+
const dateFormatter = new Intl.DateTimeFormat("en-US", {
|
|
18
|
+
month: "short",
|
|
19
|
+
day: "numeric",
|
|
20
|
+
year: "numeric",
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
const formatDate = (date: Date) => dateFormatter.format(date)
|
|
24
|
+
|
|
25
|
+
type DatePickerBaseProps = {
|
|
26
|
+
/** Options forwarded to Calendar, excluding its selection mode. */
|
|
27
|
+
calendarProps?: Omit<PropsBase, "mode" | "required">
|
|
28
|
+
/** Classes applied to the trigger button. */
|
|
29
|
+
className?: string
|
|
30
|
+
/** Disables the trigger button. */
|
|
31
|
+
disabled?: boolean
|
|
32
|
+
/** Placeholder shown when no date is selected. */
|
|
33
|
+
placeholder?: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type DatePickerSingleProps = DatePickerBaseProps & {
|
|
37
|
+
mode?: "single"
|
|
38
|
+
selected?: Date
|
|
39
|
+
onSelect?: (date: Date | undefined) => void
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export type DatePickerRangeProps = DatePickerBaseProps & {
|
|
43
|
+
mode: "range"
|
|
44
|
+
selected?: DateRange
|
|
45
|
+
onSelect?: (range: DateRange | undefined) => void
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type DatePickerProps = DatePickerSingleProps | DatePickerRangeProps
|
|
49
|
+
|
|
50
|
+
const DatePickerTrigger = ({
|
|
51
|
+
className,
|
|
52
|
+
disabled,
|
|
53
|
+
empty,
|
|
54
|
+
label,
|
|
55
|
+
}: {
|
|
56
|
+
className?: string
|
|
57
|
+
disabled?: boolean
|
|
58
|
+
empty: boolean
|
|
59
|
+
label: string
|
|
60
|
+
}) => (
|
|
61
|
+
<PopoverTrigger
|
|
62
|
+
render={
|
|
63
|
+
<Button
|
|
64
|
+
type="button"
|
|
65
|
+
size="sm"
|
|
66
|
+
variant="outline"
|
|
67
|
+
disabled={disabled}
|
|
68
|
+
prefix={<IconCalendar1 aria-hidden />}
|
|
69
|
+
className={cn("w-56 justify-start", className)}
|
|
70
|
+
/>
|
|
71
|
+
}
|
|
72
|
+
>
|
|
73
|
+
<span
|
|
74
|
+
className={cn(
|
|
75
|
+
"min-w-0 flex-1 truncate text-left",
|
|
76
|
+
empty && "text-fg-tertiary",
|
|
77
|
+
)}
|
|
78
|
+
>
|
|
79
|
+
{label}
|
|
80
|
+
</span>
|
|
81
|
+
</PopoverTrigger>
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
const DatePickerPopup = ({ children }: { children: ReactNode }) => (
|
|
85
|
+
<PopoverPortal>
|
|
86
|
+
<PopoverPositioner align="start" sideOffset={6}>
|
|
87
|
+
<PopoverPopup className="w-auto gap-0 p-0">{children}</PopoverPopup>
|
|
88
|
+
</PopoverPositioner>
|
|
89
|
+
</PopoverPortal>
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
const SingleDatePicker = ({
|
|
93
|
+
calendarProps,
|
|
94
|
+
className,
|
|
95
|
+
disabled,
|
|
96
|
+
onSelect,
|
|
97
|
+
placeholder = "Pick a date",
|
|
98
|
+
selected,
|
|
99
|
+
}: DatePickerSingleProps) => {
|
|
100
|
+
const [open, setOpen] = useState(false)
|
|
101
|
+
|
|
102
|
+
const handleSelect = (date: Date | undefined) => {
|
|
103
|
+
onSelect?.(date)
|
|
104
|
+
if (date) setOpen(false)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<Popover open={open} onOpenChange={setOpen}>
|
|
109
|
+
<DatePickerTrigger
|
|
110
|
+
className={className}
|
|
111
|
+
disabled={disabled}
|
|
112
|
+
empty={!selected}
|
|
113
|
+
label={selected ? formatDate(selected) : placeholder}
|
|
114
|
+
/>
|
|
115
|
+
<DatePickerPopup>
|
|
116
|
+
<Calendar
|
|
117
|
+
{...calendarProps}
|
|
118
|
+
className={cn("border-0", calendarProps?.className)}
|
|
119
|
+
mode="single"
|
|
120
|
+
selected={selected}
|
|
121
|
+
onSelect={handleSelect}
|
|
122
|
+
/>
|
|
123
|
+
</DatePickerPopup>
|
|
124
|
+
</Popover>
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const RangeDatePicker = ({
|
|
129
|
+
calendarProps,
|
|
130
|
+
className,
|
|
131
|
+
disabled,
|
|
132
|
+
onSelect,
|
|
133
|
+
placeholder = "Pick a date range",
|
|
134
|
+
selected,
|
|
135
|
+
}: DatePickerRangeProps) => {
|
|
136
|
+
const [open, setOpen] = useState(false)
|
|
137
|
+
const label = selected?.from
|
|
138
|
+
? selected.to
|
|
139
|
+
? `${formatDate(selected.from)} – ${formatDate(selected.to)}`
|
|
140
|
+
: `${formatDate(selected.from)} – Select end date`
|
|
141
|
+
: placeholder
|
|
142
|
+
|
|
143
|
+
return (
|
|
144
|
+
<Popover open={open} onOpenChange={setOpen}>
|
|
145
|
+
<DatePickerTrigger
|
|
146
|
+
className={className}
|
|
147
|
+
disabled={disabled}
|
|
148
|
+
empty={!selected?.from}
|
|
149
|
+
label={label}
|
|
150
|
+
/>
|
|
151
|
+
<DatePickerPopup>
|
|
152
|
+
<Calendar
|
|
153
|
+
{...calendarProps}
|
|
154
|
+
className={cn("border-0", calendarProps?.className)}
|
|
155
|
+
mode="range"
|
|
156
|
+
selected={selected}
|
|
157
|
+
onSelect={onSelect}
|
|
158
|
+
/>
|
|
159
|
+
</DatePickerPopup>
|
|
160
|
+
</Popover>
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export const DatePicker = (props: DatePickerProps) =>
|
|
165
|
+
props.mode === "range" ? (
|
|
166
|
+
<RangeDatePicker {...props} />
|
|
167
|
+
) : (
|
|
168
|
+
<SingleDatePicker {...props} />
|
|
169
|
+
)
|
package/src/icons.tsx
CHANGED
|
@@ -2,13 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
import type { CentralIconBaseProps } from "@central-icons-react/round-outlined-radius-2-stroke-2/CentralIconBase"
|
|
4
4
|
import { IconBell as IconBellBase } from "@central-icons-react/round-outlined-radius-2-stroke-2/IconBell"
|
|
5
|
+
import { IconCalendar1 as IconCalendar1Base } from "@central-icons-react/round-outlined-radius-2-stroke-2/IconCalendar1"
|
|
5
6
|
import { IconChainLink1 as IconChainLink1Base } from "@central-icons-react/round-outlined-radius-2-stroke-2/IconChainLink1"
|
|
6
7
|
import { IconCheckmark1 as IconCheckmark1Base } from "@central-icons-react/round-outlined-radius-2-stroke-2/IconCheckmark1"
|
|
7
8
|
import { IconChevronBottom as IconChevronBottomBase } from "@central-icons-react/round-outlined-radius-2-stroke-2/IconChevronBottom"
|
|
8
9
|
import { IconChevronDownSmall as IconChevronDownSmallBase } from "@central-icons-react/round-outlined-radius-2-stroke-2/IconChevronDownSmall"
|
|
9
10
|
import { IconChevronRightSmall as IconChevronRightSmallBase } from "@central-icons-react/round-outlined-radius-2-stroke-2/IconChevronRightSmall"
|
|
11
|
+
import { IconCircleCheck as IconCircleCheckBase } from "@central-icons-react/round-outlined-radius-2-stroke-2/IconCircleCheck"
|
|
12
|
+
import { IconCircleInfo as IconCircleInfoBase } from "@central-icons-react/round-outlined-radius-2-stroke-2/IconCircleInfo"
|
|
10
13
|
import { IconClipboard as IconClipboardBase } from "@central-icons-react/round-outlined-radius-2-stroke-2/IconClipboard"
|
|
11
14
|
import { IconCrossSmall as IconCrossSmallBase } from "@central-icons-react/round-outlined-radius-2-stroke-2/IconCrossSmall"
|
|
15
|
+
import { IconDotGrid1x3Horizontal as IconDotGrid1x3HorizontalBase } from "@central-icons-react/round-outlined-radius-2-stroke-2/IconDotGrid1x3Horizontal"
|
|
16
|
+
import { IconExclamationCircle as IconExclamationCircleBase } from "@central-icons-react/round-outlined-radius-2-stroke-2/IconExclamationCircle"
|
|
17
|
+
import { IconExclamationTriangle as IconExclamationTriangleBase } from "@central-icons-react/round-outlined-radius-2-stroke-2/IconExclamationTriangle"
|
|
12
18
|
import { IconHome as IconHomeBase } from "@central-icons-react/round-outlined-radius-2-stroke-2/IconHome"
|
|
13
19
|
import { IconMagnifyingGlass as IconMagnifyingGlassBase } from "@central-icons-react/round-outlined-radius-2-stroke-2/IconMagnifyingGlass"
|
|
14
20
|
import { IconMinusMedium as IconMinusBase } from "@central-icons-react/round-outlined-radius-2-stroke-2/IconMinusMedium"
|
|
@@ -17,6 +23,7 @@ import { IconPeople as IconPeopleBase } from "@central-icons-react/round-outline
|
|
|
17
23
|
import { IconPlusMedium as IconPlusBase } from "@central-icons-react/round-outlined-radius-2-stroke-2/IconPlusMedium"
|
|
18
24
|
import { IconSettingsGear1 as IconSettingsGear1Base } from "@central-icons-react/round-outlined-radius-2-stroke-2/IconSettingsGear1"
|
|
19
25
|
import { IconSquareBehindSquare6 as IconSquareBehindSquare6Base } from "@central-icons-react/round-outlined-radius-2-stroke-2/IconSquareBehindSquare6"
|
|
26
|
+
import { IconStar as IconStarBase } from "@central-icons-react/round-outlined-radius-2-stroke-2/IconStar"
|
|
20
27
|
import { IconSun as IconSunBase } from "@central-icons-react/round-outlined-radius-2-stroke-2/IconSun"
|
|
21
28
|
import { IconX as IconXBase } from "@central-icons-react/round-outlined-radius-2-stroke-2/IconX"
|
|
22
29
|
import type { ComponentType } from "react"
|
|
@@ -43,6 +50,7 @@ export const withCentralIconDefaults = (
|
|
|
43
50
|
}
|
|
44
51
|
|
|
45
52
|
export const IconBell = withCentralIconDefaults(IconBellBase)
|
|
53
|
+
export const IconCalendar1 = withCentralIconDefaults(IconCalendar1Base)
|
|
46
54
|
export const IconChainLink1 = withCentralIconDefaults(IconChainLink1Base)
|
|
47
55
|
export const IconCheckmark1 = withCentralIconDefaults(IconCheckmark1Base)
|
|
48
56
|
export const IconChevronBottom = withCentralIconDefaults(IconChevronBottomBase)
|
|
@@ -52,8 +60,19 @@ export const IconChevronDownSmall = withCentralIconDefaults(
|
|
|
52
60
|
export const IconChevronRightSmall = withCentralIconDefaults(
|
|
53
61
|
IconChevronRightSmallBase,
|
|
54
62
|
)
|
|
63
|
+
export const IconCircleCheck = withCentralIconDefaults(IconCircleCheckBase)
|
|
64
|
+
export const IconCircleInfo = withCentralIconDefaults(IconCircleInfoBase)
|
|
55
65
|
export const IconClipboard = withCentralIconDefaults(IconClipboardBase)
|
|
56
66
|
export const IconCrossSmall = withCentralIconDefaults(IconCrossSmallBase)
|
|
67
|
+
export const IconDotGrid1x3Horizontal = withCentralIconDefaults(
|
|
68
|
+
IconDotGrid1x3HorizontalBase,
|
|
69
|
+
)
|
|
70
|
+
export const IconExclamationCircle = withCentralIconDefaults(
|
|
71
|
+
IconExclamationCircleBase,
|
|
72
|
+
)
|
|
73
|
+
export const IconExclamationTriangle = withCentralIconDefaults(
|
|
74
|
+
IconExclamationTriangleBase,
|
|
75
|
+
)
|
|
57
76
|
export const IconHome = withCentralIconDefaults(IconHomeBase)
|
|
58
77
|
export const IconMagnifyingGlass = withCentralIconDefaults(
|
|
59
78
|
IconMagnifyingGlassBase,
|
|
@@ -66,11 +85,13 @@ export const IconSettingsGear1 = withCentralIconDefaults(IconSettingsGear1Base)
|
|
|
66
85
|
export const IconSquareBehindSquare6 = withCentralIconDefaults(
|
|
67
86
|
IconSquareBehindSquare6Base,
|
|
68
87
|
)
|
|
88
|
+
export const IconStar = withCentralIconDefaults(IconStarBase)
|
|
69
89
|
export const IconSun = withCentralIconDefaults(IconSunBase)
|
|
70
90
|
export const IconX = withCentralIconDefaults(IconXBase)
|
|
71
91
|
|
|
72
92
|
export const iconGallery = [
|
|
73
93
|
{ name: "IconHome", Icon: IconHome },
|
|
94
|
+
{ name: "IconCalendar1", Icon: IconCalendar1 },
|
|
74
95
|
{ name: "IconMagnifyingGlass", Icon: IconMagnifyingGlass },
|
|
75
96
|
{ name: "IconSettingsGear1", Icon: IconSettingsGear1 },
|
|
76
97
|
{ name: "IconBell", Icon: IconBell },
|
|
@@ -85,7 +106,13 @@ export const iconGallery = [
|
|
|
85
106
|
{ name: "IconChevronBottom", Icon: IconChevronBottom },
|
|
86
107
|
{ name: "IconChevronDownSmall", Icon: IconChevronDownSmall },
|
|
87
108
|
{ name: "IconChevronRightSmall", Icon: IconChevronRightSmall },
|
|
109
|
+
{ name: "IconCircleCheck", Icon: IconCircleCheck },
|
|
110
|
+
{ name: "IconCircleInfo", Icon: IconCircleInfo },
|
|
88
111
|
{ name: "IconClipboard", Icon: IconClipboard },
|
|
112
|
+
{ name: "IconDotGrid1x3Horizontal", Icon: IconDotGrid1x3Horizontal },
|
|
89
113
|
{ name: "IconSquareBehindSquare6", Icon: IconSquareBehindSquare6 },
|
|
90
114
|
{ name: "IconChainLink1", Icon: IconChainLink1 },
|
|
115
|
+
{ name: "IconExclamationCircle", Icon: IconExclamationCircle },
|
|
116
|
+
{ name: "IconExclamationTriangle", Icon: IconExclamationTriangle },
|
|
117
|
+
{ name: "IconStar", Icon: IconStar },
|
|
91
118
|
] as const
|
package/src/index.ts
CHANGED
|
@@ -92,17 +92,27 @@ export {
|
|
|
92
92
|
type AvatarFallbackProps,
|
|
93
93
|
} from "./avatar";
|
|
94
94
|
export { Calendar, type CalendarProps } from "./calendar";
|
|
95
|
+
export {
|
|
96
|
+
DatePicker,
|
|
97
|
+
type DatePickerProps,
|
|
98
|
+
type DatePickerSingleProps,
|
|
99
|
+
type DatePickerRangeProps,
|
|
100
|
+
} from "./date-picker";
|
|
101
|
+
export type { DateRange } from "react-day-picker";
|
|
95
102
|
export {
|
|
96
103
|
Card,
|
|
97
104
|
CardHeader,
|
|
98
105
|
CardTitle,
|
|
99
106
|
CardDescription,
|
|
107
|
+
CardAction,
|
|
100
108
|
CardContent,
|
|
101
109
|
CardFooter,
|
|
110
|
+
cardVariants,
|
|
102
111
|
type CardProps,
|
|
103
112
|
type CardHeaderProps,
|
|
104
113
|
type CardTitleProps,
|
|
105
114
|
type CardDescriptionProps,
|
|
115
|
+
type CardActionProps,
|
|
106
116
|
type CardContentProps,
|
|
107
117
|
type CardFooterProps,
|
|
108
118
|
} from "./card";
|
|
@@ -650,6 +660,7 @@ export {
|
|
|
650
660
|
BreadcrumbLink,
|
|
651
661
|
BreadcrumbPage,
|
|
652
662
|
BreadcrumbSeparator,
|
|
663
|
+
breadcrumbSeparatorVariants,
|
|
653
664
|
type BreadcrumbProps,
|
|
654
665
|
type BreadcrumbListProps,
|
|
655
666
|
type BreadcrumbItemProps,
|
|
@@ -785,13 +796,19 @@ export {
|
|
|
785
796
|
withCentralIconDefaults,
|
|
786
797
|
iconGallery,
|
|
787
798
|
IconBell,
|
|
799
|
+
IconCalendar1,
|
|
788
800
|
IconChainLink1,
|
|
789
801
|
IconCheckmark1,
|
|
790
802
|
IconChevronBottom,
|
|
791
803
|
IconChevronDownSmall,
|
|
792
804
|
IconChevronRightSmall,
|
|
805
|
+
IconCircleCheck,
|
|
806
|
+
IconCircleInfo,
|
|
793
807
|
IconClipboard,
|
|
794
808
|
IconCrossSmall,
|
|
809
|
+
IconDotGrid1x3Horizontal,
|
|
810
|
+
IconExclamationCircle,
|
|
811
|
+
IconExclamationTriangle,
|
|
795
812
|
IconHome,
|
|
796
813
|
IconMagnifyingGlass,
|
|
797
814
|
IconMinus,
|
|
@@ -800,6 +817,7 @@ export {
|
|
|
800
817
|
IconPlus,
|
|
801
818
|
IconSettingsGear1,
|
|
802
819
|
IconSquareBehindSquare6,
|
|
820
|
+
IconStar,
|
|
803
821
|
IconSun,
|
|
804
822
|
IconX,
|
|
805
823
|
type CentralIconProps,
|
package/src/menu.tsx
CHANGED
|
@@ -34,7 +34,7 @@ export type MenuSubmenuTriggerProps = ComponentProps<
|
|
|
34
34
|
export type MenuViewportProps = ComponentProps<typeof BaseMenu.Viewport>
|
|
35
35
|
|
|
36
36
|
const menuItemClassName = cn(
|
|
37
|
-
"flex
|
|
37
|
+
"flex h-8 cursor-default items-center gap-2 rounded-sm px-2.5 py-1.5 text-sm text-fg-primary outline-none select-none",
|
|
38
38
|
motion.colors,
|
|
39
39
|
"data-disabled:cursor-not-allowed data-disabled:opacity-50 data-highlighted:bg-background-tertiary",
|
|
40
40
|
)
|
|
@@ -59,7 +59,7 @@ export const MenuBackdrop = ({ className, ...props }: MenuBackdropProps) => (
|
|
|
59
59
|
)
|
|
60
60
|
|
|
61
61
|
export const MenuPositioner = ({
|
|
62
|
-
sideOffset =
|
|
62
|
+
sideOffset = 8,
|
|
63
63
|
className,
|
|
64
64
|
...props
|
|
65
65
|
}: MenuPositionerProps) => (
|
|
@@ -73,7 +73,7 @@ export const MenuPositioner = ({
|
|
|
73
73
|
export const MenuPopup = ({ className, ...props }: MenuPopupProps) => (
|
|
74
74
|
<BaseMenu.Popup
|
|
75
75
|
className={cn(
|
|
76
|
-
"z-50 min-w-40 overflow-hidden rounded-
|
|
76
|
+
"z-50 min-w-40 overflow-hidden rounded-xl border border-[var(--border-faint)] bg-surface p-1.5 shadow-lg outline-none",
|
|
77
77
|
motion.popupAnchor,
|
|
78
78
|
className,
|
|
79
79
|
)}
|