rn-grid-date-time-picker 1.0.0 → 1.2.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/CHANGELOG.md +86 -0
- package/README.md +100 -638
- package/lib/commonjs/adapters/utcMidnight.js +15 -6
- package/lib/commonjs/adapters/utcMidnight.js.map +1 -1
- package/lib/commonjs/components/DateTimePicker.js +484 -85
- package/lib/commonjs/components/DateTimePicker.js.map +1 -1
- package/lib/commonjs/components/calendar/Calendar.js +21 -7
- package/lib/commonjs/components/calendar/Calendar.js.map +1 -1
- package/lib/commonjs/components/calendar/CalendarHeader.js +46 -6
- package/lib/commonjs/components/calendar/CalendarHeader.js.map +1 -1
- package/lib/commonjs/components/calendar/CalendarSwitch.js +150 -0
- package/lib/commonjs/components/calendar/CalendarSwitch.js.map +1 -0
- package/lib/commonjs/components/calendar/DayCell.js +8 -3
- package/lib/commonjs/components/calendar/DayCell.js.map +1 -1
- package/lib/commonjs/components/calendar/DayGrid.js +13 -2
- package/lib/commonjs/components/calendar/DayGrid.js.map +1 -1
- package/lib/commonjs/components/calendar/PeriodGrid.js +3 -1
- package/lib/commonjs/components/calendar/PeriodGrid.js.map +1 -1
- package/lib/commonjs/components/calendar/calendarStyles.js +3 -2
- package/lib/commonjs/components/calendar/calendarStyles.js.map +1 -1
- package/lib/commonjs/components/calendar/localeNames.js +46 -24
- package/lib/commonjs/components/calendar/localeNames.js.map +1 -1
- package/lib/commonjs/components/calendar/selection.js +9 -1
- package/lib/commonjs/components/calendar/selection.js.map +1 -1
- package/lib/commonjs/components/container/DefaultSheet.js +42 -11
- package/lib/commonjs/components/container/DefaultSheet.js.map +1 -1
- package/lib/commonjs/components/container/PickerContainer.js +4 -0
- package/lib/commonjs/components/container/PickerContainer.js.map +1 -1
- package/lib/commonjs/components/container/PickerLayout.js +1 -1
- package/lib/commonjs/components/container/PickerLayout.js.map +1 -1
- package/lib/commonjs/components/container/containerStyles.js +12 -4
- package/lib/commonjs/components/container/containerStyles.js.map +1 -1
- package/lib/commonjs/components/field/RangeFields.js +5 -1
- package/lib/commonjs/components/field/RangeFields.js.map +1 -1
- package/lib/commonjs/components/field/SegmentedInput.js +8 -3
- package/lib/commonjs/components/field/SegmentedInput.js.map +1 -1
- package/lib/commonjs/components/field/ValueField.js +64 -8
- package/lib/commonjs/components/field/ValueField.js.map +1 -1
- package/lib/commonjs/components/field/fieldStyles.js +17 -0
- package/lib/commonjs/components/field/fieldStyles.js.map +1 -1
- package/lib/commonjs/components/field/fieldText.js +29 -13
- package/lib/commonjs/components/field/fieldText.js.map +1 -1
- package/lib/commonjs/components/hooks/useBottomInset.js +32 -0
- package/lib/commonjs/components/hooks/useBottomInset.js.map +1 -0
- package/lib/commonjs/components/hooks/useKeyboardFold.js +36 -13
- package/lib/commonjs/components/hooks/useKeyboardFold.js.map +1 -1
- package/lib/commonjs/components/hooks/useOpenPicker.js +39 -17
- package/lib/commonjs/components/hooks/useOpenPicker.js.map +1 -1
- package/lib/commonjs/components/hooks/useTypedSegments.js +6 -2
- package/lib/commonjs/components/hooks/useTypedSegments.js.map +1 -1
- package/lib/commonjs/components/theme/defaultStrings.js +13 -3
- package/lib/commonjs/components/theme/defaultStrings.js.map +1 -1
- package/lib/commonjs/components/theme/direction.js +17 -0
- package/lib/commonjs/components/theme/direction.js.map +1 -0
- package/lib/commonjs/components/theme/numerals.js +16 -0
- package/lib/commonjs/components/theme/numerals.js.map +1 -0
- package/lib/commonjs/components/theme/styleKeys.js +10 -2
- package/lib/commonjs/components/theme/styleKeys.js.map +1 -1
- package/lib/commonjs/components/theme/tokens.js +4 -0
- package/lib/commonjs/components/theme/tokens.js.map +1 -1
- package/lib/commonjs/components/time/TimeRow.js +10 -2
- package/lib/commonjs/components/time/TimeRow.js.map +1 -1
- package/lib/commonjs/components/time/TypedTime.js +3 -1
- package/lib/commonjs/components/time/TypedTime.js.map +1 -1
- package/lib/commonjs/components/time/Wheel.js +20 -3
- package/lib/commonjs/components/time/Wheel.js.map +1 -1
- package/lib/commonjs/components/time/timeStyles.js +4 -5
- package/lib/commonjs/components/time/timeStyles.js.map +1 -1
- package/lib/commonjs/components/types.js +10 -0
- package/lib/commonjs/components/types.js.map +1 -1
- package/lib/commonjs/core/calendarSystem.js +123 -22
- package/lib/commonjs/core/calendarSystem.js.map +1 -1
- package/lib/commonjs/core/digits.js +25 -0
- package/lib/commonjs/core/digits.js.map +1 -0
- package/lib/commonjs/core/draft.js +31 -10
- package/lib/commonjs/core/draft.js.map +1 -1
- package/lib/commonjs/core/locale.js +20 -4
- package/lib/commonjs/core/locale.js.map +1 -1
- package/lib/commonjs/core/numerals.js +46 -0
- package/lib/commonjs/core/numerals.js.map +1 -0
- package/lib/commonjs/core/segmentEditor.js +9 -0
- package/lib/commonjs/core/segmentEditor.js.map +1 -1
- package/lib/commonjs/core/segments.js +2 -11
- package/lib/commonjs/core/segments.js.map +1 -1
- package/lib/commonjs/core/selectionRules.js +2 -1
- package/lib/commonjs/core/selectionRules.js.map +1 -1
- package/lib/commonjs/core/timeEntry.js +7 -91
- package/lib/commonjs/core/timeEntry.js.map +1 -1
- package/lib/commonjs/icons/index.js +5 -1
- package/lib/commonjs/icons/index.js.map +1 -1
- package/lib/commonjs/index.js +20 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/adapters/utcMidnight.js +14 -5
- package/lib/module/adapters/utcMidnight.js.map +1 -1
- package/lib/module/components/DateTimePicker.js +490 -91
- package/lib/module/components/DateTimePicker.js.map +1 -1
- package/lib/module/components/calendar/Calendar.js +25 -11
- package/lib/module/components/calendar/Calendar.js.map +1 -1
- package/lib/module/components/calendar/CalendarHeader.js +47 -7
- package/lib/module/components/calendar/CalendarHeader.js.map +1 -1
- package/lib/module/components/calendar/CalendarSwitch.js +145 -0
- package/lib/module/components/calendar/CalendarSwitch.js.map +1 -0
- package/lib/module/components/calendar/DayCell.js +8 -3
- package/lib/module/components/calendar/DayCell.js.map +1 -1
- package/lib/module/components/calendar/DayGrid.js +14 -3
- package/lib/module/components/calendar/DayGrid.js.map +1 -1
- package/lib/module/components/calendar/PeriodGrid.js +3 -1
- package/lib/module/components/calendar/PeriodGrid.js.map +1 -1
- package/lib/module/components/calendar/calendarStyles.js +3 -2
- package/lib/module/components/calendar/calendarStyles.js.map +1 -1
- package/lib/module/components/calendar/localeNames.js +46 -24
- package/lib/module/components/calendar/localeNames.js.map +1 -1
- package/lib/module/components/calendar/selection.js +7 -0
- package/lib/module/components/calendar/selection.js.map +1 -1
- package/lib/module/components/container/DefaultSheet.js +42 -12
- package/lib/module/components/container/DefaultSheet.js.map +1 -1
- package/lib/module/components/container/PickerContainer.js +4 -0
- package/lib/module/components/container/PickerContainer.js.map +1 -1
- package/lib/module/components/container/PickerLayout.js +1 -1
- package/lib/module/components/container/PickerLayout.js.map +1 -1
- package/lib/module/components/container/containerStyles.js +11 -3
- package/lib/module/components/container/containerStyles.js.map +1 -1
- package/lib/module/components/field/RangeFields.js +5 -1
- package/lib/module/components/field/RangeFields.js.map +1 -1
- package/lib/module/components/field/SegmentedInput.js +8 -3
- package/lib/module/components/field/SegmentedInput.js.map +1 -1
- package/lib/module/components/field/ValueField.js +66 -10
- package/lib/module/components/field/ValueField.js.map +1 -1
- package/lib/module/components/field/fieldStyles.js +17 -0
- package/lib/module/components/field/fieldStyles.js.map +1 -1
- package/lib/module/components/field/fieldText.js +28 -11
- package/lib/module/components/field/fieldText.js.map +1 -1
- package/lib/module/components/hooks/useBottomInset.js +27 -0
- package/lib/module/components/hooks/useBottomInset.js.map +1 -0
- package/lib/module/components/hooks/useKeyboardFold.js +33 -12
- package/lib/module/components/hooks/useKeyboardFold.js.map +1 -1
- package/lib/module/components/hooks/useOpenPicker.js +39 -17
- package/lib/module/components/hooks/useOpenPicker.js.map +1 -1
- package/lib/module/components/hooks/useTypedSegments.js +6 -2
- package/lib/module/components/hooks/useTypedSegments.js.map +1 -1
- package/lib/module/components/theme/defaultStrings.js +11 -2
- package/lib/module/components/theme/defaultStrings.js.map +1 -1
- package/lib/module/components/theme/direction.js +13 -0
- package/lib/module/components/theme/direction.js.map +1 -0
- package/lib/module/components/theme/numerals.js +12 -0
- package/lib/module/components/theme/numerals.js.map +1 -0
- package/lib/module/components/theme/styleKeys.js +10 -2
- package/lib/module/components/theme/styleKeys.js.map +1 -1
- package/lib/module/components/theme/tokens.js +4 -0
- package/lib/module/components/theme/tokens.js.map +1 -1
- package/lib/module/components/time/TimeRow.js +11 -3
- package/lib/module/components/time/TimeRow.js.map +1 -1
- package/lib/module/components/time/TypedTime.js +3 -1
- package/lib/module/components/time/TypedTime.js.map +1 -1
- package/lib/module/components/time/Wheel.js +18 -2
- package/lib/module/components/time/Wheel.js.map +1 -1
- package/lib/module/components/time/timeStyles.js +4 -5
- package/lib/module/components/time/timeStyles.js.map +1 -1
- package/lib/module/components/types.js +10 -0
- package/lib/module/components/types.js.map +1 -1
- package/lib/module/core/calendarSystem.js +118 -19
- package/lib/module/core/calendarSystem.js.map +1 -1
- package/lib/module/core/digits.js +20 -0
- package/lib/module/core/digits.js.map +1 -0
- package/lib/module/core/draft.js +29 -9
- package/lib/module/core/draft.js.map +1 -1
- package/lib/module/core/locale.js +18 -3
- package/lib/module/core/locale.js.map +1 -1
- package/lib/module/core/numerals.js +39 -0
- package/lib/module/core/numerals.js.map +1 -0
- package/lib/module/core/segmentEditor.js +9 -0
- package/lib/module/core/segmentEditor.js.map +1 -1
- package/lib/module/core/segments.js +0 -8
- package/lib/module/core/segments.js.map +1 -1
- package/lib/module/core/selectionRules.js +2 -1
- package/lib/module/core/selectionRules.js.map +1 -1
- package/lib/module/core/timeEntry.js +7 -89
- package/lib/module/core/timeEntry.js.map +1 -1
- package/lib/module/icons/index.js +5 -1
- package/lib/module/icons/index.js.map +1 -1
- package/lib/module/index.js +2 -0
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/commonjs/src/adapters/utcMidnight.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/DateTimePicker.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/calendar/Calendar.d.ts +8 -4
- package/lib/typescript/commonjs/src/components/calendar/Calendar.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/calendar/CalendarHeader.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/calendar/CalendarSwitch.d.ts +26 -0
- package/lib/typescript/commonjs/src/components/calendar/CalendarSwitch.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/components/calendar/DayCell.d.ts +1 -1
- package/lib/typescript/commonjs/src/components/calendar/DayCell.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/calendar/DayGrid.d.ts +2 -0
- package/lib/typescript/commonjs/src/components/calendar/DayGrid.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/calendar/PeriodGrid.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/calendar/calendarStyles.d.ts +1 -1
- package/lib/typescript/commonjs/src/components/calendar/calendarStyles.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/calendar/localeNames.d.ts +8 -3
- package/lib/typescript/commonjs/src/components/calendar/localeNames.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/calendar/selection.d.ts +2 -0
- package/lib/typescript/commonjs/src/components/calendar/selection.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/container/DefaultSheet.d.ts +10 -2
- package/lib/typescript/commonjs/src/components/container/DefaultSheet.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/container/PickerContainer.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/container/containerStyles.d.ts +6 -0
- package/lib/typescript/commonjs/src/components/container/containerStyles.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/field/RangeFields.d.ts +5 -0
- package/lib/typescript/commonjs/src/components/field/RangeFields.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/field/SegmentedInput.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/field/ValueField.d.ts +7 -0
- package/lib/typescript/commonjs/src/components/field/ValueField.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/field/fieldStyles.d.ts +15 -0
- package/lib/typescript/commonjs/src/components/field/fieldStyles.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/field/fieldText.d.ts +14 -5
- package/lib/typescript/commonjs/src/components/field/fieldText.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/hooks/useBottomInset.d.ts +8 -0
- package/lib/typescript/commonjs/src/components/hooks/useBottomInset.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/components/hooks/useKeyboardFold.d.ts +10 -2
- package/lib/typescript/commonjs/src/components/hooks/useKeyboardFold.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/hooks/useOpenPicker.d.ts +2 -1
- package/lib/typescript/commonjs/src/components/hooks/useOpenPicker.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/hooks/useTypedSegments.d.ts +3 -2
- package/lib/typescript/commonjs/src/components/hooks/useTypedSegments.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/theme/defaultStrings.d.ts +13 -2
- package/lib/typescript/commonjs/src/components/theme/defaultStrings.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/theme/direction.d.ts +8 -0
- package/lib/typescript/commonjs/src/components/theme/direction.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/components/theme/numerals.d.ts +7 -0
- package/lib/typescript/commonjs/src/components/theme/numerals.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/components/theme/styleKeys.d.ts +1 -1
- package/lib/typescript/commonjs/src/components/theme/styleKeys.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/theme/tokens.d.ts +3 -1
- package/lib/typescript/commonjs/src/components/theme/tokens.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/time/TimeRow.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/time/TypedTime.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/time/Wheel.d.ts +5 -0
- package/lib/typescript/commonjs/src/components/time/Wheel.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/time/timeStyles.d.ts +0 -2
- package/lib/typescript/commonjs/src/components/time/timeStyles.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/types.d.ts +84 -4
- package/lib/typescript/commonjs/src/components/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/core/calendarSystem.d.ts +20 -5
- package/lib/typescript/commonjs/src/core/calendarSystem.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/core/digits.d.ts +3 -0
- package/lib/typescript/commonjs/src/core/digits.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/core/draft.d.ts +12 -1
- package/lib/typescript/commonjs/src/core/draft.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/core/locale.d.ts +6 -0
- package/lib/typescript/commonjs/src/core/locale.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/core/numerals.d.ts +15 -0
- package/lib/typescript/commonjs/src/core/numerals.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/core/segmentEditor.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/core/segments.d.ts +0 -2
- package/lib/typescript/commonjs/src/core/segments.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/core/selectionRules.d.ts +3 -2
- package/lib/typescript/commonjs/src/core/selectionRules.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/core/timeEntry.d.ts +4 -24
- package/lib/typescript/commonjs/src/core/timeEntry.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/icons/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/index.d.ts +7 -3
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
- package/lib/typescript/module/src/adapters/utcMidnight.d.ts.map +1 -1
- package/lib/typescript/module/src/components/DateTimePicker.d.ts.map +1 -1
- package/lib/typescript/module/src/components/calendar/Calendar.d.ts +8 -4
- package/lib/typescript/module/src/components/calendar/Calendar.d.ts.map +1 -1
- package/lib/typescript/module/src/components/calendar/CalendarHeader.d.ts.map +1 -1
- package/lib/typescript/module/src/components/calendar/CalendarSwitch.d.ts +26 -0
- package/lib/typescript/module/src/components/calendar/CalendarSwitch.d.ts.map +1 -0
- package/lib/typescript/module/src/components/calendar/DayCell.d.ts +1 -1
- package/lib/typescript/module/src/components/calendar/DayCell.d.ts.map +1 -1
- package/lib/typescript/module/src/components/calendar/DayGrid.d.ts +2 -0
- package/lib/typescript/module/src/components/calendar/DayGrid.d.ts.map +1 -1
- package/lib/typescript/module/src/components/calendar/PeriodGrid.d.ts.map +1 -1
- package/lib/typescript/module/src/components/calendar/calendarStyles.d.ts +1 -1
- package/lib/typescript/module/src/components/calendar/calendarStyles.d.ts.map +1 -1
- package/lib/typescript/module/src/components/calendar/localeNames.d.ts +8 -3
- package/lib/typescript/module/src/components/calendar/localeNames.d.ts.map +1 -1
- package/lib/typescript/module/src/components/calendar/selection.d.ts +2 -0
- package/lib/typescript/module/src/components/calendar/selection.d.ts.map +1 -1
- package/lib/typescript/module/src/components/container/DefaultSheet.d.ts +10 -2
- package/lib/typescript/module/src/components/container/DefaultSheet.d.ts.map +1 -1
- package/lib/typescript/module/src/components/container/PickerContainer.d.ts.map +1 -1
- package/lib/typescript/module/src/components/container/containerStyles.d.ts +6 -0
- package/lib/typescript/module/src/components/container/containerStyles.d.ts.map +1 -1
- package/lib/typescript/module/src/components/field/RangeFields.d.ts +5 -0
- package/lib/typescript/module/src/components/field/RangeFields.d.ts.map +1 -1
- package/lib/typescript/module/src/components/field/SegmentedInput.d.ts.map +1 -1
- package/lib/typescript/module/src/components/field/ValueField.d.ts +7 -0
- package/lib/typescript/module/src/components/field/ValueField.d.ts.map +1 -1
- package/lib/typescript/module/src/components/field/fieldStyles.d.ts +15 -0
- package/lib/typescript/module/src/components/field/fieldStyles.d.ts.map +1 -1
- package/lib/typescript/module/src/components/field/fieldText.d.ts +14 -5
- package/lib/typescript/module/src/components/field/fieldText.d.ts.map +1 -1
- package/lib/typescript/module/src/components/hooks/useBottomInset.d.ts +8 -0
- package/lib/typescript/module/src/components/hooks/useBottomInset.d.ts.map +1 -0
- package/lib/typescript/module/src/components/hooks/useKeyboardFold.d.ts +10 -2
- package/lib/typescript/module/src/components/hooks/useKeyboardFold.d.ts.map +1 -1
- package/lib/typescript/module/src/components/hooks/useOpenPicker.d.ts +2 -1
- package/lib/typescript/module/src/components/hooks/useOpenPicker.d.ts.map +1 -1
- package/lib/typescript/module/src/components/hooks/useTypedSegments.d.ts +3 -2
- package/lib/typescript/module/src/components/hooks/useTypedSegments.d.ts.map +1 -1
- package/lib/typescript/module/src/components/theme/defaultStrings.d.ts +13 -2
- package/lib/typescript/module/src/components/theme/defaultStrings.d.ts.map +1 -1
- package/lib/typescript/module/src/components/theme/direction.d.ts +8 -0
- package/lib/typescript/module/src/components/theme/direction.d.ts.map +1 -0
- package/lib/typescript/module/src/components/theme/numerals.d.ts +7 -0
- package/lib/typescript/module/src/components/theme/numerals.d.ts.map +1 -0
- package/lib/typescript/module/src/components/theme/styleKeys.d.ts +1 -1
- package/lib/typescript/module/src/components/theme/styleKeys.d.ts.map +1 -1
- package/lib/typescript/module/src/components/theme/tokens.d.ts +3 -1
- package/lib/typescript/module/src/components/theme/tokens.d.ts.map +1 -1
- package/lib/typescript/module/src/components/time/TimeRow.d.ts.map +1 -1
- package/lib/typescript/module/src/components/time/TypedTime.d.ts.map +1 -1
- package/lib/typescript/module/src/components/time/Wheel.d.ts +5 -0
- package/lib/typescript/module/src/components/time/Wheel.d.ts.map +1 -1
- package/lib/typescript/module/src/components/time/timeStyles.d.ts +0 -2
- package/lib/typescript/module/src/components/time/timeStyles.d.ts.map +1 -1
- package/lib/typescript/module/src/components/types.d.ts +84 -4
- package/lib/typescript/module/src/components/types.d.ts.map +1 -1
- package/lib/typescript/module/src/core/calendarSystem.d.ts +20 -5
- package/lib/typescript/module/src/core/calendarSystem.d.ts.map +1 -1
- package/lib/typescript/module/src/core/digits.d.ts +3 -0
- package/lib/typescript/module/src/core/digits.d.ts.map +1 -0
- package/lib/typescript/module/src/core/draft.d.ts +12 -1
- package/lib/typescript/module/src/core/draft.d.ts.map +1 -1
- package/lib/typescript/module/src/core/locale.d.ts +6 -0
- package/lib/typescript/module/src/core/locale.d.ts.map +1 -1
- package/lib/typescript/module/src/core/numerals.d.ts +15 -0
- package/lib/typescript/module/src/core/numerals.d.ts.map +1 -0
- package/lib/typescript/module/src/core/segmentEditor.d.ts.map +1 -1
- package/lib/typescript/module/src/core/segments.d.ts +0 -2
- package/lib/typescript/module/src/core/segments.d.ts.map +1 -1
- package/lib/typescript/module/src/core/selectionRules.d.ts +3 -2
- package/lib/typescript/module/src/core/selectionRules.d.ts.map +1 -1
- package/lib/typescript/module/src/core/timeEntry.d.ts +4 -24
- package/lib/typescript/module/src/core/timeEntry.d.ts.map +1 -1
- package/lib/typescript/module/src/icons/index.d.ts.map +1 -1
- package/lib/typescript/module/src/index.d.ts +7 -3
- package/lib/typescript/module/src/index.d.ts.map +1 -1
- package/package.json +22 -7
- package/src/adapters/utcMidnight.ts +14 -5
- package/src/components/DateTimePicker.tsx +607 -108
- package/src/components/calendar/Calendar.tsx +54 -16
- package/src/components/calendar/CalendarHeader.tsx +41 -9
- package/src/components/calendar/CalendarSwitch.tsx +170 -0
- package/src/components/calendar/DayCell.tsx +16 -4
- package/src/components/calendar/DayGrid.tsx +18 -3
- package/src/components/calendar/PeriodGrid.tsx +3 -1
- package/src/components/calendar/calendarStyles.ts +3 -2
- package/src/components/calendar/localeNames.ts +52 -22
- package/src/components/calendar/selection.ts +8 -0
- package/src/components/container/DefaultSheet.tsx +60 -14
- package/src/components/container/PickerContainer.tsx +4 -0
- package/src/components/container/PickerLayout.tsx +1 -1
- package/src/components/container/containerStyles.ts +12 -3
- package/src/components/field/RangeFields.tsx +12 -2
- package/src/components/field/SegmentedInput.tsx +8 -3
- package/src/components/field/ValueField.tsx +94 -18
- package/src/components/field/fieldStyles.ts +6 -0
- package/src/components/field/fieldText.ts +68 -15
- package/src/components/hooks/useBottomInset.ts +33 -0
- package/src/components/hooks/useKeyboardFold.ts +41 -13
- package/src/components/hooks/useOpenPicker.ts +41 -18
- package/src/components/hooks/useTypedSegments.ts +7 -3
- package/src/components/theme/defaultStrings.ts +29 -4
- package/src/components/theme/direction.ts +12 -0
- package/src/components/theme/numerals.ts +11 -0
- package/src/components/theme/styleKeys.ts +18 -1
- package/src/components/theme/tokens.ts +5 -1
- package/src/components/time/TimeRow.tsx +23 -3
- package/src/components/time/TypedTime.tsx +3 -1
- package/src/components/time/Wheel.tsx +19 -5
- package/src/components/time/timeStyles.ts +2 -3
- package/src/components/types.ts +86 -4
- package/src/core/calendarSystem.ts +145 -21
- package/src/core/digits.ts +21 -0
- package/src/core/draft.ts +41 -13
- package/src/core/locale.ts +20 -3
- package/src/core/numerals.ts +35 -0
- package/src/core/segmentEditor.ts +13 -0
- package/src/core/segments.ts +0 -8
- package/src/core/selectionRules.ts +3 -2
- package/src/core/timeEntry.ts +6 -96
- package/src/icons/index.tsx +3 -1
- package/src/index.tsx +12 -2
|
@@ -1,20 +1,26 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { weekdayOf } from '../../core/calendarDate';
|
|
2
|
+
import { withCalendar } from '../../core/locale';
|
|
2
3
|
import type { CalendarDate, Weekday } from '../../core/types';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
|
-
* Month and weekday names from
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* Month and weekday names from the platform's Intl, cached per locale. Each
|
|
7
|
+
* name is formatted on its own (not read from formatToParts: iOS labels every
|
|
8
|
+
* part of some locales, such as 'de-DE' and 'ar-SA', as plain text), in the
|
|
9
|
+
* Gregorian calendar. Falls back to 'en-US' when the device's Intl can't name
|
|
10
|
+
* the locale, and to built-in English names after that.
|
|
8
11
|
*/
|
|
9
12
|
interface Names {
|
|
10
13
|
monthsShort: string[];
|
|
11
14
|
monthsLong: string[];
|
|
15
|
+
/** Monday … Sunday, as the weekday row shows them. */
|
|
12
16
|
weekdays: string[];
|
|
17
|
+
/** Monday … Sunday, for screen readers. */
|
|
18
|
+
weekdaysLong: string[];
|
|
13
19
|
}
|
|
14
20
|
|
|
15
21
|
const cache = new Map<string, Names>();
|
|
16
22
|
|
|
17
|
-
const FALLBACK = {
|
|
23
|
+
const FALLBACK: Names = {
|
|
18
24
|
monthsShort: [
|
|
19
25
|
'Jan',
|
|
20
26
|
'Feb',
|
|
@@ -43,26 +49,53 @@ const FALLBACK = {
|
|
|
43
49
|
'November',
|
|
44
50
|
'December',
|
|
45
51
|
],
|
|
46
|
-
// Luxon order: Monday … Sunday.
|
|
47
52
|
weekdays: ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'],
|
|
53
|
+
weekdaysLong: [
|
|
54
|
+
'Monday',
|
|
55
|
+
'Tuesday',
|
|
56
|
+
'Wednesday',
|
|
57
|
+
'Thursday',
|
|
58
|
+
'Friday',
|
|
59
|
+
'Saturday',
|
|
60
|
+
'Sunday',
|
|
61
|
+
],
|
|
48
62
|
};
|
|
49
63
|
|
|
64
|
+
const range = (n: number) => Array.from({ length: n }, (_, i) => i);
|
|
65
|
+
|
|
50
66
|
const readNames = (locale: string): Names | null => {
|
|
51
67
|
try {
|
|
52
|
-
const
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
68
|
+
const tag = withCalendar(locale, 'gregory');
|
|
69
|
+
const namer = (options: Intl.DateTimeFormatOptions) => {
|
|
70
|
+
const f = new Intl.DateTimeFormat(tag, { timeZone: 'UTC', ...options });
|
|
71
|
+
return (d: Date) => f.format(d);
|
|
72
|
+
};
|
|
73
|
+
// Mid-month, at noon UTC, so no zone moves the day.
|
|
74
|
+
const months = range(12).map((i) => new Date(Date.UTC(2021, i, 15, 12)));
|
|
75
|
+
// 1 February 2021 was a Monday.
|
|
76
|
+
const days = range(7).map((i) => new Date(Date.UTC(2021, 1, 1 + i, 12)));
|
|
77
|
+
const short = days.map(namer({ weekday: 'short' }));
|
|
78
|
+
// The language Intl actually uses: an unknown tag falls back to the device's.
|
|
79
|
+
const english = new Intl.DateTimeFormat(tag)
|
|
80
|
+
.resolvedOptions()
|
|
81
|
+
.locale.startsWith('en');
|
|
82
|
+
const names: Names = {
|
|
83
|
+
monthsShort: months.map(namer({ month: 'short' })),
|
|
84
|
+
monthsLong: months.map(namer({ month: 'long' })),
|
|
56
85
|
// Two letters for English ("Su", "Mo"); other locales keep their short form.
|
|
57
|
-
weekdays:
|
|
58
|
-
|
|
59
|
-
: short,
|
|
86
|
+
weekdays: english ? short.map((w) => w.slice(0, 2)) : short,
|
|
87
|
+
weekdaysLong: days.map(namer({ weekday: 'long' })),
|
|
60
88
|
};
|
|
61
|
-
|
|
62
|
-
|
|
89
|
+
// Every name present and different (an engine that ignores the options
|
|
90
|
+
// writes whole dates, or the same text, instead).
|
|
91
|
+
const complete = (list: string[], length: number) =>
|
|
92
|
+
list.length === length &&
|
|
93
|
+
list.every(Boolean) &&
|
|
94
|
+
new Set(list).size === length;
|
|
63
95
|
return complete(names.monthsShort, 12) &&
|
|
64
96
|
complete(names.monthsLong, 12) &&
|
|
65
|
-
complete(names.weekdays, 7)
|
|
97
|
+
complete(names.weekdays, 7) &&
|
|
98
|
+
complete(names.weekdaysLong, 7)
|
|
66
99
|
? names
|
|
67
100
|
: null;
|
|
68
101
|
} catch {
|
|
@@ -84,10 +117,7 @@ export const weekdayName = (locale: string, weekday: Weekday): string =>
|
|
|
84
117
|
|
|
85
118
|
/** Full date for screen readers, e.g. "Wednesday, 21 October 2026". */
|
|
86
119
|
export const fullDateLabel = (locale: string, day: CalendarDate): string => {
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
} catch {
|
|
91
|
-
return dt.toFormat('cccc, d LLLL yyyy');
|
|
92
|
-
}
|
|
120
|
+
const names = localeNames(locale);
|
|
121
|
+
const weekday = names.weekdaysLong[weekdayOf(day) - 1];
|
|
122
|
+
return `${weekday}, ${day.day} ${names.monthsLong[day.month - 1]} ${day.year}`;
|
|
93
123
|
};
|
|
@@ -17,6 +17,14 @@ export const firstSelectedDay = (
|
|
|
17
17
|
return sel.days[0] ?? null;
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
+
/** Every selected day. */
|
|
21
|
+
export const selectedDays = (sel: CalendarSelection): CalendarDate[] => {
|
|
22
|
+
if (sel.kind === 'single') return sel.day ? [sel.day] : [];
|
|
23
|
+
if (sel.kind === 'range')
|
|
24
|
+
return [sel.from, sel.to].filter((d): d is CalendarDate => !!d);
|
|
25
|
+
return sel.days;
|
|
26
|
+
};
|
|
27
|
+
|
|
20
28
|
const isNextDay = (a: CalendarDate, b: CalendarDate): boolean => {
|
|
21
29
|
const next = new Date(Date.UTC(a.year, a.month - 1, a.day + 1));
|
|
22
30
|
return (
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
KeyboardAvoidingView,
|
|
4
4
|
Modal,
|
|
5
|
-
Platform,
|
|
6
5
|
Pressable,
|
|
7
6
|
useWindowDimensions,
|
|
8
7
|
View,
|
|
@@ -10,23 +9,36 @@ import {
|
|
|
10
9
|
import type { PickerStyles } from '../theme/styleKeys';
|
|
11
10
|
import type { ThemeTokens } from '../theme/tokens';
|
|
12
11
|
import type { SheetRenderProps, SheetSize } from '../types';
|
|
13
|
-
import {
|
|
12
|
+
import { useBottomInset } from '../hooks/useBottomInset';
|
|
13
|
+
import { useKeyboard } from '../hooks/useKeyboardFold';
|
|
14
|
+
import { buildContainerStyles, SHEET_PADDING_BOTTOM } from './containerStyles';
|
|
14
15
|
|
|
15
16
|
interface Props extends SheetRenderProps {
|
|
16
17
|
height?: SheetSize;
|
|
17
18
|
maxHeight?: SheetSize;
|
|
19
|
+
keyboardMaxHeight?: SheetSize;
|
|
20
|
+
/** Space kept free below the footer; default: the app's safe-area inset. */
|
|
21
|
+
bottomInset?: number;
|
|
22
|
+
/** The backdrop's screen-reader label. */
|
|
23
|
+
closeLabel: string;
|
|
18
24
|
tokens: ThemeTokens;
|
|
19
25
|
styles?: PickerStyles;
|
|
20
26
|
}
|
|
21
27
|
|
|
28
|
+
/** The least room the sheet gets while the keyboard is up, in points. */
|
|
29
|
+
const MIN_ROOM = 160;
|
|
30
|
+
|
|
22
31
|
/** Points for a size given in points or as a percentage of the screen. */
|
|
23
32
|
const toPoints = (size: SheetSize, screen: number): number =>
|
|
24
33
|
typeof size === 'number' ? size : (screen * parseFloat(size)) / 100;
|
|
25
34
|
|
|
26
35
|
/**
|
|
27
36
|
* The built-in bottom sheet: an RN Modal with a backdrop and a panel pinned to
|
|
28
|
-
* the bottom, up to 90% of the screen (`sheet.height` / `sheet.maxHeight`).
|
|
29
|
-
*
|
|
37
|
+
* the bottom, up to 90% of the screen (`sheet.height` / `sheet.maxHeight`).
|
|
38
|
+
* While the keyboard is up it sits on the keyboard, within `sheet.keyboardMaxHeight`
|
|
39
|
+
* (default `maxHeight`) of the room above it; otherwise it keeps the bottom
|
|
40
|
+
* safe-area inset (`sheet.bottomInset`) free below the footer. Backdrop taps
|
|
41
|
+
* and Android back call onRequestClose. `styles.sheet` styles the panel;
|
|
30
42
|
* `renderSheet` replaces the whole sheet.
|
|
31
43
|
*/
|
|
32
44
|
const DefaultSheet: React.FC<Props> = ({
|
|
@@ -36,15 +48,36 @@ const DefaultSheet: React.FC<Props> = ({
|
|
|
36
48
|
testID,
|
|
37
49
|
height,
|
|
38
50
|
maxHeight = '90%',
|
|
51
|
+
keyboardMaxHeight = maxHeight,
|
|
52
|
+
bottomInset,
|
|
53
|
+
closeLabel,
|
|
39
54
|
tokens,
|
|
40
55
|
styles,
|
|
41
56
|
}) => {
|
|
42
57
|
const { height: screen } = useWindowDimensions();
|
|
43
|
-
const
|
|
58
|
+
const keyboard = useKeyboard(true);
|
|
59
|
+
// The room above the keyboard: measured (padding on iOS, the window on
|
|
60
|
+
// Android), and the screen less the keyboard for an Android window that
|
|
61
|
+
// isn't resized.
|
|
62
|
+
const [measured, setMeasured] = useState(screen);
|
|
63
|
+
// Never less than a strip to show the sheet in, even when the keyboard
|
|
64
|
+
// reports itself as tall as the window (split screen, Slide Over).
|
|
65
|
+
const room = Math.max(
|
|
66
|
+
Math.min(measured, screen - keyboard.height),
|
|
67
|
+
Math.min(screen, MIN_ROOM)
|
|
68
|
+
);
|
|
69
|
+
const max = keyboard.up
|
|
70
|
+
? Math.min(toPoints(keyboardMaxHeight, room), room)
|
|
71
|
+
: toPoints(maxHeight, screen);
|
|
44
72
|
const size =
|
|
45
73
|
height === undefined
|
|
46
74
|
? { maxHeight: max }
|
|
47
75
|
: { height: Math.min(toPoints(height, screen), max) };
|
|
76
|
+
// Below the footer: the home indicator or Android's navigation bar, which
|
|
77
|
+
// an edge-to-edge app draws under. While the keyboard is up the sheet sits
|
|
78
|
+
// on the keyboard instead, with nothing under it.
|
|
79
|
+
const safeInset = useBottomInset();
|
|
80
|
+
const inset = keyboard.up ? 0 : Math.max(0, bottomInset ?? safeInset);
|
|
48
81
|
const s = buildContainerStyles(tokens);
|
|
49
82
|
return (
|
|
50
83
|
<Modal
|
|
@@ -54,20 +87,33 @@ const DefaultSheet: React.FC<Props> = ({
|
|
|
54
87
|
statusBarTranslucent
|
|
55
88
|
onRequestClose={onRequestClose}
|
|
56
89
|
>
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
>
|
|
90
|
+
{/* Pads by the part of the screen the keyboard covers: all of it in an
|
|
91
|
+
edge-to-edge Android app, whose window the keyboard doesn't resize;
|
|
92
|
+
none where the window does shrink. */}
|
|
93
|
+
<KeyboardAvoidingView behavior="padding" style={s.sheetRoot}>
|
|
61
94
|
<Pressable
|
|
62
95
|
testID={testID ? `${testID}-backdrop` : undefined}
|
|
63
96
|
accessibilityRole="button"
|
|
64
|
-
accessibilityLabel=
|
|
97
|
+
accessibilityLabel={closeLabel}
|
|
65
98
|
onPress={onRequestClose}
|
|
66
99
|
style={[s.sheetBackdrop, styles?.sheetBackdrop]}
|
|
67
100
|
/>
|
|
68
|
-
<View
|
|
69
|
-
{
|
|
70
|
-
{
|
|
101
|
+
<View
|
|
102
|
+
style={s.sheetRoom}
|
|
103
|
+
onLayout={(e) => setMeasured(e.nativeEvent.layout.height)}
|
|
104
|
+
>
|
|
105
|
+
<View
|
|
106
|
+
testID={testID}
|
|
107
|
+
style={[
|
|
108
|
+
s.sheet,
|
|
109
|
+
size,
|
|
110
|
+
inset > 0 && { paddingBottom: SHEET_PADDING_BOTTOM + inset },
|
|
111
|
+
styles?.sheet,
|
|
112
|
+
]}
|
|
113
|
+
>
|
|
114
|
+
{body}
|
|
115
|
+
{footer}
|
|
116
|
+
</View>
|
|
71
117
|
</View>
|
|
72
118
|
</KeyboardAvoidingView>
|
|
73
119
|
</Modal>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
|
+
import { DEFAULT_STRINGS } from '../theme/defaultStrings';
|
|
3
4
|
import type { SheetOptions, SheetRenderProps } from '../types';
|
|
4
5
|
import DefaultSheet from './DefaultSheet';
|
|
5
6
|
import { buildPickerLayout, type PickerLayoutProps } from './PickerLayout';
|
|
@@ -52,6 +53,9 @@ const PickerContainer: React.FC<PickerContainerProps> = ({
|
|
|
52
53
|
{...p}
|
|
53
54
|
height={sheet?.height}
|
|
54
55
|
maxHeight={sheet?.maxHeight}
|
|
56
|
+
keyboardMaxHeight={sheet?.keyboardMaxHeight}
|
|
57
|
+
bottomInset={sheet?.bottomInset}
|
|
58
|
+
closeLabel={layout.state.strings.a11yClose ?? DEFAULT_STRINGS.a11yClose}
|
|
55
59
|
tokens={layout.state.tokens}
|
|
56
60
|
styles={layout.styles}
|
|
57
61
|
/>
|
|
@@ -134,7 +134,7 @@ export const buildPickerLayout = ({
|
|
|
134
134
|
keyboardShouldPersistTaps="handled"
|
|
135
135
|
nestedScrollEnabled
|
|
136
136
|
bounces={false}
|
|
137
|
-
showsVerticalScrollIndicator
|
|
137
|
+
showsVerticalScrollIndicator={false}
|
|
138
138
|
>
|
|
139
139
|
{headerScrolls ? headerNode : null}
|
|
140
140
|
{content}
|
|
@@ -2,12 +2,20 @@ import { StyleSheet } from 'react-native';
|
|
|
2
2
|
import { fontStyle, type ThemeTokens } from '../theme/tokens';
|
|
3
3
|
|
|
4
4
|
const GUTTER = 16;
|
|
5
|
+
/** Space under the sheet's footer, before any bottom inset. */
|
|
6
|
+
export const SHEET_PADDING_BOTTOM = 8;
|
|
5
7
|
|
|
6
8
|
const cache = new WeakMap<ThemeTokens, ReturnType<typeof create>>();
|
|
7
9
|
|
|
8
10
|
const create = (t: ThemeTokens) =>
|
|
9
11
|
StyleSheet.create({
|
|
10
|
-
sheetRoot: { flex: 1
|
|
12
|
+
sheetRoot: { flex: 1 },
|
|
13
|
+
// The room above the keyboard (all of the screen while it's down); the panel sits at its bottom.
|
|
14
|
+
sheetRoom: {
|
|
15
|
+
flex: 1,
|
|
16
|
+
justifyContent: 'flex-end',
|
|
17
|
+
pointerEvents: 'box-none',
|
|
18
|
+
},
|
|
11
19
|
sheetBackdrop: {
|
|
12
20
|
...StyleSheet.absoluteFill,
|
|
13
21
|
backgroundColor: 'rgba(0, 0, 0, 0.4)',
|
|
@@ -16,7 +24,7 @@ const create = (t: ThemeTokens) =>
|
|
|
16
24
|
borderTopLeftRadius: t.radius * 2,
|
|
17
25
|
borderTopRightRadius: t.radius * 2,
|
|
18
26
|
backgroundColor: t.background,
|
|
19
|
-
paddingBottom:
|
|
27
|
+
paddingBottom: SHEET_PADDING_BOTTOM,
|
|
20
28
|
},
|
|
21
29
|
container: { width: '100%', paddingHorizontal: GUTTER },
|
|
22
30
|
// In a sheet the body shrinks to the sheet's max height and scrolls.
|
|
@@ -30,7 +38,8 @@ const create = (t: ThemeTokens) =>
|
|
|
30
38
|
flexDirection: 'row',
|
|
31
39
|
alignItems: 'center',
|
|
32
40
|
justifyContent: 'space-between',
|
|
33
|
-
|
|
41
|
+
// Room between the sheet's top edge and the title.
|
|
42
|
+
paddingTop: 24,
|
|
34
43
|
paddingBottom: 12,
|
|
35
44
|
},
|
|
36
45
|
title: {
|
|
@@ -8,7 +8,7 @@ import type { PickerStyles } from '../theme/styleKeys';
|
|
|
8
8
|
import type { ThemeTokens } from '../theme/tokens';
|
|
9
9
|
import type { LabelRenderProps } from '../types';
|
|
10
10
|
import FieldMessages from './FieldMessages';
|
|
11
|
-
import { formatRangeText } from './fieldText';
|
|
11
|
+
import { formatRangeText, type DateTextFormatter } from './fieldText';
|
|
12
12
|
import ValueField from './ValueField';
|
|
13
13
|
|
|
14
14
|
export type RangeEnd = 'from' | 'to';
|
|
@@ -30,6 +30,8 @@ interface Props {
|
|
|
30
30
|
errorMessage?: string;
|
|
31
31
|
type: PickerType;
|
|
32
32
|
dateFormat: string;
|
|
33
|
+
/** Writes the shown dates another way (as Hijri dates). Not used while typing. */
|
|
34
|
+
dateText?: DateTextFormatter;
|
|
33
35
|
timeFormat: TimeFormat;
|
|
34
36
|
yearRange?: { first: number; last: number };
|
|
35
37
|
disabled?: boolean;
|
|
@@ -45,6 +47,8 @@ interface Props {
|
|
|
45
47
|
tokens: ThemeTokens;
|
|
46
48
|
styles?: PickerStyles;
|
|
47
49
|
strings: PickerStrings;
|
|
50
|
+
/** The texts of the typed-input errors. Default `strings`. */
|
|
51
|
+
errorStrings?: PickerStrings;
|
|
48
52
|
testID?: string;
|
|
49
53
|
}
|
|
50
54
|
|
|
@@ -70,6 +74,7 @@ const RangeFields: React.FC<Props> = (props) => {
|
|
|
70
74
|
errorMessage,
|
|
71
75
|
type,
|
|
72
76
|
dateFormat,
|
|
77
|
+
dateText,
|
|
73
78
|
timeFormat,
|
|
74
79
|
yearRange,
|
|
75
80
|
disabled,
|
|
@@ -81,11 +86,13 @@ const RangeFields: React.FC<Props> = (props) => {
|
|
|
81
86
|
tokens,
|
|
82
87
|
styles,
|
|
83
88
|
strings,
|
|
89
|
+
errorStrings,
|
|
84
90
|
testID,
|
|
85
91
|
} = props;
|
|
86
92
|
const common = {
|
|
87
93
|
type,
|
|
88
94
|
dateFormat,
|
|
95
|
+
dateText,
|
|
89
96
|
timeFormat,
|
|
90
97
|
yearRange,
|
|
91
98
|
renderLabel,
|
|
@@ -94,6 +101,7 @@ const RangeFields: React.FC<Props> = (props) => {
|
|
|
94
101
|
tokens,
|
|
95
102
|
styles,
|
|
96
103
|
strings,
|
|
104
|
+
errorStrings,
|
|
97
105
|
disabled,
|
|
98
106
|
};
|
|
99
107
|
|
|
@@ -108,7 +116,9 @@ const RangeFields: React.FC<Props> = (props) => {
|
|
|
108
116
|
type,
|
|
109
117
|
dateFormat,
|
|
110
118
|
timeFormat,
|
|
111
|
-
strings.rangeSeparator
|
|
119
|
+
strings.rangeSeparator,
|
|
120
|
+
dateText,
|
|
121
|
+
strings
|
|
112
122
|
)}
|
|
113
123
|
placeholder={placeholder}
|
|
114
124
|
allowClear={allowClear}
|
|
@@ -12,10 +12,12 @@ import type {
|
|
|
12
12
|
SegmentEditorAction,
|
|
13
13
|
SegmentEditorState,
|
|
14
14
|
} from '../../core/segmentEditor';
|
|
15
|
+
import { toLatinDigits } from '../../core/digits';
|
|
15
16
|
import type { Period, SegmentKey, SegmentSpec } from '../../core/segments';
|
|
16
17
|
import type { PickerStrings } from '../theme/defaultStrings';
|
|
17
18
|
import type { PickerStyles } from '../theme/styleKeys';
|
|
18
19
|
import { MAX_FONT_SCALE } from '../theme/a11y';
|
|
20
|
+
import { useNumerals } from '../theme/numerals';
|
|
19
21
|
import type { ThemeTokens } from '../theme/tokens';
|
|
20
22
|
import { buildFieldStyles } from './fieldStyles';
|
|
21
23
|
|
|
@@ -105,6 +107,7 @@ const SegmentedInput: React.FC<Props> = ({
|
|
|
105
107
|
fieldLabel,
|
|
106
108
|
testID,
|
|
107
109
|
}) => {
|
|
110
|
+
const digits = useNumerals();
|
|
108
111
|
// Each box's text as last rendered, and as it last reported. Fast input (a
|
|
109
112
|
// hardware keyboard, autofill) sends the next character before React has
|
|
110
113
|
// re-rendered, and the native box may ignore React's reset while it's
|
|
@@ -188,7 +191,7 @@ const SegmentedInput: React.FC<Props> = ({
|
|
|
188
191
|
}}
|
|
189
192
|
testID={testID ? `${testID}-segment-${spec.key}` : undefined}
|
|
190
193
|
accessibilityLabel={labels[spec.key]}
|
|
191
|
-
value={text}
|
|
194
|
+
value={digits(text)}
|
|
192
195
|
placeholder={placeholders[spec.key]}
|
|
193
196
|
placeholderTextColor={tokens.placeholder}
|
|
194
197
|
keyboardType="number-pad"
|
|
@@ -204,8 +207,10 @@ const SegmentedInput: React.FC<Props> = ({
|
|
|
204
207
|
dispatch({ type: 'blur' });
|
|
205
208
|
}}
|
|
206
209
|
onKeyPress={onKeyPress}
|
|
207
|
-
onChangeText={(
|
|
210
|
+
onChangeText={(raw) => {
|
|
208
211
|
claimFocus();
|
|
212
|
+
// An Arabic or Persian number pad types ٠–٩ / ۰–۹.
|
|
213
|
+
const next = toLatinDigits(raw);
|
|
209
214
|
const { rendered, reported } = track;
|
|
210
215
|
const before =
|
|
211
216
|
reported !== undefined &&
|
|
@@ -287,7 +292,7 @@ const SegmentedInput: React.FC<Props> = ({
|
|
|
287
292
|
{dateSpecs.map((spec, i) => renderNumeric(spec, i))}
|
|
288
293
|
</View>
|
|
289
294
|
{timeSpecs.length ? (
|
|
290
|
-
<View style={s.segmentGroup}>
|
|
295
|
+
<View style={[s.segmentGroup, dateSpecs.length > 0 && s.segmentTime]}>
|
|
291
296
|
{timeSpecs.map((spec, i) =>
|
|
292
297
|
spec.key === 'period' ? renderPeriod() : renderNumeric(spec, i)
|
|
293
298
|
)}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useEffect, useRef, useState } from 'react';
|
|
2
|
-
import { Pressable, Text, View } from 'react-native';
|
|
2
|
+
import { Pressable, ScrollView, Text, View } from 'react-native';
|
|
3
3
|
import type { SegmentEditorAction } from '../../core/segmentEditor';
|
|
4
4
|
import type { ParsedSegments } from '../../core/segments';
|
|
5
5
|
import type { DateTimeValue, PickerType, TimeFormat } from '../../core/types';
|
|
@@ -11,19 +11,33 @@ import {
|
|
|
11
11
|
type IconSet,
|
|
12
12
|
} from '../../icons';
|
|
13
13
|
import { useTypedSegments } from '../hooks/useTypedSegments';
|
|
14
|
+
import type { ScrollViewRef } from '../nativeTypes';
|
|
14
15
|
import type { PickerStrings } from '../theme/defaultStrings';
|
|
15
16
|
import type { PickerStyles } from '../theme/styleKeys';
|
|
17
|
+
import { useNumerals } from '../theme/numerals';
|
|
16
18
|
import type { ThemeTokens } from '../theme/tokens';
|
|
17
19
|
import type { InstructionRenderProps, LabelRenderProps } from '../types';
|
|
18
20
|
import FieldMessages from './FieldMessages';
|
|
19
21
|
import {
|
|
22
|
+
formatValueParts,
|
|
20
23
|
formatValueText,
|
|
21
24
|
placeholderText,
|
|
22
25
|
segmentErrorText,
|
|
26
|
+
type DateTextFormatter,
|
|
23
27
|
} from './fieldText';
|
|
24
28
|
import { buildFieldStyles } from './fieldStyles';
|
|
25
29
|
import SegmentedInput from './SegmentedInput';
|
|
26
30
|
|
|
31
|
+
// Hebrew and Arabic letters; Arabic-Indic digits (٠–٩, ۰–۹) are left out, since
|
|
32
|
+
// digits don't set the reading direction.
|
|
33
|
+
const RTL_LETTER = '--ٟ٪-ۯۺ-ࣿ';
|
|
34
|
+
const FIRST_LETTER_RTL = new RegExp(
|
|
35
|
+
`^[^A-Za-zÀ-ɏ${RTL_LETTER}]*[${RTL_LETTER}]`
|
|
36
|
+
);
|
|
37
|
+
/** Whether a text reads right to left: its first letter is Hebrew or Arabic. */
|
|
38
|
+
export const startsRightToLeft = (text: string): boolean =>
|
|
39
|
+
FIRST_LETTER_RTL.test(text);
|
|
40
|
+
|
|
27
41
|
export interface ValueFieldProps {
|
|
28
42
|
type: PickerType;
|
|
29
43
|
/** The value to show (or to start typing from). */
|
|
@@ -32,6 +46,8 @@ export interface ValueFieldProps {
|
|
|
32
46
|
displayText?: string;
|
|
33
47
|
/** Date format, e.g. 'dd/MM/yyyy'. */
|
|
34
48
|
dateFormat: string;
|
|
49
|
+
/** Writes the shown date another way (as a Hijri date). Not used while typing. */
|
|
50
|
+
dateText?: DateTextFormatter;
|
|
35
51
|
timeFormat: TimeFormat;
|
|
36
52
|
yearRange?: { first: number; last: number };
|
|
37
53
|
/** Typed date + time segments. Otherwise the field shows text and opens the picker on tap. */
|
|
@@ -75,6 +91,8 @@ export interface ValueFieldProps {
|
|
|
75
91
|
tokens: ThemeTokens;
|
|
76
92
|
styles?: PickerStyles;
|
|
77
93
|
strings: PickerStrings;
|
|
94
|
+
/** The texts of its typed-input errors. Default `strings`. */
|
|
95
|
+
errorStrings?: PickerStrings;
|
|
78
96
|
testID?: string;
|
|
79
97
|
}
|
|
80
98
|
|
|
@@ -123,11 +141,13 @@ const DefaultInstruction: React.FC<
|
|
|
123
141
|
* results go to `onTyped`, and the sheet decides what to do with them.
|
|
124
142
|
*/
|
|
125
143
|
const ValueField: React.FC<ValueFieldProps> = (props) => {
|
|
144
|
+
const digits = useNumerals();
|
|
126
145
|
const {
|
|
127
146
|
type,
|
|
128
147
|
value,
|
|
129
148
|
displayText,
|
|
130
149
|
dateFormat,
|
|
150
|
+
dateText,
|
|
131
151
|
timeFormat,
|
|
132
152
|
yearRange,
|
|
133
153
|
allowTyping,
|
|
@@ -154,17 +174,20 @@ const ValueField: React.FC<ValueFieldProps> = (props) => {
|
|
|
154
174
|
tokens,
|
|
155
175
|
styles,
|
|
156
176
|
strings,
|
|
177
|
+
errorStrings = strings,
|
|
157
178
|
testID,
|
|
158
179
|
} = props;
|
|
159
180
|
const s = buildFieldStyles(tokens);
|
|
160
181
|
const ico = resolveIcons(iconOverrides);
|
|
182
|
+
const scrollRef = useRef<ScrollViewRef>(null);
|
|
161
183
|
const [lastParsed, setLastParsed] = useState<ParsedSegments | null>(null);
|
|
162
184
|
const { state, dispatch, getState } = useTypedSegments(
|
|
163
185
|
value,
|
|
164
186
|
{ dateFormat, type, timeFormat, yearRange },
|
|
165
|
-
(parsed) => {
|
|
187
|
+
(parsed, fromOutside) => {
|
|
166
188
|
setLastParsed(parsed);
|
|
167
|
-
|
|
189
|
+
// A value shown from outside (a calendar tap) isn't an edit.
|
|
190
|
+
if (!fromOutside) onTyped?.(parsed);
|
|
168
191
|
}
|
|
169
192
|
);
|
|
170
193
|
|
|
@@ -198,12 +221,25 @@ const ValueField: React.FC<ValueFieldProps> = (props) => {
|
|
|
198
221
|
const typing = !!allowTyping && editable;
|
|
199
222
|
const typedError =
|
|
200
223
|
typing && !state.focused && lastParsed && !lastParsed.isEmpty
|
|
201
|
-
? segmentErrorText(lastParsed.errors,
|
|
224
|
+
? segmentErrorText(lastParsed.errors, errorStrings, yearRange)
|
|
202
225
|
: '';
|
|
203
226
|
const error = typedError || errorMessage || '';
|
|
204
227
|
const hasValue = typing ? !state.parsed.isEmpty : !!value || !!displayText;
|
|
205
228
|
const text =
|
|
206
|
-
displayText ??
|
|
229
|
+
displayText ??
|
|
230
|
+
formatValueText(value, type, dateFormat, timeFormat, dateText, strings);
|
|
231
|
+
// With a fieldDateText style, a single date-time shows its date and time
|
|
232
|
+
// apart (no sideways scroll).
|
|
233
|
+
const valueParts =
|
|
234
|
+
styles?.fieldDateText && displayText === undefined && value
|
|
235
|
+
? formatValueParts(value, type, dateFormat, timeFormat, dateText, strings)
|
|
236
|
+
: null;
|
|
237
|
+
const parts = valueParts?.time ? valueParts : null;
|
|
238
|
+
const valueStyle = [
|
|
239
|
+
s.text,
|
|
240
|
+
styles?.fieldText,
|
|
241
|
+
disabled && [s.disabledText, styles?.fieldTextDisabled],
|
|
242
|
+
];
|
|
207
243
|
|
|
208
244
|
const clear = () => {
|
|
209
245
|
dispatch({ type: 'reset', value: null });
|
|
@@ -292,19 +328,59 @@ const ValueField: React.FC<ValueFieldProps> = (props) => {
|
|
|
292
328
|
onPress={onPress}
|
|
293
329
|
style={fieldStyle}
|
|
294
330
|
>
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
331
|
+
{parts ? (
|
|
332
|
+
<>
|
|
333
|
+
<Text
|
|
334
|
+
numberOfLines={1}
|
|
335
|
+
ellipsizeMode="clip"
|
|
336
|
+
style={[valueStyle, s.textScrolled, styles?.fieldDateText]}
|
|
337
|
+
>
|
|
338
|
+
{digits(`${parts.date}${strings.dateTimeSeparator ?? ' '}`)}
|
|
339
|
+
</Text>
|
|
340
|
+
<Text numberOfLines={1} ellipsizeMode="clip" style={valueStyle}>
|
|
341
|
+
{digits(parts.time)}
|
|
342
|
+
</Text>
|
|
343
|
+
</>
|
|
344
|
+
) : text ? (
|
|
345
|
+
// A value too long for the box scrolls sideways; a tap still opens.
|
|
346
|
+
<ScrollView
|
|
347
|
+
ref={scrollRef}
|
|
348
|
+
horizontal
|
|
349
|
+
showsHorizontalScrollIndicator={false}
|
|
350
|
+
keyboardShouldPersistTaps="always"
|
|
351
|
+
style={s.textScroll}
|
|
352
|
+
contentContainerStyle={s.textScrollContent}
|
|
353
|
+
// Right-to-left text (a Hijri date) starts at its right end.
|
|
354
|
+
onContentSizeChange={() => {
|
|
355
|
+
if (startsRightToLeft(text))
|
|
356
|
+
scrollRef.current?.scrollToEnd({ animated: false });
|
|
357
|
+
}}
|
|
358
|
+
>
|
|
359
|
+
<Text
|
|
360
|
+
numberOfLines={1}
|
|
361
|
+
// Android can measure a line a pixel short (right-to-left text
|
|
362
|
+
// most often) and would then swap its last word for "…".
|
|
363
|
+
ellipsizeMode="clip"
|
|
364
|
+
style={[valueStyle, s.textScrolled]}
|
|
365
|
+
>
|
|
366
|
+
{digits(text)}
|
|
367
|
+
</Text>
|
|
368
|
+
</ScrollView>
|
|
369
|
+
) : (
|
|
370
|
+
<Text
|
|
371
|
+
numberOfLines={1}
|
|
372
|
+
style={[
|
|
373
|
+
s.text,
|
|
374
|
+
styles?.fieldText,
|
|
375
|
+
s.placeholder,
|
|
376
|
+
styles?.fieldPlaceholder,
|
|
377
|
+
disabled && s.disabledText,
|
|
378
|
+
]}
|
|
379
|
+
>
|
|
380
|
+
{placeholder ||
|
|
381
|
+
placeholderText(type, dateFormat, timeFormat, strings)}
|
|
382
|
+
</Text>
|
|
383
|
+
)}
|
|
308
384
|
{icons}
|
|
309
385
|
</Pressable>
|
|
310
386
|
);
|
|
@@ -32,6 +32,10 @@ const create = (t: ThemeTokens) =>
|
|
|
32
32
|
fontSize: t.fontSizeMedium,
|
|
33
33
|
color: t.text,
|
|
34
34
|
},
|
|
35
|
+
textScroll: { flex: 1 },
|
|
36
|
+
textScrollContent: { flexGrow: 1, alignItems: 'center' },
|
|
37
|
+
// In the scroll, or as a date set apart from its time, the text keeps its full width.
|
|
38
|
+
textScrolled: { flex: 0, flexShrink: 0 },
|
|
35
39
|
placeholder: { color: t.placeholder },
|
|
36
40
|
disabledText: { color: t.disabledText },
|
|
37
41
|
icons: { flexDirection: 'row', alignItems: 'center', marginStart: 8 },
|
|
@@ -55,6 +59,8 @@ const create = (t: ThemeTokens) =>
|
|
|
55
59
|
alignItems: 'center',
|
|
56
60
|
flexWrap: 'nowrap',
|
|
57
61
|
},
|
|
62
|
+
// After a date, the time sits in the middle of the space left before the icons.
|
|
63
|
+
segmentTime: { flexGrow: 1, justifyContent: 'center' },
|
|
58
64
|
segment: {
|
|
59
65
|
paddingVertical: 8,
|
|
60
66
|
paddingHorizontal: 0,
|