@snack-uikit/list 0.29.7-preview-c824da44.0 → 0.30.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/cjs/components/Lists/ListPrivate/ListPrivate.d.ts +4 -3
- package/dist/cjs/components/Lists/ListPrivate/ListPrivate.js +9 -14
- package/dist/esm/components/Lists/ListPrivate/ListPrivate.d.ts +4 -3
- package/dist/esm/components/Lists/ListPrivate/ListPrivate.js +9 -14
- package/package.json +2 -2
- package/src/components/Lists/ListPrivate/ListPrivate.tsx +11 -19
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.30.0 (2025-06-23)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* **PDS-2461:** list virtualization scroll to initial value ([9ff5a87](https://github.com/cloud-ru-tech/snack-uikit/commit/9ff5a8781367fd3ea0bdc879fb4f5484228459be))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
6
17
|
## 0.29.6 (2025-06-19)
|
|
7
18
|
|
|
8
19
|
### Only dependencies have been changed
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ItemId } from '../../Items';
|
|
1
2
|
export declare const ListPrivate: import("react").ForwardRefExoticComponent<Omit<import("../types").ListProps, "items" | "hasListInFocusChain" | "pinTop" | "pinBottom"> & {
|
|
2
3
|
nested?: boolean;
|
|
3
4
|
active?: boolean;
|
|
@@ -8,7 +9,7 @@ export declare const ListPrivate: import("react").ForwardRefExoticComponent<Omit
|
|
|
8
9
|
onKeyDown?(e: import("react").KeyboardEvent<HTMLElement>): void;
|
|
9
10
|
limitedScrollHeight?: boolean;
|
|
10
11
|
searchItem?: import("../../Items").FlattenBaseItem;
|
|
11
|
-
pinTop?:
|
|
12
|
-
items:
|
|
13
|
-
pinBottom?:
|
|
12
|
+
pinTop?: ItemId[];
|
|
13
|
+
items: ItemId[];
|
|
14
|
+
pinBottom?: ItemId[];
|
|
14
15
|
} & import("react").RefAttributes<HTMLElement>>;
|
|
@@ -84,7 +84,6 @@ exports.ListPrivate = (0, react_1.forwardRef)((_a, ref) => {
|
|
|
84
84
|
browser: null,
|
|
85
85
|
measured: false
|
|
86
86
|
});
|
|
87
|
-
console.info('[DEBUG] ScrollState', scrollState);
|
|
88
87
|
const emptyStates = (0, helperComponents_1.useEmptyState)({
|
|
89
88
|
noDataState,
|
|
90
89
|
noResultsState,
|
|
@@ -137,35 +136,32 @@ exports.ListPrivate = (0, react_1.forwardRef)((_a, ref) => {
|
|
|
137
136
|
(0, react_1.useEffect)(() => {
|
|
138
137
|
var _a;
|
|
139
138
|
if (isScrollToItemEnabled) {
|
|
140
|
-
console.info('[DEBUG] selectedItemIndex', selectedItemIndex);
|
|
141
139
|
if (!scrollState.measured) {
|
|
142
|
-
console.info('[DEBUG] Not measured yet');
|
|
143
140
|
return; // Not measured yet
|
|
144
141
|
}
|
|
145
142
|
if (selectedItemIndex < 0 || !selectedItem) {
|
|
146
|
-
console.info('[DEBUG] Cannot scroll to non-existing item');
|
|
147
143
|
return; // Cannot scroll to non-existing item
|
|
148
144
|
}
|
|
149
|
-
if (scrollState.virtualizer ===
|
|
150
|
-
console.info('[DEBUG] No need to re-scroll to the same item during re-renders');
|
|
145
|
+
if (scrollState.virtualizer === selectedItem.originalId) {
|
|
151
146
|
return; // No need to re-scroll to the same item during re-renders
|
|
152
147
|
}
|
|
153
148
|
if ((selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.itemRef) && ((_a = innerScrollRef.current) === null || _a === void 0 ? void 0 : _a.contains(selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.itemRef.current))) {
|
|
154
|
-
console.info('[DEBUG] No need to scroll to manually clicked item currently present in DOM');
|
|
155
149
|
return; // No need to scroll to manually clicked item currently present in DOM
|
|
156
150
|
}
|
|
157
|
-
console.info('[DEBUG] SCROLLING BY VIRTUALIZER');
|
|
158
151
|
virtualizer.scrollToIndex(selectedItemIndex, {
|
|
159
152
|
align: 'center'
|
|
160
153
|
});
|
|
161
154
|
setScrollState(prevState => Object.assign(Object.assign({}, prevState), {
|
|
162
|
-
virtualizer:
|
|
155
|
+
virtualizer: selectedItem.originalId
|
|
163
156
|
}));
|
|
164
157
|
}
|
|
165
158
|
}, [isScrollToItemEnabled, scrollState, selectedItem, selectedItemIndex, virtualizer]);
|
|
166
159
|
const isTargetPresentInDom = Boolean((_b = selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.itemRef) === null || _b === void 0 ? void 0 : _b.current);
|
|
167
160
|
(0, react_1.useEffect)(() => {
|
|
168
|
-
var _a, _b
|
|
161
|
+
var _a, _b;
|
|
162
|
+
if (!selectedItem) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
169
165
|
if (scrollState.virtualizer === null) {
|
|
170
166
|
return; // Not scrolled by virtualizer yet, no need for additional scroll
|
|
171
167
|
}
|
|
@@ -175,14 +171,13 @@ exports.ListPrivate = (0, react_1.forwardRef)((_a, ref) => {
|
|
|
175
171
|
if (scrollState.virtualizer === scrollState.browser) {
|
|
176
172
|
return; // Virtualizer scroll has not been executed => no need for additional scroll
|
|
177
173
|
}
|
|
178
|
-
|
|
179
|
-
(_c = (_b = selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.itemRef) === null || _b === void 0 ? void 0 : _b.current) === null || _c === void 0 ? void 0 : _c.scrollIntoView({
|
|
174
|
+
(_b = (_a = selectedItem.itemRef) === null || _a === void 0 ? void 0 : _a.current) === null || _b === void 0 ? void 0 : _b.scrollIntoView({
|
|
180
175
|
block: 'center'
|
|
181
176
|
});
|
|
182
177
|
setScrollState(prevState => Object.assign(Object.assign({}, prevState), {
|
|
183
|
-
browser:
|
|
178
|
+
browser: selectedItem.originalId
|
|
184
179
|
}));
|
|
185
|
-
}, [scrollState, selectedItem
|
|
180
|
+
}, [scrollState, selectedItem, isTargetPresentInDom, selectedItemIndex]);
|
|
186
181
|
const loadingJSX = (0, react_1.useMemo)(() => loading && (0, jsx_runtime_1.jsx)("div", {
|
|
187
182
|
role: 'spinbutton',
|
|
188
183
|
tabIndex: -1,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ItemId } from '../../Items';
|
|
1
2
|
export declare const ListPrivate: import("react").ForwardRefExoticComponent<Omit<import("../types").ListProps, "items" | "hasListInFocusChain" | "pinTop" | "pinBottom"> & {
|
|
2
3
|
nested?: boolean;
|
|
3
4
|
active?: boolean;
|
|
@@ -8,7 +9,7 @@ export declare const ListPrivate: import("react").ForwardRefExoticComponent<Omit
|
|
|
8
9
|
onKeyDown?(e: import("react").KeyboardEvent<HTMLElement>): void;
|
|
9
10
|
limitedScrollHeight?: boolean;
|
|
10
11
|
searchItem?: import("../../Items").FlattenBaseItem;
|
|
11
|
-
pinTop?:
|
|
12
|
-
items:
|
|
13
|
-
pinBottom?:
|
|
12
|
+
pinTop?: ItemId[];
|
|
13
|
+
items: ItemId[];
|
|
14
|
+
pinBottom?: ItemId[];
|
|
14
15
|
} & import("react").RefAttributes<HTMLElement>>;
|
|
@@ -34,7 +34,6 @@ export const ListPrivate = forwardRef((_a, ref) => {
|
|
|
34
34
|
const itemsPinTopJSX = useRenderItems(pinTop);
|
|
35
35
|
const itemsPinBottomJSX = useRenderItems(pinBottom);
|
|
36
36
|
const [scrollState, setScrollState] = useState({ virtualizer: null, browser: null, measured: false });
|
|
37
|
-
console.info('[DEBUG] ScrollState', scrollState);
|
|
38
37
|
const emptyStates = useEmptyState({ noDataState, noResultsState, errorDataState });
|
|
39
38
|
const hasNoItems = items.length === 0;
|
|
40
39
|
const { selectedItemIndex, selectedItem } = useMemo(() => {
|
|
@@ -78,31 +77,28 @@ export const ListPrivate = forwardRef((_a, ref) => {
|
|
|
78
77
|
useEffect(() => {
|
|
79
78
|
var _a;
|
|
80
79
|
if (isScrollToItemEnabled) {
|
|
81
|
-
console.info('[DEBUG] selectedItemIndex', selectedItemIndex);
|
|
82
80
|
if (!scrollState.measured) {
|
|
83
|
-
console.info('[DEBUG] Not measured yet');
|
|
84
81
|
return; // Not measured yet
|
|
85
82
|
}
|
|
86
83
|
if (selectedItemIndex < 0 || !selectedItem) {
|
|
87
|
-
console.info('[DEBUG] Cannot scroll to non-existing item');
|
|
88
84
|
return; // Cannot scroll to non-existing item
|
|
89
85
|
}
|
|
90
|
-
if (scrollState.virtualizer ===
|
|
91
|
-
console.info('[DEBUG] No need to re-scroll to the same item during re-renders');
|
|
86
|
+
if (scrollState.virtualizer === selectedItem.originalId) {
|
|
92
87
|
return; // No need to re-scroll to the same item during re-renders
|
|
93
88
|
}
|
|
94
89
|
if ((selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.itemRef) && ((_a = innerScrollRef.current) === null || _a === void 0 ? void 0 : _a.contains(selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.itemRef.current))) {
|
|
95
|
-
console.info('[DEBUG] No need to scroll to manually clicked item currently present in DOM');
|
|
96
90
|
return; // No need to scroll to manually clicked item currently present in DOM
|
|
97
91
|
}
|
|
98
|
-
console.info('[DEBUG] SCROLLING BY VIRTUALIZER');
|
|
99
92
|
virtualizer.scrollToIndex(selectedItemIndex, { align: 'center' });
|
|
100
|
-
setScrollState(prevState => (Object.assign(Object.assign({}, prevState), { virtualizer:
|
|
93
|
+
setScrollState(prevState => (Object.assign(Object.assign({}, prevState), { virtualizer: selectedItem.originalId })));
|
|
101
94
|
}
|
|
102
95
|
}, [isScrollToItemEnabled, scrollState, selectedItem, selectedItemIndex, virtualizer]);
|
|
103
96
|
const isTargetPresentInDom = Boolean((_b = selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.itemRef) === null || _b === void 0 ? void 0 : _b.current);
|
|
104
97
|
useEffect(() => {
|
|
105
|
-
var _a, _b
|
|
98
|
+
var _a, _b;
|
|
99
|
+
if (!selectedItem) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
106
102
|
if (scrollState.virtualizer === null) {
|
|
107
103
|
return; // Not scrolled by virtualizer yet, no need for additional scroll
|
|
108
104
|
}
|
|
@@ -112,10 +108,9 @@ export const ListPrivate = forwardRef((_a, ref) => {
|
|
|
112
108
|
if (scrollState.virtualizer === scrollState.browser) {
|
|
113
109
|
return; // Virtualizer scroll has not been executed => no need for additional scroll
|
|
114
110
|
}
|
|
115
|
-
|
|
116
|
-
(
|
|
117
|
-
|
|
118
|
-
}, [scrollState, selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.itemRef, isTargetPresentInDom, selectedItemIndex]);
|
|
111
|
+
(_b = (_a = selectedItem.itemRef) === null || _a === void 0 ? void 0 : _a.current) === null || _b === void 0 ? void 0 : _b.scrollIntoView({ block: 'center' });
|
|
112
|
+
setScrollState(prevState => (Object.assign(Object.assign({}, prevState), { browser: selectedItem.originalId })));
|
|
113
|
+
}, [scrollState, selectedItem, isTargetPresentInDom, selectedItemIndex]);
|
|
119
114
|
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]);
|
|
120
115
|
const content = useMemo(() => (_jsxs(_Fragment, { children: [virtualized ? (_jsx("div", { className: styles.virtualizedContainer, style: { height: virtualizer.getTotalSize() }, tabIndex: -1, children: virtualItems.map(virtualRow => (_jsx("div", { "data-index": virtualRow.index, ref: virtualizer.measureElement, tabIndex: -1, className: styles.virtualizedPositionBox, style: {
|
|
121
116
|
transform: `translateY(${virtualRow.start}px)`,
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
6
|
"title": "List",
|
|
7
|
-
"version": "0.
|
|
7
|
+
"version": "0.30.0",
|
|
8
8
|
"sideEffects": [
|
|
9
9
|
"*.css",
|
|
10
10
|
"*.woff",
|
|
@@ -54,5 +54,5 @@
|
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"@snack-uikit/locale": "*"
|
|
56
56
|
},
|
|
57
|
-
"gitHead": "
|
|
57
|
+
"gitHead": "cab80a84247484f1f7a06635d6d3d15ae7628aac"
|
|
58
58
|
}
|
|
@@ -9,7 +9,7 @@ import { extractSupportProps } from '@snack-uikit/utils';
|
|
|
9
9
|
|
|
10
10
|
import { ListEmptyState, useEmptyState } from '../../../helperComponents';
|
|
11
11
|
import { stopPropagation } from '../../../utils';
|
|
12
|
-
import { PinBottomGroupItem, PinTopGroupItem, SearchItem, useRenderItems } from '../../Items';
|
|
12
|
+
import { ItemId, PinBottomGroupItem, PinTopGroupItem, SearchItem, useRenderItems } from '../../Items';
|
|
13
13
|
import { useNewListContext, useSelectionContext } from '../contexts';
|
|
14
14
|
import commonStyles from '../styles.module.scss';
|
|
15
15
|
import { ListPrivateProps } from '../types';
|
|
@@ -17,8 +17,8 @@ import { ALL_SIZES } from './constants';
|
|
|
17
17
|
import styles from './styles.module.scss';
|
|
18
18
|
|
|
19
19
|
type ScrollState = {
|
|
20
|
-
virtualizer:
|
|
21
|
-
browser:
|
|
20
|
+
virtualizer: ItemId | null;
|
|
21
|
+
browser: ItemId | null;
|
|
22
22
|
measured: boolean;
|
|
23
23
|
};
|
|
24
24
|
|
|
@@ -67,7 +67,6 @@ export const ListPrivate = forwardRef(
|
|
|
67
67
|
const itemsPinBottomJSX = useRenderItems(pinBottom);
|
|
68
68
|
|
|
69
69
|
const [scrollState, setScrollState] = useState<ScrollState>({ virtualizer: null, browser: null, measured: false });
|
|
70
|
-
console.info('[DEBUG] ScrollState', scrollState);
|
|
71
70
|
|
|
72
71
|
const emptyStates = useEmptyState({ noDataState, noResultsState, errorDataState });
|
|
73
72
|
const hasNoItems = items.length === 0;
|
|
@@ -125,30 +124,24 @@ export const ListPrivate = forwardRef(
|
|
|
125
124
|
|
|
126
125
|
useEffect(() => {
|
|
127
126
|
if (isScrollToItemEnabled) {
|
|
128
|
-
console.info('[DEBUG] selectedItemIndex', selectedItemIndex);
|
|
129
127
|
if (!scrollState.measured) {
|
|
130
|
-
console.info('[DEBUG] Not measured yet');
|
|
131
128
|
return; // Not measured yet
|
|
132
129
|
}
|
|
133
130
|
if (selectedItemIndex < 0 || !selectedItem) {
|
|
134
|
-
console.info('[DEBUG] Cannot scroll to non-existing item');
|
|
135
131
|
return; // Cannot scroll to non-existing item
|
|
136
132
|
}
|
|
137
|
-
if (scrollState.virtualizer ===
|
|
138
|
-
console.info('[DEBUG] No need to re-scroll to the same item during re-renders');
|
|
133
|
+
if (scrollState.virtualizer === selectedItem.originalId) {
|
|
139
134
|
return; // No need to re-scroll to the same item during re-renders
|
|
140
135
|
}
|
|
141
136
|
if (selectedItem?.itemRef && innerScrollRef.current?.contains(selectedItem?.itemRef.current)) {
|
|
142
|
-
console.info('[DEBUG] No need to scroll to manually clicked item currently present in DOM');
|
|
143
137
|
return; // No need to scroll to manually clicked item currently present in DOM
|
|
144
138
|
}
|
|
145
139
|
|
|
146
|
-
console.info('[DEBUG] SCROLLING BY VIRTUALIZER');
|
|
147
140
|
virtualizer.scrollToIndex(selectedItemIndex, { align: 'center' });
|
|
148
141
|
|
|
149
142
|
setScrollState(prevState => ({
|
|
150
143
|
...prevState,
|
|
151
|
-
virtualizer:
|
|
144
|
+
virtualizer: selectedItem.originalId,
|
|
152
145
|
}));
|
|
153
146
|
}
|
|
154
147
|
}, [isScrollToItemEnabled, scrollState, selectedItem, selectedItemIndex, virtualizer]);
|
|
@@ -156,27 +149,26 @@ export const ListPrivate = forwardRef(
|
|
|
156
149
|
const isTargetPresentInDom = Boolean(selectedItem?.itemRef?.current);
|
|
157
150
|
|
|
158
151
|
useEffect(() => {
|
|
152
|
+
if (!selectedItem) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
159
155
|
if (scrollState.virtualizer === null) {
|
|
160
156
|
return; // Not scrolled by virtualizer yet, no need for additional scroll
|
|
161
157
|
}
|
|
162
|
-
|
|
163
158
|
if (!isTargetPresentInDom) {
|
|
164
159
|
return; // Target element is not present in DOM yet, additional scroll does not work without it
|
|
165
160
|
}
|
|
166
|
-
|
|
167
161
|
if (scrollState.virtualizer === scrollState.browser) {
|
|
168
162
|
return; // Virtualizer scroll has not been executed => no need for additional scroll
|
|
169
163
|
}
|
|
170
164
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
selectedItem?.itemRef?.current?.scrollIntoView({ block: 'center' });
|
|
165
|
+
selectedItem.itemRef?.current?.scrollIntoView({ block: 'center' });
|
|
174
166
|
|
|
175
167
|
setScrollState(prevState => ({
|
|
176
168
|
...prevState,
|
|
177
|
-
browser:
|
|
169
|
+
browser: selectedItem.originalId,
|
|
178
170
|
}));
|
|
179
|
-
}, [scrollState, selectedItem
|
|
171
|
+
}, [scrollState, selectedItem, isTargetPresentInDom, selectedItemIndex]);
|
|
180
172
|
|
|
181
173
|
const loadingJSX = useMemo(
|
|
182
174
|
() =>
|