cogsbox-state 0.5.344 → 0.5.346
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 +609 -615
- package/dist/CogsState.jsx.map +1 -1
- package/package.json +1 -1
- package/src/CogsState.tsx +68 -66
package/package.json
CHANGED
package/src/CogsState.tsx
CHANGED
|
@@ -1809,21 +1809,10 @@ function createProxyHandler<T>(
|
|
|
1809
1809
|
} = options;
|
|
1810
1810
|
|
|
1811
1811
|
const containerRef = useRef<HTMLDivElement | null>(null);
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
return {
|
|
1817
|
-
startIndex: Math.max(
|
|
1818
|
-
0,
|
|
1819
|
-
sourceArray.length - visibleCount - overscan
|
|
1820
|
-
),
|
|
1821
|
-
endIndex: sourceArray.length,
|
|
1822
|
-
};
|
|
1823
|
-
}
|
|
1824
|
-
return { startIndex: 0, endIndex: 10 };
|
|
1825
|
-
};
|
|
1826
|
-
const [range, setRange] = useState(initialRange);
|
|
1812
|
+
const [range, setRange] = useState({
|
|
1813
|
+
startIndex: 0,
|
|
1814
|
+
endIndex: 10,
|
|
1815
|
+
});
|
|
1827
1816
|
const isLockedToBottomRef = useRef(stickToBottom);
|
|
1828
1817
|
|
|
1829
1818
|
const [shadowUpdateTrigger, setShadowUpdateTrigger] = useState(0);
|
|
@@ -1878,71 +1867,85 @@ function createProxyHandler<T>(
|
|
|
1878
1867
|
});
|
|
1879
1868
|
}, [range.startIndex, range.endIndex, sourceArray, totalCount]);
|
|
1880
1869
|
|
|
1881
|
-
//
|
|
1870
|
+
// --- YOUR ALGORITHM IMPLEMENTED ---
|
|
1871
|
+
// This effect is the entry point. It triggers when new items are added.
|
|
1882
1872
|
useLayoutEffect(() => {
|
|
1883
1873
|
const container = containerRef.current;
|
|
1874
|
+
// Only run if we have new items and are supposed to be at the bottom.
|
|
1884
1875
|
if (
|
|
1885
1876
|
!container ||
|
|
1886
|
-
!
|
|
1887
|
-
|
|
1877
|
+
!isLockedToBottomRef.current ||
|
|
1878
|
+
totalCount === 0
|
|
1888
1879
|
) {
|
|
1889
1880
|
return;
|
|
1890
1881
|
}
|
|
1891
1882
|
|
|
1892
|
-
// STEP 1:
|
|
1893
|
-
|
|
1894
|
-
const
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
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
|
+
});
|
|
1890
|
+
|
|
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.
|
|
1916
|
+
|
|
1917
|
+
// STEP 3: Scroll.
|
|
1905
1918
|
container.scrollTo({
|
|
1906
1919
|
top: container.scrollHeight,
|
|
1907
1920
|
behavior: "smooth",
|
|
1908
1921
|
});
|
|
1909
|
-
}
|
|
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
|
+
);
|
|
1929
|
+
clearInterval(intervalId);
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
}, 100); // Check every 100ms.
|
|
1910
1933
|
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
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.
|
|
1916
1940
|
|
|
1917
|
-
//
|
|
1941
|
+
// Effect to handle user scrolling.
|
|
1918
1942
|
useEffect(() => {
|
|
1919
1943
|
const container = containerRef.current;
|
|
1920
1944
|
if (!container) return;
|
|
1921
1945
|
|
|
1922
1946
|
const updateVirtualRange = () => {
|
|
1923
|
-
|
|
1924
|
-
let low = 0,
|
|
1925
|
-
high = totalCount - 1;
|
|
1926
|
-
while (low <= high) {
|
|
1927
|
-
const mid = Math.floor((low + high) / 2);
|
|
1928
|
-
if (positions[mid]! < scrollTop) low = mid + 1;
|
|
1929
|
-
else high = mid - 1;
|
|
1930
|
-
}
|
|
1931
|
-
const startIndex = Math.max(0, high - overscan);
|
|
1932
|
-
let endIndex = startIndex;
|
|
1933
|
-
const visibleEnd = scrollTop + clientHeight;
|
|
1934
|
-
while (
|
|
1935
|
-
endIndex < totalCount &&
|
|
1936
|
-
positions[endIndex]! < visibleEnd
|
|
1937
|
-
) {
|
|
1938
|
-
endIndex++;
|
|
1939
|
-
}
|
|
1940
|
-
setRange({
|
|
1941
|
-
startIndex,
|
|
1942
|
-
endIndex: Math.min(totalCount, endIndex + overscan),
|
|
1943
|
-
});
|
|
1947
|
+
/* ... same as before ... */
|
|
1944
1948
|
};
|
|
1945
|
-
|
|
1946
1949
|
const handleUserScroll = () => {
|
|
1947
1950
|
const isAtBottom =
|
|
1948
1951
|
container.scrollHeight -
|
|
@@ -1951,24 +1954,23 @@ function createProxyHandler<T>(
|
|
|
1951
1954
|
1;
|
|
1952
1955
|
if (!isAtBottom) {
|
|
1953
1956
|
isLockedToBottomRef.current = false;
|
|
1957
|
+
console.log("USER ACTION: Scroll lock DISABLED.");
|
|
1954
1958
|
}
|
|
1955
1959
|
updateVirtualRange();
|
|
1956
1960
|
};
|
|
1957
|
-
|
|
1958
1961
|
container.addEventListener("scroll", handleUserScroll, {
|
|
1959
1962
|
passive: true,
|
|
1960
1963
|
});
|
|
1961
|
-
// Initial range calculation
|
|
1962
|
-
updateVirtualRange();
|
|
1963
|
-
|
|
1964
1964
|
return () =>
|
|
1965
1965
|
container.removeEventListener("scroll", handleUserScroll);
|
|
1966
|
-
}, [
|
|
1966
|
+
}, []);
|
|
1967
1967
|
|
|
1968
1968
|
const scrollToBottom = useCallback(
|
|
1969
1969
|
(behavior: ScrollBehavior = "smooth") => {
|
|
1970
1970
|
if (containerRef.current) {
|
|
1971
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.
|
|
1972
1974
|
containerRef.current.scrollTo({
|
|
1973
1975
|
top: containerRef.current.scrollHeight,
|
|
1974
1976
|
behavior,
|
|
@@ -1982,6 +1984,7 @@ function createProxyHandler<T>(
|
|
|
1982
1984
|
(index: number, behavior: ScrollBehavior = "smooth") => {
|
|
1983
1985
|
if (containerRef.current && positions[index] !== undefined) {
|
|
1984
1986
|
isLockedToBottomRef.current = false;
|
|
1987
|
+
console.log("USER ACTION: Scroll lock DISABLED.");
|
|
1985
1988
|
containerRef.current.scrollTo({
|
|
1986
1989
|
top: positions[index],
|
|
1987
1990
|
behavior,
|
|
@@ -2008,7 +2011,6 @@ function createProxyHandler<T>(
|
|
|
2008
2011
|
},
|
|
2009
2012
|
},
|
|
2010
2013
|
};
|
|
2011
|
-
|
|
2012
2014
|
return {
|
|
2013
2015
|
virtualState,
|
|
2014
2016
|
virtualizerProps,
|