@trackunit/react-components 3.8.4-alpha-7afddbbe4cc.0 → 3.8.5-alpha-4acfba00274.0

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
@@ -2361,6 +2361,7 @@ const cvaTagText = cssClassVarianceUtilities.cva({
2361
2361
  },
2362
2362
  });
2363
2363
  const cvaTagIconContainer = cssClassVarianceUtilities.cva({ base: ["shrink-0", "inline-flex", "self-center"] });
2364
+ const cvaTagDismissButton = cssClassVarianceUtilities.cva({ base: ["inline-flex", "rounded-full", "focus-visible:outline-native"] });
2364
2365
  const cvaTagIcon = cssClassVarianceUtilities.cva({
2365
2366
  base: ["cursor-pointer", "transition-opacity", "hover:opacity-70", "text-neutral-500"],
2366
2367
  });
@@ -2414,9 +2415,11 @@ const TAG_TEXT_MIN_WIDTH_PX = sharedUtils.parseTailwindArbitraryValue(TAG_TEXT_M
2414
2415
  * @param {TagProps} props - The props for the Tag component.
2415
2416
  * @returns {ReactElement} The rendered Tag component.
2416
2417
  */
2417
- const Tag = ({ className, "data-testid": dataTestId, children, size = "medium", onClickClose, color = "info", disabled = false, ref, icon, onMouseEnter, style, removeTagLabel, }) => {
2418
+ const Tag = ({ className, "data-testid": dataTestId, children, size = "medium", onClickClose, color = "info", disabled = false, ref, icon, onMouseEnter, style, removeTagLabel, removeButtonInTabOrder = true, }) => {
2418
2419
  const textRef = react.useRef(null);
2419
2420
  const [shouldTruncate, setShouldTruncate] = react.useState(false);
2421
+ const textId = react.useId();
2422
+ const removeButtonId = react.useId();
2420
2423
  react.useLayoutEffect(() => {
2421
2424
  // Using simple DOM measurements to avoid the complexity of the useMeasure hook.
2422
2425
  // Resize observers have some overhead and we don't need the full power of the useMeasure hook here.
@@ -2428,28 +2431,22 @@ const Tag = ({ className, "data-testid": dataTestId, children, size = "medium",
2428
2431
  setShouldTruncate(width >= TAG_TEXT_MIN_WIDTH_PX);
2429
2432
  }
2430
2433
  }, [children]);
2431
- const isSupportedDismissColor = react.useMemo(() => {
2432
- if (color === "neutral" || color === "primary" || color === "white" || color === "info") {
2433
- return true;
2434
- }
2435
- return false;
2436
- }, [color]);
2437
2434
  const layout = react.useMemo(() => {
2438
- if (onClickClose !== undefined && isSupportedDismissColor && !disabled) {
2435
+ if (onClickClose !== undefined && !disabled) {
2439
2436
  return "containsDismiss";
2440
2437
  }
2441
2438
  if (icon !== null && icon !== undefined) {
2442
2439
  return "containsIcon";
2443
2440
  }
2444
2441
  return "default";
2445
- }, [onClickClose, isSupportedDismissColor, disabled, icon]);
2442
+ }, [onClickClose, disabled, icon]);
2446
2443
  return (jsxRuntime.jsxs("div", { className: cvaTag({
2447
2444
  className,
2448
2445
  size,
2449
2446
  color,
2450
2447
  layout,
2451
2448
  border: color === "white" ? "default" : "none",
2452
- }), "data-testid": dataTestId, onMouseEnter: onMouseEnter, ref: ref, style: style, children: [icon !== null && icon !== undefined && size === "medium" ? (jsxRuntime.jsx("div", { className: cvaTagIconContainer(), "data-slot": "icon", children: icon })) : null, jsxRuntime.jsx("span", { className: cvaTagText({ truncate: shouldTruncate }), ref: textRef, children: children }), Boolean(onClickClose) && isSupportedDismissColor && size === "medium" && !disabled ? (jsxRuntime.jsx("div", { className: cvaTagIconContainer(), "data-slot": "dismiss", onClick: onClickClose, children: jsxRuntime.jsx(Tooltip, { disabled: disabled, label: removeTagLabel, placement: "bottom", children: jsxRuntime.jsx(Icon, { className: cvaTagIcon(), "data-testid": `${dataTestId}Icon`, name: "XCircle", size: "small", style: { WebkitTransition: "-webkit-transform 0.150s" }, type: "solid" }) }) })) : null] }));
2449
+ }), "data-testid": dataTestId, onMouseEnter: onMouseEnter, ref: ref, style: style, children: [icon !== null && icon !== undefined && size === "medium" ? (jsxRuntime.jsx("div", { className: cvaTagIconContainer(), "data-slot": "icon", children: icon })) : null, jsxRuntime.jsx("span", { className: cvaTagText({ truncate: shouldTruncate }), id: textId, ref: textRef, children: children }), Boolean(onClickClose) && size === "medium" && !disabled ? (jsxRuntime.jsx("div", { className: cvaTagIconContainer(), "data-slot": "dismiss", onClick: onClickClose, children: jsxRuntime.jsx(Tooltip, { disabled: disabled, label: removeTagLabel, placement: "bottom", children: jsxRuntime.jsx("button", { "aria-label": removeTagLabel, "aria-labelledby": `${removeButtonId} ${textId}`, className: cvaTagDismissButton(), id: removeButtonId, tabIndex: removeButtonInTabOrder ? undefined : -1, type: "button", children: jsxRuntime.jsx(Icon, { ariaHidden: true, className: cvaTagIcon(), "data-testid": `${dataTestId}Icon`, name: "XCircle", size: "small", style: { WebkitTransition: "-webkit-transform 0.150s" }, type: "solid" }) }) }) })) : null] }));
2453
2450
  };
2454
2451
 
2455
2452
  // Mirrors the slug logic in @trackunit/storybook-docs-components SectionName so anchors line up
@@ -14588,6 +14585,8 @@ const useCursorUrlSync = ({ paramName = DEFAULT_PARAM_NAME, debounceMs = DEFAULT
14588
14585
  ...prev,
14589
14586
  [paramNameRef.current]: cursor,
14590
14587
  }),
14588
+ // Without this the router drops the fragment, and with it the table layout.
14589
+ hash: true,
14591
14590
  replace: true,
14592
14591
  });
14593
14592
  }, debounceMs);
package/index.esm.js CHANGED
@@ -3,7 +3,7 @@ import { registerTranslations, useNamespaceTranslation } from '@trackunit/i18n-l
3
3
  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
- import { useRef, useMemo, useEffect, useSyncExternalStore, useState, useLayoutEffect, createContext, useContext, isValidElement, cloneElement, createElement, useCallback, Fragment as Fragment$1, memo, forwardRef, useId, useReducer, Children } from 'react';
6
+ import { useRef, useMemo, useEffect, useSyncExternalStore, useState, useLayoutEffect, createContext, useContext, isValidElement, cloneElement, createElement, useId, useCallback, Fragment as Fragment$1, memo, forwardRef, useReducer, Children } from 'react';
7
7
  import { rentalStatusPalette, sitesPalette, utilizationPalette, activityPalette, criticalityPalette, trackunitBrandingPalette, 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';
@@ -2360,6 +2360,7 @@ const cvaTagText = cva({
2360
2360
  },
2361
2361
  });
2362
2362
  const cvaTagIconContainer = cva({ base: ["shrink-0", "inline-flex", "self-center"] });
2363
+ const cvaTagDismissButton = cva({ base: ["inline-flex", "rounded-full", "focus-visible:outline-native"] });
2363
2364
  const cvaTagIcon = cva({
2364
2365
  base: ["cursor-pointer", "transition-opacity", "hover:opacity-70", "text-neutral-500"],
2365
2366
  });
@@ -2413,9 +2414,11 @@ const TAG_TEXT_MIN_WIDTH_PX = parseTailwindArbitraryValue(TAG_TEXT_MIN_WIDTH_CLA
2413
2414
  * @param {TagProps} props - The props for the Tag component.
2414
2415
  * @returns {ReactElement} The rendered Tag component.
2415
2416
  */
2416
- const Tag = ({ className, "data-testid": dataTestId, children, size = "medium", onClickClose, color = "info", disabled = false, ref, icon, onMouseEnter, style, removeTagLabel, }) => {
2417
+ const Tag = ({ className, "data-testid": dataTestId, children, size = "medium", onClickClose, color = "info", disabled = false, ref, icon, onMouseEnter, style, removeTagLabel, removeButtonInTabOrder = true, }) => {
2417
2418
  const textRef = useRef(null);
2418
2419
  const [shouldTruncate, setShouldTruncate] = useState(false);
2420
+ const textId = useId();
2421
+ const removeButtonId = useId();
2419
2422
  useLayoutEffect(() => {
2420
2423
  // Using simple DOM measurements to avoid the complexity of the useMeasure hook.
2421
2424
  // Resize observers have some overhead and we don't need the full power of the useMeasure hook here.
@@ -2427,28 +2430,22 @@ const Tag = ({ className, "data-testid": dataTestId, children, size = "medium",
2427
2430
  setShouldTruncate(width >= TAG_TEXT_MIN_WIDTH_PX);
2428
2431
  }
2429
2432
  }, [children]);
2430
- const isSupportedDismissColor = useMemo(() => {
2431
- if (color === "neutral" || color === "primary" || color === "white" || color === "info") {
2432
- return true;
2433
- }
2434
- return false;
2435
- }, [color]);
2436
2433
  const layout = useMemo(() => {
2437
- if (onClickClose !== undefined && isSupportedDismissColor && !disabled) {
2434
+ if (onClickClose !== undefined && !disabled) {
2438
2435
  return "containsDismiss";
2439
2436
  }
2440
2437
  if (icon !== null && icon !== undefined) {
2441
2438
  return "containsIcon";
2442
2439
  }
2443
2440
  return "default";
2444
- }, [onClickClose, isSupportedDismissColor, disabled, icon]);
2441
+ }, [onClickClose, disabled, icon]);
2445
2442
  return (jsxs("div", { className: cvaTag({
2446
2443
  className,
2447
2444
  size,
2448
2445
  color,
2449
2446
  layout,
2450
2447
  border: color === "white" ? "default" : "none",
2451
- }), "data-testid": dataTestId, onMouseEnter: onMouseEnter, ref: ref, style: style, children: [icon !== null && icon !== undefined && size === "medium" ? (jsx("div", { className: cvaTagIconContainer(), "data-slot": "icon", children: icon })) : null, jsx("span", { className: cvaTagText({ truncate: shouldTruncate }), ref: textRef, children: children }), Boolean(onClickClose) && isSupportedDismissColor && size === "medium" && !disabled ? (jsx("div", { className: cvaTagIconContainer(), "data-slot": "dismiss", onClick: onClickClose, children: jsx(Tooltip, { disabled: disabled, label: removeTagLabel, placement: "bottom", children: jsx(Icon, { className: cvaTagIcon(), "data-testid": `${dataTestId}Icon`, name: "XCircle", size: "small", style: { WebkitTransition: "-webkit-transform 0.150s" }, type: "solid" }) }) })) : null] }));
2448
+ }), "data-testid": dataTestId, onMouseEnter: onMouseEnter, ref: ref, style: style, children: [icon !== null && icon !== undefined && size === "medium" ? (jsx("div", { className: cvaTagIconContainer(), "data-slot": "icon", children: icon })) : null, jsx("span", { className: cvaTagText({ truncate: shouldTruncate }), id: textId, ref: textRef, children: children }), Boolean(onClickClose) && size === "medium" && !disabled ? (jsx("div", { className: cvaTagIconContainer(), "data-slot": "dismiss", onClick: onClickClose, children: jsx(Tooltip, { disabled: disabled, label: removeTagLabel, placement: "bottom", children: jsx("button", { "aria-label": removeTagLabel, "aria-labelledby": `${removeButtonId} ${textId}`, className: cvaTagDismissButton(), id: removeButtonId, tabIndex: removeButtonInTabOrder ? undefined : -1, type: "button", children: jsx(Icon, { ariaHidden: true, className: cvaTagIcon(), "data-testid": `${dataTestId}Icon`, name: "XCircle", size: "small", style: { WebkitTransition: "-webkit-transform 0.150s" }, type: "solid" }) }) }) })) : null] }));
2452
2449
  };
2453
2450
 
2454
2451
  // Mirrors the slug logic in @trackunit/storybook-docs-components SectionName so anchors line up
@@ -14587,6 +14584,8 @@ const useCursorUrlSync = ({ paramName = DEFAULT_PARAM_NAME, debounceMs = DEFAULT
14587
14584
  ...prev,
14588
14585
  [paramNameRef.current]: cursor,
14589
14586
  }),
14587
+ // Without this the router drops the fragment, and with it the table layout.
14588
+ hash: true,
14590
14589
  replace: true,
14591
14590
  });
14592
14591
  }, debounceMs);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-components",
3
- "version": "3.8.4-alpha-7afddbbe4cc.0",
3
+ "version": "3.8.5-alpha-4acfba00274.0",
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.18.7-alpha-7afddbbe4cc.0",
18
- "@trackunit/css-class-variance-utilities": "2.3.7-alpha-7afddbbe4cc.0",
19
- "@trackunit/shared-utils": "1.19.7-alpha-7afddbbe4cc.0",
20
- "@trackunit/ui-icons": "1.17.7-alpha-7afddbbe4cc.0",
17
+ "@trackunit/ui-design-tokens": "1.18.7-alpha-4acfba00274.0",
18
+ "@trackunit/css-class-variance-utilities": "2.3.7-alpha-4acfba00274.0",
19
+ "@trackunit/shared-utils": "1.19.7-alpha-4acfba00274.0",
20
+ "@trackunit/ui-icons": "1.17.7-alpha-4acfba00274.0",
21
21
  "es-toolkit": "^1.52.0",
22
22
  "@tanstack/react-virtual": "^3.14.13",
23
23
  "dequal": "^2.0.3",
24
24
  "fflate": "^0.8.3",
25
25
  "zod": "^3.25.76",
26
- "@trackunit/i18n-library-translation": "2.8.7-alpha-7afddbbe4cc.0"
26
+ "@trackunit/i18n-library-translation": "2.8.7-alpha-4acfba00274.0"
27
27
  },
28
28
  "peerDependencies": {
29
29
  "react": "^19.0.0",
@@ -38,29 +38,36 @@ interface TagBaseProps extends CommonProps, Styleable, Refable<HTMLDivElement> {
38
38
  }
39
39
  interface NonDismissibleTagProps extends TagBaseProps {
40
40
  /**
41
- * A handler for a click event triggered on X icon.
42
- * If not passed then x icon won't be visible.
43
- * Available only for neutral, primary and white tags.
41
+ * Called when the remove button is clicked.
42
+ * If not passed then the remove button won't be visible.
43
+ * Available only for medium tags.
44
44
  *
45
45
  */
46
46
  onClickClose?: undefined;
47
47
  /**
48
- * Label for the remove button.
48
+ * Tooltip of the remove button, such as "Remove".
49
49
  */
50
50
  removeTagLabel?: string;
51
+ removeButtonInTabOrder?: undefined;
51
52
  }
52
53
  interface DismissibleTagProps extends TagBaseProps {
53
54
  /**
54
- * A handler for a click event triggered on X icon.
55
- * If not passed then x icon won't be visible.
56
- * Available only for neutral, primary and white tags.
55
+ * Called when the remove button is clicked.
56
+ * If not passed then the remove button won't be visible.
57
+ * Available only for medium tags.
57
58
  *
58
59
  */
59
60
  onClickClose: MouseEventHandler<HTMLDivElement>;
60
61
  /**
61
- * Label for the remove button.
62
+ * Tooltip of the remove button, such as "Remove".
63
+ * Screen readers hear it followed by the tag's text, such as "Remove Chocolate".
62
64
  */
63
65
  removeTagLabel: string;
66
+ /**
67
+ * Set to false when the surrounding widget already offers keyboard removal, such as a multi-select,
68
+ * so the remove button adds no Tab stop. Defaults to true.
69
+ */
70
+ removeButtonInTabOrder?: boolean;
64
71
  }
65
72
  export type TagProps = DismissibleTagProps | NonDismissibleTagProps;
66
73
  /**
@@ -111,5 +118,5 @@ export type TagProps = DismissibleTagProps | NonDismissibleTagProps;
111
118
  * @param {TagProps} props - The props for the Tag component.
112
119
  * @returns {ReactElement} The rendered Tag component.
113
120
  */
114
- export declare const Tag: ({ className, "data-testid": dataTestId, children, size, onClickClose, color, disabled, ref, icon, onMouseEnter, style, removeTagLabel, }: TagProps) => ReactElement;
121
+ export declare const Tag: ({ className, "data-testid": dataTestId, children, size, onClickClose, color, disabled, ref, icon, onMouseEnter, style, removeTagLabel, removeButtonInTabOrder, }: TagProps) => ReactElement;
115
122
  export {};
@@ -154,6 +154,12 @@ export declare const cvaTagIconContainer: import("cva").CVAComponent<Omit<{
154
154
  variants: unknown;
155
155
  defaultVariants: Omit<{}, never>;
156
156
  }, unknown>;
157
+ export declare const cvaTagDismissButton: import("cva").CVAComponent<Omit<{
158
+ base: string[];
159
+ }, "defaultVariants"> & {
160
+ variants: unknown;
161
+ defaultVariants: Omit<{}, never>;
162
+ }, unknown>;
157
163
  export declare const cvaTagIcon: import("cva").CVAComponent<Omit<{
158
164
  base: string[];
159
165
  }, "defaultVariants"> & {