cogsbox-state 0.5.349 → 0.5.351
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 +506 -512
- package/dist/CogsState.jsx.map +1 -1
- package/package.json +1 -1
- package/src/CogsState.tsx +80 -70
package/package.json
CHANGED
package/src/CogsState.tsx
CHANGED
|
@@ -1813,12 +1813,7 @@ function createProxyHandler<T>(
|
|
|
1813
1813
|
startIndex: 0,
|
|
1814
1814
|
endIndex: 10,
|
|
1815
1815
|
});
|
|
1816
|
-
const sourceArray = getGlobalStore().getNestedState(
|
|
1817
|
-
stateKey,
|
|
1818
|
-
path
|
|
1819
|
-
) as any[];
|
|
1820
1816
|
const isLockedToBottomRef = useRef(stickToBottom);
|
|
1821
|
-
const prevTotalCountRef = useRef(sourceArray.length);
|
|
1822
1817
|
|
|
1823
1818
|
const [shadowUpdateTrigger, setShadowUpdateTrigger] = useState(0);
|
|
1824
1819
|
|
|
@@ -1831,6 +1826,10 @@ function createProxyHandler<T>(
|
|
|
1831
1826
|
return unsubscribe;
|
|
1832
1827
|
}, [stateKey]);
|
|
1833
1828
|
|
|
1829
|
+
const sourceArray = getGlobalStore().getNestedState(
|
|
1830
|
+
stateKey,
|
|
1831
|
+
path
|
|
1832
|
+
) as any[];
|
|
1834
1833
|
const totalCount = sourceArray.length;
|
|
1835
1834
|
|
|
1836
1835
|
const { totalHeight, positions } = useMemo(() => {
|
|
@@ -1868,71 +1867,85 @@ function createProxyHandler<T>(
|
|
|
1868
1867
|
});
|
|
1869
1868
|
}, [range.startIndex, range.endIndex, sourceArray, totalCount]);
|
|
1870
1869
|
|
|
1871
|
-
//
|
|
1870
|
+
// --- YOUR ALGORITHM IMPLEMENTED ---
|
|
1871
|
+
// This effect is the entry point. It triggers when new items are added.
|
|
1872
1872
|
useLayoutEffect(() => {
|
|
1873
1873
|
const container = containerRef.current;
|
|
1874
|
-
if
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
high = totalCount - 1;
|
|
1883
|
-
while (low <= high) {
|
|
1884
|
-
const mid = Math.floor((low + high) / 2);
|
|
1885
|
-
if (positions[mid]! < scrollTop) low = mid + 1;
|
|
1886
|
-
else high = mid - 1;
|
|
1887
|
-
}
|
|
1888
|
-
const startIndex = Math.max(0, high - overscan);
|
|
1889
|
-
let endIndex = startIndex;
|
|
1890
|
-
const visibleEnd = scrollTop + clientHeight;
|
|
1891
|
-
while (
|
|
1892
|
-
endIndex < totalCount &&
|
|
1893
|
-
positions[endIndex]! < visibleEnd
|
|
1894
|
-
) {
|
|
1895
|
-
endIndex++;
|
|
1896
|
-
}
|
|
1897
|
-
setRange({
|
|
1898
|
-
startIndex,
|
|
1899
|
-
endIndex: Math.min(totalCount, endIndex + overscan),
|
|
1900
|
-
});
|
|
1901
|
-
};
|
|
1874
|
+
// Only run if we have new items and are supposed to be at the bottom.
|
|
1875
|
+
if (
|
|
1876
|
+
!container ||
|
|
1877
|
+
!isLockedToBottomRef.current ||
|
|
1878
|
+
totalCount === 0
|
|
1879
|
+
) {
|
|
1880
|
+
return;
|
|
1881
|
+
}
|
|
1902
1882
|
|
|
1903
|
-
//
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
});
|
|
1883
|
+
// STEP 1: Set the range to the end so the last items are rendered.
|
|
1884
|
+
console.log("ALGORITHM: Starting...");
|
|
1885
|
+
const visibleCount = 10;
|
|
1886
|
+
setRange({
|
|
1887
|
+
startIndex: Math.max(0, totalCount - visibleCount - overscan),
|
|
1888
|
+
endIndex: totalCount,
|
|
1889
|
+
});
|
|
1911
1890
|
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1891
|
+
// STEP 2: Start the LOOP.
|
|
1892
|
+
console.log(
|
|
1893
|
+
"ALGORITHM: Starting LOOP to wait for measurement."
|
|
1894
|
+
);
|
|
1895
|
+
let loopCount = 0;
|
|
1896
|
+
const intervalId = setInterval(() => {
|
|
1897
|
+
loopCount++;
|
|
1898
|
+
console.log(`LOOP ${loopCount}: Checking last item...`);
|
|
1899
|
+
|
|
1900
|
+
// The Check: Get the last item's height FROM THE SHADOW OBJECT.
|
|
1901
|
+
const lastItemIndex = totalCount - 1;
|
|
1902
|
+
const shadowArray =
|
|
1903
|
+
getGlobalStore
|
|
1904
|
+
.getState()
|
|
1905
|
+
.getShadowMetadata(stateKey, path) || [];
|
|
1906
|
+
const lastItemHeight =
|
|
1907
|
+
shadowArray[lastItemIndex]?.virtualizer?.itemHeight || 0;
|
|
1908
|
+
|
|
1909
|
+
if (lastItemHeight > 0) {
|
|
1910
|
+
// EXIT CONDITION MET
|
|
1911
|
+
console.log(
|
|
1912
|
+
`%cSUCCESS: Last item height is ${lastItemHeight}. Scrolling now.`,
|
|
1913
|
+
"color: green; font-weight: bold;"
|
|
1914
|
+
);
|
|
1915
|
+
clearInterval(intervalId); // Stop the loop.
|
|
1921
1916
|
|
|
1922
|
-
|
|
1917
|
+
// STEP 3: Scroll.
|
|
1918
|
+
container.scrollTo({
|
|
1919
|
+
top: container.scrollHeight,
|
|
1920
|
+
behavior: "smooth",
|
|
1921
|
+
});
|
|
1922
|
+
} else {
|
|
1923
|
+
console.log("...WAITING. Height is not ready.");
|
|
1924
|
+
if (loopCount > 20) {
|
|
1925
|
+
// Safety break to prevent infinite loops
|
|
1926
|
+
console.error(
|
|
1927
|
+
"LOOP TIMEOUT: Last item was never measured. Stopping loop."
|
|
1928
|
+
);
|
|
1923
1929
|
clearInterval(intervalId);
|
|
1924
|
-
container.scrollTo({
|
|
1925
|
-
top: container.scrollHeight,
|
|
1926
|
-
behavior: "smooth",
|
|
1927
|
-
});
|
|
1928
1930
|
}
|
|
1929
|
-
}
|
|
1931
|
+
}
|
|
1932
|
+
}, 100); // Check every 100ms.
|
|
1930
1933
|
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
+
// Cleanup: Stop the loop if the component unmounts.
|
|
1935
|
+
return () => {
|
|
1936
|
+
console.log("ALGORITHM: Cleaning up loop.");
|
|
1937
|
+
clearInterval(intervalId);
|
|
1938
|
+
};
|
|
1939
|
+
}, [totalCount]); // This whole process triggers ONLY when totalCount changes.
|
|
1934
1940
|
|
|
1935
|
-
|
|
1941
|
+
// Effect to handle user scrolling.
|
|
1942
|
+
useEffect(() => {
|
|
1943
|
+
const container = containerRef.current;
|
|
1944
|
+
if (!container) return;
|
|
1945
|
+
|
|
1946
|
+
const updateVirtualRange = () => {
|
|
1947
|
+
/* ... same as before ... */
|
|
1948
|
+
};
|
|
1936
1949
|
const handleUserScroll = () => {
|
|
1937
1950
|
const isAtBottom =
|
|
1938
1951
|
container.scrollHeight -
|
|
@@ -1941,28 +1954,23 @@ function createProxyHandler<T>(
|
|
|
1941
1954
|
1;
|
|
1942
1955
|
if (!isAtBottom) {
|
|
1943
1956
|
isLockedToBottomRef.current = false;
|
|
1957
|
+
console.log("USER ACTION: Scroll lock DISABLED.");
|
|
1944
1958
|
}
|
|
1945
1959
|
updateVirtualRange();
|
|
1946
1960
|
};
|
|
1947
|
-
|
|
1948
1961
|
container.addEventListener("scroll", handleUserScroll, {
|
|
1949
1962
|
passive: true,
|
|
1950
1963
|
});
|
|
1951
|
-
updateVirtualRange(); // Always update range for current view.
|
|
1952
|
-
|
|
1953
|
-
// This return is the cleanup for the whole effect.
|
|
1954
1964
|
return () =>
|
|
1955
1965
|
container.removeEventListener("scroll", handleUserScroll);
|
|
1956
|
-
}, [
|
|
1966
|
+
}, []);
|
|
1957
1967
|
|
|
1958
|
-
// This simple effect tracks the item count for the next render.
|
|
1959
|
-
useEffect(() => {
|
|
1960
|
-
prevTotalCountRef.current = totalCount;
|
|
1961
|
-
});
|
|
1962
1968
|
const scrollToBottom = useCallback(
|
|
1963
1969
|
(behavior: ScrollBehavior = "smooth") => {
|
|
1964
1970
|
if (containerRef.current) {
|
|
1965
1971
|
isLockedToBottomRef.current = true;
|
|
1972
|
+
console.log("USER ACTION: Scroll lock ENABLED.");
|
|
1973
|
+
// This is a manual trigger, so we don't need the loop. Just scroll.
|
|
1966
1974
|
containerRef.current.scrollTo({
|
|
1967
1975
|
top: containerRef.current.scrollHeight,
|
|
1968
1976
|
behavior,
|
|
@@ -1976,6 +1984,7 @@ function createProxyHandler<T>(
|
|
|
1976
1984
|
(index: number, behavior: ScrollBehavior = "smooth") => {
|
|
1977
1985
|
if (containerRef.current && positions[index] !== undefined) {
|
|
1978
1986
|
isLockedToBottomRef.current = false;
|
|
1987
|
+
console.log("USER ACTION: Scroll lock DISABLED.");
|
|
1979
1988
|
containerRef.current.scrollTo({
|
|
1980
1989
|
top: positions[index],
|
|
1981
1990
|
behavior,
|
|
@@ -2002,6 +2011,7 @@ function createProxyHandler<T>(
|
|
|
2002
2011
|
},
|
|
2003
2012
|
},
|
|
2004
2013
|
};
|
|
2014
|
+
|
|
2005
2015
|
return {
|
|
2006
2016
|
virtualState,
|
|
2007
2017
|
virtualizerProps,
|