@skbkontur/react-ui 6.1.6 → 6.1.7-1c902.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.
Files changed (152) hide show
  1. package/components/Checkbox/Checkbox.d.ts +5 -0
  2. package/components/Checkbox/Checkbox.js +42 -21
  3. package/components/Checkbox/Checkbox.js.map +1 -1
  4. package/components/Checkbox/Checkbox.mixins.d.ts +2 -0
  5. package/components/Checkbox/Checkbox.mixins.js +6 -0
  6. package/components/Checkbox/Checkbox.mixins.js.map +1 -1
  7. package/components/Checkbox/Checkbox.styles.d.ts +7 -0
  8. package/components/Checkbox/Checkbox.styles.js +23 -2
  9. package/components/Checkbox/Checkbox.styles.js.map +1 -1
  10. package/components/Group/Group.js +3 -2
  11. package/components/Group/Group.js.map +1 -1
  12. package/components/Input/Input.d.ts +1 -1
  13. package/components/Input/Input.js.map +1 -1
  14. package/components/MenuItem/MenuItem.js +1 -0
  15. package/components/MenuItem/MenuItem.js.map +1 -1
  16. package/components/MenuItem/MenuItem.styles.d.ts +1 -0
  17. package/components/MenuItem/MenuItem.styles.js +10 -7
  18. package/components/MenuItem/MenuItem.styles.js.map +1 -1
  19. package/components/Radio/Radio.d.ts +4 -0
  20. package/components/Radio/Radio.js +20 -1
  21. package/components/Radio/Radio.js.map +1 -1
  22. package/components/Radio/Radio.mixins.d.ts +2 -0
  23. package/components/Radio/Radio.mixins.js +6 -0
  24. package/components/Radio/Radio.mixins.js.map +1 -1
  25. package/components/Radio/Radio.styles.d.ts +6 -0
  26. package/components/Radio/Radio.styles.js +22 -4
  27. package/components/Radio/Radio.styles.js.map +1 -1
  28. package/components/TimePicker/TimeClockIcon.d.ts +3 -0
  29. package/components/TimePicker/TimeClockIcon.js +11 -0
  30. package/components/TimePicker/TimeClockIcon.js.map +1 -0
  31. package/components/TimePicker/TimePicker.d.ts +137 -0
  32. package/components/TimePicker/TimePicker.js +648 -0
  33. package/components/TimePicker/TimePicker.js.map +1 -0
  34. package/components/TimePicker/TimePicker.styles.d.ts +11 -0
  35. package/components/TimePicker/TimePicker.styles.js +36 -0
  36. package/components/TimePicker/TimePicker.styles.js.map +1 -0
  37. package/components/TimePicker/TimePickerItems.d.ts +20 -0
  38. package/components/TimePicker/TimePickerItems.js +108 -0
  39. package/components/TimePicker/TimePickerItems.js.map +1 -0
  40. package/components/TimePicker/TimePickerMobilePopup.d.ts +45 -0
  41. package/components/TimePicker/TimePickerMobilePopup.js +45 -0
  42. package/components/TimePicker/TimePickerMobilePopup.js.map +1 -0
  43. package/components/TimePicker/TimePickerPopup.d.ts +23 -0
  44. package/components/TimePicker/TimePickerPopup.js +18 -0
  45. package/components/TimePicker/TimePickerPopup.js.map +1 -0
  46. package/components/TimePicker/helpers/TimePicker.constants.d.ts +24 -0
  47. package/components/TimePicker/helpers/TimePicker.constants.js +33 -0
  48. package/components/TimePicker/helpers/TimePicker.constants.js.map +1 -0
  49. package/components/TimePicker/helpers/TimePicker.editing.d.ts +23 -0
  50. package/components/TimePicker/helpers/TimePicker.editing.js +101 -0
  51. package/components/TimePicker/helpers/TimePicker.editing.js.map +1 -0
  52. package/components/TimePicker/helpers/TimePicker.layout.d.ts +6 -0
  53. package/components/TimePicker/helpers/TimePicker.layout.js +49 -0
  54. package/components/TimePicker/helpers/TimePicker.layout.js.map +1 -0
  55. package/components/TimePicker/helpers/TimePicker.selection.d.ts +5 -0
  56. package/components/TimePicker/helpers/TimePicker.selection.js +23 -0
  57. package/components/TimePicker/helpers/TimePicker.selection.js.map +1 -0
  58. package/components/TimePicker/helpers/TimePicker.shared.d.ts +82 -0
  59. package/components/TimePicker/helpers/TimePicker.shared.js +94 -0
  60. package/components/TimePicker/helpers/TimePicker.shared.js.map +1 -0
  61. package/components/TimePicker/helpers/TimePicker.value.d.ts +59 -0
  62. package/components/TimePicker/helpers/TimePicker.value.js +175 -0
  63. package/components/TimePicker/helpers/TimePicker.value.js.map +1 -0
  64. package/components/TimePicker/helpers/scrollSelectedItemIntoView.d.ts +4 -0
  65. package/components/TimePicker/helpers/scrollSelectedItemIntoView.js +24 -0
  66. package/components/TimePicker/helpers/scrollSelectedItemIntoView.js.map +1 -0
  67. package/components/TimePicker/helpers/validateTimePicker.d.ts +8 -0
  68. package/components/TimePicker/helpers/validateTimePicker.js +17 -0
  69. package/components/TimePicker/helpers/validateTimePicker.js.map +1 -0
  70. package/components/TimePicker/hooks/useTimePickerDropdown.d.ts +18 -0
  71. package/components/TimePicker/hooks/useTimePickerDropdown.js +85 -0
  72. package/components/TimePicker/hooks/useTimePickerDropdown.js.map +1 -0
  73. package/components/TimePicker/hooks/useTimePickerSelection.d.ts +18 -0
  74. package/components/TimePicker/hooks/useTimePickerSelection.js +66 -0
  75. package/components/TimePicker/hooks/useTimePickerSelection.js.map +1 -0
  76. package/components/TimePicker/hooks/useTimePickerValue.d.ts +27 -0
  77. package/components/TimePicker/hooks/useTimePickerValue.js +76 -0
  78. package/components/TimePicker/hooks/useTimePickerValue.js.map +1 -0
  79. package/components/TimePicker/index.d.ts +2 -0
  80. package/components/TimePicker/index.js +2 -0
  81. package/components/TimePicker/index.js.map +1 -0
  82. package/components/TimePicker/locale/index.d.ts +4 -0
  83. package/components/TimePicker/locale/index.js +9 -0
  84. package/components/TimePicker/locale/index.js.map +1 -0
  85. package/components/TimePicker/locale/locales/en.d.ts +2 -0
  86. package/components/TimePicker/locale/locales/en.js +5 -0
  87. package/components/TimePicker/locale/locales/en.js.map +1 -0
  88. package/components/TimePicker/locale/locales/ru.d.ts +2 -0
  89. package/components/TimePicker/locale/locales/ru.js +5 -0
  90. package/components/TimePicker/locale/locales/ru.js.map +1 -0
  91. package/components/TimePicker/locale/types.d.ts +4 -0
  92. package/components/TimePicker/locale/types.js +2 -0
  93. package/components/TimePicker/locale/types.js.map +1 -0
  94. package/components/Toggle/Toggle.d.ts +5 -0
  95. package/components/Toggle/Toggle.js +46 -22
  96. package/components/Toggle/Toggle.js.map +1 -1
  97. package/components/Toggle/Toggle.mixins.d.ts +2 -0
  98. package/components/Toggle/Toggle.mixins.js +6 -0
  99. package/components/Toggle/Toggle.mixins.js.map +1 -1
  100. package/components/Toggle/Toggle.styles.d.ts +9 -0
  101. package/components/Toggle/Toggle.styles.js +29 -2
  102. package/components/Toggle/Toggle.styles.js.map +1 -1
  103. package/index.d.ts +1 -0
  104. package/index.js +1 -0
  105. package/index.js.map +1 -1
  106. package/internal/NativeTimeInput/NativeTimeInput.d.ts +16 -0
  107. package/internal/NativeTimeInput/NativeTimeInput.js +25 -0
  108. package/internal/NativeTimeInput/NativeTimeInput.js.map +1 -0
  109. package/internal/NativeTimeInput/NativeTimeInput.styles.d.ts +3 -0
  110. package/internal/NativeTimeInput/NativeTimeInput.styles.js +15 -0
  111. package/internal/NativeTimeInput/NativeTimeInput.styles.js.map +1 -0
  112. package/internal/NativeTimeInput/NativeTimeInput.utils.d.ts +7 -0
  113. package/internal/NativeTimeInput/NativeTimeInput.utils.js +28 -0
  114. package/internal/NativeTimeInput/NativeTimeInput.utils.js.map +1 -0
  115. package/internal/NativeTimeInput/index.d.ts +1 -0
  116. package/internal/NativeTimeInput/index.js +2 -0
  117. package/internal/NativeTimeInput/index.js.map +1 -0
  118. package/internal/TimeInput/TimeFragments.d.ts +15 -0
  119. package/internal/TimeInput/TimeFragments.js +72 -0
  120. package/internal/TimeInput/TimeFragments.js.map +1 -0
  121. package/internal/TimeInput/TimeFragments.styles.d.ts +12 -0
  122. package/internal/TimeInput/TimeFragments.styles.js +43 -0
  123. package/internal/TimeInput/TimeFragments.styles.js.map +1 -0
  124. package/internal/TimeInput/TimeInput.d.ts +22 -0
  125. package/internal/TimeInput/TimeInput.js +103 -0
  126. package/internal/TimeInput/TimeInput.js.map +1 -0
  127. package/internal/TimeInput/TimeInput.styles.d.ts +6 -0
  128. package/internal/TimeInput/TimeInput.styles.js +21 -0
  129. package/internal/TimeInput/TimeInput.styles.js.map +1 -0
  130. package/internal/TimeInput/index.d.ts +1 -0
  131. package/internal/TimeInput/index.js +2 -0
  132. package/internal/TimeInput/index.js.map +1 -0
  133. package/internal/icons2022/TimeClockIcon/TimeClockIcon16Light.d.ts +2 -0
  134. package/internal/icons2022/TimeClockIcon/TimeClockIcon16Light.js +20 -0
  135. package/internal/icons2022/TimeClockIcon/TimeClockIcon16Light.js.map +1 -0
  136. package/internal/icons2022/TimeClockIcon/TimeClockIcon20Light.d.ts +2 -0
  137. package/internal/icons2022/TimeClockIcon/TimeClockIcon20Light.js +20 -0
  138. package/internal/icons2022/TimeClockIcon/TimeClockIcon20Light.js.map +1 -0
  139. package/internal/icons2022/TimeClockIcon/TimeClockIcon24Regular.d.ts +2 -0
  140. package/internal/icons2022/TimeClockIcon/TimeClockIcon24Regular.js +20 -0
  141. package/internal/icons2022/TimeClockIcon/TimeClockIcon24Regular.js.map +1 -0
  142. package/internal/themes/BasicTheme.d.ts +65 -0
  143. package/internal/themes/BasicTheme.js +253 -0
  144. package/internal/themes/BasicTheme.js.map +1 -1
  145. package/internal/themes/DarkTheme6_0.js +1 -0
  146. package/internal/themes/DarkTheme6_0.js.map +1 -1
  147. package/lib/locale/types.d.ts +2 -0
  148. package/lib/locale/types.js.map +1 -1
  149. package/lib/utils.d.ts +2 -0
  150. package/lib/utils.js +1 -0
  151. package/lib/utils.js.map +1 -1
  152. package/package.json +9 -1
@@ -0,0 +1,175 @@
1
+ import { DIGIT_REGEXP, EMPTY_SEGMENT, EMPTY_VALUE, TIME_SEPARATOR } from './TimePicker.constants.js';
2
+ import { getDigits, getDisplaySegments, getTimeSegments, normalizeTimeSegment, sanitizeSegment, getTimeItemLabel, getTimeItemValue, isTimeItemDisabled, isTimeItem, } from './TimePicker.shared.js';
3
+ /** Проверяет, содержит ли display-значение хотя бы одну введенную цифру. */
4
+ export var isTimeDisplayEmpty = function (value) { return !DIGIT_REGEXP.test(value); };
5
+ /** Приводит значение поля — элемент, строку или пустое значение — к строке времени. */
6
+ export var getTimeValueString = function (value) {
7
+ if (value === null || value === undefined) {
8
+ return EMPTY_VALUE;
9
+ }
10
+ return getTimeItemValue(value);
11
+ };
12
+ /**
13
+ * Разбирает элементы источника для отрисовки: достает время и подпись,
14
+ * а `disabled` дополняет проверкой диапазона `minTime`/`maxTime`.
15
+ * Исходный элемент сохраняется как есть — именно он уходит в `onValueChange`.
16
+ * React-элементы остаются на своих местах.
17
+ */
18
+ export var resolveTimeItems = function (items, format, minTime, maxTime) {
19
+ return items.map(function (item) {
20
+ if (!isTimeItem(item)) {
21
+ return item;
22
+ }
23
+ var value = getTimeItemValue(item);
24
+ return {
25
+ item: item,
26
+ value: value,
27
+ label: getTimeItemLabel(item),
28
+ disabled: isTimeItemDisabled(item) || isTimeValueOutOfRange(value, format, minTime, maxTime),
29
+ };
30
+ });
31
+ };
32
+ /**
33
+ * Оставляет в списке только первый элемент для каждого времени.
34
+ * Времена сравниваются после нормализации к текущему формату,
35
+ * поэтому в формате `HH:mm` элементы `12:00` и `12:00:30` считаются одинаковыми.
36
+ * React-элементы не участвуют в сравнении и остаются на своих местах.
37
+ */
38
+ export var dedupeTimeItems = function (items, format) {
39
+ var usedValues = new Set();
40
+ return items.filter(function (item) {
41
+ if (!isTimeItem(item)) {
42
+ return true;
43
+ }
44
+ var normalizedValue = normalizeTimeValue(getTimeItemValue(item), format);
45
+ if (usedValues.has(normalizedValue)) {
46
+ return false;
47
+ }
48
+ usedValues.add(normalizedValue);
49
+ return true;
50
+ });
51
+ };
52
+ /**
53
+ * Проверяет, выходит ли значение за диапазон `minTime`/`maxTime` после нормализации.
54
+ * Пустое значение не считается выходящим за диапазон. Если `minTime > maxTime`, диапазон трактуется как переходящий через полночь.
55
+ */
56
+ export var isTimeValueOutOfRange = function (value, format, minTime, maxTime) {
57
+ var normalizedValue = normalizeTimeValue(value, format);
58
+ if (normalizedValue === EMPTY_VALUE) {
59
+ return false;
60
+ }
61
+ var normalizedMinTime = normalizeTimeRangeValue(minTime, format);
62
+ var normalizedMaxTime = normalizeTimeRangeValue(maxTime, format);
63
+ if (normalizedMinTime && normalizedMaxTime && normalizedMinTime > normalizedMaxTime) {
64
+ return normalizedValue < normalizedMinTime && normalizedValue > normalizedMaxTime;
65
+ }
66
+ return ((normalizedMinTime !== undefined && normalizedValue < normalizedMinTime) ||
67
+ (normalizedMaxTime !== undefined && normalizedValue > normalizedMaxTime));
68
+ };
69
+ /**
70
+ * Нормализует display-значение в committed-форму `HH:mm[:ss]`.
71
+ * Частично заполненные сегменты дополняются и ограничиваются максимумами сегментов.
72
+ */
73
+ export var normalizeTimeValue = function (value, format) {
74
+ if (isTimeDisplayEmpty(value)) {
75
+ return EMPTY_VALUE;
76
+ }
77
+ return getTimeSegments(format)
78
+ .map(function (segment, index) { return normalizeTimeSegment(getDisplaySegments(value, format)[index], segment); })
79
+ .join(TIME_SEPARATOR);
80
+ };
81
+ var normalizeTimeRangeValue = function (value, format) {
82
+ if (!value) {
83
+ return undefined;
84
+ }
85
+ var normalizedValue = normalizeTimeValue(value, format);
86
+ return normalizedValue === EMPTY_VALUE ? undefined : normalizedValue;
87
+ };
88
+ /**
89
+ * Преобразует display-значение в partial raw value для `onValueChange`.
90
+ * Заполненные сегменты дополняются до двух цифр, пропущенные сегменты до последнего заполненного становятся `00`.
91
+ */
92
+ export var serializeTimeValue = function (value, format) {
93
+ var serializedSegments = getDisplaySegments(value, format).map(function (segmentValue) {
94
+ var digits = getDigits(segmentValue);
95
+ return digits ? digits.padStart(EMPTY_SEGMENT.length, '0') : EMPTY_VALUE;
96
+ });
97
+ var lastFilledIndex = serializedSegments.reduce(function (result, segmentValue, index) { return (segmentValue ? index : result); }, -1);
98
+ if (lastFilledIndex < 0) {
99
+ return EMPTY_VALUE;
100
+ }
101
+ return serializedSegments
102
+ .slice(0, lastFilledIndex + 1)
103
+ .map(function (segmentValue) { return segmentValue || '00'; })
104
+ .join(TIME_SEPARATOR);
105
+ };
106
+ /** Возвращает display-значение с плейсхолдерами из partial или committed value. */
107
+ export var getTimeDisplayValue = function (value, format) {
108
+ if (value === EMPTY_VALUE) {
109
+ return EMPTY_VALUE;
110
+ }
111
+ return getDisplaySegments(value, format).join(TIME_SEPARATOR);
112
+ };
113
+ /** Заменяет значение выбранного сегмента, сохраняя остальные сегменты display-значения без изменений. */
114
+ export var replaceTimeSegment = function (value, segment, nextSegmentValue, format) {
115
+ var segments = getDisplaySegments(value, format);
116
+ var index = getTimeSegments(format).indexOf(segment);
117
+ segments[index] = sanitizeSegment(nextSegmentValue);
118
+ return segments.join(TIME_SEPARATOR);
119
+ };
120
+ /**
121
+ * Парсит вставленное пользователем значение и сразу преобразует его в committed-форму.
122
+ */
123
+ export var parsePastedTimeValue = function (value, format) {
124
+ if (!DIGIT_REGEXP.test(value)) {
125
+ return EMPTY_VALUE;
126
+ }
127
+ var segments = getDisplaySegments(value, format);
128
+ return normalizeTimeValue(segments.join(TIME_SEPARATOR), format);
129
+ };
130
+ /** Возвращает текущее display-значение сегмента или пустой сегмент, если индекс отсутствует. */
131
+ export var getTimeSegmentValue = function (value, segment, format) {
132
+ var _a;
133
+ var segments = getDisplaySegments(value, format);
134
+ var index = getTimeSegments(format).indexOf(segment);
135
+ return (_a = segments[index]) !== null && _a !== void 0 ? _a : EMPTY_SEGMENT;
136
+ };
137
+ /** Возвращает полностью пустое display-значение для выбранной точности времени. */
138
+ export var getEmptyDisplayValue = function (precision) {
139
+ return getTimeSegments(precision)
140
+ .map(function () { return EMPTY_SEGMENT; })
141
+ .join(TIME_SEPARATOR);
142
+ };
143
+ /**
144
+ * Преобразует display-значение в поисковый запрос для фильтрации элементов.
145
+ * Сегменты содержат только введенные цифры, незаполненный хвост отбрасывается: `12:3_` => `12:3`, `1_:__` => `1`.
146
+ * Позиции сегментов сохраняются, поэтому ведущие незаполненные сегменты остаются пустыми: `__:34` => `:34`.
147
+ * Это нужно для посегментного сравнения в `filterTimeItems` и передается как есть в пользовательскую `source`.
148
+ */
149
+ export var getTimeFilterQuery = function (value, format) {
150
+ var segments = getDisplaySegments(value, format).map(getDigits);
151
+ var lastFilledIndex = segments.reduce(function (result, segmentValue, index) { return (segmentValue ? index : result); }, -1);
152
+ if (lastFilledIndex < 0) {
153
+ return EMPTY_VALUE;
154
+ }
155
+ return segments.slice(0, lastFilledIndex + 1).join(TIME_SEPARATOR);
156
+ };
157
+ /**
158
+ * Дефолтная функция фильтрации элементов по запросу из поля ввода.
159
+ * Сравнивает запрос посегментно: введенные цифры сегмента должны быть префиксом соответствующего сегмента элемента.
160
+ * Пустой запрос возвращает все элементы.
161
+ */
162
+ export var filterTimeItems = function (items, query, format) {
163
+ var querySegments = query.split(TIME_SEPARATOR).map(getDigits);
164
+ if (querySegments.every(function (segmentValue) { return !segmentValue; })) {
165
+ return items;
166
+ }
167
+ return items.filter(function (item) {
168
+ if (!isTimeItem(item)) {
169
+ return true;
170
+ }
171
+ var itemSegments = getDisplaySegments(normalizeTimeValue(getTimeItemValue(item), format), format);
172
+ return querySegments.every(function (segmentValue, index) { var _a; return !segmentValue || ((_a = itemSegments[index]) !== null && _a !== void 0 ? _a : EMPTY_VALUE).startsWith(segmentValue); });
173
+ });
174
+ };
175
+ //# sourceMappingURL=TimePicker.value.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TimePicker.value.js","sourceRoot":"","sources":["TimePicker.value.ts"],"names":[],"mappings":"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","sourcesContent":["import { DIGIT_REGEXP, EMPTY_SEGMENT, EMPTY_VALUE, TIME_SEPARATOR } from './TimePicker.constants.js';\nimport {\n getDigits,\n getDisplaySegments,\n getTimeSegments,\n normalizeTimeSegment,\n sanitizeSegment,\n getTimeItemLabel,\n getTimeItemValue,\n isTimeItemDisabled,\n type TimeFormat,\n type TimeItemValue,\n type TimePickerExtendedItem,\n type TimePickerMenuItem,\n type TimeSegment,\n isTimeItem,\n} from './TimePicker.shared.js';\n\n/** Проверяет, содержит ли display-значение хотя бы одну введенную цифру. */\nexport const isTimeDisplayEmpty = (value: string): boolean => !DIGIT_REGEXP.test(value);\n\n/** Приводит значение поля — элемент, строку или пустое значение — к строке времени. */\nexport const getTimeValueString = (value: TimeItemValue | null | undefined): string => {\n if (value === null || value === undefined) {\n return EMPTY_VALUE;\n }\n\n return getTimeItemValue(value);\n};\n\n/**\n * Разбирает элементы источника для отрисовки: достает время и подпись,\n * а `disabled` дополняет проверкой диапазона `minTime`/`maxTime`.\n * Исходный элемент сохраняется как есть — именно он уходит в `onValueChange`.\n * React-элементы остаются на своих местах.\n */\nexport const resolveTimeItems = <T extends TimeItemValue>(\n items: Array<TimePickerExtendedItem<T>>,\n format: TimeFormat,\n minTime?: string,\n maxTime?: string,\n): Array<TimePickerMenuItem<T>> =>\n items.map((item) => {\n if (!isTimeItem(item)) {\n return item;\n }\n\n const value = getTimeItemValue(item);\n\n return {\n item,\n value,\n label: getTimeItemLabel(item),\n disabled: isTimeItemDisabled(item) || isTimeValueOutOfRange(value, format, minTime, maxTime),\n };\n });\n\n/**\n * Оставляет в списке только первый элемент для каждого времени.\n * Времена сравниваются после нормализации к текущему формату,\n * поэтому в формате `HH:mm` элементы `12:00` и `12:00:30` считаются одинаковыми.\n * React-элементы не участвуют в сравнении и остаются на своих местах.\n */\nexport const dedupeTimeItems = <T extends TimeItemValue>(\n items: Array<TimePickerExtendedItem<T>>,\n format: TimeFormat,\n): Array<TimePickerExtendedItem<T>> => {\n const usedValues = new Set<string>();\n\n return items.filter((item) => {\n if (!isTimeItem(item)) {\n return true;\n }\n\n const normalizedValue = normalizeTimeValue(getTimeItemValue(item), format);\n\n if (usedValues.has(normalizedValue)) {\n return false;\n }\n\n usedValues.add(normalizedValue);\n\n return true;\n });\n};\n\n/**\n * Проверяет, выходит ли значение за диапазон `minTime`/`maxTime` после нормализации.\n * Пустое значение не считается выходящим за диапазон. Если `minTime > maxTime`, диапазон трактуется как переходящий через полночь.\n */\nexport const isTimeValueOutOfRange = (\n value: string,\n format: TimeFormat,\n minTime?: string,\n maxTime?: string,\n): boolean => {\n const normalizedValue = normalizeTimeValue(value, format);\n\n if (normalizedValue === EMPTY_VALUE) {\n return false;\n }\n\n const normalizedMinTime = normalizeTimeRangeValue(minTime, format);\n const normalizedMaxTime = normalizeTimeRangeValue(maxTime, format);\n\n if (normalizedMinTime && normalizedMaxTime && normalizedMinTime > normalizedMaxTime) {\n return normalizedValue < normalizedMinTime && normalizedValue > normalizedMaxTime;\n }\n\n return (\n (normalizedMinTime !== undefined && normalizedValue < normalizedMinTime) ||\n (normalizedMaxTime !== undefined && normalizedValue > normalizedMaxTime)\n );\n};\n\n/**\n * Нормализует display-значение в committed-форму `HH:mm[:ss]`.\n * Частично заполненные сегменты дополняются и ограничиваются максимумами сегментов.\n */\nexport const normalizeTimeValue = (value: string, format: TimeFormat): string => {\n if (isTimeDisplayEmpty(value)) {\n return EMPTY_VALUE;\n }\n\n return getTimeSegments(format)\n .map((segment, index) => normalizeTimeSegment(getDisplaySegments(value, format)[index], segment))\n .join(TIME_SEPARATOR);\n};\n\nconst normalizeTimeRangeValue = (value: string | undefined, format: TimeFormat): string | undefined => {\n if (!value) {\n return undefined;\n }\n\n const normalizedValue = normalizeTimeValue(value, format);\n\n return normalizedValue === EMPTY_VALUE ? undefined : normalizedValue;\n};\n\n/**\n * Преобразует display-значение в partial raw value для `onValueChange`.\n * Заполненные сегменты дополняются до двух цифр, пропущенные сегменты до последнего заполненного становятся `00`.\n */\nexport const serializeTimeValue = (value: string, format: TimeFormat): string => {\n const serializedSegments = getDisplaySegments(value, format).map((segmentValue) => {\n const digits = getDigits(segmentValue);\n\n return digits ? digits.padStart(EMPTY_SEGMENT.length, '0') : EMPTY_VALUE;\n });\n\n const lastFilledIndex = serializedSegments.reduce(\n (result, segmentValue, index) => (segmentValue ? index : result),\n -1,\n );\n\n if (lastFilledIndex < 0) {\n return EMPTY_VALUE;\n }\n\n return serializedSegments\n .slice(0, lastFilledIndex + 1)\n .map((segmentValue) => segmentValue || '00')\n .join(TIME_SEPARATOR);\n};\n\n/** Возвращает display-значение с плейсхолдерами из partial или committed value. */\nexport const getTimeDisplayValue = (value: string, format: TimeFormat): string => {\n if (value === EMPTY_VALUE) {\n return EMPTY_VALUE;\n }\n\n return getDisplaySegments(value, format).join(TIME_SEPARATOR);\n};\n\n/** Заменяет значение выбранного сегмента, сохраняя остальные сегменты display-значения без изменений. */\nexport const replaceTimeSegment = (\n value: string,\n segment: TimeSegment,\n nextSegmentValue: string,\n format: TimeFormat,\n): string => {\n const segments = getDisplaySegments(value, format);\n const index = getTimeSegments(format).indexOf(segment);\n\n segments[index] = sanitizeSegment(nextSegmentValue);\n\n return segments.join(TIME_SEPARATOR);\n};\n\n/**\n * Парсит вставленное пользователем значение и сразу преобразует его в committed-форму.\n */\nexport const parsePastedTimeValue = (value: string, format: TimeFormat): string => {\n if (!DIGIT_REGEXP.test(value)) {\n return EMPTY_VALUE;\n }\n\n const segments = getDisplaySegments(value, format);\n\n return normalizeTimeValue(segments.join(TIME_SEPARATOR), format);\n};\n\n/** Возвращает текущее display-значение сегмента или пустой сегмент, если индекс отсутствует. */\nexport const getTimeSegmentValue = (value: string, segment: TimeSegment, format: TimeFormat): string => {\n const segments = getDisplaySegments(value, format);\n const index = getTimeSegments(format).indexOf(segment);\n\n return segments[index] ?? EMPTY_SEGMENT;\n};\n\n/** Возвращает полностью пустое display-значение для выбранной точности времени. */\nexport const getEmptyDisplayValue = (precision: TimeFormat): string =>\n getTimeSegments(precision)\n .map(() => EMPTY_SEGMENT)\n .join(TIME_SEPARATOR);\n\n/**\n * Преобразует display-значение в поисковый запрос для фильтрации элементов.\n * Сегменты содержат только введенные цифры, незаполненный хвост отбрасывается: `12:3_` => `12:3`, `1_:__` => `1`.\n * Позиции сегментов сохраняются, поэтому ведущие незаполненные сегменты остаются пустыми: `__:34` => `:34`.\n * Это нужно для посегментного сравнения в `filterTimeItems` и передается как есть в пользовательскую `source`.\n */\nexport const getTimeFilterQuery = (value: string, format: TimeFormat): string => {\n const segments = getDisplaySegments(value, format).map(getDigits);\n\n const lastFilledIndex = segments.reduce((result, segmentValue, index) => (segmentValue ? index : result), -1);\n\n if (lastFilledIndex < 0) {\n return EMPTY_VALUE;\n }\n\n return segments.slice(0, lastFilledIndex + 1).join(TIME_SEPARATOR);\n};\n\n/**\n * Дефолтная функция фильтрации элементов по запросу из поля ввода.\n * Сравнивает запрос посегментно: введенные цифры сегмента должны быть префиксом соответствующего сегмента элемента.\n * Пустой запрос возвращает все элементы.\n */\nexport const filterTimeItems = <T extends TimeItemValue>(\n items: Array<TimePickerExtendedItem<T>>,\n query: string,\n format: TimeFormat,\n): Array<TimePickerExtendedItem<T>> => {\n const querySegments = query.split(TIME_SEPARATOR).map(getDigits);\n\n if (querySegments.every((segmentValue) => !segmentValue)) {\n return items;\n }\n\n return items.filter((item) => {\n if (!isTimeItem(item)) {\n return true;\n }\n\n const itemSegments = getDisplaySegments(normalizeTimeValue(getTimeItemValue(item), format), format);\n\n return querySegments.every(\n (segmentValue, index) => !segmentValue || (itemSegments[index] ?? EMPTY_VALUE).startsWith(segmentValue),\n );\n });\n};\n"]}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Прокручивает ближайший scrollable-контейнер так, чтобы выбранный элемент оказался ближе к центру viewport контейнера.
3
+ */
4
+ export declare const scrollSelectedItemIntoView: (element: HTMLElement) => void;
@@ -0,0 +1,24 @@
1
+ import { findNearestScrollableParent } from '../../../lib/dom/scrollYCenterIntoNearestScrollable.js';
2
+ import { getOwnerGlobalObject, isBrowser } from '../../../lib/globalObject.js';
3
+ /**
4
+ * Прокручивает ближайший scrollable-контейнер так, чтобы выбранный элемент оказался ближе к центру viewport контейнера.
5
+ */
6
+ export var scrollSelectedItemIntoView = function (element) {
7
+ var globalObject = getOwnerGlobalObject(element);
8
+ if (!isBrowser(globalObject)) {
9
+ return;
10
+ }
11
+ var parent = findNearestScrollableParent(element);
12
+ if (!parent) {
13
+ return;
14
+ }
15
+ var elementRect = element.getBoundingClientRect();
16
+ var parentRect = parent.getBoundingClientRect();
17
+ var scrollTopPos = elementRect.top - parentRect.top;
18
+ var scrollBottomPos = elementRect.bottom - parentRect.bottom;
19
+ var scrollCenterPos = (scrollTopPos + scrollBottomPos) / 2;
20
+ if (scrollCenterPos !== 0) {
21
+ parent.scrollTo({ top: parent.scrollTop + scrollCenterPos });
22
+ }
23
+ };
24
+ //# sourceMappingURL=scrollSelectedItemIntoView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scrollSelectedItemIntoView.js","sourceRoot":"","sources":["scrollSelectedItemIntoView.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,wDAAwD,CAAC;AACrG,OAAO,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAE/E;;GAEG;AACH,MAAM,CAAC,IAAM,0BAA0B,GAAG,UAAC,OAAoB;IAC7D,IAAM,YAAY,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAEnD,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7B,OAAO;IACT,CAAC;IAED,IAAM,MAAM,GAAG,2BAA2B,CAAC,OAAO,CAAC,CAAC;IAEpD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO;IACT,CAAC;IAED,IAAM,WAAW,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC;IACpD,IAAM,UAAU,GAAG,MAAM,CAAC,qBAAqB,EAAE,CAAC;IAElD,IAAM,YAAY,GAAG,WAAW,CAAC,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC;IACtD,IAAM,eAAe,GAAG,WAAW,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;IAC/D,IAAM,eAAe,GAAG,CAAC,YAAY,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IAE7D,IAAI,eAAe,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,SAAS,GAAG,eAAe,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC,CAAC","sourcesContent":["import { findNearestScrollableParent } from '../../../lib/dom/scrollYCenterIntoNearestScrollable.js';\nimport { getOwnerGlobalObject, isBrowser } from '../../../lib/globalObject.js';\n\n/**\n * Прокручивает ближайший scrollable-контейнер так, чтобы выбранный элемент оказался ближе к центру viewport контейнера.\n */\nexport const scrollSelectedItemIntoView = (element: HTMLElement): void => {\n const globalObject = getOwnerGlobalObject(element);\n\n if (!isBrowser(globalObject)) {\n return;\n }\n\n const parent = findNearestScrollableParent(element);\n\n if (!parent) {\n return;\n }\n\n const elementRect = element.getBoundingClientRect();\n const parentRect = parent.getBoundingClientRect();\n\n const scrollTopPos = elementRect.top - parentRect.top;\n const scrollBottomPos = elementRect.bottom - parentRect.bottom;\n const scrollCenterPos = (scrollTopPos + scrollBottomPos) / 2;\n\n if (scrollCenterPos !== 0) {\n parent.scrollTo({ top: parent.scrollTop + scrollCenterPos });\n }\n};\n"]}
@@ -0,0 +1,8 @@
1
+ import type { Nullable } from '../../../typings/utility-types.js';
2
+ import type { TimeFormat, TimeItem } from './TimePicker.shared.js';
3
+ export interface TimePickerValidationOptions {
4
+ format?: TimeFormat;
5
+ minTime?: string;
6
+ maxTime?: string;
7
+ }
8
+ export declare const validateTimePicker: (value: Nullable<string | TimeItem>, options?: TimePickerValidationOptions) => boolean;
@@ -0,0 +1,17 @@
1
+ import { getTimeDisplayValue, getTimeValueString, isTimeValueOutOfRange, normalizeTimeValue, } from './TimePicker.value.js';
2
+ export var validateTimePicker = function (value, options) {
3
+ if (options === void 0) { options = {}; }
4
+ var timeValue = getTimeValueString(value);
5
+ if (!timeValue) {
6
+ return false;
7
+ }
8
+ var _a = options.format, format = _a === void 0 ? 'HH:mm' : _a, minTime = options.minTime, maxTime = options.maxTime;
9
+ if (getTimeDisplayValue(timeValue, format) !== timeValue) {
10
+ return false;
11
+ }
12
+ if (normalizeTimeValue(timeValue, format) !== timeValue) {
13
+ return false;
14
+ }
15
+ return !isTimeValueOutOfRange(timeValue, format, minTime, maxTime);
16
+ };
17
+ //# sourceMappingURL=validateTimePicker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validateTimePicker.js","sourceRoot":"","sources":["validateTimePicker.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAQ/B,MAAM,CAAC,IAAM,kBAAkB,GAAG,UAChC,KAAkC,EAClC,OAAyC;IAAzC,wBAAA,EAAA,YAAyC;IAEzC,IAAM,SAAS,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAE5C,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,IAAA,KAAuC,OAAO,OAA9B,EAAhB,MAAM,mBAAG,OAAO,KAAA,EAAE,OAAO,GAAc,OAAO,QAArB,EAAE,OAAO,GAAK,OAAO,QAAZ,CAAa;IAEvD,IAAI,mBAAmB,CAAC,SAAS,EAAE,MAAM,CAAC,KAAK,SAAS,EAAE,CAAC;QACzD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,kBAAkB,CAAC,SAAS,EAAE,MAAM,CAAC,KAAK,SAAS,EAAE,CAAC;QACxD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,CAAC,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AACrE,CAAC,CAAC","sourcesContent":["import type { Nullable } from '../../../typings/utility-types.js';\nimport type { TimeFormat, TimeItem } from './TimePicker.shared.js';\nimport {\n getTimeDisplayValue,\n getTimeValueString,\n isTimeValueOutOfRange,\n normalizeTimeValue,\n} from './TimePicker.value.js';\n\nexport interface TimePickerValidationOptions {\n format?: TimeFormat;\n minTime?: string;\n maxTime?: string;\n}\n\nexport const validateTimePicker = (\n value: Nullable<string | TimeItem>,\n options: TimePickerValidationOptions = {},\n): boolean => {\n const timeValue = getTimeValueString(value);\n\n if (!timeValue) {\n return false;\n }\n\n const { format = 'HH:mm', minTime, maxTime } = options;\n\n if (getTimeDisplayValue(timeValue, format) !== timeValue) {\n return false;\n }\n\n if (normalizeTimeValue(timeValue, format) !== timeValue) {\n return false;\n }\n\n return !isTimeValueOutOfRange(timeValue, format, minTime, maxTime);\n};\n"]}
@@ -0,0 +1,18 @@
1
+ import { type TimeItemValue, type TimePickerMenuItem } from '../helpers/TimePicker.shared.js';
2
+ interface UseTimePickerDropdownOptions<T extends TimeItemValue> {
3
+ hasDropdown: boolean;
4
+ disabled?: boolean;
5
+ items: Array<TimePickerMenuItem<T>>;
6
+ selectedItemIndex: number | null;
7
+ autoHighlightKey: string | null;
8
+ }
9
+ interface UseTimePickerDropdownResult {
10
+ isDropdownOpened: boolean;
11
+ highlightedItemIndex: number | null;
12
+ openDropdown(): void;
13
+ closeDropdown(): void;
14
+ resetHighlightedItem(): void;
15
+ tryNavigateItems(step: 1 | -1): boolean;
16
+ }
17
+ export declare const useTimePickerDropdown: <T extends TimeItemValue>(options: UseTimePickerDropdownOptions<T>) => UseTimePickerDropdownResult;
18
+ export {};
@@ -0,0 +1,85 @@
1
+ import { useCallback, useEffect, useRef, useState } from 'react';
2
+ import { isTimeMenuItem } from '../helpers/TimePicker.shared.js';
3
+ export var useTimePickerDropdown = function (options) {
4
+ var hasDropdown = options.hasDropdown, disabled = options.disabled, items = options.items, selectedItemIndex = options.selectedItemIndex, autoHighlightKey = options.autoHighlightKey;
5
+ var _a = useState(false), isDropdownOpened = _a[0], setIsDropdownOpened = _a[1];
6
+ var _b = useState(null), highlightedItemIndex = _b[0], setHighlightedItemIndex = _b[1];
7
+ var lastAutoHighlightKeyRef = useRef(null);
8
+ var openDropdown = useCallback(function () {
9
+ if (!hasDropdown || disabled) {
10
+ return;
11
+ }
12
+ setIsDropdownOpened(true);
13
+ }, [disabled, hasDropdown]);
14
+ var closeDropdown = useCallback(function () {
15
+ setIsDropdownOpened(false);
16
+ setHighlightedItemIndex(null);
17
+ }, []);
18
+ var resetHighlightedItem = useCallback(function () {
19
+ setHighlightedItemIndex(null);
20
+ }, []);
21
+ useEffect(function () {
22
+ if (lastAutoHighlightKeyRef.current === autoHighlightKey) {
23
+ return;
24
+ }
25
+ lastAutoHighlightKeyRef.current = autoHighlightKey;
26
+ if (autoHighlightKey === null) {
27
+ setHighlightedItemIndex(null);
28
+ return;
29
+ }
30
+ var firstEnabledItemIndex = items.findIndex(function (item) { return isTimeMenuItem(item) && !item.disabled; });
31
+ setHighlightedItemIndex(firstEnabledItemIndex >= 0 ? firstEnabledItemIndex : null);
32
+ }, [autoHighlightKey, items]);
33
+ useEffect(function () {
34
+ setHighlightedItemIndex(function (current) {
35
+ if (current === null) {
36
+ return current;
37
+ }
38
+ var item = items[current];
39
+ return !item || !isTimeMenuItem(item) || item.disabled ? null : current;
40
+ });
41
+ }, [items]);
42
+ var tryNavigateItems = useCallback(function (step) {
43
+ if (!hasDropdown || !isDropdownOpened) {
44
+ return false;
45
+ }
46
+ var enabledIndexes = items
47
+ .map(function (item, index) { return ({ item: item, index: index }); })
48
+ .filter(function (_a) {
49
+ var item = _a.item;
50
+ return isTimeMenuItem(item) && !item.disabled;
51
+ })
52
+ .map(function (_a) {
53
+ var index = _a.index;
54
+ return index;
55
+ });
56
+ if (enabledIndexes.length === 0) {
57
+ return false;
58
+ }
59
+ if (highlightedItemIndex === null) {
60
+ if (selectedItemIndex !== null) {
61
+ var selectedEnabledIndex = enabledIndexes.indexOf(selectedItemIndex);
62
+ if (selectedEnabledIndex >= 0) {
63
+ var nextEnabledIndex_1 = enabledIndexes[selectedEnabledIndex + step];
64
+ setHighlightedItemIndex(nextEnabledIndex_1 !== null && nextEnabledIndex_1 !== void 0 ? nextEnabledIndex_1 : (step > 0 ? enabledIndexes[0] : enabledIndexes[enabledIndexes.length - 1]));
65
+ return true;
66
+ }
67
+ }
68
+ setHighlightedItemIndex(step > 0 ? enabledIndexes[0] : enabledIndexes[enabledIndexes.length - 1]);
69
+ return true;
70
+ }
71
+ var currentIndex = enabledIndexes.indexOf(highlightedItemIndex);
72
+ var nextEnabledIndex = enabledIndexes[currentIndex + step];
73
+ setHighlightedItemIndex(nextEnabledIndex !== null && nextEnabledIndex !== void 0 ? nextEnabledIndex : (step > 0 ? enabledIndexes[0] : enabledIndexes[enabledIndexes.length - 1]));
74
+ return true;
75
+ }, [hasDropdown, highlightedItemIndex, isDropdownOpened, selectedItemIndex, items]);
76
+ return {
77
+ isDropdownOpened: isDropdownOpened,
78
+ highlightedItemIndex: highlightedItemIndex,
79
+ openDropdown: openDropdown,
80
+ closeDropdown: closeDropdown,
81
+ resetHighlightedItem: resetHighlightedItem,
82
+ tryNavigateItems: tryNavigateItems,
83
+ };
84
+ };
85
+ //# sourceMappingURL=useTimePickerDropdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTimePickerDropdown.js","sourceRoot":"","sources":["useTimePickerDropdown.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\n\nimport { isTimeMenuItem, type TimeItemValue, type TimePickerMenuItem } from '../helpers/TimePicker.shared.js';\n\ninterface UseTimePickerDropdownOptions<T extends TimeItemValue> {\n hasDropdown: boolean;\n disabled?: boolean;\n items: Array<TimePickerMenuItem<T>>;\n selectedItemIndex: number | null;\n autoHighlightKey: string | null;\n}\n\ninterface UseTimePickerDropdownResult {\n isDropdownOpened: boolean;\n highlightedItemIndex: number | null;\n openDropdown(): void;\n closeDropdown(): void;\n resetHighlightedItem(): void;\n tryNavigateItems(step: 1 | -1): boolean;\n}\n\nexport const useTimePickerDropdown = <T extends TimeItemValue>(\n options: UseTimePickerDropdownOptions<T>,\n): UseTimePickerDropdownResult => {\n const { hasDropdown, disabled, items, selectedItemIndex, autoHighlightKey } = options;\n\n const [isDropdownOpened, setIsDropdownOpened] = useState(false);\n const [highlightedItemIndex, setHighlightedItemIndex] = useState<number | null>(null);\n const lastAutoHighlightKeyRef = useRef<string | null>(null);\n\n const openDropdown = useCallback(() => {\n if (!hasDropdown || disabled) {\n return;\n }\n\n setIsDropdownOpened(true);\n }, [disabled, hasDropdown]);\n\n const closeDropdown = useCallback(() => {\n setIsDropdownOpened(false);\n setHighlightedItemIndex(null);\n }, []);\n\n const resetHighlightedItem = useCallback(() => {\n setHighlightedItemIndex(null);\n }, []);\n\n useEffect(() => {\n if (lastAutoHighlightKeyRef.current === autoHighlightKey) {\n return;\n }\n\n lastAutoHighlightKeyRef.current = autoHighlightKey;\n\n if (autoHighlightKey === null) {\n setHighlightedItemIndex(null);\n return;\n }\n\n const firstEnabledItemIndex = items.findIndex((item) => isTimeMenuItem(item) && !item.disabled);\n setHighlightedItemIndex(firstEnabledItemIndex >= 0 ? firstEnabledItemIndex : null);\n }, [autoHighlightKey, items]);\n\n useEffect(() => {\n setHighlightedItemIndex((current) => {\n if (current === null) {\n return current;\n }\n\n const item = items[current];\n\n return !item || !isTimeMenuItem(item) || item.disabled ? null : current;\n });\n }, [items]);\n\n const tryNavigateItems = useCallback(\n (step: 1 | -1) => {\n if (!hasDropdown || !isDropdownOpened) {\n return false;\n }\n\n const enabledIndexes = items\n .map((item, index) => ({ item, index }))\n .filter(({ item }) => isTimeMenuItem(item) && !item.disabled)\n .map(({ index }) => index);\n\n if (enabledIndexes.length === 0) {\n return false;\n }\n\n if (highlightedItemIndex === null) {\n if (selectedItemIndex !== null) {\n const selectedEnabledIndex = enabledIndexes.indexOf(selectedItemIndex);\n\n if (selectedEnabledIndex >= 0) {\n const nextEnabledIndex = enabledIndexes[selectedEnabledIndex + step];\n\n setHighlightedItemIndex(\n nextEnabledIndex ?? (step > 0 ? enabledIndexes[0] : enabledIndexes[enabledIndexes.length - 1]),\n );\n return true;\n }\n }\n\n setHighlightedItemIndex(step > 0 ? enabledIndexes[0] : enabledIndexes[enabledIndexes.length - 1]);\n return true;\n }\n\n const currentIndex = enabledIndexes.indexOf(highlightedItemIndex);\n const nextEnabledIndex = enabledIndexes[currentIndex + step];\n\n setHighlightedItemIndex(\n nextEnabledIndex ?? (step > 0 ? enabledIndexes[0] : enabledIndexes[enabledIndexes.length - 1]),\n );\n\n return true;\n },\n [hasDropdown, highlightedItemIndex, isDropdownOpened, selectedItemIndex, items],\n );\n\n return {\n isDropdownOpened,\n highlightedItemIndex,\n openDropdown,\n closeDropdown,\n resetHighlightedItem,\n tryNavigateItems,\n };\n};\n"]}
@@ -0,0 +1,18 @@
1
+ import type { TimeInputRef } from '../../../internal/TimeInput/index.js';
2
+ import type { TimeFormat, TimeSegment } from '../helpers/TimePicker.shared.js';
3
+ type TimePickerSelection = TimeSegment | 'all';
4
+ interface UseTimePickerSelectionOptions {
5
+ isInputFocused: boolean;
6
+ format: TimeFormat;
7
+ getInput: () => TimeInputRef | null;
8
+ displayValue: string;
9
+ }
10
+ interface UseTimePickerSelectionResult {
11
+ selection: TimePickerSelection;
12
+ selectedSegment: TimeSegment;
13
+ selectSegment: (segment: TimeSegment) => void;
14
+ selectAll: () => void;
15
+ syncSelectionWithDOM: () => boolean;
16
+ }
17
+ export declare const useTimePickerSelection: (options: UseTimePickerSelectionOptions) => UseTimePickerSelectionResult;
18
+ export {};
@@ -0,0 +1,66 @@
1
+ import { useCallback, useLayoutEffect, useState } from 'react';
2
+ export var useTimePickerSelection = function (options) {
3
+ var isInputFocused = options.isInputFocused, format = options.format, displayValue = options.displayValue, getInput = options.getInput;
4
+ var _a = useState('hours'), selection = _a[0], setSelectionState = _a[1];
5
+ var selectedSegment = selection === 'all' ? 'hours' : selection;
6
+ var applySelectionToInput = useCallback(function (nextSelection) {
7
+ var currentInput = getInput();
8
+ if (!currentInput) {
9
+ return;
10
+ }
11
+ var node = currentInput.getNode();
12
+ var isInputActive = (node === null || node === void 0 ? void 0 : node.ownerDocument.activeElement) === node;
13
+ var applySelection = function (input) {
14
+ if (nextSelection === 'all') {
15
+ input.selectAll();
16
+ return;
17
+ }
18
+ input.selectSegment(nextSelection);
19
+ };
20
+ if (isInputActive) {
21
+ applySelection(currentInput);
22
+ return;
23
+ }
24
+ setTimeout(function () {
25
+ var nextInput = getInput();
26
+ if (!nextInput) {
27
+ return;
28
+ }
29
+ nextInput.focus();
30
+ applySelection(nextInput);
31
+ }, 0);
32
+ }, [getInput]);
33
+ var selectSegment = useCallback(function (segment) {
34
+ if (segment === 'seconds' && format === 'HH:mm') {
35
+ return;
36
+ }
37
+ setSelectionState(segment);
38
+ applySelectionToInput(segment);
39
+ }, [applySelectionToInput, format]);
40
+ var selectAll = useCallback(function () {
41
+ setSelectionState('all');
42
+ applySelectionToInput('all');
43
+ }, [applySelectionToInput]);
44
+ var syncSelectionWithDOM = useCallback(function () {
45
+ var _a;
46
+ if (!((_a = getInput()) === null || _a === void 0 ? void 0 : _a.isAllSelected())) {
47
+ return false;
48
+ }
49
+ setSelectionState('all');
50
+ return true;
51
+ }, [getInput]);
52
+ useLayoutEffect(function () {
53
+ if (!isInputFocused || !getInput()) {
54
+ return;
55
+ }
56
+ applySelectionToInput(selection);
57
+ }, [applySelectionToInput, displayValue, getInput, isInputFocused, selection]);
58
+ return {
59
+ selection: selection,
60
+ selectedSegment: selectedSegment,
61
+ selectSegment: selectSegment,
62
+ selectAll: selectAll,
63
+ syncSelectionWithDOM: syncSelectionWithDOM,
64
+ };
65
+ };
66
+ //# sourceMappingURL=useTimePickerSelection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTimePickerSelection.js","sourceRoot":"","sources":["useTimePickerSelection.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useLayoutEffect, useState } from 'react';\n\nimport type { TimeInputRef } from '../../../internal/TimeInput/index.js';\nimport type { TimeFormat, TimeSegment } from '../helpers/TimePicker.shared.js';\n\ntype TimePickerSelection = TimeSegment | 'all';\n\ninterface UseTimePickerSelectionOptions {\n isInputFocused: boolean;\n format: TimeFormat;\n getInput: () => TimeInputRef | null;\n displayValue: string;\n}\ninterface UseTimePickerSelectionResult {\n selection: TimePickerSelection;\n selectedSegment: TimeSegment;\n selectSegment: (segment: TimeSegment) => void;\n selectAll: () => void;\n syncSelectionWithDOM: () => boolean;\n}\nexport const useTimePickerSelection = (options: UseTimePickerSelectionOptions): UseTimePickerSelectionResult => {\n const { isInputFocused, format, displayValue, getInput } = options;\n\n const [selection, setSelectionState] = useState<TimePickerSelection>('hours');\n\n const selectedSegment = selection === 'all' ? 'hours' : selection;\n\n const applySelectionToInput = useCallback(\n (nextSelection: TimePickerSelection) => {\n const currentInput = getInput();\n\n if (!currentInput) {\n return;\n }\n\n const node = currentInput.getNode();\n const isInputActive = node?.ownerDocument.activeElement === node;\n\n const applySelection = (input: TimeInputRef) => {\n if (nextSelection === 'all') {\n input.selectAll();\n return;\n }\n\n input.selectSegment(nextSelection);\n };\n\n if (isInputActive) {\n applySelection(currentInput);\n return;\n }\n\n setTimeout(() => {\n const nextInput = getInput();\n\n if (!nextInput) {\n return;\n }\n\n nextInput.focus();\n applySelection(nextInput);\n }, 0);\n },\n [getInput],\n );\n\n const selectSegment = useCallback(\n (segment: TimeSegment) => {\n if (segment === 'seconds' && format === 'HH:mm') {\n return;\n }\n\n setSelectionState(segment);\n applySelectionToInput(segment);\n },\n [applySelectionToInput, format],\n );\n\n const selectAll = useCallback(() => {\n setSelectionState('all');\n applySelectionToInput('all');\n }, [applySelectionToInput]);\n\n const syncSelectionWithDOM = useCallback(() => {\n if (!getInput()?.isAllSelected()) {\n return false;\n }\n\n setSelectionState('all');\n return true;\n }, [getInput]);\n\n useLayoutEffect(() => {\n if (!isInputFocused || !getInput()) {\n return;\n }\n\n applySelectionToInput(selection);\n }, [applySelectionToInput, displayValue, getInput, isInputFocused, selection]);\n\n return {\n selection,\n selectedSegment,\n selectSegment,\n selectAll,\n syncSelectionWithDOM,\n };\n};\n"]}
@@ -0,0 +1,27 @@
1
+ import type { RefObject } from 'react';
2
+ import { type TimeFormat, type TimeItemValue } from '../helpers/TimePicker.shared.js';
3
+ interface UseTimePickerValueOptions {
4
+ isInputFocused: boolean;
5
+ /** Внешнее значение, приведенное к строке времени. */
6
+ externalValue: string;
7
+ format: TimeFormat;
8
+ /**
9
+ * Вызывается при коммите значения: получает нормализованное время
10
+ * и элемент из `source`, если значение выбрано в выпадающем меню.
11
+ */
12
+ onCommitValue(value: string, item: TimeItemValue | null): void;
13
+ onInputValueChange?(value: string): void;
14
+ }
15
+ interface UseTimePickerValueResult {
16
+ editingValue: string;
17
+ editingValueRef: RefObject<string>;
18
+ setEditingValue(value: string): void;
19
+ updateEditingValue(value: string): void;
20
+ commitEditingValue(): string;
21
+ /** Коммитит значение, введенное пользователем. Не эмитит повторно то же самое время. */
22
+ commitValue(value: string, item?: TimeItemValue | null): string;
23
+ /** Коммитит элемент, выбранный в выпадающем меню. Эмитит всегда, так как это явное действие пользователя. */
24
+ commitItem(item: TimeItemValue): string;
25
+ }
26
+ export declare const useTimePickerValue: (options: UseTimePickerValueOptions) => UseTimePickerValueResult;
27
+ export {};
@@ -0,0 +1,76 @@
1
+ import { useCallback, useEffect, useRef, useState } from 'react';
2
+ import { EMPTY_VALUE } from '../helpers/TimePicker.constants.js';
3
+ import { getTimeItemValue } from '../helpers/TimePicker.shared.js';
4
+ import { getTimeDisplayValue, isTimeDisplayEmpty, normalizeTimeValue, serializeTimeValue, } from '../helpers/TimePicker.value.js';
5
+ export var useTimePickerValue = function (options) {
6
+ var externalValue = options.externalValue, format = options.format, isInputFocused = options.isInputFocused, onCommitValue = options.onCommitValue, onInputValueChange = options.onInputValueChange;
7
+ var externalEditingValue = getTimeDisplayValue(externalValue, format);
8
+ var _a = useState(externalEditingValue), editingValue = _a[0], setEditingValueState = _a[1];
9
+ var editingValueRef = useRef(editingValue);
10
+ var emittedInputValueRef = useRef(externalValue);
11
+ var emittedValueRef = useRef(externalValue);
12
+ var lastEmittedValueRef = useRef(externalValue);
13
+ var syncEmittedValues = useCallback(function (nextValue) {
14
+ emittedInputValueRef.current = nextValue;
15
+ emittedValueRef.current = nextValue;
16
+ lastEmittedValueRef.current = nextValue;
17
+ }, []);
18
+ var setEditingValue = useCallback(function (nextEditingValue) {
19
+ editingValueRef.current = nextEditingValue;
20
+ setEditingValueState(nextEditingValue);
21
+ }, []);
22
+ var emitInputValue = useCallback(function (nextValue) {
23
+ if (emittedInputValueRef.current !== nextValue) {
24
+ emittedInputValueRef.current = nextValue;
25
+ lastEmittedValueRef.current = nextValue;
26
+ onInputValueChange === null || onInputValueChange === void 0 ? void 0 : onInputValueChange(nextValue);
27
+ }
28
+ }, [onInputValueChange]);
29
+ var emitValue = useCallback(function (nextValue, item) {
30
+ emittedValueRef.current = nextValue;
31
+ lastEmittedValueRef.current = nextValue;
32
+ onCommitValue(nextValue, item);
33
+ }, [onCommitValue]);
34
+ var updateEditingValue = useCallback(function (nextEditingValue) {
35
+ setEditingValue(nextEditingValue);
36
+ emitInputValue(serializeTimeValue(nextEditingValue, format));
37
+ }, [emitInputValue, format, setEditingValue]);
38
+ var commitValue = useCallback(function (nextValue, item) {
39
+ if (item === void 0) { item = null; }
40
+ var normalizedValue = normalizeTimeValue(nextValue, format);
41
+ setEditingValue(normalizedValue);
42
+ if (emittedValueRef.current !== normalizedValue) {
43
+ emitValue(normalizedValue, item);
44
+ }
45
+ return normalizedValue;
46
+ }, [emitValue, format, setEditingValue]);
47
+ var commitItem = useCallback(function (item) {
48
+ var normalizedValue = normalizeTimeValue(getTimeItemValue(item), format);
49
+ setEditingValue(normalizedValue);
50
+ emitValue(normalizedValue, item);
51
+ return normalizedValue;
52
+ }, [emitValue, format, setEditingValue]);
53
+ var commitEditingValue = useCallback(function () {
54
+ var currentEditingValue = editingValueRef.current;
55
+ if (isTimeDisplayEmpty(currentEditingValue)) {
56
+ return commitValue(EMPTY_VALUE);
57
+ }
58
+ return commitValue(currentEditingValue);
59
+ }, [commitValue, editingValueRef]);
60
+ useEffect(function () {
61
+ if (!isInputFocused || externalValue !== lastEmittedValueRef.current) {
62
+ setEditingValue(externalEditingValue);
63
+ }
64
+ syncEmittedValues(externalValue);
65
+ }, [externalEditingValue, externalValue, isInputFocused, setEditingValue, syncEmittedValues]);
66
+ return {
67
+ editingValue: editingValue,
68
+ editingValueRef: editingValueRef,
69
+ setEditingValue: setEditingValue,
70
+ updateEditingValue: updateEditingValue,
71
+ commitEditingValue: commitEditingValue,
72
+ commitValue: commitValue,
73
+ commitItem: commitItem,
74
+ };
75
+ };
76
+ //# sourceMappingURL=useTimePickerValue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTimePickerValue.js","sourceRoot":"","sources":["useTimePickerValue.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RefObject } from 'react';\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nimport { EMPTY_VALUE } from '../helpers/TimePicker.constants.js';\nimport { getTimeItemValue, type TimeFormat, type TimeItemValue } from '../helpers/TimePicker.shared.js';\nimport {\n getTimeDisplayValue,\n isTimeDisplayEmpty,\n normalizeTimeValue,\n serializeTimeValue,\n} from '../helpers/TimePicker.value.js';\n\ninterface UseTimePickerValueOptions {\n isInputFocused: boolean;\n /** Внешнее значение, приведенное к строке времени. */\n externalValue: string;\n format: TimeFormat;\n /**\n * Вызывается при коммите значения: получает нормализованное время\n * и элемент из `source`, если значение выбрано в выпадающем меню.\n */\n onCommitValue(value: string, item: TimeItemValue | null): void;\n onInputValueChange?(value: string): void;\n}\n\ninterface UseTimePickerValueResult {\n editingValue: string;\n editingValueRef: RefObject<string>;\n setEditingValue(value: string): void;\n updateEditingValue(value: string): void;\n commitEditingValue(): string;\n /** Коммитит значение, введенное пользователем. Не эмитит повторно то же самое время. */\n commitValue(value: string, item?: TimeItemValue | null): string;\n /** Коммитит элемент, выбранный в выпадающем меню. Эмитит всегда, так как это явное действие пользователя. */\n commitItem(item: TimeItemValue): string;\n}\n\nexport const useTimePickerValue = (options: UseTimePickerValueOptions): UseTimePickerValueResult => {\n const { externalValue, format, isInputFocused, onCommitValue, onInputValueChange } = options;\n\n const externalEditingValue = getTimeDisplayValue(externalValue, format);\n\n const [editingValue, setEditingValueState] = useState<string>(externalEditingValue);\n\n const editingValueRef = useRef(editingValue);\n const emittedInputValueRef = useRef(externalValue);\n const emittedValueRef = useRef(externalValue);\n const lastEmittedValueRef = useRef(externalValue);\n\n const syncEmittedValues = useCallback((nextValue: string) => {\n emittedInputValueRef.current = nextValue;\n emittedValueRef.current = nextValue;\n lastEmittedValueRef.current = nextValue;\n }, []);\n\n const setEditingValue = useCallback((nextEditingValue: string) => {\n editingValueRef.current = nextEditingValue;\n setEditingValueState(nextEditingValue);\n }, []);\n\n const emitInputValue = useCallback(\n (nextValue: string) => {\n if (emittedInputValueRef.current !== nextValue) {\n emittedInputValueRef.current = nextValue;\n lastEmittedValueRef.current = nextValue;\n onInputValueChange?.(nextValue);\n }\n },\n [onInputValueChange],\n );\n\n const emitValue = useCallback(\n (nextValue: string, item: TimeItemValue | null) => {\n emittedValueRef.current = nextValue;\n lastEmittedValueRef.current = nextValue;\n onCommitValue(nextValue, item);\n },\n [onCommitValue],\n );\n\n const updateEditingValue = useCallback(\n (nextEditingValue: string) => {\n setEditingValue(nextEditingValue);\n emitInputValue(serializeTimeValue(nextEditingValue, format));\n },\n [emitInputValue, format, setEditingValue],\n );\n\n const commitValue = useCallback(\n (nextValue: string, item: TimeItemValue | null = null): string => {\n const normalizedValue = normalizeTimeValue(nextValue, format);\n\n setEditingValue(normalizedValue);\n\n if (emittedValueRef.current !== normalizedValue) {\n emitValue(normalizedValue, item);\n }\n\n return normalizedValue;\n },\n [emitValue, format, setEditingValue],\n );\n\n const commitItem = useCallback(\n (item: TimeItemValue): string => {\n const normalizedValue = normalizeTimeValue(getTimeItemValue(item), format);\n\n setEditingValue(normalizedValue);\n emitValue(normalizedValue, item);\n\n return normalizedValue;\n },\n [emitValue, format, setEditingValue],\n );\n\n const commitEditingValue = useCallback((): string => {\n const currentEditingValue = editingValueRef.current;\n\n if (isTimeDisplayEmpty(currentEditingValue)) {\n return commitValue(EMPTY_VALUE);\n }\n\n return commitValue(currentEditingValue);\n }, [commitValue, editingValueRef]);\n\n useEffect(() => {\n if (!isInputFocused || externalValue !== lastEmittedValueRef.current) {\n setEditingValue(externalEditingValue);\n }\n\n syncEmittedValues(externalValue);\n }, [externalEditingValue, externalValue, isInputFocused, setEditingValue, syncEmittedValues]);\n\n return {\n editingValue,\n editingValueRef,\n setEditingValue,\n updateEditingValue,\n commitEditingValue,\n commitValue,\n commitItem,\n };\n};\n"]}