@kalyx/react 1.0.0-rc.1 → 1.0.0-rc.10
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 +273 -0
- package/README.md +2 -2
- package/dist/index.cjs +775 -363
- 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 +764 -368
- 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,11 @@ 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);
|
|
158
160
|
let formattedValue = "";
|
|
159
161
|
if (ctx.value) {
|
|
160
162
|
try {
|
|
@@ -171,47 +173,62 @@ var DatePickerInput = react.forwardRef(
|
|
|
171
173
|
},
|
|
172
174
|
[ctx, onClick]
|
|
173
175
|
);
|
|
176
|
+
const commitText = react.useCallback(
|
|
177
|
+
(text) => {
|
|
178
|
+
if (!text) {
|
|
179
|
+
ctx.selectDate(null);
|
|
180
|
+
setInputText(null);
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
const parsed = core.parseInputValue(text, ctx.adapter);
|
|
184
|
+
if (parsed) {
|
|
185
|
+
ctx.selectDate(parsed);
|
|
186
|
+
setInputText(null);
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
return false;
|
|
190
|
+
},
|
|
191
|
+
[ctx]
|
|
192
|
+
);
|
|
174
193
|
const handleBlur = react.useCallback(
|
|
175
194
|
(e) => {
|
|
176
195
|
if (inputText !== null) {
|
|
177
|
-
|
|
178
|
-
if (parsed) {
|
|
179
|
-
ctx.selectDate(parsed);
|
|
180
|
-
}
|
|
196
|
+
commitText(inputText);
|
|
181
197
|
setInputText(null);
|
|
182
198
|
}
|
|
183
199
|
onBlur?.(e);
|
|
184
200
|
},
|
|
185
|
-
[inputText,
|
|
201
|
+
[inputText, commitText, onBlur]
|
|
186
202
|
);
|
|
187
203
|
const handleChange = react.useCallback(
|
|
188
204
|
(e) => {
|
|
189
205
|
const text = e.target.value;
|
|
190
206
|
setInputText(text);
|
|
191
|
-
if (
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
207
|
+
if (isComposingRef.current) return;
|
|
208
|
+
commitText(text);
|
|
209
|
+
},
|
|
210
|
+
[commitText]
|
|
211
|
+
);
|
|
212
|
+
const handleCompositionStart = react.useCallback(() => {
|
|
213
|
+
isComposingRef.current = true;
|
|
214
|
+
}, []);
|
|
215
|
+
const handleCompositionEnd = react.useCallback(
|
|
216
|
+
(e) => {
|
|
217
|
+
isComposingRef.current = false;
|
|
218
|
+
commitText(e.target.value);
|
|
201
219
|
},
|
|
202
|
-
[
|
|
220
|
+
[commitText]
|
|
203
221
|
);
|
|
204
222
|
const handleKeyDown = react.useCallback(
|
|
205
223
|
(e) => {
|
|
206
224
|
if (e.key === "Escape") {
|
|
207
225
|
ctx.close();
|
|
208
226
|
} else if (e.key === "Enter") {
|
|
227
|
+
if (ctx.isOpen) e.preventDefault();
|
|
209
228
|
if (inputText !== null) {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
setInputText(null);
|
|
214
|
-
}
|
|
229
|
+
commitText(inputText);
|
|
230
|
+
} else if (ctx.isOpen) {
|
|
231
|
+
ctx.selectDate(ctx.focusedDate);
|
|
215
232
|
}
|
|
216
233
|
} else if (e.key === "ArrowDown" && !ctx.isOpen) {
|
|
217
234
|
e.preventDefault();
|
|
@@ -219,36 +236,42 @@ var DatePickerInput = react.forwardRef(
|
|
|
219
236
|
}
|
|
220
237
|
onKeyDown?.(e);
|
|
221
238
|
},
|
|
222
|
-
[ctx, inputText,
|
|
239
|
+
[ctx, inputText, commitText, onKeyDown]
|
|
223
240
|
);
|
|
224
241
|
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
|
-
|
|
242
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
243
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
244
|
+
"input",
|
|
245
|
+
{
|
|
246
|
+
ref: (node) => {
|
|
247
|
+
ctx.referenceRef.current = node;
|
|
248
|
+
if (typeof ref === "function") ref(node);
|
|
249
|
+
else if (ref) ref.current = node;
|
|
250
|
+
},
|
|
251
|
+
type: "text",
|
|
252
|
+
role: "combobox",
|
|
253
|
+
"aria-expanded": ctx.isOpen,
|
|
254
|
+
"aria-haspopup": "dialog",
|
|
255
|
+
"aria-controls": ctx.isOpen ? calendarId : void 0,
|
|
256
|
+
"aria-autocomplete": "none",
|
|
257
|
+
autoComplete: "off",
|
|
258
|
+
value: displayValue,
|
|
259
|
+
disabled: ctx.isDisabled || props.disabled,
|
|
260
|
+
readOnly: ctx.isReadOnly,
|
|
261
|
+
onChange: handleChange,
|
|
262
|
+
onClick: handleClick,
|
|
263
|
+
onBlur: handleBlur,
|
|
264
|
+
onKeyDown: handleKeyDown,
|
|
265
|
+
onCompositionStart: handleCompositionStart,
|
|
266
|
+
onCompositionEnd: handleCompositionEnd,
|
|
267
|
+
...props
|
|
268
|
+
}
|
|
269
|
+
),
|
|
270
|
+
name ? /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: ctx.value ?? "" }) : null
|
|
271
|
+
] });
|
|
250
272
|
}
|
|
251
273
|
);
|
|
274
|
+
DatePickerInput.displayName = "DatePicker.Input";
|
|
252
275
|
var DatePickerTrigger = react.forwardRef(
|
|
253
276
|
function DatePickerTrigger2({ onClick, children, ...props }, ref) {
|
|
254
277
|
const ctx = useDatePickerContext("DatePicker.Trigger");
|
|
@@ -272,6 +295,7 @@ var DatePickerTrigger = react.forwardRef(
|
|
|
272
295
|
tabIndex: 0,
|
|
273
296
|
"aria-label": ctx.isOpen ? ctx.labels.triggerClose : ctx.labels.triggerOpen,
|
|
274
297
|
"aria-expanded": ctx.isOpen,
|
|
298
|
+
"aria-haspopup": "dialog",
|
|
275
299
|
"aria-controls": ctx.isOpen ? calendarId : void 0,
|
|
276
300
|
disabled: ctx.isDisabled || props.disabled,
|
|
277
301
|
onClick: handleClick,
|
|
@@ -302,6 +326,8 @@ var DatePickerTrigger = react.forwardRef(
|
|
|
302
326
|
);
|
|
303
327
|
}
|
|
304
328
|
);
|
|
329
|
+
DatePickerTrigger.displayName = "DatePicker.Trigger";
|
|
330
|
+
var POPOVER_MIDDLEWARE = [react$1.offset(4), react$1.flip(), react$1.shift({ padding: 8 })];
|
|
305
331
|
function usePopover({
|
|
306
332
|
isOpen,
|
|
307
333
|
close,
|
|
@@ -313,7 +339,7 @@ function usePopover({
|
|
|
313
339
|
const { refs, floatingStyles, isPositioned } = react$1.useFloating({
|
|
314
340
|
open: isOpen,
|
|
315
341
|
placement,
|
|
316
|
-
middleware:
|
|
342
|
+
middleware: POPOVER_MIDDLEWARE,
|
|
317
343
|
whileElementsMounted: react$1.autoUpdate
|
|
318
344
|
});
|
|
319
345
|
react.useEffect(() => {
|
|
@@ -360,6 +386,24 @@ function usePopover({
|
|
|
360
386
|
document.addEventListener("keydown", handleKeyDown);
|
|
361
387
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
362
388
|
}, [isOpen, close]);
|
|
389
|
+
react.useEffect(() => {
|
|
390
|
+
if (!isOpen) return;
|
|
391
|
+
function handleFocusOut(e) {
|
|
392
|
+
const next = e.relatedTarget;
|
|
393
|
+
const floating = floatingRef.current;
|
|
394
|
+
const reference = referenceRef.current;
|
|
395
|
+
if (!next) return;
|
|
396
|
+
const insideFloating = floating?.contains(next) ?? false;
|
|
397
|
+
const insideReference = reference?.contains(next) ?? false;
|
|
398
|
+
if (!insideFloating && !insideReference) {
|
|
399
|
+
close();
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
const node = floatingRef.current;
|
|
403
|
+
if (!node) return;
|
|
404
|
+
node.addEventListener("focusout", handleFocusOut);
|
|
405
|
+
return () => node.removeEventListener("focusout", handleFocusOut);
|
|
406
|
+
}, [isOpen, close, referenceRef]);
|
|
363
407
|
const setFloatingRef = react.useCallback(
|
|
364
408
|
(node) => {
|
|
365
409
|
floatingRef.current = node;
|
|
@@ -421,20 +465,36 @@ var srOnly = {
|
|
|
421
465
|
function DatePickerCalendar({
|
|
422
466
|
classNames,
|
|
423
467
|
onTitleClick,
|
|
468
|
+
showWeekNumber = false,
|
|
469
|
+
fixedWeeks = false,
|
|
424
470
|
...props
|
|
425
471
|
}) {
|
|
426
472
|
const ctx = useDatePickerContext("DatePicker.Calendar");
|
|
427
473
|
const gridRef = react.useRef(null);
|
|
428
474
|
const [announcement, setAnnouncement] = react.useState("");
|
|
429
475
|
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
|
-
|
|
476
|
+
const weekdays = react.useMemo(() => core.getWeekdayNames(locale, weekStartsOn), [locale, weekStartsOn]);
|
|
477
|
+
const weeks = react.useMemo(
|
|
478
|
+
() => core.getCalendarDays(viewMonth, adapter, {
|
|
479
|
+
weekStartsOn,
|
|
480
|
+
selected: ctx.value,
|
|
481
|
+
focusedDate,
|
|
482
|
+
disabled,
|
|
483
|
+
timezone: displayTimezone,
|
|
484
|
+
fixedWeeks
|
|
485
|
+
}),
|
|
486
|
+
[
|
|
487
|
+
viewMonth,
|
|
488
|
+
adapter,
|
|
489
|
+
weekStartsOn,
|
|
490
|
+
ctx.value,
|
|
491
|
+
focusedDate,
|
|
492
|
+
disabled,
|
|
493
|
+
displayTimezone,
|
|
494
|
+
fixedWeeks
|
|
495
|
+
]
|
|
496
|
+
);
|
|
497
|
+
const thursdayIndex = weekStartsOn === 0 ? 4 : 3;
|
|
438
498
|
const year = adapter.getYear(viewMonth);
|
|
439
499
|
const month = adapter.getMonth(viewMonth);
|
|
440
500
|
const title = core.formatMonthYear(year, month, locale);
|
|
@@ -514,6 +574,15 @@ function DatePickerCalendar({
|
|
|
514
574
|
}
|
|
515
575
|
if (newFocused) {
|
|
516
576
|
e.preventDefault();
|
|
577
|
+
const skipStep = e.key === "ArrowLeft" || e.key === "ArrowUp" || e.key === "PageUp" || e.key === "Home" ? -1 : 1;
|
|
578
|
+
let attempts = 0;
|
|
579
|
+
while (core.isDateDisabled(newFocused, disabled, adapter) && attempts < 42) {
|
|
580
|
+
newFocused = adapter.addDays(newFocused, skipStep);
|
|
581
|
+
attempts++;
|
|
582
|
+
}
|
|
583
|
+
if (attempts >= 42) {
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
517
586
|
ctx.setFocusedDate(newFocused);
|
|
518
587
|
if (!adapter.isSameMonth(newFocused, viewMonth)) {
|
|
519
588
|
ctx.setViewMonth(newFocused);
|
|
@@ -561,62 +630,170 @@ function DatePickerCalendar({
|
|
|
561
630
|
ref: gridRef,
|
|
562
631
|
role: "grid",
|
|
563
632
|
"aria-label": title,
|
|
633
|
+
"aria-rowcount": weeks.length + 1,
|
|
634
|
+
"aria-colcount": 7,
|
|
564
635
|
className: classNames?.grid,
|
|
565
636
|
onKeyDown: handleKeyDown,
|
|
566
637
|
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",
|
|
638
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { role: "row", "aria-rowindex": 1, children: [
|
|
639
|
+
showWeekNumber ? /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", "aria-hidden": "true", className: classNames?.weekNumberHeader, children: "#" }) : null,
|
|
640
|
+
weekdays.map((day, colIndex) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
641
|
+
"th",
|
|
588
642
|
{
|
|
589
|
-
role: "
|
|
590
|
-
|
|
591
|
-
"
|
|
592
|
-
"aria-
|
|
593
|
-
className: classNames?.
|
|
594
|
-
children:
|
|
595
|
-
|
|
643
|
+
role: "columnheader",
|
|
644
|
+
abbr: day.full,
|
|
645
|
+
scope: "col",
|
|
646
|
+
"aria-colindex": colIndex + 1,
|
|
647
|
+
className: classNames?.weekdayHeader,
|
|
648
|
+
children: day.short
|
|
649
|
+
},
|
|
650
|
+
day.short
|
|
651
|
+
))
|
|
652
|
+
] }) }),
|
|
653
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: weeks.map((week, weekIndex) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
654
|
+
"tr",
|
|
655
|
+
{
|
|
656
|
+
role: "row",
|
|
657
|
+
"aria-rowindex": weekIndex + 2,
|
|
658
|
+
className: classNames?.gridRow,
|
|
659
|
+
children: [
|
|
660
|
+
showWeekNumber ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
661
|
+
"th",
|
|
596
662
|
{
|
|
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
|
|
663
|
+
scope: "row",
|
|
664
|
+
"aria-hidden": "true",
|
|
665
|
+
className: classNames?.weekNumber,
|
|
666
|
+
"data-week-number": true,
|
|
667
|
+
children: core.getISOWeekNumber(week[thursdayIndex].isoString)
|
|
608
668
|
}
|
|
609
|
-
)
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
669
|
+
) : null,
|
|
670
|
+
week.map((day, colIndex) => {
|
|
671
|
+
const dayClasses = [
|
|
672
|
+
classNames?.day,
|
|
673
|
+
day.isSelected && classNames?.daySelected,
|
|
674
|
+
day.isToday && classNames?.dayToday,
|
|
675
|
+
day.isDisabled && classNames?.dayDisabled,
|
|
676
|
+
!day.isCurrentMonth && classNames?.dayOutsideMonth
|
|
677
|
+
].filter(Boolean).join(" ") || void 0;
|
|
678
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
679
|
+
"td",
|
|
680
|
+
{
|
|
681
|
+
role: "gridcell",
|
|
682
|
+
"aria-colindex": colIndex + 1,
|
|
683
|
+
"aria-selected": day.isSelected || void 0,
|
|
684
|
+
"aria-disabled": day.isDisabled || void 0,
|
|
685
|
+
"aria-current": day.isToday ? "date" : void 0,
|
|
686
|
+
className: classNames?.gridCell,
|
|
687
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
688
|
+
"button",
|
|
689
|
+
{
|
|
690
|
+
type: "button",
|
|
691
|
+
tabIndex: day.isFocused ? 0 : -1,
|
|
692
|
+
disabled: day.isDisabled,
|
|
693
|
+
"data-focused": day.isFocused || void 0,
|
|
694
|
+
"data-selected": day.isSelected || void 0,
|
|
695
|
+
"data-today": day.isToday || void 0,
|
|
696
|
+
"data-outside-month": !day.isCurrentMonth || void 0,
|
|
697
|
+
className: dayClasses,
|
|
698
|
+
onClick: () => handleDayClick(day),
|
|
699
|
+
"aria-label": safeFormatFullDate(day.isoString, locale),
|
|
700
|
+
children: day.dayNumber
|
|
701
|
+
}
|
|
702
|
+
)
|
|
703
|
+
},
|
|
704
|
+
day.isoString
|
|
705
|
+
);
|
|
706
|
+
})
|
|
707
|
+
]
|
|
708
|
+
},
|
|
709
|
+
weekIndex
|
|
710
|
+
)) })
|
|
614
711
|
]
|
|
615
712
|
}
|
|
616
713
|
),
|
|
617
714
|
/* @__PURE__ */ jsxRuntime.jsx("div", { role: "status", "aria-live": "polite", "aria-atomic": "true", style: srOnly, children: announcement })
|
|
618
715
|
] });
|
|
619
716
|
}
|
|
717
|
+
function isRangeFullyDisabled(start, end, rules, adapter) {
|
|
718
|
+
for (const rule of rules) {
|
|
719
|
+
if ("before" in rule && adapter.isBefore(end, rule.before)) return true;
|
|
720
|
+
if ("after" in rule && adapter.isAfter(start, rule.after)) return true;
|
|
721
|
+
}
|
|
722
|
+
return false;
|
|
723
|
+
}
|
|
724
|
+
function useGridState(opts) {
|
|
725
|
+
const { initialIndex, disabledFlags, onSelect, onPageUp, onPageDown, onEscape } = opts;
|
|
726
|
+
const gridRef = react.useRef(null);
|
|
727
|
+
const [focusedIndex, setFocusedIndex] = react.useState(initialIndex);
|
|
728
|
+
const handleKeyDown = (e) => {
|
|
729
|
+
let next = null;
|
|
730
|
+
let step = 1;
|
|
731
|
+
switch (e.key) {
|
|
732
|
+
case "ArrowLeft":
|
|
733
|
+
next = Math.max(0, focusedIndex - 1);
|
|
734
|
+
step = -1;
|
|
735
|
+
break;
|
|
736
|
+
case "ArrowRight":
|
|
737
|
+
next = Math.min(11, focusedIndex + 1);
|
|
738
|
+
break;
|
|
739
|
+
case "ArrowUp":
|
|
740
|
+
next = Math.max(0, focusedIndex - 3);
|
|
741
|
+
step = -1;
|
|
742
|
+
break;
|
|
743
|
+
case "ArrowDown":
|
|
744
|
+
next = Math.min(11, focusedIndex + 3);
|
|
745
|
+
break;
|
|
746
|
+
case "Home":
|
|
747
|
+
next = focusedIndex - focusedIndex % 3;
|
|
748
|
+
step = -1;
|
|
749
|
+
break;
|
|
750
|
+
case "End":
|
|
751
|
+
next = focusedIndex - focusedIndex % 3 + 2;
|
|
752
|
+
break;
|
|
753
|
+
case "PageUp":
|
|
754
|
+
e.preventDefault();
|
|
755
|
+
onPageUp();
|
|
756
|
+
return;
|
|
757
|
+
case "PageDown":
|
|
758
|
+
e.preventDefault();
|
|
759
|
+
onPageDown();
|
|
760
|
+
return;
|
|
761
|
+
case "Enter":
|
|
762
|
+
case " ":
|
|
763
|
+
e.preventDefault();
|
|
764
|
+
onSelect(focusedIndex);
|
|
765
|
+
return;
|
|
766
|
+
case "Escape":
|
|
767
|
+
onEscape();
|
|
768
|
+
return;
|
|
769
|
+
default:
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
if (next === null) return;
|
|
773
|
+
e.preventDefault();
|
|
774
|
+
if (disabledFlags) {
|
|
775
|
+
let attempts = 0;
|
|
776
|
+
while (next >= 0 && next < 12 && disabledFlags[next] && attempts < 12) {
|
|
777
|
+
next += step;
|
|
778
|
+
attempts++;
|
|
779
|
+
}
|
|
780
|
+
if (next < 0 || next >= 12 || disabledFlags[next]) return;
|
|
781
|
+
}
|
|
782
|
+
if (next !== focusedIndex) setFocusedIndex(next);
|
|
783
|
+
};
|
|
784
|
+
react.useEffect(() => {
|
|
785
|
+
if (!disabledFlags || !disabledFlags[focusedIndex]) return;
|
|
786
|
+
const firstEnabled = disabledFlags.findIndex((d) => !d);
|
|
787
|
+
if (firstEnabled !== -1 && firstEnabled !== focusedIndex) {
|
|
788
|
+
setFocusedIndex(firstEnabled);
|
|
789
|
+
}
|
|
790
|
+
}, [disabledFlags, focusedIndex]);
|
|
791
|
+
react.useEffect(() => {
|
|
792
|
+
const btn = gridRef.current?.querySelector('[data-focused="true"]');
|
|
793
|
+
btn?.focus({ preventScroll: true });
|
|
794
|
+
}, [focusedIndex]);
|
|
795
|
+
return { gridRef, focusedIndex, handleKeyDown };
|
|
796
|
+
}
|
|
620
797
|
function DatePickerMonthGrid({
|
|
621
798
|
classNames,
|
|
622
799
|
onSelect,
|
|
@@ -624,15 +801,18 @@ function DatePickerMonthGrid({
|
|
|
624
801
|
...props
|
|
625
802
|
}) {
|
|
626
803
|
const ctx = useDatePickerContext("DatePicker.MonthGrid");
|
|
627
|
-
const { adapter, viewMonth, locale } = ctx;
|
|
804
|
+
const { adapter, viewMonth, locale, displayTimezone } = ctx;
|
|
628
805
|
const currentYear = adapter.getYear(viewMonth);
|
|
629
806
|
const currentMonth = adapter.getMonth(viewMonth);
|
|
630
|
-
const
|
|
631
|
-
|
|
807
|
+
const [today, setToday] = react.useState(null);
|
|
808
|
+
react.useEffect(() => {
|
|
809
|
+
setToday(adapter.today(displayTimezone));
|
|
810
|
+
}, [adapter, displayTimezone]);
|
|
811
|
+
const todayMonth = today !== null ? adapter.getMonth(today) : -1;
|
|
812
|
+
const todayYear = today !== null ? adapter.getYear(today) : -1;
|
|
632
813
|
const navigateYear = react.useCallback(
|
|
633
814
|
(direction) => {
|
|
634
|
-
|
|
635
|
-
ctx.setViewMonth(newDate);
|
|
815
|
+
ctx.setViewMonth(adapter.addYears(viewMonth, direction));
|
|
636
816
|
},
|
|
637
817
|
[adapter, viewMonth, ctx]
|
|
638
818
|
);
|
|
@@ -645,12 +825,13 @@ function DatePickerMonthGrid({
|
|
|
645
825
|
},
|
|
646
826
|
[currentYear, ctx, onSelect]
|
|
647
827
|
);
|
|
648
|
-
const
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
828
|
+
const { gridRef, focusedIndex, handleKeyDown } = useGridState({
|
|
829
|
+
initialIndex: currentMonth,
|
|
830
|
+
onSelect: handleMonthSelect,
|
|
831
|
+
onPageUp: () => navigateYear(-1),
|
|
832
|
+
onPageDown: () => navigateYear(1),
|
|
833
|
+
onEscape: ctx.close
|
|
834
|
+
});
|
|
654
835
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classNames?.root, ...props, children: [
|
|
655
836
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: classNames?.header, children: [
|
|
656
837
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -678,30 +859,37 @@ function DatePickerMonthGrid({
|
|
|
678
859
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
679
860
|
"div",
|
|
680
861
|
{
|
|
862
|
+
ref: gridRef,
|
|
681
863
|
role: "grid",
|
|
682
864
|
"aria-label": `${currentYear} months`,
|
|
683
865
|
className: classNames?.grid,
|
|
684
866
|
style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)" },
|
|
685
|
-
|
|
686
|
-
|
|
867
|
+
onKeyDown: handleKeyDown,
|
|
868
|
+
children: Array.from({ length: 12 }, (_, i) => {
|
|
869
|
+
const isSelected = i === currentMonth;
|
|
870
|
+
const isCurrent = i === todayMonth && currentYear === todayYear;
|
|
871
|
+
const isFocused = i === focusedIndex;
|
|
872
|
+
const cls = [
|
|
687
873
|
classNames?.month,
|
|
688
|
-
|
|
689
|
-
|
|
874
|
+
isSelected && classNames?.monthSelected,
|
|
875
|
+
isCurrent && classNames?.monthCurrent
|
|
690
876
|
].filter(Boolean).join(" ") || void 0;
|
|
691
877
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
692
878
|
"button",
|
|
693
879
|
{
|
|
694
880
|
type: "button",
|
|
695
881
|
role: "gridcell",
|
|
696
|
-
|
|
697
|
-
"aria-
|
|
698
|
-
"
|
|
699
|
-
"data-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
882
|
+
tabIndex: isFocused ? 0 : -1,
|
|
883
|
+
"aria-selected": isSelected || void 0,
|
|
884
|
+
"aria-current": isCurrent ? "date" : void 0,
|
|
885
|
+
"data-selected": isSelected || void 0,
|
|
886
|
+
"data-current": isCurrent || void 0,
|
|
887
|
+
"data-focused": isFocused || void 0,
|
|
888
|
+
className: cls,
|
|
889
|
+
onClick: () => handleMonthSelect(i),
|
|
890
|
+
children: core.getMonthName(i, locale)
|
|
703
891
|
},
|
|
704
|
-
|
|
892
|
+
i
|
|
705
893
|
);
|
|
706
894
|
})
|
|
707
895
|
}
|
|
@@ -710,38 +898,38 @@ function DatePickerMonthGrid({
|
|
|
710
898
|
}
|
|
711
899
|
function DatePickerYearGrid({ classNames, onSelect, ...props }) {
|
|
712
900
|
const ctx = useDatePickerContext("DatePicker.YearGrid");
|
|
713
|
-
const { adapter, viewMonth } = ctx;
|
|
901
|
+
const { adapter, viewMonth, displayTimezone } = ctx;
|
|
714
902
|
const currentYear = adapter.getYear(viewMonth);
|
|
715
|
-
const
|
|
903
|
+
const [today, setToday] = react.useState(null);
|
|
904
|
+
react.useEffect(() => {
|
|
905
|
+
setToday(adapter.today(displayTimezone));
|
|
906
|
+
}, [adapter, displayTimezone]);
|
|
907
|
+
const todayYear = today !== null ? adapter.getYear(today) : -1;
|
|
716
908
|
const decadeStart = currentYear - currentYear % 12;
|
|
717
909
|
const navigateDecade = react.useCallback(
|
|
718
910
|
(direction) => {
|
|
719
|
-
|
|
720
|
-
ctx.setViewMonth(newDate);
|
|
911
|
+
ctx.setViewMonth(adapter.addYears(viewMonth, direction * 12));
|
|
721
912
|
},
|
|
722
913
|
[adapter, viewMonth, ctx]
|
|
723
914
|
);
|
|
724
915
|
const handleYearSelect = react.useCallback(
|
|
725
|
-
(
|
|
916
|
+
(indexInDecade) => {
|
|
917
|
+
const year = decadeStart + indexInDecade;
|
|
726
918
|
const currentMonth = adapter.getMonth(viewMonth);
|
|
727
919
|
const target = new Date(Date.UTC(year, currentMonth, 1)).toISOString();
|
|
728
920
|
ctx.setViewMonth(target);
|
|
729
921
|
ctx.setFocusedDate(target);
|
|
730
922
|
onSelect?.();
|
|
731
923
|
},
|
|
732
|
-
[adapter, viewMonth, ctx, onSelect]
|
|
733
|
-
);
|
|
734
|
-
const
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
};
|
|
742
|
-
}),
|
|
743
|
-
[decadeStart, currentYear, todayYear]
|
|
744
|
-
);
|
|
924
|
+
[adapter, viewMonth, ctx, onSelect, decadeStart]
|
|
925
|
+
);
|
|
926
|
+
const { gridRef, focusedIndex, handleKeyDown } = useGridState({
|
|
927
|
+
initialIndex: currentYear - decadeStart,
|
|
928
|
+
onSelect: handleYearSelect,
|
|
929
|
+
onPageUp: () => navigateDecade(-1),
|
|
930
|
+
onPageDown: () => navigateDecade(1),
|
|
931
|
+
onEscape: ctx.close
|
|
932
|
+
});
|
|
745
933
|
const rangeLabel = `${decadeStart}\u2013${decadeStart + 11}`;
|
|
746
934
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classNames?.root, ...props, children: [
|
|
747
935
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: classNames?.header, children: [
|
|
@@ -770,30 +958,38 @@ function DatePickerYearGrid({ classNames, onSelect, ...props }) {
|
|
|
770
958
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
771
959
|
"div",
|
|
772
960
|
{
|
|
961
|
+
ref: gridRef,
|
|
773
962
|
role: "grid",
|
|
774
963
|
"aria-label": rangeLabel,
|
|
775
964
|
className: classNames?.grid,
|
|
776
965
|
style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)" },
|
|
777
|
-
|
|
778
|
-
|
|
966
|
+
onKeyDown: handleKeyDown,
|
|
967
|
+
children: Array.from({ length: 12 }, (_, i) => {
|
|
968
|
+
const year = decadeStart + i;
|
|
969
|
+
const isSelected = year === currentYear;
|
|
970
|
+
const isCurrent = year === todayYear;
|
|
971
|
+
const isFocused = i === focusedIndex;
|
|
972
|
+
const cls = [
|
|
779
973
|
classNames?.year,
|
|
780
|
-
|
|
781
|
-
|
|
974
|
+
isSelected && classNames?.yearSelected,
|
|
975
|
+
isCurrent && classNames?.yearCurrent
|
|
782
976
|
].filter(Boolean).join(" ") || void 0;
|
|
783
977
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
784
978
|
"button",
|
|
785
979
|
{
|
|
786
980
|
type: "button",
|
|
787
981
|
role: "gridcell",
|
|
788
|
-
|
|
789
|
-
"aria-
|
|
790
|
-
"
|
|
791
|
-
"data-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
982
|
+
tabIndex: isFocused ? 0 : -1,
|
|
983
|
+
"aria-selected": isSelected || void 0,
|
|
984
|
+
"aria-current": isCurrent ? "date" : void 0,
|
|
985
|
+
"data-selected": isSelected || void 0,
|
|
986
|
+
"data-current": isCurrent || void 0,
|
|
987
|
+
"data-focused": isFocused || void 0,
|
|
988
|
+
className: cls,
|
|
989
|
+
onClick: () => handleYearSelect(i),
|
|
990
|
+
children: year
|
|
795
991
|
},
|
|
796
|
-
|
|
992
|
+
i
|
|
797
993
|
);
|
|
798
994
|
})
|
|
799
995
|
}
|
|
@@ -866,8 +1062,7 @@ function DatePickerPreset({
|
|
|
866
1062
|
"button",
|
|
867
1063
|
{
|
|
868
1064
|
type: "button",
|
|
869
|
-
|
|
870
|
-
"aria-selected": isActive,
|
|
1065
|
+
"aria-pressed": isActive,
|
|
871
1066
|
"data-active": isActive || void 0,
|
|
872
1067
|
disabled: ctx.isDisabled,
|
|
873
1068
|
onClick: handleClick,
|
|
@@ -931,10 +1126,10 @@ function RangePickerRoot({
|
|
|
931
1126
|
const [selectingTarget, setSelectingTarget] = react.useState("start");
|
|
932
1127
|
const [hoverDate, setHoverDate] = react.useState(null);
|
|
933
1128
|
const [viewMonth, setViewMonth] = react.useState(
|
|
934
|
-
currentValue.start ?? adapter.today(displayTimezone)
|
|
1129
|
+
() => currentValue.start ?? adapter.today(displayTimezone)
|
|
935
1130
|
);
|
|
936
1131
|
const [focusedDate, setFocusedDate] = react.useState(
|
|
937
|
-
currentValue.start ?? adapter.today(displayTimezone)
|
|
1132
|
+
() => currentValue.start ?? adapter.today(displayTimezone)
|
|
938
1133
|
);
|
|
939
1134
|
useChangeEffect(isOpen, onOpenChange);
|
|
940
1135
|
const viewMonthStart = react.useMemo(() => adapter.startOfMonth(viewMonth), [viewMonth, adapter]);
|
|
@@ -1084,6 +1279,8 @@ var RangePickerInput = react.forwardRef(
|
|
|
1084
1279
|
(e) => {
|
|
1085
1280
|
if (e.key === "Escape") {
|
|
1086
1281
|
ctx.close();
|
|
1282
|
+
} else if (e.key === "Enter" && ctx.isOpen) {
|
|
1283
|
+
e.preventDefault();
|
|
1087
1284
|
} else if (e.key === "ArrowDown" && !ctx.isOpen) {
|
|
1088
1285
|
e.preventDefault();
|
|
1089
1286
|
ctx.open();
|
|
@@ -1120,6 +1317,7 @@ var RangePickerInput = react.forwardRef(
|
|
|
1120
1317
|
);
|
|
1121
1318
|
}
|
|
1122
1319
|
);
|
|
1320
|
+
RangePickerInput.displayName = "RangePicker.Input";
|
|
1123
1321
|
function RangePickerPopover({ children, ...props }) {
|
|
1124
1322
|
const ctx = useRangePickerContext("RangePicker.Popover");
|
|
1125
1323
|
const calendarId = `${ctx.pickerId}-calendar`;
|
|
@@ -1169,6 +1367,8 @@ var srOnly2 = {
|
|
|
1169
1367
|
function RangePickerCalendar({
|
|
1170
1368
|
classNames,
|
|
1171
1369
|
selectionMode = "range",
|
|
1370
|
+
showWeekNumber = false,
|
|
1371
|
+
fixedWeeks = false,
|
|
1172
1372
|
...props
|
|
1173
1373
|
}) {
|
|
1174
1374
|
const ctx = useRangePickerContext("RangePicker.Calendar");
|
|
@@ -1186,15 +1386,30 @@ function RangePickerCalendar({
|
|
|
1186
1386
|
displayTimezone
|
|
1187
1387
|
} = ctx;
|
|
1188
1388
|
const { locale } = ctx;
|
|
1189
|
-
const weekdays = core.getWeekdayNames(locale, weekStartsOn);
|
|
1190
|
-
const weeks =
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1389
|
+
const weekdays = react.useMemo(() => core.getWeekdayNames(locale, weekStartsOn), [locale, weekStartsOn]);
|
|
1390
|
+
const weeks = react.useMemo(
|
|
1391
|
+
() => core.getCalendarDays(viewMonth, adapter, {
|
|
1392
|
+
weekStartsOn,
|
|
1393
|
+
focusedDate,
|
|
1394
|
+
disabled,
|
|
1395
|
+
range: value,
|
|
1396
|
+
rangeHover: hoverDate,
|
|
1397
|
+
timezone: displayTimezone,
|
|
1398
|
+
fixedWeeks
|
|
1399
|
+
}),
|
|
1400
|
+
[
|
|
1401
|
+
viewMonth,
|
|
1402
|
+
adapter,
|
|
1403
|
+
weekStartsOn,
|
|
1404
|
+
focusedDate,
|
|
1405
|
+
disabled,
|
|
1406
|
+
value,
|
|
1407
|
+
hoverDate,
|
|
1408
|
+
displayTimezone,
|
|
1409
|
+
fixedWeeks
|
|
1410
|
+
]
|
|
1411
|
+
);
|
|
1412
|
+
const thursdayIndex = weekStartsOn === 0 ? 4 : 3;
|
|
1198
1413
|
const year = adapter.getYear(viewMonth);
|
|
1199
1414
|
const month = adapter.getMonth(viewMonth);
|
|
1200
1415
|
const title = core.formatMonthYear(year, month, locale);
|
|
@@ -1294,6 +1509,13 @@ function RangePickerCalendar({
|
|
|
1294
1509
|
}
|
|
1295
1510
|
if (newFocused) {
|
|
1296
1511
|
e.preventDefault();
|
|
1512
|
+
const skipStep = e.key === "ArrowLeft" || e.key === "ArrowUp" || e.key === "PageUp" || e.key === "Home" ? -1 : 1;
|
|
1513
|
+
let attempts = 0;
|
|
1514
|
+
while (core.isDateDisabled(newFocused, disabled, adapter) && attempts < 42) {
|
|
1515
|
+
newFocused = adapter.addDays(newFocused, skipStep);
|
|
1516
|
+
attempts++;
|
|
1517
|
+
}
|
|
1518
|
+
if (attempts >= 42) return;
|
|
1297
1519
|
ctx.setFocusedDate(newFocused);
|
|
1298
1520
|
if (!adapter.isSameMonth(newFocused, viewMonth)) {
|
|
1299
1521
|
ctx.setViewMonth(newFocused);
|
|
@@ -1346,63 +1568,90 @@ function RangePickerCalendar({
|
|
|
1346
1568
|
ref: gridRef,
|
|
1347
1569
|
role: "grid",
|
|
1348
1570
|
"aria-label": title,
|
|
1349
|
-
"aria-
|
|
1571
|
+
"aria-rowcount": weeks.length + 1,
|
|
1572
|
+
"aria-colcount": 7,
|
|
1350
1573
|
className: classNames?.grid,
|
|
1351
1574
|
onKeyDown: handleKeyDown,
|
|
1352
1575
|
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",
|
|
1576
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { role: "row", "aria-rowindex": 1, children: [
|
|
1577
|
+
showWeekNumber ? /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", "aria-hidden": "true", className: classNames?.weekNumberHeader, children: "#" }) : null,
|
|
1578
|
+
weekdays.map((day, colIndex) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1579
|
+
"th",
|
|
1377
1580
|
{
|
|
1378
|
-
role: "
|
|
1379
|
-
|
|
1380
|
-
"
|
|
1381
|
-
"aria-
|
|
1382
|
-
className: classNames?.
|
|
1383
|
-
children:
|
|
1384
|
-
|
|
1581
|
+
role: "columnheader",
|
|
1582
|
+
abbr: day.full,
|
|
1583
|
+
scope: "col",
|
|
1584
|
+
"aria-colindex": colIndex + 1,
|
|
1585
|
+
className: classNames?.weekdayHeader,
|
|
1586
|
+
children: day.short
|
|
1587
|
+
},
|
|
1588
|
+
day.short
|
|
1589
|
+
))
|
|
1590
|
+
] }) }),
|
|
1591
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: weeks.map((week, weekIndex) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1592
|
+
"tr",
|
|
1593
|
+
{
|
|
1594
|
+
role: "row",
|
|
1595
|
+
"aria-rowindex": weekIndex + 2,
|
|
1596
|
+
className: classNames?.gridRow,
|
|
1597
|
+
children: [
|
|
1598
|
+
showWeekNumber ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1599
|
+
"th",
|
|
1385
1600
|
{
|
|
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
|
|
1601
|
+
scope: "row",
|
|
1602
|
+
"aria-hidden": "true",
|
|
1603
|
+
className: classNames?.weekNumber,
|
|
1604
|
+
"data-week-number": true,
|
|
1605
|
+
children: core.getISOWeekNumber(week[thursdayIndex].isoString)
|
|
1400
1606
|
}
|
|
1401
|
-
)
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1607
|
+
) : null,
|
|
1608
|
+
week.map((day, colIndex) => {
|
|
1609
|
+
const dayClasses = [
|
|
1610
|
+
classNames?.day,
|
|
1611
|
+
day.isRangeStart && classNames?.dayRangeStart,
|
|
1612
|
+
day.isRangeEnd && classNames?.dayRangeEnd,
|
|
1613
|
+
day.isInRange && classNames?.dayInRange,
|
|
1614
|
+
day.isToday && classNames?.dayToday,
|
|
1615
|
+
day.isDisabled && classNames?.dayDisabled,
|
|
1616
|
+
!day.isCurrentMonth && classNames?.dayOutsideMonth
|
|
1617
|
+
].filter(Boolean).join(" ") || void 0;
|
|
1618
|
+
const isSelected = selectionMode === "week" ? day.isRangeStart || day.isRangeEnd || day.isInRange : day.isRangeStart || day.isRangeEnd;
|
|
1619
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1620
|
+
"td",
|
|
1621
|
+
{
|
|
1622
|
+
role: "gridcell",
|
|
1623
|
+
"aria-colindex": colIndex + 1,
|
|
1624
|
+
"aria-selected": isSelected || void 0,
|
|
1625
|
+
"aria-disabled": day.isDisabled || void 0,
|
|
1626
|
+
"aria-current": day.isToday ? "date" : void 0,
|
|
1627
|
+
className: classNames?.gridCell,
|
|
1628
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1629
|
+
"button",
|
|
1630
|
+
{
|
|
1631
|
+
type: "button",
|
|
1632
|
+
tabIndex: day.isFocused ? 0 : -1,
|
|
1633
|
+
disabled: day.isDisabled,
|
|
1634
|
+
"data-focused": day.isFocused || void 0,
|
|
1635
|
+
"data-range-start": day.isRangeStart || void 0,
|
|
1636
|
+
"data-range-end": day.isRangeEnd || void 0,
|
|
1637
|
+
"data-in-range": day.isInRange || void 0,
|
|
1638
|
+
"data-today": day.isToday || void 0,
|
|
1639
|
+
"data-outside-month": !day.isCurrentMonth || void 0,
|
|
1640
|
+
className: dayClasses,
|
|
1641
|
+
onClick: () => handleDayClick(day),
|
|
1642
|
+
onMouseEnter: () => handleDayMouseEnter(day),
|
|
1643
|
+
"aria-label": safeFormatFullDate2(day.isoString, locale),
|
|
1644
|
+
children: day.dayNumber
|
|
1645
|
+
}
|
|
1646
|
+
)
|
|
1647
|
+
},
|
|
1648
|
+
day.isoString
|
|
1649
|
+
);
|
|
1650
|
+
})
|
|
1651
|
+
]
|
|
1652
|
+
},
|
|
1653
|
+
weekIndex
|
|
1654
|
+
)) })
|
|
1406
1655
|
]
|
|
1407
1656
|
}
|
|
1408
1657
|
),
|
|
@@ -1464,41 +1713,33 @@ function RangePickerPreset({
|
|
|
1464
1713
|
...props
|
|
1465
1714
|
}) {
|
|
1466
1715
|
const ctx = useRangePickerContext("RangePicker.Preset");
|
|
1716
|
+
const resolved = react.useMemo(() => {
|
|
1717
|
+
if (directRange) return directRange;
|
|
1718
|
+
if (presetKey)
|
|
1719
|
+
return resolvePreset(presetKey, ctx.adapter.today(ctx.displayTimezone), ctx.adapter);
|
|
1720
|
+
return null;
|
|
1721
|
+
}, [directRange, presetKey, ctx.adapter, ctx.displayTimezone]);
|
|
1467
1722
|
const handleClick = react.useCallback(
|
|
1468
1723
|
(e) => {
|
|
1469
1724
|
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
|
-
}
|
|
1725
|
+
if (!resolved) return;
|
|
1478
1726
|
ctx.setRange(resolved);
|
|
1479
1727
|
ctx.close();
|
|
1480
1728
|
onClick?.(e);
|
|
1481
1729
|
},
|
|
1482
|
-
[ctx,
|
|
1730
|
+
[ctx, resolved, onClick]
|
|
1483
1731
|
);
|
|
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 {
|
|
1732
|
+
const isActive = react.useMemo(() => {
|
|
1733
|
+
if (!ctx.value.start || !ctx.value.end || !resolved || !resolved.start || !resolved.end) {
|
|
1492
1734
|
return false;
|
|
1493
1735
|
}
|
|
1494
|
-
return
|
|
1495
|
-
})
|
|
1736
|
+
return ctx.adapter.isSameDay(ctx.value.start, resolved.start) && ctx.adapter.isSameDay(ctx.value.end, resolved.end);
|
|
1737
|
+
}, [ctx.value.start, ctx.value.end, ctx.adapter, resolved]);
|
|
1496
1738
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1497
1739
|
"button",
|
|
1498
1740
|
{
|
|
1499
1741
|
type: "button",
|
|
1500
|
-
|
|
1501
|
-
"aria-selected": isActive,
|
|
1742
|
+
"aria-pressed": isActive,
|
|
1502
1743
|
"data-active": isActive || void 0,
|
|
1503
1744
|
disabled: ctx.isDisabled,
|
|
1504
1745
|
onClick: handleClick,
|
|
@@ -1531,9 +1772,6 @@ function useTimePickerContext(componentName) {
|
|
|
1531
1772
|
}
|
|
1532
1773
|
return context;
|
|
1533
1774
|
}
|
|
1534
|
-
function getDefaultIso() {
|
|
1535
|
-
return core.DateFnsAdapter.today();
|
|
1536
|
-
}
|
|
1537
1775
|
function TimePickerRoot({
|
|
1538
1776
|
value: controlledValue,
|
|
1539
1777
|
defaultValue,
|
|
@@ -1544,6 +1782,7 @@ function TimePickerRoot({
|
|
|
1544
1782
|
displayTimezone,
|
|
1545
1783
|
disabled = false,
|
|
1546
1784
|
readOnly = false,
|
|
1785
|
+
filterTime,
|
|
1547
1786
|
labels: labelsProp,
|
|
1548
1787
|
children
|
|
1549
1788
|
}) {
|
|
@@ -1557,21 +1796,21 @@ function TimePickerRoot({
|
|
|
1557
1796
|
defaultValue ?? null
|
|
1558
1797
|
);
|
|
1559
1798
|
const currentValue = isControlled ? controlledValue ?? null : uncontrolledValue;
|
|
1560
|
-
const
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
);
|
|
1799
|
+
const currentTime = react.useMemo(() => {
|
|
1800
|
+
if (!currentValue) return { hours: 0, minutes: 0, seconds: 0 };
|
|
1801
|
+
return displayTimezone ? core.getTimeInTimezone(currentValue, displayTimezone) : core.getTime(currentValue);
|
|
1802
|
+
}, [currentValue, displayTimezone]);
|
|
1565
1803
|
const setTime = react.useCallback(
|
|
1566
1804
|
(partial) => {
|
|
1567
1805
|
if (disabled || readOnly) return;
|
|
1568
|
-
const
|
|
1806
|
+
const base = currentValue ?? core.DateFnsAdapter.today(displayTimezone);
|
|
1807
|
+
const newIso = displayTimezone ? core.setTimeInTimezone(base, partial, displayTimezone) : core.setTime(base, partial);
|
|
1569
1808
|
if (!isControlled) {
|
|
1570
1809
|
setUncontrolledValue(newIso);
|
|
1571
1810
|
}
|
|
1572
1811
|
onChange?.(newIso);
|
|
1573
1812
|
},
|
|
1574
|
-
[disabled, readOnly,
|
|
1813
|
+
[disabled, readOnly, currentValue, displayTimezone, isControlled, onChange]
|
|
1575
1814
|
);
|
|
1576
1815
|
const contextValue = react.useMemo(
|
|
1577
1816
|
() => ({
|
|
@@ -1585,7 +1824,8 @@ function TimePickerRoot({
|
|
|
1585
1824
|
isReadOnly: readOnly,
|
|
1586
1825
|
currentTime,
|
|
1587
1826
|
pickerId,
|
|
1588
|
-
labels: mergedLabels
|
|
1827
|
+
labels: mergedLabels,
|
|
1828
|
+
filterTime
|
|
1589
1829
|
}),
|
|
1590
1830
|
[
|
|
1591
1831
|
currentValue,
|
|
@@ -1598,7 +1838,8 @@ function TimePickerRoot({
|
|
|
1598
1838
|
readOnly,
|
|
1599
1839
|
currentTime,
|
|
1600
1840
|
pickerId,
|
|
1601
|
-
mergedLabels
|
|
1841
|
+
mergedLabels,
|
|
1842
|
+
filterTime
|
|
1602
1843
|
]
|
|
1603
1844
|
);
|
|
1604
1845
|
return /* @__PURE__ */ jsxRuntime.jsx(TimePickerContext.Provider, { value: contextValue, children });
|
|
@@ -1655,6 +1896,7 @@ var TimePickerInput = react.forwardRef(
|
|
|
1655
1896
|
);
|
|
1656
1897
|
}
|
|
1657
1898
|
);
|
|
1899
|
+
TimePickerInput.displayName = "TimePicker.Input";
|
|
1658
1900
|
function useListboxNavigation({
|
|
1659
1901
|
items,
|
|
1660
1902
|
onSelect,
|
|
@@ -1702,17 +1944,41 @@ function useListboxNavigation({
|
|
|
1702
1944
|
}
|
|
1703
1945
|
function TimePickerHourList({ classNames, ...props }) {
|
|
1704
1946
|
const ctx = useTimePickerContext("TimePicker.HourList");
|
|
1705
|
-
const { format, currentTime, isDisabled, isReadOnly } = ctx;
|
|
1706
|
-
const hours = core.generateHours(format);
|
|
1947
|
+
const { format, step, currentTime, isDisabled, isReadOnly, filterTime } = ctx;
|
|
1948
|
+
const hours = react.useMemo(() => core.generateHours(format), [format]);
|
|
1707
1949
|
const selectedHourDisplay = format === "12h" ? core.to12Hour(currentTime.hours).hours12 : currentTime.hours;
|
|
1708
1950
|
const currentPeriod = format === "12h" ? core.to12Hour(currentTime.hours).period : null;
|
|
1951
|
+
const fullyDisabledHours24 = react.useMemo(() => {
|
|
1952
|
+
if (!filterTime) return null;
|
|
1953
|
+
const disabled = /* @__PURE__ */ new Set();
|
|
1954
|
+
for (let h = 0; h < 24; h++) {
|
|
1955
|
+
let allRejected = true;
|
|
1956
|
+
for (let m = 0; m < 60; m += step) {
|
|
1957
|
+
if (!filterTime(h, m)) {
|
|
1958
|
+
allRejected = false;
|
|
1959
|
+
break;
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1962
|
+
if (allRejected) disabled.add(h);
|
|
1963
|
+
}
|
|
1964
|
+
return disabled;
|
|
1965
|
+
}, [filterTime, step]);
|
|
1966
|
+
const isHourDisabled = react.useCallback(
|
|
1967
|
+
(hourDisplay) => {
|
|
1968
|
+
if (!fullyDisabledHours24) return false;
|
|
1969
|
+
const hours24 = format === "12h" && currentPeriod ? core.to24Hour(hourDisplay, currentPeriod) : hourDisplay;
|
|
1970
|
+
return fullyDisabledHours24.has(hours24);
|
|
1971
|
+
},
|
|
1972
|
+
[fullyDisabledHours24, format, currentPeriod]
|
|
1973
|
+
);
|
|
1709
1974
|
const handleSelect = react.useCallback(
|
|
1710
1975
|
(hourDisplay) => {
|
|
1711
1976
|
if (isDisabled || isReadOnly) return;
|
|
1977
|
+
if (isHourDisabled(hourDisplay)) return;
|
|
1712
1978
|
const hours24 = format === "12h" && currentPeriod ? core.to24Hour(hourDisplay, currentPeriod) : hourDisplay;
|
|
1713
1979
|
ctx.setTime({ hours: hours24 });
|
|
1714
1980
|
},
|
|
1715
|
-
[format, currentPeriod, ctx, isDisabled, isReadOnly]
|
|
1981
|
+
[format, currentPeriod, ctx, isDisabled, isReadOnly, isHourDisabled]
|
|
1716
1982
|
);
|
|
1717
1983
|
const { listRef, handleKeyDown } = useListboxNavigation({
|
|
1718
1984
|
items: hours,
|
|
@@ -1730,13 +1996,14 @@ function TimePickerHourList({ classNames, ...props }) {
|
|
|
1730
1996
|
...props,
|
|
1731
1997
|
children: hours.map((hour) => {
|
|
1732
1998
|
const isSelected = hour === selectedHourDisplay;
|
|
1999
|
+
const isHourFullyDisabled = isHourDisabled(hour);
|
|
1733
2000
|
const optionClass = [classNames?.option, isSelected && classNames?.optionSelected].filter(Boolean).join(" ") || void 0;
|
|
1734
2001
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1735
2002
|
"li",
|
|
1736
2003
|
{
|
|
1737
2004
|
role: "option",
|
|
1738
2005
|
"aria-selected": isSelected,
|
|
1739
|
-
"aria-disabled": isDisabled || void 0,
|
|
2006
|
+
"aria-disabled": isDisabled || isHourFullyDisabled || void 0,
|
|
1740
2007
|
"aria-label": ctx.labels.hourOption(hour),
|
|
1741
2008
|
"data-selected": isSelected || void 0,
|
|
1742
2009
|
tabIndex: isSelected ? 0 : -1,
|
|
@@ -1753,14 +2020,22 @@ function TimePickerHourList({ classNames, ...props }) {
|
|
|
1753
2020
|
}
|
|
1754
2021
|
function TimePickerMinuteList({ classNames, ...props }) {
|
|
1755
2022
|
const ctx = useTimePickerContext("TimePicker.MinuteList");
|
|
1756
|
-
const { step, currentTime, isDisabled, isReadOnly } = ctx;
|
|
1757
|
-
const minutes = core.generateMinutes(step);
|
|
2023
|
+
const { step, currentTime, isDisabled, isReadOnly, filterTime } = ctx;
|
|
2024
|
+
const minutes = react.useMemo(() => core.generateMinutes(step), [step]);
|
|
2025
|
+
const isMinuteDisabled = react.useCallback(
|
|
2026
|
+
(minute) => {
|
|
2027
|
+
if (!filterTime) return false;
|
|
2028
|
+
return filterTime(currentTime.hours, minute);
|
|
2029
|
+
},
|
|
2030
|
+
[filterTime, currentTime.hours]
|
|
2031
|
+
);
|
|
1758
2032
|
const handleSelect = react.useCallback(
|
|
1759
2033
|
(minute) => {
|
|
1760
2034
|
if (isDisabled || isReadOnly) return;
|
|
2035
|
+
if (isMinuteDisabled(minute)) return;
|
|
1761
2036
|
ctx.setTime({ minutes: minute });
|
|
1762
2037
|
},
|
|
1763
|
-
[ctx, isDisabled, isReadOnly]
|
|
2038
|
+
[ctx, isDisabled, isReadOnly, isMinuteDisabled]
|
|
1764
2039
|
);
|
|
1765
2040
|
const { listRef, handleKeyDown } = useListboxNavigation({
|
|
1766
2041
|
items: minutes,
|
|
@@ -1778,13 +2053,14 @@ function TimePickerMinuteList({ classNames, ...props }) {
|
|
|
1778
2053
|
...props,
|
|
1779
2054
|
children: minutes.map((minute) => {
|
|
1780
2055
|
const isSelected = minute === currentTime.minutes;
|
|
2056
|
+
const isMinuteFullyDisabled = isMinuteDisabled(minute);
|
|
1781
2057
|
const optionClass = [classNames?.option, isSelected && classNames?.optionSelected].filter(Boolean).join(" ") || void 0;
|
|
1782
2058
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1783
2059
|
"li",
|
|
1784
2060
|
{
|
|
1785
2061
|
role: "option",
|
|
1786
2062
|
"aria-selected": isSelected,
|
|
1787
|
-
"aria-disabled": isDisabled || void 0,
|
|
2063
|
+
"aria-disabled": isDisabled || isMinuteFullyDisabled || void 0,
|
|
1788
2064
|
"aria-label": ctx.labels.minuteOption(minute),
|
|
1789
2065
|
"data-selected": isSelected || void 0,
|
|
1790
2066
|
tabIndex: isSelected ? 0 : -1,
|
|
@@ -1801,29 +2077,70 @@ function TimePickerMinuteList({ classNames, ...props }) {
|
|
|
1801
2077
|
}
|
|
1802
2078
|
function TimePickerAmPmToggle({ classNames, ...props }) {
|
|
1803
2079
|
const ctx = useTimePickerContext("TimePicker.AmPmToggle");
|
|
1804
|
-
|
|
1805
|
-
const
|
|
2080
|
+
const amRef = react.useRef(null);
|
|
2081
|
+
const pmRef = react.useRef(null);
|
|
1806
2082
|
const setPeriod = react.useCallback(
|
|
1807
2083
|
(newPeriod) => {
|
|
1808
2084
|
if (ctx.isDisabled || ctx.isReadOnly) return;
|
|
2085
|
+
const { hours12 } = core.to12Hour(ctx.currentTime.hours);
|
|
1809
2086
|
const newHours24 = core.to24Hour(hours12, newPeriod);
|
|
1810
2087
|
ctx.setTime({ hours: newHours24 });
|
|
1811
2088
|
},
|
|
1812
|
-
[
|
|
2089
|
+
[ctx]
|
|
1813
2090
|
);
|
|
2091
|
+
if (ctx.format !== "12h") return null;
|
|
2092
|
+
const { period } = core.to12Hour(ctx.currentTime.hours);
|
|
2093
|
+
const focusOther = (target) => {
|
|
2094
|
+
(target === "AM" ? amRef : pmRef).current?.focus();
|
|
2095
|
+
};
|
|
2096
|
+
const handleKeyDown = (e, target) => {
|
|
2097
|
+
switch (e.key) {
|
|
2098
|
+
case "ArrowRight":
|
|
2099
|
+
case "ArrowDown":
|
|
2100
|
+
case "ArrowLeft":
|
|
2101
|
+
case "ArrowUp": {
|
|
2102
|
+
e.preventDefault();
|
|
2103
|
+
const next = target === "AM" ? "PM" : "AM";
|
|
2104
|
+
setPeriod(next);
|
|
2105
|
+
focusOther(next);
|
|
2106
|
+
break;
|
|
2107
|
+
}
|
|
2108
|
+
case "Home": {
|
|
2109
|
+
e.preventDefault();
|
|
2110
|
+
setPeriod("AM");
|
|
2111
|
+
focusOther("AM");
|
|
2112
|
+
break;
|
|
2113
|
+
}
|
|
2114
|
+
case "End": {
|
|
2115
|
+
e.preventDefault();
|
|
2116
|
+
setPeriod("PM");
|
|
2117
|
+
focusOther("PM");
|
|
2118
|
+
break;
|
|
2119
|
+
}
|
|
2120
|
+
case " ":
|
|
2121
|
+
case "Enter": {
|
|
2122
|
+
e.preventDefault();
|
|
2123
|
+
setPeriod(target);
|
|
2124
|
+
break;
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
};
|
|
1814
2128
|
const renderButton = (target) => {
|
|
1815
2129
|
const isSelected = period === target;
|
|
1816
2130
|
const optionClass = [classNames?.option, isSelected && classNames?.optionSelected].filter(Boolean).join(" ") || void 0;
|
|
1817
2131
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1818
2132
|
"button",
|
|
1819
2133
|
{
|
|
2134
|
+
ref: target === "AM" ? amRef : pmRef,
|
|
1820
2135
|
type: "button",
|
|
1821
2136
|
role: "radio",
|
|
1822
2137
|
"aria-checked": isSelected,
|
|
2138
|
+
tabIndex: isSelected ? 0 : -1,
|
|
1823
2139
|
"data-selected": isSelected || void 0,
|
|
1824
2140
|
disabled: ctx.isDisabled,
|
|
1825
2141
|
className: optionClass,
|
|
1826
2142
|
onClick: () => setPeriod(target),
|
|
2143
|
+
onKeyDown: (e) => handleKeyDown(e, target),
|
|
1827
2144
|
children: target
|
|
1828
2145
|
}
|
|
1829
2146
|
);
|
|
@@ -1850,9 +2167,6 @@ var TimePicker = Object.assign(TimePickerRoot, {
|
|
|
1850
2167
|
MinuteList: TimePickerMinuteList,
|
|
1851
2168
|
AmPmToggle: TimePickerAmPmToggle
|
|
1852
2169
|
});
|
|
1853
|
-
function getDefaultIso2() {
|
|
1854
|
-
return core.DateFnsAdapter.today();
|
|
1855
|
-
}
|
|
1856
2170
|
function DateTimePickerRoot({
|
|
1857
2171
|
value: controlledValue,
|
|
1858
2172
|
defaultValue,
|
|
@@ -1861,6 +2175,8 @@ function DateTimePickerRoot({
|
|
|
1861
2175
|
onCalendarNavigate,
|
|
1862
2176
|
format = "24h",
|
|
1863
2177
|
step = 1,
|
|
2178
|
+
withSeconds = false,
|
|
2179
|
+
filterTime,
|
|
1864
2180
|
disabled = false,
|
|
1865
2181
|
readOnly = false,
|
|
1866
2182
|
weekStartsOn = 0,
|
|
@@ -1888,10 +2204,10 @@ function DateTimePickerRoot({
|
|
|
1888
2204
|
const currentValue = isControlled ? controlledValue ?? null : uncontrolledValue;
|
|
1889
2205
|
const [isOpen, setIsOpen] = react.useState(false);
|
|
1890
2206
|
const [viewMonth, setViewMonth] = react.useState(
|
|
1891
|
-
currentValue ?? adapter.today(displayTimezone)
|
|
2207
|
+
() => currentValue ?? adapter.today(displayTimezone)
|
|
1892
2208
|
);
|
|
1893
2209
|
const [focusedDate, setFocusedDate] = react.useState(
|
|
1894
|
-
currentValue ?? adapter.today(displayTimezone)
|
|
2210
|
+
() => currentValue ?? adapter.today(displayTimezone)
|
|
1895
2211
|
);
|
|
1896
2212
|
useChangeEffect(isOpen, onOpenChange);
|
|
1897
2213
|
const viewMonthStart = react.useMemo(() => adapter.startOfMonth(viewMonth), [viewMonth, adapter]);
|
|
@@ -1901,11 +2217,10 @@ function DateTimePickerRoot({
|
|
|
1901
2217
|
() => Array.isArray(disabled) ? disabled : [],
|
|
1902
2218
|
[disabled]
|
|
1903
2219
|
);
|
|
1904
|
-
const
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
);
|
|
2220
|
+
const currentTime = react.useMemo(() => {
|
|
2221
|
+
if (!currentValue) return { hours: 0, minutes: 0, seconds: 0 };
|
|
2222
|
+
return displayTimezone ? core.getTimeInTimezone(currentValue, displayTimezone) : core.getTime(currentValue);
|
|
2223
|
+
}, [currentValue, displayTimezone]);
|
|
1909
2224
|
const updateValue = react.useCallback(
|
|
1910
2225
|
(next) => {
|
|
1911
2226
|
if (isDisabled || readOnly) return;
|
|
@@ -1931,11 +2246,11 @@ function DateTimePickerRoot({
|
|
|
1931
2246
|
);
|
|
1932
2247
|
const setTime = react.useCallback(
|
|
1933
2248
|
(partial) => {
|
|
1934
|
-
const base = currentValue ??
|
|
2249
|
+
const base = currentValue ?? adapter.today(displayTimezone);
|
|
1935
2250
|
const merged = displayTimezone ? core.setTimeInTimezone(base, partial, displayTimezone) : core.setTime(base, partial);
|
|
1936
2251
|
updateValue(merged);
|
|
1937
2252
|
},
|
|
1938
|
-
[currentValue, updateValue, displayTimezone]
|
|
2253
|
+
[currentValue, updateValue, displayTimezone, adapter]
|
|
1939
2254
|
);
|
|
1940
2255
|
const open = react.useCallback(() => {
|
|
1941
2256
|
if (isDisabled || readOnly) return;
|
|
@@ -2002,25 +2317,28 @@ function DateTimePickerRoot({
|
|
|
2002
2317
|
setTime,
|
|
2003
2318
|
format,
|
|
2004
2319
|
step,
|
|
2005
|
-
withSeconds
|
|
2320
|
+
withSeconds,
|
|
2006
2321
|
displayTimezone,
|
|
2007
2322
|
isDisabled,
|
|
2008
2323
|
isReadOnly: readOnly,
|
|
2009
2324
|
currentTime,
|
|
2010
2325
|
pickerId,
|
|
2011
|
-
labels: mergedTimeLabels
|
|
2326
|
+
labels: mergedTimeLabels,
|
|
2327
|
+
filterTime
|
|
2012
2328
|
}),
|
|
2013
2329
|
[
|
|
2014
2330
|
currentValue,
|
|
2015
2331
|
setTime,
|
|
2016
2332
|
format,
|
|
2017
2333
|
step,
|
|
2334
|
+
withSeconds,
|
|
2018
2335
|
displayTimezone,
|
|
2019
2336
|
isDisabled,
|
|
2020
2337
|
readOnly,
|
|
2021
2338
|
currentTime,
|
|
2022
2339
|
pickerId,
|
|
2023
|
-
mergedTimeLabels
|
|
2340
|
+
mergedTimeLabels,
|
|
2341
|
+
filterTime
|
|
2024
2342
|
]
|
|
2025
2343
|
);
|
|
2026
2344
|
return /* @__PURE__ */ jsxRuntime.jsx(DatePickerContext.Provider, { value: dateContext, children: /* @__PURE__ */ jsxRuntime.jsx(TimePickerContext.Provider, { value: timeContext, children }) });
|
|
@@ -2049,6 +2367,8 @@ var DateTimePickerInput = react.forwardRef(
|
|
|
2049
2367
|
(e) => {
|
|
2050
2368
|
if (e.key === "Escape") {
|
|
2051
2369
|
ctx.close();
|
|
2370
|
+
} else if (e.key === "Enter" && ctx.isOpen) {
|
|
2371
|
+
e.preventDefault();
|
|
2052
2372
|
} else if (e.key === "ArrowDown" && !ctx.isOpen) {
|
|
2053
2373
|
e.preventDefault();
|
|
2054
2374
|
ctx.open();
|
|
@@ -2084,6 +2404,7 @@ var DateTimePickerInput = react.forwardRef(
|
|
|
2084
2404
|
);
|
|
2085
2405
|
}
|
|
2086
2406
|
);
|
|
2407
|
+
DateTimePickerInput.displayName = "DateTimePicker.Input";
|
|
2087
2408
|
|
|
2088
2409
|
// src/components/DateTimePicker/index.ts
|
|
2089
2410
|
var DateTimePicker = Object.assign(DateTimePickerRoot, {
|
|
@@ -2102,7 +2423,7 @@ function MonthPickerRoot(props) {
|
|
|
2102
2423
|
}
|
|
2103
2424
|
function MonthPickerGrid({ classNames, ...props }) {
|
|
2104
2425
|
const ctx = useDatePickerContext("MonthPicker.Grid");
|
|
2105
|
-
const { adapter, viewMonth, locale, value, displayTimezone, labels } = ctx;
|
|
2426
|
+
const { adapter, viewMonth, locale, value, displayTimezone, labels, disabled } = ctx;
|
|
2106
2427
|
const currentYear = adapter.getYear(viewMonth);
|
|
2107
2428
|
const [valueYear, valueMonthZeroBased] = react.useMemo(() => {
|
|
2108
2429
|
if (!value) return [null, null];
|
|
@@ -2113,9 +2434,19 @@ function MonthPickerGrid({ classNames, ...props }) {
|
|
|
2113
2434
|
return [null, null];
|
|
2114
2435
|
}
|
|
2115
2436
|
}, [value, adapter, displayTimezone]);
|
|
2116
|
-
const today =
|
|
2117
|
-
|
|
2118
|
-
|
|
2437
|
+
const [today, setToday] = react.useState(null);
|
|
2438
|
+
react.useEffect(() => {
|
|
2439
|
+
setToday(adapter.today(displayTimezone));
|
|
2440
|
+
}, [adapter, displayTimezone]);
|
|
2441
|
+
const todayYear = today !== null ? adapter.getYear(today) : -1;
|
|
2442
|
+
const todayMonth = today !== null ? adapter.getMonth(today) : -1;
|
|
2443
|
+
const monthDisabledFlags = react.useMemo(
|
|
2444
|
+
() => Array.from({ length: 12 }, (_, i) => {
|
|
2445
|
+
const monthStart = new Date(Date.UTC(currentYear, i, 1)).toISOString();
|
|
2446
|
+
return isRangeFullyDisabled(monthStart, adapter.endOfMonth(monthStart), disabled, adapter);
|
|
2447
|
+
}),
|
|
2448
|
+
[currentYear, disabled, adapter]
|
|
2449
|
+
);
|
|
2119
2450
|
const navigateYear = react.useCallback(
|
|
2120
2451
|
(direction) => {
|
|
2121
2452
|
ctx.setViewMonth(adapter.addYears(viewMonth, direction));
|
|
@@ -2124,17 +2455,23 @@ function MonthPickerGrid({ classNames, ...props }) {
|
|
|
2124
2455
|
);
|
|
2125
2456
|
const handleMonthSelect = react.useCallback(
|
|
2126
2457
|
(monthIndex) => {
|
|
2458
|
+
if (monthDisabledFlags[monthIndex]) return;
|
|
2127
2459
|
const target = new Date(Date.UTC(currentYear, monthIndex, 1)).toISOString();
|
|
2128
2460
|
ctx.selectDate(target);
|
|
2129
2461
|
},
|
|
2130
|
-
[currentYear, ctx]
|
|
2131
|
-
);
|
|
2132
|
-
const
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2462
|
+
[currentYear, ctx, monthDisabledFlags]
|
|
2463
|
+
);
|
|
2464
|
+
const naturalIndex = valueYear === currentYear && valueMonthZeroBased !== null ? valueMonthZeroBased : adapter.getMonth(viewMonth);
|
|
2465
|
+
const firstEnabled = monthDisabledFlags.findIndex((d) => !d);
|
|
2466
|
+
const initialIndex = monthDisabledFlags[naturalIndex] ? firstEnabled === -1 ? naturalIndex : firstEnabled : naturalIndex;
|
|
2467
|
+
const { gridRef, focusedIndex, handleKeyDown } = useGridState({
|
|
2468
|
+
initialIndex,
|
|
2469
|
+
disabledFlags: monthDisabledFlags,
|
|
2470
|
+
onSelect: handleMonthSelect,
|
|
2471
|
+
onPageUp: () => navigateYear(-1),
|
|
2472
|
+
onPageDown: () => navigateYear(1),
|
|
2473
|
+
onEscape: ctx.close
|
|
2474
|
+
});
|
|
2138
2475
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classNames?.root, ...props, children: [
|
|
2139
2476
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: classNames?.header, children: [
|
|
2140
2477
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2159,37 +2496,57 @@ function MonthPickerGrid({ classNames, ...props }) {
|
|
|
2159
2496
|
}
|
|
2160
2497
|
)
|
|
2161
2498
|
] }),
|
|
2162
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2499
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2163
2500
|
"div",
|
|
2164
2501
|
{
|
|
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
|
-
|
|
2502
|
+
ref: gridRef,
|
|
2503
|
+
role: "grid",
|
|
2504
|
+
"aria-label": `${currentYear} months`,
|
|
2505
|
+
className: classNames?.grid,
|
|
2506
|
+
onKeyDown: handleKeyDown,
|
|
2507
|
+
children: Array.from({ length: 4 }, (_, rowIndex) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2508
|
+
"div",
|
|
2509
|
+
{
|
|
2510
|
+
role: "row",
|
|
2511
|
+
className: classNames?.gridRow,
|
|
2512
|
+
style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)" },
|
|
2513
|
+
children: Array.from({ length: 3 }, (_2, col) => {
|
|
2514
|
+
const i = rowIndex * 3 + col;
|
|
2515
|
+
const isSelected = valueYear === currentYear && valueMonthZeroBased === i;
|
|
2516
|
+
const isCurrent = todayYear === currentYear && todayMonth === i;
|
|
2517
|
+
const isFocused = i === focusedIndex;
|
|
2518
|
+
const isDisabled = monthDisabledFlags[i] ?? false;
|
|
2519
|
+
const cls = [
|
|
2520
|
+
classNames?.month,
|
|
2521
|
+
isSelected && classNames?.monthSelected,
|
|
2522
|
+
isCurrent && classNames?.monthCurrent,
|
|
2523
|
+
isDisabled && classNames?.monthDisabled
|
|
2524
|
+
].filter(Boolean).join(" ") || void 0;
|
|
2525
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2526
|
+
"button",
|
|
2527
|
+
{
|
|
2528
|
+
type: "button",
|
|
2529
|
+
role: "gridcell",
|
|
2530
|
+
tabIndex: isFocused ? 0 : -1,
|
|
2531
|
+
disabled: isDisabled,
|
|
2532
|
+
"aria-selected": isSelected || void 0,
|
|
2533
|
+
"aria-disabled": isDisabled || void 0,
|
|
2534
|
+
"aria-current": isCurrent ? "date" : void 0,
|
|
2535
|
+
"data-selected": isSelected || void 0,
|
|
2536
|
+
"data-current": isCurrent || void 0,
|
|
2537
|
+
"data-focused": isFocused || void 0,
|
|
2538
|
+
className: cls,
|
|
2539
|
+
onClick: () => handleMonthSelect(i),
|
|
2540
|
+
children: core.getMonthName(i, locale)
|
|
2541
|
+
},
|
|
2542
|
+
i
|
|
2543
|
+
);
|
|
2544
|
+
})
|
|
2545
|
+
},
|
|
2546
|
+
rowIndex
|
|
2547
|
+
))
|
|
2548
|
+
}
|
|
2549
|
+
)
|
|
2193
2550
|
] });
|
|
2194
2551
|
}
|
|
2195
2552
|
|
|
@@ -2206,7 +2563,7 @@ function YearPickerRoot(props) {
|
|
|
2206
2563
|
}
|
|
2207
2564
|
function YearPickerGrid({ classNames, ...props }) {
|
|
2208
2565
|
const ctx = useDatePickerContext("YearPicker.Grid");
|
|
2209
|
-
const { adapter, viewMonth, value, displayTimezone, labels } = ctx;
|
|
2566
|
+
const { adapter, viewMonth, value, displayTimezone, labels, disabled } = ctx;
|
|
2210
2567
|
const currentYear = adapter.getYear(viewMonth);
|
|
2211
2568
|
const decadeStart = currentYear - currentYear % 12;
|
|
2212
2569
|
const valueYear = react.useMemo(() => {
|
|
@@ -2217,7 +2574,20 @@ function YearPickerGrid({ classNames, ...props }) {
|
|
|
2217
2574
|
return null;
|
|
2218
2575
|
}
|
|
2219
2576
|
}, [value, adapter, displayTimezone]);
|
|
2220
|
-
const
|
|
2577
|
+
const [today, setToday] = react.useState(null);
|
|
2578
|
+
react.useEffect(() => {
|
|
2579
|
+
setToday(adapter.today(displayTimezone));
|
|
2580
|
+
}, [adapter, displayTimezone]);
|
|
2581
|
+
const todayYear = today !== null ? adapter.getYear(today) : -1;
|
|
2582
|
+
const yearDisabledFlags = react.useMemo(
|
|
2583
|
+
() => Array.from({ length: 12 }, (_, i) => {
|
|
2584
|
+
const year = decadeStart + i;
|
|
2585
|
+
const yearStart = new Date(Date.UTC(year, 0, 1)).toISOString();
|
|
2586
|
+
const yearEnd = new Date(Date.UTC(year, 11, 31, 23, 59, 59, 999)).toISOString();
|
|
2587
|
+
return isRangeFullyDisabled(yearStart, yearEnd, disabled, adapter);
|
|
2588
|
+
}),
|
|
2589
|
+
[decadeStart, disabled, adapter]
|
|
2590
|
+
);
|
|
2221
2591
|
const navigateDecade = react.useCallback(
|
|
2222
2592
|
(direction) => {
|
|
2223
2593
|
ctx.setViewMonth(adapter.addYears(viewMonth, direction * 12));
|
|
@@ -2225,19 +2595,24 @@ function YearPickerGrid({ classNames, ...props }) {
|
|
|
2225
2595
|
[adapter, viewMonth, ctx]
|
|
2226
2596
|
);
|
|
2227
2597
|
const handleYearSelect = react.useCallback(
|
|
2228
|
-
(
|
|
2598
|
+
(indexInDecade) => {
|
|
2599
|
+
if (yearDisabledFlags[indexInDecade]) return;
|
|
2600
|
+
const year = decadeStart + indexInDecade;
|
|
2229
2601
|
const target = new Date(Date.UTC(year, 0, 1)).toISOString();
|
|
2230
2602
|
ctx.selectDate(target);
|
|
2231
2603
|
},
|
|
2232
|
-
[ctx]
|
|
2233
|
-
);
|
|
2234
|
-
const
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2604
|
+
[ctx, decadeStart, yearDisabledFlags]
|
|
2605
|
+
);
|
|
2606
|
+
const naturalIndex = valueYear !== null && valueYear >= decadeStart && valueYear <= decadeStart + 11 ? valueYear - decadeStart : currentYear - decadeStart;
|
|
2607
|
+
const firstEnabled = yearDisabledFlags.findIndex((d) => !d);
|
|
2608
|
+
const initialIndex = yearDisabledFlags[naturalIndex] ? firstEnabled === -1 ? naturalIndex : firstEnabled : naturalIndex;
|
|
2609
|
+
const { gridRef, focusedIndex, handleKeyDown } = useGridState({
|
|
2610
|
+
initialIndex,
|
|
2611
|
+
disabledFlags: yearDisabledFlags,
|
|
2612
|
+
onSelect: handleYearSelect,
|
|
2613
|
+
onPageUp: () => navigateDecade(-1),
|
|
2614
|
+
onPageDown: () => navigateDecade(1),
|
|
2615
|
+
onEscape: ctx.close
|
|
2241
2616
|
});
|
|
2242
2617
|
const rangeLabel = `${decadeStart}\u2013${decadeStart + 11}`;
|
|
2243
2618
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classNames?.root, ...props, children: [
|
|
@@ -2264,37 +2639,58 @@ function YearPickerGrid({ classNames, ...props }) {
|
|
|
2264
2639
|
}
|
|
2265
2640
|
)
|
|
2266
2641
|
] }),
|
|
2267
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2642
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2268
2643
|
"div",
|
|
2269
2644
|
{
|
|
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
|
-
|
|
2645
|
+
ref: gridRef,
|
|
2646
|
+
role: "grid",
|
|
2647
|
+
"aria-label": rangeLabel,
|
|
2648
|
+
className: classNames?.grid,
|
|
2649
|
+
onKeyDown: handleKeyDown,
|
|
2650
|
+
children: Array.from({ length: 4 }, (_, rowIndex) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2651
|
+
"div",
|
|
2652
|
+
{
|
|
2653
|
+
role: "row",
|
|
2654
|
+
className: classNames?.gridRow,
|
|
2655
|
+
style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)" },
|
|
2656
|
+
children: Array.from({ length: 3 }, (_2, col) => {
|
|
2657
|
+
const i = rowIndex * 3 + col;
|
|
2658
|
+
const year = decadeStart + i;
|
|
2659
|
+
const isSelected = year === valueYear;
|
|
2660
|
+
const isCurrent = year === todayYear;
|
|
2661
|
+
const isFocused = i === focusedIndex;
|
|
2662
|
+
const isDisabled = yearDisabledFlags[i] ?? false;
|
|
2663
|
+
const cls = [
|
|
2664
|
+
classNames?.year,
|
|
2665
|
+
isSelected && classNames?.yearSelected,
|
|
2666
|
+
isCurrent && classNames?.yearCurrent,
|
|
2667
|
+
isDisabled && classNames?.yearDisabled
|
|
2668
|
+
].filter(Boolean).join(" ") || void 0;
|
|
2669
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2670
|
+
"button",
|
|
2671
|
+
{
|
|
2672
|
+
type: "button",
|
|
2673
|
+
role: "gridcell",
|
|
2674
|
+
tabIndex: isFocused ? 0 : -1,
|
|
2675
|
+
disabled: isDisabled,
|
|
2676
|
+
"aria-selected": isSelected || void 0,
|
|
2677
|
+
"aria-disabled": isDisabled || void 0,
|
|
2678
|
+
"aria-current": isCurrent ? "date" : void 0,
|
|
2679
|
+
"data-selected": isSelected || void 0,
|
|
2680
|
+
"data-current": isCurrent || void 0,
|
|
2681
|
+
"data-focused": isFocused || void 0,
|
|
2682
|
+
className: cls,
|
|
2683
|
+
onClick: () => handleYearSelect(i),
|
|
2684
|
+
children: year
|
|
2685
|
+
},
|
|
2686
|
+
i
|
|
2687
|
+
);
|
|
2688
|
+
})
|
|
2689
|
+
},
|
|
2690
|
+
rowIndex
|
|
2691
|
+
))
|
|
2692
|
+
}
|
|
2693
|
+
)
|
|
2298
2694
|
] });
|
|
2299
2695
|
}
|
|
2300
2696
|
|
|
@@ -2515,7 +2911,7 @@ function useRangePicker(options = {}) {
|
|
|
2515
2911
|
adapter
|
|
2516
2912
|
};
|
|
2517
2913
|
}
|
|
2518
|
-
function
|
|
2914
|
+
function getDefaultIso() {
|
|
2519
2915
|
return core.DateFnsAdapter.today();
|
|
2520
2916
|
}
|
|
2521
2917
|
function useTimePicker(options = {}) {
|
|
@@ -2533,7 +2929,7 @@ function useTimePicker(options = {}) {
|
|
|
2533
2929
|
defaultValue ?? null
|
|
2534
2930
|
);
|
|
2535
2931
|
const currentValue = isControlled ? controlledValue ?? null : uncontrolledValue;
|
|
2536
|
-
const baseIso = currentValue ??
|
|
2932
|
+
const baseIso = currentValue ?? getDefaultIso();
|
|
2537
2933
|
const currentTime = react.useMemo(
|
|
2538
2934
|
() => displayTimezone ? core.getTimeInTimezone(baseIso, displayTimezone) : core.getTime(baseIso),
|
|
2539
2935
|
[baseIso, displayTimezone]
|
|
@@ -2584,6 +2980,22 @@ function useTimePicker(options = {}) {
|
|
|
2584
2980
|
};
|
|
2585
2981
|
}
|
|
2586
2982
|
|
|
2983
|
+
Object.defineProperty(exports, "DEFAULT_DATEPICKER_LABELS", {
|
|
2984
|
+
enumerable: true,
|
|
2985
|
+
get: function () { return core.DEFAULT_DATEPICKER_LABELS; }
|
|
2986
|
+
});
|
|
2987
|
+
Object.defineProperty(exports, "DEFAULT_DATETIMEPICKER_LABELS", {
|
|
2988
|
+
enumerable: true,
|
|
2989
|
+
get: function () { return core.DEFAULT_DATETIMEPICKER_LABELS; }
|
|
2990
|
+
});
|
|
2991
|
+
Object.defineProperty(exports, "DEFAULT_RANGEPICKER_LABELS", {
|
|
2992
|
+
enumerable: true,
|
|
2993
|
+
get: function () { return core.DEFAULT_RANGEPICKER_LABELS; }
|
|
2994
|
+
});
|
|
2995
|
+
Object.defineProperty(exports, "DEFAULT_TIMEPICKER_LABELS", {
|
|
2996
|
+
enumerable: true,
|
|
2997
|
+
get: function () { return core.DEFAULT_TIMEPICKER_LABELS; }
|
|
2998
|
+
});
|
|
2587
2999
|
Object.defineProperty(exports, "DateFnsAdapter", {
|
|
2588
3000
|
enumerable: true,
|
|
2589
3001
|
get: function () { return core.DateFnsAdapter; }
|