cogsbox-state 0.5.406 → 0.5.408

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.406",
3
+ "version": "0.5.408",
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,9 +1803,7 @@ function createProxyHandler<T>(
1803
1803
  return selectedIndex ?? -1;
1804
1804
  };
1805
1805
  }
1806
- // Simplified useVirtualView approach
1807
- // Optimal approach - replace the useVirtualView implementation
1808
- // Complete useVirtualView implementation with comprehensive logging
1806
+ // Complete fixed useVirtualView implementation
1809
1807
  if (prop === "useVirtualView") {
1810
1808
  return (
1811
1809
  options: VirtualViewOptions
@@ -1817,19 +1815,13 @@ function createProxyHandler<T>(
1817
1815
  dependencies = [],
1818
1816
  } = options;
1819
1817
 
1820
- console.log("useVirtualView initialized with:", {
1821
- itemHeight,
1822
- overscan,
1823
- stickToBottom,
1824
- });
1825
-
1826
1818
  const containerRef = useRef<HTMLDivElement | null>(null);
1827
1819
  const [range, setRange] = useState({
1828
1820
  startIndex: 0,
1829
1821
  endIndex: 10,
1830
1822
  });
1831
1823
  const [shadowUpdateTrigger, setShadowUpdateTrigger] = useState(0);
1832
- const isUserScrollingRef = useRef(false);
1824
+ const isProgrammaticScrollRef = useRef(false); // Track if we're scrolling programmatically
1833
1825
  const shouldStickToBottomRef = useRef(true);
1834
1826
  const scrollToBottomIntervalRef = useRef<NodeJS.Timeout | null>(
1835
1827
  null
@@ -1837,11 +1829,9 @@ function createProxyHandler<T>(
1837
1829
 
1838
1830
  // Subscribe to shadow state updates
1839
1831
  useEffect(() => {
1840
- console.log("Setting up shadow state subscription");
1841
1832
  const unsubscribe = getGlobalStore
1842
1833
  .getState()
1843
1834
  .subscribeToShadowState(stateKey, () => {
1844
- console.log("Shadow state updated");
1845
1835
  setShadowUpdateTrigger((prev) => prev + 1);
1846
1836
  });
1847
1837
  return unsubscribe;
@@ -1852,11 +1842,9 @@ function createProxyHandler<T>(
1852
1842
  path
1853
1843
  ) as any[];
1854
1844
  const totalCount = sourceArray.length;
1855
- console.log("Source array length:", totalCount);
1856
1845
 
1857
1846
  // Calculate heights and positions
1858
1847
  const { totalHeight, positions } = useMemo(() => {
1859
- console.log("Recalculating heights and positions");
1860
1848
  const shadowArray =
1861
1849
  getGlobalStore.getState().getShadowMetadata(stateKey, path) ||
1862
1850
  [];
@@ -1868,7 +1856,6 @@ function createProxyHandler<T>(
1868
1856
  shadowArray[i]?.virtualizer?.itemHeight;
1869
1857
  height += measuredHeight || itemHeight;
1870
1858
  }
1871
- console.log("Total height calculated:", height);
1872
1859
  return { totalHeight: height, positions: pos };
1873
1860
  }, [
1874
1861
  totalCount,
@@ -1882,10 +1869,6 @@ function createProxyHandler<T>(
1882
1869
  const virtualState = useMemo(() => {
1883
1870
  const start = Math.max(0, range.startIndex);
1884
1871
  const end = Math.min(totalCount, range.endIndex);
1885
- console.log("Creating virtual state for range:", {
1886
- start,
1887
- end,
1888
- });
1889
1872
  const validIndices = Array.from(
1890
1873
  { length: end - start },
1891
1874
  (_, i) => start + i
@@ -1899,41 +1882,12 @@ function createProxyHandler<T>(
1899
1882
 
1900
1883
  // Handle auto-scroll to bottom
1901
1884
  useEffect(() => {
1902
- console.log("Auto-scroll effect triggered:", {
1903
- stickToBottom,
1904
- hasContainer: !!containerRef.current,
1905
- totalCount,
1906
- shouldStickToBottom: shouldStickToBottomRef.current,
1907
- range,
1908
- });
1909
-
1910
- if (!stickToBottom) {
1911
- console.log("Stick to bottom is false, skipping");
1885
+ if (!stickToBottom || !containerRef.current || totalCount === 0)
1912
1886
  return;
1913
- }
1914
-
1915
- if (!containerRef.current) {
1916
- console.log("No container ref, skipping");
1917
- return;
1918
- }
1919
-
1920
- if (totalCount === 0) {
1921
- console.log("No items, skipping");
1922
- return;
1923
- }
1924
-
1925
- if (!shouldStickToBottomRef.current) {
1926
- console.log(
1927
- "Should not stick to bottom (user scrolled), skipping"
1928
- );
1929
- return;
1930
- }
1931
-
1932
- console.log("Proceeding with auto-scroll logic");
1887
+ if (!shouldStickToBottomRef.current) return;
1933
1888
 
1934
1889
  // Clear any existing interval
1935
1890
  if (scrollToBottomIntervalRef.current) {
1936
- console.log("Clearing existing scroll interval");
1937
1891
  clearInterval(scrollToBottomIntervalRef.current);
1938
1892
  }
1939
1893
 
@@ -1942,68 +1896,61 @@ function createProxyHandler<T>(
1942
1896
  const isInitialLoad = range.endIndex < jumpThreshold;
1943
1897
  const isBigJump = totalCount > range.endIndex + jumpThreshold;
1944
1898
 
1945
- console.log("Jump check:", {
1946
- isInitialLoad,
1947
- isBigJump,
1948
- totalCount,
1949
- currentEndIndex: range.endIndex,
1950
- });
1951
-
1952
1899
  if (isInitialLoad || isBigJump) {
1900
+ // Set programmatic scroll flag BEFORE changing range
1901
+ isProgrammaticScrollRef.current = true;
1902
+
1953
1903
  const newRange = {
1954
1904
  startIndex: Math.max(0, totalCount - 20),
1955
1905
  endIndex: totalCount,
1956
1906
  };
1957
- console.log("Jumping to end range:", newRange);
1958
1907
  setRange(newRange);
1908
+
1909
+ // Reset flag after a delay to ensure scroll events are ignored
1910
+ setTimeout(() => {
1911
+ isProgrammaticScrollRef.current = false;
1912
+ }, 100);
1959
1913
  }
1960
1914
 
1961
1915
  // Keep scrolling to bottom until we're actually there
1962
1916
  let attempts = 0;
1963
1917
  const maxAttempts = 50; // 5 seconds max
1964
1918
 
1965
- console.log("Starting scroll-to-bottom interval");
1966
-
1967
1919
  scrollToBottomIntervalRef.current = setInterval(() => {
1968
1920
  const container = containerRef.current;
1969
- if (!container) {
1970
- console.log("Container lost during interval");
1971
- return;
1972
- }
1921
+ if (!container) return;
1973
1922
 
1974
1923
  attempts++;
1975
1924
 
1976
1925
  const { scrollTop, scrollHeight, clientHeight } = container;
1977
1926
  const currentBottom = scrollTop + clientHeight;
1978
1927
  const actualBottom = scrollHeight;
1979
- const isAtBottom = actualBottom - currentBottom < 5;
1980
-
1981
- console.log(`Scroll attempt ${attempts}:`, {
1982
- currentBottom,
1983
- actualBottom,
1984
- isAtBottom,
1985
- scrollTop,
1986
- scrollHeight,
1987
- clientHeight,
1988
- });
1928
+ const isAtBottom = actualBottom - currentBottom < 50; // Increased tolerance
1989
1929
 
1990
1930
  if (isAtBottom || attempts >= maxAttempts) {
1991
- console.log(
1992
- isAtBottom
1993
- ? "Successfully reached bottom!"
1994
- : "Timeout - giving up"
1995
- );
1996
1931
  clearInterval(scrollToBottomIntervalRef.current!);
1997
1932
  scrollToBottomIntervalRef.current = null;
1933
+
1934
+ // Do one final scroll to ensure we're truly at bottom
1935
+ if (
1936
+ isAtBottom &&
1937
+ container.scrollTop <
1938
+ container.scrollHeight - container.clientHeight
1939
+ ) {
1940
+ container.scrollTop = container.scrollHeight;
1941
+ }
1998
1942
  } else {
1999
- console.log("Scrolling to", container.scrollHeight);
2000
- container.scrollTop = container.scrollHeight;
1943
+ // Only scroll if we're not already scrolling there
1944
+ const targetScroll =
1945
+ container.scrollHeight - container.clientHeight;
1946
+ if (Math.abs(container.scrollTop - targetScroll) > 1) {
1947
+ container.scrollTop = container.scrollHeight;
1948
+ }
2001
1949
  }
2002
1950
  }, 100);
2003
1951
 
2004
1952
  // Cleanup
2005
1953
  return () => {
2006
- console.log("Cleaning up scroll interval");
2007
1954
  if (scrollToBottomIntervalRef.current) {
2008
1955
  clearInterval(scrollToBottomIntervalRef.current);
2009
1956
  scrollToBottomIntervalRef.current = null;
@@ -2014,37 +1961,28 @@ function createProxyHandler<T>(
2014
1961
  // Handle user scroll
2015
1962
  useEffect(() => {
2016
1963
  const container = containerRef.current;
2017
- if (!container) {
2018
- console.log("No container for scroll handler");
2019
- return;
2020
- }
1964
+ if (!container) return;
2021
1965
 
2022
- console.log("Setting up scroll handler");
1966
+ const handleScroll = () => {
1967
+ // Ignore programmatic scrolls
1968
+ if (isProgrammaticScrollRef.current) {
1969
+ return;
1970
+ }
2023
1971
 
2024
- let scrollTimeout: NodeJS.Timeout;
1972
+ // This is a real user scroll
1973
+ const { scrollTop, scrollHeight, clientHeight } = container;
1974
+ const distanceFromBottom =
1975
+ scrollHeight - scrollTop - clientHeight;
1976
+ const isAtBottom = distanceFromBottom < 50; // Increased tolerance
2025
1977
 
2026
- const handleScroll = () => {
1978
+ // Stop any auto-scrolling if user scrolls
2027
1979
  if (scrollToBottomIntervalRef.current) {
2028
- console.log("User scrolled - stopping auto-scroll");
2029
1980
  clearInterval(scrollToBottomIntervalRef.current);
2030
1981
  scrollToBottomIntervalRef.current = null;
2031
1982
  }
2032
1983
 
2033
- const { scrollTop, scrollHeight, clientHeight } = container;
2034
- const isAtBottom =
2035
- scrollHeight - scrollTop - clientHeight < 10;
2036
-
2037
- // Update whether we should stick to bottom
1984
+ // Only update this for real user scrolls
2038
1985
  shouldStickToBottomRef.current = isAtBottom;
2039
- console.log("User scroll - at bottom:", isAtBottom);
2040
-
2041
- // Mark as user scrolling
2042
- clearTimeout(scrollTimeout);
2043
- isUserScrollingRef.current = true;
2044
- scrollTimeout = setTimeout(() => {
2045
- isUserScrollingRef.current = false;
2046
- console.log("User stopped scrolling");
2047
- }, 150);
2048
1986
 
2049
1987
  // Update visible range
2050
1988
  let startIndex = 0;
@@ -2064,49 +2002,49 @@ function createProxyHandler<T>(
2064
2002
  endIndex = i;
2065
2003
  }
2066
2004
 
2067
- const newRange = {
2005
+ setRange({
2068
2006
  startIndex: Math.max(0, startIndex),
2069
2007
  endIndex: Math.min(totalCount, endIndex + 1 + overscan),
2070
- };
2071
-
2072
- console.log("Updating visible range:", newRange);
2073
- setRange(newRange);
2008
+ });
2074
2009
  };
2075
2010
 
2076
2011
  container.addEventListener("scroll", handleScroll, {
2077
2012
  passive: true,
2078
2013
  });
2079
- console.log("Initial scroll calculation");
2080
2014
  handleScroll(); // Initial calculation
2081
2015
 
2082
2016
  return () => {
2083
- console.log("Removing scroll handler");
2084
2017
  container.removeEventListener("scroll", handleScroll);
2085
- clearTimeout(scrollTimeout);
2086
2018
  };
2087
2019
  }, [positions, totalCount, itemHeight, overscan]);
2088
2020
 
2089
2021
  const scrollToBottom = useCallback(
2090
2022
  (behavior: ScrollBehavior = "auto") => {
2091
- console.log("Manual scrollToBottom called");
2092
2023
  shouldStickToBottomRef.current = true;
2024
+ isProgrammaticScrollRef.current = true;
2093
2025
  if (containerRef.current) {
2094
2026
  containerRef.current.scrollTop =
2095
2027
  containerRef.current.scrollHeight;
2096
2028
  }
2029
+ setTimeout(() => {
2030
+ isProgrammaticScrollRef.current = false;
2031
+ }, 100);
2097
2032
  },
2098
2033
  []
2099
2034
  );
2100
2035
 
2101
2036
  const scrollToIndex = useCallback(
2102
2037
  (index: number, behavior: ScrollBehavior = "smooth") => {
2103
- console.log("scrollToIndex called:", index);
2038
+ isProgrammaticScrollRef.current = true;
2104
2039
  if (containerRef.current && positions[index] !== undefined) {
2105
2040
  containerRef.current.scrollTo({
2106
2041
  top: positions[index],
2107
2042
  behavior,
2108
2043
  });
2109
2044
  }
2045
+ setTimeout(() => {
2046
+ isProgrammaticScrollRef.current = false;
2047
+ }, 100);
2110
2048
  },
2111
2049
  [positions]
2112
2050
  );
@@ -2129,12 +2067,6 @@ function createProxyHandler<T>(
2129
2067
  },
2130
2068
  };
2131
2069
 
2132
- console.log("Returning virtualizer with props:", {
2133
- range,
2134
- totalHeight,
2135
- startPosition: positions[range.startIndex] || 0,
2136
- });
2137
-
2138
2070
  return {
2139
2071
  virtualState,
2140
2072
  virtualizerProps,