cogsbox-state 0.5.318 → 0.5.320
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 +581 -617
- package/dist/CogsState.jsx.map +1 -1
- package/package.json +1 -1
- package/src/CogsState.tsx +51 -119
package/package.json
CHANGED
package/src/CogsState.tsx
CHANGED
|
@@ -1809,6 +1809,14 @@ function createProxyHandler<T>(
|
|
|
1809
1809
|
} = options;
|
|
1810
1810
|
|
|
1811
1811
|
const containerRef = useRef<HTMLDivElement | null>(null);
|
|
1812
|
+
|
|
1813
|
+
const sourceArray = getGlobalStore().getNestedState(
|
|
1814
|
+
stateKey,
|
|
1815
|
+
path
|
|
1816
|
+
) as any[];
|
|
1817
|
+
const totalCount = sourceArray.length;
|
|
1818
|
+
|
|
1819
|
+
// Start at top, will adjust once container is measured
|
|
1812
1820
|
const [range, setRange] = useState({
|
|
1813
1821
|
startIndex: 0,
|
|
1814
1822
|
endIndex: 10,
|
|
@@ -1816,104 +1824,41 @@ function createProxyHandler<T>(
|
|
|
1816
1824
|
|
|
1817
1825
|
const isLockedToBottomRef = useRef(stickToBottom);
|
|
1818
1826
|
const [shadowUpdateTrigger, setShadowUpdateTrigger] = useState(0);
|
|
1819
|
-
|
|
1820
|
-
// Track if we've scrolled to bottom after initial load
|
|
1821
|
-
const hasScrolledToBottomRef = useRef(false);
|
|
1822
|
-
const lastTotalCountRef = useRef(0);
|
|
1827
|
+
const hasInitializedRef = useRef(false);
|
|
1823
1828
|
|
|
1824
1829
|
useEffect(() => {
|
|
1825
|
-
let updateCount = 0;
|
|
1826
1830
|
const unsubscribe = getGlobalStore
|
|
1827
1831
|
.getState()
|
|
1828
1832
|
.subscribeToShadowState(stateKey, () => {
|
|
1829
|
-
updateCount++;
|
|
1830
|
-
if (updateCount <= 5) {
|
|
1831
|
-
console.log(
|
|
1832
|
-
`[VirtualView] Shadow update #${updateCount}`
|
|
1833
|
-
);
|
|
1834
|
-
}
|
|
1835
1833
|
setShadowUpdateTrigger((prev) => prev + 1);
|
|
1836
1834
|
});
|
|
1837
1835
|
return unsubscribe;
|
|
1838
1836
|
}, [stateKey]);
|
|
1839
1837
|
|
|
1840
|
-
const
|
|
1838
|
+
const { totalHeight, positions } = useMemo(() => {
|
|
1839
|
+
const shadowArray =
|
|
1840
|
+
getGlobalStore.getState().getShadowMetadata(stateKey, path) ||
|
|
1841
|
+
[];
|
|
1842
|
+
let height = 0;
|
|
1843
|
+
const pos: number[] = [];
|
|
1844
|
+
for (let i = 0; i < totalCount; i++) {
|
|
1845
|
+
pos[i] = height;
|
|
1846
|
+
const measuredHeight =
|
|
1847
|
+
shadowArray[i]?.virtualizer?.itemHeight;
|
|
1848
|
+
height += measuredHeight || itemHeight;
|
|
1849
|
+
}
|
|
1850
|
+
return { totalHeight: height, positions: pos };
|
|
1851
|
+
}, [
|
|
1852
|
+
totalCount,
|
|
1841
1853
|
stateKey,
|
|
1842
|
-
path
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
console.log(
|
|
1847
|
-
`[VirtualView] Initial setup - totalCount: ${totalCount}, itemHeight: ${itemHeight}, stickToBottom: ${stickToBottom}`
|
|
1848
|
-
);
|
|
1854
|
+
path.join("."),
|
|
1855
|
+
itemHeight,
|
|
1856
|
+
shadowUpdateTrigger,
|
|
1857
|
+
]);
|
|
1849
1858
|
|
|
1850
|
-
// Reset when array size changes significantly
|
|
1851
|
-
if (totalCount !== lastTotalCountRef.current) {
|
|
1852
|
-
console.log(
|
|
1853
|
-
`[VirtualView] Array size changed from ${lastTotalCountRef.current} to ${totalCount}`
|
|
1854
|
-
);
|
|
1855
|
-
hasScrolledToBottomRef.current = false;
|
|
1856
|
-
lastTotalCountRef.current = totalCount;
|
|
1857
|
-
}
|
|
1858
|
-
|
|
1859
|
-
// Calculate heights from shadow state
|
|
1860
|
-
const { totalHeight, positions, visibleMeasured } =
|
|
1861
|
-
useMemo(() => {
|
|
1862
|
-
const shadowArray =
|
|
1863
|
-
getGlobalStore
|
|
1864
|
-
.getState()
|
|
1865
|
-
.getShadowMetadata(stateKey, path) || [];
|
|
1866
|
-
let height = 0;
|
|
1867
|
-
const pos: number[] = [];
|
|
1868
|
-
let measuredCount = 0;
|
|
1869
|
-
let visibleMeasuredCount = 0;
|
|
1870
|
-
|
|
1871
|
-
for (let i = 0; i < totalCount; i++) {
|
|
1872
|
-
pos[i] = height;
|
|
1873
|
-
const measuredHeight =
|
|
1874
|
-
shadowArray[i]?.virtualizer?.itemHeight;
|
|
1875
|
-
if (measuredHeight) {
|
|
1876
|
-
measuredCount++;
|
|
1877
|
-
// Count measured items in current visible range
|
|
1878
|
-
if (i >= range.startIndex && i < range.endIndex) {
|
|
1879
|
-
visibleMeasuredCount++;
|
|
1880
|
-
}
|
|
1881
|
-
}
|
|
1882
|
-
height += measuredHeight || itemHeight;
|
|
1883
|
-
}
|
|
1884
|
-
|
|
1885
|
-
// Check if all VISIBLE items are measured
|
|
1886
|
-
const visibleCount = range.endIndex - range.startIndex;
|
|
1887
|
-
const allVisibleMeasured =
|
|
1888
|
-
visibleMeasuredCount === visibleCount && visibleCount > 0;
|
|
1889
|
-
|
|
1890
|
-
console.log(
|
|
1891
|
-
`[VirtualView] Heights calc - measured: ${measuredCount}/${totalCount}, visible measured: ${visibleMeasuredCount}/${visibleCount}, totalHeight: ${height}`
|
|
1892
|
-
);
|
|
1893
|
-
|
|
1894
|
-
return {
|
|
1895
|
-
totalHeight: height,
|
|
1896
|
-
positions: pos,
|
|
1897
|
-
visibleMeasured: allVisibleMeasured,
|
|
1898
|
-
};
|
|
1899
|
-
}, [
|
|
1900
|
-
totalCount,
|
|
1901
|
-
stateKey,
|
|
1902
|
-
path.join("."),
|
|
1903
|
-
itemHeight,
|
|
1904
|
-
shadowUpdateTrigger,
|
|
1905
|
-
range, // Add range dependency
|
|
1906
|
-
]);
|
|
1907
|
-
|
|
1908
|
-
// Memoize the virtualized slice
|
|
1909
1859
|
const virtualState = useMemo(() => {
|
|
1910
1860
|
const start = Math.max(0, range.startIndex);
|
|
1911
1861
|
const end = Math.min(totalCount, range.endIndex);
|
|
1912
|
-
|
|
1913
|
-
console.log(
|
|
1914
|
-
`[VirtualView] Creating virtual slice - range: ${start}-${end} (${end - start} items)`
|
|
1915
|
-
);
|
|
1916
|
-
|
|
1917
1862
|
const validIndices = Array.from(
|
|
1918
1863
|
{ length: end - start },
|
|
1919
1864
|
(_, i) => start + i
|
|
@@ -1925,7 +1870,6 @@ function createProxyHandler<T>(
|
|
|
1925
1870
|
});
|
|
1926
1871
|
}, [range.startIndex, range.endIndex, sourceArray, totalCount]);
|
|
1927
1872
|
|
|
1928
|
-
// Main layout effect
|
|
1929
1873
|
useLayoutEffect(() => {
|
|
1930
1874
|
const container = containerRef.current;
|
|
1931
1875
|
if (!container) return;
|
|
@@ -1966,44 +1910,32 @@ function createProxyHandler<T>(
|
|
|
1966
1910
|
passive: true,
|
|
1967
1911
|
});
|
|
1968
1912
|
|
|
1969
|
-
//
|
|
1913
|
+
// Initialize at bottom if needed
|
|
1970
1914
|
if (
|
|
1971
1915
|
stickToBottom &&
|
|
1972
|
-
!
|
|
1973
|
-
totalCount > 0
|
|
1916
|
+
!hasInitializedRef.current &&
|
|
1917
|
+
totalCount > 0 &&
|
|
1918
|
+
container.clientHeight > 0
|
|
1974
1919
|
) {
|
|
1975
|
-
|
|
1976
|
-
const currentRange = range;
|
|
1977
|
-
const atEnd = currentRange.endIndex >= totalCount - 5; // Close to end
|
|
1920
|
+
hasInitializedRef.current = true;
|
|
1978
1921
|
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
`[VirtualView] Jumping near bottom to trigger measurements`
|
|
1997
|
-
);
|
|
1998
|
-
const estimatedScrollPosition = Math.max(
|
|
1999
|
-
0,
|
|
2000
|
-
(totalCount - 20) * itemHeight
|
|
2001
|
-
);
|
|
2002
|
-
container.scrollTo({
|
|
2003
|
-
top: estimatedScrollPosition,
|
|
2004
|
-
behavior: "auto",
|
|
2005
|
-
});
|
|
2006
|
-
}
|
|
1922
|
+
// Now we have the actual container height, calculate visible items
|
|
1923
|
+
const visibleCount = Math.ceil(
|
|
1924
|
+
container.clientHeight / itemHeight
|
|
1925
|
+
);
|
|
1926
|
+
const startIdx = Math.max(
|
|
1927
|
+
0,
|
|
1928
|
+
totalCount - visibleCount - overscan
|
|
1929
|
+
);
|
|
1930
|
+
|
|
1931
|
+
// Set range to show bottom items
|
|
1932
|
+
setRange({
|
|
1933
|
+
startIndex: startIdx,
|
|
1934
|
+
endIndex: totalCount,
|
|
1935
|
+
});
|
|
1936
|
+
|
|
1937
|
+
// Scroll to bottom
|
|
1938
|
+
container.scrollTop = container.scrollHeight;
|
|
2007
1939
|
}
|
|
2008
1940
|
|
|
2009
1941
|
updateVirtualRange();
|
|
@@ -2011,7 +1943,7 @@ function createProxyHandler<T>(
|
|
|
2011
1943
|
return () => {
|
|
2012
1944
|
container.removeEventListener("scroll", handleUserScroll);
|
|
2013
1945
|
};
|
|
2014
|
-
}, [totalCount, positions, stickToBottom]);
|
|
1946
|
+
}, [totalCount, positions, stickToBottom, itemHeight, overscan]);
|
|
2015
1947
|
|
|
2016
1948
|
const scrollToBottom = useCallback(
|
|
2017
1949
|
(behavior: ScrollBehavior = "smooth") => {
|