cogsbox-state 0.5.332 → 0.5.334
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 +572 -583
- package/dist/CogsState.jsx.map +1 -1
- package/package.json +1 -1
- package/src/CogsState.tsx +26 -49
package/package.json
CHANGED
package/src/CogsState.tsx
CHANGED
|
@@ -1814,11 +1814,9 @@ function createProxyHandler<T>(
|
|
|
1814
1814
|
endIndex: 10,
|
|
1815
1815
|
});
|
|
1816
1816
|
|
|
1817
|
-
|
|
1818
|
-
const isLockedToBottomRef = useRef(stickToBottom);
|
|
1819
|
-
|
|
1820
|
-
// This state triggers a re-render when item heights change.
|
|
1817
|
+
const isLockedToBottomRef = useRef(false); // Always start false
|
|
1821
1818
|
const [shadowUpdateTrigger, setShadowUpdateTrigger] = useState(0);
|
|
1819
|
+
const lastTotalCountRef = useRef(0); // Track previous count
|
|
1822
1820
|
|
|
1823
1821
|
useEffect(() => {
|
|
1824
1822
|
const unsubscribe = getGlobalStore
|
|
@@ -1835,7 +1833,6 @@ function createProxyHandler<T>(
|
|
|
1835
1833
|
) as any[];
|
|
1836
1834
|
const totalCount = sourceArray.length;
|
|
1837
1835
|
|
|
1838
|
-
// Calculate heights from shadow state. This runs when data or measurements change.
|
|
1839
1836
|
const { totalHeight, positions } = useMemo(() => {
|
|
1840
1837
|
const shadowArray =
|
|
1841
1838
|
getGlobalStore.getState().getShadowMetadata(stateKey, path) ||
|
|
@@ -1857,7 +1854,6 @@ function createProxyHandler<T>(
|
|
|
1857
1854
|
shadowUpdateTrigger,
|
|
1858
1855
|
]);
|
|
1859
1856
|
|
|
1860
|
-
// Memoize the virtualized slice of data.
|
|
1861
1857
|
const virtualState = useMemo(() => {
|
|
1862
1858
|
const start = Math.max(0, range.startIndex);
|
|
1863
1859
|
const end = Math.min(totalCount, range.endIndex);
|
|
@@ -1871,37 +1867,11 @@ function createProxyHandler<T>(
|
|
|
1871
1867
|
validIndices,
|
|
1872
1868
|
});
|
|
1873
1869
|
}, [range.startIndex, range.endIndex, sourceArray, totalCount]);
|
|
1874
|
-
useEffect(() => {
|
|
1875
|
-
if (stickToBottom && totalCount > 0 && containerRef.current) {
|
|
1876
|
-
// When count increases, immediately adjust range to show bottom
|
|
1877
|
-
const container = containerRef.current;
|
|
1878
|
-
const visibleCount = Math.ceil(
|
|
1879
|
-
container.clientHeight / itemHeight
|
|
1880
|
-
);
|
|
1881
|
-
|
|
1882
|
-
// Set range to show the last items including the new one
|
|
1883
|
-
setRange({
|
|
1884
|
-
startIndex: Math.max(
|
|
1885
|
-
0,
|
|
1886
|
-
totalCount - visibleCount - overscan
|
|
1887
|
-
),
|
|
1888
|
-
endIndex: totalCount,
|
|
1889
|
-
});
|
|
1890
1870
|
|
|
1891
|
-
// Then scroll to bottom after a short delay
|
|
1892
|
-
setTimeout(() => {
|
|
1893
|
-
container.scrollTop = container.scrollHeight;
|
|
1894
|
-
}, 100);
|
|
1895
|
-
}
|
|
1896
|
-
}, [totalCount]);
|
|
1897
|
-
// This is the main effect that handles all scrolling and updates.
|
|
1898
1871
|
useLayoutEffect(() => {
|
|
1899
1872
|
const container = containerRef.current;
|
|
1900
1873
|
if (!container) return;
|
|
1901
1874
|
|
|
1902
|
-
let scrollTimeoutId: NodeJS.Timeout;
|
|
1903
|
-
|
|
1904
|
-
// This function determines what's visible in the viewport.
|
|
1905
1875
|
const updateVirtualRange = () => {
|
|
1906
1876
|
if (!container) return;
|
|
1907
1877
|
const { scrollTop } = container;
|
|
@@ -1925,7 +1895,6 @@ function createProxyHandler<T>(
|
|
|
1925
1895
|
setRange({ startIndex, endIndex });
|
|
1926
1896
|
};
|
|
1927
1897
|
|
|
1928
|
-
// This function handles ONLY user-initiated scrolls.
|
|
1929
1898
|
const handleUserScroll = () => {
|
|
1930
1899
|
isLockedToBottomRef.current =
|
|
1931
1900
|
container.scrollHeight -
|
|
@@ -1938,31 +1907,39 @@ function createProxyHandler<T>(
|
|
|
1938
1907
|
container.addEventListener("scroll", handleUserScroll, {
|
|
1939
1908
|
passive: true,
|
|
1940
1909
|
});
|
|
1941
|
-
|
|
1942
|
-
//
|
|
1943
|
-
if (stickToBottom &&
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1910
|
+
console.log("totalCount", totalCount);
|
|
1911
|
+
// Handle scrolling
|
|
1912
|
+
if (stickToBottom && totalCount > 0) {
|
|
1913
|
+
const isInitialLoad =
|
|
1914
|
+
lastTotalCountRef.current === 0 && totalCount > 0;
|
|
1915
|
+
const hasNewItems = totalCount > lastTotalCountRef.current;
|
|
1916
|
+
console.log("isInitialLoad", isInitialLoad);
|
|
1917
|
+
console.log("hasNewItems", hasNewItems);
|
|
1918
|
+
if (isInitialLoad) {
|
|
1919
|
+
// First load - always scroll to bottom
|
|
1920
|
+
setTimeout(() => {
|
|
1921
|
+
container.scrollTop = container.scrollHeight;
|
|
1922
|
+
isLockedToBottomRef.current = true;
|
|
1923
|
+
}, 1000); // Longer delay for initial load
|
|
1924
|
+
} else if (hasNewItems && isLockedToBottomRef.current) {
|
|
1925
|
+
// New items added and user is at bottom - smooth scroll
|
|
1926
|
+
setTimeout(() => {
|
|
1949
1927
|
container.scrollTo({
|
|
1950
|
-
top:
|
|
1951
|
-
behavior: "smooth",
|
|
1928
|
+
top: container.scrollHeight,
|
|
1929
|
+
behavior: "smooth",
|
|
1952
1930
|
});
|
|
1953
|
-
}
|
|
1954
|
-
}
|
|
1931
|
+
}, 100);
|
|
1932
|
+
}
|
|
1933
|
+
// If user has scrolled up, don't auto-scroll
|
|
1955
1934
|
}
|
|
1956
1935
|
|
|
1957
1936
|
updateVirtualRange();
|
|
1937
|
+
lastTotalCountRef.current = totalCount;
|
|
1958
1938
|
|
|
1959
|
-
// Cleanup function is vital to prevent memory leaks.
|
|
1960
1939
|
return () => {
|
|
1961
|
-
clearTimeout(scrollTimeoutId);
|
|
1962
1940
|
container.removeEventListener("scroll", handleUserScroll);
|
|
1963
1941
|
};
|
|
1964
|
-
|
|
1965
|
-
}, [totalCount, positions, totalHeight, stickToBottom]);
|
|
1942
|
+
}, [totalCount, positions, stickToBottom]);
|
|
1966
1943
|
|
|
1967
1944
|
const scrollToBottom = useCallback(
|
|
1968
1945
|
(behavior: ScrollBehavior = "smooth") => {
|