xiod-ui 1.0.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/LICENSE +73 -0
- package/README.md +167 -0
- package/dist/components/accordion.d.ts +9 -0
- package/dist/components/accordion.js +46 -0
- package/dist/components/agent-steps.d.ts +47 -0
- package/dist/components/agent-steps.js +223 -0
- package/dist/components/alert-dialog.d.ts +21 -0
- package/dist/components/alert-dialog.js +74 -0
- package/dist/components/alert.d.ts +12 -0
- package/dist/components/alert.js +45 -0
- package/dist/components/aspect-ratio.d.ts +9 -0
- package/dist/components/aspect-ratio.js +22 -0
- package/dist/components/autocomplete.d.ts +35 -0
- package/dist/components/autocomplete.js +160 -0
- package/dist/components/avatar.d.ts +17 -0
- package/dist/components/avatar.js +65 -0
- package/dist/components/badge.d.ts +15 -0
- package/dist/components/badge.js +46 -0
- package/dist/components/breadcrumb.d.ts +12 -0
- package/dist/components/breadcrumb.js +75 -0
- package/dist/components/button-group.d.ts +14 -0
- package/dist/components/button-group.js +45 -0
- package/dist/components/button-split.d.ts +19 -0
- package/dist/components/button-split.js +73 -0
- package/dist/components/button.d.ts +15 -0
- package/dist/components/button.js +54 -0
- package/dist/components/calendar.d.ts +63 -0
- package/dist/components/calendar.js +425 -0
- package/dist/components/card.d.ts +17 -0
- package/dist/components/card.js +139 -0
- package/dist/components/carousel.d.ts +59 -0
- package/dist/components/carousel.js +503 -0
- package/dist/components/checkbox.d.ts +16 -0
- package/dist/components/checkbox.js +86 -0
- package/dist/components/circular-progress.d.ts +28 -0
- package/dist/components/circular-progress.js +127 -0
- package/dist/components/collapsible.d.ts +8 -0
- package/dist/components/collapsible.js +27 -0
- package/dist/components/color-picker.d.ts +159 -0
- package/dist/components/color-picker.js +1589 -0
- package/dist/components/combobox.d.ts +46 -0
- package/dist/components/combobox.js +237 -0
- package/dist/components/command.d.ts +22 -0
- package/dist/components/command.js +129 -0
- package/dist/components/context-menu.d.ts +38 -0
- package/dist/components/context-menu.js +164 -0
- package/dist/components/copy-to-clipboard.d.ts +32 -0
- package/dist/components/copy-to-clipboard.js +83 -0
- package/dist/components/corner-badge.d.ts +22 -0
- package/dist/components/corner-badge.js +84 -0
- package/dist/components/dashboard-grid.d.ts +83 -0
- package/dist/components/dashboard-grid.js +486 -0
- package/dist/components/date-picker.d.ts +29 -0
- package/dist/components/date-picker.js +261 -0
- package/dist/components/dialog.d.ts +26 -0
- package/dist/components/dialog.js +97 -0
- package/dist/components/dot-matrix.d.ts +32 -0
- package/dist/components/dot-matrix.js +707 -0
- package/dist/components/draggable.d.ts +42 -0
- package/dist/components/draggable.js +346 -0
- package/dist/components/drawer.d.ts +66 -0
- package/dist/components/drawer.js +304 -0
- package/dist/components/empty.d.ts +14 -0
- package/dist/components/empty.js +75 -0
- package/dist/components/field.d.ts +12 -0
- package/dist/components/field.js +44 -0
- package/dist/components/fieldset.d.ts +7 -0
- package/dist/components/fieldset.js +21 -0
- package/dist/components/file-upload.d.ts +61 -0
- package/dist/components/file-upload.js +482 -0
- package/dist/components/form.d.ts +6 -0
- package/dist/components/form.js +14 -0
- package/dist/components/frame.d.ts +10 -0
- package/dist/components/frame.js +47 -0
- package/dist/components/gauge.d.ts +27 -0
- package/dist/components/gauge.js +74 -0
- package/dist/components/grid.d.ts +26 -0
- package/dist/components/grid.js +204 -0
- package/dist/components/group.d.ts +19 -0
- package/dist/components/group.js +45 -0
- package/dist/components/input-group.d.ts +15 -0
- package/dist/components/input-group.js +61 -0
- package/dist/components/input-otp.d.ts +24 -0
- package/dist/components/input-otp.js +50 -0
- package/dist/components/input-payment.d.ts +131 -0
- package/dist/components/input-payment.js +1140 -0
- package/dist/components/input-phone.d.ts +70 -0
- package/dist/components/input-phone.js +657 -0
- package/dist/components/input-sensitive.d.ts +12 -0
- package/dist/components/input-sensitive.js +169 -0
- package/dist/components/input.d.ts +13 -0
- package/dist/components/input.js +26 -0
- package/dist/components/kbd.d.ts +6 -0
- package/dist/components/kbd.js +19 -0
- package/dist/components/kinetic-click.d.ts +48 -0
- package/dist/components/kinetic-click.js +1184 -0
- package/dist/components/label.d.ts +6 -0
- package/dist/components/label.js +18 -0
- package/dist/components/list-box.d.ts +20 -0
- package/dist/components/list-box.js +148 -0
- package/dist/components/loader.d.ts +13 -0
- package/dist/components/loader.js +430 -0
- package/dist/components/marker.d.ts +15 -0
- package/dist/components/marker.js +59 -0
- package/dist/components/menu.d.ts +42 -0
- package/dist/components/menu.js +186 -0
- package/dist/components/menubar.d.ts +40 -0
- package/dist/components/menubar.js +107 -0
- package/dist/components/message.d.ts +33 -0
- package/dist/components/message.js +112 -0
- package/dist/components/meter.d.ts +10 -0
- package/dist/components/meter.js +42 -0
- package/dist/components/morphic-toast.d.ts +61 -0
- package/dist/components/morphic-toast.js +916 -0
- package/dist/components/navigation-menu.d.ts +26 -0
- package/dist/components/navigation-menu.js +116 -0
- package/dist/components/number-field.d.ts +15 -0
- package/dist/components/number-field.js +86 -0
- package/dist/components/option-picker.d.ts +18 -0
- package/dist/components/option-picker.js +89 -0
- package/dist/components/orb.d.ts +38 -0
- package/dist/components/orb.js +1413 -0
- package/dist/components/pagination.d.ts +25 -0
- package/dist/components/pagination.js +147 -0
- package/dist/components/popover.d.ts +22 -0
- package/dist/components/popover.js +79 -0
- package/dist/components/preview-card.d.ts +16 -0
- package/dist/components/preview-card.js +60 -0
- package/dist/components/progress.d.ts +21 -0
- package/dist/components/progress.js +139 -0
- package/dist/components/radio.d.ts +16 -0
- package/dist/components/radio.js +68 -0
- package/dist/components/resizable.d.ts +58 -0
- package/dist/components/resizable.js +964 -0
- package/dist/components/ruler-picker.d.ts +27 -0
- package/dist/components/ruler-picker.js +253 -0
- package/dist/components/scroll-area.d.ts +13 -0
- package/dist/components/scroll-area.js +34 -0
- package/dist/components/scroll-bar.d.ts +13 -0
- package/dist/components/scroll-bar.js +47 -0
- package/dist/components/select.d.ts +29 -0
- package/dist/components/select.js +140 -0
- package/dist/components/separator.d.ts +6 -0
- package/dist/components/separator.js +15 -0
- package/dist/components/sidebar.d.ts +65 -0
- package/dist/components/sidebar.js +408 -0
- package/dist/components/skeleton.d.ts +5 -0
- package/dist/components/skeleton.js +12 -0
- package/dist/components/slider.d.ts +12 -0
- package/dist/components/slider.js +96 -0
- package/dist/components/sortable.d.ts +44 -0
- package/dist/components/sortable.js +327 -0
- package/dist/components/switch.d.ts +15 -0
- package/dist/components/switch.js +63 -0
- package/dist/components/table.d.ts +12 -0
- package/dist/components/table.js +65 -0
- package/dist/components/tabs.d.ts +12 -0
- package/dist/components/tabs.js +39 -0
- package/dist/components/text.d.ts +14 -0
- package/dist/components/text.js +69 -0
- package/dist/components/textarea.d.ts +9 -0
- package/dist/components/textarea.js +20 -0
- package/dist/components/theme-provider.d.ts +52 -0
- package/dist/components/theme-provider.js +148 -0
- package/dist/components/timeline.d.ts +34 -0
- package/dist/components/timeline.js +147 -0
- package/dist/components/toast.d.ts +17 -0
- package/dist/components/toast.js +161 -0
- package/dist/components/toggle-group.d.ts +14 -0
- package/dist/components/toggle-group.js +53 -0
- package/dist/components/toggle.d.ts +11 -0
- package/dist/components/toggle.js +36 -0
- package/dist/components/toolbar.d.ts +11 -0
- package/dist/components/toolbar.js +49 -0
- package/dist/components/tooltip.d.ts +17 -0
- package/dist/components/tooltip.js +56 -0
- package/dist/components/waveform.d.ts +61 -0
- package/dist/components/waveform.js +500 -0
- package/dist/components/wheel-picker.d.ts +44 -0
- package/dist/components/wheel-picker.js +771 -0
- package/dist/hooks/use-copy-to-clipboard.d.ts +9 -0
- package/dist/hooks/use-copy-to-clipboard.js +36 -0
- package/dist/hooks/use-media-query.d.ts +21 -0
- package/dist/hooks/use-media-query.js +58 -0
- package/dist/styles.css +202 -0
- package/dist/themes/afterglow.css +89 -0
- package/dist/themes/afterglow.scoped.css +90 -0
- package/dist/themes/blacklight.css +89 -0
- package/dist/themes/blacklight.scoped.css +90 -0
- package/dist/themes/cathode.css +89 -0
- package/dist/themes/cathode.scoped.css +90 -0
- package/dist/themes/cel.css +89 -0
- package/dist/themes/cel.scoped.css +90 -0
- package/dist/themes/cinder.css +89 -0
- package/dist/themes/cinder.scoped.css +90 -0
- package/dist/themes/clay.css +89 -0
- package/dist/themes/clay.scoped.css +90 -0
- package/dist/themes/cobalt.css +89 -0
- package/dist/themes/cobalt.scoped.css +90 -0
- package/dist/themes/crimson.css +89 -0
- package/dist/themes/crimson.scoped.css +90 -0
- package/dist/themes/ion.css +89 -0
- package/dist/themes/ion.scoped.css +90 -0
- package/dist/themes/iris.css +89 -0
- package/dist/themes/iris.scoped.css +90 -0
- package/dist/themes/lagoon.css +89 -0
- package/dist/themes/lagoon.scoped.css +90 -0
- package/dist/themes/mochi.css +89 -0
- package/dist/themes/mochi.scoped.css +90 -0
- package/dist/themes/riso.css +89 -0
- package/dist/themes/riso.scoped.css +90 -0
- package/dist/themes/roast.css +89 -0
- package/dist/themes/roast.scoped.css +90 -0
- package/dist/themes/sage.css +89 -0
- package/dist/themes/sage.scoped.css +90 -0
- package/dist/themes/sepia.css +89 -0
- package/dist/themes/sepia.scoped.css +90 -0
- package/dist/themes/sorbet.css +89 -0
- package/dist/themes/sorbet.scoped.css +90 -0
- package/dist/themes/taffy.css +89 -0
- package/dist/themes/taffy.scoped.css +90 -0
- package/dist/themes/toxin.css +89 -0
- package/dist/themes/toxin.scoped.css +90 -0
- package/package.json +140 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Button } from "./button.js";
|
|
3
|
+
import { Group, GroupSeparator } from "./group.js";
|
|
4
|
+
import { Popover, PopoverContent as PopoverPopup, PopoverTrigger } from "./popover.js";
|
|
5
|
+
import { cn } from "cn";
|
|
6
|
+
import { ChevronDown } from "xiod-icons/icons/ChevronDown";
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
8
|
+
import * as React$1 from "react";
|
|
9
|
+
//#region src/components/button-split.tsx
|
|
10
|
+
const ButtonSplitContext = React$1.createContext({
|
|
11
|
+
variant: "default",
|
|
12
|
+
size: "default"
|
|
13
|
+
});
|
|
14
|
+
function ButtonSplit({ variant = "default", size = "default", className, children, ...props }) {
|
|
15
|
+
const contextValue = React$1.useMemo(() => ({
|
|
16
|
+
variant,
|
|
17
|
+
size
|
|
18
|
+
}), [variant, size]);
|
|
19
|
+
return /* @__PURE__ */ jsx(Popover, {
|
|
20
|
+
...props,
|
|
21
|
+
children: /* @__PURE__ */ jsx(ButtonSplitContext.Provider, {
|
|
22
|
+
value: contextValue,
|
|
23
|
+
children: /* @__PURE__ */ jsx(Group, {
|
|
24
|
+
className: cn("rounded-lg [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0", "*:rounded-[inherit] [&>*:before]:rounded-[inherit]", className),
|
|
25
|
+
"data-slot": "button-split",
|
|
26
|
+
children
|
|
27
|
+
})
|
|
28
|
+
})
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function ButtonSplitAction({ className, render, ...props }) {
|
|
32
|
+
const { variant, size } = React$1.useContext(ButtonSplitContext);
|
|
33
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
34
|
+
variant: props.variant ?? variant,
|
|
35
|
+
size: props.size ?? size,
|
|
36
|
+
className: cn(className),
|
|
37
|
+
render,
|
|
38
|
+
...props
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
function ButtonSplitSeparator({ className, ...props }) {
|
|
42
|
+
return /* @__PURE__ */ jsx(GroupSeparator, {
|
|
43
|
+
className: cn(className),
|
|
44
|
+
...props
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function ButtonSplitTrigger({ className, render, children, ...props }) {
|
|
48
|
+
const { variant, size } = React$1.useContext(ButtonSplitContext);
|
|
49
|
+
const triggerSize = size === "sm" ? "icon-sm" : size === "lg" ? "icon-lg" : size === "xs" ? "icon-xs" : size === "xl" ? "icon-xl" : "icon";
|
|
50
|
+
return /* @__PURE__ */ jsx(PopoverTrigger, {
|
|
51
|
+
className: cn(className),
|
|
52
|
+
render: render ?? /* @__PURE__ */ jsx(Button, {
|
|
53
|
+
variant,
|
|
54
|
+
size: triggerSize
|
|
55
|
+
}),
|
|
56
|
+
...props,
|
|
57
|
+
children: children ?? /* @__PURE__ */ jsx(ChevronDown, {})
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
function ButtonSplitContent({ className, sideOffset = 8, hideArrow = false, children, ...props }) {
|
|
61
|
+
return /* @__PURE__ */ jsx(PopoverPopup, {
|
|
62
|
+
className: cn("min-w-(--anchor-width) w-(--popup-width,max-content) **:data-[slot=popover-viewport]:p-1", className),
|
|
63
|
+
sideOffset,
|
|
64
|
+
hideArrow,
|
|
65
|
+
...props,
|
|
66
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
67
|
+
className: "flex w-full flex-col gap-1",
|
|
68
|
+
children
|
|
69
|
+
})
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
//#endregion
|
|
73
|
+
export { ButtonSplit, ButtonSplitAction, ButtonSplitContent, ButtonSplitSeparator, ButtonSplitTrigger };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { VariantProps } from "class-variance-authority";
|
|
2
|
+
import * as React$1 from "react";
|
|
3
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
4
|
+
//#region src/components/button.d.ts
|
|
5
|
+
declare const buttonVariants: (props?: ({
|
|
6
|
+
size?: "sm" | "lg" | "xs" | "xl" | "default" | "icon" | "icon-lg" | "icon-sm" | "icon-xl" | "icon-xs" | null | undefined;
|
|
7
|
+
variant?: "default" | "destructive" | "outline" | "secondary" | "destructive-outline" | "ghost" | "link" | null | undefined;
|
|
8
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
9
|
+
interface ButtonProps extends useRender.ComponentProps<"button"> {
|
|
10
|
+
variant?: VariantProps<typeof buttonVariants>["variant"];
|
|
11
|
+
size?: VariantProps<typeof buttonVariants>["size"];
|
|
12
|
+
}
|
|
13
|
+
declare function Button({ className, variant, size, render, ...props }: ButtonProps): React$1.ReactElement;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { Button, buttonVariants };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "cn";
|
|
3
|
+
import { cva } from "class-variance-authority";
|
|
4
|
+
import { mergeProps } from "@base-ui/react/merge-props";
|
|
5
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
6
|
+
//#region src/components/button.tsx
|
|
7
|
+
const buttonVariants = cva("[&_svg]:-mx-0.5 relative inline-flex shrink-0 cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-lg border font-medium text-base outline-none transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-64 sm:text-sm [&_svg:not([class*='opacity-'])]:opacity-80 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0", {
|
|
8
|
+
defaultVariants: {
|
|
9
|
+
size: "default",
|
|
10
|
+
variant: "default"
|
|
11
|
+
},
|
|
12
|
+
variants: {
|
|
13
|
+
size: {
|
|
14
|
+
default: "h-9 px-[calc(--spacing(3)-1px)] sm:h-8",
|
|
15
|
+
icon: "size-9 sm:size-8",
|
|
16
|
+
"icon-lg": "size-10 sm:size-9",
|
|
17
|
+
"icon-sm": "size-8 sm:size-7",
|
|
18
|
+
"icon-xl": "size-11 sm:size-10 [&_svg:not([class*='size-'])]:size-5 sm:[&_svg:not([class*='size-'])]:size-4.5",
|
|
19
|
+
"icon-xs": "size-7 rounded-md before:rounded-[calc(var(--radius-md)-1px)] sm:size-6 not-in-data-[slot=input-group]:[&_svg:not([class*='size-'])]:size-4 sm:not-in-data-[slot=input-group]:[&_svg:not([class*='size-'])]:size-3.5",
|
|
20
|
+
lg: "h-10 px-[calc(--spacing(3.5)-1px)] sm:h-9",
|
|
21
|
+
sm: "h-8 gap-1.5 px-[calc(--spacing(2.5)-1px)] sm:h-7",
|
|
22
|
+
xl: "h-11 px-[calc(--spacing(4)-1px)] text-lg sm:h-10 sm:text-base [&_svg:not([class*='size-'])]:size-5 sm:[&_svg:not([class*='size-'])]:size-4.5",
|
|
23
|
+
xs: "h-7 gap-1 rounded-md px-[calc(--spacing(2)-1px)] text-sm before:rounded-[calc(var(--radius-md)-1px)] sm:h-6 sm:text-xs [&_svg:not([class*='size-'])]:size-4 sm:[&_svg:not([class*='size-'])]:size-3.5"
|
|
24
|
+
},
|
|
25
|
+
variant: {
|
|
26
|
+
default: "not-disabled:inset-shadow-[0_1px_--theme(--color-white/16%)] border-primary bg-primary text-primary-foreground shadow-primary/24 shadow-xs [:active,[data-pressed]]:inset-shadow-[0_1px_--theme(--color-black/8%)] [:disabled,:active,[data-pressed]]:shadow-none [:hover,[data-pressed]]:bg-primary/90",
|
|
27
|
+
destructive: "not-disabled:inset-shadow-[0_1px_--theme(--color-white/16%)] border-destructive bg-destructive text-white shadow-destructive/24 shadow-xs [:active,[data-pressed]]:inset-shadow-[0_1px_--theme(--color-black/8%)] [:disabled,:active,[data-pressed]]:shadow-none [:hover,[data-pressed]]:bg-destructive/90",
|
|
28
|
+
"destructive-outline": "border-input bg-popover not-dark:bg-clip-padding text-destructive-foreground shadow-xs/5 not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] dark:bg-input/32 dark:not-disabled:before:shadow-[0_-1px_--theme(--color-white/2%)] dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [:disabled,:active,[data-pressed]]:shadow-none [:hover,[data-pressed]]:border-destructive/32 [:hover,[data-pressed]]:bg-destructive/4",
|
|
29
|
+
ghost: "border-transparent text-foreground data-pressed:bg-accent [:hover,[data-pressed]]:bg-accent",
|
|
30
|
+
link: "border-transparent underline-offset-4 [:hover,[data-pressed]]:underline",
|
|
31
|
+
outline: "border-input bg-popover not-dark:bg-clip-padding text-foreground shadow-xs/5 not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] dark:bg-input/32 dark:not-disabled:before:shadow-[0_-1px_--theme(--color-white/2%)] dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [:disabled,:active,[data-pressed]]:shadow-none [:hover,[data-pressed]]:bg-accent/50 dark:[:hover,[data-pressed]]:bg-input/64",
|
|
32
|
+
secondary: "border-transparent bg-secondary text-secondary-foreground [:active,[data-pressed]]:bg-secondary/80 [:hover,[data-pressed]]:bg-secondary/90"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
function Button({ className, variant, size, render, ...props }) {
|
|
37
|
+
const typeValue = render ? void 0 : "button";
|
|
38
|
+
const defaultProps = {
|
|
39
|
+
className: cn(buttonVariants({
|
|
40
|
+
className,
|
|
41
|
+
size,
|
|
42
|
+
variant
|
|
43
|
+
})),
|
|
44
|
+
"data-slot": "button",
|
|
45
|
+
type: typeValue
|
|
46
|
+
};
|
|
47
|
+
return useRender({
|
|
48
|
+
defaultTagName: "button",
|
|
49
|
+
props: mergeProps(defaultProps, props),
|
|
50
|
+
render
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
//#endregion
|
|
54
|
+
export { Button, buttonVariants };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import * as React$1 from "react";
|
|
2
|
+
//#region src/components/calendar.d.ts
|
|
3
|
+
export type CalendarMode = "single" | "range";
|
|
4
|
+
export interface DateRange {
|
|
5
|
+
from?: Date;
|
|
6
|
+
to?: Date;
|
|
7
|
+
}
|
|
8
|
+
export type Matcher = boolean | Date | Date[] | ((date: Date) => boolean) | {
|
|
9
|
+
before?: Date;
|
|
10
|
+
after?: Date;
|
|
11
|
+
} | {
|
|
12
|
+
after?: Date;
|
|
13
|
+
} | {
|
|
14
|
+
before?: Date;
|
|
15
|
+
} | {
|
|
16
|
+
dayOfWeek?: number | number[];
|
|
17
|
+
};
|
|
18
|
+
export interface CalendarClassNames {
|
|
19
|
+
root?: string;
|
|
20
|
+
nav?: string;
|
|
21
|
+
button_previous?: string;
|
|
22
|
+
button_next?: string;
|
|
23
|
+
caption_label?: string;
|
|
24
|
+
grid?: string;
|
|
25
|
+
weekday?: string;
|
|
26
|
+
day?: string;
|
|
27
|
+
day_selected?: string;
|
|
28
|
+
day_today?: string;
|
|
29
|
+
day_outside?: string;
|
|
30
|
+
day_range_start?: string;
|
|
31
|
+
day_range_end?: string;
|
|
32
|
+
day_range_middle?: string;
|
|
33
|
+
month_view_grid?: string;
|
|
34
|
+
year_view_grid?: string;
|
|
35
|
+
footer?: string;
|
|
36
|
+
today_button?: string;
|
|
37
|
+
}
|
|
38
|
+
export interface CalendarProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "onSelect" | "disabled"> {
|
|
39
|
+
mode?: CalendarMode;
|
|
40
|
+
selected?: Date | DateRange | null;
|
|
41
|
+
onSelect?: (date: Date | DateRange | undefined) => void;
|
|
42
|
+
showOutsideDays?: boolean;
|
|
43
|
+
disableOutsideDays?: boolean;
|
|
44
|
+
minDate?: Date;
|
|
45
|
+
maxDate?: Date;
|
|
46
|
+
disabled?: Matcher | Matcher[];
|
|
47
|
+
modifiers?: Record<string, Matcher | Matcher[]>;
|
|
48
|
+
modifiersClassNames?: Record<string, string>;
|
|
49
|
+
weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
|
|
50
|
+
numberOfMonths?: number;
|
|
51
|
+
fixedWeeks?: boolean;
|
|
52
|
+
localeWeekdays?: string[];
|
|
53
|
+
localeWeekdaysLong?: string[];
|
|
54
|
+
localeMonths?: string[];
|
|
55
|
+
localeMonthsShort?: string[];
|
|
56
|
+
classNames?: CalendarClassNames;
|
|
57
|
+
}
|
|
58
|
+
declare function Calendar({ className, mode, selected, onSelect, showOutsideDays, disableOutsideDays, minDate, maxDate, disabled, modifiers, modifiersClassNames, weekStartsOn, numberOfMonths, fixedWeeks, localeWeekdays, localeWeekdaysLong, localeMonths, localeMonthsShort, classNames, ...props }: CalendarProps): React$1.JSX.Element;
|
|
59
|
+
declare namespace Calendar {
|
|
60
|
+
var displayName: string;
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
export { Calendar };
|
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "cn";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import * as React$1 from "react";
|
|
5
|
+
import { ChevronRight } from "xiod-icons/icons/ChevronRight";
|
|
6
|
+
import { ChevronLeft } from "xiod-icons/icons/ChevronLeft";
|
|
7
|
+
//#region src/components/calendar.tsx
|
|
8
|
+
const startOfDay = (d) => new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
|
9
|
+
const sameDay = (a, b) => !!a && !!b && a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
10
|
+
const addDays = (d, n) => new Date(d.getFullYear(), d.getMonth(), d.getDate() + n);
|
|
11
|
+
const firstOfMonth = (d) => new Date(d.getFullYear(), d.getMonth(), 1);
|
|
12
|
+
function buildMonth(cursor, weekStartsOn = 0, fixedWeeks = true) {
|
|
13
|
+
const first = firstOfMonth(cursor);
|
|
14
|
+
const offset = (first.getDay() - weekStartsOn + 7) % 7;
|
|
15
|
+
const start = addDays(first, -offset);
|
|
16
|
+
const out = [];
|
|
17
|
+
let totalDays = 42;
|
|
18
|
+
if (!fixedWeeks) {
|
|
19
|
+
if (addDays(start, 35).getMonth() !== cursor.getMonth()) totalDays = 35;
|
|
20
|
+
}
|
|
21
|
+
for (let i = 0; i < totalDays; i++) {
|
|
22
|
+
const date = addDays(start, i);
|
|
23
|
+
out.push({
|
|
24
|
+
date,
|
|
25
|
+
inMonth: date.getMonth() === cursor.getMonth()
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
function matchDate(date, matcher) {
|
|
31
|
+
if (!matcher) return false;
|
|
32
|
+
if (Array.isArray(matcher)) return matcher.some((m) => matchDate(date, m));
|
|
33
|
+
if (typeof matcher === "boolean") return matcher;
|
|
34
|
+
if (matcher instanceof Date) return sameDay(date, matcher);
|
|
35
|
+
if (typeof matcher === "function") return matcher(date);
|
|
36
|
+
if (typeof matcher === "object") {
|
|
37
|
+
const start = startOfDay(date).getTime();
|
|
38
|
+
if ("before" in matcher && matcher.before) {
|
|
39
|
+
if (start < startOfDay(matcher.before).getTime()) return true;
|
|
40
|
+
}
|
|
41
|
+
if ("after" in matcher && matcher.after) {
|
|
42
|
+
if (start > startOfDay(matcher.after).getTime()) return true;
|
|
43
|
+
}
|
|
44
|
+
if ("dayOfWeek" in matcher && matcher.dayOfWeek) {
|
|
45
|
+
const dow = matcher.dayOfWeek;
|
|
46
|
+
if (Array.isArray(dow)) return dow.includes(date.getDay());
|
|
47
|
+
return dow === date.getDay();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
const WEEKDAYS = [
|
|
53
|
+
"Su",
|
|
54
|
+
"Mo",
|
|
55
|
+
"Tu",
|
|
56
|
+
"We",
|
|
57
|
+
"Th",
|
|
58
|
+
"Fr",
|
|
59
|
+
"Sa"
|
|
60
|
+
];
|
|
61
|
+
const WEEKDAYS_LONG = [
|
|
62
|
+
"Sunday",
|
|
63
|
+
"Monday",
|
|
64
|
+
"Tuesday",
|
|
65
|
+
"Wednesday",
|
|
66
|
+
"Thursday",
|
|
67
|
+
"Friday",
|
|
68
|
+
"Saturday"
|
|
69
|
+
];
|
|
70
|
+
const MONTHS = [
|
|
71
|
+
"January",
|
|
72
|
+
"February",
|
|
73
|
+
"March",
|
|
74
|
+
"April",
|
|
75
|
+
"May",
|
|
76
|
+
"June",
|
|
77
|
+
"July",
|
|
78
|
+
"August",
|
|
79
|
+
"September",
|
|
80
|
+
"October",
|
|
81
|
+
"November",
|
|
82
|
+
"December"
|
|
83
|
+
];
|
|
84
|
+
const MONTHS_SHORT = [
|
|
85
|
+
"Jan",
|
|
86
|
+
"Feb",
|
|
87
|
+
"Mar",
|
|
88
|
+
"Apr",
|
|
89
|
+
"May",
|
|
90
|
+
"Jun",
|
|
91
|
+
"Jul",
|
|
92
|
+
"Aug",
|
|
93
|
+
"Sep",
|
|
94
|
+
"Oct",
|
|
95
|
+
"Nov",
|
|
96
|
+
"Dec"
|
|
97
|
+
];
|
|
98
|
+
function getYearRangeStart(date) {
|
|
99
|
+
const year = date.getFullYear();
|
|
100
|
+
return year - (year % 12 + 12) % 12;
|
|
101
|
+
}
|
|
102
|
+
function Calendar({ className, mode = "single", selected, onSelect, showOutsideDays = true, disableOutsideDays = false, minDate, maxDate, disabled, modifiers, modifiersClassNames, weekStartsOn = 0, numberOfMonths = 1, fixedWeeks = true, localeWeekdays, localeWeekdaysLong, localeMonths, localeMonthsShort, classNames, ...props }) {
|
|
103
|
+
const today = React$1.useMemo(() => /* @__PURE__ */ new Date(), []);
|
|
104
|
+
const weekdaysList = localeWeekdays || WEEKDAYS;
|
|
105
|
+
const weekdaysLongList = localeWeekdaysLong || WEEKDAYS_LONG;
|
|
106
|
+
const monthsList = localeMonths || MONTHS;
|
|
107
|
+
const monthsShortList = localeMonthsShort || MONTHS_SHORT;
|
|
108
|
+
const initialCursor = React$1.useMemo(() => {
|
|
109
|
+
if (selected instanceof Date) return firstOfMonth(selected);
|
|
110
|
+
if (selected && typeof selected === "object" && "from" in selected && selected.from) return firstOfMonth(selected.from);
|
|
111
|
+
return firstOfMonth(today);
|
|
112
|
+
}, [selected, today]);
|
|
113
|
+
const [cursor, setCursor] = React$1.useState(initialCursor);
|
|
114
|
+
const [viewMode, setViewMode] = React$1.useState("days");
|
|
115
|
+
React$1.useEffect(() => {
|
|
116
|
+
if (selected instanceof Date) setCursor(firstOfMonth(selected));
|
|
117
|
+
else if (selected && typeof selected === "object" && "from" in selected && selected.from) setCursor(firstOfMonth(selected.from));
|
|
118
|
+
}, [selected]);
|
|
119
|
+
const [focusDate, setFocusDate] = React$1.useState(() => {
|
|
120
|
+
if (selected instanceof Date) return selected;
|
|
121
|
+
if (selected && typeof selected === "object" && "from" in selected && selected.from) return selected.from;
|
|
122
|
+
return today;
|
|
123
|
+
});
|
|
124
|
+
const gridRef = React$1.useRef(null);
|
|
125
|
+
const isDateDisabled = React$1.useCallback((date) => {
|
|
126
|
+
if (minDate && startOfDay(date).getTime() < startOfDay(minDate).getTime()) return true;
|
|
127
|
+
if (maxDate && startOfDay(date).getTime() > startOfDay(maxDate).getTime()) return true;
|
|
128
|
+
return matchDate(date, disabled);
|
|
129
|
+
}, [
|
|
130
|
+
disabled,
|
|
131
|
+
minDate,
|
|
132
|
+
maxDate
|
|
133
|
+
]);
|
|
134
|
+
const handleDateClick = (date) => {
|
|
135
|
+
if (isDateDisabled(date)) return;
|
|
136
|
+
if (mode === "single") onSelect?.(date);
|
|
137
|
+
else {
|
|
138
|
+
const range = selected || {};
|
|
139
|
+
if (!range.from || range.from && range.to) onSelect?.({
|
|
140
|
+
from: date,
|
|
141
|
+
to: void 0
|
|
142
|
+
});
|
|
143
|
+
else if (range.from && !range.to) {
|
|
144
|
+
if (date.getTime() < range.from.getTime()) onSelect?.({
|
|
145
|
+
from: date,
|
|
146
|
+
to: void 0
|
|
147
|
+
});
|
|
148
|
+
else onSelect?.({
|
|
149
|
+
from: range.from,
|
|
150
|
+
to: date
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
setFocusDate(date);
|
|
155
|
+
if (date.getMonth() !== cursor.getMonth()) setCursor(firstOfMonth(date));
|
|
156
|
+
};
|
|
157
|
+
const isPrevNavigationDisabled = React$1.useMemo(() => {
|
|
158
|
+
if (!minDate) return false;
|
|
159
|
+
const minStart = startOfDay(minDate);
|
|
160
|
+
if (viewMode === "days") return firstOfMonth(cursor).getTime() <= minStart.getTime();
|
|
161
|
+
if (viewMode === "months") return cursor.getFullYear() <= minDate.getFullYear();
|
|
162
|
+
return cursor.getFullYear() - (cursor.getFullYear() % 12 + 12) % 12 <= minDate.getFullYear();
|
|
163
|
+
}, [
|
|
164
|
+
cursor,
|
|
165
|
+
minDate,
|
|
166
|
+
viewMode
|
|
167
|
+
]);
|
|
168
|
+
const isNextNavigationDisabled = React$1.useMemo(() => {
|
|
169
|
+
if (!maxDate) return false;
|
|
170
|
+
const maxStart = startOfDay(maxDate);
|
|
171
|
+
if (viewMode === "days") return new Date(cursor.getFullYear(), cursor.getMonth() + numberOfMonths - 1, 1).getTime() >= firstOfMonth(maxStart).getTime();
|
|
172
|
+
if (viewMode === "months") return cursor.getFullYear() >= maxDate.getFullYear();
|
|
173
|
+
return cursor.getFullYear() - (cursor.getFullYear() % 12 + 12) % 12 + 11 >= maxDate.getFullYear();
|
|
174
|
+
}, [
|
|
175
|
+
cursor,
|
|
176
|
+
maxDate,
|
|
177
|
+
viewMode,
|
|
178
|
+
numberOfMonths
|
|
179
|
+
]);
|
|
180
|
+
const handlePrev = () => {
|
|
181
|
+
if (isPrevNavigationDisabled) return;
|
|
182
|
+
if (viewMode === "days") setCursor((c) => new Date(c.getFullYear(), c.getMonth() - numberOfMonths, 1));
|
|
183
|
+
else if (viewMode === "months") setCursor((c) => new Date(c.getFullYear() - 1, c.getMonth(), 1));
|
|
184
|
+
else setCursor((c) => new Date(c.getFullYear() - 12, c.getMonth(), 1));
|
|
185
|
+
};
|
|
186
|
+
const handleNext = () => {
|
|
187
|
+
if (isNextNavigationDisabled) return;
|
|
188
|
+
if (viewMode === "days") setCursor((c) => new Date(c.getFullYear(), c.getMonth() + numberOfMonths, 1));
|
|
189
|
+
else if (viewMode === "months") setCursor((c) => new Date(c.getFullYear() + 1, c.getMonth(), 1));
|
|
190
|
+
else setCursor((c) => new Date(c.getFullYear() + 12, c.getMonth(), 1));
|
|
191
|
+
};
|
|
192
|
+
const handleHeaderClick = () => {
|
|
193
|
+
if (viewMode === "days") setViewMode("months");
|
|
194
|
+
else if (viewMode === "months") setViewMode("years");
|
|
195
|
+
};
|
|
196
|
+
const moveFocus = (days) => {
|
|
197
|
+
setFocusDate((prev) => {
|
|
198
|
+
const next = addDays(prev, days);
|
|
199
|
+
if (isDateDisabled(next)) return prev;
|
|
200
|
+
if (next.getMonth() !== prev.getMonth() || next.getFullYear() !== prev.getFullYear()) setCursor(firstOfMonth(next));
|
|
201
|
+
return next;
|
|
202
|
+
});
|
|
203
|
+
};
|
|
204
|
+
const handleKeyDown = (e) => {
|
|
205
|
+
if (viewMode !== "days") return;
|
|
206
|
+
switch (e.key) {
|
|
207
|
+
case "ArrowLeft":
|
|
208
|
+
e.preventDefault();
|
|
209
|
+
moveFocus(-1);
|
|
210
|
+
break;
|
|
211
|
+
case "ArrowRight":
|
|
212
|
+
e.preventDefault();
|
|
213
|
+
moveFocus(1);
|
|
214
|
+
break;
|
|
215
|
+
case "ArrowUp":
|
|
216
|
+
e.preventDefault();
|
|
217
|
+
moveFocus(-7);
|
|
218
|
+
break;
|
|
219
|
+
case "ArrowDown":
|
|
220
|
+
e.preventDefault();
|
|
221
|
+
moveFocus(7);
|
|
222
|
+
break;
|
|
223
|
+
case "PageUp":
|
|
224
|
+
e.preventDefault();
|
|
225
|
+
handlePrev();
|
|
226
|
+
break;
|
|
227
|
+
case "PageDown":
|
|
228
|
+
e.preventDefault();
|
|
229
|
+
handleNext();
|
|
230
|
+
break;
|
|
231
|
+
case "Enter":
|
|
232
|
+
case " ":
|
|
233
|
+
e.preventDefault();
|
|
234
|
+
handleDateClick(focusDate);
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
React$1.useEffect(() => {
|
|
238
|
+
if (viewMode !== "days") return;
|
|
239
|
+
if (Number.isNaN(focusDate.getTime())) return;
|
|
240
|
+
(gridRef.current?.querySelector("[data-focused=\"true\"]"))?.focus();
|
|
241
|
+
}, [viewMode, focusDate]);
|
|
242
|
+
const renderHeaderLabel = () => {
|
|
243
|
+
if (viewMode === "days") {
|
|
244
|
+
if (numberOfMonths === 1) return `${monthsList[cursor.getMonth()]} ${cursor.getFullYear()}`;
|
|
245
|
+
const nextMonth = new Date(cursor.getFullYear(), cursor.getMonth() + numberOfMonths - 1, 1);
|
|
246
|
+
return `${monthsList[cursor.getMonth()]} ${cursor.getFullYear()} - ${monthsList[nextMonth.getMonth()]} ${nextMonth.getFullYear()}`;
|
|
247
|
+
}
|
|
248
|
+
if (viewMode === "months") return `${cursor.getFullYear()}`;
|
|
249
|
+
const start = getYearRangeStart(cursor);
|
|
250
|
+
return `${start} – ${start + 11}`;
|
|
251
|
+
};
|
|
252
|
+
const getDaySelectionState = (date) => {
|
|
253
|
+
const isStart = mode === "range" && selected && typeof selected === "object" && "from" in selected && sameDay(date, selected.from);
|
|
254
|
+
const isEnd = mode === "range" && selected && typeof selected === "object" && "to" in selected && sameDay(date, selected.to);
|
|
255
|
+
const isMiddle = mode === "range" && selected && typeof selected === "object" && "from" in selected && "to" in selected && selected.from && selected.to && date.getTime() > selected.from.getTime() && date.getTime() < selected.to.getTime();
|
|
256
|
+
const isSelectedSingle = mode === "single" && selected instanceof Date && sameDay(date, selected);
|
|
257
|
+
return {
|
|
258
|
+
isSelected: isStart || isEnd || isSelectedSingle,
|
|
259
|
+
isStart,
|
|
260
|
+
isEnd,
|
|
261
|
+
isMiddle
|
|
262
|
+
};
|
|
263
|
+
};
|
|
264
|
+
const getModifierClassNames = (date) => {
|
|
265
|
+
if (!modifiers) return "";
|
|
266
|
+
const activeModifiers = [];
|
|
267
|
+
for (const [key, matcher] of Object.entries(modifiers)) if (matchDate(date, matcher)) activeModifiers.push(key);
|
|
268
|
+
return activeModifiers.map((m) => modifiersClassNames?.[m]).filter(Boolean).join(" ");
|
|
269
|
+
};
|
|
270
|
+
const rotatedWeekdays = React$1.useMemo(() => {
|
|
271
|
+
return [...weekdaysList.slice(weekStartsOn), ...weekdaysList.slice(0, weekStartsOn)];
|
|
272
|
+
}, [weekdaysList, weekStartsOn]);
|
|
273
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
274
|
+
"data-slot": "calendar",
|
|
275
|
+
style: { "--number-of-months": numberOfMonths },
|
|
276
|
+
className: cn("relative flex flex-col rounded-2xl border bg-card p-4 shadow-xs/5 select-none text-foreground before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-2xl)-1px)] not-data-disabled:not-focus-visible:not-aria-invalid:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] dark:not-data-disabled:not-focus-visible:not-aria-invalid:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 [&_svg:not([class*='opacity-'])]:opacity-80", numberOfMonths === 1 ? "w-72" : "w-full md:w-[calc(16rem*var(--number-of-months)+2rem)]", classNames?.root, className),
|
|
277
|
+
...props,
|
|
278
|
+
children: [
|
|
279
|
+
/* @__PURE__ */ jsxs("div", {
|
|
280
|
+
className: cn("flex items-center justify-between mb-4", classNames?.nav),
|
|
281
|
+
children: [
|
|
282
|
+
/* @__PURE__ */ jsx("button", {
|
|
283
|
+
type: "button",
|
|
284
|
+
onClick: handlePrev,
|
|
285
|
+
disabled: isPrevNavigationDisabled,
|
|
286
|
+
className: cn("relative inline-flex size-8 items-center justify-center rounded-lg border border-input bg-background/20 transition-colors hover:bg-accent hover:text-accent-foreground outline-none focus-visible:ring-1 focus-visible:ring-ring pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 disabled:pointer-events-none disabled:opacity-64", classNames?.button_previous),
|
|
287
|
+
"aria-label": "Previous Page",
|
|
288
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-4 shrink-0 pointer-events-none" })
|
|
289
|
+
}),
|
|
290
|
+
/* @__PURE__ */ jsx("button", {
|
|
291
|
+
type: "button",
|
|
292
|
+
onClick: handleHeaderClick,
|
|
293
|
+
disabled: viewMode === "years",
|
|
294
|
+
className: cn("rounded-md px-2.5 py-1 text-sm font-semibold tracking-tight transition-colors outline-none focus-visible:ring-1 focus-visible:ring-ring", viewMode !== "years" && "hover:bg-accent hover:text-accent-foreground", classNames?.caption_label),
|
|
295
|
+
children: renderHeaderLabel()
|
|
296
|
+
}),
|
|
297
|
+
/* @__PURE__ */ jsx("button", {
|
|
298
|
+
type: "button",
|
|
299
|
+
onClick: handleNext,
|
|
300
|
+
disabled: isNextNavigationDisabled,
|
|
301
|
+
className: cn("relative inline-flex size-8 items-center justify-center rounded-lg border border-input bg-background/20 transition-colors hover:bg-accent hover:text-accent-foreground outline-none focus-visible:ring-1 focus-visible:ring-ring pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 disabled:pointer-events-none disabled:opacity-64", classNames?.button_next),
|
|
302
|
+
"aria-label": "Next Page",
|
|
303
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-4 shrink-0 pointer-events-none" })
|
|
304
|
+
})
|
|
305
|
+
]
|
|
306
|
+
}),
|
|
307
|
+
/* @__PURE__ */ jsxs("div", {
|
|
308
|
+
ref: gridRef,
|
|
309
|
+
onKeyDown: handleKeyDown,
|
|
310
|
+
className: cn("relative overflow-hidden rounded-xl bg-muted/20 border border-border/30 p-2 shadow-[inset_0_1px_2px_rgba(0,0,0,0.02)]", viewMode === "days" ? "h-fit" : "h-60", classNames?.grid),
|
|
311
|
+
children: [
|
|
312
|
+
viewMode === "days" && /* @__PURE__ */ jsx("div", {
|
|
313
|
+
className: cn("flex flex-col gap-6 md:flex-row", numberOfMonths > 1 && "divide-x divide-border/20 md:gap-0"),
|
|
314
|
+
children: Array.from({ length: numberOfMonths }).map((_, monthIdx) => {
|
|
315
|
+
const currentMonthCursor = new Date(cursor.getFullYear(), cursor.getMonth() + monthIdx, 1);
|
|
316
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
317
|
+
className: cn("flex flex-col w-full md:w-64", numberOfMonths > 1 && "px-4 first:ps-0 last:pe-0"),
|
|
318
|
+
children: [
|
|
319
|
+
numberOfMonths > 1 && /* @__PURE__ */ jsxs("div", {
|
|
320
|
+
className: "text-center text-xs font-semibold mb-3 tracking-tight text-muted-foreground",
|
|
321
|
+
children: [
|
|
322
|
+
monthsList[currentMonthCursor.getMonth()],
|
|
323
|
+
" ",
|
|
324
|
+
currentMonthCursor.getFullYear()
|
|
325
|
+
]
|
|
326
|
+
}),
|
|
327
|
+
/* @__PURE__ */ jsx("div", {
|
|
328
|
+
className: "grid grid-cols-7 mb-1 text-center w-full",
|
|
329
|
+
children: rotatedWeekdays.map((d) => /* @__PURE__ */ jsx("span", {
|
|
330
|
+
className: cn("text-[10px] font-bold uppercase tracking-wider text-muted-foreground/60 h-6 flex items-center justify-center", classNames?.weekday),
|
|
331
|
+
children: d
|
|
332
|
+
}, d))
|
|
333
|
+
}),
|
|
334
|
+
/* @__PURE__ */ jsx("div", {
|
|
335
|
+
className: "grid grid-cols-7 grid-rows-6 gap-y-0.5 w-full",
|
|
336
|
+
children: buildMonth(currentMonthCursor, weekStartsOn, fixedWeeks).map(({ date, inMonth }) => {
|
|
337
|
+
const { isSelected, isStart, isEnd, isMiddle } = getDaySelectionState(date);
|
|
338
|
+
const isToday = sameDay(date, today);
|
|
339
|
+
const disabledState = isDateDisabled(date) || disableOutsideDays && !inMonth;
|
|
340
|
+
const showCell = inMonth || showOutsideDays;
|
|
341
|
+
const customClasses = getModifierClassNames(date);
|
|
342
|
+
if (!showCell) return /* @__PURE__ */ jsx("div", { className: "h-8 w-8 sm:h-7.5 sm:w-7.5" }, date.toISOString());
|
|
343
|
+
const isFocused = sameDay(date, focusDate);
|
|
344
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
345
|
+
type: "button",
|
|
346
|
+
tabIndex: isFocused ? 0 : -1,
|
|
347
|
+
"data-focused": isFocused,
|
|
348
|
+
disabled: disabledState,
|
|
349
|
+
onClick: () => handleDateClick(date),
|
|
350
|
+
className: cn("relative h-8 w-8 sm:h-7.5 sm:w-7.5 m-auto text-[12.5px] font-medium transition-[background-color,color,border-radius] duration-150 flex items-center justify-center outline-none focus-visible:z-10 focus-visible:ring-1 focus-visible:ring-ring pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11", isMiddle && "bg-primary/12 text-primary rounded-none w-full h-8 sm:h-7.5 m-0", isMiddle && classNames?.day_range_middle, isStart && "bg-primary text-primary-foreground font-semibold rounded-l-lg rounded-r-none w-full h-8 sm:h-7.5 m-0", isStart && classNames?.day_range_start, isEnd && "bg-primary text-primary-foreground font-semibold rounded-r-lg rounded-l-none w-full h-8 sm:h-7.5 m-0", isEnd && classNames?.day_range_end, isSelected && !isStart && !isEnd && "bg-primary text-primary-foreground font-semibold rounded-lg", isSelected && classNames?.day_selected, !isSelected && !isMiddle && !disabledState && "hover:bg-accent hover:text-accent-foreground rounded-lg", !isSelected && !isMiddle && (inMonth ? "text-foreground" : "text-muted-foreground/35"), !inMonth && classNames?.day_outside, isToday && classNames?.day_today, disabledState && "opacity-30 cursor-not-allowed line-through", customClasses, classNames?.day),
|
|
351
|
+
"aria-label": `${weekdaysLongList[date.getDay()]}, ${monthsList[date.getMonth()]} ${date.getDate()}, ${date.getFullYear()}`,
|
|
352
|
+
"aria-pressed": isSelected,
|
|
353
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
354
|
+
className: "relative z-10",
|
|
355
|
+
children: date.getDate()
|
|
356
|
+
}), isToday && /* @__PURE__ */ jsx("span", { className: cn("absolute bottom-1 size-1 rounded-full", isSelected || isStart || isEnd ? "bg-primary-foreground" : "bg-primary") })]
|
|
357
|
+
}, date.toISOString());
|
|
358
|
+
})
|
|
359
|
+
})
|
|
360
|
+
]
|
|
361
|
+
}, currentMonthCursor.toISOString());
|
|
362
|
+
})
|
|
363
|
+
}),
|
|
364
|
+
viewMode === "months" && /* @__PURE__ */ jsx("div", {
|
|
365
|
+
className: cn("grid h-full grid-cols-3 grid-rows-4 gap-1.5 p-1 w-full max-w-64 mx-auto", classNames?.month_view_grid),
|
|
366
|
+
children: monthsShortList.map((mName, mIdx) => {
|
|
367
|
+
const isSelectedMonth = selected instanceof Date && selected.getMonth() === mIdx && selected.getFullYear() === cursor.getFullYear();
|
|
368
|
+
return /* @__PURE__ */ jsx("button", {
|
|
369
|
+
type: "button",
|
|
370
|
+
onClick: () => {
|
|
371
|
+
setCursor(new Date(cursor.getFullYear(), mIdx, 1));
|
|
372
|
+
setViewMode("days");
|
|
373
|
+
},
|
|
374
|
+
className: cn("rounded-lg text-xs font-semibold transition-colors hover:bg-accent hover:text-accent-foreground outline-none focus-visible:ring-1 focus-visible:ring-ring pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11", isSelectedMonth ? "bg-primary text-primary-foreground" : "text-foreground"),
|
|
375
|
+
children: mName
|
|
376
|
+
}, mName);
|
|
377
|
+
})
|
|
378
|
+
}),
|
|
379
|
+
viewMode === "years" && /* @__PURE__ */ jsx("div", {
|
|
380
|
+
className: cn("grid h-full grid-cols-3 grid-rows-4 gap-1.5 p-1 w-full max-w-64 mx-auto", classNames?.year_view_grid),
|
|
381
|
+
children: Array.from({ length: 12 }, (_, i) => getYearRangeStart(cursor) + i).map((yr) => {
|
|
382
|
+
const isSelectedYear = selected instanceof Date && selected.getFullYear() === yr;
|
|
383
|
+
return /* @__PURE__ */ jsx("button", {
|
|
384
|
+
type: "button",
|
|
385
|
+
onClick: () => {
|
|
386
|
+
setCursor(new Date(yr, cursor.getMonth(), 1));
|
|
387
|
+
setViewMode("months");
|
|
388
|
+
},
|
|
389
|
+
className: cn("rounded-lg text-xs font-semibold transition-colors hover:bg-accent hover:text-accent-foreground outline-none focus-visible:ring-1 focus-visible:ring-ring pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11", isSelectedYear ? "bg-primary text-primary-foreground" : "text-foreground"),
|
|
390
|
+
children: yr
|
|
391
|
+
}, yr);
|
|
392
|
+
})
|
|
393
|
+
})
|
|
394
|
+
]
|
|
395
|
+
}),
|
|
396
|
+
/* @__PURE__ */ jsxs("div", {
|
|
397
|
+
className: cn("flex items-center justify-between mt-3 px-1 pt-1 border-t border-border/20", classNames?.footer),
|
|
398
|
+
children: [
|
|
399
|
+
/* @__PURE__ */ jsx("button", {
|
|
400
|
+
type: "button",
|
|
401
|
+
onClick: () => {
|
|
402
|
+
setCursor(firstOfMonth(today));
|
|
403
|
+
setFocusDate(today);
|
|
404
|
+
handleDateClick(today);
|
|
405
|
+
setViewMode("days");
|
|
406
|
+
},
|
|
407
|
+
className: cn("text-xs font-semibold text-primary transition-colors hover:text-primary/80 outline-none focus-visible:ring-1 focus-visible:ring-ring pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11", classNames?.today_button),
|
|
408
|
+
children: "Today"
|
|
409
|
+
}),
|
|
410
|
+
selected instanceof Date && /* @__PURE__ */ jsx("span", {
|
|
411
|
+
className: "text-2xs tabular-nums text-muted-foreground/80 font-medium",
|
|
412
|
+
children: `${monthsShortList[selected.getMonth()]} ${selected.getDate()}, ${selected.getFullYear()}`
|
|
413
|
+
}),
|
|
414
|
+
selected && typeof selected === "object" && "from" in selected && selected.from && /* @__PURE__ */ jsxs("span", {
|
|
415
|
+
className: "text-2xs tabular-nums text-muted-foreground/80 font-medium",
|
|
416
|
+
children: [`${monthsShortList[selected.from.getMonth()]} ${selected.from.getDate()}`, selected.to ? ` - ${monthsShortList[selected.to.getMonth()]} ${selected.to.getDate()}` : " - ..."]
|
|
417
|
+
})
|
|
418
|
+
]
|
|
419
|
+
})
|
|
420
|
+
]
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
Calendar.displayName = "Calendar";
|
|
424
|
+
//#endregion
|
|
425
|
+
export { Calendar };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as React$1 from "react";
|
|
2
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
3
|
+
//#region src/components/card.d.ts
|
|
4
|
+
declare function Card({ className, render, ...props }: useRender.ComponentProps<"div">): React$1.ReactElement;
|
|
5
|
+
declare function CardFrame({ className, render, ...props }: useRender.ComponentProps<"div">): React$1.ReactElement;
|
|
6
|
+
declare function CardFrameHeader({ className, render, ...props }: useRender.ComponentProps<"div">): React$1.ReactElement;
|
|
7
|
+
declare function CardFrameTitle({ className, render, ...props }: useRender.ComponentProps<"div">): React$1.ReactElement;
|
|
8
|
+
declare function CardFrameDescription({ className, render, ...props }: useRender.ComponentProps<"div">): React$1.ReactElement;
|
|
9
|
+
declare function CardFrameFooter({ className, render, ...props }: useRender.ComponentProps<"div">): React$1.ReactElement;
|
|
10
|
+
declare function CardHeader({ className, render, ...props }: useRender.ComponentProps<"div">): React$1.ReactElement;
|
|
11
|
+
declare function CardTitle({ className, render, ...props }: useRender.ComponentProps<"div">): React$1.ReactElement;
|
|
12
|
+
declare function CardDescription({ className, render, ...props }: useRender.ComponentProps<"div">): React$1.ReactElement;
|
|
13
|
+
declare function CardAction({ className, render, ...props }: useRender.ComponentProps<"div">): React$1.ReactElement;
|
|
14
|
+
declare function CardPanel({ className, render, ...props }: useRender.ComponentProps<"div">): React$1.ReactElement;
|
|
15
|
+
declare function CardFooter({ className, render, ...props }: useRender.ComponentProps<"div">): React$1.ReactElement;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { Card, CardAction, CardPanel as CardContent, CardPanel, CardDescription, CardFooter, CardFrame, CardFrameDescription, CardFrameFooter, CardFrameHeader, CardFrameTitle, CardHeader, CardTitle };
|