cogsbox-state 0.5.350 → 0.5.352

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.350",
3
+ "version": "0.5.352",
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
@@ -45,6 +45,7 @@ export type VirtualViewOptions = {
45
45
  itemHeight?: number;
46
46
  overscan?: number;
47
47
  stickToBottom?: boolean;
48
+ dependencies?: any[];
48
49
  };
49
50
 
50
51
  // The result now returns a real StateObject
@@ -1269,7 +1270,7 @@ export function useCogsStateFn<TStateObject extends unknown>(
1269
1270
  break;
1270
1271
 
1271
1272
  case "cut":
1272
- // For array cut, remove element from shadow array
1273
+ // For array cut, remove element from shadow a
1273
1274
  const arrayPath = path.slice(0, -1);
1274
1275
  const index = parseInt(path[path.length - 1]!);
1275
1276
  store.removeShadowArrayElement(thisKey, arrayPath, index);
@@ -1813,8 +1814,8 @@ function createProxyHandler<T>(
1813
1814
  startIndex: 0,
1814
1815
  endIndex: 10,
1815
1816
  });
1817
+
1816
1818
  const isLockedToBottomRef = useRef(stickToBottom);
1817
- const prevTotalCountRef = useRef(0);
1818
1819
 
1819
1820
  const [shadowUpdateTrigger, setShadowUpdateTrigger] = useState(0);
1820
1821
 
@@ -1868,28 +1869,37 @@ function createProxyHandler<T>(
1868
1869
  });
1869
1870
  }, [range.startIndex, range.endIndex, sourceArray, totalCount]);
1870
1871
 
1871
- // --- YOUR WORKING SCROLL ALGORITHM - UNTOUCHED ---
1872
+ // --- YOUR ALGORITHM IMPLEMENTED ---
1873
+ // This effect is the entry point. It triggers when new items are added.
1872
1874
  useLayoutEffect(() => {
1873
1875
  const container = containerRef.current;
1874
- const hasNewItems = totalCount > prevTotalCountRef.current;
1875
-
1876
+ // Only run if we have new items and are supposed to be at the bottom.
1876
1877
  if (
1877
1878
  !container ||
1878
- !stickToBottom ||
1879
1879
  !isLockedToBottomRef.current ||
1880
- !hasNewItems
1880
+ totalCount === 0
1881
1881
  ) {
1882
1882
  return;
1883
1883
  }
1884
1884
 
1885
- // STEP 1: Set range to the end to render the items we need to measure.
1885
+ // STEP 1: Set the range to the end so the last items are rendered.
1886
+ console.log("ALGORITHM: Starting...");
1887
+ const visibleCount = 10;
1886
1888
  setRange({
1887
- startIndex: Math.max(0, totalCount - 10 - overscan),
1889
+ startIndex: Math.max(0, totalCount - visibleCount - overscan),
1888
1890
  endIndex: totalCount,
1889
1891
  });
1890
1892
 
1891
- // STEP 2: The LOOP.
1893
+ // STEP 2: Start the LOOP.
1894
+ console.log(
1895
+ "ALGORITHM: Starting LOOP to wait for measurement."
1896
+ );
1897
+ let loopCount = 0;
1892
1898
  const intervalId = setInterval(() => {
1899
+ loopCount++;
1900
+ console.log(`LOOP ${loopCount}: Checking last item...`);
1901
+
1902
+ // The Check: Get the last item's height FROM THE SHADOW OBJECT.
1893
1903
  const lastItemIndex = totalCount - 1;
1894
1904
  const shadowArray =
1895
1905
  getGlobalStore
@@ -1899,48 +1909,45 @@ function createProxyHandler<T>(
1899
1909
  shadowArray[lastItemIndex]?.virtualizer?.itemHeight || 0;
1900
1910
 
1901
1911
  if (lastItemHeight > 0) {
1902
- clearInterval(intervalId);
1912
+ // EXIT CONDITION MET
1913
+ console.log(
1914
+ `%cSUCCESS: Last item height is ${lastItemHeight}. Scrolling now.`,
1915
+ "color: green; font-weight: bold;"
1916
+ );
1917
+ clearInterval(intervalId); // Stop the loop.
1918
+
1903
1919
  // STEP 3: Scroll.
1904
1920
  container.scrollTo({
1905
1921
  top: container.scrollHeight,
1906
1922
  behavior: "smooth",
1907
1923
  });
1924
+ } else {
1925
+ console.log("...WAITING. Height is not ready.");
1926
+ if (loopCount > 20) {
1927
+ // Safety break to prevent infinite loops
1928
+ console.error(
1929
+ "LOOP TIMEOUT: Last item was never measured. Stopping loop."
1930
+ );
1931
+ clearInterval(intervalId);
1932
+ }
1908
1933
  }
1909
- }, 100);
1934
+ }, 100); // Check every 100ms.
1910
1935
 
1911
- return () => clearInterval(intervalId);
1912
- }, [totalCount]);
1936
+ // Cleanup: Stop the loop if the component unmounts.
1937
+ return () => {
1938
+ console.log("ALGORITHM: Cleaning up loop.");
1939
+ clearInterval(intervalId);
1940
+ };
1941
+ }, [totalCount, ...(options.dependencies ?? [])]); // This whole process triggers ONLY when totalCount changes.
1913
1942
 
1914
- // --- THE FIX IS HERE ---
1915
- // This effect now correctly updates when data changes.
1943
+ // Effect to handle user scrolling.
1916
1944
  useEffect(() => {
1917
1945
  const container = containerRef.current;
1918
1946
  if (!container) return;
1919
1947
 
1920
1948
  const updateVirtualRange = () => {
1921
- const { scrollTop, clientHeight } = container;
1922
- let low = 0,
1923
- high = totalCount - 1;
1924
- while (low <= high) {
1925
- const mid = Math.floor((low + high) / 2);
1926
- if (positions[mid]! < scrollTop) low = mid + 1;
1927
- else high = mid - 1;
1928
- }
1929
- const startIndex = Math.max(0, high - overscan);
1930
- let endIndex = startIndex;
1931
- const visibleEnd = scrollTop + clientHeight;
1932
- while (
1933
- endIndex < totalCount &&
1934
- positions[endIndex]! < visibleEnd
1935
- ) {
1936
- endIndex++;
1937
- }
1938
- setRange({
1939
- startIndex,
1940
- endIndex: Math.min(totalCount, endIndex + overscan),
1941
- });
1949
+ /* ... same as before ... */
1942
1950
  };
1943
-
1944
1951
  const handleUserScroll = () => {
1945
1952
  const isAtBottom =
1946
1953
  container.scrollHeight -
@@ -1949,23 +1956,17 @@ function createProxyHandler<T>(
1949
1956
  1;
1950
1957
  if (!isAtBottom) {
1951
1958
  isLockedToBottomRef.current = false;
1959
+ console.log("USER ACTION: Scroll lock DISABLED.");
1952
1960
  }
1953
1961
  updateVirtualRange();
1954
1962
  };
1955
-
1956
1963
  container.addEventListener("scroll", handleUserScroll, {
1957
1964
  passive: true,
1958
1965
  });
1959
- updateVirtualRange(); // Always update range on render.
1960
-
1961
1966
  return () =>
1962
1967
  container.removeEventListener("scroll", handleUserScroll);
1963
- }, [totalCount, positions]); // FIX: This now has dependencies.
1968
+ }, []);
1964
1969
 
1965
- // Simple effect to track previous item count for the scroll algorithm.
1966
- useEffect(() => {
1967
- prevTotalCountRef.current = totalCount;
1968
- });
1969
1970
  const scrollToBottom = useCallback(
1970
1971
  (behavior: ScrollBehavior = "smooth") => {
1971
1972
  if (containerRef.current) {
@@ -2540,10 +2541,6 @@ function createProxyHandler<T>(
2540
2541
  sessionId
2541
2542
  );
2542
2543
 
2543
- // ===================================================================
2544
- // REPLACE THE OLD LOGIC WITH THIS DIRECT COPY
2545
- // ===================================================================
2546
-
2547
2544
  const stateEntry = getGlobalStore
2548
2545
  .getState()
2549
2546
  .stateComponents.get(stateKey); // Use stateKey here