cogsbox-state 0.5.376 → 0.5.377
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/dist/CogsState.jsx +670 -675
- package/dist/CogsState.jsx.map +1 -1
- package/package.json +1 -1
- package/src/CogsState.tsx +29 -48
package/package.json
CHANGED
package/src/CogsState.tsx
CHANGED
|
@@ -1827,8 +1827,7 @@ function createProxyHandler<T>(
|
|
|
1827
1827
|
const isProgrammaticScroll = useRef(false);
|
|
1828
1828
|
const prevTotalCountRef = useRef(0);
|
|
1829
1829
|
const prevDepsRef = useRef(dependencies);
|
|
1830
|
-
const
|
|
1831
|
-
|
|
1830
|
+
const lastUpdateAtScrollTop = useRef(0);
|
|
1832
1831
|
const [shadowUpdateTrigger, setShadowUpdateTrigger] = useState(0);
|
|
1833
1832
|
|
|
1834
1833
|
useEffect(() => {
|
|
@@ -2001,71 +2000,50 @@ function createProxyHandler<T>(
|
|
|
2001
2000
|
const container = containerRef.current;
|
|
2002
2001
|
if (!container) return;
|
|
2003
2002
|
|
|
2004
|
-
//
|
|
2003
|
+
// The scroll distance threshold. One item's height is a great default.
|
|
2004
|
+
const scrollThreshold = itemHeight;
|
|
2005
2005
|
|
|
2006
2006
|
const handleUserScroll = () => {
|
|
2007
|
-
// Essential
|
|
2007
|
+
// Essential guard for our own programmatic scrolls.
|
|
2008
2008
|
if (isProgrammaticScroll.current) {
|
|
2009
2009
|
return;
|
|
2010
2010
|
}
|
|
2011
2011
|
|
|
2012
|
-
const
|
|
2013
|
-
|
|
2014
|
-
// --- Part 1: Quick state update logic (still important) ---
|
|
2015
|
-
const isAtBottom =
|
|
2016
|
-
container.scrollHeight -
|
|
2017
|
-
scrollTop -
|
|
2018
|
-
container.clientHeight <
|
|
2019
|
-
1;
|
|
2012
|
+
const scrollTop = container.scrollTop;
|
|
2020
2013
|
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2014
|
+
// --- THE CORE LOGIC YOU REQUESTED ---
|
|
2015
|
+
// Is the user just wiggling the scrollbar? If so, exit.
|
|
2016
|
+
// This is a very cheap check that runs on every scroll event.
|
|
2017
|
+
if (
|
|
2018
|
+
Math.abs(scrollTop - lastUpdateAtScrollTop.current) <
|
|
2019
|
+
scrollThreshold
|
|
2020
|
+
) {
|
|
2021
|
+
return;
|
|
2029
2022
|
}
|
|
2030
|
-
// NOTE: We've removed `shouldNotScroll` as its purpose is now better
|
|
2031
|
-
// served by the state machine itself. The state `IDLE_NOT_AT_BOTTOM`
|
|
2032
|
-
// already tells us the user has scrolled up.
|
|
2033
2023
|
|
|
2034
|
-
// ---
|
|
2024
|
+
// --- IF WE ARE HERE, WE HAVE SCROLLED A "DECENT AMOUNT" ---
|
|
2025
|
+
|
|
2026
|
+
console.log(
|
|
2027
|
+
`Threshold passed at ${scrollTop}px. Recalculating range...`
|
|
2028
|
+
);
|
|
2035
2029
|
|
|
2036
|
-
//
|
|
2037
|
-
|
|
2030
|
+
// NOW we do the expensive work.
|
|
2031
|
+
const { clientHeight } = container;
|
|
2038
2032
|
let high = totalCount - 1;
|
|
2039
2033
|
let low = 0;
|
|
2040
|
-
let
|
|
2034
|
+
let topItemIndex = 0;
|
|
2041
2035
|
while (low <= high) {
|
|
2042
2036
|
const mid = Math.floor((low + high) / 2);
|
|
2043
2037
|
if (positions[mid]! < scrollTop) {
|
|
2044
|
-
|
|
2038
|
+
topItemIndex = mid;
|
|
2045
2039
|
low = mid + 1;
|
|
2046
2040
|
} else {
|
|
2047
2041
|
high = mid - 1;
|
|
2048
2042
|
}
|
|
2049
2043
|
}
|
|
2050
2044
|
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
const potentialStartIndex = Math.max(
|
|
2054
|
-
0,
|
|
2055
|
-
potentialTopIndex - overscan
|
|
2056
|
-
);
|
|
2057
|
-
if (potentialStartIndex === range.startIndex) {
|
|
2058
|
-
// The visible items haven't changed, so we do nothing.
|
|
2059
|
-
// This is the core of the optimization.
|
|
2060
|
-
return;
|
|
2061
|
-
}
|
|
2062
|
-
|
|
2063
|
-
// --- Part 3: If we're here, we MUST update the range ---
|
|
2064
|
-
console.log(
|
|
2065
|
-
`Index changed from ${range.startIndex} to ${potentialStartIndex}. Updating range.`
|
|
2066
|
-
);
|
|
2067
|
-
|
|
2068
|
-
let endIndex = potentialStartIndex;
|
|
2045
|
+
const startIndex = Math.max(0, topItemIndex - overscan);
|
|
2046
|
+
let endIndex = startIndex;
|
|
2069
2047
|
const visibleEnd = scrollTop + clientHeight;
|
|
2070
2048
|
while (
|
|
2071
2049
|
endIndex < totalCount &&
|
|
@@ -2075,9 +2053,12 @@ function createProxyHandler<T>(
|
|
|
2075
2053
|
}
|
|
2076
2054
|
|
|
2077
2055
|
setRange({
|
|
2078
|
-
startIndex
|
|
2056
|
+
startIndex,
|
|
2079
2057
|
endIndex: Math.min(totalCount, endIndex + overscan),
|
|
2080
2058
|
});
|
|
2059
|
+
|
|
2060
|
+
// Finally, we record that we did the work at THIS scroll position.
|
|
2061
|
+
lastUpdateAtScrollTop.current = scrollTop;
|
|
2081
2062
|
};
|
|
2082
2063
|
|
|
2083
2064
|
container.addEventListener("scroll", handleUserScroll, {
|
|
@@ -2085,7 +2066,7 @@ function createProxyHandler<T>(
|
|
|
2085
2066
|
});
|
|
2086
2067
|
return () =>
|
|
2087
2068
|
container.removeEventListener("scroll", handleUserScroll);
|
|
2088
|
-
}, [totalCount, positions,
|
|
2069
|
+
}, [totalCount, positions, itemHeight, overscan, status]);
|
|
2089
2070
|
|
|
2090
2071
|
const scrollToBottom = useCallback(() => {
|
|
2091
2072
|
console.log(
|