@os-design/core 1.0.280 → 1.0.281

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.
Files changed (198) hide show
  1. package/dist/Avatar/utils/nameToInitials.d.ts.map +1 -1
  2. package/dist/Avatar/utils/strToHue.d.ts.map +1 -1
  3. package/dist/Button/index.d.ts.map +1 -1
  4. package/dist/Button/index.js +1 -1
  5. package/dist/Button/utils/useButtonColors.d.ts.map +1 -1
  6. package/dist/ButtonLink/index.d.ts.map +1 -1
  7. package/dist/ButtonLink/index.js +0 -5
  8. package/dist/Checkbox/index.d.ts.map +1 -1
  9. package/dist/Checkbox/index.js +1 -6
  10. package/dist/DateCalendar/Calendar.d.ts +25 -0
  11. package/dist/DateCalendar/Calendar.d.ts.map +1 -0
  12. package/dist/DateCalendar/Calendar.js +271 -0
  13. package/dist/DateCalendar/MonthPicker.d.ts +12 -0
  14. package/dist/DateCalendar/MonthPicker.d.ts.map +1 -0
  15. package/dist/DateCalendar/MonthPicker.js +159 -0
  16. package/dist/DateCalendar/index.d.ts +41 -0
  17. package/dist/DateCalendar/index.d.ts.map +1 -0
  18. package/dist/DateCalendar/index.js +77 -0
  19. package/dist/DateCalendar/locale.d.ts +6 -0
  20. package/dist/DateCalendar/locale.d.ts.map +1 -0
  21. package/dist/DateCalendar/locale.js +4 -0
  22. package/dist/DateCalendar/utils/calendarDays.d.ts +10 -0
  23. package/dist/DateCalendar/utils/calendarDays.d.ts.map +1 -0
  24. package/dist/DateCalendar/utils/calendarDays.js +46 -0
  25. package/dist/DateCalendar/utils/dayOfWeek.d.ts +8 -0
  26. package/dist/DateCalendar/utils/dayOfWeek.d.ts.map +1 -0
  27. package/dist/DateCalendar/utils/dayOfWeek.js +6 -0
  28. package/dist/DateCalendar/utils/daysInMonth.d.ts +7 -0
  29. package/dist/DateCalendar/utils/daysInMonth.d.ts.map +1 -0
  30. package/dist/DateCalendar/utils/daysInMonth.js +14 -0
  31. package/dist/DateCalendar/utils/month.d.ts +14 -0
  32. package/dist/DateCalendar/utils/month.d.ts.map +1 -0
  33. package/dist/DateCalendar/utils/month.js +24 -0
  34. package/dist/DateCalendar/utils/shift.d.ts +3 -0
  35. package/dist/DateCalendar/utils/shift.d.ts.map +1 -0
  36. package/dist/DateCalendar/utils/shift.js +12 -0
  37. package/dist/DatePicker/index.d.ts +68 -62
  38. package/dist/DatePicker/index.d.ts.map +1 -1
  39. package/dist/DatePicker/index.js +359 -265
  40. package/dist/DatePicker/utils/createTimes.d.ts +7 -0
  41. package/dist/DatePicker/utils/createTimes.d.ts.map +1 -0
  42. package/dist/DatePicker/utils/createTimes.js +15 -0
  43. package/dist/GlobalStyles/resetStyles.d.ts.map +1 -1
  44. package/dist/GlobalStyles/typographyStyles.d.ts.map +1 -1
  45. package/dist/Input/index.d.ts +15 -0
  46. package/dist/Input/index.d.ts.map +1 -1
  47. package/dist/Input/index.js +5 -5
  48. package/dist/Input/utils/getFocusableElements.d.ts.map +1 -1
  49. package/dist/InputDateUnstyled/index.d.ts +94 -0
  50. package/dist/InputDateUnstyled/index.d.ts.map +1 -0
  51. package/dist/InputDateUnstyled/index.js +406 -0
  52. package/dist/InputDateUnstyled/utils/convertHours.d.ts +4 -0
  53. package/dist/InputDateUnstyled/utils/convertHours.d.ts.map +1 -0
  54. package/dist/InputDateUnstyled/utils/convertHours.js +12 -0
  55. package/dist/InputDateUnstyled/utils/convertToFullYear.d.ts +3 -0
  56. package/dist/InputDateUnstyled/utils/convertToFullYear.d.ts.map +1 -0
  57. package/dist/InputDateUnstyled/utils/convertToFullYear.js +10 -0
  58. package/dist/InputDateUnstyled/utils/dateToString.d.ts +3 -0
  59. package/dist/InputDateUnstyled/utils/dateToString.d.ts.map +1 -0
  60. package/dist/InputDateUnstyled/utils/dateToString.js +10 -0
  61. package/dist/InputDateUnstyled/utils/daysInMonth.d.ts +7 -0
  62. package/dist/InputDateUnstyled/utils/daysInMonth.d.ts.map +1 -0
  63. package/dist/InputDateUnstyled/utils/daysInMonth.js +14 -0
  64. package/dist/InputDateUnstyled/utils/ensureCaretVisible.d.ts +3 -0
  65. package/dist/InputDateUnstyled/utils/ensureCaretVisible.d.ts.map +1 -0
  66. package/dist/InputDateUnstyled/utils/ensureCaretVisible.js +32 -0
  67. package/dist/InputDateUnstyled/utils/eraseSelectedTokens.d.ts +10 -0
  68. package/dist/InputDateUnstyled/utils/eraseSelectedTokens.d.ts.map +1 -0
  69. package/dist/InputDateUnstyled/utils/eraseSelectedTokens.js +29 -0
  70. package/dist/InputDateUnstyled/utils/replaceSubstring.d.ts +3 -0
  71. package/dist/InputDateUnstyled/utils/replaceSubstring.d.ts.map +1 -0
  72. package/dist/InputDateUnstyled/utils/replaceSubstring.js +9 -0
  73. package/dist/InputDateUnstyled/utils/same.d.ts +6 -0
  74. package/dist/InputDateUnstyled/utils/same.d.ts.map +1 -0
  75. package/dist/InputDateUnstyled/utils/same.js +3 -0
  76. package/dist/InputDateUnstyled/utils/stringToDay.d.ts +12 -0
  77. package/dist/InputDateUnstyled/utils/stringToDay.d.ts.map +1 -0
  78. package/dist/InputDateUnstyled/utils/stringToDay.js +55 -0
  79. package/dist/InputDateUnstyled/utils/stringToTime.d.ts +7 -0
  80. package/dist/InputDateUnstyled/utils/stringToTime.d.ts.map +1 -0
  81. package/dist/InputDateUnstyled/utils/stringToTime.js +40 -0
  82. package/dist/InputDateUnstyled/utils/token.d.ts +9 -0
  83. package/dist/InputDateUnstyled/utils/token.d.ts.map +1 -0
  84. package/dist/InputDateUnstyled/utils/token.js +66 -0
  85. package/dist/Link/index.d.ts.map +1 -1
  86. package/dist/Link/index.js +3 -8
  87. package/dist/LinkButton/index.d.ts.map +1 -1
  88. package/dist/LinkButton/index.js +0 -5
  89. package/dist/List/utils/bodyPointerEvents.d.ts.map +1 -1
  90. package/dist/List/utils/frameTimeout.d.ts.map +1 -1
  91. package/dist/List/utils/useRWLoadNext.d.ts.map +1 -1
  92. package/dist/LogoLink/index.d.ts.map +1 -1
  93. package/dist/LogoLink/index.js +1 -6
  94. package/dist/Menu/utils/useFocusWithArrows.d.ts.map +1 -1
  95. package/dist/Modal/index.d.ts +5 -0
  96. package/dist/Modal/index.d.ts.map +1 -1
  97. package/dist/Modal/index.js +53 -48
  98. package/dist/Navigation/utils/useScrollFlags.d.ts.map +1 -1
  99. package/dist/NavigationItem/index.d.ts.map +1 -1
  100. package/dist/NavigationItem/index.js +1 -6
  101. package/dist/Popover/utils/usePopoverPosition.d.ts.map +1 -1
  102. package/dist/ScrollButton/utils/useContainerPosition.d.ts.map +1 -1
  103. package/dist/ScrollButton/utils/useVisibility.d.ts.map +1 -1
  104. package/dist/Select/index.d.ts.map +1 -1
  105. package/dist/Select/index.js +2 -3
  106. package/dist/Switch/index.d.ts.map +1 -1
  107. package/dist/Switch/index.js +1 -7
  108. package/dist/TagLink/index.d.ts.map +1 -1
  109. package/dist/TagLink/index.js +1 -6
  110. package/dist/TimeGrid/index.d.ts +63 -0
  111. package/dist/TimeGrid/index.d.ts.map +1 -0
  112. package/dist/TimeGrid/index.js +111 -0
  113. package/dist/TimeGrid/utils/convertHours.d.ts +4 -0
  114. package/dist/TimeGrid/utils/convertHours.d.ts.map +1 -0
  115. package/dist/TimeGrid/utils/convertHours.js +12 -0
  116. package/dist/TimeGrid/utils/createTimes.d.ts +7 -0
  117. package/dist/TimeGrid/utils/createTimes.d.ts.map +1 -0
  118. package/dist/TimeGrid/utils/createTimes.js +15 -0
  119. package/dist/TimeGrid/utils/timeToString.d.ts +4 -0
  120. package/dist/TimeGrid/utils/timeToString.d.ts.map +1 -0
  121. package/dist/TimeGrid/utils/timeToString.js +12 -0
  122. package/dist/TimeGridSkeleton/index.d.ts +18 -0
  123. package/dist/TimeGridSkeleton/index.d.ts.map +1 -0
  124. package/dist/TimeGridSkeleton/index.js +33 -0
  125. package/dist/TimeList/index.d.ts +45 -0
  126. package/dist/TimeList/index.d.ts.map +1 -0
  127. package/dist/TimeList/index.js +80 -0
  128. package/dist/TimeList/utils/convertHours.d.ts +4 -0
  129. package/dist/TimeList/utils/convertHours.d.ts.map +1 -0
  130. package/dist/TimeList/utils/convertHours.js +12 -0
  131. package/dist/TimeList/utils/createTimes.d.ts +7 -0
  132. package/dist/TimeList/utils/createTimes.d.ts.map +1 -0
  133. package/dist/TimeList/utils/createTimes.js +15 -0
  134. package/dist/TimeList/utils/timeToString.d.ts +4 -0
  135. package/dist/TimeList/utils/timeToString.d.ts.map +1 -0
  136. package/dist/TimeList/utils/timeToString.js +12 -0
  137. package/dist/TimeListSkeleton/index.d.ts +13 -0
  138. package/dist/TimeListSkeleton/index.d.ts.map +1 -0
  139. package/dist/TimeListSkeleton/index.js +30 -0
  140. package/dist/index.d.ts +12 -0
  141. package/dist/index.d.ts.map +1 -1
  142. package/dist/index.js +12 -0
  143. package/dist/message/styles.d.ts.map +1 -1
  144. package/package.json +8 -8
  145. package/src/Button/index.tsx +1 -1
  146. package/src/ButtonLink/index.tsx +0 -5
  147. package/src/Checkbox/index.tsx +1 -6
  148. package/src/DateCalendar/Calendar.tsx +400 -0
  149. package/src/DateCalendar/MonthPicker.tsx +212 -0
  150. package/src/DateCalendar/index.tsx +135 -0
  151. package/src/DateCalendar/locale.ts +22 -0
  152. package/src/DateCalendar/utils/calendarDays.ts +61 -0
  153. package/src/DateCalendar/utils/dayOfWeek.ts +14 -0
  154. package/src/DateCalendar/utils/daysInMonth.ts +22 -0
  155. package/src/DateCalendar/utils/month.ts +30 -0
  156. package/src/DateCalendar/utils/shift.ts +14 -0
  157. package/src/DatePicker/index.tsx +506 -417
  158. package/src/DatePicker/utils/createTimes.ts +20 -0
  159. package/src/Input/index.tsx +11 -8
  160. package/src/InputDateUnstyled/index.tsx +533 -0
  161. package/src/InputDateUnstyled/utils/convertHours.ts +15 -0
  162. package/src/InputDateUnstyled/utils/convertToFullYear.ts +11 -0
  163. package/src/InputDateUnstyled/utils/dateToString.ts +21 -0
  164. package/src/InputDateUnstyled/utils/daysInMonth.ts +22 -0
  165. package/src/InputDateUnstyled/utils/ensureCaretVisible.ts +37 -0
  166. package/src/InputDateUnstyled/utils/eraseSelectedTokens.ts +38 -0
  167. package/src/InputDateUnstyled/utils/replaceSubstring.ts +10 -0
  168. package/src/InputDateUnstyled/utils/same.ts +15 -0
  169. package/src/InputDateUnstyled/utils/stringToDay.ts +69 -0
  170. package/src/InputDateUnstyled/utils/stringToTime.ts +48 -0
  171. package/src/InputDateUnstyled/utils/token.ts +102 -0
  172. package/src/Link/index.tsx +5 -25
  173. package/src/LinkButton/index.tsx +2 -15
  174. package/src/LogoLink/index.tsx +2 -6
  175. package/src/Modal/index.tsx +71 -60
  176. package/src/NavigationItem/index.tsx +2 -16
  177. package/src/Select/index.tsx +2 -3
  178. package/src/Switch/index.tsx +1 -11
  179. package/src/TagLink/index.tsx +3 -11
  180. package/src/TimeGrid/index.tsx +189 -0
  181. package/src/TimeGrid/utils/convertHours.ts +15 -0
  182. package/src/TimeGrid/utils/createTimes.ts +20 -0
  183. package/src/TimeGrid/utils/timeToString.ts +17 -0
  184. package/src/TimeGridSkeleton/index.tsx +50 -0
  185. package/src/TimeList/index.tsx +135 -0
  186. package/src/TimeList/utils/convertHours.ts +15 -0
  187. package/src/TimeList/utils/createTimes.ts +20 -0
  188. package/src/TimeList/utils/timeToString.ts +17 -0
  189. package/src/TimeListSkeleton/index.tsx +44 -0
  190. package/src/index.ts +12 -0
  191. package/dist/DatePicker/DatePickerCalendar.d.ts +0 -11
  192. package/dist/DatePicker/DatePickerCalendar.d.ts.map +0 -1
  193. package/dist/DatePicker/DatePickerCalendar.js +0 -178
  194. package/dist/TimePicker/index.d.ts +0 -29
  195. package/dist/TimePicker/index.d.ts.map +0 -1
  196. package/dist/TimePicker/index.js +0 -100
  197. package/src/DatePicker/DatePickerCalendar.tsx +0 -230
  198. package/src/TimePicker/index.tsx +0 -144
@@ -1,315 +1,409 @@
1
- import styled from '@emotion/styled';
2
- import { defaultLocale, getAccessibilityDateLabel, useFormattedValue, isSameDay } from '@os-design/date-picker-utils';
3
- import { Down, Up } from '@os-design/icons';
4
1
  import { useIsMinWidth } from '@os-design/media';
5
- import { ThemeOverrider } from '@os-design/theming';
6
- import { useForwardedRef, useForwardedState, useKeyPress } from '@os-design/utils';
7
- import React, { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from 'react';
8
- import Button from '../Button/index.js';
2
+ import { enableScrollingStyles, resetFocusStyles } from '@os-design/styles';
3
+ import { omitEmotionProps, useForwardedRef, useForwardedState } from '@os-design/utils';
4
+ import { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from 'react';
9
5
  import Modal from '../Modal/index.js';
6
+ import InputDateUnstyled, { convertTo12hours, nextToken, replaceSubstring, tokens } from '../InputDateUnstyled/index.js';
7
+ import DateCalendar from '../DateCalendar/index.js';
8
+ import TimeGrid from '../TimeGrid/index.js';
9
+ import styled from '@emotion/styled';
10
10
  import Popover from '../Popover/index.js';
11
- import { ClearIcon, Placeholder, SelectContainer, Title, ToggleContent, ToggleIconContainer, ToggleLeftAddon, ToggleRightAddon } from '../Select/index.js';
12
- import TimePicker from '../TimePicker/index.js';
13
- import DatePickerCalendar from './DatePickerCalendar.js';
14
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
15
- const StyledPopover = styled(Popover)`
16
- padding: ${p => p.theme.datePickerPadding}em;
17
- `;
18
- const TimeContainer = styled.div`
19
- display: flex;
20
- justify-content: center;
21
- margin-top: 0.5em;
22
- `;
23
- const Dash = styled.div`
24
- margin: 0 0.5em;
25
- line-height: ${p => p.theme.baseHeight}em;
26
- `;
27
- const StyledTimePicker = styled(TimePicker)`
28
- width: 2.5em;
29
- text-align: center;
30
- `;
31
- const timePickerStyle = {
32
- style: {
33
- width: 'auto'
11
+ import Button from '../Button/index.js';
12
+ import { Calendar } from '@os-design/icons';
13
+ import { InputContainer, TimeGridSkeleton } from '../index.js';
14
+ import { clr, ThemeOverrider } from '@os-design/theming';
15
+ import { css } from '@emotion/react';
16
+ import createTimes from './utils/createTimes.js';
17
+
18
+ /* eslint-disable @typescript-eslint/no-explicit-any */
19
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
20
+ const dateTokens = ['DD', 'MM', 'YYYY', 'YY'];
21
+ const timeTokens = ['hh', 'HH', 'mm', 'aa'];
22
+ const tokenGetterMap = {
23
+ DD: ({
24
+ day
25
+ }) => day.toString().padStart(2, '0'),
26
+ MM: ({
27
+ month
28
+ }) => (month + 1).toString().padStart(2, '0'),
29
+ YYYY: ({
30
+ year
31
+ }) => year.toString(),
32
+ YY: ({
33
+ year
34
+ }) => year.toString().slice(2, 4),
35
+ hh: ({
36
+ hour
37
+ }) => {
38
+ const [h] = convertTo12hours(hour);
39
+ return h.toString().padStart(2, '0');
40
+ },
41
+ HH: ({
42
+ hour
43
+ }) => hour.toString().padStart(2, '0'),
44
+ mm: ({
45
+ minute
46
+ }) => minute.toString().padStart(2, '0'),
47
+ aa: ({
48
+ hour
49
+ }) => {
50
+ const [, meridiem] = convertTo12hours(hour);
51
+ return meridiem;
52
+ }
53
+ };
54
+ const getPickerType = token => {
55
+ if (dateTokens.includes(token)) {
56
+ return 'date';
57
+ }
58
+ if (timeTokens.includes(token)) {
59
+ return 'time';
34
60
  }
61
+ return null;
35
62
  };
36
- const createDate = (date, time) => {
37
- const d = new Date(0);
38
- d.setFullYear(date.getFullYear());
39
- d.setMonth(date.getMonth());
40
- d.setDate(date.getDate());
41
- d.setHours(0);
42
- d.setMinutes(0);
43
- if (time) {
44
- d.setHours(time.getHours());
45
- d.setMinutes(time.getMinutes());
63
+ const getNextTokenDiffType = (startPos, format) => {
64
+ const current = nextToken(startPos, format, tokens);
65
+ if (!current) return null;
66
+ const currentType = getPickerType(current.token);
67
+ let pos = current.end;
68
+ while (pos < format.length) {
69
+ const next = nextToken(pos, format, tokens);
70
+ if (!next) return null;
71
+ const nextType = getPickerType(next.token);
72
+ if (nextType !== currentType) return next;
73
+ pos = next.end;
46
74
  }
47
- return d;
75
+ return null;
48
76
  };
77
+ const preventDefault = e => e.preventDefault();
78
+ const notHasRightStyles = p => !p.hasRight && css`
79
+ padding-right: ${p.theme.inputPaddingHorizontal}em;
80
+ `;
81
+ const hideSpinButton = css`
82
+ /* Chrome, Safari, Edge, Opera */
83
+ &::-webkit-outer-spin-button,
84
+ &::-webkit-inner-spin-button {
85
+ -webkit-appearance: none;
86
+ margin: 0;
87
+ }
88
+ /* Firefox */
89
+ appearance: textfield;
90
+ `;
91
+ const StyledInputDateUnstyled = styled(InputDateUnstyled, omitEmotionProps('hasRight'))`
92
+ ${resetFocusStyles};
93
+ border: none;
94
+ font-size: 1em;
95
+ flex: 1;
96
+ width: 100%;
97
+ overflow: hidden;
49
98
 
99
+ color: ${p => clr(p.theme.inputColorText)};
100
+ background-color: transparent;
101
+ padding-left: ${p => p.theme.inputPaddingHorizontal}em;
102
+
103
+ &::placeholder {
104
+ color: ${p => clr(p.theme.inputColorPlaceholder)};
105
+ }
106
+
107
+ ${hideSpinButton};
108
+ ${notHasRightStyles};
109
+ `;
110
+ const PickerButtonContainer = styled.div`
111
+ display: flex;
112
+ align-items: center;
113
+ `;
114
+ const PADDING_EM = 0.8;
115
+ const StyledPopover = styled(Popover)`
116
+ padding: ${PADDING_EM}em;
117
+ width: ${p => p.theme.dateCalendarCellSize * 7 + PADDING_EM * 2}em;
118
+ max-height: ${p => p.theme.baseHeight * p.theme.sizes.small + 0.5 + p.theme.dateCalendarCellSize * 7}em;
119
+ ${enableScrollingStyles('y')};
120
+ `;
121
+ const StyledModal = styled(Modal)`
122
+ padding: ${PADDING_EM}em;
123
+ `;
124
+ const defaultTimes = createTimes({
125
+ hour: 9,
126
+ minute: 0
127
+ }, {
128
+ hour: 18,
129
+ minute: 0
130
+ }, 30);
50
131
  /**
51
- * The component to choose a date.
132
+ * The component to enter or choose a date/time.
52
133
  */
53
134
  const DatePicker = /*#__PURE__*/forwardRef(({
54
- left,
55
- leftHasPadding = false,
56
- right,
57
- rightHasPadding = false,
58
- placeholder,
135
+ format = 'DD.MM.YYYY',
136
+ firstDayOfWeek = 0,
137
+ times = defaultTimes,
138
+ timeColumns = 3,
59
139
  disabled = false,
60
- autoFocus = false,
140
+ disabledDays,
141
+ disabledTimes: disabledTimesFn,
142
+ locale,
143
+ showPicker = false,
61
144
  autoOpen = false,
62
- format,
63
- firstDayOfWeek = 'sunday',
64
- locale = defaultLocale,
65
- showTime = false,
66
- timeNotation = '12-hour',
67
- range = false,
145
+ containerRef,
146
+ containerProps = {},
68
147
  value,
69
148
  defaultValue,
70
149
  onChange,
71
- onClose = () => {},
150
+ onDayChange = () => {},
151
+ onTimeChange = () => {},
152
+ onDayError,
153
+ onFocus = () => {},
72
154
  onBlur = () => {},
155
+ onEnd = () => {},
73
156
  size,
74
157
  ...rest
75
158
  }, ref) => {
76
- const [containerRef, mergedContainerRef] = useForwardedRef(ref);
77
- const [opened, setOpened] = useState(autoOpen);
78
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
159
+ const [innerContainerRef, mergedContainerRef] = useForwardedRef(containerRef);
160
+ const [innerInputRef, mergedInputRef] = useForwardedRef(ref);
161
+ const [inputValue, setInputValue] = useState(undefined);
162
+ const [inputSelection, setInputSelection] = useState({
163
+ start: 0,
164
+ end: 0
165
+ });
166
+ const [inputFocused, setInputFocused] = useState(false);
79
167
  const [forwardedValue, setForwardedValue] = useForwardedState({
80
168
  value,
81
169
  defaultValue,
82
170
  onChange
83
171
  });
172
+ const [pickerType, setPickerType] = useState('date');
173
+ const [pickerVisibility, setPickerVisibility] = useState(false);
174
+ const [day, setDay] = useState(null);
175
+ const [time, setTime] = useState(null);
176
+ const [loadingTimes, setLoadingTimes] = useState(false);
177
+ const [disabledTimes, setDisabledTimes] = useState([]);
178
+ const inputValueRef = useRef(inputValue);
179
+ useEffect(() => {
180
+ inputValueRef.current = inputValue;
181
+ }, [inputValue]);
182
+ const inputSelectionRef = useRef(inputSelection);
84
183
  useEffect(() => {
85
- if (autoFocus) containerRef.current?.focus();
86
- }, [autoFocus, containerRef]);
87
- const onCloseRef = useRef(onClose);
184
+ inputSelectionRef.current = inputSelection;
185
+ }, [inputSelection]);
186
+ const forwardedValueRef = useRef(forwardedValue);
88
187
  useEffect(() => {
89
- onCloseRef.current = onClose;
90
- }, [onClose]);
188
+ forwardedValueRef.current = forwardedValue;
189
+ }, [forwardedValue]);
190
+ const formatRef = useRef(format);
91
191
  useEffect(() => {
92
- if (!opened) {
93
- onCloseRef.current();
94
- containerRef.current?.focus();
192
+ formatRef.current = format;
193
+ }, [format]);
194
+ useEffect(() => {
195
+ if (day) onDayChange(day);
196
+ }, [day, onDayChange]);
197
+ useEffect(() => {
198
+ if (time) onTimeChange(time);
199
+ }, [time, onTimeChange]);
200
+ useEffect(() => {
201
+ const {
202
+ start,
203
+ end
204
+ } = inputSelection;
205
+ if (end === start && end === format.length) {
206
+ onEnd();
95
207
  }
96
- }, [containerRef, opened]);
97
- const formattedValue = useFormattedValue({
98
- forwardedValue,
99
- format,
100
- showTime,
101
- timeNotation
102
- });
103
- const closeHandler = useCallback(() => {
104
- setOpened(false);
105
- }, []);
106
- useKeyPress(typeof window !== 'undefined' ? window : undefined, 'Escape', closeHandler);
208
+ }, [format.length, inputSelection, onEnd]);
107
209
  const isMinXs = useIsMinWidth('xs');
108
- const blurHandler = useCallback(e => {
109
- if (!opened) onBlur(e);
110
- }, [onBlur, opened]);
111
- const valueIsSpecified = useMemo(() => formattedValue !== undefined && formattedValue !== null, [formattedValue]);
112
- const rightHasPaddingValue = useMemo(() => {
113
- if (valueIsSpecified) return false;
114
- return right ? rightHasPadding : true;
115
- }, [right, rightHasPadding, valueIsSpecified]);
116
- const rightValue = useMemo(() => {
117
- if (valueIsSpecified) {
118
- return /*#__PURE__*/_jsx("div", {
119
- "aria-hidden": true,
120
- children: /*#__PURE__*/_jsx(Button, {
121
- type: "ghost",
122
- wide: "never",
123
- size: "small",
124
- disabled: disabled,
125
- onClick: e => {
126
- setForwardedValue(null);
127
- e.stopPropagation();
128
- },
129
- onKeyDown: e => {
130
- if (disabled) return;
131
- if (['Enter', ' '].includes(e.key)) {
132
- setForwardedValue(null);
133
- if (!containerRef.current) return;
134
- containerRef.current.focus();
135
- e.preventDefault();
136
- e.stopPropagation();
137
- }
138
- },
139
- "aria-label": locale.clearLabel,
140
- children: /*#__PURE__*/_jsx(ClearIcon, {})
141
- })
142
- });
210
+
211
+ // Set the input focus
212
+ useEffect(() => {
213
+ if (!innerInputRef.current) return;
214
+ if (inputFocused) {
215
+ innerInputRef.current.focus();
216
+ } else {
217
+ innerInputRef.current.blur();
143
218
  }
144
- return right || /*#__PURE__*/_jsx(ToggleIconContainer, {
145
- children: opened ? /*#__PURE__*/_jsx(Up, {}) : /*#__PURE__*/_jsx(Down, {})
146
- });
147
- }, [containerRef, disabled, locale.clearLabel, opened, right, setForwardedValue, valueIsSpecified]);
148
- const firstTimePickerRef = useRef(null);
149
- const secondTimePickerRef = useRef(null);
150
- const rangeStartedRef = useRef(false);
219
+ }, [innerInputRef, inputFocused]);
220
+
221
+ // Open the picker automatically
151
222
  useEffect(() => {
152
- rangeStartedRef.current = false;
153
- }, [opened]);
154
- const changeHandler = useCallback(date => {
155
- setForwardedValue(prev => {
156
- if (!range) return createDate(date, prev);
157
- const d = createDate(date);
158
- const nextValue = prev && Array.isArray(prev) && rangeStartedRef.current ? [new Date(prev[0].getTime()), createDate(date, prev[1])] : [d, d];
159
- rangeStartedRef.current = !rangeStartedRef.current;
160
- return nextValue.sort((a, b) => a.getTime() - b.getTime());
161
- });
162
- }, [range, setForwardedValue]);
163
- const calendarComponent = useMemo(() => /*#__PURE__*/_jsx(DatePickerCalendar, {
164
- firstDayOfWeek: firstDayOfWeek,
165
- locale: locale,
166
- value: forwardedValue,
167
- onSelect: v => {
168
- changeHandler(v);
169
- firstTimePickerRef.current?.focus();
170
- if (!showTime && (!range || !rangeStartedRef.current)) {
171
- closeHandler();
223
+ let pickerType = null;
224
+
225
+ // Find the nearest token from the current caret position
226
+ const next = nextToken(inputSelection.start, formatRef.current, tokens);
227
+ if (next) {
228
+ if (dateTokens.includes(next.token)) {
229
+ pickerType = 'date';
230
+ }
231
+ if (timeTokens.includes(next.token)) {
232
+ pickerType = 'time';
172
233
  }
173
234
  }
174
- }), [changeHandler, closeHandler, firstDayOfWeek, forwardedValue, locale, range, showTime]);
175
- const tabOnInputComplete = useCallback(e => {
176
- if (e.target.selectionStart < 5) return;
177
- secondTimePickerRef.current?.focus();
178
- setForwardedValue(([from, to]) => {
179
- const nextTo = new Date(to.getTime());
180
- if (isSameDay(from, to)) {
181
- nextTo.setHours(from.getHours() + 1);
182
- nextTo.setMinutes(from.getMinutes());
183
- } else {
184
- nextTo.setHours(from.getHours());
185
- nextTo.setMinutes(from.getMinutes());
235
+ if (pickerType && inputFocused) {
236
+ setPickerType(pickerType);
237
+ if (showPicker && autoOpen && isMinXs) {
238
+ setPickerVisibility(true);
186
239
  }
187
- return [from, nextTo];
240
+ } else {
241
+ setPickerVisibility(false);
242
+ }
243
+ }, [autoOpen, inputFocused, inputSelection.start, isMinXs, showPicker]);
244
+ const moveCaretToNextTokenDiffType = useCallback(pos => {
245
+ const nextTokenDiffType = getNextTokenDiffType(pos, formatRef.current);
246
+ const nextPos = nextTokenDiffType ? nextTokenDiffType.pos : formatRef.current.length;
247
+ setInputSelection({
248
+ start: nextPos,
249
+ end: nextPos
188
250
  });
189
- }, [setForwardedValue]);
190
- const closeOnInputComplete = useCallback(e => {
191
- if (e.target.selectionStart < 5) return;
192
- closeHandler();
193
- }, [closeHandler]);
194
- const timeComponent = useMemo(() => showTime && forwardedValue ? /*#__PURE__*/_jsx(TimeContainer, {
195
- children: Array.isArray(forwardedValue) ? /*#__PURE__*/_jsxs(_Fragment, {
196
- children: [/*#__PURE__*/_jsx(StyledTimePicker, {
197
- ref: firstTimePickerRef,
198
- autoFocus: true,
199
- disabled: disabled,
200
- notation: timeNotation,
201
- containerProps: timePickerStyle,
202
- value: forwardedValue[0],
203
- onChange: v => setForwardedValue([v, forwardedValue[1]]),
204
- onKeyDown: e => {
205
- if (disabled) return;
206
- if (e.key === 'Enter') {
207
- setOpened(!opened);
208
- }
209
- },
210
- onKeyUp: tabOnInputComplete
211
- }), /*#__PURE__*/_jsx(Dash, {
212
- children: "\u2013"
213
- }), /*#__PURE__*/_jsx(StyledTimePicker, {
214
- ref: secondTimePickerRef,
215
- disabled: disabled,
216
- notation: timeNotation,
217
- containerProps: timePickerStyle,
218
- value: forwardedValue[1],
219
- onChange: v => setForwardedValue([forwardedValue[0], v]),
220
- onKeyDown: e => {
221
- if (disabled) return;
222
- if (e.key === 'Enter') {
223
- setOpened(!opened);
224
- }
225
- },
226
- onKeyUp: closeOnInputComplete
227
- })]
228
- }) : /*#__PURE__*/_jsx(StyledTimePicker, {
229
- ref: firstTimePickerRef,
230
- autoFocus: true,
231
- disabled: disabled,
232
- notation: timeNotation,
233
- containerProps: timePickerStyle,
234
- value: forwardedValue,
235
- onChange: setForwardedValue,
236
- onKeyDown: e => {
237
- if (disabled) return;
238
- if (e.key === 'Enter') {
239
- setOpened(!opened);
240
- }
241
- },
242
- onKeyUp: closeOnInputComplete
243
- })
244
- }) : null, [closeOnInputComplete, disabled, forwardedValue, opened, setForwardedValue, showTime, tabOnInputComplete, timeNotation]);
251
+ }, []);
252
+ const changeHandler = useCallback((tokens, value) => {
253
+ if (!inputValueRef.current || value === null) return;
254
+ const start = inputSelectionRef.current.start;
255
+ let nextValue = inputValueRef.current;
256
+ tokens.forEach(token => {
257
+ const tokenIndex = formatRef.current.indexOf(token);
258
+ if (tokenIndex >= 0) {
259
+ nextValue = replaceSubstring(nextValue, tokenIndex, '_'.repeat(token.length));
260
+ }
261
+ });
262
+ tokens.forEach(token => {
263
+ const tokenIndex = formatRef.current.indexOf(token);
264
+ if (tokenIndex >= 0 && tokenGetterMap[token] && nextValue[tokenIndex] === '_') {
265
+ nextValue = replaceSubstring(nextValue, tokenIndex, tokenGetterMap[token](value));
266
+ }
267
+ });
268
+ setInputValue(nextValue);
269
+ moveCaretToNextTokenDiffType(start);
270
+ }, [moveCaretToNextTokenDiffType]);
271
+ const dateChangeHandler = useCallback(day => {
272
+ changeHandler(dateTokens, day);
273
+ setDay(day);
274
+ }, [changeHandler]);
275
+ const timeChangeHandler = useCallback(time => changeHandler(timeTokens, time), [changeHandler]);
276
+ const hour12 = useMemo(() => format.includes('hh'), [format]);
277
+ useEffect(() => {
278
+ if (!disabledTimesFn || !day) return;
279
+ let mounted = true;
280
+ const fn = async () => {
281
+ setLoadingTimes(true);
282
+ const disabledTimes = await disabledTimesFn(day);
283
+ if (mounted) {
284
+ setDisabledTimes(disabledTimes);
285
+ setLoadingTimes(false);
286
+ }
287
+ };
288
+ fn();
289
+ return () => {
290
+ mounted = false;
291
+ };
292
+ }, [disabledTimesFn, day]);
293
+ const pickerComponent = useMemo(() => {
294
+ if (pickerType === 'date') {
295
+ return /*#__PURE__*/_jsx(DateCalendar, {
296
+ firstDayOfWeek: firstDayOfWeek,
297
+ disabledDays: disabledDays,
298
+ locale: locale,
299
+ value: day,
300
+ onChange: dateChangeHandler
301
+ });
302
+ }
303
+ if (pickerType === 'time') {
304
+ if (loadingTimes) {
305
+ return /*#__PURE__*/_jsx(TimeGridSkeleton, {
306
+ count: times.length,
307
+ columns: timeColumns
308
+ });
309
+ }
310
+ return /*#__PURE__*/_jsx(TimeGrid, {
311
+ times: times,
312
+ hour12: hour12,
313
+ columns: timeColumns,
314
+ disabledTimes: disabledTimes,
315
+ value: time,
316
+ onChange: timeChangeHandler
317
+ });
318
+ }
319
+ return null;
320
+ }, [dateChangeHandler, day, disabledDays, disabledTimes, firstDayOfWeek, hour12, loadingTimes, locale, pickerType, time, timeChangeHandler, timeColumns, times]);
321
+ const openPicker = useCallback(() => {
322
+ if (!innerInputRef.current) return;
323
+ const next = nextToken(0, formatRef.current, tokens);
324
+ if (next) {
325
+ const type = getPickerType(next.token);
326
+ if (type) {
327
+ setInputFocused(true);
328
+ setInputSelection({
329
+ start: next.pos,
330
+ end: next.pos
331
+ });
332
+ setPickerType(type);
333
+ setPickerVisibility(true);
334
+ }
335
+ }
336
+ }, [innerInputRef]);
337
+ const focusHandler = useCallback(e => {
338
+ setInputFocused(true);
339
+ onFocus(e);
340
+ }, [onFocus]);
341
+ const blurHandler = useCallback(e => {
342
+ if (isMinXs) {
343
+ setPickerVisibility(false);
344
+ }
345
+ setInputFocused(false);
346
+ onBlur(e);
347
+ }, [isMinXs, onBlur]);
348
+ const showPickerButton = useMemo(() => showPicker && (!autoOpen || !isMinXs), [autoOpen, isMinXs, showPicker]);
245
349
  return /*#__PURE__*/_jsxs(_Fragment, {
246
- children: [/*#__PURE__*/_jsxs(SelectContainer, {
247
- opened: opened,
350
+ children: [/*#__PURE__*/_jsxs(InputContainer, {
351
+ ...containerProps,
248
352
  disabled: disabled,
249
353
  size: size,
250
- tabIndex: !disabled ? 0 : -1,
251
- onClick: () => {
252
- if (disabled) return;
253
- setOpened(!opened);
254
- },
255
- onKeyDown: e => {
256
- if (disabled) return;
257
- if (['Enter', ' '].includes(e.key)) {
258
- setOpened(!opened);
259
- e.preventDefault();
260
- }
261
- },
262
- onMouseDown: e => e.preventDefault(),
263
- onBlur: blurHandler,
264
- role: "combobox",
265
- "aria-label": forwardedValue ? getAccessibilityDateLabel(forwardedValue, locale) : undefined,
266
- "aria-disabled": disabled,
267
- ...rest,
268
354
  ref: mergedContainerRef,
269
- children: [left && /*#__PURE__*/_jsx(ThemeOverrider, {
270
- overrides: t => ({
271
- buttonPaddingHorizontal: 0.8,
272
- baseHeight: t.selectToggleListItemHeight / t.sizes.small
273
- }),
274
- children: /*#__PURE__*/_jsx(ToggleLeftAddon, {
275
- hasPadding: leftHasPadding,
276
- children: left
277
- })
278
- }), /*#__PURE__*/_jsx(ToggleContent, {
279
- hasLeft: !!left,
280
- hasRight: !!right,
281
- children: valueIsSpecified ? /*#__PURE__*/_jsx(Title, {
282
- disabled: disabled,
283
- "aria-hidden": true,
284
- children: formattedValue
285
- }) : /*#__PURE__*/_jsx(Placeholder, {
286
- children: placeholder
287
- })
288
- }), rightValue && /*#__PURE__*/_jsx(ThemeOverrider, {
289
- overrides: t => ({
290
- buttonPaddingHorizontal: 0.8,
291
- baseHeight: t.selectToggleListItemHeight / t.sizes.small
292
- }),
293
- children: /*#__PURE__*/_jsx(ToggleRightAddon, {
294
- hasPadding: rightHasPaddingValue,
295
- children: rightValue
355
+ children: [/*#__PURE__*/_jsx(StyledInputDateUnstyled, {
356
+ ...rest,
357
+ disabled: disabled,
358
+ hasRight: showPickerButton,
359
+ format: format,
360
+ value: forwardedValue,
361
+ inputValue: inputValue,
362
+ selection: inputSelection,
363
+ onChange: setForwardedValue,
364
+ onInputChange: setInputValue,
365
+ onSelectionChange: setInputSelection,
366
+ onDayChange: setDay,
367
+ onTimeChange: setTime,
368
+ onDayError: onDayError,
369
+ onFocus: focusHandler,
370
+ onBlur: blurHandler,
371
+ ref: mergedInputRef
372
+ }), showPickerButton && /*#__PURE__*/_jsx(ThemeOverrider, {
373
+ overrides: {
374
+ buttonPaddingHorizontal: 0.8
375
+ },
376
+ children: /*#__PURE__*/_jsx(PickerButtonContainer, {
377
+ children: /*#__PURE__*/_jsx(Button, {
378
+ type: "ghost",
379
+ size: "small",
380
+ wide: "never",
381
+ disabled: disabled,
382
+ onClick: openPicker,
383
+ onMouseDown: preventDefault,
384
+ children: /*#__PURE__*/_jsx(Calendar, {})
385
+ })
296
386
  })
297
387
  })]
298
- }), isMinXs ? /*#__PURE__*/_jsxs(StyledPopover, {
299
- trigger: containerRef,
388
+ }), isMinXs ? /*#__PURE__*/_jsx(StyledPopover, {
389
+ trigger: innerContainerRef,
300
390
  placement: "bottom-start",
301
- visible: opened,
302
- onClose: closeHandler,
391
+ visible: pickerVisibility,
392
+ onMouseDown: preventDefault // To prevent loosing the input focus
393
+ ,
303
394
  size: size,
304
- children: [calendarComponent, timeComponent]
305
- }) : /*#__PURE__*/_jsxs(Modal, {
306
- title: placeholder,
395
+ children: pickerComponent
396
+ }) : /*#__PURE__*/_jsx(StyledModal, {
307
397
  header: null,
308
398
  footer: null,
309
- visible: opened,
310
- onClose: closeHandler,
399
+ visible: pickerVisibility,
400
+ onClose: () => setPickerVisibility(false),
401
+ lockedFocus: false // To prevent loosing the input focus
402
+ ,
403
+ onMouseDown: preventDefault // To prevent loosing the input focus
404
+ ,
311
405
  size: size,
312
- children: [calendarComponent, timeComponent]
406
+ children: pickerComponent
313
407
  })]
314
408
  });
315
409
  });