@versini/ui-datagrid 0.3.8 → 0.4.1
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/README.md +106 -29
- package/dist/DataGrid/DataGrid.js +1 -1
- package/dist/DataGrid/DataGridContext.js +1 -1
- package/dist/DataGrid/DataGridTypes.d.ts +280 -0
- package/dist/DataGrid/DataGridTypes.js +9 -0
- package/dist/DataGrid/index.js +1 -1
- package/dist/DataGridAnimated/AnimatedWrapper.d.ts +11 -7
- package/dist/DataGridAnimated/AnimatedWrapper.js +12 -8
- package/dist/DataGridAnimated/index.js +1 -1
- package/dist/DataGridAnimated/useAnimatedHeight.js +1 -1
- package/dist/DataGridBody/DataGridBody.js +12 -56
- package/dist/DataGridBody/getBodyClass.d.ts +10 -0
- package/dist/DataGridBody/getBodyClass.js +24 -0
- package/dist/DataGridBody/index.js +1 -1
- package/dist/DataGridBody/useColumnMeasurement.d.ts +11 -0
- package/dist/DataGridBody/useColumnMeasurement.js +68 -0
- package/dist/DataGridCell/DataGridCell.js +1 -1
- package/dist/DataGridCell/index.js +1 -1
- package/dist/DataGridCellSort/DataGridCellSort.js +1 -1
- package/dist/DataGridCellSort/index.js +1 -1
- package/dist/DataGridConstants/DataGridConstants.js +1 -1
- package/dist/DataGridConstants/index.js +1 -1
- package/dist/DataGridFooter/DataGridFooter.js +1 -1
- package/dist/DataGridFooter/index.js +1 -1
- package/dist/DataGridHeader/DataGridHeader.js +1 -1
- package/dist/DataGridHeader/index.js +1 -1
- package/dist/DataGridInfinite/DataGridInfiniteBody.d.ts +52 -0
- package/dist/DataGridInfinite/DataGridInfiniteBody.js +335 -0
- package/dist/DataGridInfinite/index.d.ts +2 -4
- package/dist/DataGridInfinite/index.js +4 -8
- package/dist/DataGridRow/DataGridRow.js +5 -3
- package/dist/DataGridRow/index.js +1 -1
- package/dist/DataGridSorting/index.js +1 -1
- package/dist/DataGridSorting/sortingUtils.js +1 -1
- package/dist/utilities/classes.d.ts +6 -2
- package/dist/utilities/classes.js +35 -8
- package/package.json +2 -2
- package/dist/DataGridInfinite/InfiniteScrollMarker.d.ts +0 -31
- package/dist/DataGridInfinite/InfiniteScrollMarker.js +0 -54
- package/dist/DataGridInfinite/useInfiniteScroll.d.ts +0 -92
- package/dist/DataGridInfinite/useInfiniteScroll.js +0 -136
|
@@ -124,12 +124,16 @@ export declare const getFooterClasses: ({ className, stickyFooter, mode, blurEff
|
|
|
124
124
|
stickyFooter?: boolean;
|
|
125
125
|
}) => string;
|
|
126
126
|
/**
|
|
127
|
-
* Generates classes for DataGridRow.
|
|
127
|
+
* Generates classes for DataGridRow. When rowIndex is provided (e.g., from
|
|
128
|
+
* DataGridInfiniteBody), explicit odd/even classes are used instead of CSS
|
|
129
|
+
* :nth-child selectors, which don't work with wrapper elements.
|
|
128
130
|
*/
|
|
129
|
-
export declare const getRowClasses: ({ mode, className, cellWrapper, }: {
|
|
131
|
+
export declare const getRowClasses: ({ mode, className, cellWrapper, rowIndex, isLastRow, }: {
|
|
130
132
|
mode: ThemeMode;
|
|
131
133
|
cellWrapper?: CellWrapperType;
|
|
132
134
|
className?: string;
|
|
135
|
+
rowIndex?: number;
|
|
136
|
+
isLastRow?: boolean;
|
|
133
137
|
}) => string;
|
|
134
138
|
/**
|
|
135
139
|
* Generates classes for DataGridCell.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
@versini/ui-datagrid v0.
|
|
2
|
+
@versini/ui-datagrid v0.4.1
|
|
3
3
|
© 2026 gizmette.com
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -181,22 +181,49 @@ import { BlurEffects, CellWrapper } from "../DataGridConstants/DataGridConstants
|
|
|
181
181
|
}), className);
|
|
182
182
|
};
|
|
183
183
|
/**
|
|
184
|
-
* Generates classes for DataGridRow.
|
|
185
|
-
|
|
184
|
+
* Generates classes for DataGridRow. When rowIndex is provided (e.g., from
|
|
185
|
+
* DataGridInfiniteBody), explicit odd/even classes are used instead of CSS
|
|
186
|
+
* :nth-child selectors, which don't work with wrapper elements.
|
|
187
|
+
*/ const getRowClasses = ({ mode, className, cellWrapper, rowIndex, isLastRow })=>{
|
|
186
188
|
const layoutClass = "group grid items-center";
|
|
187
189
|
if (cellWrapper === CellWrapper.HEADER || cellWrapper === CellWrapper.FOOTER) {
|
|
188
190
|
return clsx(layoutClass, className);
|
|
189
191
|
}
|
|
190
|
-
|
|
192
|
+
/**
|
|
193
|
+
* When rowIndex is provided, use explicit classes instead of CSS :nth-child
|
|
194
|
+
* selectors. CSS :nth-child doesn't work correctly when rows are wrapped
|
|
195
|
+
* (e.g., in DataGridInfiniteBody).
|
|
196
|
+
*/ const hasExplicitIndex = rowIndex !== undefined;
|
|
197
|
+
const isOdd = hasExplicitIndex && rowIndex % 2 === 0; // 0-based index: 0,2,4 are visually "odd" rows (1st, 3rd, 5th)
|
|
198
|
+
const isEven = hasExplicitIndex && rowIndex % 2 === 1;
|
|
199
|
+
/**
|
|
200
|
+
* Border classes: use explicit border-0 for last row when isLastRow is
|
|
201
|
+
* provided, otherwise fall back to CSS :last-child selector.
|
|
202
|
+
*/ const borderClasses = isLastRow !== undefined ? isLastRow ? "border-b border-b-transparent" // Last row: transparent border to maintain spacing
|
|
203
|
+
: "border-b" : "border-b last:border-0"; // Fallback to CSS :last-child
|
|
204
|
+
return clsx(layoutClass, borderClasses, getBorderClasses({
|
|
191
205
|
mode
|
|
192
206
|
}), {
|
|
193
|
-
|
|
207
|
+
// Explicit odd/even when rowIndex is provided.
|
|
208
|
+
"bg-table-dark-odd": hasExplicitIndex && isOdd && mode === "dark",
|
|
209
|
+
"bg-table-dark-even": hasExplicitIndex && isEven && mode === "dark",
|
|
210
|
+
"bg-table-light-odd": hasExplicitIndex && isOdd && mode === "light",
|
|
211
|
+
"bg-table-light-even": hasExplicitIndex && isEven && mode === "light",
|
|
212
|
+
// System mode with explicit index.
|
|
213
|
+
"bg-table-dark-odd dark:bg-table-light-odd": hasExplicitIndex && isOdd && mode === "system",
|
|
214
|
+
"bg-table-dark-even dark:bg-table-light-even": hasExplicitIndex && isEven && mode === "system",
|
|
215
|
+
// Alt-system mode with explicit index.
|
|
216
|
+
"bg-table-light-odd dark:bg-table-dark-odd": hasExplicitIndex && isOdd && mode === "alt-system",
|
|
217
|
+
"bg-table-light-even dark:bg-table-dark-even": hasExplicitIndex && isEven && mode === "alt-system",
|
|
218
|
+
// CSS :nth-child selectors (original behavior when rowIndex not provided).
|
|
219
|
+
"odd:bg-table-dark-odd even:bg-table-dark-even": !hasExplicitIndex && mode === "dark",
|
|
220
|
+
"odd:bg-table-light-odd even:bg-table-light-even": !hasExplicitIndex && mode === "light",
|
|
221
|
+
"odd:bg-table-dark-odd even:bg-table-dark-even dark:odd:bg-table-light-odd dark:even:bg-table-light-even": !hasExplicitIndex && mode === "system",
|
|
222
|
+
"odd:bg-table-light-odd even:bg-table-light-even dark:odd:bg-table-dark-odd dark:even:bg-table-dark-even": !hasExplicitIndex && mode === "alt-system",
|
|
223
|
+
// Hover effects (same for both modes).
|
|
194
224
|
"hover:bg-table-dark-hover": mode === "dark",
|
|
195
|
-
"odd:bg-table-light-odd even:bg-table-light-even": mode === "light",
|
|
196
225
|
"hover:bg-table-light-hover": mode === "light",
|
|
197
|
-
"odd:bg-table-dark-odd even:bg-table-dark-even dark:odd:bg-table-light-odd dark:even:bg-table-light-even": mode === "system",
|
|
198
226
|
"hover:bg-table-dark-hover dark:hover:bg-table-light-hover": mode === "system",
|
|
199
|
-
"odd:bg-table-light-odd even:bg-table-light-even dark:odd:bg-table-dark-odd dark:even:bg-table-dark-even": mode === "alt-system",
|
|
200
227
|
"hover:bg-table-light-hover dark:hover:bg-table-dark-hover": mode === "alt-system"
|
|
201
228
|
}, className);
|
|
202
229
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@versini/ui-datagrid",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Arno Versini",
|
|
6
6
|
"publishConfig": {
|
|
@@ -94,5 +94,5 @@
|
|
|
94
94
|
"sideEffects": [
|
|
95
95
|
"**/*.css"
|
|
96
96
|
],
|
|
97
|
-
"gitHead": "
|
|
97
|
+
"gitHead": "77685390e91706f56ebacec061f047f85e6e2982"
|
|
98
98
|
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
export type InfiniteScrollMarkerProps = {
|
|
2
|
-
/**
|
|
3
|
-
* Custom class name for the row.
|
|
4
|
-
*/
|
|
5
|
-
className?: string;
|
|
6
|
-
/**
|
|
7
|
-
* Whether to show the marker (for debugging). In production, the marker is
|
|
8
|
-
* invisible.
|
|
9
|
-
*/
|
|
10
|
-
debug?: boolean;
|
|
11
|
-
};
|
|
12
|
-
/**
|
|
13
|
-
* Invisible marker row for infinite scroll. Place this at the end of your
|
|
14
|
-
* DataGridBody.
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* ```tsx
|
|
18
|
-
* const { hasMore, markerRef } = useInfiniteScroll({ totalItems: data.length });
|
|
19
|
-
*
|
|
20
|
-
* return (
|
|
21
|
-
* <DataGridBody>
|
|
22
|
-
* {data.slice(0, visibleCount).map((item) => (
|
|
23
|
-
* <DataGridRow key={item.id}>...</DataGridRow>
|
|
24
|
-
* ))}
|
|
25
|
-
* {hasMore && <InfiniteScrollMarker ref={markerRef} />}
|
|
26
|
-
* </DataGridBody>
|
|
27
|
-
* );
|
|
28
|
-
* ```
|
|
29
|
-
*
|
|
30
|
-
*/
|
|
31
|
-
export declare const InfiniteScrollMarker: import("react").ForwardRefExoticComponent<InfiniteScrollMarkerProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
@versini/ui-datagrid v0.3.8
|
|
3
|
-
© 2026 gizmette.com
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { jsx } from "react/jsx-runtime";
|
|
7
|
-
import { forwardRef } from "react";
|
|
8
|
-
|
|
9
|
-
;// CONCATENATED MODULE: external "react/jsx-runtime"
|
|
10
|
-
|
|
11
|
-
;// CONCATENATED MODULE: external "react"
|
|
12
|
-
|
|
13
|
-
;// CONCATENATED MODULE: ./src/DataGridInfinite/InfiniteScrollMarker.tsx
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Invisible marker row for infinite scroll. Place this at the end of your
|
|
18
|
-
* DataGridBody.
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
* ```tsx
|
|
22
|
-
* const { hasMore, markerRef } = useInfiniteScroll({ totalItems: data.length });
|
|
23
|
-
*
|
|
24
|
-
* return (
|
|
25
|
-
* <DataGridBody>
|
|
26
|
-
* {data.slice(0, visibleCount).map((item) => (
|
|
27
|
-
* <DataGridRow key={item.id}>...</DataGridRow>
|
|
28
|
-
* ))}
|
|
29
|
-
* {hasMore && <InfiniteScrollMarker ref={markerRef} />}
|
|
30
|
-
* </DataGridBody>
|
|
31
|
-
* );
|
|
32
|
-
* ```
|
|
33
|
-
*
|
|
34
|
-
*/ const InfiniteScrollMarker_InfiniteScrollMarker = /*#__PURE__*/ forwardRef(function InfiniteScrollMarker({ className, debug = false }, ref) {
|
|
35
|
-
return /*#__PURE__*/ jsx("div", {
|
|
36
|
-
ref: ref,
|
|
37
|
-
role: "row",
|
|
38
|
-
className: className,
|
|
39
|
-
"aria-hidden": "true",
|
|
40
|
-
style: {
|
|
41
|
-
height: debug ? "40px" : "1px",
|
|
42
|
-
background: debug ? "red" : "transparent"
|
|
43
|
-
},
|
|
44
|
-
children: /*#__PURE__*/ jsx("div", {
|
|
45
|
-
role: "gridcell",
|
|
46
|
-
style: {
|
|
47
|
-
padding: 0,
|
|
48
|
-
border: 0
|
|
49
|
-
}
|
|
50
|
-
})
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
export { InfiniteScrollMarker_InfiniteScrollMarker as InfiniteScrollMarker };
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Finds the nearest scrollable ancestor of an element. Returns null if no
|
|
3
|
-
* scrollable ancestor is found (uses viewport).
|
|
4
|
-
*/
|
|
5
|
-
export declare function findScrollableAncestor(element: HTMLElement): Element | null;
|
|
6
|
-
export type UseInfiniteScrollOptions = {
|
|
7
|
-
/**
|
|
8
|
-
* Number of items to show initially and to add on each scroll.
|
|
9
|
-
* @default 20
|
|
10
|
-
*/
|
|
11
|
-
batchSize?: number;
|
|
12
|
-
/**
|
|
13
|
-
* How many items before the end to trigger loading more.
|
|
14
|
-
* @default 5
|
|
15
|
-
*/
|
|
16
|
-
threshold?: number;
|
|
17
|
-
/**
|
|
18
|
-
* IntersectionObserver root margin.
|
|
19
|
-
* @default "20px"
|
|
20
|
-
*/
|
|
21
|
-
rootMargin?: string;
|
|
22
|
-
/**
|
|
23
|
-
* Total number of items in the dataset. Used to determine if more items can be
|
|
24
|
-
* loaded.
|
|
25
|
-
*/
|
|
26
|
-
totalItems: number;
|
|
27
|
-
/**
|
|
28
|
-
* Initial number of visible items (optional). If not provided, uses batchSize.
|
|
29
|
-
* + threshold.
|
|
30
|
-
*/
|
|
31
|
-
initialVisibleCount?: number;
|
|
32
|
-
/**
|
|
33
|
-
* Callback when more items are loaded.
|
|
34
|
-
*/
|
|
35
|
-
onLoadMore?: (newVisibleCount: number) => void;
|
|
36
|
-
/**
|
|
37
|
-
* The scroll container element for IntersectionObserver root. Required when
|
|
38
|
-
* the DataGrid is inside a scrollable container (e.g., with maxHeight). Pass
|
|
39
|
-
* null to use the viewport as root.
|
|
40
|
-
*/
|
|
41
|
-
scrollContainer?: Element | null;
|
|
42
|
-
};
|
|
43
|
-
export type UseInfiniteScrollReturn = {
|
|
44
|
-
/**
|
|
45
|
-
* Current number of visible items.
|
|
46
|
-
*/
|
|
47
|
-
visibleCount: number;
|
|
48
|
-
/**
|
|
49
|
-
* Whether there are more items to load.
|
|
50
|
-
*/
|
|
51
|
-
hasMore: boolean;
|
|
52
|
-
/**
|
|
53
|
-
* Callback ref to attach to the marker element.
|
|
54
|
-
*/
|
|
55
|
-
markerRef: (node: HTMLElement | null) => void;
|
|
56
|
-
/**
|
|
57
|
-
* Reset visible count to initial value.
|
|
58
|
-
*/
|
|
59
|
-
reset: () => void;
|
|
60
|
-
/**
|
|
61
|
-
* Manually set the visible count (useful for scroll-to-item).
|
|
62
|
-
*/
|
|
63
|
-
setVisibleCount: React.Dispatch<React.SetStateAction<number>>;
|
|
64
|
-
/**
|
|
65
|
-
* Expand visible count to include a specific index.
|
|
66
|
-
*/
|
|
67
|
-
expandToInclude: (index: number) => void;
|
|
68
|
-
};
|
|
69
|
-
/**
|
|
70
|
-
* Hook for implementing infinite scroll with IntersectionObserver.
|
|
71
|
-
*
|
|
72
|
-
* @example
|
|
73
|
-
* ```tsx
|
|
74
|
-
* const { visibleCount, hasMore, markerRef } = useInfiniteScroll({
|
|
75
|
-
* totalItems: data.length,
|
|
76
|
-
* batchSize: 25,
|
|
77
|
-
* });
|
|
78
|
-
*
|
|
79
|
-
* return (
|
|
80
|
-
* <DataGrid>
|
|
81
|
-
* <DataGridBody>
|
|
82
|
-
* {data.slice(0, visibleCount).map((item, index) => (
|
|
83
|
-
* <DataGridRow key={item.id}>...</DataGridRow>
|
|
84
|
-
* ))}
|
|
85
|
-
* {hasMore && <InfiniteScrollMarker ref={markerRef} />}
|
|
86
|
-
* </DataGridBody>
|
|
87
|
-
* </DataGrid>
|
|
88
|
-
* );
|
|
89
|
-
* ```
|
|
90
|
-
*
|
|
91
|
-
*/
|
|
92
|
-
export declare function useInfiniteScroll({ batchSize, threshold, rootMargin, totalItems, initialVisibleCount, onLoadMore, scrollContainer, }: UseInfiniteScrollOptions): UseInfiniteScrollReturn;
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
@versini/ui-datagrid v0.3.8
|
|
3
|
-
© 2026 gizmette.com
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { useCallback, useEffect, useRef, useState } from "react";
|
|
7
|
-
|
|
8
|
-
;// CONCATENATED MODULE: external "react"
|
|
9
|
-
|
|
10
|
-
;// CONCATENATED MODULE: ./src/DataGridInfinite/useInfiniteScroll.ts
|
|
11
|
-
|
|
12
|
-
const DEFAULT_BATCH_SIZE = 20;
|
|
13
|
-
const DEFAULT_THRESHOLD = 5;
|
|
14
|
-
const DEFAULT_ROOT_MARGIN = "20px";
|
|
15
|
-
/**
|
|
16
|
-
* Finds the nearest scrollable ancestor of an element. Returns null if no
|
|
17
|
-
* scrollable ancestor is found (uses viewport).
|
|
18
|
-
*/ function findScrollableAncestor(element) {
|
|
19
|
-
let parent = element.parentElement;
|
|
20
|
-
while(parent){
|
|
21
|
-
const style = getComputedStyle(parent);
|
|
22
|
-
const overflowY = style.overflowY;
|
|
23
|
-
if (overflowY === "auto" || overflowY === "scroll") {
|
|
24
|
-
return parent;
|
|
25
|
-
}
|
|
26
|
-
parent = parent.parentElement;
|
|
27
|
-
}
|
|
28
|
-
return null;
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Hook for implementing infinite scroll with IntersectionObserver.
|
|
32
|
-
*
|
|
33
|
-
* @example
|
|
34
|
-
* ```tsx
|
|
35
|
-
* const { visibleCount, hasMore, markerRef } = useInfiniteScroll({
|
|
36
|
-
* totalItems: data.length,
|
|
37
|
-
* batchSize: 25,
|
|
38
|
-
* });
|
|
39
|
-
*
|
|
40
|
-
* return (
|
|
41
|
-
* <DataGrid>
|
|
42
|
-
* <DataGridBody>
|
|
43
|
-
* {data.slice(0, visibleCount).map((item, index) => (
|
|
44
|
-
* <DataGridRow key={item.id}>...</DataGridRow>
|
|
45
|
-
* ))}
|
|
46
|
-
* {hasMore && <InfiniteScrollMarker ref={markerRef} />}
|
|
47
|
-
* </DataGridBody>
|
|
48
|
-
* </DataGrid>
|
|
49
|
-
* );
|
|
50
|
-
* ```
|
|
51
|
-
*
|
|
52
|
-
*/ function useInfiniteScroll({ batchSize = DEFAULT_BATCH_SIZE, threshold = DEFAULT_THRESHOLD, rootMargin = DEFAULT_ROOT_MARGIN, totalItems, initialVisibleCount, onLoadMore, scrollContainer }) {
|
|
53
|
-
const observerRef = useRef(null);
|
|
54
|
-
const initialCount = initialVisibleCount ?? batchSize + threshold;
|
|
55
|
-
const [visibleCount, setVisibleCount] = useState(Math.min(initialCount, totalItems));
|
|
56
|
-
const hasMore = visibleCount < totalItems;
|
|
57
|
-
/**
|
|
58
|
-
* IntersectionObserver callback - triggered when marker becomes visible.
|
|
59
|
-
*/ const handleIntersection = useCallback((entries)=>{
|
|
60
|
-
const target = entries[0];
|
|
61
|
-
if (target?.isIntersecting) {
|
|
62
|
-
setVisibleCount((prev)=>{
|
|
63
|
-
const newCount = Math.min(prev + batchSize, totalItems);
|
|
64
|
-
if (onLoadMore && newCount > prev) {
|
|
65
|
-
onLoadMore(newCount);
|
|
66
|
-
}
|
|
67
|
-
return newCount;
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
}, [
|
|
71
|
-
batchSize,
|
|
72
|
-
totalItems,
|
|
73
|
-
onLoadMore
|
|
74
|
-
]);
|
|
75
|
-
/**
|
|
76
|
-
* Callback ref for the marker element. Creates/disconnects observer as needed.
|
|
77
|
-
*/ const markerRef = useCallback((node)=>{
|
|
78
|
-
// Disconnect previous observer.
|
|
79
|
-
if (observerRef.current) {
|
|
80
|
-
observerRef.current.disconnect();
|
|
81
|
-
observerRef.current = null;
|
|
82
|
-
}
|
|
83
|
-
if (node && typeof IntersectionObserver !== "undefined") {
|
|
84
|
-
// Find the scrollable ancestor if not explicitly provided.
|
|
85
|
-
const root = scrollContainer ?? findScrollableAncestor(node);
|
|
86
|
-
const options = {
|
|
87
|
-
root,
|
|
88
|
-
rootMargin
|
|
89
|
-
};
|
|
90
|
-
observerRef.current = new IntersectionObserver(handleIntersection, options);
|
|
91
|
-
observerRef.current.observe(node);
|
|
92
|
-
}
|
|
93
|
-
}, [
|
|
94
|
-
handleIntersection,
|
|
95
|
-
rootMargin,
|
|
96
|
-
scrollContainer
|
|
97
|
-
]);
|
|
98
|
-
/**
|
|
99
|
-
* Reset to initial count.
|
|
100
|
-
*/ const reset = useCallback(()=>{
|
|
101
|
-
setVisibleCount(Math.min(initialCount, totalItems));
|
|
102
|
-
}, [
|
|
103
|
-
initialCount,
|
|
104
|
-
totalItems
|
|
105
|
-
]);
|
|
106
|
-
/**
|
|
107
|
-
* Expand visible count to include a specific index. Useful for scroll-to-row
|
|
108
|
-
* functionality.
|
|
109
|
-
*/ const expandToInclude = useCallback((index)=>{
|
|
110
|
-
if (index >= visibleCount) {
|
|
111
|
-
setVisibleCount(index + threshold);
|
|
112
|
-
}
|
|
113
|
-
}, [
|
|
114
|
-
visibleCount,
|
|
115
|
-
threshold
|
|
116
|
-
]);
|
|
117
|
-
/**
|
|
118
|
-
* Cleanup observer on unmount.
|
|
119
|
-
*/ useEffect(()=>{
|
|
120
|
-
return ()=>{
|
|
121
|
-
if (observerRef.current) {
|
|
122
|
-
observerRef.current.disconnect();
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
}, []);
|
|
126
|
-
return {
|
|
127
|
-
visibleCount,
|
|
128
|
-
hasMore,
|
|
129
|
-
markerRef,
|
|
130
|
-
reset,
|
|
131
|
-
setVisibleCount,
|
|
132
|
-
expandToInclude
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export { findScrollableAncestor, useInfiniteScroll };
|