@snack-uikit/list 0.1.1-preview-57c837e3.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 (151) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/LICENSE +201 -0
  3. package/README.md +73 -0
  4. package/dist/components/Items/AccordionItem/AccordionItem.d.ts +2 -0
  5. package/dist/components/Items/AccordionItem/AccordionItem.js +41 -0
  6. package/dist/components/Items/AccordionItem/index.d.ts +1 -0
  7. package/dist/components/Items/AccordionItem/index.js +1 -0
  8. package/dist/components/Items/BaseItem/BaseItem.d.ts +8 -0
  9. package/dist/components/Items/BaseItem/BaseItem.js +67 -0
  10. package/dist/components/Items/BaseItem/constants.d.ts +2 -0
  11. package/dist/components/Items/BaseItem/constants.js +5 -0
  12. package/dist/components/Items/BaseItem/index.d.ts +1 -0
  13. package/dist/components/Items/BaseItem/index.js +1 -0
  14. package/dist/components/Items/BaseItem/styles.module.css +205 -0
  15. package/dist/components/Items/GroupItem/GroupItem.d.ts +2 -0
  16. package/dist/components/Items/GroupItem/GroupItem.js +9 -0
  17. package/dist/components/Items/GroupItem/index.d.ts +1 -0
  18. package/dist/components/Items/GroupItem/index.js +1 -0
  19. package/dist/components/Items/NextListItem/NextListItem.d.ts +2 -0
  20. package/dist/components/Items/NextListItem/NextListItem.js +66 -0
  21. package/dist/components/Items/NextListItem/hooks.d.ts +19 -0
  22. package/dist/components/Items/NextListItem/hooks.js +80 -0
  23. package/dist/components/Items/NextListItem/index.d.ts +1 -0
  24. package/dist/components/Items/NextListItem/index.js +1 -0
  25. package/dist/components/Items/PinGroupItem/PinGroupItem.d.ts +7 -0
  26. package/dist/components/Items/PinGroupItem/PinGroupItem.js +15 -0
  27. package/dist/components/Items/PinGroupItem/index.d.ts +1 -0
  28. package/dist/components/Items/PinGroupItem/index.js +1 -0
  29. package/dist/components/Items/PinGroupItem/styles.module.css +31 -0
  30. package/dist/components/Items/SearchItem/SearchItem.d.ts +5 -0
  31. package/dist/components/Items/SearchItem/SearchItem.js +28 -0
  32. package/dist/components/Items/SearchItem/index.d.ts +1 -0
  33. package/dist/components/Items/SearchItem/index.js +1 -0
  34. package/dist/components/Items/SearchItem/styles.module.css +11 -0
  35. package/dist/components/Items/hooks.d.ts +22 -0
  36. package/dist/components/Items/hooks.js +61 -0
  37. package/dist/components/Items/index.d.ts +9 -0
  38. package/dist/components/Items/index.js +9 -0
  39. package/dist/components/Items/styles.module.css +74 -0
  40. package/dist/components/Items/types.d.ts +43 -0
  41. package/dist/components/Items/types.js +1 -0
  42. package/dist/components/Items/utils.d.ts +17 -0
  43. package/dist/components/Items/utils.js +42 -0
  44. package/dist/components/Lists/Droplist/DropList.d.ts +2 -0
  45. package/dist/components/Lists/Droplist/DropList.js +97 -0
  46. package/dist/components/Lists/Droplist/index.d.ts +1 -0
  47. package/dist/components/Lists/Droplist/index.js +1 -0
  48. package/dist/components/Lists/List/List.d.ts +14 -0
  49. package/dist/components/Lists/List/List.js +77 -0
  50. package/dist/components/Lists/List/index.d.ts +1 -0
  51. package/dist/components/Lists/List/index.js +1 -0
  52. package/dist/components/Lists/ListPrivate/ListPrivate.d.ts +22 -0
  53. package/dist/components/Lists/ListPrivate/ListPrivate.js +41 -0
  54. package/dist/components/Lists/ListPrivate/index.d.ts +1 -0
  55. package/dist/components/Lists/ListPrivate/index.js +1 -0
  56. package/dist/components/Lists/ListPrivate/styles.module.css +46 -0
  57. package/dist/components/Lists/contexts/CollapseProvider.d.ts +6 -0
  58. package/dist/components/Lists/contexts/CollapseProvider.js +3 -0
  59. package/dist/components/Lists/contexts/ListProvider.d.ts +12 -0
  60. package/dist/components/Lists/contexts/ListProvider.js +22 -0
  61. package/dist/components/Lists/contexts/ParentListProvider.d.ts +18 -0
  62. package/dist/components/Lists/contexts/ParentListProvider.js +12 -0
  63. package/dist/components/Lists/contexts/SelectionProvider.d.ts +53 -0
  64. package/dist/components/Lists/contexts/SelectionProvider.js +61 -0
  65. package/dist/components/Lists/contexts/index.d.ts +4 -0
  66. package/dist/components/Lists/contexts/index.js +4 -0
  67. package/dist/components/Lists/hooks.d.ts +16 -0
  68. package/dist/components/Lists/hooks.js +73 -0
  69. package/dist/components/Lists/index.d.ts +4 -0
  70. package/dist/components/Lists/index.js +2 -0
  71. package/dist/components/Lists/styles.module.css +70 -0
  72. package/dist/components/Lists/types.d.ts +35 -0
  73. package/dist/components/Lists/types.js +1 -0
  74. package/dist/components/index.d.ts +2 -0
  75. package/dist/components/index.js +1 -0
  76. package/dist/helperComponents/CollapseBlockPrivate/CollapseBlockPrivate.d.ts +9 -0
  77. package/dist/helperComponents/CollapseBlockPrivate/CollapseBlockPrivate.js +20 -0
  78. package/dist/helperComponents/CollapseBlockPrivate/index.d.ts +1 -0
  79. package/dist/helperComponents/CollapseBlockPrivate/index.js +1 -0
  80. package/dist/helperComponents/CollapseBlockPrivate/styles.module.css +38 -0
  81. package/dist/helperComponents/HiddenTabButton/HiddenTabButton.d.ts +6 -0
  82. package/dist/helperComponents/HiddenTabButton/HiddenTabButton.js +17 -0
  83. package/dist/helperComponents/HiddenTabButton/index.d.ts +1 -0
  84. package/dist/helperComponents/HiddenTabButton/index.js +1 -0
  85. package/dist/helperComponents/HiddenTabButton/styles.module.css +9 -0
  86. package/dist/helperComponents/Separator/Separator.d.ts +7 -0
  87. package/dist/helperComponents/Separator/Separator.js +12 -0
  88. package/dist/helperComponents/Separator/index.d.ts +1 -0
  89. package/dist/helperComponents/Separator/index.js +1 -0
  90. package/dist/helperComponents/Separator/styles.module.css +112 -0
  91. package/dist/helperComponents/index.d.ts +3 -0
  92. package/dist/helperComponents/index.js +3 -0
  93. package/dist/index.d.ts +1 -0
  94. package/dist/index.js +1 -0
  95. package/dist/types.d.ts +12 -0
  96. package/dist/types.js +1 -0
  97. package/dist/utils.d.ts +18 -0
  98. package/dist/utils.js +69 -0
  99. package/package.json +48 -0
  100. package/src/components/Items/AccordionItem/AccordionItem.tsx +60 -0
  101. package/src/components/Items/AccordionItem/index.ts +1 -0
  102. package/src/components/Items/BaseItem/BaseItem.tsx +150 -0
  103. package/src/components/Items/BaseItem/constants.ts +7 -0
  104. package/src/components/Items/BaseItem/index.ts +1 -0
  105. package/src/components/Items/BaseItem/styles.module.scss +190 -0
  106. package/src/components/Items/GroupItem/GroupItem.tsx +17 -0
  107. package/src/components/Items/GroupItem/index.ts +1 -0
  108. package/src/components/Items/NextListItem/NextListItem.tsx +131 -0
  109. package/src/components/Items/NextListItem/hooks.ts +105 -0
  110. package/src/components/Items/NextListItem/index.ts +1 -0
  111. package/src/components/Items/PinGroupItem/PinGroupItem.tsx +28 -0
  112. package/src/components/Items/PinGroupItem/index.ts +1 -0
  113. package/src/components/Items/PinGroupItem/styles.module.scss +38 -0
  114. package/src/components/Items/SearchItem/SearchItem.tsx +52 -0
  115. package/src/components/Items/SearchItem/index.ts +1 -0
  116. package/src/components/Items/SearchItem/styles.module.scss +13 -0
  117. package/src/components/Items/hooks.tsx +101 -0
  118. package/src/components/Items/index.ts +9 -0
  119. package/src/components/Items/styles.module.scss +78 -0
  120. package/src/components/Items/types.ts +61 -0
  121. package/src/components/Items/utils.ts +69 -0
  122. package/src/components/Lists/Droplist/DropList.tsx +166 -0
  123. package/src/components/Lists/Droplist/index.ts +1 -0
  124. package/src/components/Lists/List/List.tsx +120 -0
  125. package/src/components/Lists/List/index.ts +1 -0
  126. package/src/components/Lists/ListPrivate/ListPrivate.tsx +149 -0
  127. package/src/components/Lists/ListPrivate/index.ts +1 -0
  128. package/src/components/Lists/ListPrivate/styles.module.scss +48 -0
  129. package/src/components/Lists/contexts/CollapseProvider.ts +9 -0
  130. package/src/components/Lists/contexts/ListProvider.tsx +24 -0
  131. package/src/components/Lists/contexts/ParentListProvider.tsx +35 -0
  132. package/src/components/Lists/contexts/SelectionProvider.tsx +171 -0
  133. package/src/components/Lists/contexts/index.ts +4 -0
  134. package/src/components/Lists/hooks.ts +99 -0
  135. package/src/components/Lists/index.ts +10 -0
  136. package/src/components/Lists/styles.module.scss +73 -0
  137. package/src/components/Lists/types.ts +47 -0
  138. package/src/components/index.ts +3 -0
  139. package/src/helperComponents/CollapseBlockPrivate/CollapseBlockPrivate.tsx +34 -0
  140. package/src/helperComponents/CollapseBlockPrivate/index.ts +1 -0
  141. package/src/helperComponents/CollapseBlockPrivate/styles.module.scss +51 -0
  142. package/src/helperComponents/HiddenTabButton/HiddenTabButton.tsx +27 -0
  143. package/src/helperComponents/HiddenTabButton/index.ts +1 -0
  144. package/src/helperComponents/HiddenTabButton/styles.module.scss +11 -0
  145. package/src/helperComponents/Separator/Separator.tsx +33 -0
  146. package/src/helperComponents/Separator/index.ts +1 -0
  147. package/src/helperComponents/Separator/styles.module.scss +63 -0
  148. package/src/helperComponents/index.ts +3 -0
  149. package/src/index.ts +1 -0
  150. package/src/types.ts +14 -0
  151. package/src/utils.ts +106 -0
@@ -0,0 +1,97 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { jsx as _jsx } from "react/jsx-runtime";
13
+ import { cloneElement, isValidElement, useCallback, useMemo, useRef, useState } from 'react';
14
+ import { useUncontrolledProp } from 'uncontrollable';
15
+ import { Dropdown } from '@snack-uikit/dropdown';
16
+ import { extractItemIds, extractItemRefs, withCollapsedItems } from '../../../utils';
17
+ import { addItemsIds, getSlicedItems, useItemsWithIds } from '../../Items';
18
+ import { extractSelectionProps, ParentListContext, SelectionProvider } from '../contexts';
19
+ import { useKeyboardNavigation } from '../hooks';
20
+ import { ListPrivate } from '../ListPrivate';
21
+ export function Droplist(_a) {
22
+ var { items: itemsProp, search, pinBottom, pinTop, footerActiveElementsRefs, children, trigger, placement, widthStrategy, triggerElemRef: triggerElemRefProp, open: openProp, onOpenChange } = _a, props = __rest(_a, ["items", "search", "pinBottom", "pinTop", "footerActiveElementsRefs", "children", "trigger", "placement", "widthStrategy", "triggerElemRef", "open", "onOpenChange"]);
23
+ const hasSearch = useMemo(() => Boolean(search), [search]);
24
+ const memorizedItems = useMemo(() => addItemsIds((pinBottom !== null && pinBottom !== void 0 ? pinBottom : []).concat(itemsProp).concat(pinTop !== null && pinTop !== void 0 ? pinTop : [])), [itemsProp, pinBottom, pinTop]);
25
+ const [openCollapsedItems, setOpenCollapsedItems] = useState([]);
26
+ const { search: searchItem, footerRefs } = useItemsWithIds({
27
+ search: hasSearch,
28
+ footerActiveElementsRefs,
29
+ });
30
+ const { items, itemRefs, ids, expandedIds } = useMemo(() => {
31
+ const res = withCollapsedItems({
32
+ items: memorizedItems,
33
+ openCollapsedItems,
34
+ });
35
+ const items = searchItem.concat(res.items).concat(footerRefs);
36
+ return {
37
+ items,
38
+ ids: extractItemIds(searchItem).concat(res.ids).concat(extractItemIds(footerRefs)),
39
+ itemRefs: extractItemRefs(searchItem).concat(res.itemRefs).concat(extractItemRefs(footerRefs)),
40
+ expandedIds: res.expandedIds,
41
+ };
42
+ }, [footerRefs, memorizedItems, openCollapsedItems, searchItem]);
43
+ const slicedItems = useMemo(() => getSlicedItems({ items, hasSearch, pinTop, pinBottom, footerRefs }), [items, hasSearch, pinTop, pinBottom, footerRefs]);
44
+ const triggerElemRef = useRef(null);
45
+ const listRef = useRef(null);
46
+ const { activeFocusIndex, setActiveFocusIndex, openNestedIndex, handleListKeyDown, resetNestedIndex, resetActiveFocusIndex, } = useKeyboardNavigation({ ids, expandedIds, parentRef: triggerElemRefProp !== null && triggerElemRefProp !== void 0 ? triggerElemRefProp : triggerElemRef, itemRefs });
47
+ const [open, setOpen] = useUncontrolledProp(openProp, false, onOpenChange);
48
+ const handleOpenChange = (open) => {
49
+ if (!open) {
50
+ resetNestedIndex();
51
+ resetActiveFocusIndex();
52
+ setOpenCollapsedItems([]);
53
+ }
54
+ setOpen(open);
55
+ };
56
+ const onKeyDown = useCallback((e, cb) => {
57
+ if (e.key === 'ArrowDown') {
58
+ e.preventDefault();
59
+ setOpen(true);
60
+ setTimeout(() => {
61
+ var _a;
62
+ (_a = listRef.current) === null || _a === void 0 ? void 0 : _a.focus();
63
+ setActiveFocusIndex(0);
64
+ }, 0);
65
+ }
66
+ cb === null || cb === void 0 ? void 0 : cb(e);
67
+ }, [setActiveFocusIndex, setOpen]);
68
+ const triggerElem = useMemo(() => {
69
+ if (isValidElement(children)) {
70
+ const props = typeof children.props === 'object' ? children.props : {};
71
+ return cloneElement(children, Object.assign(Object.assign({}, props), { onKeyDown: (e) => {
72
+ var _a;
73
+ onKeyDown(e, (_a = children.props) === null || _a === void 0 ? void 0 : _a.onKeyDown);
74
+ } }));
75
+ }
76
+ return children;
77
+ }, [onKeyDown, children]);
78
+ return (
79
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
80
+ // @ts-ignore
81
+ _jsx(SelectionProvider, Object.assign({}, extractSelectionProps(props), { children: _jsx(ParentListContext.Provider, { value: {
82
+ parentIds: ids,
83
+ parentActiveFocusIndex: activeFocusIndex,
84
+ parentExpandedIds: expandedIds,
85
+ parentItemRefs: itemRefs,
86
+ parentOpenNestedIndex: openNestedIndex,
87
+ triggerRef: triggerElemRefProp !== null && triggerElemRefProp !== void 0 ? triggerElemRefProp : triggerElemRef,
88
+ parentRef: listRef,
89
+ parentResetNestedIndex: resetNestedIndex,
90
+ parentResetActiveFocusIndex: resetActiveFocusIndex,
91
+ toggleOpenCollapsedItems: id => setOpenCollapsedItems(items => items.includes(id) ? items.filter(item => item !== id) : items.concat([id])),
92
+ }, children: _jsx(Dropdown, Object.assign({ content: _jsx(ListPrivate, Object.assign({ onKeyDown: handleListKeyDown, tabIndex: 0, ref: listRef, search: search }, slicedItems, props)), trigger: trigger, placement: placement, widthStrategy: widthStrategy }, (triggerElemRefProp
93
+ ? {}
94
+ : {
95
+ triggerRef: triggerElemRef,
96
+ }), { open: open, onOpenChange: handleOpenChange, children: triggerElem })) }) })));
97
+ }
@@ -0,0 +1 @@
1
+ export * from './DropList';
@@ -0,0 +1 @@
1
+ export * from './DropList';
@@ -0,0 +1,14 @@
1
+ /// <reference types="react" />
2
+ export declare const List: import("react").ForwardRefExoticComponent<{
3
+ 'data-test-id'?: string | undefined;
4
+ } & import("react").AriaAttributes & {
5
+ items: import("../../Items").ItemProps[];
6
+ pinTop?: import("../../Items").ItemProps[] | undefined;
7
+ pinBottom?: import("../../Items").ItemProps[] | undefined;
8
+ footer?: import("react").ReactNode;
9
+ search?: import("../../../types").SearchState | undefined;
10
+ loading?: boolean | undefined;
11
+ noData?: string | undefined;
12
+ noResults?: string | undefined;
13
+ footerActiveElementsRefs?: import("react").RefObject<HTMLElement>[] | undefined;
14
+ } & Pick<import("../contexts").SelectionProviderProps, "value" | "defaultValue" | "selection" | "onChange"> & import("../contexts").ListContextType & import("../../../types").ScrollProps & import("react").RefAttributes<HTMLElement>>;
@@ -0,0 +1,77 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
+ import { forwardRef, useMemo, useRef, useState } from 'react';
14
+ import { HiddenTabButton } from '../../../helperComponents';
15
+ import { extractItemIds, extractItemRefs, withCollapsedItems } from '../../../utils';
16
+ import { addItemsIds, getSlicedItems, useItemsWithIds } from '../../Items';
17
+ import { extractSelectionProps, ParentListContext, SelectionProvider, useParentListContext } from '../contexts';
18
+ import { useKeyboardNavigation } from '../hooks';
19
+ import { ListPrivate } from '../ListPrivate';
20
+ import styles from '../styles.module.css';
21
+ export const List = forwardRef((_a) => {
22
+ var { items: itemsProp, search, pinBottom, pinTop, footerActiveElementsRefs } = _a, props = __rest(_a, ["items", "search", "pinBottom", "pinTop", "footerActiveElementsRefs"]);
23
+ const hasSearch = useMemo(() => Boolean(search), [search]);
24
+ const memorizedItems = useMemo(() => addItemsIds((pinTop !== null && pinTop !== void 0 ? pinTop : []).concat(itemsProp).concat(pinBottom !== null && pinBottom !== void 0 ? pinBottom : [])), [itemsProp, pinBottom, pinTop]);
25
+ const [openCollapsedItems, setOpenCollapsedItems] = useState([]);
26
+ const { search: searchItem, footerRefs } = useItemsWithIds({
27
+ search: hasSearch,
28
+ footerActiveElementsRefs,
29
+ });
30
+ const { items, itemRefs, ids, expandedIds } = useMemo(() => {
31
+ const res = withCollapsedItems({
32
+ items: memorizedItems,
33
+ openCollapsedItems,
34
+ });
35
+ const items = searchItem.concat(res.items).concat(footerRefs);
36
+ return {
37
+ items,
38
+ ids: extractItemIds(searchItem).concat(res.ids).concat(extractItemIds(footerRefs)),
39
+ itemRefs: extractItemRefs(searchItem).concat(res.itemRefs).concat(extractItemRefs(footerRefs)),
40
+ expandedIds: res.expandedIds,
41
+ };
42
+ }, [footerRefs, memorizedItems, openCollapsedItems, searchItem]);
43
+ const slicedItems = useMemo(() => getSlicedItems({ items, hasSearch, pinTop, pinBottom, footerRefs }), [items, hasSearch, pinTop, pinBottom, footerRefs]);
44
+ const listRef = useRef(null);
45
+ const btnRef = useRef(null);
46
+ const { triggerRef } = useParentListContext();
47
+ const { activeFocusIndex, openNestedIndex, handleListKeyDown, resetNestedIndex, resetActiveFocusIndex, setActiveFocusIndex, } = useKeyboardNavigation({
48
+ ids,
49
+ expandedIds,
50
+ parentRef: listRef,
51
+ btnRef,
52
+ itemRefs,
53
+ });
54
+ const isActive = listRef.current === document.activeElement && activeFocusIndex === -1 && openNestedIndex === -1;
55
+ return (
56
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
57
+ // @ts-ignore
58
+ _jsx(SelectionProvider, Object.assign({}, extractSelectionProps(props), { children: _jsx(ParentListContext.Provider, { value: {
59
+ parentIds: ids,
60
+ parentActiveFocusIndex: activeFocusIndex,
61
+ parentExpandedIds: expandedIds,
62
+ parentItemRefs: itemRefs,
63
+ parentOpenNestedIndex: openNestedIndex,
64
+ triggerRef: triggerRef !== null && triggerRef !== void 0 ? triggerRef : listRef,
65
+ parentRef: listRef,
66
+ parentSetActiveFocusIndex: setActiveFocusIndex,
67
+ parentResetNestedIndex: resetNestedIndex,
68
+ parentResetActiveFocusIndex: resetActiveFocusIndex,
69
+ openCollapsedItems,
70
+ toggleOpenCollapsedItems: id => setOpenCollapsedItems(items => items.includes(id) ? items.filter(item => item !== id) : items.concat([id])),
71
+ }, children: _jsxs("div", { className: styles.wrapper, "data-active": isActive || undefined, children: [_jsx(ListPrivate, Object.assign({}, props, slicedItems, { ref: listRef, onFocus: e => {
72
+ if (e.relatedTarget === null ||
73
+ (e.relatedTarget && itemRefs.every(({ current }) => current !== e.relatedTarget))) {
74
+ resetActiveFocusIndex();
75
+ }
76
+ }, onKeyDown: handleListKeyDown, tabIndex: 0, search: search, nested: false })), _jsx(HiddenTabButton, { ref: btnRef, listRef: listRef })] }) }) })));
77
+ });
@@ -0,0 +1 @@
1
+ export * from './List';
@@ -0,0 +1 @@
1
+ export * from './List';
@@ -0,0 +1,22 @@
1
+ import { RefObject } from 'react';
2
+ export declare const ListPrivate: import("react").ForwardRefExoticComponent<{
3
+ 'data-test-id'?: string | undefined;
4
+ } & import("react").AriaAttributes & {
5
+ items: import("../../Items").ItemProps[];
6
+ pinTop?: import("../../Items").ItemProps[] | undefined;
7
+ pinBottom?: import("../../Items").ItemProps[] | undefined;
8
+ footer?: import("react").ReactNode;
9
+ search?: import("../../../types").SearchState | undefined;
10
+ loading?: boolean | undefined;
11
+ noData?: string | undefined;
12
+ noResults?: string | undefined;
13
+ footerActiveElementsRefs?: RefObject<HTMLElement>[] | undefined;
14
+ } & Pick<import("../contexts").SelectionProviderProps, "value" | "defaultValue" | "selection" | "onChange"> & import("../contexts").ListContextType & import("../../../types").ScrollProps & {
15
+ nested?: boolean | undefined;
16
+ active?: boolean | undefined;
17
+ tabIndex?: number | undefined;
18
+ onFocus?(e: import("react").FocusEvent<HTMLElement, Element>): void;
19
+ onBlur?(e: import("react").FocusEvent<HTMLElement, Element>): void;
20
+ onKeyDown?(e: import("react").KeyboardEvent<HTMLElement>): void;
21
+ collapse?: "single" | "multiple" | undefined;
22
+ } & import("react").RefAttributes<HTMLElement>>;
@@ -0,0 +1,41 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
13
+ import cn from 'classnames';
14
+ import { forwardRef, useMemo } from 'react';
15
+ import { Spinner } from '@snack-uikit/loaders';
16
+ import { Scroll } from '@snack-uikit/scroll';
17
+ import { ToggleGroup } from '@snack-uikit/toggles';
18
+ import { extractSupportProps } from '@snack-uikit/utils';
19
+ import { PinBottomGroupItem, PinTopGroupItem, SearchItem, useRenderItems } from '../../Items';
20
+ import { ListContextProvider } from '../contexts';
21
+ import commonStyles from '../styles.module.css';
22
+ import styles from './styles.module.css';
23
+ export const ListPrivate = forwardRef((_a, ref) => {
24
+ var _b, _c;
25
+ var { items, pinTop, pinBottom, collapse = 'multiple', onKeyDown, onBlur, onFocus, tabIndex, active, scroll, nested, search, scrollRef, scrollContainerRef, footer, loading, noData = 'No data', noResults = 'No results', size = 's', marker } = _a, props = __rest(_a, ["items", "pinTop", "pinBottom", "collapse", "onKeyDown", "onBlur", "onFocus", "tabIndex", "active", "scroll", "nested", "search", "scrollRef", "scrollContainerRef", "footer", "loading", "noData", "noResults", "size", "marker"]);
26
+ const itemsJSX = useRenderItems(items);
27
+ const itemsPinTopJSX = useRenderItems(pinTop !== null && pinTop !== void 0 ? pinTop : []);
28
+ const itemsPinBottomJSX = useRenderItems(pinBottom !== null && pinBottom !== void 0 ? pinBottom : []);
29
+ const hasNoItems = items.length + ((_b = pinTop === null || pinTop === void 0 ? void 0 : pinTop.length) !== null && _b !== void 0 ? _b : 0) + ((_c = pinBottom === null || pinBottom === void 0 ? void 0 : pinBottom.length) !== null && _c !== void 0 ? _c : 0) === 0;
30
+ const loadingJSX = useMemo(() => loading && (_jsx("div", { role: 'spinbutton', tabIndex: -1, className: styles.loader, "data-size": size, "data-no-items": hasNoItems || undefined, "data-test-id": 'list__loader', children: _jsx(Spinner, { size: size === 'l' ? 's' : 'xs' }) })), [hasNoItems, loading, size]);
31
+ const content = useMemo(() => (_jsxs(_Fragment, { children: [itemsJSX, loadingJSX, hasNoItems && !(search === null || search === void 0 ? void 0 : search.value) && !loading && (_jsx("div", { className: commonStyles.infoBlock, "data-test-id": 'list__no-data', children: noData })), hasNoItems && (search === null || search === void 0 ? void 0 : search.value) && !loading && (_jsx("div", { className: commonStyles.infoBlock, "data-test-id": 'list__no-results', children: noResults }))] })), [hasNoItems, itemsJSX, loading, loadingJSX, noData, noResults, search === null || search === void 0 ? void 0 : search.value]);
32
+ const listJSX = (_jsx("ul", Object.assign({ className: commonStyles.listContainer, ref: ref, onKeyDown: onKeyDown, tabIndex: tabIndex, onFocus: !nested ? onFocus : undefined, onBlur: onBlur, "data-active": active || undefined, role: 'menu' }, extractSupportProps(props), { children: _jsxs(ToggleGroup, { selectionMode: collapse, children: [(Number(pinTop === null || pinTop === void 0 ? void 0 : pinTop.length) > 0 || search) && (_jsxs(PinTopGroupItem, { children: [search && _jsx(SearchItem, { search: search }), Number(pinTop === null || pinTop === void 0 ? void 0 : pinTop.length) > 0 && itemsPinTopJSX] })), scroll ? (_jsxs(Scroll, { className: cn({
33
+ [commonStyles.scrollContainerS]: scroll && size === 's',
34
+ [commonStyles.scrollContainerM]: scroll && size === 'm',
35
+ [commonStyles.scrollContainerL]: scroll && size === 'l',
36
+ }), barHideStrategy: 'never', size: 's', ref: scrollContainerRef, children: [content, _jsx("div", { className: styles.scrollStub, ref: scrollRef })] })) : (_jsx(_Fragment, { children: content })), (Number(pinBottom === null || pinBottom === void 0 ? void 0 : pinBottom.length) > 0 || footer) && (_jsxs(PinBottomGroupItem, { children: [Number(pinBottom === null || pinBottom === void 0 ? void 0 : pinBottom.length) > 0 && itemsPinBottomJSX, footer && _jsx("div", { className: styles.footer, children: footer })] }))] }) })));
37
+ if (!nested) {
38
+ return (_jsx(ListContextProvider, { size: size, marker: marker, children: listJSX }));
39
+ }
40
+ return (_jsx("li", { style: { listStyleType: 'none' }, role: 'menuitem', children: listJSX }));
41
+ });
@@ -0,0 +1 @@
1
+ export * from './ListPrivate';
@@ -0,0 +1 @@
1
+ export * from './ListPrivate';
@@ -0,0 +1,46 @@
1
+ .loader{
2
+ display:flex;
3
+ align-items:center;
4
+ justify-content:center;
5
+ }
6
+ .loader[data-size=s]{
7
+ height:var(--dimension-3m, 24px);
8
+ }
9
+ .loader[data-size=s][data-no-items]{
10
+ height:calc(3 * var(--dimension-3m, 24px));
11
+ }
12
+ .loader[data-size=m]{
13
+ height:var(--dimension-4m, 32px);
14
+ }
15
+ .loader[data-size=m][data-no-items]{
16
+ height:calc(3 * var(--dimension-4m, 32px));
17
+ }
18
+ .loader[data-size=l]{
19
+ height:var(--dimension-5m, 40px);
20
+ }
21
+ .loader[data-size=l][data-no-items]{
22
+ height:calc(3 * var(--dimension-5m, 40px));
23
+ }
24
+ .loader:focus-visible{
25
+ outline-width:var(--border-state-focus-s-border-width, 2px);
26
+ outline-style:var(--border-state-focus-s-border-style, solid);
27
+ outline-color:var(--border-state-focus-s-border-color, );
28
+ outline-offset:calc(var(--border-state-focus-s-border-width, 2px) * -1);
29
+ outline-color:var(--sys-available-complementary, #131313);
30
+ }
31
+
32
+ .scrollStub{
33
+ height:calc(var(--dimension-025m, 2px) / 2);
34
+ margin-top:calc(var(--dimension-025m, 2px) / -2);
35
+ background:transparent;
36
+ }
37
+
38
+ .footer{
39
+ display:flex;
40
+ flex-direction:column;
41
+ gap:var(--dimension-050m, 4px);
42
+ align-items:center;
43
+ justify-content:center;
44
+ box-sizing:border-box;
45
+ padding:var(--dimension-050m, 4px);
46
+ }
@@ -0,0 +1,6 @@
1
+ /// <reference types="react" />
2
+ export type CollapseContextType = {
3
+ level?: number;
4
+ };
5
+ export declare const CollapseContext: import("react").Context<CollapseContextType>;
6
+ export declare const useCollapseContext: () => CollapseContextType;
@@ -0,0 +1,3 @@
1
+ import { createContext, useContext } from 'react';
2
+ export const CollapseContext = createContext({});
3
+ export const useCollapseContext = () => useContext(CollapseContext);
@@ -0,0 +1,12 @@
1
+ import { ReactNode } from 'react';
2
+ export type ListContextType = {
3
+ size?: 's' | 'm' | 'l';
4
+ marker?: boolean;
5
+ };
6
+ type Child = {
7
+ children: ReactNode;
8
+ };
9
+ export declare const ListContext: import("react").Context<ListContextType>;
10
+ export declare const useListContext: () => ListContextType;
11
+ export declare function ListContextProvider({ children, ...props }: ListContextType & Child): import("react/jsx-runtime").JSX.Element;
12
+ export {};
@@ -0,0 +1,22 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { jsx as _jsx } from "react/jsx-runtime";
13
+ import { createContext, useContext } from 'react';
14
+ export const ListContext = createContext({});
15
+ export const useListContext = () => useContext(ListContext);
16
+ function extractListProps({ size, marker }) {
17
+ return { size, marker };
18
+ }
19
+ export function ListContextProvider(_a) {
20
+ var { children } = _a, props = __rest(_a, ["children"]);
21
+ return _jsx(ListContext.Provider, { value: extractListProps(props), children: children });
22
+ }
@@ -0,0 +1,18 @@
1
+ import { RefObject } from 'react';
2
+ export type ParentListContextType = {
3
+ parentActiveFocusIndex: number;
4
+ parentSetActiveFocusIndex?(idx: number): void;
5
+ parentResetActiveFocusIndex?(): void;
6
+ parentIds: Array<string | number>;
7
+ parentExpandedIds: Array<string | number>;
8
+ parentItemRefs: Array<RefObject<HTMLButtonElement>>;
9
+ parentOpenNestedIndex: number;
10
+ parentResetNestedIndex?(): void;
11
+ openCollapsedItems?: Array<string | number>;
12
+ toggleOpenCollapsedItems?(id: string | number): void;
13
+ triggerRef?: RefObject<HTMLElement>;
14
+ parentRef?: RefObject<HTMLElement>;
15
+ };
16
+ export declare const ParentListContext: import("react").Context<ParentListContextType>;
17
+ export declare const useParentListContext: () => ParentListContextType;
18
+ export declare function ParentListProvider(): null;
@@ -0,0 +1,12 @@
1
+ import { createContext, useContext } from 'react';
2
+ export const ParentListContext = createContext({
3
+ parentActiveFocusIndex: -1,
4
+ parentOpenNestedIndex: -1,
5
+ parentIds: [],
6
+ parentExpandedIds: [],
7
+ parentItemRefs: [],
8
+ });
9
+ export const useParentListContext = () => useContext(ParentListContext);
10
+ export function ParentListProvider() {
11
+ return null;
12
+ }
@@ -0,0 +1,53 @@
1
+ import { ReactNode } from 'react';
2
+ type SelectionSingleValueType = string | number | undefined;
3
+ export type SelectionSingleProps = {
4
+ /** Начальное состояние */
5
+ defaultValue?: SelectionSingleValueType;
6
+ /** Controlled состояние */
7
+ value?: SelectionSingleValueType;
8
+ /** Controlled обработчик измения состояния */
9
+ onChange?(value: any): void;
10
+ setValue?(value: any): void;
11
+ /** Режим выбора */
12
+ selection: 'single';
13
+ /** Режим выбора single */
14
+ isSelectionSingle: true;
15
+ /** Режим выбора multi */
16
+ isSelectionMultiple: false;
17
+ };
18
+ export type SelectionMultipleProps = {
19
+ /** Начальное состояние */
20
+ defaultValue?: SelectionSingleValueType[];
21
+ /** Controlled состояние */
22
+ value?: SelectionSingleValueType[];
23
+ /** Controlled обработчик измения состояния */
24
+ onChange?(value: any): void;
25
+ setValue?(value: any): void;
26
+ /** Режим выбора */
27
+ selection: 'multiple';
28
+ /** Режим выбора single */
29
+ isSelectionSingle: false;
30
+ /** Режим выбора multi */
31
+ isSelectionMultiple: true;
32
+ };
33
+ type SelectionNoneProps = {
34
+ selection?: undefined;
35
+ value?: undefined;
36
+ onChange?: undefined;
37
+ setValue?: undefined;
38
+ defaultValue?: undefined;
39
+ isSelectionSingle?: undefined;
40
+ isSelectionMultiple?: undefined;
41
+ };
42
+ export type SelectionProviderProps = SelectionSingleProps | SelectionMultipleProps | SelectionNoneProps;
43
+ type SelectionContextType = Omit<SelectionNoneProps, 'defaultValue'> | Omit<SelectionSingleProps, 'defaultValue'> | Omit<SelectionMultipleProps, 'defaultValue'>;
44
+ export declare const SelectionContext: import("react").Context<SelectionContextType>;
45
+ export declare function isSelectionMultipleProps(props: any): props is SelectionMultipleProps;
46
+ export declare function isSelectionSingleProps(props: any): props is SelectionSingleProps;
47
+ type Child = {
48
+ children: ReactNode;
49
+ };
50
+ export declare function SelectionProvider(props: SelectionProviderProps & Child): import("react/jsx-runtime").JSX.Element;
51
+ export declare const useSelectionContext: () => SelectionContextType;
52
+ export declare function extractSelectionProps<T extends SelectionProviderProps>({ selection, value, defaultValue, onChange, }: T): SelectionProviderProps;
53
+ export {};
@@ -0,0 +1,61 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, useCallback, useContext } from 'react';
3
+ import { useUncontrolledProp } from 'uncontrollable';
4
+ export const SelectionContext = createContext({
5
+ value: undefined,
6
+ onChange: undefined,
7
+ selection: undefined,
8
+ });
9
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
+ export function isSelectionMultipleProps(props) {
11
+ return 'selection' in props && props['selection'] === 'multiple';
12
+ }
13
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
+ export function isSelectionSingleProps(props) {
15
+ return 'selection' in props && props['selection'] === 'single';
16
+ }
17
+ function SelectionSingleProvider({ value: valueProp, defaultValue, onChange: onChangeProp, children, }) {
18
+ const [value, setValue] = useUncontrolledProp(valueProp, defaultValue, cb => {
19
+ onChangeProp === null || onChangeProp === void 0 ? void 0 : onChangeProp(cb(value));
20
+ });
21
+ const onChange = useCallback((newValue) => setValue((oldValue) => {
22
+ if (newValue !== oldValue) {
23
+ return newValue;
24
+ }
25
+ return undefined;
26
+ }), [setValue]);
27
+ return (_jsx(SelectionContext.Provider, { value: { value, onChange, selection: 'single', isSelectionSingle: true, isSelectionMultiple: false, setValue }, children: children }));
28
+ }
29
+ function SelectionMultipleProvider({ value: valueProp, defaultValue, onChange: onChangeProp, children, }) {
30
+ const [value, setValue] = useUncontrolledProp(valueProp, defaultValue, cb => {
31
+ onChangeProp === null || onChangeProp === void 0 ? void 0 : onChangeProp(cb(value));
32
+ });
33
+ const onChange = useCallback((newValue) => setValue((oldValues) => {
34
+ if (Array.isArray(oldValues)) {
35
+ if (oldValues.includes(newValue)) {
36
+ return oldValues.filter(oldValue => oldValue !== newValue);
37
+ }
38
+ return oldValues.concat(newValue);
39
+ }
40
+ return undefined;
41
+ }), [setValue]);
42
+ return (_jsx(SelectionContext.Provider, { value: { value, onChange, selection: 'multiple', isSelectionSingle: false, isSelectionMultiple: true, setValue }, children: children }));
43
+ }
44
+ export function SelectionProvider(props) {
45
+ if (isSelectionSingleProps(props)) {
46
+ return _jsx(SelectionSingleProvider, Object.assign({}, props));
47
+ }
48
+ if (isSelectionMultipleProps(props)) {
49
+ return _jsx(SelectionMultipleProvider, Object.assign({}, props));
50
+ }
51
+ return _jsx(SelectionContext.Provider, { value: {}, children: props.children });
52
+ }
53
+ export const useSelectionContext = () => useContext(SelectionContext);
54
+ export function extractSelectionProps({ selection, value, defaultValue, onChange, }) {
55
+ return {
56
+ selection,
57
+ value,
58
+ defaultValue,
59
+ onChange,
60
+ };
61
+ }
@@ -0,0 +1,4 @@
1
+ export * from './ListProvider';
2
+ export * from './SelectionProvider';
3
+ export * from './ParentListProvider';
4
+ export * from './CollapseProvider';
@@ -0,0 +1,4 @@
1
+ export * from './ListProvider';
2
+ export * from './SelectionProvider';
3
+ export * from './ParentListProvider';
4
+ export * from './CollapseProvider';
@@ -0,0 +1,16 @@
1
+ import { KeyboardEvent, RefObject } from 'react';
2
+ export type UseKeyboardNavigationProps<T extends HTMLElement> = {
3
+ ids: Array<number | string>;
4
+ expandedIds: Array<number | string>;
5
+ parentRef?: RefObject<T>;
6
+ btnRef?: RefObject<HTMLButtonElement>;
7
+ itemRefs?: RefObject<HTMLButtonElement>[];
8
+ };
9
+ export declare function useKeyboardNavigation<T extends HTMLElement>({ ids, itemRefs, expandedIds, parentRef, btnRef, }: UseKeyboardNavigationProps<T>): {
10
+ activeFocusIndex: number;
11
+ setActiveFocusIndex: import("react").Dispatch<import("react").SetStateAction<number>>;
12
+ openNestedIndex: number;
13
+ resetNestedIndex: () => void;
14
+ resetActiveFocusIndex: () => void;
15
+ handleListKeyDown: (e: KeyboardEvent<T>) => void;
16
+ };
@@ -0,0 +1,73 @@
1
+ import { useEffect, useState } from 'react';
2
+ export function useKeyboardNavigation({ ids, itemRefs, expandedIds, parentRef, btnRef, }) {
3
+ const [activeFocusIndex, setActiveFocusIndex] = useState(-1);
4
+ const [openNestedIndex, setOpenNestedIndex] = useState(-1);
5
+ const handleListKeyDown = (e) => {
6
+ var _a, _b, _c, _d;
7
+ switch (e.key) {
8
+ case 'ArrowDown': {
9
+ setActiveFocusIndex(activeIndex => Math.min(activeIndex + 1, ids.length - 1));
10
+ // TODO: go to loader from last item
11
+ // if (activeFocusIndex === ids.length - 2) {
12
+ // return;
13
+ // }
14
+ e.stopPropagation();
15
+ e.preventDefault();
16
+ return;
17
+ }
18
+ case 'ArrowUp': {
19
+ if (activeFocusIndex === 0) {
20
+ (_a = parentRef === null || parentRef === void 0 ? void 0 : parentRef.current) === null || _a === void 0 ? void 0 : _a.focus();
21
+ setActiveFocusIndex(-1);
22
+ return;
23
+ }
24
+ setActiveFocusIndex(activeIndex => Math.max(activeIndex - 1, 0));
25
+ e.stopPropagation();
26
+ e.preventDefault();
27
+ return;
28
+ }
29
+ case 'ArrowRight': {
30
+ if (expandedIds.includes(ids[activeFocusIndex])) {
31
+ setOpenNestedIndex(activeFocusIndex);
32
+ }
33
+ e.stopPropagation();
34
+ e.preventDefault();
35
+ return;
36
+ }
37
+ case 'Tab': {
38
+ if (parentRef && activeFocusIndex !== -1) {
39
+ e.preventDefault();
40
+ (_b = parentRef === null || parentRef === void 0 ? void 0 : parentRef.current) === null || _b === void 0 ? void 0 : _b.focus();
41
+ }
42
+ else if (activeFocusIndex === -1) {
43
+ btnRef && !e.shiftKey ? (_c = btnRef === null || btnRef === void 0 ? void 0 : btnRef.current) === null || _c === void 0 ? void 0 : _c.focus() : (_d = parentRef === null || parentRef === void 0 ? void 0 : parentRef.current) === null || _d === void 0 ? void 0 : _d.focus();
44
+ }
45
+ setOpenNestedIndex(-1);
46
+ setActiveFocusIndex(-1);
47
+ return;
48
+ }
49
+ default: {
50
+ return;
51
+ }
52
+ }
53
+ };
54
+ const resetNestedIndex = () => {
55
+ setActiveFocusIndex(openNestedIndex);
56
+ setOpenNestedIndex(-1);
57
+ };
58
+ const resetActiveFocusIndex = () => {
59
+ setActiveFocusIndex(-1);
60
+ };
61
+ useEffect(() => {
62
+ var _a, _b;
63
+ activeFocusIndex !== -1 && openNestedIndex === -1 && ((_b = (_a = itemRefs === null || itemRefs === void 0 ? void 0 : itemRefs[activeFocusIndex]) === null || _a === void 0 ? void 0 : _a.current) === null || _b === void 0 ? void 0 : _b.focus());
64
+ }, [activeFocusIndex, itemRefs, openNestedIndex]);
65
+ return {
66
+ activeFocusIndex,
67
+ setActiveFocusIndex,
68
+ openNestedIndex,
69
+ resetNestedIndex,
70
+ resetActiveFocusIndex,
71
+ handleListKeyDown,
72
+ };
73
+ }
@@ -0,0 +1,4 @@
1
+ export * from './Droplist';
2
+ export * from './List';
3
+ export type { ListProps, DroplistProps } from './types';
4
+ export type { SelectionSingleProps, SelectionMultipleProps, isSelectionSingleProps, isSelectionMultipleProps, } from './contexts';
@@ -0,0 +1,2 @@
1
+ export * from './Droplist';
2
+ export * from './List';