react-virtual-renderer 1.0.3
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/README.md +170 -0
- package/dist/App.d.ts +3 -0
- package/dist/App.d.ts.map +1 -0
- package/dist/App.js +7 -0
- package/dist/App.js.map +1 -0
- package/dist/accessibility/a11y.d.ts +111 -0
- package/dist/accessibility/a11y.d.ts.map +1 -0
- package/dist/accessibility/a11y.js +254 -0
- package/dist/accessibility/a11y.js.map +1 -0
- package/dist/components/VirtualGrid.d.ts +8 -0
- package/dist/components/VirtualGrid.d.ts.map +1 -0
- package/dist/components/VirtualGrid.js +187 -0
- package/dist/components/VirtualGrid.js.map +1 -0
- package/dist/components/VirtualList.d.ts +8 -0
- package/dist/components/VirtualList.d.ts.map +1 -0
- package/dist/components/VirtualList.js +102 -0
- package/dist/components/VirtualList.js.map +1 -0
- package/dist/core/MeasurementSystem.d.ts +52 -0
- package/dist/core/MeasurementSystem.d.ts.map +1 -0
- package/dist/core/MeasurementSystem.js +138 -0
- package/dist/core/MeasurementSystem.js.map +1 -0
- package/dist/core/VirtualizationEngine.d.ts +65 -0
- package/dist/core/VirtualizationEngine.d.ts.map +1 -0
- package/dist/core/VirtualizationEngine.js +203 -0
- package/dist/core/VirtualizationEngine.js.map +1 -0
- package/dist/examples/AdvancedExamples.d.ts +24 -0
- package/dist/examples/AdvancedExamples.d.ts.map +1 -0
- package/dist/examples/AdvancedExamples.js +216 -0
- package/dist/examples/AdvancedExamples.js.map +1 -0
- package/dist/examples/Example.d.ts +26 -0
- package/dist/examples/Example.d.ts.map +1 -0
- package/dist/examples/Example.js +186 -0
- package/dist/examples/Example.js.map +1 -0
- package/dist/hooks/useInfiniteScroll.d.ts +17 -0
- package/dist/hooks/useInfiniteScroll.d.ts.map +1 -0
- package/dist/hooks/useInfiniteScroll.js +41 -0
- package/dist/hooks/useInfiniteScroll.js.map +1 -0
- package/dist/hooks/useLazyLoad.d.ts +16 -0
- package/dist/hooks/useLazyLoad.d.ts.map +1 -0
- package/dist/hooks/useLazyLoad.js +34 -0
- package/dist/hooks/useLazyLoad.js.map +1 -0
- package/dist/hooks/useScrollRestoration.d.ts +10 -0
- package/dist/hooks/useScrollRestoration.d.ts.map +1 -0
- package/dist/hooks/useScrollRestoration.js +63 -0
- package/dist/hooks/useScrollRestoration.js.map +1 -0
- package/dist/hooks/useVirtualList.d.ts +33 -0
- package/dist/hooks/useVirtualList.d.ts.map +1 -0
- package/dist/hooks/useVirtualList.js +226 -0
- package/dist/hooks/useVirtualList.js.map +1 -0
- package/dist/hooks/useVirtualizedSearch.d.ts +40 -0
- package/dist/hooks/useVirtualizedSearch.d.ts.map +1 -0
- package/dist/hooks/useVirtualizedSearch.js +168 -0
- package/dist/hooks/useVirtualizedSearch.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.esm.js +11 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +6 -0
- package/dist/main.js.map +1 -0
- package/dist/performance/metrics.d.ts +110 -0
- package/dist/performance/metrics.d.ts.map +1 -0
- package/dist/performance/metrics.js +310 -0
- package/dist/performance/metrics.js.map +1 -0
- package/dist/plugin.d.ts +182 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +409 -0
- package/dist/plugin.js.map +1 -0
- package/dist/types.d.ts +84 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/helpers.d.ts +66 -0
- package/dist/utils/helpers.d.ts.map +1 -0
- package/dist/utils/helpers.js +166 -0
- package/dist/utils/helpers.js.map +1 -0
- package/package.json +111 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef, useMemo, useState, useRef, useImperativeHandle, } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* VirtualGrid Component
|
|
5
|
+
* Efficient rendering for grid and masonry layouts
|
|
6
|
+
*/
|
|
7
|
+
export const VirtualGrid = forwardRef(({ items, renderItem, itemKey, height, width, columnCount = 3, rowHeight = 200, columnWidth, layout = 'grid', overscan = 3, gap = 16, onScroll, className = '', style = {}, }, containerRef) => {
|
|
8
|
+
const [scrollOffset, setScrollOffset] = useState(0);
|
|
9
|
+
const [isScrolling, setIsScrolling] = useState(false);
|
|
10
|
+
const internalContainerRef = useRef(null);
|
|
11
|
+
const scrollTimeoutRef = useRef(null);
|
|
12
|
+
const columnHeightsRef = useRef([]);
|
|
13
|
+
/**
|
|
14
|
+
* Expose container ref
|
|
15
|
+
*/
|
|
16
|
+
useImperativeHandle(containerRef, () => internalContainerRef.current);
|
|
17
|
+
/**
|
|
18
|
+
* Calculate columns
|
|
19
|
+
*/
|
|
20
|
+
const cols = typeof columnCount === 'number'
|
|
21
|
+
? columnCount
|
|
22
|
+
: Math.floor(width /
|
|
23
|
+
(typeof columnWidth === 'number'
|
|
24
|
+
? columnWidth
|
|
25
|
+
: 200));
|
|
26
|
+
/**
|
|
27
|
+
* Calculate column width
|
|
28
|
+
*/
|
|
29
|
+
const colWidth = typeof columnWidth === 'number'
|
|
30
|
+
? columnWidth
|
|
31
|
+
: width / cols;
|
|
32
|
+
/**
|
|
33
|
+
* Calculate item positions
|
|
34
|
+
*/
|
|
35
|
+
const positions = useMemo(() => {
|
|
36
|
+
const calculatedPositions = [];
|
|
37
|
+
if (layout === 'masonry') {
|
|
38
|
+
const columnHeights = Array(cols).fill(0);
|
|
39
|
+
items.forEach((_, index) => {
|
|
40
|
+
const shortestColIndex = columnHeights.indexOf(Math.min(...columnHeights));
|
|
41
|
+
const itemHeight = typeof rowHeight === 'function'
|
|
42
|
+
? rowHeight(index)
|
|
43
|
+
: rowHeight;
|
|
44
|
+
const position = {
|
|
45
|
+
row: 0,
|
|
46
|
+
col: shortestColIndex,
|
|
47
|
+
x: shortestColIndex *
|
|
48
|
+
(colWidth + gap),
|
|
49
|
+
y: columnHeights[shortestColIndex],
|
|
50
|
+
width: colWidth,
|
|
51
|
+
height: itemHeight,
|
|
52
|
+
};
|
|
53
|
+
calculatedPositions.push(position);
|
|
54
|
+
columnHeights[shortestColIndex] +=
|
|
55
|
+
itemHeight + gap;
|
|
56
|
+
});
|
|
57
|
+
columnHeightsRef.current = columnHeights;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
items.forEach((_, index) => {
|
|
61
|
+
const row = Math.floor(index / cols);
|
|
62
|
+
const col = index % cols;
|
|
63
|
+
const itemHeight = typeof rowHeight === 'function'
|
|
64
|
+
? rowHeight(index)
|
|
65
|
+
: rowHeight;
|
|
66
|
+
calculatedPositions.push({
|
|
67
|
+
row,
|
|
68
|
+
col,
|
|
69
|
+
x: col * (colWidth + gap),
|
|
70
|
+
y: row * (itemHeight + gap),
|
|
71
|
+
width: colWidth,
|
|
72
|
+
height: itemHeight,
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return calculatedPositions;
|
|
77
|
+
}, [
|
|
78
|
+
items,
|
|
79
|
+
cols,
|
|
80
|
+
colWidth,
|
|
81
|
+
gap,
|
|
82
|
+
layout,
|
|
83
|
+
rowHeight,
|
|
84
|
+
]);
|
|
85
|
+
/**
|
|
86
|
+
* Visible range calculation
|
|
87
|
+
*/
|
|
88
|
+
const visibleRange = useMemo(() => {
|
|
89
|
+
const startIdx = positions.findIndex((p) => p.y + p.height > scrollOffset);
|
|
90
|
+
const endIdx = positions.findIndex((p) => p.y > scrollOffset + height);
|
|
91
|
+
const start = Math.max(0, (startIdx === -1 ? 0 : startIdx) - overscan);
|
|
92
|
+
const end = endIdx === -1
|
|
93
|
+
? items.length
|
|
94
|
+
: Math.min(items.length, endIdx + overscan);
|
|
95
|
+
return { start, end };
|
|
96
|
+
}, [
|
|
97
|
+
positions,
|
|
98
|
+
scrollOffset,
|
|
99
|
+
height,
|
|
100
|
+
overscan,
|
|
101
|
+
items.length,
|
|
102
|
+
]);
|
|
103
|
+
/**
|
|
104
|
+
* Scroll handler
|
|
105
|
+
*/
|
|
106
|
+
const handleScroll = (e) => {
|
|
107
|
+
const offset = e.currentTarget.scrollTop;
|
|
108
|
+
setScrollOffset(offset);
|
|
109
|
+
setIsScrolling(true);
|
|
110
|
+
if (onScroll) {
|
|
111
|
+
onScroll(offset);
|
|
112
|
+
}
|
|
113
|
+
if (scrollTimeoutRef.current) {
|
|
114
|
+
clearTimeout(scrollTimeoutRef.current);
|
|
115
|
+
}
|
|
116
|
+
scrollTimeoutRef.current = setTimeout(() => {
|
|
117
|
+
setIsScrolling(false);
|
|
118
|
+
}, 150);
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* Total grid height
|
|
122
|
+
*/
|
|
123
|
+
const totalHeight = useMemo(() => {
|
|
124
|
+
if (layout === 'masonry') {
|
|
125
|
+
return Math.max(...(columnHeightsRef.current.length
|
|
126
|
+
? columnHeightsRef.current
|
|
127
|
+
: [0]));
|
|
128
|
+
}
|
|
129
|
+
const totalRows = Math.ceil(items.length / cols);
|
|
130
|
+
const maxItemHeight = Math.max(...Array.from({ length: items.length || 1 }, (_, i) => typeof rowHeight === 'function'
|
|
131
|
+
? rowHeight(i)
|
|
132
|
+
: rowHeight));
|
|
133
|
+
return totalRows * (maxItemHeight + gap);
|
|
134
|
+
}, [
|
|
135
|
+
items.length,
|
|
136
|
+
cols,
|
|
137
|
+
gap,
|
|
138
|
+
layout,
|
|
139
|
+
rowHeight,
|
|
140
|
+
]);
|
|
141
|
+
/**
|
|
142
|
+
* Container style
|
|
143
|
+
*/
|
|
144
|
+
const containerStyle = {
|
|
145
|
+
height,
|
|
146
|
+
width,
|
|
147
|
+
overflow: 'auto',
|
|
148
|
+
position: 'relative',
|
|
149
|
+
...style,
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* Grid wrapper style
|
|
153
|
+
*/
|
|
154
|
+
const gridStyle = {
|
|
155
|
+
position: 'relative',
|
|
156
|
+
height: totalHeight,
|
|
157
|
+
width: '100%',
|
|
158
|
+
};
|
|
159
|
+
return (_jsx("div", { ref: internalContainerRef, className: `virtualize-grid ${className}`, style: containerStyle, onScroll: handleScroll, children: _jsx("div", { style: gridStyle, className: "virtualize-grid-inner", children: items.map((item, index) => {
|
|
160
|
+
if (index < visibleRange.start ||
|
|
161
|
+
index >= visibleRange.end) {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
const position = positions[index];
|
|
165
|
+
if (!position) {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
const renderProps = {
|
|
169
|
+
item,
|
|
170
|
+
index,
|
|
171
|
+
style: {
|
|
172
|
+
position: 'absolute',
|
|
173
|
+
left: position.x,
|
|
174
|
+
top: position.y,
|
|
175
|
+
width: position.width,
|
|
176
|
+
height: position.height,
|
|
177
|
+
},
|
|
178
|
+
isScrolling,
|
|
179
|
+
};
|
|
180
|
+
const key = itemKey
|
|
181
|
+
? itemKey(index, item)
|
|
182
|
+
: index;
|
|
183
|
+
return (_jsx("div", { style: renderProps.style, "data-virtualize-index": index, children: renderItem(renderProps) }, key));
|
|
184
|
+
}) }) }));
|
|
185
|
+
});
|
|
186
|
+
VirtualGrid.displayName = 'VirtualGrid';
|
|
187
|
+
//# sourceMappingURL=VirtualGrid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VirtualGrid.js","sourceRoot":"","sources":["../../src/components/VirtualGrid.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { VirtualListProps } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* VirtualList Component
|
|
5
|
+
* Drop-in replacement for long lists with virtualization support
|
|
6
|
+
*/
|
|
7
|
+
export declare const VirtualList: React.ForwardRefExoticComponent<VirtualListProps<any> & React.RefAttributes<HTMLDivElement>>;
|
|
8
|
+
//# sourceMappingURL=VirtualList.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VirtualList.d.ts","sourceRoot":"","sources":["../../src/components/VirtualList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AAGf,OAAO,EAAE,gBAAgB,EAAmB,MAAM,UAAU,CAAC;AAE7D;;;GAGG;AACH,eAAO,MAAM,WAAW,8FAsLvB,CAAC"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, } from 'react';
|
|
3
|
+
import { useVirtualList } from '../hooks/useVirtualList';
|
|
4
|
+
/**
|
|
5
|
+
* VirtualList Component
|
|
6
|
+
* Drop-in replacement for long lists with virtualization support
|
|
7
|
+
*/
|
|
8
|
+
export const VirtualList = forwardRef(({ items, renderItem, itemKey, height = 400, width = 500, itemSize, overscan = 5, scrollDirection = 'forward', onScroll, className = '', style = {}, estimatedItemSize = 35, getItemSize, stickyIndices = [], onScrollEnd, innerRef, scrollOffsetRef, }, containerRef) => {
|
|
9
|
+
const { virtualItems, isScrolling, scrollOffset, totalSize, containerRef: internalContainerRef, innerRef: internalInnerRef, getItemStyle, } = useVirtualList({
|
|
10
|
+
items,
|
|
11
|
+
getItemKey: itemKey,
|
|
12
|
+
containerHeight: height,
|
|
13
|
+
containerWidth: width,
|
|
14
|
+
itemSize: getItemSize || itemSize,
|
|
15
|
+
overscan,
|
|
16
|
+
scrollDirection,
|
|
17
|
+
estimatedItemSize,
|
|
18
|
+
onScroll,
|
|
19
|
+
onScrollEnd,
|
|
20
|
+
stickyIndices,
|
|
21
|
+
// scrollMargin,
|
|
22
|
+
});
|
|
23
|
+
/**
|
|
24
|
+
* Local refs
|
|
25
|
+
*/
|
|
26
|
+
const mergedContainerRef = useRef(null);
|
|
27
|
+
const mergedInnerRef = useRef(null);
|
|
28
|
+
/**
|
|
29
|
+
* Expose refs to parent
|
|
30
|
+
*/
|
|
31
|
+
useImperativeHandle(containerRef, () => mergedContainerRef.current);
|
|
32
|
+
useImperativeHandle(innerRef, () => mergedInnerRef.current);
|
|
33
|
+
/**
|
|
34
|
+
* Expose scroll offset externally
|
|
35
|
+
*/
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
if (scrollOffsetRef) {
|
|
38
|
+
scrollOffsetRef.current = scrollOffset;
|
|
39
|
+
}
|
|
40
|
+
}, [scrollOffset, scrollOffsetRef]);
|
|
41
|
+
/**
|
|
42
|
+
* Store measured DOM elements
|
|
43
|
+
*/
|
|
44
|
+
const measurementRef = useRef(new Map());
|
|
45
|
+
const handleItemRef = useCallback((element, index) => {
|
|
46
|
+
if (element) {
|
|
47
|
+
measurementRef.current.set(index, element);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
measurementRef.current.delete(index);
|
|
51
|
+
}
|
|
52
|
+
}, []);
|
|
53
|
+
/**
|
|
54
|
+
* Container styles
|
|
55
|
+
*/
|
|
56
|
+
const containerStyle = {
|
|
57
|
+
height,
|
|
58
|
+
width,
|
|
59
|
+
overflow: 'auto',
|
|
60
|
+
position: 'relative',
|
|
61
|
+
...style,
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Inner wrapper styles
|
|
65
|
+
*/
|
|
66
|
+
const innerStyle = {
|
|
67
|
+
position: 'relative',
|
|
68
|
+
height: totalSize,
|
|
69
|
+
width: '100%',
|
|
70
|
+
};
|
|
71
|
+
return (_jsx("div", { ref: (el) => {
|
|
72
|
+
mergedContainerRef.current = el;
|
|
73
|
+
internalContainerRef.current = el;
|
|
74
|
+
}, className: `virtualize-container ${className}`, style: containerStyle, onScroll: (e) => {
|
|
75
|
+
const handler = renderItem?.__scrollHandler;
|
|
76
|
+
if (handler) {
|
|
77
|
+
handler(e);
|
|
78
|
+
}
|
|
79
|
+
if (onScroll) {
|
|
80
|
+
onScroll(e.target.scrollTop, "auto");
|
|
81
|
+
}
|
|
82
|
+
}, children: _jsx("div", { ref: (el) => {
|
|
83
|
+
mergedInnerRef.current = el;
|
|
84
|
+
internalInnerRef.current = el;
|
|
85
|
+
}, style: innerStyle, className: "virtualize-inner", children: virtualItems.map((virtualItem) => {
|
|
86
|
+
const item = items[virtualItem.index];
|
|
87
|
+
const key = itemKey
|
|
88
|
+
? itemKey(virtualItem.index, item)
|
|
89
|
+
: virtualItem.index;
|
|
90
|
+
const renderProps = {
|
|
91
|
+
item,
|
|
92
|
+
index: virtualItem.index,
|
|
93
|
+
style: getItemStyle(virtualItem.index, virtualItem.size),
|
|
94
|
+
isScrolling,
|
|
95
|
+
};
|
|
96
|
+
return (_jsx("div", { ref: (el) => {
|
|
97
|
+
handleItemRef(el, virtualItem.index);
|
|
98
|
+
}, style: renderProps.style, "data-virtualize-index": virtualItem.index, children: renderItem(renderProps) }, key));
|
|
99
|
+
}) }) }));
|
|
100
|
+
});
|
|
101
|
+
VirtualList.displayName = 'VirtualList';
|
|
102
|
+
//# sourceMappingURL=VirtualList.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VirtualList.js","sourceRoot":"","sources":["../../src/components/VirtualList.tsx"],"names":[],"mappings":";AAAA,OAAc,EACV,UAAU,EACV,WAAW,EACX,SAAS,EACT,mBAAmB,EACnB,MAAM,GACT,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAGzD;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,UAAU,CAIjC,CACI,EACI,KAAK,EACL,UAAU,EACV,OAAO,EACP,MAAM,GAAG,GAAG,EACZ,KAAK,GAAG,GAAG,EACX,QAAQ,EACR,QAAQ,GAAG,CAAC,EACZ,eAAe,GAAG,SAAS,EAC3B,QAAQ,EACR,SAAS,GAAG,EAAE,EACd,KAAK,GAAG,EAAE,EACV,iBAAiB,GAAG,EAAE,EACtB,WAAW,EACX,aAAa,GAAG,EAAE,EAClB,WAAW,EACX,QAAQ,EACR,eAAe,GAClB,EACD,YAAY,EACd,EAAE;IACA,MAAM,EACF,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,SAAS,EACT,YAAY,EAAE,oBAAoB,EAClC,QAAQ,EAAE,gBAAgB,EAC1B,YAAY,GACf,GAAG,cAAc,CAAC;QACf,KAAK;QACL,UAAU,EAAE,OAAO;QACnB,eAAe,EAAE,MAAM;QACvB,cAAc,EAAE,KAAK;QACrB,QAAQ,EAAE,WAAW,IAAI,QAAQ;QACjC,QAAQ;QACR,eAAe;QACf,iBAAiB;QACjB,QAAQ;QACR,WAAW;QACX,aAAa;QACb,gBAAgB;KACnB,CAAC,CAAC;IAEH;;OAEG;IACH,MAAM,kBAAkB,GAAG,MAAM,CAAwB,IAAI,CAAC,CAAC;IAC/D,MAAM,cAAc,GAAG,MAAM,CAAwB,IAAI,CAAC,CAAC;IAE3D;;OAEG;IACH,mBAAmB,CACf,YAAY,EACZ,GAAG,EAAE,CAAC,kBAAkB,CAAC,OAAyB,CACrD,CAAC;IAEF,mBAAmB,CACf,QAAQ,EACR,GAAG,EAAE,CAAC,cAAc,CAAC,OAAyB,CACjD,CAAC;IAEF;;OAEG;IACH,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,eAAe,EAAE;YACjB,eAAe,CAAC,OAAO,GAAG,YAAY,CAAC;SAC1C;IACL,CAAC,EAAE,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC,CAAC;IAEpC;;OAEG;IACH,MAAM,cAAc,GAAG,MAAM,CACzB,IAAI,GAAG,EAAE,CACZ,CAAC;IAEF,MAAM,aAAa,GAAG,WAAW,CAC7B,CAAC,OAA2B,EAAE,KAAa,EAAE,EAAE;QAC3C,IAAI,OAAO,EAAE;YACT,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;SAC9C;aAAM;YACH,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;SACxC;IACL,CAAC,EACD,EAAE,CACL,CAAC;IAEF;;OAEG;IACH,MAAM,cAAc,GAAwB;QACxC,MAAM;QACN,KAAK;QACL,QAAQ,EAAE,MAAM;QAChB,QAAQ,EAAE,UAAU;QACpB,GAAG,KAAK;KACX,CAAC;IAEF;;OAEG;IACH,MAAM,UAAU,GAAwB;QACpC,QAAQ,EAAE,UAAU;QACpB,MAAM,EAAE,SAAS;QACjB,KAAK,EAAE,MAAM;KAChB,CAAC;IAEF,OAAO,CACH,cACI,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE;YACR,kBAAkB,CAAC,OAAO,GAAG,EAAE,CAAC;YAChC,oBAAoB,CAAC,OAAO,GAAG,EAAE,CAAC;QACtC,CAAC,EACD,SAAS,EAAE,wBAAwB,SAAS,EAAE,EAC9C,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE;YACZ,MAAM,OAAO,GAAI,UAAkB,EAAE,eAAe,CAAC;YAErD,IAAI,OAAO,EAAE;gBACT,OAAO,CAAC,CAAC,CAAC,CAAC;aACd;YAED,IAAI,QAAQ,EAAE;gBACV,QAAQ,CAAE,CAAC,CAAC,MAAsB,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;aACzD;QACL,CAAC,YAED,cACI,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE;gBACR,cAAc,CAAC,OAAO,GAAG,EAAE,CAAC;gBAC5B,gBAAgB,CAAC,OAAO,GAAG,EAAE,CAAC;YAClC,CAAC,EACD,KAAK,EAAE,UAAU,EACjB,SAAS,EAAC,kBAAkB,YAE3B,YAAY,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE;gBAC9B,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;gBAEtC,MAAM,GAAG,GAAG,OAAO;oBACf,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC;oBAClC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC;gBAExB,MAAM,WAAW,GAAyB;oBACtC,IAAI;oBACJ,KAAK,EAAE,WAAW,CAAC,KAAK;oBACxB,KAAK,EAAE,YAAY,CACf,WAAW,CAAC,KAAK,EACjB,WAAW,CAAC,IAAI,CACnB;oBACD,WAAW;iBACd,CAAC;gBAEF,OAAO,CACH,cAEI,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE;wBACR,aAAa,CACT,EAAE,EACF,WAAW,CAAC,KAAK,CACpB,CAAC;oBACN,CAAC,EACD,KAAK,EAAE,WAAW,CAAC,KAAK,2BAEpB,WAAW,CAAC,KAAK,YAGpB,UAAU,CAAC,WAAW,CAAC,IAZnB,GAAG,CAaN,CACT,CAAC;YACN,CAAC,CAAC,GACA,GACJ,CACT,CAAC;AACN,CAAC,CACJ,CAAC;AAEF,WAAW,CAAC,WAAW,GAAG,aAAa,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handles automatic measurement of item sizes using ResizeObserver
|
|
3
|
+
* Integrates with VirtualizationEngine to track dynamic sizes
|
|
4
|
+
*/
|
|
5
|
+
export declare class MeasurementSystem {
|
|
6
|
+
private resizeObserver;
|
|
7
|
+
private measurements;
|
|
8
|
+
private pendingMeasurements;
|
|
9
|
+
private onMeasure;
|
|
10
|
+
constructor();
|
|
11
|
+
/**
|
|
12
|
+
* Start measuring items in a container
|
|
13
|
+
*/
|
|
14
|
+
startMeasuring(container: HTMLElement, onMeasure: (index: number, size: number) => void): void;
|
|
15
|
+
/**
|
|
16
|
+
* Stop measuring
|
|
17
|
+
*/
|
|
18
|
+
stopMeasuring(): void;
|
|
19
|
+
/**
|
|
20
|
+
* Handle ResizeObserver callback
|
|
21
|
+
*/
|
|
22
|
+
private handleResize;
|
|
23
|
+
/**
|
|
24
|
+
* Observe a new item
|
|
25
|
+
*/
|
|
26
|
+
observeItem(index: number, element: HTMLElement): void;
|
|
27
|
+
/**
|
|
28
|
+
* Synchronous measurement (fallback for ResizeObserver)
|
|
29
|
+
*/
|
|
30
|
+
syncMeasure(index: number, element: HTMLElement): void;
|
|
31
|
+
/**
|
|
32
|
+
* Unobserve a specific item
|
|
33
|
+
*/
|
|
34
|
+
unobserveItem(element: HTMLElement): void;
|
|
35
|
+
/**
|
|
36
|
+
* Get measured size for an item
|
|
37
|
+
*/
|
|
38
|
+
getMeasurement(index: number): number | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* Get all measurements
|
|
41
|
+
*/
|
|
42
|
+
getAllMeasurements(): Map<number, number>;
|
|
43
|
+
/**
|
|
44
|
+
* Clear pending measurements
|
|
45
|
+
*/
|
|
46
|
+
clearPending(): void;
|
|
47
|
+
/**
|
|
48
|
+
* Cleanup on unmount
|
|
49
|
+
*/
|
|
50
|
+
destroy(): void;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=MeasurementSystem.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MeasurementSystem.d.ts","sourceRoot":"","sources":["../../src/core/MeasurementSystem.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,iBAAiB;IAC1B,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,mBAAmB,CAA0B;IACrD,OAAO,CAAC,SAAS,CAAwD;;IAQzE;;OAEG;IACH,cAAc,CACV,SAAS,EAAE,WAAW,EACtB,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,GACjD,IAAI;IAYP;;OAEG;IACH,aAAa,IAAI,IAAI;IAQrB;;OAEG;IACH,OAAO,CAAC,YAAY;IAsBpB;;OAEG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI;IAWtD;;OAEG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI;IAUtD;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAMzC;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIjD;;OAEG;IACH,kBAAkB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAIzC;;OAEG;IACH,YAAY,IAAI,IAAI;IAIpB;;OAEG;IACH,OAAO,IAAI,IAAI;CAMlB"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handles automatic measurement of item sizes using ResizeObserver
|
|
3
|
+
* Integrates with VirtualizationEngine to track dynamic sizes
|
|
4
|
+
*/
|
|
5
|
+
export class MeasurementSystem {
|
|
6
|
+
constructor() {
|
|
7
|
+
Object.defineProperty(this, "resizeObserver", {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
configurable: true,
|
|
10
|
+
writable: true,
|
|
11
|
+
value: null
|
|
12
|
+
});
|
|
13
|
+
Object.defineProperty(this, "measurements", {
|
|
14
|
+
enumerable: true,
|
|
15
|
+
configurable: true,
|
|
16
|
+
writable: true,
|
|
17
|
+
value: new Map()
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(this, "pendingMeasurements", {
|
|
20
|
+
enumerable: true,
|
|
21
|
+
configurable: true,
|
|
22
|
+
writable: true,
|
|
23
|
+
value: new Set()
|
|
24
|
+
});
|
|
25
|
+
Object.defineProperty(this, "onMeasure", {
|
|
26
|
+
enumerable: true,
|
|
27
|
+
configurable: true,
|
|
28
|
+
writable: true,
|
|
29
|
+
value: null
|
|
30
|
+
});
|
|
31
|
+
if (typeof window !== 'undefined' && 'ResizeObserver' in window) {
|
|
32
|
+
this.resizeObserver = new ResizeObserver(this.handleResize.bind(this));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Start measuring items in a container
|
|
37
|
+
*/
|
|
38
|
+
startMeasuring(container, onMeasure) {
|
|
39
|
+
this.onMeasure = onMeasure;
|
|
40
|
+
if (this.resizeObserver) {
|
|
41
|
+
// Observe all current items
|
|
42
|
+
const items = container.querySelectorAll('[data-virtualize-index]');
|
|
43
|
+
items.forEach((item) => {
|
|
44
|
+
this.resizeObserver?.observe(item);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Stop measuring
|
|
50
|
+
*/
|
|
51
|
+
stopMeasuring() {
|
|
52
|
+
if (this.resizeObserver) {
|
|
53
|
+
this.resizeObserver.disconnect();
|
|
54
|
+
}
|
|
55
|
+
this.measurements.clear();
|
|
56
|
+
this.pendingMeasurements.clear();
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Handle ResizeObserver callback
|
|
60
|
+
*/
|
|
61
|
+
handleResize(entries) {
|
|
62
|
+
entries.forEach((entry) => {
|
|
63
|
+
const element = entry.target;
|
|
64
|
+
const index = element.getAttribute('data-virtualize-index');
|
|
65
|
+
if (index) {
|
|
66
|
+
const size = entry.contentRect.height || element.offsetHeight;
|
|
67
|
+
const indexNum = parseInt(index, 10);
|
|
68
|
+
// Only trigger update if size changed
|
|
69
|
+
if (this.measurements.get(indexNum) !== size) {
|
|
70
|
+
this.measurements.set(indexNum, size);
|
|
71
|
+
this.pendingMeasurements.add(indexNum);
|
|
72
|
+
if (this.onMeasure) {
|
|
73
|
+
this.onMeasure(indexNum, size);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Observe a new item
|
|
81
|
+
*/
|
|
82
|
+
observeItem(index, element) {
|
|
83
|
+
element.setAttribute('data-virtualize-index', String(index));
|
|
84
|
+
if (this.resizeObserver) {
|
|
85
|
+
this.resizeObserver.observe(element);
|
|
86
|
+
}
|
|
87
|
+
// Immediate synchronous measurement as fallback
|
|
88
|
+
this.syncMeasure(index, element);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Synchronous measurement (fallback for ResizeObserver)
|
|
92
|
+
*/
|
|
93
|
+
syncMeasure(index, element) {
|
|
94
|
+
const size = element.offsetHeight;
|
|
95
|
+
if (size > 0 && this.measurements.get(index) !== size) {
|
|
96
|
+
this.measurements.set(index, size);
|
|
97
|
+
if (this.onMeasure) {
|
|
98
|
+
this.onMeasure(index, size);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Unobserve a specific item
|
|
104
|
+
*/
|
|
105
|
+
unobserveItem(element) {
|
|
106
|
+
if (this.resizeObserver) {
|
|
107
|
+
this.resizeObserver.unobserve(element);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Get measured size for an item
|
|
112
|
+
*/
|
|
113
|
+
getMeasurement(index) {
|
|
114
|
+
return this.measurements.get(index);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Get all measurements
|
|
118
|
+
*/
|
|
119
|
+
getAllMeasurements() {
|
|
120
|
+
return new Map(this.measurements);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Clear pending measurements
|
|
124
|
+
*/
|
|
125
|
+
clearPending() {
|
|
126
|
+
this.pendingMeasurements.clear();
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Cleanup on unmount
|
|
130
|
+
*/
|
|
131
|
+
destroy() {
|
|
132
|
+
this.stopMeasuring();
|
|
133
|
+
this.measurements.clear();
|
|
134
|
+
this.pendingMeasurements.clear();
|
|
135
|
+
this.onMeasure = null;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=MeasurementSystem.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MeasurementSystem.js","sourceRoot":"","sources":["../../src/core/MeasurementSystem.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { ItemSize, VirtualRange, MeasurementCache, ScrollDirection } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Core virtualization engine
|
|
4
|
+
* Handles:
|
|
5
|
+
* - visible range calculation
|
|
6
|
+
* - dynamic item sizing
|
|
7
|
+
* - item measurements
|
|
8
|
+
* - scroll positioning
|
|
9
|
+
*/
|
|
10
|
+
export declare class VirtualizationEngine {
|
|
11
|
+
private itemSizeMap;
|
|
12
|
+
private itemOffsets;
|
|
13
|
+
private totalSize;
|
|
14
|
+
private estimatedItemSize;
|
|
15
|
+
constructor(estimatedItemSize?: number);
|
|
16
|
+
/**
|
|
17
|
+
* Record measured item size
|
|
18
|
+
*/
|
|
19
|
+
recordItemSize(index: number, size: number): void;
|
|
20
|
+
/**
|
|
21
|
+
* Recalculate item offsets
|
|
22
|
+
*/
|
|
23
|
+
private recalculateOffsets;
|
|
24
|
+
/**
|
|
25
|
+
* Get item size
|
|
26
|
+
*/
|
|
27
|
+
getItemSize(index: number): number;
|
|
28
|
+
/**
|
|
29
|
+
* Get item offset
|
|
30
|
+
*/
|
|
31
|
+
getItemOffset(index: number): number;
|
|
32
|
+
/**
|
|
33
|
+
* Get total size
|
|
34
|
+
*/
|
|
35
|
+
getTotalSize(): number;
|
|
36
|
+
/**
|
|
37
|
+
* Calculate visible range
|
|
38
|
+
*/
|
|
39
|
+
getVisibleRange(scrollOffset: number, containerSize: number, itemCount: number, overscan?: number, scrollDirection?: ScrollDirection): VirtualRange;
|
|
40
|
+
/**
|
|
41
|
+
* Reverse scrolling support
|
|
42
|
+
*/
|
|
43
|
+
private getVisibleRangeReverse;
|
|
44
|
+
/**
|
|
45
|
+
* Get visible items
|
|
46
|
+
*/
|
|
47
|
+
getVisibleItems(scrollOffset: number, containerSize: number, itemCount: number, overscan: number, scrollDirection?: ScrollDirection): ItemSize[];
|
|
48
|
+
/**
|
|
49
|
+
* Scroll offset for item index
|
|
50
|
+
*/
|
|
51
|
+
getScrollOffsetForIndex(index: number, containerSize: number, alignment?: 'start' | 'center' | 'end'): number;
|
|
52
|
+
/**
|
|
53
|
+
* Clear cache
|
|
54
|
+
*/
|
|
55
|
+
clearCache(): void;
|
|
56
|
+
/**
|
|
57
|
+
* Get cache
|
|
58
|
+
*/
|
|
59
|
+
getCache(): MeasurementCache;
|
|
60
|
+
/**
|
|
61
|
+
* Adaptive overscan
|
|
62
|
+
*/
|
|
63
|
+
getAdaptiveOverscan(scrollVelocity: number, baseOverscan?: number): number;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=VirtualizationEngine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VirtualizationEngine.d.ts","sourceRoot":"","sources":["../../src/core/VirtualizationEngine.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,QAAQ,EACR,YAAY,EACZ,gBAAgB,EAChB,eAAe,EAClB,MAAM,UAAU,CAAC;AAElB;;;;;;;GAOG;AACH,qBAAa,oBAAoB;IAC7B,OAAO,CAAC,WAAW,CAAwB;IAE3C,OAAO,CAAC,WAAW,CAAiB;IAEpC,OAAO,CAAC,SAAS,CAAK;IAEtB,OAAO,CAAC,iBAAiB,CAAS;gBAEtB,iBAAiB,GAAE,MAAW;IAI1C;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAUjD;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAsB1B;;OAEG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAOlC;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAcpC;;OAEG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;IACH,eAAe,CACX,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,EACjB,QAAQ,GAAE,MAAU,EACpB,eAAe,GAAE,eAA2B,GAC7C,YAAY;IAoEf;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAwB9B;;OAEG;IACH,eAAe,CACX,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,eAAe,GAAE,eAA2B,GAC7C,QAAQ,EAAE;IA2Bb;;OAEG;IACH,uBAAuB,CACnB,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,EACrB,SAAS,GACH,OAAO,GACP,QAAQ,GACR,KAAe,GACtB,MAAM;IA+BT;;OAEG;IACH,UAAU,IAAI,IAAI;IAQlB;;OAEG;IACH,QAAQ,IAAI,gBAAgB;IAM5B;;OAEG;IACH,mBAAmB,CACf,cAAc,EAAE,MAAM,EACtB,YAAY,GAAE,MAAU,GACzB,MAAM;CAUZ"}
|