cogsbox-state 0.5.373 → 0.5.375

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.373",
3
+ "version": "0.5.375",
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
@@ -1824,9 +1824,10 @@ function createProxyHandler<T>(
1824
1824
  endIndex: 10,
1825
1825
  });
1826
1826
  const [status, setStatus] = useState<Status>("IDLE_AT_TOP");
1827
-
1827
+ const isProgrammaticScroll = useRef(false);
1828
1828
  const prevTotalCountRef = useRef(0);
1829
1829
  const prevDepsRef = useRef(dependencies);
1830
+ const lastScrollTopRef = useRef(0);
1830
1831
 
1831
1832
  const [shadowUpdateTrigger, setShadowUpdateTrigger] = useState(0);
1832
1833
 
@@ -1962,6 +1963,7 @@ function createProxyHandler<T>(
1962
1963
  console.log(
1963
1964
  "ACTION (SCROLLING_TO_BOTTOM): Executing scroll."
1964
1965
  );
1966
+ isProgrammaticScroll.current = true;
1965
1967
  // Use 'auto' for initial load, 'smooth' for new messages.
1966
1968
  const scrollBehavior =
1967
1969
  prevTotalCountRef.current === 0 ? "auto" : "smooth";
@@ -1976,6 +1978,7 @@ function createProxyHandler<T>(
1976
1978
  console.log(
1977
1979
  "ACTION (SCROLLING_TO_BOTTOM): Scroll finished -> LOCKED_AT_BOTTOM"
1978
1980
  );
1981
+ isProgrammaticScroll.current = false;
1979
1982
  shouldNotScroll.current = false;
1980
1983
  setStatus("LOCKED_AT_BOTTOM");
1981
1984
  },
@@ -1998,28 +2001,63 @@ function createProxyHandler<T>(
1998
2001
  const container = containerRef.current;
1999
2002
  if (!container) return;
2000
2003
 
2004
+ // Define our threshold. Updating every half-item feels very smooth.
2005
+ // You can adjust this value. Using a full itemHeight also works well.
2006
+ const scrollThreshold = itemHeight / 2;
2007
+
2001
2008
  const handleUserScroll = () => {
2002
- // This is the core logic you wanted.
2009
+ // Exit early for programmatic scrolls. This is still essential.
2010
+ if (isProgrammaticScroll.current) {
2011
+ return;
2012
+ }
2003
2013
 
2014
+ const scrollTop = container.scrollTop;
2015
+
2016
+ // --- Part 1: Handle state changes immediately (this is cheap) ---
2004
2017
  const isAtBottom =
2005
2018
  container.scrollHeight -
2006
- container.scrollTop -
2019
+ scrollTop -
2007
2020
  container.clientHeight <
2008
2021
  1;
2009
2022
 
2010
2023
  if (!isAtBottom) {
2011
- console.log(
2012
- "USER ACTION: Scrolled up -> IDLE_NOT_AT_BOTTOM"
2013
- );
2024
+ if (status !== "IDLE_NOT_AT_BOTTOM") {
2025
+ console.log(
2026
+ "USER ACTION: Scrolled up -> IDLE_NOT_AT_BOTTOM"
2027
+ );
2028
+ setStatus("IDLE_NOT_AT_BOTTOM");
2029
+ }
2014
2030
  shouldNotScroll.current = true;
2015
- setStatus("IDLE_NOT_AT_BOTTOM");
2016
2031
  } else {
2032
+ if (status === "IDLE_NOT_AT_BOTTOM") {
2033
+ console.log(
2034
+ "USER ACTION: Scrolled back to bottom -> LOCKED_AT_BOTTOM"
2035
+ );
2036
+ setStatus("LOCKED_AT_BOTTOM");
2037
+ }
2017
2038
  shouldNotScroll.current = false;
2018
2039
  }
2019
2040
 
2020
- // We always update the range, regardless of state.
2021
- // This is the full, non-placeholder function.
2022
- const { scrollTop, clientHeight } = container;
2041
+ // --- Part 2: The "Smarter" Threshold Check ---
2042
+
2043
+ // Check if the scroll distance is greater than our threshold.
2044
+ // Math.abs() handles both scrolling up and down.
2045
+ if (
2046
+ Math.abs(scrollTop - lastScrollTopRef.current) <
2047
+ scrollThreshold
2048
+ ) {
2049
+ // Not scrolled far enough, do nothing.
2050
+ return;
2051
+ }
2052
+
2053
+ // If we've passed the threshold, update our reference for the next check.
2054
+ lastScrollTopRef.current = scrollTop;
2055
+
2056
+ console.log("Threshold passed: Updating virtual range."); // For debugging
2057
+
2058
+ // --- Part 3: Run the expensive calculation ---
2059
+ // This code now only runs when it's actually needed.
2060
+ const { clientHeight } = container;
2023
2061
  let low = 0,
2024
2062
  high = totalCount - 1;
2025
2063
  while (low <= high) {
@@ -2047,7 +2085,7 @@ function createProxyHandler<T>(
2047
2085
  });
2048
2086
  return () =>
2049
2087
  container.removeEventListener("scroll", handleUserScroll);
2050
- }, [totalCount, positions, status]); // Depends on status to know if it should break the lock
2088
+ }, [totalCount, positions, status, itemHeight]); // Added itemHeight to deps
2051
2089
 
2052
2090
  const scrollToBottom = useCallback(() => {
2053
2091
  console.log(