clear-virtualizer 0.1.2 → 0.1.4
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/lib/index.cjs +59 -46
- package/lib/index.js +59 -46
- package/package.json +1 -1
package/lib/index.cjs
CHANGED
|
@@ -111,6 +111,7 @@ function useVirtualizer({ count, estimateSize, overscan = DEFAULT_OVERSCAN }) {
|
|
|
111
111
|
const [scrollOffset, setScrollOffset] = react.useState({ value: 0 });
|
|
112
112
|
const [forcedRange, setForcedRange] = react.useState(null);
|
|
113
113
|
const scrollElementRef = react.useRef(null);
|
|
114
|
+
const [scrollElement, setScrollElement] = react.useState(null);
|
|
114
115
|
const rafRef = react.useRef(null);
|
|
115
116
|
const observersRef = react.useRef(/* @__PURE__ */ new Map());
|
|
116
117
|
const containerObserverRef = react.useRef(null);
|
|
@@ -128,7 +129,18 @@ function useVirtualizer({ count, estimateSize, overscan = DEFAULT_OVERSCAN }) {
|
|
|
128
129
|
if (fenwickRef.current === null || !fenwickRef.current.total())
|
|
129
130
|
fenwickRef.current = getFenwickTree(count, estimateSize);
|
|
130
131
|
if (prevCountRef.current !== count) {
|
|
131
|
-
fenwickRef.current
|
|
132
|
+
const prevTree = fenwickRef.current;
|
|
133
|
+
const prevCount = prevCountRef.current;
|
|
134
|
+
const nextTree = getFenwickTree(count, estimateSize);
|
|
135
|
+
if (prevTree && prevCount > 0) {
|
|
136
|
+
const keep = Math.min(prevCount, count);
|
|
137
|
+
for (let i = 0; i < keep; i++) {
|
|
138
|
+
const delta = prevTree.prefixSum(i + 1) - prevTree.prefixSum(i) - (nextTree.prefixSum(i + 1) - nextTree.prefixSum(i));
|
|
139
|
+
if (delta !== 0)
|
|
140
|
+
nextTree.update(i, delta);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
fenwickRef.current = nextTree;
|
|
132
144
|
prevCountRef.current = count;
|
|
133
145
|
}
|
|
134
146
|
const computeItems = react.useCallback(
|
|
@@ -188,22 +200,7 @@ function useVirtualizer({ count, estimateSize, overscan = DEFAULT_OVERSCAN }) {
|
|
|
188
200
|
},
|
|
189
201
|
[count, forcedRange, overscan]
|
|
190
202
|
);
|
|
191
|
-
const
|
|
192
|
-
if (!element) {
|
|
193
|
-
const entry = observersRef.current.get(index);
|
|
194
|
-
if (entry) {
|
|
195
|
-
entry.observer.disconnect();
|
|
196
|
-
observersRef.current.delete(index);
|
|
197
|
-
}
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
const existing = observersRef.current.get(index);
|
|
201
|
-
if (existing && existing.element === element)
|
|
202
|
-
return;
|
|
203
|
-
if (existing) {
|
|
204
|
-
existing.observer.disconnect();
|
|
205
|
-
observersRef.current.delete(index);
|
|
206
|
-
}
|
|
203
|
+
const observeItem = react.useCallback((index, element) => {
|
|
207
204
|
if (typeof ResizeObserver === "undefined")
|
|
208
205
|
return;
|
|
209
206
|
const observer = new ResizeObserver(([entry]) => {
|
|
@@ -223,6 +220,27 @@ function useVirtualizer({ count, estimateSize, overscan = DEFAULT_OVERSCAN }) {
|
|
|
223
220
|
observer.observe(element);
|
|
224
221
|
observersRef.current.set(index, { observer, element });
|
|
225
222
|
}, []);
|
|
223
|
+
const measureElement = react.useCallback(
|
|
224
|
+
(element, index) => {
|
|
225
|
+
if (!element) {
|
|
226
|
+
const entry = observersRef.current.get(index);
|
|
227
|
+
if (entry) {
|
|
228
|
+
entry.observer.disconnect();
|
|
229
|
+
observersRef.current.delete(index);
|
|
230
|
+
}
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
const existing = observersRef.current.get(index);
|
|
234
|
+
if (existing && existing.element === element)
|
|
235
|
+
return;
|
|
236
|
+
if (existing) {
|
|
237
|
+
existing.observer.disconnect();
|
|
238
|
+
observersRef.current.delete(index);
|
|
239
|
+
}
|
|
240
|
+
observeItem(index, element);
|
|
241
|
+
},
|
|
242
|
+
[observeItem]
|
|
243
|
+
);
|
|
226
244
|
const getMeasureRef = react.useCallback(
|
|
227
245
|
(index) => {
|
|
228
246
|
let fn = refCacheRef.current.get(index);
|
|
@@ -352,42 +370,37 @@ function useVirtualizer({ count, estimateSize, overscan = DEFAULT_OVERSCAN }) {
|
|
|
352
370
|
setScrollOffset({ value: el.scrollTop });
|
|
353
371
|
});
|
|
354
372
|
}, [releaseSettle, countRef]);
|
|
355
|
-
const scrollRef = react.useCallback(
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
373
|
+
const scrollRef = react.useCallback((element) => {
|
|
374
|
+
scrollElementRef.current = element;
|
|
375
|
+
setScrollElement(element);
|
|
376
|
+
setScrollOffset(element ? { value: element.scrollTop } : { value: 0 });
|
|
377
|
+
}, []);
|
|
378
|
+
react.useEffect(() => {
|
|
379
|
+
const el = scrollElement;
|
|
380
|
+
const itemObservers = observersRef.current;
|
|
381
|
+
if (el) {
|
|
382
|
+
el.addEventListener("scroll", handleScroll, { passive: true });
|
|
383
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
384
|
+
const observer = new ResizeObserver(() => {
|
|
385
|
+
setScrollOffset((prevState) => ({ ...prevState }));
|
|
386
|
+
});
|
|
387
|
+
observer.observe(el);
|
|
388
|
+
containerObserverRef.current = observer;
|
|
371
389
|
}
|
|
372
|
-
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
react.useEffect(
|
|
377
|
-
() => () => {
|
|
390
|
+
}
|
|
391
|
+
for (const [index, { element }] of Array.from(itemObservers))
|
|
392
|
+
observeItem(index, element);
|
|
393
|
+
return () => {
|
|
378
394
|
if (rafRef.current !== null)
|
|
379
395
|
cancelAnimationFrame(rafRef.current);
|
|
380
396
|
if (tickRafRef.current !== null)
|
|
381
397
|
cancelAnimationFrame(tickRafRef.current);
|
|
382
|
-
|
|
383
|
-
observersRef.current.clear();
|
|
398
|
+
el?.removeEventListener("scroll", handleScroll);
|
|
384
399
|
containerObserverRef.current?.disconnect();
|
|
385
400
|
containerObserverRef.current = null;
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
[handleScroll]
|
|
390
|
-
);
|
|
401
|
+
itemObservers.forEach((entry) => entry.observer.disconnect());
|
|
402
|
+
};
|
|
403
|
+
}, [scrollElement, handleScroll, observeItem]);
|
|
391
404
|
const { virtualItems, scrollHeight } = react.useMemo(
|
|
392
405
|
() => computeItems(scrollOffset.value),
|
|
393
406
|
[computeItems, scrollOffset]
|
package/lib/index.js
CHANGED
|
@@ -109,6 +109,7 @@ function useVirtualizer({ count, estimateSize, overscan = DEFAULT_OVERSCAN }) {
|
|
|
109
109
|
const [scrollOffset, setScrollOffset] = useState({ value: 0 });
|
|
110
110
|
const [forcedRange, setForcedRange] = useState(null);
|
|
111
111
|
const scrollElementRef = useRef(null);
|
|
112
|
+
const [scrollElement, setScrollElement] = useState(null);
|
|
112
113
|
const rafRef = useRef(null);
|
|
113
114
|
const observersRef = useRef(/* @__PURE__ */ new Map());
|
|
114
115
|
const containerObserverRef = useRef(null);
|
|
@@ -126,7 +127,18 @@ function useVirtualizer({ count, estimateSize, overscan = DEFAULT_OVERSCAN }) {
|
|
|
126
127
|
if (fenwickRef.current === null || !fenwickRef.current.total())
|
|
127
128
|
fenwickRef.current = getFenwickTree(count, estimateSize);
|
|
128
129
|
if (prevCountRef.current !== count) {
|
|
129
|
-
fenwickRef.current
|
|
130
|
+
const prevTree = fenwickRef.current;
|
|
131
|
+
const prevCount = prevCountRef.current;
|
|
132
|
+
const nextTree = getFenwickTree(count, estimateSize);
|
|
133
|
+
if (prevTree && prevCount > 0) {
|
|
134
|
+
const keep = Math.min(prevCount, count);
|
|
135
|
+
for (let i = 0; i < keep; i++) {
|
|
136
|
+
const delta = prevTree.prefixSum(i + 1) - prevTree.prefixSum(i) - (nextTree.prefixSum(i + 1) - nextTree.prefixSum(i));
|
|
137
|
+
if (delta !== 0)
|
|
138
|
+
nextTree.update(i, delta);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
fenwickRef.current = nextTree;
|
|
130
142
|
prevCountRef.current = count;
|
|
131
143
|
}
|
|
132
144
|
const computeItems = useCallback(
|
|
@@ -186,22 +198,7 @@ function useVirtualizer({ count, estimateSize, overscan = DEFAULT_OVERSCAN }) {
|
|
|
186
198
|
},
|
|
187
199
|
[count, forcedRange, overscan]
|
|
188
200
|
);
|
|
189
|
-
const
|
|
190
|
-
if (!element) {
|
|
191
|
-
const entry = observersRef.current.get(index);
|
|
192
|
-
if (entry) {
|
|
193
|
-
entry.observer.disconnect();
|
|
194
|
-
observersRef.current.delete(index);
|
|
195
|
-
}
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
const existing = observersRef.current.get(index);
|
|
199
|
-
if (existing && existing.element === element)
|
|
200
|
-
return;
|
|
201
|
-
if (existing) {
|
|
202
|
-
existing.observer.disconnect();
|
|
203
|
-
observersRef.current.delete(index);
|
|
204
|
-
}
|
|
201
|
+
const observeItem = useCallback((index, element) => {
|
|
205
202
|
if (typeof ResizeObserver === "undefined")
|
|
206
203
|
return;
|
|
207
204
|
const observer = new ResizeObserver(([entry]) => {
|
|
@@ -221,6 +218,27 @@ function useVirtualizer({ count, estimateSize, overscan = DEFAULT_OVERSCAN }) {
|
|
|
221
218
|
observer.observe(element);
|
|
222
219
|
observersRef.current.set(index, { observer, element });
|
|
223
220
|
}, []);
|
|
221
|
+
const measureElement = useCallback(
|
|
222
|
+
(element, index) => {
|
|
223
|
+
if (!element) {
|
|
224
|
+
const entry = observersRef.current.get(index);
|
|
225
|
+
if (entry) {
|
|
226
|
+
entry.observer.disconnect();
|
|
227
|
+
observersRef.current.delete(index);
|
|
228
|
+
}
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
const existing = observersRef.current.get(index);
|
|
232
|
+
if (existing && existing.element === element)
|
|
233
|
+
return;
|
|
234
|
+
if (existing) {
|
|
235
|
+
existing.observer.disconnect();
|
|
236
|
+
observersRef.current.delete(index);
|
|
237
|
+
}
|
|
238
|
+
observeItem(index, element);
|
|
239
|
+
},
|
|
240
|
+
[observeItem]
|
|
241
|
+
);
|
|
224
242
|
const getMeasureRef = useCallback(
|
|
225
243
|
(index) => {
|
|
226
244
|
let fn = refCacheRef.current.get(index);
|
|
@@ -350,42 +368,37 @@ function useVirtualizer({ count, estimateSize, overscan = DEFAULT_OVERSCAN }) {
|
|
|
350
368
|
setScrollOffset({ value: el.scrollTop });
|
|
351
369
|
});
|
|
352
370
|
}, [releaseSettle, countRef]);
|
|
353
|
-
const scrollRef = useCallback(
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
});
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
371
|
+
const scrollRef = useCallback((element) => {
|
|
372
|
+
scrollElementRef.current = element;
|
|
373
|
+
setScrollElement(element);
|
|
374
|
+
setScrollOffset(element ? { value: element.scrollTop } : { value: 0 });
|
|
375
|
+
}, []);
|
|
376
|
+
useEffect(() => {
|
|
377
|
+
const el = scrollElement;
|
|
378
|
+
const itemObservers = observersRef.current;
|
|
379
|
+
if (el) {
|
|
380
|
+
el.addEventListener("scroll", handleScroll, { passive: true });
|
|
381
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
382
|
+
const observer = new ResizeObserver(() => {
|
|
383
|
+
setScrollOffset((prevState) => ({ ...prevState }));
|
|
384
|
+
});
|
|
385
|
+
observer.observe(el);
|
|
386
|
+
containerObserverRef.current = observer;
|
|
369
387
|
}
|
|
370
|
-
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
useEffect(
|
|
375
|
-
() => () => {
|
|
388
|
+
}
|
|
389
|
+
for (const [index, { element }] of Array.from(itemObservers))
|
|
390
|
+
observeItem(index, element);
|
|
391
|
+
return () => {
|
|
376
392
|
if (rafRef.current !== null)
|
|
377
393
|
cancelAnimationFrame(rafRef.current);
|
|
378
394
|
if (tickRafRef.current !== null)
|
|
379
395
|
cancelAnimationFrame(tickRafRef.current);
|
|
380
|
-
|
|
381
|
-
observersRef.current.clear();
|
|
396
|
+
el?.removeEventListener("scroll", handleScroll);
|
|
382
397
|
containerObserverRef.current?.disconnect();
|
|
383
398
|
containerObserverRef.current = null;
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
[handleScroll]
|
|
388
|
-
);
|
|
399
|
+
itemObservers.forEach((entry) => entry.observer.disconnect());
|
|
400
|
+
};
|
|
401
|
+
}, [scrollElement, handleScroll, observeItem]);
|
|
389
402
|
const { virtualItems, scrollHeight } = useMemo(
|
|
390
403
|
() => computeItems(scrollOffset.value),
|
|
391
404
|
[computeItems, scrollOffset]
|
package/package.json
CHANGED