@trackunit/react-components 1.9.20 → 1.9.21
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 +55 -21
- package/index.esm.js +55 -21
- package/package.json +1 -1
- package/src/components/List/List.d.ts +1 -1
- package/src/components/List/useList.d.ts +8 -4
package/index.cjs.js
CHANGED
|
@@ -3579,7 +3579,7 @@ const ListLoadingIndicator = ({ type, hasThumbnail, thumbnailShape, hasDescripti
|
|
|
3579
3579
|
*/
|
|
3580
3580
|
const List = ({ children, className, dataTestId, topSeparatorOnScroll = false, separator = "line",
|
|
3581
3581
|
// UseListResult properties
|
|
3582
|
-
containerRef, listRef, rows, getListItemProps, header, loadingIndicator, isScrolling, scrollOffset,
|
|
3582
|
+
containerRef, listRef, rows, getListItemProps, header, loadingIndicator, shouldShowLoaderAtIndex, count, isScrolling, scrollOffset,
|
|
3583
3583
|
// Unused but part of UseListResult interface
|
|
3584
3584
|
getTotalSize: _getTotalSize, getVirtualItems: _getVirtualItems, scrollToOffset: _scrollToOffset, scrollToIndex: _scrollToIndex, measure: _measure, }) => {
|
|
3585
3585
|
return (jsxRuntime.jsx("div", { className: cvaListContainer({
|
|
@@ -3597,10 +3597,12 @@ getTotalSize: _getTotalSize, getVirtualItems: _getVirtualItems, scrollToOffset:
|
|
|
3597
3597
|
type: "skeleton",
|
|
3598
3598
|
...DEFAULT_SKELETON_LIST_ITEM_PROPS,
|
|
3599
3599
|
};
|
|
3600
|
-
|
|
3601
|
-
const
|
|
3602
|
-
const
|
|
3603
|
-
const
|
|
3600
|
+
// Use the total data count from useList, not visible rows (which are virtualized)
|
|
3601
|
+
const hasHeaderRow = !!header;
|
|
3602
|
+
const dataStartIndex = hasHeaderRow ? 1 : 0;
|
|
3603
|
+
const totalDataRows = dataStartIndex + count;
|
|
3604
|
+
const loaderIndex = row.virtualRow.index - totalDataRows;
|
|
3605
|
+
const shouldShowLoader = shouldShowLoaderAtIndex(loaderIndex);
|
|
3604
3606
|
return (jsxRuntime.jsx("li", { ...listItemProps, children: shouldShowLoader ? jsxRuntime.jsx(ListLoadingIndicator, { ...loadingConfig }) : null }, key));
|
|
3605
3607
|
}
|
|
3606
3608
|
// Render header row
|
|
@@ -3612,6 +3614,11 @@ getTotalSize: _getTotalSize, getVirtualItems: _getVirtualItems, scrollToOffset:
|
|
|
3612
3614
|
}) }) }));
|
|
3613
3615
|
};
|
|
3614
3616
|
|
|
3617
|
+
const DEFAULT_LOADING_INDICATOR_CONFIG = {
|
|
3618
|
+
type: "skeleton",
|
|
3619
|
+
initialLoadingCount: 10,
|
|
3620
|
+
scrollLoadingCount: 3,
|
|
3621
|
+
};
|
|
3615
3622
|
/**
|
|
3616
3623
|
* A hook for managing virtualized list state and behavior.
|
|
3617
3624
|
*
|
|
@@ -3644,7 +3651,7 @@ getTotalSize: _getTotalSize, getVirtualItems: _getVirtualItems, scrollToOffset:
|
|
|
3644
3651
|
* );
|
|
3645
3652
|
* ```
|
|
3646
3653
|
*/
|
|
3647
|
-
const useList = ({ count, pagination, header, getItem, loadingIndicator, onRowClick, onChange, estimateItemSize, estimateHeaderSize, overscan, }) => {
|
|
3654
|
+
const useList = ({ count, pagination, header, getItem, loadingIndicator = DEFAULT_LOADING_INDICATOR_CONFIG, onRowClick, onChange, estimateItemSize, estimateHeaderSize, overscan, }) => {
|
|
3648
3655
|
const containerRef = react.useRef(null);
|
|
3649
3656
|
const listRef = react.useRef(null);
|
|
3650
3657
|
const rowRefsMap = react.useRef(new Map());
|
|
@@ -3655,8 +3662,6 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator, onRowCl
|
|
|
3655
3662
|
const totalDataRows = dataStartIndex + dataCount;
|
|
3656
3663
|
// Calculate how many loading rows we need
|
|
3657
3664
|
const getLoadingRowsCount = react.useCallback(() => {
|
|
3658
|
-
if (!loadingIndicator)
|
|
3659
|
-
return 0;
|
|
3660
3665
|
if (pagination?.isLoading === false)
|
|
3661
3666
|
return 0;
|
|
3662
3667
|
const { type: loadingIndicatorType } = loadingIndicator;
|
|
@@ -3677,15 +3682,49 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator, onRowCl
|
|
|
3677
3682
|
}
|
|
3678
3683
|
}
|
|
3679
3684
|
}, [loadingIndicator, pagination?.isLoading, pagination?.pageInfo]);
|
|
3680
|
-
|
|
3685
|
+
// Helper to determine if a specific loader index should be shown
|
|
3686
|
+
const shouldShowLoaderAtIndex = react.useCallback((loaderIndex) => {
|
|
3687
|
+
if (pagination?.isLoading === false)
|
|
3688
|
+
return false;
|
|
3689
|
+
const { type: loadingIndicatorType } = loadingIndicator;
|
|
3690
|
+
let result;
|
|
3691
|
+
switch (loadingIndicatorType) {
|
|
3692
|
+
case "none":
|
|
3693
|
+
result = false;
|
|
3694
|
+
break;
|
|
3695
|
+
case "spinner":
|
|
3696
|
+
result = loaderIndex === 0;
|
|
3697
|
+
break;
|
|
3698
|
+
case "custom":
|
|
3699
|
+
case "skeleton": {
|
|
3700
|
+
const isInitialLoading = !pagination?.pageInfo;
|
|
3701
|
+
const initialCount = loadingIndicator.initialLoadingCount ?? 10;
|
|
3702
|
+
const scrollCount = loadingIndicator.scrollLoadingCount ?? 3;
|
|
3703
|
+
const maxCount = isInitialLoading ? initialCount : scrollCount;
|
|
3704
|
+
result = loaderIndex < maxCount;
|
|
3705
|
+
break;
|
|
3706
|
+
}
|
|
3707
|
+
default: {
|
|
3708
|
+
throw new Error(`${loadingIndicatorType} is not known`);
|
|
3709
|
+
}
|
|
3710
|
+
}
|
|
3711
|
+
return result;
|
|
3712
|
+
}, [loadingIndicator, pagination?.isLoading, pagination?.pageInfo]);
|
|
3713
|
+
const totalRowCount = react.useMemo(() => {
|
|
3714
|
+
// Only add the exact number of loading rows we want to show
|
|
3715
|
+
const loadingRows = pagination?.isLoading === true ? getLoadingRowsCount() : 0;
|
|
3716
|
+
const total = totalDataRows + loadingRows;
|
|
3717
|
+
return total;
|
|
3718
|
+
}, [totalDataRows, pagination?.isLoading, getLoadingRowsCount]);
|
|
3681
3719
|
// Estimate size for all rows (header, data, loading)
|
|
3682
3720
|
const estimateSize = react.useCallback((index) => {
|
|
3683
3721
|
// Loading rows
|
|
3684
3722
|
if (index >= totalDataRows) {
|
|
3685
3723
|
const loaderIndex = index - totalDataRows;
|
|
3686
|
-
const shouldShowLoader =
|
|
3724
|
+
const shouldShowLoader = shouldShowLoaderAtIndex(loaderIndex);
|
|
3725
|
+
const estimatedHeight = shouldShowLoader ? estimateItemSize(0) : 0;
|
|
3687
3726
|
// Empty loader rows should be estimated at 0 height to prevent blank space
|
|
3688
|
-
return
|
|
3727
|
+
return estimatedHeight;
|
|
3689
3728
|
}
|
|
3690
3729
|
// Header row (if exists, it's always at index 0)
|
|
3691
3730
|
if (hasHeader && index === 0) {
|
|
@@ -3695,15 +3734,7 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator, onRowCl
|
|
|
3695
3734
|
// Data rows - calculate the data index
|
|
3696
3735
|
const dataIndex = index - dataStartIndex;
|
|
3697
3736
|
return estimateItemSize(dataIndex);
|
|
3698
|
-
}, [
|
|
3699
|
-
estimateItemSize,
|
|
3700
|
-
estimateHeaderSize,
|
|
3701
|
-
totalDataRows,
|
|
3702
|
-
pagination?.isLoading,
|
|
3703
|
-
getLoadingRowsCount,
|
|
3704
|
-
hasHeader,
|
|
3705
|
-
dataStartIndex,
|
|
3706
|
-
]);
|
|
3737
|
+
}, [estimateItemSize, estimateHeaderSize, totalDataRows, shouldShowLoaderAtIndex, hasHeader, dataStartIndex]);
|
|
3707
3738
|
// Set up virtualization
|
|
3708
3739
|
const virtualizer = useInfiniteScroll({
|
|
3709
3740
|
pagination: pagination ?? noPagination,
|
|
@@ -3735,7 +3766,8 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator, onRowCl
|
|
|
3735
3766
|
}, []);
|
|
3736
3767
|
// Transform virtual items into typed rows
|
|
3737
3768
|
const rows = react.useMemo(() => {
|
|
3738
|
-
|
|
3769
|
+
const virtualItems = virtualizer.getVirtualItems();
|
|
3770
|
+
return virtualItems.map((virtualRow) => {
|
|
3739
3771
|
const { index } = virtualRow;
|
|
3740
3772
|
// Determine row type
|
|
3741
3773
|
const isLoaderRow = index >= totalDataRows;
|
|
@@ -3802,6 +3834,8 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator, onRowCl
|
|
|
3802
3834
|
getListItemProps,
|
|
3803
3835
|
header,
|
|
3804
3836
|
loadingIndicator,
|
|
3837
|
+
shouldShowLoaderAtIndex,
|
|
3838
|
+
count,
|
|
3805
3839
|
};
|
|
3806
3840
|
};
|
|
3807
3841
|
|
package/index.esm.js
CHANGED
|
@@ -3577,7 +3577,7 @@ const ListLoadingIndicator = ({ type, hasThumbnail, thumbnailShape, hasDescripti
|
|
|
3577
3577
|
*/
|
|
3578
3578
|
const List = ({ children, className, dataTestId, topSeparatorOnScroll = false, separator = "line",
|
|
3579
3579
|
// UseListResult properties
|
|
3580
|
-
containerRef, listRef, rows, getListItemProps, header, loadingIndicator, isScrolling, scrollOffset,
|
|
3580
|
+
containerRef, listRef, rows, getListItemProps, header, loadingIndicator, shouldShowLoaderAtIndex, count, isScrolling, scrollOffset,
|
|
3581
3581
|
// Unused but part of UseListResult interface
|
|
3582
3582
|
getTotalSize: _getTotalSize, getVirtualItems: _getVirtualItems, scrollToOffset: _scrollToOffset, scrollToIndex: _scrollToIndex, measure: _measure, }) => {
|
|
3583
3583
|
return (jsx("div", { className: cvaListContainer({
|
|
@@ -3595,10 +3595,12 @@ getTotalSize: _getTotalSize, getVirtualItems: _getVirtualItems, scrollToOffset:
|
|
|
3595
3595
|
type: "skeleton",
|
|
3596
3596
|
...DEFAULT_SKELETON_LIST_ITEM_PROPS,
|
|
3597
3597
|
};
|
|
3598
|
-
|
|
3599
|
-
const
|
|
3600
|
-
const
|
|
3601
|
-
const
|
|
3598
|
+
// Use the total data count from useList, not visible rows (which are virtualized)
|
|
3599
|
+
const hasHeaderRow = !!header;
|
|
3600
|
+
const dataStartIndex = hasHeaderRow ? 1 : 0;
|
|
3601
|
+
const totalDataRows = dataStartIndex + count;
|
|
3602
|
+
const loaderIndex = row.virtualRow.index - totalDataRows;
|
|
3603
|
+
const shouldShowLoader = shouldShowLoaderAtIndex(loaderIndex);
|
|
3602
3604
|
return (jsx("li", { ...listItemProps, children: shouldShowLoader ? jsx(ListLoadingIndicator, { ...loadingConfig }) : null }, key));
|
|
3603
3605
|
}
|
|
3604
3606
|
// Render header row
|
|
@@ -3610,6 +3612,11 @@ getTotalSize: _getTotalSize, getVirtualItems: _getVirtualItems, scrollToOffset:
|
|
|
3610
3612
|
}) }) }));
|
|
3611
3613
|
};
|
|
3612
3614
|
|
|
3615
|
+
const DEFAULT_LOADING_INDICATOR_CONFIG = {
|
|
3616
|
+
type: "skeleton",
|
|
3617
|
+
initialLoadingCount: 10,
|
|
3618
|
+
scrollLoadingCount: 3,
|
|
3619
|
+
};
|
|
3613
3620
|
/**
|
|
3614
3621
|
* A hook for managing virtualized list state and behavior.
|
|
3615
3622
|
*
|
|
@@ -3642,7 +3649,7 @@ getTotalSize: _getTotalSize, getVirtualItems: _getVirtualItems, scrollToOffset:
|
|
|
3642
3649
|
* );
|
|
3643
3650
|
* ```
|
|
3644
3651
|
*/
|
|
3645
|
-
const useList = ({ count, pagination, header, getItem, loadingIndicator, onRowClick, onChange, estimateItemSize, estimateHeaderSize, overscan, }) => {
|
|
3652
|
+
const useList = ({ count, pagination, header, getItem, loadingIndicator = DEFAULT_LOADING_INDICATOR_CONFIG, onRowClick, onChange, estimateItemSize, estimateHeaderSize, overscan, }) => {
|
|
3646
3653
|
const containerRef = useRef(null);
|
|
3647
3654
|
const listRef = useRef(null);
|
|
3648
3655
|
const rowRefsMap = useRef(new Map());
|
|
@@ -3653,8 +3660,6 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator, onRowCl
|
|
|
3653
3660
|
const totalDataRows = dataStartIndex + dataCount;
|
|
3654
3661
|
// Calculate how many loading rows we need
|
|
3655
3662
|
const getLoadingRowsCount = useCallback(() => {
|
|
3656
|
-
if (!loadingIndicator)
|
|
3657
|
-
return 0;
|
|
3658
3663
|
if (pagination?.isLoading === false)
|
|
3659
3664
|
return 0;
|
|
3660
3665
|
const { type: loadingIndicatorType } = loadingIndicator;
|
|
@@ -3675,15 +3680,49 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator, onRowCl
|
|
|
3675
3680
|
}
|
|
3676
3681
|
}
|
|
3677
3682
|
}, [loadingIndicator, pagination?.isLoading, pagination?.pageInfo]);
|
|
3678
|
-
|
|
3683
|
+
// Helper to determine if a specific loader index should be shown
|
|
3684
|
+
const shouldShowLoaderAtIndex = useCallback((loaderIndex) => {
|
|
3685
|
+
if (pagination?.isLoading === false)
|
|
3686
|
+
return false;
|
|
3687
|
+
const { type: loadingIndicatorType } = loadingIndicator;
|
|
3688
|
+
let result;
|
|
3689
|
+
switch (loadingIndicatorType) {
|
|
3690
|
+
case "none":
|
|
3691
|
+
result = false;
|
|
3692
|
+
break;
|
|
3693
|
+
case "spinner":
|
|
3694
|
+
result = loaderIndex === 0;
|
|
3695
|
+
break;
|
|
3696
|
+
case "custom":
|
|
3697
|
+
case "skeleton": {
|
|
3698
|
+
const isInitialLoading = !pagination?.pageInfo;
|
|
3699
|
+
const initialCount = loadingIndicator.initialLoadingCount ?? 10;
|
|
3700
|
+
const scrollCount = loadingIndicator.scrollLoadingCount ?? 3;
|
|
3701
|
+
const maxCount = isInitialLoading ? initialCount : scrollCount;
|
|
3702
|
+
result = loaderIndex < maxCount;
|
|
3703
|
+
break;
|
|
3704
|
+
}
|
|
3705
|
+
default: {
|
|
3706
|
+
throw new Error(`${loadingIndicatorType} is not known`);
|
|
3707
|
+
}
|
|
3708
|
+
}
|
|
3709
|
+
return result;
|
|
3710
|
+
}, [loadingIndicator, pagination?.isLoading, pagination?.pageInfo]);
|
|
3711
|
+
const totalRowCount = useMemo(() => {
|
|
3712
|
+
// Only add the exact number of loading rows we want to show
|
|
3713
|
+
const loadingRows = pagination?.isLoading === true ? getLoadingRowsCount() : 0;
|
|
3714
|
+
const total = totalDataRows + loadingRows;
|
|
3715
|
+
return total;
|
|
3716
|
+
}, [totalDataRows, pagination?.isLoading, getLoadingRowsCount]);
|
|
3679
3717
|
// Estimate size for all rows (header, data, loading)
|
|
3680
3718
|
const estimateSize = useCallback((index) => {
|
|
3681
3719
|
// Loading rows
|
|
3682
3720
|
if (index >= totalDataRows) {
|
|
3683
3721
|
const loaderIndex = index - totalDataRows;
|
|
3684
|
-
const shouldShowLoader =
|
|
3722
|
+
const shouldShowLoader = shouldShowLoaderAtIndex(loaderIndex);
|
|
3723
|
+
const estimatedHeight = shouldShowLoader ? estimateItemSize(0) : 0;
|
|
3685
3724
|
// Empty loader rows should be estimated at 0 height to prevent blank space
|
|
3686
|
-
return
|
|
3725
|
+
return estimatedHeight;
|
|
3687
3726
|
}
|
|
3688
3727
|
// Header row (if exists, it's always at index 0)
|
|
3689
3728
|
if (hasHeader && index === 0) {
|
|
@@ -3693,15 +3732,7 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator, onRowCl
|
|
|
3693
3732
|
// Data rows - calculate the data index
|
|
3694
3733
|
const dataIndex = index - dataStartIndex;
|
|
3695
3734
|
return estimateItemSize(dataIndex);
|
|
3696
|
-
}, [
|
|
3697
|
-
estimateItemSize,
|
|
3698
|
-
estimateHeaderSize,
|
|
3699
|
-
totalDataRows,
|
|
3700
|
-
pagination?.isLoading,
|
|
3701
|
-
getLoadingRowsCount,
|
|
3702
|
-
hasHeader,
|
|
3703
|
-
dataStartIndex,
|
|
3704
|
-
]);
|
|
3735
|
+
}, [estimateItemSize, estimateHeaderSize, totalDataRows, shouldShowLoaderAtIndex, hasHeader, dataStartIndex]);
|
|
3705
3736
|
// Set up virtualization
|
|
3706
3737
|
const virtualizer = useInfiniteScroll({
|
|
3707
3738
|
pagination: pagination ?? noPagination,
|
|
@@ -3733,7 +3764,8 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator, onRowCl
|
|
|
3733
3764
|
}, []);
|
|
3734
3765
|
// Transform virtual items into typed rows
|
|
3735
3766
|
const rows = useMemo(() => {
|
|
3736
|
-
|
|
3767
|
+
const virtualItems = virtualizer.getVirtualItems();
|
|
3768
|
+
return virtualItems.map((virtualRow) => {
|
|
3737
3769
|
const { index } = virtualRow;
|
|
3738
3770
|
// Determine row type
|
|
3739
3771
|
const isLoaderRow = index >= totalDataRows;
|
|
@@ -3800,6 +3832,8 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator, onRowCl
|
|
|
3800
3832
|
getListItemProps,
|
|
3801
3833
|
header,
|
|
3802
3834
|
loadingIndicator,
|
|
3835
|
+
shouldShowLoaderAtIndex,
|
|
3836
|
+
count,
|
|
3803
3837
|
};
|
|
3804
3838
|
};
|
|
3805
3839
|
|
package/package.json
CHANGED
|
@@ -100,4 +100,4 @@ export interface ListProps<TItem = unknown> extends CommonProps, UseListResult<T
|
|
|
100
100
|
* );
|
|
101
101
|
* ```
|
|
102
102
|
*/
|
|
103
|
-
export declare const List: <TItem = unknown>({ children, className, dataTestId, topSeparatorOnScroll, separator, containerRef, listRef, rows, getListItemProps, header, loadingIndicator, isScrolling, scrollOffset, getTotalSize: _getTotalSize, getVirtualItems: _getVirtualItems, scrollToOffset: _scrollToOffset, scrollToIndex: _scrollToIndex, measure: _measure, }: ListProps<TItem>) => ReactElement;
|
|
103
|
+
export declare const List: <TItem = unknown>({ children, className, dataTestId, topSeparatorOnScroll, separator, containerRef, listRef, rows, getListItemProps, header, loadingIndicator, shouldShowLoaderAtIndex, count, isScrolling, scrollOffset, getTotalSize: _getTotalSize, getVirtualItems: _getVirtualItems, scrollToOffset: _scrollToOffset, scrollToIndex: _scrollToIndex, measure: _measure, }: ListProps<TItem>) => ReactElement;
|
|
@@ -121,16 +121,20 @@ export interface UseListResult<TItem> extends Pick<Virtualizer<HTMLDivElement, H
|
|
|
121
121
|
/** Reference to attach to the list */
|
|
122
122
|
listRef: RefObject<HTMLUListElement | null>;
|
|
123
123
|
/** Array of row data to render */
|
|
124
|
-
rows:
|
|
124
|
+
readonly rows: ReadonlyArray<ListRow<TItem>>;
|
|
125
125
|
/** Helper to create list item props for a given row */
|
|
126
|
-
getListItemProps: (row: ListRow<TItem>, options: {
|
|
126
|
+
readonly getListItemProps: (row: ListRow<TItem>, options: {
|
|
127
127
|
className: string;
|
|
128
128
|
onClick?: () => void;
|
|
129
129
|
}) => VirtualizationListItemProps;
|
|
130
130
|
/** Header element (if provided) */
|
|
131
|
-
header?: ReactElement;
|
|
131
|
+
readonly header?: ReactElement;
|
|
132
132
|
/** Loading indicator configuration */
|
|
133
|
-
loadingIndicator?: ListLoadingIndicatorProps;
|
|
133
|
+
readonly loadingIndicator?: ListLoadingIndicatorProps;
|
|
134
|
+
/** Helper to determine if a specific loader index should be shown */
|
|
135
|
+
readonly shouldShowLoaderAtIndex: (loaderIndex: number) => boolean;
|
|
136
|
+
/** Total number of data items (for consistent calculations) */
|
|
137
|
+
readonly count: number;
|
|
134
138
|
}
|
|
135
139
|
/**
|
|
136
140
|
* A hook for managing virtualized list state and behavior.
|