@trackunit/react-components 1.9.13 → 1.9.18
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
|
@@ -32,7 +32,7 @@ const cvaIcon = cssClassVarianceUtilities.cvaMerge(["aspect-square", "inline-gri
|
|
|
32
32
|
variants: {
|
|
33
33
|
color: {
|
|
34
34
|
primary: "text-primary-600",
|
|
35
|
-
secondary: "text-
|
|
35
|
+
secondary: "text-neutral-400",
|
|
36
36
|
neutral: "text-neutral-400",
|
|
37
37
|
info: "text-info-600",
|
|
38
38
|
success: "text-success-600",
|
|
@@ -201,7 +201,7 @@ const cvaTag = cssClassVarianceUtilities.cvaMerge([
|
|
|
201
201
|
},
|
|
202
202
|
color: {
|
|
203
203
|
primary: ["bg-primary-100", "text-primary-700"],
|
|
204
|
-
secondary: ["bg-
|
|
204
|
+
secondary: ["bg-neutral-100", "text-neutral-700"],
|
|
205
205
|
neutral: ["bg-neutral-200", "text-neutral-700"],
|
|
206
206
|
black: ["bg-neutral-100", "text-neutral-700"],
|
|
207
207
|
white: ["bg-white", "text-neutral-600"],
|
|
@@ -222,7 +222,7 @@ const cvaTag = cssClassVarianceUtilities.cvaMerge([
|
|
|
222
222
|
},
|
|
223
223
|
border: {
|
|
224
224
|
none: "border-none",
|
|
225
|
-
default: "
|
|
225
|
+
default: "border-none outline outline-1 -outline-offset-1 outline-neutral-300",
|
|
226
226
|
},
|
|
227
227
|
},
|
|
228
228
|
defaultVariants: {
|
|
@@ -410,7 +410,7 @@ const cvaSpinner = cssClassVarianceUtilities.cvaMerge(["bg-transparent", "rounde
|
|
|
410
410
|
},
|
|
411
411
|
mode: {
|
|
412
412
|
dark: ["border-white/[0.32]", "border-b-white/75"],
|
|
413
|
-
light: ["border-
|
|
413
|
+
light: ["border-neutral-900/25", "border-b-neutral-900/50"],
|
|
414
414
|
},
|
|
415
415
|
},
|
|
416
416
|
defaultVariants: {
|
|
@@ -428,7 +428,7 @@ const cvaSpinnerContainer = cssClassVarianceUtilities.cvaMerge(["box-border", "p
|
|
|
428
428
|
},
|
|
429
429
|
mode: {
|
|
430
430
|
dark: ["text-white/75"],
|
|
431
|
-
light: ["text-
|
|
431
|
+
light: ["text-neutral-900/50"],
|
|
432
432
|
},
|
|
433
433
|
},
|
|
434
434
|
defaultVariants: {
|
|
@@ -1828,7 +1828,7 @@ const useBreadcrumbItemsToRender = (breadcrumbItems) => {
|
|
|
1828
1828
|
const breadCrumbItemsToJSX = breadcrumbItems.map((item, index, array) => {
|
|
1829
1829
|
const isLast = index === array.length - 1;
|
|
1830
1830
|
if (!isLast) {
|
|
1831
|
-
return (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx(Button, { asChild: true, size: "small", variant: "ghost-neutral", children: jsxRuntime.jsx(reactRouter.Link, { to: item.to, children: item.label }) }), jsxRuntime.jsx(Icon, { className: "text-
|
|
1831
|
+
return (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx(Button, { asChild: true, size: "small", variant: "ghost-neutral", children: jsxRuntime.jsx(reactRouter.Link, { to: item.to, children: item.label }) }), jsxRuntime.jsx(Icon, { className: "text-neutral-300", name: "Slash", size: "small" })] }, index));
|
|
1832
1832
|
}
|
|
1833
1833
|
return (jsxRuntime.jsx(Text, { className: "text-nowrap", size: "small", children: item.label }, index));
|
|
1834
1834
|
});
|
|
@@ -1895,7 +1895,7 @@ const cvaCard = cssClassVarianceUtilities.cvaMerge([
|
|
|
1895
1895
|
fullHeight: false,
|
|
1896
1896
|
},
|
|
1897
1897
|
});
|
|
1898
|
-
const cvaCardFooterDensityContainer = cssClassVarianceUtilities.cvaMerge(["flex", "border-t", "border-
|
|
1898
|
+
const cvaCardFooterDensityContainer = cssClassVarianceUtilities.cvaMerge(["flex", "border-t", "border-neutral-200", "justify-end", "flex-row"], {
|
|
1899
1899
|
variants: {
|
|
1900
1900
|
border: {
|
|
1901
1901
|
default: "",
|
|
@@ -1918,7 +1918,7 @@ const cvaCardFooterDensityContainer = cssClassVarianceUtilities.cvaMerge(["flex"
|
|
|
1918
1918
|
});
|
|
1919
1919
|
const cvaCardHeader = cssClassVarianceUtilities.cvaMerge(["flex", "justify-between", "flex-1"]);
|
|
1920
1920
|
const cvaCardHeaderHeadingContainer = cssClassVarianceUtilities.cvaMerge(["flex", "gap-4", "items-center"]);
|
|
1921
|
-
const cvaCardHeaderDensityContainer = cssClassVarianceUtilities.cvaMerge(["flex", "border-b", "border-
|
|
1921
|
+
const cvaCardHeaderDensityContainer = cssClassVarianceUtilities.cvaMerge(["flex", "border-b", "border-neutral-200"], {
|
|
1922
1922
|
variants: {
|
|
1923
1923
|
border: {
|
|
1924
1924
|
default: "",
|
|
@@ -2076,7 +2076,7 @@ const cvaCollapse = cssClassVarianceUtilities.cvaMerge([
|
|
|
2076
2076
|
"block",
|
|
2077
2077
|
"border",
|
|
2078
2078
|
"border-solid",
|
|
2079
|
-
"border-
|
|
2079
|
+
"border-neutral-300",
|
|
2080
2080
|
"rounded-md",
|
|
2081
2081
|
"overflow-hidden",
|
|
2082
2082
|
"bg-white",
|
|
@@ -2087,14 +2087,14 @@ const cvaCollapseHeader = cssClassVarianceUtilities.cvaMerge([
|
|
|
2087
2087
|
"justify-between",
|
|
2088
2088
|
"cursor-pointer",
|
|
2089
2089
|
"bg-white",
|
|
2090
|
-
"hover:bg-
|
|
2090
|
+
"hover:bg-neutral-100",
|
|
2091
2091
|
"px-3",
|
|
2092
2092
|
"gap-4",
|
|
2093
2093
|
"py-1.5",
|
|
2094
2094
|
"transition-all",
|
|
2095
2095
|
], {
|
|
2096
2096
|
variants: {
|
|
2097
|
-
expanded: { true: ["border-
|
|
2097
|
+
expanded: { true: ["border-neutral-200", "border-b", "border-solid"], false: "" },
|
|
2098
2098
|
},
|
|
2099
2099
|
});
|
|
2100
2100
|
const cvaCollapseLabelContainer = cssClassVarianceUtilities.cvaMerge(["flex", "items-center", "w-full", "justify-between"]);
|
|
@@ -2231,7 +2231,7 @@ const CopyableText = ({ text, alternativeText, dataTestId, className }) => {
|
|
|
2231
2231
|
return (jsxRuntime.jsx("span", { className: cvaCopyableText({ animating, className }), "data-testid": dataTestId, onAnimationEnd: () => setAnimating(false), onClick: handleOnClick, title: value, children: text }));
|
|
2232
2232
|
};
|
|
2233
2233
|
|
|
2234
|
-
const cvaDetailsList = cssClassVarianceUtilities.cvaMerge(["flex", "w-full", "min-w-0", "items-center", "truncate", "text-xs", "text-
|
|
2234
|
+
const cvaDetailsList = cssClassVarianceUtilities.cvaMerge(["flex", "w-full", "min-w-0", "items-center", "truncate", "text-xs", "text-neutral-600", "font-medium"], {
|
|
2235
2235
|
variants: {
|
|
2236
2236
|
density: {
|
|
2237
2237
|
default: "pt-0",
|
|
@@ -2296,20 +2296,30 @@ const cvaSkeletonLine = cssClassVarianceUtilities.cvaMerge([
|
|
|
2296
2296
|
|
|
2297
2297
|
/**
|
|
2298
2298
|
* Display placeholder lines before the data gets loaded to reduce load-time frustration.
|
|
2299
|
+
* All width values are automatically constrained using CSS min() function to prevent overflow.
|
|
2299
2300
|
*/
|
|
2300
|
-
const SkeletonLines = react.memo(({ lines = 1, height = "0.75rem", width = "100%",
|
|
2301
|
-
const gapStyle = typeof
|
|
2301
|
+
const SkeletonLines = react.memo(({ lines = 1, height = "0.75rem", width = "100%", gap = 10, maxWidth = "100%", className, dataTestId, }) => {
|
|
2302
|
+
const gapStyle = typeof gap === "number" ? `${gap}px` : gap;
|
|
2302
2303
|
return (jsxRuntime.jsx("div", { "aria-label": `Loading ${lines} ${lines === 1 ? "item" : "items"}`, className: cvaSkeletonContainer({ className }), "data-testid": dataTestId, role: "status", style: { gap: gapStyle }, children: Array.from({ length: lines }, (_, index) => (jsxRuntime.jsx("div", { className: cvaSkeletonLine(), "data-testid": dataTestId ? `${dataTestId}-${index}` : `skeleton-lines-${index}`, "data-type": "loading-skeleton-line", style: {
|
|
2303
|
-
width: getDimension(width, index),
|
|
2304
|
-
height: getDimension(height, index),
|
|
2304
|
+
width: getDimension({ dimension: width, index, direction: "width", maxWidth }),
|
|
2305
|
+
height: getDimension({ dimension: height, index, direction: "height" }),
|
|
2305
2306
|
} }, index))) }));
|
|
2306
2307
|
});
|
|
2307
|
-
const getDimension = (
|
|
2308
|
+
const getDimension = (params) => {
|
|
2309
|
+
const { dimension, index } = params;
|
|
2310
|
+
let value;
|
|
2308
2311
|
if (Array.isArray(dimension)) {
|
|
2309
|
-
const
|
|
2310
|
-
|
|
2312
|
+
const dimValue = dimension[index] ?? dimension[0] ?? "100%";
|
|
2313
|
+
value = typeof dimValue === "number" ? `${dimValue}px` : dimValue;
|
|
2311
2314
|
}
|
|
2312
|
-
|
|
2315
|
+
else {
|
|
2316
|
+
value = typeof dimension === "number" ? `${dimension}px` : dimension;
|
|
2317
|
+
}
|
|
2318
|
+
// For width values, wrap in min() to ensure max container width
|
|
2319
|
+
if (params.direction === "width") {
|
|
2320
|
+
return `min(${value}, ${params.maxWidth})`;
|
|
2321
|
+
}
|
|
2322
|
+
return value;
|
|
2313
2323
|
};
|
|
2314
2324
|
|
|
2315
2325
|
const cvaContainerStyles = cssClassVarianceUtilities.cvaMerge([
|
|
@@ -2592,7 +2602,7 @@ const HorizontalOverflowScroller = ({ className, dataTestId, children, onScrollS
|
|
|
2592
2602
|
behavior: "smooth",
|
|
2593
2603
|
});
|
|
2594
2604
|
};
|
|
2595
|
-
return (jsxRuntime.jsxs(ZStack, { className: cvaHorizontalOverflowScrollerAndIndicatorsContainer({ className }), children: [jsxRuntime.jsx("div", { className: cvaHorizontalOverflowScroller(
|
|
2605
|
+
return (jsxRuntime.jsxs(ZStack, { className: cvaHorizontalOverflowScrollerAndIndicatorsContainer({ className }), children: [jsxRuntime.jsx("div", { className: cvaHorizontalOverflowScroller(), "data-testid": dataTestId, ref: containerRef, children: childrenArray.map((child, index) => (jsxRuntime.jsx(react.Fragment, { children: child }, index))) }), isScrollable && !isAtBeginning ? (jsxRuntime.jsx(OverflowIndicator, { dataTestId: `${dataTestId}-left-indicator`, direction: "left", onClickScroll: handleScrollLeft })) : null, isScrollable && !isAtEnd ? (jsxRuntime.jsx(OverflowIndicator, { dataTestId: `${dataTestId}-right-indicator`, direction: "right", onClickScroll: handleScrollRight })) : null] }));
|
|
2596
2606
|
};
|
|
2597
2607
|
|
|
2598
2608
|
const PADDING = 12;
|
|
@@ -2907,11 +2917,11 @@ const PopoverTrigger = function PopoverTrigger({ children, renderButton = false,
|
|
|
2907
2917
|
};
|
|
2908
2918
|
|
|
2909
2919
|
const cvaTooltipContainer = cssClassVarianceUtilities.cvaMerge(["flex", "leading-5"]);
|
|
2910
|
-
const cvaTooltipIcon = cssClassVarianceUtilities.cvaMerge(["flex", "h-max", "w-fit", "text-
|
|
2920
|
+
const cvaTooltipIcon = cssClassVarianceUtilities.cvaMerge(["flex", "h-max", "w-fit", "text-neutral-300", "transition", "hover:cursor-pointer", "hover:text-neutral-400"], {
|
|
2911
2921
|
variants: {
|
|
2912
2922
|
color: {
|
|
2913
2923
|
light: "hover:text-white",
|
|
2914
|
-
dark: "hover:text-
|
|
2924
|
+
dark: "hover:text-neutral-400",
|
|
2915
2925
|
},
|
|
2916
2926
|
defaultVariants: {
|
|
2917
2927
|
color: "dark",
|
|
@@ -3042,7 +3052,7 @@ const cvaIndicatorPing = cssClassVarianceUtilities.cvaMerge(["animate-ping-sm",
|
|
|
3042
3052
|
variants: {
|
|
3043
3053
|
color: {
|
|
3044
3054
|
primary: "bg-primary-600",
|
|
3045
|
-
secondary: "bg-
|
|
3055
|
+
secondary: "bg-neutral-600",
|
|
3046
3056
|
neutral: "bg-neutral-600",
|
|
3047
3057
|
info: "bg-info-600",
|
|
3048
3058
|
success: "bg-success-600",
|
|
@@ -3085,7 +3095,7 @@ const cvaIndicatorIconBackground = cssClassVarianceUtilities.cvaMerge(["rounded-
|
|
|
3085
3095
|
variants: {
|
|
3086
3096
|
color: {
|
|
3087
3097
|
primary: "bg-primary-100 text-primary-600",
|
|
3088
|
-
secondary: "bg-
|
|
3098
|
+
secondary: "bg-neutral-100 text-neutral-600",
|
|
3089
3099
|
neutral: "bg-neutral-100 text-neutral-600",
|
|
3090
3100
|
info: "bg-info-100 text-info-600",
|
|
3091
3101
|
success: "bg-success-100 text-success-600",
|
|
@@ -3199,7 +3209,7 @@ const cvaKPIValueContainer = cssClassVarianceUtilities.cvaMerge(["truncate", "wh
|
|
|
3199
3209
|
},
|
|
3200
3210
|
});
|
|
3201
3211
|
|
|
3202
|
-
const LoadingContent$1 = () => (jsxRuntime.jsx("div", { className: "flex h-11 flex-row items-center gap-3", "data-testid": "kpi-card-loading-content", children: jsxRuntime.jsx("div", { className: "w-full", children: jsxRuntime.jsx(SkeletonLines, { height: [14, 18], lines: 2,
|
|
3212
|
+
const LoadingContent$1 = () => (jsxRuntime.jsx("div", { className: "flex h-11 flex-row items-center gap-3", "data-testid": "kpi-card-loading-content", children: jsxRuntime.jsx("div", { className: "w-full", children: jsxRuntime.jsx(SkeletonLines, { gap: 3, height: [14, 18], lines: 2, width: [80, 60] }) }) }));
|
|
3203
3213
|
/**
|
|
3204
3214
|
* The KPI component is used to display KPIs.
|
|
3205
3215
|
*
|
|
@@ -3231,7 +3241,7 @@ const cvaKPICard = cssClassVarianceUtilities.cvaMerge([
|
|
|
3231
3241
|
withTrends: ["min-h-[94px]"],
|
|
3232
3242
|
},
|
|
3233
3243
|
isClickable: {
|
|
3234
|
-
true: ["hover:bg-
|
|
3244
|
+
true: ["hover:bg-neutral-50", "component-card-border"],
|
|
3235
3245
|
false: [],
|
|
3236
3246
|
},
|
|
3237
3247
|
isActive: {
|
|
@@ -3561,7 +3571,7 @@ const cvaMenuList = cssClassVarianceUtilities.cvaMerge([
|
|
|
3561
3571
|
"z-popover",
|
|
3562
3572
|
"bg-white",
|
|
3563
3573
|
"border",
|
|
3564
|
-
"border-
|
|
3574
|
+
"border-neutral-300",
|
|
3565
3575
|
"grid",
|
|
3566
3576
|
"min-w-[200px]",
|
|
3567
3577
|
"max-w-[300px]",
|
|
@@ -3574,7 +3584,7 @@ const cvaMenuList = cssClassVarianceUtilities.cvaMerge([
|
|
|
3574
3584
|
},
|
|
3575
3585
|
},
|
|
3576
3586
|
});
|
|
3577
|
-
const cvaMenuListDivider = cssClassVarianceUtilities.cvaMerge(["mx-[-4px]", "my-1", "min-h-px", "bg-
|
|
3587
|
+
const cvaMenuListDivider = cssClassVarianceUtilities.cvaMerge(["mx-[-4px]", "my-1", "min-h-px", "bg-neutral-300"]);
|
|
3578
3588
|
const cvaMenuListMultiSelect = cssClassVarianceUtilities.cvaMerge("hover:!bg-blue-200");
|
|
3579
3589
|
const cvaMenuListItem = cssClassVarianceUtilities.cvaMerge("max-w-full");
|
|
3580
3590
|
|
|
@@ -3655,9 +3665,9 @@ const cvaMenuItemLabel = cssClassVarianceUtilities.cvaMerge(["flex-grow", "trunc
|
|
|
3655
3665
|
},
|
|
3656
3666
|
});
|
|
3657
3667
|
const cvaMenuItemPrefix = cssClassVarianceUtilities.cvaMerge([
|
|
3658
|
-
"text-
|
|
3659
|
-
"hover:text-
|
|
3660
|
-
"focus:text-
|
|
3668
|
+
"text-neutral-400",
|
|
3669
|
+
"hover:text-neutral-500",
|
|
3670
|
+
"focus:text-neutral-500",
|
|
3661
3671
|
"h-min",
|
|
3662
3672
|
"leading-[0]",
|
|
3663
3673
|
"flex",
|
|
@@ -3665,7 +3675,7 @@ const cvaMenuItemPrefix = cssClassVarianceUtilities.cvaMerge([
|
|
|
3665
3675
|
], {
|
|
3666
3676
|
variants: {
|
|
3667
3677
|
selected: {
|
|
3668
|
-
true: "text-
|
|
3678
|
+
true: "text-neutral-600",
|
|
3669
3679
|
false: "",
|
|
3670
3680
|
},
|
|
3671
3681
|
variant: {
|
|
@@ -3673,7 +3683,7 @@ const cvaMenuItemPrefix = cssClassVarianceUtilities.cvaMerge([
|
|
|
3673
3683
|
danger: ["text-danger-600", "hover:text-danger-700", "focus:bg-danger-200", "focus:text-danger-800"],
|
|
3674
3684
|
},
|
|
3675
3685
|
disabled: {
|
|
3676
|
-
true: "text-
|
|
3686
|
+
true: "text-neutral opacity-50",
|
|
3677
3687
|
false: "",
|
|
3678
3688
|
},
|
|
3679
3689
|
},
|
|
@@ -3682,10 +3692,10 @@ const cvaMenuItemPrefix = cssClassVarianceUtilities.cvaMerge([
|
|
|
3682
3692
|
disabled: false,
|
|
3683
3693
|
},
|
|
3684
3694
|
});
|
|
3685
|
-
const cvaMenuItemSuffix = cssClassVarianceUtilities.cvaMerge(["text-
|
|
3695
|
+
const cvaMenuItemSuffix = cssClassVarianceUtilities.cvaMerge(["text-neutral-400", "text-sm", "flex", "items-center"], {
|
|
3686
3696
|
variants: {
|
|
3687
3697
|
selected: {
|
|
3688
|
-
true: "text-
|
|
3698
|
+
true: "text-neutral-600",
|
|
3689
3699
|
false: "",
|
|
3690
3700
|
},
|
|
3691
3701
|
variant: {
|
|
@@ -3693,7 +3703,7 @@ const cvaMenuItemSuffix = cssClassVarianceUtilities.cvaMerge(["text-secondary-40
|
|
|
3693
3703
|
danger: ["text-danger-600", "hover:text-danger-700", "focus:bg-danger-200", "focus:text-danger-800"],
|
|
3694
3704
|
},
|
|
3695
3705
|
disabled: {
|
|
3696
|
-
true: "text-
|
|
3706
|
+
true: "text-neutral opacity-50",
|
|
3697
3707
|
false: "",
|
|
3698
3708
|
},
|
|
3699
3709
|
},
|
|
@@ -3732,7 +3742,7 @@ const MenuItem = ({ className, dataTestId, label, children, selected = false, fo
|
|
|
3732
3742
|
e.stopPropagation();
|
|
3733
3743
|
}
|
|
3734
3744
|
onClick?.(e);
|
|
3735
|
-
}, onKeyDown: handleKeyDown, role: "menuitem", tabIndex: disabled ? -1 : (tabIndex ?? 0), children: [prefix !== null && prefix !== undefined ? (jsxRuntime.jsx("div", { className: cvaMenuItemPrefix({ selected, variant, disabled }), "data-testid": dataTestId ? `${dataTestId}-prefix` : "menu-item-prefix", children: prefix })) : null, children !== null && children !== undefined && typeof children !== "string" ? (children) : (jsxRuntime.jsxs("div", { className: cvaMenuItemLabel({ variant, disabled }), "data-testid": dataTestId ? `${dataTestId}-label` : "menu-item-label", children: [optionPrefix !== null && optionPrefix !== undefined ? optionPrefix : null, children ?? label, optionLabelDescription !== undefined && optionLabelDescription !== "" ? (jsxRuntime.jsxs("span", { className: "text-
|
|
3745
|
+
}, onKeyDown: handleKeyDown, role: "menuitem", tabIndex: disabled ? -1 : (tabIndex ?? 0), children: [prefix !== null && prefix !== undefined ? (jsxRuntime.jsx("div", { className: cvaMenuItemPrefix({ selected, variant, disabled }), "data-testid": dataTestId ? `${dataTestId}-prefix` : "menu-item-prefix", children: prefix })) : null, children !== null && children !== undefined && typeof children !== "string" ? (children) : (jsxRuntime.jsxs("div", { className: cvaMenuItemLabel({ variant, disabled }), "data-testid": dataTestId ? `${dataTestId}-label` : "menu-item-label", children: [optionPrefix !== null && optionPrefix !== undefined ? optionPrefix : null, children ?? label, optionLabelDescription !== undefined && optionLabelDescription !== "" ? (jsxRuntime.jsxs("span", { className: "ml-1 text-neutral-400", children: ["(", optionLabelDescription, ")"] })) : null] })), suffix !== null && suffix !== undefined ? (jsxRuntime.jsx("div", { className: cvaMenuItemSuffix({ selected, variant, disabled }), "data-testid": dataTestId ? `${dataTestId}-suffix` : "menu-item-suffix", children: suffix })) : null] }));
|
|
3736
3746
|
};
|
|
3737
3747
|
|
|
3738
3748
|
/**
|
|
@@ -3798,7 +3808,7 @@ const cvaMoreMenu = cssClassVarianceUtilities.cvaMerge(["p-0"]);
|
|
|
3798
3808
|
*/
|
|
3799
3809
|
const MoreMenu = ({ className, dataTestId, popoverProps, iconProps = {
|
|
3800
3810
|
size: "medium",
|
|
3801
|
-
className: "text-
|
|
3811
|
+
className: "text-neutral-400",
|
|
3802
3812
|
}, iconButtonProps = {
|
|
3803
3813
|
size: "medium",
|
|
3804
3814
|
circular: false,
|
|
@@ -3902,7 +3912,7 @@ const PageContent = ({ className, children, dataTestId, layout }) => {
|
|
|
3902
3912
|
return (jsxRuntime.jsx("div", { className: cvaPageContent({ className, layout }), "data-testid": dataTestId ? dataTestId : "page-content", children: children }));
|
|
3903
3913
|
};
|
|
3904
3914
|
|
|
3905
|
-
const LoadingContent = () => (jsxRuntime.jsx("div", { className: "flex flex-row items-center gap-3", "data-testid": "kpi-card-loading-content", children: jsxRuntime.jsx("div", { className: "w-full", children: jsxRuntime.jsx(SkeletonLines, { height: [16, 25], lines: 2,
|
|
3915
|
+
const LoadingContent = () => (jsxRuntime.jsx("div", { className: "flex flex-row items-center gap-3", "data-testid": "kpi-card-loading-content", children: jsxRuntime.jsx("div", { className: "w-full", children: jsxRuntime.jsx(SkeletonLines, { gap: 3, height: [16, 25], lines: 2, width: [50, 40] }) }) }));
|
|
3906
3916
|
/**
|
|
3907
3917
|
* The PageHeaderKpiMetrics component is used to render the KPI metrics in the PageHeader component.
|
|
3908
3918
|
*
|
|
@@ -3917,7 +3927,7 @@ const PageHeaderKpiMetrics = ({ kpiMetrics }) => {
|
|
|
3917
3927
|
if (kpi.loading === true) {
|
|
3918
3928
|
return jsxRuntime.jsx(LoadingContent, {}, `${kpi}-${index}`);
|
|
3919
3929
|
}
|
|
3920
|
-
return (jsxRuntime.jsxs("div", { className: "flex flex-col text-nowrap text-left", children: [jsxRuntime.jsx("span", { className: "text-xs text-
|
|
3930
|
+
return (jsxRuntime.jsxs("div", { className: "flex flex-col text-nowrap text-left", children: [jsxRuntime.jsx("span", { className: "text-xs text-neutral-500", children: kpi.header }), jsxRuntime.jsxs("div", { className: "flex flex-row items-center gap-1", children: [jsxRuntime.jsx("span", { className: "text-lg font-medium text-neutral-900", children: kpi.value }), kpi.unit ? jsxRuntime.jsx("span", { className: "text-xs text-neutral-900", children: kpi.unit }) : null] })] }, `${kpi}-${index}`));
|
|
3921
3931
|
}) }));
|
|
3922
3932
|
};
|
|
3923
3933
|
|
|
@@ -3983,13 +3993,13 @@ const PageHeaderSecondaryActions = ({ actions, hasPrimaryAction = false, }) => {
|
|
|
3983
3993
|
const cvaPageHeaderContainer = cssClassVarianceUtilities.cvaMerge(["bg-white", "tu-page-header"], {
|
|
3984
3994
|
variants: {
|
|
3985
3995
|
withBorder: {
|
|
3986
|
-
true: ["border-b", "border-b-
|
|
3996
|
+
true: ["border-b", "border-b-neutral-200"],
|
|
3987
3997
|
false: "",
|
|
3988
3998
|
},
|
|
3989
3999
|
},
|
|
3990
4000
|
});
|
|
3991
4001
|
const cvaPageHeader = cssClassVarianceUtilities.cvaMerge(["box-border", "py-4", "px-6", "flex", "items-center", "gap-y-1"]);
|
|
3992
|
-
const cvaPageHeaderHeading = cssClassVarianceUtilities.cvaMerge(["text-
|
|
4002
|
+
const cvaPageHeaderHeading = cssClassVarianceUtilities.cvaMerge(["text-neutral-900", "text-xl", "font-semibold", "truncate"]);
|
|
3993
4003
|
|
|
3994
4004
|
/**
|
|
3995
4005
|
* The PageHeaderTitle component is used to display the title of the page header.
|
|
@@ -4311,7 +4321,7 @@ const cvaTabList = cssClassVarianceUtilities.cvaMerge([
|
|
|
4311
4321
|
"flex",
|
|
4312
4322
|
"flex-row",
|
|
4313
4323
|
"border-b",
|
|
4314
|
-
"border-b-
|
|
4324
|
+
"border-b-neutral-200",
|
|
4315
4325
|
"overflow-auto",
|
|
4316
4326
|
"no-scrollbar",
|
|
4317
4327
|
]);
|
|
@@ -4334,13 +4344,13 @@ const cvaTab = cssClassVarianceUtilities.cvaMerge([
|
|
|
4334
4344
|
"hover:border-b-transparent",
|
|
4335
4345
|
"data-[state=active]:border-b-primary-600",
|
|
4336
4346
|
"data-[state=active]:font-semibold",
|
|
4337
|
-
"data-[state=active]:text-
|
|
4347
|
+
"data-[state=active]:text-neutral-900",
|
|
4338
4348
|
"data-[state=inactive]:font-medium",
|
|
4339
|
-
"data-[state=inactive]:text-
|
|
4340
|
-
"data-[state=inactive]:hover:text-
|
|
4349
|
+
"data-[state=inactive]:text-neutral-700",
|
|
4350
|
+
"data-[state=inactive]:hover:text-neutral-900",
|
|
4341
4351
|
"disabled:cursor-not-allowed",
|
|
4342
|
-
"data-[state=active]disabled:text-
|
|
4343
|
-
"data-[state=inactive]:disabled:text-
|
|
4352
|
+
"data-[state=active]disabled:text-neutral-400",
|
|
4353
|
+
"data-[state=inactive]:disabled:text-neutral-400",
|
|
4344
4354
|
], {
|
|
4345
4355
|
variants: {
|
|
4346
4356
|
isFullWidth: {
|
|
@@ -4379,12 +4389,13 @@ const TabContent = ({ className, dataTestId, children, ...rest }) => {
|
|
|
4379
4389
|
/**
|
|
4380
4390
|
* Wrapper for radix tab list component.
|
|
4381
4391
|
*/
|
|
4382
|
-
const TabList = ({ className, dataTestId, children, ...rest }) => {
|
|
4392
|
+
const TabList = ({ className, dataTestId, children, autoScrollToActive = true, ...rest }) => {
|
|
4383
4393
|
const listRef = react.useRef(null);
|
|
4384
4394
|
react.useEffect(() => {
|
|
4385
4395
|
const element = listRef.current;
|
|
4386
|
-
if (!element)
|
|
4396
|
+
if (!element) {
|
|
4387
4397
|
return;
|
|
4398
|
+
}
|
|
4388
4399
|
const handleWheel = (event) => {
|
|
4389
4400
|
const canScrollHorizontally = element.scrollWidth > element.clientWidth;
|
|
4390
4401
|
if (canScrollHorizontally) {
|
|
@@ -4400,6 +4411,24 @@ const TabList = ({ className, dataTestId, children, ...rest }) => {
|
|
|
4400
4411
|
element.removeEventListener("wheel", handleWheel);
|
|
4401
4412
|
};
|
|
4402
4413
|
}, []);
|
|
4414
|
+
// Auto-scroll active tab into view when enabled
|
|
4415
|
+
react.useLayoutEffect(() => {
|
|
4416
|
+
if (!autoScrollToActive) {
|
|
4417
|
+
return;
|
|
4418
|
+
}
|
|
4419
|
+
const element = listRef.current;
|
|
4420
|
+
if (!element)
|
|
4421
|
+
return;
|
|
4422
|
+
// Find the active tab using a radix UI build in selector
|
|
4423
|
+
const activeTab = element.querySelector('[aria-selected="true"]');
|
|
4424
|
+
if (activeTab && typeof activeTab.scrollIntoView === "function") {
|
|
4425
|
+
activeTab.scrollIntoView({
|
|
4426
|
+
behavior: "instant",
|
|
4427
|
+
block: "nearest",
|
|
4428
|
+
inline: "center",
|
|
4429
|
+
});
|
|
4430
|
+
}
|
|
4431
|
+
}, [autoScrollToActive]);
|
|
4403
4432
|
return (jsxRuntime.jsx(reactTabs.List, { className: cvaTabList({ className }), "data-testid": dataTestId, ref: listRef, ...rest, children: children }));
|
|
4404
4433
|
};
|
|
4405
4434
|
|
|
@@ -4584,7 +4613,7 @@ const cvaValueBar = cssClassVarianceUtilities.cvaMerge([
|
|
|
4584
4613
|
"w-full",
|
|
4585
4614
|
"overflow-hidden",
|
|
4586
4615
|
"rounded",
|
|
4587
|
-
"bg-
|
|
4616
|
+
"bg-neutral-100",
|
|
4588
4617
|
"appearance-none",
|
|
4589
4618
|
"[&::-webkit-progress-bar]:bg-transparent",
|
|
4590
4619
|
"[&::-webkit-progress-value]:bg-current",
|
package/index.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
|
|
2
|
-
import { useRef, useMemo, useEffect, useState, useCallback, createElement, useReducer, forwardRef, Fragment, memo, Children, isValidElement, cloneElement, createContext, useContext } from 'react';
|
|
2
|
+
import { useRef, useMemo, useEffect, useState, useCallback, createElement, useReducer, forwardRef, Fragment, memo, Children, isValidElement, cloneElement, createContext, useContext, useLayoutEffect } from 'react';
|
|
3
3
|
import { objectKeys, uuidv4, objectEntries, objectValues, nonNullable } from '@trackunit/shared-utils';
|
|
4
4
|
import { intentPalette, generalPalette, criticalityPalette, activityPalette, utilizationPalette, sitesPalette, rentalStatusPalette, themeScreenSizeAsNumber, color } from '@trackunit/ui-design-tokens';
|
|
5
5
|
import { iconNames } from '@trackunit/ui-icons';
|
|
@@ -30,7 +30,7 @@ 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-
|
|
33
|
+
secondary: "text-neutral-400",
|
|
34
34
|
neutral: "text-neutral-400",
|
|
35
35
|
info: "text-info-600",
|
|
36
36
|
success: "text-success-600",
|
|
@@ -199,7 +199,7 @@ const cvaTag = cvaMerge([
|
|
|
199
199
|
},
|
|
200
200
|
color: {
|
|
201
201
|
primary: ["bg-primary-100", "text-primary-700"],
|
|
202
|
-
secondary: ["bg-
|
|
202
|
+
secondary: ["bg-neutral-100", "text-neutral-700"],
|
|
203
203
|
neutral: ["bg-neutral-200", "text-neutral-700"],
|
|
204
204
|
black: ["bg-neutral-100", "text-neutral-700"],
|
|
205
205
|
white: ["bg-white", "text-neutral-600"],
|
|
@@ -220,7 +220,7 @@ const cvaTag = cvaMerge([
|
|
|
220
220
|
},
|
|
221
221
|
border: {
|
|
222
222
|
none: "border-none",
|
|
223
|
-
default: "
|
|
223
|
+
default: "border-none outline outline-1 -outline-offset-1 outline-neutral-300",
|
|
224
224
|
},
|
|
225
225
|
},
|
|
226
226
|
defaultVariants: {
|
|
@@ -408,7 +408,7 @@ const cvaSpinner = cvaMerge(["bg-transparent", "rounded-full", "border-2", "bord
|
|
|
408
408
|
},
|
|
409
409
|
mode: {
|
|
410
410
|
dark: ["border-white/[0.32]", "border-b-white/75"],
|
|
411
|
-
light: ["border-
|
|
411
|
+
light: ["border-neutral-900/25", "border-b-neutral-900/50"],
|
|
412
412
|
},
|
|
413
413
|
},
|
|
414
414
|
defaultVariants: {
|
|
@@ -426,7 +426,7 @@ const cvaSpinnerContainer = cvaMerge(["box-border", "p-0.5", "overflow-hidden"],
|
|
|
426
426
|
},
|
|
427
427
|
mode: {
|
|
428
428
|
dark: ["text-white/75"],
|
|
429
|
-
light: ["text-
|
|
429
|
+
light: ["text-neutral-900/50"],
|
|
430
430
|
},
|
|
431
431
|
},
|
|
432
432
|
defaultVariants: {
|
|
@@ -1826,7 +1826,7 @@ const useBreadcrumbItemsToRender = (breadcrumbItems) => {
|
|
|
1826
1826
|
const breadCrumbItemsToJSX = breadcrumbItems.map((item, index, array) => {
|
|
1827
1827
|
const isLast = index === array.length - 1;
|
|
1828
1828
|
if (!isLast) {
|
|
1829
|
-
return (jsxs("div", { children: [jsx(Button, { asChild: true, size: "small", variant: "ghost-neutral", children: jsx(Link, { to: item.to, children: item.label }) }), jsx(Icon, { className: "text-
|
|
1829
|
+
return (jsxs("div", { children: [jsx(Button, { asChild: true, size: "small", variant: "ghost-neutral", children: jsx(Link, { to: item.to, children: item.label }) }), jsx(Icon, { className: "text-neutral-300", name: "Slash", size: "small" })] }, index));
|
|
1830
1830
|
}
|
|
1831
1831
|
return (jsx(Text, { className: "text-nowrap", size: "small", children: item.label }, index));
|
|
1832
1832
|
});
|
|
@@ -1893,7 +1893,7 @@ const cvaCard = cvaMerge([
|
|
|
1893
1893
|
fullHeight: false,
|
|
1894
1894
|
},
|
|
1895
1895
|
});
|
|
1896
|
-
const cvaCardFooterDensityContainer = cvaMerge(["flex", "border-t", "border-
|
|
1896
|
+
const cvaCardFooterDensityContainer = cvaMerge(["flex", "border-t", "border-neutral-200", "justify-end", "flex-row"], {
|
|
1897
1897
|
variants: {
|
|
1898
1898
|
border: {
|
|
1899
1899
|
default: "",
|
|
@@ -1916,7 +1916,7 @@ const cvaCardFooterDensityContainer = cvaMerge(["flex", "border-t", "border-seco
|
|
|
1916
1916
|
});
|
|
1917
1917
|
const cvaCardHeader = cvaMerge(["flex", "justify-between", "flex-1"]);
|
|
1918
1918
|
const cvaCardHeaderHeadingContainer = cvaMerge(["flex", "gap-4", "items-center"]);
|
|
1919
|
-
const cvaCardHeaderDensityContainer = cvaMerge(["flex", "border-b", "border-
|
|
1919
|
+
const cvaCardHeaderDensityContainer = cvaMerge(["flex", "border-b", "border-neutral-200"], {
|
|
1920
1920
|
variants: {
|
|
1921
1921
|
border: {
|
|
1922
1922
|
default: "",
|
|
@@ -2074,7 +2074,7 @@ const cvaCollapse = cvaMerge([
|
|
|
2074
2074
|
"block",
|
|
2075
2075
|
"border",
|
|
2076
2076
|
"border-solid",
|
|
2077
|
-
"border-
|
|
2077
|
+
"border-neutral-300",
|
|
2078
2078
|
"rounded-md",
|
|
2079
2079
|
"overflow-hidden",
|
|
2080
2080
|
"bg-white",
|
|
@@ -2085,14 +2085,14 @@ const cvaCollapseHeader = cvaMerge([
|
|
|
2085
2085
|
"justify-between",
|
|
2086
2086
|
"cursor-pointer",
|
|
2087
2087
|
"bg-white",
|
|
2088
|
-
"hover:bg-
|
|
2088
|
+
"hover:bg-neutral-100",
|
|
2089
2089
|
"px-3",
|
|
2090
2090
|
"gap-4",
|
|
2091
2091
|
"py-1.5",
|
|
2092
2092
|
"transition-all",
|
|
2093
2093
|
], {
|
|
2094
2094
|
variants: {
|
|
2095
|
-
expanded: { true: ["border-
|
|
2095
|
+
expanded: { true: ["border-neutral-200", "border-b", "border-solid"], false: "" },
|
|
2096
2096
|
},
|
|
2097
2097
|
});
|
|
2098
2098
|
const cvaCollapseLabelContainer = cvaMerge(["flex", "items-center", "w-full", "justify-between"]);
|
|
@@ -2229,7 +2229,7 @@ const CopyableText = ({ text, alternativeText, dataTestId, className }) => {
|
|
|
2229
2229
|
return (jsx("span", { className: cvaCopyableText({ animating, className }), "data-testid": dataTestId, onAnimationEnd: () => setAnimating(false), onClick: handleOnClick, title: value, children: text }));
|
|
2230
2230
|
};
|
|
2231
2231
|
|
|
2232
|
-
const cvaDetailsList = cvaMerge(["flex", "w-full", "min-w-0", "items-center", "truncate", "text-xs", "text-
|
|
2232
|
+
const cvaDetailsList = cvaMerge(["flex", "w-full", "min-w-0", "items-center", "truncate", "text-xs", "text-neutral-600", "font-medium"], {
|
|
2233
2233
|
variants: {
|
|
2234
2234
|
density: {
|
|
2235
2235
|
default: "pt-0",
|
|
@@ -2294,20 +2294,30 @@ const cvaSkeletonLine = cvaMerge([
|
|
|
2294
2294
|
|
|
2295
2295
|
/**
|
|
2296
2296
|
* Display placeholder lines before the data gets loaded to reduce load-time frustration.
|
|
2297
|
+
* All width values are automatically constrained using CSS min() function to prevent overflow.
|
|
2297
2298
|
*/
|
|
2298
|
-
const SkeletonLines = memo(({ lines = 1, height = "0.75rem", width = "100%",
|
|
2299
|
-
const gapStyle = typeof
|
|
2299
|
+
const SkeletonLines = memo(({ lines = 1, height = "0.75rem", width = "100%", gap = 10, maxWidth = "100%", className, dataTestId, }) => {
|
|
2300
|
+
const gapStyle = typeof gap === "number" ? `${gap}px` : gap;
|
|
2300
2301
|
return (jsx("div", { "aria-label": `Loading ${lines} ${lines === 1 ? "item" : "items"}`, className: cvaSkeletonContainer({ className }), "data-testid": dataTestId, role: "status", style: { gap: gapStyle }, children: Array.from({ length: lines }, (_, index) => (jsx("div", { className: cvaSkeletonLine(), "data-testid": dataTestId ? `${dataTestId}-${index}` : `skeleton-lines-${index}`, "data-type": "loading-skeleton-line", style: {
|
|
2301
|
-
width: getDimension(width, index),
|
|
2302
|
-
height: getDimension(height, index),
|
|
2302
|
+
width: getDimension({ dimension: width, index, direction: "width", maxWidth }),
|
|
2303
|
+
height: getDimension({ dimension: height, index, direction: "height" }),
|
|
2303
2304
|
} }, index))) }));
|
|
2304
2305
|
});
|
|
2305
|
-
const getDimension = (
|
|
2306
|
+
const getDimension = (params) => {
|
|
2307
|
+
const { dimension, index } = params;
|
|
2308
|
+
let value;
|
|
2306
2309
|
if (Array.isArray(dimension)) {
|
|
2307
|
-
const
|
|
2308
|
-
|
|
2310
|
+
const dimValue = dimension[index] ?? dimension[0] ?? "100%";
|
|
2311
|
+
value = typeof dimValue === "number" ? `${dimValue}px` : dimValue;
|
|
2309
2312
|
}
|
|
2310
|
-
|
|
2313
|
+
else {
|
|
2314
|
+
value = typeof dimension === "number" ? `${dimension}px` : dimension;
|
|
2315
|
+
}
|
|
2316
|
+
// For width values, wrap in min() to ensure max container width
|
|
2317
|
+
if (params.direction === "width") {
|
|
2318
|
+
return `min(${value}, ${params.maxWidth})`;
|
|
2319
|
+
}
|
|
2320
|
+
return value;
|
|
2311
2321
|
};
|
|
2312
2322
|
|
|
2313
2323
|
const cvaContainerStyles = cvaMerge([
|
|
@@ -2590,7 +2600,7 @@ const HorizontalOverflowScroller = ({ className, dataTestId, children, onScrollS
|
|
|
2590
2600
|
behavior: "smooth",
|
|
2591
2601
|
});
|
|
2592
2602
|
};
|
|
2593
|
-
return (jsxs(ZStack, { className: cvaHorizontalOverflowScrollerAndIndicatorsContainer({ className }), children: [jsx("div", { className: cvaHorizontalOverflowScroller(
|
|
2603
|
+
return (jsxs(ZStack, { className: cvaHorizontalOverflowScrollerAndIndicatorsContainer({ className }), children: [jsx("div", { className: cvaHorizontalOverflowScroller(), "data-testid": dataTestId, ref: containerRef, children: childrenArray.map((child, index) => (jsx(Fragment, { children: child }, index))) }), isScrollable && !isAtBeginning ? (jsx(OverflowIndicator, { dataTestId: `${dataTestId}-left-indicator`, direction: "left", onClickScroll: handleScrollLeft })) : null, isScrollable && !isAtEnd ? (jsx(OverflowIndicator, { dataTestId: `${dataTestId}-right-indicator`, direction: "right", onClickScroll: handleScrollRight })) : null] }));
|
|
2594
2604
|
};
|
|
2595
2605
|
|
|
2596
2606
|
const PADDING = 12;
|
|
@@ -2905,11 +2915,11 @@ const PopoverTrigger = function PopoverTrigger({ children, renderButton = false,
|
|
|
2905
2915
|
};
|
|
2906
2916
|
|
|
2907
2917
|
const cvaTooltipContainer = cvaMerge(["flex", "leading-5"]);
|
|
2908
|
-
const cvaTooltipIcon = cvaMerge(["flex", "h-max", "w-fit", "text-
|
|
2918
|
+
const cvaTooltipIcon = cvaMerge(["flex", "h-max", "w-fit", "text-neutral-300", "transition", "hover:cursor-pointer", "hover:text-neutral-400"], {
|
|
2909
2919
|
variants: {
|
|
2910
2920
|
color: {
|
|
2911
2921
|
light: "hover:text-white",
|
|
2912
|
-
dark: "hover:text-
|
|
2922
|
+
dark: "hover:text-neutral-400",
|
|
2913
2923
|
},
|
|
2914
2924
|
defaultVariants: {
|
|
2915
2925
|
color: "dark",
|
|
@@ -3040,7 +3050,7 @@ const cvaIndicatorPing = cvaMerge(["animate-ping-sm", "absolute", "inline-flex",
|
|
|
3040
3050
|
variants: {
|
|
3041
3051
|
color: {
|
|
3042
3052
|
primary: "bg-primary-600",
|
|
3043
|
-
secondary: "bg-
|
|
3053
|
+
secondary: "bg-neutral-600",
|
|
3044
3054
|
neutral: "bg-neutral-600",
|
|
3045
3055
|
info: "bg-info-600",
|
|
3046
3056
|
success: "bg-success-600",
|
|
@@ -3083,7 +3093,7 @@ const cvaIndicatorIconBackground = cvaMerge(["rounded-full", "items-center", "ju
|
|
|
3083
3093
|
variants: {
|
|
3084
3094
|
color: {
|
|
3085
3095
|
primary: "bg-primary-100 text-primary-600",
|
|
3086
|
-
secondary: "bg-
|
|
3096
|
+
secondary: "bg-neutral-100 text-neutral-600",
|
|
3087
3097
|
neutral: "bg-neutral-100 text-neutral-600",
|
|
3088
3098
|
info: "bg-info-100 text-info-600",
|
|
3089
3099
|
success: "bg-success-100 text-success-600",
|
|
@@ -3197,7 +3207,7 @@ const cvaKPIValueContainer = cvaMerge(["truncate", "whitespace-nowrap"], {
|
|
|
3197
3207
|
},
|
|
3198
3208
|
});
|
|
3199
3209
|
|
|
3200
|
-
const LoadingContent$1 = () => (jsx("div", { className: "flex h-11 flex-row items-center gap-3", "data-testid": "kpi-card-loading-content", children: jsx("div", { className: "w-full", children: jsx(SkeletonLines, { height: [14, 18], lines: 2,
|
|
3210
|
+
const LoadingContent$1 = () => (jsx("div", { className: "flex h-11 flex-row items-center gap-3", "data-testid": "kpi-card-loading-content", children: jsx("div", { className: "w-full", children: jsx(SkeletonLines, { gap: 3, height: [14, 18], lines: 2, width: [80, 60] }) }) }));
|
|
3201
3211
|
/**
|
|
3202
3212
|
* The KPI component is used to display KPIs.
|
|
3203
3213
|
*
|
|
@@ -3229,7 +3239,7 @@ const cvaKPICard = cvaMerge([
|
|
|
3229
3239
|
withTrends: ["min-h-[94px]"],
|
|
3230
3240
|
},
|
|
3231
3241
|
isClickable: {
|
|
3232
|
-
true: ["hover:bg-
|
|
3242
|
+
true: ["hover:bg-neutral-50", "component-card-border"],
|
|
3233
3243
|
false: [],
|
|
3234
3244
|
},
|
|
3235
3245
|
isActive: {
|
|
@@ -3559,7 +3569,7 @@ const cvaMenuList = cvaMerge([
|
|
|
3559
3569
|
"z-popover",
|
|
3560
3570
|
"bg-white",
|
|
3561
3571
|
"border",
|
|
3562
|
-
"border-
|
|
3572
|
+
"border-neutral-300",
|
|
3563
3573
|
"grid",
|
|
3564
3574
|
"min-w-[200px]",
|
|
3565
3575
|
"max-w-[300px]",
|
|
@@ -3572,7 +3582,7 @@ const cvaMenuList = cvaMerge([
|
|
|
3572
3582
|
},
|
|
3573
3583
|
},
|
|
3574
3584
|
});
|
|
3575
|
-
const cvaMenuListDivider = cvaMerge(["mx-[-4px]", "my-1", "min-h-px", "bg-
|
|
3585
|
+
const cvaMenuListDivider = cvaMerge(["mx-[-4px]", "my-1", "min-h-px", "bg-neutral-300"]);
|
|
3576
3586
|
const cvaMenuListMultiSelect = cvaMerge("hover:!bg-blue-200");
|
|
3577
3587
|
const cvaMenuListItem = cvaMerge("max-w-full");
|
|
3578
3588
|
|
|
@@ -3653,9 +3663,9 @@ const cvaMenuItemLabel = cvaMerge(["flex-grow", "truncate", "text-black", "font-
|
|
|
3653
3663
|
},
|
|
3654
3664
|
});
|
|
3655
3665
|
const cvaMenuItemPrefix = cvaMerge([
|
|
3656
|
-
"text-
|
|
3657
|
-
"hover:text-
|
|
3658
|
-
"focus:text-
|
|
3666
|
+
"text-neutral-400",
|
|
3667
|
+
"hover:text-neutral-500",
|
|
3668
|
+
"focus:text-neutral-500",
|
|
3659
3669
|
"h-min",
|
|
3660
3670
|
"leading-[0]",
|
|
3661
3671
|
"flex",
|
|
@@ -3663,7 +3673,7 @@ const cvaMenuItemPrefix = cvaMerge([
|
|
|
3663
3673
|
], {
|
|
3664
3674
|
variants: {
|
|
3665
3675
|
selected: {
|
|
3666
|
-
true: "text-
|
|
3676
|
+
true: "text-neutral-600",
|
|
3667
3677
|
false: "",
|
|
3668
3678
|
},
|
|
3669
3679
|
variant: {
|
|
@@ -3671,7 +3681,7 @@ const cvaMenuItemPrefix = cvaMerge([
|
|
|
3671
3681
|
danger: ["text-danger-600", "hover:text-danger-700", "focus:bg-danger-200", "focus:text-danger-800"],
|
|
3672
3682
|
},
|
|
3673
3683
|
disabled: {
|
|
3674
|
-
true: "text-
|
|
3684
|
+
true: "text-neutral opacity-50",
|
|
3675
3685
|
false: "",
|
|
3676
3686
|
},
|
|
3677
3687
|
},
|
|
@@ -3680,10 +3690,10 @@ const cvaMenuItemPrefix = cvaMerge([
|
|
|
3680
3690
|
disabled: false,
|
|
3681
3691
|
},
|
|
3682
3692
|
});
|
|
3683
|
-
const cvaMenuItemSuffix = cvaMerge(["text-
|
|
3693
|
+
const cvaMenuItemSuffix = cvaMerge(["text-neutral-400", "text-sm", "flex", "items-center"], {
|
|
3684
3694
|
variants: {
|
|
3685
3695
|
selected: {
|
|
3686
|
-
true: "text-
|
|
3696
|
+
true: "text-neutral-600",
|
|
3687
3697
|
false: "",
|
|
3688
3698
|
},
|
|
3689
3699
|
variant: {
|
|
@@ -3691,7 +3701,7 @@ const cvaMenuItemSuffix = cvaMerge(["text-secondary-400", "text-sm", "flex", "it
|
|
|
3691
3701
|
danger: ["text-danger-600", "hover:text-danger-700", "focus:bg-danger-200", "focus:text-danger-800"],
|
|
3692
3702
|
},
|
|
3693
3703
|
disabled: {
|
|
3694
|
-
true: "text-
|
|
3704
|
+
true: "text-neutral opacity-50",
|
|
3695
3705
|
false: "",
|
|
3696
3706
|
},
|
|
3697
3707
|
},
|
|
@@ -3730,7 +3740,7 @@ const MenuItem = ({ className, dataTestId, label, children, selected = false, fo
|
|
|
3730
3740
|
e.stopPropagation();
|
|
3731
3741
|
}
|
|
3732
3742
|
onClick?.(e);
|
|
3733
|
-
}, onKeyDown: handleKeyDown, role: "menuitem", tabIndex: disabled ? -1 : (tabIndex ?? 0), children: [prefix !== null && prefix !== undefined ? (jsx("div", { className: cvaMenuItemPrefix({ selected, variant, disabled }), "data-testid": dataTestId ? `${dataTestId}-prefix` : "menu-item-prefix", children: prefix })) : null, children !== null && children !== undefined && typeof children !== "string" ? (children) : (jsxs("div", { className: cvaMenuItemLabel({ variant, disabled }), "data-testid": dataTestId ? `${dataTestId}-label` : "menu-item-label", children: [optionPrefix !== null && optionPrefix !== undefined ? optionPrefix : null, children ?? label, optionLabelDescription !== undefined && optionLabelDescription !== "" ? (jsxs("span", { className: "text-
|
|
3743
|
+
}, onKeyDown: handleKeyDown, role: "menuitem", tabIndex: disabled ? -1 : (tabIndex ?? 0), children: [prefix !== null && prefix !== undefined ? (jsx("div", { className: cvaMenuItemPrefix({ selected, variant, disabled }), "data-testid": dataTestId ? `${dataTestId}-prefix` : "menu-item-prefix", children: prefix })) : null, children !== null && children !== undefined && typeof children !== "string" ? (children) : (jsxs("div", { className: cvaMenuItemLabel({ variant, disabled }), "data-testid": dataTestId ? `${dataTestId}-label` : "menu-item-label", children: [optionPrefix !== null && optionPrefix !== undefined ? optionPrefix : null, children ?? label, optionLabelDescription !== undefined && optionLabelDescription !== "" ? (jsxs("span", { className: "ml-1 text-neutral-400", children: ["(", optionLabelDescription, ")"] })) : null] })), suffix !== null && suffix !== undefined ? (jsx("div", { className: cvaMenuItemSuffix({ selected, variant, disabled }), "data-testid": dataTestId ? `${dataTestId}-suffix` : "menu-item-suffix", children: suffix })) : null] }));
|
|
3734
3744
|
};
|
|
3735
3745
|
|
|
3736
3746
|
/**
|
|
@@ -3796,7 +3806,7 @@ const cvaMoreMenu = cvaMerge(["p-0"]);
|
|
|
3796
3806
|
*/
|
|
3797
3807
|
const MoreMenu = ({ className, dataTestId, popoverProps, iconProps = {
|
|
3798
3808
|
size: "medium",
|
|
3799
|
-
className: "text-
|
|
3809
|
+
className: "text-neutral-400",
|
|
3800
3810
|
}, iconButtonProps = {
|
|
3801
3811
|
size: "medium",
|
|
3802
3812
|
circular: false,
|
|
@@ -3900,7 +3910,7 @@ const PageContent = ({ className, children, dataTestId, layout }) => {
|
|
|
3900
3910
|
return (jsx("div", { className: cvaPageContent({ className, layout }), "data-testid": dataTestId ? dataTestId : "page-content", children: children }));
|
|
3901
3911
|
};
|
|
3902
3912
|
|
|
3903
|
-
const LoadingContent = () => (jsx("div", { className: "flex flex-row items-center gap-3", "data-testid": "kpi-card-loading-content", children: jsx("div", { className: "w-full", children: jsx(SkeletonLines, { height: [16, 25], lines: 2,
|
|
3913
|
+
const LoadingContent = () => (jsx("div", { className: "flex flex-row items-center gap-3", "data-testid": "kpi-card-loading-content", children: jsx("div", { className: "w-full", children: jsx(SkeletonLines, { gap: 3, height: [16, 25], lines: 2, width: [50, 40] }) }) }));
|
|
3904
3914
|
/**
|
|
3905
3915
|
* The PageHeaderKpiMetrics component is used to render the KPI metrics in the PageHeader component.
|
|
3906
3916
|
*
|
|
@@ -3915,7 +3925,7 @@ const PageHeaderKpiMetrics = ({ kpiMetrics }) => {
|
|
|
3915
3925
|
if (kpi.loading === true) {
|
|
3916
3926
|
return jsx(LoadingContent, {}, `${kpi}-${index}`);
|
|
3917
3927
|
}
|
|
3918
|
-
return (jsxs("div", { className: "flex flex-col text-nowrap text-left", children: [jsx("span", { className: "text-xs text-
|
|
3928
|
+
return (jsxs("div", { className: "flex flex-col text-nowrap text-left", children: [jsx("span", { className: "text-xs text-neutral-500", children: kpi.header }), jsxs("div", { className: "flex flex-row items-center gap-1", children: [jsx("span", { className: "text-lg font-medium text-neutral-900", children: kpi.value }), kpi.unit ? jsx("span", { className: "text-xs text-neutral-900", children: kpi.unit }) : null] })] }, `${kpi}-${index}`));
|
|
3919
3929
|
}) }));
|
|
3920
3930
|
};
|
|
3921
3931
|
|
|
@@ -3981,13 +3991,13 @@ const PageHeaderSecondaryActions = ({ actions, hasPrimaryAction = false, }) => {
|
|
|
3981
3991
|
const cvaPageHeaderContainer = cvaMerge(["bg-white", "tu-page-header"], {
|
|
3982
3992
|
variants: {
|
|
3983
3993
|
withBorder: {
|
|
3984
|
-
true: ["border-b", "border-b-
|
|
3994
|
+
true: ["border-b", "border-b-neutral-200"],
|
|
3985
3995
|
false: "",
|
|
3986
3996
|
},
|
|
3987
3997
|
},
|
|
3988
3998
|
});
|
|
3989
3999
|
const cvaPageHeader = cvaMerge(["box-border", "py-4", "px-6", "flex", "items-center", "gap-y-1"]);
|
|
3990
|
-
const cvaPageHeaderHeading = cvaMerge(["text-
|
|
4000
|
+
const cvaPageHeaderHeading = cvaMerge(["text-neutral-900", "text-xl", "font-semibold", "truncate"]);
|
|
3991
4001
|
|
|
3992
4002
|
/**
|
|
3993
4003
|
* The PageHeaderTitle component is used to display the title of the page header.
|
|
@@ -4309,7 +4319,7 @@ const cvaTabList = cvaMerge([
|
|
|
4309
4319
|
"flex",
|
|
4310
4320
|
"flex-row",
|
|
4311
4321
|
"border-b",
|
|
4312
|
-
"border-b-
|
|
4322
|
+
"border-b-neutral-200",
|
|
4313
4323
|
"overflow-auto",
|
|
4314
4324
|
"no-scrollbar",
|
|
4315
4325
|
]);
|
|
@@ -4332,13 +4342,13 @@ const cvaTab = cvaMerge([
|
|
|
4332
4342
|
"hover:border-b-transparent",
|
|
4333
4343
|
"data-[state=active]:border-b-primary-600",
|
|
4334
4344
|
"data-[state=active]:font-semibold",
|
|
4335
|
-
"data-[state=active]:text-
|
|
4345
|
+
"data-[state=active]:text-neutral-900",
|
|
4336
4346
|
"data-[state=inactive]:font-medium",
|
|
4337
|
-
"data-[state=inactive]:text-
|
|
4338
|
-
"data-[state=inactive]:hover:text-
|
|
4347
|
+
"data-[state=inactive]:text-neutral-700",
|
|
4348
|
+
"data-[state=inactive]:hover:text-neutral-900",
|
|
4339
4349
|
"disabled:cursor-not-allowed",
|
|
4340
|
-
"data-[state=active]disabled:text-
|
|
4341
|
-
"data-[state=inactive]:disabled:text-
|
|
4350
|
+
"data-[state=active]disabled:text-neutral-400",
|
|
4351
|
+
"data-[state=inactive]:disabled:text-neutral-400",
|
|
4342
4352
|
], {
|
|
4343
4353
|
variants: {
|
|
4344
4354
|
isFullWidth: {
|
|
@@ -4377,12 +4387,13 @@ const TabContent = ({ className, dataTestId, children, ...rest }) => {
|
|
|
4377
4387
|
/**
|
|
4378
4388
|
* Wrapper for radix tab list component.
|
|
4379
4389
|
*/
|
|
4380
|
-
const TabList = ({ className, dataTestId, children, ...rest }) => {
|
|
4390
|
+
const TabList = ({ className, dataTestId, children, autoScrollToActive = true, ...rest }) => {
|
|
4381
4391
|
const listRef = useRef(null);
|
|
4382
4392
|
useEffect(() => {
|
|
4383
4393
|
const element = listRef.current;
|
|
4384
|
-
if (!element)
|
|
4394
|
+
if (!element) {
|
|
4385
4395
|
return;
|
|
4396
|
+
}
|
|
4386
4397
|
const handleWheel = (event) => {
|
|
4387
4398
|
const canScrollHorizontally = element.scrollWidth > element.clientWidth;
|
|
4388
4399
|
if (canScrollHorizontally) {
|
|
@@ -4398,6 +4409,24 @@ const TabList = ({ className, dataTestId, children, ...rest }) => {
|
|
|
4398
4409
|
element.removeEventListener("wheel", handleWheel);
|
|
4399
4410
|
};
|
|
4400
4411
|
}, []);
|
|
4412
|
+
// Auto-scroll active tab into view when enabled
|
|
4413
|
+
useLayoutEffect(() => {
|
|
4414
|
+
if (!autoScrollToActive) {
|
|
4415
|
+
return;
|
|
4416
|
+
}
|
|
4417
|
+
const element = listRef.current;
|
|
4418
|
+
if (!element)
|
|
4419
|
+
return;
|
|
4420
|
+
// Find the active tab using a radix UI build in selector
|
|
4421
|
+
const activeTab = element.querySelector('[aria-selected="true"]');
|
|
4422
|
+
if (activeTab && typeof activeTab.scrollIntoView === "function") {
|
|
4423
|
+
activeTab.scrollIntoView({
|
|
4424
|
+
behavior: "instant",
|
|
4425
|
+
block: "nearest",
|
|
4426
|
+
inline: "center",
|
|
4427
|
+
});
|
|
4428
|
+
}
|
|
4429
|
+
}, [autoScrollToActive]);
|
|
4401
4430
|
return (jsx(List$1, { className: cvaTabList({ className }), "data-testid": dataTestId, ref: listRef, ...rest, children: children }));
|
|
4402
4431
|
};
|
|
4403
4432
|
|
|
@@ -4582,7 +4611,7 @@ const cvaValueBar = cvaMerge([
|
|
|
4582
4611
|
"w-full",
|
|
4583
4612
|
"overflow-hidden",
|
|
4584
4613
|
"rounded",
|
|
4585
|
-
"bg-
|
|
4614
|
+
"bg-neutral-100",
|
|
4586
4615
|
"appearance-none",
|
|
4587
4616
|
"[&::-webkit-progress-bar]:bg-transparent",
|
|
4588
4617
|
"[&::-webkit-progress-value]:bg-current",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/react-components",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.18",
|
|
4
4
|
"repository": "https://github.com/Trackunit/manager",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"engines": {
|
|
@@ -16,12 +16,12 @@
|
|
|
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-table-pagination": "1.7.
|
|
24
|
-
"@trackunit/react-test-setup": "1.4.
|
|
19
|
+
"@trackunit/ui-design-tokens": "1.7.10",
|
|
20
|
+
"@trackunit/css-class-variance-utilities": "1.7.10",
|
|
21
|
+
"@trackunit/shared-utils": "1.9.10",
|
|
22
|
+
"@trackunit/ui-icons": "1.7.12",
|
|
23
|
+
"@trackunit/react-table-pagination": "1.7.10",
|
|
24
|
+
"@trackunit/react-test-setup": "1.4.10",
|
|
25
25
|
"@tanstack/react-router": "1.114.29",
|
|
26
26
|
"es-toolkit": "^1.39.10"
|
|
27
27
|
},
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { CommonProps } from "../../common/CommonProps";
|
|
2
|
-
type
|
|
2
|
+
type SizeUnit = "px" | "%" | "rem" | "em";
|
|
3
|
+
type SizeValue = `${number}${SizeUnit}` | "inherit" | (string & {});
|
|
4
|
+
type GapUnit = "px" | "rem" | "em";
|
|
5
|
+
type GapValue = `${number}${GapUnit}` | "inherit";
|
|
6
|
+
type SkeletonDimension = number | SizeValue | Array<number | SizeValue>;
|
|
3
7
|
export interface SkeletonLinesProps extends CommonProps {
|
|
4
8
|
/**
|
|
5
9
|
* The number of lines to display.
|
|
@@ -11,15 +15,22 @@ export interface SkeletonLinesProps extends CommonProps {
|
|
|
11
15
|
height?: SkeletonDimension;
|
|
12
16
|
/**
|
|
13
17
|
* The width of each line. Can be a number, string, or an array of numbers/strings.
|
|
18
|
+
* All width values are automatically wrapped in min(width, maxWidth) to prevent overflow.
|
|
14
19
|
*/
|
|
15
20
|
width?: SkeletonDimension;
|
|
16
21
|
/**
|
|
17
|
-
* Gap between skeleton lines
|
|
22
|
+
* Gap between skeleton lines.
|
|
18
23
|
*/
|
|
19
|
-
|
|
24
|
+
gap?: number | GapValue;
|
|
25
|
+
/**
|
|
26
|
+
* Maximum width percentage to constrain skeleton lines. Defaults to "100%".
|
|
27
|
+
* Used in CSS min() function: min(width, maxWidth). Examples: "80%", "120%", "50%"
|
|
28
|
+
*/
|
|
29
|
+
maxWidth?: `${number}%`;
|
|
20
30
|
}
|
|
21
31
|
/**
|
|
22
32
|
* Display placeholder lines before the data gets loaded to reduce load-time frustration.
|
|
33
|
+
* All width values are automatically constrained using CSS min() function to prevent overflow.
|
|
23
34
|
*/
|
|
24
35
|
export declare const SkeletonLines: import("react").NamedExoticComponent<SkeletonLinesProps>;
|
|
25
36
|
export {};
|
|
@@ -14,8 +14,14 @@ export interface TabListProps extends TabsListProps {
|
|
|
14
14
|
* An ID that can be used in tests to locate the component.
|
|
15
15
|
*/
|
|
16
16
|
dataTestId?: string;
|
|
17
|
+
/**
|
|
18
|
+
* If set to true, automatically scrolls the active tab into view when changed.
|
|
19
|
+
*
|
|
20
|
+
* @default true
|
|
21
|
+
*/
|
|
22
|
+
autoScrollToActive?: boolean;
|
|
17
23
|
}
|
|
18
24
|
/**
|
|
19
25
|
* Wrapper for radix tab list component.
|
|
20
26
|
*/
|
|
21
|
-
export declare const TabList: ({ className, dataTestId, children, ...rest }: TabListProps) => ReactElement;
|
|
27
|
+
export declare const TabList: ({ className, dataTestId, children, autoScrollToActive, ...rest }: TabListProps) => ReactElement;
|