cogsbox-state 0.5.306 → 0.5.307

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.306",
3
+ "version": "0.5.307",
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,6 +1820,7 @@ function createProxyHandler<T>(
1820
1820
  const isAtBottomRef = useRef(stickToBottom);
1821
1821
  const previousTotalCountRef = useRef(0);
1822
1822
  const isInitialMountRef = useRef(true);
1823
+ const previousTotalHeightRef = useRef(0);
1823
1824
 
1824
1825
  // Subscribe to shadow state changes
1825
1826
  useEffect(() => {
@@ -1853,6 +1854,28 @@ function createProxyHandler<T>(
1853
1854
  return { totalHeight: height, positions: pos };
1854
1855
  }, [totalCount, stateKey, path.join("."), itemHeight]);
1855
1856
 
1857
+ // Adjust scroll when height changes while at bottom
1858
+ useLayoutEffect(() => {
1859
+ const container = containerRef.current;
1860
+ if (!container) return;
1861
+
1862
+ const heightChanged =
1863
+ totalHeight !== previousTotalHeightRef.current;
1864
+ previousTotalHeightRef.current = totalHeight;
1865
+
1866
+ // If we're at bottom and height changed, maintain bottom position
1867
+ if (
1868
+ heightChanged &&
1869
+ isAtBottomRef.current &&
1870
+ !isInitialMountRef.current
1871
+ ) {
1872
+ container.scrollTo({
1873
+ top: container.scrollHeight,
1874
+ behavior: "auto",
1875
+ });
1876
+ }
1877
+ }, [totalHeight]);
1878
+
1856
1879
  const virtualState = useMemo(() => {
1857
1880
  const start = Math.max(0, range.startIndex);
1858
1881
  const end = Math.min(totalCount, range.endIndex);
@@ -1919,34 +1942,36 @@ function createProxyHandler<T>(
1919
1942
  passive: true,
1920
1943
  });
1921
1944
 
1922
- // Handle stick to bottom
1923
- if (stickToBottom) {
1924
- if (isInitialMountRef.current && totalCount > 0) {
1925
- // Double rAF to ensure everything is rendered and measured
1926
- requestAnimationFrame(() => {
1927
- requestAnimationFrame(() => {
1928
- if (containerRef.current) {
1929
- containerRef.current.scrollTo({
1930
- top: containerRef.current.scrollHeight,
1931
- behavior: "auto",
1932
- });
1933
- isInitialMountRef.current = false;
1934
- }
1935
- });
1936
- });
1937
- } else if (
1938
- !isInitialMountRef.current &&
1939
- wasAtBottom &&
1940
- listGrew
1941
- ) {
1942
- // New items added and we were at bottom - stay at bottom
1943
- requestAnimationFrame(() => {
1944
- container.scrollTo({
1945
- top: container.scrollHeight,
1946
- behavior: "smooth",
1945
+ // Handle stick to bottom for initial mount only
1946
+ if (
1947
+ stickToBottom &&
1948
+ isInitialMountRef.current &&
1949
+ totalCount > 0
1950
+ ) {
1951
+ // Set flag first to prevent height adjustment from interfering
1952
+ isAtBottomRef.current = true;
1953
+ // Wait for next frame to ensure everything is rendered
1954
+ requestAnimationFrame(() => {
1955
+ if (containerRef.current) {
1956
+ containerRef.current.scrollTo({
1957
+ top: containerRef.current.scrollHeight,
1958
+ behavior: "auto",
1947
1959
  });
1960
+ isInitialMountRef.current = false;
1961
+ }
1962
+ });
1963
+ } else if (
1964
+ !isInitialMountRef.current &&
1965
+ wasAtBottom &&
1966
+ listGrew
1967
+ ) {
1968
+ // New items added and we were at bottom - stay at bottom
1969
+ requestAnimationFrame(() => {
1970
+ container.scrollTo({
1971
+ top: container.scrollHeight,
1972
+ behavior: "smooth",
1948
1973
  });
1949
- }
1974
+ });
1950
1975
  }
1951
1976
 
1952
1977
  // Run handleScroll once to set initial range