@kalyx/react 1.0.0-rc.1 → 1.0.0-rc.3
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 +62 -0
- package/dist/index.cjs +251 -152
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +254 -155
- package/dist/index.js.map +1 -1
- package/package.json +18 -3
package/dist/index.d.cts
CHANGED
|
@@ -198,6 +198,12 @@ declare function DatePickerPreset({ value: presetKey, date: directDate, children
|
|
|
198
198
|
interface DatePickerInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'type'> {
|
|
199
199
|
/** Date display format (defaults to parent's displayFormat) */
|
|
200
200
|
format?: string;
|
|
201
|
+
/**
|
|
202
|
+
* Form field name. When set, a hidden `<input type="hidden" name={name} value={ISO}>`
|
|
203
|
+
* is rendered alongside the visible input so the value participates in native form
|
|
204
|
+
* submission (and integrates with `react-hook-form` Controller-less flows).
|
|
205
|
+
*/
|
|
206
|
+
name?: string;
|
|
201
207
|
}
|
|
202
208
|
|
|
203
209
|
interface DatePickerTriggerProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'type'> {
|
package/dist/index.d.ts
CHANGED
|
@@ -198,6 +198,12 @@ declare function DatePickerPreset({ value: presetKey, date: directDate, children
|
|
|
198
198
|
interface DatePickerInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'type'> {
|
|
199
199
|
/** Date display format (defaults to parent's displayFormat) */
|
|
200
200
|
format?: string;
|
|
201
|
+
/**
|
|
202
|
+
* Form field name. When set, a hidden `<input type="hidden" name={name} value={ISO}>`
|
|
203
|
+
* is rendered alongside the visible input so the value participates in native form
|
|
204
|
+
* submission (and integrates with `react-hook-form` Controller-less flows).
|
|
205
|
+
*/
|
|
206
|
+
name?: string;
|
|
201
207
|
}
|
|
202
208
|
|
|
203
209
|
interface DatePickerTriggerProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'type'> {
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
|
+
import { createContext, forwardRef, useState, useRef, useCallback, useContext, useId, useMemo, useEffect } from 'react';
|
|
2
3
|
import { parseInputValue, formatTimeString, parseTimeString, getTimeInTimezone, getTime, DateFnsAdapter, DEFAULT_DATEPICKER_LABELS, civilMidnightFromUtcDay, getMonthName, getWeekdayNames, getCalendarDays, formatMonthYear, isDateDisabled, DEFAULT_RANGEPICKER_LABELS, DEFAULT_TIMEPICKER_LABELS, setTimeInTimezone, setTime, to12Hour, to24Hour, generateMinutes, generateHours, formatFullDate } from '@kalyx/core';
|
|
3
4
|
export { DateFnsAdapter } from '@kalyx/core';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
5
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
6
|
+
import { offset, flip, shift, useFloating, autoUpdate } from '@floating-ui/react';
|
|
6
7
|
|
|
7
8
|
// src/components/DatePicker/Root.tsx
|
|
8
9
|
var DatePickerContext = createContext(null);
|
|
@@ -56,10 +57,10 @@ function DatePickerRoot({
|
|
|
56
57
|
const currentValue = isControlled ? controlledValue ?? null : uncontrolledValue;
|
|
57
58
|
const [isOpen, setIsOpen] = useState(false);
|
|
58
59
|
const [viewMonth, setViewMonth] = useState(
|
|
59
|
-
currentValue ?? adapter.today(displayTimezone)
|
|
60
|
+
() => currentValue ?? adapter.today(displayTimezone)
|
|
60
61
|
);
|
|
61
62
|
const [focusedDate, setFocusedDate] = useState(
|
|
62
|
-
currentValue ?? adapter.today(displayTimezone)
|
|
63
|
+
() => currentValue ?? adapter.today(displayTimezone)
|
|
63
64
|
);
|
|
64
65
|
useChangeEffect(isOpen, onOpenChange);
|
|
65
66
|
const viewMonthStart = useMemo(() => adapter.startOfMonth(viewMonth), [viewMonth, adapter]);
|
|
@@ -150,10 +151,11 @@ function DatePickerRoot({
|
|
|
150
151
|
return /* @__PURE__ */ jsx(DatePickerContext.Provider, { value: contextValue, children });
|
|
151
152
|
}
|
|
152
153
|
var DatePickerInput = forwardRef(
|
|
153
|
-
function DatePickerInput2({ format: formatProp, onClick, onBlur, onKeyDown, ...props }, ref) {
|
|
154
|
+
function DatePickerInput2({ format: formatProp, name, onClick, onBlur, onKeyDown, ...props }, ref) {
|
|
154
155
|
const ctx = useDatePickerContext("DatePicker.Input");
|
|
155
156
|
const displayFormat = formatProp ?? ctx.displayFormat;
|
|
156
157
|
const [inputText, setInputText] = useState(null);
|
|
158
|
+
const isComposingRef = useRef(false);
|
|
157
159
|
let formattedValue = "";
|
|
158
160
|
if (ctx.value) {
|
|
159
161
|
try {
|
|
@@ -170,47 +172,62 @@ var DatePickerInput = forwardRef(
|
|
|
170
172
|
},
|
|
171
173
|
[ctx, onClick]
|
|
172
174
|
);
|
|
175
|
+
const commitText = useCallback(
|
|
176
|
+
(text) => {
|
|
177
|
+
if (!text) {
|
|
178
|
+
ctx.selectDate(null);
|
|
179
|
+
setInputText(null);
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
const parsed = parseInputValue(text, ctx.adapter);
|
|
183
|
+
if (parsed) {
|
|
184
|
+
ctx.selectDate(parsed);
|
|
185
|
+
setInputText(null);
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
return false;
|
|
189
|
+
},
|
|
190
|
+
[ctx]
|
|
191
|
+
);
|
|
173
192
|
const handleBlur = useCallback(
|
|
174
193
|
(e) => {
|
|
175
194
|
if (inputText !== null) {
|
|
176
|
-
|
|
177
|
-
if (parsed) {
|
|
178
|
-
ctx.selectDate(parsed);
|
|
179
|
-
}
|
|
195
|
+
commitText(inputText);
|
|
180
196
|
setInputText(null);
|
|
181
197
|
}
|
|
182
198
|
onBlur?.(e);
|
|
183
199
|
},
|
|
184
|
-
[inputText,
|
|
200
|
+
[inputText, commitText, onBlur]
|
|
185
201
|
);
|
|
186
202
|
const handleChange = useCallback(
|
|
187
203
|
(e) => {
|
|
188
204
|
const text = e.target.value;
|
|
189
205
|
setInputText(text);
|
|
190
|
-
if (
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
206
|
+
if (isComposingRef.current) return;
|
|
207
|
+
commitText(text);
|
|
208
|
+
},
|
|
209
|
+
[commitText]
|
|
210
|
+
);
|
|
211
|
+
const handleCompositionStart = useCallback(() => {
|
|
212
|
+
isComposingRef.current = true;
|
|
213
|
+
}, []);
|
|
214
|
+
const handleCompositionEnd = useCallback(
|
|
215
|
+
(e) => {
|
|
216
|
+
isComposingRef.current = false;
|
|
217
|
+
commitText(e.target.value);
|
|
200
218
|
},
|
|
201
|
-
[
|
|
219
|
+
[commitText]
|
|
202
220
|
);
|
|
203
221
|
const handleKeyDown = useCallback(
|
|
204
222
|
(e) => {
|
|
205
223
|
if (e.key === "Escape") {
|
|
206
224
|
ctx.close();
|
|
207
225
|
} else if (e.key === "Enter") {
|
|
226
|
+
if (ctx.isOpen) e.preventDefault();
|
|
208
227
|
if (inputText !== null) {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
setInputText(null);
|
|
213
|
-
}
|
|
228
|
+
commitText(inputText);
|
|
229
|
+
} else if (ctx.isOpen) {
|
|
230
|
+
ctx.selectDate(ctx.focusedDate);
|
|
214
231
|
}
|
|
215
232
|
} else if (e.key === "ArrowDown" && !ctx.isOpen) {
|
|
216
233
|
e.preventDefault();
|
|
@@ -218,36 +235,42 @@ var DatePickerInput = forwardRef(
|
|
|
218
235
|
}
|
|
219
236
|
onKeyDown?.(e);
|
|
220
237
|
},
|
|
221
|
-
[ctx, inputText,
|
|
238
|
+
[ctx, inputText, commitText, onKeyDown]
|
|
222
239
|
);
|
|
223
240
|
const calendarId = `${ctx.pickerId}-calendar`;
|
|
224
|
-
return /* @__PURE__ */
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
241
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
242
|
+
/* @__PURE__ */ jsx(
|
|
243
|
+
"input",
|
|
244
|
+
{
|
|
245
|
+
ref: (node) => {
|
|
246
|
+
ctx.referenceRef.current = node;
|
|
247
|
+
if (typeof ref === "function") ref(node);
|
|
248
|
+
else if (ref) ref.current = node;
|
|
249
|
+
},
|
|
250
|
+
type: "text",
|
|
251
|
+
role: "combobox",
|
|
252
|
+
"aria-expanded": ctx.isOpen,
|
|
253
|
+
"aria-haspopup": "dialog",
|
|
254
|
+
"aria-controls": ctx.isOpen ? calendarId : void 0,
|
|
255
|
+
"aria-autocomplete": "none",
|
|
256
|
+
autoComplete: "off",
|
|
257
|
+
value: displayValue,
|
|
258
|
+
disabled: ctx.isDisabled || props.disabled,
|
|
259
|
+
readOnly: ctx.isReadOnly,
|
|
260
|
+
onChange: handleChange,
|
|
261
|
+
onClick: handleClick,
|
|
262
|
+
onBlur: handleBlur,
|
|
263
|
+
onKeyDown: handleKeyDown,
|
|
264
|
+
onCompositionStart: handleCompositionStart,
|
|
265
|
+
onCompositionEnd: handleCompositionEnd,
|
|
266
|
+
...props
|
|
267
|
+
}
|
|
268
|
+
),
|
|
269
|
+
name ? /* @__PURE__ */ jsx("input", { type: "hidden", name, value: ctx.value ?? "" }) : null
|
|
270
|
+
] });
|
|
249
271
|
}
|
|
250
272
|
);
|
|
273
|
+
DatePickerInput.displayName = "DatePicker.Input";
|
|
251
274
|
var DatePickerTrigger = forwardRef(
|
|
252
275
|
function DatePickerTrigger2({ onClick, children, ...props }, ref) {
|
|
253
276
|
const ctx = useDatePickerContext("DatePicker.Trigger");
|
|
@@ -271,6 +294,7 @@ var DatePickerTrigger = forwardRef(
|
|
|
271
294
|
tabIndex: 0,
|
|
272
295
|
"aria-label": ctx.isOpen ? ctx.labels.triggerClose : ctx.labels.triggerOpen,
|
|
273
296
|
"aria-expanded": ctx.isOpen,
|
|
297
|
+
"aria-haspopup": "dialog",
|
|
274
298
|
"aria-controls": ctx.isOpen ? calendarId : void 0,
|
|
275
299
|
disabled: ctx.isDisabled || props.disabled,
|
|
276
300
|
onClick: handleClick,
|
|
@@ -301,6 +325,8 @@ var DatePickerTrigger = forwardRef(
|
|
|
301
325
|
);
|
|
302
326
|
}
|
|
303
327
|
);
|
|
328
|
+
DatePickerTrigger.displayName = "DatePicker.Trigger";
|
|
329
|
+
var POPOVER_MIDDLEWARE = [offset(4), flip(), shift({ padding: 8 })];
|
|
304
330
|
function usePopover({
|
|
305
331
|
isOpen,
|
|
306
332
|
close,
|
|
@@ -312,7 +338,7 @@ function usePopover({
|
|
|
312
338
|
const { refs, floatingStyles, isPositioned } = useFloating({
|
|
313
339
|
open: isOpen,
|
|
314
340
|
placement,
|
|
315
|
-
middleware:
|
|
341
|
+
middleware: POPOVER_MIDDLEWARE,
|
|
316
342
|
whileElementsMounted: autoUpdate
|
|
317
343
|
});
|
|
318
344
|
useEffect(() => {
|
|
@@ -359,6 +385,24 @@ function usePopover({
|
|
|
359
385
|
document.addEventListener("keydown", handleKeyDown);
|
|
360
386
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
361
387
|
}, [isOpen, close]);
|
|
388
|
+
useEffect(() => {
|
|
389
|
+
if (!isOpen) return;
|
|
390
|
+
function handleFocusOut(e) {
|
|
391
|
+
const next = e.relatedTarget;
|
|
392
|
+
const floating = floatingRef.current;
|
|
393
|
+
const reference = referenceRef.current;
|
|
394
|
+
if (!next) return;
|
|
395
|
+
const insideFloating = floating?.contains(next) ?? false;
|
|
396
|
+
const insideReference = reference?.contains(next) ?? false;
|
|
397
|
+
if (!insideFloating && !insideReference) {
|
|
398
|
+
close();
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
const node = floatingRef.current;
|
|
402
|
+
if (!node) return;
|
|
403
|
+
node.addEventListener("focusout", handleFocusOut);
|
|
404
|
+
return () => node.removeEventListener("focusout", handleFocusOut);
|
|
405
|
+
}, [isOpen, close, referenceRef]);
|
|
362
406
|
const setFloatingRef = useCallback(
|
|
363
407
|
(node) => {
|
|
364
408
|
floatingRef.current = node;
|
|
@@ -426,14 +470,17 @@ function DatePickerCalendar({
|
|
|
426
470
|
const gridRef = useRef(null);
|
|
427
471
|
const [announcement, setAnnouncement] = useState("");
|
|
428
472
|
const { adapter, viewMonth, focusedDate, weekStartsOn, disabled, locale, displayTimezone } = ctx;
|
|
429
|
-
const weekdays = getWeekdayNames(locale, weekStartsOn);
|
|
430
|
-
const weeks =
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
473
|
+
const weekdays = useMemo(() => getWeekdayNames(locale, weekStartsOn), [locale, weekStartsOn]);
|
|
474
|
+
const weeks = useMemo(
|
|
475
|
+
() => getCalendarDays(viewMonth, adapter, {
|
|
476
|
+
weekStartsOn,
|
|
477
|
+
selected: ctx.value,
|
|
478
|
+
focusedDate,
|
|
479
|
+
disabled,
|
|
480
|
+
timezone: displayTimezone
|
|
481
|
+
}),
|
|
482
|
+
[viewMonth, adapter, weekStartsOn, ctx.value, focusedDate, disabled, displayTimezone]
|
|
483
|
+
);
|
|
437
484
|
const year = adapter.getYear(viewMonth);
|
|
438
485
|
const month = adapter.getMonth(viewMonth);
|
|
439
486
|
const title = formatMonthYear(year, month, locale);
|
|
@@ -513,6 +560,15 @@ function DatePickerCalendar({
|
|
|
513
560
|
}
|
|
514
561
|
if (newFocused) {
|
|
515
562
|
e.preventDefault();
|
|
563
|
+
const skipStep = e.key === "ArrowLeft" || e.key === "ArrowUp" || e.key === "PageUp" || e.key === "Home" ? -1 : 1;
|
|
564
|
+
let attempts = 0;
|
|
565
|
+
while (isDateDisabled(newFocused, disabled, adapter) && attempts < 42) {
|
|
566
|
+
newFocused = adapter.addDays(newFocused, skipStep);
|
|
567
|
+
attempts++;
|
|
568
|
+
}
|
|
569
|
+
if (attempts >= 42) {
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
516
572
|
ctx.setFocusedDate(newFocused);
|
|
517
573
|
if (!adapter.isSameMonth(newFocused, viewMonth)) {
|
|
518
574
|
ctx.setViewMonth(newFocused);
|
|
@@ -560,56 +616,69 @@ function DatePickerCalendar({
|
|
|
560
616
|
ref: gridRef,
|
|
561
617
|
role: "grid",
|
|
562
618
|
"aria-label": title,
|
|
619
|
+
"aria-rowcount": weeks.length + 1,
|
|
620
|
+
"aria-colcount": 7,
|
|
563
621
|
className: classNames?.grid,
|
|
564
622
|
onKeyDown: handleKeyDown,
|
|
565
623
|
children: [
|
|
566
|
-
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { role: "row", children: weekdays.map((day) => /* @__PURE__ */ jsx(
|
|
624
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { role: "row", "aria-rowindex": 1, children: weekdays.map((day, colIndex) => /* @__PURE__ */ jsx(
|
|
567
625
|
"th",
|
|
568
626
|
{
|
|
569
627
|
role: "columnheader",
|
|
570
628
|
abbr: day.full,
|
|
571
629
|
scope: "col",
|
|
630
|
+
"aria-colindex": colIndex + 1,
|
|
572
631
|
className: classNames?.weekdayHeader,
|
|
573
632
|
children: day.short
|
|
574
633
|
},
|
|
575
634
|
day.short
|
|
576
635
|
)) }) }),
|
|
577
|
-
/* @__PURE__ */ jsx("tbody", { children: weeks.map((week, weekIndex) => /* @__PURE__ */ jsx(
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
"
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
children: /* @__PURE__ */ jsx(
|
|
594
|
-
"button",
|
|
636
|
+
/* @__PURE__ */ jsx("tbody", { children: weeks.map((week, weekIndex) => /* @__PURE__ */ jsx(
|
|
637
|
+
"tr",
|
|
638
|
+
{
|
|
639
|
+
role: "row",
|
|
640
|
+
"aria-rowindex": weekIndex + 2,
|
|
641
|
+
className: classNames?.gridRow,
|
|
642
|
+
children: week.map((day, colIndex) => {
|
|
643
|
+
const dayClasses = [
|
|
644
|
+
classNames?.day,
|
|
645
|
+
day.isSelected && classNames?.daySelected,
|
|
646
|
+
day.isToday && classNames?.dayToday,
|
|
647
|
+
day.isDisabled && classNames?.dayDisabled,
|
|
648
|
+
!day.isCurrentMonth && classNames?.dayOutsideMonth
|
|
649
|
+
].filter(Boolean).join(" ") || void 0;
|
|
650
|
+
return /* @__PURE__ */ jsx(
|
|
651
|
+
"td",
|
|
595
652
|
{
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
"
|
|
600
|
-
"
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
653
|
+
role: "gridcell",
|
|
654
|
+
"aria-colindex": colIndex + 1,
|
|
655
|
+
"aria-selected": day.isSelected || void 0,
|
|
656
|
+
"aria-disabled": day.isDisabled || void 0,
|
|
657
|
+
"aria-current": day.isToday ? "date" : void 0,
|
|
658
|
+
className: classNames?.gridCell,
|
|
659
|
+
children: /* @__PURE__ */ jsx(
|
|
660
|
+
"button",
|
|
661
|
+
{
|
|
662
|
+
type: "button",
|
|
663
|
+
tabIndex: day.isFocused ? 0 : -1,
|
|
664
|
+
disabled: day.isDisabled,
|
|
665
|
+
"data-focused": day.isFocused || void 0,
|
|
666
|
+
"data-selected": day.isSelected || void 0,
|
|
667
|
+
"data-today": day.isToday || void 0,
|
|
668
|
+
"data-outside-month": !day.isCurrentMonth || void 0,
|
|
669
|
+
className: dayClasses,
|
|
670
|
+
onClick: () => handleDayClick(day),
|
|
671
|
+
"aria-label": safeFormatFullDate(day.isoString, locale),
|
|
672
|
+
children: day.dayNumber
|
|
673
|
+
}
|
|
674
|
+
)
|
|
675
|
+
},
|
|
676
|
+
day.isoString
|
|
677
|
+
);
|
|
678
|
+
})
|
|
679
|
+
},
|
|
680
|
+
weekIndex
|
|
681
|
+
)) })
|
|
613
682
|
]
|
|
614
683
|
}
|
|
615
684
|
),
|
|
@@ -930,10 +999,10 @@ function RangePickerRoot({
|
|
|
930
999
|
const [selectingTarget, setSelectingTarget] = useState("start");
|
|
931
1000
|
const [hoverDate, setHoverDate] = useState(null);
|
|
932
1001
|
const [viewMonth, setViewMonth] = useState(
|
|
933
|
-
currentValue.start ?? adapter.today(displayTimezone)
|
|
1002
|
+
() => currentValue.start ?? adapter.today(displayTimezone)
|
|
934
1003
|
);
|
|
935
1004
|
const [focusedDate, setFocusedDate] = useState(
|
|
936
|
-
currentValue.start ?? adapter.today(displayTimezone)
|
|
1005
|
+
() => currentValue.start ?? adapter.today(displayTimezone)
|
|
937
1006
|
);
|
|
938
1007
|
useChangeEffect(isOpen, onOpenChange);
|
|
939
1008
|
const viewMonthStart = useMemo(() => adapter.startOfMonth(viewMonth), [viewMonth, adapter]);
|
|
@@ -1083,6 +1152,8 @@ var RangePickerInput = forwardRef(
|
|
|
1083
1152
|
(e) => {
|
|
1084
1153
|
if (e.key === "Escape") {
|
|
1085
1154
|
ctx.close();
|
|
1155
|
+
} else if (e.key === "Enter" && ctx.isOpen) {
|
|
1156
|
+
e.preventDefault();
|
|
1086
1157
|
} else if (e.key === "ArrowDown" && !ctx.isOpen) {
|
|
1087
1158
|
e.preventDefault();
|
|
1088
1159
|
ctx.open();
|
|
@@ -1119,6 +1190,7 @@ var RangePickerInput = forwardRef(
|
|
|
1119
1190
|
);
|
|
1120
1191
|
}
|
|
1121
1192
|
);
|
|
1193
|
+
RangePickerInput.displayName = "RangePicker.Input";
|
|
1122
1194
|
function RangePickerPopover({ children, ...props }) {
|
|
1123
1195
|
const ctx = useRangePickerContext("RangePicker.Popover");
|
|
1124
1196
|
const calendarId = `${ctx.pickerId}-calendar`;
|
|
@@ -1185,15 +1257,18 @@ function RangePickerCalendar({
|
|
|
1185
1257
|
displayTimezone
|
|
1186
1258
|
} = ctx;
|
|
1187
1259
|
const { locale } = ctx;
|
|
1188
|
-
const weekdays = getWeekdayNames(locale, weekStartsOn);
|
|
1189
|
-
const weeks =
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1260
|
+
const weekdays = useMemo(() => getWeekdayNames(locale, weekStartsOn), [locale, weekStartsOn]);
|
|
1261
|
+
const weeks = useMemo(
|
|
1262
|
+
() => getCalendarDays(viewMonth, adapter, {
|
|
1263
|
+
weekStartsOn,
|
|
1264
|
+
focusedDate,
|
|
1265
|
+
disabled,
|
|
1266
|
+
range: value,
|
|
1267
|
+
rangeHover: hoverDate,
|
|
1268
|
+
timezone: displayTimezone
|
|
1269
|
+
}),
|
|
1270
|
+
[viewMonth, adapter, weekStartsOn, focusedDate, disabled, value, hoverDate, displayTimezone]
|
|
1271
|
+
);
|
|
1197
1272
|
const year = adapter.getYear(viewMonth);
|
|
1198
1273
|
const month = adapter.getMonth(viewMonth);
|
|
1199
1274
|
const title = formatMonthYear(year, month, locale);
|
|
@@ -1293,6 +1368,13 @@ function RangePickerCalendar({
|
|
|
1293
1368
|
}
|
|
1294
1369
|
if (newFocused) {
|
|
1295
1370
|
e.preventDefault();
|
|
1371
|
+
const skipStep = e.key === "ArrowLeft" || e.key === "ArrowUp" || e.key === "PageUp" || e.key === "Home" ? -1 : 1;
|
|
1372
|
+
let attempts = 0;
|
|
1373
|
+
while (isDateDisabled(newFocused, disabled, adapter) && attempts < 42) {
|
|
1374
|
+
newFocused = adapter.addDays(newFocused, skipStep);
|
|
1375
|
+
attempts++;
|
|
1376
|
+
}
|
|
1377
|
+
if (attempts >= 42) return;
|
|
1296
1378
|
ctx.setFocusedDate(newFocused);
|
|
1297
1379
|
if (!adapter.isSameMonth(newFocused, viewMonth)) {
|
|
1298
1380
|
ctx.setViewMonth(newFocused);
|
|
@@ -1346,62 +1428,75 @@ function RangePickerCalendar({
|
|
|
1346
1428
|
role: "grid",
|
|
1347
1429
|
"aria-label": title,
|
|
1348
1430
|
"aria-multiselectable": "true",
|
|
1431
|
+
"aria-rowcount": weeks.length + 1,
|
|
1432
|
+
"aria-colcount": 7,
|
|
1349
1433
|
className: classNames?.grid,
|
|
1350
1434
|
onKeyDown: handleKeyDown,
|
|
1351
1435
|
children: [
|
|
1352
|
-
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { role: "row", children: weekdays.map((day) => /* @__PURE__ */ jsx(
|
|
1436
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { role: "row", "aria-rowindex": 1, children: weekdays.map((day, colIndex) => /* @__PURE__ */ jsx(
|
|
1353
1437
|
"th",
|
|
1354
1438
|
{
|
|
1355
1439
|
role: "columnheader",
|
|
1356
1440
|
abbr: day.full,
|
|
1357
1441
|
scope: "col",
|
|
1442
|
+
"aria-colindex": colIndex + 1,
|
|
1358
1443
|
className: classNames?.weekdayHeader,
|
|
1359
1444
|
children: day.short
|
|
1360
1445
|
},
|
|
1361
1446
|
day.short
|
|
1362
1447
|
)) }) }),
|
|
1363
|
-
/* @__PURE__ */ jsx("tbody", { children: weeks.map((week, weekIndex) => /* @__PURE__ */ jsx(
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
day
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
"
|
|
1379
|
-
"
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
children: /* @__PURE__ */ jsx(
|
|
1383
|
-
"button",
|
|
1448
|
+
/* @__PURE__ */ jsx("tbody", { children: weeks.map((week, weekIndex) => /* @__PURE__ */ jsx(
|
|
1449
|
+
"tr",
|
|
1450
|
+
{
|
|
1451
|
+
role: "row",
|
|
1452
|
+
"aria-rowindex": weekIndex + 2,
|
|
1453
|
+
className: classNames?.gridRow,
|
|
1454
|
+
children: week.map((day, colIndex) => {
|
|
1455
|
+
const dayClasses = [
|
|
1456
|
+
classNames?.day,
|
|
1457
|
+
day.isRangeStart && classNames?.dayRangeStart,
|
|
1458
|
+
day.isRangeEnd && classNames?.dayRangeEnd,
|
|
1459
|
+
day.isInRange && classNames?.dayInRange,
|
|
1460
|
+
day.isToday && classNames?.dayToday,
|
|
1461
|
+
day.isDisabled && classNames?.dayDisabled,
|
|
1462
|
+
!day.isCurrentMonth && classNames?.dayOutsideMonth
|
|
1463
|
+
].filter(Boolean).join(" ") || void 0;
|
|
1464
|
+
const isSelected = selectionMode === "week" ? day.isRangeStart || day.isRangeEnd || day.isInRange : day.isRangeStart || day.isRangeEnd;
|
|
1465
|
+
return /* @__PURE__ */ jsx(
|
|
1466
|
+
"td",
|
|
1384
1467
|
{
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
"
|
|
1389
|
-
"
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1468
|
+
role: "gridcell",
|
|
1469
|
+
"aria-colindex": colIndex + 1,
|
|
1470
|
+
"aria-selected": isSelected || void 0,
|
|
1471
|
+
"aria-disabled": day.isDisabled || void 0,
|
|
1472
|
+
"aria-current": day.isToday ? "date" : void 0,
|
|
1473
|
+
className: classNames?.gridCell,
|
|
1474
|
+
children: /* @__PURE__ */ jsx(
|
|
1475
|
+
"button",
|
|
1476
|
+
{
|
|
1477
|
+
type: "button",
|
|
1478
|
+
tabIndex: day.isFocused ? 0 : -1,
|
|
1479
|
+
disabled: day.isDisabled,
|
|
1480
|
+
"data-focused": day.isFocused || void 0,
|
|
1481
|
+
"data-range-start": day.isRangeStart || void 0,
|
|
1482
|
+
"data-range-end": day.isRangeEnd || void 0,
|
|
1483
|
+
"data-in-range": day.isInRange || void 0,
|
|
1484
|
+
"data-today": day.isToday || void 0,
|
|
1485
|
+
"data-outside-month": !day.isCurrentMonth || void 0,
|
|
1486
|
+
className: dayClasses,
|
|
1487
|
+
onClick: () => handleDayClick(day),
|
|
1488
|
+
onMouseEnter: () => handleDayMouseEnter(day),
|
|
1489
|
+
"aria-label": safeFormatFullDate2(day.isoString, locale),
|
|
1490
|
+
children: day.dayNumber
|
|
1491
|
+
}
|
|
1492
|
+
)
|
|
1493
|
+
},
|
|
1494
|
+
day.isoString
|
|
1495
|
+
);
|
|
1496
|
+
})
|
|
1497
|
+
},
|
|
1498
|
+
weekIndex
|
|
1499
|
+
)) })
|
|
1405
1500
|
]
|
|
1406
1501
|
}
|
|
1407
1502
|
),
|
|
@@ -1654,6 +1749,7 @@ var TimePickerInput = forwardRef(
|
|
|
1654
1749
|
);
|
|
1655
1750
|
}
|
|
1656
1751
|
);
|
|
1752
|
+
TimePickerInput.displayName = "TimePicker.Input";
|
|
1657
1753
|
function useListboxNavigation({
|
|
1658
1754
|
items,
|
|
1659
1755
|
onSelect,
|
|
@@ -1702,7 +1798,7 @@ function useListboxNavigation({
|
|
|
1702
1798
|
function TimePickerHourList({ classNames, ...props }) {
|
|
1703
1799
|
const ctx = useTimePickerContext("TimePicker.HourList");
|
|
1704
1800
|
const { format, currentTime, isDisabled, isReadOnly } = ctx;
|
|
1705
|
-
const hours = generateHours(format);
|
|
1801
|
+
const hours = useMemo(() => generateHours(format), [format]);
|
|
1706
1802
|
const selectedHourDisplay = format === "12h" ? to12Hour(currentTime.hours).hours12 : currentTime.hours;
|
|
1707
1803
|
const currentPeriod = format === "12h" ? to12Hour(currentTime.hours).period : null;
|
|
1708
1804
|
const handleSelect = useCallback(
|
|
@@ -1753,7 +1849,7 @@ function TimePickerHourList({ classNames, ...props }) {
|
|
|
1753
1849
|
function TimePickerMinuteList({ classNames, ...props }) {
|
|
1754
1850
|
const ctx = useTimePickerContext("TimePicker.MinuteList");
|
|
1755
1851
|
const { step, currentTime, isDisabled, isReadOnly } = ctx;
|
|
1756
|
-
const minutes = generateMinutes(step);
|
|
1852
|
+
const minutes = useMemo(() => generateMinutes(step), [step]);
|
|
1757
1853
|
const handleSelect = useCallback(
|
|
1758
1854
|
(minute) => {
|
|
1759
1855
|
if (isDisabled || isReadOnly) return;
|
|
@@ -1887,10 +1983,10 @@ function DateTimePickerRoot({
|
|
|
1887
1983
|
const currentValue = isControlled ? controlledValue ?? null : uncontrolledValue;
|
|
1888
1984
|
const [isOpen, setIsOpen] = useState(false);
|
|
1889
1985
|
const [viewMonth, setViewMonth] = useState(
|
|
1890
|
-
currentValue ?? adapter.today(displayTimezone)
|
|
1986
|
+
() => currentValue ?? adapter.today(displayTimezone)
|
|
1891
1987
|
);
|
|
1892
1988
|
const [focusedDate, setFocusedDate] = useState(
|
|
1893
|
-
currentValue ?? adapter.today(displayTimezone)
|
|
1989
|
+
() => currentValue ?? adapter.today(displayTimezone)
|
|
1894
1990
|
);
|
|
1895
1991
|
useChangeEffect(isOpen, onOpenChange);
|
|
1896
1992
|
const viewMonthStart = useMemo(() => adapter.startOfMonth(viewMonth), [viewMonth, adapter]);
|
|
@@ -2048,6 +2144,8 @@ var DateTimePickerInput = forwardRef(
|
|
|
2048
2144
|
(e) => {
|
|
2049
2145
|
if (e.key === "Escape") {
|
|
2050
2146
|
ctx.close();
|
|
2147
|
+
} else if (e.key === "Enter" && ctx.isOpen) {
|
|
2148
|
+
e.preventDefault();
|
|
2051
2149
|
} else if (e.key === "ArrowDown" && !ctx.isOpen) {
|
|
2052
2150
|
e.preventDefault();
|
|
2053
2151
|
ctx.open();
|
|
@@ -2083,6 +2181,7 @@ var DateTimePickerInput = forwardRef(
|
|
|
2083
2181
|
);
|
|
2084
2182
|
}
|
|
2085
2183
|
);
|
|
2184
|
+
DateTimePickerInput.displayName = "DateTimePicker.Input";
|
|
2086
2185
|
|
|
2087
2186
|
// src/components/DateTimePicker/index.ts
|
|
2088
2187
|
var DateTimePicker = Object.assign(DateTimePickerRoot, {
|