@ttt-productions/ui-core 0.11.32 → 0.11.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/index.d.ts +2 -2
- package/dist/browser/index.js +1 -1
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/reload-recovery-watch.d.ts +2 -2
- package/dist/browser/reload-recovery-watch.d.ts.map +1 -1
- package/dist/browser/reload-recovery-watch.js +5 -5
- package/dist/browser/reload-recovery-watch.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/lib/format-numbers.js +2 -2
- package/dist/lib/format-numbers.js.map +1 -1
- package/dist/lib/reload-recovery.js +13 -13
- package/dist/lib/reload-recovery.js.map +1 -1
- package/dist/lib/utils.js.map +1 -1
- package/dist/react/components/accordion.d.ts +2 -2
- package/dist/react/components/accordion.d.ts.map +1 -1
- package/dist/react/components/accordion.js +8 -8
- package/dist/react/components/accordion.js.map +1 -1
- package/dist/react/components/action-row.d.ts +32 -0
- package/dist/react/components/action-row.d.ts.map +1 -0
- package/dist/react/components/action-row.js +16 -0
- package/dist/react/components/action-row.js.map +1 -0
- package/dist/react/components/alert-dialog.d.ts +2 -2
- package/dist/react/components/alert-dialog.d.ts.map +1 -1
- package/dist/react/components/alert-dialog.js +15 -15
- package/dist/react/components/alert-dialog.js.map +1 -1
- package/dist/react/components/alert.d.ts +2 -2
- package/dist/react/components/alert.d.ts.map +1 -1
- package/dist/react/components/alert.js +12 -12
- package/dist/react/components/alert.js.map +1 -1
- package/dist/react/components/avatar.d.ts +2 -2
- package/dist/react/components/avatar.d.ts.map +1 -1
- package/dist/react/components/avatar.js +7 -7
- package/dist/react/components/avatar.js.map +1 -1
- package/dist/react/components/badge.d.ts +2 -2
- package/dist/react/components/badge.d.ts.map +1 -1
- package/dist/react/components/badge.js +9 -9
- package/dist/react/components/badge.js.map +1 -1
- package/dist/react/components/button.d.ts +2 -2
- package/dist/react/components/button.d.ts.map +1 -1
- package/dist/react/components/button.js +28 -28
- package/dist/react/components/button.js.map +1 -1
- package/dist/react/components/card.d.ts +1 -1
- package/dist/react/components/card.d.ts.map +1 -1
- package/dist/react/components/card.js +15 -15
- package/dist/react/components/card.js.map +1 -1
- package/dist/react/components/checkbox.d.ts +2 -2
- package/dist/react/components/checkbox.d.ts.map +1 -1
- package/dist/react/components/checkbox.js +6 -6
- package/dist/react/components/checkbox.js.map +1 -1
- package/dist/react/components/collapsible.d.ts +1 -1
- package/dist/react/components/collapsible.d.ts.map +1 -1
- package/dist/react/components/collapsible.js +2 -2
- package/dist/react/components/collapsible.js.map +1 -1
- package/dist/react/components/consequence-dialog.d.ts.map +1 -1
- package/dist/react/components/consequence-dialog.js +4 -2
- package/dist/react/components/consequence-dialog.js.map +1 -1
- package/dist/react/components/date-picker.d.ts +1 -1
- package/dist/react/components/date-picker.d.ts.map +1 -1
- package/dist/react/components/date-picker.js +102 -66
- package/dist/react/components/date-picker.js.map +1 -1
- package/dist/react/components/date-time-picker.d.ts +1 -1
- package/dist/react/components/date-time-picker.d.ts.map +1 -1
- package/dist/react/components/date-time-picker.js +20 -18
- package/dist/react/components/date-time-picker.js.map +1 -1
- package/dist/react/components/dialog.d.ts +2 -2
- package/dist/react/components/dialog.d.ts.map +1 -1
- package/dist/react/components/dialog.js +14 -14
- package/dist/react/components/dialog.js.map +1 -1
- package/dist/react/components/dropdown-menu.d.ts +2 -2
- package/dist/react/components/dropdown-menu.d.ts.map +1 -1
- package/dist/react/components/dropdown-menu.js +23 -18
- package/dist/react/components/dropdown-menu.js.map +1 -1
- package/dist/react/components/end-of-list-indicator.d.ts +1 -1
- package/dist/react/components/end-of-list-indicator.js +3 -3
- package/dist/react/components/end-of-list-indicator.js.map +1 -1
- package/dist/react/components/form.d.ts +3 -3
- package/dist/react/components/form.d.ts.map +1 -1
- package/dist/react/components/form.js +17 -17
- package/dist/react/components/form.js.map +1 -1
- package/dist/react/components/format-control.d.ts +12 -5
- package/dist/react/components/format-control.d.ts.map +1 -1
- package/dist/react/components/format-control.js +23 -7
- package/dist/react/components/format-control.js.map +1 -1
- package/dist/react/components/input.d.ts +10 -10
- package/dist/react/components/input.d.ts.map +1 -1
- package/dist/react/components/input.js +11 -7
- package/dist/react/components/input.js.map +1 -1
- package/dist/react/components/label.d.ts +3 -3
- package/dist/react/components/label.d.ts.map +1 -1
- package/dist/react/components/label.js +6 -6
- package/dist/react/components/label.js.map +1 -1
- package/dist/react/components/layout/screen-adaptive-view.d.ts +2 -2
- package/dist/react/components/layout/screen-adaptive-view.d.ts.map +1 -1
- package/dist/react/components/layout/screen-adaptive-view.js +39 -35
- package/dist/react/components/layout/screen-adaptive-view.js.map +1 -1
- package/dist/react/components/list-pagination.d.ts +1 -1
- package/dist/react/components/list-pagination.js +10 -10
- package/dist/react/components/list-pagination.js.map +1 -1
- package/dist/react/components/menubar.d.ts +2 -2
- package/dist/react/components/menubar.d.ts.map +1 -1
- package/dist/react/components/menubar.js +17 -17
- package/dist/react/components/menubar.js.map +1 -1
- package/dist/react/components/opener-focus.d.ts +1 -1
- package/dist/react/components/opener-focus.d.ts.map +1 -1
- package/dist/react/components/opener-focus.js +3 -3
- package/dist/react/components/opener-focus.js.map +1 -1
- package/dist/react/components/pending-guard.d.ts +1 -1
- package/dist/react/components/pending-guard.d.ts.map +1 -1
- package/dist/react/components/pending-guard.js +1 -1
- package/dist/react/components/pending-guard.js.map +1 -1
- package/dist/react/components/popover.d.ts +2 -2
- package/dist/react/components/popover.d.ts.map +1 -1
- package/dist/react/components/popover.js +5 -5
- package/dist/react/components/popover.js.map +1 -1
- package/dist/react/components/progress.d.ts +2 -2
- package/dist/react/components/progress.d.ts.map +1 -1
- package/dist/react/components/progress.js +5 -5
- package/dist/react/components/progress.js.map +1 -1
- package/dist/react/components/radio-group.d.ts +2 -2
- package/dist/react/components/radio-group.d.ts.map +1 -1
- package/dist/react/components/radio-group.js +7 -7
- package/dist/react/components/radio-group.js.map +1 -1
- package/dist/react/components/relative-time.d.ts +1 -1
- package/dist/react/components/relative-time.d.ts.map +1 -1
- package/dist/react/components/relative-time.js +8 -7
- package/dist/react/components/relative-time.js.map +1 -1
- package/dist/react/components/reload-recovery-notice.d.ts +3 -3
- package/dist/react/components/reload-recovery-notice.js +7 -7
- package/dist/react/components/reload-recovery-notice.js.map +1 -1
- package/dist/react/components/scroll-area.d.ts +2 -2
- package/dist/react/components/scroll-area.d.ts.map +1 -1
- package/dist/react/components/scroll-area.js +6 -8
- package/dist/react/components/scroll-area.js.map +1 -1
- package/dist/react/components/scroll-to-top-button.d.ts +5 -5
- package/dist/react/components/scroll-to-top-button.js +9 -9
- package/dist/react/components/scroll-to-top-button.js.map +1 -1
- package/dist/react/components/search-dropdown.d.ts.map +1 -1
- package/dist/react/components/search-dropdown.js +8 -3
- package/dist/react/components/search-dropdown.js.map +1 -1
- package/dist/react/components/select.d.ts +2 -2
- package/dist/react/components/select.d.ts.map +1 -1
- package/dist/react/components/select.js +19 -19
- package/dist/react/components/select.js.map +1 -1
- package/dist/react/components/separator.d.ts +2 -2
- package/dist/react/components/separator.d.ts.map +1 -1
- package/dist/react/components/separator.js +5 -5
- package/dist/react/components/separator.js.map +1 -1
- package/dist/react/components/sheet.d.ts +3 -3
- package/dist/react/components/sheet.d.ts.map +1 -1
- package/dist/react/components/sheet.js +21 -21
- package/dist/react/components/sheet.js.map +1 -1
- package/dist/react/components/show-more-toggle.d.ts +2 -2
- package/dist/react/components/show-more-toggle.d.ts.map +1 -1
- package/dist/react/components/show-more-toggle.js +6 -6
- package/dist/react/components/show-more-toggle.js.map +1 -1
- package/dist/react/components/skeleton.d.ts +1 -1
- package/dist/react/components/skeleton.d.ts.map +1 -1
- package/dist/react/components/skeleton.js +3 -3
- package/dist/react/components/skeleton.js.map +1 -1
- package/dist/react/components/slider.d.ts +2 -2
- package/dist/react/components/slider.d.ts.map +1 -1
- package/dist/react/components/slider.js +5 -5
- package/dist/react/components/slider.js.map +1 -1
- package/dist/react/components/spinner.d.ts +1 -1
- package/dist/react/components/spinner.d.ts.map +1 -1
- package/dist/react/components/spinner.js +10 -10
- package/dist/react/components/spinner.js.map +1 -1
- package/dist/react/components/switch.d.ts +2 -2
- package/dist/react/components/switch.d.ts.map +1 -1
- package/dist/react/components/switch.js +13 -8
- package/dist/react/components/switch.js.map +1 -1
- package/dist/react/components/table.d.ts +2 -2
- package/dist/react/components/table.d.ts.map +1 -1
- package/dist/react/components/table.js +24 -24
- package/dist/react/components/table.js.map +1 -1
- package/dist/react/components/tabs.d.ts +2 -2
- package/dist/react/components/tabs.d.ts.map +1 -1
- package/dist/react/components/tabs.js +7 -7
- package/dist/react/components/tabs.js.map +1 -1
- package/dist/react/components/textarea.d.ts +5 -5
- package/dist/react/components/textarea.d.ts.map +1 -1
- package/dist/react/components/textarea.js +11 -7
- package/dist/react/components/textarea.js.map +1 -1
- package/dist/react/components/toast.d.ts +4 -4
- package/dist/react/components/toast.d.ts.map +1 -1
- package/dist/react/components/toast.js +25 -25
- package/dist/react/components/toast.js.map +1 -1
- package/dist/react/components/toaster.d.ts.map +1 -1
- package/dist/react/components/toaster.js +5 -5
- package/dist/react/components/toaster.js.map +1 -1
- package/dist/react/components/tooltip.d.ts +2 -2
- package/dist/react/components/tooltip.d.ts.map +1 -1
- package/dist/react/components/tooltip.js +5 -5
- package/dist/react/components/tooltip.js.map +1 -1
- package/dist/react/hooks/use-async-action.js +2 -2
- package/dist/react/hooks/use-async-action.js.map +1 -1
- package/dist/react/hooks/use-cursor-page.d.ts +1 -1
- package/dist/react/hooks/use-cursor-page.js +2 -2
- package/dist/react/hooks/use-cursor-page.js.map +1 -1
- package/dist/react/hooks/use-media-query.js +5 -5
- package/dist/react/hooks/use-media-query.js.map +1 -1
- package/dist/react/hooks/use-paged-list.js +2 -2
- package/dist/react/hooks/use-paged-list.js.map +1 -1
- package/dist/react/hooks/use-return-scroll.d.ts +1 -1
- package/dist/react/hooks/use-return-scroll.d.ts.map +1 -1
- package/dist/react/hooks/use-return-scroll.js +11 -11
- package/dist/react/hooks/use-return-scroll.js.map +1 -1
- package/dist/react/hooks/use-toast.d.ts +3 -3
- package/dist/react/hooks/use-toast.d.ts.map +1 -1
- package/dist/react/hooks/use-toast.js +17 -17
- package/dist/react/hooks/use-toast.js.map +1 -1
- package/dist/react/index.d.ts +74 -72
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +51 -50
- package/dist/react/index.js.map +1 -1
- package/package.json +8 -6
|
@@ -1,19 +1,47 @@
|
|
|
1
|
-
|
|
1
|
+
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import * as React from
|
|
4
|
-
import { ChevronLeft, ChevronRight } from
|
|
5
|
-
import { Button } from
|
|
6
|
-
import { cn } from
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { ChevronLeft, ChevronRight } from 'lucide-react';
|
|
5
|
+
import { Button } from './button.js';
|
|
6
|
+
import { cn } from '../../lib/utils.js';
|
|
7
7
|
const MONTHS = [
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
'January',
|
|
9
|
+
'February',
|
|
10
|
+
'March',
|
|
11
|
+
'April',
|
|
12
|
+
'May',
|
|
13
|
+
'June',
|
|
14
|
+
'July',
|
|
15
|
+
'August',
|
|
16
|
+
'September',
|
|
17
|
+
'October',
|
|
18
|
+
'November',
|
|
19
|
+
'December',
|
|
10
20
|
];
|
|
11
21
|
const MONTHS_SHORT = [
|
|
12
|
-
|
|
13
|
-
|
|
22
|
+
'Jan',
|
|
23
|
+
'Feb',
|
|
24
|
+
'Mar',
|
|
25
|
+
'Apr',
|
|
26
|
+
'May',
|
|
27
|
+
'Jun',
|
|
28
|
+
'Jul',
|
|
29
|
+
'Aug',
|
|
30
|
+
'Sep',
|
|
31
|
+
'Oct',
|
|
32
|
+
'Nov',
|
|
33
|
+
'Dec',
|
|
34
|
+
];
|
|
35
|
+
const DAYS = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'];
|
|
36
|
+
const DAY_NAMES_LONG = [
|
|
37
|
+
'Sunday',
|
|
38
|
+
'Monday',
|
|
39
|
+
'Tuesday',
|
|
40
|
+
'Wednesday',
|
|
41
|
+
'Thursday',
|
|
42
|
+
'Friday',
|
|
43
|
+
'Saturday',
|
|
14
44
|
];
|
|
15
|
-
const DAYS = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
16
|
-
const DAY_NAMES_LONG = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
|
|
17
45
|
const YEARS_PER_PAGE = 12;
|
|
18
46
|
/** Six rows × seven columns — a calendar month never spans more, and always
|
|
19
47
|
* filling six rows keeps the day grid (and therefore the whole popover
|
|
@@ -26,7 +54,9 @@ const startOfDay = (d) => {
|
|
|
26
54
|
const monthStart = (year, month) => new Date(year, month, 1);
|
|
27
55
|
const addMonths = (d, n) => new Date(d.getFullYear(), d.getMonth() + n, 1);
|
|
28
56
|
const daysInMonth = (year, month) => new Date(year, month + 1, 0).getDate();
|
|
29
|
-
const isSameDay = (a, b) => a.getFullYear() === b.getFullYear() &&
|
|
57
|
+
const isSameDay = (a, b) => a.getFullYear() === b.getFullYear() &&
|
|
58
|
+
a.getMonth() === b.getMonth() &&
|
|
59
|
+
a.getDate() === b.getDate();
|
|
30
60
|
const isSameMonth = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth();
|
|
31
61
|
const fullDateLabel = (date) => `${MONTHS[date.getMonth()]} ${date.getDate()}, ${date.getFullYear()}`;
|
|
32
62
|
/**
|
|
@@ -49,7 +79,7 @@ const fullDateLabel = (date) => `${MONTHS[date.getMonth()]} ${date.getDate()}, $
|
|
|
49
79
|
function DatePicker({ selected, onSelect, disabled, disablePast = false, disableFuture = false, className, }) {
|
|
50
80
|
const today = React.useMemo(() => startOfDay(new Date()), []);
|
|
51
81
|
const [viewDate, setViewDate] = React.useState(() => monthStart((selected ?? today).getFullYear(), (selected ?? today).getMonth()));
|
|
52
|
-
const [view, setView] = React.useState(
|
|
82
|
+
const [view, setView] = React.useState('days');
|
|
53
83
|
const [yearPageStart, setYearPageStart] = React.useState(() => Math.floor((selected ?? today).getFullYear() / YEARS_PER_PAGE) * YEARS_PER_PAGE);
|
|
54
84
|
const [focusedDate, setFocusedDate] = React.useState(() => startOfDay(selected ?? today));
|
|
55
85
|
const monthTriggerRef = React.useRef(null);
|
|
@@ -88,7 +118,7 @@ function DatePicker({ selected, onSelect, disabled, disablePast = false, disable
|
|
|
88
118
|
return false;
|
|
89
119
|
return true;
|
|
90
120
|
};
|
|
91
|
-
const isSelectedDay = (date) =>
|
|
121
|
+
const isSelectedDay = (date) => selected ? isSameDay(startOfDay(selected), startOfDay(date)) : false;
|
|
92
122
|
const isTodayDate = (date) => isSameDay(startOfDay(date), today);
|
|
93
123
|
/** The best in-month day to seed roving focus: the selected day, then today,
|
|
94
124
|
* then the first available day, then the 1st. */
|
|
@@ -126,18 +156,18 @@ function DatePicker({ selected, onSelect, disabled, disablePast = false, disable
|
|
|
126
156
|
if (!target)
|
|
127
157
|
return;
|
|
128
158
|
pendingFocusRef.current = null;
|
|
129
|
-
if (target ===
|
|
159
|
+
if (target === 'monthTrigger') {
|
|
130
160
|
monthTriggerRef.current?.focus();
|
|
131
161
|
}
|
|
132
|
-
else if (target ===
|
|
162
|
+
else if (target === 'yearTrigger') {
|
|
133
163
|
yearTriggerRef.current?.focus();
|
|
134
164
|
}
|
|
135
|
-
else if (target ===
|
|
165
|
+
else if (target === 'day') {
|
|
136
166
|
daysGridRef.current?.querySelector('[data-roving="true"]')?.focus();
|
|
137
167
|
}
|
|
138
|
-
else if (target ===
|
|
168
|
+
else if (target === 'monthGrid' || target === 'yearGrid') {
|
|
139
169
|
const active = overlayRef.current?.querySelector('[data-active="true"]:not([disabled])');
|
|
140
|
-
const fallback = overlayRef.current?.querySelector(
|
|
170
|
+
const fallback = overlayRef.current?.querySelector('button:not([disabled])');
|
|
141
171
|
(active ?? fallback)?.focus();
|
|
142
172
|
}
|
|
143
173
|
});
|
|
@@ -167,7 +197,7 @@ function DatePicker({ selected, onSelect, disabled, disablePast = false, disable
|
|
|
167
197
|
setFocusedDate(d);
|
|
168
198
|
if (!isSameMonth(d, viewDate))
|
|
169
199
|
setViewDate(monthStart(d.getFullYear(), d.getMonth()));
|
|
170
|
-
pendingFocusRef.current =
|
|
200
|
+
pendingFocusRef.current = 'day';
|
|
171
201
|
};
|
|
172
202
|
/** From `origin`, walk `step` days at a time until an available day is found
|
|
173
203
|
* (inclusive of `origin`). Returns null if none within `maxSteps`. */
|
|
@@ -185,44 +215,44 @@ function DatePicker({ selected, onSelect, disabled, disablePast = false, disable
|
|
|
185
215
|
let candidate;
|
|
186
216
|
let probeStep;
|
|
187
217
|
switch (e.key) {
|
|
188
|
-
case
|
|
218
|
+
case 'ArrowLeft':
|
|
189
219
|
candidate = new Date(base.getFullYear(), base.getMonth(), base.getDate() - 1);
|
|
190
220
|
probeStep = -1;
|
|
191
221
|
break;
|
|
192
|
-
case
|
|
222
|
+
case 'ArrowRight':
|
|
193
223
|
candidate = new Date(base.getFullYear(), base.getMonth(), base.getDate() + 1);
|
|
194
224
|
probeStep = 1;
|
|
195
225
|
break;
|
|
196
|
-
case
|
|
226
|
+
case 'ArrowUp':
|
|
197
227
|
candidate = new Date(base.getFullYear(), base.getMonth(), base.getDate() - 7);
|
|
198
228
|
probeStep = -1;
|
|
199
229
|
break;
|
|
200
|
-
case
|
|
230
|
+
case 'ArrowDown':
|
|
201
231
|
candidate = new Date(base.getFullYear(), base.getMonth(), base.getDate() + 7);
|
|
202
232
|
probeStep = 1;
|
|
203
233
|
break;
|
|
204
|
-
case
|
|
234
|
+
case 'Home':
|
|
205
235
|
candidate = new Date(base.getFullYear(), base.getMonth(), base.getDate() - base.getDay());
|
|
206
236
|
probeStep = 1;
|
|
207
237
|
break;
|
|
208
|
-
case
|
|
238
|
+
case 'End':
|
|
209
239
|
candidate = new Date(base.getFullYear(), base.getMonth(), base.getDate() + (6 - base.getDay()));
|
|
210
240
|
probeStep = -1;
|
|
211
241
|
break;
|
|
212
|
-
case
|
|
242
|
+
case 'PageUp': {
|
|
213
243
|
const prev = addMonths(base, -1);
|
|
214
244
|
candidate = new Date(prev.getFullYear(), prev.getMonth(), Math.min(base.getDate(), daysInMonth(prev.getFullYear(), prev.getMonth())));
|
|
215
245
|
probeStep = 1;
|
|
216
246
|
break;
|
|
217
247
|
}
|
|
218
|
-
case
|
|
248
|
+
case 'PageDown': {
|
|
219
249
|
const next = addMonths(base, 1);
|
|
220
250
|
candidate = new Date(next.getFullYear(), next.getMonth(), Math.min(base.getDate(), daysInMonth(next.getFullYear(), next.getMonth())));
|
|
221
251
|
probeStep = 1;
|
|
222
252
|
break;
|
|
223
253
|
}
|
|
224
|
-
case
|
|
225
|
-
case
|
|
254
|
+
case 'Enter':
|
|
255
|
+
case ' ':
|
|
226
256
|
e.preventDefault();
|
|
227
257
|
commitDay(base);
|
|
228
258
|
return;
|
|
@@ -244,17 +274,17 @@ function DatePicker({ selected, onSelect, disabled, disablePast = false, disable
|
|
|
244
274
|
let nextDisabled;
|
|
245
275
|
let prevLabel;
|
|
246
276
|
let nextLabel;
|
|
247
|
-
if (view ===
|
|
277
|
+
if (view === 'days') {
|
|
248
278
|
prevDisabled = isMonthDisabled(prevMonthDate.getFullYear(), prevMonthDate.getMonth());
|
|
249
279
|
nextDisabled = isMonthDisabled(nextMonthDate.getFullYear(), nextMonthDate.getMonth());
|
|
250
|
-
prevLabel =
|
|
251
|
-
nextLabel =
|
|
280
|
+
prevLabel = 'Previous month';
|
|
281
|
+
nextLabel = 'Next month';
|
|
252
282
|
}
|
|
253
|
-
else if (view ===
|
|
283
|
+
else if (view === 'months') {
|
|
254
284
|
prevDisabled = isYearDisabled(viewDate.getFullYear() - 1);
|
|
255
285
|
nextDisabled = isYearDisabled(viewDate.getFullYear() + 1);
|
|
256
|
-
prevLabel =
|
|
257
|
-
nextLabel =
|
|
286
|
+
prevLabel = 'Previous year';
|
|
287
|
+
nextLabel = 'Next year';
|
|
258
288
|
}
|
|
259
289
|
else {
|
|
260
290
|
prevDisabled = rangeAllYearsDisabled(yearPageStart - YEARS_PER_PAGE, yearPageStart - 1);
|
|
@@ -263,62 +293,62 @@ function DatePicker({ selected, onSelect, disabled, disablePast = false, disable
|
|
|
263
293
|
nextLabel = `Next ${YEARS_PER_PAGE} years`;
|
|
264
294
|
}
|
|
265
295
|
const handlePrev = () => {
|
|
266
|
-
if (view ===
|
|
296
|
+
if (view === 'days')
|
|
267
297
|
setViewDate(prevMonthDate);
|
|
268
|
-
else if (view ===
|
|
298
|
+
else if (view === 'months')
|
|
269
299
|
setViewDate(monthStart(viewDate.getFullYear() - 1, viewDate.getMonth()));
|
|
270
300
|
else
|
|
271
301
|
setYearPageStart((s) => s - YEARS_PER_PAGE);
|
|
272
302
|
};
|
|
273
303
|
const handleNext = () => {
|
|
274
|
-
if (view ===
|
|
304
|
+
if (view === 'days')
|
|
275
305
|
setViewDate(nextMonthDate);
|
|
276
|
-
else if (view ===
|
|
306
|
+
else if (view === 'months')
|
|
277
307
|
setViewDate(monthStart(viewDate.getFullYear() + 1, viewDate.getMonth()));
|
|
278
308
|
else
|
|
279
309
|
setYearPageStart((s) => s + YEARS_PER_PAGE);
|
|
280
310
|
};
|
|
281
311
|
const openMonths = () => {
|
|
282
|
-
if (view ===
|
|
283
|
-
setView(
|
|
284
|
-
pendingFocusRef.current =
|
|
312
|
+
if (view === 'months') {
|
|
313
|
+
setView('days');
|
|
314
|
+
pendingFocusRef.current = 'monthTrigger';
|
|
285
315
|
}
|
|
286
316
|
else {
|
|
287
|
-
setView(
|
|
288
|
-
pendingFocusRef.current =
|
|
317
|
+
setView('months');
|
|
318
|
+
pendingFocusRef.current = 'monthGrid';
|
|
289
319
|
}
|
|
290
320
|
};
|
|
291
321
|
const openYears = () => {
|
|
292
|
-
if (view ===
|
|
293
|
-
setView(
|
|
294
|
-
pendingFocusRef.current =
|
|
322
|
+
if (view === 'years') {
|
|
323
|
+
setView('days');
|
|
324
|
+
pendingFocusRef.current = 'yearTrigger';
|
|
295
325
|
}
|
|
296
326
|
else {
|
|
297
327
|
setYearPageStart(Math.floor(viewDate.getFullYear() / YEARS_PER_PAGE) * YEARS_PER_PAGE);
|
|
298
|
-
setView(
|
|
299
|
-
pendingFocusRef.current =
|
|
328
|
+
setView('years');
|
|
329
|
+
pendingFocusRef.current = 'yearGrid';
|
|
300
330
|
}
|
|
301
331
|
};
|
|
302
332
|
// Month selection: keep the year, return to days, focus the Month trigger.
|
|
303
333
|
const handleMonthPick = (month) => {
|
|
304
334
|
setViewDate(monthStart(viewDate.getFullYear(), month));
|
|
305
|
-
setView(
|
|
306
|
-
pendingFocusRef.current =
|
|
335
|
+
setView('days');
|
|
336
|
+
pendingFocusRef.current = 'monthTrigger';
|
|
307
337
|
};
|
|
308
338
|
// Year selection: keep the month, return to days (never months), focus Year.
|
|
309
339
|
const handleYearPick = (year) => {
|
|
310
340
|
setViewDate(monthStart(year, viewDate.getMonth()));
|
|
311
|
-
setView(
|
|
312
|
-
pendingFocusRef.current =
|
|
341
|
+
setView('days');
|
|
342
|
+
pendingFocusRef.current = 'yearTrigger';
|
|
313
343
|
};
|
|
314
344
|
const calendarDays = generateCalendarDays();
|
|
315
345
|
const yearPage = Array.from({ length: YEARS_PER_PAGE }, (_, i) => yearPageStart + i);
|
|
316
|
-
const overlayActive = view !==
|
|
317
|
-
const triggerClass =
|
|
318
|
-
|
|
319
|
-
const gridCellClass =
|
|
320
|
-
|
|
321
|
-
return (_jsxs("div", { className: cn(
|
|
346
|
+
const overlayActive = view !== 'days';
|
|
347
|
+
const triggerClass = 'min-h-[1.5rem] px-1 text-base font-bold text-foreground underline decoration-1 underline-offset-4 decoration-border rounded-sm ' +
|
|
348
|
+
'hover:opacity-80 transition-opacity focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background';
|
|
349
|
+
const gridCellClass = 'h-10 rounded-lg text-sm font-semibold transition-transform flex items-center justify-center ' +
|
|
350
|
+
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background';
|
|
351
|
+
return (_jsxs("div", { className: cn('p-4 bg-card rounded-lg', className), children: [_jsxs("div", { className: "flex items-center justify-between mb-4", children: [_jsx(Button, { variant: "ghost", size: "icon", className: "h-9 w-9 p-0", "aria-label": prevLabel, disabled: prevDisabled, onClick: handlePrev, children: _jsx(ChevronLeft, { className: "h-4 w-4", "aria-hidden": "true" }) }), _jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx("button", { ref: monthTriggerRef, type: "button", onClick: openMonths, "aria-expanded": view === 'months', "aria-label": `Choose month, currently ${MONTHS[viewDate.getMonth()]}`, className: triggerClass, children: MONTHS[viewDate.getMonth()] }), _jsx("button", { ref: yearTriggerRef, type: "button", onClick: openYears, "aria-expanded": view === 'years', "aria-label": `Choose year, currently ${viewDate.getFullYear()}`, className: triggerClass, children: viewDate.getFullYear() })] }), _jsx(Button, { variant: "ghost", size: "icon", className: "h-9 w-9 p-0", "aria-label": nextLabel, disabled: nextDisabled, onClick: handleNext, children: _jsx(ChevronRight, { className: "h-4 w-4", "aria-hidden": "true" }) })] }), _jsxs("div", { "aria-live": "polite", "aria-atomic": "true", className: "sr-only", children: [MONTHS[viewDate.getMonth()], " ", viewDate.getFullYear()] }), _jsxs("div", { className: "relative", children: [_jsxs("div", { "aria-hidden": overlayActive ? true : undefined, children: [_jsx("div", { className: "grid grid-cols-7 gap-1 mb-2", children: DAYS.map((day, i) => (_jsxs("div", { className: "text-center text-sm font-bold py-2 text-foreground", "aria-hidden": "true", children: [_jsx("span", { className: "sr-only", children: DAY_NAMES_LONG[i] }), _jsx("span", { "aria-hidden": "true", children: day })] }, day))) }), _jsx("div", { ref: daysGridRef, className: "grid grid-cols-7 gap-1", role: "group", "aria-label": "Calendar", onKeyDown: overlayActive ? undefined : handleDaysKeyDown, children: calendarDays.map((date, index) => {
|
|
322
352
|
if (!date)
|
|
323
353
|
return _jsx("div", { className: "h-9", "aria-hidden": "true" }, `empty-${index}`);
|
|
324
354
|
const dateDisabled = isDateDisabled(date);
|
|
@@ -326,17 +356,23 @@ function DatePicker({ selected, onSelect, disabled, disablePast = false, disable
|
|
|
326
356
|
const todayDate = isTodayDate(date);
|
|
327
357
|
const roving = isSameDay(date, rovingDate);
|
|
328
358
|
const tabIndex = !overlayActive && roving ? 0 : -1;
|
|
329
|
-
return (_jsxs("button", { type: "button", onClick: () => commitDay(date), disabled: dateDisabled, tabIndex: tabIndex, "data-roving": roving ?
|
|
330
|
-
|
|
359
|
+
return (_jsxs("button", { type: "button", onClick: () => commitDay(date), disabled: dateDisabled, tabIndex: tabIndex, "data-roving": roving ? 'true' : undefined, "aria-label": fullDateLabel(date), "aria-pressed": dateSelected, "aria-current": todayDate ? 'date' : undefined, className: cn('h-9 w-9 rounded-lg text-sm font-semibold transition-transform', 'motion-safe:hover:scale-105 motion-safe:active:scale-95', 'flex items-center justify-center', 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background', !dateDisabled &&
|
|
360
|
+
!dateSelected &&
|
|
361
|
+
!todayDate &&
|
|
362
|
+
'text-foreground hover:bg-primary/10', todayDate &&
|
|
363
|
+
!dateSelected &&
|
|
364
|
+
'bg-accent text-accent-foreground font-bold ring-2 ring-border', dateSelected && 'bg-primary text-primary-foreground font-bold', dateDisabled &&
|
|
365
|
+
'opacity-30 cursor-not-allowed motion-safe:hover:scale-100 hover:bg-transparent relative'), children: [date.getDate(), dateDisabled && (_jsx("span", { className: "absolute inset-0 flex items-center justify-center", "aria-hidden": "true", children: _jsx("span", { className: "w-px h-full bg-current transform rotate-45" }) }))] }, date.toISOString()));
|
|
366
|
+
}) }), _jsxs("div", { className: "mt-4 pt-3 border-t border-border text-xs space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "h-3 w-3 rounded-sm bg-primary", "aria-hidden": "true" }), _jsx("span", { className: "text-muted-foreground", children: "Selected" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "h-3 w-3 rounded-sm bg-accent ring-2 ring-border", "aria-hidden": "true" }), _jsx("span", { className: "text-muted-foreground", children: "Today" })] }), (disablePast || disableFuture || disabled) && (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "h-3 w-3 rounded-sm bg-muted opacity-30 relative", "aria-hidden": "true", children: _jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: _jsx("div", { className: "w-px h-full bg-foreground transform rotate-45" }) }) }), _jsx("span", { className: "text-muted-foreground", children: "Unavailable" })] }))] })] }), overlayActive && (_jsxs("div", { ref: overlayRef, className: "absolute inset-0 bg-card rounded-lg flex flex-col justify-center", children: [view === 'years' && (_jsxs("div", { className: "mb-2 text-center text-sm font-semibold text-muted-foreground", "aria-hidden": "true", children: [yearPageStart, " \u2013 ", yearPageStart + YEARS_PER_PAGE - 1] })), view === 'months' && (_jsx("div", { className: "grid grid-cols-3 gap-1", children: MONTHS_SHORT.map((label, month) => {
|
|
331
367
|
const monthDisabled = isMonthDisabled(viewDate.getFullYear(), month);
|
|
332
368
|
const isViewMonth = month === viewDate.getMonth();
|
|
333
|
-
return (_jsx("button", { type: "button", disabled: monthDisabled, "data-active": isViewMonth ?
|
|
334
|
-
}) })), view ===
|
|
369
|
+
return (_jsx("button", { type: "button", disabled: monthDisabled, "data-active": isViewMonth ? 'true' : undefined, "aria-pressed": isViewMonth, "aria-label": `${MONTHS[month]} ${viewDate.getFullYear()}`, onClick: () => handleMonthPick(month), className: cn(gridCellClass, !monthDisabled && !isViewMonth && 'text-foreground hover:bg-primary/10', isViewMonth && 'bg-primary text-primary-foreground font-bold', monthDisabled && 'opacity-30 cursor-not-allowed'), children: label }, label));
|
|
370
|
+
}) })), view === 'years' && (_jsx("div", { className: "grid grid-cols-3 gap-1", children: yearPage.map((year) => {
|
|
335
371
|
const yearDisabled = isYearDisabled(year);
|
|
336
372
|
const isViewYear = year === viewDate.getFullYear();
|
|
337
|
-
return (_jsx("button", { type: "button", disabled: yearDisabled, "data-active": isViewYear ?
|
|
373
|
+
return (_jsx("button", { type: "button", disabled: yearDisabled, "data-active": isViewYear ? 'true' : undefined, "aria-pressed": isViewYear, "aria-label": `Year ${year}`, onClick: () => handleYearPick(year), className: cn(gridCellClass, !yearDisabled && !isViewYear && 'text-foreground hover:bg-primary/10', isViewYear && 'bg-primary text-primary-foreground font-bold', yearDisabled && 'opacity-30 cursor-not-allowed'), children: year }, year));
|
|
338
374
|
}) }))] }))] })] }));
|
|
339
375
|
}
|
|
340
|
-
DatePicker.displayName =
|
|
376
|
+
DatePicker.displayName = 'DatePicker';
|
|
341
377
|
export { DatePicker };
|
|
342
378
|
//# sourceMappingURL=date-picker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date-picker.js","sourceRoot":"","sources":["../../../src/react/components/date-picker.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { ChevronLeft, ChevronRight } from \"lucide-react\"\nimport { Button } from \"./button.js\"\nimport { cn } from \"../../lib/utils.js\"\n\nexport interface DatePickerProps {\n selected?: Date\n onSelect?: (date: Date | undefined) => void\n disabled?: (date: Date) => boolean\n disablePast?: boolean\n disableFuture?: boolean\n className?: string\n}\n\nconst MONTHS = [\n \"January\", \"February\", \"March\", \"April\", \"May\", \"June\",\n \"July\", \"August\", \"September\", \"October\", \"November\", \"December\",\n]\n\nconst MONTHS_SHORT = [\n \"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\",\n \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\",\n]\n\nconst DAYS = [\"Su\", \"Mo\", \"Tu\", \"We\", \"Th\", \"Fr\", \"Sa\"]\nconst DAY_NAMES_LONG = [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"]\n\nconst YEARS_PER_PAGE = 12\n/** Six rows × seven columns — a calendar month never spans more, and always\n * filling six rows keeps the day grid (and therefore the whole popover\n * footprint) the same height for every month. */\nconst CALENDAR_CELLS = 42\n\ntype View = \"days\" | \"months\" | \"years\"\ntype PendingFocus = \"day\" | \"monthTrigger\" | \"yearTrigger\" | \"monthGrid\" | \"yearGrid\"\n\nconst startOfDay = (d: Date) => {\n const x = new Date(d.getFullYear(), d.getMonth(), d.getDate())\n return x\n}\nconst monthStart = (year: number, month: number) => new Date(year, month, 1)\nconst addMonths = (d: Date, n: number) => new Date(d.getFullYear(), d.getMonth() + n, 1)\nconst daysInMonth = (year: number, month: number) => new Date(year, month + 1, 0).getDate()\nconst isSameDay = (a: Date, b: Date) =>\n a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate()\nconst isSameMonth = (a: Date, b: Date) =>\n a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth()\nconst fullDateLabel = (date: Date) => `${MONTHS[date.getMonth()]} ${date.getDate()}, ${date.getFullYear()}`\n\n/**\n * Generic date-of-birth-friendly calendar.\n *\n * Stable footprint: the six-row day grid is always rendered, so the outer width\n * and content height never change; the month and year choosers render as an\n * overlay ON TOP of that grid rather than replacing it, so a Radix popover never\n * flips sides just because the internal view changed.\n *\n * Month and year are INDEPENDENT pickers: choosing a month keeps the current\n * year and returns to the day grid; choosing a year keeps the current month and\n * returns DIRECTLY to the day grid (it never opens the month grid). Only\n * choosing a day calls `onSelect` (which commits and, in a popover, closes).\n *\n * Keyboard: roving day focus with Arrow (±1 day / ±7 days), Home/End (within the\n * week), PageUp/PageDown (±1 month), and Enter/Space to select — no extra\n * dependency. Exactly one day sits in the tab order at a time.\n */\nfunction DatePicker({\n selected,\n onSelect,\n disabled,\n disablePast = false,\n disableFuture = false,\n className,\n}: DatePickerProps) {\n const today = React.useMemo(() => startOfDay(new Date()), [])\n\n const [viewDate, setViewDate] = React.useState(() =>\n monthStart((selected ?? today).getFullYear(), (selected ?? today).getMonth()),\n )\n const [view, setView] = React.useState<View>(\"days\")\n const [yearPageStart, setYearPageStart] = React.useState(\n () => Math.floor((selected ?? today).getFullYear() / YEARS_PER_PAGE) * YEARS_PER_PAGE,\n )\n const [focusedDate, setFocusedDate] = React.useState(() => startOfDay(selected ?? today))\n\n const monthTriggerRef = React.useRef<HTMLButtonElement | null>(null)\n const yearTriggerRef = React.useRef<HTMLButtonElement | null>(null)\n const daysGridRef = React.useRef<HTMLDivElement | null>(null)\n const overlayRef = React.useRef<HTMLDivElement | null>(null)\n const pendingFocusRef = React.useRef<PendingFocus | null>(null)\n\n const isDateDisabled = (date: Date) => {\n const checkDate = startOfDay(date)\n if (disablePast && checkDate < today) return true\n if (disableFuture && checkDate > today) return true\n if (disabled && disabled(checkDate)) return true\n return false\n }\n\n /** A whole month is unpickable only when every day in it is out of range. */\n const isMonthDisabled = (year: number, month: number) => {\n if (disableFuture && new Date(year, month, 1) > today) return true\n if (disablePast && new Date(year, month + 1, 0) < today) return true\n return false\n }\n\n const isYearDisabled = (year: number) => {\n if (disableFuture && year > today.getFullYear()) return true\n if (disablePast && year < today.getFullYear()) return true\n return false\n }\n\n const rangeAllYearsDisabled = (from: number, to: number) => {\n for (let y = from; y <= to; y++) if (!isYearDisabled(y)) return false\n return true\n }\n\n const isSelectedDay = (date: Date) => (selected ? isSameDay(startOfDay(selected), startOfDay(date)) : false)\n const isTodayDate = (date: Date) => isSameDay(startOfDay(date), today)\n\n /** The best in-month day to seed roving focus: the selected day, then today,\n * then the first available day, then the 1st. */\n const pickInMonthFocus = (vd: Date): Date => {\n const year = vd.getFullYear()\n const month = vd.getMonth()\n if (selected) {\n const s = startOfDay(selected)\n if (isSameMonth(s, vd) && !isDateDisabled(s)) return s\n }\n if (isSameMonth(today, vd) && !isDateDisabled(today)) return new Date(today)\n const dim = daysInMonth(year, month)\n for (let d = 1; d <= dim; d++) {\n const cand = new Date(year, month, d)\n if (!isDateDisabled(cand)) return cand\n }\n return new Date(year, month, 1)\n }\n\n // Resynchronize the visible month/year (and roving focus) when the controlled\n // `selected` prop changes — e.g. the consumer's typed MM/DD/YYYY fields.\n const selectedTime = selected ? startOfDay(selected).getTime() : undefined\n React.useEffect(() => {\n if (selectedTime === undefined) return\n const d = new Date(selectedTime)\n setViewDate(monthStart(d.getFullYear(), d.getMonth()))\n setFocusedDate(startOfDay(d))\n }, [selectedTime])\n\n // Deliberate focus after every view transition — never left on document.body.\n React.useLayoutEffect(() => {\n const target = pendingFocusRef.current\n if (!target) return\n pendingFocusRef.current = null\n if (target === \"monthTrigger\") {\n monthTriggerRef.current?.focus()\n } else if (target === \"yearTrigger\") {\n yearTriggerRef.current?.focus()\n } else if (target === \"day\") {\n daysGridRef.current?.querySelector<HTMLButtonElement>('[data-roving=\"true\"]')?.focus()\n } else if (target === \"monthGrid\" || target === \"yearGrid\") {\n const active = overlayRef.current?.querySelector<HTMLButtonElement>('[data-active=\"true\"]:not([disabled])')\n const fallback = overlayRef.current?.querySelector<HTMLButtonElement>(\"button:not([disabled])\")\n ;(active ?? fallback)?.focus()\n }\n })\n\n const generateCalendarDays = (): (Date | null)[] => {\n const year = viewDate.getFullYear()\n const month = viewDate.getMonth()\n const dim = daysInMonth(year, month)\n const firstDay = new Date(year, month, 1).getDay()\n const days: (Date | null)[] = []\n for (let i = 0; i < firstDay; i++) days.push(null)\n for (let day = 1; day <= dim; day++) days.push(new Date(year, month, day))\n while (days.length < CALENDAR_CELLS) days.push(null)\n return days\n }\n\n const inViewMonth = isSameMonth(focusedDate, viewDate)\n const rovingDate = inViewMonth ? focusedDate : pickInMonthFocus(viewDate)\n\n const commitDay = (date: Date) => {\n if (isDateDisabled(date)) return\n onSelect?.(date)\n }\n\n const moveFocusTo = (date: Date) => {\n const d = startOfDay(date)\n setFocusedDate(d)\n if (!isSameMonth(d, viewDate)) setViewDate(monthStart(d.getFullYear(), d.getMonth()))\n pendingFocusRef.current = \"day\"\n }\n\n /** From `origin`, walk `step` days at a time until an available day is found\n * (inclusive of `origin`). Returns null if none within `maxSteps`. */\n const firstAvailableFrom = (origin: Date, step: number, maxSteps: number): Date | null => {\n let d = startOfDay(origin)\n for (let i = 0; i < maxSteps; i++) {\n if (!isDateDisabled(d)) return d\n d = new Date(d.getFullYear(), d.getMonth(), d.getDate() + step)\n }\n return null\n }\n\n const handleDaysKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n const base = rovingDate\n let candidate: Date\n let probeStep: number\n\n switch (e.key) {\n case \"ArrowLeft\":\n candidate = new Date(base.getFullYear(), base.getMonth(), base.getDate() - 1)\n probeStep = -1\n break\n case \"ArrowRight\":\n candidate = new Date(base.getFullYear(), base.getMonth(), base.getDate() + 1)\n probeStep = 1\n break\n case \"ArrowUp\":\n candidate = new Date(base.getFullYear(), base.getMonth(), base.getDate() - 7)\n probeStep = -1\n break\n case \"ArrowDown\":\n candidate = new Date(base.getFullYear(), base.getMonth(), base.getDate() + 7)\n probeStep = 1\n break\n case \"Home\":\n candidate = new Date(base.getFullYear(), base.getMonth(), base.getDate() - base.getDay())\n probeStep = 1\n break\n case \"End\":\n candidate = new Date(base.getFullYear(), base.getMonth(), base.getDate() + (6 - base.getDay()))\n probeStep = -1\n break\n case \"PageUp\": {\n const prev = addMonths(base, -1)\n candidate = new Date(\n prev.getFullYear(),\n prev.getMonth(),\n Math.min(base.getDate(), daysInMonth(prev.getFullYear(), prev.getMonth())),\n )\n probeStep = 1\n break\n }\n case \"PageDown\": {\n const next = addMonths(base, 1)\n candidate = new Date(\n next.getFullYear(),\n next.getMonth(),\n Math.min(base.getDate(), daysInMonth(next.getFullYear(), next.getMonth())),\n )\n probeStep = 1\n break\n }\n case \"Enter\":\n case \" \":\n e.preventDefault()\n commitDay(base)\n return\n default:\n return\n }\n\n e.preventDefault()\n let target = firstAvailableFrom(candidate, probeStep, 62)\n if (!target && probeStep !== -1) target = firstAvailableFrom(candidate, -1, 62)\n if (target) moveFocusTo(target)\n }\n\n // Header prev/next adapt to the active view; disabled when the whole target\n // range is unavailable so navigation never lands on a dead page.\n const prevMonthDate = addMonths(viewDate, -1)\n const nextMonthDate = addMonths(viewDate, 1)\n\n let prevDisabled: boolean\n let nextDisabled: boolean\n let prevLabel: string\n let nextLabel: string\n\n if (view === \"days\") {\n prevDisabled = isMonthDisabled(prevMonthDate.getFullYear(), prevMonthDate.getMonth())\n nextDisabled = isMonthDisabled(nextMonthDate.getFullYear(), nextMonthDate.getMonth())\n prevLabel = \"Previous month\"\n nextLabel = \"Next month\"\n } else if (view === \"months\") {\n prevDisabled = isYearDisabled(viewDate.getFullYear() - 1)\n nextDisabled = isYearDisabled(viewDate.getFullYear() + 1)\n prevLabel = \"Previous year\"\n nextLabel = \"Next year\"\n } else {\n prevDisabled = rangeAllYearsDisabled(yearPageStart - YEARS_PER_PAGE, yearPageStart - 1)\n nextDisabled = rangeAllYearsDisabled(yearPageStart + YEARS_PER_PAGE, yearPageStart + YEARS_PER_PAGE * 2 - 1)\n prevLabel = `Previous ${YEARS_PER_PAGE} years`\n nextLabel = `Next ${YEARS_PER_PAGE} years`\n }\n\n const handlePrev = () => {\n if (view === \"days\") setViewDate(prevMonthDate)\n else if (view === \"months\") setViewDate(monthStart(viewDate.getFullYear() - 1, viewDate.getMonth()))\n else setYearPageStart((s) => s - YEARS_PER_PAGE)\n }\n const handleNext = () => {\n if (view === \"days\") setViewDate(nextMonthDate)\n else if (view === \"months\") setViewDate(monthStart(viewDate.getFullYear() + 1, viewDate.getMonth()))\n else setYearPageStart((s) => s + YEARS_PER_PAGE)\n }\n\n const openMonths = () => {\n if (view === \"months\") {\n setView(\"days\")\n pendingFocusRef.current = \"monthTrigger\"\n } else {\n setView(\"months\")\n pendingFocusRef.current = \"monthGrid\"\n }\n }\n const openYears = () => {\n if (view === \"years\") {\n setView(\"days\")\n pendingFocusRef.current = \"yearTrigger\"\n } else {\n setYearPageStart(Math.floor(viewDate.getFullYear() / YEARS_PER_PAGE) * YEARS_PER_PAGE)\n setView(\"years\")\n pendingFocusRef.current = \"yearGrid\"\n }\n }\n\n // Month selection: keep the year, return to days, focus the Month trigger.\n const handleMonthPick = (month: number) => {\n setViewDate(monthStart(viewDate.getFullYear(), month))\n setView(\"days\")\n pendingFocusRef.current = \"monthTrigger\"\n }\n // Year selection: keep the month, return to days (never months), focus Year.\n const handleYearPick = (year: number) => {\n setViewDate(monthStart(year, viewDate.getMonth()))\n setView(\"days\")\n pendingFocusRef.current = \"yearTrigger\"\n }\n\n const calendarDays = generateCalendarDays()\n const yearPage = Array.from({ length: YEARS_PER_PAGE }, (_, i) => yearPageStart + i)\n const overlayActive = view !== \"days\"\n\n const triggerClass =\n \"min-h-[1.5rem] px-1 text-base font-bold text-foreground underline decoration-1 underline-offset-4 decoration-border rounded-sm \" +\n \"hover:opacity-80 transition-opacity focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\"\n\n const gridCellClass =\n \"h-10 rounded-lg text-sm font-semibold transition-transform flex items-center justify-center \" +\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\"\n\n return (\n <div className={cn(\"p-4 bg-card rounded-lg\", className)}>\n {/* Header — same footprint in every view. */}\n <div className=\"flex items-center justify-between mb-4\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-9 w-9 p-0\"\n aria-label={prevLabel}\n disabled={prevDisabled}\n onClick={handlePrev}\n >\n <ChevronLeft className=\"h-4 w-4\" aria-hidden=\"true\" />\n </Button>\n\n <div className=\"flex items-center gap-1.5\">\n <button\n ref={monthTriggerRef}\n type=\"button\"\n onClick={openMonths}\n aria-expanded={view === \"months\"}\n aria-label={`Choose month, currently ${MONTHS[viewDate.getMonth()]}`}\n className={triggerClass}\n >\n {MONTHS[viewDate.getMonth()]}\n </button>\n <button\n ref={yearTriggerRef}\n type=\"button\"\n onClick={openYears}\n aria-expanded={view === \"years\"}\n aria-label={`Choose year, currently ${viewDate.getFullYear()}`}\n className={triggerClass}\n >\n {viewDate.getFullYear()}\n </button>\n </div>\n\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-9 w-9 p-0\"\n aria-label={nextLabel}\n disabled={nextDisabled}\n onClick={handleNext}\n >\n <ChevronRight className=\"h-4 w-4\" aria-hidden=\"true\" />\n </Button>\n </div>\n\n {/* One polite live region for the displayed month/year. */}\n <div aria-live=\"polite\" aria-atomic=\"true\" className=\"sr-only\">\n {MONTHS[viewDate.getMonth()]} {viewDate.getFullYear()}\n </div>\n\n <div className=\"relative\">\n {/* Day grid — ALWAYS rendered so width and height stay stable; inert\n while a chooser overlay covers it. */}\n <div aria-hidden={overlayActive ? true : undefined}>\n <div className=\"grid grid-cols-7 gap-1 mb-2\">\n {DAYS.map((day, i) => (\n <div key={day} className=\"text-center text-sm font-bold py-2 text-foreground\" aria-hidden=\"true\">\n <span className=\"sr-only\">{DAY_NAMES_LONG[i]}</span>\n <span aria-hidden=\"true\">{day}</span>\n </div>\n ))}\n </div>\n\n <div\n ref={daysGridRef}\n className=\"grid grid-cols-7 gap-1\"\n role=\"group\"\n aria-label=\"Calendar\"\n onKeyDown={overlayActive ? undefined : handleDaysKeyDown}\n >\n {calendarDays.map((date, index) => {\n if (!date) return <div key={`empty-${index}`} className=\"h-9\" aria-hidden=\"true\" />\n\n const dateDisabled = isDateDisabled(date)\n const dateSelected = isSelectedDay(date)\n const todayDate = isTodayDate(date)\n const roving = isSameDay(date, rovingDate)\n const tabIndex = !overlayActive && roving ? 0 : -1\n\n return (\n <button\n key={date.toISOString()}\n type=\"button\"\n onClick={() => commitDay(date)}\n disabled={dateDisabled}\n tabIndex={tabIndex}\n data-roving={roving ? \"true\" : undefined}\n aria-label={fullDateLabel(date)}\n aria-pressed={dateSelected}\n aria-current={todayDate ? \"date\" : undefined}\n className={cn(\n \"h-9 w-9 rounded-lg text-sm font-semibold transition-transform\",\n \"motion-safe:hover:scale-105 motion-safe:active:scale-95\",\n \"flex items-center justify-center\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n !dateDisabled && !dateSelected && !todayDate && \"text-foreground hover:bg-primary/10\",\n todayDate && !dateSelected && \"bg-accent text-accent-foreground font-bold ring-2 ring-border\",\n dateSelected && \"bg-primary text-primary-foreground font-bold\",\n dateDisabled && \"opacity-30 cursor-not-allowed motion-safe:hover:scale-100 hover:bg-transparent relative\",\n )}\n >\n {date.getDate()}\n {dateDisabled && (\n <span className=\"absolute inset-0 flex items-center justify-center\" aria-hidden=\"true\">\n <span className=\"w-px h-full bg-current transform rotate-45\" />\n </span>\n )}\n </button>\n )\n })}\n </div>\n\n <div className=\"mt-4 pt-3 border-t border-border text-xs space-y-1\">\n <div className=\"flex items-center gap-2\">\n <div className=\"h-3 w-3 rounded-sm bg-primary\" aria-hidden=\"true\" />\n <span className=\"text-muted-foreground\">Selected</span>\n </div>\n <div className=\"flex items-center gap-2\">\n <div className=\"h-3 w-3 rounded-sm bg-accent ring-2 ring-border\" aria-hidden=\"true\" />\n <span className=\"text-muted-foreground\">Today</span>\n </div>\n {(disablePast || disableFuture || disabled) && (\n <div className=\"flex items-center gap-2\">\n <div className=\"h-3 w-3 rounded-sm bg-muted opacity-30 relative\" aria-hidden=\"true\">\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <div className=\"w-px h-full bg-foreground transform rotate-45\" />\n </div>\n </div>\n <span className=\"text-muted-foreground\">Unavailable</span>\n </div>\n )}\n </div>\n </div>\n\n {/* Month / year choosers overlay the day grid — same footprint. */}\n {overlayActive && (\n <div ref={overlayRef} className=\"absolute inset-0 bg-card rounded-lg flex flex-col justify-center\">\n {view === \"years\" && (\n <div className=\"mb-2 text-center text-sm font-semibold text-muted-foreground\" aria-hidden=\"true\">\n {yearPageStart} – {yearPageStart + YEARS_PER_PAGE - 1}\n </div>\n )}\n\n {view === \"months\" && (\n <div className=\"grid grid-cols-3 gap-1\">\n {MONTHS_SHORT.map((label, month) => {\n const monthDisabled = isMonthDisabled(viewDate.getFullYear(), month)\n const isViewMonth = month === viewDate.getMonth()\n return (\n <button\n key={label}\n type=\"button\"\n disabled={monthDisabled}\n data-active={isViewMonth ? \"true\" : undefined}\n aria-pressed={isViewMonth}\n aria-label={`${MONTHS[month]} ${viewDate.getFullYear()}`}\n onClick={() => handleMonthPick(month)}\n className={cn(\n gridCellClass,\n !monthDisabled && !isViewMonth && \"text-foreground hover:bg-primary/10\",\n isViewMonth && \"bg-primary text-primary-foreground font-bold\",\n monthDisabled && \"opacity-30 cursor-not-allowed\",\n )}\n >\n {label}\n </button>\n )\n })}\n </div>\n )}\n\n {view === \"years\" && (\n <div className=\"grid grid-cols-3 gap-1\">\n {yearPage.map((year) => {\n const yearDisabled = isYearDisabled(year)\n const isViewYear = year === viewDate.getFullYear()\n return (\n <button\n key={year}\n type=\"button\"\n disabled={yearDisabled}\n data-active={isViewYear ? \"true\" : undefined}\n aria-pressed={isViewYear}\n aria-label={`Year ${year}`}\n onClick={() => handleYearPick(year)}\n className={cn(\n gridCellClass,\n !yearDisabled && !isViewYear && \"text-foreground hover:bg-primary/10\",\n isViewYear && \"bg-primary text-primary-foreground font-bold\",\n yearDisabled && \"opacity-30 cursor-not-allowed\",\n )}\n >\n {year}\n </button>\n )\n })}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n )\n}\n\nDatePicker.displayName = \"DatePicker\"\n\nexport { DatePicker }\n"]}
|
|
1
|
+
{"version":3,"file":"date-picker.js","sourceRoot":"","sources":["../../../src/react/components/date-picker.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { ChevronLeft, ChevronRight } from 'lucide-react';\nimport { Button } from './button.js';\nimport { cn } from '../../lib/utils.js';\n\nexport interface DatePickerProps {\n selected?: Date;\n onSelect?: (date: Date | undefined) => void;\n disabled?: (date: Date) => boolean;\n disablePast?: boolean;\n disableFuture?: boolean;\n className?: string;\n}\n\nconst MONTHS = [\n 'January',\n 'February',\n 'March',\n 'April',\n 'May',\n 'June',\n 'July',\n 'August',\n 'September',\n 'October',\n 'November',\n 'December',\n];\n\nconst MONTHS_SHORT = [\n 'Jan',\n 'Feb',\n 'Mar',\n 'Apr',\n 'May',\n 'Jun',\n 'Jul',\n 'Aug',\n 'Sep',\n 'Oct',\n 'Nov',\n 'Dec',\n];\n\nconst DAYS = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'];\nconst DAY_NAMES_LONG = [\n 'Sunday',\n 'Monday',\n 'Tuesday',\n 'Wednesday',\n 'Thursday',\n 'Friday',\n 'Saturday',\n];\n\nconst YEARS_PER_PAGE = 12;\n/** Six rows × seven columns — a calendar month never spans more, and always\n * filling six rows keeps the day grid (and therefore the whole popover\n * footprint) the same height for every month. */\nconst CALENDAR_CELLS = 42;\n\ntype View = 'days' | 'months' | 'years';\ntype PendingFocus = 'day' | 'monthTrigger' | 'yearTrigger' | 'monthGrid' | 'yearGrid';\n\nconst startOfDay = (d: Date) => {\n const x = new Date(d.getFullYear(), d.getMonth(), d.getDate());\n return x;\n};\nconst monthStart = (year: number, month: number) => new Date(year, month, 1);\nconst addMonths = (d: Date, n: number) => new Date(d.getFullYear(), d.getMonth() + n, 1);\nconst daysInMonth = (year: number, month: number) => new Date(year, month + 1, 0).getDate();\nconst isSameDay = (a: Date, b: Date) =>\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate();\nconst isSameMonth = (a: Date, b: Date) =>\n a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth();\nconst fullDateLabel = (date: Date) =>\n `${MONTHS[date.getMonth()]} ${date.getDate()}, ${date.getFullYear()}`;\n\n/**\n * Generic date-of-birth-friendly calendar.\n *\n * Stable footprint: the six-row day grid is always rendered, so the outer width\n * and content height never change; the month and year choosers render as an\n * overlay ON TOP of that grid rather than replacing it, so a Radix popover never\n * flips sides just because the internal view changed.\n *\n * Month and year are INDEPENDENT pickers: choosing a month keeps the current\n * year and returns to the day grid; choosing a year keeps the current month and\n * returns DIRECTLY to the day grid (it never opens the month grid). Only\n * choosing a day calls `onSelect` (which commits and, in a popover, closes).\n *\n * Keyboard: roving day focus with Arrow (±1 day / ±7 days), Home/End (within the\n * week), PageUp/PageDown (±1 month), and Enter/Space to select — no extra\n * dependency. Exactly one day sits in the tab order at a time.\n */\nfunction DatePicker({\n selected,\n onSelect,\n disabled,\n disablePast = false,\n disableFuture = false,\n className,\n}: DatePickerProps) {\n const today = React.useMemo(() => startOfDay(new Date()), []);\n\n const [viewDate, setViewDate] = React.useState(() =>\n monthStart((selected ?? today).getFullYear(), (selected ?? today).getMonth()),\n );\n const [view, setView] = React.useState<View>('days');\n const [yearPageStart, setYearPageStart] = React.useState(\n () => Math.floor((selected ?? today).getFullYear() / YEARS_PER_PAGE) * YEARS_PER_PAGE,\n );\n const [focusedDate, setFocusedDate] = React.useState(() => startOfDay(selected ?? today));\n\n const monthTriggerRef = React.useRef<HTMLButtonElement | null>(null);\n const yearTriggerRef = React.useRef<HTMLButtonElement | null>(null);\n const daysGridRef = React.useRef<HTMLDivElement | null>(null);\n const overlayRef = React.useRef<HTMLDivElement | null>(null);\n const pendingFocusRef = React.useRef<PendingFocus | null>(null);\n\n const isDateDisabled = (date: Date) => {\n const checkDate = startOfDay(date);\n if (disablePast && checkDate < today) return true;\n if (disableFuture && checkDate > today) return true;\n if (disabled && disabled(checkDate)) return true;\n return false;\n };\n\n /** A whole month is unpickable only when every day in it is out of range. */\n const isMonthDisabled = (year: number, month: number) => {\n if (disableFuture && new Date(year, month, 1) > today) return true;\n if (disablePast && new Date(year, month + 1, 0) < today) return true;\n return false;\n };\n\n const isYearDisabled = (year: number) => {\n if (disableFuture && year > today.getFullYear()) return true;\n if (disablePast && year < today.getFullYear()) return true;\n return false;\n };\n\n const rangeAllYearsDisabled = (from: number, to: number) => {\n for (let y = from; y <= to; y++) if (!isYearDisabled(y)) return false;\n return true;\n };\n\n const isSelectedDay = (date: Date) =>\n selected ? isSameDay(startOfDay(selected), startOfDay(date)) : false;\n const isTodayDate = (date: Date) => isSameDay(startOfDay(date), today);\n\n /** The best in-month day to seed roving focus: the selected day, then today,\n * then the first available day, then the 1st. */\n const pickInMonthFocus = (vd: Date): Date => {\n const year = vd.getFullYear();\n const month = vd.getMonth();\n if (selected) {\n const s = startOfDay(selected);\n if (isSameMonth(s, vd) && !isDateDisabled(s)) return s;\n }\n if (isSameMonth(today, vd) && !isDateDisabled(today)) return new Date(today);\n const dim = daysInMonth(year, month);\n for (let d = 1; d <= dim; d++) {\n const cand = new Date(year, month, d);\n if (!isDateDisabled(cand)) return cand;\n }\n return new Date(year, month, 1);\n };\n\n // Resynchronize the visible month/year (and roving focus) when the controlled\n // `selected` prop changes — e.g. the consumer's typed MM/DD/YYYY fields.\n const selectedTime = selected ? startOfDay(selected).getTime() : undefined;\n React.useEffect(() => {\n if (selectedTime === undefined) return;\n const d = new Date(selectedTime);\n setViewDate(monthStart(d.getFullYear(), d.getMonth()));\n setFocusedDate(startOfDay(d));\n }, [selectedTime]);\n\n // Deliberate focus after every view transition — never left on document.body.\n React.useLayoutEffect(() => {\n const target = pendingFocusRef.current;\n if (!target) return;\n pendingFocusRef.current = null;\n if (target === 'monthTrigger') {\n monthTriggerRef.current?.focus();\n } else if (target === 'yearTrigger') {\n yearTriggerRef.current?.focus();\n } else if (target === 'day') {\n daysGridRef.current?.querySelector<HTMLButtonElement>('[data-roving=\"true\"]')?.focus();\n } else if (target === 'monthGrid' || target === 'yearGrid') {\n const active = overlayRef.current?.querySelector<HTMLButtonElement>(\n '[data-active=\"true\"]:not([disabled])',\n );\n const fallback =\n overlayRef.current?.querySelector<HTMLButtonElement>('button:not([disabled])');\n (active ?? fallback)?.focus();\n }\n });\n\n const generateCalendarDays = (): (Date | null)[] => {\n const year = viewDate.getFullYear();\n const month = viewDate.getMonth();\n const dim = daysInMonth(year, month);\n const firstDay = new Date(year, month, 1).getDay();\n const days: (Date | null)[] = [];\n for (let i = 0; i < firstDay; i++) days.push(null);\n for (let day = 1; day <= dim; day++) days.push(new Date(year, month, day));\n while (days.length < CALENDAR_CELLS) days.push(null);\n return days;\n };\n\n const inViewMonth = isSameMonth(focusedDate, viewDate);\n const rovingDate = inViewMonth ? focusedDate : pickInMonthFocus(viewDate);\n\n const commitDay = (date: Date) => {\n if (isDateDisabled(date)) return;\n onSelect?.(date);\n };\n\n const moveFocusTo = (date: Date) => {\n const d = startOfDay(date);\n setFocusedDate(d);\n if (!isSameMonth(d, viewDate)) setViewDate(monthStart(d.getFullYear(), d.getMonth()));\n pendingFocusRef.current = 'day';\n };\n\n /** From `origin`, walk `step` days at a time until an available day is found\n * (inclusive of `origin`). Returns null if none within `maxSteps`. */\n const firstAvailableFrom = (origin: Date, step: number, maxSteps: number): Date | null => {\n let d = startOfDay(origin);\n for (let i = 0; i < maxSteps; i++) {\n if (!isDateDisabled(d)) return d;\n d = new Date(d.getFullYear(), d.getMonth(), d.getDate() + step);\n }\n return null;\n };\n\n const handleDaysKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n const base = rovingDate;\n let candidate: Date;\n let probeStep: number;\n\n switch (e.key) {\n case 'ArrowLeft':\n candidate = new Date(base.getFullYear(), base.getMonth(), base.getDate() - 1);\n probeStep = -1;\n break;\n case 'ArrowRight':\n candidate = new Date(base.getFullYear(), base.getMonth(), base.getDate() + 1);\n probeStep = 1;\n break;\n case 'ArrowUp':\n candidate = new Date(base.getFullYear(), base.getMonth(), base.getDate() - 7);\n probeStep = -1;\n break;\n case 'ArrowDown':\n candidate = new Date(base.getFullYear(), base.getMonth(), base.getDate() + 7);\n probeStep = 1;\n break;\n case 'Home':\n candidate = new Date(base.getFullYear(), base.getMonth(), base.getDate() - base.getDay());\n probeStep = 1;\n break;\n case 'End':\n candidate = new Date(\n base.getFullYear(),\n base.getMonth(),\n base.getDate() + (6 - base.getDay()),\n );\n probeStep = -1;\n break;\n case 'PageUp': {\n const prev = addMonths(base, -1);\n candidate = new Date(\n prev.getFullYear(),\n prev.getMonth(),\n Math.min(base.getDate(), daysInMonth(prev.getFullYear(), prev.getMonth())),\n );\n probeStep = 1;\n break;\n }\n case 'PageDown': {\n const next = addMonths(base, 1);\n candidate = new Date(\n next.getFullYear(),\n next.getMonth(),\n Math.min(base.getDate(), daysInMonth(next.getFullYear(), next.getMonth())),\n );\n probeStep = 1;\n break;\n }\n case 'Enter':\n case ' ':\n e.preventDefault();\n commitDay(base);\n return;\n default:\n return;\n }\n\n e.preventDefault();\n let target = firstAvailableFrom(candidate, probeStep, 62);\n if (!target && probeStep !== -1) target = firstAvailableFrom(candidate, -1, 62);\n if (target) moveFocusTo(target);\n };\n\n // Header prev/next adapt to the active view; disabled when the whole target\n // range is unavailable so navigation never lands on a dead page.\n const prevMonthDate = addMonths(viewDate, -1);\n const nextMonthDate = addMonths(viewDate, 1);\n\n let prevDisabled: boolean;\n let nextDisabled: boolean;\n let prevLabel: string;\n let nextLabel: string;\n\n if (view === 'days') {\n prevDisabled = isMonthDisabled(prevMonthDate.getFullYear(), prevMonthDate.getMonth());\n nextDisabled = isMonthDisabled(nextMonthDate.getFullYear(), nextMonthDate.getMonth());\n prevLabel = 'Previous month';\n nextLabel = 'Next month';\n } else if (view === 'months') {\n prevDisabled = isYearDisabled(viewDate.getFullYear() - 1);\n nextDisabled = isYearDisabled(viewDate.getFullYear() + 1);\n prevLabel = 'Previous year';\n nextLabel = 'Next year';\n } else {\n prevDisabled = rangeAllYearsDisabled(yearPageStart - YEARS_PER_PAGE, yearPageStart - 1);\n nextDisabled = rangeAllYearsDisabled(\n yearPageStart + YEARS_PER_PAGE,\n yearPageStart + YEARS_PER_PAGE * 2 - 1,\n );\n prevLabel = `Previous ${YEARS_PER_PAGE} years`;\n nextLabel = `Next ${YEARS_PER_PAGE} years`;\n }\n\n const handlePrev = () => {\n if (view === 'days') setViewDate(prevMonthDate);\n else if (view === 'months')\n setViewDate(monthStart(viewDate.getFullYear() - 1, viewDate.getMonth()));\n else setYearPageStart((s) => s - YEARS_PER_PAGE);\n };\n const handleNext = () => {\n if (view === 'days') setViewDate(nextMonthDate);\n else if (view === 'months')\n setViewDate(monthStart(viewDate.getFullYear() + 1, viewDate.getMonth()));\n else setYearPageStart((s) => s + YEARS_PER_PAGE);\n };\n\n const openMonths = () => {\n if (view === 'months') {\n setView('days');\n pendingFocusRef.current = 'monthTrigger';\n } else {\n setView('months');\n pendingFocusRef.current = 'monthGrid';\n }\n };\n const openYears = () => {\n if (view === 'years') {\n setView('days');\n pendingFocusRef.current = 'yearTrigger';\n } else {\n setYearPageStart(Math.floor(viewDate.getFullYear() / YEARS_PER_PAGE) * YEARS_PER_PAGE);\n setView('years');\n pendingFocusRef.current = 'yearGrid';\n }\n };\n\n // Month selection: keep the year, return to days, focus the Month trigger.\n const handleMonthPick = (month: number) => {\n setViewDate(monthStart(viewDate.getFullYear(), month));\n setView('days');\n pendingFocusRef.current = 'monthTrigger';\n };\n // Year selection: keep the month, return to days (never months), focus Year.\n const handleYearPick = (year: number) => {\n setViewDate(monthStart(year, viewDate.getMonth()));\n setView('days');\n pendingFocusRef.current = 'yearTrigger';\n };\n\n const calendarDays = generateCalendarDays();\n const yearPage = Array.from({ length: YEARS_PER_PAGE }, (_, i) => yearPageStart + i);\n const overlayActive = view !== 'days';\n\n const triggerClass =\n 'min-h-[1.5rem] px-1 text-base font-bold text-foreground underline decoration-1 underline-offset-4 decoration-border rounded-sm ' +\n 'hover:opacity-80 transition-opacity focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background';\n\n const gridCellClass =\n 'h-10 rounded-lg text-sm font-semibold transition-transform flex items-center justify-center ' +\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background';\n\n return (\n <div className={cn('p-4 bg-card rounded-lg', className)}>\n {/* Header — same footprint in every view. */}\n <div className=\"flex items-center justify-between mb-4\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-9 w-9 p-0\"\n aria-label={prevLabel}\n disabled={prevDisabled}\n onClick={handlePrev}\n >\n <ChevronLeft className=\"h-4 w-4\" aria-hidden=\"true\" />\n </Button>\n\n <div className=\"flex items-center gap-1.5\">\n <button\n ref={monthTriggerRef}\n type=\"button\"\n onClick={openMonths}\n aria-expanded={view === 'months'}\n aria-label={`Choose month, currently ${MONTHS[viewDate.getMonth()]}`}\n className={triggerClass}\n >\n {MONTHS[viewDate.getMonth()]}\n </button>\n <button\n ref={yearTriggerRef}\n type=\"button\"\n onClick={openYears}\n aria-expanded={view === 'years'}\n aria-label={`Choose year, currently ${viewDate.getFullYear()}`}\n className={triggerClass}\n >\n {viewDate.getFullYear()}\n </button>\n </div>\n\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-9 w-9 p-0\"\n aria-label={nextLabel}\n disabled={nextDisabled}\n onClick={handleNext}\n >\n <ChevronRight className=\"h-4 w-4\" aria-hidden=\"true\" />\n </Button>\n </div>\n\n {/* One polite live region for the displayed month/year. */}\n <div aria-live=\"polite\" aria-atomic=\"true\" className=\"sr-only\">\n {MONTHS[viewDate.getMonth()]} {viewDate.getFullYear()}\n </div>\n\n <div className=\"relative\">\n {/* Day grid — ALWAYS rendered so width and height stay stable; inert\n while a chooser overlay covers it. */}\n <div aria-hidden={overlayActive ? true : undefined}>\n <div className=\"grid grid-cols-7 gap-1 mb-2\">\n {DAYS.map((day, i) => (\n <div\n key={day}\n className=\"text-center text-sm font-bold py-2 text-foreground\"\n aria-hidden=\"true\"\n >\n <span className=\"sr-only\">{DAY_NAMES_LONG[i]}</span>\n <span aria-hidden=\"true\">{day}</span>\n </div>\n ))}\n </div>\n\n <div\n ref={daysGridRef}\n className=\"grid grid-cols-7 gap-1\"\n role=\"group\"\n aria-label=\"Calendar\"\n onKeyDown={overlayActive ? undefined : handleDaysKeyDown}\n >\n {calendarDays.map((date, index) => {\n if (!date) return <div key={`empty-${index}`} className=\"h-9\" aria-hidden=\"true\" />;\n\n const dateDisabled = isDateDisabled(date);\n const dateSelected = isSelectedDay(date);\n const todayDate = isTodayDate(date);\n const roving = isSameDay(date, rovingDate);\n const tabIndex = !overlayActive && roving ? 0 : -1;\n\n return (\n <button\n key={date.toISOString()}\n type=\"button\"\n onClick={() => commitDay(date)}\n disabled={dateDisabled}\n tabIndex={tabIndex}\n data-roving={roving ? 'true' : undefined}\n aria-label={fullDateLabel(date)}\n aria-pressed={dateSelected}\n aria-current={todayDate ? 'date' : undefined}\n className={cn(\n 'h-9 w-9 rounded-lg text-sm font-semibold transition-transform',\n 'motion-safe:hover:scale-105 motion-safe:active:scale-95',\n 'flex items-center justify-center',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background',\n !dateDisabled &&\n !dateSelected &&\n !todayDate &&\n 'text-foreground hover:bg-primary/10',\n todayDate &&\n !dateSelected &&\n 'bg-accent text-accent-foreground font-bold ring-2 ring-border',\n dateSelected && 'bg-primary text-primary-foreground font-bold',\n dateDisabled &&\n 'opacity-30 cursor-not-allowed motion-safe:hover:scale-100 hover:bg-transparent relative',\n )}\n >\n {date.getDate()}\n {dateDisabled && (\n <span\n className=\"absolute inset-0 flex items-center justify-center\"\n aria-hidden=\"true\"\n >\n <span className=\"w-px h-full bg-current transform rotate-45\" />\n </span>\n )}\n </button>\n );\n })}\n </div>\n\n <div className=\"mt-4 pt-3 border-t border-border text-xs space-y-1\">\n <div className=\"flex items-center gap-2\">\n <div className=\"h-3 w-3 rounded-sm bg-primary\" aria-hidden=\"true\" />\n <span className=\"text-muted-foreground\">Selected</span>\n </div>\n <div className=\"flex items-center gap-2\">\n <div className=\"h-3 w-3 rounded-sm bg-accent ring-2 ring-border\" aria-hidden=\"true\" />\n <span className=\"text-muted-foreground\">Today</span>\n </div>\n {(disablePast || disableFuture || disabled) && (\n <div className=\"flex items-center gap-2\">\n <div className=\"h-3 w-3 rounded-sm bg-muted opacity-30 relative\" aria-hidden=\"true\">\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <div className=\"w-px h-full bg-foreground transform rotate-45\" />\n </div>\n </div>\n <span className=\"text-muted-foreground\">Unavailable</span>\n </div>\n )}\n </div>\n </div>\n\n {/* Month / year choosers overlay the day grid — same footprint. */}\n {overlayActive && (\n <div\n ref={overlayRef}\n className=\"absolute inset-0 bg-card rounded-lg flex flex-col justify-center\"\n >\n {view === 'years' && (\n <div\n className=\"mb-2 text-center text-sm font-semibold text-muted-foreground\"\n aria-hidden=\"true\"\n >\n {yearPageStart} – {yearPageStart + YEARS_PER_PAGE - 1}\n </div>\n )}\n\n {view === 'months' && (\n <div className=\"grid grid-cols-3 gap-1\">\n {MONTHS_SHORT.map((label, month) => {\n const monthDisabled = isMonthDisabled(viewDate.getFullYear(), month);\n const isViewMonth = month === viewDate.getMonth();\n return (\n <button\n key={label}\n type=\"button\"\n disabled={monthDisabled}\n data-active={isViewMonth ? 'true' : undefined}\n aria-pressed={isViewMonth}\n aria-label={`${MONTHS[month]} ${viewDate.getFullYear()}`}\n onClick={() => handleMonthPick(month)}\n className={cn(\n gridCellClass,\n !monthDisabled && !isViewMonth && 'text-foreground hover:bg-primary/10',\n isViewMonth && 'bg-primary text-primary-foreground font-bold',\n monthDisabled && 'opacity-30 cursor-not-allowed',\n )}\n >\n {label}\n </button>\n );\n })}\n </div>\n )}\n\n {view === 'years' && (\n <div className=\"grid grid-cols-3 gap-1\">\n {yearPage.map((year) => {\n const yearDisabled = isYearDisabled(year);\n const isViewYear = year === viewDate.getFullYear();\n return (\n <button\n key={year}\n type=\"button\"\n disabled={yearDisabled}\n data-active={isViewYear ? 'true' : undefined}\n aria-pressed={isViewYear}\n aria-label={`Year ${year}`}\n onClick={() => handleYearPick(year)}\n className={cn(\n gridCellClass,\n !yearDisabled && !isViewYear && 'text-foreground hover:bg-primary/10',\n isViewYear && 'bg-primary text-primary-foreground font-bold',\n yearDisabled && 'opacity-30 cursor-not-allowed',\n )}\n >\n {year}\n </button>\n );\n })}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n}\n\nDatePicker.displayName = 'DatePicker';\n\nexport { DatePicker };\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date-time-picker.d.ts","sourceRoot":"","sources":["../../../src/react/components/date-time-picker.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,
|
|
1
|
+
{"version":3,"file":"date-time-picker.d.ts","sourceRoot":"","sources":["../../../src/react/components/date-time-picker.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,MAAM,WAAW,kBAAkB;IACjC,WAAW;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW;IACX,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,uCAAuC;IACvC,KAAK,CAAC,EAAE,IAAI,CAAC;IACb,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,KAAK,IAAI,CAAC;IACjC,+EAA+E;IAC/E,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,2EAA2E;IAC3E,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gGAAgG;IAChG,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAuBD;;;;;;;;;;;;;;GAcG;AACH,iBAAS,cAAc,CAAC,EACtB,KAAK,EACL,QAAQ,EACR,GAAG,EACH,GAAG,EACH,UAAc,EACd,WAAwC,EACxC,SAAS,GACV,EAAE,mBAAmB,qBAsJrB;kBA9JQ,cAAc;;;AA0PvB,OAAO,EAAE,cAAc,EAAE,CAAC"}
|