@snack-uikit/list 0.9.2-preview-c8f85f20.0 → 0.9.2-preview-0a44b2fc.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 +51 -23
- package/dist/components/Items/AccordionItem/AccordionItem.d.ts +2 -2
- package/dist/components/Items/AccordionItem/AccordionItem.js +19 -16
- package/dist/components/Items/BaseItem/BaseItem.d.ts +5 -4
- package/dist/components/Items/BaseItem/BaseItem.js +22 -16
- package/dist/components/Items/BaseItem/styles.module.css +9 -122
- package/dist/components/Items/GroupItem/GroupItem.d.ts +2 -2
- package/dist/components/Items/GroupItem/GroupItem.js +3 -3
- package/dist/components/Items/NextListItem/NextListItem.d.ts +2 -2
- package/dist/components/Items/NextListItem/NextListItem.js +37 -36
- package/dist/components/Items/SearchItem/SearchItem.d.ts +3 -1
- package/dist/components/Items/SearchItem/SearchItem.js +7 -8
- package/dist/components/Items/hooks.d.ts +14 -9
- package/dist/components/Items/hooks.js +46 -30
- package/dist/components/Items/types.d.ts +41 -26
- package/dist/components/Items/utils.d.ts +7 -17
- package/dist/components/Items/utils.js +3 -31
- package/dist/components/Lists/Droplist/DropList.d.ts +2 -1
- package/dist/components/Lists/Droplist/DropList.js +85 -50
- package/dist/components/Lists/List/List.d.ts +7 -11
- package/dist/components/Lists/List/List.js +61 -53
- package/dist/components/Lists/ListPrivate/ListPrivate.d.ts +18 -20
- package/dist/components/Lists/ListPrivate/ListPrivate.js +10 -9
- package/dist/components/Lists/contexts/CollapseProvider.d.ts +13 -1
- package/dist/components/Lists/contexts/CollapseProvider.js +2 -0
- package/dist/components/Lists/contexts/FocusListProvider.d.ts +9 -0
- package/dist/components/Lists/contexts/FocusListProvider.js +5 -0
- package/dist/components/Lists/contexts/NewListProvider.d.ts +27 -0
- package/dist/components/Lists/contexts/{ListProvider.js → NewListProvider.js} +10 -5
- package/dist/components/Lists/contexts/SelectionProvider.d.ts +28 -15
- package/dist/components/Lists/contexts/SelectionProvider.js +14 -8
- package/dist/components/Lists/contexts/index.d.ts +2 -2
- package/dist/components/Lists/contexts/index.js +2 -2
- package/dist/components/Lists/hooks.d.ts +11 -11
- package/dist/components/Lists/hooks.js +80 -41
- package/dist/components/Lists/types.d.ts +19 -15
- package/dist/helperComponents/ItemContent/ItemContent.d.ts +15 -0
- package/dist/helperComponents/ItemContent/ItemContent.js +23 -0
- package/dist/helperComponents/ItemContent/index.d.ts +1 -0
- package/dist/helperComponents/ItemContent/index.js +1 -0
- package/dist/helperComponents/ItemContent/styles.module.css +117 -0
- package/dist/helperComponents/ListEmptyState/ListEmptyState.d.ts +2 -2
- package/dist/helperComponents/ListEmptyState/ListEmptyState.js +13 -4
- package/dist/helperComponents/index.d.ts +1 -0
- package/dist/helperComponents/index.js +1 -0
- package/dist/hooks.d.ts +1 -1
- package/dist/hooks.js +15 -10
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/legacy/components/Items/hooks.d.ts +12 -0
- package/dist/legacy/components/Items/hooks.js +33 -0
- package/dist/legacy/components/index.d.ts +1 -0
- package/dist/legacy/components/index.js +1 -0
- package/dist/legacy/hooks.d.ts +5 -0
- package/dist/legacy/hooks.js +15 -0
- package/dist/legacy/index.d.ts +3 -0
- package/dist/legacy/index.js +3 -0
- package/dist/legacy/utils.d.ts +29 -0
- package/dist/legacy/utils.js +107 -0
- package/dist/types.d.ts +1 -1
- package/dist/utils.d.ts +27 -25
- package/dist/utils.js +74 -103
- package/package.json +12 -12
- package/src/components/Items/AccordionItem/AccordionItem.tsx +26 -19
- package/src/components/Items/BaseItem/BaseItem.tsx +48 -46
- package/src/components/Items/BaseItem/styles.module.scss +8 -70
- package/src/components/Items/GroupItem/GroupItem.tsx +6 -5
- package/src/components/Items/NextListItem/NextListItem.tsx +67 -78
- package/src/components/Items/SearchItem/SearchItem.tsx +8 -8
- package/src/components/Items/hooks.tsx +76 -54
- package/src/components/Items/types.ts +61 -31
- package/src/components/Items/utils.ts +9 -58
- package/src/components/Lists/Droplist/DropList.tsx +155 -102
- package/src/components/Lists/List/List.tsx +120 -105
- package/src/components/Lists/ListPrivate/ListPrivate.tsx +26 -27
- package/src/components/Lists/contexts/CollapseProvider.tsx +22 -0
- package/src/components/Lists/contexts/FocusListProvider.tsx +16 -0
- package/src/components/Lists/contexts/NewListProvider.tsx +49 -0
- package/src/components/Lists/contexts/SelectionProvider.tsx +63 -36
- package/src/components/Lists/contexts/index.ts +3 -2
- package/src/components/Lists/hooks.ts +139 -75
- package/src/components/Lists/types.ts +29 -27
- package/src/helperComponents/ItemContent/ItemContent.tsx +63 -0
- package/src/helperComponents/ItemContent/index.ts +1 -0
- package/src/helperComponents/ItemContent/styles.module.scss +78 -0
- package/src/helperComponents/ListEmptyState/ListEmptyState.tsx +21 -13
- package/src/helperComponents/index.ts +1 -0
- package/src/hooks.ts +21 -15
- package/src/index.ts +9 -2
- package/src/legacy/components/Items/hooks.tsx +53 -0
- package/src/legacy/components/index.ts +1 -0
- package/src/legacy/hooks.ts +27 -0
- package/src/legacy/index.ts +3 -0
- package/src/legacy/utils.ts +166 -0
- package/src/types.ts +1 -1
- package/src/utils.ts +153 -139
- package/dist/components/Items/NextListItem/hooks.d.ts +0 -19
- package/dist/components/Items/NextListItem/hooks.js +0 -80
- package/dist/components/Lists/contexts/ListProvider.d.ts +0 -17
- package/dist/components/Lists/contexts/ParentListProvider.d.ts +0 -18
- package/dist/components/Lists/contexts/ParentListProvider.js +0 -12
- package/src/components/Items/NextListItem/hooks.ts +0 -105
- package/src/components/Lists/contexts/CollapseProvider.ts +0 -9
- package/src/components/Lists/contexts/ListProvider.tsx +0 -28
- package/src/components/Lists/contexts/ParentListProvider.tsx +0 -35
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
import { RefObject } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import { AnyType, FlattenBaseItem, FlattenItem, ItemId } from './types';
|
|
3
|
+
type UseRenderItemsProps<Meta = AnyType> = {
|
|
4
|
+
items: ItemId[];
|
|
5
|
+
flattenedItems: Record<string, FlattenItem<Meta>>;
|
|
6
|
+
};
|
|
7
|
+
export declare function useRenderItems<Meta>(props: UseRenderItemsProps<Meta> | undefined): null[] | import("react/jsx-runtime").JSX.Element[];
|
|
8
|
+
type UseCreateBaseItemsProps = {
|
|
5
9
|
search?: boolean;
|
|
6
10
|
footerActiveElementsRefs?: RefObject<HTMLElement>[];
|
|
7
11
|
};
|
|
8
|
-
export declare function
|
|
9
|
-
|
|
10
|
-
|
|
12
|
+
export declare function useCreateBaseItems<Meta>({ footerActiveElementsRefs }: UseCreateBaseItemsProps): {
|
|
13
|
+
searchItem: FlattenBaseItem<Meta>;
|
|
14
|
+
footerItems: FlattenBaseItem<Meta>[];
|
|
11
15
|
};
|
|
12
16
|
type UseGroupItemSelectionProps = {
|
|
13
|
-
|
|
14
|
-
|
|
17
|
+
allChildIds: ItemId[];
|
|
18
|
+
items: ItemId[];
|
|
19
|
+
id: ItemId;
|
|
15
20
|
disabled?: boolean;
|
|
16
21
|
};
|
|
17
|
-
export declare function useGroupItemSelection({ id,
|
|
22
|
+
export declare function useGroupItemSelection({ id, disabled, allChildIds }: UseGroupItemSelectionProps): {
|
|
18
23
|
checked: boolean | undefined;
|
|
19
24
|
isIndeterminate: boolean;
|
|
20
25
|
handleOnSelect: () => void;
|
|
@@ -1,41 +1,57 @@
|
|
|
1
1
|
import { createElement as _createElement } from "react";
|
|
2
2
|
import { createRef, useEffect, useMemo } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
import { useSelectionContext } from '../Lists/contexts';
|
|
3
|
+
import { useNewListContext, useSelectionContext } from '../Lists/contexts';
|
|
5
4
|
import { AccordionItem } from './AccordionItem';
|
|
6
5
|
import { BaseItem } from './BaseItem';
|
|
7
6
|
import { GroupItem } from './GroupItem';
|
|
8
7
|
import { NextListItem } from './NextListItem';
|
|
9
|
-
import {
|
|
10
|
-
export function useRenderItems(
|
|
11
|
-
return useMemo(() =>
|
|
12
|
-
if (
|
|
13
|
-
return
|
|
8
|
+
import { isAccordionItemProps, isBaseItemProps, isGroupItemProps, isNextListItemProps } from './utils';
|
|
9
|
+
export function useRenderItems(props) {
|
|
10
|
+
return useMemo(() => {
|
|
11
|
+
if (!props) {
|
|
12
|
+
return [null];
|
|
14
13
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
const { items, flattenedItems } = props;
|
|
15
|
+
return items.map(id => {
|
|
16
|
+
const item = flattenedItems[id];
|
|
17
|
+
if (isGroupItemProps(item)) {
|
|
18
|
+
return _createElement(GroupItem, Object.assign({}, item, { key: item.label }));
|
|
19
|
+
}
|
|
20
|
+
if (isAccordionItemProps(item)) {
|
|
21
|
+
return _createElement(AccordionItem, Object.assign({}, item, { key: item.key }));
|
|
22
|
+
}
|
|
23
|
+
if (isNextListItemProps(item)) {
|
|
24
|
+
return _createElement(NextListItem, Object.assign({}, item, { key: item.key }));
|
|
25
|
+
}
|
|
26
|
+
return _createElement(BaseItem, Object.assign({}, item, { key: item.key }));
|
|
27
|
+
});
|
|
28
|
+
}, [props]);
|
|
23
29
|
}
|
|
24
|
-
export function
|
|
25
|
-
return useMemo(() =>
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
export function useCreateBaseItems({ footerActiveElementsRefs }) {
|
|
31
|
+
return useMemo(() => {
|
|
32
|
+
var _a;
|
|
33
|
+
return ({
|
|
34
|
+
searchItem: {
|
|
35
|
+
itemRef: createRef(),
|
|
36
|
+
id: '~search',
|
|
37
|
+
parentId: '~main',
|
|
38
|
+
},
|
|
39
|
+
footerItems: (_a = footerActiveElementsRefs === null || footerActiveElementsRefs === void 0 ? void 0 : footerActiveElementsRefs.map((itemRef, idx) => ({
|
|
40
|
+
id: `~footer__${idx}`,
|
|
41
|
+
itemRef,
|
|
42
|
+
parentId: '~main',
|
|
43
|
+
}))) !== null && _a !== void 0 ? _a : [],
|
|
44
|
+
});
|
|
45
|
+
}, [footerActiveElementsRefs]);
|
|
31
46
|
}
|
|
32
|
-
export function useGroupItemSelection({ id,
|
|
47
|
+
export function useGroupItemSelection({ id, disabled, allChildIds }) {
|
|
33
48
|
const { value, setValue, isSelectionMultiple } = useSelectionContext();
|
|
34
|
-
const {
|
|
49
|
+
const { flattenedItems } = useNewListContext();
|
|
50
|
+
const baseChildIds = useMemo(() => allChildIds.filter(itemId => isBaseItemProps(flattenedItems[itemId])), [allChildIds, flattenedItems]);
|
|
35
51
|
const isIndeterminate = isSelectionMultiple
|
|
36
|
-
?
|
|
37
|
-
:
|
|
38
|
-
const checked = isSelectionMultiple ?
|
|
52
|
+
? baseChildIds.some(childId => value === null || value === void 0 ? void 0 : value.includes(childId))
|
|
53
|
+
: baseChildIds.includes(value !== null && value !== void 0 ? value : '');
|
|
54
|
+
const checked = isSelectionMultiple ? baseChildIds.every(childId => value === null || value === void 0 ? void 0 : value.includes(childId)) : undefined;
|
|
39
55
|
useEffect(() => {
|
|
40
56
|
if (isSelectionMultiple) {
|
|
41
57
|
if (checked && !(value === null || value === void 0 ? void 0 : value.includes(id))) {
|
|
@@ -48,14 +64,14 @@ export function useGroupItemSelection({ id, items, disabled }) {
|
|
|
48
64
|
}, [checked, disabled, id, isSelectionMultiple, setValue, value]);
|
|
49
65
|
const handleOnSelect = () => {
|
|
50
66
|
if (checked) {
|
|
51
|
-
setValue === null || setValue === void 0 ? void 0 : setValue((value) => (value !== null && value !== void 0 ? value : []).filter(itemId => itemId !== id && !
|
|
67
|
+
setValue === null || setValue === void 0 ? void 0 : setValue((value) => (value !== null && value !== void 0 ? value : []).filter(itemId => itemId !== id && !baseChildIds.includes(itemId)));
|
|
52
68
|
return;
|
|
53
69
|
}
|
|
54
70
|
if (isIndeterminate) {
|
|
55
|
-
setValue === null || setValue === void 0 ? void 0 : setValue((value) => Array.from(new Set([...(value !== null && value !== void 0 ? value : []), ...
|
|
71
|
+
setValue === null || setValue === void 0 ? void 0 : setValue((value) => Array.from(new Set([...(value !== null && value !== void 0 ? value : []), ...baseChildIds, id])));
|
|
56
72
|
return;
|
|
57
73
|
}
|
|
58
|
-
setValue === null || setValue === void 0 ? void 0 : setValue((value) => (value !== null && value !== void 0 ? value : []).concat([...
|
|
74
|
+
setValue === null || setValue === void 0 ? void 0 : setValue((value) => (value !== null && value !== void 0 ? value : []).concat([...baseChildIds, id !== null && id !== void 0 ? id : '']));
|
|
59
75
|
};
|
|
60
76
|
return { checked, isIndeterminate, handleOnSelect };
|
|
61
77
|
}
|
|
@@ -1,23 +1,18 @@
|
|
|
1
1
|
import { FocusEvent, KeyboardEvent, MouseEvent, ReactNode, RefObject } from 'react';
|
|
2
|
-
import { TruncateStringProps } from '@snack-uikit/truncate-string';
|
|
3
2
|
import { WithSupportProps } from '@snack-uikit/utils';
|
|
4
|
-
import { SeparatorProps } from '../../helperComponents';
|
|
3
|
+
import { ItemContentProps, SeparatorProps } from '../../helperComponents';
|
|
5
4
|
import { ScrollProps, SearchState } from '../../types';
|
|
6
|
-
export type ItemContentProps = {
|
|
7
|
-
option: string;
|
|
8
|
-
caption?: string;
|
|
9
|
-
description?: string;
|
|
10
|
-
truncate?: {
|
|
11
|
-
option?: number;
|
|
12
|
-
description?: number;
|
|
13
|
-
variant?: TruncateStringProps['variant'];
|
|
14
|
-
};
|
|
15
|
-
};
|
|
16
5
|
export type BaseItemPrivateProps = {
|
|
17
6
|
expandIcon?: ReactNode;
|
|
18
7
|
open?: boolean;
|
|
19
8
|
};
|
|
20
|
-
export type
|
|
9
|
+
export type AnyType = any;
|
|
10
|
+
export type ContentRenderProps<Meta = AnyType> = {
|
|
11
|
+
label: string | number;
|
|
12
|
+
meta?: Meta;
|
|
13
|
+
};
|
|
14
|
+
export type ItemId = string | number;
|
|
15
|
+
export type BaseItemProps<Meta = AnyType> = WithSupportProps<{
|
|
21
16
|
/**
|
|
22
17
|
* Слот до основного контента
|
|
23
18
|
* @type ReactElement
|
|
@@ -28,8 +23,10 @@ export type BaseItemProps = WithSupportProps<{
|
|
|
28
23
|
* @type ReactElement
|
|
29
24
|
*/
|
|
30
25
|
afterContent?: ReactNode;
|
|
31
|
-
/**
|
|
32
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Основной контент айтема
|
|
28
|
+
*/
|
|
29
|
+
content?: ItemContentProps | ReactNode;
|
|
33
30
|
/** Колбек обработки клика */
|
|
34
31
|
onClick?(e: MouseEvent<HTMLElement>): void;
|
|
35
32
|
/** Колбек обработки нажатия кнопки мыши */
|
|
@@ -41,7 +38,7 @@ export type BaseItemProps = WithSupportProps<{
|
|
|
41
38
|
/** Колбек обработки блюра */
|
|
42
39
|
onBlur?(e: FocusEvent<HTMLElement>): void;
|
|
43
40
|
/** Уникальный идентификатор */
|
|
44
|
-
id?:
|
|
41
|
+
id?: ItemId;
|
|
45
42
|
/** Флаг неактивности элемента */
|
|
46
43
|
disabled?: boolean;
|
|
47
44
|
itemRef?: RefObject<HTMLElement>;
|
|
@@ -58,22 +55,40 @@ export type BaseItemProps = WithSupportProps<{
|
|
|
58
55
|
switch?: boolean;
|
|
59
56
|
key?: string | number;
|
|
60
57
|
itemWrapRender?(item: ReactNode): ReactNode;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
58
|
+
}> & {
|
|
59
|
+
/**
|
|
60
|
+
* Дополнительные поля для айтема, которые можно использовать для contentRender функции или поиска
|
|
61
|
+
*/
|
|
62
|
+
meta?: Meta;
|
|
63
|
+
};
|
|
64
|
+
type BaseItemsWithoutNonGroupProps<Meta = AnyType> = Omit<BaseItemProps<Meta>, 'switch' | 'inactive'>;
|
|
65
|
+
export type ItemProps<Meta = AnyType> = BaseItemProps<Meta> | AccordionItemProps<Meta> | NextListItemProps<Meta> | GroupItemProps<Meta>;
|
|
66
|
+
export type AccordionItemProps<Meta = AnyType> = BaseItemsWithoutNonGroupProps<Meta> & {
|
|
67
|
+
items: ItemProps<Meta>[];
|
|
66
68
|
type: 'collapse';
|
|
67
69
|
};
|
|
68
|
-
export type NextListItemProps = BaseItemsWithoutNonGroupProps & {
|
|
69
|
-
items: ItemProps[];
|
|
70
|
+
export type NextListItemProps<Meta = AnyType> = BaseItemsWithoutNonGroupProps<Meta> & {
|
|
71
|
+
items: ItemProps<Meta>[];
|
|
70
72
|
type: 'next-list';
|
|
71
73
|
placement?: 'right-start' | 'left-start' | 'left' | 'right' | 'left-end' | 'right-end';
|
|
72
74
|
search?: SearchState;
|
|
73
|
-
onSublistOpenChanged?(open: boolean, id?: string | number): void;
|
|
74
75
|
} & ScrollProps;
|
|
75
|
-
export type GroupItemProps = Omit<SeparatorProps, 'size'> & {
|
|
76
|
-
items: ItemProps[];
|
|
76
|
+
export type GroupItemProps<Meta = AnyType> = Omit<SeparatorProps, 'size'> & {
|
|
77
|
+
items: ItemProps<Meta>[];
|
|
77
78
|
id?: string | number;
|
|
79
|
+
meta?: undefined;
|
|
80
|
+
};
|
|
81
|
+
type RequiredFields<T, K extends keyof T> = Required<Pick<T, K>> & Omit<T, K>;
|
|
82
|
+
export type Flatten<T, K extends keyof T> = RequiredFields<T, K>;
|
|
83
|
+
type CommonFlattenProps = {
|
|
84
|
+
items: ItemId[];
|
|
85
|
+
allChildIds: ItemId[];
|
|
86
|
+
};
|
|
87
|
+
export type FlattenBaseItem<Meta = AnyType> = Flatten<BaseItemProps<Meta>, 'id' | 'itemRef'>;
|
|
88
|
+
export type FlattenNextListItem<Meta = AnyType> = Flatten<Omit<NextListItemProps<Meta>, 'items'>, 'id' | 'itemRef'> & CommonFlattenProps;
|
|
89
|
+
export type FlattenGroupListItem<Meta = AnyType> = Flatten<Omit<GroupItemProps<Meta>, 'items'>, 'id'> & CommonFlattenProps;
|
|
90
|
+
export type FlattenAccordionItem<Meta = AnyType> = Flatten<Omit<AccordionItemProps<Meta>, 'items'>, 'id' | 'itemRef'> & CommonFlattenProps;
|
|
91
|
+
export type FlattenItem<Meta = AnyType> = (FlattenBaseItem<Meta> | FlattenNextListItem<Meta> | FlattenGroupListItem<Meta> | FlattenAccordionItem<Meta>) & {
|
|
92
|
+
parentId?: ItemId;
|
|
78
93
|
};
|
|
79
94
|
export {};
|
|
@@ -1,17 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function
|
|
5
|
-
export declare function
|
|
6
|
-
export declare function
|
|
7
|
-
|
|
8
|
-
hasSearch: boolean;
|
|
9
|
-
footerRefs: ItemProps[];
|
|
10
|
-
pinTop?: ItemProps[];
|
|
11
|
-
pinBottom?: ItemProps[];
|
|
12
|
-
}): {
|
|
13
|
-
pinTop: ItemProps[];
|
|
14
|
-
items: ItemProps[];
|
|
15
|
-
pinBottom: ItemProps[];
|
|
16
|
-
};
|
|
17
|
-
export declare function addItemsIds(itemsProp: ItemProps[], prefix?: string | number): ItemProps[];
|
|
1
|
+
import { ItemContentProps } from '../../helperComponents';
|
|
2
|
+
import { AccordionItemProps, AnyType, BaseItemProps, GroupItemProps, NextListItemProps } from './types';
|
|
3
|
+
export declare function isBaseItemProps<Meta, ReturnType = BaseItemProps<Meta>>(item: AnyType): item is ReturnType;
|
|
4
|
+
export declare function isAccordionItemProps<Meta, ReturnType = AccordionItemProps<Meta>>(item: AnyType): item is ReturnType;
|
|
5
|
+
export declare function isNextListItemProps<Meta, ReturnType = NextListItemProps<Meta>>(item: AnyType): item is ReturnType;
|
|
6
|
+
export declare function isGroupItemProps<Meta, ReturnType = GroupItemProps<Meta>>(item: AnyType): item is ReturnType;
|
|
7
|
+
export declare function isContentItemProps(item: AnyType): item is ItemContentProps;
|
|
@@ -1,43 +1,15 @@
|
|
|
1
|
-
import { createRef } from 'react';
|
|
2
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3
1
|
export function isBaseItemProps(item) {
|
|
4
|
-
return '
|
|
2
|
+
return !('items' in item);
|
|
5
3
|
}
|
|
6
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7
4
|
export function isAccordionItemProps(item) {
|
|
8
5
|
return 'items' in item && item['type'] === 'collapse';
|
|
9
6
|
}
|
|
10
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
11
7
|
export function isNextListItemProps(item) {
|
|
12
8
|
return 'items' in item && item['type'] === 'next-list';
|
|
13
9
|
}
|
|
14
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
10
|
export function isGroupItemProps(item) {
|
|
16
11
|
return 'items' in item && item['type'] === undefined;
|
|
17
12
|
}
|
|
18
|
-
export function
|
|
19
|
-
|
|
20
|
-
const searchShift = hasSearch ? 1 : 0;
|
|
21
|
-
const pinTopNumber = (_a = pinTop === null || pinTop === void 0 ? void 0 : pinTop.length) !== null && _a !== void 0 ? _a : 0;
|
|
22
|
-
const pinBottomNumber = (_b = pinBottom === null || pinBottom === void 0 ? void 0 : pinBottom.length) !== null && _b !== void 0 ? _b : 0;
|
|
23
|
-
const footerElementsNumber = (_c = footerRefs === null || footerRefs === void 0 ? void 0 : footerRefs.length) !== null && _c !== void 0 ? _c : 0;
|
|
24
|
-
return {
|
|
25
|
-
pinTop: items.slice(searchShift, pinTopNumber + searchShift),
|
|
26
|
-
items: items.slice(pinTopNumber + searchShift, items.length - pinBottomNumber - footerElementsNumber),
|
|
27
|
-
pinBottom: items.slice(items.length - pinBottomNumber - footerElementsNumber, items.length - footerElementsNumber),
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
export function addItemsIds(itemsProp, prefix) {
|
|
31
|
-
return itemsProp.map((item, idx) => {
|
|
32
|
-
var _a;
|
|
33
|
-
const autoId = prefix !== undefined ? [prefix, idx].join('-') : String(idx);
|
|
34
|
-
const itemId = (_a = item.id) !== null && _a !== void 0 ? _a : autoId;
|
|
35
|
-
if (isGroupItemProps(item)) {
|
|
36
|
-
return Object.assign(Object.assign({ key: autoId }, item), { id: itemId, items: addItemsIds(item.items, itemId) });
|
|
37
|
-
}
|
|
38
|
-
if (isAccordionItemProps(item) || isNextListItemProps(item)) {
|
|
39
|
-
return Object.assign(Object.assign({ key: autoId }, item), { id: itemId, items: addItemsIds(item.items, itemId), itemRef: item.itemRef || createRef() });
|
|
40
|
-
}
|
|
41
|
-
return Object.assign(Object.assign({ key: autoId }, item), { id: itemId, itemRef: item.itemRef || createRef() });
|
|
42
|
-
});
|
|
13
|
+
export function isContentItemProps(item) {
|
|
14
|
+
return typeof item === 'object' && item['option'] !== undefined;
|
|
43
15
|
}
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
+
import { AnyType } from '../../Items';
|
|
1
2
|
import { DroplistProps } from '../types';
|
|
2
|
-
export declare function Droplist({ items: itemsProp, search, pinBottom, pinTop, footerActiveElementsRefs, children, trigger, placement, widthStrategy, triggerElemRef: triggerElemRefProp, open: openProp, onOpenChange, collapse, ...props }: DroplistProps): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
export declare function Droplist<Meta = AnyType>({ items: itemsProp, search, pinBottom: pinBottomProp, pinTop: pinTopProp, footerActiveElementsRefs, children, trigger, placement, widthStrategy, triggerElemRef: triggerElemRefProp, open: openProp, onOpenChange, collapse, triggerClassName, selection, contentRender, size, marker, className, ...props }: DroplistProps<Meta>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -10,46 +10,77 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
12
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
|
+
import cn from 'classnames';
|
|
13
14
|
import { cloneElement, isValidElement, useCallback, useMemo, useRef } from 'react';
|
|
14
|
-
import { useUncontrolledProp } from 'uncontrollable';
|
|
15
15
|
import { Dropdown } from '@snack-uikit/dropdown';
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
16
|
+
import { useValueControl } from '@snack-uikit/utils';
|
|
17
|
+
import { extractActiveItems, kindFlattenItems } from '../../../utils';
|
|
18
|
+
import { useCreateBaseItems } from '../../Items';
|
|
19
|
+
import { CollapseContext, FocusListContext, NewListContextProvider, SelectionProvider } from '../contexts';
|
|
20
|
+
import { useNewKeyboardNavigation } from '../hooks';
|
|
20
21
|
import { ListPrivate } from '../ListPrivate';
|
|
22
|
+
import styles from '../styles.module.css';
|
|
23
|
+
const DEFAULT_FALLBACK_PLACEMENTS = ['top', 'right', 'bottom', 'left'];
|
|
21
24
|
export function Droplist(_a) {
|
|
22
|
-
var
|
|
23
|
-
var { items: itemsProp, search, pinBottom, pinTop, footerActiveElementsRefs, children, trigger, placement, widthStrategy, triggerElemRef: triggerElemRefProp, open: openProp, onOpenChange, collapse = {} } = _a, props = __rest(_a, ["items", "search", "pinBottom", "pinTop", "footerActiveElementsRefs", "children", "trigger", "placement", "widthStrategy", "triggerElemRef", "open", "onOpenChange", "collapse"]);
|
|
25
|
+
var { items: itemsProp, search, pinBottom: pinBottomProp = [], pinTop: pinTopProp = [], footerActiveElementsRefs, children, trigger, placement, widthStrategy, triggerElemRef: triggerElemRefProp, open: openProp, onOpenChange, collapse = {}, triggerClassName, selection, contentRender, size = 's', marker = true, className } = _a, props = __rest(_a, ["items", "search", "pinBottom", "pinTop", "footerActiveElementsRefs", "children", "trigger", "placement", "widthStrategy", "triggerElemRef", "open", "onOpenChange", "collapse", "triggerClassName", "selection", "contentRender", "size", "marker", "className"]);
|
|
24
26
|
const hasSearch = useMemo(() => Boolean(search), [search]);
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
const [openCollapseItems = [], setOpenCollapsedItems] = useValueControl(collapse);
|
|
28
|
+
const toggleOpenCollapseItem = useCallback((id) => setOpenCollapsedItems((items) => (items === null || items === void 0 ? void 0 : items.includes(id)) ? items.filter(item => item !== id) : (items !== null && items !== void 0 ? items : []).concat([id])), [setOpenCollapsedItems]);
|
|
29
|
+
const [open = false, setOpen] = useValueControl({
|
|
30
|
+
value: openProp,
|
|
31
|
+
defaultValue: false,
|
|
32
|
+
onChange: onOpenChange,
|
|
30
33
|
});
|
|
31
|
-
const {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
const { searchItem, footerItems } = useCreateBaseItems({ footerActiveElementsRefs });
|
|
35
|
+
/**
|
|
36
|
+
* Объект с пропсами всех вложенных айтемов; ключ id
|
|
37
|
+
*/
|
|
38
|
+
const _b = useMemo(() => {
|
|
39
|
+
const pinTop = kindFlattenItems({ items: pinTopProp, prefix: '~pinTop', parentId: '~main' });
|
|
40
|
+
const items = kindFlattenItems({ items: itemsProp, prefix: '~main', parentId: '~main' });
|
|
41
|
+
const pinBottom = kindFlattenItems({ items: pinBottomProp, prefix: '~pinBottom', parentId: '~main' });
|
|
42
|
+
const flattenedItems = Object.assign(Object.assign(Object.assign({}, pinTop.flattenedItems), pinBottom.flattenedItems), items.flattenedItems);
|
|
43
|
+
[...footerItems, searchItem].forEach(item => {
|
|
44
|
+
flattenedItems[item.id] = item;
|
|
45
|
+
});
|
|
46
|
+
return { items, pinTop, pinBottom, flattenedItems };
|
|
47
|
+
}, [itemsProp, pinTopProp, pinBottomProp, searchItem, footerItems]), { flattenedItems } = _b, memorizedItems = __rest(_b, ["flattenedItems"]);
|
|
48
|
+
const { itemRefs, ids, expandedIds } = useMemo(() => {
|
|
49
|
+
const { pinTop, items, pinBottom } = memorizedItems;
|
|
50
|
+
let ids = [];
|
|
51
|
+
let expandedIds = [];
|
|
52
|
+
let itemRefs = [];
|
|
53
|
+
if (hasSearch) {
|
|
54
|
+
ids.push(searchItem.id);
|
|
55
|
+
itemRefs.push(searchItem.itemRef);
|
|
56
|
+
}
|
|
57
|
+
[pinTop, items, pinBottom].forEach(({ flattenedItems, items }) => {
|
|
58
|
+
const activeItems = extractActiveItems({ flattenedItems, items, openCollapseItems });
|
|
59
|
+
ids = ids.concat(activeItems.ids);
|
|
60
|
+
expandedIds = expandedIds.concat(activeItems.expandedIds);
|
|
61
|
+
itemRefs = itemRefs.concat(activeItems.itemRefs);
|
|
62
|
+
});
|
|
63
|
+
footerItems.forEach(footerItem => {
|
|
64
|
+
ids.push(footerItem.id);
|
|
65
|
+
itemRefs.push(footerItem.itemRef);
|
|
35
66
|
});
|
|
36
|
-
const items = searchItem.concat(res.items).concat(footerRefs);
|
|
37
67
|
return {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
expandedIds: res.expandedIds,
|
|
68
|
+
ids,
|
|
69
|
+
itemRefs,
|
|
70
|
+
expandedIds,
|
|
42
71
|
};
|
|
43
|
-
}, [
|
|
44
|
-
const slicedItems = useMemo(() => getSlicedItems({ items, hasSearch, pinTop, pinBottom, footerRefs }), [items, hasSearch, pinTop, pinBottom, footerRefs]);
|
|
72
|
+
}, [footerItems, hasSearch, memorizedItems, openCollapseItems, searchItem.id, searchItem.itemRef]);
|
|
45
73
|
const triggerElemRef = useRef(null);
|
|
46
74
|
const listRef = useRef(null);
|
|
47
|
-
const {
|
|
48
|
-
|
|
75
|
+
const { handleListKeyDownFactory, resetActiveItemId, activeItemId, forceUpdateActiveItemId } = useNewKeyboardNavigation({
|
|
76
|
+
mainRef: triggerElemRefProp !== null && triggerElemRefProp !== void 0 ? triggerElemRefProp : triggerElemRef,
|
|
77
|
+
itemRefs,
|
|
78
|
+
expandedIds,
|
|
79
|
+
flattenedItems,
|
|
80
|
+
});
|
|
81
|
+
const handleListKeyDown = useCallback((e) => handleListKeyDownFactory(ids, expandedIds)(e), [handleListKeyDownFactory, ids, expandedIds]);
|
|
49
82
|
const handleOpenChange = (open) => {
|
|
50
|
-
|
|
51
|
-
resetActiveFocusIndex();
|
|
52
|
-
setOpenCollapsedItems([]);
|
|
83
|
+
resetActiveItemId();
|
|
53
84
|
setOpen(open);
|
|
54
85
|
};
|
|
55
86
|
const onKeyDown = useCallback((e, cb) => {
|
|
@@ -58,12 +89,16 @@ export function Droplist(_a) {
|
|
|
58
89
|
setOpen(true);
|
|
59
90
|
setTimeout(() => {
|
|
60
91
|
var _a;
|
|
92
|
+
resetActiveItemId();
|
|
61
93
|
(_a = listRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
62
|
-
setActiveFocusIndex(0);
|
|
63
94
|
}, 0);
|
|
64
95
|
}
|
|
96
|
+
if (e.key === 'ArrowUp') {
|
|
97
|
+
// e.preventDefault();
|
|
98
|
+
setOpen(false);
|
|
99
|
+
}
|
|
65
100
|
cb === null || cb === void 0 ? void 0 : cb(e);
|
|
66
|
-
}, [
|
|
101
|
+
}, [resetActiveItemId, setOpen]);
|
|
67
102
|
const triggerElem = useMemo(() => {
|
|
68
103
|
if (isValidElement(children)) {
|
|
69
104
|
const props = typeof children.props === 'object' ? children.props : {};
|
|
@@ -77,24 +112,24 @@ export function Droplist(_a) {
|
|
|
77
112
|
}
|
|
78
113
|
return children;
|
|
79
114
|
}, [onKeyDown, children]);
|
|
80
|
-
|
|
81
|
-
//
|
|
82
|
-
//
|
|
83
|
-
_jsx(SelectionProvider, Object.assign({},
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
115
|
+
// const handleOnFocus = e => {
|
|
116
|
+
// // resetActiveItemId();
|
|
117
|
+
// };
|
|
118
|
+
return (_jsx(NewListContextProvider, { flattenedItems: flattenedItems, contentRender: contentRender, size: size, marker: marker, children: _jsx(SelectionProvider, Object.assign({}, selection, { children: _jsx(CollapseContext.Provider, { value: {
|
|
119
|
+
openCollapseItems,
|
|
120
|
+
toggleOpenCollapseItem,
|
|
121
|
+
}, children: _jsx(FocusListContext.Provider, { value: {
|
|
122
|
+
activeItemId,
|
|
123
|
+
handleListKeyDownFactory,
|
|
124
|
+
forceUpdateActiveItemId,
|
|
125
|
+
}, children: _jsx(Dropdown, Object.assign({ content: _jsx("div", { className: cn(styles.wrapper, className), children: _jsx(ListPrivate, Object.assign({}, props, memorizedItems, { onKeyDown: handleListKeyDown, tabIndex: 0, ref: listRef, search: search,
|
|
126
|
+
// onFocus={handleOnFocus}
|
|
127
|
+
onFocus: e => {
|
|
128
|
+
e.stopPropagation();
|
|
129
|
+
forceUpdateActiveItemId === null || forceUpdateActiveItemId === void 0 ? void 0 : forceUpdateActiveItemId(ids[0]);
|
|
130
|
+
}, limitedScrollHeight: true })) }), triggerClassName: triggerClassName, fallbackPlacements: DEFAULT_FALLBACK_PLACEMENTS, trigger: trigger, placement: placement, widthStrategy: widthStrategy }, (triggerElemRefProp
|
|
131
|
+
? {}
|
|
132
|
+
: {
|
|
133
|
+
triggerRef: triggerElemRef,
|
|
134
|
+
}), { open: open, onOpenChange: handleOpenChange, children: triggerElem })) }) }) })) }));
|
|
100
135
|
}
|
|
@@ -1,20 +1,16 @@
|
|
|
1
|
-
import { KeyboardEvent } from 'react';
|
|
1
|
+
import { KeyboardEvent, RefObject } from 'react';
|
|
2
2
|
export declare const List: import("react").ForwardRefExoticComponent<{
|
|
3
3
|
'data-test-id'?: string | undefined;
|
|
4
4
|
} & import("react").AriaAttributes & {
|
|
5
|
-
items: import("../../Items").ItemProps[];
|
|
6
|
-
pinTop?: import("../../Items").ItemProps[] | undefined;
|
|
7
|
-
pinBottom?: import("../../Items").ItemProps[] | undefined;
|
|
5
|
+
items: import("../../Items").ItemProps<unknown>[];
|
|
6
|
+
pinTop?: import("../../Items").ItemProps<unknown>[] | undefined;
|
|
7
|
+
pinBottom?: import("../../Items").ItemProps<unknown>[] | undefined;
|
|
8
8
|
footer?: import("react").ReactNode;
|
|
9
|
-
footerActiveElementsRefs?:
|
|
9
|
+
footerActiveElementsRefs?: RefObject<HTMLElement>[] | undefined;
|
|
10
10
|
search?: import("../../..").SearchState | undefined;
|
|
11
11
|
tabIndex?: number | undefined;
|
|
12
|
-
collapse?:
|
|
13
|
-
value?: (string | number)[] | undefined;
|
|
14
|
-
onChange?(value: (string | number)[]): void;
|
|
15
|
-
defaultValue?: (string | number)[] | undefined;
|
|
16
|
-
} | undefined;
|
|
12
|
+
collapse?: import("../contexts").CollapseState | undefined;
|
|
17
13
|
className?: string | undefined;
|
|
18
14
|
onKeyDown?(e: KeyboardEvent<HTMLElement>): void;
|
|
19
15
|
loading?: boolean | undefined;
|
|
20
|
-
} & import("../contexts").SelectionState & import("../contexts").
|
|
16
|
+
} & import("../contexts").SelectionState & import("../contexts").PublicListContextType<unknown> & import("../../../types").ScrollProps & import("../types").EmptyState & import("react").RefAttributes<HTMLElement>>;
|