@kalyx/react 1.0.0-rc.1 → 1.0.0-rc.11
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/CHANGELOG.md +308 -0
- package/README.md +2 -2
- package/dist/index.cjs +821 -385
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +80 -7
- package/dist/index.d.ts +80 -7
- package/dist/index.js +810 -390
- package/dist/index.js.map +1 -1
- package/package.json +18 -3
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
'use strict';
|
|
2
3
|
|
|
3
4
|
var react = require('react');
|
|
@@ -57,10 +58,10 @@ function DatePickerRoot({
|
|
|
57
58
|
const currentValue = isControlled ? controlledValue ?? null : uncontrolledValue;
|
|
58
59
|
const [isOpen, setIsOpen] = react.useState(false);
|
|
59
60
|
const [viewMonth, setViewMonth] = react.useState(
|
|
60
|
-
currentValue ?? adapter.today(displayTimezone)
|
|
61
|
+
() => currentValue ?? adapter.today(displayTimezone)
|
|
61
62
|
);
|
|
62
63
|
const [focusedDate, setFocusedDate] = react.useState(
|
|
63
|
-
currentValue ?? adapter.today(displayTimezone)
|
|
64
|
+
() => currentValue ?? adapter.today(displayTimezone)
|
|
64
65
|
);
|
|
65
66
|
useChangeEffect(isOpen, onOpenChange);
|
|
66
67
|
const viewMonthStart = react.useMemo(() => adapter.startOfMonth(viewMonth), [viewMonth, adapter]);
|
|
@@ -151,10 +152,15 @@ function DatePickerRoot({
|
|
|
151
152
|
return /* @__PURE__ */ jsxRuntime.jsx(DatePickerContext.Provider, { value: contextValue, children });
|
|
152
153
|
}
|
|
153
154
|
var DatePickerInput = react.forwardRef(
|
|
154
|
-
function DatePickerInput2({ format: formatProp, onClick, onBlur, onKeyDown, ...props }, ref) {
|
|
155
|
+
function DatePickerInput2({ format: formatProp, name, onClick, onBlur, onKeyDown, ...props }, ref) {
|
|
155
156
|
const ctx = useDatePickerContext("DatePicker.Input");
|
|
156
157
|
const displayFormat = formatProp ?? ctx.displayFormat;
|
|
157
158
|
const [inputText, setInputText] = react.useState(null);
|
|
159
|
+
const isComposingRef = react.useRef(false);
|
|
160
|
+
react.useEffect(() => {
|
|
161
|
+
if (isComposingRef.current) return;
|
|
162
|
+
setInputText(null);
|
|
163
|
+
}, [ctx.value]);
|
|
158
164
|
let formattedValue = "";
|
|
159
165
|
if (ctx.value) {
|
|
160
166
|
try {
|
|
@@ -171,47 +177,62 @@ var DatePickerInput = react.forwardRef(
|
|
|
171
177
|
},
|
|
172
178
|
[ctx, onClick]
|
|
173
179
|
);
|
|
180
|
+
const commitText = react.useCallback(
|
|
181
|
+
(text) => {
|
|
182
|
+
if (!text) {
|
|
183
|
+
ctx.selectDate(null);
|
|
184
|
+
setInputText(null);
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
const parsed = core.parseInputValue(text, ctx.adapter);
|
|
188
|
+
if (parsed) {
|
|
189
|
+
ctx.selectDate(parsed);
|
|
190
|
+
setInputText(null);
|
|
191
|
+
return true;
|
|
192
|
+
}
|
|
193
|
+
return false;
|
|
194
|
+
},
|
|
195
|
+
[ctx]
|
|
196
|
+
);
|
|
174
197
|
const handleBlur = react.useCallback(
|
|
175
198
|
(e) => {
|
|
176
199
|
if (inputText !== null) {
|
|
177
|
-
|
|
178
|
-
if (parsed) {
|
|
179
|
-
ctx.selectDate(parsed);
|
|
180
|
-
}
|
|
200
|
+
commitText(inputText);
|
|
181
201
|
setInputText(null);
|
|
182
202
|
}
|
|
183
203
|
onBlur?.(e);
|
|
184
204
|
},
|
|
185
|
-
[inputText,
|
|
205
|
+
[inputText, commitText, onBlur]
|
|
186
206
|
);
|
|
187
207
|
const handleChange = react.useCallback(
|
|
188
208
|
(e) => {
|
|
189
209
|
const text = e.target.value;
|
|
190
210
|
setInputText(text);
|
|
191
|
-
if (
|
|
192
|
-
|
|
193
|
-
setInputText(null);
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
|
-
const parsed = core.parseInputValue(text, ctx.adapter);
|
|
197
|
-
if (parsed) {
|
|
198
|
-
ctx.selectDate(parsed);
|
|
199
|
-
setInputText(null);
|
|
200
|
-
}
|
|
211
|
+
if (isComposingRef.current) return;
|
|
212
|
+
commitText(text);
|
|
201
213
|
},
|
|
202
|
-
[
|
|
214
|
+
[commitText]
|
|
215
|
+
);
|
|
216
|
+
const handleCompositionStart = react.useCallback(() => {
|
|
217
|
+
isComposingRef.current = true;
|
|
218
|
+
}, []);
|
|
219
|
+
const handleCompositionEnd = react.useCallback(
|
|
220
|
+
(e) => {
|
|
221
|
+
isComposingRef.current = false;
|
|
222
|
+
commitText(e.target.value);
|
|
223
|
+
},
|
|
224
|
+
[commitText]
|
|
203
225
|
);
|
|
204
226
|
const handleKeyDown = react.useCallback(
|
|
205
227
|
(e) => {
|
|
206
228
|
if (e.key === "Escape") {
|
|
207
229
|
ctx.close();
|
|
208
230
|
} else if (e.key === "Enter") {
|
|
231
|
+
if (ctx.isOpen) e.preventDefault();
|
|
209
232
|
if (inputText !== null) {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
setInputText(null);
|
|
214
|
-
}
|
|
233
|
+
commitText(inputText);
|
|
234
|
+
} else if (ctx.isOpen) {
|
|
235
|
+
ctx.selectDate(ctx.focusedDate);
|
|
215
236
|
}
|
|
216
237
|
} else if (e.key === "ArrowDown" && !ctx.isOpen) {
|
|
217
238
|
e.preventDefault();
|
|
@@ -219,36 +240,42 @@ var DatePickerInput = react.forwardRef(
|
|
|
219
240
|
}
|
|
220
241
|
onKeyDown?.(e);
|
|
221
242
|
},
|
|
222
|
-
[ctx, inputText,
|
|
243
|
+
[ctx, inputText, commitText, onKeyDown]
|
|
223
244
|
);
|
|
224
245
|
const calendarId = `${ctx.pickerId}-calendar`;
|
|
225
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
246
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
247
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
248
|
+
"input",
|
|
249
|
+
{
|
|
250
|
+
ref: (node) => {
|
|
251
|
+
ctx.referenceRef.current = node;
|
|
252
|
+
if (typeof ref === "function") ref(node);
|
|
253
|
+
else if (ref) ref.current = node;
|
|
254
|
+
},
|
|
255
|
+
type: "text",
|
|
256
|
+
role: "combobox",
|
|
257
|
+
"aria-expanded": ctx.isOpen,
|
|
258
|
+
"aria-haspopup": "dialog",
|
|
259
|
+
"aria-controls": ctx.isOpen ? calendarId : void 0,
|
|
260
|
+
"aria-autocomplete": "none",
|
|
261
|
+
autoComplete: "off",
|
|
262
|
+
value: displayValue,
|
|
263
|
+
disabled: ctx.isDisabled || props.disabled,
|
|
264
|
+
readOnly: ctx.isReadOnly,
|
|
265
|
+
onChange: handleChange,
|
|
266
|
+
onClick: handleClick,
|
|
267
|
+
onBlur: handleBlur,
|
|
268
|
+
onKeyDown: handleKeyDown,
|
|
269
|
+
onCompositionStart: handleCompositionStart,
|
|
270
|
+
onCompositionEnd: handleCompositionEnd,
|
|
271
|
+
...props
|
|
272
|
+
}
|
|
273
|
+
),
|
|
274
|
+
name ? /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: ctx.value ?? "" }) : null
|
|
275
|
+
] });
|
|
250
276
|
}
|
|
251
277
|
);
|
|
278
|
+
DatePickerInput.displayName = "DatePicker.Input";
|
|
252
279
|
var DatePickerTrigger = react.forwardRef(
|
|
253
280
|
function DatePickerTrigger2({ onClick, children, ...props }, ref) {
|
|
254
281
|
const ctx = useDatePickerContext("DatePicker.Trigger");
|
|
@@ -272,6 +299,7 @@ var DatePickerTrigger = react.forwardRef(
|
|
|
272
299
|
tabIndex: 0,
|
|
273
300
|
"aria-label": ctx.isOpen ? ctx.labels.triggerClose : ctx.labels.triggerOpen,
|
|
274
301
|
"aria-expanded": ctx.isOpen,
|
|
302
|
+
"aria-haspopup": "dialog",
|
|
275
303
|
"aria-controls": ctx.isOpen ? calendarId : void 0,
|
|
276
304
|
disabled: ctx.isDisabled || props.disabled,
|
|
277
305
|
onClick: handleClick,
|
|
@@ -302,6 +330,8 @@ var DatePickerTrigger = react.forwardRef(
|
|
|
302
330
|
);
|
|
303
331
|
}
|
|
304
332
|
);
|
|
333
|
+
DatePickerTrigger.displayName = "DatePicker.Trigger";
|
|
334
|
+
var POPOVER_MIDDLEWARE = [react$1.offset(4), react$1.flip(), react$1.shift({ padding: 8 })];
|
|
305
335
|
function usePopover({
|
|
306
336
|
isOpen,
|
|
307
337
|
close,
|
|
@@ -313,7 +343,7 @@ function usePopover({
|
|
|
313
343
|
const { refs, floatingStyles, isPositioned } = react$1.useFloating({
|
|
314
344
|
open: isOpen,
|
|
315
345
|
placement,
|
|
316
|
-
middleware:
|
|
346
|
+
middleware: POPOVER_MIDDLEWARE,
|
|
317
347
|
whileElementsMounted: react$1.autoUpdate
|
|
318
348
|
});
|
|
319
349
|
react.useEffect(() => {
|
|
@@ -360,6 +390,24 @@ function usePopover({
|
|
|
360
390
|
document.addEventListener("keydown", handleKeyDown);
|
|
361
391
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
362
392
|
}, [isOpen, close]);
|
|
393
|
+
react.useEffect(() => {
|
|
394
|
+
if (!isOpen) return;
|
|
395
|
+
function handleFocusOut(e) {
|
|
396
|
+
const next = e.relatedTarget;
|
|
397
|
+
const floating = floatingRef.current;
|
|
398
|
+
const reference = referenceRef.current;
|
|
399
|
+
if (!next) return;
|
|
400
|
+
const insideFloating = floating?.contains(next) ?? false;
|
|
401
|
+
const insideReference = reference?.contains(next) ?? false;
|
|
402
|
+
if (!insideFloating && !insideReference) {
|
|
403
|
+
close();
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
const node = floatingRef.current;
|
|
407
|
+
if (!node) return;
|
|
408
|
+
node.addEventListener("focusout", handleFocusOut);
|
|
409
|
+
return () => node.removeEventListener("focusout", handleFocusOut);
|
|
410
|
+
}, [isOpen, close, referenceRef]);
|
|
363
411
|
const setFloatingRef = react.useCallback(
|
|
364
412
|
(node) => {
|
|
365
413
|
floatingRef.current = node;
|
|
@@ -421,20 +469,36 @@ var srOnly = {
|
|
|
421
469
|
function DatePickerCalendar({
|
|
422
470
|
classNames,
|
|
423
471
|
onTitleClick,
|
|
472
|
+
showWeekNumber = false,
|
|
473
|
+
fixedWeeks = false,
|
|
424
474
|
...props
|
|
425
475
|
}) {
|
|
426
476
|
const ctx = useDatePickerContext("DatePicker.Calendar");
|
|
427
477
|
const gridRef = react.useRef(null);
|
|
428
478
|
const [announcement, setAnnouncement] = react.useState("");
|
|
429
479
|
const { adapter, viewMonth, focusedDate, weekStartsOn, disabled, locale, displayTimezone } = ctx;
|
|
430
|
-
const weekdays = core.getWeekdayNames(locale, weekStartsOn);
|
|
431
|
-
const weeks =
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
480
|
+
const weekdays = react.useMemo(() => core.getWeekdayNames(locale, weekStartsOn), [locale, weekStartsOn]);
|
|
481
|
+
const weeks = react.useMemo(
|
|
482
|
+
() => core.getCalendarDays(viewMonth, adapter, {
|
|
483
|
+
weekStartsOn,
|
|
484
|
+
selected: ctx.value,
|
|
485
|
+
focusedDate,
|
|
486
|
+
disabled,
|
|
487
|
+
timezone: displayTimezone,
|
|
488
|
+
fixedWeeks
|
|
489
|
+
}),
|
|
490
|
+
[
|
|
491
|
+
viewMonth,
|
|
492
|
+
adapter,
|
|
493
|
+
weekStartsOn,
|
|
494
|
+
ctx.value,
|
|
495
|
+
focusedDate,
|
|
496
|
+
disabled,
|
|
497
|
+
displayTimezone,
|
|
498
|
+
fixedWeeks
|
|
499
|
+
]
|
|
500
|
+
);
|
|
501
|
+
const thursdayIndex = weekStartsOn === 0 ? 4 : 3;
|
|
438
502
|
const year = adapter.getYear(viewMonth);
|
|
439
503
|
const month = adapter.getMonth(viewMonth);
|
|
440
504
|
const title = core.formatMonthYear(year, month, locale);
|
|
@@ -514,6 +578,15 @@ function DatePickerCalendar({
|
|
|
514
578
|
}
|
|
515
579
|
if (newFocused) {
|
|
516
580
|
e.preventDefault();
|
|
581
|
+
const skipStep = e.key === "ArrowLeft" || e.key === "ArrowUp" || e.key === "PageUp" || e.key === "Home" ? -1 : 1;
|
|
582
|
+
let attempts = 0;
|
|
583
|
+
while (core.isDateDisabled(newFocused, disabled, adapter) && attempts < 42) {
|
|
584
|
+
newFocused = adapter.addDays(newFocused, skipStep);
|
|
585
|
+
attempts++;
|
|
586
|
+
}
|
|
587
|
+
if (attempts >= 42) {
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
517
590
|
ctx.setFocusedDate(newFocused);
|
|
518
591
|
if (!adapter.isSameMonth(newFocused, viewMonth)) {
|
|
519
592
|
ctx.setViewMonth(newFocused);
|
|
@@ -561,62 +634,170 @@ function DatePickerCalendar({
|
|
|
561
634
|
ref: gridRef,
|
|
562
635
|
role: "grid",
|
|
563
636
|
"aria-label": title,
|
|
637
|
+
"aria-rowcount": weeks.length + 1,
|
|
638
|
+
"aria-colcount": 7,
|
|
564
639
|
className: classNames?.grid,
|
|
565
640
|
onKeyDown: handleKeyDown,
|
|
566
641
|
children: [
|
|
567
|
-
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.
|
|
568
|
-
"th",
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
abbr: day.full,
|
|
572
|
-
scope: "col",
|
|
573
|
-
className: classNames?.weekdayHeader,
|
|
574
|
-
children: day.short
|
|
575
|
-
},
|
|
576
|
-
day.short
|
|
577
|
-
)) }) }),
|
|
578
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: weeks.map((week, weekIndex) => /* @__PURE__ */ jsxRuntime.jsx("tr", { role: "row", className: classNames?.gridRow, children: week.map((day) => {
|
|
579
|
-
const dayClasses = [
|
|
580
|
-
classNames?.day,
|
|
581
|
-
day.isSelected && classNames?.daySelected,
|
|
582
|
-
day.isToday && classNames?.dayToday,
|
|
583
|
-
day.isDisabled && classNames?.dayDisabled,
|
|
584
|
-
!day.isCurrentMonth && classNames?.dayOutsideMonth
|
|
585
|
-
].filter(Boolean).join(" ") || void 0;
|
|
586
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
587
|
-
"td",
|
|
642
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { role: "row", "aria-rowindex": 1, children: [
|
|
643
|
+
showWeekNumber ? /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", "aria-hidden": "true", className: classNames?.weekNumberHeader, children: "#" }) : null,
|
|
644
|
+
weekdays.map((day, colIndex) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
645
|
+
"th",
|
|
588
646
|
{
|
|
589
|
-
role: "
|
|
590
|
-
|
|
591
|
-
"
|
|
592
|
-
"aria-
|
|
593
|
-
className: classNames?.
|
|
594
|
-
children:
|
|
595
|
-
|
|
647
|
+
role: "columnheader",
|
|
648
|
+
abbr: day.full,
|
|
649
|
+
scope: "col",
|
|
650
|
+
"aria-colindex": colIndex + 1,
|
|
651
|
+
className: classNames?.weekdayHeader,
|
|
652
|
+
children: day.short
|
|
653
|
+
},
|
|
654
|
+
day.short
|
|
655
|
+
))
|
|
656
|
+
] }) }),
|
|
657
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: weeks.map((week, weekIndex) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
658
|
+
"tr",
|
|
659
|
+
{
|
|
660
|
+
role: "row",
|
|
661
|
+
"aria-rowindex": weekIndex + 2,
|
|
662
|
+
className: classNames?.gridRow,
|
|
663
|
+
children: [
|
|
664
|
+
showWeekNumber ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
665
|
+
"th",
|
|
596
666
|
{
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
"data-
|
|
601
|
-
|
|
602
|
-
"data-today": day.isToday || void 0,
|
|
603
|
-
"data-outside-month": !day.isCurrentMonth || void 0,
|
|
604
|
-
className: dayClasses,
|
|
605
|
-
onClick: () => handleDayClick(day),
|
|
606
|
-
"aria-label": safeFormatFullDate(day.isoString, locale),
|
|
607
|
-
children: day.dayNumber
|
|
667
|
+
scope: "row",
|
|
668
|
+
"aria-hidden": "true",
|
|
669
|
+
className: classNames?.weekNumber,
|
|
670
|
+
"data-week-number": true,
|
|
671
|
+
children: core.getISOWeekNumber(week[thursdayIndex].isoString)
|
|
608
672
|
}
|
|
609
|
-
)
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
673
|
+
) : null,
|
|
674
|
+
week.map((day, colIndex) => {
|
|
675
|
+
const dayClasses = [
|
|
676
|
+
classNames?.day,
|
|
677
|
+
day.isSelected && classNames?.daySelected,
|
|
678
|
+
day.isToday && classNames?.dayToday,
|
|
679
|
+
day.isDisabled && classNames?.dayDisabled,
|
|
680
|
+
!day.isCurrentMonth && classNames?.dayOutsideMonth
|
|
681
|
+
].filter(Boolean).join(" ") || void 0;
|
|
682
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
683
|
+
"td",
|
|
684
|
+
{
|
|
685
|
+
role: "gridcell",
|
|
686
|
+
"aria-colindex": colIndex + 1,
|
|
687
|
+
"aria-selected": day.isSelected || void 0,
|
|
688
|
+
"aria-disabled": day.isDisabled || void 0,
|
|
689
|
+
"aria-current": day.isToday ? "date" : void 0,
|
|
690
|
+
className: classNames?.gridCell,
|
|
691
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
692
|
+
"button",
|
|
693
|
+
{
|
|
694
|
+
type: "button",
|
|
695
|
+
tabIndex: day.isFocused ? 0 : -1,
|
|
696
|
+
disabled: day.isDisabled,
|
|
697
|
+
"data-focused": day.isFocused || void 0,
|
|
698
|
+
"data-selected": day.isSelected || void 0,
|
|
699
|
+
"data-today": day.isToday || void 0,
|
|
700
|
+
"data-outside-month": !day.isCurrentMonth || void 0,
|
|
701
|
+
className: dayClasses,
|
|
702
|
+
onClick: () => handleDayClick(day),
|
|
703
|
+
"aria-label": safeFormatFullDate(day.isoString, locale),
|
|
704
|
+
children: day.dayNumber
|
|
705
|
+
}
|
|
706
|
+
)
|
|
707
|
+
},
|
|
708
|
+
day.isoString
|
|
709
|
+
);
|
|
710
|
+
})
|
|
711
|
+
]
|
|
712
|
+
},
|
|
713
|
+
weekIndex
|
|
714
|
+
)) })
|
|
614
715
|
]
|
|
615
716
|
}
|
|
616
717
|
),
|
|
617
718
|
/* @__PURE__ */ jsxRuntime.jsx("div", { role: "status", "aria-live": "polite", "aria-atomic": "true", style: srOnly, children: announcement })
|
|
618
719
|
] });
|
|
619
720
|
}
|
|
721
|
+
function isRangeFullyDisabled(start, end, rules, adapter) {
|
|
722
|
+
for (const rule of rules) {
|
|
723
|
+
if ("before" in rule && adapter.isBefore(end, rule.before)) return true;
|
|
724
|
+
if ("after" in rule && adapter.isAfter(start, rule.after)) return true;
|
|
725
|
+
}
|
|
726
|
+
return false;
|
|
727
|
+
}
|
|
728
|
+
function useGridState(opts) {
|
|
729
|
+
const { initialIndex, disabledFlags, onSelect, onPageUp, onPageDown, onEscape } = opts;
|
|
730
|
+
const gridRef = react.useRef(null);
|
|
731
|
+
const [focusedIndex, setFocusedIndex] = react.useState(initialIndex);
|
|
732
|
+
const handleKeyDown = (e) => {
|
|
733
|
+
let next = null;
|
|
734
|
+
let step = 1;
|
|
735
|
+
switch (e.key) {
|
|
736
|
+
case "ArrowLeft":
|
|
737
|
+
next = Math.max(0, focusedIndex - 1);
|
|
738
|
+
step = -1;
|
|
739
|
+
break;
|
|
740
|
+
case "ArrowRight":
|
|
741
|
+
next = Math.min(11, focusedIndex + 1);
|
|
742
|
+
break;
|
|
743
|
+
case "ArrowUp":
|
|
744
|
+
next = Math.max(0, focusedIndex - 3);
|
|
745
|
+
step = -1;
|
|
746
|
+
break;
|
|
747
|
+
case "ArrowDown":
|
|
748
|
+
next = Math.min(11, focusedIndex + 3);
|
|
749
|
+
break;
|
|
750
|
+
case "Home":
|
|
751
|
+
next = focusedIndex - focusedIndex % 3;
|
|
752
|
+
step = -1;
|
|
753
|
+
break;
|
|
754
|
+
case "End":
|
|
755
|
+
next = focusedIndex - focusedIndex % 3 + 2;
|
|
756
|
+
break;
|
|
757
|
+
case "PageUp":
|
|
758
|
+
e.preventDefault();
|
|
759
|
+
onPageUp();
|
|
760
|
+
return;
|
|
761
|
+
case "PageDown":
|
|
762
|
+
e.preventDefault();
|
|
763
|
+
onPageDown();
|
|
764
|
+
return;
|
|
765
|
+
case "Enter":
|
|
766
|
+
case " ":
|
|
767
|
+
e.preventDefault();
|
|
768
|
+
onSelect(focusedIndex);
|
|
769
|
+
return;
|
|
770
|
+
case "Escape":
|
|
771
|
+
onEscape();
|
|
772
|
+
return;
|
|
773
|
+
default:
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
if (next === null) return;
|
|
777
|
+
e.preventDefault();
|
|
778
|
+
if (disabledFlags) {
|
|
779
|
+
let attempts = 0;
|
|
780
|
+
while (next >= 0 && next < 12 && disabledFlags[next] && attempts < 12) {
|
|
781
|
+
next += step;
|
|
782
|
+
attempts++;
|
|
783
|
+
}
|
|
784
|
+
if (next < 0 || next >= 12 || disabledFlags[next]) return;
|
|
785
|
+
}
|
|
786
|
+
if (next !== focusedIndex) setFocusedIndex(next);
|
|
787
|
+
};
|
|
788
|
+
react.useEffect(() => {
|
|
789
|
+
if (!disabledFlags || !disabledFlags[focusedIndex]) return;
|
|
790
|
+
const firstEnabled = disabledFlags.findIndex((d) => !d);
|
|
791
|
+
if (firstEnabled !== -1 && firstEnabled !== focusedIndex) {
|
|
792
|
+
setFocusedIndex(firstEnabled);
|
|
793
|
+
}
|
|
794
|
+
}, [disabledFlags, focusedIndex]);
|
|
795
|
+
react.useEffect(() => {
|
|
796
|
+
const btn = gridRef.current?.querySelector('[data-focused="true"]');
|
|
797
|
+
btn?.focus({ preventScroll: true });
|
|
798
|
+
}, [focusedIndex]);
|
|
799
|
+
return { gridRef, focusedIndex, handleKeyDown };
|
|
800
|
+
}
|
|
620
801
|
function DatePickerMonthGrid({
|
|
621
802
|
classNames,
|
|
622
803
|
onSelect,
|
|
@@ -624,15 +805,18 @@ function DatePickerMonthGrid({
|
|
|
624
805
|
...props
|
|
625
806
|
}) {
|
|
626
807
|
const ctx = useDatePickerContext("DatePicker.MonthGrid");
|
|
627
|
-
const { adapter, viewMonth, locale } = ctx;
|
|
808
|
+
const { adapter, viewMonth, locale, displayTimezone } = ctx;
|
|
628
809
|
const currentYear = adapter.getYear(viewMonth);
|
|
629
810
|
const currentMonth = adapter.getMonth(viewMonth);
|
|
630
|
-
const
|
|
631
|
-
|
|
811
|
+
const [today, setToday] = react.useState(null);
|
|
812
|
+
react.useEffect(() => {
|
|
813
|
+
setToday(adapter.today(displayTimezone));
|
|
814
|
+
}, [adapter, displayTimezone]);
|
|
815
|
+
const todayMonth = today !== null ? adapter.getMonth(today) : -1;
|
|
816
|
+
const todayYear = today !== null ? adapter.getYear(today) : -1;
|
|
632
817
|
const navigateYear = react.useCallback(
|
|
633
818
|
(direction) => {
|
|
634
|
-
|
|
635
|
-
ctx.setViewMonth(newDate);
|
|
819
|
+
ctx.setViewMonth(adapter.addYears(viewMonth, direction));
|
|
636
820
|
},
|
|
637
821
|
[adapter, viewMonth, ctx]
|
|
638
822
|
);
|
|
@@ -645,12 +829,13 @@ function DatePickerMonthGrid({
|
|
|
645
829
|
},
|
|
646
830
|
[currentYear, ctx, onSelect]
|
|
647
831
|
);
|
|
648
|
-
const
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
832
|
+
const { gridRef, focusedIndex, handleKeyDown } = useGridState({
|
|
833
|
+
initialIndex: currentMonth,
|
|
834
|
+
onSelect: handleMonthSelect,
|
|
835
|
+
onPageUp: () => navigateYear(-1),
|
|
836
|
+
onPageDown: () => navigateYear(1),
|
|
837
|
+
onEscape: ctx.close
|
|
838
|
+
});
|
|
654
839
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classNames?.root, ...props, children: [
|
|
655
840
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: classNames?.header, children: [
|
|
656
841
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -678,30 +863,37 @@ function DatePickerMonthGrid({
|
|
|
678
863
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
679
864
|
"div",
|
|
680
865
|
{
|
|
866
|
+
ref: gridRef,
|
|
681
867
|
role: "grid",
|
|
682
868
|
"aria-label": `${currentYear} months`,
|
|
683
869
|
className: classNames?.grid,
|
|
684
870
|
style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)" },
|
|
685
|
-
|
|
686
|
-
|
|
871
|
+
onKeyDown: handleKeyDown,
|
|
872
|
+
children: Array.from({ length: 12 }, (_, i) => {
|
|
873
|
+
const isSelected = i === currentMonth;
|
|
874
|
+
const isCurrent = i === todayMonth && currentYear === todayYear;
|
|
875
|
+
const isFocused = i === focusedIndex;
|
|
876
|
+
const cls = [
|
|
687
877
|
classNames?.month,
|
|
688
|
-
|
|
689
|
-
|
|
878
|
+
isSelected && classNames?.monthSelected,
|
|
879
|
+
isCurrent && classNames?.monthCurrent
|
|
690
880
|
].filter(Boolean).join(" ") || void 0;
|
|
691
881
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
692
882
|
"button",
|
|
693
883
|
{
|
|
694
884
|
type: "button",
|
|
695
885
|
role: "gridcell",
|
|
696
|
-
|
|
697
|
-
"aria-
|
|
698
|
-
"
|
|
699
|
-
"data-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
886
|
+
tabIndex: isFocused ? 0 : -1,
|
|
887
|
+
"aria-selected": isSelected || void 0,
|
|
888
|
+
"aria-current": isCurrent ? "date" : void 0,
|
|
889
|
+
"data-selected": isSelected || void 0,
|
|
890
|
+
"data-current": isCurrent || void 0,
|
|
891
|
+
"data-focused": isFocused || void 0,
|
|
892
|
+
className: cls,
|
|
893
|
+
onClick: () => handleMonthSelect(i),
|
|
894
|
+
children: core.getMonthName(i, locale)
|
|
703
895
|
},
|
|
704
|
-
|
|
896
|
+
i
|
|
705
897
|
);
|
|
706
898
|
})
|
|
707
899
|
}
|
|
@@ -710,38 +902,38 @@ function DatePickerMonthGrid({
|
|
|
710
902
|
}
|
|
711
903
|
function DatePickerYearGrid({ classNames, onSelect, ...props }) {
|
|
712
904
|
const ctx = useDatePickerContext("DatePicker.YearGrid");
|
|
713
|
-
const { adapter, viewMonth } = ctx;
|
|
905
|
+
const { adapter, viewMonth, displayTimezone } = ctx;
|
|
714
906
|
const currentYear = adapter.getYear(viewMonth);
|
|
715
|
-
const
|
|
907
|
+
const [today, setToday] = react.useState(null);
|
|
908
|
+
react.useEffect(() => {
|
|
909
|
+
setToday(adapter.today(displayTimezone));
|
|
910
|
+
}, [adapter, displayTimezone]);
|
|
911
|
+
const todayYear = today !== null ? adapter.getYear(today) : -1;
|
|
716
912
|
const decadeStart = currentYear - currentYear % 12;
|
|
717
913
|
const navigateDecade = react.useCallback(
|
|
718
914
|
(direction) => {
|
|
719
|
-
|
|
720
|
-
ctx.setViewMonth(newDate);
|
|
915
|
+
ctx.setViewMonth(adapter.addYears(viewMonth, direction * 12));
|
|
721
916
|
},
|
|
722
917
|
[adapter, viewMonth, ctx]
|
|
723
918
|
);
|
|
724
919
|
const handleYearSelect = react.useCallback(
|
|
725
|
-
(
|
|
920
|
+
(indexInDecade) => {
|
|
921
|
+
const year = decadeStart + indexInDecade;
|
|
726
922
|
const currentMonth = adapter.getMonth(viewMonth);
|
|
727
923
|
const target = new Date(Date.UTC(year, currentMonth, 1)).toISOString();
|
|
728
924
|
ctx.setViewMonth(target);
|
|
729
925
|
ctx.setFocusedDate(target);
|
|
730
926
|
onSelect?.();
|
|
731
927
|
},
|
|
732
|
-
[adapter, viewMonth, ctx, onSelect]
|
|
733
|
-
);
|
|
734
|
-
const
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
};
|
|
742
|
-
}),
|
|
743
|
-
[decadeStart, currentYear, todayYear]
|
|
744
|
-
);
|
|
928
|
+
[adapter, viewMonth, ctx, onSelect, decadeStart]
|
|
929
|
+
);
|
|
930
|
+
const { gridRef, focusedIndex, handleKeyDown } = useGridState({
|
|
931
|
+
initialIndex: currentYear - decadeStart,
|
|
932
|
+
onSelect: handleYearSelect,
|
|
933
|
+
onPageUp: () => navigateDecade(-1),
|
|
934
|
+
onPageDown: () => navigateDecade(1),
|
|
935
|
+
onEscape: ctx.close
|
|
936
|
+
});
|
|
745
937
|
const rangeLabel = `${decadeStart}\u2013${decadeStart + 11}`;
|
|
746
938
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classNames?.root, ...props, children: [
|
|
747
939
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: classNames?.header, children: [
|
|
@@ -770,30 +962,38 @@ function DatePickerYearGrid({ classNames, onSelect, ...props }) {
|
|
|
770
962
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
771
963
|
"div",
|
|
772
964
|
{
|
|
965
|
+
ref: gridRef,
|
|
773
966
|
role: "grid",
|
|
774
967
|
"aria-label": rangeLabel,
|
|
775
968
|
className: classNames?.grid,
|
|
776
969
|
style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)" },
|
|
777
|
-
|
|
778
|
-
|
|
970
|
+
onKeyDown: handleKeyDown,
|
|
971
|
+
children: Array.from({ length: 12 }, (_, i) => {
|
|
972
|
+
const year = decadeStart + i;
|
|
973
|
+
const isSelected = year === currentYear;
|
|
974
|
+
const isCurrent = year === todayYear;
|
|
975
|
+
const isFocused = i === focusedIndex;
|
|
976
|
+
const cls = [
|
|
779
977
|
classNames?.year,
|
|
780
|
-
|
|
781
|
-
|
|
978
|
+
isSelected && classNames?.yearSelected,
|
|
979
|
+
isCurrent && classNames?.yearCurrent
|
|
782
980
|
].filter(Boolean).join(" ") || void 0;
|
|
783
981
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
784
982
|
"button",
|
|
785
983
|
{
|
|
786
984
|
type: "button",
|
|
787
985
|
role: "gridcell",
|
|
788
|
-
|
|
789
|
-
"aria-
|
|
790
|
-
"
|
|
791
|
-
"data-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
986
|
+
tabIndex: isFocused ? 0 : -1,
|
|
987
|
+
"aria-selected": isSelected || void 0,
|
|
988
|
+
"aria-current": isCurrent ? "date" : void 0,
|
|
989
|
+
"data-selected": isSelected || void 0,
|
|
990
|
+
"data-current": isCurrent || void 0,
|
|
991
|
+
"data-focused": isFocused || void 0,
|
|
992
|
+
className: cls,
|
|
993
|
+
onClick: () => handleYearSelect(i),
|
|
994
|
+
children: year
|
|
795
995
|
},
|
|
796
|
-
|
|
996
|
+
i
|
|
797
997
|
);
|
|
798
998
|
})
|
|
799
999
|
}
|
|
@@ -866,8 +1066,7 @@ function DatePickerPreset({
|
|
|
866
1066
|
"button",
|
|
867
1067
|
{
|
|
868
1068
|
type: "button",
|
|
869
|
-
|
|
870
|
-
"aria-selected": isActive,
|
|
1069
|
+
"aria-pressed": isActive,
|
|
871
1070
|
"data-active": isActive || void 0,
|
|
872
1071
|
disabled: ctx.isDisabled,
|
|
873
1072
|
onClick: handleClick,
|
|
@@ -904,6 +1103,17 @@ function useRangePickerContext(componentName) {
|
|
|
904
1103
|
return context;
|
|
905
1104
|
}
|
|
906
1105
|
var EMPTY_RANGE = { start: null, end: null };
|
|
1106
|
+
var SR_ONLY = {
|
|
1107
|
+
position: "absolute",
|
|
1108
|
+
width: 1,
|
|
1109
|
+
height: 1,
|
|
1110
|
+
padding: 0,
|
|
1111
|
+
margin: -1,
|
|
1112
|
+
overflow: "hidden",
|
|
1113
|
+
clip: "rect(0, 0, 0, 0)",
|
|
1114
|
+
whiteSpace: "nowrap",
|
|
1115
|
+
border: 0
|
|
1116
|
+
};
|
|
907
1117
|
function RangePickerRoot({
|
|
908
1118
|
value: controlledValue,
|
|
909
1119
|
defaultValue,
|
|
@@ -930,11 +1140,13 @@ function RangePickerRoot({
|
|
|
930
1140
|
const [isOpen, setIsOpen] = react.useState(false);
|
|
931
1141
|
const [selectingTarget, setSelectingTarget] = react.useState("start");
|
|
932
1142
|
const [hoverDate, setHoverDate] = react.useState(null);
|
|
1143
|
+
const [announcement, setAnnouncement] = react.useState("");
|
|
1144
|
+
const announce = react.useCallback((message) => setAnnouncement(message), []);
|
|
933
1145
|
const [viewMonth, setViewMonth] = react.useState(
|
|
934
|
-
currentValue.start ?? adapter.today(displayTimezone)
|
|
1146
|
+
() => currentValue.start ?? adapter.today(displayTimezone)
|
|
935
1147
|
);
|
|
936
1148
|
const [focusedDate, setFocusedDate] = react.useState(
|
|
937
|
-
currentValue.start ?? adapter.today(displayTimezone)
|
|
1149
|
+
() => currentValue.start ?? adapter.today(displayTimezone)
|
|
938
1150
|
);
|
|
939
1151
|
useChangeEffect(isOpen, onOpenChange);
|
|
940
1152
|
const viewMonthStart = react.useMemo(() => adapter.startOfMonth(viewMonth), [viewMonth, adapter]);
|
|
@@ -1032,7 +1244,8 @@ function RangePickerRoot({
|
|
|
1032
1244
|
isDisabled,
|
|
1033
1245
|
isReadOnly: readOnly,
|
|
1034
1246
|
pickerId,
|
|
1035
|
-
labels: mergedLabels
|
|
1247
|
+
labels: mergedLabels,
|
|
1248
|
+
announce
|
|
1036
1249
|
}),
|
|
1037
1250
|
[
|
|
1038
1251
|
currentValue,
|
|
@@ -1055,10 +1268,14 @@ function RangePickerRoot({
|
|
|
1055
1268
|
isDisabled,
|
|
1056
1269
|
readOnly,
|
|
1057
1270
|
pickerId,
|
|
1058
|
-
mergedLabels
|
|
1271
|
+
mergedLabels,
|
|
1272
|
+
announce
|
|
1059
1273
|
]
|
|
1060
1274
|
);
|
|
1061
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
1275
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(RangePickerContext.Provider, { value: contextValue, children: [
|
|
1276
|
+
children,
|
|
1277
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { role: "status", "aria-live": "polite", "aria-atomic": "true", style: SR_ONLY, children: announcement })
|
|
1278
|
+
] });
|
|
1062
1279
|
}
|
|
1063
1280
|
var RangePickerInput = react.forwardRef(
|
|
1064
1281
|
function RangePickerInput2({ part, format: formatProp, onClick, onKeyDown, ...props }, ref) {
|
|
@@ -1084,6 +1301,8 @@ var RangePickerInput = react.forwardRef(
|
|
|
1084
1301
|
(e) => {
|
|
1085
1302
|
if (e.key === "Escape") {
|
|
1086
1303
|
ctx.close();
|
|
1304
|
+
} else if (e.key === "Enter" && ctx.isOpen) {
|
|
1305
|
+
e.preventDefault();
|
|
1087
1306
|
} else if (e.key === "ArrowDown" && !ctx.isOpen) {
|
|
1088
1307
|
e.preventDefault();
|
|
1089
1308
|
ctx.open();
|
|
@@ -1120,6 +1339,7 @@ var RangePickerInput = react.forwardRef(
|
|
|
1120
1339
|
);
|
|
1121
1340
|
}
|
|
1122
1341
|
);
|
|
1342
|
+
RangePickerInput.displayName = "RangePicker.Input";
|
|
1123
1343
|
function RangePickerPopover({ children, ...props }) {
|
|
1124
1344
|
const ctx = useRangePickerContext("RangePicker.Popover");
|
|
1125
1345
|
const calendarId = `${ctx.pickerId}-calendar`;
|
|
@@ -1155,25 +1375,15 @@ function safeFormatFullDate2(iso, locale) {
|
|
|
1155
1375
|
return iso;
|
|
1156
1376
|
}
|
|
1157
1377
|
}
|
|
1158
|
-
var srOnly2 = {
|
|
1159
|
-
position: "absolute",
|
|
1160
|
-
width: "1px",
|
|
1161
|
-
height: "1px",
|
|
1162
|
-
padding: 0,
|
|
1163
|
-
margin: "-1px",
|
|
1164
|
-
overflow: "hidden",
|
|
1165
|
-
clip: "rect(0, 0, 0, 0)",
|
|
1166
|
-
whiteSpace: "nowrap",
|
|
1167
|
-
border: 0
|
|
1168
|
-
};
|
|
1169
1378
|
function RangePickerCalendar({
|
|
1170
1379
|
classNames,
|
|
1171
1380
|
selectionMode = "range",
|
|
1381
|
+
showWeekNumber = false,
|
|
1382
|
+
fixedWeeks = false,
|
|
1172
1383
|
...props
|
|
1173
1384
|
}) {
|
|
1174
1385
|
const ctx = useRangePickerContext("RangePicker.Calendar");
|
|
1175
1386
|
const gridRef = react.useRef(null);
|
|
1176
|
-
const [announcement, setAnnouncement] = react.useState("");
|
|
1177
1387
|
const {
|
|
1178
1388
|
adapter,
|
|
1179
1389
|
viewMonth,
|
|
@@ -1186,15 +1396,30 @@ function RangePickerCalendar({
|
|
|
1186
1396
|
displayTimezone
|
|
1187
1397
|
} = ctx;
|
|
1188
1398
|
const { locale } = ctx;
|
|
1189
|
-
const weekdays = core.getWeekdayNames(locale, weekStartsOn);
|
|
1190
|
-
const weeks =
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1399
|
+
const weekdays = react.useMemo(() => core.getWeekdayNames(locale, weekStartsOn), [locale, weekStartsOn]);
|
|
1400
|
+
const weeks = react.useMemo(
|
|
1401
|
+
() => core.getCalendarDays(viewMonth, adapter, {
|
|
1402
|
+
weekStartsOn,
|
|
1403
|
+
focusedDate,
|
|
1404
|
+
disabled,
|
|
1405
|
+
range: value,
|
|
1406
|
+
rangeHover: hoverDate,
|
|
1407
|
+
timezone: displayTimezone,
|
|
1408
|
+
fixedWeeks
|
|
1409
|
+
}),
|
|
1410
|
+
[
|
|
1411
|
+
viewMonth,
|
|
1412
|
+
adapter,
|
|
1413
|
+
weekStartsOn,
|
|
1414
|
+
focusedDate,
|
|
1415
|
+
disabled,
|
|
1416
|
+
value,
|
|
1417
|
+
hoverDate,
|
|
1418
|
+
displayTimezone,
|
|
1419
|
+
fixedWeeks
|
|
1420
|
+
]
|
|
1421
|
+
);
|
|
1422
|
+
const thursdayIndex = weekStartsOn === 0 ? 4 : 3;
|
|
1198
1423
|
const year = adapter.getYear(viewMonth);
|
|
1199
1424
|
const month = adapter.getMonth(viewMonth);
|
|
1200
1425
|
const title = core.formatMonthYear(year, month, locale);
|
|
@@ -1210,7 +1435,7 @@ function RangePickerCalendar({
|
|
|
1210
1435
|
ctx.setFocusedDate(adapter.startOfMonth(newMonth));
|
|
1211
1436
|
const y = adapter.getYear(newMonth);
|
|
1212
1437
|
const m = adapter.getMonth(newMonth);
|
|
1213
|
-
|
|
1438
|
+
ctx.announce(core.formatMonthYear(y, m, locale));
|
|
1214
1439
|
},
|
|
1215
1440
|
[adapter, viewMonth, ctx, locale]
|
|
1216
1441
|
);
|
|
@@ -1222,15 +1447,27 @@ function RangePickerCalendar({
|
|
|
1222
1447
|
const range = { start: weekStart, end: weekEnd };
|
|
1223
1448
|
ctx.setRange(range);
|
|
1224
1449
|
ctx.close();
|
|
1225
|
-
|
|
1226
|
-
`${safeFormatFullDate2(weekStart, locale)} \u2013 ${safeFormatFullDate2(weekEnd, locale)}`
|
|
1450
|
+
ctx.announce(
|
|
1451
|
+
`${ctx.labels.rangeSelected}: ${safeFormatFullDate2(weekStart, locale)} \u2013 ${safeFormatFullDate2(weekEnd, locale)}`
|
|
1227
1452
|
);
|
|
1228
1453
|
} else {
|
|
1454
|
+
const wasPickingStart = selectingTarget === "start";
|
|
1455
|
+
const previousStart = value.start;
|
|
1229
1456
|
ctx.selectDate(iso);
|
|
1230
|
-
|
|
1457
|
+
const formatted = safeFormatFullDate2(iso, locale);
|
|
1458
|
+
if (wasPickingStart) {
|
|
1459
|
+
ctx.announce(`${formatted}. ${ctx.labels.selectingEnd}`);
|
|
1460
|
+
} else if (previousStart) {
|
|
1461
|
+
const [start, end] = adapter.isBefore(iso, previousStart) ? [iso, previousStart] : [previousStart, iso];
|
|
1462
|
+
ctx.announce(
|
|
1463
|
+
`${ctx.labels.rangeSelected}: ${safeFormatFullDate2(start, locale)} \u2013 ${safeFormatFullDate2(end, locale)}`
|
|
1464
|
+
);
|
|
1465
|
+
} else {
|
|
1466
|
+
ctx.announce(formatted);
|
|
1467
|
+
}
|
|
1231
1468
|
}
|
|
1232
1469
|
},
|
|
1233
|
-
[selectionMode, adapter, weekStartsOn, ctx, locale]
|
|
1470
|
+
[selectionMode, adapter, weekStartsOn, ctx, locale, selectingTarget, value.start]
|
|
1234
1471
|
);
|
|
1235
1472
|
const handleDayClick = react.useCallback(
|
|
1236
1473
|
(day) => {
|
|
@@ -1294,6 +1531,13 @@ function RangePickerCalendar({
|
|
|
1294
1531
|
}
|
|
1295
1532
|
if (newFocused) {
|
|
1296
1533
|
e.preventDefault();
|
|
1534
|
+
const skipStep = e.key === "ArrowLeft" || e.key === "ArrowUp" || e.key === "PageUp" || e.key === "Home" ? -1 : 1;
|
|
1535
|
+
let attempts = 0;
|
|
1536
|
+
while (core.isDateDisabled(newFocused, disabled, adapter) && attempts < 42) {
|
|
1537
|
+
newFocused = adapter.addDays(newFocused, skipStep);
|
|
1538
|
+
attempts++;
|
|
1539
|
+
}
|
|
1540
|
+
if (attempts >= 42) return;
|
|
1297
1541
|
ctx.setFocusedDate(newFocused);
|
|
1298
1542
|
if (!adapter.isSameMonth(newFocused, viewMonth)) {
|
|
1299
1543
|
ctx.setViewMonth(newFocused);
|
|
@@ -1346,67 +1590,93 @@ function RangePickerCalendar({
|
|
|
1346
1590
|
ref: gridRef,
|
|
1347
1591
|
role: "grid",
|
|
1348
1592
|
"aria-label": title,
|
|
1349
|
-
"aria-
|
|
1593
|
+
"aria-rowcount": weeks.length + 1,
|
|
1594
|
+
"aria-colcount": 7,
|
|
1350
1595
|
className: classNames?.grid,
|
|
1351
1596
|
onKeyDown: handleKeyDown,
|
|
1352
1597
|
children: [
|
|
1353
|
-
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.
|
|
1354
|
-
"th",
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
abbr: day.full,
|
|
1358
|
-
scope: "col",
|
|
1359
|
-
className: classNames?.weekdayHeader,
|
|
1360
|
-
children: day.short
|
|
1361
|
-
},
|
|
1362
|
-
day.short
|
|
1363
|
-
)) }) }),
|
|
1364
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: weeks.map((week, weekIndex) => /* @__PURE__ */ jsxRuntime.jsx("tr", { role: "row", className: classNames?.gridRow, children: week.map((day) => {
|
|
1365
|
-
const dayClasses = [
|
|
1366
|
-
classNames?.day,
|
|
1367
|
-
day.isRangeStart && classNames?.dayRangeStart,
|
|
1368
|
-
day.isRangeEnd && classNames?.dayRangeEnd,
|
|
1369
|
-
day.isInRange && classNames?.dayInRange,
|
|
1370
|
-
day.isToday && classNames?.dayToday,
|
|
1371
|
-
day.isDisabled && classNames?.dayDisabled,
|
|
1372
|
-
!day.isCurrentMonth && classNames?.dayOutsideMonth
|
|
1373
|
-
].filter(Boolean).join(" ") || void 0;
|
|
1374
|
-
const isSelected = selectionMode === "week" ? day.isRangeStart || day.isRangeEnd || day.isInRange : day.isRangeStart || day.isRangeEnd;
|
|
1375
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1376
|
-
"td",
|
|
1598
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { role: "row", "aria-rowindex": 1, children: [
|
|
1599
|
+
showWeekNumber ? /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", "aria-hidden": "true", className: classNames?.weekNumberHeader, children: "#" }) : null,
|
|
1600
|
+
weekdays.map((day, colIndex) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1601
|
+
"th",
|
|
1377
1602
|
{
|
|
1378
|
-
role: "
|
|
1379
|
-
|
|
1380
|
-
"
|
|
1381
|
-
"aria-
|
|
1382
|
-
className: classNames?.
|
|
1383
|
-
children:
|
|
1384
|
-
|
|
1603
|
+
role: "columnheader",
|
|
1604
|
+
abbr: day.full,
|
|
1605
|
+
scope: "col",
|
|
1606
|
+
"aria-colindex": colIndex + 1,
|
|
1607
|
+
className: classNames?.weekdayHeader,
|
|
1608
|
+
children: day.short
|
|
1609
|
+
},
|
|
1610
|
+
day.short
|
|
1611
|
+
))
|
|
1612
|
+
] }) }),
|
|
1613
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: weeks.map((week, weekIndex) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1614
|
+
"tr",
|
|
1615
|
+
{
|
|
1616
|
+
role: "row",
|
|
1617
|
+
"aria-rowindex": weekIndex + 2,
|
|
1618
|
+
className: classNames?.gridRow,
|
|
1619
|
+
children: [
|
|
1620
|
+
showWeekNumber ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1621
|
+
"th",
|
|
1385
1622
|
{
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
"data-
|
|
1390
|
-
|
|
1391
|
-
"data-range-end": day.isRangeEnd || void 0,
|
|
1392
|
-
"data-in-range": day.isInRange || void 0,
|
|
1393
|
-
"data-today": day.isToday || void 0,
|
|
1394
|
-
"data-outside-month": !day.isCurrentMonth || void 0,
|
|
1395
|
-
className: dayClasses,
|
|
1396
|
-
onClick: () => handleDayClick(day),
|
|
1397
|
-
onMouseEnter: () => handleDayMouseEnter(day),
|
|
1398
|
-
"aria-label": safeFormatFullDate2(day.isoString, locale),
|
|
1399
|
-
children: day.dayNumber
|
|
1623
|
+
scope: "row",
|
|
1624
|
+
"aria-hidden": "true",
|
|
1625
|
+
className: classNames?.weekNumber,
|
|
1626
|
+
"data-week-number": true,
|
|
1627
|
+
children: core.getISOWeekNumber(week[thursdayIndex].isoString)
|
|
1400
1628
|
}
|
|
1401
|
-
)
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1629
|
+
) : null,
|
|
1630
|
+
week.map((day, colIndex) => {
|
|
1631
|
+
const dayClasses = [
|
|
1632
|
+
classNames?.day,
|
|
1633
|
+
day.isRangeStart && classNames?.dayRangeStart,
|
|
1634
|
+
day.isRangeEnd && classNames?.dayRangeEnd,
|
|
1635
|
+
day.isInRange && classNames?.dayInRange,
|
|
1636
|
+
day.isToday && classNames?.dayToday,
|
|
1637
|
+
day.isDisabled && classNames?.dayDisabled,
|
|
1638
|
+
!day.isCurrentMonth && classNames?.dayOutsideMonth
|
|
1639
|
+
].filter(Boolean).join(" ") || void 0;
|
|
1640
|
+
const isSelected = selectionMode === "week" ? day.isRangeStart || day.isRangeEnd || day.isInRange : day.isRangeStart || day.isRangeEnd;
|
|
1641
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1642
|
+
"td",
|
|
1643
|
+
{
|
|
1644
|
+
role: "gridcell",
|
|
1645
|
+
"aria-colindex": colIndex + 1,
|
|
1646
|
+
"aria-selected": isSelected || void 0,
|
|
1647
|
+
"aria-disabled": day.isDisabled || void 0,
|
|
1648
|
+
"aria-current": day.isToday ? "date" : void 0,
|
|
1649
|
+
className: classNames?.gridCell,
|
|
1650
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1651
|
+
"button",
|
|
1652
|
+
{
|
|
1653
|
+
type: "button",
|
|
1654
|
+
tabIndex: day.isFocused ? 0 : -1,
|
|
1655
|
+
disabled: day.isDisabled,
|
|
1656
|
+
"data-focused": day.isFocused || void 0,
|
|
1657
|
+
"data-range-start": day.isRangeStart || void 0,
|
|
1658
|
+
"data-range-end": day.isRangeEnd || void 0,
|
|
1659
|
+
"data-in-range": day.isInRange || void 0,
|
|
1660
|
+
"data-today": day.isToday || void 0,
|
|
1661
|
+
"data-outside-month": !day.isCurrentMonth || void 0,
|
|
1662
|
+
className: dayClasses,
|
|
1663
|
+
onClick: () => handleDayClick(day),
|
|
1664
|
+
onMouseEnter: () => handleDayMouseEnter(day),
|
|
1665
|
+
"aria-label": safeFormatFullDate2(day.isoString, locale),
|
|
1666
|
+
children: day.dayNumber
|
|
1667
|
+
}
|
|
1668
|
+
)
|
|
1669
|
+
},
|
|
1670
|
+
day.isoString
|
|
1671
|
+
);
|
|
1672
|
+
})
|
|
1673
|
+
]
|
|
1674
|
+
},
|
|
1675
|
+
weekIndex
|
|
1676
|
+
)) })
|
|
1406
1677
|
]
|
|
1407
1678
|
}
|
|
1408
|
-
)
|
|
1409
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { role: "status", "aria-live": "polite", "aria-atomic": "true", style: srOnly2, children: announcement })
|
|
1679
|
+
)
|
|
1410
1680
|
] });
|
|
1411
1681
|
}
|
|
1412
1682
|
function RangePickerPresets({ classNames, children, ...props }) {
|
|
@@ -1464,41 +1734,33 @@ function RangePickerPreset({
|
|
|
1464
1734
|
...props
|
|
1465
1735
|
}) {
|
|
1466
1736
|
const ctx = useRangePickerContext("RangePicker.Preset");
|
|
1737
|
+
const resolved = react.useMemo(() => {
|
|
1738
|
+
if (directRange) return directRange;
|
|
1739
|
+
if (presetKey)
|
|
1740
|
+
return resolvePreset(presetKey, ctx.adapter.today(ctx.displayTimezone), ctx.adapter);
|
|
1741
|
+
return null;
|
|
1742
|
+
}, [directRange, presetKey, ctx.adapter, ctx.displayTimezone]);
|
|
1467
1743
|
const handleClick = react.useCallback(
|
|
1468
1744
|
(e) => {
|
|
1469
1745
|
if (ctx.isDisabled || ctx.isReadOnly) return;
|
|
1470
|
-
|
|
1471
|
-
if (directRange) {
|
|
1472
|
-
resolved = directRange;
|
|
1473
|
-
} else if (presetKey) {
|
|
1474
|
-
resolved = resolvePreset(presetKey, ctx.adapter.today(), ctx.adapter);
|
|
1475
|
-
} else {
|
|
1476
|
-
return;
|
|
1477
|
-
}
|
|
1746
|
+
if (!resolved) return;
|
|
1478
1747
|
ctx.setRange(resolved);
|
|
1479
1748
|
ctx.close();
|
|
1480
1749
|
onClick?.(e);
|
|
1481
1750
|
},
|
|
1482
|
-
[ctx,
|
|
1751
|
+
[ctx, resolved, onClick]
|
|
1483
1752
|
);
|
|
1484
|
-
const isActive = (() => {
|
|
1485
|
-
if (!ctx.value.start || !ctx.value.end)
|
|
1486
|
-
let target;
|
|
1487
|
-
if (directRange) {
|
|
1488
|
-
target = directRange;
|
|
1489
|
-
} else if (presetKey) {
|
|
1490
|
-
target = resolvePreset(presetKey, ctx.adapter.today(), ctx.adapter);
|
|
1491
|
-
} else {
|
|
1753
|
+
const isActive = react.useMemo(() => {
|
|
1754
|
+
if (!ctx.value.start || !ctx.value.end || !resolved || !resolved.start || !resolved.end) {
|
|
1492
1755
|
return false;
|
|
1493
1756
|
}
|
|
1494
|
-
return
|
|
1495
|
-
})
|
|
1757
|
+
return ctx.adapter.isSameDay(ctx.value.start, resolved.start) && ctx.adapter.isSameDay(ctx.value.end, resolved.end);
|
|
1758
|
+
}, [ctx.value.start, ctx.value.end, ctx.adapter, resolved]);
|
|
1496
1759
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1497
1760
|
"button",
|
|
1498
1761
|
{
|
|
1499
1762
|
type: "button",
|
|
1500
|
-
|
|
1501
|
-
"aria-selected": isActive,
|
|
1763
|
+
"aria-pressed": isActive,
|
|
1502
1764
|
"data-active": isActive || void 0,
|
|
1503
1765
|
disabled: ctx.isDisabled,
|
|
1504
1766
|
onClick: handleClick,
|
|
@@ -1531,9 +1793,6 @@ function useTimePickerContext(componentName) {
|
|
|
1531
1793
|
}
|
|
1532
1794
|
return context;
|
|
1533
1795
|
}
|
|
1534
|
-
function getDefaultIso() {
|
|
1535
|
-
return core.DateFnsAdapter.today();
|
|
1536
|
-
}
|
|
1537
1796
|
function TimePickerRoot({
|
|
1538
1797
|
value: controlledValue,
|
|
1539
1798
|
defaultValue,
|
|
@@ -1544,6 +1803,7 @@ function TimePickerRoot({
|
|
|
1544
1803
|
displayTimezone,
|
|
1545
1804
|
disabled = false,
|
|
1546
1805
|
readOnly = false,
|
|
1806
|
+
filterTime,
|
|
1547
1807
|
labels: labelsProp,
|
|
1548
1808
|
children
|
|
1549
1809
|
}) {
|
|
@@ -1557,21 +1817,21 @@ function TimePickerRoot({
|
|
|
1557
1817
|
defaultValue ?? null
|
|
1558
1818
|
);
|
|
1559
1819
|
const currentValue = isControlled ? controlledValue ?? null : uncontrolledValue;
|
|
1560
|
-
const
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
);
|
|
1820
|
+
const currentTime = react.useMemo(() => {
|
|
1821
|
+
if (!currentValue) return { hours: 0, minutes: 0, seconds: 0 };
|
|
1822
|
+
return displayTimezone ? core.getTimeInTimezone(currentValue, displayTimezone) : core.getTime(currentValue);
|
|
1823
|
+
}, [currentValue, displayTimezone]);
|
|
1565
1824
|
const setTime = react.useCallback(
|
|
1566
1825
|
(partial) => {
|
|
1567
1826
|
if (disabled || readOnly) return;
|
|
1568
|
-
const
|
|
1827
|
+
const base = currentValue ?? core.DateFnsAdapter.today(displayTimezone);
|
|
1828
|
+
const newIso = displayTimezone ? core.setTimeInTimezone(base, partial, displayTimezone) : core.setTime(base, partial);
|
|
1569
1829
|
if (!isControlled) {
|
|
1570
1830
|
setUncontrolledValue(newIso);
|
|
1571
1831
|
}
|
|
1572
1832
|
onChange?.(newIso);
|
|
1573
1833
|
},
|
|
1574
|
-
[disabled, readOnly,
|
|
1834
|
+
[disabled, readOnly, currentValue, displayTimezone, isControlled, onChange]
|
|
1575
1835
|
);
|
|
1576
1836
|
const contextValue = react.useMemo(
|
|
1577
1837
|
() => ({
|
|
@@ -1585,7 +1845,8 @@ function TimePickerRoot({
|
|
|
1585
1845
|
isReadOnly: readOnly,
|
|
1586
1846
|
currentTime,
|
|
1587
1847
|
pickerId,
|
|
1588
|
-
labels: mergedLabels
|
|
1848
|
+
labels: mergedLabels,
|
|
1849
|
+
filterTime
|
|
1589
1850
|
}),
|
|
1590
1851
|
[
|
|
1591
1852
|
currentValue,
|
|
@@ -1598,7 +1859,8 @@ function TimePickerRoot({
|
|
|
1598
1859
|
readOnly,
|
|
1599
1860
|
currentTime,
|
|
1600
1861
|
pickerId,
|
|
1601
|
-
mergedLabels
|
|
1862
|
+
mergedLabels,
|
|
1863
|
+
filterTime
|
|
1602
1864
|
]
|
|
1603
1865
|
);
|
|
1604
1866
|
return /* @__PURE__ */ jsxRuntime.jsx(TimePickerContext.Provider, { value: contextValue, children });
|
|
@@ -1607,6 +1869,9 @@ var TimePickerInput = react.forwardRef(
|
|
|
1607
1869
|
function TimePickerInput2({ onBlur, onKeyDown, ...props }, ref) {
|
|
1608
1870
|
const ctx = useTimePickerContext("TimePicker.Input");
|
|
1609
1871
|
const [inputText, setInputText] = react.useState(null);
|
|
1872
|
+
react.useEffect(() => {
|
|
1873
|
+
setInputText(null);
|
|
1874
|
+
}, [ctx.value]);
|
|
1610
1875
|
const displayValue = inputText !== null ? inputText : core.formatTimeString(ctx.currentTime, ctx.withSeconds);
|
|
1611
1876
|
const commitInput = react.useCallback(() => {
|
|
1612
1877
|
if (inputText === null) return;
|
|
@@ -1655,6 +1920,7 @@ var TimePickerInput = react.forwardRef(
|
|
|
1655
1920
|
);
|
|
1656
1921
|
}
|
|
1657
1922
|
);
|
|
1923
|
+
TimePickerInput.displayName = "TimePicker.Input";
|
|
1658
1924
|
function useListboxNavigation({
|
|
1659
1925
|
items,
|
|
1660
1926
|
onSelect,
|
|
@@ -1702,17 +1968,41 @@ function useListboxNavigation({
|
|
|
1702
1968
|
}
|
|
1703
1969
|
function TimePickerHourList({ classNames, ...props }) {
|
|
1704
1970
|
const ctx = useTimePickerContext("TimePicker.HourList");
|
|
1705
|
-
const { format, currentTime, isDisabled, isReadOnly } = ctx;
|
|
1706
|
-
const hours = core.generateHours(format);
|
|
1971
|
+
const { format, step, currentTime, isDisabled, isReadOnly, filterTime } = ctx;
|
|
1972
|
+
const hours = react.useMemo(() => core.generateHours(format), [format]);
|
|
1707
1973
|
const selectedHourDisplay = format === "12h" ? core.to12Hour(currentTime.hours).hours12 : currentTime.hours;
|
|
1708
1974
|
const currentPeriod = format === "12h" ? core.to12Hour(currentTime.hours).period : null;
|
|
1975
|
+
const fullyDisabledHours24 = react.useMemo(() => {
|
|
1976
|
+
if (!filterTime) return null;
|
|
1977
|
+
const disabled = /* @__PURE__ */ new Set();
|
|
1978
|
+
for (let h = 0; h < 24; h++) {
|
|
1979
|
+
let allRejected = true;
|
|
1980
|
+
for (let m = 0; m < 60; m += step) {
|
|
1981
|
+
if (!filterTime(h, m)) {
|
|
1982
|
+
allRejected = false;
|
|
1983
|
+
break;
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
if (allRejected) disabled.add(h);
|
|
1987
|
+
}
|
|
1988
|
+
return disabled;
|
|
1989
|
+
}, [filterTime, step]);
|
|
1990
|
+
const isHourDisabled = react.useCallback(
|
|
1991
|
+
(hourDisplay) => {
|
|
1992
|
+
if (!fullyDisabledHours24) return false;
|
|
1993
|
+
const hours24 = format === "12h" && currentPeriod ? core.to24Hour(hourDisplay, currentPeriod) : hourDisplay;
|
|
1994
|
+
return fullyDisabledHours24.has(hours24);
|
|
1995
|
+
},
|
|
1996
|
+
[fullyDisabledHours24, format, currentPeriod]
|
|
1997
|
+
);
|
|
1709
1998
|
const handleSelect = react.useCallback(
|
|
1710
1999
|
(hourDisplay) => {
|
|
1711
2000
|
if (isDisabled || isReadOnly) return;
|
|
2001
|
+
if (isHourDisabled(hourDisplay)) return;
|
|
1712
2002
|
const hours24 = format === "12h" && currentPeriod ? core.to24Hour(hourDisplay, currentPeriod) : hourDisplay;
|
|
1713
2003
|
ctx.setTime({ hours: hours24 });
|
|
1714
2004
|
},
|
|
1715
|
-
[format, currentPeriod, ctx, isDisabled, isReadOnly]
|
|
2005
|
+
[format, currentPeriod, ctx, isDisabled, isReadOnly, isHourDisabled]
|
|
1716
2006
|
);
|
|
1717
2007
|
const { listRef, handleKeyDown } = useListboxNavigation({
|
|
1718
2008
|
items: hours,
|
|
@@ -1730,13 +2020,14 @@ function TimePickerHourList({ classNames, ...props }) {
|
|
|
1730
2020
|
...props,
|
|
1731
2021
|
children: hours.map((hour) => {
|
|
1732
2022
|
const isSelected = hour === selectedHourDisplay;
|
|
2023
|
+
const isHourFullyDisabled = isHourDisabled(hour);
|
|
1733
2024
|
const optionClass = [classNames?.option, isSelected && classNames?.optionSelected].filter(Boolean).join(" ") || void 0;
|
|
1734
2025
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1735
2026
|
"li",
|
|
1736
2027
|
{
|
|
1737
2028
|
role: "option",
|
|
1738
2029
|
"aria-selected": isSelected,
|
|
1739
|
-
"aria-disabled": isDisabled || void 0,
|
|
2030
|
+
"aria-disabled": isDisabled || isHourFullyDisabled || void 0,
|
|
1740
2031
|
"aria-label": ctx.labels.hourOption(hour),
|
|
1741
2032
|
"data-selected": isSelected || void 0,
|
|
1742
2033
|
tabIndex: isSelected ? 0 : -1,
|
|
@@ -1753,14 +2044,22 @@ function TimePickerHourList({ classNames, ...props }) {
|
|
|
1753
2044
|
}
|
|
1754
2045
|
function TimePickerMinuteList({ classNames, ...props }) {
|
|
1755
2046
|
const ctx = useTimePickerContext("TimePicker.MinuteList");
|
|
1756
|
-
const { step, currentTime, isDisabled, isReadOnly } = ctx;
|
|
1757
|
-
const minutes = core.generateMinutes(step);
|
|
2047
|
+
const { step, currentTime, isDisabled, isReadOnly, filterTime } = ctx;
|
|
2048
|
+
const minutes = react.useMemo(() => core.generateMinutes(step), [step]);
|
|
2049
|
+
const isMinuteDisabled = react.useCallback(
|
|
2050
|
+
(minute) => {
|
|
2051
|
+
if (!filterTime) return false;
|
|
2052
|
+
return filterTime(currentTime.hours, minute);
|
|
2053
|
+
},
|
|
2054
|
+
[filterTime, currentTime.hours]
|
|
2055
|
+
);
|
|
1758
2056
|
const handleSelect = react.useCallback(
|
|
1759
2057
|
(minute) => {
|
|
1760
2058
|
if (isDisabled || isReadOnly) return;
|
|
2059
|
+
if (isMinuteDisabled(minute)) return;
|
|
1761
2060
|
ctx.setTime({ minutes: minute });
|
|
1762
2061
|
},
|
|
1763
|
-
[ctx, isDisabled, isReadOnly]
|
|
2062
|
+
[ctx, isDisabled, isReadOnly, isMinuteDisabled]
|
|
1764
2063
|
);
|
|
1765
2064
|
const { listRef, handleKeyDown } = useListboxNavigation({
|
|
1766
2065
|
items: minutes,
|
|
@@ -1778,13 +2077,14 @@ function TimePickerMinuteList({ classNames, ...props }) {
|
|
|
1778
2077
|
...props,
|
|
1779
2078
|
children: minutes.map((minute) => {
|
|
1780
2079
|
const isSelected = minute === currentTime.minutes;
|
|
2080
|
+
const isMinuteFullyDisabled = isMinuteDisabled(minute);
|
|
1781
2081
|
const optionClass = [classNames?.option, isSelected && classNames?.optionSelected].filter(Boolean).join(" ") || void 0;
|
|
1782
2082
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1783
2083
|
"li",
|
|
1784
2084
|
{
|
|
1785
2085
|
role: "option",
|
|
1786
2086
|
"aria-selected": isSelected,
|
|
1787
|
-
"aria-disabled": isDisabled || void 0,
|
|
2087
|
+
"aria-disabled": isDisabled || isMinuteFullyDisabled || void 0,
|
|
1788
2088
|
"aria-label": ctx.labels.minuteOption(minute),
|
|
1789
2089
|
"data-selected": isSelected || void 0,
|
|
1790
2090
|
tabIndex: isSelected ? 0 : -1,
|
|
@@ -1801,29 +2101,70 @@ function TimePickerMinuteList({ classNames, ...props }) {
|
|
|
1801
2101
|
}
|
|
1802
2102
|
function TimePickerAmPmToggle({ classNames, ...props }) {
|
|
1803
2103
|
const ctx = useTimePickerContext("TimePicker.AmPmToggle");
|
|
1804
|
-
|
|
1805
|
-
const
|
|
2104
|
+
const amRef = react.useRef(null);
|
|
2105
|
+
const pmRef = react.useRef(null);
|
|
1806
2106
|
const setPeriod = react.useCallback(
|
|
1807
2107
|
(newPeriod) => {
|
|
1808
2108
|
if (ctx.isDisabled || ctx.isReadOnly) return;
|
|
2109
|
+
const { hours12 } = core.to12Hour(ctx.currentTime.hours);
|
|
1809
2110
|
const newHours24 = core.to24Hour(hours12, newPeriod);
|
|
1810
2111
|
ctx.setTime({ hours: newHours24 });
|
|
1811
2112
|
},
|
|
1812
|
-
[
|
|
2113
|
+
[ctx]
|
|
1813
2114
|
);
|
|
2115
|
+
if (ctx.format !== "12h") return null;
|
|
2116
|
+
const { period } = core.to12Hour(ctx.currentTime.hours);
|
|
2117
|
+
const focusOther = (target) => {
|
|
2118
|
+
(target === "AM" ? amRef : pmRef).current?.focus();
|
|
2119
|
+
};
|
|
2120
|
+
const handleKeyDown = (e, target) => {
|
|
2121
|
+
switch (e.key) {
|
|
2122
|
+
case "ArrowRight":
|
|
2123
|
+
case "ArrowDown":
|
|
2124
|
+
case "ArrowLeft":
|
|
2125
|
+
case "ArrowUp": {
|
|
2126
|
+
e.preventDefault();
|
|
2127
|
+
const next = target === "AM" ? "PM" : "AM";
|
|
2128
|
+
setPeriod(next);
|
|
2129
|
+
focusOther(next);
|
|
2130
|
+
break;
|
|
2131
|
+
}
|
|
2132
|
+
case "Home": {
|
|
2133
|
+
e.preventDefault();
|
|
2134
|
+
setPeriod("AM");
|
|
2135
|
+
focusOther("AM");
|
|
2136
|
+
break;
|
|
2137
|
+
}
|
|
2138
|
+
case "End": {
|
|
2139
|
+
e.preventDefault();
|
|
2140
|
+
setPeriod("PM");
|
|
2141
|
+
focusOther("PM");
|
|
2142
|
+
break;
|
|
2143
|
+
}
|
|
2144
|
+
case " ":
|
|
2145
|
+
case "Enter": {
|
|
2146
|
+
e.preventDefault();
|
|
2147
|
+
setPeriod(target);
|
|
2148
|
+
break;
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
};
|
|
1814
2152
|
const renderButton = (target) => {
|
|
1815
2153
|
const isSelected = period === target;
|
|
1816
2154
|
const optionClass = [classNames?.option, isSelected && classNames?.optionSelected].filter(Boolean).join(" ") || void 0;
|
|
1817
2155
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1818
2156
|
"button",
|
|
1819
2157
|
{
|
|
2158
|
+
ref: target === "AM" ? amRef : pmRef,
|
|
1820
2159
|
type: "button",
|
|
1821
2160
|
role: "radio",
|
|
1822
2161
|
"aria-checked": isSelected,
|
|
2162
|
+
tabIndex: isSelected ? 0 : -1,
|
|
1823
2163
|
"data-selected": isSelected || void 0,
|
|
1824
2164
|
disabled: ctx.isDisabled,
|
|
1825
2165
|
className: optionClass,
|
|
1826
2166
|
onClick: () => setPeriod(target),
|
|
2167
|
+
onKeyDown: (e) => handleKeyDown(e, target),
|
|
1827
2168
|
children: target
|
|
1828
2169
|
}
|
|
1829
2170
|
);
|
|
@@ -1850,9 +2191,6 @@ var TimePicker = Object.assign(TimePickerRoot, {
|
|
|
1850
2191
|
MinuteList: TimePickerMinuteList,
|
|
1851
2192
|
AmPmToggle: TimePickerAmPmToggle
|
|
1852
2193
|
});
|
|
1853
|
-
function getDefaultIso2() {
|
|
1854
|
-
return core.DateFnsAdapter.today();
|
|
1855
|
-
}
|
|
1856
2194
|
function DateTimePickerRoot({
|
|
1857
2195
|
value: controlledValue,
|
|
1858
2196
|
defaultValue,
|
|
@@ -1861,6 +2199,8 @@ function DateTimePickerRoot({
|
|
|
1861
2199
|
onCalendarNavigate,
|
|
1862
2200
|
format = "24h",
|
|
1863
2201
|
step = 1,
|
|
2202
|
+
withSeconds = false,
|
|
2203
|
+
filterTime,
|
|
1864
2204
|
disabled = false,
|
|
1865
2205
|
readOnly = false,
|
|
1866
2206
|
weekStartsOn = 0,
|
|
@@ -1888,10 +2228,10 @@ function DateTimePickerRoot({
|
|
|
1888
2228
|
const currentValue = isControlled ? controlledValue ?? null : uncontrolledValue;
|
|
1889
2229
|
const [isOpen, setIsOpen] = react.useState(false);
|
|
1890
2230
|
const [viewMonth, setViewMonth] = react.useState(
|
|
1891
|
-
currentValue ?? adapter.today(displayTimezone)
|
|
2231
|
+
() => currentValue ?? adapter.today(displayTimezone)
|
|
1892
2232
|
);
|
|
1893
2233
|
const [focusedDate, setFocusedDate] = react.useState(
|
|
1894
|
-
currentValue ?? adapter.today(displayTimezone)
|
|
2234
|
+
() => currentValue ?? adapter.today(displayTimezone)
|
|
1895
2235
|
);
|
|
1896
2236
|
useChangeEffect(isOpen, onOpenChange);
|
|
1897
2237
|
const viewMonthStart = react.useMemo(() => adapter.startOfMonth(viewMonth), [viewMonth, adapter]);
|
|
@@ -1901,11 +2241,10 @@ function DateTimePickerRoot({
|
|
|
1901
2241
|
() => Array.isArray(disabled) ? disabled : [],
|
|
1902
2242
|
[disabled]
|
|
1903
2243
|
);
|
|
1904
|
-
const
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
);
|
|
2244
|
+
const currentTime = react.useMemo(() => {
|
|
2245
|
+
if (!currentValue) return { hours: 0, minutes: 0, seconds: 0 };
|
|
2246
|
+
return displayTimezone ? core.getTimeInTimezone(currentValue, displayTimezone) : core.getTime(currentValue);
|
|
2247
|
+
}, [currentValue, displayTimezone]);
|
|
1909
2248
|
const updateValue = react.useCallback(
|
|
1910
2249
|
(next) => {
|
|
1911
2250
|
if (isDisabled || readOnly) return;
|
|
@@ -1931,11 +2270,11 @@ function DateTimePickerRoot({
|
|
|
1931
2270
|
);
|
|
1932
2271
|
const setTime = react.useCallback(
|
|
1933
2272
|
(partial) => {
|
|
1934
|
-
const base = currentValue ??
|
|
2273
|
+
const base = currentValue ?? adapter.today(displayTimezone);
|
|
1935
2274
|
const merged = displayTimezone ? core.setTimeInTimezone(base, partial, displayTimezone) : core.setTime(base, partial);
|
|
1936
2275
|
updateValue(merged);
|
|
1937
2276
|
},
|
|
1938
|
-
[currentValue, updateValue, displayTimezone]
|
|
2277
|
+
[currentValue, updateValue, displayTimezone, adapter]
|
|
1939
2278
|
);
|
|
1940
2279
|
const open = react.useCallback(() => {
|
|
1941
2280
|
if (isDisabled || readOnly) return;
|
|
@@ -2002,25 +2341,28 @@ function DateTimePickerRoot({
|
|
|
2002
2341
|
setTime,
|
|
2003
2342
|
format,
|
|
2004
2343
|
step,
|
|
2005
|
-
withSeconds
|
|
2344
|
+
withSeconds,
|
|
2006
2345
|
displayTimezone,
|
|
2007
2346
|
isDisabled,
|
|
2008
2347
|
isReadOnly: readOnly,
|
|
2009
2348
|
currentTime,
|
|
2010
2349
|
pickerId,
|
|
2011
|
-
labels: mergedTimeLabels
|
|
2350
|
+
labels: mergedTimeLabels,
|
|
2351
|
+
filterTime
|
|
2012
2352
|
}),
|
|
2013
2353
|
[
|
|
2014
2354
|
currentValue,
|
|
2015
2355
|
setTime,
|
|
2016
2356
|
format,
|
|
2017
2357
|
step,
|
|
2358
|
+
withSeconds,
|
|
2018
2359
|
displayTimezone,
|
|
2019
2360
|
isDisabled,
|
|
2020
2361
|
readOnly,
|
|
2021
2362
|
currentTime,
|
|
2022
2363
|
pickerId,
|
|
2023
|
-
mergedTimeLabels
|
|
2364
|
+
mergedTimeLabels,
|
|
2365
|
+
filterTime
|
|
2024
2366
|
]
|
|
2025
2367
|
);
|
|
2026
2368
|
return /* @__PURE__ */ jsxRuntime.jsx(DatePickerContext.Provider, { value: dateContext, children: /* @__PURE__ */ jsxRuntime.jsx(TimePickerContext.Provider, { value: timeContext, children }) });
|
|
@@ -2049,6 +2391,8 @@ var DateTimePickerInput = react.forwardRef(
|
|
|
2049
2391
|
(e) => {
|
|
2050
2392
|
if (e.key === "Escape") {
|
|
2051
2393
|
ctx.close();
|
|
2394
|
+
} else if (e.key === "Enter" && ctx.isOpen) {
|
|
2395
|
+
e.preventDefault();
|
|
2052
2396
|
} else if (e.key === "ArrowDown" && !ctx.isOpen) {
|
|
2053
2397
|
e.preventDefault();
|
|
2054
2398
|
ctx.open();
|
|
@@ -2084,6 +2428,7 @@ var DateTimePickerInput = react.forwardRef(
|
|
|
2084
2428
|
);
|
|
2085
2429
|
}
|
|
2086
2430
|
);
|
|
2431
|
+
DateTimePickerInput.displayName = "DateTimePicker.Input";
|
|
2087
2432
|
|
|
2088
2433
|
// src/components/DateTimePicker/index.ts
|
|
2089
2434
|
var DateTimePicker = Object.assign(DateTimePickerRoot, {
|
|
@@ -2102,7 +2447,7 @@ function MonthPickerRoot(props) {
|
|
|
2102
2447
|
}
|
|
2103
2448
|
function MonthPickerGrid({ classNames, ...props }) {
|
|
2104
2449
|
const ctx = useDatePickerContext("MonthPicker.Grid");
|
|
2105
|
-
const { adapter, viewMonth, locale, value, displayTimezone, labels } = ctx;
|
|
2450
|
+
const { adapter, viewMonth, locale, value, displayTimezone, labels, disabled } = ctx;
|
|
2106
2451
|
const currentYear = adapter.getYear(viewMonth);
|
|
2107
2452
|
const [valueYear, valueMonthZeroBased] = react.useMemo(() => {
|
|
2108
2453
|
if (!value) return [null, null];
|
|
@@ -2113,9 +2458,19 @@ function MonthPickerGrid({ classNames, ...props }) {
|
|
|
2113
2458
|
return [null, null];
|
|
2114
2459
|
}
|
|
2115
2460
|
}, [value, adapter, displayTimezone]);
|
|
2116
|
-
const today =
|
|
2117
|
-
|
|
2118
|
-
|
|
2461
|
+
const [today, setToday] = react.useState(null);
|
|
2462
|
+
react.useEffect(() => {
|
|
2463
|
+
setToday(adapter.today(displayTimezone));
|
|
2464
|
+
}, [adapter, displayTimezone]);
|
|
2465
|
+
const todayYear = today !== null ? adapter.getYear(today) : -1;
|
|
2466
|
+
const todayMonth = today !== null ? adapter.getMonth(today) : -1;
|
|
2467
|
+
const monthDisabledFlags = react.useMemo(
|
|
2468
|
+
() => Array.from({ length: 12 }, (_, i) => {
|
|
2469
|
+
const monthStart = new Date(Date.UTC(currentYear, i, 1)).toISOString();
|
|
2470
|
+
return isRangeFullyDisabled(monthStart, adapter.endOfMonth(monthStart), disabled, adapter);
|
|
2471
|
+
}),
|
|
2472
|
+
[currentYear, disabled, adapter]
|
|
2473
|
+
);
|
|
2119
2474
|
const navigateYear = react.useCallback(
|
|
2120
2475
|
(direction) => {
|
|
2121
2476
|
ctx.setViewMonth(adapter.addYears(viewMonth, direction));
|
|
@@ -2124,17 +2479,23 @@ function MonthPickerGrid({ classNames, ...props }) {
|
|
|
2124
2479
|
);
|
|
2125
2480
|
const handleMonthSelect = react.useCallback(
|
|
2126
2481
|
(monthIndex) => {
|
|
2482
|
+
if (monthDisabledFlags[monthIndex]) return;
|
|
2127
2483
|
const target = new Date(Date.UTC(currentYear, monthIndex, 1)).toISOString();
|
|
2128
2484
|
ctx.selectDate(target);
|
|
2129
2485
|
},
|
|
2130
|
-
[currentYear, ctx]
|
|
2131
|
-
);
|
|
2132
|
-
const
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2486
|
+
[currentYear, ctx, monthDisabledFlags]
|
|
2487
|
+
);
|
|
2488
|
+
const naturalIndex = valueYear === currentYear && valueMonthZeroBased !== null ? valueMonthZeroBased : adapter.getMonth(viewMonth);
|
|
2489
|
+
const firstEnabled = monthDisabledFlags.findIndex((d) => !d);
|
|
2490
|
+
const initialIndex = monthDisabledFlags[naturalIndex] ? firstEnabled === -1 ? naturalIndex : firstEnabled : naturalIndex;
|
|
2491
|
+
const { gridRef, focusedIndex, handleKeyDown } = useGridState({
|
|
2492
|
+
initialIndex,
|
|
2493
|
+
disabledFlags: monthDisabledFlags,
|
|
2494
|
+
onSelect: handleMonthSelect,
|
|
2495
|
+
onPageUp: () => navigateYear(-1),
|
|
2496
|
+
onPageDown: () => navigateYear(1),
|
|
2497
|
+
onEscape: ctx.close
|
|
2498
|
+
});
|
|
2138
2499
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classNames?.root, ...props, children: [
|
|
2139
2500
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: classNames?.header, children: [
|
|
2140
2501
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2159,37 +2520,57 @@ function MonthPickerGrid({ classNames, ...props }) {
|
|
|
2159
2520
|
}
|
|
2160
2521
|
)
|
|
2161
2522
|
] }),
|
|
2162
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2523
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2163
2524
|
"div",
|
|
2164
2525
|
{
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
"
|
|
2176
|
-
{
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2526
|
+
ref: gridRef,
|
|
2527
|
+
role: "grid",
|
|
2528
|
+
"aria-label": `${currentYear} months`,
|
|
2529
|
+
className: classNames?.grid,
|
|
2530
|
+
onKeyDown: handleKeyDown,
|
|
2531
|
+
children: Array.from({ length: 4 }, (_, rowIndex) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2532
|
+
"div",
|
|
2533
|
+
{
|
|
2534
|
+
role: "row",
|
|
2535
|
+
className: classNames?.gridRow,
|
|
2536
|
+
style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)" },
|
|
2537
|
+
children: Array.from({ length: 3 }, (_2, col) => {
|
|
2538
|
+
const i = rowIndex * 3 + col;
|
|
2539
|
+
const isSelected = valueYear === currentYear && valueMonthZeroBased === i;
|
|
2540
|
+
const isCurrent = todayYear === currentYear && todayMonth === i;
|
|
2541
|
+
const isFocused = i === focusedIndex;
|
|
2542
|
+
const isDisabled = monthDisabledFlags[i] ?? false;
|
|
2543
|
+
const cls = [
|
|
2544
|
+
classNames?.month,
|
|
2545
|
+
isSelected && classNames?.monthSelected,
|
|
2546
|
+
isCurrent && classNames?.monthCurrent,
|
|
2547
|
+
isDisabled && classNames?.monthDisabled
|
|
2548
|
+
].filter(Boolean).join(" ") || void 0;
|
|
2549
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2550
|
+
"button",
|
|
2551
|
+
{
|
|
2552
|
+
type: "button",
|
|
2553
|
+
role: "gridcell",
|
|
2554
|
+
tabIndex: isFocused ? 0 : -1,
|
|
2555
|
+
disabled: isDisabled,
|
|
2556
|
+
"aria-selected": isSelected || void 0,
|
|
2557
|
+
"aria-disabled": isDisabled || void 0,
|
|
2558
|
+
"aria-current": isCurrent ? "date" : void 0,
|
|
2559
|
+
"data-selected": isSelected || void 0,
|
|
2560
|
+
"data-current": isCurrent || void 0,
|
|
2561
|
+
"data-focused": isFocused || void 0,
|
|
2562
|
+
className: cls,
|
|
2563
|
+
onClick: () => handleMonthSelect(i),
|
|
2564
|
+
children: core.getMonthName(i, locale)
|
|
2565
|
+
},
|
|
2566
|
+
i
|
|
2567
|
+
);
|
|
2568
|
+
})
|
|
2569
|
+
},
|
|
2570
|
+
rowIndex
|
|
2571
|
+
))
|
|
2572
|
+
}
|
|
2573
|
+
)
|
|
2193
2574
|
] });
|
|
2194
2575
|
}
|
|
2195
2576
|
|
|
@@ -2206,7 +2587,7 @@ function YearPickerRoot(props) {
|
|
|
2206
2587
|
}
|
|
2207
2588
|
function YearPickerGrid({ classNames, ...props }) {
|
|
2208
2589
|
const ctx = useDatePickerContext("YearPicker.Grid");
|
|
2209
|
-
const { adapter, viewMonth, value, displayTimezone, labels } = ctx;
|
|
2590
|
+
const { adapter, viewMonth, value, displayTimezone, labels, disabled } = ctx;
|
|
2210
2591
|
const currentYear = adapter.getYear(viewMonth);
|
|
2211
2592
|
const decadeStart = currentYear - currentYear % 12;
|
|
2212
2593
|
const valueYear = react.useMemo(() => {
|
|
@@ -2217,7 +2598,20 @@ function YearPickerGrid({ classNames, ...props }) {
|
|
|
2217
2598
|
return null;
|
|
2218
2599
|
}
|
|
2219
2600
|
}, [value, adapter, displayTimezone]);
|
|
2220
|
-
const
|
|
2601
|
+
const [today, setToday] = react.useState(null);
|
|
2602
|
+
react.useEffect(() => {
|
|
2603
|
+
setToday(adapter.today(displayTimezone));
|
|
2604
|
+
}, [adapter, displayTimezone]);
|
|
2605
|
+
const todayYear = today !== null ? adapter.getYear(today) : -1;
|
|
2606
|
+
const yearDisabledFlags = react.useMemo(
|
|
2607
|
+
() => Array.from({ length: 12 }, (_, i) => {
|
|
2608
|
+
const year = decadeStart + i;
|
|
2609
|
+
const yearStart = new Date(Date.UTC(year, 0, 1)).toISOString();
|
|
2610
|
+
const yearEnd = new Date(Date.UTC(year, 11, 31, 23, 59, 59, 999)).toISOString();
|
|
2611
|
+
return isRangeFullyDisabled(yearStart, yearEnd, disabled, adapter);
|
|
2612
|
+
}),
|
|
2613
|
+
[decadeStart, disabled, adapter]
|
|
2614
|
+
);
|
|
2221
2615
|
const navigateDecade = react.useCallback(
|
|
2222
2616
|
(direction) => {
|
|
2223
2617
|
ctx.setViewMonth(adapter.addYears(viewMonth, direction * 12));
|
|
@@ -2225,19 +2619,24 @@ function YearPickerGrid({ classNames, ...props }) {
|
|
|
2225
2619
|
[adapter, viewMonth, ctx]
|
|
2226
2620
|
);
|
|
2227
2621
|
const handleYearSelect = react.useCallback(
|
|
2228
|
-
(
|
|
2622
|
+
(indexInDecade) => {
|
|
2623
|
+
if (yearDisabledFlags[indexInDecade]) return;
|
|
2624
|
+
const year = decadeStart + indexInDecade;
|
|
2229
2625
|
const target = new Date(Date.UTC(year, 0, 1)).toISOString();
|
|
2230
2626
|
ctx.selectDate(target);
|
|
2231
2627
|
},
|
|
2232
|
-
[ctx]
|
|
2233
|
-
);
|
|
2234
|
-
const
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2628
|
+
[ctx, decadeStart, yearDisabledFlags]
|
|
2629
|
+
);
|
|
2630
|
+
const naturalIndex = valueYear !== null && valueYear >= decadeStart && valueYear <= decadeStart + 11 ? valueYear - decadeStart : currentYear - decadeStart;
|
|
2631
|
+
const firstEnabled = yearDisabledFlags.findIndex((d) => !d);
|
|
2632
|
+
const initialIndex = yearDisabledFlags[naturalIndex] ? firstEnabled === -1 ? naturalIndex : firstEnabled : naturalIndex;
|
|
2633
|
+
const { gridRef, focusedIndex, handleKeyDown } = useGridState({
|
|
2634
|
+
initialIndex,
|
|
2635
|
+
disabledFlags: yearDisabledFlags,
|
|
2636
|
+
onSelect: handleYearSelect,
|
|
2637
|
+
onPageUp: () => navigateDecade(-1),
|
|
2638
|
+
onPageDown: () => navigateDecade(1),
|
|
2639
|
+
onEscape: ctx.close
|
|
2241
2640
|
});
|
|
2242
2641
|
const rangeLabel = `${decadeStart}\u2013${decadeStart + 11}`;
|
|
2243
2642
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classNames?.root, ...props, children: [
|
|
@@ -2264,37 +2663,58 @@ function YearPickerGrid({ classNames, ...props }) {
|
|
|
2264
2663
|
}
|
|
2265
2664
|
)
|
|
2266
2665
|
] }),
|
|
2267
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2666
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2268
2667
|
"div",
|
|
2269
2668
|
{
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
"
|
|
2281
|
-
{
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2669
|
+
ref: gridRef,
|
|
2670
|
+
role: "grid",
|
|
2671
|
+
"aria-label": rangeLabel,
|
|
2672
|
+
className: classNames?.grid,
|
|
2673
|
+
onKeyDown: handleKeyDown,
|
|
2674
|
+
children: Array.from({ length: 4 }, (_, rowIndex) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2675
|
+
"div",
|
|
2676
|
+
{
|
|
2677
|
+
role: "row",
|
|
2678
|
+
className: classNames?.gridRow,
|
|
2679
|
+
style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)" },
|
|
2680
|
+
children: Array.from({ length: 3 }, (_2, col) => {
|
|
2681
|
+
const i = rowIndex * 3 + col;
|
|
2682
|
+
const year = decadeStart + i;
|
|
2683
|
+
const isSelected = year === valueYear;
|
|
2684
|
+
const isCurrent = year === todayYear;
|
|
2685
|
+
const isFocused = i === focusedIndex;
|
|
2686
|
+
const isDisabled = yearDisabledFlags[i] ?? false;
|
|
2687
|
+
const cls = [
|
|
2688
|
+
classNames?.year,
|
|
2689
|
+
isSelected && classNames?.yearSelected,
|
|
2690
|
+
isCurrent && classNames?.yearCurrent,
|
|
2691
|
+
isDisabled && classNames?.yearDisabled
|
|
2692
|
+
].filter(Boolean).join(" ") || void 0;
|
|
2693
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2694
|
+
"button",
|
|
2695
|
+
{
|
|
2696
|
+
type: "button",
|
|
2697
|
+
role: "gridcell",
|
|
2698
|
+
tabIndex: isFocused ? 0 : -1,
|
|
2699
|
+
disabled: isDisabled,
|
|
2700
|
+
"aria-selected": isSelected || void 0,
|
|
2701
|
+
"aria-disabled": isDisabled || void 0,
|
|
2702
|
+
"aria-current": isCurrent ? "date" : void 0,
|
|
2703
|
+
"data-selected": isSelected || void 0,
|
|
2704
|
+
"data-current": isCurrent || void 0,
|
|
2705
|
+
"data-focused": isFocused || void 0,
|
|
2706
|
+
className: cls,
|
|
2707
|
+
onClick: () => handleYearSelect(i),
|
|
2708
|
+
children: year
|
|
2709
|
+
},
|
|
2710
|
+
i
|
|
2711
|
+
);
|
|
2712
|
+
})
|
|
2713
|
+
},
|
|
2714
|
+
rowIndex
|
|
2715
|
+
))
|
|
2716
|
+
}
|
|
2717
|
+
)
|
|
2298
2718
|
] });
|
|
2299
2719
|
}
|
|
2300
2720
|
|
|
@@ -2515,7 +2935,7 @@ function useRangePicker(options = {}) {
|
|
|
2515
2935
|
adapter
|
|
2516
2936
|
};
|
|
2517
2937
|
}
|
|
2518
|
-
function
|
|
2938
|
+
function getDefaultIso() {
|
|
2519
2939
|
return core.DateFnsAdapter.today();
|
|
2520
2940
|
}
|
|
2521
2941
|
function useTimePicker(options = {}) {
|
|
@@ -2533,7 +2953,7 @@ function useTimePicker(options = {}) {
|
|
|
2533
2953
|
defaultValue ?? null
|
|
2534
2954
|
);
|
|
2535
2955
|
const currentValue = isControlled ? controlledValue ?? null : uncontrolledValue;
|
|
2536
|
-
const baseIso = currentValue ??
|
|
2956
|
+
const baseIso = currentValue ?? getDefaultIso();
|
|
2537
2957
|
const currentTime = react.useMemo(
|
|
2538
2958
|
() => displayTimezone ? core.getTimeInTimezone(baseIso, displayTimezone) : core.getTime(baseIso),
|
|
2539
2959
|
[baseIso, displayTimezone]
|
|
@@ -2584,6 +3004,22 @@ function useTimePicker(options = {}) {
|
|
|
2584
3004
|
};
|
|
2585
3005
|
}
|
|
2586
3006
|
|
|
3007
|
+
Object.defineProperty(exports, "DEFAULT_DATEPICKER_LABELS", {
|
|
3008
|
+
enumerable: true,
|
|
3009
|
+
get: function () { return core.DEFAULT_DATEPICKER_LABELS; }
|
|
3010
|
+
});
|
|
3011
|
+
Object.defineProperty(exports, "DEFAULT_DATETIMEPICKER_LABELS", {
|
|
3012
|
+
enumerable: true,
|
|
3013
|
+
get: function () { return core.DEFAULT_DATETIMEPICKER_LABELS; }
|
|
3014
|
+
});
|
|
3015
|
+
Object.defineProperty(exports, "DEFAULT_RANGEPICKER_LABELS", {
|
|
3016
|
+
enumerable: true,
|
|
3017
|
+
get: function () { return core.DEFAULT_RANGEPICKER_LABELS; }
|
|
3018
|
+
});
|
|
3019
|
+
Object.defineProperty(exports, "DEFAULT_TIMEPICKER_LABELS", {
|
|
3020
|
+
enumerable: true,
|
|
3021
|
+
get: function () { return core.DEFAULT_TIMEPICKER_LABELS; }
|
|
3022
|
+
});
|
|
2587
3023
|
Object.defineProperty(exports, "DateFnsAdapter", {
|
|
2588
3024
|
enumerable: true,
|
|
2589
3025
|
get: function () { return core.DateFnsAdapter; }
|