@snack-uikit/list 0.10.0 → 0.10.1-preview-80576138.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/README.md +56 -24
  2. package/dist/components/Items/AccordionItem/AccordionItem.d.ts +4 -2
  3. package/dist/components/Items/AccordionItem/AccordionItem.js +18 -16
  4. package/dist/components/Items/BaseItem/BaseItem.d.ts +8 -4
  5. package/dist/components/Items/BaseItem/BaseItem.js +20 -14
  6. package/dist/components/Items/BaseItem/styles.module.css +9 -122
  7. package/dist/components/Items/GroupItem/GroupItem.d.ts +5 -1
  8. package/dist/components/Items/GroupItem/GroupItem.js +1 -3
  9. package/dist/components/Items/GroupSelectItem/GroupSelectItem.d.ts +4 -0
  10. package/dist/components/Items/GroupSelectItem/GroupSelectItem.js +18 -0
  11. package/dist/components/Items/GroupSelectItem/index.d.ts +1 -0
  12. package/dist/components/Items/GroupSelectItem/index.js +1 -0
  13. package/dist/components/Items/NextListItem/NextListItem.d.ts +6 -2
  14. package/dist/components/Items/NextListItem/NextListItem.js +53 -45
  15. package/dist/components/Items/NextListItem/constants.d.ts +2 -0
  16. package/dist/components/Items/NextListItem/constants.js +10 -0
  17. package/dist/components/Items/SearchItem/SearchItem.d.ts +3 -1
  18. package/dist/components/Items/SearchItem/SearchItem.js +5 -8
  19. package/dist/components/Items/hooks.d.ts +11 -10
  20. package/dist/components/Items/hooks.js +64 -46
  21. package/dist/components/Items/index.d.ts +1 -5
  22. package/dist/components/Items/index.js +1 -5
  23. package/dist/components/Items/types.d.ts +68 -34
  24. package/dist/components/Items/utils.d.ts +33 -16
  25. package/dist/components/Items/utils.js +132 -37
  26. package/dist/components/Lists/Droplist/DropList.d.ts +1 -1
  27. package/dist/components/Lists/Droplist/DropList.js +73 -50
  28. package/dist/components/Lists/List/List.d.ts +5 -9
  29. package/dist/components/Lists/List/List.js +56 -54
  30. package/dist/components/Lists/ListPrivate/ListPrivate.d.ts +6 -20
  31. package/dist/components/Lists/ListPrivate/ListPrivate.js +9 -8
  32. package/dist/components/Lists/contexts/CollapseProvider.d.ts +13 -1
  33. package/dist/components/Lists/contexts/CollapseProvider.js +2 -0
  34. package/dist/components/Lists/contexts/FocusListProvider.d.ts +9 -0
  35. package/dist/components/Lists/contexts/FocusListProvider.js +5 -0
  36. package/dist/components/Lists/contexts/NewListProvider.d.ts +32 -0
  37. package/dist/components/Lists/contexts/{ListProvider.js → NewListProvider.js} +10 -5
  38. package/dist/components/Lists/contexts/SelectionProvider.d.ts +25 -15
  39. package/dist/components/Lists/contexts/SelectionProvider.js +17 -13
  40. package/dist/components/Lists/contexts/index.d.ts +2 -2
  41. package/dist/components/Lists/contexts/index.js +2 -2
  42. package/dist/components/Lists/hooks.d.ts +10 -12
  43. package/dist/components/Lists/hooks.js +73 -40
  44. package/dist/components/Lists/types.d.ts +12 -14
  45. package/dist/components/index.d.ts +2 -2
  46. package/dist/components/index.js +1 -1
  47. package/dist/helperComponents/ItemContent/ItemContent.d.ts +15 -0
  48. package/dist/helperComponents/ItemContent/ItemContent.js +23 -0
  49. package/dist/helperComponents/ItemContent/index.d.ts +1 -0
  50. package/dist/helperComponents/ItemContent/index.js +1 -0
  51. package/dist/helperComponents/ItemContent/styles.module.css +117 -0
  52. package/dist/helperComponents/ListEmptyState/ListEmptyState.d.ts +2 -2
  53. package/dist/helperComponents/ListEmptyState/ListEmptyState.js +13 -4
  54. package/dist/helperComponents/Separator/Separator.d.ts +8 -2
  55. package/dist/helperComponents/Separator/Separator.js +29 -2
  56. package/dist/helperComponents/index.d.ts +1 -0
  57. package/dist/helperComponents/index.js +1 -0
  58. package/dist/hooks.d.ts +1 -1
  59. package/dist/hooks.js +15 -10
  60. package/dist/index.d.ts +3 -2
  61. package/dist/index.js +3 -2
  62. package/dist/legacy/components/Items/hooks.d.ts +12 -0
  63. package/dist/legacy/components/Items/hooks.js +33 -0
  64. package/dist/legacy/components/index.d.ts +1 -0
  65. package/dist/legacy/components/index.js +1 -0
  66. package/dist/legacy/hooks.d.ts +5 -0
  67. package/dist/legacy/hooks.js +15 -0
  68. package/dist/legacy/index.d.ts +3 -0
  69. package/dist/legacy/index.js +3 -0
  70. package/dist/{utils.d.ts → legacy/utils.d.ts} +2 -3
  71. package/dist/{utils.js → legacy/utils.js} +4 -12
  72. package/dist/types.d.ts +1 -1
  73. package/package.json +14 -14
  74. package/src/components/Items/AccordionItem/AccordionItem.tsx +24 -20
  75. package/src/components/Items/BaseItem/BaseItem.tsx +48 -43
  76. package/src/components/Items/BaseItem/styles.module.scss +8 -70
  77. package/src/components/Items/GroupItem/GroupItem.tsx +5 -5
  78. package/src/components/Items/GroupSelectItem/GroupSelectItem.tsx +44 -0
  79. package/src/components/Items/GroupSelectItem/index.ts +1 -0
  80. package/src/components/Items/NextListItem/NextListItem.tsx +86 -85
  81. package/src/components/Items/NextListItem/constants.ts +12 -0
  82. package/src/components/Items/SearchItem/SearchItem.tsx +6 -8
  83. package/src/components/Items/hooks.tsx +86 -66
  84. package/src/components/Items/index.ts +1 -5
  85. package/src/components/Items/types.ts +91 -42
  86. package/src/components/Items/utils.ts +193 -52
  87. package/src/components/Lists/Droplist/DropList.tsx +151 -98
  88. package/src/components/Lists/List/List.tsx +124 -104
  89. package/src/components/Lists/ListPrivate/ListPrivate.tsx +19 -20
  90. package/src/components/Lists/contexts/CollapseProvider.tsx +22 -0
  91. package/src/components/Lists/contexts/FocusListProvider.tsx +16 -0
  92. package/src/components/Lists/contexts/NewListProvider.tsx +54 -0
  93. package/src/components/Lists/contexts/SelectionProvider.tsx +56 -39
  94. package/src/components/Lists/contexts/index.ts +3 -2
  95. package/src/components/Lists/hooks.ts +124 -75
  96. package/src/components/Lists/types.ts +20 -24
  97. package/src/components/index.ts +16 -2
  98. package/src/helperComponents/ItemContent/ItemContent.tsx +63 -0
  99. package/src/helperComponents/ItemContent/index.ts +1 -0
  100. package/src/helperComponents/ItemContent/styles.module.scss +78 -0
  101. package/src/helperComponents/ListEmptyState/ListEmptyState.tsx +26 -12
  102. package/src/helperComponents/Separator/Separator.tsx +65 -8
  103. package/src/helperComponents/index.ts +1 -0
  104. package/src/hooks.ts +21 -15
  105. package/src/index.ts +5 -2
  106. package/src/legacy/components/Items/hooks.tsx +53 -0
  107. package/src/legacy/components/index.ts +1 -0
  108. package/src/legacy/hooks.ts +27 -0
  109. package/src/legacy/index.ts +3 -0
  110. package/src/{utils.ts → legacy/utils.ts} +4 -13
  111. package/src/types.ts +1 -1
  112. package/dist/components/Items/NextListItem/hooks.d.ts +0 -19
  113. package/dist/components/Items/NextListItem/hooks.js +0 -80
  114. package/dist/components/Lists/contexts/ListProvider.d.ts +0 -17
  115. package/dist/components/Lists/contexts/ParentListProvider.d.ts +0 -18
  116. package/dist/components/Lists/contexts/ParentListProvider.js +0 -12
  117. package/src/components/Items/NextListItem/hooks.ts +0 -105
  118. package/src/components/Lists/contexts/CollapseProvider.ts +0 -9
  119. package/src/components/Lists/contexts/ListProvider.tsx +0 -28
  120. package/src/components/Lists/contexts/ParentListProvider.tsx +0 -35
@@ -10,58 +10,66 @@ 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 { useCallback, useMemo, useRef, useState } from 'react';
13
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
14
14
  import { Dropdown } from '@snack-uikit/dropdown';
15
15
  import { ChevronRightSVG } from '@snack-uikit/icons';
16
- import { withCollapsedItems } from '../../../utils';
17
- import { ParentListContext, useParentListContext } from '../../Lists/contexts';
16
+ import { useCollapseContext, useFocusListContext, useNewListContext } from '../../Lists/contexts';
18
17
  import { ListPrivate } from '../../Lists/ListPrivate';
19
18
  import { BaseItem } from '../BaseItem';
20
19
  import { useGroupItemSelection } from '../hooks';
21
- import { useKeyboardNavigation } from './hooks';
22
- const FALLBACK_PLACEMENTS = [
23
- 'right',
24
- 'right-start',
25
- 'right-end',
26
- 'left',
27
- 'left-start',
28
- 'left-end',
29
- ];
20
+ import { extractActiveItems, isNextListItem } from '../utils';
21
+ import { FALLBACK_PLACEMENTS } from './constants';
30
22
  export function NextListItem(_a) {
31
- var { items: itemsProp, placement = 'right-start', id, search, scroll, scrollRef, disabled, onSublistOpenChanged, loading = false } = _a, option = __rest(_a, ["items", "placement", "id", "search", "scroll", "scrollRef", "disabled", "onSublistOpenChanged", "loading"]);
32
- const listRef = useRef(null);
33
- const [openCollapsedItems, setOpenCollapsedItems] = useState([]);
34
- const { items, itemRefs, ids, expandedIds } = useMemo(() => withCollapsedItems({
35
- items: itemsProp,
36
- openCollapsedItems,
37
- }), [itemsProp, openCollapsedItems]);
38
- const { parentOpenNestedIndex, parentIds, triggerRef, parentResetNestedIndex, parentResetActiveFocusIndex } = useParentListContext();
39
- const { open, setOpen, handleListKeyDown, activeFocusIndex, openNestedIndex, resetNestedIndex, resetActiveFocusIndex, } = useKeyboardNavigation({ ids, expandedIds, itemRefs, id });
40
- const { isIndeterminate, checked, handleOnSelect } = useGroupItemSelection({ items: itemsProp, id, disabled });
41
- const handleOpenChange = useCallback((open) => {
42
- if (!open) {
43
- resetActiveFocusIndex();
44
- resetNestedIndex();
45
- setOpenCollapsedItems([]);
23
+ var { items, placement = 'right-start', id, scroll, scrollRef, disabled, onSublistOpenChanged, allChildIds, loading = false, focusId = id } = _a, option = __rest(_a, ["items", "placement", "id", "scroll", "scrollRef", "disabled", "onSublistOpenChanged", "allChildIds", "loading", "focusId"]);
24
+ const { flattenItems, focusFlattenItems } = useNewListContext();
25
+ const { openCollapseItems = [] } = useCollapseContext();
26
+ const item = flattenItems[id];
27
+ const { ids, expandedIds } = useMemo(() => {
28
+ const { ids, expandedIds } = extractActiveItems({
29
+ focusCloseChildIds: items,
30
+ focusFlattenItems,
31
+ openCollapseItems,
32
+ });
33
+ return { ids, expandedIds: expandedIds.concat([id]) };
34
+ }, [focusFlattenItems, id, items, openCollapseItems]);
35
+ const { handleListKeyDownFactory, activeItemId, forceUpdateActiveItemId } = useFocusListContext();
36
+ const [open, setOpen] = useState();
37
+ const handleListKeyDown = useCallback((e) => {
38
+ handleListKeyDownFactory(ids, expandedIds)(e);
39
+ if (e.code === 'ArrowLeft') {
40
+ forceUpdateActiveItemId === null || forceUpdateActiveItemId === void 0 ? void 0 : forceUpdateActiveItemId(focusId);
41
+ setOpen(false);
42
+ e.stopPropagation();
43
+ return;
46
44
  }
47
- onSublistOpenChanged === null || onSublistOpenChanged === void 0 ? void 0 : onSublistOpenChanged(open, id);
48
- setOpen(open);
49
- }, [id, onSublistOpenChanged, resetActiveFocusIndex, resetNestedIndex, setOpen]);
45
+ }, [handleListKeyDownFactory, ids, expandedIds, forceUpdateActiveItemId, focusId]);
46
+ const { indeterminate, checked, handleOnSelect } = useGroupItemSelection({
47
+ items: isNextListItem(item) ? item.items : [],
48
+ id,
49
+ disabled,
50
+ allChildIds,
51
+ });
50
52
  const handleOutsideClick = useCallback(() => {
51
- parentResetNestedIndex === null || parentResetNestedIndex === void 0 ? void 0 : parentResetNestedIndex();
52
- parentResetActiveFocusIndex === null || parentResetActiveFocusIndex === void 0 ? void 0 : parentResetActiveFocusIndex();
53
+ forceUpdateActiveItemId === null || forceUpdateActiveItemId === void 0 ? void 0 : forceUpdateActiveItemId('~drop-focus');
54
+ setOpen(false);
53
55
  return true;
54
- }, [parentResetActiveFocusIndex, parentResetNestedIndex]);
55
- return (_jsx(Dropdown, { outsideClick: handleOutsideClick, fallbackPlacements: FALLBACK_PLACEMENTS, content: _jsx(ParentListContext.Provider, { value: {
56
- parentIds: ids,
57
- parentActiveFocusIndex: activeFocusIndex,
58
- parentExpandedIds: expandedIds,
59
- parentItemRefs: itemRefs,
60
- parentOpenNestedIndex: openNestedIndex,
61
- triggerRef,
62
- parentRef: listRef,
63
- parentResetNestedIndex: resetNestedIndex,
64
- parentResetActiveFocusIndex: resetActiveFocusIndex,
65
- toggleOpenCollapsedItems: id => setOpenCollapsedItems(items => items.includes(id) ? items.filter(item => item !== id) : items.concat([id])),
66
- }, children: _jsx(ListPrivate, { onKeyDown: handleListKeyDown, items: items, nested: true, search: search, scroll: scroll, scrollRef: scrollRef, limitedScrollHeight: true, loading: loading }) }), trigger: 'hover', open: (open || parentIds[parentOpenNestedIndex] === id) && !disabled, onOpenChange: handleOpenChange, placement: placement, widthStrategy: 'auto', children: _jsx(BaseItem, Object.assign({}, option, { disabled: disabled, open: open, expandIcon: _jsx(ChevronRightSVG, {}), id: id, isParentNode: true, indeterminate: isIndeterminate && !checked, onSelect: handleOnSelect })) }));
56
+ }, [forceUpdateActiveItemId]);
57
+ const isOpen = useMemo(() => Boolean(!disabled && activeItemId && focusFlattenItems[focusId].allChildIds.includes(activeItemId)), [activeItemId, disabled, focusFlattenItems, focusId]);
58
+ useEffect(() => {
59
+ setOpen(open => open && isOpen);
60
+ }, [id, isOpen]);
61
+ const listRef = useRef(null);
62
+ return (_jsx(Dropdown, { outsideClick: handleOutsideClick, fallbackPlacements: FALLBACK_PLACEMENTS, content: _jsx(ListPrivate, { onKeyDown: handleListKeyDown, items: items, nested: true, scroll: scroll, tabIndex: 0, ref: listRef, onFocus: e => {
63
+ e.stopPropagation();
64
+ forceUpdateActiveItemId === null || forceUpdateActiveItemId === void 0 ? void 0 : forceUpdateActiveItemId(ids[0]);
65
+ }, scrollRef: scrollRef, limitedScrollHeight: true, loading: loading }), trigger: 'hover', open: isOpen || open, onOpenChange: value => {
66
+ setOpen(value);
67
+ onSublistOpenChanged === null || onSublistOpenChanged === void 0 ? void 0 : onSublistOpenChanged(value, id);
68
+ }, placement: placement, widthStrategy: 'auto', children: _jsx(BaseItem, Object.assign({}, option, { disabled: disabled, open: open, expandIcon: _jsx(ChevronRightSVG, {}), id: id, isParentNode: true, indeterminate: indeterminate, checked: checked, onOpenNestedList: () => {
69
+ setOpen(true);
70
+ setTimeout(() => {
71
+ var _a;
72
+ (_a = listRef.current) === null || _a === void 0 ? void 0 : _a.focus();
73
+ }, 0);
74
+ }, onSelect: handleOnSelect })) }));
67
75
  }
@@ -0,0 +1,2 @@
1
+ import { DropdownProps } from '@snack-uikit/dropdown';
2
+ export declare const FALLBACK_PLACEMENTS: DropdownProps['fallbackPlacements'];
@@ -0,0 +1,10 @@
1
+ export const FALLBACK_PLACEMENTS = [
2
+ 'right',
3
+ 'right-start',
4
+ 'right-end',
5
+ 'left',
6
+ 'left-start',
7
+ 'left-end',
8
+ 'bottom',
9
+ 'top',
10
+ ];
@@ -1,5 +1,7 @@
1
+ import { RefObject } from 'react';
1
2
  import { SearchState } from '../../../types';
2
3
  export type SearchItemProps = {
3
4
  search?: SearchState;
5
+ itemRef?: RefObject<HTMLElement>;
4
6
  };
5
- export declare function SearchItem({ search }: SearchItemProps): import("react/jsx-runtime").JSX.Element | null;
7
+ export declare function SearchItem({ search, itemRef }: SearchItemProps): import("react/jsx-runtime").JSX.Element | null;
@@ -1,28 +1,25 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import cn from 'classnames';
3
3
  import { SearchPrivate } from '@snack-uikit/search-private';
4
- import { useListContext, useParentListContext } from '../../Lists/contexts';
4
+ import { useNewListContext } from '../../Lists/contexts';
5
5
  import commonStyles from '../styles.module.css';
6
6
  import styles from './styles.module.css';
7
- export function SearchItem({ search }) {
8
- const { parentItemRefs, parentSetActiveFocusIndex } = useParentListContext();
9
- const { size } = useListContext();
7
+ export function SearchItem({ search, itemRef }) {
8
+ const { size = 's' } = useNewListContext();
10
9
  const handleKeyDown = (e) => {
11
10
  if (['ArrowDown', 'ArrowUp'].includes(e.key)) {
12
11
  e.preventDefault();
13
12
  }
14
13
  if (['ArrowRight'].includes(e.key)) {
15
14
  e.stopPropagation();
15
+ e.preventDefault();
16
16
  }
17
17
  };
18
18
  const handleFocus = (e) => {
19
- if (e.target === parentItemRefs[0].current) {
20
- parentSetActiveFocusIndex === null || parentSetActiveFocusIndex === void 0 ? void 0 : parentSetActiveFocusIndex(0);
21
- }
22
19
  e.stopPropagation();
23
20
  };
24
21
  if (!Boolean(search)) {
25
22
  return null;
26
23
  }
27
- return (_jsx("div", { className: cn(commonStyles.listItem, styles.searchItem), "data-size": size, "data-test-id": 'list__search-item', children: _jsx(SearchPrivate, Object.assign({ size: size, tabIndex: -1, onKeyDown: handleKeyDown, onFocus: handleFocus }, search, { ref: parentItemRefs[0] })) }));
24
+ return (_jsx("div", { className: cn(commonStyles.listItem, styles.searchItem), "data-size": size, "data-test-id": 'list__search-item', children: _jsx(SearchPrivate, Object.assign({ size: size, tabIndex: -1, onKeyDown: handleKeyDown, onFocus: handleFocus }, search, { ref: itemRef })) }));
28
25
  }
@@ -1,22 +1,23 @@
1
1
  import { RefObject } from 'react';
2
- import { ItemProps } from './types';
3
- export declare function useRenderItems(items: ItemProps[]): import("react/jsx-runtime").JSX.Element[];
4
- type UseItemsWithIdsProps = {
2
+ import { Flatten, FlattenBaseItem, ItemId } from './types';
3
+ export declare function useRenderItems(focusCloseChildIds?: ItemId[]): import("react/jsx-runtime").JSX.Element[] | null[];
4
+ type UseCreateBaseItemsProps = {
5
5
  search?: boolean;
6
6
  footerActiveElementsRefs?: RefObject<HTMLElement>[];
7
7
  };
8
- export declare function useItemsWithIds({ search, footerActiveElementsRefs }: UseItemsWithIdsProps): {
9
- search: ItemProps[];
10
- footerRefs: ItemProps[];
8
+ export declare function useCreateBaseItems({ footerActiveElementsRefs }: UseCreateBaseItemsProps): {
9
+ searchItem: Flatten<FlattenBaseItem, 'itemRef'>;
10
+ footerItems: Flatten<FlattenBaseItem, 'itemRef'>[];
11
11
  };
12
12
  type UseGroupItemSelectionProps = {
13
- items: ItemProps[];
14
- id?: string | number;
13
+ allChildIds: ItemId[];
14
+ items: ItemId[];
15
+ id: ItemId;
15
16
  disabled?: boolean;
16
17
  };
17
- export declare function useGroupItemSelection({ id, items, disabled }: UseGroupItemSelectionProps): {
18
+ export declare function useGroupItemSelection({ id, allChildIds }: UseGroupItemSelectionProps): {
18
19
  checked: boolean | undefined;
19
- isIndeterminate: boolean;
20
+ indeterminate: boolean;
20
21
  handleOnSelect: () => void;
21
22
  };
22
23
  export {};
@@ -1,61 +1,79 @@
1
1
  import { createElement as _createElement } from "react";
2
- import { createRef, useEffect, useMemo } from 'react';
3
- import { extractAllChildIds, extractChildIds } from '../../utils';
4
- import { useSelectionContext } from '../Lists/contexts';
2
+ import { createRef, useMemo } from 'react';
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';
7
+ import { GroupSelectItem } from './GroupSelectItem';
8
8
  import { NextListItem } from './NextListItem';
9
- import { addItemsIds, isAccordionItemProps, isGroupItemProps, isNextListItemProps } from './utils';
10
- export function useRenderItems(items) {
11
- return useMemo(() => items.map(item => {
12
- if (isGroupItemProps(item)) {
13
- return _createElement(GroupItem, Object.assign({}, item, { key: item.label }));
9
+ import { isAccordionItem, isGroupItem, isGroupSelectItem, isNextListItem } from './utils';
10
+ export function useRenderItems(focusCloseChildIds) {
11
+ const { focusFlattenItems, flattenItems } = useNewListContext();
12
+ const { isSelectionSingle } = useSelectionContext();
13
+ return useMemo(() => {
14
+ if (!focusCloseChildIds) {
15
+ return [null];
14
16
  }
15
- if (isAccordionItemProps(item)) {
16
- return _createElement(AccordionItem, Object.assign({}, item, { key: item.key }));
17
- }
18
- if (isNextListItemProps(item)) {
19
- return _createElement(NextListItem, Object.assign({}, item, { key: item.key }));
20
- }
21
- return _createElement(BaseItem, Object.assign({}, item, { key: item.key }));
22
- }), [items]);
17
+ return focusCloseChildIds.map(id => {
18
+ const { itemRef, key, originalId, items } = focusFlattenItems[id];
19
+ const flattenItem = flattenItems[originalId];
20
+ if (isGroupItem(flattenItem) ||
21
+ (isSelectionSingle && isGroupSelectItem(flattenItem))) {
22
+ return _createElement(GroupItem, Object.assign({}, flattenItem, { items: items, key: key }));
23
+ }
24
+ if (isGroupSelectItem(flattenItem)) {
25
+ return _createElement(GroupSelectItem, Object.assign({}, flattenItem, { items: items, itemRef: itemRef, key: key }));
26
+ }
27
+ if (isAccordionItem(flattenItem)) {
28
+ return _createElement(AccordionItem, Object.assign({}, flattenItem, { items: items, itemRef: itemRef, key: key }));
29
+ }
30
+ if (isNextListItem(flattenItem)) {
31
+ return _createElement(NextListItem, Object.assign({}, flattenItem, { focusId: id, items: items, itemRef: itemRef, key: key }));
32
+ }
33
+ return _createElement(BaseItem, Object.assign({}, flattenItem, { itemRef: itemRef, key: key }));
34
+ });
35
+ }, [flattenItems, focusCloseChildIds, focusFlattenItems, isSelectionSingle]);
23
36
  }
24
- export function useItemsWithIds({ search, footerActiveElementsRefs }) {
25
- return useMemo(() => ({
26
- search: addItemsIds(search ? [{ itemRef: createRef() }] : [], 'search'),
27
- footerRefs: addItemsIds(footerActiveElementsRefs
28
- ? footerActiveElementsRefs === null || footerActiveElementsRefs === void 0 ? void 0 : footerActiveElementsRefs.map(ref => ({ itemRef: ref }))
29
- : [], 'footer'),
30
- }), [footerActiveElementsRefs, search]);
37
+ export function useCreateBaseItems({ footerActiveElementsRefs }) {
38
+ return useMemo(() => {
39
+ var _a;
40
+ return ({
41
+ searchItem: {
42
+ itemRef: createRef(),
43
+ id: '~search',
44
+ parentId: '~main',
45
+ items: [],
46
+ allChildIds: [],
47
+ },
48
+ footerItems: (_a = footerActiveElementsRefs === null || footerActiveElementsRefs === void 0 ? void 0 : footerActiveElementsRefs.map((itemRef, idx) => ({
49
+ id: `~footer__${idx}`,
50
+ itemRef,
51
+ parentId: '~main',
52
+ items: [],
53
+ allChildIds: [],
54
+ }))) !== null && _a !== void 0 ? _a : [],
55
+ });
56
+ }, [footerActiveElementsRefs]);
31
57
  }
32
- export function useGroupItemSelection({ id, items, disabled }) {
58
+ export function useGroupItemSelection({ id, allChildIds }) {
33
59
  const { value, setValue, isSelectionMultiple } = useSelectionContext();
34
- const { childIds, allChildIds } = useMemo(() => ({ childIds: extractChildIds({ items }), allChildIds: extractAllChildIds({ items }) }), [items]);
35
- const isIndeterminate = isSelectionMultiple
36
- ? allChildIds.some(childId => value === null || value === void 0 ? void 0 : value.includes(childId))
37
- : allChildIds.includes(value !== null && value !== void 0 ? value : '');
38
- const checked = isSelectionMultiple ? allChildIds.every(childId => value === null || value === void 0 ? void 0 : value.includes(childId)) : undefined;
39
- useEffect(() => {
40
- if (isSelectionMultiple) {
41
- if (checked && !(value === null || value === void 0 ? void 0 : value.includes(id))) {
42
- setValue === null || setValue === void 0 ? void 0 : setValue((value) => (value !== null && value !== void 0 ? value : []).concat([id !== null && id !== void 0 ? id : '']));
43
- }
44
- if (!checked && (value === null || value === void 0 ? void 0 : value.includes(id))) {
45
- setValue === null || setValue === void 0 ? void 0 : setValue((value) => (value !== null && value !== void 0 ? value : []).filter(itemId => itemId !== id));
46
- }
47
- }
48
- }, [checked, disabled, id, isSelectionMultiple, setValue, value]);
60
+ const { flattenItems } = useNewListContext();
61
+ const baseChildIds = useMemo(() => allChildIds.filter(itemId => {
62
+ const item = flattenItems[itemId];
63
+ return item && !('type' in item);
64
+ }), [allChildIds, flattenItems]);
65
+ const checked = isSelectionMultiple
66
+ ? value && Boolean(value.length) && baseChildIds.every(childId => value === null || value === void 0 ? void 0 : value.includes(childId))
67
+ : undefined;
68
+ const indeterminate = isSelectionMultiple
69
+ ? !checked && baseChildIds.some(childId => value === null || value === void 0 ? void 0 : value.includes(childId))
70
+ : baseChildIds.includes(value !== null && value !== void 0 ? value : '');
49
71
  const handleOnSelect = () => {
50
72
  if (checked) {
51
- setValue === null || setValue === void 0 ? void 0 : setValue((value) => (value !== null && value !== void 0 ? value : []).filter(itemId => itemId !== id && !childIds.includes(itemId)));
52
- return;
53
- }
54
- if (isIndeterminate) {
55
- setValue === null || setValue === void 0 ? void 0 : setValue((value) => Array.from(new Set([...(value !== null && value !== void 0 ? value : []), ...childIds, id])));
73
+ setValue === null || setValue === void 0 ? void 0 : setValue((value) => (value !== null && value !== void 0 ? value : []).filter(itemId => itemId !== id && !baseChildIds.includes(itemId)));
56
74
  return;
57
75
  }
58
- setValue === null || setValue === void 0 ? void 0 : setValue((value) => (value !== null && value !== void 0 ? value : []).concat([...childIds, id !== null && id !== void 0 ? id : '']));
76
+ setValue === null || setValue === void 0 ? void 0 : setValue((value) => Array.from(new Set([...(value !== null && value !== void 0 ? value : []), ...baseChildIds])));
59
77
  };
60
- return { checked, isIndeterminate, handleOnSelect };
78
+ return { checked, indeterminate, handleOnSelect };
61
79
  }
@@ -1,9 +1,5 @@
1
- export * from './BaseItem';
2
- export * from './NextListItem';
3
- export * from './AccordionItem';
4
- export * from './GroupItem';
5
- export * from './SearchItem';
6
1
  export * from './hooks';
7
2
  export * from './types';
8
3
  export * from './utils';
4
+ export * from './SearchItem';
9
5
  export * from './PinGroupItem';
@@ -1,9 +1,5 @@
1
- export * from './BaseItem';
2
- export * from './NextListItem';
3
- export * from './AccordionItem';
4
- export * from './GroupItem';
5
- export * from './SearchItem';
6
1
  export * from './hooks';
7
2
  export * from './types';
8
3
  export * from './utils';
4
+ export * from './SearchItem';
9
5
  export * from './PinGroupItem';
@@ -1,23 +1,12 @@
1
1
  import { FocusEvent, KeyboardEvent, MouseEvent, ReactNode, RefObject } from 'react';
2
2
  import { TruncateStringProps } from '@snack-uikit/truncate-string';
3
3
  import { WithSupportProps } from '@snack-uikit/utils';
4
- import { SeparatorProps } from '../../helperComponents';
5
- 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
- export type BaseItemPrivateProps = {
17
- expandIcon?: ReactNode;
18
- open?: boolean;
19
- };
20
- export type BaseItemProps = WithSupportProps<{
4
+ import { ItemContentProps } from '../../helperComponents';
5
+ import { ScrollProps } from '../../types';
6
+ export type AnyType = any;
7
+ export type ItemId = string | number;
8
+ type ItemContent = ItemContentProps;
9
+ export type BaseItem = WithSupportProps<{
21
10
  /**
22
11
  * Слот до основного контента
23
12
  * @type ReactElement
@@ -28,8 +17,10 @@ export type BaseItemProps = WithSupportProps<{
28
17
  * @type ReactElement
29
18
  */
30
19
  afterContent?: ReactNode;
31
- /** Основной контент айтема */
32
- content: ItemContentProps;
20
+ /**
21
+ * Основной контент айтема
22
+ */
23
+ content?: ItemContent | ReactNode;
33
24
  /** Колбек обработки клика */
34
25
  onClick?(e: MouseEvent<HTMLElement>): void;
35
26
  /** Колбек обработки нажатия кнопки мыши */
@@ -41,7 +32,7 @@ export type BaseItemProps = WithSupportProps<{
41
32
  /** Колбек обработки блюра */
42
33
  onBlur?(e: FocusEvent<HTMLElement>): void;
43
34
  /** Уникальный идентификатор */
44
- id?: string | number;
35
+ id?: ItemId;
45
36
  /** Флаг неактивности элемента */
46
37
  disabled?: boolean;
47
38
  itemRef?: RefObject<HTMLElement>;
@@ -56,25 +47,68 @@ export type BaseItemProps = WithSupportProps<{
56
47
  * Флаг отображения состояния выбранного элемента через switch
57
48
  */
58
49
  switch?: boolean;
59
- key?: string | number;
60
50
  itemWrapRender?(item: ReactNode): ReactNode;
61
51
  }>;
62
- type BaseItemsWithoutNonGroupProps = Omit<BaseItemProps, 'switch' | 'inactive'>;
63
- export type ItemProps = BaseItemProps | AccordionItemProps | NextListItemProps | GroupItemProps;
64
- export type AccordionItemProps = BaseItemsWithoutNonGroupProps & {
65
- items: ItemProps[];
52
+ type BaseItemWithoutNonGroup = Omit<BaseItem, 'switch' | 'inactive'>;
53
+ export type Item = BaseItem | AccordionItem | NextListItem | GroupItem | GroupSelectItem;
54
+ export type AccordionItem = BaseItemWithoutNonGroup & {
55
+ items: Item[];
66
56
  type: 'collapse';
67
57
  };
68
- export type NextListItemProps = BaseItemsWithoutNonGroupProps & {
69
- items: ItemProps[];
58
+ export type NextListItem = BaseItemWithoutNonGroup & ScrollProps & {
59
+ items: Item[];
70
60
  type: 'next-list';
71
- placement?: 'right-start' | 'left-start' | 'left' | 'right' | 'left-end' | 'right-end';
72
- search?: SearchState;
73
- onSublistOpenChanged?(open: boolean, id?: string | number): void;
61
+ onSublistOpenChanged?(open: boolean, id?: ItemId): void;
74
62
  loading?: boolean;
75
- } & ScrollProps;
76
- export type GroupItemProps = Omit<SeparatorProps, 'size'> & {
77
- items: ItemProps[];
78
- id?: string | number;
63
+ dataError?: boolean;
64
+ dataFiltered?: boolean;
65
+ placement?: 'right-start' | 'left-start' | 'left' | 'right' | 'left-end' | 'right-end';
66
+ };
67
+ type CommonGroupItem = {
68
+ label?: string;
69
+ truncate?: {
70
+ variant?: TruncateStringProps['variant'];
71
+ };
72
+ mode?: 'primary' | 'secondary';
73
+ divider?: boolean;
74
+ };
75
+ export type GroupItem = CommonGroupItem & {
76
+ items: Item[];
77
+ type: 'group';
78
+ };
79
+ export type GroupSelectItem = CommonGroupItem & {
80
+ items: Item[];
81
+ type: 'group-select';
82
+ id?: ItemId;
83
+ itemRef?: RefObject<HTMLElement>;
84
+ };
85
+ type RequiredFields<T, K extends keyof T> = Required<Pick<T, K>> & Omit<T, K>;
86
+ export type Flatten<T, K extends keyof T> = RequiredFields<T, K>;
87
+ export type CommonFlattenProps = {
88
+ items: ItemId[];
89
+ allChildIds: ItemId[];
90
+ };
91
+ export type FlattenBaseItem = Flatten<BaseItem, 'id'>;
92
+ export type FlattenNextListItem = Flatten<Omit<NextListItem, 'items'>, 'id'>;
93
+ export type FlattenGroupListItem = Omit<GroupItem, 'items'> & {
94
+ id: ItemId;
79
95
  };
96
+ export type FlattenGroupSelectListItem = Flatten<Omit<GroupSelectItem, 'items'>, 'id'>;
97
+ export type FlattenAccordionItem = Flatten<Omit<AccordionItem, 'items'>, 'id'>;
98
+ export type FlattenItem = FlattenBaseItem | ((FlattenNextListItem | FlattenGroupListItem | FlattenAccordionItem | FlattenGroupSelectListItem) & CommonFlattenProps);
99
+ export type FocusFlattenItem = {
100
+ key: ItemId;
101
+ id: ItemId;
102
+ originalId: ItemId;
103
+ parentId?: ItemId;
104
+ itemRef?: RefObject<HTMLElement>;
105
+ type?: 'next-list' | 'collapse' | 'group' | 'group-select';
106
+ disabled?: boolean;
107
+ } & CommonFlattenProps;
108
+ export type ItemProps = Item;
109
+ export type BaseItemProps = BaseItem;
110
+ export type GroupItemProps = GroupItem;
111
+ export type NextListItemProps = NextListItem;
112
+ export type AccordionItemProps = AccordionItem;
113
+ export type GroupSelectItemProps = GroupSelectItem;
80
114
  export {};
@@ -1,17 +1,34 @@
1
- import { AccordionItemProps, BaseItemProps, GroupItemProps, ItemProps, NextListItemProps } from './types';
2
- export declare function isBaseItemProps(item: any): item is BaseItemProps;
3
- export declare function isAccordionItemProps(item: any): item is AccordionItemProps;
4
- export declare function isNextListItemProps(item: any): item is NextListItemProps;
5
- export declare function isGroupItemProps(item: any): item is GroupItemProps;
6
- export declare function getSlicedItems({ items, hasSearch, pinTop, pinBottom, footerRefs, }: {
7
- items: ItemProps[];
8
- hasSearch: boolean;
9
- footerRefs: ItemProps[];
10
- pinTop?: ItemProps[];
11
- pinBottom?: ItemProps[];
12
- }): {
13
- pinTop: ItemProps[];
14
- items: ItemProps[];
15
- pinBottom: ItemProps[];
1
+ import { ItemContentProps } from '../../helperComponents';
2
+ import { AccordionItem, AnyType, BaseItem, FlattenItem, FocusFlattenItem, GroupItem, GroupSelectItem, Item, ItemId, NextListItem } from './types';
3
+ export declare function isBaseItem<ReturnType = BaseItem>(item: AnyType): item is ReturnType;
4
+ export declare function isAccordionItem<ReturnType = AccordionItem>(item: AnyType): item is ReturnType;
5
+ export declare function isNextListItem<ReturnType = NextListItem>(item: AnyType): item is ReturnType;
6
+ export declare function isGroupItem<ReturnType = GroupItem>(item: AnyType): item is ReturnType;
7
+ export declare function isGroupSelectItem<ReturnType = GroupSelectItem>(item: AnyType): item is ReturnType;
8
+ export declare function isContentItem(item: AnyType): item is ItemContentProps;
9
+ export declare const isBaseItemProps: typeof isBaseItem;
10
+ export declare const isAccordionItemProps: typeof isAccordionItem;
11
+ export declare const isNextListItemProps: typeof isNextListItem;
12
+ export declare const isGroupItemProps: typeof isGroupItem;
13
+ type KindFlattenItemsProps = {
14
+ items: Item[];
15
+ prefix?: ItemId;
16
+ parentId?: ItemId;
16
17
  };
17
- export declare function addItemsIds(itemsProp: ItemProps[], prefix?: string | number): ItemProps[];
18
+ export declare function kindFlattenItems({ items, prefix, parentId }: KindFlattenItemsProps): {
19
+ focusCloseChildIds: ItemId[];
20
+ allChildIds: ItemId[];
21
+ flattenItems: Record<string, FlattenItem>;
22
+ focusFlattenItems: Record<string, FocusFlattenItem>;
23
+ };
24
+ type ExtractActiveItemsProps = {
25
+ focusFlattenItems: Record<string, FocusFlattenItem>;
26
+ focusCloseChildIds: ItemId[];
27
+ openCollapseItems: ItemId[];
28
+ };
29
+ type ExtractActiveItemsReturnType = {
30
+ ids: ItemId[];
31
+ expandedIds: ItemId[];
32
+ };
33
+ export declare function extractActiveItems({ focusFlattenItems, focusCloseChildIds, openCollapseItems, }: ExtractActiveItemsProps): ExtractActiveItemsReturnType;
34
+ export {};