@os-design/core 1.0.280 → 1.0.282
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/Avatar/utils/nameToInitials.d.ts.map +1 -1
- package/dist/Avatar/utils/strToHue.d.ts.map +1 -1
- package/dist/Button/index.d.ts.map +1 -1
- package/dist/Button/index.js +1 -1
- package/dist/Button/utils/useButtonColors.d.ts.map +1 -1
- package/dist/ButtonLink/index.d.ts.map +1 -1
- package/dist/ButtonLink/index.js +0 -5
- package/dist/Checkbox/index.d.ts.map +1 -1
- package/dist/Checkbox/index.js +1 -6
- package/dist/DateCalendar/Calendar.d.ts +25 -0
- package/dist/DateCalendar/Calendar.d.ts.map +1 -0
- package/dist/DateCalendar/Calendar.js +271 -0
- package/dist/DateCalendar/MonthPicker.d.ts +12 -0
- package/dist/DateCalendar/MonthPicker.d.ts.map +1 -0
- package/dist/DateCalendar/MonthPicker.js +159 -0
- package/dist/DateCalendar/index.d.ts +41 -0
- package/dist/DateCalendar/index.d.ts.map +1 -0
- package/dist/DateCalendar/index.js +77 -0
- package/dist/DateCalendar/locale.d.ts +6 -0
- package/dist/DateCalendar/locale.d.ts.map +1 -0
- package/dist/DateCalendar/locale.js +4 -0
- package/dist/DateCalendar/utils/calendarDays.d.ts +10 -0
- package/dist/DateCalendar/utils/calendarDays.d.ts.map +1 -0
- package/dist/DateCalendar/utils/calendarDays.js +46 -0
- package/dist/DateCalendar/utils/dayOfWeek.d.ts +8 -0
- package/dist/DateCalendar/utils/dayOfWeek.d.ts.map +1 -0
- package/dist/DateCalendar/utils/dayOfWeek.js +6 -0
- package/dist/DateCalendar/utils/daysInMonth.d.ts +7 -0
- package/dist/DateCalendar/utils/daysInMonth.d.ts.map +1 -0
- package/dist/DateCalendar/utils/daysInMonth.js +14 -0
- package/dist/DateCalendar/utils/month.d.ts +14 -0
- package/dist/DateCalendar/utils/month.d.ts.map +1 -0
- package/dist/DateCalendar/utils/month.js +24 -0
- package/dist/DateCalendar/utils/shift.d.ts +3 -0
- package/dist/DateCalendar/utils/shift.d.ts.map +1 -0
- package/dist/DateCalendar/utils/shift.js +12 -0
- package/dist/DatePicker/index.d.ts +68 -62
- package/dist/DatePicker/index.d.ts.map +1 -1
- package/dist/DatePicker/index.js +359 -265
- package/dist/DatePicker/utils/createTimes.d.ts +7 -0
- package/dist/DatePicker/utils/createTimes.d.ts.map +1 -0
- package/dist/DatePicker/utils/createTimes.js +15 -0
- package/dist/GlobalStyles/resetStyles.d.ts.map +1 -1
- package/dist/GlobalStyles/typographyStyles.d.ts.map +1 -1
- package/dist/Input/index.d.ts +15 -0
- package/dist/Input/index.d.ts.map +1 -1
- package/dist/Input/index.js +5 -5
- package/dist/Input/utils/getFocusableElements.d.ts.map +1 -1
- package/dist/InputDateUnstyled/index.d.ts +94 -0
- package/dist/InputDateUnstyled/index.d.ts.map +1 -0
- package/dist/InputDateUnstyled/index.js +406 -0
- package/dist/InputDateUnstyled/utils/convertHours.d.ts +4 -0
- package/dist/InputDateUnstyled/utils/convertHours.d.ts.map +1 -0
- package/dist/InputDateUnstyled/utils/convertHours.js +12 -0
- package/dist/InputDateUnstyled/utils/convertToFullYear.d.ts +3 -0
- package/dist/InputDateUnstyled/utils/convertToFullYear.d.ts.map +1 -0
- package/dist/InputDateUnstyled/utils/convertToFullYear.js +10 -0
- package/dist/InputDateUnstyled/utils/dateToString.d.ts +3 -0
- package/dist/InputDateUnstyled/utils/dateToString.d.ts.map +1 -0
- package/dist/InputDateUnstyled/utils/dateToString.js +10 -0
- package/dist/InputDateUnstyled/utils/daysInMonth.d.ts +7 -0
- package/dist/InputDateUnstyled/utils/daysInMonth.d.ts.map +1 -0
- package/dist/InputDateUnstyled/utils/daysInMonth.js +14 -0
- package/dist/InputDateUnstyled/utils/ensureCaretVisible.d.ts +3 -0
- package/dist/InputDateUnstyled/utils/ensureCaretVisible.d.ts.map +1 -0
- package/dist/InputDateUnstyled/utils/ensureCaretVisible.js +32 -0
- package/dist/InputDateUnstyled/utils/eraseSelectedTokens.d.ts +10 -0
- package/dist/InputDateUnstyled/utils/eraseSelectedTokens.d.ts.map +1 -0
- package/dist/InputDateUnstyled/utils/eraseSelectedTokens.js +29 -0
- package/dist/InputDateUnstyled/utils/replaceSubstring.d.ts +3 -0
- package/dist/InputDateUnstyled/utils/replaceSubstring.d.ts.map +1 -0
- package/dist/InputDateUnstyled/utils/replaceSubstring.js +9 -0
- package/dist/InputDateUnstyled/utils/same.d.ts +6 -0
- package/dist/InputDateUnstyled/utils/same.d.ts.map +1 -0
- package/dist/InputDateUnstyled/utils/same.js +3 -0
- package/dist/InputDateUnstyled/utils/stringToDay.d.ts +12 -0
- package/dist/InputDateUnstyled/utils/stringToDay.d.ts.map +1 -0
- package/dist/InputDateUnstyled/utils/stringToDay.js +55 -0
- package/dist/InputDateUnstyled/utils/stringToTime.d.ts +7 -0
- package/dist/InputDateUnstyled/utils/stringToTime.d.ts.map +1 -0
- package/dist/InputDateUnstyled/utils/stringToTime.js +40 -0
- package/dist/InputDateUnstyled/utils/token.d.ts +9 -0
- package/dist/InputDateUnstyled/utils/token.d.ts.map +1 -0
- package/dist/InputDateUnstyled/utils/token.js +66 -0
- package/dist/Link/index.d.ts.map +1 -1
- package/dist/Link/index.js +3 -8
- package/dist/LinkButton/index.d.ts.map +1 -1
- package/dist/LinkButton/index.js +0 -5
- package/dist/List/utils/bodyPointerEvents.d.ts.map +1 -1
- package/dist/List/utils/frameTimeout.d.ts.map +1 -1
- package/dist/List/utils/useRWLoadNext.d.ts.map +1 -1
- package/dist/LogoLink/index.d.ts.map +1 -1
- package/dist/LogoLink/index.js +1 -6
- package/dist/Menu/utils/useFocusWithArrows.d.ts.map +1 -1
- package/dist/Modal/index.d.ts +5 -0
- package/dist/Modal/index.d.ts.map +1 -1
- package/dist/Modal/index.js +53 -48
- package/dist/Navigation/utils/useScrollFlags.d.ts.map +1 -1
- package/dist/NavigationItem/index.d.ts.map +1 -1
- package/dist/NavigationItem/index.js +1 -6
- package/dist/Popover/utils/usePopoverPosition.d.ts.map +1 -1
- package/dist/ScrollButton/utils/useContainerPosition.d.ts.map +1 -1
- package/dist/ScrollButton/utils/useVisibility.d.ts.map +1 -1
- package/dist/Select/index.d.ts.map +1 -1
- package/dist/Select/index.js +2 -3
- package/dist/Switch/index.d.ts.map +1 -1
- package/dist/Switch/index.js +1 -7
- package/dist/TagLink/index.d.ts.map +1 -1
- package/dist/TagLink/index.js +1 -6
- package/dist/TimeGrid/index.d.ts +63 -0
- package/dist/TimeGrid/index.d.ts.map +1 -0
- package/dist/TimeGrid/index.js +111 -0
- package/dist/TimeGrid/utils/convertHours.d.ts +4 -0
- package/dist/TimeGrid/utils/convertHours.d.ts.map +1 -0
- package/dist/TimeGrid/utils/convertHours.js +12 -0
- package/dist/TimeGrid/utils/createTimes.d.ts +7 -0
- package/dist/TimeGrid/utils/createTimes.d.ts.map +1 -0
- package/dist/TimeGrid/utils/createTimes.js +15 -0
- package/dist/TimeGrid/utils/timeToString.d.ts +4 -0
- package/dist/TimeGrid/utils/timeToString.d.ts.map +1 -0
- package/dist/TimeGrid/utils/timeToString.js +12 -0
- package/dist/TimeGridSkeleton/index.d.ts +18 -0
- package/dist/TimeGridSkeleton/index.d.ts.map +1 -0
- package/dist/TimeGridSkeleton/index.js +33 -0
- package/dist/TimeList/index.d.ts +45 -0
- package/dist/TimeList/index.d.ts.map +1 -0
- package/dist/TimeList/index.js +80 -0
- package/dist/TimeList/utils/convertHours.d.ts +4 -0
- package/dist/TimeList/utils/convertHours.d.ts.map +1 -0
- package/dist/TimeList/utils/convertHours.js +12 -0
- package/dist/TimeList/utils/createTimes.d.ts +7 -0
- package/dist/TimeList/utils/createTimes.d.ts.map +1 -0
- package/dist/TimeList/utils/createTimes.js +15 -0
- package/dist/TimeList/utils/timeToString.d.ts +4 -0
- package/dist/TimeList/utils/timeToString.d.ts.map +1 -0
- package/dist/TimeList/utils/timeToString.js +12 -0
- package/dist/TimeListSkeleton/index.d.ts +13 -0
- package/dist/TimeListSkeleton/index.d.ts.map +1 -0
- package/dist/TimeListSkeleton/index.js +30 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -0
- package/dist/message/styles.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/Button/index.tsx +1 -1
- package/src/ButtonLink/index.tsx +0 -5
- package/src/Checkbox/index.tsx +1 -6
- package/src/DateCalendar/Calendar.tsx +400 -0
- package/src/DateCalendar/MonthPicker.tsx +212 -0
- package/src/DateCalendar/index.tsx +135 -0
- package/src/DateCalendar/locale.ts +22 -0
- package/src/DateCalendar/utils/calendarDays.ts +61 -0
- package/src/DateCalendar/utils/dayOfWeek.ts +14 -0
- package/src/DateCalendar/utils/daysInMonth.ts +22 -0
- package/src/DateCalendar/utils/month.ts +30 -0
- package/src/DateCalendar/utils/shift.ts +14 -0
- package/src/DatePicker/index.tsx +506 -417
- package/src/DatePicker/utils/createTimes.ts +20 -0
- package/src/Input/index.tsx +11 -8
- package/src/InputDateUnstyled/index.tsx +533 -0
- package/src/InputDateUnstyled/utils/convertHours.ts +15 -0
- package/src/InputDateUnstyled/utils/convertToFullYear.ts +11 -0
- package/src/InputDateUnstyled/utils/dateToString.ts +21 -0
- package/src/InputDateUnstyled/utils/daysInMonth.ts +22 -0
- package/src/InputDateUnstyled/utils/ensureCaretVisible.ts +37 -0
- package/src/InputDateUnstyled/utils/eraseSelectedTokens.ts +38 -0
- package/src/InputDateUnstyled/utils/replaceSubstring.ts +10 -0
- package/src/InputDateUnstyled/utils/same.ts +15 -0
- package/src/InputDateUnstyled/utils/stringToDay.ts +69 -0
- package/src/InputDateUnstyled/utils/stringToTime.ts +48 -0
- package/src/InputDateUnstyled/utils/token.ts +102 -0
- package/src/Link/index.tsx +5 -25
- package/src/LinkButton/index.tsx +2 -15
- package/src/LogoLink/index.tsx +2 -6
- package/src/Modal/index.tsx +71 -60
- package/src/NavigationItem/index.tsx +2 -16
- package/src/Select/index.tsx +2 -3
- package/src/Switch/index.tsx +1 -11
- package/src/TagLink/index.tsx +3 -11
- package/src/TimeGrid/index.tsx +189 -0
- package/src/TimeGrid/utils/convertHours.ts +15 -0
- package/src/TimeGrid/utils/createTimes.ts +20 -0
- package/src/TimeGrid/utils/timeToString.ts +17 -0
- package/src/TimeGridSkeleton/index.tsx +50 -0
- package/src/TimeList/index.tsx +135 -0
- package/src/TimeList/utils/convertHours.ts +15 -0
- package/src/TimeList/utils/createTimes.ts +20 -0
- package/src/TimeList/utils/timeToString.ts +17 -0
- package/src/TimeListSkeleton/index.tsx +44 -0
- package/src/index.ts +12 -0
- package/dist/DatePicker/DatePickerCalendar.d.ts +0 -11
- package/dist/DatePicker/DatePickerCalendar.d.ts.map +0 -1
- package/dist/DatePicker/DatePickerCalendar.js +0 -178
- package/dist/TimePicker/index.d.ts +0 -29
- package/dist/TimePicker/index.d.ts.map +0 -1
- package/dist/TimePicker/index.js +0 -100
- package/src/DatePicker/DatePickerCalendar.tsx +0 -230
- package/src/TimePicker/index.tsx +0 -144
package/src/DatePicker/index.tsx
CHANGED
|
@@ -1,569 +1,658 @@
|
|
|
1
|
-
import styled from '@emotion/styled';
|
|
2
|
-
import {
|
|
3
|
-
type DatePickerLocale,
|
|
4
|
-
defaultLocale,
|
|
5
|
-
getAccessibilityDateLabel,
|
|
6
|
-
useFormattedValue,
|
|
7
|
-
isSameDay,
|
|
8
|
-
} from '@os-design/date-picker-utils';
|
|
9
|
-
import { Down, Up } from '@os-design/icons';
|
|
10
1
|
import { useIsMinWidth } from '@os-design/media';
|
|
11
|
-
import type { WithSize } from '@os-design/styles';
|
|
12
|
-
import { ThemeOverrider } from '@os-design/theming';
|
|
13
2
|
import {
|
|
3
|
+
enableScrollingStyles,
|
|
4
|
+
resetFocusStyles,
|
|
5
|
+
type WithSize,
|
|
6
|
+
} from '@os-design/styles';
|
|
7
|
+
import {
|
|
8
|
+
omitEmotionProps,
|
|
14
9
|
useForwardedRef,
|
|
15
10
|
useForwardedState,
|
|
16
|
-
useKeyPress,
|
|
17
11
|
} from '@os-design/utils';
|
|
18
|
-
import
|
|
12
|
+
import {
|
|
19
13
|
forwardRef,
|
|
20
14
|
useCallback,
|
|
21
15
|
useEffect,
|
|
22
16
|
useMemo,
|
|
23
17
|
useRef,
|
|
24
18
|
useState,
|
|
19
|
+
type FocusEvent,
|
|
20
|
+
type ForwardedRef,
|
|
21
|
+
type MouseEvent,
|
|
25
22
|
} from 'react';
|
|
26
|
-
import Button from '../Button/index.js';
|
|
27
23
|
import Modal from '../Modal/index.js';
|
|
24
|
+
import { type DateCalendarLocale } from '../DateCalendar/locale.js';
|
|
25
|
+
import type { Day, Month } from '../DateCalendar/utils/calendarDays.js';
|
|
26
|
+
import InputDateUnstyled, {
|
|
27
|
+
convertTo12hours,
|
|
28
|
+
nextToken,
|
|
29
|
+
replaceSubstring,
|
|
30
|
+
tokens,
|
|
31
|
+
type OnDayError,
|
|
32
|
+
type Time,
|
|
33
|
+
type Token,
|
|
34
|
+
} from '../InputDateUnstyled/index.js';
|
|
35
|
+
import DateCalendar from '../DateCalendar/index.js';
|
|
36
|
+
import TimeGrid from '../TimeGrid/index.js';
|
|
37
|
+
import styled from '@emotion/styled';
|
|
28
38
|
import Popover from '../Popover/index.js';
|
|
29
|
-
import
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
ToggleRightAddon,
|
|
38
|
-
} from '../Select/index.js';
|
|
39
|
-
import TimePicker from '../TimePicker/index.js';
|
|
40
|
-
import DatePickerCalendar from './DatePickerCalendar.js';
|
|
39
|
+
import Button from '../Button/index.js';
|
|
40
|
+
import { Calendar } from '@os-design/icons';
|
|
41
|
+
import { InputContainer, TimeGridSkeleton } from '../index.js';
|
|
42
|
+
import { clr, ThemeOverrider } from '@os-design/theming';
|
|
43
|
+
import { css } from '@emotion/react';
|
|
44
|
+
import createTimes from './utils/createTimes.js';
|
|
45
|
+
|
|
46
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
41
47
|
|
|
42
48
|
type JsxDivProps = Omit<
|
|
43
49
|
JSX.IntrinsicElements['div'],
|
|
44
50
|
'value' | 'defaultValue' | 'onChange' | 'ref'
|
|
45
51
|
>;
|
|
46
|
-
interface
|
|
52
|
+
export interface DatePickerProps extends JsxDivProps, WithSize {
|
|
47
53
|
/**
|
|
48
|
-
* The
|
|
49
|
-
*
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
54
|
+
* The string format. Supported tokens:
|
|
55
|
+
* `DD` - The day of the month (01-31).
|
|
56
|
+
* `MM` - The month (01-12).
|
|
57
|
+
* `YYYY` - Four-digit year (2025).
|
|
58
|
+
* `YY` - Two-digit year (25).
|
|
59
|
+
* `hh` - The hour, 12-hour clock (01-12).
|
|
60
|
+
* `HH` - The hour, 24-hour clock (00-23).
|
|
61
|
+
* `mm` - The minute (00-59).
|
|
62
|
+
* `aa` - The meridiem (am, pm).
|
|
63
|
+
* @default `DD.MM.YYYY`
|
|
56
64
|
*/
|
|
57
|
-
|
|
65
|
+
format?: string;
|
|
58
66
|
/**
|
|
59
|
-
*
|
|
60
|
-
* @default
|
|
67
|
+
* First day of week (0 - Sunday).
|
|
68
|
+
* @default 0
|
|
61
69
|
*/
|
|
62
|
-
|
|
70
|
+
firstDayOfWeek?: number;
|
|
63
71
|
/**
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* @default false
|
|
72
|
+
* Times shown in the list in minutes (600 is 10:00).
|
|
73
|
+
* @default []
|
|
67
74
|
*/
|
|
68
|
-
|
|
75
|
+
times?: Time[];
|
|
69
76
|
/**
|
|
70
|
-
*
|
|
71
|
-
* @default
|
|
77
|
+
* Number of columns where the times are shown.
|
|
78
|
+
* @default 3
|
|
72
79
|
*/
|
|
73
|
-
|
|
80
|
+
timeColumns?: number;
|
|
74
81
|
/**
|
|
75
82
|
* Whether the date picker is disabled.
|
|
76
83
|
* @default false
|
|
77
84
|
*/
|
|
78
85
|
disabled?: boolean;
|
|
79
86
|
/**
|
|
80
|
-
*
|
|
81
|
-
* @default
|
|
87
|
+
* What days are not allowed to choose in the selected month.
|
|
88
|
+
* @default undefined
|
|
82
89
|
*/
|
|
83
|
-
|
|
90
|
+
disabledDays?: (month: Month) => number[] | Promise<number[]>;
|
|
84
91
|
/**
|
|
85
|
-
*
|
|
86
|
-
* @default
|
|
92
|
+
* What times are not allowed to choose in the selected day.
|
|
93
|
+
* @default undefined
|
|
87
94
|
*/
|
|
88
|
-
|
|
95
|
+
disabledTimes?: (day: Day) => Time[] | Promise<Time[]>;
|
|
89
96
|
/**
|
|
90
|
-
* The
|
|
97
|
+
* The locale.
|
|
91
98
|
* @default undefined
|
|
92
99
|
*/
|
|
93
|
-
|
|
100
|
+
locale?: DateCalendarLocale;
|
|
94
101
|
/**
|
|
95
|
-
*
|
|
96
|
-
*
|
|
102
|
+
* Whether to show the calendar and time picker.
|
|
103
|
+
* When autoOpen is false, there is a button on the right side. When
|
|
104
|
+
* the user clicks on it, the calendar/time picker is shown. This button
|
|
105
|
+
* is hidden when autoOpen is true on the wide screens.
|
|
106
|
+
* @default false
|
|
97
107
|
*/
|
|
98
|
-
|
|
108
|
+
showPicker?: boolean;
|
|
99
109
|
/**
|
|
100
|
-
*
|
|
101
|
-
* @default
|
|
110
|
+
* Whether the calendar and time picker is opened automatically.
|
|
111
|
+
* @default false
|
|
102
112
|
*/
|
|
103
|
-
|
|
113
|
+
autoOpen?: boolean;
|
|
104
114
|
/**
|
|
105
|
-
*
|
|
106
|
-
* @default
|
|
115
|
+
* The ref of the input container.
|
|
116
|
+
* @default undefined
|
|
107
117
|
*/
|
|
108
|
-
|
|
118
|
+
containerRef?: ForwardedRef<HTMLDivElement>;
|
|
109
119
|
/**
|
|
110
|
-
* The
|
|
111
|
-
* @default
|
|
120
|
+
* The props of the input container.
|
|
121
|
+
* @default undefined
|
|
112
122
|
*/
|
|
113
|
-
|
|
123
|
+
containerProps?: JSX.IntrinsicElements['div'];
|
|
114
124
|
/**
|
|
115
|
-
*
|
|
125
|
+
* The selected date.
|
|
116
126
|
* @default undefined
|
|
117
127
|
*/
|
|
118
|
-
value?:
|
|
128
|
+
value?: Date | null;
|
|
119
129
|
/**
|
|
120
130
|
* The default value.
|
|
121
131
|
* @default undefined
|
|
122
132
|
*/
|
|
123
|
-
defaultValue?:
|
|
133
|
+
defaultValue?: Date | null;
|
|
124
134
|
/**
|
|
125
135
|
* The change event handler.
|
|
126
136
|
* @default undefined
|
|
127
137
|
*/
|
|
128
|
-
onChange?: (value:
|
|
138
|
+
onChange?: (value: Date | null) => void;
|
|
129
139
|
/**
|
|
130
|
-
* The
|
|
140
|
+
* The callback called when the day is changed.
|
|
131
141
|
* @default undefined
|
|
132
142
|
*/
|
|
133
|
-
|
|
134
|
-
}
|
|
135
|
-
export interface DateNotRangePickerProps extends BaseDatePickerProps<Date> {
|
|
143
|
+
onDayChange?: (value: Day) => void;
|
|
136
144
|
/**
|
|
137
|
-
*
|
|
138
|
-
* @default
|
|
145
|
+
* The callback called when the time is changed.
|
|
146
|
+
* @default undefined
|
|
139
147
|
*/
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
export interface DateRangePickerProps
|
|
143
|
-
extends BaseDatePickerProps<[Date, Date]> {
|
|
148
|
+
onTimeChange?: (value: Time) => void;
|
|
144
149
|
/**
|
|
145
|
-
*
|
|
146
|
-
* @default
|
|
150
|
+
* The error handler called when the day has been entered incorrectly.
|
|
151
|
+
* @default undefined
|
|
147
152
|
*/
|
|
148
|
-
|
|
153
|
+
onDayError?: OnDayError;
|
|
154
|
+
/**
|
|
155
|
+
* The callback called when the caret has been moved to the end.
|
|
156
|
+
* @default undefined
|
|
157
|
+
*/
|
|
158
|
+
onEnd?: () => void;
|
|
149
159
|
}
|
|
150
|
-
export type DatePickerProps = DateNotRangePickerProps | DateRangePickerProps;
|
|
151
160
|
|
|
152
|
-
|
|
153
|
-
|
|
161
|
+
type PickerType = 'date' | 'time';
|
|
162
|
+
|
|
163
|
+
const dateTokens = ['DD', 'MM', 'YYYY', 'YY'] as const;
|
|
164
|
+
const timeTokens = ['hh', 'HH', 'mm', 'aa'] as const;
|
|
165
|
+
|
|
166
|
+
type DateToken = (typeof dateTokens)[number];
|
|
167
|
+
type TimeToken = (typeof timeTokens)[number];
|
|
168
|
+
|
|
169
|
+
type TokenGetterMap = {
|
|
170
|
+
[P in Token]: (
|
|
171
|
+
value: P extends DateToken ? Day : P extends TimeToken ? Time : unknown
|
|
172
|
+
) => string;
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const tokenGetterMap: TokenGetterMap = {
|
|
176
|
+
DD: ({ day }) => day.toString().padStart(2, '0'),
|
|
177
|
+
MM: ({ month }) => (month + 1).toString().padStart(2, '0'),
|
|
178
|
+
YYYY: ({ year }) => year.toString(),
|
|
179
|
+
YY: ({ year }) => year.toString().slice(2, 4),
|
|
180
|
+
hh: ({ hour }) => {
|
|
181
|
+
const [h] = convertTo12hours(hour);
|
|
182
|
+
return h.toString().padStart(2, '0');
|
|
183
|
+
},
|
|
184
|
+
HH: ({ hour }) => hour.toString().padStart(2, '0'),
|
|
185
|
+
mm: ({ minute }) => minute.toString().padStart(2, '0'),
|
|
186
|
+
aa: ({ hour }) => {
|
|
187
|
+
const [, meridiem] = convertTo12hours(hour);
|
|
188
|
+
return meridiem;
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
const getPickerType = (token: Token) => {
|
|
193
|
+
if (dateTokens.includes(token as any)) {
|
|
194
|
+
return 'date';
|
|
195
|
+
}
|
|
196
|
+
if (timeTokens.includes(token as any)) {
|
|
197
|
+
return 'time';
|
|
198
|
+
}
|
|
199
|
+
return null;
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const getNextTokenDiffType = (startPos: number, format: string) => {
|
|
203
|
+
const current = nextToken(startPos, format, tokens);
|
|
204
|
+
if (!current) return null;
|
|
205
|
+
|
|
206
|
+
const currentType = getPickerType(current.token);
|
|
207
|
+
let pos = current.end;
|
|
208
|
+
|
|
209
|
+
while (pos < format.length) {
|
|
210
|
+
const next = nextToken(pos, format, tokens);
|
|
211
|
+
if (!next) return null;
|
|
212
|
+
const nextType = getPickerType(next.token);
|
|
213
|
+
if (nextType !== currentType) return next;
|
|
214
|
+
pos = next.end;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return null;
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
const preventDefault = (e: MouseEvent) => e.preventDefault();
|
|
221
|
+
|
|
222
|
+
const notHasRightStyles = (p) =>
|
|
223
|
+
!p.hasRight &&
|
|
224
|
+
css`
|
|
225
|
+
padding-right: ${p.theme.inputPaddingHorizontal}em;
|
|
226
|
+
`;
|
|
227
|
+
|
|
228
|
+
const hideSpinButton = css`
|
|
229
|
+
/* Chrome, Safari, Edge, Opera */
|
|
230
|
+
&::-webkit-outer-spin-button,
|
|
231
|
+
&::-webkit-inner-spin-button {
|
|
232
|
+
-webkit-appearance: none;
|
|
233
|
+
margin: 0;
|
|
234
|
+
}
|
|
235
|
+
/* Firefox */
|
|
236
|
+
appearance: textfield;
|
|
154
237
|
`;
|
|
155
238
|
|
|
156
|
-
|
|
239
|
+
interface StyledInputDateUnstyledProps {
|
|
240
|
+
hasRight?: boolean;
|
|
241
|
+
}
|
|
242
|
+
const StyledInputDateUnstyled = styled(
|
|
243
|
+
InputDateUnstyled,
|
|
244
|
+
omitEmotionProps('hasRight')
|
|
245
|
+
)<StyledInputDateUnstyledProps>`
|
|
246
|
+
${resetFocusStyles};
|
|
247
|
+
border: none;
|
|
248
|
+
font-size: 1em;
|
|
249
|
+
flex: 1;
|
|
250
|
+
width: 100%;
|
|
251
|
+
overflow: hidden;
|
|
252
|
+
|
|
253
|
+
color: ${(p) => clr(p.theme.inputColorText)};
|
|
254
|
+
background-color: transparent;
|
|
255
|
+
padding-left: ${(p) => p.theme.inputPaddingHorizontal}em;
|
|
256
|
+
|
|
257
|
+
&::placeholder {
|
|
258
|
+
color: ${(p) => clr(p.theme.inputColorPlaceholder)};
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
${hideSpinButton};
|
|
262
|
+
${notHasRightStyles};
|
|
263
|
+
`;
|
|
264
|
+
|
|
265
|
+
const PickerButtonContainer = styled.div`
|
|
157
266
|
display: flex;
|
|
158
|
-
|
|
159
|
-
margin-top: 0.5em;
|
|
267
|
+
align-items: center;
|
|
160
268
|
`;
|
|
161
269
|
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
270
|
+
const PADDING_EM = 0.8;
|
|
271
|
+
|
|
272
|
+
const StyledPopover = styled(Popover)`
|
|
273
|
+
padding: ${PADDING_EM}em;
|
|
274
|
+
width: ${(p) => p.theme.dateCalendarCellSize * 7 + PADDING_EM * 2}em;
|
|
275
|
+
max-height: ${(p) =>
|
|
276
|
+
p.theme.baseHeight * p.theme.sizes.small +
|
|
277
|
+
0.5 +
|
|
278
|
+
p.theme.dateCalendarCellSize * 7}em;
|
|
279
|
+
${enableScrollingStyles('y')};
|
|
165
280
|
`;
|
|
166
281
|
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
text-align: center;
|
|
282
|
+
const StyledModal = styled(Modal)`
|
|
283
|
+
padding: ${PADDING_EM}em;
|
|
170
284
|
`;
|
|
171
285
|
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
d.setHours(time.getHours());
|
|
183
|
-
d.setMinutes(time.getMinutes());
|
|
184
|
-
}
|
|
185
|
-
return d;
|
|
186
|
-
};
|
|
286
|
+
const defaultTimes = createTimes(
|
|
287
|
+
{ hour: 9, minute: 0 },
|
|
288
|
+
{ hour: 18, minute: 0 },
|
|
289
|
+
30
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
interface Selection {
|
|
293
|
+
start: number;
|
|
294
|
+
end: number;
|
|
295
|
+
}
|
|
187
296
|
|
|
188
297
|
/**
|
|
189
|
-
* The component to choose a date.
|
|
298
|
+
* The component to enter or choose a date/time.
|
|
190
299
|
*/
|
|
191
|
-
const DatePicker = forwardRef<
|
|
300
|
+
const DatePicker = forwardRef<HTMLInputElement, DatePickerProps>(
|
|
192
301
|
(
|
|
193
302
|
{
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
placeholder,
|
|
303
|
+
format = 'DD.MM.YYYY',
|
|
304
|
+
firstDayOfWeek = 0,
|
|
305
|
+
times = defaultTimes,
|
|
306
|
+
timeColumns = 3,
|
|
199
307
|
disabled = false,
|
|
200
|
-
|
|
308
|
+
disabledDays,
|
|
309
|
+
disabledTimes: disabledTimesFn,
|
|
310
|
+
locale,
|
|
311
|
+
showPicker = false,
|
|
201
312
|
autoOpen = false,
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
locale = defaultLocale,
|
|
205
|
-
showTime = false,
|
|
206
|
-
timeNotation = '12-hour',
|
|
207
|
-
range = false,
|
|
313
|
+
containerRef,
|
|
314
|
+
containerProps = {},
|
|
208
315
|
value,
|
|
209
316
|
defaultValue,
|
|
210
317
|
onChange,
|
|
211
|
-
|
|
318
|
+
onDayChange = () => {},
|
|
319
|
+
onTimeChange = () => {},
|
|
320
|
+
onDayError,
|
|
321
|
+
onFocus = () => {},
|
|
212
322
|
onBlur = () => {},
|
|
323
|
+
onEnd = () => {},
|
|
213
324
|
size,
|
|
214
325
|
...rest
|
|
215
326
|
},
|
|
216
327
|
ref
|
|
217
328
|
) => {
|
|
218
|
-
const [
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
const [
|
|
329
|
+
const [innerContainerRef, mergedContainerRef] =
|
|
330
|
+
useForwardedRef(containerRef);
|
|
331
|
+
const [innerInputRef, mergedInputRef] = useForwardedRef(ref);
|
|
332
|
+
const [inputValue, setInputValue] = useState<string | undefined>(undefined);
|
|
333
|
+
const [inputSelection, setInputSelection] = useState<Selection>({
|
|
334
|
+
start: 0,
|
|
335
|
+
end: 0,
|
|
336
|
+
});
|
|
337
|
+
const [inputFocused, setInputFocused] = useState(false);
|
|
338
|
+
const [forwardedValue, setForwardedValue] = useForwardedState({
|
|
222
339
|
value,
|
|
223
340
|
defaultValue,
|
|
224
341
|
onChange,
|
|
225
342
|
});
|
|
226
343
|
|
|
344
|
+
const [pickerType, setPickerType] = useState<PickerType>('date');
|
|
345
|
+
const [pickerVisibility, setPickerVisibility] = useState(false);
|
|
346
|
+
|
|
347
|
+
const [day, setDay] = useState<Day | null>(null);
|
|
348
|
+
const [time, setTime] = useState<Time | null>(null);
|
|
349
|
+
|
|
350
|
+
const [loadingTimes, setLoadingTimes] = useState(false);
|
|
351
|
+
const [disabledTimes, setDisabledTimes] = useState<Time[]>([]);
|
|
352
|
+
|
|
353
|
+
const inputValueRef = useRef(inputValue);
|
|
354
|
+
useEffect(() => {
|
|
355
|
+
inputValueRef.current = inputValue;
|
|
356
|
+
}, [inputValue]);
|
|
357
|
+
|
|
358
|
+
const inputSelectionRef = useRef(inputSelection);
|
|
359
|
+
useEffect(() => {
|
|
360
|
+
inputSelectionRef.current = inputSelection;
|
|
361
|
+
}, [inputSelection]);
|
|
362
|
+
|
|
363
|
+
const forwardedValueRef = useRef(forwardedValue);
|
|
364
|
+
useEffect(() => {
|
|
365
|
+
forwardedValueRef.current = forwardedValue;
|
|
366
|
+
}, [forwardedValue]);
|
|
367
|
+
|
|
368
|
+
const formatRef = useRef(format);
|
|
369
|
+
useEffect(() => {
|
|
370
|
+
formatRef.current = format;
|
|
371
|
+
}, [format]);
|
|
372
|
+
|
|
227
373
|
useEffect(() => {
|
|
228
|
-
if (
|
|
229
|
-
}, [
|
|
374
|
+
if (day) onDayChange(day);
|
|
375
|
+
}, [day, onDayChange]);
|
|
230
376
|
|
|
231
|
-
const onCloseRef = useRef(onClose);
|
|
232
377
|
useEffect(() => {
|
|
233
|
-
|
|
234
|
-
}, [
|
|
378
|
+
if (time) onTimeChange(time);
|
|
379
|
+
}, [time, onTimeChange]);
|
|
235
380
|
|
|
236
381
|
useEffect(() => {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
382
|
+
const { start, end } = inputSelection;
|
|
383
|
+
if (end === start && end === format.length) {
|
|
384
|
+
onEnd();
|
|
240
385
|
}
|
|
241
|
-
}, [
|
|
386
|
+
}, [format.length, inputSelection, onEnd]);
|
|
242
387
|
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
388
|
+
const isMinXs = useIsMinWidth('xs');
|
|
389
|
+
|
|
390
|
+
// Set the input focus
|
|
391
|
+
useEffect(() => {
|
|
392
|
+
if (!innerInputRef.current) return;
|
|
393
|
+
if (inputFocused) {
|
|
394
|
+
innerInputRef.current.focus();
|
|
395
|
+
} else {
|
|
396
|
+
innerInputRef.current.blur();
|
|
397
|
+
}
|
|
398
|
+
}, [innerInputRef, inputFocused]);
|
|
399
|
+
|
|
400
|
+
// Open the picker automatically
|
|
401
|
+
useEffect(() => {
|
|
402
|
+
let pickerType: PickerType | null = null;
|
|
403
|
+
|
|
404
|
+
// Find the nearest token from the current caret position
|
|
405
|
+
const next = nextToken(inputSelection.start, formatRef.current, tokens);
|
|
406
|
+
|
|
407
|
+
if (next) {
|
|
408
|
+
if (dateTokens.includes(next.token as any)) {
|
|
409
|
+
pickerType = 'date';
|
|
410
|
+
}
|
|
411
|
+
if (timeTokens.includes(next.token as any)) {
|
|
412
|
+
pickerType = 'time';
|
|
413
|
+
}
|
|
414
|
+
}
|
|
249
415
|
|
|
250
|
-
|
|
251
|
-
|
|
416
|
+
if (pickerType && inputFocused) {
|
|
417
|
+
setPickerType(pickerType);
|
|
418
|
+
if (showPicker && autoOpen && isMinXs) {
|
|
419
|
+
setPickerVisibility(true);
|
|
420
|
+
}
|
|
421
|
+
} else {
|
|
422
|
+
setPickerVisibility(false);
|
|
423
|
+
}
|
|
424
|
+
}, [autoOpen, inputFocused, inputSelection.start, isMinXs, showPicker]);
|
|
425
|
+
|
|
426
|
+
const moveCaretToNextTokenDiffType = useCallback((pos: number) => {
|
|
427
|
+
const nextTokenDiffType = getNextTokenDiffType(pos, formatRef.current);
|
|
428
|
+
const nextPos = nextTokenDiffType
|
|
429
|
+
? nextTokenDiffType.pos
|
|
430
|
+
: formatRef.current.length;
|
|
431
|
+
|
|
432
|
+
setInputSelection({ start: nextPos, end: nextPos });
|
|
252
433
|
}, []);
|
|
253
434
|
|
|
254
|
-
|
|
255
|
-
(typeof
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
435
|
+
const changeHandler = useCallback(
|
|
436
|
+
(tokens: typeof dateTokens | typeof timeTokens, value: any) => {
|
|
437
|
+
if (!inputValueRef.current || value === null) return;
|
|
438
|
+
|
|
439
|
+
const start = inputSelectionRef.current.start;
|
|
440
|
+
|
|
441
|
+
let nextValue = inputValueRef.current;
|
|
442
|
+
tokens.forEach((token) => {
|
|
443
|
+
const tokenIndex = formatRef.current.indexOf(token);
|
|
444
|
+
if (tokenIndex >= 0) {
|
|
445
|
+
nextValue = replaceSubstring(
|
|
446
|
+
nextValue,
|
|
447
|
+
tokenIndex,
|
|
448
|
+
'_'.repeat(token.length)
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
tokens.forEach((token) => {
|
|
453
|
+
const tokenIndex = formatRef.current.indexOf(token);
|
|
454
|
+
if (
|
|
455
|
+
tokenIndex >= 0 &&
|
|
456
|
+
tokenGetterMap[token] &&
|
|
457
|
+
nextValue[tokenIndex] === '_'
|
|
458
|
+
) {
|
|
459
|
+
nextValue = replaceSubstring(
|
|
460
|
+
nextValue,
|
|
461
|
+
tokenIndex,
|
|
462
|
+
tokenGetterMap[token](value)
|
|
463
|
+
);
|
|
464
|
+
}
|
|
465
|
+
});
|
|
260
466
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
if (!opened) onBlur(e);
|
|
467
|
+
setInputValue(nextValue);
|
|
468
|
+
moveCaretToNextTokenDiffType(start);
|
|
264
469
|
},
|
|
265
|
-
[
|
|
470
|
+
[moveCaretToNextTokenDiffType]
|
|
266
471
|
);
|
|
267
472
|
|
|
268
|
-
const
|
|
269
|
-
(
|
|
270
|
-
|
|
473
|
+
const dateChangeHandler = useCallback(
|
|
474
|
+
(day: Day | null) => {
|
|
475
|
+
changeHandler(dateTokens, day);
|
|
476
|
+
setDay(day);
|
|
477
|
+
},
|
|
478
|
+
[changeHandler]
|
|
479
|
+
);
|
|
480
|
+
const timeChangeHandler = useCallback(
|
|
481
|
+
(time: Time | null) => changeHandler(timeTokens, time),
|
|
482
|
+
[changeHandler]
|
|
271
483
|
);
|
|
272
484
|
|
|
273
|
-
const
|
|
274
|
-
if (valueIsSpecified) return false;
|
|
275
|
-
return right ? rightHasPadding : true;
|
|
276
|
-
}, [right, rightHasPadding, valueIsSpecified]);
|
|
485
|
+
const hour12 = useMemo(() => format.includes('hh'), [format]);
|
|
277
486
|
|
|
278
|
-
|
|
279
|
-
if (
|
|
487
|
+
useEffect(() => {
|
|
488
|
+
if (!disabledTimesFn || !day) return;
|
|
489
|
+
let mounted = true;
|
|
490
|
+
const fn = async () => {
|
|
491
|
+
setLoadingTimes(true);
|
|
492
|
+
const disabledTimes = await disabledTimesFn(day);
|
|
493
|
+
if (mounted) {
|
|
494
|
+
setDisabledTimes(disabledTimes);
|
|
495
|
+
setLoadingTimes(false);
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
fn();
|
|
499
|
+
return () => {
|
|
500
|
+
mounted = false;
|
|
501
|
+
};
|
|
502
|
+
}, [disabledTimesFn, day]);
|
|
503
|
+
|
|
504
|
+
const pickerComponent = useMemo(() => {
|
|
505
|
+
if (pickerType === 'date') {
|
|
506
|
+
return (
|
|
507
|
+
<DateCalendar
|
|
508
|
+
firstDayOfWeek={firstDayOfWeek}
|
|
509
|
+
disabledDays={disabledDays}
|
|
510
|
+
locale={locale}
|
|
511
|
+
value={day}
|
|
512
|
+
onChange={dateChangeHandler}
|
|
513
|
+
/>
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
if (pickerType === 'time') {
|
|
517
|
+
if (loadingTimes) {
|
|
518
|
+
return (
|
|
519
|
+
<TimeGridSkeleton count={times.length} columns={timeColumns} />
|
|
520
|
+
);
|
|
521
|
+
}
|
|
280
522
|
return (
|
|
281
|
-
<
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
e.stopPropagation();
|
|
290
|
-
}}
|
|
291
|
-
onKeyDown={(e) => {
|
|
292
|
-
if (disabled) return;
|
|
293
|
-
if (['Enter', ' '].includes(e.key)) {
|
|
294
|
-
setForwardedValue(null);
|
|
295
|
-
if (!containerRef.current) return;
|
|
296
|
-
containerRef.current.focus();
|
|
297
|
-
e.preventDefault();
|
|
298
|
-
e.stopPropagation();
|
|
299
|
-
}
|
|
300
|
-
}}
|
|
301
|
-
aria-label={locale.clearLabel}
|
|
302
|
-
>
|
|
303
|
-
<ClearIcon />
|
|
304
|
-
</Button>
|
|
305
|
-
</div>
|
|
523
|
+
<TimeGrid
|
|
524
|
+
times={times}
|
|
525
|
+
hour12={hour12}
|
|
526
|
+
columns={timeColumns}
|
|
527
|
+
disabledTimes={disabledTimes}
|
|
528
|
+
value={time}
|
|
529
|
+
onChange={timeChangeHandler}
|
|
530
|
+
/>
|
|
306
531
|
);
|
|
307
532
|
}
|
|
308
|
-
return
|
|
309
|
-
right || (
|
|
310
|
-
<ToggleIconContainer>
|
|
311
|
-
{opened ? <Up /> : <Down />}
|
|
312
|
-
</ToggleIconContainer>
|
|
313
|
-
)
|
|
314
|
-
);
|
|
533
|
+
return null;
|
|
315
534
|
}, [
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
535
|
+
dateChangeHandler,
|
|
536
|
+
day,
|
|
537
|
+
disabledDays,
|
|
538
|
+
disabledTimes,
|
|
539
|
+
firstDayOfWeek,
|
|
540
|
+
hour12,
|
|
541
|
+
loadingTimes,
|
|
542
|
+
locale,
|
|
543
|
+
pickerType,
|
|
544
|
+
time,
|
|
545
|
+
timeChangeHandler,
|
|
546
|
+
timeColumns,
|
|
547
|
+
times,
|
|
323
548
|
]);
|
|
324
549
|
|
|
325
|
-
const
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
const nextValue =
|
|
340
|
-
prev && Array.isArray(prev) && rangeStartedRef.current
|
|
341
|
-
? [new Date(prev[0].getTime()), createDate(date, prev[1])]
|
|
342
|
-
: [d, d];
|
|
343
|
-
|
|
344
|
-
rangeStartedRef.current = !rangeStartedRef.current;
|
|
345
|
-
return nextValue.sort(
|
|
346
|
-
(a: Date, b: Date) => a.getTime() - b.getTime()
|
|
347
|
-
);
|
|
348
|
-
});
|
|
349
|
-
},
|
|
350
|
-
[range, setForwardedValue]
|
|
351
|
-
);
|
|
352
|
-
|
|
353
|
-
const calendarComponent = useMemo(
|
|
354
|
-
() => (
|
|
355
|
-
<DatePickerCalendar
|
|
356
|
-
firstDayOfWeek={firstDayOfWeek}
|
|
357
|
-
locale={locale}
|
|
358
|
-
value={forwardedValue}
|
|
359
|
-
onSelect={(v) => {
|
|
360
|
-
changeHandler(v);
|
|
361
|
-
firstTimePickerRef.current?.focus();
|
|
362
|
-
if (!showTime && (!range || !rangeStartedRef.current)) {
|
|
363
|
-
closeHandler();
|
|
364
|
-
}
|
|
365
|
-
}}
|
|
366
|
-
/>
|
|
367
|
-
),
|
|
368
|
-
[
|
|
369
|
-
changeHandler,
|
|
370
|
-
closeHandler,
|
|
371
|
-
firstDayOfWeek,
|
|
372
|
-
forwardedValue,
|
|
373
|
-
locale,
|
|
374
|
-
range,
|
|
375
|
-
showTime,
|
|
376
|
-
]
|
|
377
|
-
);
|
|
550
|
+
const openPicker = useCallback(() => {
|
|
551
|
+
if (!innerInputRef.current) return;
|
|
552
|
+
const next = nextToken(0, formatRef.current, tokens);
|
|
553
|
+
|
|
554
|
+
if (next) {
|
|
555
|
+
const type = getPickerType(next.token);
|
|
556
|
+
if (type) {
|
|
557
|
+
setInputFocused(true);
|
|
558
|
+
setInputSelection({ start: next.pos, end: next.pos });
|
|
559
|
+
setPickerType(type);
|
|
560
|
+
setPickerVisibility(true);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}, [innerInputRef]);
|
|
378
564
|
|
|
379
|
-
const
|
|
380
|
-
(e) => {
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
setForwardedValue(([from, to]) => {
|
|
384
|
-
const nextTo = new Date(to.getTime());
|
|
385
|
-
if (isSameDay(from, to)) {
|
|
386
|
-
nextTo.setHours(from.getHours() + 1);
|
|
387
|
-
nextTo.setMinutes(from.getMinutes());
|
|
388
|
-
} else {
|
|
389
|
-
nextTo.setHours(from.getHours());
|
|
390
|
-
nextTo.setMinutes(from.getMinutes());
|
|
391
|
-
}
|
|
392
|
-
return [from, nextTo];
|
|
393
|
-
});
|
|
565
|
+
const focusHandler = useCallback(
|
|
566
|
+
(e: FocusEvent<HTMLInputElement>) => {
|
|
567
|
+
setInputFocused(true);
|
|
568
|
+
onFocus(e);
|
|
394
569
|
},
|
|
395
|
-
[
|
|
570
|
+
[onFocus]
|
|
396
571
|
);
|
|
397
572
|
|
|
398
|
-
const
|
|
399
|
-
(e) => {
|
|
400
|
-
if (
|
|
401
|
-
|
|
573
|
+
const blurHandler = useCallback(
|
|
574
|
+
(e: FocusEvent<HTMLInputElement>) => {
|
|
575
|
+
if (isMinXs) {
|
|
576
|
+
setPickerVisibility(false);
|
|
577
|
+
}
|
|
578
|
+
setInputFocused(false);
|
|
579
|
+
onBlur(e);
|
|
402
580
|
},
|
|
403
|
-
[
|
|
581
|
+
[isMinXs, onBlur]
|
|
404
582
|
);
|
|
405
583
|
|
|
406
|
-
const
|
|
407
|
-
() =>
|
|
408
|
-
|
|
409
|
-
<TimeContainer>
|
|
410
|
-
{Array.isArray(forwardedValue) ? (
|
|
411
|
-
<>
|
|
412
|
-
<StyledTimePicker
|
|
413
|
-
ref={firstTimePickerRef}
|
|
414
|
-
autoFocus
|
|
415
|
-
disabled={disabled}
|
|
416
|
-
notation={timeNotation}
|
|
417
|
-
containerProps={timePickerStyle}
|
|
418
|
-
value={forwardedValue[0]}
|
|
419
|
-
onChange={(v) => setForwardedValue([v, forwardedValue[1]])}
|
|
420
|
-
onKeyDown={(e) => {
|
|
421
|
-
if (disabled) return;
|
|
422
|
-
if (e.key === 'Enter') {
|
|
423
|
-
setOpened(!opened);
|
|
424
|
-
}
|
|
425
|
-
}}
|
|
426
|
-
onKeyUp={tabOnInputComplete}
|
|
427
|
-
/>
|
|
428
|
-
<Dash>–</Dash>
|
|
429
|
-
<StyledTimePicker
|
|
430
|
-
ref={secondTimePickerRef}
|
|
431
|
-
disabled={disabled}
|
|
432
|
-
notation={timeNotation}
|
|
433
|
-
containerProps={timePickerStyle}
|
|
434
|
-
value={forwardedValue[1]}
|
|
435
|
-
onChange={(v) => setForwardedValue([forwardedValue[0], v])}
|
|
436
|
-
onKeyDown={(e) => {
|
|
437
|
-
if (disabled) return;
|
|
438
|
-
if (e.key === 'Enter') {
|
|
439
|
-
setOpened(!opened);
|
|
440
|
-
}
|
|
441
|
-
}}
|
|
442
|
-
onKeyUp={closeOnInputComplete}
|
|
443
|
-
/>
|
|
444
|
-
</>
|
|
445
|
-
) : (
|
|
446
|
-
<StyledTimePicker
|
|
447
|
-
ref={firstTimePickerRef}
|
|
448
|
-
autoFocus
|
|
449
|
-
disabled={disabled}
|
|
450
|
-
notation={timeNotation}
|
|
451
|
-
containerProps={timePickerStyle}
|
|
452
|
-
value={forwardedValue}
|
|
453
|
-
onChange={setForwardedValue}
|
|
454
|
-
onKeyDown={(e) => {
|
|
455
|
-
if (disabled) return;
|
|
456
|
-
if (e.key === 'Enter') {
|
|
457
|
-
setOpened(!opened);
|
|
458
|
-
}
|
|
459
|
-
}}
|
|
460
|
-
onKeyUp={closeOnInputComplete}
|
|
461
|
-
/>
|
|
462
|
-
)}
|
|
463
|
-
</TimeContainer>
|
|
464
|
-
) : null,
|
|
465
|
-
[
|
|
466
|
-
closeOnInputComplete,
|
|
467
|
-
disabled,
|
|
468
|
-
forwardedValue,
|
|
469
|
-
opened,
|
|
470
|
-
setForwardedValue,
|
|
471
|
-
showTime,
|
|
472
|
-
tabOnInputComplete,
|
|
473
|
-
timeNotation,
|
|
474
|
-
]
|
|
584
|
+
const showPickerButton = useMemo(
|
|
585
|
+
() => showPicker && (!autoOpen || !isMinXs),
|
|
586
|
+
[autoOpen, isMinXs, showPicker]
|
|
475
587
|
);
|
|
476
588
|
|
|
477
589
|
return (
|
|
478
590
|
<>
|
|
479
|
-
<
|
|
480
|
-
|
|
591
|
+
<InputContainer
|
|
592
|
+
{...containerProps}
|
|
481
593
|
disabled={disabled}
|
|
482
594
|
size={size}
|
|
483
|
-
tabIndex={!disabled ? 0 : -1}
|
|
484
|
-
onClick={() => {
|
|
485
|
-
if (disabled) return;
|
|
486
|
-
setOpened(!opened);
|
|
487
|
-
}}
|
|
488
|
-
onKeyDown={(e) => {
|
|
489
|
-
if (disabled) return;
|
|
490
|
-
if (['Enter', ' '].includes(e.key)) {
|
|
491
|
-
setOpened(!opened);
|
|
492
|
-
e.preventDefault();
|
|
493
|
-
}
|
|
494
|
-
}}
|
|
495
|
-
onMouseDown={(e) => e.preventDefault()}
|
|
496
|
-
onBlur={blurHandler}
|
|
497
|
-
role='combobox'
|
|
498
|
-
aria-label={
|
|
499
|
-
forwardedValue
|
|
500
|
-
? getAccessibilityDateLabel(forwardedValue, locale)
|
|
501
|
-
: undefined
|
|
502
|
-
}
|
|
503
|
-
aria-disabled={disabled}
|
|
504
|
-
{...rest}
|
|
505
595
|
ref={mergedContainerRef}
|
|
506
596
|
>
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
{
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
</
|
|
597
|
+
<StyledInputDateUnstyled
|
|
598
|
+
{...rest}
|
|
599
|
+
disabled={disabled}
|
|
600
|
+
hasRight={showPickerButton}
|
|
601
|
+
format={format}
|
|
602
|
+
value={forwardedValue}
|
|
603
|
+
inputValue={inputValue}
|
|
604
|
+
selection={inputSelection}
|
|
605
|
+
onChange={setForwardedValue}
|
|
606
|
+
onInputChange={setInputValue}
|
|
607
|
+
onSelectionChange={setInputSelection}
|
|
608
|
+
onDayChange={setDay}
|
|
609
|
+
onTimeChange={setTime}
|
|
610
|
+
onDayError={onDayError}
|
|
611
|
+
onFocus={focusHandler}
|
|
612
|
+
onBlur={blurHandler}
|
|
613
|
+
ref={mergedInputRef}
|
|
614
|
+
/>
|
|
615
|
+
|
|
616
|
+
{showPickerButton && (
|
|
617
|
+
<ThemeOverrider overrides={{ buttonPaddingHorizontal: 0.8 }}>
|
|
618
|
+
<PickerButtonContainer>
|
|
619
|
+
<Button
|
|
620
|
+
type='ghost'
|
|
621
|
+
size='small'
|
|
622
|
+
wide='never'
|
|
623
|
+
disabled={disabled}
|
|
624
|
+
onClick={openPicker}
|
|
625
|
+
onMouseDown={preventDefault}
|
|
626
|
+
>
|
|
627
|
+
<Calendar />
|
|
628
|
+
</Button>
|
|
629
|
+
</PickerButtonContainer>
|
|
540
630
|
</ThemeOverrider>
|
|
541
631
|
)}
|
|
542
|
-
</
|
|
632
|
+
</InputContainer>
|
|
543
633
|
|
|
544
634
|
{isMinXs ? (
|
|
545
635
|
<StyledPopover
|
|
546
|
-
trigger={
|
|
636
|
+
trigger={innerContainerRef}
|
|
547
637
|
placement='bottom-start'
|
|
548
|
-
visible={
|
|
549
|
-
|
|
638
|
+
visible={pickerVisibility}
|
|
639
|
+
onMouseDown={preventDefault} // To prevent loosing the input focus
|
|
550
640
|
size={size}
|
|
551
641
|
>
|
|
552
|
-
{
|
|
553
|
-
{timeComponent}
|
|
642
|
+
{pickerComponent}
|
|
554
643
|
</StyledPopover>
|
|
555
644
|
) : (
|
|
556
|
-
<
|
|
557
|
-
title={placeholder}
|
|
645
|
+
<StyledModal
|
|
558
646
|
header={null}
|
|
559
647
|
footer={null}
|
|
560
|
-
visible={
|
|
561
|
-
onClose={
|
|
648
|
+
visible={pickerVisibility}
|
|
649
|
+
onClose={() => setPickerVisibility(false)}
|
|
650
|
+
lockedFocus={false} // To prevent loosing the input focus
|
|
651
|
+
onMouseDown={preventDefault} // To prevent loosing the input focus
|
|
562
652
|
size={size}
|
|
563
653
|
>
|
|
564
|
-
{
|
|
565
|
-
|
|
566
|
-
</Modal>
|
|
654
|
+
{pickerComponent}
|
|
655
|
+
</StyledModal>
|
|
567
656
|
)}
|
|
568
657
|
</>
|
|
569
658
|
);
|