@trackunit/react-components 1.9.31 → 1.9.33
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/index.cjs.js
CHANGED
|
@@ -1353,31 +1353,46 @@ const useGeometry = (ref, { skip = false } = {}) => {
|
|
|
1353
1353
|
};
|
|
1354
1354
|
});
|
|
1355
1355
|
const resizeObserver = react.useRef(null);
|
|
1356
|
+
const [element, setElement] = react.useState(ref.current);
|
|
1357
|
+
// Track changes to ref.current on every render
|
|
1358
|
+
if (ref.current !== element) {
|
|
1359
|
+
setElement(ref.current);
|
|
1360
|
+
}
|
|
1356
1361
|
react.useEffect(() => {
|
|
1357
|
-
if (skip || !
|
|
1362
|
+
if (skip || !element) {
|
|
1358
1363
|
return;
|
|
1359
1364
|
}
|
|
1365
|
+
// Update geometry immediately when element changes
|
|
1366
|
+
const elementRect = element.getBoundingClientRect();
|
|
1367
|
+
setGeometry({
|
|
1368
|
+
width: elementRect.width,
|
|
1369
|
+
height: elementRect.height,
|
|
1370
|
+
top: elementRect.top,
|
|
1371
|
+
bottom: elementRect.bottom,
|
|
1372
|
+
left: elementRect.left,
|
|
1373
|
+
right: elementRect.right,
|
|
1374
|
+
x: elementRect.x,
|
|
1375
|
+
y: elementRect.y,
|
|
1376
|
+
});
|
|
1360
1377
|
const observe = () => {
|
|
1361
1378
|
if (!resizeObserver.current) {
|
|
1362
1379
|
resizeObserver.current = new ResizeObserver(entries => {
|
|
1363
1380
|
for (const entry of entries) {
|
|
1364
|
-
const
|
|
1381
|
+
const entryRect = entry.target.getBoundingClientRect();
|
|
1365
1382
|
setGeometry({
|
|
1366
|
-
width:
|
|
1367
|
-
height:
|
|
1368
|
-
top:
|
|
1369
|
-
bottom:
|
|
1370
|
-
left:
|
|
1371
|
-
right:
|
|
1372
|
-
x:
|
|
1373
|
-
y:
|
|
1383
|
+
width: entryRect.width,
|
|
1384
|
+
height: entryRect.height,
|
|
1385
|
+
top: entryRect.top,
|
|
1386
|
+
bottom: entryRect.bottom,
|
|
1387
|
+
left: entryRect.left,
|
|
1388
|
+
right: entryRect.right,
|
|
1389
|
+
x: entryRect.x,
|
|
1390
|
+
y: entryRect.y,
|
|
1374
1391
|
});
|
|
1375
1392
|
}
|
|
1376
1393
|
});
|
|
1377
1394
|
}
|
|
1378
|
-
|
|
1379
|
-
resizeObserver.current.observe(ref.current);
|
|
1380
|
-
}
|
|
1395
|
+
resizeObserver.current.observe(element);
|
|
1381
1396
|
};
|
|
1382
1397
|
observe();
|
|
1383
1398
|
return () => {
|
|
@@ -1385,7 +1400,7 @@ const useGeometry = (ref, { skip = false } = {}) => {
|
|
|
1385
1400
|
resizeObserver.current.disconnect();
|
|
1386
1401
|
}
|
|
1387
1402
|
};
|
|
1388
|
-
}, [
|
|
1403
|
+
}, [element, skip]);
|
|
1389
1404
|
return geometry;
|
|
1390
1405
|
};
|
|
1391
1406
|
|
|
@@ -1445,6 +1460,9 @@ const useInfiniteScroll = ({ pagination, scrollElementRef, count, estimateSize,
|
|
|
1445
1460
|
estimateSize: handleEstimateSize,
|
|
1446
1461
|
overscan: overscan ?? OVERSCAN,
|
|
1447
1462
|
onChange: handleChange,
|
|
1463
|
+
// This option enables wrapping ResizeObserver measurements in requestAnimationFrame for smoother updates and reduced layout thrashing.
|
|
1464
|
+
// It helps prevent the "ResizeObserver loop completed with undelivered notifications" error by ensuring that measurements align with the rendering cycle
|
|
1465
|
+
useAnimationFrameWithResizeObserver: true,
|
|
1448
1466
|
});
|
|
1449
1467
|
const virtualItems = rowVirtualizer.getVirtualItems();
|
|
1450
1468
|
// Auto-load more data based on scroll position and content height
|
|
@@ -3454,12 +3472,28 @@ const cvaList = cssClassVarianceUtilities.cvaMerge(["relative"]);
|
|
|
3454
3472
|
const cvaListItem$1 = cssClassVarianceUtilities.cvaMerge(["absolute", "top-0", "left-0", "w-full"], {
|
|
3455
3473
|
variants: {
|
|
3456
3474
|
separator: {
|
|
3457
|
-
line:
|
|
3475
|
+
line: "border-neutral-200",
|
|
3458
3476
|
none: "",
|
|
3459
3477
|
},
|
|
3478
|
+
contentFillsContainer: {
|
|
3479
|
+
true: "",
|
|
3480
|
+
false: "",
|
|
3481
|
+
},
|
|
3460
3482
|
},
|
|
3483
|
+
compoundVariants: [
|
|
3484
|
+
{
|
|
3485
|
+
contentFillsContainer: true,
|
|
3486
|
+
separator: "line",
|
|
3487
|
+
class: ["[&:not(:last-child)]:border-b"],
|
|
3488
|
+
},
|
|
3489
|
+
{
|
|
3490
|
+
contentFillsContainer: false,
|
|
3491
|
+
separator: "line",
|
|
3492
|
+
class: ["border-b"],
|
|
3493
|
+
},
|
|
3494
|
+
],
|
|
3461
3495
|
defaultVariants: {
|
|
3462
|
-
separator: "
|
|
3496
|
+
separator: "line",
|
|
3463
3497
|
},
|
|
3464
3498
|
});
|
|
3465
3499
|
|
|
@@ -3592,16 +3626,19 @@ const ListLoadingIndicator = ({ type, hasThumbnail, thumbnailShape, hasDescripti
|
|
|
3592
3626
|
*/
|
|
3593
3627
|
const List = ({ children, className, dataTestId,
|
|
3594
3628
|
// UseListResult properties
|
|
3595
|
-
containerRef, listRef, rows, getListItemProps, header, loadingIndicator, shouldShowLoaderAtIndex, count, isScrolling,
|
|
3596
|
-
// Unused but part of UseListResult interface
|
|
3597
|
-
getTotalSize: _getTotalSize, getVirtualItems: _getVirtualItems, scrollToOffset: _scrollToOffset, scrollToIndex: _scrollToIndex, measure: _measure, }) => {
|
|
3629
|
+
containerRef, listRef, rows, getListItemProps, header, loadingIndicator, shouldShowLoaderAtIndex, count, isScrolling, separator, topSeparatorOnScroll, isAtTop, contentFillsContainer,
|
|
3630
|
+
// Unused but part of UseListResult interface (can be used from parent)
|
|
3631
|
+
scrollOffset: _scrollOffset, getTotalSize: _getTotalSize, getVirtualItems: _getVirtualItems, scrollToOffset: _scrollToOffset, scrollToIndex: _scrollToIndex, measure: _measure, }) => {
|
|
3598
3632
|
return (jsxRuntime.jsx("div", { className: cvaListContainer({
|
|
3599
|
-
withTopSeparator: topSeparatorOnScroll &&
|
|
3633
|
+
withTopSeparator: topSeparatorOnScroll && !isAtTop,
|
|
3600
3634
|
className,
|
|
3601
3635
|
}), "data-is-scrolling": isScrolling, "data-testid": dataTestId, ref: containerRef, children: jsxRuntime.jsx("ul", { className: cvaList(), ref: listRef, children: rows.map(row => {
|
|
3602
|
-
// Generate list item props with separator styling
|
|
3636
|
+
// Generate list item props with clean separator styling
|
|
3603
3637
|
const listItemProps = getListItemProps(row, {
|
|
3604
|
-
className: cvaListItem$1({
|
|
3638
|
+
className: cvaListItem$1({
|
|
3639
|
+
separator,
|
|
3640
|
+
contentFillsContainer,
|
|
3641
|
+
}),
|
|
3605
3642
|
});
|
|
3606
3643
|
const key = row.virtualRow.key;
|
|
3607
3644
|
// Render loading row
|
|
@@ -3775,6 +3812,10 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator = DEFAUL
|
|
|
3775
3812
|
// eslint-disable-next-line react-hooks/react-compiler
|
|
3776
3813
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3777
3814
|
}, []);
|
|
3815
|
+
// Scroll to top when item count changes (like after filtering)
|
|
3816
|
+
react.useLayoutEffect(() => {
|
|
3817
|
+
virtualizer.scrollToOffset(0);
|
|
3818
|
+
}, [count, virtualizer]);
|
|
3778
3819
|
// Transform virtual items into typed rows
|
|
3779
3820
|
const rows = react.useMemo(() => {
|
|
3780
3821
|
const virtualItems = virtualizer.getVirtualItems();
|
|
@@ -3837,6 +3878,11 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator = DEFAUL
|
|
|
3837
3878
|
tabIndex: -1,
|
|
3838
3879
|
};
|
|
3839
3880
|
}, [onRowClick, virtualizer]);
|
|
3881
|
+
// Calculate scroll position states
|
|
3882
|
+
const isAtTop = react.useMemo(() => virtualizer.scrollOffset === 0, [virtualizer.scrollOffset]);
|
|
3883
|
+
// totalSize must be out from from useMemo since otherwise we'll not be able to have the the totalSize as a dependency for the contentFillsContainer
|
|
3884
|
+
const totalSize = virtualizer.getTotalSize();
|
|
3885
|
+
const contentFillsContainer = react.useMemo(() => (containerRef.current ? totalSize >= containerRef.current.clientHeight : false), [totalSize]);
|
|
3840
3886
|
return {
|
|
3841
3887
|
...virtualizer,
|
|
3842
3888
|
containerRef,
|
|
@@ -3849,6 +3895,8 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator = DEFAUL
|
|
|
3849
3895
|
count,
|
|
3850
3896
|
separator,
|
|
3851
3897
|
topSeparatorOnScroll,
|
|
3898
|
+
isAtTop,
|
|
3899
|
+
contentFillsContainer,
|
|
3852
3900
|
};
|
|
3853
3901
|
};
|
|
3854
3902
|
const getResolvedLoadingIndicator = (loadingIndicator) => {
|
package/index.esm.js
CHANGED
|
@@ -1351,31 +1351,46 @@ const useGeometry = (ref, { skip = false } = {}) => {
|
|
|
1351
1351
|
};
|
|
1352
1352
|
});
|
|
1353
1353
|
const resizeObserver = useRef(null);
|
|
1354
|
+
const [element, setElement] = useState(ref.current);
|
|
1355
|
+
// Track changes to ref.current on every render
|
|
1356
|
+
if (ref.current !== element) {
|
|
1357
|
+
setElement(ref.current);
|
|
1358
|
+
}
|
|
1354
1359
|
useEffect(() => {
|
|
1355
|
-
if (skip || !
|
|
1360
|
+
if (skip || !element) {
|
|
1356
1361
|
return;
|
|
1357
1362
|
}
|
|
1363
|
+
// Update geometry immediately when element changes
|
|
1364
|
+
const elementRect = element.getBoundingClientRect();
|
|
1365
|
+
setGeometry({
|
|
1366
|
+
width: elementRect.width,
|
|
1367
|
+
height: elementRect.height,
|
|
1368
|
+
top: elementRect.top,
|
|
1369
|
+
bottom: elementRect.bottom,
|
|
1370
|
+
left: elementRect.left,
|
|
1371
|
+
right: elementRect.right,
|
|
1372
|
+
x: elementRect.x,
|
|
1373
|
+
y: elementRect.y,
|
|
1374
|
+
});
|
|
1358
1375
|
const observe = () => {
|
|
1359
1376
|
if (!resizeObserver.current) {
|
|
1360
1377
|
resizeObserver.current = new ResizeObserver(entries => {
|
|
1361
1378
|
for (const entry of entries) {
|
|
1362
|
-
const
|
|
1379
|
+
const entryRect = entry.target.getBoundingClientRect();
|
|
1363
1380
|
setGeometry({
|
|
1364
|
-
width:
|
|
1365
|
-
height:
|
|
1366
|
-
top:
|
|
1367
|
-
bottom:
|
|
1368
|
-
left:
|
|
1369
|
-
right:
|
|
1370
|
-
x:
|
|
1371
|
-
y:
|
|
1381
|
+
width: entryRect.width,
|
|
1382
|
+
height: entryRect.height,
|
|
1383
|
+
top: entryRect.top,
|
|
1384
|
+
bottom: entryRect.bottom,
|
|
1385
|
+
left: entryRect.left,
|
|
1386
|
+
right: entryRect.right,
|
|
1387
|
+
x: entryRect.x,
|
|
1388
|
+
y: entryRect.y,
|
|
1372
1389
|
});
|
|
1373
1390
|
}
|
|
1374
1391
|
});
|
|
1375
1392
|
}
|
|
1376
|
-
|
|
1377
|
-
resizeObserver.current.observe(ref.current);
|
|
1378
|
-
}
|
|
1393
|
+
resizeObserver.current.observe(element);
|
|
1379
1394
|
};
|
|
1380
1395
|
observe();
|
|
1381
1396
|
return () => {
|
|
@@ -1383,7 +1398,7 @@ const useGeometry = (ref, { skip = false } = {}) => {
|
|
|
1383
1398
|
resizeObserver.current.disconnect();
|
|
1384
1399
|
}
|
|
1385
1400
|
};
|
|
1386
|
-
}, [
|
|
1401
|
+
}, [element, skip]);
|
|
1387
1402
|
return geometry;
|
|
1388
1403
|
};
|
|
1389
1404
|
|
|
@@ -1443,6 +1458,9 @@ const useInfiniteScroll = ({ pagination, scrollElementRef, count, estimateSize,
|
|
|
1443
1458
|
estimateSize: handleEstimateSize,
|
|
1444
1459
|
overscan: overscan ?? OVERSCAN,
|
|
1445
1460
|
onChange: handleChange,
|
|
1461
|
+
// This option enables wrapping ResizeObserver measurements in requestAnimationFrame for smoother updates and reduced layout thrashing.
|
|
1462
|
+
// It helps prevent the "ResizeObserver loop completed with undelivered notifications" error by ensuring that measurements align with the rendering cycle
|
|
1463
|
+
useAnimationFrameWithResizeObserver: true,
|
|
1446
1464
|
});
|
|
1447
1465
|
const virtualItems = rowVirtualizer.getVirtualItems();
|
|
1448
1466
|
// Auto-load more data based on scroll position and content height
|
|
@@ -3452,12 +3470,28 @@ const cvaList = cvaMerge(["relative"]);
|
|
|
3452
3470
|
const cvaListItem$1 = cvaMerge(["absolute", "top-0", "left-0", "w-full"], {
|
|
3453
3471
|
variants: {
|
|
3454
3472
|
separator: {
|
|
3455
|
-
line:
|
|
3473
|
+
line: "border-neutral-200",
|
|
3456
3474
|
none: "",
|
|
3457
3475
|
},
|
|
3476
|
+
contentFillsContainer: {
|
|
3477
|
+
true: "",
|
|
3478
|
+
false: "",
|
|
3479
|
+
},
|
|
3458
3480
|
},
|
|
3481
|
+
compoundVariants: [
|
|
3482
|
+
{
|
|
3483
|
+
contentFillsContainer: true,
|
|
3484
|
+
separator: "line",
|
|
3485
|
+
class: ["[&:not(:last-child)]:border-b"],
|
|
3486
|
+
},
|
|
3487
|
+
{
|
|
3488
|
+
contentFillsContainer: false,
|
|
3489
|
+
separator: "line",
|
|
3490
|
+
class: ["border-b"],
|
|
3491
|
+
},
|
|
3492
|
+
],
|
|
3459
3493
|
defaultVariants: {
|
|
3460
|
-
separator: "
|
|
3494
|
+
separator: "line",
|
|
3461
3495
|
},
|
|
3462
3496
|
});
|
|
3463
3497
|
|
|
@@ -3590,16 +3624,19 @@ const ListLoadingIndicator = ({ type, hasThumbnail, thumbnailShape, hasDescripti
|
|
|
3590
3624
|
*/
|
|
3591
3625
|
const List = ({ children, className, dataTestId,
|
|
3592
3626
|
// UseListResult properties
|
|
3593
|
-
containerRef, listRef, rows, getListItemProps, header, loadingIndicator, shouldShowLoaderAtIndex, count, isScrolling,
|
|
3594
|
-
// Unused but part of UseListResult interface
|
|
3595
|
-
getTotalSize: _getTotalSize, getVirtualItems: _getVirtualItems, scrollToOffset: _scrollToOffset, scrollToIndex: _scrollToIndex, measure: _measure, }) => {
|
|
3627
|
+
containerRef, listRef, rows, getListItemProps, header, loadingIndicator, shouldShowLoaderAtIndex, count, isScrolling, separator, topSeparatorOnScroll, isAtTop, contentFillsContainer,
|
|
3628
|
+
// Unused but part of UseListResult interface (can be used from parent)
|
|
3629
|
+
scrollOffset: _scrollOffset, getTotalSize: _getTotalSize, getVirtualItems: _getVirtualItems, scrollToOffset: _scrollToOffset, scrollToIndex: _scrollToIndex, measure: _measure, }) => {
|
|
3596
3630
|
return (jsx("div", { className: cvaListContainer({
|
|
3597
|
-
withTopSeparator: topSeparatorOnScroll &&
|
|
3631
|
+
withTopSeparator: topSeparatorOnScroll && !isAtTop,
|
|
3598
3632
|
className,
|
|
3599
3633
|
}), "data-is-scrolling": isScrolling, "data-testid": dataTestId, ref: containerRef, children: jsx("ul", { className: cvaList(), ref: listRef, children: rows.map(row => {
|
|
3600
|
-
// Generate list item props with separator styling
|
|
3634
|
+
// Generate list item props with clean separator styling
|
|
3601
3635
|
const listItemProps = getListItemProps(row, {
|
|
3602
|
-
className: cvaListItem$1({
|
|
3636
|
+
className: cvaListItem$1({
|
|
3637
|
+
separator,
|
|
3638
|
+
contentFillsContainer,
|
|
3639
|
+
}),
|
|
3603
3640
|
});
|
|
3604
3641
|
const key = row.virtualRow.key;
|
|
3605
3642
|
// Render loading row
|
|
@@ -3773,6 +3810,10 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator = DEFAUL
|
|
|
3773
3810
|
// eslint-disable-next-line react-hooks/react-compiler
|
|
3774
3811
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3775
3812
|
}, []);
|
|
3813
|
+
// Scroll to top when item count changes (like after filtering)
|
|
3814
|
+
useLayoutEffect(() => {
|
|
3815
|
+
virtualizer.scrollToOffset(0);
|
|
3816
|
+
}, [count, virtualizer]);
|
|
3776
3817
|
// Transform virtual items into typed rows
|
|
3777
3818
|
const rows = useMemo(() => {
|
|
3778
3819
|
const virtualItems = virtualizer.getVirtualItems();
|
|
@@ -3835,6 +3876,11 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator = DEFAUL
|
|
|
3835
3876
|
tabIndex: -1,
|
|
3836
3877
|
};
|
|
3837
3878
|
}, [onRowClick, virtualizer]);
|
|
3879
|
+
// Calculate scroll position states
|
|
3880
|
+
const isAtTop = useMemo(() => virtualizer.scrollOffset === 0, [virtualizer.scrollOffset]);
|
|
3881
|
+
// totalSize must be out from from useMemo since otherwise we'll not be able to have the the totalSize as a dependency for the contentFillsContainer
|
|
3882
|
+
const totalSize = virtualizer.getTotalSize();
|
|
3883
|
+
const contentFillsContainer = useMemo(() => (containerRef.current ? totalSize >= containerRef.current.clientHeight : false), [totalSize]);
|
|
3838
3884
|
return {
|
|
3839
3885
|
...virtualizer,
|
|
3840
3886
|
containerRef,
|
|
@@ -3847,6 +3893,8 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator = DEFAUL
|
|
|
3847
3893
|
count,
|
|
3848
3894
|
separator,
|
|
3849
3895
|
topSeparatorOnScroll,
|
|
3896
|
+
isAtTop,
|
|
3897
|
+
contentFillsContainer,
|
|
3850
3898
|
};
|
|
3851
3899
|
};
|
|
3852
3900
|
const getResolvedLoadingIndicator = (loadingIndicator) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/react-components",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.33",
|
|
4
4
|
"repository": "https://github.com/Trackunit/manager",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"engines": {
|
|
@@ -16,11 +16,11 @@
|
|
|
16
16
|
"@floating-ui/react": "^0.26.25",
|
|
17
17
|
"string-ts": "^2.0.0",
|
|
18
18
|
"tailwind-merge": "^2.0.0",
|
|
19
|
-
"@trackunit/ui-design-tokens": "1.7.
|
|
20
|
-
"@trackunit/css-class-variance-utilities": "1.7.
|
|
21
|
-
"@trackunit/shared-utils": "1.9.
|
|
22
|
-
"@trackunit/ui-icons": "1.7.
|
|
23
|
-
"@trackunit/react-test-setup": "1.4.
|
|
19
|
+
"@trackunit/ui-design-tokens": "1.7.24",
|
|
20
|
+
"@trackunit/css-class-variance-utilities": "1.7.23",
|
|
21
|
+
"@trackunit/shared-utils": "1.9.23",
|
|
22
|
+
"@trackunit/ui-icons": "1.7.25",
|
|
23
|
+
"@trackunit/react-test-setup": "1.4.23",
|
|
24
24
|
"@tanstack/react-router": "1.114.29",
|
|
25
25
|
"es-toolkit": "^1.39.10",
|
|
26
26
|
"@tanstack/react-virtual": "3.13.12"
|
|
@@ -89,4 +89,4 @@ export interface ListProps<TItem = unknown> extends CommonProps, UseListResult<T
|
|
|
89
89
|
* );
|
|
90
90
|
* ```
|
|
91
91
|
*/
|
|
92
|
-
export declare const List: <TItem = unknown>({ children, className, dataTestId, containerRef, listRef, rows, getListItemProps, header, loadingIndicator, shouldShowLoaderAtIndex, count, isScrolling,
|
|
92
|
+
export declare const List: <TItem = unknown>({ children, className, dataTestId, containerRef, listRef, rows, getListItemProps, header, loadingIndicator, shouldShowLoaderAtIndex, count, isScrolling, separator, topSeparatorOnScroll, isAtTop, contentFillsContainer, scrollOffset: _scrollOffset, getTotalSize: _getTotalSize, getVirtualItems: _getVirtualItems, scrollToOffset: _scrollToOffset, scrollToIndex: _scrollToIndex, measure: _measure, }: ListProps<TItem>) => ReactElement;
|
|
@@ -4,4 +4,5 @@ export declare const cvaListContainer: (props?: ({
|
|
|
4
4
|
export declare const cvaList: (props?: import("class-variance-authority/dist/types").ClassProp | undefined) => string;
|
|
5
5
|
export declare const cvaListItem: (props?: ({
|
|
6
6
|
separator?: "line" | "none" | null | undefined;
|
|
7
|
+
contentFillsContainer?: boolean | null | undefined;
|
|
7
8
|
} & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
|
|
@@ -150,6 +150,10 @@ export interface UseListResult<TItem> extends Pick<Virtualizer<HTMLDivElement, H
|
|
|
150
150
|
readonly separator: "none" | "line";
|
|
151
151
|
/** Show a top separator when the list is scrolled */
|
|
152
152
|
readonly topSeparatorOnScroll: boolean;
|
|
153
|
+
/** Whether the user is scrolled to the top */
|
|
154
|
+
readonly isAtTop: boolean;
|
|
155
|
+
/** Whether the content fills the container */
|
|
156
|
+
readonly contentFillsContainer: boolean;
|
|
153
157
|
}
|
|
154
158
|
/**
|
|
155
159
|
* A hook for managing virtualized list state and behavior.
|