cogsbox-state 0.5.286 → 0.5.288

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cogsbox-state",
3
- "version": "0.5.286",
3
+ "version": "0.5.288",
4
4
  "description": "React state management library with form controls and server sync",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/src/CogsState.tsx CHANGED
@@ -1803,8 +1803,9 @@ function createProxyHandler<T>(
1803
1803
  return (
1804
1804
  options: VirtualViewOptions
1805
1805
  ): VirtualStateObjectResult<any[]> => {
1806
+ // --- CHANGE 1: itemHeight is now optional with a default ---
1806
1807
  const {
1807
- itemHeight = 50, // Default height for unmeasured items
1808
+ itemHeight = 50, // Serves as a fallback for unmeasured items
1808
1809
  overscan = 5,
1809
1810
  stickToBottom = false,
1810
1811
  } = options;
@@ -1815,18 +1816,7 @@ function createProxyHandler<T>(
1815
1816
  endIndex: 10,
1816
1817
  });
1817
1818
 
1818
- // --- State Tracking Refs for stickToBottom ---
1819
- const isAtBottomRef = useRef(stickToBottom);
1820
- const previousTotalCountRef = useRef(0);
1821
- const isInitialMountRef = useRef(true);
1822
-
1823
- const sourceArray = getGlobalStore().getNestedState(
1824
- stateKey,
1825
- path
1826
- ) as any[];
1827
- const totalCount = sourceArray.length;
1828
-
1829
- // Helper to get an item's measured height or the default
1819
+ // --- CHANGE 2: Add a helper to get heights from shadow store ---
1830
1820
  const getItemHeight = useCallback(
1831
1821
  (index: number): number => {
1832
1822
  const metadata = getGlobalStore
@@ -1837,7 +1827,18 @@ function createProxyHandler<T>(
1837
1827
  [itemHeight, stateKey, path]
1838
1828
  );
1839
1829
 
1840
- // Pre-calculate total height and the top offset of each item
1830
+ const isAtBottomRef = useRef(stickToBottom);
1831
+ const previousTotalCountRef = useRef(0);
1832
+ const isInitialMountRef = useRef(true);
1833
+
1834
+ const sourceArray = getGlobalStore().getNestedState(
1835
+ stateKey,
1836
+ path
1837
+ ) as any[];
1838
+ const totalCount = sourceArray.length;
1839
+
1840
+ // --- CHANGE 3: Pre-calculate total height and item positions ---
1841
+ // This replaces all instances of `totalCount * itemHeight`.
1841
1842
  const { totalHeight, positions } = useMemo(() => {
1842
1843
  let currentHeight = 0;
1843
1844
  const pos: number[] = [];
@@ -1848,6 +1849,7 @@ function createProxyHandler<T>(
1848
1849
  return { totalHeight: currentHeight, positions: pos };
1849
1850
  }, [totalCount, getItemHeight]);
1850
1851
 
1852
+ // This part is IDENTICAL to your original code
1851
1853
  const virtualState = useMemo(() => {
1852
1854
  const start = Math.max(0, range.startIndex);
1853
1855
  const end = Math.min(totalCount, range.endIndex);
@@ -1875,8 +1877,10 @@ function createProxyHandler<T>(
1875
1877
  isAtBottomRef.current =
1876
1878
  scrollHeight - scrollTop - clientHeight < 10;
1877
1879
 
1878
- // Find the start index by searching for the first item in the viewport
1880
+ // --- CHANGE 4: Update scroll logic to use positions array ---
1881
+ // This is the dynamic equivalent of `Math.floor(scrollTop / itemHeight)`.
1879
1882
  let startIndex = 0;
1883
+ // A simple loop is robust and easy to understand.
1880
1884
  for (let i = 0; i < positions.length; i++) {
1881
1885
  if (positions[i]! >= scrollTop) {
1882
1886
  startIndex = i;
@@ -1884,16 +1888,15 @@ function createProxyHandler<T>(
1884
1888
  }
1885
1889
  }
1886
1890
 
1887
- // Find the end index by seeing how many items fit in the viewport
1888
1891
  let endIndex = startIndex;
1889
1892
  while (
1890
1893
  endIndex < totalCount &&
1894
+ positions[endIndex] &&
1891
1895
  positions[endIndex]! < scrollTop + clientHeight
1892
1896
  ) {
1893
1897
  endIndex++;
1894
1898
  }
1895
1899
 
1896
- // Apply overscan
1897
1900
  startIndex = Math.max(0, startIndex - overscan);
1898
1901
  endIndex = Math.min(totalCount, endIndex + overscan);
1899
1902
 
@@ -1902,7 +1905,7 @@ function createProxyHandler<T>(
1902
1905
  prevRange.startIndex !== startIndex ||
1903
1906
  prevRange.endIndex !== endIndex
1904
1907
  ) {
1905
- return { startIndex, endIndex };
1908
+ return { startIndex: startIndex, endIndex: endIndex };
1906
1909
  }
1907
1910
  return prevRange;
1908
1911
  });
@@ -1912,7 +1915,7 @@ function createProxyHandler<T>(
1912
1915
  passive: true,
1913
1916
  });
1914
1917
 
1915
- // Logic to keep the view scrolled to the bottom
1918
+ // This logic is IDENTICAL to your original code
1916
1919
  if (stickToBottom) {
1917
1920
  if (isInitialMountRef.current) {
1918
1921
  container.scrollTo({
@@ -1928,12 +1931,12 @@ function createProxyHandler<T>(
1928
1931
  });
1929
1932
  }
1930
1933
  }
1931
-
1932
1934
  isInitialMountRef.current = false;
1933
- handleScroll(); // Initial calculation
1935
+ handleScroll();
1934
1936
 
1935
1937
  return () =>
1936
1938
  container.removeEventListener("scroll", handleScroll);
1939
+ // The dependencies are almost identical, just swapping itemHeight for `positions`
1937
1940
  }, [totalCount, overscan, stickToBottom, positions]);
1938
1941
 
1939
1942
  const scrollToBottom = useCallback(
@@ -1948,18 +1951,20 @@ function createProxyHandler<T>(
1948
1951
  []
1949
1952
  );
1950
1953
 
1954
+ // --- CHANGE 5: Update scrollToIndex to use positions array ---
1951
1955
  const scrollToIndex = useCallback(
1952
1956
  (index: number, behavior: ScrollBehavior = "smooth") => {
1953
1957
  if (containerRef.current && positions[index] !== undefined) {
1954
1958
  containerRef.current.scrollTo({
1955
- top: positions[index],
1959
+ top: positions[index], // Instead of `index * itemHeight`
1956
1960
  behavior,
1957
1961
  });
1958
1962
  }
1959
1963
  },
1960
- [positions] // Depends on the calculated positions
1964
+ [positions] // Depends on `positions` now instead of `itemHeight`
1961
1965
  );
1962
1966
 
1967
+ // --- CHANGE 6: Update props to use dynamic totalHeight and offsets ---
1963
1968
  const virtualizerProps = {
1964
1969
  outer: {
1965
1970
  ref: containerRef,
@@ -1967,12 +1972,13 @@ function createProxyHandler<T>(
1967
1972
  },
1968
1973
  inner: {
1969
1974
  style: {
1970
- height: `${totalHeight}px`,
1975
+ height: `${totalHeight}px`, // Use calculated total height
1971
1976
  position: "relative",
1972
1977
  },
1973
1978
  },
1974
1979
  list: {
1975
1980
  style: {
1981
+ // Use the pre-calculated position of the first visible item
1976
1982
  transform: `translateY(${positions[range.startIndex] || 0}px)`,
1977
1983
  },
1978
1984
  },