@skbkontur/react-ui 6.1.6 → 6.1.7-65057.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.d.ts +1 -1
  15. package/components/MenuItem/MenuItem.js.map +1 -1
  16. package/components/Radio/Radio.d.ts +4 -0
  17. package/components/Radio/Radio.js +20 -1
  18. package/components/Radio/Radio.js.map +1 -1
  19. package/components/Radio/Radio.mixins.d.ts +2 -0
  20. package/components/Radio/Radio.mixins.js +6 -0
  21. package/components/Radio/Radio.mixins.js.map +1 -1
  22. package/components/Radio/Radio.styles.d.ts +6 -0
  23. package/components/Radio/Radio.styles.js +22 -4
  24. package/components/Radio/Radio.styles.js.map +1 -1
  25. package/components/TimePicker/TimeClockIcon.d.ts +3 -0
  26. package/components/TimePicker/TimeClockIcon.js +11 -0
  27. package/components/TimePicker/TimeClockIcon.js.map +1 -0
  28. package/components/TimePicker/TimePicker.d.ts +150 -0
  29. package/components/TimePicker/TimePicker.js +729 -0
  30. package/components/TimePicker/TimePicker.js.map +1 -0
  31. package/components/TimePicker/TimePicker.styles.d.ts +13 -0
  32. package/components/TimePicker/TimePicker.styles.js +42 -0
  33. package/components/TimePicker/TimePicker.styles.js.map +1 -0
  34. package/components/TimePicker/TimePickerItems.d.ts +20 -0
  35. package/components/TimePicker/TimePickerItems.js +115 -0
  36. package/components/TimePicker/TimePickerItems.js.map +1 -0
  37. package/components/TimePicker/TimePickerMobilePopup.d.ts +45 -0
  38. package/components/TimePicker/TimePickerMobilePopup.js +45 -0
  39. package/components/TimePicker/TimePickerMobilePopup.js.map +1 -0
  40. package/components/TimePicker/TimePickerPopup.d.ts +23 -0
  41. package/components/TimePicker/TimePickerPopup.js +18 -0
  42. package/components/TimePicker/TimePickerPopup.js.map +1 -0
  43. package/components/TimePicker/helpers/TimePicker.constants.d.ts +29 -0
  44. package/components/TimePicker/helpers/TimePicker.constants.js +38 -0
  45. package/components/TimePicker/helpers/TimePicker.constants.js.map +1 -0
  46. package/components/TimePicker/helpers/TimePicker.editing.d.ts +23 -0
  47. package/components/TimePicker/helpers/TimePicker.editing.js +101 -0
  48. package/components/TimePicker/helpers/TimePicker.editing.js.map +1 -0
  49. package/components/TimePicker/helpers/TimePicker.layout.d.ts +6 -0
  50. package/components/TimePicker/helpers/TimePicker.layout.js +49 -0
  51. package/components/TimePicker/helpers/TimePicker.layout.js.map +1 -0
  52. package/components/TimePicker/helpers/TimePicker.selection.d.ts +5 -0
  53. package/components/TimePicker/helpers/TimePicker.selection.js +23 -0
  54. package/components/TimePicker/helpers/TimePicker.selection.js.map +1 -0
  55. package/components/TimePicker/helpers/TimePicker.shared.d.ts +91 -0
  56. package/components/TimePicker/helpers/TimePicker.shared.js +111 -0
  57. package/components/TimePicker/helpers/TimePicker.shared.js.map +1 -0
  58. package/components/TimePicker/helpers/TimePicker.value.d.ts +80 -0
  59. package/components/TimePicker/helpers/TimePicker.value.js +237 -0
  60. package/components/TimePicker/helpers/TimePicker.value.js.map +1 -0
  61. package/components/TimePicker/helpers/scrollSelectedItemIntoView.d.ts +4 -0
  62. package/components/TimePicker/helpers/scrollSelectedItemIntoView.js +24 -0
  63. package/components/TimePicker/helpers/scrollSelectedItemIntoView.js.map +1 -0
  64. package/components/TimePicker/helpers/validateTimePicker.d.ts +8 -0
  65. package/components/TimePicker/helpers/validateTimePicker.js +17 -0
  66. package/components/TimePicker/helpers/validateTimePicker.js.map +1 -0
  67. package/components/TimePicker/hooks/useTimePickerDropdown.d.ts +23 -0
  68. package/components/TimePicker/hooks/useTimePickerDropdown.js +83 -0
  69. package/components/TimePicker/hooks/useTimePickerDropdown.js.map +1 -0
  70. package/components/TimePicker/hooks/useTimePickerSelection.d.ts +18 -0
  71. package/components/TimePicker/hooks/useTimePickerSelection.js +66 -0
  72. package/components/TimePicker/hooks/useTimePickerSelection.js.map +1 -0
  73. package/components/TimePicker/hooks/useTimePickerSource.d.ts +27 -0
  74. package/components/TimePicker/hooks/useTimePickerSource.js +59 -0
  75. package/components/TimePicker/hooks/useTimePickerSource.js.map +1 -0
  76. package/components/TimePicker/hooks/useTimePickerValue.d.ts +33 -0
  77. package/components/TimePicker/hooks/useTimePickerValue.js +97 -0
  78. package/components/TimePicker/hooks/useTimePickerValue.js.map +1 -0
  79. package/components/TimePicker/index.d.ts +4 -0
  80. package/components/TimePicker/index.js +3 -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,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 { TimeFormat, TimeItemValue, TimePickerExtendedItem, TimePickerSource } from '../helpers/TimePicker.shared.js';
2
+ interface UseTimePickerSourceOptions<T extends TimeItemValue> {
3
+ source?: TimePickerSource<T>;
4
+ format: TimeFormat;
5
+ isDropdownOpened: boolean;
6
+ /** Текущий запрос: введенные цифры сегментов с сохранением их позиций. */
7
+ filterQuery: string;
8
+ }
9
+ interface UseTimePickerSourceResult<T extends TimeItemValue> {
10
+ /** Элементы источника, готовые к фильтрации и отрисовке. */
11
+ items: Array<TimePickerExtendedItem<T>>;
12
+ /** Запрос, для которого получены текущие элементы функции-источника. */
13
+ fetchedQuery: string | null;
14
+ isLoading: boolean;
15
+ }
16
+ /**
17
+ * Отдает элементы выпадающего списка из массива или функции-источника.
18
+ *
19
+ * Функция вызывается только для открытого меню и на каждый новый запрос;
20
+ * ответ на устаревший запрос отбрасывается, а отказ трактуется как пустой результат.
21
+ * При закрытии меню результаты функции сбрасываются, чтобы следующее открытие
22
+ * не показывало элементы для старого запроса.
23
+ * Замена самой функции уже открытый список не перезапрашивает: актуальная функция
24
+ * используется при следующем запросе.
25
+ */
26
+ export declare const useTimePickerSource: <T extends TimeItemValue>(options: UseTimePickerSourceOptions<T>) => UseTimePickerSourceResult<T>;
27
+ export {};
@@ -0,0 +1,59 @@
1
+ import { useEffect, useMemo, useRef, useState } from 'react';
2
+ import { sanitizeTimeItems } from '../helpers/TimePicker.value.js';
3
+ /** Общая пустая коллекция элементов: не создает новую ссылку на каждый рендер. */
4
+ var EMPTY_ITEMS = [];
5
+ /**
6
+ * Отдает элементы выпадающего списка из массива или функции-источника.
7
+ *
8
+ * Функция вызывается только для открытого меню и на каждый новый запрос;
9
+ * ответ на устаревший запрос отбрасывается, а отказ трактуется как пустой результат.
10
+ * При закрытии меню результаты функции сбрасываются, чтобы следующее открытие
11
+ * не показывало элементы для старого запроса.
12
+ * Замена самой функции уже открытый список не перезапрашивает: актуальная функция
13
+ * используется при следующем запросе.
14
+ */
15
+ export var useTimePickerSource = function (options) {
16
+ var source = options.source, format = options.format, isDropdownOpened = options.isDropdownOpened, filterQuery = options.filterQuery;
17
+ var isSourceFunction = typeof source === 'function';
18
+ var _a = useState([]), fetchedItems = _a[0], setFetchedItems = _a[1];
19
+ var _b = useState(null), fetchedQuery = _b[0], setFetchedQuery = _b[1];
20
+ var _c = useState(false), isLoading = _c[0], setIsLoading = _c[1];
21
+ var sourceRef = useRef(source);
22
+ sourceRef.current = source;
23
+ useEffect(function () {
24
+ var currentSource = sourceRef.current;
25
+ if (typeof currentSource !== 'function' || !isDropdownOpened) {
26
+ setIsLoading(false);
27
+ return;
28
+ }
29
+ var cancelled = false;
30
+ setIsLoading(true);
31
+ new Promise(function (resolve) { return resolve(currentSource(filterQuery)); }).then(function (nextItems) {
32
+ if (!cancelled) {
33
+ setFetchedItems(nextItems);
34
+ setFetchedQuery(filterQuery);
35
+ setIsLoading(false);
36
+ }
37
+ }, function () {
38
+ if (!cancelled) {
39
+ setFetchedItems([]);
40
+ setFetchedQuery(filterQuery);
41
+ setIsLoading(false);
42
+ }
43
+ });
44
+ return function () {
45
+ cancelled = true;
46
+ };
47
+ }, [filterQuery, isDropdownOpened, isSourceFunction]);
48
+ useEffect(function () {
49
+ if (isDropdownOpened || !isSourceFunction) {
50
+ return;
51
+ }
52
+ setFetchedItems(EMPTY_ITEMS);
53
+ setFetchedQuery(null);
54
+ }, [isDropdownOpened, isSourceFunction]);
55
+ var sourceItems = useMemo(function () { return (Array.isArray(source) ? source : EMPTY_ITEMS); }, [source]);
56
+ var items = useMemo(function () { return sanitizeTimeItems(isSourceFunction ? fetchedItems : sourceItems, format); }, [fetchedItems, format, isSourceFunction, sourceItems]);
57
+ return { items: items, fetchedQuery: fetchedQuery, isLoading: isLoading };
58
+ };
59
+ //# sourceMappingURL=useTimePickerSource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTimePickerSource.js","sourceRoot":"","sources":["useTimePickerSource.ts"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useMemo, useRef, useState } from 'react';\n\nimport type {\n TimeFormat,\n TimeItemValue,\n TimePickerExtendedItem,\n TimePickerSource,\n} from '../helpers/TimePicker.shared.js';\nimport { sanitizeTimeItems } from '../helpers/TimePicker.value.js';\n\n/** Общая пустая коллекция элементов: не создает новую ссылку на каждый рендер. */\nconst EMPTY_ITEMS: never[] = [];\n\ninterface UseTimePickerSourceOptions<T extends TimeItemValue> {\n source?: TimePickerSource<T>;\n format: TimeFormat;\n isDropdownOpened: boolean;\n /** Текущий запрос: введенные цифры сегментов с сохранением их позиций. */\n filterQuery: string;\n}\n\ninterface UseTimePickerSourceResult<T extends TimeItemValue> {\n /** Элементы источника, готовые к фильтрации и отрисовке. */\n items: Array<TimePickerExtendedItem<T>>;\n /** Запрос, для которого получены текущие элементы функции-источника. */\n fetchedQuery: string | null;\n isLoading: boolean;\n}\n\n/**\n * Отдает элементы выпадающего списка из массива или функции-источника.\n *\n * Функция вызывается только для открытого меню и на каждый новый запрос;\n * ответ на устаревший запрос отбрасывается, а отказ трактуется как пустой результат.\n * При закрытии меню результаты функции сбрасываются, чтобы следующее открытие\n * не показывало элементы для старого запроса.\n * Замена самой функции уже открытый список не перезапрашивает: актуальная функция\n * используется при следующем запросе.\n */\nexport const useTimePickerSource = <T extends TimeItemValue>(\n options: UseTimePickerSourceOptions<T>,\n): UseTimePickerSourceResult<T> => {\n const { source, format, isDropdownOpened, filterQuery } = options;\n\n const isSourceFunction = typeof source === 'function';\n\n const [fetchedItems, setFetchedItems] = useState<Array<TimePickerExtendedItem<T>>>([]);\n const [fetchedQuery, setFetchedQuery] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n const sourceRef = useRef(source);\n sourceRef.current = source;\n\n useEffect(() => {\n const currentSource = sourceRef.current;\n\n if (typeof currentSource !== 'function' || !isDropdownOpened) {\n setIsLoading(false);\n return;\n }\n\n let cancelled = false;\n\n setIsLoading(true);\n\n new Promise<Array<TimePickerExtendedItem<T>>>((resolve) => resolve(currentSource(filterQuery))).then(\n (nextItems) => {\n if (!cancelled) {\n setFetchedItems(nextItems);\n setFetchedQuery(filterQuery);\n setIsLoading(false);\n }\n },\n () => {\n if (!cancelled) {\n setFetchedItems([]);\n setFetchedQuery(filterQuery);\n setIsLoading(false);\n }\n },\n );\n\n return () => {\n cancelled = true;\n };\n }, [filterQuery, isDropdownOpened, isSourceFunction]);\n\n useEffect(() => {\n if (isDropdownOpened || !isSourceFunction) {\n return;\n }\n\n setFetchedItems(EMPTY_ITEMS);\n setFetchedQuery(null);\n }, [isDropdownOpened, isSourceFunction]);\n\n const sourceItems = useMemo(() => (Array.isArray(source) ? source : EMPTY_ITEMS), [source]);\n\n const items = useMemo(\n () => sanitizeTimeItems(isSourceFunction ? fetchedItems : sourceItems, format),\n [fetchedItems, format, isSourceFunction, sourceItems],\n );\n\n return { items, fetchedQuery, isLoading };\n};\n"]}
@@ -0,0 +1,33 @@
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
+ /**
8
+ * Значением управляет родитель: проп `value` задан.
9
+ * Если проп не задан, компонент неконтролируемый и хранит значение сам,
10
+ * поэтому внешнее пустое значение не должно затирать введенное пользователем.
11
+ */
12
+ isValueControlled: boolean;
13
+ format: TimeFormat;
14
+ /**
15
+ * Вызывается при коммите значения: получает нормализованное время
16
+ * и элемент из `source`, если значение выбрано в выпадающем меню.
17
+ */
18
+ onCommitValue(value: string, item: TimeItemValue | null): void;
19
+ onInputValueChange?(value: string): void;
20
+ }
21
+ interface UseTimePickerValueResult {
22
+ editingValue: string;
23
+ editingValueRef: RefObject<string>;
24
+ setEditingValue(value: string): void;
25
+ updateEditingValue(value: string): void;
26
+ commitEditingValue(): string;
27
+ /** Коммитит значение, введенное пользователем. Не эмитит повторно то же самое время. */
28
+ commitValue(value: string, item?: TimeItemValue | null): string;
29
+ /** Коммитит элемент, выбранный в выпадающем меню. Эмитит всегда, так как это явное действие пользователя. */
30
+ commitItem(item: TimeItemValue): string;
31
+ }
32
+ export declare const useTimePickerValue: (options: UseTimePickerValueOptions) => UseTimePickerValueResult;
33
+ export {};
@@ -0,0 +1,97 @@
1
+ import { useCallback, useEffect, useRef, useState } from 'react';
2
+ import warning from 'warning';
3
+ import { EMPTY_VALUE } from '../helpers/TimePicker.constants.js';
4
+ import { getTimeItemValue } from '../helpers/TimePicker.shared.js';
5
+ import { getExternalTimeDisplayValue, isTimeDisplayEmpty, normalizeTimeValue, serializeTimeValue, } from '../helpers/TimePicker.value.js';
6
+ export var useTimePickerValue = function (options) {
7
+ var externalValue = options.externalValue, isValueControlled = options.isValueControlled, format = options.format, isInputFocused = options.isInputFocused, onCommitValue = options.onCommitValue, onInputValueChange = options.onInputValueChange;
8
+ var externalEditingValue = getExternalTimeDisplayValue(externalValue, format);
9
+ var _a = useState(externalEditingValue), editingValue = _a[0], setEditingValueState = _a[1];
10
+ var editingValueRef = useRef(editingValue);
11
+ var emittedInputValueRef = useRef(externalValue);
12
+ var emittedValueRef = useRef(externalValue);
13
+ var lastEmittedValueRef = useRef(externalValue);
14
+ /**
15
+ * Синхронизирует счетчики отданных значений с внешним значением.
16
+ * Коммит сравнивает время в нормализованной форме, поэтому счетчик закоммиченного значения хранит ее:
17
+ * иначе внешнее `9:00` или `09:00:00` в формате `HH:mm` выглядело бы как изменение
18
+ * и поле коммитило бы его заново, собирая элемент вместо исходного.
19
+ * Остальные счетчики хранят значение как есть: с ними сравнивают частичное значение и то,
20
+ * что вернул родитель.
21
+ */
22
+ var syncEmittedValues = useCallback(function (nextValue) {
23
+ emittedInputValueRef.current = nextValue;
24
+ emittedValueRef.current = normalizeTimeValue(nextValue, format);
25
+ lastEmittedValueRef.current = nextValue;
26
+ }, [format]);
27
+ var setEditingValue = useCallback(function (nextEditingValue) {
28
+ editingValueRef.current = nextEditingValue;
29
+ setEditingValueState(nextEditingValue);
30
+ }, []);
31
+ var emitInputValue = useCallback(function (nextValue) {
32
+ if (emittedInputValueRef.current !== nextValue) {
33
+ emittedInputValueRef.current = nextValue;
34
+ lastEmittedValueRef.current = nextValue;
35
+ onInputValueChange === null || onInputValueChange === void 0 ? void 0 : onInputValueChange(nextValue);
36
+ }
37
+ }, [onInputValueChange]);
38
+ var emitValue = useCallback(function (nextValue, item) {
39
+ emittedInputValueRef.current = nextValue;
40
+ emittedValueRef.current = nextValue;
41
+ lastEmittedValueRef.current = nextValue;
42
+ onCommitValue(nextValue, item);
43
+ }, [onCommitValue]);
44
+ var updateEditingValue = useCallback(function (nextEditingValue) {
45
+ setEditingValue(nextEditingValue);
46
+ emitInputValue(serializeTimeValue(nextEditingValue, format));
47
+ }, [emitInputValue, format, setEditingValue]);
48
+ var commitValue = useCallback(function (nextValue, item) {
49
+ if (item === void 0) { item = null; }
50
+ var normalizedValue = normalizeTimeValue(nextValue, format);
51
+ setEditingValue(normalizedValue);
52
+ if (emittedValueRef.current !== normalizedValue) {
53
+ emitValue(normalizedValue, item);
54
+ }
55
+ return normalizedValue;
56
+ }, [emitValue, format, setEditingValue]);
57
+ var commitItem = useCallback(function (item) {
58
+ var normalizedValue = normalizeTimeValue(getTimeItemValue(item), format);
59
+ setEditingValue(normalizedValue);
60
+ emitValue(normalizedValue, item);
61
+ return normalizedValue;
62
+ }, [emitValue, format, setEditingValue]);
63
+ var commitEditingValue = useCallback(function () {
64
+ var currentEditingValue = editingValueRef.current;
65
+ if (isTimeDisplayEmpty(currentEditingValue)) {
66
+ return commitValue(EMPTY_VALUE);
67
+ }
68
+ return commitValue(currentEditingValue);
69
+ }, [commitValue, editingValueRef]);
70
+ var initialIsValueControlledRef = useRef(isValueControlled);
71
+ useEffect(function () {
72
+ warning(initialIsValueControlledRef.current === isValueControlled, isValueControlled
73
+ ? '[TimePicker]: a component is changing an uncontrolled value to be controlled. ' +
74
+ 'Decide between using a controlled or uncontrolled value for the lifetime of the component.'
75
+ : '[TimePicker]: a component is changing a controlled value to be uncontrolled. ' +
76
+ 'Pass an empty string or null instead of undefined to keep the value controlled.');
77
+ }, [isValueControlled]);
78
+ useEffect(function () {
79
+ if (!isValueControlled) {
80
+ return;
81
+ }
82
+ if (!isInputFocused || externalValue !== lastEmittedValueRef.current) {
83
+ setEditingValue(externalEditingValue);
84
+ }
85
+ syncEmittedValues(externalValue);
86
+ }, [externalEditingValue, externalValue, isInputFocused, isValueControlled, setEditingValue, syncEmittedValues]);
87
+ return {
88
+ editingValue: editingValue,
89
+ editingValueRef: editingValueRef,
90
+ setEditingValue: setEditingValue,
91
+ updateEditingValue: updateEditingValue,
92
+ commitEditingValue: commitEditingValue,
93
+ commitValue: commitValue,
94
+ commitItem: commitItem,
95
+ };
96
+ };
97
+ //# 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';\nimport warning from 'warning';\n\nimport { EMPTY_VALUE } from '../helpers/TimePicker.constants.js';\nimport { getTimeItemValue, type TimeFormat, type TimeItemValue } from '../helpers/TimePicker.shared.js';\nimport {\n getExternalTimeDisplayValue,\n isTimeDisplayEmpty,\n normalizeTimeValue,\n serializeTimeValue,\n} from '../helpers/TimePicker.value.js';\n\ninterface UseTimePickerValueOptions {\n isInputFocused: boolean;\n /** Внешнее значение, приведенное к строке времени. */\n externalValue: string;\n /**\n * Значением управляет родитель: проп `value` задан.\n * Если проп не задан, компонент неконтролируемый и хранит значение сам,\n * поэтому внешнее пустое значение не должно затирать введенное пользователем.\n */\n isValueControlled: boolean;\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, isValueControlled, format, isInputFocused, onCommitValue, onInputValueChange } = options;\n\n const externalEditingValue = getExternalTimeDisplayValue(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 /**\n * Синхронизирует счетчики отданных значений с внешним значением.\n * Коммит сравнивает время в нормализованной форме, поэтому счетчик закоммиченного значения хранит ее:\n * иначе внешнее `9:00` или `09:00:00` в формате `HH:mm` выглядело бы как изменение\n * и поле коммитило бы его заново, собирая элемент вместо исходного.\n * Остальные счетчики хранят значение как есть: с ними сравнивают частичное значение и то,\n * что вернул родитель.\n */\n const syncEmittedValues = useCallback(\n (nextValue: string) => {\n emittedInputValueRef.current = nextValue;\n emittedValueRef.current = normalizeTimeValue(nextValue, format);\n lastEmittedValueRef.current = nextValue;\n },\n [format],\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 emittedInputValueRef.current = nextValue;\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 const initialIsValueControlledRef = useRef(isValueControlled);\n\n useEffect(() => {\n warning(\n initialIsValueControlledRef.current === isValueControlled,\n isValueControlled\n ? '[TimePicker]: a component is changing an uncontrolled value to be controlled. ' +\n 'Decide between using a controlled or uncontrolled value for the lifetime of the component.'\n : '[TimePicker]: a component is changing a controlled value to be uncontrolled. ' +\n 'Pass an empty string or null instead of undefined to keep the value controlled.',\n );\n }, [isValueControlled]);\n\n useEffect(() => {\n if (!isValueControlled) {\n return;\n }\n\n if (!isInputFocused || externalValue !== lastEmittedValueRef.current) {\n setEditingValue(externalEditingValue);\n }\n\n syncEmittedValues(externalValue);\n }, [externalEditingValue, externalValue, isInputFocused, isValueControlled, setEditingValue, syncEmittedValues]);\n\n return {\n editingValue,\n editingValueRef,\n setEditingValue,\n updateEditingValue,\n commitEditingValue,\n commitValue,\n commitItem,\n };\n};\n"]}
@@ -0,0 +1,4 @@
1
+ export * from './TimePicker.js';
2
+ export { TimePickerDataTids } from './helpers/TimePicker.constants.js';
3
+ export type { TimePickerValidationOptions } from './helpers/validateTimePicker.js';
4
+ export type { TimeFormat, TimeSegment, TimeItem, TimeItemValue, TimePickerExtendedItem, TimePickerMenuItem, TimePickerResolvedItem, TimePickerSource, TimePickerValue, TimePickerValueToItem, } from './helpers/TimePicker.shared.js';
@@ -0,0 +1,3 @@
1
+ export * from './TimePicker.js';
2
+ export { TimePickerDataTids } from './helpers/TimePicker.constants.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC","sourcesContent":["export * from './TimePicker.js';\nexport { TimePickerDataTids } from './helpers/TimePicker.constants.js';\nexport type { TimePickerValidationOptions } from './helpers/validateTimePicker.js';\nexport type {\n TimeFormat,\n TimeSegment,\n TimeItem,\n TimeItemValue,\n TimePickerExtendedItem,\n TimePickerMenuItem,\n TimePickerResolvedItem,\n TimePickerSource,\n TimePickerValue,\n TimePickerValueToItem,\n} from './helpers/TimePicker.shared.js';\n"]}
@@ -0,0 +1,4 @@
1
+ import { LocaleHelper } from '../../../lib/locale/LocaleHelper.js';
2
+ import type { TimePickerLocale } from './types.js';
3
+ export * from './types.js';
4
+ export declare const TimePickerLocaleHelper: LocaleHelper<TimePickerLocale>;
@@ -0,0 +1,9 @@
1
+ import { LocaleHelper } from '../../../lib/locale/LocaleHelper.js';
2
+ import { componentsLocales as en_GB } from './locales/en.js';
3
+ import { componentsLocales as ru_RU } from './locales/ru.js';
4
+ export * from './types.js';
5
+ export var TimePickerLocaleHelper = new LocaleHelper({
6
+ ru_RU: ru_RU,
7
+ en_GB: en_GB,
8
+ });
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AACnE,OAAO,EAAE,iBAAiB,IAAI,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,IAAI,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAG7D,cAAc,YAAY,CAAC;AAE3B,MAAM,CAAC,IAAM,sBAAsB,GAAG,IAAI,YAAY,CAAmB;IACvE,KAAK,OAAA;IACL,KAAK,OAAA;CACN,CAAC,CAAC","sourcesContent":["import { LocaleHelper } from '../../../lib/locale/LocaleHelper.js';\nimport { componentsLocales as en_GB } from './locales/en.js';\nimport { componentsLocales as ru_RU } from './locales/ru.js';\nimport type { TimePickerLocale } from './types.js';\n\nexport * from './types.js';\n\nexport const TimePickerLocaleHelper = new LocaleHelper<TimePickerLocale>({\n ru_RU,\n en_GB,\n});\n"]}
@@ -0,0 +1,2 @@
1
+ import type { TimePickerLocale } from '../types.js';
2
+ export declare const componentsLocales: TimePickerLocale;
@@ -0,0 +1,5 @@
1
+ export var componentsLocales = {
2
+ ariaPlaceholderHHMM: 'hh:mm',
3
+ ariaPlaceholderHHMMSS: 'hh:mm:ss',
4
+ };
5
+ //# sourceMappingURL=en.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"en.js","sourceRoot":"","sources":["en.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,IAAM,iBAAiB,GAAqB;IACjD,mBAAmB,EAAE,OAAO;IAC5B,qBAAqB,EAAE,UAAU;CAClC,CAAC","sourcesContent":["import type { TimePickerLocale } from '../types.js';\n\nexport const componentsLocales: TimePickerLocale = {\n ariaPlaceholderHHMM: 'hh:mm',\n ariaPlaceholderHHMMSS: 'hh:mm:ss',\n};\n"]}
@@ -0,0 +1,2 @@
1
+ import type { TimePickerLocale } from '../types.js';
2
+ export declare const componentsLocales: TimePickerLocale;
@@ -0,0 +1,5 @@
1
+ export var componentsLocales = {
2
+ ariaPlaceholderHHMM: 'чч:мм',
3
+ ariaPlaceholderHHMMSS: 'чч:мм:сс',
4
+ };
5
+ //# sourceMappingURL=ru.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ru.js","sourceRoot":"","sources":["ru.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,IAAM,iBAAiB,GAAqB;IACjD,mBAAmB,EAAE,OAAO;IAC5B,qBAAqB,EAAE,UAAU;CAClC,CAAC","sourcesContent":["import type { TimePickerLocale } from '../types.js';\n\nexport const componentsLocales: TimePickerLocale = {\n ariaPlaceholderHHMM: 'чч:мм',\n ariaPlaceholderHHMMSS: 'чч:мм:сс',\n};\n"]}
@@ -0,0 +1,4 @@
1
+ export interface TimePickerLocale {
2
+ ariaPlaceholderHHMM: string;
3
+ ariaPlaceholderHHMMSS: string;
4
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"","sourcesContent":["export interface TimePickerLocale {\n ariaPlaceholderHHMM: string;\n ariaPlaceholderHHMMSS: string;\n}\n"]}
@@ -39,6 +39,8 @@ export interface ToggleProps extends Pick<AriaAttributes, 'aria-label' | 'aria-d
39
39
  onBlur?: React.FocusEventHandler<HTMLInputElement>;
40
40
  /** Отключает анимацию. */
41
41
  disableAnimations?: boolean;
42
+ /** Задаёт второстепенный пояснительный текст под основным текстом тогла. */
43
+ comment?: React.ReactNode;
42
44
  }
43
45
  export interface ToggleState {
44
46
  checked?: boolean;
@@ -80,7 +82,10 @@ export declare class Toggle extends React.Component<ToggleProps, ToggleState> {
80
82
  private getRootSizeClassName;
81
83
  private getInputSizeClassName;
82
84
  private getCaptionSizeClassName;
85
+ private getSubcaptionSizeClassName;
83
86
  private renderMain;
87
+ private renderCaption;
88
+ private renderComment;
84
89
  private inputRef;
85
90
  private handleChange;
86
91
  private handleFocus;
@@ -181,9 +181,20 @@ var Toggle = /** @class */ (function (_super) {
181
181
  return this.styles.captionSmall(this.theme);
182
182
  }
183
183
  };
184
+ Toggle.prototype.getSubcaptionSizeClassName = function () {
185
+ switch (this.size) {
186
+ case 'large':
187
+ return this.styles.subcaptionLarge(this.theme);
188
+ case 'medium':
189
+ return this.styles.subcaptionMedium(this.theme);
190
+ case 'small':
191
+ default:
192
+ return this.styles.subcaptionSmall(this.theme);
193
+ }
194
+ };
184
195
  Toggle.prototype.renderMain = function () {
185
196
  var _a, _b, _c, _d, _e;
186
- var _f = this.props, children = _f.children, warning = _f.warning, error = _f.error, id = _f.id, name = _f.name, ariaDescribedby = _f["aria-describedby"], ariaLabel = _f["aria-label"];
197
+ var _f = this.props, children = _f.children, warning = _f.warning, error = _f.error, id = _f.id, name = _f.name, comment = _f.comment, ariaDescribedby = _f["aria-describedby"], ariaLabel = _f["aria-label"];
187
198
  var _g = this.getProps(), loading = _g.loading, captionPosition = _g.captionPosition, disableAnimations = _g.disableAnimations;
188
199
  var disabled = this.getProps().disabled || loading;
189
200
  var checked = this.isUncontrolled() ? this.state.checked : this.props.checked;
@@ -201,32 +212,45 @@ var Toggle = /** @class */ (function (_super) {
201
212
  _b[globalClasses.disabled] = !!disabled,
202
213
  _b[this.styles.disableAnimation()] = disableAnimations,
203
214
  _b));
204
- var caption = null;
205
- if (children) {
206
- var captionClass = this.cx(this.getCaptionSizeClassName(), (_c = {},
207
- _c[this.styles.caption(this.theme)] = true,
208
- _c[this.styles.captionLeft(this.theme)] = captionPosition === 'left',
209
- _c[this.styles.disabledCaption(this.theme)] = !!disabled,
210
- _c));
211
- caption = React.createElement("span", { className: captionClass }, children);
212
- }
213
215
  return (React.createElement(CommonWrapper, __assign({ rootNodeRef: this.setRootNode }, this.props),
214
216
  React.createElement("label", { "data-tid": ToggleDataTids.root, className: labelClassNames },
215
- React.createElement("div", { className: this.cx(this.getButtonSizeClassName(), (_d = {},
216
- _d[this.styles.button(this.theme)] = true,
217
- _d[this.styles.buttonRight()] = captionPosition === 'left',
218
- _d[this.styles.isWarning(this.theme)] = !!warning,
219
- _d[this.styles.isError(this.theme)] = !!error,
220
- _d[this.styles.focused(this.theme)] = !disabled && !!this.state.focusByTab,
221
- _d)) },
217
+ React.createElement("div", { className: this.cx(this.getButtonSizeClassName(), (_c = {},
218
+ _c[this.styles.button(this.theme)] = true,
219
+ _c[this.styles.buttonRight()] = captionPosition === 'left',
220
+ _c[this.styles.isWarning(this.theme)] = !!warning,
221
+ _c[this.styles.isError(this.theme)] = !!error,
222
+ _c[this.styles.focused(this.theme)] = !disabled && !!this.state.focusByTab,
223
+ _c)) },
222
224
  React.createElement(FocusControlWrapper, { onBlurWhenDisabled: this.resetFocus },
223
225
  React.createElement("input", { type: "checkbox", checked: checked, onChange: this.handleChange, className: this.cx(this.getInputSizeClassName(), this.styles.input(this.theme)), onFocus: this.handleFocus, onBlur: this.handleBlur, ref: this.inputRef, disabled: disabled, id: id, name: name, role: "switch", "aria-label": ariaLabel, "aria-describedby": ariaDescribedby })),
224
226
  React.createElement("div", { className: containerClassNames }),
225
- React.createElement("div", { className: this.cx(this.getHandleSizeClassName(), globalClasses.handle, (_e = {},
226
- _e[this.styles.handle(this.theme)] = true,
227
- _e[this.styles.handleDisabled(this.theme)] = disabled,
228
- _e)) })),
229
- caption)));
227
+ React.createElement("div", { className: this.cx(this.getHandleSizeClassName(), globalClasses.handle, (_d = {},
228
+ _d[this.styles.handle(this.theme)] = true,
229
+ _d[this.styles.handleDisabled(this.theme)] = disabled,
230
+ _d)) })),
231
+ children &&
232
+ (comment ? (React.createElement("div", { className: this.cx(this.styles.captionWrapper(), (_e = {},
233
+ _e[this.styles.captionWrapperGap(this.theme)] = captionPosition !== 'left',
234
+ _e[this.styles.captionWrapperGapLeft(this.theme)] = captionPosition === 'left',
235
+ _e)) },
236
+ this.renderCaption(disabled, captionPosition, true),
237
+ this.renderComment(disabled))) : (this.renderCaption(disabled, captionPosition, false))))));
238
+ };
239
+ Toggle.prototype.renderCaption = function (disabled, captionPosition, noGap) {
240
+ var _a;
241
+ var captionClass = this.cx(this.getCaptionSizeClassName(), (_a = {},
242
+ _a[this.styles.caption(this.theme)] = true,
243
+ _a[this.styles.captionLeft(this.theme)] = captionPosition === 'left',
244
+ _a[this.styles.disabledCaption(this.theme)] = !!disabled,
245
+ _a[this.styles.captionNoGap()] = noGap,
246
+ _a));
247
+ return React.createElement("div", { className: captionClass }, this.props.children);
248
+ };
249
+ Toggle.prototype.renderComment = function (disabled) {
250
+ var _a;
251
+ return (React.createElement("div", { className: this.cx(this.styles.subcaption(this.theme), this.getSubcaptionSizeClassName(), (_a = {},
252
+ _a[this.styles.subcaptionDisabled(this.theme)] = !!disabled,
253
+ _a)) }, this.props.comment));
230
254
  };
231
255
  Toggle.prototype.isUncontrolled = function () {
232
256
  return this.props.checked === undefined;