@seekalfred/primitives 0.5.0 → 0.6.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/README.md +664 -9
- package/dist/accordion/accordion.d.ts +5 -5
- package/dist/accordion/accordion.js +22 -11
- package/dist/accordion/accordion.js.map +1 -1
- package/dist/action-button/action-button.d.ts +50 -0
- package/dist/action-button/action-button.js +159 -0
- package/dist/action-button/action-button.js.map +1 -0
- package/dist/action-button/index.d.ts +2 -0
- package/dist/action-button/index.js +2 -0
- package/dist/alert/alert.d.ts +16 -2
- package/dist/alert/alert.js +118 -20
- package/dist/alert/alert.js.map +1 -1
- package/dist/alert-dialog/alert-dialog.d.ts +1 -1
- package/dist/alert-dialog/alert-dialog.js +4 -2
- package/dist/alert-dialog/alert-dialog.js.map +1 -1
- package/dist/avatar/avatar.d.ts +7 -1
- package/dist/avatar/avatar.js +51 -18
- package/dist/avatar/avatar.js.map +1 -1
- package/dist/badge/badge.d.ts +10 -3
- package/dist/badge/badge.js +37 -5
- package/dist/badge/badge.js.map +1 -1
- package/dist/breadcrumb/breadcrumb.d.ts +3 -30
- package/dist/breadcrumb/breadcrumb.js +25 -8
- package/dist/breadcrumb/breadcrumb.js.map +1 -1
- package/dist/button/button.d.ts +36 -23
- package/dist/button/button.js +178 -33
- package/dist/button/button.js.map +1 -1
- package/dist/button-group/button-group.d.ts +76 -0
- package/dist/button-group/button-group.js +403 -0
- package/dist/button-group/button-group.js.map +1 -0
- package/dist/button-group/index.d.ts +2 -0
- package/dist/button-group/index.js +2 -0
- package/dist/calendar/calendar.d.ts +3 -3
- package/dist/calendar/calendar.js +263 -34
- package/dist/calendar/calendar.js.map +1 -1
- package/dist/card/card.d.ts +14 -7
- package/dist/card/card.js +32 -14
- package/dist/card/card.js.map +1 -1
- package/dist/checkbox/checkbox.d.ts +2 -9
- package/dist/checkbox/checkbox.js +28 -29
- package/dist/checkbox/checkbox.js.map +1 -1
- package/dist/confirm-morph/confirm-morph.d.ts +85 -0
- package/dist/confirm-morph/confirm-morph.js +652 -0
- package/dist/confirm-morph/confirm-morph.js.map +1 -0
- package/dist/confirm-morph/index.d.ts +2 -0
- package/dist/confirm-morph/index.js +2 -0
- package/dist/copy-button/copy-button.d.ts +32 -0
- package/dist/copy-button/copy-button.js +134 -0
- package/dist/copy-button/copy-button.js.map +1 -0
- package/dist/copy-button/index.d.ts +2 -0
- package/dist/copy-button/index.js +2 -0
- package/dist/date-picker/date-picker.d.ts +51 -0
- package/dist/date-picker/date-picker.js +241 -0
- package/dist/date-picker/date-picker.js.map +1 -0
- package/dist/date-picker/date-range-picker.d.ts +78 -0
- package/dist/date-picker/date-range-picker.js +1015 -0
- package/dist/date-picker/date-range-picker.js.map +1 -0
- package/dist/date-picker/index.d.ts +4 -0
- package/dist/date-picker/index.js +4 -0
- package/dist/date-picker/picker-parts.d.ts +46 -0
- package/dist/date-picker/picker-parts.js +135 -0
- package/dist/date-picker/picker-parts.js.map +1 -0
- package/dist/dialog/dialog.d.ts +12 -16
- package/dist/dialog/dialog.js +45 -14
- package/dist/dialog/dialog.js.map +1 -1
- package/dist/empty-state/empty-state.d.ts +44 -0
- package/dist/empty-state/empty-state.js +83 -0
- package/dist/empty-state/empty-state.js.map +1 -0
- package/dist/empty-state/index.d.ts +2 -0
- package/dist/empty-state/index.js +2 -0
- package/dist/expanding-button-group/expanding-button-group.d.ts +54 -0
- package/dist/expanding-button-group/expanding-button-group.js +350 -0
- package/dist/expanding-button-group/expanding-button-group.js.map +1 -0
- package/dist/expanding-button-group/index.d.ts +2 -0
- package/dist/expanding-button-group/index.js +2 -0
- package/dist/file-drop-zone/file-drop-zone.d.ts +71 -0
- package/dist/file-drop-zone/file-drop-zone.js +116 -0
- package/dist/file-drop-zone/file-drop-zone.js.map +1 -0
- package/dist/file-drop-zone/index.d.ts +2 -0
- package/dist/file-drop-zone/index.js +2 -0
- package/dist/filter-bar/filter-bar.d.ts +121 -0
- package/dist/filter-bar/filter-bar.js +300 -0
- package/dist/filter-bar/filter-bar.js.map +1 -0
- package/dist/filter-bar/index.d.ts +2 -0
- package/dist/filter-bar/index.js +2 -0
- package/dist/floating-button-group/floating-button-group.d.ts +61 -0
- package/dist/floating-button-group/floating-button-group.js +340 -0
- package/dist/floating-button-group/floating-button-group.js.map +1 -0
- package/dist/floating-button-group/index.d.ts +2 -0
- package/dist/floating-button-group/index.js +2 -0
- package/dist/icon-morph/icon-morph.d.ts +55 -0
- package/dist/icon-morph/icon-morph.js +331 -0
- package/dist/icon-morph/icon-morph.js.map +1 -0
- package/dist/icon-morph/index.d.ts +2 -0
- package/dist/icon-morph/index.js +2 -0
- package/dist/index.d.ts +24 -2
- package/dist/index.js +29 -7
- package/dist/input/input.d.ts +23 -1
- package/dist/input/input.js +37 -13
- package/dist/input/input.js.map +1 -1
- package/dist/label/label.d.ts +1 -1
- package/dist/label/label.js +4 -2
- package/dist/label/label.js.map +1 -1
- package/dist/lib/count-to.js +113 -0
- package/dist/lib/count-to.js.map +1 -0
- package/dist/lib/eye-morph.js +62 -0
- package/dist/lib/eye-morph.js.map +1 -0
- package/dist/lib/field-message.js +336 -0
- package/dist/lib/field-message.js.map +1 -0
- package/dist/lib/field-shell.js +81 -0
- package/dist/lib/field-shell.js.map +1 -0
- package/dist/lib/field-surface.js +4 -2
- package/dist/lib/field-surface.js.map +1 -1
- package/dist/lib/flip.js +80 -0
- package/dist/lib/flip.js.map +1 -0
- package/dist/lib/height-follow.js +59 -0
- package/dist/lib/height-follow.js.map +1 -0
- package/dist/lib/icon-swap.js +47 -0
- package/dist/lib/icon-swap.js.map +1 -0
- package/dist/lib/leaving-list.js +57 -0
- package/dist/lib/leaving-list.js.map +1 -0
- package/dist/lib/merge-refs.js +22 -0
- package/dist/lib/merge-refs.js.map +1 -0
- package/dist/lib/morph-text.js +128 -0
- package/dist/lib/morph-text.js.map +1 -0
- package/dist/lib/motion.js +162 -0
- package/dist/lib/motion.js.map +1 -0
- package/dist/lib/pausable-timeout.js +67 -0
- package/dist/lib/pausable-timeout.js.map +1 -0
- package/dist/lib/rolling-value.js +31 -0
- package/dist/lib/rolling-value.js.map +1 -0
- package/dist/lib/spring-progress.js +114 -0
- package/dist/lib/spring-progress.js.map +1 -0
- package/dist/lib/svg-id.js +10 -0
- package/dist/lib/svg-id.js.map +1 -0
- package/dist/lib/swap-text.js +77 -0
- package/dist/lib/swap-text.js.map +1 -0
- package/dist/lib/use-copy-feedback.js +36 -0
- package/dist/lib/use-copy-feedback.js.map +1 -0
- package/dist/menu/menu.d.ts +5 -5
- package/dist/menu/menu.js +10 -6
- package/dist/menu/menu.js.map +1 -1
- package/dist/page-header/index.d.ts +2 -0
- package/dist/page-header/index.js +2 -0
- package/dist/page-header/page-header.d.ts +75 -0
- package/dist/page-header/page-header.js +83 -0
- package/dist/page-header/page-header.js.map +1 -0
- package/dist/password-field/index.d.ts +2 -0
- package/dist/password-field/index.js +2 -0
- package/dist/password-field/password-field.d.ts +37 -0
- package/dist/password-field/password-field.js +101 -0
- package/dist/password-field/password-field.js.map +1 -0
- package/dist/password-strength/index.d.ts +2 -0
- package/dist/password-strength/index.js +2 -0
- package/dist/password-strength/password-strength.d.ts +127 -0
- package/dist/password-strength/password-strength.js +455 -0
- package/dist/password-strength/password-strength.js.map +1 -0
- package/dist/popover/popover.d.ts +10 -2
- package/dist/popover/popover.js +6 -4
- package/dist/popover/popover.js.map +1 -1
- package/dist/progress/progress.d.ts +2 -2
- package/dist/progress/progress.js +50 -7
- package/dist/progress/progress.js.map +1 -1
- package/dist/radio-group/radio-group.d.ts +3 -3
- package/dist/radio-group/radio-group.js +14 -10
- package/dist/radio-group/radio-group.js.map +1 -1
- package/dist/scroll-area/scroll-area.d.ts +17 -6
- package/dist/scroll-area/scroll-area.js +30 -6
- package/dist/scroll-area/scroll-area.js.map +1 -1
- package/dist/search-field/index.d.ts +2 -0
- package/dist/search-field/index.js +2 -0
- package/dist/search-field/search-field.d.ts +26 -0
- package/dist/search-field/search-field.js +155 -0
- package/dist/search-field/search-field.js.map +1 -0
- package/dist/select/select.d.ts +3 -3
- package/dist/select/select.js +85 -24
- package/dist/select/select.js.map +1 -1
- package/dist/separator/separator.d.ts +1 -1
- package/dist/separator/separator.js +4 -2
- package/dist/separator/separator.js.map +1 -1
- package/dist/sheet/sheet.d.ts +1 -1
- package/dist/sheet/sheet.js +6 -3
- package/dist/sheet/sheet.js.map +1 -1
- package/dist/side-nav/index.d.ts +2 -0
- package/dist/side-nav/index.js +2 -0
- package/dist/side-nav/side-nav.d.ts +72 -0
- package/dist/side-nav/side-nav.js +142 -0
- package/dist/side-nav/side-nav.js.map +1 -0
- package/dist/skeleton/skeleton.d.ts +8 -2
- package/dist/skeleton/skeleton.js +9 -3
- package/dist/skeleton/skeleton.js.map +1 -1
- package/dist/slider/slider.d.ts +2 -2
- package/dist/slider/slider.js +64 -8
- package/dist/slider/slider.js.map +1 -1
- package/dist/spinner/spinner.d.ts +1 -1
- package/dist/spinner/spinner.js +4 -2
- package/dist/spinner/spinner.js.map +1 -1
- package/dist/split-button/index.d.ts +2 -0
- package/dist/split-button/index.js +2 -0
- package/dist/split-button/split-button.d.ts +46 -0
- package/dist/split-button/split-button.js +122 -0
- package/dist/split-button/split-button.js.map +1 -0
- package/dist/stat-card/index.d.ts +2 -0
- package/dist/stat-card/index.js +2 -0
- package/dist/stat-card/stat-card.d.ts +81 -0
- package/dist/stat-card/stat-card.js +152 -0
- package/dist/stat-card/stat-card.js.map +1 -0
- package/dist/styles.css +1 -1
- package/dist/switch/switch.d.ts +2 -2
- package/dist/switch/switch.js +11 -8
- package/dist/switch/switch.js.map +1 -1
- package/dist/table/index.d.ts +2 -2
- package/dist/table/index.js +2 -2
- package/dist/table/table.d.ts +38 -7
- package/dist/table/table.js +114 -12
- package/dist/table/table.js.map +1 -1
- package/dist/tabs/tabs.d.ts +4 -4
- package/dist/tabs/tabs.js +153 -12
- package/dist/tabs/tabs.js.map +1 -1
- package/dist/textarea/textarea.d.ts +24 -1
- package/dist/textarea/textarea.js +27 -3
- package/dist/textarea/textarea.js.map +1 -1
- package/dist/theme-switch/index.d.ts +2 -0
- package/dist/theme-switch/index.js +2 -0
- package/dist/theme-switch/theme-switch.d.ts +37 -0
- package/dist/theme-switch/theme-switch.js +123 -0
- package/dist/theme-switch/theme-switch.js.map +1 -0
- package/dist/time-picker/index.d.ts +2 -0
- package/dist/time-picker/index.js +2 -0
- package/dist/time-picker/time-picker.d.ts +54 -0
- package/dist/time-picker/time-picker.js +201 -0
- package/dist/time-picker/time-picker.js.map +1 -0
- package/dist/toast/toast.d.ts +2 -2
- package/dist/toast/toast.js +61 -39
- package/dist/toast/toast.js.map +1 -1
- package/dist/tooltip/tooltip.d.ts +3 -3
- package/dist/tooltip/tooltip.js +66 -15
- package/dist/tooltip/tooltip.js.map +1 -1
- package/package.json +83 -3
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../lib/cn.js";
|
|
3
|
+
import { useIsomorphicLayoutEffect } from "../lib/motion.js";
|
|
4
|
+
import { SwapText } from "../lib/swap-text.js";
|
|
3
5
|
import { cva } from "class-variance-authority";
|
|
6
|
+
import { forwardRef, useContext, useRef, useState } from "react";
|
|
4
7
|
import { Button, Calendar, CalendarCell, CalendarGrid, CalendarGridBody, CalendarGridHeader, CalendarHeaderCell, CalendarHeading, CalendarStateContext, RangeCalendar, RangeCalendarStateContext } from "react-aria-components";
|
|
5
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
-
import { useContext } from "react";
|
|
8
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
7
9
|
//#region src/calendar/calendar.tsx
|
|
8
10
|
/**
|
|
9
11
|
* Calendar, built on React Aria's Calendar and RangeCalendar.
|
|
@@ -41,7 +43,7 @@ const calendarNavVariants = cva([
|
|
|
41
43
|
"[&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
42
44
|
"[&_svg:not([class*='size-'])]:size-(--icon-sm)",
|
|
43
45
|
"[&_svg]:rtl:-scale-x-100",
|
|
44
|
-
"
|
|
46
|
+
"calendar-nav-motion",
|
|
45
47
|
"data-[hovered]:bg-muted data-[pressed]:bg-muted",
|
|
46
48
|
"data-[focus-visible]:outline-solid data-[focus-visible]:outline-(length:--focus-ring-width)",
|
|
47
49
|
"data-[focus-visible]:outline-offset-(--focus-ring-offset) data-[focus-visible]:outline-(--color-ring)",
|
|
@@ -49,6 +51,8 @@ const calendarNavVariants = cva([
|
|
|
49
51
|
]);
|
|
50
52
|
const calendarMonthsVariants = cva(["flex flex-col gap-(--density-gap) sm:flex-row sm:items-start"]);
|
|
51
53
|
const calendarHeadingVariants = cva(["mb-1 text-center text-sm font-semibold text-foreground"]);
|
|
54
|
+
/** The month title of a one-month calendar, in the header beside the buttons. */
|
|
55
|
+
const calendarTitleVariants = cva(["min-w-0 flex-1 text-start text-sm font-semibold text-foreground tabular-nums whitespace-nowrap"]);
|
|
52
56
|
const calendarGridVariants = cva(["border-collapse"]);
|
|
53
57
|
const calendarHeaderCellVariants = cva(["w-(--density-control-h-sm) pb-1", "text-center text-2xs font-medium text-muted-foreground"]);
|
|
54
58
|
const calendarClearVariants = cva([
|
|
@@ -79,8 +83,8 @@ const calendarCellVariants = cva([
|
|
|
79
83
|
"size-(--density-control-h-sm) rounded-md",
|
|
80
84
|
"text-sm leading-(--leading-normal) text-foreground",
|
|
81
85
|
"cursor-pointer select-none outline-none",
|
|
82
|
-
"
|
|
83
|
-
"data-[hovered]:bg-muted",
|
|
86
|
+
"relative z-10 calendar-day",
|
|
87
|
+
"data-[hovered]:not-data-[selected]:bg-muted",
|
|
84
88
|
"data-[today]:font-semibold data-[today]:underline data-[today]:underline-offset-4",
|
|
85
89
|
"data-[outside-month]:text-muted-foreground data-[outside-month]:opacity-(--opacity-disabled)",
|
|
86
90
|
"data-[unavailable]:cursor-not-allowed data-[unavailable]:text-muted-foreground",
|
|
@@ -96,13 +100,24 @@ const calendarCellVariants = cva([
|
|
|
96
100
|
* exactly what OCP asks a variant to model.
|
|
97
101
|
*/
|
|
98
102
|
selection: {
|
|
99
|
-
single: ["data-[selected]:
|
|
103
|
+
single: ["data-[selected]:text-primary-foreground", "data-[selected]:font-semibold"],
|
|
100
104
|
range: [
|
|
101
105
|
"data-[selected]:rounded-none data-[selected]:bg-muted data-[selected]:text-foreground",
|
|
102
106
|
"data-[selection-start]:rounded-s-md data-[selection-start]:bg-primary",
|
|
103
107
|
"data-[selection-start]:font-semibold data-[selection-start]:text-primary-foreground",
|
|
104
108
|
"data-[selection-end]:rounded-e-md data-[selection-end]:bg-primary",
|
|
105
109
|
"data-[selection-end]:font-semibold data-[selection-end]:text-primary-foreground"
|
|
110
|
+
],
|
|
111
|
+
/**
|
|
112
|
+
* The range picker's own look: the band and the ends are drawn beneath the
|
|
113
|
+
* cells by the picker, which slides and stretches them, so the cells paint
|
|
114
|
+
* only their text (and the shorter press, .9 in 120ms).
|
|
115
|
+
*/
|
|
116
|
+
band: [
|
|
117
|
+
"[--press-scale:0.9] [--press-time:120ms]",
|
|
118
|
+
"data-[selected]:not-data-[selection-start]:not-data-[selection-end]:text-foreground",
|
|
119
|
+
"data-[selection-start]:font-medium data-[selection-start]:text-primary-foreground data-[selection-start]:[--number-delay:40ms]",
|
|
120
|
+
"data-[selection-end]:font-medium data-[selection-end]:text-primary-foreground data-[selection-end]:[--number-delay:40ms]"
|
|
106
121
|
]
|
|
107
122
|
} },
|
|
108
123
|
defaultVariants: { selection: "single" }
|
|
@@ -169,25 +184,245 @@ function ClearButton({ label }) {
|
|
|
169
184
|
children: label
|
|
170
185
|
});
|
|
171
186
|
}
|
|
187
|
+
/** The month's rows, headers and cells: one grid for the month `offset` months from the first visible one. */
|
|
188
|
+
function MonthGrid({ offset, selection }) {
|
|
189
|
+
return /* @__PURE__ */ jsxs(CalendarGrid, {
|
|
190
|
+
offset: { months: offset },
|
|
191
|
+
className: calendarGridVariants(),
|
|
192
|
+
children: [/* @__PURE__ */ jsx(CalendarGridHeader, { children: (weekday) => /* @__PURE__ */ jsx(CalendarHeaderCell, {
|
|
193
|
+
className: calendarHeaderCellVariants(),
|
|
194
|
+
children: weekday
|
|
195
|
+
}) }), /* @__PURE__ */ jsx(CalendarGridBody, { children: (date) => /* @__PURE__ */ jsx(CalendarCell, {
|
|
196
|
+
date,
|
|
197
|
+
"data-slot": "calendar-cell",
|
|
198
|
+
className: calendarCellVariants({ selection })
|
|
199
|
+
}) })]
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
/** The first visible day, from whichever root we are under. */
|
|
203
|
+
function useVisibleStart() {
|
|
204
|
+
const single = useContext(CalendarStateContext);
|
|
205
|
+
const range = useContext(RangeCalendarStateContext);
|
|
206
|
+
return (single ?? range)?.visibleRange.start;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* The month title. React Aria's own heading stays, visually hidden, as the text;
|
|
210
|
+
* the copy the eye sees crosses in place: the new month arrives from the side the
|
|
211
|
+
* strip travels to while the old one leaves toward the other. Nothing animates on
|
|
212
|
+
* first mount.
|
|
213
|
+
*/
|
|
214
|
+
function MonthTitle() {
|
|
215
|
+
const start = useVisibleStart();
|
|
216
|
+
const headingRef = useRef(null);
|
|
217
|
+
const [text, setText] = useState("");
|
|
218
|
+
const [shown, setShown] = useState(start);
|
|
219
|
+
const [dir, setDir] = useState(1);
|
|
220
|
+
if (start && shown && start.compare(shown) !== 0) {
|
|
221
|
+
setShown(start);
|
|
222
|
+
setDir(start.compare(shown) > 0 ? 1 : -1);
|
|
223
|
+
}
|
|
224
|
+
useIsomorphicLayoutEffect(() => {
|
|
225
|
+
const next = headingRef.current?.textContent ?? "";
|
|
226
|
+
if (next !== text) setText(next);
|
|
227
|
+
});
|
|
228
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(CalendarHeading, {
|
|
229
|
+
ref: headingRef,
|
|
230
|
+
className: "sr-only"
|
|
231
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
232
|
+
"aria-hidden": "true",
|
|
233
|
+
"data-slot": "calendar-title",
|
|
234
|
+
className: calendarTitleVariants(),
|
|
235
|
+
children: /* @__PURE__ */ jsx(SwapText, {
|
|
236
|
+
swapKey: text,
|
|
237
|
+
dir,
|
|
238
|
+
motion: "slide",
|
|
239
|
+
className: "block",
|
|
240
|
+
children: text
|
|
241
|
+
}, text === "" ? "boot" : "live")
|
|
242
|
+
})] });
|
|
243
|
+
}
|
|
244
|
+
/** A day cell's place in its month's grid, read from the table's structure: no layout is forced. */
|
|
245
|
+
function gridPlace(cell) {
|
|
246
|
+
const td = cell.closest("td");
|
|
247
|
+
const tr = td?.parentElement;
|
|
248
|
+
return td && tr ? {
|
|
249
|
+
col: td.cellIndex,
|
|
250
|
+
row: tr.sectionRowIndex
|
|
251
|
+
} : null;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Drives the selected disc of every month. The disc is one element under the day
|
|
255
|
+
* cells, placed from the selected cell's measured box, so it glides on a straight
|
|
256
|
+
* line between any two days, keeps its place while the strip slides, and only
|
|
257
|
+
* grows in or fades out when the selection enters or leaves a month. Each number
|
|
258
|
+
* flips colour as the disc actually passes it: the day it lands on waits longer on
|
|
259
|
+
* long hops, the day it leaves waits longer on short ones.
|
|
260
|
+
*
|
|
261
|
+
* It is one component, first in the tree, because order matters: the colour
|
|
262
|
+
* transitions start at the first style recalculation after a cell's state
|
|
263
|
+
* changes, and anything that measures the page (the title's swap does, on every
|
|
264
|
+
* commit) forces one. So every delay is set from the table's structure before any
|
|
265
|
+
* box is measured, and it runs before the header's effects do.
|
|
266
|
+
*/
|
|
267
|
+
function DiscDriver() {
|
|
268
|
+
const marker = useRef(null);
|
|
269
|
+
const memory = useRef(/* @__PURE__ */ new WeakMap());
|
|
270
|
+
useContext(CalendarStateContext);
|
|
271
|
+
useIsomorphicLayoutEffect(() => {
|
|
272
|
+
const root = marker.current?.parentElement;
|
|
273
|
+
if (!root) return;
|
|
274
|
+
const work = [...root.querySelectorAll("[data-slot=\"calendar-month\"]")].flatMap((pane) => {
|
|
275
|
+
const el = pane.querySelector(":scope > [data-slot=\"calendar-disc\"]");
|
|
276
|
+
if (!el) return [];
|
|
277
|
+
return [{
|
|
278
|
+
pane,
|
|
279
|
+
el,
|
|
280
|
+
cell: pane.querySelector("[data-slot=\"calendar-cell\"][data-selected]")
|
|
281
|
+
}];
|
|
282
|
+
});
|
|
283
|
+
for (const { el, cell } of work) {
|
|
284
|
+
if (!cell) continue;
|
|
285
|
+
const place = gridPlace(cell);
|
|
286
|
+
const before = memory.current.get(el);
|
|
287
|
+
if (el.dataset.visible === void 0 || !before || before.cell === cell || !place) continue;
|
|
288
|
+
const distance = Math.hypot(place.col - before.col, place.row - before.row);
|
|
289
|
+
if (distance === 0) continue;
|
|
290
|
+
cell.style.setProperty("--number-delay", `${Math.round(Math.min(260, 95 + 85 * Math.log(distance)))}ms`);
|
|
291
|
+
if (before.cell.isConnected) before.cell.style.setProperty("--number-delay", `${Math.round(Math.max(20, 130 / distance))}ms`);
|
|
292
|
+
}
|
|
293
|
+
for (const { pane, el, cell } of work) {
|
|
294
|
+
if (!cell) {
|
|
295
|
+
delete el.dataset.visible;
|
|
296
|
+
memory.current.delete(el);
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
const box = cell.getBoundingClientRect();
|
|
300
|
+
const paneBox = pane.getBoundingClientRect();
|
|
301
|
+
const x = box.left - paneBox.left - (box.width - cell.offsetWidth) / 2;
|
|
302
|
+
const y = box.top - paneBox.top - (box.height - cell.offsetHeight) / 2;
|
|
303
|
+
el.style.width = `${cell.offsetWidth}px`;
|
|
304
|
+
el.style.height = `${cell.offsetHeight}px`;
|
|
305
|
+
if (el.dataset.visible === void 0) {
|
|
306
|
+
el.style.transition = "none";
|
|
307
|
+
el.style.translate = `${x}px ${y}px`;
|
|
308
|
+
el.offsetWidth;
|
|
309
|
+
el.style.transition = "";
|
|
310
|
+
el.dataset.visible = "";
|
|
311
|
+
} else el.style.translate = `${x}px ${y}px`;
|
|
312
|
+
const place = gridPlace(cell);
|
|
313
|
+
if (place) memory.current.set(el, {
|
|
314
|
+
cell,
|
|
315
|
+
...place
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
return /* @__PURE__ */ jsx("span", {
|
|
320
|
+
ref: marker,
|
|
321
|
+
hidden: true,
|
|
322
|
+
"data-slot": "calendar-disc-driver"
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
/** The disc itself: an empty shell the driver places. */
|
|
326
|
+
function SelectionDisc() {
|
|
327
|
+
return /* @__PURE__ */ jsx("span", {
|
|
328
|
+
"aria-hidden": "true",
|
|
329
|
+
"data-slot": "calendar-disc",
|
|
330
|
+
className: "calendar-disc",
|
|
331
|
+
children: /* @__PURE__ */ jsx("span", { className: "calendar-disc-fill" })
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* One month of the strip. Months sit side by side in a clipped window and slide
|
|
336
|
+
* on a spring; the pane that is not the current month fades back and is inert.
|
|
337
|
+
*/
|
|
338
|
+
function MonthPane({ offset, dir, fresh, disc, selection }) {
|
|
339
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
340
|
+
ref: (node) => {
|
|
341
|
+
if (!node) return;
|
|
342
|
+
if (offset === 0) node.removeAttribute("inert");
|
|
343
|
+
else node.setAttribute("inert", "");
|
|
344
|
+
},
|
|
345
|
+
"data-slot": "calendar-month",
|
|
346
|
+
"data-offset": offset,
|
|
347
|
+
"aria-hidden": offset === 0 ? void 0 : true,
|
|
348
|
+
style: {
|
|
349
|
+
"--k": offset,
|
|
350
|
+
"--dir": dir
|
|
351
|
+
},
|
|
352
|
+
className: cn("calendar-pane", fresh && "motion-safe:animate-calendar-pane-in"),
|
|
353
|
+
children: [disc ? /* @__PURE__ */ jsx(SelectionDisc, {}) : null, /* @__PURE__ */ jsx(MonthGrid, {
|
|
354
|
+
offset,
|
|
355
|
+
selection
|
|
356
|
+
})]
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* One month, shown with its neighbours beside it on a strip. Moving by a month
|
|
361
|
+
* slides the strip; a jump of more than a month brings the new month in from one
|
|
362
|
+
* month away instead of scrolling through the ones between.
|
|
363
|
+
*/
|
|
364
|
+
function MonthStrip({ selection }) {
|
|
365
|
+
const start = useVisibleStart();
|
|
366
|
+
const [shown, setShown] = useState(start);
|
|
367
|
+
const [dir, setDir] = useState(1);
|
|
368
|
+
const [fresh, setFresh] = useState(null);
|
|
369
|
+
const strip = useRef(null);
|
|
370
|
+
useIsomorphicLayoutEffect(() => {
|
|
371
|
+
const el = strip.current;
|
|
372
|
+
const current = el?.querySelector("[data-offset=\"0\"]");
|
|
373
|
+
if (el && current) el.style.height = `${current.offsetHeight}px`;
|
|
374
|
+
});
|
|
375
|
+
const keyOf = (offset) => {
|
|
376
|
+
const d = start?.add({ months: offset });
|
|
377
|
+
return d ? `${d.era}-${d.year}-${d.month}` : String(offset);
|
|
378
|
+
};
|
|
379
|
+
if (start && shown && start.compare(shown) !== 0) {
|
|
380
|
+
const months = (start.year - shown.year) * 12 + (start.month - shown.month);
|
|
381
|
+
setShown(start);
|
|
382
|
+
setDir(months > 0 ? 1 : -1);
|
|
383
|
+
setFresh(Math.abs(months) > 1 ? keyOf(0) : null);
|
|
384
|
+
}
|
|
385
|
+
return /* @__PURE__ */ jsx("div", {
|
|
386
|
+
ref: strip,
|
|
387
|
+
"data-slot": "calendar-months",
|
|
388
|
+
className: "calendar-strip",
|
|
389
|
+
children: [
|
|
390
|
+
-1,
|
|
391
|
+
0,
|
|
392
|
+
1
|
|
393
|
+
].map((offset) => /* @__PURE__ */ jsx(MonthPane, {
|
|
394
|
+
offset,
|
|
395
|
+
dir,
|
|
396
|
+
fresh: fresh === keyOf(offset) && offset === 0,
|
|
397
|
+
disc: selection === "single",
|
|
398
|
+
selection
|
|
399
|
+
}, keyOf(offset)))
|
|
400
|
+
});
|
|
401
|
+
}
|
|
172
402
|
/** Header, grids and Clear — identical under both calendar roots. */
|
|
173
403
|
function CalendarBody({ visibleMonths, clearable, clearLabel, previousLabel, nextLabel, selection }) {
|
|
174
|
-
|
|
404
|
+
const strip = visibleMonths === 1;
|
|
405
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
406
|
+
strip && selection === "single" ? /* @__PURE__ */ jsx(DiscDriver, {}) : null,
|
|
175
407
|
/* @__PURE__ */ jsxs("header", {
|
|
176
408
|
"data-slot": "calendar-header",
|
|
177
409
|
className: calendarHeaderVariants(),
|
|
178
|
-
children: [/* @__PURE__ */ jsx(
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
410
|
+
children: [strip ? /* @__PURE__ */ jsx(MonthTitle, {}) : null, /* @__PURE__ */ jsxs("div", {
|
|
411
|
+
className: "ms-auto flex items-center gap-0.5",
|
|
412
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
413
|
+
slot: "previous",
|
|
414
|
+
"aria-label": previousLabel,
|
|
415
|
+
className: calendarNavVariants(),
|
|
416
|
+
children: /* @__PURE__ */ jsx(ChevronPrevious, {})
|
|
417
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
418
|
+
slot: "next",
|
|
419
|
+
"aria-label": nextLabel,
|
|
420
|
+
className: calendarNavVariants(),
|
|
421
|
+
children: /* @__PURE__ */ jsx(ChevronNext, {})
|
|
422
|
+
})]
|
|
188
423
|
})]
|
|
189
424
|
}),
|
|
190
|
-
/* @__PURE__ */ jsx("div", {
|
|
425
|
+
strip ? /* @__PURE__ */ jsx(MonthStrip, { selection }) : /* @__PURE__ */ jsx("div", {
|
|
191
426
|
"data-slot": "calendar-months",
|
|
192
427
|
className: calendarMonthsVariants(),
|
|
193
428
|
children: Array.from({ length: visibleMonths }, (_, offset) => /* @__PURE__ */ jsxs("div", {
|
|
@@ -195,17 +430,9 @@ function CalendarBody({ visibleMonths, clearable, clearLabel, previousLabel, nex
|
|
|
195
430
|
children: [/* @__PURE__ */ jsx(CalendarHeading, {
|
|
196
431
|
offset: { months: offset },
|
|
197
432
|
className: calendarHeadingVariants()
|
|
198
|
-
}), /* @__PURE__ */
|
|
199
|
-
offset
|
|
200
|
-
|
|
201
|
-
children: [/* @__PURE__ */ jsx(CalendarGridHeader, { children: (weekday) => /* @__PURE__ */ jsx(CalendarHeaderCell, {
|
|
202
|
-
className: calendarHeaderCellVariants(),
|
|
203
|
-
children: weekday
|
|
204
|
-
}) }), /* @__PURE__ */ jsx(CalendarGridBody, { children: (date) => /* @__PURE__ */ jsx(CalendarCell, {
|
|
205
|
-
date,
|
|
206
|
-
"data-slot": "calendar-cell",
|
|
207
|
-
className: calendarCellVariants({ selection })
|
|
208
|
-
}) })]
|
|
433
|
+
}), /* @__PURE__ */ jsx(MonthGrid, {
|
|
434
|
+
offset,
|
|
435
|
+
selection
|
|
209
436
|
})]
|
|
210
437
|
}, offset))
|
|
211
438
|
}),
|
|
@@ -225,8 +452,9 @@ function CalendarBody({ visibleMonths, clearable, clearLabel, previousLabel, nex
|
|
|
225
452
|
* @example
|
|
226
453
|
* <Calendar label="Report date" value={date} onChange={setDate} clearable />
|
|
227
454
|
*/
|
|
228
|
-
|
|
455
|
+
const Calendar$1 = forwardRef(function Calendar$2({ className, label, labelHidden = false, visibleMonths = 1, clearable = false, clearLabel = "Clear", previousLabel = "Previous month", nextLabel = "Next month", ...props }, ref) {
|
|
229
456
|
return /* @__PURE__ */ jsxs(Calendar, {
|
|
457
|
+
ref,
|
|
230
458
|
...props,
|
|
231
459
|
"aria-label": label,
|
|
232
460
|
visibleDuration: { months: visibleMonths },
|
|
@@ -245,7 +473,7 @@ function Calendar$1({ className, label, labelHidden = false, visibleMonths = 1,
|
|
|
245
473
|
selection: "single"
|
|
246
474
|
})]
|
|
247
475
|
});
|
|
248
|
-
}
|
|
476
|
+
});
|
|
249
477
|
/**
|
|
250
478
|
* A calendar for picking a contiguous date range.
|
|
251
479
|
*
|
|
@@ -255,8 +483,9 @@ function Calendar$1({ className, label, labelHidden = false, visibleMonths = 1,
|
|
|
255
483
|
* <CalendarRange label="Period" visibleMonths={3}
|
|
256
484
|
* value={range} onChange={setRange} clearable />
|
|
257
485
|
*/
|
|
258
|
-
function CalendarRange({ className, label, labelHidden = false, visibleMonths = 1, clearable = false, clearLabel = "Clear", previousLabel = "Previous month", nextLabel = "Next month", ...props }) {
|
|
486
|
+
const CalendarRange = forwardRef(function CalendarRange({ className, label, labelHidden = false, visibleMonths = 1, clearable = false, clearLabel = "Clear", previousLabel = "Previous month", nextLabel = "Next month", ...props }, ref) {
|
|
259
487
|
return /* @__PURE__ */ jsxs(RangeCalendar, {
|
|
488
|
+
ref,
|
|
260
489
|
...props,
|
|
261
490
|
"aria-label": label,
|
|
262
491
|
visibleDuration: { months: visibleMonths },
|
|
@@ -275,8 +504,8 @@ function CalendarRange({ className, label, labelHidden = false, visibleMonths =
|
|
|
275
504
|
selection: "range"
|
|
276
505
|
})]
|
|
277
506
|
});
|
|
278
|
-
}
|
|
507
|
+
});
|
|
279
508
|
//#endregion
|
|
280
|
-
export { Calendar$1 as Calendar, CalendarRange, calendarCellVariants, calendarClearVariants, calendarGridVariants, calendarHeaderCellVariants, calendarHeaderVariants, calendarHeadingVariants, calendarLabelVariants, calendarMonthsVariants, calendarNavVariants, calendarVariants };
|
|
509
|
+
export { Calendar$1 as Calendar, CalendarRange, calendarCellVariants, calendarClearVariants, calendarGridVariants, calendarHeaderCellVariants, calendarHeaderVariants, calendarHeadingVariants, calendarLabelVariants, calendarMonthsVariants, calendarNavVariants, calendarTitleVariants, calendarVariants };
|
|
281
510
|
|
|
282
511
|
//# sourceMappingURL=calendar.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"calendar.js","names":["AriaButton","AriaCalendarHeading","AriaCalendarGrid","AriaCalendarGridHeader","AriaCalendarHeaderCell","AriaCalendarGridBody","AriaCalendarCell","Calendar","AriaCalendar","AriaRangeCalendar"],"sources":["../../src/calendar/calendar.tsx"],"sourcesContent":["\"use client\";\n\nimport type { DateValue } from \"@internationalized/date\";\nimport { cva } from \"class-variance-authority\";\nimport { useContext } from \"react\";\nimport {\n Button as AriaButton,\n Calendar as AriaCalendar,\n CalendarCell as AriaCalendarCell,\n CalendarGrid as AriaCalendarGrid,\n CalendarGridBody as AriaCalendarGridBody,\n CalendarGridHeader as AriaCalendarGridHeader,\n CalendarHeaderCell as AriaCalendarHeaderCell,\n CalendarHeading as AriaCalendarHeading,\n CalendarStateContext,\n RangeCalendar as AriaRangeCalendar,\n RangeCalendarStateContext,\n type CalendarProps as AriaCalendarProps,\n type RangeCalendarProps as AriaRangeCalendarProps,\n} from \"react-aria-components\";\n\nimport { cn } from \"../lib/cn.js\";\n\n/**\n * Calendar, built on React Aria's Calendar and RangeCalendar.\n *\n * Values are `DateValue` objects from `@internationalized/date`, NOT JS\n * `Date`. ADR 0006 names that package the one allowed public type dependency\n * precisely here: a calendar day has no time zone, so modelling it as a\n * timestamp is what costs you a day at a DST boundary. The import is\n * `import type` only — nothing at runtime needs a constructor from it, so the\n * package contributes zero bytes to the bundle.\n *\n * Every string below is a STATIC literal. Tailwind scans source text, so a\n * class assembled at runtime is invisible to it and would simply never be\n * emitted — the component would render unstyled, with no error anywhere.\n *\n * State comes from React Aria's data attributes rather than pseudo-classes:\n * `data-[focus-visible]` is keyboard focus only, and `data-[hovered]` /\n * `data-[pressed]` cover pointer, touch and keyboard uniformly.\n */\nexport const calendarVariants = cva([\n \"flex w-fit flex-col gap-(--density-gap) box-border\",\n \"font-sans text-sm leading-(--leading-normal) text-foreground\",\n]);\n\nexport const calendarLabelVariants = cva([\"text-sm font-medium text-foreground\"]);\n\nexport const calendarHeaderVariants = cva([\n \"flex items-center justify-between gap-(--density-control-gap)\",\n]);\n\n/**\n * The month/prev/next buttons.\n *\n * Deliberately NOT `buttonVariants` from ../button. That would put a\n * cross-component import in the bundle for one caller and six classes, and\n * DRY extracts at two callers, not one.\n */\nexport const calendarNavVariants = cva([\n \"inline-flex shrink-0 items-center justify-center\",\n \"size-(--density-control-h-sm) rounded-md\",\n // A library consumer may load no reset at all, so a bare <button> keeps its\n // user-agent border and ButtonFace grey without these two.\n \"border-(length:--border-width) border-transparent bg-transparent\",\n \"cursor-pointer select-none text-foreground outline-none\",\n \"[&_svg]:pointer-events-none [&_svg]:shrink-0\",\n \"[&_svg:not([class*='size-'])]:size-(--icon-sm)\",\n // The glyph is directional where the BEHAVIOUR is logical: React Aria maps\n // slot=\"previous\" to the correct month either way, so only the arrow flips.\n \"[&_svg]:rtl:-scale-x-100\",\n \"motion-safe:transition-colors motion-safe:duration-(--duration-fast) motion-safe:ease-standard\",\n \"data-[hovered]:bg-muted data-[pressed]:bg-muted\",\n \"data-[focus-visible]:outline-solid data-[focus-visible]:outline-(length:--focus-ring-width)\",\n \"data-[focus-visible]:outline-offset-(--focus-ring-offset) data-[focus-visible]:outline-(--color-ring)\",\n \"data-[disabled]:cursor-not-allowed data-[disabled]:opacity-(--opacity-disabled)\",\n]);\n\nexport const calendarMonthsVariants = cva([\n \"flex flex-col gap-(--density-gap) sm:flex-row sm:items-start\",\n]);\n\nexport const calendarHeadingVariants = cva([\n \"mb-1 text-center text-sm font-semibold text-foreground\",\n]);\n\nexport const calendarGridVariants = cva([\n // Without this a bare <table> falls back to user-agent border spacing and\n // the range band shows gaps between cells.\n \"border-collapse\",\n]);\n\nexport const calendarHeaderCellVariants = cva([\n \"w-(--density-control-h-sm) pb-1\",\n \"text-center text-2xs font-medium text-muted-foreground\",\n]);\n\nexport const calendarClearVariants = cva([\n \"self-end rounded-md px-2 py-1\",\n \"border-(length:--border-width) border-transparent bg-transparent\",\n \"cursor-pointer select-none text-sm text-muted-foreground outline-none\",\n \"motion-safe:transition-colors motion-safe:duration-(--duration-fast) motion-safe:ease-standard\",\n \"data-[hovered]:bg-muted data-[hovered]:text-foreground\",\n \"data-[focus-visible]:outline-solid data-[focus-visible]:outline-(length:--focus-ring-width)\",\n \"data-[focus-visible]:outline-offset-(--focus-ring-offset) data-[focus-visible]:outline-(--color-ring)\",\n]);\n\n/**\n * A day.\n *\n * Sized from `--density-control-h-sm` rather than a new\n * `--density-calendar-cell`: the density contract test requires every scope to\n * declare every token name, so a new one is three file edits — and this one is\n * already 30/36/42px, all clear of the 24px floor that WCAG 2.2 SC 2.5.8 sets.\n *\n * ARCHITECTURE section 5 rule 6 — no state is carried by colour alone, because\n * every author colour is replaced under forced-colors and the distinction\n * would vanish. Selected adds weight, the range ends add SHAPE, today is an\n * underline (not an outline, which would fight the focus ring) and unavailable\n * is a strikethrough.\n */\nexport const calendarCellVariants = cva(\n [\n \"flex items-center justify-center box-border\",\n \"size-(--density-control-h-sm) rounded-md\",\n \"text-sm leading-(--leading-normal) text-foreground\",\n \"cursor-pointer select-none outline-none\",\n \"motion-safe:transition-colors motion-safe:duration-(--duration-fast) motion-safe:ease-standard\",\n \"data-[hovered]:bg-muted\",\n \"data-[today]:font-semibold data-[today]:underline data-[today]:underline-offset-4\",\n \"data-[outside-month]:text-muted-foreground data-[outside-month]:opacity-(--opacity-disabled)\",\n // Unavailable dates stay FOCUSABLE, so ADR 0007 holds them to 4.5:1 — this\n // dims to muted-foreground, which the contrast contract grades, never below.\n \"data-[unavailable]:cursor-not-allowed data-[unavailable]:text-muted-foreground\",\n \"data-[unavailable]:line-through\",\n \"data-[disabled]:cursor-not-allowed data-[disabled]:opacity-(--opacity-disabled)\",\n \"data-[focus-visible]:outline-solid data-[focus-visible]:outline-(length:--focus-ring-width)\",\n \"data-[focus-visible]:outline-offset-(--focus-ring-offset) data-[focus-visible]:outline-(--color-ring)\",\n ],\n {\n variants: {\n /**\n * A variant axis rather than a boolean prop, because the two modes are\n * mutually exclusive visual treatments of the same element — which is\n * exactly what OCP asks a variant to model.\n */\n selection: {\n single: [\n \"data-[selected]:bg-primary data-[selected]:text-primary-foreground\",\n \"data-[selected]:font-semibold\",\n ],\n range: [\n // The band is `muted` — a pair the contrast contract already grades\n // at 4.5:1, so the range needs no new contrast-pairs.json entry.\n \"data-[selected]:rounded-none data-[selected]:bg-muted data-[selected]:text-foreground\",\n \"data-[selection-start]:rounded-s-md data-[selection-start]:bg-primary\",\n \"data-[selection-start]:font-semibold data-[selection-start]:text-primary-foreground\",\n \"data-[selection-end]:rounded-e-md data-[selection-end]:bg-primary\",\n \"data-[selection-end]:font-semibold data-[selection-end]:text-primary-foreground\",\n ],\n },\n },\n defaultVariants: { selection: \"single\" },\n },\n);\n\nfunction ChevronPrevious() {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" aria-hidden=\"true\">\n <path d=\"m15 18-6-6 6-6\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n );\n}\n\nfunction ChevronNext() {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" aria-hidden=\"true\">\n <path d=\"m9 18 6-6-6-6\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n );\n}\n\n/**\n * Resets the selection to null.\n *\n * It reads the calendar state from React Aria's context and calls\n * `setValue(null)`, which runs through `useControlledState` — so it fires\n * `onChange` for a controlled parent AND updates uncontrolled state, with no\n * mirrored state here. That is the whole reason there is no `onClear` prop:\n * from inside the provider tree the reset is free, and from outside it it\n * would force every consumer to own the value.\n *\n * The two states are narrowed separately rather than through a union, because\n * `setValue` has a different parameter type on each and the union call is not\n * assignable to either.\n *\n * `slot={null}` opts out of the Button context: inside a Calendar that context\n * carries the previous/next slots, and an unslotted Button would claim one.\n */\nfunction ClearButton({ label }: { label: string }) {\n const calendarState = useContext(CalendarStateContext);\n const rangeState = useContext(RangeCalendarStateContext);\n\n /*\n * Inherit the calendar's own inert states.\n *\n * Without this the Clear button stayed focusable and announced as enabled\n * inside an `isDisabled` calendar — every cell and both nav buttons were\n * inert, and one control in the middle of them was not. `isReadOnly` is the\n * same argument: \"the value is immutable\" has to include clearing it.\n */\n const state = calendarState ?? rangeState;\n const isInert = Boolean(state?.isDisabled ?? false) || Boolean(state?.isReadOnly ?? false);\n\n return (\n <AriaButton\n slot={null}\n data-slot=\"calendar-clear\"\n isDisabled={isInert}\n className={calendarClearVariants()}\n // Stays enabled when there is nothing to clear. Disabling it on press\n // moves focus to <body>, which silently strands a keyboard user mid-grid.\n onPress={() => {\n if (calendarState) calendarState.setValue(null);\n else rangeState?.setValue(null);\n }}\n >\n {label}\n </AriaButton>\n );\n}\n\ninterface CalendarBodyProps {\n visibleMonths: number;\n clearable: boolean;\n clearLabel: string;\n previousLabel: string;\n nextLabel: string;\n selection: \"single\" | \"range\";\n}\n\n/** Header, grids and Clear — identical under both calendar roots. */\nfunction CalendarBody({\n visibleMonths,\n clearable,\n clearLabel,\n previousLabel,\n nextLabel,\n selection,\n}: CalendarBodyProps) {\n return (\n <>\n <header data-slot=\"calendar-header\" className={calendarHeaderVariants()}>\n <AriaButton slot=\"previous\" aria-label={previousLabel} className={calendarNavVariants()}>\n <ChevronPrevious />\n </AriaButton>\n <AriaButton slot=\"next\" aria-label={nextLabel} className={calendarNavVariants()}>\n <ChevronNext />\n </AriaButton>\n </header>\n\n <div data-slot=\"calendar-months\" className={calendarMonthsVariants()}>\n {Array.from({ length: visibleMonths }, (_, offset) => (\n <div key={offset} data-slot=\"calendar-month\">\n {/* Per grid, so three months are three named columns rather than\n one combined range nobody can map back to a column. */}\n <AriaCalendarHeading\n offset={{ months: offset }}\n className={calendarHeadingVariants()}\n />\n <AriaCalendarGrid offset={{ months: offset }} className={calendarGridVariants()}>\n <AriaCalendarGridHeader>\n {(weekday) => (\n <AriaCalendarHeaderCell className={calendarHeaderCellVariants()}>\n {weekday}\n </AriaCalendarHeaderCell>\n )}\n </AriaCalendarGridHeader>\n <AriaCalendarGridBody>\n {(date) => (\n <AriaCalendarCell\n date={date}\n data-slot=\"calendar-cell\"\n className={calendarCellVariants({ selection })}\n />\n )}\n </AriaCalendarGridBody>\n </AriaCalendarGrid>\n </div>\n ))}\n </div>\n\n {clearable ? <ClearButton label={clearLabel} /> : null}\n </>\n );\n}\n\ninterface CalendarSharedProps {\n /**\n * Accessible name for the calendar.\n *\n * REQUIRED. React Aria renders the root as `role=\"application\"`, which has\n * no implicit name, so without this every calendar announces as an unnamed\n * application — the same finding that made `label` required on Select,\n * Progress, Slider and ScrollArea.\n */\n label: string;\n /**\n * Hide the label visually while leaving it on the accessibility tree. Pass\n * this when the surrounding UI already names the control.\n *\n * @default false\n */\n labelHidden?: boolean;\n /**\n * Number of months displayed side by side. Maps to React Aria's\n * `visibleDuration`, which is omitted from the public surface so the two\n * cannot disagree.\n *\n * @default 1\n */\n visibleMonths?: number;\n /**\n * Render a Clear button that resets the selection to `null`.\n *\n * Works controlled and uncontrolled: the button calls React Aria's\n * `setValue(null)` through context, so `onChange` fires either way and there\n * is no `onClear` for a consumer to wire up.\n *\n * @default false\n */\n clearable?: boolean;\n /**\n * Visible text of the Clear button.\n *\n * A prop rather than a literal because `ARCHITECTURE.md` §7 rule 9 forbids\n * hard-coded user-visible strings and says it cannot be retrofitted.\n * `useMessages()` does not exist yet, so this follows Dialog's `closeLabel`.\n *\n * @default \"Clear\"\n */\n clearLabel?: string;\n /**\n * Accessible name for the previous-month button, which is icon-only. Same\n * reasoning as {@link CalendarSharedProps.clearLabel}.\n *\n * @default \"Previous month\"\n */\n previousLabel?: string;\n /**\n * Accessible name for the next-month button. Same reasoning as\n * {@link CalendarSharedProps.clearLabel}.\n *\n * @default \"Next month\"\n */\n nextLabel?: string;\n /** Extra classes. Merged last through `cn()`, so the consumer wins. */\n className?: string;\n}\n\n/**\n * Props for {@link Calendar}.\n *\n * Extends the React Aria type via `Omit` rather than\n * `ComponentPropsWithoutRef`, matching every other React Aria-backed component\n * here and recorded in ADR 0008. Intersecting would advertise DOM props that\n * React Aria ignores silently.\n */\nexport interface CalendarProps\n extends Omit<\n AriaCalendarProps<DateValue>,\n \"className\" | \"style\" | \"children\" | \"visibleDuration\"\n >,\n CalendarSharedProps {}\n\n/** Props for {@link CalendarRange}. */\nexport interface CalendarRangeProps\n extends Omit<\n AriaRangeCalendarProps<DateValue>,\n \"className\" | \"style\" | \"children\" | \"visibleDuration\"\n >,\n CalendarSharedProps {}\n\n/**\n * A calendar for picking a single date.\n *\n * Maturity: **experimental**. `ARCHITECTURE.md` §7 rule 8's metadata mechanism\n * does not exist yet, and ADR 0006 blocks `stable` until a WebKit test\n * instance lands regardless.\n *\n * `onChange` hands back a `DateValue`; `String(value)` is its `YYYY-MM-DD`\n * form, which is what an API filter or query parameter wants.\n *\n * @example\n * <Calendar label=\"Report date\" value={date} onChange={setDate} clearable />\n */\nexport function Calendar({\n className,\n label,\n labelHidden = false,\n visibleMonths = 1,\n clearable = false,\n clearLabel = \"Clear\",\n previousLabel = \"Previous month\",\n nextLabel = \"Next month\",\n ...props\n}: CalendarProps) {\n return (\n <AriaCalendar\n {...props}\n aria-label={label}\n visibleDuration={{ months: visibleMonths }}\n data-slot=\"calendar\"\n className={cn(calendarVariants(), className)}\n >\n {labelHidden ? null : (\n <span data-slot=\"calendar-label\" className={calendarLabelVariants()}>\n {label}\n </span>\n )}\n <CalendarBody\n visibleMonths={visibleMonths}\n clearable={clearable}\n clearLabel={clearLabel}\n previousLabel={previousLabel}\n nextLabel={nextLabel}\n selection=\"single\"\n />\n </AriaCalendar>\n );\n}\n\n/**\n * A calendar for picking a contiguous date range.\n *\n * `onChange` hands back `{ start, end }`, both `DateValue`.\n *\n * @example\n * <CalendarRange label=\"Period\" visibleMonths={3}\n * value={range} onChange={setRange} clearable />\n */\nexport function CalendarRange({\n className,\n label,\n labelHidden = false,\n visibleMonths = 1,\n clearable = false,\n clearLabel = \"Clear\",\n previousLabel = \"Previous month\",\n nextLabel = \"Next month\",\n ...props\n}: CalendarRangeProps) {\n return (\n <AriaRangeCalendar\n {...props}\n aria-label={label}\n visibleDuration={{ months: visibleMonths }}\n data-slot=\"calendar\"\n className={cn(calendarVariants(), className)}\n >\n {labelHidden ? null : (\n <span data-slot=\"calendar-label\" className={calendarLabelVariants()}>\n {label}\n </span>\n )}\n <CalendarBody\n visibleMonths={visibleMonths}\n clearable={clearable}\n clearLabel={clearLabel}\n previousLabel={previousLabel}\n nextLabel={nextLabel}\n selection=\"range\"\n />\n </AriaRangeCalendar>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"calendar.js","names":["AriaButton","AriaCalendarGrid","AriaCalendarGridHeader","AriaCalendarHeaderCell","AriaCalendarGridBody","AriaCalendarCell","AriaCalendarHeading","Calendar","AriaCalendar","AriaRangeCalendar"],"sources":["../../src/calendar/calendar.tsx"],"sourcesContent":["\"use client\";\n\nimport type { DateValue } from \"@internationalized/date\";\nimport { cva } from \"class-variance-authority\";\nimport {\n forwardRef,\n useContext,\n useRef,\n useState,\n type CSSProperties,\n} from \"react\";\nimport {\n Button as AriaButton,\n Calendar as AriaCalendar,\n CalendarCell as AriaCalendarCell,\n CalendarGrid as AriaCalendarGrid,\n CalendarGridBody as AriaCalendarGridBody,\n CalendarGridHeader as AriaCalendarGridHeader,\n CalendarHeaderCell as AriaCalendarHeaderCell,\n CalendarHeading as AriaCalendarHeading,\n CalendarStateContext,\n RangeCalendar as AriaRangeCalendar,\n RangeCalendarStateContext,\n type CalendarProps as AriaCalendarProps,\n type RangeCalendarProps as AriaRangeCalendarProps,\n} from \"react-aria-components\";\n\nimport { cn } from \"../lib/cn.js\";\nimport { useIsomorphicLayoutEffect } from \"../lib/motion.js\";\nimport { SwapText } from \"../lib/swap-text.js\";\n\n/**\n * Calendar, built on React Aria's Calendar and RangeCalendar.\n *\n * Values are `DateValue` objects from `@internationalized/date`, NOT JS\n * `Date`. ADR 0006 names that package the one allowed public type dependency\n * precisely here: a calendar day has no time zone, so modelling it as a\n * timestamp is what costs you a day at a DST boundary. The import is\n * `import type` only — nothing at runtime needs a constructor from it, so the\n * package contributes zero bytes to the bundle.\n *\n * Every string below is a STATIC literal. Tailwind scans source text, so a\n * class assembled at runtime is invisible to it and would simply never be\n * emitted — the component would render unstyled, with no error anywhere.\n *\n * State comes from React Aria's data attributes rather than pseudo-classes:\n * `data-[focus-visible]` is keyboard focus only, and `data-[hovered]` /\n * `data-[pressed]` cover pointer, touch and keyboard uniformly.\n */\nexport const calendarVariants = cva([\n \"flex w-fit flex-col gap-(--density-gap) box-border\",\n \"font-sans text-sm leading-(--leading-normal) text-foreground\",\n]);\n\nexport const calendarLabelVariants = cva([\"text-sm font-medium text-foreground\"]);\n\nexport const calendarHeaderVariants = cva([\n \"flex items-center justify-between gap-(--density-control-gap)\",\n]);\n\n/**\n * The month/prev/next buttons.\n *\n * Deliberately NOT `buttonVariants` from ../button. That would put a\n * cross-component import in the bundle for one caller and six classes, and\n * DRY extracts at two callers, not one.\n */\nexport const calendarNavVariants = cva([\n \"inline-flex shrink-0 items-center justify-center\",\n \"size-(--density-control-h-sm) rounded-md\",\n // A library consumer may load no reset at all, so a bare <button> keeps its\n // user-agent border and ButtonFace grey without these two.\n \"border-(length:--border-width) border-transparent bg-transparent\",\n \"cursor-pointer select-none text-foreground outline-none\",\n \"[&_svg]:pointer-events-none [&_svg]:shrink-0\",\n \"[&_svg:not([class*='size-'])]:size-(--icon-sm)\",\n // The glyph is directional where the BEHAVIOUR is logical: React Aria maps\n // slot=\"previous\" to the correct month either way, so only the arrow flips.\n \"[&_svg]:rtl:-scale-x-100\",\n // Fill and colour ease in over 160ms; the press shrinks to .96 and springs back.\n \"calendar-nav-motion\",\n \"data-[hovered]:bg-muted data-[pressed]:bg-muted\",\n \"data-[focus-visible]:outline-solid data-[focus-visible]:outline-(length:--focus-ring-width)\",\n \"data-[focus-visible]:outline-offset-(--focus-ring-offset) data-[focus-visible]:outline-(--color-ring)\",\n \"data-[disabled]:cursor-not-allowed data-[disabled]:opacity-(--opacity-disabled)\",\n]);\n\nexport const calendarMonthsVariants = cva([\n \"flex flex-col gap-(--density-gap) sm:flex-row sm:items-start\",\n]);\n\nexport const calendarHeadingVariants = cva([\n \"mb-1 text-center text-sm font-semibold text-foreground\",\n]);\n\n/** The month title of a one-month calendar, in the header beside the buttons. */\nexport const calendarTitleVariants = cva([\n \"min-w-0 flex-1 text-start text-sm font-semibold text-foreground tabular-nums whitespace-nowrap\",\n]);\n\nexport const calendarGridVariants = cva([\n // Without this a bare <table> falls back to user-agent border spacing and\n // the range band shows gaps between cells.\n \"border-collapse\",\n]);\n\nexport const calendarHeaderCellVariants = cva([\n \"w-(--density-control-h-sm) pb-1\",\n \"text-center text-2xs font-medium text-muted-foreground\",\n]);\n\nexport const calendarClearVariants = cva([\n \"self-end rounded-md px-2 py-1\",\n \"border-(length:--border-width) border-transparent bg-transparent\",\n \"cursor-pointer select-none text-sm text-muted-foreground outline-none\",\n \"motion-safe:transition-colors motion-safe:duration-(--duration-fast) motion-safe:ease-standard\",\n \"data-[hovered]:bg-muted data-[hovered]:text-foreground\",\n \"data-[focus-visible]:outline-solid data-[focus-visible]:outline-(length:--focus-ring-width)\",\n \"data-[focus-visible]:outline-offset-(--focus-ring-offset) data-[focus-visible]:outline-(--color-ring)\",\n]);\n\n/**\n * A day.\n *\n * Sized from `--density-control-h-sm` rather than a new\n * `--density-calendar-cell`: the density contract test requires every scope to\n * declare every token name, so a new one is three file edits — and this one is\n * already 30/36/42px, all clear of the 24px floor that WCAG 2.2 SC 2.5.8 sets.\n *\n * ARCHITECTURE section 5 rule 6 — no state is carried by colour alone, because\n * every author colour is replaced under forced-colors and the distinction\n * would vanish. Selected adds weight, the range ends add SHAPE, today is an\n * underline (not an outline, which would fight the focus ring) and unavailable\n * is a strikethrough.\n */\nexport const calendarCellVariants = cva(\n [\n \"flex items-center justify-center box-border\",\n \"size-(--density-control-h-sm) rounded-md\",\n \"text-sm leading-(--leading-normal) text-foreground\",\n \"cursor-pointer select-none outline-none\",\n // Above the selection disc that glides beneath it. Colour, fill and the press\n // scale are one utility; --number-delay lets the number flip as the disc passes.\n \"relative z-10 calendar-day\",\n \"data-[hovered]:not-data-[selected]:bg-muted\",\n \"data-[today]:font-semibold data-[today]:underline data-[today]:underline-offset-4\",\n \"data-[outside-month]:text-muted-foreground data-[outside-month]:opacity-(--opacity-disabled)\",\n // Unavailable dates stay FOCUSABLE, so ADR 0007 holds them to 4.5:1 — this\n // dims to muted-foreground, which the contrast contract grades, never below.\n \"data-[unavailable]:cursor-not-allowed data-[unavailable]:text-muted-foreground\",\n \"data-[unavailable]:line-through\",\n \"data-[disabled]:cursor-not-allowed data-[disabled]:opacity-(--opacity-disabled)\",\n \"data-[focus-visible]:outline-solid data-[focus-visible]:outline-(length:--focus-ring-width)\",\n \"data-[focus-visible]:outline-offset-(--focus-ring-offset) data-[focus-visible]:outline-(--color-ring)\",\n ],\n {\n variants: {\n /**\n * A variant axis rather than a boolean prop, because the two modes are\n * mutually exclusive visual treatments of the same element — which is\n * exactly what OCP asks a variant to model.\n */\n selection: {\n single: [\n // The fill is the disc under the cell, not the cell: it glides between days.\n \"data-[selected]:text-primary-foreground\",\n \"data-[selected]:font-semibold\",\n ],\n range: [\n // The band is `muted` — a pair the contrast contract already grades\n // at 4.5:1, so the range needs no new contrast-pairs.json entry.\n \"data-[selected]:rounded-none data-[selected]:bg-muted data-[selected]:text-foreground\",\n \"data-[selection-start]:rounded-s-md data-[selection-start]:bg-primary\",\n \"data-[selection-start]:font-semibold data-[selection-start]:text-primary-foreground\",\n \"data-[selection-end]:rounded-e-md data-[selection-end]:bg-primary\",\n \"data-[selection-end]:font-semibold data-[selection-end]:text-primary-foreground\",\n ],\n /**\n * The range picker's own look: the band and the ends are drawn beneath the\n * cells by the picker, which slides and stretches them, so the cells paint\n * only their text (and the shorter press, .9 in 120ms).\n */\n band: [\n \"[--press-scale:0.9] [--press-time:120ms]\",\n \"data-[selected]:not-data-[selection-start]:not-data-[selection-end]:text-foreground\",\n \"data-[selection-start]:font-medium data-[selection-start]:text-primary-foreground data-[selection-start]:[--number-delay:40ms]\",\n \"data-[selection-end]:font-medium data-[selection-end]:text-primary-foreground data-[selection-end]:[--number-delay:40ms]\",\n ],\n },\n },\n defaultVariants: { selection: \"single\" },\n },\n);\n\nfunction ChevronPrevious() {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" aria-hidden=\"true\">\n <path d=\"m15 18-6-6 6-6\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n );\n}\n\nfunction ChevronNext() {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" aria-hidden=\"true\">\n <path d=\"m9 18 6-6-6-6\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n );\n}\n\n/**\n * Resets the selection to null.\n *\n * It reads the calendar state from React Aria's context and calls\n * `setValue(null)`, which runs through `useControlledState` — so it fires\n * `onChange` for a controlled parent AND updates uncontrolled state, with no\n * mirrored state here. That is the whole reason there is no `onClear` prop:\n * from inside the provider tree the reset is free, and from outside it it\n * would force every consumer to own the value.\n *\n * The two states are narrowed separately rather than through a union, because\n * `setValue` has a different parameter type on each and the union call is not\n * assignable to either.\n *\n * `slot={null}` opts out of the Button context: inside a Calendar that context\n * carries the previous/next slots, and an unslotted Button would claim one.\n */\nfunction ClearButton({ label }: { label: string }) {\n const calendarState = useContext(CalendarStateContext);\n const rangeState = useContext(RangeCalendarStateContext);\n\n /*\n * Inherit the calendar's own inert states.\n *\n * Without this the Clear button stayed focusable and announced as enabled\n * inside an `isDisabled` calendar — every cell and both nav buttons were\n * inert, and one control in the middle of them was not. `isReadOnly` is the\n * same argument: \"the value is immutable\" has to include clearing it.\n */\n const state = calendarState ?? rangeState;\n const isInert = Boolean(state?.isDisabled ?? false) || Boolean(state?.isReadOnly ?? false);\n\n return (\n <AriaButton\n slot={null}\n data-slot=\"calendar-clear\"\n isDisabled={isInert}\n className={calendarClearVariants()}\n // Stays enabled when there is nothing to clear. Disabling it on press\n // moves focus to <body>, which silently strands a keyboard user mid-grid.\n onPress={() => {\n if (calendarState) calendarState.setValue(null);\n else rangeState?.setValue(null);\n }}\n >\n {label}\n </AriaButton>\n );\n}\n\ninterface CalendarBodyProps {\n visibleMonths: number;\n clearable: boolean;\n clearLabel: string;\n previousLabel: string;\n nextLabel: string;\n selection: \"single\" | \"range\";\n}\n\n/** The month's rows, headers and cells: one grid for the month `offset` months from the first visible one. */\nfunction MonthGrid({ offset, selection }: { offset: number; selection: \"single\" | \"range\" }) {\n return (\n <AriaCalendarGrid offset={{ months: offset }} className={calendarGridVariants()}>\n <AriaCalendarGridHeader>\n {(weekday) => (\n <AriaCalendarHeaderCell className={calendarHeaderCellVariants()}>\n {weekday}\n </AriaCalendarHeaderCell>\n )}\n </AriaCalendarGridHeader>\n <AriaCalendarGridBody>\n {(date) => (\n <AriaCalendarCell\n date={date}\n data-slot=\"calendar-cell\"\n className={calendarCellVariants({ selection })}\n />\n )}\n </AriaCalendarGridBody>\n </AriaCalendarGrid>\n );\n}\n\n/** The first visible day, from whichever root we are under. */\nfunction useVisibleStart() {\n const single = useContext(CalendarStateContext);\n const range = useContext(RangeCalendarStateContext);\n return (single ?? range)?.visibleRange.start;\n}\n\n/**\n * The month title. React Aria's own heading stays, visually hidden, as the text;\n * the copy the eye sees crosses in place: the new month arrives from the side the\n * strip travels to while the old one leaves toward the other. Nothing animates on\n * first mount.\n */\nfunction MonthTitle() {\n const start = useVisibleStart();\n const headingRef = useRef<HTMLHeadingElement>(null);\n const [text, setText] = useState(\"\");\n const [shown, setShown] = useState(start);\n const [dir, setDir] = useState(1);\n if (start && shown && start.compare(shown) !== 0) {\n setShown(start);\n setDir(start.compare(shown) > 0 ? 1 : -1);\n }\n useIsomorphicLayoutEffect(() => {\n const next = headingRef.current?.textContent ?? \"\";\n if (next !== text) setText(next);\n });\n return (\n <>\n <AriaCalendarHeading ref={headingRef} className=\"sr-only\" />\n <span aria-hidden=\"true\" data-slot=\"calendar-title\" className={calendarTitleVariants()}>\n {/* The text is read from the heading a render after the first, so the first text is a fresh swap, not a change. */}\n <SwapText key={text === \"\" ? \"boot\" : \"live\"} swapKey={text} dir={dir} motion=\"slide\" className=\"block\">\n {text}\n </SwapText>\n </span>\n </>\n );\n}\n\n/** A day cell's place in its month's grid, read from the table's structure: no layout is forced. */\nfunction gridPlace(cell: HTMLElement) {\n const td = cell.closest(\"td\");\n const tr = td?.parentElement as HTMLTableRowElement | null | undefined;\n return td && tr ? { col: td.cellIndex, row: tr.sectionRowIndex } : null;\n}\n\ninterface DiscMemory {\n cell: HTMLElement;\n col: number;\n row: number;\n}\n\n/**\n * Drives the selected disc of every month. The disc is one element under the day\n * cells, placed from the selected cell's measured box, so it glides on a straight\n * line between any two days, keeps its place while the strip slides, and only\n * grows in or fades out when the selection enters or leaves a month. Each number\n * flips colour as the disc actually passes it: the day it lands on waits longer on\n * long hops, the day it leaves waits longer on short ones.\n *\n * It is one component, first in the tree, because order matters: the colour\n * transitions start at the first style recalculation after a cell's state\n * changes, and anything that measures the page (the title's swap does, on every\n * commit) forces one. So every delay is set from the table's structure before any\n * box is measured, and it runs before the header's effects do.\n */\nfunction DiscDriver() {\n const marker = useRef<HTMLSpanElement>(null);\n const memory = useRef(new WeakMap<HTMLElement, DiscMemory>());\n // Subscribing re-renders the driver when the selection, the month or the focus changes.\n useContext(CalendarStateContext);\n useIsomorphicLayoutEffect(() => {\n const root = marker.current?.parentElement;\n if (!root) return;\n const panes = [...root.querySelectorAll<HTMLElement>('[data-slot=\"calendar-month\"]')];\n const work = panes.flatMap((pane) => {\n const el = pane.querySelector<HTMLElement>(':scope > [data-slot=\"calendar-disc\"]');\n if (!el) return [];\n const cell = pane.querySelector<HTMLElement>('[data-slot=\"calendar-cell\"][data-selected]');\n return [{ pane, el, cell }];\n });\n // Pass 1, no layout reads: the number delays.\n for (const { el, cell } of work) {\n if (!cell) continue;\n const place = gridPlace(cell);\n const before = memory.current.get(el);\n if (el.dataset.visible === undefined || !before || before.cell === cell || !place) continue;\n const distance = Math.hypot(place.col - before.col, place.row - before.row);\n if (distance === 0) continue;\n cell.style.setProperty(\n \"--number-delay\",\n `${Math.round(Math.min(260, 95 + 85 * Math.log(distance)))}ms`,\n );\n if (before.cell.isConnected)\n before.cell.style.setProperty(\n \"--number-delay\",\n `${Math.round(Math.max(20, 130 / distance))}ms`,\n );\n }\n // Pass 2: place the discs.\n for (const { pane, el, cell } of work) {\n if (!cell) {\n delete el.dataset.visible;\n memory.current.delete(el);\n continue;\n }\n const box = cell.getBoundingClientRect();\n const paneBox = pane.getBoundingClientRect();\n // A pressed cell is scaled about its centre; offsetWidth is the unscaled box.\n const x = box.left - paneBox.left - (box.width - cell.offsetWidth) / 2;\n const y = box.top - paneBox.top - (box.height - cell.offsetHeight) / 2;\n el.style.width = `${cell.offsetWidth}px`;\n el.style.height = `${cell.offsetHeight}px`;\n if (el.dataset.visible === undefined) {\n // Arriving in this month: land in place, then grow in.\n el.style.transition = \"none\";\n el.style.translate = `${x}px ${y}px`;\n void el.offsetWidth;\n el.style.transition = \"\";\n el.dataset.visible = \"\";\n } else {\n el.style.translate = `${x}px ${y}px`;\n }\n const place = gridPlace(cell);\n if (place) memory.current.set(el, { cell, ...place });\n }\n });\n return <span ref={marker} hidden data-slot=\"calendar-disc-driver\" />;\n}\n\n/** The disc itself: an empty shell the driver places. */\nfunction SelectionDisc() {\n return (\n <span aria-hidden=\"true\" data-slot=\"calendar-disc\" className=\"calendar-disc\">\n <span className=\"calendar-disc-fill\" />\n </span>\n );\n}\n\n/**\n * One month of the strip. Months sit side by side in a clipped window and slide\n * on a spring; the pane that is not the current month fades back and is inert.\n */\nfunction MonthPane({\n offset,\n dir,\n fresh,\n disc,\n selection,\n}: {\n offset: number;\n dir: number;\n fresh: boolean;\n disc: boolean;\n selection: \"single\" | \"range\";\n}) {\n return (\n <div\n ref={(node) => {\n if (!node) return;\n if (offset === 0) node.removeAttribute(\"inert\");\n else node.setAttribute(\"inert\", \"\");\n }}\n data-slot=\"calendar-month\"\n data-offset={offset}\n aria-hidden={offset === 0 ? undefined : true}\n style={{ \"--k\": offset, \"--dir\": dir } as CSSProperties}\n className={cn(\"calendar-pane\", fresh && \"motion-safe:animate-calendar-pane-in\")}\n >\n {disc ? <SelectionDisc /> : null}\n <MonthGrid offset={offset} selection={selection} />\n </div>\n );\n}\n\n/**\n * One month, shown with its neighbours beside it on a strip. Moving by a month\n * slides the strip; a jump of more than a month brings the new month in from one\n * month away instead of scrolling through the ones between.\n */\nfunction MonthStrip({ selection }: { selection: \"single\" | \"range\" }) {\n const start = useVisibleStart();\n const [shown, setShown] = useState(start);\n const [dir, setDir] = useState(1);\n const [fresh, setFresh] = useState<string | null>(null);\n const strip = useRef<HTMLDivElement>(null);\n // The window is as tall as the month in view, and follows it when a month has more\n // or fewer weeks than the last, so the calendar never leaves a gap or clips a row.\n useIsomorphicLayoutEffect(() => {\n const el = strip.current;\n const current = el?.querySelector<HTMLElement>('[data-offset=\"0\"]');\n if (el && current) el.style.height = `${current.offsetHeight}px`;\n });\n const keyOf = (offset: number) => {\n const d = start?.add({ months: offset });\n return d ? `${d.era}-${d.year}-${d.month}` : String(offset);\n };\n if (start && shown && start.compare(shown) !== 0) {\n const months = (start.year - shown.year) * 12 + (start.month - shown.month);\n setShown(start);\n setDir(months > 0 ? 1 : -1);\n setFresh(Math.abs(months) > 1 ? keyOf(0) : null);\n }\n return (\n <div ref={strip} data-slot=\"calendar-months\" className=\"calendar-strip\">\n {[-1, 0, 1].map((offset) => (\n <MonthPane\n key={keyOf(offset)}\n offset={offset}\n dir={dir}\n fresh={fresh === keyOf(offset) && offset === 0}\n disc={selection === \"single\"}\n selection={selection}\n />\n ))}\n </div>\n );\n}\n\n/** Header, grids and Clear — identical under both calendar roots. */\nfunction CalendarBody({\n visibleMonths,\n clearable,\n clearLabel,\n previousLabel,\n nextLabel,\n selection,\n}: CalendarBodyProps) {\n // One month shows as a strip with its title in the header; several months stay side by side.\n const strip = visibleMonths === 1;\n return (\n <>\n {strip && selection === \"single\" ? <DiscDriver /> : null}\n <header data-slot=\"calendar-header\" className={calendarHeaderVariants()}>\n {strip ? <MonthTitle /> : null}\n <div className=\"ms-auto flex items-center gap-0.5\">\n <AriaButton slot=\"previous\" aria-label={previousLabel} className={calendarNavVariants()}>\n <ChevronPrevious />\n </AriaButton>\n <AriaButton slot=\"next\" aria-label={nextLabel} className={calendarNavVariants()}>\n <ChevronNext />\n </AriaButton>\n </div>\n </header>\n\n {strip ? (\n <MonthStrip selection={selection} />\n ) : (\n <div data-slot=\"calendar-months\" className={calendarMonthsVariants()}>\n {Array.from({ length: visibleMonths }, (_, offset) => (\n <div key={offset} data-slot=\"calendar-month\">\n {/* Per grid, so three months are three named columns rather than\n one combined range nobody can map back to a column. */}\n <AriaCalendarHeading\n offset={{ months: offset }}\n className={calendarHeadingVariants()}\n />\n <MonthGrid offset={offset} selection={selection} />\n </div>\n ))}\n </div>\n )}\n\n {clearable ? <ClearButton label={clearLabel} /> : null}\n </>\n );\n}\n\ninterface CalendarSharedProps {\n /**\n * Accessible name for the calendar.\n *\n * REQUIRED. React Aria renders the root as `role=\"application\"`, which has\n * no implicit name, so without this every calendar announces as an unnamed\n * application — the same finding that made `label` required on Select,\n * Progress, Slider and ScrollArea.\n */\n label: string;\n /**\n * Hide the label visually while leaving it on the accessibility tree. Pass\n * this when the surrounding UI already names the control.\n *\n * @default false\n */\n labelHidden?: boolean;\n /**\n * Number of months displayed side by side. Maps to React Aria's\n * `visibleDuration`, which is omitted from the public surface so the two\n * cannot disagree.\n *\n * @default 1\n */\n visibleMonths?: number;\n /**\n * Render a Clear button that resets the selection to `null`.\n *\n * Works controlled and uncontrolled: the button calls React Aria's\n * `setValue(null)` through context, so `onChange` fires either way and there\n * is no `onClear` for a consumer to wire up.\n *\n * @default false\n */\n clearable?: boolean;\n /**\n * Visible text of the Clear button.\n *\n * A prop rather than a literal because `ARCHITECTURE.md` §7 rule 9 forbids\n * hard-coded user-visible strings and says it cannot be retrofitted.\n * `useMessages()` does not exist yet, so this follows Dialog's `closeLabel`.\n *\n * @default \"Clear\"\n */\n clearLabel?: string;\n /**\n * Accessible name for the previous-month button, which is icon-only. Same\n * reasoning as {@link CalendarSharedProps.clearLabel}.\n *\n * @default \"Previous month\"\n */\n previousLabel?: string;\n /**\n * Accessible name for the next-month button. Same reasoning as\n * {@link CalendarSharedProps.clearLabel}.\n *\n * @default \"Next month\"\n */\n nextLabel?: string;\n /** Extra classes. Merged last through `cn()`, so the consumer wins. */\n className?: string;\n}\n\n/**\n * Props for {@link Calendar}.\n *\n * Extends the React Aria type via `Omit` rather than\n * `ComponentPropsWithoutRef`, matching every other React Aria-backed component\n * here and recorded in ADR 0008. Intersecting would advertise DOM props that\n * React Aria ignores silently.\n */\nexport interface CalendarProps\n extends Omit<\n AriaCalendarProps<DateValue>,\n \"className\" | \"style\" | \"children\" | \"visibleDuration\"\n >,\n CalendarSharedProps {}\n\n/** Props for {@link CalendarRange}. */\nexport interface CalendarRangeProps\n extends Omit<\n AriaRangeCalendarProps<DateValue>,\n \"className\" | \"style\" | \"children\" | \"visibleDuration\"\n >,\n CalendarSharedProps {}\n\n/**\n * A calendar for picking a single date.\n *\n * Maturity: **experimental**. `ARCHITECTURE.md` §7 rule 8's metadata mechanism\n * does not exist yet, and ADR 0006 blocks `stable` until a WebKit test\n * instance lands regardless.\n *\n * `onChange` hands back a `DateValue`; `String(value)` is its `YYYY-MM-DD`\n * form, which is what an API filter or query parameter wants.\n *\n * @example\n * <Calendar label=\"Report date\" value={date} onChange={setDate} clearable />\n */\nexport const Calendar = forwardRef<HTMLDivElement, CalendarProps>(function Calendar(\n {\n className,\n label,\n labelHidden = false,\n visibleMonths = 1,\n clearable = false,\n clearLabel = \"Clear\",\n previousLabel = \"Previous month\",\n nextLabel = \"Next month\",\n ...props\n },\n ref,\n) {\n return (\n <AriaCalendar\n ref={ref}\n {...props}\n aria-label={label}\n visibleDuration={{ months: visibleMonths }}\n data-slot=\"calendar\"\n className={cn(calendarVariants(), className)}\n >\n {labelHidden ? null : (\n <span data-slot=\"calendar-label\" className={calendarLabelVariants()}>\n {label}\n </span>\n )}\n <CalendarBody\n visibleMonths={visibleMonths}\n clearable={clearable}\n clearLabel={clearLabel}\n previousLabel={previousLabel}\n nextLabel={nextLabel}\n selection=\"single\"\n />\n </AriaCalendar>\n );\n});\n\n/**\n * A calendar for picking a contiguous date range.\n *\n * `onChange` hands back `{ start, end }`, both `DateValue`.\n *\n * @example\n * <CalendarRange label=\"Period\" visibleMonths={3}\n * value={range} onChange={setRange} clearable />\n */\nexport const CalendarRange = forwardRef<HTMLDivElement, CalendarRangeProps>(function CalendarRange(\n {\n className,\n label,\n labelHidden = false,\n visibleMonths = 1,\n clearable = false,\n clearLabel = \"Clear\",\n previousLabel = \"Previous month\",\n nextLabel = \"Next month\",\n ...props\n },\n ref,\n) {\n return (\n <AriaRangeCalendar\n ref={ref}\n {...props}\n aria-label={label}\n visibleDuration={{ months: visibleMonths }}\n data-slot=\"calendar\"\n className={cn(calendarVariants(), className)}\n >\n {labelHidden ? null : (\n <span data-slot=\"calendar-label\" className={calendarLabelVariants()}>\n {label}\n </span>\n )}\n <CalendarBody\n visibleMonths={visibleMonths}\n clearable={clearable}\n clearLabel={clearLabel}\n previousLabel={previousLabel}\n nextLabel={nextLabel}\n selection=\"range\"\n />\n </AriaRangeCalendar>\n );\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDA,MAAa,mBAAmB,IAAI,CAClC,sDACA,8DACF,CAAC;AAED,MAAa,wBAAwB,IAAI,CAAC,qCAAqC,CAAC;AAEhF,MAAa,yBAAyB,IAAI,CACxC,+DACF,CAAC;;;;;;;;AASD,MAAa,sBAAsB,IAAI;CACrC;CACA;CAGA;CACA;CACA;CACA;CAGA;CAEA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,MAAa,yBAAyB,IAAI,CACxC,8DACF,CAAC;AAED,MAAa,0BAA0B,IAAI,CACzC,wDACF,CAAC;;AAGD,MAAa,wBAAwB,IAAI,CACvC,gGACF,CAAC;AAED,MAAa,uBAAuB,IAAI,CAGtC,iBACF,CAAC;AAED,MAAa,6BAA6B,IAAI,CAC5C,mCACA,wDACF,CAAC;AAED,MAAa,wBAAwB,IAAI;CACvC;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;;;;;;;;;;;;;;;AAgBD,MAAa,uBAAuB,IAClC;CACE;CACA;CACA;CACA;CAGA;CACA;CACA;CACA;CAGA;CACA;CACA;CACA;CACA;AACF,GACA;CACE,UAAU;;;;;;AAMR,WAAW;EACT,QAAQ,CAEN,2CACA,+BACF;EACA,OAAO;GAGL;GACA;GACA;GACA;GACA;EACF;;;;;;EAMA,MAAM;GACJ;GACA;GACA;GACA;EACF;CACF,EACF;CACA,iBAAiB,EAAE,WAAW,SAAS;AACzC,CACF;AAEA,SAAS,kBAAkB;CACzB,OACE,oBAAC,OAAD;EAAK,SAAQ;EAAY,MAAK;EAAO,QAAO;EAAe,aAAY;EAAI,eAAY;EACrF,UAAA,oBAAC,QAAD;GAAM,GAAE;GAAiB,eAAc;GAAQ,gBAAe;EAAS,CAAA;CACpE,CAAA;AAET;AAEA,SAAS,cAAc;CACrB,OACE,oBAAC,OAAD;EAAK,SAAQ;EAAY,MAAK;EAAO,QAAO;EAAe,aAAY;EAAI,eAAY;EACrF,UAAA,oBAAC,QAAD;GAAM,GAAE;GAAgB,eAAc;GAAQ,gBAAe;EAAS,CAAA;CACnE,CAAA;AAET;;;;;;;;;;;;;;;;;;AAmBA,SAAS,YAAY,EAAE,SAA4B;CACjD,MAAM,gBAAgB,WAAW,oBAAoB;CACrD,MAAM,aAAa,WAAW,yBAAyB;CAUvD,MAAM,QAAQ,iBAAiB;CAC/B,MAAM,UAAU,QAAQ,OAAO,cAAc,KAAK,KAAK,QAAQ,OAAO,cAAc,KAAK;CAEzF,OACE,oBAACA,QAAD;EACE,MAAM;EACN,aAAU;EACV,YAAY;EACZ,WAAW,sBAAsB;EAGjC,eAAe;GACb,IAAI,eAAe,cAAc,SAAS,IAAI;QACzC,YAAY,SAAS,IAAI;EAChC;EAEC,UAAA;CACS,CAAA;AAEhB;;AAYA,SAAS,UAAU,EAAE,QAAQ,aAAgE;CAC3F,OACE,qBAACC,cAAD;EAAkB,QAAQ,EAAE,QAAQ,OAAO;EAAG,WAAW,qBAAqB;EAA9E,UAAA,CACE,oBAACC,oBAAD,EAAA,WACI,YACA,oBAACC,oBAAD;GAAwB,WAAW,2BAA2B;GAC3D,UAAA;EACqB,CAAA,EAEJ,CAAA,GACxB,oBAACC,kBAAD,EAAA,WACI,SACA,oBAACC,cAAD;GACQ;GACN,aAAU;GACV,WAAW,qBAAqB,EAAE,UAAU,CAAC;EAC9C,CAAA,EAEiB,CAAA,CACN;;AAEtB;;AAGA,SAAS,kBAAkB;CACzB,MAAM,SAAS,WAAW,oBAAoB;CAC9C,MAAM,QAAQ,WAAW,yBAAyB;CAClD,QAAQ,UAAU,MAAA,EAAQ,aAAa;AACzC;;;;;;;AAQA,SAAS,aAAa;CACpB,MAAM,QAAQ,gBAAgB;CAC9B,MAAM,aAAa,OAA2B,IAAI;CAClD,MAAM,CAAC,MAAM,WAAW,SAAS,EAAE;CACnC,MAAM,CAAC,OAAO,YAAY,SAAS,KAAK;CACxC,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC;CAChC,IAAI,SAAS,SAAS,MAAM,QAAQ,KAAK,MAAM,GAAG;EAChD,SAAS,KAAK;EACd,OAAO,MAAM,QAAQ,KAAK,IAAI,IAAI,IAAI,EAAE;CAC1C;CACA,gCAAgC;EAC9B,MAAM,OAAO,WAAW,SAAS,eAAe;EAChD,IAAI,SAAS,MAAM,QAAQ,IAAI;CACjC,CAAC;CACD,OACE,qBAAA,YAAA,EAAA,UAAA,CACE,oBAACC,iBAAD;EAAqB,KAAK;EAAY,WAAU;CAAW,CAAA,GAC3D,oBAAC,QAAD;EAAM,eAAY;EAAO,aAAU;EAAiB,WAAW,sBAAsB;EAEnF,UAAA,oBAAC,UAAD;GAA8C,SAAS;GAAW;GAAK,QAAO;GAAQ,WAAU;GAC7F,UAAA;EACO,GAFK,SAAS,KAAK,SAAS,MAE5B;CACN,CAAA,CACN,EAAA,CAAA;AAEN;;AAGA,SAAS,UAAU,MAAmB;CACpC,MAAM,KAAK,KAAK,QAAQ,IAAI;CAC5B,MAAM,KAAK,IAAI;CACf,OAAO,MAAM,KAAK;EAAE,KAAK,GAAG;EAAW,KAAK,GAAG;CAAgB,IAAI;AACrE;;;;;;;;;;;;;;;AAsBA,SAAS,aAAa;CACpB,MAAM,SAAS,OAAwB,IAAI;CAC3C,MAAM,SAAS,uBAAO,IAAI,QAAiC,CAAC;CAE5D,WAAW,oBAAoB;CAC/B,gCAAgC;EAC9B,MAAM,OAAO,OAAO,SAAS;EAC7B,IAAI,CAAC,MAAM;EAEX,MAAM,OAAO,CADE,GAAG,KAAK,iBAA8B,gCAA8B,CAClE,CAAC,CAAC,SAAS,SAAS;GACnC,MAAM,KAAK,KAAK,cAA2B,wCAAsC;GACjF,IAAI,CAAC,IAAI,OAAO,CAAC;GAEjB,OAAO,CAAC;IAAE;IAAM;IAAI,MADP,KAAK,cAA2B,8CACtB;GAAE,CAAC;EAC5B,CAAC;EAED,KAAK,MAAM,EAAE,IAAI,UAAU,MAAM;GAC/B,IAAI,CAAC,MAAM;GACX,MAAM,QAAQ,UAAU,IAAI;GAC5B,MAAM,SAAS,OAAO,QAAQ,IAAI,EAAE;GACpC,IAAI,GAAG,QAAQ,YAAY,KAAA,KAAa,CAAC,UAAU,OAAO,SAAS,QAAQ,CAAC,OAAO;GACnF,MAAM,WAAW,KAAK,MAAM,MAAM,MAAM,OAAO,KAAK,MAAM,MAAM,OAAO,GAAG;GAC1E,IAAI,aAAa,GAAG;GACpB,KAAK,MAAM,YACT,kBACA,GAAG,KAAK,MAAM,KAAK,IAAI,KAAK,KAAK,KAAK,KAAK,IAAI,QAAQ,CAAC,CAAC,EAAE,GAC7D;GACA,IAAI,OAAO,KAAK,aACd,OAAO,KAAK,MAAM,YAChB,kBACA,GAAG,KAAK,MAAM,KAAK,IAAI,IAAI,MAAM,QAAQ,CAAC,EAAE,GAC9C;EACJ;EAEA,KAAK,MAAM,EAAE,MAAM,IAAI,UAAU,MAAM;GACrC,IAAI,CAAC,MAAM;IACT,OAAO,GAAG,QAAQ;IAClB,OAAO,QAAQ,OAAO,EAAE;IACxB;GACF;GACA,MAAM,MAAM,KAAK,sBAAsB;GACvC,MAAM,UAAU,KAAK,sBAAsB;GAE3C,MAAM,IAAI,IAAI,OAAO,QAAQ,QAAQ,IAAI,QAAQ,KAAK,eAAe;GACrE,MAAM,IAAI,IAAI,MAAM,QAAQ,OAAO,IAAI,SAAS,KAAK,gBAAgB;GACrE,GAAG,MAAM,QAAQ,GAAG,KAAK,YAAY;GACrC,GAAG,MAAM,SAAS,GAAG,KAAK,aAAa;GACvC,IAAI,GAAG,QAAQ,YAAY,KAAA,GAAW;IAEpC,GAAG,MAAM,aAAa;IACtB,GAAG,MAAM,YAAY,GAAG,EAAE,KAAK,EAAE;IACjC,GAAQ;IACR,GAAG,MAAM,aAAa;IACtB,GAAG,QAAQ,UAAU;GACvB,OACE,GAAG,MAAM,YAAY,GAAG,EAAE,KAAK,EAAE;GAEnC,MAAM,QAAQ,UAAU,IAAI;GAC5B,IAAI,OAAO,OAAO,QAAQ,IAAI,IAAI;IAAE;IAAM,GAAG;GAAM,CAAC;EACtD;CACF,CAAC;CACD,OAAO,oBAAC,QAAD;EAAM,KAAK;EAAQ,QAAA;EAAO,aAAU;CAAwB,CAAA;AACrE;;AAGA,SAAS,gBAAgB;CACvB,OACE,oBAAC,QAAD;EAAM,eAAY;EAAO,aAAU;EAAgB,WAAU;EAC3D,UAAA,oBAAC,QAAD,EAAM,WAAU,qBAAsB,CAAA;CAClC,CAAA;AAEV;;;;;AAMA,SAAS,UAAU,EACjB,QACA,KACA,OACA,MACA,aAOC;CACD,OACE,qBAAC,OAAD;EACE,MAAM,SAAS;GACb,IAAI,CAAC,MAAM;GACX,IAAI,WAAW,GAAG,KAAK,gBAAgB,OAAO;QACzC,KAAK,aAAa,SAAS,EAAE;EACpC;EACA,aAAU;EACV,eAAa;EACb,eAAa,WAAW,IAAI,KAAA,IAAY;EACxC,OAAO;GAAE,OAAO;GAAQ,SAAS;EAAI;EACrC,WAAW,GAAG,iBAAiB,SAAS,sCAAsC;EAVhF,UAAA,CAYG,OAAO,oBAAC,eAAD,CAAgB,CAAA,IAAI,MAC5B,oBAAC,WAAD;GAAmB;GAAmB;EAAY,CAAA,CAC/C;;AAET;;;;;;AAOA,SAAS,WAAW,EAAE,aAAgD;CACpE,MAAM,QAAQ,gBAAgB;CAC9B,MAAM,CAAC,OAAO,YAAY,SAAS,KAAK;CACxC,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC;CAChC,MAAM,CAAC,OAAO,YAAY,SAAwB,IAAI;CACtD,MAAM,QAAQ,OAAuB,IAAI;CAGzC,gCAAgC;EAC9B,MAAM,KAAK,MAAM;EACjB,MAAM,UAAU,IAAI,cAA2B,qBAAmB;EAClE,IAAI,MAAM,SAAS,GAAG,MAAM,SAAS,GAAG,QAAQ,aAAa;CAC/D,CAAC;CACD,MAAM,SAAS,WAAmB;EAChC,MAAM,IAAI,OAAO,IAAI,EAAE,QAAQ,OAAO,CAAC;EACvC,OAAO,IAAI,GAAG,EAAE,IAAI,GAAG,EAAE,KAAK,GAAG,EAAE,UAAU,OAAO,MAAM;CAC5D;CACA,IAAI,SAAS,SAAS,MAAM,QAAQ,KAAK,MAAM,GAAG;EAChD,MAAM,UAAU,MAAM,OAAO,MAAM,QAAQ,MAAM,MAAM,QAAQ,MAAM;EACrE,SAAS,KAAK;EACd,OAAO,SAAS,IAAI,IAAI,EAAE;EAC1B,SAAS,KAAK,IAAI,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,IAAI;CACjD;CACA,OACE,oBAAC,OAAD;EAAK,KAAK;EAAO,aAAU;EAAkB,WAAU;EACpD,UAAA;GAAC;GAAI;GAAG;EAAC,CAAC,CAAC,KAAK,WACf,oBAAC,WAAD;GAEU;GACH;GACL,OAAO,UAAU,MAAM,MAAM,KAAK,WAAW;GAC7C,MAAM,cAAc;GACT;EACZ,GANM,MAAM,MAAM,CAMlB,CACF;CACE,CAAA;AAET;;AAGA,SAAS,aAAa,EACpB,eACA,WACA,YACA,eACA,WACA,aACoB;CAEpB,MAAM,QAAQ,kBAAkB;CAChC,OACE,qBAAA,YAAA,EAAA,UAAA;EACG,SAAS,cAAc,WAAW,oBAAC,YAAD,CAAa,CAAA,IAAI;EACpD,qBAAC,UAAD;GAAQ,aAAU;GAAkB,WAAW,uBAAuB;GAAtE,UAAA,CACG,QAAQ,oBAAC,YAAD,CAAa,CAAA,IAAI,MAC1B,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,oBAACN,QAAD;KAAY,MAAK;KAAW,cAAY;KAAe,WAAW,oBAAoB;KACpF,UAAA,oBAAC,iBAAD,CAAkB,CAAA;IACR,CAAA,GACZ,oBAACA,QAAD;KAAY,MAAK;KAAO,cAAY;KAAW,WAAW,oBAAoB;KAC5E,UAAA,oBAAC,aAAD,CAAc,CAAA;IACJ,CAAA,CACT;GACC,CAAA,CAAA;;EAEP,QACC,oBAAC,YAAD,EAAuB,UAAY,CAAA,IAEnC,oBAAC,OAAD;GAAK,aAAU;GAAkB,WAAW,uBAAuB;GAChE,UAAA,MAAM,KAAK,EAAE,QAAQ,cAAc,IAAI,GAAG,WACzC,qBAAC,OAAD;IAAkB,aAAU;IAA5B,UAAA,CAGE,oBAACM,iBAAD;KACE,QAAQ,EAAE,QAAQ,OAAO;KACzB,WAAW,wBAAwB;IACpC,CAAA,GACD,oBAAC,WAAD;KAAmB;KAAmB;IAAY,CAAA,CAC/C;GARK,GAAA,MAQL,CACN;EACE,CAAA;EAGN,YAAY,oBAAC,aAAD,EAAa,OAAO,WAAa,CAAA,IAAI;CAClD,EAAA,CAAA;AAEN;;;;;;;;;;;;;;AAqGA,MAAaC,aAAW,WAA0C,SAASA,WACzE,EACE,WACA,OACA,cAAc,OACd,gBAAgB,GAChB,YAAY,OACZ,aAAa,SACb,gBAAgB,kBAChB,YAAY,cACZ,GAAG,SAEL,KACA;CACA,OACE,qBAACC,UAAD;EACO;EACL,GAAI;EACJ,cAAY;EACZ,iBAAiB,EAAE,QAAQ,cAAc;EACzC,aAAU;EACV,WAAW,GAAG,iBAAiB,GAAG,SAAS;EAN7C,UAAA,CAQG,cAAc,OACb,oBAAC,QAAD;GAAM,aAAU;GAAiB,WAAW,sBAAsB;GAC/D,UAAA;EACG,CAAA,GAER,oBAAC,cAAD;GACiB;GACJ;GACC;GACG;GACJ;GACX,WAAU;EACX,CAAA,CACW;;AAElB,CAAC;;;;;;;;;;AAWD,MAAa,gBAAgB,WAA+C,SAAS,cACnF,EACE,WACA,OACA,cAAc,OACd,gBAAgB,GAChB,YAAY,OACZ,aAAa,SACb,gBAAgB,kBAChB,YAAY,cACZ,GAAG,SAEL,KACA;CACA,OACE,qBAACC,eAAD;EACO;EACL,GAAI;EACJ,cAAY;EACZ,iBAAiB,EAAE,QAAQ,cAAc;EACzC,aAAU;EACV,WAAW,GAAG,iBAAiB,GAAG,SAAS;EAN7C,UAAA,CAQG,cAAc,OACb,oBAAC,QAAD;GAAM,aAAU;GAAiB,WAAW,sBAAsB;GAC/D,UAAA;EACG,CAAA,GAER,oBAAC,cAAD;GACiB;GACJ;GACC;GACG;GACJ;GACX,WAAU;EACX,CAAA,CACgB;;AAEvB,CAAC"}
|
package/dist/card/card.d.ts
CHANGED
|
@@ -53,11 +53,18 @@ export declare const cardFooterVariants: (props?: import("class-variance-authori
|
|
|
53
53
|
* <CardContent>Twelve of eighteen modules complete.</CardContent>
|
|
54
54
|
* </Card>
|
|
55
55
|
*/
|
|
56
|
-
export
|
|
57
|
-
|
|
56
|
+
export interface CardProps extends ComponentPropsWithoutRef<"div"> {
|
|
57
|
+
/**
|
|
58
|
+
* Make the card respond to a pointer: it floats 2px on a spring while it is pointed
|
|
59
|
+
* at, its border darkens and its shadow deepens. Mouse and pen only; touch never lifts.
|
|
60
|
+
* Leave it off for a card that is not a target: a static card should not move.
|
|
61
|
+
*/
|
|
62
|
+
interactive?: boolean;
|
|
63
|
+
}
|
|
64
|
+
export declare const Card: import("react").ForwardRefExoticComponent<CardProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
58
65
|
/** Title and description, stacked. */
|
|
59
66
|
export type CardHeaderProps = ComponentPropsWithoutRef<"div">;
|
|
60
|
-
export declare
|
|
67
|
+
export declare const CardHeader: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
61
68
|
/**
|
|
62
69
|
* The card's heading.
|
|
63
70
|
*
|
|
@@ -79,15 +86,15 @@ export interface CardTitleProps extends ComponentPropsWithoutRef<"h3"> {
|
|
|
79
86
|
*/
|
|
80
87
|
level?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
81
88
|
}
|
|
82
|
-
export declare
|
|
89
|
+
export declare const CardTitle: import("react").ForwardRefExoticComponent<CardTitleProps & import("react").RefAttributes<HTMLHeadingElement>>;
|
|
83
90
|
/** Secondary text under the title. */
|
|
84
91
|
export type CardDescriptionProps = ComponentPropsWithoutRef<"div">;
|
|
85
|
-
export declare
|
|
92
|
+
export declare const CardDescription: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
86
93
|
/** The card's body. */
|
|
87
94
|
export type CardContentProps = ComponentPropsWithoutRef<"div">;
|
|
88
|
-
export declare
|
|
95
|
+
export declare const CardContent: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
89
96
|
/** Actions or metadata at the foot of the card. */
|
|
90
97
|
export type CardFooterProps = ComponentPropsWithoutRef<"div">;
|
|
91
|
-
export declare
|
|
98
|
+
export declare const CardFooter: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
92
99
|
//#endregion
|
|
93
100
|
//# sourceMappingURL=card.d.ts.map
|