@react-aria/datepicker 3.0.0-rc.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.js +84 -35
- package/dist/main.js.map +1 -1
- package/dist/module.js +85 -36
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +16 -15
- package/src/useDatePickerGroup.ts +2 -2
- package/src/useDateRangePicker.ts +1 -7
- package/src/useDateSegment.ts +73 -29
package/dist/module.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {createFocusManager as $cIPI0$createFocusManager, getFocusableTreeWalker as $cIPI0$getFocusableTreeWalker} from "@react-aria/focus";
|
|
2
|
-
import {useId as $cIPI0$useId, useDescription as $cIPI0$useDescription, filterDOMProps as $cIPI0$filterDOMProps, mergeProps as $cIPI0$mergeProps, isMac as $cIPI0$isMac, scrollIntoView as $cIPI0$scrollIntoView, getScrollParent as $cIPI0$getScrollParent, useEvent as $cIPI0$useEvent, isIOS as $cIPI0$isIOS, useLabels as $cIPI0$useLabels} from "@react-aria/utils";
|
|
2
|
+
import {useId as $cIPI0$useId, useDescription as $cIPI0$useDescription, filterDOMProps as $cIPI0$filterDOMProps, mergeProps as $cIPI0$mergeProps, isMac as $cIPI0$isMac, scrollIntoView as $cIPI0$scrollIntoView, getScrollParent as $cIPI0$getScrollParent, useEvent as $cIPI0$useEvent, useLayoutEffect as $cIPI0$useLayoutEffect, isIOS as $cIPI0$isIOS, useLabels as $cIPI0$useLabels} from "@react-aria/utils";
|
|
3
3
|
import $cIPI0$react, {useMemo as $cIPI0$useMemo, useRef as $cIPI0$useRef, useEffect as $cIPI0$useEffect} from "react";
|
|
4
4
|
import {useField as $cIPI0$useField} from "@react-aria/label";
|
|
5
5
|
import {useMessageFormatter as $cIPI0$useMessageFormatter, useLocale as $cIPI0$useLocale, useDateFormatter as $cIPI0$useDateFormatter, useFilter as $cIPI0$useFilter} from "@react-aria/i18n";
|
|
6
6
|
import {useFocusWithin as $cIPI0$useFocusWithin, usePress as $cIPI0$usePress} from "@react-aria/interactions";
|
|
7
|
+
import {toCalendar as $cIPI0$toCalendar, CalendarDate as $cIPI0$CalendarDate} from "@internationalized/date";
|
|
7
8
|
import {NumberParser as $cIPI0$NumberParser} from "@internationalized/number";
|
|
8
9
|
import {useSpinButton as $cIPI0$useSpinButton} from "@react-aria/spinbutton";
|
|
9
10
|
import {MessageDictionary as $cIPI0$MessageDictionary} from "@internationalized/message";
|
|
@@ -248,9 +249,9 @@ function $3dfb0f96be0d6a08$export$4a931266a3838b86(state, ref1, disableArrowNavi
|
|
|
248
249
|
}while (last)
|
|
249
250
|
}
|
|
250
251
|
// Now go backwards until we find an element that is not a placeholder.
|
|
251
|
-
while(target === null || target === void 0 ? void 0 : target.
|
|
252
|
+
while(target === null || target === void 0 ? void 0 : target.hasAttribute('data-placeholder')){
|
|
252
253
|
let prev = walker.previousNode();
|
|
253
|
-
if (prev && prev.
|
|
254
|
+
if (prev && prev.hasAttribute('data-placeholder')) target = prev;
|
|
254
255
|
else break;
|
|
255
256
|
}
|
|
256
257
|
if (target) target.focus();
|
|
@@ -457,6 +458,7 @@ function $6057a3d2a53a12fd$export$42df105a73306d51(props, state, ref) {
|
|
|
457
458
|
|
|
458
459
|
|
|
459
460
|
|
|
461
|
+
|
|
460
462
|
function $3aeceb3a64eb8358$export$d42c60378c8168f8() {
|
|
461
463
|
let { locale: locale } = $cIPI0$useLocale();
|
|
462
464
|
return $cIPI0$useMemo(()=>{
|
|
@@ -491,7 +493,7 @@ function $32489daedd52963e$export$1315d136e6f7581(segment, state, ref) {
|
|
|
491
493
|
let { locale: locale } = $cIPI0$useLocale();
|
|
492
494
|
let displayNames = $3aeceb3a64eb8358$export$d42c60378c8168f8();
|
|
493
495
|
let { ariaLabel: ariaLabel , ariaLabelledBy: ariaLabelledBy , ariaDescribedBy: ariaDescribedBy , focusManager: focusManager } = $16f0b7bb276bc17e$export$653eddfc964b0f8a.get(state);
|
|
494
|
-
let textValue = segment.text;
|
|
496
|
+
let textValue = segment.isPlaceholder ? '' : segment.text;
|
|
495
497
|
let options = $cIPI0$useMemo(()=>state.dateFormatter.resolvedOptions()
|
|
496
498
|
, [
|
|
497
499
|
state.dateFormatter
|
|
@@ -505,11 +507,14 @@ function $32489daedd52963e$export$1315d136e6f7581(segment, state, ref) {
|
|
|
505
507
|
hour12: options.hour12,
|
|
506
508
|
timeZone: options.timeZone
|
|
507
509
|
});
|
|
508
|
-
if (segment.type === 'month') {
|
|
510
|
+
if (segment.type === 'month' && !segment.isPlaceholder) {
|
|
509
511
|
let monthTextValue = monthDateFormatter.format(state.dateValue);
|
|
510
512
|
textValue = monthTextValue !== textValue ? `${textValue} – ${monthTextValue}` : monthTextValue;
|
|
511
|
-
} else if (segment.type === 'hour') textValue = hourDateFormatter.format(state.dateValue);
|
|
513
|
+
} else if (segment.type === 'hour' && !segment.isPlaceholder) textValue = hourDateFormatter.format(state.dateValue);
|
|
512
514
|
let { spinButtonProps: spinButtonProps } = $cIPI0$useSpinButton({
|
|
515
|
+
// The ARIA spec says aria-valuenow is optional if there's no value, but aXe seems to require it.
|
|
516
|
+
// This doesn't seem to have any negative effects with real AT since we also use aria-valuetext.
|
|
517
|
+
// https://github.com/dequelabs/axe-core/issues/3505
|
|
513
518
|
value: segment.value,
|
|
514
519
|
textValue: textValue,
|
|
515
520
|
minValue: segment.minValue,
|
|
@@ -563,14 +568,6 @@ function $32489daedd52963e$export$1315d136e6f7581(segment, state, ref) {
|
|
|
563
568
|
if (e.key === 'a' && ($cIPI0$isMac() ? e.metaKey : e.ctrlKey)) e.preventDefault();
|
|
564
569
|
if (e.ctrlKey || e.metaKey || e.shiftKey || e.altKey) return;
|
|
565
570
|
switch(e.key){
|
|
566
|
-
case 'Enter':
|
|
567
|
-
e.preventDefault();
|
|
568
|
-
e.stopPropagation();
|
|
569
|
-
if (segment.isPlaceholder && !state.isReadOnly) state.confirmPlaceholder(segment.type);
|
|
570
|
-
focusManager.focusNext();
|
|
571
|
-
break;
|
|
572
|
-
case 'Tab':
|
|
573
|
-
break;
|
|
574
571
|
case 'Backspace':
|
|
575
572
|
case 'Delete':
|
|
576
573
|
// Safari on iOS does not fire beforeinput for the backspace key because the cursor is at the start.
|
|
@@ -604,6 +601,42 @@ function $32489daedd52963e$export$1315d136e6f7581(segment, state, ref) {
|
|
|
604
601
|
}, [
|
|
605
602
|
amPmFormatter
|
|
606
603
|
]);
|
|
604
|
+
// Get a list of formatted era names so users can type the first character to choose one.
|
|
605
|
+
let eraFormatter = $cIPI0$useDateFormatter({
|
|
606
|
+
year: 'numeric',
|
|
607
|
+
era: 'narrow',
|
|
608
|
+
timeZone: 'UTC'
|
|
609
|
+
});
|
|
610
|
+
let eras1 = $cIPI0$useMemo(()=>{
|
|
611
|
+
if (segment.type !== 'era') return [];
|
|
612
|
+
let date = $cIPI0$toCalendar(new $cIPI0$CalendarDate(1, 1, 1), state.calendar);
|
|
613
|
+
let eras = state.calendar.getEras().map((era)=>{
|
|
614
|
+
let eraDate = date.set({
|
|
615
|
+
year: 1,
|
|
616
|
+
month: 1,
|
|
617
|
+
day: 1,
|
|
618
|
+
era: era
|
|
619
|
+
}).toDate('UTC');
|
|
620
|
+
let parts = eraFormatter.formatToParts(eraDate);
|
|
621
|
+
let formatted = parts.find((p)=>p.type === 'era'
|
|
622
|
+
).value;
|
|
623
|
+
return {
|
|
624
|
+
era: era,
|
|
625
|
+
formatted: formatted
|
|
626
|
+
};
|
|
627
|
+
});
|
|
628
|
+
// Remove the common prefix from formatted values. This is so that in calendars with eras like
|
|
629
|
+
// ERA0 and ERA1 (e.g. Ethiopic), users can press "0" and "1" to select an era. In other cases,
|
|
630
|
+
// the first letter is used.
|
|
631
|
+
let prefixLength = $32489daedd52963e$var$commonPrefixLength(eras.map((era)=>era.formatted
|
|
632
|
+
));
|
|
633
|
+
if (prefixLength) for (let era1 of eras)era1.formatted = era1.formatted.slice(prefixLength);
|
|
634
|
+
return eras;
|
|
635
|
+
}, [
|
|
636
|
+
eraFormatter,
|
|
637
|
+
state.calendar,
|
|
638
|
+
segment.type
|
|
639
|
+
]);
|
|
607
640
|
let onInput = (key)=>{
|
|
608
641
|
if (state.isDisabled || state.isReadOnly) return;
|
|
609
642
|
let newValue = enteredKeys.current + key;
|
|
@@ -614,6 +647,16 @@ function $32489daedd52963e$export$1315d136e6f7581(segment, state, ref) {
|
|
|
614
647
|
else break;
|
|
615
648
|
focusManager.focusNext();
|
|
616
649
|
break;
|
|
650
|
+
case 'era':
|
|
651
|
+
{
|
|
652
|
+
let matched = eras1.find((e)=>startsWith(e.formatted, key)
|
|
653
|
+
);
|
|
654
|
+
if (matched) {
|
|
655
|
+
state.setSegment('era', matched.era);
|
|
656
|
+
focusManager.focusNext();
|
|
657
|
+
}
|
|
658
|
+
break;
|
|
659
|
+
}
|
|
617
660
|
case 'day':
|
|
618
661
|
case 'hour':
|
|
619
662
|
case 'minute':
|
|
@@ -651,14 +694,9 @@ function $32489daedd52963e$export$1315d136e6f7581(segment, state, ref) {
|
|
|
651
694
|
let onFocus = ()=>{
|
|
652
695
|
enteredKeys.current = '';
|
|
653
696
|
$cIPI0$scrollIntoView($cIPI0$getScrollParent(ref.current), ref.current);
|
|
654
|
-
//
|
|
655
|
-
// Since usePress disables text selection, this won't happen by default.
|
|
656
|
-
ref.current.style.webkitUserSelect = 'text';
|
|
657
|
-
ref.current.style.userSelect = 'text';
|
|
697
|
+
// Collapse selection to start or Chrome won't fire input events.
|
|
658
698
|
let selection = window.getSelection();
|
|
659
699
|
selection.collapse(ref.current);
|
|
660
|
-
ref.current.style.webkitUserSelect = 'none';
|
|
661
|
-
ref.current.style.userSelect = 'none';
|
|
662
700
|
};
|
|
663
701
|
let compositionRef = $cIPI0$useRef('');
|
|
664
702
|
// @ts-ignore - TODO: possibly old TS version? doesn't fail in my editor...
|
|
@@ -694,10 +732,19 @@ function $32489daedd52963e$export$1315d136e6f7581(segment, state, ref) {
|
|
|
694
732
|
break;
|
|
695
733
|
}
|
|
696
734
|
});
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
735
|
+
$cIPI0$useLayoutEffect(()=>{
|
|
736
|
+
let element = ref.current;
|
|
737
|
+
return ()=>{
|
|
738
|
+
// If the focused segment is removed, focus the previous one, or the next one if there was no previous one.
|
|
739
|
+
if (document.activeElement === element) {
|
|
740
|
+
let prev = focusManager.focusPrevious();
|
|
741
|
+
if (!prev) focusManager.focusNext();
|
|
742
|
+
}
|
|
743
|
+
};
|
|
744
|
+
}, [
|
|
745
|
+
ref,
|
|
746
|
+
focusManager
|
|
747
|
+
]);
|
|
701
748
|
// spinbuttons cannot be focused with VoiceOver on iOS.
|
|
702
749
|
let touchPropOverrides = $cIPI0$isIOS() || segment.type === 'timeZoneName' ? {
|
|
703
750
|
role: 'textbox',
|
|
@@ -737,8 +784,8 @@ function $32489daedd52963e$export$1315d136e6f7581(segment, state, ref) {
|
|
|
737
784
|
...touchPropOverrides,
|
|
738
785
|
'aria-invalid': state.validationState === 'invalid' ? 'true' : undefined,
|
|
739
786
|
'aria-describedby': ariaDescribedBy,
|
|
740
|
-
'aria-placeholder': segment.isPlaceholder ? segment.text : undefined,
|
|
741
787
|
'aria-readonly': state.isReadOnly || !segment.isEditable ? 'true' : undefined,
|
|
788
|
+
'data-placeholder': segment.isPlaceholder || undefined,
|
|
742
789
|
contentEditable: isEditable,
|
|
743
790
|
suppressContentEditableWarning: isEditable,
|
|
744
791
|
spellCheck: isEditable ? 'false' : undefined,
|
|
@@ -746,14 +793,12 @@ function $32489daedd52963e$export$1315d136e6f7581(segment, state, ref) {
|
|
|
746
793
|
autoCorrect: isEditable ? 'off' : undefined,
|
|
747
794
|
// Capitalization was changed in React 17...
|
|
748
795
|
[parseInt($cIPI0$react.version, 10) >= 17 ? 'enterKeyHint' : 'enterkeyhint']: isEditable ? 'next' : undefined,
|
|
749
|
-
inputMode: state.isDisabled || segment.type === 'dayPeriod' || !isEditable ? undefined : 'numeric',
|
|
796
|
+
inputMode: state.isDisabled || segment.type === 'dayPeriod' || segment.type === 'era' || !isEditable ? undefined : 'numeric',
|
|
750
797
|
tabIndex: state.isDisabled ? undefined : 0,
|
|
751
798
|
onKeyDown: onKeyDown,
|
|
752
799
|
onFocus: onFocus,
|
|
753
800
|
style: {
|
|
754
|
-
caretColor: 'transparent'
|
|
755
|
-
userSelect: 'none',
|
|
756
|
-
WebkitUserSelect: 'none'
|
|
801
|
+
caretColor: 'transparent'
|
|
757
802
|
},
|
|
758
803
|
// Prevent pointer events from reaching useDatePickerGroup, and allow native browser behavior to focus the segment.
|
|
759
804
|
onPointerDown (e) {
|
|
@@ -765,7 +810,16 @@ function $32489daedd52963e$export$1315d136e6f7581(segment, state, ref) {
|
|
|
765
810
|
})
|
|
766
811
|
};
|
|
767
812
|
}
|
|
768
|
-
|
|
813
|
+
function $32489daedd52963e$var$commonPrefixLength(strings) {
|
|
814
|
+
// Sort the strings, and compare the characters in the first and last to find the common prefix.
|
|
815
|
+
strings.sort();
|
|
816
|
+
let first = strings[0];
|
|
817
|
+
let last = strings[strings.length - 1];
|
|
818
|
+
for(let i = 0; i < first.length; i++){
|
|
819
|
+
if (first[i] !== last[i]) return i;
|
|
820
|
+
}
|
|
821
|
+
return 0;
|
|
822
|
+
}
|
|
769
823
|
|
|
770
824
|
|
|
771
825
|
|
|
@@ -805,11 +859,6 @@ function $887cac91b7cc8801$export$12fd5f0e9f4bb192(props, state, ref) {
|
|
|
805
859
|
let buttonId = $cIPI0$useId();
|
|
806
860
|
let dialogId = $cIPI0$useId();
|
|
807
861
|
let groupProps = $3dfb0f96be0d6a08$export$4a931266a3838b86(state, ref);
|
|
808
|
-
let { focusWithinProps: focusWithinProps } = $cIPI0$useFocusWithin({
|
|
809
|
-
onBlurWithin () {
|
|
810
|
-
state.confirmPlaceholder();
|
|
811
|
-
}
|
|
812
|
-
});
|
|
813
862
|
let ariaDescribedBy = [
|
|
814
863
|
descProps['aria-describedby'],
|
|
815
864
|
fieldProps['aria-describedby']
|
|
@@ -839,7 +888,7 @@ function $887cac91b7cc8801$export$12fd5f0e9f4bb192(props, state, ref) {
|
|
|
839
888
|
};
|
|
840
889
|
let domProps = $cIPI0$filterDOMProps(props);
|
|
841
890
|
return {
|
|
842
|
-
groupProps: $cIPI0$mergeProps(domProps, groupProps, fieldProps, descProps,
|
|
891
|
+
groupProps: $cIPI0$mergeProps(domProps, groupProps, fieldProps, descProps, {
|
|
843
892
|
role: 'group',
|
|
844
893
|
'aria-disabled': props.isDisabled || null,
|
|
845
894
|
'aria-describedby': ariaDescribedBy
|