@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.
- package/CHANGELOG.md +28 -0
- package/README.md +6 -6
- package/dist/components/FieldDate/FieldDate.js +5 -3
- package/dist/components/FieldDecorator/FieldDecorator.d.ts +1 -1
- package/dist/components/FieldDecorator/FieldDecorator.js +4 -3
- package/dist/components/FieldSecure/FieldSecure.js +3 -1
- package/dist/components/FieldSelect/FieldSelectMultiple.d.ts +3 -1
- package/dist/components/FieldSelect/FieldSelectMultiple.js +13 -4
- package/dist/components/FieldSelect/FieldSelectSingle.d.ts +3 -1
- package/dist/components/FieldSelect/FieldSelectSingle.js +20 -6
- package/dist/components/FieldSelect/hooks.js +8 -2
- package/dist/components/FieldSelect/legacy/components/Items/hooks.d.ts +12 -0
- package/dist/components/FieldSelect/legacy/components/Items/hooks.js +33 -0
- package/dist/components/FieldSelect/legacy/components/index.d.ts +1 -0
- package/dist/components/FieldSelect/legacy/components/index.js +1 -0
- package/dist/components/FieldSelect/legacy/hooks.d.ts +5 -0
- package/dist/components/FieldSelect/legacy/hooks.js +19 -0
- package/dist/components/FieldSelect/legacy/index.d.ts +3 -0
- package/dist/components/FieldSelect/legacy/index.js +3 -0
- package/dist/components/FieldSelect/legacy/utils.d.ts +29 -0
- package/dist/components/FieldSelect/legacy/utils.js +107 -0
- package/dist/components/FieldSelect/types.d.ts +6 -3
- package/dist/components/FieldSelect/utils/extractListProps.d.ts +1 -1
- package/dist/components/FieldSelect/utils/extractListProps.js +1 -3
- package/dist/components/FieldSelect/utils/options.js +1 -1
- package/dist/components/FieldSelect/utils/typeGuards.js +1 -1
- package/dist/components/FieldSelect/utils/updateItems.d.ts +6 -6
- package/dist/components/FieldSelect/utils/updateItems.js +12 -3
- package/dist/components/FieldStepper/FieldStepper.js +3 -1
- package/dist/components/FieldText/FieldText.js +3 -1
- package/dist/components/FieldTextArea/FieldTextArea.js +3 -1
- package/dist/helperComponents/FieldContainerPrivate/styles.module.css +1 -1
- package/dist/utils/getValidationState.d.ts +5 -0
- package/dist/utils/getValidationState.js +4 -0
- package/package.json +15 -13
- package/src/components/FieldDate/FieldDate.tsx +5 -3
- package/src/components/FieldDecorator/FieldDecorator.tsx +4 -3
- package/src/components/FieldSecure/FieldSecure.tsx +5 -2
- package/src/components/FieldSelect/FieldSelectMultiple.tsx +15 -4
- package/src/components/FieldSelect/FieldSelectSingle.tsx +19 -5
- package/src/components/FieldSelect/hooks.ts +11 -2
- package/src/components/FieldSelect/legacy/components/Items/hooks.tsx +53 -0
- package/src/components/FieldSelect/legacy/components/index.ts +1 -0
- package/src/components/FieldSelect/legacy/hooks.ts +32 -0
- package/src/components/FieldSelect/legacy/index.ts +3 -0
- package/src/components/FieldSelect/legacy/utils.ts +166 -0
- package/src/components/FieldSelect/types.ts +29 -12
- package/src/components/FieldSelect/utils/extractListProps.ts +0 -4
- package/src/components/FieldSelect/utils/options.ts +2 -1
- package/src/components/FieldSelect/utils/typeGuards.ts +1 -1
- package/src/components/FieldSelect/utils/updateItems.ts +14 -4
- package/src/components/FieldStepper/FieldStepper.tsx +5 -2
- package/src/components/FieldText/FieldText.tsx +4 -2
- package/src/components/FieldTextArea/FieldTextArea.tsx +5 -2
- 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 | `
|
|
336
|
-
| onChange | `
|
|
337
|
-
| defaultValue | `
|
|
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/
|
|
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:
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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 ?
|
|
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:
|
|
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, "
|
|
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
|
|
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 =>
|
|
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
|
-
|
|
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:
|
|
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, "
|
|
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
|
|
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 =>
|
|
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), {
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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 {
|
|
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 =>
|
|
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,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
|
+
}
|