cogsbox-state 0.5.385 → 0.5.387
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/dist/CogsState.jsx +474 -470
- package/dist/CogsState.jsx.map +1 -1
- package/package.json +1 -1
- package/src/CogsState.tsx +49 -30
package/package.json
CHANGED
package/src/CogsState.tsx
CHANGED
|
@@ -1829,7 +1829,10 @@ function createProxyHandler<T>(
|
|
|
1829
1829
|
const prevDepsRef = useRef(dependencies);
|
|
1830
1830
|
const lastUpdateAtScrollTop = useRef(0);
|
|
1831
1831
|
const [shadowUpdateTrigger, setShadowUpdateTrigger] = useState(0);
|
|
1832
|
-
|
|
1832
|
+
const scrollAnchorRef = useRef<{
|
|
1833
|
+
top: number;
|
|
1834
|
+
height: number;
|
|
1835
|
+
} | null>(null);
|
|
1833
1836
|
useEffect(() => {
|
|
1834
1837
|
const unsubscribe = getGlobalStore
|
|
1835
1838
|
.getState()
|
|
@@ -1884,27 +1887,46 @@ function createProxyHandler<T>(
|
|
|
1884
1887
|
// --- 1. STATE CONTROLLER ---
|
|
1885
1888
|
// This effect decides which state to transition TO.
|
|
1886
1889
|
useLayoutEffect(() => {
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
prevDepsRef.current
|
|
1890
|
-
);
|
|
1890
|
+
// THIS `IF` BLOCK IS THE NEW LOGIC
|
|
1891
|
+
const container = containerRef.current;
|
|
1891
1892
|
const hasNewItems = totalCount > prevTotalCountRef.current;
|
|
1892
1893
|
|
|
1893
|
-
if (
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1894
|
+
if (hasNewItems && scrollAnchorRef.current && container) {
|
|
1895
|
+
// User was scrolled up, new items arrived. Restore the scroll position.
|
|
1896
|
+
const { top: prevScrollTop, height: prevScrollHeight } =
|
|
1897
|
+
scrollAnchorRef.current;
|
|
1898
|
+
container.scrollTop =
|
|
1899
|
+
prevScrollTop + (container.scrollHeight - prevScrollHeight);
|
|
1898
1900
|
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
status === "LOCKED_AT_BOTTOM" &&
|
|
1902
|
-
stickToBottom
|
|
1903
|
-
) {
|
|
1901
|
+
// IMPORTANT: Clear the anchor after using it.
|
|
1902
|
+
scrollAnchorRef.current = null;
|
|
1904
1903
|
console.log(
|
|
1905
|
-
|
|
1904
|
+
`ANCHOR RESTORED to scrollTop: ${container.scrollTop}`
|
|
1906
1905
|
);
|
|
1907
|
-
|
|
1906
|
+
}
|
|
1907
|
+
// YOUR EXISTING LOGIC CONTINUES BELOW in an else-if structure
|
|
1908
|
+
else {
|
|
1909
|
+
const depsChanged = !isDeepEqual(
|
|
1910
|
+
dependencies,
|
|
1911
|
+
prevDepsRef.current
|
|
1912
|
+
);
|
|
1913
|
+
|
|
1914
|
+
if (depsChanged) {
|
|
1915
|
+
console.log("TRANSITION: Deps changed -> IDLE_AT_TOP");
|
|
1916
|
+
setStatus("IDLE_AT_TOP");
|
|
1917
|
+
return; // Stop here, let the next effect handle the action for the new state.
|
|
1918
|
+
}
|
|
1919
|
+
|
|
1920
|
+
if (
|
|
1921
|
+
hasNewItems &&
|
|
1922
|
+
status === "LOCKED_AT_BOTTOM" &&
|
|
1923
|
+
stickToBottom
|
|
1924
|
+
) {
|
|
1925
|
+
console.log(
|
|
1926
|
+
"TRANSITION: New items arrived while locked -> GETTING_HEIGHTS"
|
|
1927
|
+
);
|
|
1928
|
+
setStatus("GETTING_HEIGHTS");
|
|
1929
|
+
}
|
|
1908
1930
|
}
|
|
1909
1931
|
|
|
1910
1932
|
prevTotalCountRef.current = totalCount;
|
|
@@ -2004,28 +2026,25 @@ function createProxyHandler<T>(
|
|
|
2004
2026
|
}
|
|
2005
2027
|
|
|
2006
2028
|
const { scrollTop, scrollHeight, clientHeight } = container;
|
|
2007
|
-
|
|
2008
|
-
"scrollTop, scrollHeight, clientHeight ",
|
|
2009
|
-
scrollTop,
|
|
2010
|
-
scrollHeight,
|
|
2011
|
-
clientHeight
|
|
2012
|
-
);
|
|
2013
|
-
// --- START OF MINIMAL FIX ---
|
|
2014
|
-
// This block is the only thing added. It updates the master 'status'.
|
|
2015
|
-
// This is the critical missing piece that tells the component if it should auto-scroll.
|
|
2016
|
-
// A 10px buffer prevents jittering when you are scrolled to the very bottom.
|
|
2029
|
+
|
|
2017
2030
|
const isAtBottom =
|
|
2018
2031
|
scrollHeight - scrollTop - clientHeight < 10;
|
|
2019
|
-
|
|
2032
|
+
|
|
2020
2033
|
if (isAtBottom) {
|
|
2021
|
-
// If we scroll back to the bottom, re-lock.
|
|
2022
2034
|
if (status !== "LOCKED_AT_BOTTOM") {
|
|
2023
2035
|
setStatus("LOCKED_AT_BOTTOM");
|
|
2036
|
+
// We are at the bottom, so we don't need an anchor.
|
|
2037
|
+
scrollAnchorRef.current = null;
|
|
2024
2038
|
}
|
|
2025
2039
|
} else {
|
|
2026
|
-
// If we have scrolled up, unlock from the bottom.
|
|
2027
2040
|
if (status !== "IDLE_NOT_AT_BOTTOM") {
|
|
2028
2041
|
setStatus("IDLE_NOT_AT_BOTTOM");
|
|
2042
|
+
// THE USER SCROLLED UP. SET THE ANCHOR.
|
|
2043
|
+
scrollAnchorRef.current = {
|
|
2044
|
+
top: scrollTop,
|
|
2045
|
+
height: scrollHeight,
|
|
2046
|
+
};
|
|
2047
|
+
console.log(`ANCHOR SET at scrollTop: ${scrollTop}`);
|
|
2029
2048
|
}
|
|
2030
2049
|
}
|
|
2031
2050
|
// --- END OF MINIMAL FIX ---
|