cogsbox-state 0.5.309 → 0.5.311

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.309",
3
+ "version": "0.5.311",
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
@@ -1814,10 +1814,11 @@ function createProxyHandler<T>(
1814
1814
  endIndex: 10,
1815
1815
  });
1816
1816
 
1817
- const isAtBottomRef = useRef(stickToBottom);
1818
- const previousTotalCountRef = useRef(0);
1817
+ // --- State and Lock Management Refs ---
1818
+ const isLockedToBottomRef = useRef(stickToBottom);
1819
1819
  const isInitialMountRef = useRef(true);
1820
- // Subscribe to shadow state changes
1820
+
1821
+ // Subscribe to shadow state changes for height updates
1821
1822
  const [shadowUpdateTrigger, setShadowUpdateTrigger] = useState(0);
1822
1823
 
1823
1824
  useEffect(() => {
@@ -1862,7 +1863,6 @@ function createProxyHandler<T>(
1862
1863
  shadowUpdateTrigger,
1863
1864
  ]);
1864
1865
 
1865
- console.log("height", totalHeight);
1866
1866
  const virtualState = useMemo(() => {
1867
1867
  const start = Math.max(0, range.startIndex);
1868
1868
  const end = Math.min(totalCount, range.endIndex);
@@ -1881,14 +1881,15 @@ function createProxyHandler<T>(
1881
1881
  const container = containerRef.current;
1882
1882
  if (!container) return;
1883
1883
 
1884
- const wasAtBottom = isAtBottomRef.current;
1885
- const listGrew = totalCount > previousTotalCountRef.current;
1886
- previousTotalCountRef.current = totalCount;
1887
-
1888
1884
  const handleScroll = () => {
1889
1885
  const { scrollTop, clientHeight, scrollHeight } = container;
1890
- isAtBottomRef.current =
1891
- scrollHeight - scrollTop - clientHeight < 10;
1886
+
1887
+ // Determine if the user is at the bottom
1888
+ const isNowAtBottom =
1889
+ scrollHeight - scrollTop - clientHeight < 1;
1890
+
1891
+ // If the user scrolls up, unlock. If they scroll back down, re-lock.
1892
+ isLockedToBottomRef.current = isNowAtBottom;
1892
1893
 
1893
1894
  // Binary search for start index
1894
1895
  let low = 0,
@@ -1929,33 +1930,28 @@ function createProxyHandler<T>(
1929
1930
  passive: true,
1930
1931
  });
1931
1932
 
1932
- // Handle stick to bottom
1933
- if (stickToBottom) {
1933
+ // --- REFINED STICK-TO-BOTTOM LOGIC ---
1934
+ if (stickToBottom && isLockedToBottomRef.current) {
1935
+ // Use 'auto' for instant snap on first load, 'smooth' for subsequent updates.
1936
+ const behavior = isInitialMountRef.current
1937
+ ? "auto"
1938
+ : "smooth";
1939
+
1940
+ container.scrollTo({
1941
+ top: container.scrollHeight,
1942
+ behavior,
1943
+ });
1944
+ }
1945
+
1946
+ // After the first layout effect, it's no longer the initial mount.
1947
+ // queueMicrotask ensures this is set *after* the current render cycle.
1948
+ queueMicrotask(() => {
1934
1949
  if (isInitialMountRef.current) {
1935
- console.log(
1936
- "stickToBottom initial mount",
1937
- container.scrollHeight
1938
- );
1939
- container.scrollTo({
1940
- top: container.scrollHeight,
1941
- behavior: "auto",
1942
- });
1943
1950
  isInitialMountRef.current = false;
1944
- } else if (wasAtBottom && listGrew) {
1945
- console.log(
1946
- "stickToBottom wasAtBottom && listGrew",
1947
- container.scrollHeight
1948
- );
1949
- requestAnimationFrame(() => {
1950
- container.scrollTo({
1951
- top: container.scrollHeight,
1952
- behavior: "smooth",
1953
- });
1954
- });
1955
1951
  }
1956
- }
1957
- console.log("wasAtBottom && listGrew", wasAtBottom, listGrew);
1958
- // Run handleScroll once to set initial range
1952
+ });
1953
+
1954
+ // Run handleScroll once on setup to set initial range and lock status
1959
1955
  handleScroll();
1960
1956
 
1961
1957
  return () =>