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/dist/CogsState.d.ts +1 -0
- package/dist/CogsState.jsx +524 -531
- package/dist/CogsState.jsx.map +1 -1
- package/package.json +1 -1
- package/src/CogsState.tsx +47 -50
package/package.json
CHANGED
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
1880
|
+
totalCount === 0
|
|
1881
1881
|
) {
|
|
1882
1882
|
return;
|
|
1883
1883
|
}
|
|
1884
1884
|
|
|
1885
|
-
// STEP 1: Set range to the end
|
|
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 -
|
|
1889
|
+
startIndex: Math.max(0, totalCount - visibleCount - overscan),
|
|
1888
1890
|
endIndex: totalCount,
|
|
1889
1891
|
});
|
|
1890
1892
|
|
|
1891
|
-
// STEP 2:
|
|
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
|
-
|
|
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
|
-
|
|
1912
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
}, [
|
|
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
|