@trackunit/react-components 1.9.15 → 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-secondary-400",
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-secondary-100", "text-secondary-700"],
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: "outline-secondary-300 border-none outline outline-1 -outline-offset-1",
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-slate-900/25", "border-b-slate-900/50"],
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-slate-900/50"],
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-secondary-300", name: "Slash", size: "small" })] }, index));
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-secondary-200", "justify-end", "flex-row"], {
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-secondary-200"], {
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-secondary-300",
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-secondary-100",
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-secondary-200", "border-b", "border-solid"], false: "" },
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-gray-600", "font-medium"], {
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%", margin = 10, className, dataTestId }) => {
2301
- const gapStyle = typeof margin === "number" ? `${margin}px` : margin;
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 = (dimension, index) => {
2308
+ const getDimension = (params) => {
2309
+ const { dimension, index } = params;
2310
+ let value;
2308
2311
  if (Array.isArray(dimension)) {
2309
- const value = dimension[index] ?? dimension[0] ?? "100%";
2310
- return typeof value === "number" ? `${value}px` : value;
2312
+ const dimValue = dimension[index] ?? dimension[0] ?? "100%";
2313
+ value = typeof dimValue === "number" ? `${dimValue}px` : dimValue;
2311
2314
  }
2312
- return typeof dimension === "number" ? `${dimension}px` : dimension;
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([
@@ -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-slate-300", "transition", "hover:cursor-pointer", "hover:text-slate-400"], {
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-slate-400",
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-secondary-600",
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-secondary-100 text-secondary-600",
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, margin: "3", width: [80, 60] }) }) }));
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-slate-50", "component-card-border"],
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-slate-300",
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-slate-300"]);
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-secondary-400",
3659
- "hover:text-secondary-500",
3660
- "focus:text-secondary-500",
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-secondary-600",
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-secondary opacity-50",
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-secondary-400", "text-sm", "flex", "items-center"], {
3695
+ const cvaMenuItemSuffix = cssClassVarianceUtilities.cvaMerge(["text-neutral-400", "text-sm", "flex", "items-center"], {
3686
3696
  variants: {
3687
3697
  selected: {
3688
- true: "text-secondary-600",
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-secondary opacity-50",
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-secondary-400 ml-1", 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] }));
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-secondary-400",
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, margin: "3", width: [50, 40] }) }) }));
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-slate-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-slate-900", children: kpi.value }), kpi.unit ? jsxRuntime.jsx("span", { className: "text-xs text-slate-900", children: kpi.unit }) : null] })] }, `${kpi}-${index}`));
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-secondary-200"],
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-slate-900", "text-xl", "font-semibold", "truncate"]);
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-secondary-200",
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-secondary-900",
4347
+ "data-[state=active]:text-neutral-900",
4338
4348
  "data-[state=inactive]:font-medium",
4339
- "data-[state=inactive]:text-secondary-700",
4340
- "data-[state=inactive]:hover:text-secondary-900",
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-secondary-400",
4343
- "data-[state=inactive]:disabled:text-secondary-400",
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-slate-100",
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-secondary-400",
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-secondary-100", "text-secondary-700"],
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: "outline-secondary-300 border-none outline outline-1 -outline-offset-1",
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-slate-900/25", "border-b-slate-900/50"],
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-slate-900/50"],
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-secondary-300", name: "Slash", size: "small" })] }, index));
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-secondary-200", "justify-end", "flex-row"], {
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-secondary-200"], {
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-secondary-300",
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-secondary-100",
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-secondary-200", "border-b", "border-solid"], false: "" },
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-gray-600", "font-medium"], {
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%", margin = 10, className, dataTestId }) => {
2299
- const gapStyle = typeof margin === "number" ? `${margin}px` : margin;
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 = (dimension, index) => {
2306
+ const getDimension = (params) => {
2307
+ const { dimension, index } = params;
2308
+ let value;
2306
2309
  if (Array.isArray(dimension)) {
2307
- const value = dimension[index] ?? dimension[0] ?? "100%";
2308
- return typeof value === "number" ? `${value}px` : value;
2310
+ const dimValue = dimension[index] ?? dimension[0] ?? "100%";
2311
+ value = typeof dimValue === "number" ? `${dimValue}px` : dimValue;
2309
2312
  }
2310
- return typeof dimension === "number" ? `${dimension}px` : dimension;
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([
@@ -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-slate-300", "transition", "hover:cursor-pointer", "hover:text-slate-400"], {
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-slate-400",
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-secondary-600",
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-secondary-100 text-secondary-600",
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, margin: "3", width: [80, 60] }) }) }));
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-slate-50", "component-card-border"],
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-slate-300",
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-slate-300"]);
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-secondary-400",
3657
- "hover:text-secondary-500",
3658
- "focus:text-secondary-500",
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-secondary-600",
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-secondary opacity-50",
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-secondary-400", "text-sm", "flex", "items-center"], {
3693
+ const cvaMenuItemSuffix = cvaMerge(["text-neutral-400", "text-sm", "flex", "items-center"], {
3684
3694
  variants: {
3685
3695
  selected: {
3686
- true: "text-secondary-600",
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-secondary opacity-50",
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-secondary-400 ml-1", 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] }));
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-secondary-400",
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, margin: "3", width: [50, 40] }) }) }));
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-slate-500", children: kpi.header }), jsxs("div", { className: "flex flex-row items-center gap-1", children: [jsx("span", { className: "text-lg font-medium text-slate-900", children: kpi.value }), kpi.unit ? jsx("span", { className: "text-xs text-slate-900", children: kpi.unit }) : null] })] }, `${kpi}-${index}`));
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-secondary-200"],
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-slate-900", "text-xl", "font-semibold", "truncate"]);
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-secondary-200",
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-secondary-900",
4345
+ "data-[state=active]:text-neutral-900",
4336
4346
  "data-[state=inactive]:font-medium",
4337
- "data-[state=inactive]:text-secondary-700",
4338
- "data-[state=inactive]:hover:text-secondary-900",
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-secondary-400",
4341
- "data-[state=inactive]:disabled:text-secondary-400",
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-slate-100",
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.15",
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.8",
20
- "@trackunit/css-class-variance-utilities": "1.7.8",
21
- "@trackunit/shared-utils": "1.9.8",
22
- "@trackunit/ui-icons": "1.7.10",
23
- "@trackunit/react-table-pagination": "1.7.8",
24
- "@trackunit/react-test-setup": "1.4.8",
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 SkeletonDimension = number | string | Array<number | string>;
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 in pixels.
22
+ * Gap between skeleton lines.
18
23
  */
19
- margin?: number | string;
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 {};
@@ -9,4 +9,4 @@
9
9
  export declare const getResponsiveRandomWidthPercentage: ({ min, max }: {
10
10
  min: number;
11
11
  max: number;
12
- }) => string;
12
+ }) => `${number}%`;
@@ -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;