@snack-uikit/fields 0.18.2-preview-86dac340.0 → 0.18.2-preview-cb79db34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -8
- package/dist/components/FieldDate/FieldDate.js +1 -1
- package/dist/components/FieldSelect/FieldSelectMultiple.d.ts +3 -2
- package/dist/components/FieldSelect/FieldSelectMultiple.js +6 -2
- package/dist/components/FieldSelect/FieldSelectSingle.d.ts +3 -2
- package/dist/components/FieldSelect/FieldSelectSingle.js +12 -3
- 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/styles.module.css +18 -8
- package/dist/components/FieldSelect/types.d.ts +7 -11
- package/dist/components/FieldSelect/utils/extractListProps.d.ts +1 -1
- package/dist/components/FieldSelect/utils/extractListProps.js +1 -5
- 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/helperComponents/FieldContainerPrivate/styles.module.css +1 -1
- package/package.json +15 -13
- package/src/components/FieldDate/FieldDate.tsx +1 -1
- package/src/components/FieldSelect/FieldSelectMultiple.tsx +6 -2
- package/src/components/FieldSelect/FieldSelectSingle.tsx +10 -2
- 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/styles.module.scss +3 -5
- package/src/components/FieldSelect/types.ts +32 -21
- package/src/components/FieldSelect/utils/extractListProps.ts +0 -8
- 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/README.md
CHANGED
|
@@ -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,28 +334,25 @@ 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 | Отображение кнопки очистки поля |
|
|
341
343
|
| prefixIcon | `ReactElement<any, string \| JSXElementConstructor<any>>` | - | Иконка-префикс для поля |
|
|
342
|
-
| footer | `ReactNode` | - |
|
|
343
|
-
| widthStrategy | enum PopoverWidthStrategy: `"auto"`, `"gte"`, `"eq"` | - | Управление шириной выпадающего списка |
|
|
344
|
+
| footer | `ReactNode` | - | |
|
|
344
345
|
| search | `SearchState` | - | |
|
|
345
346
|
| autocomplete | `boolean` | - | |
|
|
346
347
|
| addOptionByEnter | `boolean` | - | |
|
|
347
348
|
| open | `boolean` | - | |
|
|
348
349
|
| onOpenChange | `(open: boolean) => void` | - | |
|
|
349
350
|
| selectedOptionFormatter | `SelectedOptionFormatter` | - | |
|
|
350
|
-
| pinTop | `ItemProps[]` | - | Элементы списка, закрепленные сверху |
|
|
351
|
-
| pinBottom | `ItemProps[]` | - | Элементы списка, закрепленные снизу |
|
|
352
|
-
| dataFiltered | `boolean` | - | |
|
|
353
351
|
| dataError | `boolean` | - | |
|
|
354
352
|
| noDataState | `EmptyStateProps` | - | Экран при отстутствии данных |
|
|
355
353
|
| noResultsState | `EmptyStateProps` | - | Экран при отстутствии результатов поиска или фильтров |
|
|
356
354
|
| errorDataState | `EmptyStateProps` | - | Экран при ошибке запроса |
|
|
355
|
+
| dataFiltered | `boolean` | - | |
|
|
357
356
|
| selection | "single" \| "multiple" | - | |
|
|
358
357
|
| ref | `Ref<HTMLInputElement>` | - | Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref). @see https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom |
|
|
359
358
|
| key | `Key` | - | |
|
|
@@ -14,7 +14,7 @@ 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';
|
|
@@ -9,17 +9,18 @@ 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;
|
|
15
17
|
readonly?: boolean | undefined;
|
|
16
18
|
prefixIcon?: import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | undefined;
|
|
17
19
|
footer?: import("react").ReactNode;
|
|
18
|
-
widthStrategy?: import("@snack-uikit/popover-private/dist/types").PopoverWidthStrategy | undefined;
|
|
19
20
|
search?: import("./types").SearchState | undefined;
|
|
20
21
|
autocomplete?: boolean | undefined;
|
|
21
22
|
addOptionByEnter?: boolean | undefined;
|
|
22
23
|
open?: boolean | undefined;
|
|
23
24
|
onOpenChange?(open: boolean): void;
|
|
24
25
|
selectedOptionFormatter?: SelectedOptionFormatter | undefined;
|
|
25
|
-
} & Pick<import("@snack-uikit/list").
|
|
26
|
+
} & Pick<import("@snack-uikit/list").ListProps, "dataError" | "dataFiltered" | "noDataState" | "noResultsState" | "errorDataState">, "showCopyButton"> & import("react").RefAttributes<HTMLInputElement>>;
|
|
@@ -14,7 +14,7 @@ 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';
|
|
@@ -22,10 +22,14 @@ import { useValueControl } from '../../hooks';
|
|
|
22
22
|
import { FieldDecorator } from '../FieldDecorator';
|
|
23
23
|
import { extractFieldDecoratorProps } from '../FieldDecorator/utils';
|
|
24
24
|
import { useButtons, useHandleDeleteItem, useHandleOnKeyDown, useSearchInput } from './hooks';
|
|
25
|
+
import { useFuzzySearch } from './legacy';
|
|
25
26
|
import styles from './styles.module.css';
|
|
26
27
|
import { extractListProps, getArrowIcon, updateMultipleItems } from './utils';
|
|
27
28
|
const BASE_MIN_WIDTH = 4;
|
|
28
|
-
const defaultSelectedOptionFormatter = item =>
|
|
29
|
+
const defaultSelectedOptionFormatter = item =>
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
31
|
+
// @ts-expect-error
|
|
32
|
+
(item === null || item === void 0 ? void 0 : item.content.option) || '';
|
|
29
33
|
export const FieldSelectMultiple = forwardRef((_a, ref) => {
|
|
30
34
|
var _b;
|
|
31
35
|
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"]);
|
|
@@ -7,17 +7,18 @@ 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;
|
|
13
15
|
readonly?: boolean | undefined;
|
|
14
16
|
prefixIcon?: import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | undefined;
|
|
15
17
|
footer?: import("react").ReactNode;
|
|
16
|
-
widthStrategy?: import("@snack-uikit/popover-private/dist/types").PopoverWidthStrategy | undefined;
|
|
17
18
|
search?: import("./types").SearchState | undefined;
|
|
18
19
|
autocomplete?: boolean | undefined;
|
|
19
20
|
addOptionByEnter?: boolean | undefined;
|
|
20
21
|
open?: boolean | undefined;
|
|
21
22
|
onOpenChange?(open: boolean): void;
|
|
22
23
|
selectedOptionFormatter?: SelectedOptionFormatter | undefined;
|
|
23
|
-
} & Pick<import("@snack-uikit/list").
|
|
24
|
+
} & Pick<import("@snack-uikit/list").ListProps, "dataError" | "dataFiltered" | "noDataState" | "noResultsState" | "errorDataState"> & import("react").RefAttributes<HTMLInputElement>>;
|
|
@@ -14,16 +14,20 @@ 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
21
|
import { FieldDecorator } from '../FieldDecorator';
|
|
22
22
|
import { extractFieldDecoratorProps } from '../FieldDecorator/utils';
|
|
23
23
|
import { useButtons, useHandleOnKeyDown, useSearchInput } from './hooks';
|
|
24
|
+
import { useFuzzySearch } from './legacy';
|
|
24
25
|
import styles from './styles.module.css';
|
|
25
26
|
import { extractListProps, getArrowIcon, updateItems } from './utils';
|
|
26
|
-
const defaultSelectedOptionFormatter = item =>
|
|
27
|
+
const defaultSelectedOptionFormatter = item =>
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
29
|
+
// @ts-expect-error
|
|
30
|
+
(item === null || item === void 0 ? void 0 : item.content.option) || '';
|
|
27
31
|
export const FieldSelectSingle = forwardRef((_a, ref) => {
|
|
28
32
|
var _b;
|
|
29
33
|
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 +39,10 @@ export const FieldSelectSingle = forwardRef((_a, ref) => {
|
|
|
35
39
|
onChange: onChangeProp,
|
|
36
40
|
});
|
|
37
41
|
const [{ selectedItem, items = [] }, setItems] = useState(() => updateItems({ options, value, currentItems: [], selectedItem: undefined }));
|
|
38
|
-
const { inputValue, setInputValue, prevInputValue, updateInputValue } = useSearchInput(Object.assign(Object.assign({}, search), {
|
|
42
|
+
const { inputValue, setInputValue, prevInputValue, updateInputValue } = useSearchInput(Object.assign(Object.assign({}, search), {
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
44
|
+
// @ts-expect-error
|
|
45
|
+
defaultValue: (_b = selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.content.option) !== null && _b !== void 0 ? _b : '', selectedOptionFormatter }));
|
|
39
46
|
const prevSelectedItem = useRef(selectedItem);
|
|
40
47
|
useLayoutEffect(() => {
|
|
41
48
|
setItems(({ selectedItem }) => updateItems({ options, value, selectedItem }));
|
|
@@ -43,6 +50,8 @@ export const FieldSelectSingle = forwardRef((_a, ref) => {
|
|
|
43
50
|
useEffect(() => {
|
|
44
51
|
if (prevSelectedItem.current &&
|
|
45
52
|
prevSelectedItem.current.id === (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.id) &&
|
|
53
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
54
|
+
// @ts-expect-error
|
|
46
55
|
prevSelectedItem.current.content.option === (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.content.option)) {
|
|
47
56
|
return;
|
|
48
57
|
}
|
|
@@ -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
|
+
}
|
|
@@ -4,8 +4,6 @@
|
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
.contentWrapper{
|
|
7
|
-
position:relative;
|
|
8
|
-
overflow:hidden;
|
|
9
7
|
display:flex;
|
|
10
8
|
flex-wrap:wrap;
|
|
11
9
|
width:100%;
|
|
@@ -73,10 +71,14 @@
|
|
|
73
71
|
}
|
|
74
72
|
.container[data-size=s][data-variant=single-line-container] .displayValue{
|
|
75
73
|
width:calc(100% - (
|
|
76
|
-
var(--space-fields-single-line-container-s-right, 6px) +
|
|
74
|
+
var(--space-fields-single-line-container-s-right, 6px) +
|
|
75
|
+
var(--space-fields-single-line-container-s-gap, 4px) +
|
|
76
|
+
calc(var(var(--space-fields-postfix-gap, 4px)) + var(--size-icon-container-xs, 16px) * 2)
|
|
77
77
|
));
|
|
78
78
|
margin-right:calc(
|
|
79
|
-
var(--space-fields-single-line-container-s-right, 6px) +
|
|
79
|
+
var(--space-fields-single-line-container-s-right, 6px) +
|
|
80
|
+
var(--space-fields-single-line-container-s-gap, 4px) +
|
|
81
|
+
calc(var(var(--space-fields-postfix-gap, 4px)) + var(--size-icon-container-xs, 16px) * 2)
|
|
80
82
|
);
|
|
81
83
|
padding-left:var(--space-fields-single-line-container-s-left, 6px);
|
|
82
84
|
border-radius:var(--radius-fields-s, 12px);
|
|
@@ -96,10 +98,14 @@
|
|
|
96
98
|
}
|
|
97
99
|
.container[data-size=m][data-variant=single-line-container] .displayValue{
|
|
98
100
|
width:calc(100% - (
|
|
99
|
-
var(--space-fields-single-line-container-m-right, 8px) +
|
|
101
|
+
var(--space-fields-single-line-container-m-right, 8px) +
|
|
102
|
+
var(--space-fields-single-line-container-m-gap, 4px) +
|
|
103
|
+
calc(var(var(--space-fields-postfix-gap, 4px)) + var(--size-icon-container-s, 24px) * 2)
|
|
100
104
|
));
|
|
101
105
|
margin-right:calc(
|
|
102
|
-
var(--space-fields-single-line-container-m-right, 8px) +
|
|
106
|
+
var(--space-fields-single-line-container-m-right, 8px) +
|
|
107
|
+
var(--space-fields-single-line-container-m-gap, 4px) +
|
|
108
|
+
calc(var(var(--space-fields-postfix-gap, 4px)) + var(--size-icon-container-s, 24px) * 2)
|
|
103
109
|
);
|
|
104
110
|
padding-left:var(--space-fields-single-line-container-m-left, 8px);
|
|
105
111
|
border-radius:var(--radius-fields-m, 14px);
|
|
@@ -119,10 +125,14 @@
|
|
|
119
125
|
}
|
|
120
126
|
.container[data-size=l][data-variant=single-line-container] .displayValue{
|
|
121
127
|
width:calc(100% - (
|
|
122
|
-
var(--space-fields-single-line-container-l-right, 10px) +
|
|
128
|
+
var(--space-fields-single-line-container-l-right, 10px) +
|
|
129
|
+
var(--space-fields-single-line-container-l-gap, 8px) +
|
|
130
|
+
calc(var(var(--space-fields-postfix-gap, 4px)) + var(--size-icon-container-s, 24px) * 2)
|
|
123
131
|
));
|
|
124
132
|
margin-right:calc(
|
|
125
|
-
var(--space-fields-single-line-container-l-right, 10px) +
|
|
133
|
+
var(--space-fields-single-line-container-l-right, 10px) +
|
|
134
|
+
var(--space-fields-single-line-container-l-gap, 8px) +
|
|
135
|
+
calc(var(var(--space-fields-postfix-gap, 4px)) + var(--size-icon-container-s, 24px) * 2)
|
|
126
136
|
);
|
|
127
137
|
padding-left:var(--space-fields-single-line-container-l-left, 10px);
|
|
128
138
|
border-radius:var(--radius-fields-l, 16px);
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { ReactElement } from 'react';
|
|
2
2
|
import { InputPrivateProps } from '@snack-uikit/input-private';
|
|
3
|
-
import { AccordionItemProps, BaseItemProps,
|
|
3
|
+
import { AccordionItemProps, BaseItemProps, GroupItemProps, ItemContentProps, ListProps, NextListItemProps, SelectionMultipleState, SelectionSingleState } from '@snack-uikit/list';
|
|
4
4
|
import { TagProps } from '@snack-uikit/tag';
|
|
5
5
|
import { WithSupportProps } from '@snack-uikit/utils';
|
|
6
6
|
import { FieldDecoratorProps } from '../FieldDecorator';
|
|
7
|
+
export type AnyType = any;
|
|
7
8
|
export type OptionProps = BaseOptionProps | AccordionOptionProps | GroupOptionProps | NestListOptionProps;
|
|
8
9
|
export type OptionWithoutGroup = BaseOptionProps | AccordionOptionProps | NestListOptionProps;
|
|
9
|
-
export type BaseOptionProps = Pick<BaseItemProps, 'beforeContent' | 'afterContent' | 'disabled'> &
|
|
10
|
+
export type BaseOptionProps = Pick<BaseItemProps, 'beforeContent' | 'afterContent' | 'disabled'> & Pick<ItemContentProps, 'option' | 'caption' | 'description'> & {
|
|
10
11
|
value: string | number;
|
|
11
12
|
} & Pick<TagProps, 'appearance'>;
|
|
12
13
|
export type AccordionOptionProps = Pick<AccordionItemProps, 'type'> & BaseOptionProps & {
|
|
@@ -36,6 +37,8 @@ export type FieldSelectPrivateProps = InputProps & WrapperProps & {
|
|
|
36
37
|
};
|
|
37
38
|
type FiledSelectCommonProps = WithSupportProps<{
|
|
38
39
|
options: OptionProps[];
|
|
40
|
+
pinTop: OptionProps[];
|
|
41
|
+
pinBottom: OptionProps[];
|
|
39
42
|
searchable?: boolean;
|
|
40
43
|
/** Отображение кнопки Копировать для поля (актуально только для `readonly = true`) */
|
|
41
44
|
showCopyButton?: boolean;
|
|
@@ -51,21 +54,14 @@ type FiledSelectCommonProps = WithSupportProps<{
|
|
|
51
54
|
readonly?: boolean;
|
|
52
55
|
/** Иконка-префикс для поля */
|
|
53
56
|
prefixIcon?: ReactElement;
|
|
54
|
-
|
|
55
|
-
* Footer списка айтемов
|
|
56
|
-
*/
|
|
57
|
-
footer?: DroplistProps['footer'];
|
|
58
|
-
/**
|
|
59
|
-
* Управление шириной выпадающего списка
|
|
60
|
-
*/
|
|
61
|
-
widthStrategy?: DroplistProps['widthStrategy'];
|
|
57
|
+
footer?: ListProps['footer'];
|
|
62
58
|
search?: SearchState;
|
|
63
59
|
autocomplete?: boolean;
|
|
64
60
|
addOptionByEnter?: boolean;
|
|
65
61
|
open?: boolean;
|
|
66
62
|
onOpenChange?(open: boolean): void;
|
|
67
63
|
selectedOptionFormatter?: SelectedOptionFormatter;
|
|
68
|
-
}> & Pick<
|
|
64
|
+
}> & Pick<ListProps, 'dataError' | 'noDataState' | 'noResultsState' | 'errorDataState' | 'dataFiltered'>;
|
|
69
65
|
export type FieldSelectSingleProps = FieldSelectPrivateProps & Omit<SelectionSingleState, 'mode'> & WrapperProps & FiledSelectCommonProps;
|
|
70
66
|
export type FieldSelectMultipleProps = FieldSelectPrivateProps & {
|
|
71
67
|
removeByBackspace?: boolean;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { DroplistProps } from '@snack-uikit/list';
|
|
2
2
|
import { FieldSelectProps } from '../types';
|
|
3
|
-
export declare function extractListProps({ dataError, noDataState, noResultsState, errorDataState,
|
|
3
|
+
export declare function extractListProps({ dataError, noDataState, noResultsState, errorDataState, dataFiltered, loading, }: Partial<FieldSelectProps>): Partial<DroplistProps>;
|
|
@@ -1,15 +1,11 @@
|
|
|
1
|
-
export function extractListProps({ dataError, noDataState, noResultsState, errorDataState,
|
|
1
|
+
export function extractListProps({ dataError, noDataState, noResultsState, errorDataState, dataFiltered, loading, }) {
|
|
2
2
|
return {
|
|
3
3
|
dataError,
|
|
4
4
|
noDataState,
|
|
5
5
|
noResultsState,
|
|
6
6
|
errorDataState,
|
|
7
|
-
pinTop,
|
|
8
|
-
pinBottom,
|
|
9
7
|
dataFiltered,
|
|
10
8
|
loading,
|
|
11
|
-
footer,
|
|
12
|
-
widthStrategy,
|
|
13
9
|
trigger: 'clickAndFocusVisible',
|
|
14
10
|
placement: 'bottom',
|
|
15
11
|
'data-test-id': 'field-select__list',
|
|
@@ -9,7 +9,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
9
9
|
}
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
|
-
import { flattenItems } from '
|
|
12
|
+
import { flattenItems } from '../legacy';
|
|
13
13
|
import { isAccordionOptionProps, isGroupOptionProps, isNextListOptionProps } from './typeGuards';
|
|
14
14
|
export function transformOptionsToItems(options) {
|
|
15
15
|
return options.map(option => {
|
|
@@ -12,7 +12,7 @@ export function isNextListOptionProps(option) {
|
|
|
12
12
|
}
|
|
13
13
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
14
14
|
export function isGroupOptionProps(option) {
|
|
15
|
-
return 'options' in option && option['type'] ===
|
|
15
|
+
return 'options' in option && option['type'] === 'group';
|
|
16
16
|
}
|
|
17
17
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
18
|
export function isFieldSelectMultipleProps(props) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { ItemProps, SelectionSingleValueType } from '@snack-uikit/list';
|
|
1
|
+
import { ItemId, ItemProps, SelectionSingleValueType } from '@snack-uikit/list';
|
|
2
2
|
import { ItemWithId, OptionProps } from '../types';
|
|
3
3
|
export declare function createPlaceholderItem(value: SelectionSingleValueType): {
|
|
4
|
-
id:
|
|
4
|
+
id: ItemId;
|
|
5
5
|
content: {
|
|
6
6
|
option: string;
|
|
7
7
|
};
|
|
@@ -9,12 +9,12 @@ export declare function createPlaceholderItem(value: SelectionSingleValueType):
|
|
|
9
9
|
};
|
|
10
10
|
export declare function updateItems({ options, value, selectedItem, }: {
|
|
11
11
|
options: OptionProps[];
|
|
12
|
-
value
|
|
12
|
+
value?: ItemId;
|
|
13
13
|
selectedItem?: ItemWithId;
|
|
14
14
|
currentItems?: ItemProps[];
|
|
15
15
|
}): {
|
|
16
16
|
selectedItem: ItemWithId | undefined;
|
|
17
|
-
items:
|
|
17
|
+
items: import("@snack-uikit/list/dist/components/Items").Item[];
|
|
18
18
|
};
|
|
19
19
|
export declare function updateMultipleItems({ options, value, selectedItems, }: {
|
|
20
20
|
options: OptionProps[];
|
|
@@ -23,10 +23,10 @@ export declare function updateMultipleItems({ options, value, selectedItems, }:
|
|
|
23
23
|
currentItems?: ItemProps[];
|
|
24
24
|
}): {
|
|
25
25
|
selectedItems: undefined;
|
|
26
|
-
items: (
|
|
26
|
+
items: (import("@snack-uikit/list/dist/components/Items").Item & {
|
|
27
27
|
appearance?: import("@snack-uikit/tag/dist/types").Appearance | undefined;
|
|
28
28
|
})[];
|
|
29
29
|
} | {
|
|
30
30
|
selectedItems: ItemWithId[];
|
|
31
|
-
items:
|
|
31
|
+
items: import("@snack-uikit/list/dist/components/Items").Item[];
|
|
32
32
|
};
|