cogsbox-state 0.5.418 → 0.5.420

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.418",
3
+ "version": "0.5.420",
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
@@ -1822,8 +1822,9 @@ function createProxyHandler<T>(
1822
1822
  });
1823
1823
  const [shadowUpdateTrigger, setShadowUpdateTrigger] = useState(0);
1824
1824
  const wasAtBottomRef = useRef(true);
1825
- const previousCountRef = useRef(0);
1826
1825
  const userHasScrolledAwayRef = useRef(false);
1826
+ const previousCountRef = useRef(0);
1827
+
1827
1828
  // Subscribe to shadow state updates
1828
1829
  useEffect(() => {
1829
1830
  const unsubscribe = getGlobalStore
@@ -1909,13 +1910,12 @@ function createProxyHandler<T>(
1909
1910
  const isInitialLoad =
1910
1911
  previousCountRef.current === 0 && totalCount > 0;
1911
1912
 
1912
- // Only auto-scroll if we haven't scrolled away AND we're at bottom
1913
+ // Only auto-scroll if user hasn't scrolled away
1913
1914
  if (
1914
1915
  (hasNewItems || isInitialLoad) &&
1915
1916
  wasAtBottomRef.current &&
1916
1917
  !userHasScrolledAwayRef.current
1917
1918
  ) {
1918
- // First, ensure the last items are in range
1919
1919
  const visibleCount = Math.ceil(
1920
1920
  (containerRef.current?.clientHeight || 0) / itemHeight
1921
1921
  );
@@ -1929,22 +1929,18 @@ function createProxyHandler<T>(
1929
1929
 
1930
1930
  setRange(newRange);
1931
1931
 
1932
- // Then scroll to the last item after it renders
1933
1932
  const timeoutId = setTimeout(() => {
1934
- const scrolled = scrollToLastItem();
1935
- if (!scrolled && containerRef.current) {
1936
- // Fallback if ref not available yet
1933
+ if (containerRef.current) {
1937
1934
  containerRef.current.scrollTop =
1938
1935
  containerRef.current.scrollHeight;
1939
1936
  }
1940
1937
  }, 50);
1941
1938
 
1942
- previousCountRef.current = totalCount;
1943
1939
  return () => clearTimeout(timeoutId);
1944
1940
  }
1945
1941
 
1946
1942
  previousCountRef.current = totalCount;
1947
- }, [totalCount]);
1943
+ }, [totalCount, itemHeight, overscan]);
1948
1944
 
1949
1945
  // Handle scroll events
1950
1946
  useEffect(() => {
@@ -1956,17 +1952,16 @@ function createProxyHandler<T>(
1956
1952
  const distanceFromBottom =
1957
1953
  scrollHeight - scrollTop - clientHeight;
1958
1954
 
1959
- // Track if user is at bottom with tight tolerance
1960
- const isAtBottom = distanceFromBottom < 5;
1961
- wasAtBottomRef.current = isAtBottom;
1955
+ // Track if we're at bottom
1956
+ wasAtBottomRef.current = distanceFromBottom < 5;
1962
1957
 
1963
- // If user scrolls away from bottom, set the flag
1964
- if (!isAtBottom && distanceFromBottom > 50) {
1958
+ // If user scrolls away from bottom past threshold, set flag
1959
+ if (distanceFromBottom > 100) {
1965
1960
  userHasScrolledAwayRef.current = true;
1966
1961
  }
1967
1962
 
1968
- // If user scrolls back to bottom, clear the flag
1969
- if (isAtBottom) {
1963
+ // If user scrolls back to bottom, clear flag
1964
+ if (distanceFromBottom < 5) {
1970
1965
  userHasScrolledAwayRef.current = false;
1971
1966
  }
1972
1967
 
@@ -1993,15 +1988,25 @@ function createProxyHandler<T>(
1993
1988
  endIndex: Math.min(totalCount, endIndex + 1 + overscan),
1994
1989
  });
1995
1990
  };
1991
+
1996
1992
  container.addEventListener("scroll", handleScroll, {
1997
1993
  passive: true,
1998
1994
  });
1999
1995
 
2000
- // Initial setup
2001
- if (stickToBottom && totalCount > 0) {
2002
- // For initial load, jump to bottom
2003
- container.scrollTop = container.scrollHeight;
1996
+ // Only auto-scroll on initial load when user hasn't scrolled away
1997
+ if (
1998
+ stickToBottom &&
1999
+ totalCount > 0 &&
2000
+ !userHasScrolledAwayRef.current
2001
+ ) {
2002
+ const { scrollTop } = container;
2003
+ // Only if we're at the very top (initial load)
2004
+ if (scrollTop === 0) {
2005
+ container.scrollTop = container.scrollHeight;
2006
+ wasAtBottomRef.current = true;
2007
+ }
2004
2008
  }
2009
+
2005
2010
  handleScroll();
2006
2011
 
2007
2012
  return () => {
@@ -2011,6 +2016,7 @@ function createProxyHandler<T>(
2011
2016
 
2012
2017
  const scrollToBottom = useCallback(() => {
2013
2018
  wasAtBottomRef.current = true;
2019
+ userHasScrolledAwayRef.current = false;
2014
2020
  const scrolled = scrollToLastItem();
2015
2021
  if (!scrolled && containerRef.current) {
2016
2022
  containerRef.current.scrollTop =