cogsbox-state 0.5.300 → 0.5.301

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.300",
3
+ "version": "0.5.301",
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
@@ -1820,27 +1820,20 @@ function createProxyHandler<T>(
1820
1820
  []
1821
1821
  );
1822
1822
 
1823
- // --- This useEffect now cleanly subscribes to height changes ---
1824
1823
  useEffect(() => {
1825
- // Subscribe to shadow state changes for this specific key.
1826
1824
  const unsubscribe = getGlobalStore
1827
1825
  .getState()
1828
1826
  .subscribeToShadowState(stateKey, forceRecalculate);
1829
-
1830
- // On initial mount, we still need to trigger one recalculation
1831
- // to capture heights from the very first render.
1832
1827
  const timer = setTimeout(forceRecalculate, 50);
1833
-
1834
- // Cleanup function to unsubscribe when the component unmounts.
1835
1828
  return () => {
1836
1829
  unsubscribe();
1837
1830
  clearTimeout(timer);
1838
1831
  };
1839
- }, [stateKey, forceRecalculate]); // Runs only once on mount.
1832
+ }, [stateKey, forceRecalculate]);
1840
1833
 
1841
1834
  const isAtBottomRef = useRef(stickToBottom);
1842
- const previousTotalCountRef = useRef(0);
1843
1835
  const isInitialMountRef = useRef(true);
1836
+ const previousTotalCountRef = useRef(0);
1844
1837
 
1845
1838
  const sourceArray = getGlobalStore().getNestedState(
1846
1839
  stateKey,
@@ -1876,34 +1869,28 @@ function createProxyHandler<T>(
1876
1869
  validIndices,
1877
1870
  });
1878
1871
  }, [range.startIndex, range.endIndex, sourceArray]);
1872
+
1879
1873
  useLayoutEffect(() => {
1880
1874
  const container = containerRef.current;
1881
1875
  if (!container) return;
1882
1876
 
1883
1877
  const listGrew = totalCount > previousTotalCountRef.current;
1884
-
1885
- // --- THE FIX for BOTH initial load and new entries ---
1886
- // We capture the scroll position *before* we do anything else.
1887
- // We also check if we are VERY close to the bottom. This will be true
1888
- // on initial load (0 scrollHeight, 0 scrollTop) and when user is at the end.
1889
- const wasAtBottom =
1890
- container.scrollHeight -
1891
- container.scrollTop -
1892
- container.clientHeight <
1893
- 5;
1894
-
1895
- // Now we update the ref for the *next* render cycle.
1896
1878
  previousTotalCountRef.current = totalCount;
1897
1879
 
1880
+ const wasAtBottom = isAtBottomRef.current;
1881
+
1898
1882
  const handleScroll = () => {
1899
- // ... (binary search logic to setRange is the same) ...
1900
1883
  const { scrollTop, clientHeight, scrollHeight } = container;
1884
+ isAtBottomRef.current =
1885
+ scrollHeight - scrollTop - clientHeight < 5;
1886
+
1901
1887
  let search = (list: number[], value: number) => {
1902
- let low = 0;
1903
- let high = list.length - 1;
1888
+ let low = 0,
1889
+ high = list.length - 1;
1904
1890
  while (low <= high) {
1905
1891
  const mid = Math.floor((low + high) / 2);
1906
- if (list[mid]! < value) {
1892
+ const midValue = list[mid]!;
1893
+ if (midValue < value) {
1907
1894
  low = mid + 1;
1908
1895
  } else {
1909
1896
  high = mid - 1;
@@ -1937,20 +1924,21 @@ function createProxyHandler<T>(
1937
1924
  });
1938
1925
  handleScroll();
1939
1926
 
1940
- // This single block now handles all cases.
1941
- if (
1942
- stickToBottom &&
1943
- (listGrew || isInitialMountRef.current) &&
1944
- wasAtBottom
1945
- ) {
1946
- container.scrollTo({
1947
- top: container.scrollHeight,
1948
- behavior: "auto",
1949
- });
1927
+ if (stickToBottom) {
1928
+ if (isInitialMountRef.current) {
1929
+ container.scrollTo({
1930
+ top: container.scrollHeight,
1931
+ behavior: "auto",
1932
+ });
1933
+ } else if (listGrew && wasAtBottom) {
1934
+ container.scrollTo({
1935
+ top: container.scrollHeight,
1936
+ behavior: "auto",
1937
+ });
1938
+ }
1950
1939
  }
1951
1940
 
1952
- // We only set this to false after the first correct layout has been established.
1953
- if (positions.length > 0) {
1941
+ if (totalCount > 0) {
1954
1942
  isInitialMountRef.current = false;
1955
1943
  }
1956
1944