@trackunit/react-components 1.9.20 → 1.9.23
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 +57 -25
- package/index.esm.js +57 -25
- package/package.json +6 -6
- package/src/components/Icon/Icon.d.ts +1 -13
- package/src/components/Icon/Icon.variants.d.ts +1 -1
- package/src/components/List/List.d.ts +1 -1
- package/src/components/List/useList.d.ts +8 -4
- package/src/components/Tag/Tag.variants.d.ts +1 -1
package/index.cjs.js
CHANGED
|
@@ -32,7 +32,6 @@ const cvaIcon = cssClassVarianceUtilities.cvaMerge(["aspect-square", "inline-gri
|
|
|
32
32
|
variants: {
|
|
33
33
|
color: {
|
|
34
34
|
primary: "text-primary-600",
|
|
35
|
-
secondary: "text-neutral-400",
|
|
36
35
|
neutral: "text-neutral-400",
|
|
37
36
|
info: "text-info-600",
|
|
38
37
|
success: "text-success-600",
|
|
@@ -201,7 +200,6 @@ const cvaTag = cssClassVarianceUtilities.cvaMerge([
|
|
|
201
200
|
},
|
|
202
201
|
color: {
|
|
203
202
|
primary: ["bg-primary-100", "text-primary-700"],
|
|
204
|
-
secondary: ["bg-neutral-100", "text-neutral-700"],
|
|
205
203
|
neutral: ["bg-neutral-200", "text-neutral-700"],
|
|
206
204
|
black: ["bg-neutral-100", "text-neutral-700"],
|
|
207
205
|
white: ["bg-white", "text-neutral-600"],
|
|
@@ -274,7 +272,7 @@ Tag.displayName = "Tag";
|
|
|
274
272
|
* A component used to display the package name and version in the Storybook docs.
|
|
275
273
|
*/
|
|
276
274
|
const PackageNameStoryComponent = ({ packageJSON }) => {
|
|
277
|
-
return (jsxRuntime.jsxs("div", { className: "flex gap-2", children: [jsxRuntime.jsx(Tag, { color: "
|
|
275
|
+
return (jsxRuntime.jsxs("div", { className: "flex gap-2", children: [jsxRuntime.jsx(Tag, { color: "neutral", children: packageJSON?.name }), jsxRuntime.jsxs(Tag, { color: "neutral", children: ["v", packageJSON?.version] })] }));
|
|
278
276
|
};
|
|
279
277
|
|
|
280
278
|
/**
|
|
@@ -1937,7 +1935,7 @@ const BreadcrumbForMediumScreen = ({ dataTestId, breadcrumbItems }) => {
|
|
|
1937
1935
|
const [expanded, setExpanded] = react.useState(false);
|
|
1938
1936
|
const getReducedArray = react.useCallback(() => {
|
|
1939
1937
|
let reducedArrayElements = [];
|
|
1940
|
-
const collapsibleButton = (jsxRuntime.jsxs("div", { className: cvaBreadcrumbItem(), children: [jsxRuntime.jsx(IconButton, { dataTestId: `collapsibleButton-${dataTestId}`, icon: jsxRuntime.jsx(Icon, { name: "EllipsisHorizontal", size: "small" }), onClick: () => setExpanded(true), size: "small", variant: "ghost-neutral" }), jsxRuntime.jsx(Icon, { color: "
|
|
1938
|
+
const collapsibleButton = (jsxRuntime.jsxs("div", { className: cvaBreadcrumbItem(), children: [jsxRuntime.jsx(IconButton, { dataTestId: `collapsibleButton-${dataTestId}`, icon: jsxRuntime.jsx(Icon, { name: "EllipsisHorizontal", size: "small" }), onClick: () => setExpanded(true), size: "small", variant: "ghost-neutral" }), jsxRuntime.jsx(Icon, { color: "neutral", name: "Slash", size: "small" })] }));
|
|
1941
1939
|
const firstBreadcrumbItem = breadcrumbItems[0];
|
|
1942
1940
|
if (firstBreadcrumbItem && breadcrumbItems.length > 3) {
|
|
1943
1941
|
const lastTwoBreadcrumbItem = breadcrumbItems.slice(-2);
|
|
@@ -3579,7 +3577,7 @@ const ListLoadingIndicator = ({ type, hasThumbnail, thumbnailShape, hasDescripti
|
|
|
3579
3577
|
*/
|
|
3580
3578
|
const List = ({ children, className, dataTestId, topSeparatorOnScroll = false, separator = "line",
|
|
3581
3579
|
// UseListResult properties
|
|
3582
|
-
containerRef, listRef, rows, getListItemProps, header, loadingIndicator, isScrolling, scrollOffset,
|
|
3580
|
+
containerRef, listRef, rows, getListItemProps, header, loadingIndicator, shouldShowLoaderAtIndex, count, isScrolling, scrollOffset,
|
|
3583
3581
|
// Unused but part of UseListResult interface
|
|
3584
3582
|
getTotalSize: _getTotalSize, getVirtualItems: _getVirtualItems, scrollToOffset: _scrollToOffset, scrollToIndex: _scrollToIndex, measure: _measure, }) => {
|
|
3585
3583
|
return (jsxRuntime.jsx("div", { className: cvaListContainer({
|
|
@@ -3597,10 +3595,12 @@ getTotalSize: _getTotalSize, getVirtualItems: _getVirtualItems, scrollToOffset:
|
|
|
3597
3595
|
type: "skeleton",
|
|
3598
3596
|
...DEFAULT_SKELETON_LIST_ITEM_PROPS,
|
|
3599
3597
|
};
|
|
3600
|
-
|
|
3601
|
-
const
|
|
3602
|
-
const
|
|
3603
|
-
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);
|
|
3604
3604
|
return (jsxRuntime.jsx("li", { ...listItemProps, children: shouldShowLoader ? jsxRuntime.jsx(ListLoadingIndicator, { ...loadingConfig }) : null }, key));
|
|
3605
3605
|
}
|
|
3606
3606
|
// Render header row
|
|
@@ -3612,6 +3612,11 @@ getTotalSize: _getTotalSize, getVirtualItems: _getVirtualItems, scrollToOffset:
|
|
|
3612
3612
|
}) }) }));
|
|
3613
3613
|
};
|
|
3614
3614
|
|
|
3615
|
+
const DEFAULT_LOADING_INDICATOR_CONFIG = {
|
|
3616
|
+
type: "skeleton",
|
|
3617
|
+
initialLoadingCount: 10,
|
|
3618
|
+
scrollLoadingCount: 3,
|
|
3619
|
+
};
|
|
3615
3620
|
/**
|
|
3616
3621
|
* A hook for managing virtualized list state and behavior.
|
|
3617
3622
|
*
|
|
@@ -3644,7 +3649,7 @@ getTotalSize: _getTotalSize, getVirtualItems: _getVirtualItems, scrollToOffset:
|
|
|
3644
3649
|
* );
|
|
3645
3650
|
* ```
|
|
3646
3651
|
*/
|
|
3647
|
-
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, }) => {
|
|
3648
3653
|
const containerRef = react.useRef(null);
|
|
3649
3654
|
const listRef = react.useRef(null);
|
|
3650
3655
|
const rowRefsMap = react.useRef(new Map());
|
|
@@ -3655,8 +3660,6 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator, onRowCl
|
|
|
3655
3660
|
const totalDataRows = dataStartIndex + dataCount;
|
|
3656
3661
|
// Calculate how many loading rows we need
|
|
3657
3662
|
const getLoadingRowsCount = react.useCallback(() => {
|
|
3658
|
-
if (!loadingIndicator)
|
|
3659
|
-
return 0;
|
|
3660
3663
|
if (pagination?.isLoading === false)
|
|
3661
3664
|
return 0;
|
|
3662
3665
|
const { type: loadingIndicatorType } = loadingIndicator;
|
|
@@ -3677,15 +3680,49 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator, onRowCl
|
|
|
3677
3680
|
}
|
|
3678
3681
|
}
|
|
3679
3682
|
}, [loadingIndicator, pagination?.isLoading, pagination?.pageInfo]);
|
|
3680
|
-
|
|
3683
|
+
// Helper to determine if a specific loader index should be shown
|
|
3684
|
+
const shouldShowLoaderAtIndex = react.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 = react.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]);
|
|
3681
3717
|
// Estimate size for all rows (header, data, loading)
|
|
3682
3718
|
const estimateSize = react.useCallback((index) => {
|
|
3683
3719
|
// Loading rows
|
|
3684
3720
|
if (index >= totalDataRows) {
|
|
3685
3721
|
const loaderIndex = index - totalDataRows;
|
|
3686
|
-
const shouldShowLoader =
|
|
3722
|
+
const shouldShowLoader = shouldShowLoaderAtIndex(loaderIndex);
|
|
3723
|
+
const estimatedHeight = shouldShowLoader ? estimateItemSize(0) : 0;
|
|
3687
3724
|
// Empty loader rows should be estimated at 0 height to prevent blank space
|
|
3688
|
-
return
|
|
3725
|
+
return estimatedHeight;
|
|
3689
3726
|
}
|
|
3690
3727
|
// Header row (if exists, it's always at index 0)
|
|
3691
3728
|
if (hasHeader && index === 0) {
|
|
@@ -3695,15 +3732,7 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator, onRowCl
|
|
|
3695
3732
|
// Data rows - calculate the data index
|
|
3696
3733
|
const dataIndex = index - dataStartIndex;
|
|
3697
3734
|
return estimateItemSize(dataIndex);
|
|
3698
|
-
}, [
|
|
3699
|
-
estimateItemSize,
|
|
3700
|
-
estimateHeaderSize,
|
|
3701
|
-
totalDataRows,
|
|
3702
|
-
pagination?.isLoading,
|
|
3703
|
-
getLoadingRowsCount,
|
|
3704
|
-
hasHeader,
|
|
3705
|
-
dataStartIndex,
|
|
3706
|
-
]);
|
|
3735
|
+
}, [estimateItemSize, estimateHeaderSize, totalDataRows, shouldShowLoaderAtIndex, hasHeader, dataStartIndex]);
|
|
3707
3736
|
// Set up virtualization
|
|
3708
3737
|
const virtualizer = useInfiniteScroll({
|
|
3709
3738
|
pagination: pagination ?? noPagination,
|
|
@@ -3735,7 +3764,8 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator, onRowCl
|
|
|
3735
3764
|
}, []);
|
|
3736
3765
|
// Transform virtual items into typed rows
|
|
3737
3766
|
const rows = react.useMemo(() => {
|
|
3738
|
-
|
|
3767
|
+
const virtualItems = virtualizer.getVirtualItems();
|
|
3768
|
+
return virtualItems.map((virtualRow) => {
|
|
3739
3769
|
const { index } = virtualRow;
|
|
3740
3770
|
// Determine row type
|
|
3741
3771
|
const isLoaderRow = index >= totalDataRows;
|
|
@@ -3802,6 +3832,8 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator, onRowCl
|
|
|
3802
3832
|
getListItemProps,
|
|
3803
3833
|
header,
|
|
3804
3834
|
loadingIndicator,
|
|
3835
|
+
shouldShowLoaderAtIndex,
|
|
3836
|
+
count,
|
|
3805
3837
|
};
|
|
3806
3838
|
};
|
|
3807
3839
|
|
package/index.esm.js
CHANGED
|
@@ -30,7 +30,6 @@ const cvaIcon = cvaMerge(["aspect-square", "inline-grid", "relative", "shrink-0"
|
|
|
30
30
|
variants: {
|
|
31
31
|
color: {
|
|
32
32
|
primary: "text-primary-600",
|
|
33
|
-
secondary: "text-neutral-400",
|
|
34
33
|
neutral: "text-neutral-400",
|
|
35
34
|
info: "text-info-600",
|
|
36
35
|
success: "text-success-600",
|
|
@@ -199,7 +198,6 @@ const cvaTag = cvaMerge([
|
|
|
199
198
|
},
|
|
200
199
|
color: {
|
|
201
200
|
primary: ["bg-primary-100", "text-primary-700"],
|
|
202
|
-
secondary: ["bg-neutral-100", "text-neutral-700"],
|
|
203
201
|
neutral: ["bg-neutral-200", "text-neutral-700"],
|
|
204
202
|
black: ["bg-neutral-100", "text-neutral-700"],
|
|
205
203
|
white: ["bg-white", "text-neutral-600"],
|
|
@@ -272,7 +270,7 @@ Tag.displayName = "Tag";
|
|
|
272
270
|
* A component used to display the package name and version in the Storybook docs.
|
|
273
271
|
*/
|
|
274
272
|
const PackageNameStoryComponent = ({ packageJSON }) => {
|
|
275
|
-
return (jsxs("div", { className: "flex gap-2", children: [jsx(Tag, { color: "
|
|
273
|
+
return (jsxs("div", { className: "flex gap-2", children: [jsx(Tag, { color: "neutral", children: packageJSON?.name }), jsxs(Tag, { color: "neutral", children: ["v", packageJSON?.version] })] }));
|
|
276
274
|
};
|
|
277
275
|
|
|
278
276
|
/**
|
|
@@ -1935,7 +1933,7 @@ const BreadcrumbForMediumScreen = ({ dataTestId, breadcrumbItems }) => {
|
|
|
1935
1933
|
const [expanded, setExpanded] = useState(false);
|
|
1936
1934
|
const getReducedArray = useCallback(() => {
|
|
1937
1935
|
let reducedArrayElements = [];
|
|
1938
|
-
const collapsibleButton = (jsxs("div", { className: cvaBreadcrumbItem(), children: [jsx(IconButton, { dataTestId: `collapsibleButton-${dataTestId}`, icon: jsx(Icon, { name: "EllipsisHorizontal", size: "small" }), onClick: () => setExpanded(true), size: "small", variant: "ghost-neutral" }), jsx(Icon, { color: "
|
|
1936
|
+
const collapsibleButton = (jsxs("div", { className: cvaBreadcrumbItem(), children: [jsx(IconButton, { dataTestId: `collapsibleButton-${dataTestId}`, icon: jsx(Icon, { name: "EllipsisHorizontal", size: "small" }), onClick: () => setExpanded(true), size: "small", variant: "ghost-neutral" }), jsx(Icon, { color: "neutral", name: "Slash", size: "small" })] }));
|
|
1939
1937
|
const firstBreadcrumbItem = breadcrumbItems[0];
|
|
1940
1938
|
if (firstBreadcrumbItem && breadcrumbItems.length > 3) {
|
|
1941
1939
|
const lastTwoBreadcrumbItem = breadcrumbItems.slice(-2);
|
|
@@ -3577,7 +3575,7 @@ const ListLoadingIndicator = ({ type, hasThumbnail, thumbnailShape, hasDescripti
|
|
|
3577
3575
|
*/
|
|
3578
3576
|
const List = ({ children, className, dataTestId, topSeparatorOnScroll = false, separator = "line",
|
|
3579
3577
|
// UseListResult properties
|
|
3580
|
-
containerRef, listRef, rows, getListItemProps, header, loadingIndicator, isScrolling, scrollOffset,
|
|
3578
|
+
containerRef, listRef, rows, getListItemProps, header, loadingIndicator, shouldShowLoaderAtIndex, count, isScrolling, scrollOffset,
|
|
3581
3579
|
// Unused but part of UseListResult interface
|
|
3582
3580
|
getTotalSize: _getTotalSize, getVirtualItems: _getVirtualItems, scrollToOffset: _scrollToOffset, scrollToIndex: _scrollToIndex, measure: _measure, }) => {
|
|
3583
3581
|
return (jsx("div", { className: cvaListContainer({
|
|
@@ -3595,10 +3593,12 @@ getTotalSize: _getTotalSize, getVirtualItems: _getVirtualItems, scrollToOffset:
|
|
|
3595
3593
|
type: "skeleton",
|
|
3596
3594
|
...DEFAULT_SKELETON_LIST_ITEM_PROPS,
|
|
3597
3595
|
};
|
|
3598
|
-
|
|
3599
|
-
const
|
|
3600
|
-
const
|
|
3601
|
-
const
|
|
3596
|
+
// Use the total data count from useList, not visible rows (which are virtualized)
|
|
3597
|
+
const hasHeaderRow = !!header;
|
|
3598
|
+
const dataStartIndex = hasHeaderRow ? 1 : 0;
|
|
3599
|
+
const totalDataRows = dataStartIndex + count;
|
|
3600
|
+
const loaderIndex = row.virtualRow.index - totalDataRows;
|
|
3601
|
+
const shouldShowLoader = shouldShowLoaderAtIndex(loaderIndex);
|
|
3602
3602
|
return (jsx("li", { ...listItemProps, children: shouldShowLoader ? jsx(ListLoadingIndicator, { ...loadingConfig }) : null }, key));
|
|
3603
3603
|
}
|
|
3604
3604
|
// Render header row
|
|
@@ -3610,6 +3610,11 @@ getTotalSize: _getTotalSize, getVirtualItems: _getVirtualItems, scrollToOffset:
|
|
|
3610
3610
|
}) }) }));
|
|
3611
3611
|
};
|
|
3612
3612
|
|
|
3613
|
+
const DEFAULT_LOADING_INDICATOR_CONFIG = {
|
|
3614
|
+
type: "skeleton",
|
|
3615
|
+
initialLoadingCount: 10,
|
|
3616
|
+
scrollLoadingCount: 3,
|
|
3617
|
+
};
|
|
3613
3618
|
/**
|
|
3614
3619
|
* A hook for managing virtualized list state and behavior.
|
|
3615
3620
|
*
|
|
@@ -3642,7 +3647,7 @@ getTotalSize: _getTotalSize, getVirtualItems: _getVirtualItems, scrollToOffset:
|
|
|
3642
3647
|
* );
|
|
3643
3648
|
* ```
|
|
3644
3649
|
*/
|
|
3645
|
-
const useList = ({ count, pagination, header, getItem, loadingIndicator, onRowClick, onChange, estimateItemSize, estimateHeaderSize, overscan, }) => {
|
|
3650
|
+
const useList = ({ count, pagination, header, getItem, loadingIndicator = DEFAULT_LOADING_INDICATOR_CONFIG, onRowClick, onChange, estimateItemSize, estimateHeaderSize, overscan, }) => {
|
|
3646
3651
|
const containerRef = useRef(null);
|
|
3647
3652
|
const listRef = useRef(null);
|
|
3648
3653
|
const rowRefsMap = useRef(new Map());
|
|
@@ -3653,8 +3658,6 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator, onRowCl
|
|
|
3653
3658
|
const totalDataRows = dataStartIndex + dataCount;
|
|
3654
3659
|
// Calculate how many loading rows we need
|
|
3655
3660
|
const getLoadingRowsCount = useCallback(() => {
|
|
3656
|
-
if (!loadingIndicator)
|
|
3657
|
-
return 0;
|
|
3658
3661
|
if (pagination?.isLoading === false)
|
|
3659
3662
|
return 0;
|
|
3660
3663
|
const { type: loadingIndicatorType } = loadingIndicator;
|
|
@@ -3675,15 +3678,49 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator, onRowCl
|
|
|
3675
3678
|
}
|
|
3676
3679
|
}
|
|
3677
3680
|
}, [loadingIndicator, pagination?.isLoading, pagination?.pageInfo]);
|
|
3678
|
-
|
|
3681
|
+
// Helper to determine if a specific loader index should be shown
|
|
3682
|
+
const shouldShowLoaderAtIndex = useCallback((loaderIndex) => {
|
|
3683
|
+
if (pagination?.isLoading === false)
|
|
3684
|
+
return false;
|
|
3685
|
+
const { type: loadingIndicatorType } = loadingIndicator;
|
|
3686
|
+
let result;
|
|
3687
|
+
switch (loadingIndicatorType) {
|
|
3688
|
+
case "none":
|
|
3689
|
+
result = false;
|
|
3690
|
+
break;
|
|
3691
|
+
case "spinner":
|
|
3692
|
+
result = loaderIndex === 0;
|
|
3693
|
+
break;
|
|
3694
|
+
case "custom":
|
|
3695
|
+
case "skeleton": {
|
|
3696
|
+
const isInitialLoading = !pagination?.pageInfo;
|
|
3697
|
+
const initialCount = loadingIndicator.initialLoadingCount ?? 10;
|
|
3698
|
+
const scrollCount = loadingIndicator.scrollLoadingCount ?? 3;
|
|
3699
|
+
const maxCount = isInitialLoading ? initialCount : scrollCount;
|
|
3700
|
+
result = loaderIndex < maxCount;
|
|
3701
|
+
break;
|
|
3702
|
+
}
|
|
3703
|
+
default: {
|
|
3704
|
+
throw new Error(`${loadingIndicatorType} is not known`);
|
|
3705
|
+
}
|
|
3706
|
+
}
|
|
3707
|
+
return result;
|
|
3708
|
+
}, [loadingIndicator, pagination?.isLoading, pagination?.pageInfo]);
|
|
3709
|
+
const totalRowCount = useMemo(() => {
|
|
3710
|
+
// Only add the exact number of loading rows we want to show
|
|
3711
|
+
const loadingRows = pagination?.isLoading === true ? getLoadingRowsCount() : 0;
|
|
3712
|
+
const total = totalDataRows + loadingRows;
|
|
3713
|
+
return total;
|
|
3714
|
+
}, [totalDataRows, pagination?.isLoading, getLoadingRowsCount]);
|
|
3679
3715
|
// Estimate size for all rows (header, data, loading)
|
|
3680
3716
|
const estimateSize = useCallback((index) => {
|
|
3681
3717
|
// Loading rows
|
|
3682
3718
|
if (index >= totalDataRows) {
|
|
3683
3719
|
const loaderIndex = index - totalDataRows;
|
|
3684
|
-
const shouldShowLoader =
|
|
3720
|
+
const shouldShowLoader = shouldShowLoaderAtIndex(loaderIndex);
|
|
3721
|
+
const estimatedHeight = shouldShowLoader ? estimateItemSize(0) : 0;
|
|
3685
3722
|
// Empty loader rows should be estimated at 0 height to prevent blank space
|
|
3686
|
-
return
|
|
3723
|
+
return estimatedHeight;
|
|
3687
3724
|
}
|
|
3688
3725
|
// Header row (if exists, it's always at index 0)
|
|
3689
3726
|
if (hasHeader && index === 0) {
|
|
@@ -3693,15 +3730,7 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator, onRowCl
|
|
|
3693
3730
|
// Data rows - calculate the data index
|
|
3694
3731
|
const dataIndex = index - dataStartIndex;
|
|
3695
3732
|
return estimateItemSize(dataIndex);
|
|
3696
|
-
}, [
|
|
3697
|
-
estimateItemSize,
|
|
3698
|
-
estimateHeaderSize,
|
|
3699
|
-
totalDataRows,
|
|
3700
|
-
pagination?.isLoading,
|
|
3701
|
-
getLoadingRowsCount,
|
|
3702
|
-
hasHeader,
|
|
3703
|
-
dataStartIndex,
|
|
3704
|
-
]);
|
|
3733
|
+
}, [estimateItemSize, estimateHeaderSize, totalDataRows, shouldShowLoaderAtIndex, hasHeader, dataStartIndex]);
|
|
3705
3734
|
// Set up virtualization
|
|
3706
3735
|
const virtualizer = useInfiniteScroll({
|
|
3707
3736
|
pagination: pagination ?? noPagination,
|
|
@@ -3733,7 +3762,8 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator, onRowCl
|
|
|
3733
3762
|
}, []);
|
|
3734
3763
|
// Transform virtual items into typed rows
|
|
3735
3764
|
const rows = useMemo(() => {
|
|
3736
|
-
|
|
3765
|
+
const virtualItems = virtualizer.getVirtualItems();
|
|
3766
|
+
return virtualItems.map((virtualRow) => {
|
|
3737
3767
|
const { index } = virtualRow;
|
|
3738
3768
|
// Determine row type
|
|
3739
3769
|
const isLoaderRow = index >= totalDataRows;
|
|
@@ -3800,6 +3830,8 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator, onRowCl
|
|
|
3800
3830
|
getListItemProps,
|
|
3801
3831
|
header,
|
|
3802
3832
|
loadingIndicator,
|
|
3833
|
+
shouldShowLoaderAtIndex,
|
|
3834
|
+
count,
|
|
3803
3835
|
};
|
|
3804
3836
|
};
|
|
3805
3837
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/react-components",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.23",
|
|
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.14",
|
|
20
|
+
"@trackunit/css-class-variance-utilities": "1.7.13",
|
|
21
|
+
"@trackunit/shared-utils": "1.9.13",
|
|
22
|
+
"@trackunit/ui-icons": "1.7.15",
|
|
23
|
+
"@trackunit/react-test-setup": "1.4.13",
|
|
24
24
|
"@tanstack/react-router": "1.114.29",
|
|
25
25
|
"es-toolkit": "^1.39.10",
|
|
26
26
|
"@tanstack/react-virtual": "3.13.12"
|
|
@@ -172,18 +172,6 @@ export declare const iconPalette: {
|
|
|
172
172
|
readonly 800: "30 64 175";
|
|
173
173
|
readonly 900: "30 58 138";
|
|
174
174
|
};
|
|
175
|
-
SECONDARY: {
|
|
176
|
-
readonly 50: "248 250 252";
|
|
177
|
-
readonly 100: "241 245 249";
|
|
178
|
-
readonly 200: "226 232 240";
|
|
179
|
-
readonly 300: "203 213 225";
|
|
180
|
-
readonly 400: "148 163 184";
|
|
181
|
-
readonly 500: "100 116 139";
|
|
182
|
-
readonly 600: "71 85 105";
|
|
183
|
-
readonly 700: "51 65 85";
|
|
184
|
-
readonly 800: "30 41 59";
|
|
185
|
-
readonly 900: "15 23 42";
|
|
186
|
-
};
|
|
187
175
|
NEUTRAL: {
|
|
188
176
|
readonly 50: "249 250 251";
|
|
189
177
|
readonly 100: "243 244 246";
|
|
@@ -251,7 +239,7 @@ export declare const iconPalette: {
|
|
|
251
239
|
readonly 900: "127 29 29";
|
|
252
240
|
};
|
|
253
241
|
};
|
|
254
|
-
export declare const iconColorNames: ("info" | "success" | "warning" | "danger" | "primary" | "
|
|
242
|
+
export declare const iconColorNames: ("info" | "success" | "warning" | "danger" | "primary" | "neutral" | "black" | "white" | "good" | "low" | "critical" | "working" | "idle" | "stopped" | "unknown" | "moving" | "active" | "excessive_usage" | "unused" | "utilized" | "heavily_utilized" | "unknown_utilization" | "site_area" | "site_classic_poi" | "site_classic_zone" | "site_depot" | "site_work_place" | "site_construction_site" | "site_unknown" | "on_rent" | "returned" | "available" | "pickup_ready" | "transfer" | "in_repair" | "other_rental_status")[];
|
|
255
243
|
type IconPropsSmall = {
|
|
256
244
|
size?: "small";
|
|
257
245
|
type?: "solid";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const cvaIcon: (props?: ({
|
|
2
|
-
color?: "default" | "primary" | "
|
|
2
|
+
color?: "default" | "primary" | "neutral" | "info" | "success" | "warning" | "danger" | "good" | "low" | "critical" | "working" | "idle" | "moving" | "active" | "excessive_usage" | "stopped" | "unknown" | "black" | "white" | "unused" | "utilized" | "heavily_utilized" | "unknown_utilization" | "site_area" | "site_classic_poi" | "site_classic_zone" | "site_depot" | "site_work_place" | "site_construction_site" | "site_unknown" | "on_rent" | "returned" | "available" | "pickup_ready" | "transfer" | "in_repair" | "other_rental_status" | null | undefined;
|
|
3
3
|
size?: "small" | "medium" | "large" | null | undefined;
|
|
4
4
|
fontSize?: boolean | null | undefined;
|
|
5
5
|
} & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
|
|
@@ -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.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export declare const cvaTag: (props?: ({
|
|
2
2
|
size?: "small" | "medium" | null | undefined;
|
|
3
3
|
layout?: "default" | "containsDismiss" | "containsIcon" | null | undefined;
|
|
4
|
-
color?: "primary" | "
|
|
4
|
+
color?: "primary" | "neutral" | "black" | "white" | "info" | "success" | "warning" | "danger" | "good" | "low" | "critical" | "working" | "stopped" | "idle" | "unknown" | "moving" | "active" | "excessive_usage" | null | undefined;
|
|
5
5
|
border?: "default" | "none" | null | undefined;
|
|
6
6
|
} & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
|
|
7
7
|
export declare const cvaTagText: (props?: import("class-variance-authority/dist/types").ClassProp | undefined) => string;
|