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