cogsbox-state 0.5.303 → 0.5.305
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 +448 -475
- package/dist/CogsState.jsx.map +1 -1
- package/package.json +1 -1
- package/src/CogsState.tsx +48 -87
package/package.json
CHANGED
package/src/CogsState.tsx
CHANGED
|
@@ -1814,28 +1814,10 @@ function createProxyHandler<T>(
|
|
|
1814
1814
|
endIndex: 10,
|
|
1815
1815
|
});
|
|
1816
1816
|
|
|
1817
|
-
const [heightsVersion, setHeightsVersion] = useState(0);
|
|
1818
|
-
const forceRecalculate = useCallback(
|
|
1819
|
-
() => setHeightsVersion((v) => v + 1),
|
|
1820
|
-
[]
|
|
1821
|
-
);
|
|
1822
|
-
|
|
1823
|
-
// Track scroll position
|
|
1824
1817
|
const isAtBottomRef = useRef(stickToBottom);
|
|
1825
1818
|
const previousTotalCountRef = useRef(0);
|
|
1826
1819
|
const isInitialMountRef = useRef(true);
|
|
1827
|
-
const
|
|
1828
|
-
|
|
1829
|
-
useEffect(() => {
|
|
1830
|
-
const unsubscribe = getGlobalStore
|
|
1831
|
-
.getState()
|
|
1832
|
-
.subscribeToShadowState(stateKey, forceRecalculate);
|
|
1833
|
-
const timer = setTimeout(forceRecalculate, 50);
|
|
1834
|
-
return () => {
|
|
1835
|
-
unsubscribe();
|
|
1836
|
-
clearTimeout(timer);
|
|
1837
|
-
};
|
|
1838
|
-
}, [stateKey, forceRecalculate]);
|
|
1820
|
+
const hasMeasurementsRef = useRef(false);
|
|
1839
1821
|
|
|
1840
1822
|
const sourceArray = getGlobalStore().getNestedState(
|
|
1841
1823
|
stateKey,
|
|
@@ -1843,32 +1825,26 @@ function createProxyHandler<T>(
|
|
|
1843
1825
|
) as any[];
|
|
1844
1826
|
const totalCount = sourceArray.length;
|
|
1845
1827
|
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
}
|
|
1863
|
-
height += measuredHeight || itemHeight;
|
|
1864
|
-
}
|
|
1828
|
+
// Calculate heights from shadow state
|
|
1829
|
+
const { totalHeight, positions } = useMemo(() => {
|
|
1830
|
+
const shadowArray =
|
|
1831
|
+
getGlobalStore.getState().getShadowMetadata(stateKey, path) ||
|
|
1832
|
+
[];
|
|
1833
|
+
let height = 0;
|
|
1834
|
+
const pos: number[] = [];
|
|
1835
|
+
let hasMeasurements = false;
|
|
1836
|
+
|
|
1837
|
+
for (let i = 0; i < totalCount; i++) {
|
|
1838
|
+
pos[i] = height;
|
|
1839
|
+
const measuredHeight =
|
|
1840
|
+
shadowArray[i]?.virtualizer?.itemHeight;
|
|
1841
|
+
if (measuredHeight) hasMeasurements = true;
|
|
1842
|
+
height += measuredHeight || itemHeight;
|
|
1843
|
+
}
|
|
1865
1844
|
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
allItemsMeasured: measured,
|
|
1870
|
-
};
|
|
1871
|
-
}, [totalCount, stateKey, path, itemHeight, heightsVersion]);
|
|
1845
|
+
hasMeasurementsRef.current = hasMeasurements;
|
|
1846
|
+
return { totalHeight: height, positions: pos };
|
|
1847
|
+
}, [totalCount, stateKey, path.join("."), itemHeight]);
|
|
1872
1848
|
|
|
1873
1849
|
const virtualState = useMemo(() => {
|
|
1874
1850
|
const start = Math.max(0, range.startIndex);
|
|
@@ -1894,7 +1870,6 @@ function createProxyHandler<T>(
|
|
|
1894
1870
|
|
|
1895
1871
|
const handleScroll = () => {
|
|
1896
1872
|
const { scrollTop, clientHeight, scrollHeight } = container;
|
|
1897
|
-
// Consider "at bottom" if within 10px
|
|
1898
1873
|
isAtBottomRef.current =
|
|
1899
1874
|
scrollHeight - scrollTop - clientHeight < 10;
|
|
1900
1875
|
|
|
@@ -1938,39 +1913,9 @@ function createProxyHandler<T>(
|
|
|
1938
1913
|
});
|
|
1939
1914
|
|
|
1940
1915
|
// Handle stick to bottom
|
|
1941
|
-
if (stickToBottom) {
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
!hasScrolledToBottomRef.current
|
|
1945
|
-
) {
|
|
1946
|
-
// For initial mount, wait for items to be measured
|
|
1947
|
-
if (allItemsMeasured && totalCount > 0) {
|
|
1948
|
-
container.scrollTo({
|
|
1949
|
-
top: container.scrollHeight,
|
|
1950
|
-
behavior: "auto",
|
|
1951
|
-
});
|
|
1952
|
-
hasScrolledToBottomRef.current = true;
|
|
1953
|
-
isInitialMountRef.current = false;
|
|
1954
|
-
} else if (totalCount > 0) {
|
|
1955
|
-
// If not all measured yet, try again soon
|
|
1956
|
-
const retryTimer = setTimeout(() => {
|
|
1957
|
-
if (containerRef.current && isInitialMountRef.current) {
|
|
1958
|
-
containerRef.current.scrollTo({
|
|
1959
|
-
top: containerRef.current.scrollHeight,
|
|
1960
|
-
behavior: "auto",
|
|
1961
|
-
});
|
|
1962
|
-
hasScrolledToBottomRef.current = true;
|
|
1963
|
-
isInitialMountRef.current = false;
|
|
1964
|
-
}
|
|
1965
|
-
}, 100);
|
|
1966
|
-
return () => clearTimeout(retryTimer);
|
|
1967
|
-
}
|
|
1968
|
-
} else if (
|
|
1969
|
-
!isInitialMountRef.current &&
|
|
1970
|
-
wasAtBottom &&
|
|
1971
|
-
listGrew
|
|
1972
|
-
) {
|
|
1973
|
-
// New items added and we were at bottom - stay at bottom
|
|
1916
|
+
if (stickToBottom && !isInitialMountRef.current) {
|
|
1917
|
+
// Only auto-scroll for new items after initial mount
|
|
1918
|
+
if (wasAtBottom && listGrew) {
|
|
1974
1919
|
requestAnimationFrame(() => {
|
|
1975
1920
|
container.scrollTo({
|
|
1976
1921
|
top: container.scrollHeight,
|
|
@@ -1978,8 +1923,6 @@ function createProxyHandler<T>(
|
|
|
1978
1923
|
});
|
|
1979
1924
|
});
|
|
1980
1925
|
}
|
|
1981
|
-
} else {
|
|
1982
|
-
isInitialMountRef.current = false;
|
|
1983
1926
|
}
|
|
1984
1927
|
|
|
1985
1928
|
// Run handleScroll once to set initial range
|
|
@@ -1987,13 +1930,31 @@ function createProxyHandler<T>(
|
|
|
1987
1930
|
|
|
1988
1931
|
return () =>
|
|
1989
1932
|
container.removeEventListener("scroll", handleScroll);
|
|
1990
|
-
}, [
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1933
|
+
}, [totalCount, positions, overscan, stickToBottom]);
|
|
1934
|
+
|
|
1935
|
+
// Separate effect for initial scroll to bottom
|
|
1936
|
+
useEffect(() => {
|
|
1937
|
+
if (
|
|
1938
|
+
stickToBottom &&
|
|
1939
|
+
isInitialMountRef.current &&
|
|
1940
|
+
totalCount > 0 &&
|
|
1941
|
+
hasMeasurementsRef.current
|
|
1942
|
+
) {
|
|
1943
|
+
const container = containerRef.current;
|
|
1944
|
+
if (container) {
|
|
1945
|
+
// Use rAF to ensure DOM is updated
|
|
1946
|
+
requestAnimationFrame(() => {
|
|
1947
|
+
requestAnimationFrame(() => {
|
|
1948
|
+
container.scrollTo({
|
|
1949
|
+
top: container.scrollHeight,
|
|
1950
|
+
behavior: "auto",
|
|
1951
|
+
});
|
|
1952
|
+
isInitialMountRef.current = false;
|
|
1953
|
+
});
|
|
1954
|
+
});
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
}, [stickToBottom, totalCount, positions]); // positions change triggers this when measurements come in
|
|
1997
1958
|
|
|
1998
1959
|
const scrollToBottom = useCallback(
|
|
1999
1960
|
(behavior: ScrollBehavior = "smooth") => {
|