@snack-uikit/fields 0.18.4-preview-5d3667ec.0 → 0.19.1

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 (55) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +6 -6
  3. package/dist/components/FieldDate/FieldDate.js +5 -3
  4. package/dist/components/FieldDecorator/FieldDecorator.d.ts +1 -1
  5. package/dist/components/FieldDecorator/FieldDecorator.js +4 -3
  6. package/dist/components/FieldSecure/FieldSecure.js +3 -1
  7. package/dist/components/FieldSelect/FieldSelectMultiple.d.ts +3 -1
  8. package/dist/components/FieldSelect/FieldSelectMultiple.js +13 -4
  9. package/dist/components/FieldSelect/FieldSelectSingle.d.ts +3 -1
  10. package/dist/components/FieldSelect/FieldSelectSingle.js +20 -6
  11. package/dist/components/FieldSelect/hooks.js +8 -2
  12. package/dist/components/FieldSelect/legacy/components/Items/hooks.d.ts +12 -0
  13. package/dist/components/FieldSelect/legacy/components/Items/hooks.js +33 -0
  14. package/dist/components/FieldSelect/legacy/components/index.d.ts +1 -0
  15. package/dist/components/FieldSelect/legacy/components/index.js +1 -0
  16. package/dist/components/FieldSelect/legacy/hooks.d.ts +5 -0
  17. package/dist/components/FieldSelect/legacy/hooks.js +19 -0
  18. package/dist/components/FieldSelect/legacy/index.d.ts +3 -0
  19. package/dist/components/FieldSelect/legacy/index.js +3 -0
  20. package/dist/components/FieldSelect/legacy/utils.d.ts +29 -0
  21. package/dist/components/FieldSelect/legacy/utils.js +107 -0
  22. package/dist/components/FieldSelect/types.d.ts +6 -3
  23. package/dist/components/FieldSelect/utils/extractListProps.d.ts +1 -1
  24. package/dist/components/FieldSelect/utils/extractListProps.js +1 -3
  25. package/dist/components/FieldSelect/utils/options.js +1 -1
  26. package/dist/components/FieldSelect/utils/typeGuards.js +1 -1
  27. package/dist/components/FieldSelect/utils/updateItems.d.ts +6 -6
  28. package/dist/components/FieldSelect/utils/updateItems.js +12 -3
  29. package/dist/components/FieldStepper/FieldStepper.js +3 -1
  30. package/dist/components/FieldText/FieldText.js +3 -1
  31. package/dist/components/FieldTextArea/FieldTextArea.js +3 -1
  32. package/dist/helperComponents/FieldContainerPrivate/styles.module.css +1 -1
  33. package/dist/utils/getValidationState.d.ts +5 -0
  34. package/dist/utils/getValidationState.js +4 -0
  35. package/package.json +15 -13
  36. package/src/components/FieldDate/FieldDate.tsx +5 -3
  37. package/src/components/FieldDecorator/FieldDecorator.tsx +4 -3
  38. package/src/components/FieldSecure/FieldSecure.tsx +5 -2
  39. package/src/components/FieldSelect/FieldSelectMultiple.tsx +15 -4
  40. package/src/components/FieldSelect/FieldSelectSingle.tsx +19 -5
  41. package/src/components/FieldSelect/hooks.ts +11 -2
  42. package/src/components/FieldSelect/legacy/components/Items/hooks.tsx +53 -0
  43. package/src/components/FieldSelect/legacy/components/index.ts +1 -0
  44. package/src/components/FieldSelect/legacy/hooks.ts +32 -0
  45. package/src/components/FieldSelect/legacy/index.ts +3 -0
  46. package/src/components/FieldSelect/legacy/utils.ts +166 -0
  47. package/src/components/FieldSelect/types.ts +29 -12
  48. package/src/components/FieldSelect/utils/extractListProps.ts +0 -4
  49. package/src/components/FieldSelect/utils/options.ts +2 -1
  50. package/src/components/FieldSelect/utils/typeGuards.ts +1 -1
  51. package/src/components/FieldSelect/utils/updateItems.ts +14 -4
  52. package/src/components/FieldStepper/FieldStepper.tsx +5 -2
  53. package/src/components/FieldText/FieldText.tsx +4 -2
  54. package/src/components/FieldTextArea/FieldTextArea.tsx +5 -2
  55. package/src/utils/getValidationState.ts +6 -0
package/CHANGELOG.md CHANGED
@@ -3,6 +3,34 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## 0.19.1 (2024-04-24)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * **FF-0011:** validationState reacts on error prop ([d4a6cb5](https://github.com/cloud-ru-tech/snack-uikit/commit/d4a6cb517662520476f6b690c0a24b37311eb369))
12
+ * **FF-00:** fix input behavior for field-slider non-linear marks ([67fda28](https://github.com/cloud-ru-tech/snack-uikit/commit/67fda2853485bd69039351d71dbe9db5d14e163f))
13
+
14
+
15
+
16
+
17
+
18
+ # 0.19.0 (2024-04-23)
19
+
20
+
21
+ ### Bug Fixes
22
+
23
+ * **PDS-59:** upd tests ([df72712](https://github.com/cloud-ru-tech/snack-uikit/commit/df7271268ac1621316dbb98b274e3d6602515b23))
24
+
25
+
26
+ ### BREAKING CHANGES
27
+
28
+
29
+ * **PDS-59:** upd typings accordance with list; fix focus control ([827ff9f](https://github.com/cloud-ru-tech/snack-uikit/commit/827ff9f03ca5bae4664bc69664e4b8d812191103))
30
+
31
+
32
+
33
+
6
34
  ## 0.18.3 (2024-04-22)
7
35
 
8
36
 
package/README.md CHANGED
@@ -180,7 +180,7 @@ const [isOpen, setIsOpen] = useState(false);
180
180
  | labelTooltipPlacement | enum Placement: `"left"`, `"left-start"`, `"left-end"`, `"right"`, `"right-start"`, `"right-end"`, `"top"`, `"top-start"`, `"top-end"`, `"bottom"`, `"bottom-start"`, `"bottom-end"` | top | Расположение подсказки лейбла |
181
181
  | length | `{ current: number; max?: number; }` | - | Допустимая длинна текста |
182
182
  | hint | `string` | - | Подсказка внизу |
183
- | validationState | enum ValidationState: `"default"`, `"error"`, `"warning"`, `"success"` | - | Состояние валидации |
183
+ | validationState | enum ValidationState: `"default"`, `"error"`, `"warning"`, `"success"` | default | Состояние валидации |
184
184
  | showHintIcon | `boolean` | - | Отображать иконку подсказки |
185
185
  ## FieldText
186
186
  ### Props
@@ -312,6 +312,8 @@ const [isOpen, setIsOpen] = useState(false);
312
312
  ### Props
313
313
  | name | type | default value | description |
314
314
  |------|------|---------------|-------------|
315
+ | pinBottom* | `OptionProps[]` | - | |
316
+ | pinTop* | `OptionProps[]` | - | |
315
317
  | options* | `OptionProps[]` | - | |
316
318
  | disabled | `boolean` | false | Является ли поле деактивированным |
317
319
  | readonly | `boolean` | false false | Является ли поле доступным только для чтения |
@@ -332,9 +334,9 @@ const [isOpen, setIsOpen] = useState(false);
332
334
  | validationState | enum ValidationState: `"default"`, `"error"`, `"warning"`, `"success"` | - | Состояние валидации |
333
335
  | showHintIcon | `boolean` | - | Отображать иконку подсказки |
334
336
  | loading | `boolean` | - | |
335
- | value | `SelectionSingleValueType \| SelectionSingleValueType[]` | - | Controlled состояние |
336
- | onChange | `((value: any) => void) \| ((value: any) => void)` | - | Controlled обработчик измения состояния |
337
- | defaultValue | `SelectionSingleValueType \| SelectionSingleValueType[]` | - | Начальное состояние |
337
+ | value | `ItemId \| ItemId[]` | - | Controlled состояние |
338
+ | onChange | `OnChangeHandler<any>` | - | Controlled обработчик измения состояния |
339
+ | defaultValue | `ItemId \| ItemId[]` | - | Начальное состояние |
338
340
  | searchable | `boolean` | - | |
339
341
  | showCopyButton | `boolean` | - | Отображение кнопки Копировать для поля (актуально только для `readonly = true`) |
340
342
  | showClearButton | `boolean` | true | Отображение кнопки очистки поля |
@@ -347,8 +349,6 @@ const [isOpen, setIsOpen] = useState(false);
347
349
  | open | `boolean` | - | |
348
350
  | onOpenChange | `(open: boolean) => void` | - | |
349
351
  | selectedOptionFormatter | `SelectedOptionFormatter` | - | |
350
- | pinTop | `ItemProps[]` | - | Элементы списка, закрепленные сверху |
351
- | pinBottom | `ItemProps[]` | - | Элементы списка, закрепленные снизу |
352
352
  | dataFiltered | `boolean` | - | |
353
353
  | dataError | `boolean` | - | |
354
354
  | noDataState | `EmptyStateProps` | - | Экран при отстутствии данных |
@@ -14,13 +14,14 @@ import mergeRefs from 'merge-refs';
14
14
  import { forwardRef, useCallback, useEffect, useMemo, useRef, useState, } from 'react';
15
15
  import { useUncontrolledProp } from 'uncontrollable';
16
16
  import { Calendar } from '@snack-uikit/calendar';
17
- import { Dropdown } from '@snack-uikit/droplist';
17
+ import { Dropdown } from '@snack-uikit/dropdown';
18
18
  import { CalendarSVG } from '@snack-uikit/icons';
19
19
  import { ICON_SIZE, InputPrivate, runAfterRerender, SIZE, useButtonNavigation, useClearButton, } from '@snack-uikit/input-private';
20
20
  import { extractSupportProps } from '@snack-uikit/utils';
21
21
  import { CONTAINER_VARIANT, VALIDATION_STATE } from '../../constants';
22
22
  import { FieldContainerPrivate } from '../../helperComponents';
23
23
  import { useCopyButton } from '../../hooks';
24
+ import { getValidationState } from '../../utils/getValidationState';
24
25
  import { FieldDecorator } from '../FieldDecorator';
25
26
  import { DEFAULT_LOCALE, SlotKey } from './constants';
26
27
  import { useDateField } from './hooks';
@@ -45,6 +46,7 @@ export const FieldDate = forwardRef((_a, ref) => {
45
46
  const showAdditionalButton = Boolean(valueProp && !disabled);
46
47
  const showClearButton = showClearButtonProp && showAdditionalButton && !readonly;
47
48
  const showCopyButton = showCopyButtonProp && showAdditionalButton && readonly;
49
+ const fieldValidationState = getValidationState({ validationState, error });
48
50
  const checkForLeavingFocus = useCallback((event) => {
49
51
  if (event.key === 'ArrowDown') {
50
52
  setPickerAutofocus(true);
@@ -133,7 +135,7 @@ export const FieldDate = forwardRef((_a, ref) => {
133
135
  e.stopPropagation();
134
136
  }
135
137
  }, [dateInputClickHandler, isOpen]);
136
- return (_jsx(FieldDecorator, Object.assign({ className: className, label: label, labelTooltip: labelTooltip, labelTooltipPlacement: labelTooltipPlacement, labelFor: id, required: required, hint: hint, disabled: disabled, readonly: readonly, showHintIcon: showHintIcon, size: size, error: error, validationState: validationState }, extractSupportProps(rest), { children: _jsx(Dropdown, Object.assign({ trigger: 'click', triggerClassName: styles.triggerClassName, widthStrategy: 'gte' }, (readonly || disabled
138
+ return (_jsx(FieldDecorator, Object.assign({ className: className, label: label, labelTooltip: labelTooltip, labelTooltipPlacement: labelTooltipPlacement, labelFor: id, required: required, hint: hint, disabled: disabled, readonly: readonly, showHintIcon: showHintIcon, size: size, error: error, validationState: fieldValidationState }, extractSupportProps(rest), { children: _jsx(Dropdown, Object.assign({ trigger: 'click', triggerClassName: styles.triggerClassName, widthStrategy: 'gte' }, (readonly || disabled
137
139
  ? { open: false }
138
140
  : {
139
141
  open: showDropList,
@@ -143,5 +145,5 @@ export const FieldDate = forwardRef((_a, ref) => {
143
145
  element === null || element === void 0 ? void 0 : element.focus();
144
146
  setPickerAutofocus(false);
145
147
  }
146
- }, onFocusLeave: handleCalendarFocusLeave, locale: locale, "data-test-id": 'field-date__calendar' }) }), children: _jsx(FieldContainerPrivate, { className: styles.container, size: size, validationState: validationState, disabled: disabled, readonly: readonly, variant: CONTAINER_VARIANT.SingleLine, focused: showDropList, inputRef: localRef, postfix: _jsxs(_Fragment, { children: [buttons, _jsx(CalendarSVG, { size: calendarIconSize, className: styles.calendarIcon, "data-size": size })] }), children: _jsx(InputPrivate, { ref: mergeRefs(ref, localRef), "data-size": size, value: value || '', placeholder: mask, onChange: handleChange, onFocus: inputHandlers.onFocus, onMouseDown: inputHandlers.onMouseDown, onBlur: onBlur, onKeyDown: handleInputKeyDown, onClick: onClick, disabled: disabled, readonly: readonly, tabIndex: inputTabIndex, type: 'text', id: id, name: name, "data-test-id": 'field-date__input' }) }) })) })));
148
+ }, onFocusLeave: handleCalendarFocusLeave, locale: locale, "data-test-id": 'field-date__calendar' }) }), children: _jsx(FieldContainerPrivate, { className: styles.container, size: size, validationState: fieldValidationState, disabled: disabled, readonly: readonly, variant: CONTAINER_VARIANT.SingleLine, focused: showDropList, inputRef: localRef, postfix: _jsxs(_Fragment, { children: [buttons, _jsx(CalendarSVG, { size: calendarIconSize, className: styles.calendarIcon, "data-size": size })] }), children: _jsx(InputPrivate, { ref: mergeRefs(ref, localRef), "data-size": size, value: value || '', placeholder: mask, onChange: handleChange, onFocus: inputHandlers.onFocus, onMouseDown: inputHandlers.onMouseDown, onBlur: onBlur, onKeyDown: handleInputKeyDown, onClick: onClick, disabled: disabled, readonly: readonly, tabIndex: inputTabIndex, type: 'text', id: id, name: name, "data-test-id": 'field-date__input' }) }) })) })));
147
149
  });
@@ -12,4 +12,4 @@ export type FieldDecoratorProps = WithSupportProps<{
12
12
  readonly?: boolean;
13
13
  error?: string;
14
14
  } & HeaderProps & FooterProps>;
15
- export declare function FieldDecorator({ children, className, label, labelTooltip, required, labelFor, length, hint, disabled, readonly, showHintIcon, labelTooltipPlacement, size, error, validationState: validationStateProp, ...rest }: FieldDecoratorProps): import("react/jsx-runtime").JSX.Element;
15
+ export declare function FieldDecorator({ children, className, label, labelTooltip, required, labelFor, length, hint, disabled, readonly, showHintIcon, labelTooltipPlacement, size, error, validationState, ...rest }: FieldDecoratorProps): import("react/jsx-runtime").JSX.Element;
@@ -14,12 +14,13 @@ import cn from 'classnames';
14
14
  import { SIZE } from '@snack-uikit/input-private';
15
15
  import { extractSupportProps } from '@snack-uikit/utils';
16
16
  import { VALIDATION_STATE } from '../../constants';
17
+ import { getValidationState } from '../../utils/getValidationState';
17
18
  import { Footer } from './Footer';
18
19
  import { Header } from './Header';
19
20
  import styles from './styles.module.css';
20
21
  export function FieldDecorator(_a) {
21
- var { children, className, label, labelTooltip, required, labelFor, length, hint, disabled, readonly, showHintIcon, labelTooltipPlacement, size = SIZE.S, error, validationState: validationStateProp = VALIDATION_STATE.Default } = _a, rest = __rest(_a, ["children", "className", "label", "labelTooltip", "required", "labelFor", "length", "hint", "disabled", "readonly", "showHintIcon", "labelTooltipPlacement", "size", "error", "validationState"]);
22
+ var { children, className, label, labelTooltip, required, labelFor, length, hint, disabled, readonly, showHintIcon, labelTooltipPlacement, size = SIZE.S, error, validationState = VALIDATION_STATE.Default } = _a, rest = __rest(_a, ["children", "className", "label", "labelTooltip", "required", "labelFor", "length", "hint", "disabled", "readonly", "showHintIcon", "labelTooltipPlacement", "size", "error", "validationState"]);
22
23
  const isFieldActive = !disabled && !readonly;
23
- const validationState = error ? VALIDATION_STATE.Error : validationStateProp;
24
- return (_jsxs("div", Object.assign({ className: cn(styles.decorator, className) }, extractSupportProps(rest), { "data-size": size, children: [label && (_jsx(Header, { labelTooltipPlacement: labelTooltipPlacement, required: required, label: label, labelTooltip: labelTooltip, labelFor: labelFor, size: size })), children, _jsx(Footer, { length: isFieldActive ? length : undefined, hint: error || hint, showHintIcon: showHintIcon, size: size, validationState: isFieldActive ? validationState : VALIDATION_STATE.Default })] })));
24
+ const fieldValidationState = getValidationState({ validationState, error });
25
+ return (_jsxs("div", Object.assign({ className: cn(styles.decorator, className) }, extractSupportProps(rest), { "data-size": size, children: [label && (_jsx(Header, { labelTooltipPlacement: labelTooltipPlacement, required: required, label: label, labelTooltip: labelTooltip, labelFor: labelFor, size: size })), children, _jsx(Footer, { length: isFieldActive ? length : undefined, hint: error || hint, showHintIcon: showHintIcon, size: size, validationState: isFieldActive ? fieldValidationState : VALIDATION_STATE.Default })] })));
25
26
  }
@@ -17,6 +17,7 @@ import { extractSupportProps } from '@snack-uikit/utils';
17
17
  import { CONTAINER_VARIANT, VALIDATION_STATE } from '../../constants';
18
18
  import { FieldContainerPrivate } from '../../helperComponents';
19
19
  import { useCopyButton, useHideButton, useValueControl } from '../../hooks';
20
+ import { getValidationState } from '../../utils/getValidationState';
20
21
  import { FieldDecorator } from '../FieldDecorator';
21
22
  export const FieldSecure = forwardRef((_a, ref) => {
22
23
  var { id, name, value: valueProp, placeholder, maxLength, disabled = false, readonly = false, showCopyButton: showCopyButtonProp = true, allowMoreThanMaxLength = false, hidden: hiddenProp, onHiddenChange, showHintIcon, onChange: onChangeProp, onFocus, onBlur, className, label, labelTooltip, labelTooltipPlacement, required = false, hint, size = SIZE.S, validationState = VALIDATION_STATE.Default, prefixIcon, error } = _a, rest = __rest(_a, ["id", "name", "value", "placeholder", "maxLength", "disabled", "readonly", "showCopyButton", "allowMoreThanMaxLength", "hidden", "onHiddenChange", "showHintIcon", "onChange", "onFocus", "onBlur", "className", "label", "labelTooltip", "labelTooltipPlacement", "required", "hint", "size", "validationState", "prefixIcon", "error"]);
@@ -35,6 +36,7 @@ export const FieldSecure = forwardRef((_a, ref) => {
35
36
  });
36
37
  const showCopyButton = showCopyButtonProp && Boolean(value) && readonly && !disabled;
37
38
  const showHideButton = !(readonly && !value);
39
+ const fieldValidationState = getValidationState({ validationState, error });
38
40
  const toggleHidden = () => {
39
41
  setHidden(!hidden);
40
42
  if (!readonly) {
@@ -53,5 +55,5 @@ export const FieldSecure = forwardRef((_a, ref) => {
53
55
  readonly,
54
56
  submitKeys: ['Enter', 'Space', 'Tab'],
55
57
  });
56
- return (_jsx(FieldDecorator, Object.assign({ className: className, label: label, labelTooltip: labelTooltip, labelTooltipPlacement: labelTooltipPlacement, labelFor: id, required: required, length: maxLength ? { max: maxLength, current: value.length } : undefined, hint: hint, disabled: disabled, readonly: readonly, showHintIcon: showHintIcon, size: size, error: error, validationState: validationState }, extractSupportProps(rest), { children: _jsx(FieldContainerPrivate, { size: size, validationState: validationState, disabled: disabled, readonly: readonly, variant: CONTAINER_VARIANT.SingleLine, inputRef: localRef, prefix: prefixIcon, postfix: buttons, children: _jsx(InputPrivate, { ref: mergeRefs(ref, localRef), "data-size": size, value: value, onChange: onChange, onFocus: onFocus, onBlur: onBlur, onKeyDown: onInputKeyDown, tabIndex: inputTabIndex, placeholder: placeholder, disabled: disabled, readonly: readonly, type: hidden ? 'password' : 'text', maxLength: allowMoreThanMaxLength ? undefined : maxLength || undefined, id: id, name: name, "data-test-id": 'field-secure__input' }) }) })));
58
+ return (_jsx(FieldDecorator, Object.assign({ className: className, label: label, labelTooltip: labelTooltip, labelTooltipPlacement: labelTooltipPlacement, labelFor: id, required: required, length: maxLength ? { max: maxLength, current: value.length } : undefined, hint: hint, disabled: disabled, readonly: readonly, showHintIcon: showHintIcon, size: size, error: error, validationState: fieldValidationState }, extractSupportProps(rest), { children: _jsx(FieldContainerPrivate, { size: size, validationState: fieldValidationState, disabled: disabled, readonly: readonly, variant: CONTAINER_VARIANT.SingleLine, inputRef: localRef, prefix: prefixIcon, postfix: buttons, children: _jsx(InputPrivate, { ref: mergeRefs(ref, localRef), "data-size": size, value: value, onChange: onChange, onFocus: onFocus, onBlur: onBlur, onKeyDown: onInputKeyDown, tabIndex: inputTabIndex, placeholder: placeholder, disabled: disabled, readonly: readonly, type: hidden ? 'password' : 'text', maxLength: allowMoreThanMaxLength ? undefined : maxLength || undefined, id: id, name: name, "data-test-id": 'field-secure__input' }) }) })));
57
59
  });
@@ -9,6 +9,8 @@ export declare const FieldSelectMultiple: import("react").ForwardRefExoticCompon
9
9
  'data-test-id'?: string | undefined;
10
10
  } & import("react").AriaAttributes & {
11
11
  options: import("./types").OptionProps[];
12
+ pinTop: import("./types").OptionProps[];
13
+ pinBottom: import("./types").OptionProps[];
12
14
  searchable?: boolean | undefined;
13
15
  showCopyButton?: boolean | undefined;
14
16
  showClearButton?: boolean | undefined;
@@ -22,4 +24,4 @@ export declare const FieldSelectMultiple: import("react").ForwardRefExoticCompon
22
24
  open?: boolean | undefined;
23
25
  onOpenChange?(open: boolean): void;
24
26
  selectedOptionFormatter?: SelectedOptionFormatter | undefined;
25
- } & Pick<import("@snack-uikit/list").DroplistProps, "pinTop" | "pinBottom" | "dataFiltered" | "dataError" | "noDataState" | "noResultsState" | "errorDataState">, "showCopyButton"> & import("react").RefAttributes<HTMLInputElement>>;
27
+ } & Pick<import("@snack-uikit/list").DroplistProps, "dataError" | "dataFiltered" | "noDataState" | "noResultsState" | "errorDataState">, "showCopyButton"> & import("react").RefAttributes<HTMLInputElement>>;
@@ -14,18 +14,23 @@ import cn from 'classnames';
14
14
  import mergeRefs from 'merge-refs';
15
15
  import { forwardRef, useLayoutEffect, useRef, useState } from 'react';
16
16
  import { InputPrivate } from '@snack-uikit/input-private';
17
- import { Droplist, useFuzzySearch } from '@snack-uikit/list';
17
+ import { Droplist } from '@snack-uikit/list';
18
18
  import { Tag } from '@snack-uikit/tag';
19
19
  import { extractSupportProps } from '@snack-uikit/utils';
20
20
  import { FieldContainerPrivate } from '../../helperComponents';
21
21
  import { useValueControl } from '../../hooks';
22
+ import { getValidationState } from '../../utils/getValidationState';
22
23
  import { FieldDecorator } from '../FieldDecorator';
23
24
  import { extractFieldDecoratorProps } from '../FieldDecorator/utils';
24
25
  import { useButtons, useHandleDeleteItem, useHandleOnKeyDown, useSearchInput } from './hooks';
26
+ import { useFuzzySearch } from './legacy';
25
27
  import styles from './styles.module.css';
26
28
  import { extractListProps, getArrowIcon, updateMultipleItems } from './utils';
27
29
  const BASE_MIN_WIDTH = 4;
28
- const defaultSelectedOptionFormatter = item => (item === null || item === void 0 ? void 0 : item.content.option) || '';
30
+ const defaultSelectedOptionFormatter = item =>
31
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
32
+ // @ts-expect-error
33
+ (item === null || item === void 0 ? void 0 : item.content.option) || '';
29
34
  export const FieldSelectMultiple = forwardRef((_a, ref) => {
30
35
  var _b;
31
36
  var { id, name, placeholder, size = 's', options, value: valueProp, defaultValue, onChange: onChangeProp, disabled = false, readonly = false, searchable = true, showClearButton = true, onKeyDown: onInputKeyDownProp, validationState = 'default', search, autocomplete = false, prefixIcon, removeByBackspace = false, addOptionByEnter = false, open: openProp, onOpenChange, selectedOptionFormatter = defaultSelectedOptionFormatter } = _a, rest = __rest(_a, ["id", "name", "placeholder", "size", "options", "value", "defaultValue", "onChange", "disabled", "readonly", "searchable", "showClearButton", "onKeyDown", "validationState", "search", "autocomplete", "prefixIcon", "removeByBackspace", "addOptionByEnter", "open", "onOpenChange", "selectedOptionFormatter"]);
@@ -47,6 +52,9 @@ export const FieldSelectMultiple = forwardRef((_a, ref) => {
47
52
  var _a;
48
53
  setValue(selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.filter(item => item.disabled).map(item => item.id));
49
54
  (_a = localRef.current) === null || _a === void 0 ? void 0 : _a.focus();
55
+ if (rest.required) {
56
+ setOpen(true);
57
+ }
50
58
  };
51
59
  const { ArrowIcon, arrowIconSize } = getArrowIcon({ size, open });
52
60
  const { buttons, inputKeyDownNavigationHandler, buttonsRefs } = useButtons({
@@ -108,7 +116,8 @@ export const FieldSelectMultiple = forwardRef((_a, ref) => {
108
116
  };
109
117
  const fuzzySearch = useFuzzySearch(items);
110
118
  const result = autocomplete || !searchable || prevInputValue.current === inputValue ? items : fuzzySearch(inputValue);
111
- return (_jsx(FieldDecorator, Object.assign({}, extractSupportProps(rest), extractFieldDecoratorProps(rest), { labelFor: id, size: size, validationState: validationState, children: _jsx(Droplist, Object.assign({}, extractListProps(rest), { items: result, triggerElemRef: localRef, selection: {
119
+ const fieldValidationState = getValidationState({ validationState, error: rest.error });
120
+ return (_jsx(FieldDecorator, Object.assign({}, extractSupportProps(rest), extractFieldDecoratorProps(rest), { labelFor: id, size: size, validationState: fieldValidationState, children: _jsx(Droplist, Object.assign({}, extractListProps(rest), { items: result, triggerElemRef: localRef, selection: {
112
121
  mode: 'multiple',
113
122
  value: value,
114
123
  onChange: value => {
@@ -117,7 +126,7 @@ export const FieldSelectMultiple = forwardRef((_a, ref) => {
117
126
  },
118
127
  }, dataFiltered: (_b = rest.dataFiltered) !== null && _b !== void 0 ? _b : Boolean(inputValue.length), size: size, open: !disabled && !readonly && open, onOpenChange: handleOpenChange, children: ({ onKeyDown }) => {
119
128
  var _a, _b, _c, _d;
120
- return (_jsx(FieldContainerPrivate, { className: cn(styles.container, styles.tagContainer), validationState: validationState, disabled: disabled, readonly: readonly, focused: open, variant: 'single-line-container', inputRef: localRef, size: size, prefix: prefixIcon, children: _jsxs(_Fragment, { children: [_jsxs("div", { className: styles.contentWrapper, ref: contentRef, children: [selectedItems &&
129
+ return (_jsx(FieldContainerPrivate, { className: cn(styles.container, styles.tagContainer), validationState: fieldValidationState, disabled: disabled, readonly: readonly, focused: open, variant: 'single-line-container', inputRef: localRef, size: size, prefix: prefixIcon, children: _jsxs(_Fragment, { children: [_jsxs("div", { className: styles.contentWrapper, ref: contentRef, children: [selectedItems &&
121
130
  selectedItems.map(option => {
122
131
  var _a;
123
132
  return (_jsx(Tag, { size: size === 'l' ? 's' : 'xs', tabIndex: -1, label: selectedOptionFormatter(option), appearance: (_a = option.appearance) !== null && _a !== void 0 ? _a : 'neutral', onDelete: !option.disabled && !disabled && !readonly ? handleItemDelete(option) : undefined }, option.id));
@@ -7,6 +7,8 @@ export declare const FieldSelectSingle: import("react").ForwardRefExoticComponen
7
7
  'data-test-id'?: string | undefined;
8
8
  } & import("react").AriaAttributes & {
9
9
  options: import("./types").OptionProps[];
10
+ pinTop: import("./types").OptionProps[];
11
+ pinBottom: import("./types").OptionProps[];
10
12
  searchable?: boolean | undefined;
11
13
  showCopyButton?: boolean | undefined;
12
14
  showClearButton?: boolean | undefined;
@@ -20,4 +22,4 @@ export declare const FieldSelectSingle: import("react").ForwardRefExoticComponen
20
22
  open?: boolean | undefined;
21
23
  onOpenChange?(open: boolean): void;
22
24
  selectedOptionFormatter?: SelectedOptionFormatter | undefined;
23
- } & Pick<import("@snack-uikit/list").DroplistProps, "pinTop" | "pinBottom" | "dataFiltered" | "dataError" | "noDataState" | "noResultsState" | "errorDataState"> & import("react").RefAttributes<HTMLInputElement>>;
25
+ } & Pick<import("@snack-uikit/list").DroplistProps, "dataError" | "dataFiltered" | "noDataState" | "noResultsState" | "errorDataState"> & import("react").RefAttributes<HTMLInputElement>>;
@@ -14,16 +14,21 @@ import cn from 'classnames';
14
14
  import mergeRefs from 'merge-refs';
15
15
  import { forwardRef, useCallback, useEffect, useLayoutEffect, useRef, useState, } from 'react';
16
16
  import { InputPrivate } from '@snack-uikit/input-private';
17
- import { Droplist, useFuzzySearch } from '@snack-uikit/list';
17
+ import { Droplist } from '@snack-uikit/list';
18
18
  import { extractSupportProps } from '@snack-uikit/utils';
19
19
  import { FieldContainerPrivate } from '../../helperComponents';
20
20
  import { useValueControl } from '../../hooks';
21
+ import { getValidationState } from '../../utils/getValidationState';
21
22
  import { FieldDecorator } from '../FieldDecorator';
22
23
  import { extractFieldDecoratorProps } from '../FieldDecorator/utils';
23
24
  import { useButtons, useHandleOnKeyDown, useSearchInput } from './hooks';
25
+ import { useFuzzySearch } from './legacy';
24
26
  import styles from './styles.module.css';
25
27
  import { extractListProps, getArrowIcon, updateItems } from './utils';
26
- const defaultSelectedOptionFormatter = item => (item === null || item === void 0 ? void 0 : item.content.option) || '';
28
+ const defaultSelectedOptionFormatter = item =>
29
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
30
+ // @ts-expect-error
31
+ (item === null || item === void 0 ? void 0 : item.content.option) || '';
27
32
  export const FieldSelectSingle = forwardRef((_a, ref) => {
28
33
  var _b;
29
34
  var { id, name, placeholder, size = 's', options, value: valueProp, defaultValue, onChange: onChangeProp, disabled = false, readonly = false, searchable = true, showCopyButton = true, showClearButton = true, onKeyDown: onInputKeyDownProp, required = false, validationState = 'default', search, autocomplete = false, prefixIcon, addOptionByEnter = false, open: openProp, onOpenChange, selectedOptionFormatter = defaultSelectedOptionFormatter } = _a, rest = __rest(_a, ["id", "name", "placeholder", "size", "options", "value", "defaultValue", "onChange", "disabled", "readonly", "searchable", "showCopyButton", "showClearButton", "onKeyDown", "required", "validationState", "search", "autocomplete", "prefixIcon", "addOptionByEnter", "open", "onOpenChange", "selectedOptionFormatter"]);
@@ -35,7 +40,10 @@ export const FieldSelectSingle = forwardRef((_a, ref) => {
35
40
  onChange: onChangeProp,
36
41
  });
37
42
  const [{ selectedItem, items = [] }, setItems] = useState(() => updateItems({ options, value, currentItems: [], selectedItem: undefined }));
38
- const { inputValue, setInputValue, prevInputValue, updateInputValue } = useSearchInput(Object.assign(Object.assign({}, search), { defaultValue: (_b = selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.content.option) !== null && _b !== void 0 ? _b : '', selectedOptionFormatter }));
43
+ const { inputValue, setInputValue, prevInputValue, updateInputValue } = useSearchInput(Object.assign(Object.assign({}, search), {
44
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
45
+ // @ts-expect-error
46
+ defaultValue: (_b = selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.content.option) !== null && _b !== void 0 ? _b : '', selectedOptionFormatter }));
39
47
  const prevSelectedItem = useRef(selectedItem);
40
48
  useLayoutEffect(() => {
41
49
  setItems(({ selectedItem }) => updateItems({ options, value, selectedItem }));
@@ -43,6 +51,8 @@ export const FieldSelectSingle = forwardRef((_a, ref) => {
43
51
  useEffect(() => {
44
52
  if (prevSelectedItem.current &&
45
53
  prevSelectedItem.current.id === (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.id) &&
54
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
55
+ // @ts-expect-error
46
56
  prevSelectedItem.current.content.option === (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.content.option)) {
47
57
  return;
48
58
  }
@@ -54,7 +64,10 @@ export const FieldSelectSingle = forwardRef((_a, ref) => {
54
64
  var _a;
55
65
  setValue(undefined);
56
66
  (_a = localRef.current) === null || _a === void 0 ? void 0 : _a.focus();
57
- }, [setValue]);
67
+ if (required) {
68
+ setOpen(true);
69
+ }
70
+ }, [required, setOpen, setValue]);
58
71
  const { ArrowIcon, arrowIconSize } = getArrowIcon({ size, open });
59
72
  const { buttons, inputKeyDownNavigationHandler, buttonsRefs } = useButtons({
60
73
  readonly,
@@ -110,11 +123,12 @@ export const FieldSelectSingle = forwardRef((_a, ref) => {
110
123
  const result = autocomplete || !searchable || selectedOptionFormatter(selectedItem) === inputValue
111
124
  ? items
112
125
  : fuzzySearch(inputValue);
113
- return (_jsx(FieldDecorator, Object.assign({}, extractSupportProps(rest), extractFieldDecoratorProps(rest), { validationState: validationState, required: required, readonly: readonly, labelFor: id, disabled: disabled, size: size, children: _jsx(Droplist, Object.assign({}, extractListProps(rest), { items: result, selection: {
126
+ const fieldValidationState = getValidationState({ validationState, error: rest.error });
127
+ return (_jsx(FieldDecorator, Object.assign({}, extractSupportProps(rest), extractFieldDecoratorProps(rest), { validationState: fieldValidationState, required: required, readonly: readonly, labelFor: id, disabled: disabled, size: size, children: _jsx(Droplist, Object.assign({}, extractListProps(rest), { items: result, selection: {
114
128
  mode: 'single',
115
129
  value: value,
116
130
  onChange: handleSelectionChange,
117
- }, size: size, open: open, onOpenChange: handleOpenChange, triggerElemRef: localRef, children: ({ onKeyDown }) => (_jsxs(FieldContainerPrivate, { className: styles.container, validationState: validationState, disabled: disabled, readonly: readonly, focused: open, variant: 'single-line-container', inputRef: localRef, size: size, prefix: prefixIcon, children: [_jsx(InputPrivate, { id: id, name: name, type: 'text', disabled: disabled, placeholder: placeholder, ref: mergeRefs(ref, localRef), onChange: searchable ? setInputValue : undefined, value: searchable ? inputValue : selectedOptionFormatter(selectedItem), readonly: readonly, "data-test-id": 'field-select__input', onKeyDown: handleOnKeyDown(onKeyDown), onBlur: handleBlur, className: cn({
131
+ }, size: size, open: open, onOpenChange: handleOpenChange, triggerElemRef: localRef, children: ({ onKeyDown }) => (_jsxs(FieldContainerPrivate, { className: styles.container, validationState: fieldValidationState, disabled: disabled, readonly: readonly, focused: open, variant: 'single-line-container', inputRef: localRef, size: size, prefix: prefixIcon, children: [_jsx(InputPrivate, { id: id, name: name, type: 'text', disabled: disabled, placeholder: placeholder, ref: mergeRefs(ref, localRef), onChange: searchable ? setInputValue : undefined, value: searchable ? inputValue : selectedOptionFormatter(selectedItem), readonly: readonly, "data-test-id": 'field-select__input', onKeyDown: handleOnKeyDown(onKeyDown), onBlur: handleBlur, className: cn({
118
132
  [styles.readonlyCursor]: !searchable,
119
133
  }) }), _jsxs("div", { className: styles.postfix, children: [buttons, _jsx(ArrowIcon, { size: arrowIconSize, className: styles.arrowIcon })] })] })) })) })));
120
134
  });
@@ -1,7 +1,10 @@
1
1
  import { useCallback, useMemo, useRef } from 'react';
2
2
  import { useButtonNavigation, useClearButton } from '@snack-uikit/input-private';
3
- import { extractChildIds, isAccordionItemProps, isNextListItemProps, } from '@snack-uikit/list';
3
+ import {
4
+ // extractChildIds,
5
+ isAccordionItemProps, isNextListItemProps, } from '@snack-uikit/list';
4
6
  import { useCopyButton, useValueControl } from '../../hooks';
7
+ import { extractChildIds } from './legacy';
5
8
  import { isBaseOptionProps } from './utils';
6
9
  export function useHandleOnKeyDown({ setOpen, inputKeyDownNavigationHandler, onInputKeyDownProp, }) {
7
10
  return useCallback((onKeyDown) => (e) => {
@@ -74,7 +77,10 @@ export function useHandleDeleteItem(setValue) {
74
77
  return;
75
78
  }
76
79
  if (isBaseOptionProps(item)) {
77
- setValue((value) => value === null || value === void 0 ? void 0 : value.filter(v => v !== item.id));
80
+ setValue((value) => value === null || value === void 0 ? void 0 : value.filter(v =>
81
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
82
+ // @ts-expect-error
83
+ v !== item.id));
78
84
  }
79
85
  }, [setValue]);
80
86
  }
@@ -0,0 +1,12 @@
1
+ import { ItemProps } from '@snack-uikit/list';
2
+ type UseGroupItemSelectionProps = {
3
+ items: ItemProps[];
4
+ id?: string | number;
5
+ disabled?: boolean;
6
+ };
7
+ export declare function useLegacyGroupItemSelection({ id, items, disabled }: UseGroupItemSelectionProps): {
8
+ checked: boolean | undefined;
9
+ isIndeterminate: boolean;
10
+ handleOnSelect: () => void;
11
+ };
12
+ export {};
@@ -0,0 +1,33 @@
1
+ import { useEffect, useMemo } from 'react';
2
+ import { useSelectionContext } from '@snack-uikit/list';
3
+ import { extractAllChildIds, extractChildIds } from '../../utils';
4
+ export function useLegacyGroupItemSelection({ id = '', items, disabled }) {
5
+ const { value, setValue, isSelectionMultiple } = useSelectionContext();
6
+ const { childIds, allChildIds } = useMemo(() => ({ childIds: extractChildIds({ items }), allChildIds: extractAllChildIds({ items }) }), [items]);
7
+ const isIndeterminate = isSelectionMultiple
8
+ ? allChildIds.some(childId => value === null || value === void 0 ? void 0 : value.includes(childId))
9
+ : allChildIds.includes(value !== null && value !== void 0 ? value : '');
10
+ const checked = isSelectionMultiple ? allChildIds.every(childId => value === null || value === void 0 ? void 0 : value.includes(childId)) : undefined;
11
+ useEffect(() => {
12
+ if (isSelectionMultiple) {
13
+ if (checked && !(value === null || value === void 0 ? void 0 : value.includes(id))) {
14
+ setValue === null || setValue === void 0 ? void 0 : setValue((value) => (value !== null && value !== void 0 ? value : []).concat([id !== null && id !== void 0 ? id : '']));
15
+ }
16
+ if (!checked && (value === null || value === void 0 ? void 0 : value.includes(id))) {
17
+ setValue === null || setValue === void 0 ? void 0 : setValue((value) => (value !== null && value !== void 0 ? value : []).filter(itemId => itemId !== id));
18
+ }
19
+ }
20
+ }, [checked, disabled, id, isSelectionMultiple, setValue, value]);
21
+ const handleOnSelect = () => {
22
+ if (checked) {
23
+ setValue === null || setValue === void 0 ? void 0 : setValue((value) => (value !== null && value !== void 0 ? value : []).filter(itemId => itemId !== id && !childIds.includes(itemId)));
24
+ return;
25
+ }
26
+ if (isIndeterminate) {
27
+ setValue === null || setValue === void 0 ? void 0 : setValue((value) => Array.from(new Set([...(value !== null && value !== void 0 ? value : []), ...childIds, id])));
28
+ return;
29
+ }
30
+ setValue === null || setValue === void 0 ? void 0 : setValue((value) => (value !== null && value !== void 0 ? value : []).concat([...childIds, id !== null && id !== void 0 ? id : '']));
31
+ };
32
+ return { checked, isIndeterminate, handleOnSelect };
33
+ }
@@ -0,0 +1 @@
1
+ export { useLegacyGroupItemSelection } from './Items/hooks';
@@ -0,0 +1 @@
1
+ export { useLegacyGroupItemSelection } from './Items/hooks';
@@ -0,0 +1,5 @@
1
+ import { ItemProps } from '@snack-uikit/list';
2
+ /**
3
+ * Нечеткий поиск среди айтемов по полям 'content.option', 'content.caption', 'content.description', 'label'
4
+ */
5
+ export declare function useFuzzySearch(items: ItemProps[], minSearchInputLength?: number): (search: string) => import("@snack-uikit/list/dist/components/Items").Item[] | import("@snack-uikit/list/dist/components/Items").FlattenItem[];
@@ -0,0 +1,19 @@
1
+ import FuzzySearch from 'fuzzy-search';
2
+ import { useCallback, useMemo } from 'react';
3
+ import { kindFlattenItems } from '@snack-uikit/list';
4
+ const DEFAULT_MIN_SEARCH_INPUT_LENGTH = 2;
5
+ /**
6
+ * Нечеткий поиск среди айтемов по полям 'content.option', 'content.caption', 'content.description', 'label'
7
+ */
8
+ export function useFuzzySearch(items, minSearchInputLength) {
9
+ const flattenItems = useMemo(() => {
10
+ const { flattenItems } = kindFlattenItems({ items });
11
+ return Object.values(flattenItems);
12
+ }, [items]);
13
+ return useCallback((search) => {
14
+ const searcher = new FuzzySearch(flattenItems, ['content.option', 'content.caption', 'content.description', 'label'], {});
15
+ return search.length > (minSearchInputLength !== null && minSearchInputLength !== void 0 ? minSearchInputLength : DEFAULT_MIN_SEARCH_INPUT_LENGTH)
16
+ ? searcher.search(search)
17
+ : items;
18
+ }, [flattenItems, items, minSearchInputLength]);
19
+ }
@@ -0,0 +1,3 @@
1
+ export * from './components';
2
+ export { useFuzzySearch } from './hooks';
3
+ export { extractChildIds, flattenItems } from './utils';
@@ -0,0 +1,3 @@
1
+ export * from './components';
2
+ export { useFuzzySearch } from './hooks';
3
+ export { extractChildIds, flattenItems } from './utils';
@@ -0,0 +1,29 @@
1
+ import { RefObject } from 'react';
2
+ import { AccordionItemProps, BaseItemProps, ItemProps, NextListItemProps } from '@snack-uikit/list';
3
+ type WithCollapsedItemsProps = {
4
+ items: ItemProps[];
5
+ openCollapsedItems: Array<number | string>;
6
+ };
7
+ export declare function withCollapsedItems({ items, openCollapsedItems }: WithCollapsedItemsProps): {
8
+ items: import("@snack-uikit/list/dist/components/Items").Item[];
9
+ itemRefs: RefObject<HTMLElement>[];
10
+ ids: (string | number)[];
11
+ expandedIds: (string | number)[];
12
+ };
13
+ /**
14
+ * Функция возвращает массив id дочерних items
15
+ * @function extractItemIds
16
+ */
17
+ export declare function extractItemIds(items: ItemProps[]): Array<string | number>;
18
+ export declare function extractChildIds({ items }: {
19
+ items: ItemProps[];
20
+ }): Array<string | number>;
21
+ export declare function extractAllChildIds({ items }: {
22
+ items: ItemProps[];
23
+ }): Array<string | number>;
24
+ /**
25
+ *  Функция разворачивает массив айтемов в плоский список
26
+ * @function flattenItems
27
+ */
28
+ export declare function flattenItems(items: ItemProps[]): (BaseItemProps | AccordionItemProps | NextListItemProps)[];
29
+ export {};
@@ -0,0 +1,107 @@
1
+ import { isAccordionItemProps, isBaseItemProps, isGroupItemProps, isNextListItemProps, } from '@snack-uikit/list';
2
+ export function withCollapsedItems({ items, openCollapsedItems }) {
3
+ let itemRefs = [];
4
+ let newItems = [];
5
+ let ids = [];
6
+ let expandedIds = [];
7
+ items.forEach(item => {
8
+ var _a;
9
+ if (((isBaseItemProps(item) && !item.inactive) || isNextListItemProps(item) || isAccordionItemProps(item)) &&
10
+ !item.disabled) {
11
+ newItems = newItems.concat([item]);
12
+ ids = ids.concat([(_a = item.id) !== null && _a !== void 0 ? _a : '']);
13
+ if (item.itemRef) {
14
+ itemRefs = itemRefs.concat([item.itemRef]);
15
+ }
16
+ }
17
+ if (isNextListItemProps(item) && item.id && !item.disabled) {
18
+ expandedIds = expandedIds.concat(item.id);
19
+ }
20
+ if (isGroupItemProps(item)) {
21
+ const { itemRefs: nestedItemsRefs, ids: nestedIds } = withCollapsedItems({
22
+ items: item.items,
23
+ openCollapsedItems,
24
+ });
25
+ ids = ids.concat(nestedIds);
26
+ itemRefs = itemRefs.concat(nestedItemsRefs);
27
+ }
28
+ if (isAccordionItemProps(item) && item.id && openCollapsedItems.includes(item.id)) {
29
+ const { itemRefs: nestedItemsRefs, ids: nestedIds, items: nestedItems, expandedIds: nestedExpandedIds, } = withCollapsedItems({
30
+ items: item.items,
31
+ openCollapsedItems,
32
+ });
33
+ ids = ids.concat(nestedIds);
34
+ newItems = newItems.concat(nestedItems);
35
+ itemRefs = itemRefs.concat(nestedItemsRefs);
36
+ expandedIds = expandedIds.concat(nestedExpandedIds);
37
+ }
38
+ });
39
+ return { items, itemRefs, ids, expandedIds };
40
+ }
41
+ /**
42
+ * Функция возвращает массив id дочерних items
43
+ * @function extractItemIds
44
+ */
45
+ export function extractItemIds(items) {
46
+ return items.reduce((prev, item) => {
47
+ if (isGroupItemProps(item)) {
48
+ return prev.concat(extractItemIds(item.items));
49
+ }
50
+ return item.id ? prev.concat([item.id]) : prev;
51
+ }, []);
52
+ }
53
+ export function extractChildIds({ items }) {
54
+ return items
55
+ .filter(item => isAccordionItemProps(item) ||
56
+ isNextListItemProps(item) ||
57
+ isGroupItemProps(item) ||
58
+ (isBaseItemProps(item) && !item.disabled && !item.inactive))
59
+ .reduce((prev, item) => {
60
+ var _a;
61
+ if (isAccordionItemProps(item) || isNextListItemProps(item)) {
62
+ return prev.concat([(_a = item.id) !== null && _a !== void 0 ? _a : '']).concat(extractChildIds({ items: item.items }));
63
+ }
64
+ if (isGroupItemProps(item)) {
65
+ return prev.concat(extractChildIds({ items: item.items }));
66
+ }
67
+ return item.id && !isGroupItemProps(item) ? prev.concat([item.id]) : prev;
68
+ }, []);
69
+ }
70
+ export function extractAllChildIds({ items }) {
71
+ return items
72
+ .filter(item => isAccordionItemProps(item) ||
73
+ isNextListItemProps(item) ||
74
+ isGroupItemProps(item) ||
75
+ (isBaseItemProps(item) && !item.inactive))
76
+ .reduce((prev, item) => {
77
+ var _a;
78
+ if (isAccordionItemProps(item) || isNextListItemProps(item)) {
79
+ return prev.concat([(_a = item.id) !== null && _a !== void 0 ? _a : '']).concat(extractAllChildIds({ items: item.items }));
80
+ }
81
+ if (isGroupItemProps(item)) {
82
+ return prev.concat(extractAllChildIds({ items: item.items }));
83
+ }
84
+ return item.id && !isGroupItemProps(item) ? prev.concat([item.id]) : prev;
85
+ }, []);
86
+ }
87
+ /**
88
+ *  Функция разворачивает массив айтемов в плоский список
89
+ * @function flattenItems
90
+ */
91
+ export function flattenItems(items) {
92
+ const flattenItems = [];
93
+ function flatten(item) {
94
+ if (!isGroupItemProps(item)) {
95
+ flattenItems.push(item);
96
+ }
97
+ if ('items' in item) {
98
+ for (const nestedItem of item.items) {
99
+ flatten(nestedItem);
100
+ }
101
+ }
102
+ }
103
+ for (const item of items) {
104
+ flatten(item);
105
+ }
106
+ return flattenItems;
107
+ }