@trackunit/react-components 2.13.23-alpha-12adfed37e0.0 → 2.13.24

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
@@ -81,6 +81,7 @@ const cvaIcon = cssClassVarianceUtilities.cva({
81
81
  variants: {
82
82
  color: {
83
83
  primary: "text-primary-600",
84
+ ai: "text-ai",
84
85
  neutral: "text-neutral-400",
85
86
  info: "text-info-600",
86
87
  success: "text-success-600",
@@ -142,6 +143,7 @@ const cvaIcon = cssClassVarianceUtilities.cva({
142
143
  const iconPalette = {
143
144
  ...uiDesignTokens.intentPalette,
144
145
  ...uiDesignTokens.generalPalette,
146
+ ...uiDesignTokens.aiPalette,
145
147
  ...uiDesignTokens.criticalityPalette,
146
148
  ...uiDesignTokens.activityPalette,
147
149
  ...uiDesignTokens.utilizationPalette,
@@ -1833,6 +1835,15 @@ const cvaButtonPrefixSuffix = cssClassVarianceUtilities.cva({
1833
1835
  const cvaIconButton = cssClassVarianceUtilities.cva({
1834
1836
  base: [],
1835
1837
  variants: {
1838
+ ai: {
1839
+ true: [
1840
+ "bg-ai",
1841
+ "hover:bg-[color-mix(in_srgb,var(--color-ai),black_10%)]",
1842
+ "active:bg-[color-mix(in_srgb,var(--color-ai),black_20%)]",
1843
+ "focus:bg-[color-mix(in_srgb,var(--color-ai),black_20%)]",
1844
+ ],
1845
+ false: [],
1846
+ },
1836
1847
  size: {
1837
1848
  /**
1838
1849
  * Sized to match a single text line (20px) so the button fits inside
@@ -2604,9 +2615,9 @@ const toButtonSize = (size) => (size === "extraSmall" ? "small" : size);
2604
2615
  * @param {IconButtonProps} props - The props for the IconButton component
2605
2616
  * @returns {ReactElement} IconButton component
2606
2617
  */
2607
- const IconButton = ({ icon, size = "medium", square = true, loading = false, disabled = false, className, title, ariaLabel, "data-testid": dataTestId, ref, ...rest }) => {
2618
+ const IconButton = ({ icon, variant = "primary", size = "medium", square = true, loading = false, disabled = false, className, title, ariaLabel, "data-testid": dataTestId, ref, ...rest }) => {
2608
2619
  const accessibleLabel = ariaLabel ?? title;
2609
- return (jsxRuntime.jsx(Tooltip, { "data-testid": "iconButton-tooltip", delayed: true, disabled: !title || disabled || loading, interactable: false, label: title, children: jsxRuntime.jsx(Button, { ...rest, ariaLabel: accessibleLabel, className: cvaIconButton({ size: size, className }), "data-testid": dataTestId ? dataTestId : undefined, disabled: disabled || loading, loading: loading, prefix: !loading ? react.cloneElement(icon, { ariaHidden: true }) : undefined, ref: ref, size: toButtonSize(size), square: square, title: undefined }) }));
2620
+ return (jsxRuntime.jsx(Tooltip, { "data-testid": "iconButton-tooltip", delayed: true, disabled: !title || disabled || loading, interactable: false, label: title, children: jsxRuntime.jsx(Button, { ...rest, ariaLabel: accessibleLabel, className: cvaIconButton({ size: size, ai: variant === "ai", className }), "data-testid": dataTestId ? dataTestId : undefined, disabled: disabled || loading, loading: loading, prefix: !loading ? react.cloneElement(icon, { ariaHidden: true }) : undefined, ref: ref, size: toButtonSize(size), square: square, title: undefined, variant: variant === "ai" ? "primary" : variant }) }));
2610
2621
  };
2611
2622
  IconButton.displayName = "IconButton";
2612
2623
 
@@ -5396,6 +5407,7 @@ const cvaHighlight = cssClassVarianceUtilities.cva({
5396
5407
  "inline-flex",
5397
5408
  "justify-center",
5398
5409
  "items-center",
5410
+ "gap-1",
5399
5411
  "rounded",
5400
5412
  "py-0.5",
5401
5413
  "px-1",
@@ -5461,11 +5473,19 @@ const cvaHighlightText = cssClassVarianceUtilities.cva({ base: ["truncate"] });
5461
5473
  * </div>
5462
5474
  * );
5463
5475
  * ```
5476
+ * @example Highlight with a leading icon
5477
+ * ```tsx
5478
+ * import { Highlight } from "@trackunit/react-components";
5479
+ *
5480
+ * const LastSeen = () => (
5481
+ * <Highlight color="danger" iconName="MapPin">3 days ago</Highlight>
5482
+ * );
5483
+ * ```
5464
5484
  * @param {HighlightProps} props - The props for the Highlight component
5465
5485
  * @returns {ReactElement} Highlight component
5466
5486
  */
5467
- const Highlight = ({ className, "data-testid": dataTestId, children, size = "small", color = "warning", style, ref, }) => {
5468
- return (jsxRuntime.jsx("div", { className: cvaHighlight({ className, size, color }), "data-testid": dataTestId, ref: ref, style: style, children: jsxRuntime.jsx("span", { className: cvaHighlightText(), children: children }) }));
5487
+ const Highlight = ({ className, "data-testid": dataTestId, children, size = "small", color = "warning", iconName = undefined, style, ref, }) => {
5488
+ return (jsxRuntime.jsxs("div", { className: cvaHighlight({ className, size, color }), "data-testid": dataTestId, ref: ref, style: style, children: [iconName !== undefined ? jsxRuntime.jsx(Icon, { ariaHidden: true, name: iconName, size: "small" }) : null, children !== undefined && children !== null ? jsxRuntime.jsx("span", { className: cvaHighlightText(), children: children }) : null] }));
5469
5489
  };
5470
5490
  Highlight.displayName = "Highlight";
5471
5491
 
package/index.esm.js CHANGED
@@ -4,7 +4,7 @@ import { twMerge } from 'tailwind-merge';
4
4
  import { objectKeys, uuidv4, parseTailwindArbitraryValue, objectEntries, nonNullable, objectValues, validateState, writeToStorage, readFromStorage, storageSerializer, filterByMultiple } from '@trackunit/shared-utils';
5
5
  export { storageSerializer } from '@trackunit/shared-utils';
6
6
  import { useRef, useMemo, useEffect, useSyncExternalStore, useState, useLayoutEffect, createContext, useContext, isValidElement, cloneElement, createElement, useCallback, Fragment as Fragment$1, memo, forwardRef, useId, useReducer, Children } from 'react';
7
- import { rentalStatusPalette, sitesPalette, utilizationPalette, activityPalette, criticalityPalette, generalPalette, intentPalette, themeScreenSizeAsNumber, themeContainerSize, color } from '@trackunit/ui-design-tokens';
7
+ import { rentalStatusPalette, sitesPalette, utilizationPalette, activityPalette, criticalityPalette, aiPalette, generalPalette, intentPalette, themeScreenSizeAsNumber, themeContainerSize, color } from '@trackunit/ui-design-tokens';
8
8
  import { iconNames } from '@trackunit/ui-icons';
9
9
  import IconSpriteMicro from '@trackunit/ui-icons/icons-sprite-micro.svg';
10
10
  import IconSpriteMini from '@trackunit/ui-icons/icons-sprite-mini.svg';
@@ -80,6 +80,7 @@ const cvaIcon = cva({
80
80
  variants: {
81
81
  color: {
82
82
  primary: "text-primary-600",
83
+ ai: "text-ai",
83
84
  neutral: "text-neutral-400",
84
85
  info: "text-info-600",
85
86
  success: "text-success-600",
@@ -141,6 +142,7 @@ const cvaIcon = cva({
141
142
  const iconPalette = {
142
143
  ...intentPalette,
143
144
  ...generalPalette,
145
+ ...aiPalette,
144
146
  ...criticalityPalette,
145
147
  ...activityPalette,
146
148
  ...utilizationPalette,
@@ -1832,6 +1834,15 @@ const cvaButtonPrefixSuffix = cva({
1832
1834
  const cvaIconButton = cva({
1833
1835
  base: [],
1834
1836
  variants: {
1837
+ ai: {
1838
+ true: [
1839
+ "bg-ai",
1840
+ "hover:bg-[color-mix(in_srgb,var(--color-ai),black_10%)]",
1841
+ "active:bg-[color-mix(in_srgb,var(--color-ai),black_20%)]",
1842
+ "focus:bg-[color-mix(in_srgb,var(--color-ai),black_20%)]",
1843
+ ],
1844
+ false: [],
1845
+ },
1835
1846
  size: {
1836
1847
  /**
1837
1848
  * Sized to match a single text line (20px) so the button fits inside
@@ -2603,9 +2614,9 @@ const toButtonSize = (size) => (size === "extraSmall" ? "small" : size);
2603
2614
  * @param {IconButtonProps} props - The props for the IconButton component
2604
2615
  * @returns {ReactElement} IconButton component
2605
2616
  */
2606
- const IconButton = ({ icon, size = "medium", square = true, loading = false, disabled = false, className, title, ariaLabel, "data-testid": dataTestId, ref, ...rest }) => {
2617
+ const IconButton = ({ icon, variant = "primary", size = "medium", square = true, loading = false, disabled = false, className, title, ariaLabel, "data-testid": dataTestId, ref, ...rest }) => {
2607
2618
  const accessibleLabel = ariaLabel ?? title;
2608
- return (jsx(Tooltip, { "data-testid": "iconButton-tooltip", delayed: true, disabled: !title || disabled || loading, interactable: false, label: title, children: jsx(Button, { ...rest, ariaLabel: accessibleLabel, className: cvaIconButton({ size: size, className }), "data-testid": dataTestId ? dataTestId : undefined, disabled: disabled || loading, loading: loading, prefix: !loading ? cloneElement(icon, { ariaHidden: true }) : undefined, ref: ref, size: toButtonSize(size), square: square, title: undefined }) }));
2619
+ return (jsx(Tooltip, { "data-testid": "iconButton-tooltip", delayed: true, disabled: !title || disabled || loading, interactable: false, label: title, children: jsx(Button, { ...rest, ariaLabel: accessibleLabel, className: cvaIconButton({ size: size, ai: variant === "ai", className }), "data-testid": dataTestId ? dataTestId : undefined, disabled: disabled || loading, loading: loading, prefix: !loading ? cloneElement(icon, { ariaHidden: true }) : undefined, ref: ref, size: toButtonSize(size), square: square, title: undefined, variant: variant === "ai" ? "primary" : variant }) }));
2609
2620
  };
2610
2621
  IconButton.displayName = "IconButton";
2611
2622
 
@@ -5395,6 +5406,7 @@ const cvaHighlight = cva({
5395
5406
  "inline-flex",
5396
5407
  "justify-center",
5397
5408
  "items-center",
5409
+ "gap-1",
5398
5410
  "rounded",
5399
5411
  "py-0.5",
5400
5412
  "px-1",
@@ -5460,11 +5472,19 @@ const cvaHighlightText = cva({ base: ["truncate"] });
5460
5472
  * </div>
5461
5473
  * );
5462
5474
  * ```
5475
+ * @example Highlight with a leading icon
5476
+ * ```tsx
5477
+ * import { Highlight } from "@trackunit/react-components";
5478
+ *
5479
+ * const LastSeen = () => (
5480
+ * <Highlight color="danger" iconName="MapPin">3 days ago</Highlight>
5481
+ * );
5482
+ * ```
5463
5483
  * @param {HighlightProps} props - The props for the Highlight component
5464
5484
  * @returns {ReactElement} Highlight component
5465
5485
  */
5466
- const Highlight = ({ className, "data-testid": dataTestId, children, size = "small", color = "warning", style, ref, }) => {
5467
- return (jsx("div", { className: cvaHighlight({ className, size, color }), "data-testid": dataTestId, ref: ref, style: style, children: jsx("span", { className: cvaHighlightText(), children: children }) }));
5486
+ const Highlight = ({ className, "data-testid": dataTestId, children, size = "small", color = "warning", iconName = undefined, style, ref, }) => {
5487
+ return (jsxs("div", { className: cvaHighlight({ className, size, color }), "data-testid": dataTestId, ref: ref, style: style, children: [iconName !== undefined ? jsx(Icon, { ariaHidden: true, name: iconName, size: "small" }) : null, children !== undefined && children !== null ? jsx("span", { className: cvaHighlightText(), children: children }) : null] }));
5468
5488
  };
5469
5489
  Highlight.displayName = "Highlight";
5470
5490
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-components",
3
- "version": "2.13.23-alpha-12adfed37e0.0",
3
+ "version": "2.13.24",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "migrations": "./migrations.json",
@@ -14,16 +14,16 @@
14
14
  "@floating-ui/react": "^0.26.25",
15
15
  "string-ts": "^2.0.0",
16
16
  "tailwind-merge": "^2.0.0",
17
- "@trackunit/ui-design-tokens": "1.15.33-alpha-12adfed37e0.0",
18
- "@trackunit/css-class-variance-utilities": "2.0.14-alpha-12adfed37e0.0",
19
- "@trackunit/shared-utils": "1.16.49-alpha-12adfed37e0.0",
20
- "@trackunit/ui-icons": "1.14.42-alpha-12adfed37e0.0",
17
+ "@trackunit/ui-design-tokens": "1.15.34",
18
+ "@trackunit/css-class-variance-utilities": "2.0.14",
19
+ "@trackunit/shared-utils": "1.16.49",
20
+ "@trackunit/ui-icons": "1.14.43",
21
21
  "es-toolkit": "^1.39.10",
22
22
  "@tanstack/react-virtual": "^3.14.3",
23
23
  "dequal": "^2.0.3",
24
24
  "fflate": "^0.8.2",
25
25
  "zod": "^3.25.76",
26
- "@trackunit/i18n-library-translation": "2.4.62-alpha-12adfed37e0.0"
26
+ "@trackunit/i18n-library-translation": "2.4.63"
27
27
  },
28
28
  "peerDependencies": {
29
29
  "react": "^19.0.0",
@@ -1,3 +1,4 @@
1
+ import { IconName } from "@trackunit/ui-icons";
1
2
  import { ReactElement, ReactNode } from "react";
2
3
  import { CommonProps } from "../../common/CommonProps";
3
4
  import { Refable } from "../../common/Refable";
@@ -17,6 +18,13 @@ export interface HighlightProps extends CommonProps, Styleable, Refable<HTMLDivE
17
18
  * The content of the highlight. Accepts any valid React children (text, numbers, elements).
18
19
  */
19
20
  children?: ReactNode;
21
+ /**
22
+ * Optional icon. When omitted, the highlight renders as text only. When provided,
23
+ * an icon is rendered before the highlight's content. The icon is always rendered
24
+ * at the "small" (16px) size regardless of the highlight's `size` — a medium
25
+ * highlight with a full-size medium icon reads as visually top-heavy.
26
+ */
27
+ iconName?: IconName;
20
28
  }
21
29
  /**
22
30
  * Highlight draws visual attention to data values that may require user action, monitoring, or investigation.
@@ -51,10 +59,18 @@ export interface HighlightProps extends CommonProps, Styleable, Refable<HTMLDivE
51
59
  * </div>
52
60
  * );
53
61
  * ```
62
+ * @example Highlight with a leading icon
63
+ * ```tsx
64
+ * import { Highlight } from "@trackunit/react-components";
65
+ *
66
+ * const LastSeen = () => (
67
+ * <Highlight color="danger" iconName="MapPin">3 days ago</Highlight>
68
+ * );
69
+ * ```
54
70
  * @param {HighlightProps} props - The props for the Highlight component
55
71
  * @returns {ReactElement} Highlight component
56
72
  */
57
73
  export declare const Highlight: {
58
- ({ className, "data-testid": dataTestId, children, size, color, style, ref, }: HighlightProps): ReactElement;
74
+ ({ className, "data-testid": dataTestId, children, size, color, iconName, style, ref, }: HighlightProps): ReactElement;
59
75
  displayName: string;
60
76
  };
@@ -1,4 +1,4 @@
1
- import { ActivityColors, CriticalityColors, GeneralColors, IntentColors, RentalStatusColors, SitesColors, UtilizationColors } from "@trackunit/ui-design-tokens";
1
+ import { ActivityColors, AiColors, CriticalityColors, GeneralColors, IntentColors, RentalStatusColors, SitesColors, UtilizationColors } from "@trackunit/ui-design-tokens";
2
2
  import { IconName } from "@trackunit/ui-icons";
3
3
  import { MouseEventHandler, ReactElement } from "react";
4
4
  import { AriaProps } from "../../common/AriaProps";
@@ -6,7 +6,7 @@ import { CommonProps } from "../../common/CommonProps";
6
6
  import { Refable } from "../../common/Refable";
7
7
  import { Size } from "../../common/Size";
8
8
  import type { Styleable } from "../../common/Styleable";
9
- export type IconColors = IntentColors | GeneralColors | CriticalityColors | ActivityColors | UtilizationColors | SitesColors | RentalStatusColors;
9
+ export type IconColors = IntentColors | AiColors | GeneralColors | CriticalityColors | ActivityColors | UtilizationColors | SitesColors | RentalStatusColors;
10
10
  export declare const iconPalette: {
11
11
  ON_RENT: {
12
12
  readonly 100: "219 234 254";
@@ -163,6 +163,9 @@ export declare const iconPalette: {
163
163
  readonly 600: "220 38 38";
164
164
  readonly 700: "185 28 28";
165
165
  };
166
+ AI: {
167
+ readonly DEFAULT: "249 66 58";
168
+ };
166
169
  PRIMARY: {
167
170
  readonly 50: "239 246 255";
168
171
  readonly 100: "219 234 254";
@@ -242,7 +245,7 @@ export declare const iconPalette: {
242
245
  readonly 900: "127 29 29";
243
246
  };
244
247
  };
245
- export declare const iconColorNames: ("black" | "white" | "active" | "primary" | "neutral" | "info" | "success" | "warning" | "danger" | "good" | "low" | "critical" | "working" | "idle" | "moving" | "excessive_usage" | "stopped" | "unknown" | "unused" | "utilized" | "heavily_utilized" | "unknown_utilization" | "site_area" | "site_classic_poi" | "site_classic_zone" | "site_depot" | "site_work_place" | "site_construction_site" | "site_unknown" | "on_rent" | "returned" | "available" | "pickup_ready" | "transfer" | "in_repair" | "other_rental_status")[];
248
+ export declare const iconColorNames: ("black" | "white" | "active" | "primary" | "ai" | "neutral" | "info" | "success" | "warning" | "danger" | "good" | "low" | "critical" | "working" | "idle" | "moving" | "excessive_usage" | "stopped" | "unknown" | "unused" | "utilized" | "heavily_utilized" | "unknown_utilization" | "site_area" | "site_classic_poi" | "site_classic_zone" | "site_depot" | "site_work_place" | "site_construction_site" | "site_unknown" | "on_rent" | "returned" | "available" | "pickup_ready" | "transfer" | "in_repair" | "other_rental_status")[];
246
249
  type IconPropsSmall = {
247
250
  size?: "small";
248
251
  type?: "solid";
@@ -3,6 +3,7 @@ export declare const cvaIcon: import("cva").CVAComponent<Omit<{
3
3
  variants: {
4
4
  color: {
5
5
  primary: string;
6
+ ai: string;
6
7
  neutral: string;
7
8
  info: string;
8
9
  success: string;
@@ -71,6 +72,7 @@ export declare const cvaIcon: import("cva").CVAComponent<Omit<{
71
72
  variants: {
72
73
  color: {
73
74
  primary: string;
75
+ ai: string;
74
76
  neutral: string;
75
77
  info: string;
76
78
  success: string;
@@ -125,6 +127,7 @@ export declare const cvaIcon: import("cva").CVAComponent<Omit<{
125
127
  }, {
126
128
  color: {
127
129
  primary: string;
130
+ ai: string;
128
131
  neutral: string;
129
132
  info: string;
130
133
  success: string;
@@ -4,7 +4,7 @@ import { Refable } from "../../../common/Refable";
4
4
  import { Icon, IconProps } from "../../Icon/Icon";
5
5
  import { ButtonCommonProps } from "../shared/ButtonProps";
6
6
  import { IconButtonSize } from "../shared/IconButtonSize";
7
- interface IconButtonBaseProps extends MappedOmit<ButtonCommonProps, "ariaLabel" | "size" | "title">, Refable<HTMLButtonElement>, Refable<HTMLButtonElement> {
7
+ interface IconButtonBaseProps extends MappedOmit<ButtonCommonProps, "ariaLabel" | "size" | "title" | "variant">, Refable<HTMLButtonElement>, Refable<HTMLButtonElement> {
8
8
  /**
9
9
  * The icon to display. Must be an `<Icon />` element.
10
10
  */
@@ -21,6 +21,8 @@ interface IconButtonBaseProps extends MappedOmit<ButtonCommonProps, "ariaLabel"
21
21
  * single text line.
22
22
  */
23
23
  size?: IconButtonSize;
24
+ /** The button appearance, including the AI icon-only treatment. */
25
+ variant?: ButtonCommonProps["variant"] | "ai";
24
26
  }
25
27
  type IconButtonAccessibleNameProps = {
26
28
  /**
@@ -85,7 +87,7 @@ export type IconButtonProps = IconButtonBaseProps & IconButtonAccessibleNameProp
85
87
  * @returns {ReactElement} IconButton component
86
88
  */
87
89
  export declare const IconButton: {
88
- ({ icon, size, square, loading, disabled, className, title, ariaLabel, "data-testid": dataTestId, ref, ...rest }: IconButtonProps): ReactElement;
90
+ ({ icon, variant, size, square, loading, disabled, className, title, ariaLabel, "data-testid": dataTestId, ref, ...rest }: IconButtonProps): ReactElement;
89
91
  displayName: string;
90
92
  };
91
93
  export {};
@@ -336,6 +336,10 @@ export declare const cvaButtonPrefixSuffix: import("cva").CVAComponent<Omit<{
336
336
  export declare const cvaIconButton: import("cva").CVAComponent<Omit<{
337
337
  base: never[];
338
338
  variants: {
339
+ ai: {
340
+ true: string[];
341
+ false: never[];
342
+ };
339
343
  size: {
340
344
  /**
341
345
  * Sized to match a single text line (20px) so the button fits inside
@@ -355,6 +359,10 @@ export declare const cvaIconButton: import("cva").CVAComponent<Omit<{
355
359
  };
356
360
  }, "defaultVariants"> & {
357
361
  variants: {
362
+ ai: {
363
+ true: string[];
364
+ false: never[];
365
+ };
358
366
  size: {
359
367
  /**
360
368
  * Sized to match a single text line (20px) so the button fits inside
@@ -373,6 +381,10 @@ export declare const cvaIconButton: import("cva").CVAComponent<Omit<{
373
381
  size: "medium";
374
382
  };
375
383
  }, {
384
+ ai: {
385
+ true: string[];
386
+ false: never[];
387
+ };
376
388
  size: {
377
389
  /**
378
390
  * Sized to match a single text line (20px) so the button fits inside