@snack-uikit/list 0.2.2-preview-0cc330d4.0 → 0.3.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/CHANGELOG.md +11 -0
- package/dist/components/Items/AccordionItem/AccordionItem.js +1 -1
- package/dist/components/Items/BaseItem/BaseItem.js +1 -1
- package/dist/components/Items/BaseItem/styles.module.css +5 -2
- package/dist/components/Items/NextListItem/NextListItem.js +12 -12
- package/dist/components/Items/NextListItem/hooks.d.ts +2 -2
- package/dist/components/Items/types.d.ts +5 -5
- package/dist/components/Lists/contexts/ParentListProvider.d.ts +1 -1
- package/dist/components/Lists/hooks.d.ts +1 -1
- package/dist/utils.d.ts +2 -2
- package/package.json +2 -2
- package/src/components/Items/AccordionItem/AccordionItem.tsx +21 -23
- package/src/components/Items/BaseItem/BaseItem.tsx +59 -59
- package/src/components/Items/BaseItem/styles.module.scss +1 -0
- package/src/components/Items/NextListItem/NextListItem.tsx +48 -50
- package/src/components/Items/NextListItem/hooks.ts +2 -2
- package/src/components/Items/types.ts +5 -5
- package/src/components/Items/utils.ts +2 -2
- package/src/components/Lists/List/List.tsx +2 -2
- package/src/components/Lists/contexts/ParentListProvider.tsx +1 -1
- package/src/components/Lists/hooks.ts +1 -1
- package/src/utils.ts +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# 0.3.0 (2024-02-07)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* **FF-4241:** add itemWrapRender ([4efb798](https://github.com/cloud-ru-tech/snack-uikit/commit/4efb79897b8ef129e89bf62a9332b93d79648bbf))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
6
17
|
## 0.2.1 (2024-02-05)
|
|
7
18
|
|
|
8
19
|
### Only dependencies have been changed
|
|
@@ -37,5 +37,5 @@ export function AccordionItem(_a) {
|
|
|
37
37
|
toggleOpenCollapsedItems === null || toggleOpenCollapsedItems === void 0 ? void 0 : toggleOpenCollapsedItems(id !== null && id !== void 0 ? id : '');
|
|
38
38
|
(_a = option.onClick) === null || _a === void 0 ? void 0 : _a.call(option, e);
|
|
39
39
|
};
|
|
40
|
-
return (_jsx(
|
|
40
|
+
return (_jsx(CollapseBlockPrivate, { header: _jsx(BaseItem, Object.assign({}, option, { id: id, disabled: disabled, expandIcon: open ? _jsx(ChevronUpSVG, {}) : _jsx(ChevronDownSVG, {}), onClick: handleItemClick, isParentNode: true, onKeyDown: handleKeyDown, indeterminate: isIndeterminate && !checked, onSelect: !disabled ? handleOnSelect : undefined })), expanded: open, "data-test-id": `list__accordion-item-${id}`, children: _jsx(CollapseContext.Provider, { value: { level: level + 1 }, children: itemsJSX }) }));
|
|
41
41
|
}
|
|
@@ -68,7 +68,7 @@ export function BaseItem(_a) {
|
|
|
68
68
|
e.stopPropagation();
|
|
69
69
|
};
|
|
70
70
|
const props = extractSupportProps(rest);
|
|
71
|
-
const item = (
|
|
71
|
+
const item = (_jsxs("li", { role: 'menuitem', "data-test-id": props['data-test-id'] || 'list__base-item_' + id, ref: itemRef, className: cn(commonStyles.listItem, styles.droplistItem, className), "data-size": size, onClick: handleItemClick, tabIndex: -1, "data-non-pointer": inactive && !onClick, "data-inactive": inactive || undefined, "data-checked": (isParentNode && (indeterminate || isChecked)) || (isChecked && !switchProp) || undefined, "data-variant": mode || undefined, "data-open": open || undefined, "aria-disabled": disabled || undefined, onKeyDown: handleItemKeyDown, onFocus: handleItemFocus, style: { '--level': level }, children: [!switchProp && isSelectionSingle && marker && !isParentNode && interactive && (_jsx("div", { className: styles.markerContainer, "data-test-id": 'list__base-item-marker' })), !switchProp && isSelectionMultiple && interactive && (_jsx("div", { className: styles.checkbox, children: _jsx(Checkbox, { size: CHECKBOX_SIZE_MAP[size !== null && size !== void 0 ? size : 's'], disabled: disabled, tabIndex: -1, onChange: handleCheckboxChange, checked: isChecked, "data-test-id": 'list__base-item-checkbox', onClick: handleCheckboxClick, indeterminate: indeterminate }) })), beforeContent && _jsx("div", { className: styles.beforeContent, children: beforeContent }), _jsxs("div", { className: styles.content, children: [_jsxs("div", { className: styles.headline, children: [_jsx("span", { className: styles.option, children: _jsx(TruncateString, { text: option, maxLines: 1 }) }), caption && _jsx("span", { className: styles.caption, children: caption })] }), description && (_jsx("div", { className: styles.description, children: _jsx(TruncateString, { text: description, maxLines: 2 }) }))] }), afterContent, switchProp && interactive && (_jsx(Switch, { disabled: disabled, checked: isChecked, "data-test-id": 'list__base-item-switch' })), !switchProp && expandIcon && _jsx("span", { className: styles.expandableIcon, children: expandIcon })] }));
|
|
72
72
|
if (!itemWrapRender) {
|
|
73
73
|
return item;
|
|
74
74
|
}
|
|
@@ -173,13 +173,16 @@
|
|
|
173
173
|
.droplistItem[data-non-pointer]{
|
|
174
174
|
cursor:inherit;
|
|
175
175
|
}
|
|
176
|
-
.droplistItem
|
|
176
|
+
.droplistItem[aria-disabled] .option,
|
|
177
|
+
.droplistItem[aria-disabled] .description,
|
|
178
|
+
.droplistItem[aria-disabled] .caption,
|
|
179
|
+
.droplistItem[aria-disabled] .expandableIcon, .droplistItem:disabled .option,
|
|
177
180
|
.droplistItem:disabled .description,
|
|
178
181
|
.droplistItem:disabled .caption,
|
|
179
182
|
.droplistItem:disabled .expandableIcon{
|
|
180
183
|
color:var(--sys-neutral-text-disabled, #9e9e9e);
|
|
181
184
|
}
|
|
182
|
-
.droplistItem:disabled .beforeContent{
|
|
185
|
+
.droplistItem[aria-disabled] .beforeContent, .droplistItem:disabled .beforeContent{
|
|
183
186
|
opacity:var(--opacity-a064, 0.64);
|
|
184
187
|
}
|
|
185
188
|
.droplistItem[data-has-checked][data-variant=single]::after, .droplistItem[data-checked][data-variant=single]::after{
|
|
@@ -51,16 +51,16 @@ export function NextListItem(_a) {
|
|
|
51
51
|
parentResetActiveFocusIndex === null || parentResetActiveFocusIndex === void 0 ? void 0 : parentResetActiveFocusIndex();
|
|
52
52
|
return true;
|
|
53
53
|
}, [parentResetActiveFocusIndex, parentResetNestedIndex]);
|
|
54
|
-
return (_jsx(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
54
|
+
return (_jsx(Dropdown, { outsideClick: handleOutsideClick, fallbackPlacements: FALLBACK_PLACEMENTS, content: _jsx(ParentListContext.Provider, { value: {
|
|
55
|
+
parentIds: ids,
|
|
56
|
+
parentActiveFocusIndex: activeFocusIndex,
|
|
57
|
+
parentExpandedIds: expandedIds,
|
|
58
|
+
parentItemRefs: itemRefs,
|
|
59
|
+
parentOpenNestedIndex: openNestedIndex,
|
|
60
|
+
triggerRef,
|
|
61
|
+
parentRef: listRef,
|
|
62
|
+
parentResetNestedIndex: resetNestedIndex,
|
|
63
|
+
parentResetActiveFocusIndex: resetActiveFocusIndex,
|
|
64
|
+
toggleOpenCollapsedItems: id => setOpenCollapsedItems(items => items.includes(id) ? items.filter(item => item !== id) : items.concat([id])),
|
|
65
|
+
}, children: _jsx(ListPrivate, { onKeyDown: handleListKeyDown, items: items, nested: true, search: search, scroll: scroll, scrollRef: scrollRef, limitedScrollHeight: true }) }), trigger: 'hover', open: (open || parentIds[parentOpenNestedIndex] === id) && !disabled, onOpenChange: handleOpenChange, placement: placement, children: _jsx(BaseItem, Object.assign({}, option, { disabled: disabled, open: open, expandIcon: _jsx(ChevronRightSVG, {}), id: id, isParentNode: true, indeterminate: isIndeterminate && !checked, onSelect: handleOnSelect })) }));
|
|
66
66
|
}
|
|
@@ -2,7 +2,7 @@ import { KeyboardEvent, RefObject } from 'react';
|
|
|
2
2
|
type UseKeyboardNavigationProps = {
|
|
3
3
|
ids: Array<number | string>;
|
|
4
4
|
expandedIds: Array<number | string>;
|
|
5
|
-
itemRefs?: RefObject<
|
|
5
|
+
itemRefs?: RefObject<HTMLElement>[];
|
|
6
6
|
id?: string | number;
|
|
7
7
|
};
|
|
8
8
|
export declare function useKeyboardNavigation({ ids, expandedIds, itemRefs, id }: UseKeyboardNavigationProps): {
|
|
@@ -12,7 +12,7 @@ export declare function useKeyboardNavigation({ ids, expandedIds, itemRefs, id }
|
|
|
12
12
|
setOpenNestedIndex: import("react").Dispatch<import("react").SetStateAction<number>>;
|
|
13
13
|
resetNestedIndex: () => void;
|
|
14
14
|
resetActiveFocusIndex: () => void;
|
|
15
|
-
handleListKeyDown: (e: KeyboardEvent<
|
|
15
|
+
handleListKeyDown: (e: KeyboardEvent<HTMLElement>) => void;
|
|
16
16
|
open: boolean;
|
|
17
17
|
setOpen: import("react").Dispatch<import("react").SetStateAction<boolean>>;
|
|
18
18
|
};
|
|
@@ -25,18 +25,18 @@ export type BaseItemProps = WithSupportProps<{
|
|
|
25
25
|
/** Основной контент айтема */
|
|
26
26
|
content: ItemContentProps;
|
|
27
27
|
/** Колбек обработки клика */
|
|
28
|
-
onClick?(e: MouseEvent<
|
|
28
|
+
onClick?(e: MouseEvent<HTMLElement>): void;
|
|
29
29
|
/** Колбек обработки нажатия клавиши */
|
|
30
|
-
onKeyDown?(e: KeyboardEvent<
|
|
30
|
+
onKeyDown?(e: KeyboardEvent<HTMLElement>): void;
|
|
31
31
|
/** Колбек обработки фокуса */
|
|
32
|
-
onFocus?(e: FocusEvent<
|
|
32
|
+
onFocus?(e: FocusEvent<HTMLElement>): void;
|
|
33
33
|
/** Колбек обработки блюра */
|
|
34
|
-
onBlur?(e: FocusEvent<
|
|
34
|
+
onBlur?(e: FocusEvent<HTMLElement>): void;
|
|
35
35
|
/** Уникальный идентификатор */
|
|
36
36
|
id?: string | number;
|
|
37
37
|
/** Флаг неактивности элемента */
|
|
38
38
|
disabled?: boolean;
|
|
39
|
-
itemRef?: RefObject<
|
|
39
|
+
itemRef?: RefObject<HTMLElement>;
|
|
40
40
|
className?: string;
|
|
41
41
|
/**
|
|
42
42
|
* Флаг отображения отключения реакции на любое css состояние (hover/focus и тд)
|
|
@@ -5,7 +5,7 @@ export type ParentListContextType = {
|
|
|
5
5
|
parentResetActiveFocusIndex?(): void;
|
|
6
6
|
parentIds: Array<string | number>;
|
|
7
7
|
parentExpandedIds: Array<string | number>;
|
|
8
|
-
parentItemRefs: Array<RefObject<
|
|
8
|
+
parentItemRefs: Array<RefObject<HTMLElement>>;
|
|
9
9
|
parentOpenNestedIndex: number;
|
|
10
10
|
parentResetNestedIndex?(): void;
|
|
11
11
|
openCollapsedItems?: Array<string | number>;
|
|
@@ -4,7 +4,7 @@ export type UseKeyboardNavigationProps<T extends HTMLElement> = {
|
|
|
4
4
|
expandedIds: Array<number | string>;
|
|
5
5
|
parentRef?: RefObject<T>;
|
|
6
6
|
btnRef?: RefObject<HTMLButtonElement>;
|
|
7
|
-
itemRefs?: RefObject<
|
|
7
|
+
itemRefs?: RefObject<HTMLElement>[];
|
|
8
8
|
};
|
|
9
9
|
export declare function useKeyboardNavigation<T extends HTMLElement>({ ids, itemRefs, expandedIds, parentRef, btnRef, }: UseKeyboardNavigationProps<T>): {
|
|
10
10
|
activeFocusIndex: number;
|
package/dist/utils.d.ts
CHANGED
|
@@ -6,11 +6,11 @@ type WithCollapsedItemsProps = {
|
|
|
6
6
|
};
|
|
7
7
|
export declare function withCollapsedItems({ items, openCollapsedItems }: WithCollapsedItemsProps): {
|
|
8
8
|
items: ItemProps[];
|
|
9
|
-
itemRefs: RefObject<
|
|
9
|
+
itemRefs: RefObject<HTMLElement>[];
|
|
10
10
|
ids: (string | number)[];
|
|
11
11
|
expandedIds: (string | number)[];
|
|
12
12
|
};
|
|
13
|
-
export declare function extractItemRefs(items: ItemProps[]): RefObject<
|
|
13
|
+
export declare function extractItemRefs(items: ItemProps[]): RefObject<HTMLElement>[];
|
|
14
14
|
export declare function extractItemIds(items: ItemProps[]): Array<string | number>;
|
|
15
15
|
export declare function extractChildIds({ items }: {
|
|
16
16
|
items: ItemProps[];
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
6
|
"title": "List",
|
|
7
|
-
"version": "0.
|
|
7
|
+
"version": "0.3.0",
|
|
8
8
|
"sideEffects": [
|
|
9
9
|
"*.css",
|
|
10
10
|
"*.woff",
|
|
@@ -45,5 +45,5 @@
|
|
|
45
45
|
"merge-refs": "1.2.2",
|
|
46
46
|
"uncontrollable": "8.0.4"
|
|
47
47
|
},
|
|
48
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "88a44a8f4c6490f3004f7feac3d50d17ff03f31c"
|
|
49
49
|
}
|
|
@@ -16,7 +16,7 @@ export function AccordionItem({ items: itemsProp, id, disabled, ...option }: Acc
|
|
|
16
16
|
|
|
17
17
|
const { isChecked: open, handleClick: handleChange } = useToggleGroup({ value: String(id) });
|
|
18
18
|
|
|
19
|
-
const handleKeyDown = (e: KeyboardEvent<
|
|
19
|
+
const handleKeyDown = (e: KeyboardEvent<HTMLElement>) => {
|
|
20
20
|
if (e.key === 'ArrowRight') {
|
|
21
21
|
handleChange();
|
|
22
22
|
toggleOpenCollapsedItems?.(id ?? '');
|
|
@@ -28,33 +28,31 @@ export function AccordionItem({ items: itemsProp, id, disabled, ...option }: Acc
|
|
|
28
28
|
|
|
29
29
|
const itemsJSX = useRenderItems(itemsProp);
|
|
30
30
|
|
|
31
|
-
const handleItemClick = (e: MouseEvent<
|
|
31
|
+
const handleItemClick = (e: MouseEvent<HTMLElement>) => {
|
|
32
32
|
handleChange();
|
|
33
33
|
toggleOpenCollapsedItems?.(id ?? '');
|
|
34
34
|
option.onClick?.(e);
|
|
35
35
|
};
|
|
36
36
|
|
|
37
37
|
return (
|
|
38
|
-
<
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
>
|
|
56
|
-
|
|
57
|
-
</CollapseBlockPrivate>
|
|
58
|
-
</li>
|
|
38
|
+
<CollapseBlockPrivate
|
|
39
|
+
header={
|
|
40
|
+
<BaseItem
|
|
41
|
+
{...option}
|
|
42
|
+
id={id}
|
|
43
|
+
disabled={disabled}
|
|
44
|
+
expandIcon={open ? <ChevronUpSVG /> : <ChevronDownSVG />}
|
|
45
|
+
onClick={handleItemClick}
|
|
46
|
+
isParentNode
|
|
47
|
+
onKeyDown={handleKeyDown}
|
|
48
|
+
indeterminate={isIndeterminate && !checked}
|
|
49
|
+
onSelect={!disabled ? handleOnSelect : undefined}
|
|
50
|
+
/>
|
|
51
|
+
}
|
|
52
|
+
expanded={open}
|
|
53
|
+
data-test-id={`list__accordion-item-${id}`}
|
|
54
|
+
>
|
|
55
|
+
<CollapseContext.Provider value={{ level: level + 1 }}>{itemsJSX}</CollapseContext.Provider>
|
|
56
|
+
</CollapseBlockPrivate>
|
|
59
57
|
);
|
|
60
58
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import cn from 'classnames';
|
|
2
|
-
import { FocusEvent, KeyboardEvent, MouseEvent } from 'react';
|
|
2
|
+
import { FocusEvent, KeyboardEvent, MouseEvent, RefObject } from 'react';
|
|
3
3
|
|
|
4
4
|
import { Checkbox, Switch } from '@snack-uikit/toggles';
|
|
5
5
|
import { TruncateString } from '@snack-uikit/truncate-string';
|
|
@@ -49,7 +49,7 @@ export function BaseItem({
|
|
|
49
49
|
onChange?.(id ?? '');
|
|
50
50
|
};
|
|
51
51
|
|
|
52
|
-
const handleItemClick = (e: MouseEvent<
|
|
52
|
+
const handleItemClick = (e: MouseEvent<HTMLElement>) => {
|
|
53
53
|
if (interactive) {
|
|
54
54
|
parentResetActiveFocusIndex?.();
|
|
55
55
|
|
|
@@ -61,7 +61,7 @@ export function BaseItem({
|
|
|
61
61
|
onClick?.(e);
|
|
62
62
|
};
|
|
63
63
|
|
|
64
|
-
const handleItemKeyDown = (e: KeyboardEvent<
|
|
64
|
+
const handleItemKeyDown = (e: KeyboardEvent<HTMLElement>) => {
|
|
65
65
|
onKeyDown?.(e);
|
|
66
66
|
|
|
67
67
|
if (e.code === 'Space' || e.key === 'Enter') {
|
|
@@ -71,14 +71,14 @@ export function BaseItem({
|
|
|
71
71
|
|
|
72
72
|
!isParentNode && handleChange();
|
|
73
73
|
// TODO: should pass an event here?
|
|
74
|
-
!isParentNode && onClick?.(e as unknown as MouseEvent<
|
|
74
|
+
!isParentNode && onClick?.(e as unknown as MouseEvent<HTMLElement>);
|
|
75
75
|
|
|
76
76
|
e.stopPropagation();
|
|
77
77
|
e.preventDefault();
|
|
78
78
|
}
|
|
79
79
|
};
|
|
80
80
|
|
|
81
|
-
const handleItemFocus = (e: FocusEvent<
|
|
81
|
+
const handleItemFocus = (e: FocusEvent<HTMLElement>) => {
|
|
82
82
|
onFocus?.(e);
|
|
83
83
|
e.stopPropagation();
|
|
84
84
|
};
|
|
@@ -98,65 +98,65 @@ export function BaseItem({
|
|
|
98
98
|
const props = extractSupportProps(rest);
|
|
99
99
|
|
|
100
100
|
const item = (
|
|
101
|
-
<li
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
{beforeContent && <div className={styles.beforeContent}>{beforeContent}</div>}
|
|
101
|
+
<li
|
|
102
|
+
role={'menuitem'}
|
|
103
|
+
data-test-id={props['data-test-id'] || 'list__base-item_' + id}
|
|
104
|
+
ref={itemRef as unknown as RefObject<HTMLLIElement>}
|
|
105
|
+
className={cn(commonStyles.listItem, styles.droplistItem, className)}
|
|
106
|
+
data-size={size}
|
|
107
|
+
onClick={handleItemClick}
|
|
108
|
+
tabIndex={-1}
|
|
109
|
+
data-non-pointer={inactive && !onClick}
|
|
110
|
+
data-inactive={inactive || undefined}
|
|
111
|
+
data-checked={(isParentNode && (indeterminate || isChecked)) || (isChecked && !switchProp) || undefined}
|
|
112
|
+
data-variant={mode || undefined}
|
|
113
|
+
data-open={open || undefined}
|
|
114
|
+
aria-disabled={disabled || undefined}
|
|
115
|
+
onKeyDown={handleItemKeyDown}
|
|
116
|
+
onFocus={handleItemFocus}
|
|
117
|
+
style={{ '--level': level }}
|
|
118
|
+
>
|
|
119
|
+
{!switchProp && isSelectionSingle && marker && !isParentNode && interactive && (
|
|
120
|
+
<div className={styles.markerContainer} data-test-id='list__base-item-marker' />
|
|
121
|
+
)}
|
|
122
|
+
{!switchProp && isSelectionMultiple && interactive && (
|
|
123
|
+
<div className={styles.checkbox}>
|
|
124
|
+
<Checkbox
|
|
125
|
+
size={CHECKBOX_SIZE_MAP[size ?? 's']}
|
|
126
|
+
disabled={disabled}
|
|
127
|
+
tabIndex={-1}
|
|
128
|
+
onChange={handleCheckboxChange}
|
|
129
|
+
checked={isChecked}
|
|
130
|
+
data-test-id='list__base-item-checkbox'
|
|
131
|
+
onClick={handleCheckboxClick}
|
|
132
|
+
indeterminate={indeterminate}
|
|
133
|
+
/>
|
|
134
|
+
</div>
|
|
135
|
+
)}
|
|
137
136
|
|
|
138
|
-
|
|
139
|
-
<div className={styles.headline}>
|
|
140
|
-
<span className={styles.option}>
|
|
141
|
-
<TruncateString text={option} maxLines={1} />
|
|
142
|
-
</span>
|
|
143
|
-
{caption && <span className={styles.caption}>{caption}</span>}
|
|
144
|
-
</div>
|
|
137
|
+
{beforeContent && <div className={styles.beforeContent}>{beforeContent}</div>}
|
|
145
138
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
139
|
+
<div className={styles.content}>
|
|
140
|
+
<div className={styles.headline}>
|
|
141
|
+
<span className={styles.option}>
|
|
142
|
+
<TruncateString text={option} maxLines={1} />
|
|
143
|
+
</span>
|
|
144
|
+
{caption && <span className={styles.caption}>{caption}</span>}
|
|
151
145
|
</div>
|
|
152
146
|
|
|
153
|
-
{
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
147
|
+
{description && (
|
|
148
|
+
<div className={styles.description}>
|
|
149
|
+
<TruncateString text={description} maxLines={2} />
|
|
150
|
+
</div>
|
|
157
151
|
)}
|
|
158
|
-
|
|
159
|
-
|
|
152
|
+
</div>
|
|
153
|
+
|
|
154
|
+
{afterContent}
|
|
155
|
+
|
|
156
|
+
{switchProp && interactive && (
|
|
157
|
+
<Switch disabled={disabled} checked={isChecked} data-test-id='list__base-item-switch' />
|
|
158
|
+
)}
|
|
159
|
+
{!switchProp && expandIcon && <span className={styles.expandableIcon}>{expandIcon}</span>}
|
|
160
160
|
</li>
|
|
161
161
|
);
|
|
162
162
|
|
|
@@ -78,55 +78,53 @@ export function NextListItem({
|
|
|
78
78
|
}, [parentResetActiveFocusIndex, parentResetNestedIndex]);
|
|
79
79
|
|
|
80
80
|
return (
|
|
81
|
-
<
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
</Dropdown>
|
|
130
|
-
</li>
|
|
81
|
+
<Dropdown
|
|
82
|
+
outsideClick={handleOutsideClick}
|
|
83
|
+
fallbackPlacements={FALLBACK_PLACEMENTS}
|
|
84
|
+
content={
|
|
85
|
+
<ParentListContext.Provider
|
|
86
|
+
value={{
|
|
87
|
+
parentIds: ids,
|
|
88
|
+
parentActiveFocusIndex: activeFocusIndex,
|
|
89
|
+
parentExpandedIds: expandedIds,
|
|
90
|
+
parentItemRefs: itemRefs,
|
|
91
|
+
parentOpenNestedIndex: openNestedIndex,
|
|
92
|
+
triggerRef,
|
|
93
|
+
parentRef: listRef,
|
|
94
|
+
parentResetNestedIndex: resetNestedIndex,
|
|
95
|
+
parentResetActiveFocusIndex: resetActiveFocusIndex,
|
|
96
|
+
toggleOpenCollapsedItems: id =>
|
|
97
|
+
setOpenCollapsedItems(items =>
|
|
98
|
+
items.includes(id) ? items.filter(item => item !== id) : items.concat([id]),
|
|
99
|
+
),
|
|
100
|
+
}}
|
|
101
|
+
>
|
|
102
|
+
<ListPrivate
|
|
103
|
+
onKeyDown={handleListKeyDown}
|
|
104
|
+
items={items}
|
|
105
|
+
nested
|
|
106
|
+
search={search}
|
|
107
|
+
scroll={scroll}
|
|
108
|
+
scrollRef={scrollRef}
|
|
109
|
+
limitedScrollHeight
|
|
110
|
+
/>
|
|
111
|
+
</ParentListContext.Provider>
|
|
112
|
+
}
|
|
113
|
+
trigger='hover'
|
|
114
|
+
open={(open || parentIds[parentOpenNestedIndex] === id) && !disabled}
|
|
115
|
+
onOpenChange={handleOpenChange}
|
|
116
|
+
placement={placement}
|
|
117
|
+
>
|
|
118
|
+
<BaseItem
|
|
119
|
+
{...option}
|
|
120
|
+
disabled={disabled}
|
|
121
|
+
open={open}
|
|
122
|
+
expandIcon={<ChevronRightSVG />}
|
|
123
|
+
id={id}
|
|
124
|
+
isParentNode
|
|
125
|
+
indeterminate={isIndeterminate && !checked}
|
|
126
|
+
onSelect={handleOnSelect}
|
|
127
|
+
/>
|
|
128
|
+
</Dropdown>
|
|
131
129
|
);
|
|
132
130
|
}
|
|
@@ -5,7 +5,7 @@ import { useParentListContext } from '../../Lists/contexts';
|
|
|
5
5
|
type UseKeyboardNavigationProps = {
|
|
6
6
|
ids: Array<number | string>;
|
|
7
7
|
expandedIds: Array<number | string>;
|
|
8
|
-
itemRefs?: RefObject<
|
|
8
|
+
itemRefs?: RefObject<HTMLElement>[];
|
|
9
9
|
id?: string | number;
|
|
10
10
|
};
|
|
11
11
|
|
|
@@ -17,7 +17,7 @@ export function useKeyboardNavigation({ ids, expandedIds, itemRefs, id }: UseKey
|
|
|
17
17
|
const [openNestedIndex, setOpenNestedIndex] = useState<number>(-1);
|
|
18
18
|
const [open, setOpen] = useState<boolean>(false);
|
|
19
19
|
|
|
20
|
-
const handleListKeyDown = (e: KeyboardEvent<
|
|
20
|
+
const handleListKeyDown = (e: KeyboardEvent<HTMLElement>) => {
|
|
21
21
|
switch (e.key) {
|
|
22
22
|
case 'ArrowDown': {
|
|
23
23
|
setActiveFocusIndex(activeIndex => Math.min(activeIndex + 1, ids.length - 1));
|
|
@@ -31,13 +31,13 @@ export type BaseItemProps = WithSupportProps<{
|
|
|
31
31
|
content: ItemContentProps;
|
|
32
32
|
|
|
33
33
|
/** Колбек обработки клика */
|
|
34
|
-
onClick?(e: MouseEvent<
|
|
34
|
+
onClick?(e: MouseEvent<HTMLElement>): void;
|
|
35
35
|
/** Колбек обработки нажатия клавиши */
|
|
36
|
-
onKeyDown?(e: KeyboardEvent<
|
|
36
|
+
onKeyDown?(e: KeyboardEvent<HTMLElement>): void;
|
|
37
37
|
/** Колбек обработки фокуса */
|
|
38
|
-
onFocus?(e: FocusEvent<
|
|
38
|
+
onFocus?(e: FocusEvent<HTMLElement>): void;
|
|
39
39
|
/** Колбек обработки блюра */
|
|
40
|
-
onBlur?(e: FocusEvent<
|
|
40
|
+
onBlur?(e: FocusEvent<HTMLElement>): void;
|
|
41
41
|
|
|
42
42
|
/** Уникальный идентификатор */
|
|
43
43
|
id?: string | number;
|
|
@@ -45,7 +45,7 @@ export type BaseItemProps = WithSupportProps<{
|
|
|
45
45
|
/** Флаг неактивности элемента */
|
|
46
46
|
disabled?: boolean;
|
|
47
47
|
|
|
48
|
-
itemRef?: RefObject<
|
|
48
|
+
itemRef?: RefObject<HTMLElement>;
|
|
49
49
|
className?: string;
|
|
50
50
|
|
|
51
51
|
/**
|
|
@@ -60,10 +60,10 @@ export function addItemsIds(itemsProp: ItemProps[], prefix?: string | number): I
|
|
|
60
60
|
...item,
|
|
61
61
|
id: itemId,
|
|
62
62
|
items: addItemsIds(item.items, itemId),
|
|
63
|
-
itemRef: item.itemRef || createRef<
|
|
63
|
+
itemRef: item.itemRef || createRef<HTMLElement>(),
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
return { ...item, id: itemId, itemRef: item.itemRef || createRef<
|
|
67
|
+
return { ...item, id: itemId, itemRef: item.itemRef || createRef<HTMLElement>() };
|
|
68
68
|
});
|
|
69
69
|
}
|
|
@@ -71,7 +71,7 @@ export const List = forwardRef<HTMLElement, ListProps>(
|
|
|
71
71
|
[items, hasSearch, pinTop, pinBottom, footerRefs],
|
|
72
72
|
);
|
|
73
73
|
|
|
74
|
-
const listRef = useRef<
|
|
74
|
+
const listRef = useRef<HTMLElement>(null);
|
|
75
75
|
const btnRef = useRef<HTMLButtonElement>(null);
|
|
76
76
|
|
|
77
77
|
const { triggerRef } = useParentListContext();
|
|
@@ -93,7 +93,7 @@ export const List = forwardRef<HTMLElement, ListProps>(
|
|
|
93
93
|
|
|
94
94
|
const isActive = listRef.current === document.activeElement && activeFocusIndex === -1 && openNestedIndex === -1;
|
|
95
95
|
|
|
96
|
-
const mergedHandlerKeyDown = (e: KeyboardEvent<
|
|
96
|
+
const mergedHandlerKeyDown = (e: KeyboardEvent<HTMLElement>) => {
|
|
97
97
|
onKeyDown?.(e);
|
|
98
98
|
handleListKeyDown?.(e);
|
|
99
99
|
};
|
|
@@ -7,7 +7,7 @@ export type ParentListContextType = {
|
|
|
7
7
|
|
|
8
8
|
parentIds: Array<string | number>;
|
|
9
9
|
parentExpandedIds: Array<string | number>;
|
|
10
|
-
parentItemRefs: Array<RefObject<
|
|
10
|
+
parentItemRefs: Array<RefObject<HTMLElement>>;
|
|
11
11
|
|
|
12
12
|
parentOpenNestedIndex: number;
|
|
13
13
|
parentResetNestedIndex?(): void;
|
|
@@ -5,7 +5,7 @@ export type UseKeyboardNavigationProps<T extends HTMLElement> = {
|
|
|
5
5
|
expandedIds: Array<number | string>;
|
|
6
6
|
parentRef?: RefObject<T>;
|
|
7
7
|
btnRef?: RefObject<HTMLButtonElement>;
|
|
8
|
-
itemRefs?: RefObject<
|
|
8
|
+
itemRefs?: RefObject<HTMLElement>[];
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
export function useKeyboardNavigation<T extends HTMLElement>({
|
package/src/utils.ts
CHANGED
|
@@ -14,7 +14,7 @@ type WithCollapsedItemsProps = {
|
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
export function withCollapsedItems({ items, openCollapsedItems }: WithCollapsedItemsProps) {
|
|
17
|
-
let itemRefs: RefObject<
|
|
17
|
+
let itemRefs: RefObject<HTMLElement>[] = [];
|
|
18
18
|
let newItems: ItemProps[] = [];
|
|
19
19
|
let ids: Array<string | number> = [];
|
|
20
20
|
let expandedIds: Array<string | number> = [];
|
|
@@ -68,13 +68,13 @@ export function withCollapsedItems({ items, openCollapsedItems }: WithCollapsedI
|
|
|
68
68
|
return { items, itemRefs, ids, expandedIds };
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
export function extractItemRefs(items: ItemProps[]): RefObject<
|
|
72
|
-
return items.reduce((prev: RefObject<
|
|
71
|
+
export function extractItemRefs(items: ItemProps[]): RefObject<HTMLElement>[] {
|
|
72
|
+
return items.reduce((prev: RefObject<HTMLElement>[], item: ItemProps) => {
|
|
73
73
|
if (isGroupItemProps(item)) {
|
|
74
74
|
return prev.concat(extractItemRefs(item.items));
|
|
75
75
|
}
|
|
76
76
|
return item.itemRef ? prev.concat([item.itemRef]) : prev;
|
|
77
|
-
}, [] as RefObject<
|
|
77
|
+
}, [] as RefObject<HTMLElement>[]);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
export function extractItemIds(items: ItemProps[]): Array<string | number> {
|