@snack-uikit/list 0.22.2 → 0.22.3-preview-91ef6a1d.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.
|
@@ -18,6 +18,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
18
18
|
});
|
|
19
19
|
exports.ListPrivate = void 0;
|
|
20
20
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
21
|
+
const react_virtual_1 = require("@tanstack/react-virtual");
|
|
21
22
|
const classnames_1 = __importDefault(require("classnames"));
|
|
22
23
|
const react_1 = require("react");
|
|
23
24
|
const loaders_1 = require("@snack-uikit/loaders");
|
|
@@ -68,6 +69,7 @@ exports.ListPrivate = (0, react_1.forwardRef)((_a, ref) => {
|
|
|
68
69
|
value,
|
|
69
70
|
isSelectionSingle
|
|
70
71
|
} = (0, contexts_1.useSelectionContext)();
|
|
72
|
+
const innerScrollRef = (0, react_1.useRef)(null);
|
|
71
73
|
const itemsJSX = (0, Items_1.useRenderItems)(items);
|
|
72
74
|
const itemsPinTopJSX = (0, Items_1.useRenderItems)(pinTop);
|
|
73
75
|
const itemsPinBottomJSX = (0, Items_1.useRenderItems)(pinBottom);
|
|
@@ -77,6 +79,12 @@ exports.ListPrivate = (0, react_1.forwardRef)((_a, ref) => {
|
|
|
77
79
|
errorDataState
|
|
78
80
|
});
|
|
79
81
|
const hasNoItems = items.length === 0;
|
|
82
|
+
const virtualizer = (0, react_virtual_1.useVirtualizer)({
|
|
83
|
+
count: itemsJSX.length,
|
|
84
|
+
getScrollElement: () => scroll ? innerScrollRef.current : null,
|
|
85
|
+
estimateSize: () => size === 'm' ? 40 : 32
|
|
86
|
+
});
|
|
87
|
+
const virtualItems = virtualizer.getVirtualItems();
|
|
80
88
|
const loadingJSX = (0, react_1.useMemo)(() => loading && (0, jsx_runtime_1.jsx)("div", {
|
|
81
89
|
role: 'spinbutton',
|
|
82
90
|
tabIndex: -1,
|
|
@@ -88,18 +96,42 @@ exports.ListPrivate = (0, react_1.forwardRef)((_a, ref) => {
|
|
|
88
96
|
size: size === 'l' ? 's' : 'xs'
|
|
89
97
|
})
|
|
90
98
|
}), [hasNoItems, loading, size]);
|
|
91
|
-
const content = (0, react_1.useMemo)(() =>
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
const content = (0, react_1.useMemo)(() => {
|
|
100
|
+
var _a, _b;
|
|
101
|
+
return (0, jsx_runtime_1.jsxs)("div", {
|
|
102
|
+
className: styles_module_scss_2.default.content,
|
|
103
|
+
children: [(0, jsx_runtime_1.jsx)("div", {
|
|
104
|
+
style: {
|
|
105
|
+
height: virtualizer.getTotalSize(),
|
|
106
|
+
width: '100%',
|
|
107
|
+
position: 'relative'
|
|
108
|
+
},
|
|
109
|
+
children: (0, jsx_runtime_1.jsx)("div", {
|
|
110
|
+
style: {
|
|
111
|
+
position: 'absolute',
|
|
112
|
+
top: 0,
|
|
113
|
+
left: 0,
|
|
114
|
+
width: '100%',
|
|
115
|
+
transform: `translateY(${(_b = (_a = virtualItems[0]) === null || _a === void 0 ? void 0 : _a.start) !== null && _b !== void 0 ? _b : 0}px)`
|
|
116
|
+
},
|
|
117
|
+
children: virtualItems.map(virtualRow => (0, jsx_runtime_1.jsx)("div", {
|
|
118
|
+
"data-index": virtualRow.index,
|
|
119
|
+
ref: virtualizer.measureElement,
|
|
120
|
+
children: itemsJSX[virtualRow.index]
|
|
121
|
+
}, virtualRow.key))
|
|
122
|
+
})
|
|
123
|
+
}), loadingJSX, (0, jsx_runtime_1.jsx)(helperComponents_1.ListEmptyState, {
|
|
124
|
+
loading: loading,
|
|
125
|
+
dataError: dataError,
|
|
126
|
+
emptyStates: emptyStates,
|
|
127
|
+
hasNoItems: hasNoItems,
|
|
128
|
+
dataFiltered: dataFiltered !== null && dataFiltered !== void 0 ? dataFiltered : Boolean(search === null || search === void 0 ? void 0 : search.value)
|
|
129
|
+
})]
|
|
130
|
+
});
|
|
131
|
+
}, [dataError, dataFiltered, emptyStates, hasNoItems, itemsJSX, loading, loadingJSX, search === null || search === void 0 ? void 0 : search.value, virtualItems, virtualizer]);
|
|
101
132
|
const onScrollInitialized = () => {
|
|
102
133
|
var _a, _b;
|
|
134
|
+
virtualizer.measure();
|
|
103
135
|
if (scrollToSelectedItem) {
|
|
104
136
|
if (!value) {
|
|
105
137
|
return;
|
|
@@ -136,7 +168,10 @@ exports.ListPrivate = (0, react_1.forwardRef)((_a, ref) => {
|
|
|
136
168
|
}, scrollContainerClassName),
|
|
137
169
|
barHideStrategy: 'never',
|
|
138
170
|
size: size === 's' ? 's' : 'm',
|
|
139
|
-
ref:
|
|
171
|
+
ref: ref => {
|
|
172
|
+
innerScrollRef.current = ref;
|
|
173
|
+
if (scrollContainerRef) scrollContainerRef.current = ref;
|
|
174
|
+
},
|
|
140
175
|
untouchableScrollbars: untouchableScrollbars,
|
|
141
176
|
onScroll: onScroll,
|
|
142
177
|
onInitialized: onScrollInitialized,
|
|
@@ -10,8 +10,9 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
12
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
13
|
+
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
13
14
|
import cn from 'classnames';
|
|
14
|
-
import { forwardRef, useMemo } from 'react';
|
|
15
|
+
import { forwardRef, useMemo, useRef } from 'react';
|
|
15
16
|
import { Spinner } from '@snack-uikit/loaders';
|
|
16
17
|
import { Scroll } from '@snack-uikit/scroll';
|
|
17
18
|
import { extractSupportProps } from '@snack-uikit/utils';
|
|
@@ -24,15 +25,47 @@ export const ListPrivate = forwardRef((_a, ref) => {
|
|
|
24
25
|
var { items, pinTop, pinBottom, onKeyDown, onBlur, onFocus, tabIndex, active, scroll, nested, search, searchItem, scrollRef, scrollContainerRef, onScroll, footer, loading, limitedScrollHeight, untouchableScrollbars, className, noDataState, noResultsState, errorDataState, dataError, dataFiltered, scrollToSelectedItem = false, scrollContainerClassName } = _a, props = __rest(_a, ["items", "pinTop", "pinBottom", "onKeyDown", "onBlur", "onFocus", "tabIndex", "active", "scroll", "nested", "search", "searchItem", "scrollRef", "scrollContainerRef", "onScroll", "footer", "loading", "limitedScrollHeight", "untouchableScrollbars", "className", "noDataState", "noResultsState", "errorDataState", "dataError", "dataFiltered", "scrollToSelectedItem", "scrollContainerClassName"]);
|
|
25
26
|
const { size = 's', flattenItems, focusFlattenItems } = useNewListContext();
|
|
26
27
|
const { value, isSelectionSingle } = useSelectionContext();
|
|
28
|
+
const innerScrollRef = useRef(null);
|
|
27
29
|
const itemsJSX = useRenderItems(items);
|
|
28
30
|
const itemsPinTopJSX = useRenderItems(pinTop);
|
|
29
31
|
const itemsPinBottomJSX = useRenderItems(pinBottom);
|
|
30
32
|
const emptyStates = useEmptyState({ noDataState, noResultsState, errorDataState });
|
|
31
33
|
const hasNoItems = items.length === 0;
|
|
34
|
+
const virtualizer = useVirtualizer({
|
|
35
|
+
count: itemsJSX.length,
|
|
36
|
+
getScrollElement: () => (scroll ? innerScrollRef.current : null),
|
|
37
|
+
estimateSize: () => (size === 'm' ? 40 : 32),
|
|
38
|
+
});
|
|
39
|
+
const virtualItems = virtualizer.getVirtualItems();
|
|
32
40
|
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]);
|
|
33
|
-
const content = useMemo(() =>
|
|
41
|
+
const content = useMemo(() => {
|
|
42
|
+
var _a, _b;
|
|
43
|
+
return (_jsxs("div", { className: styles.content, children: [_jsx("div", { style: {
|
|
44
|
+
height: virtualizer.getTotalSize(),
|
|
45
|
+
width: '100%',
|
|
46
|
+
position: 'relative',
|
|
47
|
+
}, children: _jsx("div", { style: {
|
|
48
|
+
position: 'absolute',
|
|
49
|
+
top: 0,
|
|
50
|
+
left: 0,
|
|
51
|
+
width: '100%',
|
|
52
|
+
transform: `translateY(${(_b = (_a = virtualItems[0]) === null || _a === void 0 ? void 0 : _a.start) !== null && _b !== void 0 ? _b : 0}px)`,
|
|
53
|
+
}, children: virtualItems.map(virtualRow => (_jsx("div", { "data-index": virtualRow.index, ref: virtualizer.measureElement, children: itemsJSX[virtualRow.index] }, virtualRow.key))) }) }), loadingJSX, _jsx(ListEmptyState, { loading: loading, dataError: dataError, emptyStates: emptyStates, hasNoItems: hasNoItems, dataFiltered: dataFiltered !== null && dataFiltered !== void 0 ? dataFiltered : Boolean(search === null || search === void 0 ? void 0 : search.value) })] }));
|
|
54
|
+
}, [
|
|
55
|
+
dataError,
|
|
56
|
+
dataFiltered,
|
|
57
|
+
emptyStates,
|
|
58
|
+
hasNoItems,
|
|
59
|
+
itemsJSX,
|
|
60
|
+
loading,
|
|
61
|
+
loadingJSX,
|
|
62
|
+
search === null || search === void 0 ? void 0 : search.value,
|
|
63
|
+
virtualItems,
|
|
64
|
+
virtualizer,
|
|
65
|
+
]);
|
|
34
66
|
const onScrollInitialized = () => {
|
|
35
67
|
var _a, _b;
|
|
68
|
+
virtualizer.measure();
|
|
36
69
|
if (scrollToSelectedItem) {
|
|
37
70
|
if (!value) {
|
|
38
71
|
return;
|
|
@@ -49,7 +82,11 @@ export const ListPrivate = forwardRef((_a, ref) => {
|
|
|
49
82
|
[commonStyles.scrollContainerS]: scroll && limitedScrollHeight && size === 's',
|
|
50
83
|
[commonStyles.scrollContainerM]: scroll && limitedScrollHeight && size === 'm',
|
|
51
84
|
[commonStyles.scrollContainerL]: scroll && limitedScrollHeight && size === 'l',
|
|
52
|
-
}, scrollContainerClassName), barHideStrategy: 'never', size: size === 's' ? 's' : 'm', ref:
|
|
85
|
+
}, scrollContainerClassName), barHideStrategy: 'never', size: size === 's' ? 's' : 'm', ref: ref => {
|
|
86
|
+
innerScrollRef.current = ref;
|
|
87
|
+
if (scrollContainerRef)
|
|
88
|
+
scrollContainerRef.current = ref;
|
|
89
|
+
}, untouchableScrollbars: untouchableScrollbars, onScroll: onScroll, onInitialized: onScrollInitialized, children: [content, _jsx("div", { className: styles.scrollStub, ref: scrollRef })] })) : (_jsx(_Fragment, { children: content })), Number(pinBottom === null || pinBottom === void 0 ? void 0 : pinBottom.length) > 0 && _jsx(PinBottomGroupItem, { children: itemsPinBottomJSX }), footer && (_jsx("div", { className: styles.footer, onFocus: e => e.stopPropagation(), children: footer }))] })));
|
|
53
90
|
if (!nested) {
|
|
54
91
|
return listJSX;
|
|
55
92
|
}
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
6
|
"title": "List",
|
|
7
|
-
"version": "0.22.
|
|
7
|
+
"version": "0.22.3-preview-91ef6a1d.0",
|
|
8
8
|
"sideEffects": [
|
|
9
9
|
"*.css",
|
|
10
10
|
"*.woff",
|
|
@@ -47,11 +47,12 @@
|
|
|
47
47
|
"@snack-uikit/toggles": "0.13.3",
|
|
48
48
|
"@snack-uikit/truncate-string": "0.6.4",
|
|
49
49
|
"@snack-uikit/utils": "3.6.0",
|
|
50
|
+
"@tanstack/react-virtual": "3.11.2",
|
|
50
51
|
"classnames": "2.5.1",
|
|
51
52
|
"merge-refs": "1.3.0"
|
|
52
53
|
},
|
|
53
54
|
"peerDependencies": {
|
|
54
55
|
"@snack-uikit/locale": "*"
|
|
55
56
|
},
|
|
56
|
-
"gitHead": "
|
|
57
|
+
"gitHead": "a9285b91576f7c1b51d9e9150ecf95b1e403fc47"
|
|
57
58
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
1
2
|
import cn from 'classnames';
|
|
2
|
-
import { ForwardedRef, forwardRef, RefObject, useMemo } from 'react';
|
|
3
|
+
import { ForwardedRef, forwardRef, RefObject, useMemo, useRef } from 'react';
|
|
3
4
|
|
|
4
5
|
import { Spinner } from '@snack-uikit/loaders';
|
|
5
6
|
import { Scroll } from '@snack-uikit/scroll';
|
|
@@ -48,6 +49,7 @@ export const ListPrivate = forwardRef(
|
|
|
48
49
|
) => {
|
|
49
50
|
const { size = 's', flattenItems, focusFlattenItems } = useNewListContext();
|
|
50
51
|
const { value, isSelectionSingle } = useSelectionContext();
|
|
52
|
+
const innerScrollRef = useRef<HTMLElement | null>(null);
|
|
51
53
|
|
|
52
54
|
const itemsJSX = useRenderItems(items);
|
|
53
55
|
const itemsPinTopJSX = useRenderItems(pinTop);
|
|
@@ -56,6 +58,13 @@ export const ListPrivate = forwardRef(
|
|
|
56
58
|
const emptyStates = useEmptyState({ noDataState, noResultsState, errorDataState });
|
|
57
59
|
const hasNoItems = items.length === 0;
|
|
58
60
|
|
|
61
|
+
const virtualizer = useVirtualizer({
|
|
62
|
+
count: itemsJSX.length,
|
|
63
|
+
getScrollElement: () => (scroll ? innerScrollRef.current : null),
|
|
64
|
+
estimateSize: () => (size === 'm' ? 40 : 32),
|
|
65
|
+
});
|
|
66
|
+
const virtualItems = virtualizer.getVirtualItems();
|
|
67
|
+
|
|
59
68
|
const loadingJSX = useMemo(
|
|
60
69
|
() =>
|
|
61
70
|
loading && (
|
|
@@ -76,7 +85,29 @@ export const ListPrivate = forwardRef(
|
|
|
76
85
|
const content = useMemo(
|
|
77
86
|
() => (
|
|
78
87
|
<div className={styles.content}>
|
|
79
|
-
|
|
88
|
+
<div
|
|
89
|
+
style={{
|
|
90
|
+
height: virtualizer.getTotalSize(),
|
|
91
|
+
width: '100%',
|
|
92
|
+
position: 'relative',
|
|
93
|
+
}}
|
|
94
|
+
>
|
|
95
|
+
<div
|
|
96
|
+
style={{
|
|
97
|
+
position: 'absolute',
|
|
98
|
+
top: 0,
|
|
99
|
+
left: 0,
|
|
100
|
+
width: '100%',
|
|
101
|
+
transform: `translateY(${virtualItems[0]?.start ?? 0}px)`,
|
|
102
|
+
}}
|
|
103
|
+
>
|
|
104
|
+
{virtualItems.map(virtualRow => (
|
|
105
|
+
<div key={virtualRow.key} data-index={virtualRow.index} ref={virtualizer.measureElement}>
|
|
106
|
+
{itemsJSX[virtualRow.index]}
|
|
107
|
+
</div>
|
|
108
|
+
))}
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
80
111
|
{loadingJSX}
|
|
81
112
|
|
|
82
113
|
<ListEmptyState
|
|
@@ -88,10 +119,23 @@ export const ListPrivate = forwardRef(
|
|
|
88
119
|
/>
|
|
89
120
|
</div>
|
|
90
121
|
),
|
|
91
|
-
[
|
|
122
|
+
[
|
|
123
|
+
dataError,
|
|
124
|
+
dataFiltered,
|
|
125
|
+
emptyStates,
|
|
126
|
+
hasNoItems,
|
|
127
|
+
itemsJSX,
|
|
128
|
+
loading,
|
|
129
|
+
loadingJSX,
|
|
130
|
+
search?.value,
|
|
131
|
+
virtualItems,
|
|
132
|
+
virtualizer,
|
|
133
|
+
],
|
|
92
134
|
);
|
|
93
135
|
|
|
94
136
|
const onScrollInitialized = () => {
|
|
137
|
+
virtualizer.measure();
|
|
138
|
+
|
|
95
139
|
if (scrollToSelectedItem) {
|
|
96
140
|
if (!value) {
|
|
97
141
|
return;
|
|
@@ -140,7 +184,10 @@ export const ListPrivate = forwardRef(
|
|
|
140
184
|
)}
|
|
141
185
|
barHideStrategy='never'
|
|
142
186
|
size={size === 's' ? 's' : 'm'}
|
|
143
|
-
ref={
|
|
187
|
+
ref={ref => {
|
|
188
|
+
innerScrollRef.current = ref;
|
|
189
|
+
if (scrollContainerRef) (scrollContainerRef as React.MutableRefObject<HTMLElement | null>).current = ref;
|
|
190
|
+
}}
|
|
144
191
|
untouchableScrollbars={untouchableScrollbars}
|
|
145
192
|
onScroll={onScroll}
|
|
146
193
|
onInitialized={onScrollInitialized}
|