@skbkontur/react-ui 6.2.0 → 6.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/components/Group/Group.js +3 -2
- package/components/Group/Group.js.map +1 -1
- package/components/Input/Input.d.ts +1 -1
- package/components/Input/Input.js.map +1 -1
- package/components/MenuItem/MenuItem.d.ts +1 -1
- package/components/MenuItem/MenuItem.js.map +1 -1
- package/components/Switcher/Switcher.d.ts +1 -1
- package/components/Switcher/Switcher.js +1 -1
- package/components/Switcher/Switcher.js.map +1 -1
- package/components/TimePicker/TimeClockIcon.d.ts +3 -0
- package/components/TimePicker/TimeClockIcon.js +11 -0
- package/components/TimePicker/TimeClockIcon.js.map +1 -0
- package/components/TimePicker/TimePicker.d.ts +144 -0
- package/components/TimePicker/TimePicker.js +795 -0
- package/components/TimePicker/TimePicker.js.map +1 -0
- package/components/TimePicker/TimePicker.styles.d.ts +12 -0
- package/components/TimePicker/TimePicker.styles.js +39 -0
- package/components/TimePicker/TimePicker.styles.js.map +1 -0
- package/components/TimePicker/TimePickerItems.d.ts +23 -0
- package/components/TimePicker/TimePickerItems.js +115 -0
- package/components/TimePicker/TimePickerItems.js.map +1 -0
- package/components/TimePicker/TimePickerMobilePopup.d.ts +48 -0
- package/components/TimePicker/TimePickerMobilePopup.js +45 -0
- package/components/TimePicker/TimePickerMobilePopup.js.map +1 -0
- package/components/TimePicker/TimePickerPopup.d.ts +26 -0
- package/components/TimePicker/TimePickerPopup.js +18 -0
- package/components/TimePicker/TimePickerPopup.js.map +1 -0
- package/components/TimePicker/helpers/TimePicker.constants.d.ts +31 -0
- package/components/TimePicker/helpers/TimePicker.constants.js +34 -0
- package/components/TimePicker/helpers/TimePicker.constants.js.map +1 -0
- package/components/TimePicker/helpers/TimePicker.editing.d.ts +19 -0
- package/components/TimePicker/helpers/TimePicker.editing.js +74 -0
- package/components/TimePicker/helpers/TimePicker.editing.js.map +1 -0
- package/components/TimePicker/helpers/TimePicker.layout.d.ts +6 -0
- package/components/TimePicker/helpers/TimePicker.layout.js +49 -0
- package/components/TimePicker/helpers/TimePicker.layout.js.map +1 -0
- package/components/TimePicker/helpers/TimePicker.selection.d.ts +5 -0
- package/components/TimePicker/helpers/TimePicker.selection.js +23 -0
- package/components/TimePicker/helpers/TimePicker.selection.js.map +1 -0
- package/components/TimePicker/helpers/TimePicker.shared.d.ts +71 -0
- package/components/TimePicker/helpers/TimePicker.shared.js +90 -0
- package/components/TimePicker/helpers/TimePicker.shared.js.map +1 -0
- package/components/TimePicker/helpers/TimePicker.value.d.ts +69 -0
- package/components/TimePicker/helpers/TimePicker.value.js +225 -0
- package/components/TimePicker/helpers/TimePicker.value.js.map +1 -0
- package/components/TimePicker/helpers/scrollSelectedItemIntoView.d.ts +6 -0
- package/components/TimePicker/helpers/scrollSelectedItemIntoView.js +26 -0
- package/components/TimePicker/helpers/scrollSelectedItemIntoView.js.map +1 -0
- package/components/TimePicker/helpers/validateTimePicker.d.ts +8 -0
- package/components/TimePicker/helpers/validateTimePicker.js +16 -0
- package/components/TimePicker/helpers/validateTimePicker.js.map +1 -0
- package/components/TimePicker/index.d.ts +4 -0
- package/components/TimePicker/index.js +3 -0
- package/components/TimePicker/index.js.map +1 -0
- package/components/TimePicker/locale/index.d.ts +4 -0
- package/components/TimePicker/locale/index.js +9 -0
- package/components/TimePicker/locale/index.js.map +1 -0
- package/components/TimePicker/locale/locales/en.d.ts +2 -0
- package/components/TimePicker/locale/locales/en.js +7 -0
- package/components/TimePicker/locale/locales/en.js.map +1 -0
- package/components/TimePicker/locale/locales/ru.d.ts +2 -0
- package/components/TimePicker/locale/locales/ru.js +7 -0
- package/components/TimePicker/locale/locales/ru.js.map +1 -0
- package/components/TimePicker/locale/types.d.ts +6 -0
- package/components/TimePicker/locale/types.js +2 -0
- package/components/TimePicker/locale/types.js.map +1 -0
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/index.js.map +1 -1
- package/internal/NativeTimeInput/NativeTimeInput.d.ts +20 -0
- package/internal/NativeTimeInput/NativeTimeInput.js +30 -0
- package/internal/NativeTimeInput/NativeTimeInput.js.map +1 -0
- package/internal/NativeTimeInput/NativeTimeInput.styles.d.ts +3 -0
- package/internal/NativeTimeInput/NativeTimeInput.styles.js +15 -0
- package/internal/NativeTimeInput/NativeTimeInput.styles.js.map +1 -0
- package/internal/NativeTimeInput/NativeTimeInput.utils.d.ts +9 -0
- package/internal/NativeTimeInput/NativeTimeInput.utils.js +24 -0
- package/internal/NativeTimeInput/NativeTimeInput.utils.js.map +1 -0
- package/internal/NativeTimeInput/index.d.ts +1 -0
- package/internal/NativeTimeInput/index.js +2 -0
- package/internal/NativeTimeInput/index.js.map +1 -0
- package/internal/TimeInput/TimeFragments.d.ts +14 -0
- package/internal/TimeInput/TimeFragments.js +94 -0
- package/internal/TimeInput/TimeFragments.js.map +1 -0
- package/internal/TimeInput/TimeFragments.styles.d.ts +32 -0
- package/internal/TimeInput/TimeFragments.styles.js +78 -0
- package/internal/TimeInput/TimeFragments.styles.js.map +1 -0
- package/internal/TimeInput/TimeInput.d.ts +21 -0
- package/internal/TimeInput/TimeInput.js +104 -0
- package/internal/TimeInput/TimeInput.js.map +1 -0
- package/internal/TimeInput/TimeInput.styles.d.ts +7 -0
- package/internal/TimeInput/TimeInput.styles.js +24 -0
- package/internal/TimeInput/TimeInput.styles.js.map +1 -0
- package/internal/TimeInput/index.d.ts +1 -0
- package/internal/TimeInput/index.js +2 -0
- package/internal/TimeInput/index.js.map +1 -0
- package/internal/TimePicker/useTimePickerDropdown.d.ts +23 -0
- package/internal/TimePicker/useTimePickerDropdown.js +67 -0
- package/internal/TimePicker/useTimePickerDropdown.js.map +1 -0
- package/internal/TimePicker/useTimePickerSelection.d.ts +18 -0
- package/internal/TimePicker/useTimePickerSelection.js +66 -0
- package/internal/TimePicker/useTimePickerSelection.js.map +1 -0
- package/internal/TimePicker/useTimePickerSource.d.ts +29 -0
- package/internal/TimePicker/useTimePickerSource.js +67 -0
- package/internal/TimePicker/useTimePickerSource.js.map +1 -0
- package/internal/TimePicker/useTimePickerValue.d.ts +35 -0
- package/internal/TimePicker/useTimePickerValue.js +94 -0
- package/internal/TimePicker/useTimePickerValue.js.map +1 -0
- package/internal/icons2022/TimeClockIcon/TimeClockIcon16Light.d.ts +2 -0
- package/internal/icons2022/TimeClockIcon/TimeClockIcon16Light.js +20 -0
- package/internal/icons2022/TimeClockIcon/TimeClockIcon16Light.js.map +1 -0
- package/internal/icons2022/TimeClockIcon/TimeClockIcon20Light.d.ts +2 -0
- package/internal/icons2022/TimeClockIcon/TimeClockIcon20Light.js +20 -0
- package/internal/icons2022/TimeClockIcon/TimeClockIcon20Light.js.map +1 -0
- package/internal/icons2022/TimeClockIcon/TimeClockIcon24Regular.d.ts +2 -0
- package/internal/icons2022/TimeClockIcon/TimeClockIcon24Regular.js +20 -0
- package/internal/icons2022/TimeClockIcon/TimeClockIcon24Regular.js.map +1 -0
- package/internal/themes/BasicTheme.d.ts +34 -0
- package/internal/themes/BasicTheme.js +90 -0
- package/internal/themes/BasicTheme.js.map +1 -1
- package/internal/themes/DarkTheme6_0.js +3 -0
- package/internal/themes/DarkTheme6_0.js.map +1 -1
- package/internal/themes/DarkTheme6_2.d.ts +1 -0
- package/internal/themes/DarkTheme6_2.js +30 -0
- package/internal/themes/DarkTheme6_2.js.map +1 -0
- package/internal/themes/DarkTheme6_3.d.ts +1 -0
- package/internal/themes/DarkTheme6_3.js +30 -0
- package/internal/themes/DarkTheme6_3.js.map +1 -0
- package/internal/themes/LightTheme6_2.d.ts +1 -0
- package/internal/themes/LightTheme6_2.js +30 -0
- package/internal/themes/LightTheme6_2.js.map +1 -0
- package/internal/themes/LightTheme6_3.d.ts +1 -0
- package/internal/themes/LightTheme6_3.js +30 -0
- package/internal/themes/LightTheme6_3.js.map +1 -0
- package/lib/locale/types.d.ts +2 -0
- package/lib/locale/types.js.map +1 -1
- package/lib/theming/ThemeVersions.d.ts +1 -1
- package/lib/theming/ThemeVersions.js.map +1 -1
- package/lib/theming/themes/DarkTheme.d.ts +2 -0
- package/lib/theming/themes/DarkTheme.js +5 -1
- package/lib/theming/themes/DarkTheme.js.map +1 -1
- package/lib/theming/themes/LightTheme.d.ts +2 -0
- package/lib/theming/themes/LightTheme.js +5 -1
- package/lib/theming/themes/LightTheme.js.map +1 -1
- package/lib/utils.d.ts +2 -0
- package/lib/utils.js +1 -0
- package/lib/utils.js.map +1 -1
- package/package.json +11 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TimePickerPopup.js","sourceRoot":"","sources":["TimePickerPopup.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAE1C,OAAO,EAAE,KAAK,EAAE,MAAM,+BAA+B,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,gCAAgC,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,sCAAsC,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AAGjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAEvE,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAuBvD,MAAM,CAAC,IAAM,eAAe,GAAG,UAA0B,KAA8B;IAEnF,IAAA,EAAE,GAkBA,KAAK,GAlBL,EACF,aAAa,GAiBX,KAAK,cAjBM,EACb,OAAO,GAgBL,KAAK,QAhBA,EACP,SAAS,GAeP,KAAK,UAfE,EACT,SAAS,GAcP,KAAK,UAdE,EACT,cAAc,GAaZ,KAAK,eAbO,EACd,IAAI,GAYF,KAAK,KAZH,EACJ,aAAa,GAWX,KAAK,cAXM,EACb,UAAU,GAUR,KAAK,WAVG,EACV,SAAS,GASP,KAAK,UATE,EACT,QAAQ,GAQN,KAAK,SARC,EACR,kBAAkB,GAOhB,KAAK,mBAPW,EAClB,mBAAmB,GAMjB,KAAK,oBANY,EACnB,oBAAoB,GAKlB,KAAK,qBALa,EACpB,aAAa,GAIX,KAAK,cAJM,EACb,QAAQ,GAGN,KAAK,SAHC,EACR,OAAO,GAEL,KAAK,QAFA,EACP,YAAY,GACV,KAAK,aADK,CACJ;IAEV,IAAM,KAAK,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;IACvC,IAAM,MAAM,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;IAEpC,OAAO,CACL,oBAAC,KAAK,IACJ,MAAM,QACN,SAAS,QACT,aAAa,EAAE,aAAa,cAClB,kBAAkB,CAAC,KAAK,EAClC,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC,SAAS,EACrC,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,qBAAqB,CAAC,EAC7C,KAAK,EAAE,SAAS,EAChB,QAAQ,EAAE,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EACtD,SAAS,EAAE,gBAAgB,CAAC,OAAO,EAAE,SAAS,CAAC;QAE/C,6BAAK,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,UAAC,KAAK,IAAK,OAAA,KAAK,CAAC,cAAc,EAAE,EAAtB,CAAsB;YAC1G,oBAAC,eAAe,IACd,YAAY,EAAE,EAAE,EAChB,IAAI,EAAE,IAAI,EACV,aAAa,EAAE,aAAa,EAC5B,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,QAAQ,EAClB,kBAAkB,EAAE,kBAAkB,EACtC,mBAAmB,EAAE,mBAAmB,EACxC,oBAAoB,EAAE,oBAAoB,EAC1C,aAAa,EAAE,aAAa,EAC5B,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,cAAc,EACzB,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,YAAY,GAC1B,CACE,CACA,CACT,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import React, { useContext } from 'react';\n\nimport { Popup } from '../../internal/Popup/index.js';\nimport { ZIndex } from '../../internal/ZIndex/index.js';\nimport { getMenuPositions } from '../../lib/getMenuPositions.js';\nimport { useStyles } from '../../lib/renderEnvironment/index.js';\nimport { ThemeContext } from '../../lib/theming/ThemeContext.js';\nimport type { SizeProp } from '../../lib/types/props.js';\nimport type { MenuItemState } from '../MenuItem/index.js';\nimport { TimePickerDataTids } from './helpers/TimePicker.constants.js';\nimport type { TimeItemValue, TimePickerMenuItem } from './helpers/TimePicker.shared.js';\nimport { getStyles } from './TimePicker.styles.js';\nimport { TimePickerItems } from './TimePickerItems.js';\n\ninterface TimePickerPopupProps<T extends TimeItemValue> {\n id?: string;\n anchorElement: HTMLElement;\n menuPos?: 'top' | 'bottom';\n menuAlign?: 'left' | 'right';\n menuWidth?: React.CSSProperties['width'];\n popupMaxHeight: string;\n size: SizeProp;\n resolvedItems: Array<TimePickerMenuItem<T>>;\n renderItem?: (item: T, state: MenuItemState) => React.ReactNode;\n isLoading?: boolean;\n isFailed: boolean;\n errorNetworkButton: string;\n errorNetworkMessage: string;\n highlightedItemIndex: number | null;\n selectedValue: string;\n itemRefs: React.RefObject<Map<number, HTMLSpanElement>>;\n onRetry(): void;\n onSelectItem(item: T): void;\n}\n\nexport const TimePickerPopup = <T extends TimeItemValue>(props: TimePickerPopupProps<T>) => {\n const {\n id,\n anchorElement,\n menuPos,\n menuAlign,\n menuWidth,\n popupMaxHeight,\n size,\n resolvedItems,\n renderItem,\n isLoading,\n isFailed,\n errorNetworkButton,\n errorNetworkMessage,\n highlightedItemIndex,\n selectedValue,\n itemRefs,\n onRetry,\n onSelectItem,\n } = props;\n\n const theme = useContext(ThemeContext);\n const styles = useStyles(getStyles);\n\n return (\n <Popup\n opened\n hasShadow\n anchorElement={anchorElement}\n data-tid={TimePickerDataTids.popup}\n priority={ZIndex.priorities.PopupMenu}\n margin={parseInt(theme.timePickerMenuOffsetY)}\n width={menuWidth}\n minWidth={menuWidth === undefined ? '100%' : undefined}\n positions={getMenuPositions(menuPos, menuAlign)}\n >\n <div id={id} role={'listbox'} className={styles.popup(theme)} onMouseDown={(event) => event.preventDefault()}>\n <TimePickerItems\n itemIdPrefix={id}\n size={size}\n resolvedItems={resolvedItems}\n renderItem={renderItem}\n isLoading={isLoading}\n isFailed={isFailed}\n errorNetworkButton={errorNetworkButton}\n errorNetworkMessage={errorNetworkMessage}\n highlightedItemIndex={highlightedItemIndex}\n selectedValue={selectedValue}\n itemRefs={itemRefs}\n maxHeight={popupMaxHeight}\n onRetry={onRetry}\n onSelectItem={onSelectItem}\n />\n </div>\n </Popup>\n );\n};\n"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { TimeFormat, TimeSegment } from './TimePicker.shared.js';
|
|
2
|
+
export declare const TimePickerDataTids: {
|
|
3
|
+
readonly root: "TimePicker__root";
|
|
4
|
+
readonly input: "TimePicker__input";
|
|
5
|
+
readonly mobileInput: "TimePicker__mobileInput";
|
|
6
|
+
readonly nativeInput: "TimePicker__nativeInput";
|
|
7
|
+
readonly popup: "TimePicker__popup";
|
|
8
|
+
readonly mobilePopup: "TimePicker__mobilePopup";
|
|
9
|
+
readonly item: "TimePicker__item";
|
|
10
|
+
readonly loading: "TimePicker__loading";
|
|
11
|
+
readonly failed: "TimePicker__failed";
|
|
12
|
+
readonly inputLoading: "TimePicker__inputLoading";
|
|
13
|
+
};
|
|
14
|
+
/** Больше двух десятков часов не бывает: такая первая цифра сразу завершает сегмент. */
|
|
15
|
+
export declare const HOURS_FIRST_DIGIT_MAX = 2;
|
|
16
|
+
export declare const TIME_PLACEHOLDER_CHAR = "\u2212";
|
|
17
|
+
export declare const TIME_SEPARATOR = ":";
|
|
18
|
+
export declare const TIME_SEGMENT_LENGTH = 2;
|
|
19
|
+
export declare const HOURS_MAX_VALUE = 23;
|
|
20
|
+
export declare const MINUTES_AND_SECONDS_MAX_VALUE = 59;
|
|
21
|
+
export declare const ZERO_PAD_CHAR = "0";
|
|
22
|
+
export declare const EMPTY_VALUE = "";
|
|
23
|
+
export declare const DIGIT_REGEXP: RegExp;
|
|
24
|
+
export declare const NON_DIGIT_REGEXP: RegExp;
|
|
25
|
+
export declare const EMPTY_SEGMENT: string;
|
|
26
|
+
export declare const MAX_TIME_SEGMENTS_COUNT = 3;
|
|
27
|
+
/** Сегменты времени через любой разделитель: `12:30`, `9:5`, `1:23:45`, `12.30`. */
|
|
28
|
+
export declare const TIME_LIKE_SEGMENTS_REGEXP: RegExp;
|
|
29
|
+
/** Время без разделителей: `1`, `12`, `1230`, `123045`. */
|
|
30
|
+
export declare const TIME_LIKE_DIGITS_REGEXP: RegExp;
|
|
31
|
+
export declare const TIME_SEGMENTS_BY_FORMAT: Record<TimeFormat, TimeSegment[]>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export var TimePickerDataTids = {
|
|
2
|
+
root: 'TimePicker__root',
|
|
3
|
+
input: 'TimePicker__input',
|
|
4
|
+
mobileInput: 'TimePicker__mobileInput',
|
|
5
|
+
nativeInput: 'TimePicker__nativeInput',
|
|
6
|
+
popup: 'TimePicker__popup',
|
|
7
|
+
mobilePopup: 'TimePicker__mobilePopup',
|
|
8
|
+
item: 'TimePicker__item',
|
|
9
|
+
loading: 'TimePicker__loading',
|
|
10
|
+
failed: 'TimePicker__failed',
|
|
11
|
+
inputLoading: 'TimePicker__inputLoading',
|
|
12
|
+
};
|
|
13
|
+
/** Больше двух десятков часов не бывает: такая первая цифра сразу завершает сегмент. */
|
|
14
|
+
export var HOURS_FIRST_DIGIT_MAX = 2;
|
|
15
|
+
export var TIME_PLACEHOLDER_CHAR = '\u2212';
|
|
16
|
+
export var TIME_SEPARATOR = ':';
|
|
17
|
+
export var TIME_SEGMENT_LENGTH = 2;
|
|
18
|
+
export var HOURS_MAX_VALUE = 23;
|
|
19
|
+
export var MINUTES_AND_SECONDS_MAX_VALUE = 59;
|
|
20
|
+
export var ZERO_PAD_CHAR = '0';
|
|
21
|
+
export var EMPTY_VALUE = '';
|
|
22
|
+
export var DIGIT_REGEXP = /\d/;
|
|
23
|
+
export var NON_DIGIT_REGEXP = /\D/g;
|
|
24
|
+
export var EMPTY_SEGMENT = TIME_PLACEHOLDER_CHAR.repeat(TIME_SEGMENT_LENGTH);
|
|
25
|
+
export var MAX_TIME_SEGMENTS_COUNT = 3;
|
|
26
|
+
/** Сегменты времени через любой разделитель: `12:30`, `9:5`, `1:23:45`, `12.30`. */
|
|
27
|
+
export var TIME_LIKE_SEGMENTS_REGEXP = new RegExp("^\\d{1,2}(?:\\D{1,3}\\d{1,2}){0,".concat(MAX_TIME_SEGMENTS_COUNT - 1, "}$"));
|
|
28
|
+
/** Время без разделителей: `1`, `12`, `1230`, `123045`. */
|
|
29
|
+
export var TIME_LIKE_DIGITS_REGEXP = new RegExp("^\\d{1,".concat(MAX_TIME_SEGMENTS_COUNT * TIME_SEGMENT_LENGTH, "}$"));
|
|
30
|
+
export var TIME_SEGMENTS_BY_FORMAT = {
|
|
31
|
+
'HH:mm': ['hours', 'minutes'],
|
|
32
|
+
'HH:mm:ss': ['hours', 'minutes', 'seconds'],
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=TimePicker.constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TimePicker.constants.js","sourceRoot":"","sources":["TimePicker.constants.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,IAAM,kBAAkB,GAAG;IAChC,IAAI,EAAE,kBAAkB;IACxB,KAAK,EAAE,mBAAmB;IAC1B,WAAW,EAAE,yBAAyB;IACtC,WAAW,EAAE,yBAAyB;IACtC,KAAK,EAAE,mBAAmB;IAC1B,WAAW,EAAE,yBAAyB;IACtC,IAAI,EAAE,kBAAkB;IACxB,OAAO,EAAE,qBAAqB;IAC9B,MAAM,EAAE,oBAAoB;IAC5B,YAAY,EAAE,0BAA0B;CAChC,CAAC;AAEX,wFAAwF;AACxF,MAAM,CAAC,IAAM,qBAAqB,GAAG,CAAC,CAAC;AACvC,MAAM,CAAC,IAAM,qBAAqB,GAAG,QAAQ,CAAC;AAC9C,MAAM,CAAC,IAAM,cAAc,GAAG,GAAG,CAAC;AAClC,MAAM,CAAC,IAAM,mBAAmB,GAAG,CAAC,CAAC;AACrC,MAAM,CAAC,IAAM,eAAe,GAAG,EAAE,CAAC;AAClC,MAAM,CAAC,IAAM,6BAA6B,GAAG,EAAE,CAAC;AAChD,MAAM,CAAC,IAAM,aAAa,GAAG,GAAG,CAAC;AACjC,MAAM,CAAC,IAAM,WAAW,GAAG,EAAE,CAAC;AAC9B,MAAM,CAAC,IAAM,YAAY,GAAG,IAAI,CAAC;AACjC,MAAM,CAAC,IAAM,gBAAgB,GAAG,KAAK,CAAC;AACtC,MAAM,CAAC,IAAM,aAAa,GAAG,qBAAqB,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAE/E,MAAM,CAAC,IAAM,uBAAuB,GAAG,CAAC,CAAC;AACzC,oFAAoF;AACpF,MAAM,CAAC,IAAM,yBAAyB,GAAG,IAAI,MAAM,CAAC,0CAAmC,uBAAuB,GAAG,CAAC,OAAI,CAAC,CAAC;AACxH,2DAA2D;AAC3D,MAAM,CAAC,IAAM,uBAAuB,GAAG,IAAI,MAAM,CAAC,iBAAU,uBAAuB,GAAG,mBAAmB,OAAI,CAAC,CAAC;AAE/G,MAAM,CAAC,IAAM,uBAAuB,GAAsC;IACxE,OAAO,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC;IAC7B,UAAU,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC;CAC5C,CAAC","sourcesContent":["import type { TimeFormat, TimeSegment } from './TimePicker.shared.js';\n\nexport const TimePickerDataTids = {\n root: 'TimePicker__root',\n input: 'TimePicker__input',\n mobileInput: 'TimePicker__mobileInput',\n nativeInput: 'TimePicker__nativeInput',\n popup: 'TimePicker__popup',\n mobilePopup: 'TimePicker__mobilePopup',\n item: 'TimePicker__item',\n loading: 'TimePicker__loading',\n failed: 'TimePicker__failed',\n inputLoading: 'TimePicker__inputLoading',\n} as const;\n\n/** Больше двух десятков часов не бывает: такая первая цифра сразу завершает сегмент. */\nexport const HOURS_FIRST_DIGIT_MAX = 2;\nexport const TIME_PLACEHOLDER_CHAR = '\\u2212';\nexport const TIME_SEPARATOR = ':';\nexport const TIME_SEGMENT_LENGTH = 2;\nexport const HOURS_MAX_VALUE = 23;\nexport const MINUTES_AND_SECONDS_MAX_VALUE = 59;\nexport const ZERO_PAD_CHAR = '0';\nexport const EMPTY_VALUE = '';\nexport const DIGIT_REGEXP = /\\d/;\nexport const NON_DIGIT_REGEXP = /\\D/g;\nexport const EMPTY_SEGMENT = TIME_PLACEHOLDER_CHAR.repeat(TIME_SEGMENT_LENGTH);\n\nexport const MAX_TIME_SEGMENTS_COUNT = 3;\n/** Сегменты времени через любой разделитель: `12:30`, `9:5`, `1:23:45`, `12.30`. */\nexport const TIME_LIKE_SEGMENTS_REGEXP = new RegExp(`^\\\\d{1,2}(?:\\\\D{1,3}\\\\d{1,2}){0,${MAX_TIME_SEGMENTS_COUNT - 1}}$`);\n/** Время без разделителей: `1`, `12`, `1230`, `123045`. */\nexport const TIME_LIKE_DIGITS_REGEXP = new RegExp(`^\\\\d{1,${MAX_TIME_SEGMENTS_COUNT * TIME_SEGMENT_LENGTH}}$`);\n\nexport const TIME_SEGMENTS_BY_FORMAT: Record<TimeFormat, TimeSegment[]> = {\n 'HH:mm': ['hours', 'minutes'],\n 'HH:mm:ss': ['hours', 'minutes', 'seconds'],\n};\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type TimeDigitInputResult, type TimeFormat, type TimeSegment } from './TimePicker.shared.js';
|
|
2
|
+
/**
|
|
3
|
+
* Удаляет одну цифру из активного сегмента справа налево.
|
|
4
|
+
* Сначала превращает заполненный сегмент в значение с одной ожидающей цифрой,
|
|
5
|
+
* затем — в полностью пустой сегмент.
|
|
6
|
+
*/
|
|
7
|
+
export declare const deleteTimeSegmentDigit: (value: string, segment: TimeSegment, format: TimeFormat) => string;
|
|
8
|
+
/**
|
|
9
|
+
* Коммитит активный сегмент при уходе с него или потере фокуса.
|
|
10
|
+
* Частично введенное значение дополняется и нормализуется, а полностью пустой сегмент остается пустым.
|
|
11
|
+
*/
|
|
12
|
+
export declare const commitTimeSegmentOnLeave: (value: string, segment: TimeSegment, format: TimeFormat) => string;
|
|
13
|
+
/**
|
|
14
|
+
* Сдвигает значение активного сегмента на шаг вверх или вниз с циклическим переходом по границам.
|
|
15
|
+
* Пустой сегмент трактуется как `00`.
|
|
16
|
+
*/
|
|
17
|
+
export declare const shiftTimeSegmentValue: (value: string, segment: TimeSegment, step: 1 | -1, format: TimeFormat) => string;
|
|
18
|
+
/** Обрабатывает ввод одной цифры в активный сегмент. */
|
|
19
|
+
export declare const formatDigitToTimeSegment: (value: string, segment: TimeSegment, digit: string, format: TimeFormat) => TimeDigitInputResult;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { DIGIT_REGEXP, EMPTY_SEGMENT, EMPTY_VALUE, HOURS_FIRST_DIGIT_MAX, TIME_PLACEHOLDER_CHAR, TIME_SEGMENT_LENGTH, ZERO_PAD_CHAR, } from './TimePicker.constants.js';
|
|
2
|
+
import { getNextTimeSegment } from './TimePicker.selection.js';
|
|
3
|
+
import { getDigits, getTimeSegmentMax, hasPendingSingleDigit, normalizeEditableSegment, } from './TimePicker.shared.js';
|
|
4
|
+
import { getTimeSegmentValue, replaceTimeSegment } from './TimePicker.value.js';
|
|
5
|
+
/**
|
|
6
|
+
* Удаляет одну цифру из активного сегмента справа налево.
|
|
7
|
+
* Сначала превращает заполненный сегмент в значение с одной ожидающей цифрой,
|
|
8
|
+
* затем — в полностью пустой сегмент.
|
|
9
|
+
*/
|
|
10
|
+
export var deleteTimeSegmentDigit = function (value, segment, format) {
|
|
11
|
+
var currentSegmentValue = getTimeSegmentValue(value, segment, format);
|
|
12
|
+
var _a = Array.from(currentSegmentValue), first = _a[0], second = _a[1];
|
|
13
|
+
if (DIGIT_REGEXP.test(second !== null && second !== void 0 ? second : EMPTY_VALUE)) {
|
|
14
|
+
return replaceTimeSegment(value, segment, "".concat(first).concat(TIME_PLACEHOLDER_CHAR), format);
|
|
15
|
+
}
|
|
16
|
+
if (DIGIT_REGEXP.test(first !== null && first !== void 0 ? first : EMPTY_VALUE)) {
|
|
17
|
+
return replaceTimeSegment(value, segment, EMPTY_SEGMENT, format);
|
|
18
|
+
}
|
|
19
|
+
return value;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Коммитит активный сегмент при уходе с него или потере фокуса.
|
|
23
|
+
* Частично введенное значение дополняется и нормализуется, а полностью пустой сегмент остается пустым.
|
|
24
|
+
*/
|
|
25
|
+
export var commitTimeSegmentOnLeave = function (value, segment, format) {
|
|
26
|
+
var nextValue = normalizeEditableSegment(getTimeSegmentValue(value, segment, format), segment);
|
|
27
|
+
return replaceTimeSegment(value, segment, nextValue, format);
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Сдвигает значение активного сегмента на шаг вверх или вниз с циклическим переходом по границам.
|
|
31
|
+
* Пустой сегмент трактуется как `00`.
|
|
32
|
+
*/
|
|
33
|
+
export var shiftTimeSegmentValue = function (value, segment, step, format) {
|
|
34
|
+
var currentSegmentValue = getTimeSegmentValue(value, segment, format);
|
|
35
|
+
var normalizedSegmentValue = normalizeEditableSegment(currentSegmentValue, segment);
|
|
36
|
+
var max = getTimeSegmentMax(segment);
|
|
37
|
+
var current = normalizedSegmentValue === EMPTY_SEGMENT ? 0 : Number(normalizedSegmentValue);
|
|
38
|
+
var next = (current + step + max + 1) % (max + 1);
|
|
39
|
+
return replaceTimeSegment(value, segment, String(next).padStart(TIME_SEGMENT_LENGTH, ZERO_PAD_CHAR), format);
|
|
40
|
+
};
|
|
41
|
+
/** Обрабатывает ввод одной цифры в активный сегмент. */
|
|
42
|
+
export var formatDigitToTimeSegment = function (value, segment, digit, format) {
|
|
43
|
+
var currentSegmentValue = getTimeSegmentValue(value, segment, format);
|
|
44
|
+
var nextSegment = getNextTimeSegment(segment, format);
|
|
45
|
+
var shouldAppend = hasPendingSingleDigit(currentSegmentValue);
|
|
46
|
+
var currentDigits = shouldAppend ? getDigits(currentSegmentValue) : '';
|
|
47
|
+
if (currentDigits.length === 0) {
|
|
48
|
+
// Первая цифра часов больше двух не может быть десятками, поэтому сегмент завершается сразу.
|
|
49
|
+
if (segment === 'hours' && Number(digit) > HOURS_FIRST_DIGIT_MAX) {
|
|
50
|
+
return {
|
|
51
|
+
shouldBlink: false,
|
|
52
|
+
selectedSegment: nextSegment !== null && nextSegment !== void 0 ? nextSegment : segment,
|
|
53
|
+
nextValue: replaceTimeSegment(value, segment, "0".concat(digit), format),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
shouldBlink: false,
|
|
58
|
+
selectedSegment: segment,
|
|
59
|
+
nextValue: replaceTimeSegment(value, segment, "".concat(digit).concat(TIME_PLACEHOLDER_CHAR), format),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (segment === 'hours' && currentDigits === '2' && Number(digit) > 3) {
|
|
63
|
+
return { shouldBlink: true, selectedSegment: segment, nextValue: value };
|
|
64
|
+
}
|
|
65
|
+
if (segment !== 'hours' && Number("".concat(currentDigits).concat(digit)) > getTimeSegmentMax(segment)) {
|
|
66
|
+
return { shouldBlink: true, selectedSegment: segment, nextValue: value };
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
shouldBlink: false,
|
|
70
|
+
selectedSegment: nextSegment !== null && nextSegment !== void 0 ? nextSegment : segment,
|
|
71
|
+
nextValue: replaceTimeSegment(value, segment, String(Number("".concat(currentDigits).concat(digit))).padStart(TIME_SEGMENT_LENGTH, ZERO_PAD_CHAR), format),
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=TimePicker.editing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TimePicker.editing.js","sourceRoot":"","sources":["TimePicker.editing.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n DIGIT_REGEXP,\n EMPTY_SEGMENT,\n EMPTY_VALUE,\n HOURS_FIRST_DIGIT_MAX,\n TIME_PLACEHOLDER_CHAR,\n TIME_SEGMENT_LENGTH,\n ZERO_PAD_CHAR,\n} from './TimePicker.constants.js';\nimport { getNextTimeSegment } from './TimePicker.selection.js';\nimport {\n getDigits,\n getTimeSegmentMax,\n hasPendingSingleDigit,\n normalizeEditableSegment,\n type TimeDigitInputResult,\n type TimeFormat,\n type TimeSegment,\n} from './TimePicker.shared.js';\nimport { getTimeSegmentValue, replaceTimeSegment } from './TimePicker.value.js';\n\n/**\n * Удаляет одну цифру из активного сегмента справа налево.\n * Сначала превращает заполненный сегмент в значение с одной ожидающей цифрой,\n * затем — в полностью пустой сегмент.\n */\nexport const deleteTimeSegmentDigit = (value: string, segment: TimeSegment, format: TimeFormat): string => {\n const currentSegmentValue = getTimeSegmentValue(value, segment, format);\n\n const [first, second] = Array.from(currentSegmentValue);\n\n if (DIGIT_REGEXP.test(second ?? EMPTY_VALUE)) {\n return replaceTimeSegment(value, segment, `${first}${TIME_PLACEHOLDER_CHAR}`, format);\n }\n\n if (DIGIT_REGEXP.test(first ?? EMPTY_VALUE)) {\n return replaceTimeSegment(value, segment, EMPTY_SEGMENT, format);\n }\n\n return value;\n};\n\n/**\n * Коммитит активный сегмент при уходе с него или потере фокуса.\n * Частично введенное значение дополняется и нормализуется, а полностью пустой сегмент остается пустым.\n */\nexport const commitTimeSegmentOnLeave = (value: string, segment: TimeSegment, format: TimeFormat): string => {\n const nextValue = normalizeEditableSegment(getTimeSegmentValue(value, segment, format), segment);\n\n return replaceTimeSegment(value, segment, nextValue, format);\n};\n\n/**\n * Сдвигает значение активного сегмента на шаг вверх или вниз с циклическим переходом по границам.\n * Пустой сегмент трактуется как `00`.\n */\nexport const shiftTimeSegmentValue = (\n value: string,\n segment: TimeSegment,\n step: 1 | -1,\n format: TimeFormat,\n): string => {\n const currentSegmentValue = getTimeSegmentValue(value, segment, format);\n\n const normalizedSegmentValue = normalizeEditableSegment(currentSegmentValue, segment);\n\n const max = getTimeSegmentMax(segment);\n\n const current = normalizedSegmentValue === EMPTY_SEGMENT ? 0 : Number(normalizedSegmentValue);\n const next = (current + step + max + 1) % (max + 1);\n\n return replaceTimeSegment(value, segment, String(next).padStart(TIME_SEGMENT_LENGTH, ZERO_PAD_CHAR), format);\n};\n\n/** Обрабатывает ввод одной цифры в активный сегмент. */\nexport const formatDigitToTimeSegment = (\n value: string,\n segment: TimeSegment,\n digit: string,\n format: TimeFormat,\n): TimeDigitInputResult => {\n const currentSegmentValue = getTimeSegmentValue(value, segment, format);\n\n const nextSegment = getNextTimeSegment(segment, format);\n\n const shouldAppend = hasPendingSingleDigit(currentSegmentValue);\n\n const currentDigits = shouldAppend ? getDigits(currentSegmentValue) : '';\n\n if (currentDigits.length === 0) {\n // Первая цифра часов больше двух не может быть десятками, поэтому сегмент завершается сразу.\n if (segment === 'hours' && Number(digit) > HOURS_FIRST_DIGIT_MAX) {\n return {\n shouldBlink: false,\n selectedSegment: nextSegment ?? segment,\n nextValue: replaceTimeSegment(value, segment, `0${digit}`, format),\n };\n }\n\n return {\n shouldBlink: false,\n selectedSegment: segment,\n nextValue: replaceTimeSegment(value, segment, `${digit}${TIME_PLACEHOLDER_CHAR}`, format),\n };\n }\n\n if (segment === 'hours' && currentDigits === '2' && Number(digit) > 3) {\n return { shouldBlink: true, selectedSegment: segment, nextValue: value };\n }\n\n if (segment !== 'hours' && Number(`${currentDigits}${digit}`) > getTimeSegmentMax(segment)) {\n return { shouldBlink: true, selectedSegment: segment, nextValue: value };\n }\n\n return {\n shouldBlink: false,\n selectedSegment: nextSegment ?? segment,\n nextValue: replaceTimeSegment(\n value,\n segment,\n String(Number(`${currentDigits}${digit}`)).padStart(TIME_SEGMENT_LENGTH, ZERO_PAD_CHAR),\n format,\n ),\n };\n};\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Theme } from '../../../lib/theming/Theme.js';
|
|
2
|
+
import type { SizeProp } from '../../../lib/types/props.js';
|
|
3
|
+
import type { TimeFormat } from './TimePicker.shared.js';
|
|
4
|
+
export declare const getTimePickerPopupMaxHeight: (size: SizeProp, theme: Theme) => string;
|
|
5
|
+
export declare const getTimePickerSuffixMargin: (size: SizeProp, theme: Theme) => string;
|
|
6
|
+
export declare const getTimePickerInputMinWidth: (size: SizeProp, format: TimeFormat, hasIcon: boolean, theme: Theme) => string;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export var getTimePickerPopupMaxHeight = function (size, theme) {
|
|
2
|
+
switch (size) {
|
|
3
|
+
case 'large':
|
|
4
|
+
return theme.timePickerMenuMaxHeightLarge;
|
|
5
|
+
case 'medium':
|
|
6
|
+
return theme.timePickerMenuMaxHeightMedium;
|
|
7
|
+
case 'small':
|
|
8
|
+
default:
|
|
9
|
+
return theme.timePickerMenuMaxHeightSmall;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
export var getTimePickerSuffixMargin = function (size, theme) {
|
|
13
|
+
switch (size) {
|
|
14
|
+
case 'large':
|
|
15
|
+
return theme.timePickerSuffixGapLarge;
|
|
16
|
+
case 'medium':
|
|
17
|
+
return theme.timePickerSuffixGapMedium;
|
|
18
|
+
case 'small':
|
|
19
|
+
default:
|
|
20
|
+
return theme.timePickerSuffixGapSmall;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
export var getTimePickerInputMinWidth = function (size, format, hasIcon, theme) {
|
|
24
|
+
switch (size) {
|
|
25
|
+
case 'large':
|
|
26
|
+
if (format === 'HH:mm:ss') {
|
|
27
|
+
return hasIcon
|
|
28
|
+
? theme.timePickerInputMinWidthWithIconAndSecondsLarge
|
|
29
|
+
: theme.timePickerInputMinWidthWithSecondsLarge;
|
|
30
|
+
}
|
|
31
|
+
return hasIcon ? theme.timePickerInputMinWidthWithIconLarge : theme.timePickerInputMinWidthLarge;
|
|
32
|
+
case 'medium':
|
|
33
|
+
if (format === 'HH:mm:ss') {
|
|
34
|
+
return hasIcon
|
|
35
|
+
? theme.timePickerInputMinWidthWithIconAndSecondsMedium
|
|
36
|
+
: theme.timePickerInputMinWidthWithSecondsMedium;
|
|
37
|
+
}
|
|
38
|
+
return hasIcon ? theme.timePickerInputMinWidthWithIconMedium : theme.timePickerInputMinWidthMedium;
|
|
39
|
+
case 'small':
|
|
40
|
+
default:
|
|
41
|
+
if (format === 'HH:mm:ss') {
|
|
42
|
+
return hasIcon
|
|
43
|
+
? theme.timePickerInputMinWidthWithIconAndSecondsSmall
|
|
44
|
+
: theme.timePickerInputMinWidthWithSecondsSmall;
|
|
45
|
+
}
|
|
46
|
+
return hasIcon ? theme.timePickerInputMinWidthWithIconSmall : theme.timePickerInputMinWidthSmall;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=TimePicker.layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TimePicker.layout.js","sourceRoot":"","sources":["TimePicker.layout.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,IAAM,2BAA2B,GAAG,UAAC,IAAc,EAAE,KAAY;IACtE,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,OAAO;YACV,OAAO,KAAK,CAAC,4BAA4B,CAAC;QAE5C,KAAK,QAAQ;YACX,OAAO,KAAK,CAAC,6BAA6B,CAAC;QAE7C,KAAK,OAAO,CAAC;QAEb;YACE,OAAO,KAAK,CAAC,4BAA4B,CAAC;IAC9C,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,IAAM,yBAAyB,GAAG,UAAC,IAAc,EAAE,KAAY;IACpE,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,OAAO;YACV,OAAO,KAAK,CAAC,wBAAwB,CAAC;QAExC,KAAK,QAAQ;YACX,OAAO,KAAK,CAAC,yBAAyB,CAAC;QAEzC,KAAK,OAAO,CAAC;QAEb;YACE,OAAO,KAAK,CAAC,wBAAwB,CAAC;IAC1C,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,IAAM,0BAA0B,GAAG,UACxC,IAAc,EACd,MAAkB,EAClB,OAAgB,EAChB,KAAY;IAEZ,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,OAAO;YACV,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;gBAC1B,OAAO,OAAO;oBACZ,CAAC,CAAC,KAAK,CAAC,8CAA8C;oBACtD,CAAC,CAAC,KAAK,CAAC,uCAAuC,CAAC;YACpD,CAAC;YAED,OAAO,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC,CAAC,KAAK,CAAC,4BAA4B,CAAC;QAEnG,KAAK,QAAQ;YACX,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;gBAC1B,OAAO,OAAO;oBACZ,CAAC,CAAC,KAAK,CAAC,+CAA+C;oBACvD,CAAC,CAAC,KAAK,CAAC,wCAAwC,CAAC;YACrD,CAAC;YAED,OAAO,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC,CAAC,KAAK,CAAC,6BAA6B,CAAC;QAErG,KAAK,OAAO,CAAC;QAEb;YACE,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;gBAC1B,OAAO,OAAO;oBACZ,CAAC,CAAC,KAAK,CAAC,8CAA8C;oBACtD,CAAC,CAAC,KAAK,CAAC,uCAAuC,CAAC;YACpD,CAAC;YAED,OAAO,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC,CAAC,KAAK,CAAC,4BAA4B,CAAC;IACrG,CAAC;AACH,CAAC,CAAC","sourcesContent":["import type { Theme } from '../../../lib/theming/Theme.js';\nimport type { SizeProp } from '../../../lib/types/props.js';\nimport type { TimeFormat } from './TimePicker.shared.js';\n\nexport const getTimePickerPopupMaxHeight = (size: SizeProp, theme: Theme): string => {\n switch (size) {\n case 'large':\n return theme.timePickerMenuMaxHeightLarge;\n\n case 'medium':\n return theme.timePickerMenuMaxHeightMedium;\n\n case 'small':\n\n default:\n return theme.timePickerMenuMaxHeightSmall;\n }\n};\n\nexport const getTimePickerSuffixMargin = (size: SizeProp, theme: Theme): string => {\n switch (size) {\n case 'large':\n return theme.timePickerSuffixGapLarge;\n\n case 'medium':\n return theme.timePickerSuffixGapMedium;\n\n case 'small':\n\n default:\n return theme.timePickerSuffixGapSmall;\n }\n};\n\nexport const getTimePickerInputMinWidth = (\n size: SizeProp,\n format: TimeFormat,\n hasIcon: boolean,\n theme: Theme,\n): string => {\n switch (size) {\n case 'large':\n if (format === 'HH:mm:ss') {\n return hasIcon\n ? theme.timePickerInputMinWidthWithIconAndSecondsLarge\n : theme.timePickerInputMinWidthWithSecondsLarge;\n }\n\n return hasIcon ? theme.timePickerInputMinWidthWithIconLarge : theme.timePickerInputMinWidthLarge;\n\n case 'medium':\n if (format === 'HH:mm:ss') {\n return hasIcon\n ? theme.timePickerInputMinWidthWithIconAndSecondsMedium\n : theme.timePickerInputMinWidthWithSecondsMedium;\n }\n\n return hasIcon ? theme.timePickerInputMinWidthWithIconMedium : theme.timePickerInputMinWidthMedium;\n\n case 'small':\n\n default:\n if (format === 'HH:mm:ss') {\n return hasIcon\n ? theme.timePickerInputMinWidthWithIconAndSecondsSmall\n : theme.timePickerInputMinWidthWithSecondsSmall;\n }\n\n return hasIcon ? theme.timePickerInputMinWidthWithIconSmall : theme.timePickerInputMinWidthSmall;\n }\n};\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { TimeFormat, TimeSegment } from './TimePicker.shared.js';
|
|
2
|
+
/** Возвращает следующий сегмент для навигации по вводу или `null`, если текущий сегмент последний. */
|
|
3
|
+
export declare const getNextTimeSegment: (segment: TimeSegment, format: TimeFormat) => TimeSegment | null;
|
|
4
|
+
/** Возвращает предыдущий сегмент для навигации по вводу или `null`, если текущий сегмент первый. */
|
|
5
|
+
export declare const getPreviousTimeSegment: (segment: TimeSegment) => TimeSegment | null;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Возвращает следующий сегмент для навигации по вводу или `null`, если текущий сегмент последний. */
|
|
2
|
+
export var getNextTimeSegment = function (segment, format) {
|
|
3
|
+
switch (segment) {
|
|
4
|
+
case 'hours':
|
|
5
|
+
return 'minutes';
|
|
6
|
+
case 'minutes':
|
|
7
|
+
return format === 'HH:mm:ss' ? 'seconds' : null;
|
|
8
|
+
case 'seconds':
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
/** Возвращает предыдущий сегмент для навигации по вводу или `null`, если текущий сегмент первый. */
|
|
13
|
+
export var getPreviousTimeSegment = function (segment) {
|
|
14
|
+
switch (segment) {
|
|
15
|
+
case 'hours':
|
|
16
|
+
return null;
|
|
17
|
+
case 'minutes':
|
|
18
|
+
return 'hours';
|
|
19
|
+
case 'seconds':
|
|
20
|
+
return 'minutes';
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=TimePicker.selection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TimePicker.selection.js","sourceRoot":"","sources":["TimePicker.selection.ts"],"names":[],"mappings":"AAEA,sGAAsG;AACtG,MAAM,CAAC,IAAM,kBAAkB,GAAG,UAAC,OAAoB,EAAE,MAAkB;IACzE,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,OAAO;YACV,OAAO,SAAS,CAAC;QAEnB,KAAK,SAAS;YACZ,OAAO,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;QAElD,KAAK,SAAS;YACZ,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC,CAAC;AAEF,oGAAoG;AACpG,MAAM,CAAC,IAAM,sBAAsB,GAAG,UAAC,OAAoB;IACzD,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,OAAO;YACV,OAAO,IAAI,CAAC;QAEd,KAAK,SAAS;YACZ,OAAO,OAAO,CAAC;QAEjB,KAAK,SAAS;YACZ,OAAO,SAAS,CAAC;IACrB,CAAC;AACH,CAAC,CAAC","sourcesContent":["import type { TimeFormat, TimeSegment } from './TimePicker.shared.js';\n\n/** Возвращает следующий сегмент для навигации по вводу или `null`, если текущий сегмент последний. */\nexport const getNextTimeSegment = (segment: TimeSegment, format: TimeFormat): TimeSegment | null => {\n switch (segment) {\n case 'hours':\n return 'minutes';\n\n case 'minutes':\n return format === 'HH:mm:ss' ? 'seconds' : null;\n\n case 'seconds':\n return null;\n }\n};\n\n/** Возвращает предыдущий сегмент для навигации по вводу или `null`, если текущий сегмент первый. */\nexport const getPreviousTimeSegment = (segment: TimeSegment): TimeSegment | null => {\n switch (segment) {\n case 'hours':\n return null;\n\n case 'minutes':\n return 'hours';\n\n case 'seconds':\n return 'minutes';\n }\n};\n"]}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { ReactElement, ReactNode } from 'react';
|
|
2
|
+
import type { MenuItemProps } from '../../MenuItem/index.js';
|
|
3
|
+
export type TimeFormat = 'HH:mm' | 'HH:mm:ss';
|
|
4
|
+
export type TimeSegment = 'hours' | 'minutes' | 'seconds';
|
|
5
|
+
export interface TimeItem {
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
value: string;
|
|
8
|
+
label?: ReactNode;
|
|
9
|
+
}
|
|
10
|
+
/** Элемент со временем: строка в формате `HH:mm[:ss]` или объект. */
|
|
11
|
+
export type TimeItemValue = string | TimeItem;
|
|
12
|
+
/**
|
|
13
|
+
* React-элемент выпадающего списка: сам элемент или функция, возвращающая его.
|
|
14
|
+
* Параметры типа заданы как `any`, чтобы тип совпадал с тем, что дает инлайн-разметка в `source`:
|
|
15
|
+
* иначе TypeScript не отличает React-элемент от элемента со временем и не выводит тип элемента.
|
|
16
|
+
*/
|
|
17
|
+
export type TimePickerMenuElement = ReactElement<any, any> | (() => ReactElement<any, any>);
|
|
18
|
+
/** Элемент, который можно передать в `source`: элемент со временем или React-элемент. */
|
|
19
|
+
export type TimePickerExtendedItem<T extends TimeItemValue = TimeItemValue> = T | TimePickerMenuElement;
|
|
20
|
+
export type TimePickerSource<T extends TimeItemValue = TimeItemValue> = Array<TimePickerExtendedItem<T>> | ((query: string) => Array<TimePickerExtendedItem<T>> | Promise<Array<TimePickerExtendedItem<T>>>);
|
|
21
|
+
/** Разобранный элемент выпадающего списка: исходный элемент, его время, подпись и доступность. */
|
|
22
|
+
export interface TimePickerResolvedItem<T extends TimeItemValue = TimeItemValue> {
|
|
23
|
+
item: T;
|
|
24
|
+
value: string;
|
|
25
|
+
label?: ReactNode;
|
|
26
|
+
disabled: boolean;
|
|
27
|
+
}
|
|
28
|
+
/** Элемент выпадающего списка: разобранный элемент со временем или React-элемент. */
|
|
29
|
+
export type TimePickerMenuItem<T extends TimeItemValue = TimeItemValue> = TimePickerResolvedItem<T> | TimePickerMenuElement;
|
|
30
|
+
/** Проверяет, что элемент источника содержит время, а не является React-элементом. */
|
|
31
|
+
export declare const isTimeItem: <T extends TimeItemValue>(item: TimePickerExtendedItem<T>) => item is T;
|
|
32
|
+
/** Проверяет, что элемент выпадающего списка содержит время, а не является React-элементом. */
|
|
33
|
+
export declare const isTimeMenuItem: <T extends TimeItemValue>(item: TimePickerMenuItem<T>) => item is TimePickerResolvedItem<T>;
|
|
34
|
+
/**
|
|
35
|
+
* Проверяет, что элемент выпадающего списка — это `MenuItem`, по которому можно ходить с клавиатуры.
|
|
36
|
+
* Заблокированные и невыбираемые пункты в навигации не участвуют, как и элементы-функции:
|
|
37
|
+
* последние отрисовываются как есть, поэтому кликом по ним по-прежнему управляет их собственный `onClick`.
|
|
38
|
+
*/
|
|
39
|
+
export declare const isNavigableMenuElement: <T extends TimeItemValue>(item: TimePickerMenuItem<T>) => item is ReactElement<MenuItemProps>;
|
|
40
|
+
/** Проверяет, что на элементе выпадающего списка может стоять выделение с клавиатуры. */
|
|
41
|
+
export declare const isHighlightableMenuItem: <T extends TimeItemValue>(item: TimePickerMenuItem<T>) => boolean;
|
|
42
|
+
export declare const getTimeItemValue: (item: TimeItemValue) => string;
|
|
43
|
+
export declare const getTimeItemLabel: (item: TimeItemValue) => ReactNode;
|
|
44
|
+
export declare const isTimeItemDisabled: (item: TimeItemValue) => boolean;
|
|
45
|
+
export declare const isTimeItemObject: (item: TimeItemValue) => item is TimeItem;
|
|
46
|
+
/** Результат ввода одной цифры: следующее display-значение, сегмент под выделением и признак вспышки. */
|
|
47
|
+
export interface TimeDigitInputResult {
|
|
48
|
+
nextValue: string;
|
|
49
|
+
selectedSegment: TimeSegment;
|
|
50
|
+
shouldBlink: boolean;
|
|
51
|
+
}
|
|
52
|
+
export declare const getTimeSegments: (format: TimeFormat) => TimeSegment[];
|
|
53
|
+
export declare const getTimeSegmentMax: (segment: TimeSegment) => number;
|
|
54
|
+
/** Извлекает из сегмента только цифры и ограничивает результат длиной сегмента. */
|
|
55
|
+
export declare const getDigits: (segment: string) => string;
|
|
56
|
+
/**
|
|
57
|
+
* Приводит произвольное строковое значение сегмента к display-форме:
|
|
58
|
+
* оставляет только цифры и плейсхолдеры, ограничивает длину и дополняет незаполненные позиции плейсхолдером.
|
|
59
|
+
*/
|
|
60
|
+
export declare const sanitizeSegment: (segment: string) => string;
|
|
61
|
+
/** Нормализует сегмент для committed-значения: пустой сегмент становится `00`. */
|
|
62
|
+
export declare const normalizeTimeSegment: (segmentValue: string, segment: TimeSegment) => string;
|
|
63
|
+
/** Нормализует сегмент для режима редактирования: полностью пустой сегмент остается пустым. */
|
|
64
|
+
export declare const normalizeEditableSegment: (segmentValue: string, segment: TimeSegment) => string;
|
|
65
|
+
/** Проверяет, что сегмент содержит одну введенную цифру и ожидает вторую. */
|
|
66
|
+
export declare const hasPendingSingleDigit: (segmentValue: string) => boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Разбивает входное значение на display-сегменты текущего формата.
|
|
69
|
+
* Поддерживает committed-значение (`HH:mm[:ss]`) и display-значение с плейсхолдерами
|
|
70
|
+
*/
|
|
71
|
+
export declare const getDisplaySegments: (value: string, format: TimeFormat) => string[];
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { isValidElement } from 'react';
|
|
2
|
+
import { isMenuItem } from '../../MenuItem/index.js';
|
|
3
|
+
import { DIGIT_REGEXP, EMPTY_SEGMENT, EMPTY_VALUE, HOURS_MAX_VALUE, MINUTES_AND_SECONDS_MAX_VALUE, NON_DIGIT_REGEXP, TIME_PLACEHOLDER_CHAR, TIME_SEGMENT_LENGTH, TIME_SEGMENTS_BY_FORMAT, TIME_SEPARATOR, ZERO_PAD_CHAR, } from './TimePicker.constants.js';
|
|
4
|
+
var isNotMenuElement = function (item) { return typeof item !== 'function' && !isValidElement(item); };
|
|
5
|
+
/** Проверяет, что элемент источника содержит время, а не является React-элементом. */
|
|
6
|
+
export var isTimeItem = function (item) {
|
|
7
|
+
return isNotMenuElement(item);
|
|
8
|
+
};
|
|
9
|
+
/** Проверяет, что элемент выпадающего списка содержит время, а не является React-элементом. */
|
|
10
|
+
export var isTimeMenuItem = function (item) { return isNotMenuElement(item); };
|
|
11
|
+
/**
|
|
12
|
+
* Проверяет, что элемент выпадающего списка — это `MenuItem`, по которому можно ходить с клавиатуры.
|
|
13
|
+
* Заблокированные и невыбираемые пункты в навигации не участвуют, как и элементы-функции:
|
|
14
|
+
* последние отрисовываются как есть, поэтому кликом по ним по-прежнему управляет их собственный `onClick`.
|
|
15
|
+
*/
|
|
16
|
+
export var isNavigableMenuElement = function (item) {
|
|
17
|
+
if (typeof item === 'function' || !isValidElement(item) || !isMenuItem(item)) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
var _a = item.props, disabled = _a.disabled, isNotSelectable = _a.isNotSelectable;
|
|
21
|
+
return !disabled && !isNotSelectable;
|
|
22
|
+
};
|
|
23
|
+
/** Проверяет, что на элементе выпадающего списка может стоять выделение с клавиатуры. */
|
|
24
|
+
export var isHighlightableMenuItem = function (item) {
|
|
25
|
+
return isTimeMenuItem(item) ? !item.disabled : isNavigableMenuElement(item);
|
|
26
|
+
};
|
|
27
|
+
export var getTimeItemValue = function (item) { return (typeof item === 'string' ? item : item.value); };
|
|
28
|
+
export var getTimeItemLabel = function (item) { return (typeof item === 'string' ? undefined : item.label); };
|
|
29
|
+
export var isTimeItemDisabled = function (item) { return typeof item !== 'string' && Boolean(item.disabled); };
|
|
30
|
+
export var isTimeItemObject = function (item) { return typeof item !== 'string'; };
|
|
31
|
+
export var getTimeSegments = function (format) { return TIME_SEGMENTS_BY_FORMAT[format]; };
|
|
32
|
+
export var getTimeSegmentMax = function (segment) {
|
|
33
|
+
return segment === 'hours' ? HOURS_MAX_VALUE : MINUTES_AND_SECONDS_MAX_VALUE;
|
|
34
|
+
};
|
|
35
|
+
/** Извлекает из сегмента только цифры и ограничивает результат длиной сегмента. */
|
|
36
|
+
export var getDigits = function (segment) {
|
|
37
|
+
return segment.replace(NON_DIGIT_REGEXP, EMPTY_VALUE).slice(0, TIME_SEGMENT_LENGTH);
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Приводит произвольное строковое значение сегмента к display-форме:
|
|
41
|
+
* оставляет только цифры и плейсхолдеры, ограничивает длину и дополняет незаполненные позиции плейсхолдером.
|
|
42
|
+
*/
|
|
43
|
+
export var sanitizeSegment = function (segment) {
|
|
44
|
+
return Array.from(segment)
|
|
45
|
+
.filter(function (char) { return DIGIT_REGEXP.test(char) || char === TIME_PLACEHOLDER_CHAR; })
|
|
46
|
+
.slice(0, TIME_SEGMENT_LENGTH)
|
|
47
|
+
.join('')
|
|
48
|
+
.padEnd(TIME_SEGMENT_LENGTH, TIME_PLACEHOLDER_CHAR);
|
|
49
|
+
};
|
|
50
|
+
var normalizeSegment = function (segmentValue, segment, emptyResult) {
|
|
51
|
+
var digits = getDigits(segmentValue);
|
|
52
|
+
if (!digits) {
|
|
53
|
+
return emptyResult;
|
|
54
|
+
}
|
|
55
|
+
return String(Math.min(Number(digits), getTimeSegmentMax(segment))).padStart(TIME_SEGMENT_LENGTH, ZERO_PAD_CHAR);
|
|
56
|
+
};
|
|
57
|
+
/** Нормализует сегмент для committed-значения: пустой сегмент становится `00`. */
|
|
58
|
+
export var normalizeTimeSegment = function (segmentValue, segment) {
|
|
59
|
+
return normalizeSegment(segmentValue, segment, '00');
|
|
60
|
+
};
|
|
61
|
+
/** Нормализует сегмент для режима редактирования: полностью пустой сегмент остается пустым. */
|
|
62
|
+
export var normalizeEditableSegment = function (segmentValue, segment) {
|
|
63
|
+
return normalizeSegment(segmentValue, segment, EMPTY_SEGMENT);
|
|
64
|
+
};
|
|
65
|
+
/** Проверяет, что сегмент содержит одну введенную цифру и ожидает вторую. */
|
|
66
|
+
export var hasPendingSingleDigit = function (segmentValue) {
|
|
67
|
+
return new RegExp("^\\d".concat(TIME_PLACEHOLDER_CHAR, "$")).test(segmentValue);
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Разбивает входное значение на display-сегменты текущего формата.
|
|
71
|
+
* Поддерживает committed-значение (`HH:mm[:ss]`) и display-значение с плейсхолдерами
|
|
72
|
+
*/
|
|
73
|
+
export var getDisplaySegments = function (value, format) {
|
|
74
|
+
var segments = getTimeSegments(format);
|
|
75
|
+
var fallback = segments.map(function () { return EMPTY_SEGMENT; });
|
|
76
|
+
if (value === EMPTY_VALUE) {
|
|
77
|
+
return fallback;
|
|
78
|
+
}
|
|
79
|
+
if (value.includes(TIME_SEPARATOR) || value.includes(TIME_PLACEHOLDER_CHAR)) {
|
|
80
|
+
var sourceParts_1 = value.split(TIME_SEPARATOR);
|
|
81
|
+
return segments.map(function (_, index) { var _a; return sanitizeSegment((_a = sourceParts_1[index]) !== null && _a !== void 0 ? _a : EMPTY_VALUE); });
|
|
82
|
+
}
|
|
83
|
+
var digits = value.replace(NON_DIGIT_REGEXP, EMPTY_VALUE);
|
|
84
|
+
return segments.map(function (_, index) {
|
|
85
|
+
var segmentStart = index * TIME_SEGMENT_LENGTH;
|
|
86
|
+
var segmentEnd = segmentStart + TIME_SEGMENT_LENGTH;
|
|
87
|
+
return sanitizeSegment(digits.slice(segmentStart, segmentEnd));
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
//# sourceMappingURL=TimePicker.shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TimePicker.shared.js","sourceRoot":"","sources":["TimePicker.shared.ts"],"names":[],"mappings":"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","sourcesContent":["import { isValidElement } from 'react';\nimport type { ReactElement, ReactNode } from 'react';\n\nimport type { MenuItemProps } from '../../MenuItem/index.js';\nimport { isMenuItem } from '../../MenuItem/index.js';\nimport {\n DIGIT_REGEXP,\n EMPTY_SEGMENT,\n EMPTY_VALUE,\n HOURS_MAX_VALUE,\n MINUTES_AND_SECONDS_MAX_VALUE,\n NON_DIGIT_REGEXP,\n TIME_PLACEHOLDER_CHAR,\n TIME_SEGMENT_LENGTH,\n TIME_SEGMENTS_BY_FORMAT,\n TIME_SEPARATOR,\n ZERO_PAD_CHAR,\n} from './TimePicker.constants.js';\n\nexport type TimeFormat = 'HH:mm' | 'HH:mm:ss';\nexport type TimeSegment = 'hours' | 'minutes' | 'seconds';\n\nexport interface TimeItem {\n disabled?: boolean;\n value: string;\n label?: ReactNode;\n}\n\n/** Элемент со временем: строка в формате `HH:mm[:ss]` или объект. */\nexport type TimeItemValue = string | TimeItem;\n\n/**\n * React-элемент выпадающего списка: сам элемент или функция, возвращающая его.\n * Параметры типа заданы как `any`, чтобы тип совпадал с тем, что дает инлайн-разметка в `source`:\n * иначе TypeScript не отличает React-элемент от элемента со временем и не выводит тип элемента.\n */\nexport type TimePickerMenuElement = ReactElement<any, any> | (() => ReactElement<any, any>);\n\n/** Элемент, который можно передать в `source`: элемент со временем или React-элемент. */\nexport type TimePickerExtendedItem<T extends TimeItemValue = TimeItemValue> = T | TimePickerMenuElement;\n\nexport type TimePickerSource<T extends TimeItemValue = TimeItemValue> =\n | Array<TimePickerExtendedItem<T>>\n | ((query: string) => Array<TimePickerExtendedItem<T>> | Promise<Array<TimePickerExtendedItem<T>>>);\n\n/** Разобранный элемент выпадающего списка: исходный элемент, его время, подпись и доступность. */\nexport interface TimePickerResolvedItem<T extends TimeItemValue = TimeItemValue> {\n item: T;\n value: string;\n label?: ReactNode;\n disabled: boolean;\n}\n\n/** Элемент выпадающего списка: разобранный элемент со временем или React-элемент. */\nexport type TimePickerMenuItem<T extends TimeItemValue = TimeItemValue> =\n | TimePickerResolvedItem<T>\n | TimePickerMenuElement;\n\nconst isNotMenuElement = (item: unknown): boolean => typeof item !== 'function' && !isValidElement(item);\n\n/** Проверяет, что элемент источника содержит время, а не является React-элементом. */\nexport const isTimeItem = <T extends TimeItemValue>(item: TimePickerExtendedItem<T>): item is T =>\n isNotMenuElement(item);\n\n/** Проверяет, что элемент выпадающего списка содержит время, а не является React-элементом. */\nexport const isTimeMenuItem = <T extends TimeItemValue>(\n item: TimePickerMenuItem<T>,\n): item is TimePickerResolvedItem<T> => isNotMenuElement(item);\n\n/**\n * Проверяет, что элемент выпадающего списка — это `MenuItem`, по которому можно ходить с клавиатуры.\n * Заблокированные и невыбираемые пункты в навигации не участвуют, как и элементы-функции:\n * последние отрисовываются как есть, поэтому кликом по ним по-прежнему управляет их собственный `onClick`.\n */\nexport const isNavigableMenuElement = <T extends TimeItemValue>(\n item: TimePickerMenuItem<T>,\n): item is ReactElement<MenuItemProps> => {\n if (typeof item === 'function' || !isValidElement(item) || !isMenuItem(item)) {\n return false;\n }\n\n const { disabled, isNotSelectable } = item.props as MenuItemProps;\n\n return !disabled && !isNotSelectable;\n};\n\n/** Проверяет, что на элементе выпадающего списка может стоять выделение с клавиатуры. */\nexport const isHighlightableMenuItem = <T extends TimeItemValue>(item: TimePickerMenuItem<T>): boolean =>\n isTimeMenuItem(item) ? !item.disabled : isNavigableMenuElement(item);\n\nexport const getTimeItemValue = (item: TimeItemValue): string => (typeof item === 'string' ? item : item.value);\n\nexport const getTimeItemLabel = (item: TimeItemValue): ReactNode => (typeof item === 'string' ? undefined : item.label);\n\nexport const isTimeItemDisabled = (item: TimeItemValue): boolean => typeof item !== 'string' && Boolean(item.disabled);\n\nexport const isTimeItemObject = (item: TimeItemValue): item is TimeItem => typeof item !== 'string';\n\n/** Результат ввода одной цифры: следующее display-значение, сегмент под выделением и признак вспышки. */\nexport interface TimeDigitInputResult {\n nextValue: string;\n selectedSegment: TimeSegment;\n shouldBlink: boolean;\n}\n\nexport const getTimeSegments = (format: TimeFormat): TimeSegment[] => TIME_SEGMENTS_BY_FORMAT[format];\n\nexport const getTimeSegmentMax = (segment: TimeSegment): number =>\n segment === 'hours' ? HOURS_MAX_VALUE : MINUTES_AND_SECONDS_MAX_VALUE;\n\n/** Извлекает из сегмента только цифры и ограничивает результат длиной сегмента. */\nexport const getDigits = (segment: string): string =>\n segment.replace(NON_DIGIT_REGEXP, EMPTY_VALUE).slice(0, TIME_SEGMENT_LENGTH);\n\n/**\n * Приводит произвольное строковое значение сегмента к display-форме:\n * оставляет только цифры и плейсхолдеры, ограничивает длину и дополняет незаполненные позиции плейсхолдером.\n */\nexport const sanitizeSegment = (segment: string): string =>\n Array.from(segment)\n .filter((char) => DIGIT_REGEXP.test(char) || char === TIME_PLACEHOLDER_CHAR)\n .slice(0, TIME_SEGMENT_LENGTH)\n .join('')\n .padEnd(TIME_SEGMENT_LENGTH, TIME_PLACEHOLDER_CHAR);\n\nconst normalizeSegment = (segmentValue: string, segment: TimeSegment, emptyResult: string): string => {\n const digits = getDigits(segmentValue);\n\n if (!digits) {\n return emptyResult;\n }\n\n return String(Math.min(Number(digits), getTimeSegmentMax(segment))).padStart(TIME_SEGMENT_LENGTH, ZERO_PAD_CHAR);\n};\n\n/** Нормализует сегмент для committed-значения: пустой сегмент становится `00`. */\nexport const normalizeTimeSegment = (segmentValue: string, segment: TimeSegment): string =>\n normalizeSegment(segmentValue, segment, '00');\n\n/** Нормализует сегмент для режима редактирования: полностью пустой сегмент остается пустым. */\nexport const normalizeEditableSegment = (segmentValue: string, segment: TimeSegment): string =>\n normalizeSegment(segmentValue, segment, EMPTY_SEGMENT);\n\n/** Проверяет, что сегмент содержит одну введенную цифру и ожидает вторую. */\nexport const hasPendingSingleDigit = (segmentValue: string): boolean =>\n new RegExp(`^\\\\d${TIME_PLACEHOLDER_CHAR}$`).test(segmentValue);\n\n/**\n * Разбивает входное значение на display-сегменты текущего формата.\n * Поддерживает committed-значение (`HH:mm[:ss]`) и display-значение с плейсхолдерами\n */\nexport const getDisplaySegments = (value: string, format: TimeFormat): string[] => {\n const segments = getTimeSegments(format);\n const fallback = segments.map(() => EMPTY_SEGMENT);\n\n if (value === EMPTY_VALUE) {\n return fallback;\n }\n\n if (value.includes(TIME_SEPARATOR) || value.includes(TIME_PLACEHOLDER_CHAR)) {\n const sourceParts = value.split(TIME_SEPARATOR);\n return segments.map((_, index) => sanitizeSegment(sourceParts[index] ?? EMPTY_VALUE));\n }\n\n const digits = value.replace(NON_DIGIT_REGEXP, EMPTY_VALUE);\n\n return segments.map((_, index) => {\n const segmentStart = index * TIME_SEGMENT_LENGTH;\n const segmentEnd = segmentStart + TIME_SEGMENT_LENGTH;\n\n return sanitizeSegment(digits.slice(segmentStart, segmentEnd));\n });\n};\n"]}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { type TimeFormat, type TimeItemValue, type TimePickerExtendedItem, type TimePickerMenuItem, type TimeSegment } from './TimePicker.shared.js';
|
|
2
|
+
/** Проверяет, что в display-значении нет ни одной введенной цифры. */
|
|
3
|
+
export declare const isTimeDisplayEmpty: (value: string) => boolean;
|
|
4
|
+
/**
|
|
5
|
+
* Разбирает элементы источника для отрисовки: достает время и подпись,
|
|
6
|
+
* а `disabled` дополняет проверкой диапазона `minTime`/`maxTime`.
|
|
7
|
+
* Время нормализуется по формату поля — и у времени элемента, и у самого элемента.
|
|
8
|
+
* React-элементы остаются на своих местах.
|
|
9
|
+
*/
|
|
10
|
+
export declare const resolveTimeItems: <T extends TimeItemValue>(items: Array<TimePickerExtendedItem<T>>, format: TimeFormat, minTime?: string, maxTime?: string) => Array<TimePickerMenuItem<T>>;
|
|
11
|
+
/**
|
|
12
|
+
* Оставляет только элементы, которые компонент умеет показать в меню.
|
|
13
|
+
* Пустые значения — результат условного рендера вроде `isVisible && item` или `items.length && item` —
|
|
14
|
+
* молча отбрасываются, а элементы, из которых не получается собрать время, отбрасываются с предупреждением.
|
|
15
|
+
*/
|
|
16
|
+
export declare const sanitizeTimeItems: <T extends TimeItemValue>(items: Array<TimePickerExtendedItem<T>>, format: TimeFormat) => Array<TimePickerExtendedItem<T>>;
|
|
17
|
+
/**
|
|
18
|
+
* Проверяет, выходит ли значение за диапазон `minTime`/`maxTime` после нормализации.
|
|
19
|
+
* Пустое значение не считается выходящим за диапазон. Если `minTime > maxTime`, диапазон трактуется как переходящий через полночь.
|
|
20
|
+
*/
|
|
21
|
+
export declare const isTimeValueOutOfRange: (value: string, format: TimeFormat, minTime?: string, maxTime?: string) => boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Нормализует display-значение в committed-форму `HH:mm[:ss]`.
|
|
24
|
+
* Частично заполненные сегменты дополняются и ограничиваются максимумами сегментов.
|
|
25
|
+
*/
|
|
26
|
+
export declare const normalizeTimeValue: (value: string, format: TimeFormat) => string;
|
|
27
|
+
/**
|
|
28
|
+
* Преобразует display-значение в промежуточное значение для `onInputValueChange`.
|
|
29
|
+
* Заполненные сегменты дополняются до двух цифр, пропущенные сегменты до последнего заполненного становятся `00`.
|
|
30
|
+
*/
|
|
31
|
+
export declare const serializeTimeValue: (value: string, format: TimeFormat) => string;
|
|
32
|
+
export declare const getTimeDisplayValue: (value: string, format: TimeFormat) => string;
|
|
33
|
+
/**
|
|
34
|
+
* Возвращает display-значение внешнего `value`.
|
|
35
|
+
* Сегменты, записанные одной цифрой, дополняются нулем, поэтому `9:00` показывается как `09:00` —
|
|
36
|
+
* так же, как компонент показывает время элементов источника.
|
|
37
|
+
* Значение без разделителя остается частично введенным: `1` — это первая цифра часов, а не `01:00`.
|
|
38
|
+
*/
|
|
39
|
+
export declare const getExternalTimeDisplayValue: (value: string, format: TimeFormat) => string;
|
|
40
|
+
/** Заменяет значение выбранного сегмента, сохраняя остальные сегменты display-значения без изменений. */
|
|
41
|
+
export declare const replaceTimeSegment: (value: string, segment: TimeSegment, nextSegmentValue: string, format: TimeFormat) => string;
|
|
42
|
+
/**
|
|
43
|
+
* Проверяет, что вставленное значение похоже на время:
|
|
44
|
+
* это либо сегменты из одной-двух цифр через любой разделитель — `12:30`, `9:5`, `1:23:45`, `12.30`, —
|
|
45
|
+
* либо цифры подряд — `9`, `1230`, `123045`.
|
|
46
|
+
* Строки, из которых время собралось бы случайно — `2026-08-01`, `hello 42`, — временем не считаются.
|
|
47
|
+
*/
|
|
48
|
+
export declare const isTimeLikePastedValue: (value: string) => boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Парсит вставленное пользователем значение и сразу преобразует его в committed-форму.
|
|
51
|
+
* Значение, не похожее на время, отдается как пустое: такую вставку компонент считает некорректным вводом.
|
|
52
|
+
*/
|
|
53
|
+
export declare const parsePastedTimeValue: (value: string, format: TimeFormat) => string;
|
|
54
|
+
/** Возвращает текущее display-значение сегмента или пустой сегмент, если индекс отсутствует. */
|
|
55
|
+
export declare const getTimeSegmentValue: (value: string, segment: TimeSegment, format: TimeFormat) => string;
|
|
56
|
+
export declare const getEmptyDisplayValue: (precision: TimeFormat) => string;
|
|
57
|
+
/**
|
|
58
|
+
* Преобразует display-значение в поисковый запрос для фильтрации элементов.
|
|
59
|
+
* Сегменты содержат только введенные цифры, незаполненный хвост отбрасывается: `12:3_` => `12:3`, `1_:__` => `1`.
|
|
60
|
+
* Позиции сегментов сохраняются, поэтому ведущие незаполненные сегменты остаются пустыми: `__:34` => `:34`.
|
|
61
|
+
* Это нужно для посегментного сравнения в `filterTimeItems` и передается как есть в пользовательскую `source`.
|
|
62
|
+
*/
|
|
63
|
+
export declare const getTimeFilterQuery: (value: string, format: TimeFormat) => string;
|
|
64
|
+
/**
|
|
65
|
+
* Фильтрует элементы по запросу из поля ввода.
|
|
66
|
+
* Сравнивает запрос посегментно: введенные цифры сегмента должны быть префиксом соответствующего сегмента элемента.
|
|
67
|
+
* Пустой запрос возвращает все элементы.
|
|
68
|
+
*/
|
|
69
|
+
export declare const filterTimeItems: <T extends TimeItemValue>(items: Array<TimePickerExtendedItem<T>>, query: string, format: TimeFormat) => Array<TimePickerExtendedItem<T>>;
|