cogsbox-state 0.5.284 → 0.5.286

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.284",
3
+ "version": "0.5.286",
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
@@ -42,7 +42,7 @@ import useMeasure from "react-use-measure";
42
42
  type Prettify<T> = { [K in keyof T]: T[K] } & {};
43
43
 
44
44
  export type VirtualViewOptions = {
45
- itemHeight: number;
45
+ itemHeight?: number;
46
46
  overscan?: number;
47
47
  stickToBottom?: boolean;
48
48
  };
@@ -1466,6 +1466,8 @@ function createProxyHandler<T>(
1466
1466
  if (localStorage.getItem(storageKey)) {
1467
1467
  localStorage.removeItem(storageKey);
1468
1468
  }
1469
+
1470
+ console.log("udpating intial State", stateKey, newState);
1469
1471
  startTransition(() => {
1470
1472
  updateInitialStateGlobal(stateKey, newState);
1471
1473
  getGlobalStore.getState().initializeShadowState(stateKey, newState);
@@ -1802,7 +1804,7 @@ function createProxyHandler<T>(
1802
1804
  options: VirtualViewOptions
1803
1805
  ): VirtualStateObjectResult<any[]> => {
1804
1806
  const {
1805
- itemHeight = 50, // Now optional with default
1807
+ itemHeight = 50, // Default height for unmeasured items
1806
1808
  overscan = 5,
1807
1809
  stickToBottom = false,
1808
1810
  } = options;
@@ -1813,35 +1815,7 @@ function createProxyHandler<T>(
1813
1815
  endIndex: 10,
1814
1816
  });
1815
1817
 
1816
- // Get item height from shadow state or fall back to default
1817
- const getItemHeight = useCallback(
1818
- (index: number) => {
1819
- const metadata = getGlobalStore
1820
- .getState()
1821
- .getShadowMetadata(stateKey, [...path, index.toString()]);
1822
- return metadata?.virtualizer?.itemHeight || itemHeight;
1823
- },
1824
- [itemHeight]
1825
- );
1826
-
1827
- // Calculate total height and item positions
1828
- const calculateHeights = useCallback(() => {
1829
- const sourceArray = getGlobalStore().getNestedState(
1830
- stateKey,
1831
- path
1832
- ) as any[];
1833
-
1834
- let totalHeight = 0;
1835
- const positions: number[] = [];
1836
-
1837
- for (let i = 0; i < sourceArray.length; i++) {
1838
- positions[i] = totalHeight;
1839
- totalHeight += getItemHeight(i);
1840
- }
1841
-
1842
- return { totalHeight, positions };
1843
- }, [getItemHeight]);
1844
-
1818
+ // --- State Tracking Refs for stickToBottom ---
1845
1819
  const isAtBottomRef = useRef(stickToBottom);
1846
1820
  const previousTotalCountRef = useRef(0);
1847
1821
  const isInitialMountRef = useRef(true);
@@ -1852,6 +1826,28 @@ function createProxyHandler<T>(
1852
1826
  ) as any[];
1853
1827
  const totalCount = sourceArray.length;
1854
1828
 
1829
+ // Helper to get an item's measured height or the default
1830
+ const getItemHeight = useCallback(
1831
+ (index: number): number => {
1832
+ const metadata = getGlobalStore
1833
+ .getState()
1834
+ .getShadowMetadata(stateKey, [...path, index.toString()]);
1835
+ return metadata?.virtualizer?.itemHeight || itemHeight;
1836
+ },
1837
+ [itemHeight, stateKey, path]
1838
+ );
1839
+
1840
+ // Pre-calculate total height and the top offset of each item
1841
+ const { totalHeight, positions } = useMemo(() => {
1842
+ let currentHeight = 0;
1843
+ const pos: number[] = [];
1844
+ for (let i = 0; i < totalCount; i++) {
1845
+ pos[i] = currentHeight;
1846
+ currentHeight += getItemHeight(i);
1847
+ }
1848
+ return { totalHeight: currentHeight, positions: pos };
1849
+ }, [totalCount, getItemHeight]);
1850
+
1855
1851
  const virtualState = useMemo(() => {
1856
1852
  const start = Math.max(0, range.startIndex);
1857
1853
  const end = Math.min(totalCount, range.endIndex);
@@ -1874,43 +1870,39 @@ function createProxyHandler<T>(
1874
1870
  const listGrew = totalCount > previousTotalCountRef.current;
1875
1871
  previousTotalCountRef.current = totalCount;
1876
1872
 
1877
- const { totalHeight, positions } = calculateHeights();
1878
-
1879
1873
  const handleScroll = () => {
1880
1874
  const { scrollTop, clientHeight, scrollHeight } = container;
1881
1875
  isAtBottomRef.current =
1882
1876
  scrollHeight - scrollTop - clientHeight < 10;
1883
1877
 
1884
- // Find start index using binary search
1885
- let start = 0;
1886
- let end = positions.length - 1;
1887
- while (start < end) {
1888
- const mid = Math.floor((start + end) / 2);
1889
- if (positions[mid]! < scrollTop) {
1890
- start = mid + 1;
1891
- } else {
1892
- end = mid;
1878
+ // Find the start index by searching for the first item in the viewport
1879
+ let startIndex = 0;
1880
+ for (let i = 0; i < positions.length; i++) {
1881
+ if (positions[i]! >= scrollTop) {
1882
+ startIndex = i;
1883
+ break;
1893
1884
  }
1894
1885
  }
1895
- start = Math.max(0, start - overscan);
1896
1886
 
1897
- // Find end index
1898
- const visibleEnd = scrollTop + clientHeight;
1899
- let endIndex = start;
1887
+ // Find the end index by seeing how many items fit in the viewport
1888
+ let endIndex = startIndex;
1900
1889
  while (
1901
- endIndex < positions.length &&
1902
- positions[endIndex]! < visibleEnd
1890
+ endIndex < totalCount &&
1891
+ positions[endIndex]! < scrollTop + clientHeight
1903
1892
  ) {
1904
1893
  endIndex++;
1905
1894
  }
1895
+
1896
+ // Apply overscan
1897
+ startIndex = Math.max(0, startIndex - overscan);
1906
1898
  endIndex = Math.min(totalCount, endIndex + overscan);
1907
1899
 
1908
1900
  setRange((prevRange) => {
1909
1901
  if (
1910
- prevRange.startIndex !== start ||
1902
+ prevRange.startIndex !== startIndex ||
1911
1903
  prevRange.endIndex !== endIndex
1912
1904
  ) {
1913
- return { startIndex: start, endIndex: endIndex };
1905
+ return { startIndex, endIndex };
1914
1906
  }
1915
1907
  return prevRange;
1916
1908
  });
@@ -1920,6 +1912,7 @@ function createProxyHandler<T>(
1920
1912
  passive: true,
1921
1913
  });
1922
1914
 
1915
+ // Logic to keep the view scrolled to the bottom
1923
1916
  if (stickToBottom) {
1924
1917
  if (isInitialMountRef.current) {
1925
1918
  container.scrollTo({
@@ -1937,11 +1930,11 @@ function createProxyHandler<T>(
1937
1930
  }
1938
1931
 
1939
1932
  isInitialMountRef.current = false;
1940
- handleScroll();
1933
+ handleScroll(); // Initial calculation
1941
1934
 
1942
1935
  return () =>
1943
1936
  container.removeEventListener("scroll", handleScroll);
1944
- }, [totalCount, calculateHeights, overscan, stickToBottom]);
1937
+ }, [totalCount, overscan, stickToBottom, positions]);
1945
1938
 
1946
1939
  const scrollToBottom = useCallback(
1947
1940
  (behavior: ScrollBehavior = "smooth") => {
@@ -1957,45 +1950,37 @@ function createProxyHandler<T>(
1957
1950
 
1958
1951
  const scrollToIndex = useCallback(
1959
1952
  (index: number, behavior: ScrollBehavior = "smooth") => {
1960
- if (containerRef.current) {
1961
- const { positions } = calculateHeights();
1953
+ if (containerRef.current && positions[index] !== undefined) {
1962
1954
  containerRef.current.scrollTo({
1963
- top: positions[index] || 0,
1955
+ top: positions[index],
1964
1956
  behavior,
1965
1957
  });
1966
1958
  }
1967
1959
  },
1968
- [calculateHeights]
1960
+ [positions] // Depends on the calculated positions
1969
1961
  );
1970
1962
 
1971
- // Calculate actual heights for rendering
1972
- const {
1973
- totalHeight: totalHeightForRender,
1974
- positions: positionsForRender,
1975
- } = calculateHeights();
1976
- const offsetY = positionsForRender[range.startIndex] || 0;
1977
-
1978
1963
  const virtualizerProps = {
1979
1964
  outer: {
1980
1965
  ref: containerRef,
1981
- style: { overflowY: "auto", height: "100%" } as CSSProperties,
1966
+ style: { overflowY: "auto", height: "100%" },
1982
1967
  },
1983
1968
  inner: {
1984
1969
  style: {
1985
- height: `${totalHeightForRender}px`,
1970
+ height: `${totalHeight}px`,
1986
1971
  position: "relative",
1987
- } as CSSProperties,
1972
+ },
1988
1973
  },
1989
1974
  list: {
1990
1975
  style: {
1991
- transform: `translateY(${offsetY}px)`,
1992
- } as CSSProperties,
1976
+ transform: `translateY(${positions[range.startIndex] || 0}px)`,
1977
+ },
1993
1978
  },
1994
1979
  };
1995
1980
 
1996
1981
  return {
1997
1982
  virtualState,
1998
- virtualizerProps,
1983
+ virtualizerProps: virtualizerProps as any,
1999
1984
  scrollToBottom,
2000
1985
  scrollToIndex,
2001
1986
  };