@trackunit/react-components 1.4.115 → 1.4.118

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
@@ -134,7 +134,7 @@ const isSafari = () => {
134
134
  * @param {IconProps} props - The props for the Icon component
135
135
  * @returns {ReactElement} Icon component
136
136
  */
137
- const Icon = ({ name, size = "medium", className, dataTestId, color, onClick, type, style, forwardedRef, ariaLabel, fontSize, ariaLabelledBy, ariaDescribedBy, }) => {
137
+ const Icon = ({ name, size = "medium", className, dataTestId, color, onClick, type, style, forwardedRef, ariaLabel, fontSize, ariaLabelledBy, ariaDescribedBy, ariaHidden, }) => {
138
138
  const useTagRef = react.useRef(null);
139
139
  const ICON_CONTAINER_ID = sharedUtils.uuidv4();
140
140
  const correctIconType = react.useMemo(() => {
@@ -173,7 +173,7 @@ const Icon = ({ name, size = "medium", className, dataTestId, color, onClick, ty
173
173
  useTagRef.current.setAttribute("href", href[correctIconType]);
174
174
  }
175
175
  }, [correctIconType, href]);
176
- return (jsxRuntime.jsx("span", { "aria-describedby": ariaDescribedBy, "aria-label": ariaLabel ? ariaLabel : stringTs.titleCase(iconName), "aria-labelledby": ariaLabelledBy, className: cvaIcon({ color, size, fontSize, className }), "data-testid": dataTestId, id: ICON_CONTAINER_ID, onClick: onClick, ref: forwardedRef, children: jsxRuntime.jsx("svg", { "aria-labelledby": ICON_CONTAINER_ID, "data-testid": dataTestId ? `${dataTestId}-${iconName}` : iconName, role: "img", style: style, viewBox: correctViewBox, children: jsxRuntime.jsx("use", { href: href[correctIconType], ref: useTagRef }) }) }));
176
+ return (jsxRuntime.jsx("span", { "aria-describedby": ariaDescribedBy, "aria-hidden": ariaHidden, "aria-label": ariaLabel ? ariaLabel : stringTs.titleCase(iconName), "aria-labelledby": ariaLabelledBy, className: cvaIcon({ color, size, fontSize, className }), "data-testid": dataTestId, id: ICON_CONTAINER_ID, onClick: onClick, ref: forwardedRef, children: jsxRuntime.jsx("svg", { "aria-labelledby": ICON_CONTAINER_ID, "data-testid": dataTestId ? `${dataTestId}-${iconName}` : iconName, role: "img", style: style, viewBox: correctViewBox, children: jsxRuntime.jsx("use", { href: href[correctIconType], ref: useTagRef }) }) }));
177
177
  };
178
178
 
179
179
  const cvaTag = cssClassVarianceUtilities.cvaMerge([
@@ -572,6 +572,7 @@ const cvaButton = cssClassVarianceUtilities.cvaMerge([
572
572
  * So we need to add padding to the min-height calculation. Two times the vertical
573
573
  * padding aka py-1 * 2 aka --spacing-1 * 2 aka spacing-2 (for small).
574
574
  */
575
+ extraSmall: ["p-0", "gap-1", "w-5", "h-8", "text-xs", "min-h-[calc(var(--line-height-sm)+var(--spacing-1))"],
575
576
  small: ["px-2", "py-1.5", "gap-1", "h-7", "text-xs", "min-h-[calc(var(--line-height-sm)+var(--spacing-2))]"],
576
577
  medium: ["px-3", "py-1.5", "gap-2", "h-8", "text-sm", "min-h-[calc(var(--line-height-sm)+var(--spacing-3))]"],
577
578
  large: [
@@ -670,6 +671,7 @@ const cvaButtonSpinner = cssClassVarianceUtilities.cvaMerge([], {
670
671
  const cvaButtonPrefixSuffix = cssClassVarianceUtilities.cvaMerge(["flex", "items-center"], {
671
672
  variants: {
672
673
  size: {
674
+ extraSmall: ["h-3"],
673
675
  small: ["h-4"],
674
676
  medium: ["h-4"],
675
677
  large: ["h-5"],
@@ -701,6 +703,7 @@ const cvaButtonPrefixSuffix = cssClassVarianceUtilities.cvaMerge(["flex", "items
701
703
  const cvaIconButton = cssClassVarianceUtilities.cvaMerge([], {
702
704
  variants: {
703
705
  size: {
706
+ extraSmall: ["p-0", "w-5", "h-8"],
704
707
  small: ["p-1.5", "w-7", "h-7"],
705
708
  medium: ["p-2", "w-8", "h-8"],
706
709
  large: ["p-2.5", "w-10", "h-10"],
@@ -1340,6 +1343,33 @@ const useIsTextTruncated = (text) => {
1340
1343
  return { ref, isTextTruncated };
1341
1344
  };
1342
1345
 
1346
+ /**
1347
+ * Hook that returns true if any modifier key (Ctrl, Alt, Shift, Meta/Cmd) is pressed
1348
+ *
1349
+ * @param props Configuration options
1350
+ * @param props.exclude Array of modifier keys to exclude from detection
1351
+ * @returns {boolean} Indicates if any non-excluded modifier key is pressed
1352
+ */
1353
+ const useModifierKey = ({ exclude = [] } = {}) => {
1354
+ const [isModifierPressed, setIsModifierPressed] = react.useState(false);
1355
+ const handleKeyEvent = react.useCallback((event) => {
1356
+ const modifierPressed = (!exclude.includes("Control") && event.ctrlKey) ||
1357
+ (!exclude.includes("Alt") && event.altKey) ||
1358
+ (!exclude.includes("Shift") && event.shiftKey) ||
1359
+ (!exclude.includes("Meta") && event.metaKey);
1360
+ setIsModifierPressed(modifierPressed);
1361
+ }, [exclude]);
1362
+ react.useEffect(() => {
1363
+ window.addEventListener("keydown", handleKeyEvent);
1364
+ window.addEventListener("keyup", handleKeyEvent);
1365
+ return () => {
1366
+ window.removeEventListener("keydown", handleKeyEvent);
1367
+ window.removeEventListener("keyup", handleKeyEvent);
1368
+ };
1369
+ }, [handleKeyEvent]);
1370
+ return isModifierPressed;
1371
+ };
1372
+
1343
1373
  /**
1344
1374
  * Custom hook to handle window resize events and provide the current window size.
1345
1375
  *
@@ -2550,7 +2580,7 @@ const Tooltip = ({ children, dataTestId = "tool-tip", disabled, className, label
2550
2580
  const arrowRef = react.useRef(null);
2551
2581
  const { refs, floatingStyles, context } = react$1.useFloating({
2552
2582
  placement: placement === "auto" ? "bottom" : placement,
2553
- open: isOpen,
2583
+ open: disabled ? false : isOpen,
2554
2584
  onOpenChange: setIsOpen,
2555
2585
  middleware: [
2556
2586
  react$1.offset(8),
@@ -2878,17 +2908,19 @@ const cvaInteractableItem = cssClassVarianceUtilities.cvaMerge("", {
2878
2908
  "not-allowed": "cursor-not-allowed",
2879
2909
  },
2880
2910
  selected: {
2881
- true: ["bg-primary-600/[.08]", "hover:bg-primary-600/[.12]", "focus-within:bg-primary-600/[.12]"],
2911
+ true: ["bg-primary-50", "hover:bg-primary-50", "focus-within:bg-primary-50"],
2882
2912
  false: "",
2883
2913
  auto: [
2884
- "has-[:checked]:bg-primary-600/[.08]",
2885
- "hover:has-[:checked]:bg-primary-600/[.12]",
2886
- "focus-within:has-[:checked]:bg-primary-600/[.12]",
2914
+ "hover:bg-neutral-100",
2915
+ "has-[:checked]:bg-primary-50",
2916
+ "hover:has-[:checked]:bg-primary-50",
2917
+ "focus-within:has-[:checked]:bg-primary-50",
2887
2918
  ],
2888
2919
  },
2889
2920
  disabled: {
2921
+ // Remember to also disable the element or set tabIndex=-1 to prevent actual interaction/focus!
2890
2922
  true: ["pointer-events-none", "!bg-neutral-100", "!cursor-not-allowed"],
2891
- false: ["hover:bg-neutral-600/5", "focus-within:bg-neutral-600/5"],
2923
+ false: "", // use compoundVariants instead
2892
2924
  },
2893
2925
  focused: {
2894
2926
  true: "outline-native",
@@ -2896,6 +2928,13 @@ const cvaInteractableItem = cssClassVarianceUtilities.cvaMerge("", {
2896
2928
  auto: "[&:has(:focus-visible)]:outline-native",
2897
2929
  },
2898
2930
  },
2931
+ compoundVariants: [
2932
+ {
2933
+ disabled: false,
2934
+ selected: false,
2935
+ className: ["hover:bg-neutral-600/5", "focus-within:bg-neutral-600/5"],
2936
+ },
2937
+ ],
2899
2938
  defaultVariants: {
2900
2939
  cursor: "auto",
2901
2940
  selected: "auto",
@@ -3176,7 +3215,7 @@ const cvaPage = cssClassVarianceUtilities.cvaMerge(["grid", "h-full"], {
3176
3215
  const cvaPageContent = cssClassVarianceUtilities.cvaMerge(["overflow-auto", "page-content", "grid", "gap-responsive-space"], {
3177
3216
  variants: {
3178
3217
  layout: {
3179
- content: "",
3218
+ content: "grid-rows-fr",
3180
3219
  "v-min-fr": ["grid-rows-min-fr"],
3181
3220
  "h-min-fr": ["grid-cols-min-fr", "sm:grid-cols-1", "sm:grid-rows-min-fr"],
3182
3221
  },
@@ -3692,7 +3731,7 @@ const cvaToggleItemText = cssClassVarianceUtilities.cvaMerge(["text-ellipsis", "
3692
3731
  * @returns {ReactElement} ToggleGroup component
3693
3732
  */
3694
3733
  const ToggleGroup = ({ list, selected, setSelected, onChange, disabled = false, size = "medium", isIconOnly = false, className, dataTestId, }) => {
3695
- return (jsxRuntime.jsx("div", { className: cvaToggleGroup(), "data-testid": dataTestId, children: list.map((item, index) => (jsxRuntime.jsx(ToggleItem, { className: tailwindMerge.twMerge(className, index === 0 ? ["rounded-l-md", "border-l"] : "", index === list.length - 1 ? ["rounded-r-md", "border-r"] : ""), dataTestId: item.dataTestId, disabled: disabled, iconName: item.iconName, isIconOnly: isIconOnly, onClick: () => {
3734
+ return (jsxRuntime.jsx("div", { className: cvaToggleGroup({ className }), "data-testid": dataTestId, children: list.map((item, index) => (jsxRuntime.jsx(ToggleItem, { className: tailwindMerge.twMerge(item.className, index === 0 ? ["rounded-l-md", "border-l"] : "", index === list.length - 1 ? ["rounded-r-md", "border-r"] : ""), dataTestId: item.dataTestId, disabled: disabled, iconName: item.iconName, isIconOnly: isIconOnly, onClick: () => {
3696
3735
  setSelected(item.id);
3697
3736
  onChange?.(item.id);
3698
3737
  }, selected: selected === item.id, size: size, text: item.text, title: item.title, tooltip: item.tooltip }, item.id))) }));
@@ -3701,7 +3740,7 @@ const ToggleGroup = ({ list, selected, setSelected, onChange, disabled = false,
3701
3740
  * Individual ToggleItem to create custom ToggleGroups
3702
3741
  */
3703
3742
  const ToggleItem = ({ title, onClick, disabled = false, isIconOnly = false, iconName, size, className, selected = false, text, tooltip, dataTestId, }) => {
3704
- return isIconOnly ? (jsxRuntime.jsx(Tooltip, { label: tooltip?.content || title, placement: tooltip?.placement || "top", children: jsxRuntime.jsx(IconButton, { className: cvaToggleItem({ className, selected }), "data-testid": dataTestId, disabled: disabled, icon: iconName ? (jsxRuntime.jsx(Icon, { className: selected ? "text-slate-600" : "text-slate-400", name: iconName, size: "small" })) : null, onClick: onClick, size: size, title: iconName, variant: "secondary" }) })) : (jsxRuntime.jsx(Tooltip, { disabled: !text?.truncate && tooltip?.content === undefined, label: tooltip?.content || title, placement: tooltip?.placement || "top", children: jsxRuntime.jsx(Button, { className: cvaToggleItem({ className, selected }), "data-testid": dataTestId, disabled: disabled, onClick: onClick, prefix: iconName ? (jsxRuntime.jsx(Icon, { className: selected ? "text-slate-600" : "text-slate-400", name: iconName, size: "small" })) : null, size: size, variant: "secondary", children: jsxRuntime.jsx("span", { className: cvaToggleItemText({ disabledAndSelected: disabled && selected, maxWidth: text?.maxWidth }), children: title }) }) }));
3743
+ return isIconOnly ? (jsxRuntime.jsx(Tooltip, { label: tooltip?.content || title, placement: tooltip?.placement || "top", children: jsxRuntime.jsx(IconButton, { className: cvaToggleItem({ className, selected }), "data-testid": dataTestId, disabled: disabled, icon: iconName ? (jsxRuntime.jsx(Icon, { className: selected ? "text-slate-600" : "text-slate-400", name: iconName, size: "small" })) : null, onClick: onClick, size: size, title: iconName, variant: "secondary" }) })) : (jsxRuntime.jsx(Tooltip, { disabled: !tooltip?.content, label: tooltip?.content, placement: tooltip?.placement || "top", children: jsxRuntime.jsx(Button, { className: cvaToggleItem({ className, selected }), "data-testid": dataTestId, disabled: disabled, onClick: onClick, prefix: iconName ? (jsxRuntime.jsx(Icon, { className: selected ? "text-slate-600" : "text-slate-400", name: iconName, size: "small" })) : null, size: size, variant: "secondary", children: jsxRuntime.jsx("span", { className: cvaToggleItemText({ disabledAndSelected: disabled && selected, maxWidth: text?.maxWidth }), children: title }) }) }));
3705
3744
  };
3706
3745
 
3707
3746
  const cvaValueBar = cssClassVarianceUtilities.cvaMerge(["w-full"], {
@@ -4111,6 +4150,7 @@ exports.useHover = useHover;
4111
4150
  exports.useIsFirstRender = useIsFirstRender;
4112
4151
  exports.useIsFullscreen = useIsFullscreen;
4113
4152
  exports.useIsTextTruncated = useIsTextTruncated;
4153
+ exports.useModifierKey = useModifierKey;
4114
4154
  exports.useOverflowItems = useOverflowItems;
4115
4155
  exports.usePopoverContext = usePopoverContext;
4116
4156
  exports.usePrompt = usePrompt;
package/index.esm.js CHANGED
@@ -132,7 +132,7 @@ const isSafari = () => {
132
132
  * @param {IconProps} props - The props for the Icon component
133
133
  * @returns {ReactElement} Icon component
134
134
  */
135
- const Icon = ({ name, size = "medium", className, dataTestId, color, onClick, type, style, forwardedRef, ariaLabel, fontSize, ariaLabelledBy, ariaDescribedBy, }) => {
135
+ const Icon = ({ name, size = "medium", className, dataTestId, color, onClick, type, style, forwardedRef, ariaLabel, fontSize, ariaLabelledBy, ariaDescribedBy, ariaHidden, }) => {
136
136
  const useTagRef = useRef(null);
137
137
  const ICON_CONTAINER_ID = uuidv4();
138
138
  const correctIconType = useMemo(() => {
@@ -171,7 +171,7 @@ const Icon = ({ name, size = "medium", className, dataTestId, color, onClick, ty
171
171
  useTagRef.current.setAttribute("href", href[correctIconType]);
172
172
  }
173
173
  }, [correctIconType, href]);
174
- return (jsx("span", { "aria-describedby": ariaDescribedBy, "aria-label": ariaLabel ? ariaLabel : titleCase(iconName), "aria-labelledby": ariaLabelledBy, className: cvaIcon({ color, size, fontSize, className }), "data-testid": dataTestId, id: ICON_CONTAINER_ID, onClick: onClick, ref: forwardedRef, children: jsx("svg", { "aria-labelledby": ICON_CONTAINER_ID, "data-testid": dataTestId ? `${dataTestId}-${iconName}` : iconName, role: "img", style: style, viewBox: correctViewBox, children: jsx("use", { href: href[correctIconType], ref: useTagRef }) }) }));
174
+ return (jsx("span", { "aria-describedby": ariaDescribedBy, "aria-hidden": ariaHidden, "aria-label": ariaLabel ? ariaLabel : titleCase(iconName), "aria-labelledby": ariaLabelledBy, className: cvaIcon({ color, size, fontSize, className }), "data-testid": dataTestId, id: ICON_CONTAINER_ID, onClick: onClick, ref: forwardedRef, children: jsx("svg", { "aria-labelledby": ICON_CONTAINER_ID, "data-testid": dataTestId ? `${dataTestId}-${iconName}` : iconName, role: "img", style: style, viewBox: correctViewBox, children: jsx("use", { href: href[correctIconType], ref: useTagRef }) }) }));
175
175
  };
176
176
 
177
177
  const cvaTag = cvaMerge([
@@ -570,6 +570,7 @@ const cvaButton = cvaMerge([
570
570
  * So we need to add padding to the min-height calculation. Two times the vertical
571
571
  * padding aka py-1 * 2 aka --spacing-1 * 2 aka spacing-2 (for small).
572
572
  */
573
+ extraSmall: ["p-0", "gap-1", "w-5", "h-8", "text-xs", "min-h-[calc(var(--line-height-sm)+var(--spacing-1))"],
573
574
  small: ["px-2", "py-1.5", "gap-1", "h-7", "text-xs", "min-h-[calc(var(--line-height-sm)+var(--spacing-2))]"],
574
575
  medium: ["px-3", "py-1.5", "gap-2", "h-8", "text-sm", "min-h-[calc(var(--line-height-sm)+var(--spacing-3))]"],
575
576
  large: [
@@ -668,6 +669,7 @@ const cvaButtonSpinner = cvaMerge([], {
668
669
  const cvaButtonPrefixSuffix = cvaMerge(["flex", "items-center"], {
669
670
  variants: {
670
671
  size: {
672
+ extraSmall: ["h-3"],
671
673
  small: ["h-4"],
672
674
  medium: ["h-4"],
673
675
  large: ["h-5"],
@@ -699,6 +701,7 @@ const cvaButtonPrefixSuffix = cvaMerge(["flex", "items-center"], {
699
701
  const cvaIconButton = cvaMerge([], {
700
702
  variants: {
701
703
  size: {
704
+ extraSmall: ["p-0", "w-5", "h-8"],
702
705
  small: ["p-1.5", "w-7", "h-7"],
703
706
  medium: ["p-2", "w-8", "h-8"],
704
707
  large: ["p-2.5", "w-10", "h-10"],
@@ -1338,6 +1341,33 @@ const useIsTextTruncated = (text) => {
1338
1341
  return { ref, isTextTruncated };
1339
1342
  };
1340
1343
 
1344
+ /**
1345
+ * Hook that returns true if any modifier key (Ctrl, Alt, Shift, Meta/Cmd) is pressed
1346
+ *
1347
+ * @param props Configuration options
1348
+ * @param props.exclude Array of modifier keys to exclude from detection
1349
+ * @returns {boolean} Indicates if any non-excluded modifier key is pressed
1350
+ */
1351
+ const useModifierKey = ({ exclude = [] } = {}) => {
1352
+ const [isModifierPressed, setIsModifierPressed] = useState(false);
1353
+ const handleKeyEvent = useCallback((event) => {
1354
+ const modifierPressed = (!exclude.includes("Control") && event.ctrlKey) ||
1355
+ (!exclude.includes("Alt") && event.altKey) ||
1356
+ (!exclude.includes("Shift") && event.shiftKey) ||
1357
+ (!exclude.includes("Meta") && event.metaKey);
1358
+ setIsModifierPressed(modifierPressed);
1359
+ }, [exclude]);
1360
+ useEffect(() => {
1361
+ window.addEventListener("keydown", handleKeyEvent);
1362
+ window.addEventListener("keyup", handleKeyEvent);
1363
+ return () => {
1364
+ window.removeEventListener("keydown", handleKeyEvent);
1365
+ window.removeEventListener("keyup", handleKeyEvent);
1366
+ };
1367
+ }, [handleKeyEvent]);
1368
+ return isModifierPressed;
1369
+ };
1370
+
1341
1371
  /**
1342
1372
  * Custom hook to handle window resize events and provide the current window size.
1343
1373
  *
@@ -2548,7 +2578,7 @@ const Tooltip = ({ children, dataTestId = "tool-tip", disabled, className, label
2548
2578
  const arrowRef = useRef(null);
2549
2579
  const { refs, floatingStyles, context } = useFloating({
2550
2580
  placement: placement === "auto" ? "bottom" : placement,
2551
- open: isOpen,
2581
+ open: disabled ? false : isOpen,
2552
2582
  onOpenChange: setIsOpen,
2553
2583
  middleware: [
2554
2584
  offset(8),
@@ -2876,17 +2906,19 @@ const cvaInteractableItem = cvaMerge("", {
2876
2906
  "not-allowed": "cursor-not-allowed",
2877
2907
  },
2878
2908
  selected: {
2879
- true: ["bg-primary-600/[.08]", "hover:bg-primary-600/[.12]", "focus-within:bg-primary-600/[.12]"],
2909
+ true: ["bg-primary-50", "hover:bg-primary-50", "focus-within:bg-primary-50"],
2880
2910
  false: "",
2881
2911
  auto: [
2882
- "has-[:checked]:bg-primary-600/[.08]",
2883
- "hover:has-[:checked]:bg-primary-600/[.12]",
2884
- "focus-within:has-[:checked]:bg-primary-600/[.12]",
2912
+ "hover:bg-neutral-100",
2913
+ "has-[:checked]:bg-primary-50",
2914
+ "hover:has-[:checked]:bg-primary-50",
2915
+ "focus-within:has-[:checked]:bg-primary-50",
2885
2916
  ],
2886
2917
  },
2887
2918
  disabled: {
2919
+ // Remember to also disable the element or set tabIndex=-1 to prevent actual interaction/focus!
2888
2920
  true: ["pointer-events-none", "!bg-neutral-100", "!cursor-not-allowed"],
2889
- false: ["hover:bg-neutral-600/5", "focus-within:bg-neutral-600/5"],
2921
+ false: "", // use compoundVariants instead
2890
2922
  },
2891
2923
  focused: {
2892
2924
  true: "outline-native",
@@ -2894,6 +2926,13 @@ const cvaInteractableItem = cvaMerge("", {
2894
2926
  auto: "[&:has(:focus-visible)]:outline-native",
2895
2927
  },
2896
2928
  },
2929
+ compoundVariants: [
2930
+ {
2931
+ disabled: false,
2932
+ selected: false,
2933
+ className: ["hover:bg-neutral-600/5", "focus-within:bg-neutral-600/5"],
2934
+ },
2935
+ ],
2897
2936
  defaultVariants: {
2898
2937
  cursor: "auto",
2899
2938
  selected: "auto",
@@ -3174,7 +3213,7 @@ const cvaPage = cvaMerge(["grid", "h-full"], {
3174
3213
  const cvaPageContent = cvaMerge(["overflow-auto", "page-content", "grid", "gap-responsive-space"], {
3175
3214
  variants: {
3176
3215
  layout: {
3177
- content: "",
3216
+ content: "grid-rows-fr",
3178
3217
  "v-min-fr": ["grid-rows-min-fr"],
3179
3218
  "h-min-fr": ["grid-cols-min-fr", "sm:grid-cols-1", "sm:grid-rows-min-fr"],
3180
3219
  },
@@ -3690,7 +3729,7 @@ const cvaToggleItemText = cvaMerge(["text-ellipsis", "truncate", "flex-grow"], {
3690
3729
  * @returns {ReactElement} ToggleGroup component
3691
3730
  */
3692
3731
  const ToggleGroup = ({ list, selected, setSelected, onChange, disabled = false, size = "medium", isIconOnly = false, className, dataTestId, }) => {
3693
- return (jsx("div", { className: cvaToggleGroup(), "data-testid": dataTestId, children: list.map((item, index) => (jsx(ToggleItem, { className: twMerge(className, index === 0 ? ["rounded-l-md", "border-l"] : "", index === list.length - 1 ? ["rounded-r-md", "border-r"] : ""), dataTestId: item.dataTestId, disabled: disabled, iconName: item.iconName, isIconOnly: isIconOnly, onClick: () => {
3732
+ return (jsx("div", { className: cvaToggleGroup({ className }), "data-testid": dataTestId, children: list.map((item, index) => (jsx(ToggleItem, { className: twMerge(item.className, index === 0 ? ["rounded-l-md", "border-l"] : "", index === list.length - 1 ? ["rounded-r-md", "border-r"] : ""), dataTestId: item.dataTestId, disabled: disabled, iconName: item.iconName, isIconOnly: isIconOnly, onClick: () => {
3694
3733
  setSelected(item.id);
3695
3734
  onChange?.(item.id);
3696
3735
  }, selected: selected === item.id, size: size, text: item.text, title: item.title, tooltip: item.tooltip }, item.id))) }));
@@ -3699,7 +3738,7 @@ const ToggleGroup = ({ list, selected, setSelected, onChange, disabled = false,
3699
3738
  * Individual ToggleItem to create custom ToggleGroups
3700
3739
  */
3701
3740
  const ToggleItem = ({ title, onClick, disabled = false, isIconOnly = false, iconName, size, className, selected = false, text, tooltip, dataTestId, }) => {
3702
- return isIconOnly ? (jsx(Tooltip, { label: tooltip?.content || title, placement: tooltip?.placement || "top", children: jsx(IconButton, { className: cvaToggleItem({ className, selected }), "data-testid": dataTestId, disabled: disabled, icon: iconName ? (jsx(Icon, { className: selected ? "text-slate-600" : "text-slate-400", name: iconName, size: "small" })) : null, onClick: onClick, size: size, title: iconName, variant: "secondary" }) })) : (jsx(Tooltip, { disabled: !text?.truncate && tooltip?.content === undefined, label: tooltip?.content || title, placement: tooltip?.placement || "top", children: jsx(Button, { className: cvaToggleItem({ className, selected }), "data-testid": dataTestId, disabled: disabled, onClick: onClick, prefix: iconName ? (jsx(Icon, { className: selected ? "text-slate-600" : "text-slate-400", name: iconName, size: "small" })) : null, size: size, variant: "secondary", children: jsx("span", { className: cvaToggleItemText({ disabledAndSelected: disabled && selected, maxWidth: text?.maxWidth }), children: title }) }) }));
3741
+ return isIconOnly ? (jsx(Tooltip, { label: tooltip?.content || title, placement: tooltip?.placement || "top", children: jsx(IconButton, { className: cvaToggleItem({ className, selected }), "data-testid": dataTestId, disabled: disabled, icon: iconName ? (jsx(Icon, { className: selected ? "text-slate-600" : "text-slate-400", name: iconName, size: "small" })) : null, onClick: onClick, size: size, title: iconName, variant: "secondary" }) })) : (jsx(Tooltip, { disabled: !tooltip?.content, label: tooltip?.content, placement: tooltip?.placement || "top", children: jsx(Button, { className: cvaToggleItem({ className, selected }), "data-testid": dataTestId, disabled: disabled, onClick: onClick, prefix: iconName ? (jsx(Icon, { className: selected ? "text-slate-600" : "text-slate-400", name: iconName, size: "small" })) : null, size: size, variant: "secondary", children: jsx("span", { className: cvaToggleItemText({ disabledAndSelected: disabled && selected, maxWidth: text?.maxWidth }), children: title }) }) }));
3703
3742
  };
3704
3743
 
3705
3744
  const cvaValueBar = cvaMerge(["w-full"], {
@@ -3999,4 +4038,4 @@ const cvaClickable = cvaMerge([
3999
4038
  },
4000
4039
  });
4001
4040
 
4002
- export { ActionRenderer, Alert, Badge, Breadcrumb, BreadcrumbContainer, Button, Card, CardBody, CardFooter, CardHeader, Collapse, CompletionStatusIndicator, CopyableText, EmptyState, EmptyValue, ExternalLink, Heading, Icon, IconButton, Indicator, KPI, KPICard, MenuDivider, MenuItem, MenuList, MoreMenu, Notice, PackageNameStoryComponent, Page, PageContent, PageHeader, PageHeaderKpiMetrics, PageHeaderSecondaryActions, PageHeaderTitle, Pagination, Polygon, Popover, PopoverContent, PopoverTitle, PopoverTrigger, Portal, Prompt, ROLE_CARD, SectionHeader, Sidebar, SkeletonLines, Spacer, Spinner, StarButton, Tab, TabContent, TabList, Tabs, Tag, Text, ToggleGroup, ToggleItem, Tooltip, ValueBar, VirtualizedList, WidgetBody, WidgetEditBody, ZStack, cvaButton, cvaButtonPrefixSuffix, cvaButtonSpinner, cvaButtonSpinnerContainer, cvaClickable, cvaContainerStyles, cvaIconButton, cvaImgStyles, cvaIndicator, cvaIndicatorIcon, cvaIndicatorIconBackground, cvaIndicatorLabel, cvaIndicatorPing, cvaInteractableItem, cvaMenuItem, cvaMenuItemLabel, cvaMenuItemPrefix, cvaMenuItemStyle, cvaMenuItemSuffix, cvaPageHeader, cvaPageHeaderContainer, cvaPageHeaderHeading, cvaToggleGroup, cvaToggleItem, cvaToggleItemText, cvaVirtualizedList, cvaVirtualizedListContainer, cvaVirtualizedListItem, cvaZStackContainer, cvaZStackItem, docs, getDevicePixelRatio, getValueBarColorByValue, iconColorNames, iconPalette, useClickOutside, useContainerBreakpoints, useContinuousTimeout, useDebounce, useDevicePixelRatio, useElevatedReducer, useElevatedState, useGeometry, useHover, useIsFirstRender, useIsFullscreen, useIsTextTruncated, useOverflowItems, usePopoverContext, usePrompt, useResize, useScrollDetection, useSelfUpdatingRef, useTimeout, useViewportBreakpoints, useWatch, useWindowActivity };
4041
+ export { ActionRenderer, Alert, Badge, Breadcrumb, BreadcrumbContainer, Button, Card, CardBody, CardFooter, CardHeader, Collapse, CompletionStatusIndicator, CopyableText, EmptyState, EmptyValue, ExternalLink, Heading, Icon, IconButton, Indicator, KPI, KPICard, MenuDivider, MenuItem, MenuList, MoreMenu, Notice, PackageNameStoryComponent, Page, PageContent, PageHeader, PageHeaderKpiMetrics, PageHeaderSecondaryActions, PageHeaderTitle, Pagination, Polygon, Popover, PopoverContent, PopoverTitle, PopoverTrigger, Portal, Prompt, ROLE_CARD, SectionHeader, Sidebar, SkeletonLines, Spacer, Spinner, StarButton, Tab, TabContent, TabList, Tabs, Tag, Text, ToggleGroup, ToggleItem, Tooltip, ValueBar, VirtualizedList, WidgetBody, WidgetEditBody, ZStack, cvaButton, cvaButtonPrefixSuffix, cvaButtonSpinner, cvaButtonSpinnerContainer, cvaClickable, cvaContainerStyles, cvaIconButton, cvaImgStyles, cvaIndicator, cvaIndicatorIcon, cvaIndicatorIconBackground, cvaIndicatorLabel, cvaIndicatorPing, cvaInteractableItem, cvaMenuItem, cvaMenuItemLabel, cvaMenuItemPrefix, cvaMenuItemStyle, cvaMenuItemSuffix, cvaPageHeader, cvaPageHeaderContainer, cvaPageHeaderHeading, cvaToggleGroup, cvaToggleItem, cvaToggleItemText, cvaVirtualizedList, cvaVirtualizedListContainer, cvaVirtualizedListItem, cvaZStackContainer, cvaZStackItem, docs, getDevicePixelRatio, getValueBarColorByValue, iconColorNames, iconPalette, useClickOutside, useContainerBreakpoints, useContinuousTimeout, useDebounce, useDevicePixelRatio, useElevatedReducer, useElevatedState, useGeometry, useHover, useIsFirstRender, useIsFullscreen, useIsTextTruncated, useModifierKey, useOverflowItems, usePopoverContext, usePrompt, useResize, useScrollDetection, useSelfUpdatingRef, useTimeout, useViewportBreakpoints, useWatch, useWindowActivity };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-components",
3
- "version": "1.4.115",
3
+ "version": "1.4.118",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
@@ -18,11 +18,11 @@
18
18
  "@tanstack/react-router": "1.114.29",
19
19
  "string-ts": "^2.0.0",
20
20
  "tailwind-merge": "^2.0.0",
21
- "@trackunit/ui-design-tokens": "1.3.97",
22
- "@trackunit/css-class-variance-utilities": "1.3.97",
23
- "@trackunit/shared-utils": "1.5.97",
24
- "@trackunit/ui-icons": "1.3.97",
25
- "@trackunit/react-table-pagination": "1.3.98"
21
+ "@trackunit/ui-design-tokens": "1.3.98",
22
+ "@trackunit/css-class-variance-utilities": "1.3.98",
23
+ "@trackunit/shared-utils": "1.5.98",
24
+ "@trackunit/ui-icons": "1.3.100",
25
+ "@trackunit/react-table-pagination": "1.3.99"
26
26
  },
27
27
  "module": "./index.esm.js",
28
28
  "main": "./index.cjs.js",
@@ -2,4 +2,5 @@ export type AriaProps = {
2
2
  ariaLabel?: string;
3
3
  ariaLabelledBy?: string;
4
4
  ariaDescribedBy?: string;
5
+ ariaHidden?: boolean;
5
6
  };
@@ -487,5 +487,5 @@ export type IconProps = DiscriminatedIconProps & CommonProps & AriaProps & {
487
487
  * @param {IconProps} props - The props for the Icon component
488
488
  * @returns {ReactElement} Icon component
489
489
  */
490
- export declare const Icon: ({ name, size, className, dataTestId, color, onClick, type, style, forwardedRef, ariaLabel, fontSize, ariaLabelledBy, ariaDescribedBy, }: IconProps) => import("react/jsx-runtime").JSX.Element;
490
+ export declare const Icon: ({ name, size, className, dataTestId, color, onClick, type, style, forwardedRef, ariaLabel, fontSize, ariaLabelledBy, ariaDescribedBy, ariaHidden, }: IconProps) => import("react/jsx-runtime").JSX.Element;
491
491
  export {};
@@ -4,7 +4,7 @@ import { IconName } from "@trackunit/ui-icons";
4
4
  import { CommonProps } from "../../common/CommonProps";
5
5
  import { TooltipPlacement } from "../Tooltip/Tooltip";
6
6
  import { cvaToggleGroup } from "./ToggleGroup.variants";
7
- export interface BasicToggleGroupListProps<TSelectedId extends string = string> {
7
+ export interface BasicToggleGroupListProps<TSelectedId extends string = string> extends CommonProps {
8
8
  /**
9
9
  * Used to identify an individual button to be able to highlight the selected one.
10
10
  */
@@ -36,7 +36,6 @@ export interface BasicToggleGroupListProps<TSelectedId extends string = string>
36
36
  content?: string;
37
37
  placement?: TooltipPlacement;
38
38
  };
39
- dataTestId?: string;
40
39
  }
41
40
  export type ToggleGroupProps<TSelectedId extends string = string> = CommonProps & Omit<VariantProps<typeof cvaToggleGroup>, "className"> & {
42
41
  list: readonly BasicToggleGroupListProps<TSelectedId>[];
@@ -1,6 +1,7 @@
1
1
  import { MouseEvent, ReactNode, Ref } from "react";
2
+ import { Size } from "../../../common";
2
3
  import { ButtonCommonProps, ButtonType } from "../shared/ButtonProps";
3
- export interface ButtonProps extends ButtonCommonProps {
4
+ export interface ButtonProps extends Omit<ButtonCommonProps, "size"> {
4
5
  onClick?: (event: MouseEvent<HTMLElement>) => void;
5
6
  /**
6
7
  * Child nodes. Can be used to pass in text to be displayed on the button.
@@ -38,6 +39,7 @@ export interface ButtonProps extends ButtonCommonProps {
38
39
  * A ref for the component
39
40
  */
40
41
  ref?: Ref<HTMLButtonElement>;
42
+ size?: "extraSmall" | Size;
41
43
  }
42
44
  /**
43
45
  * Buttons are clickable elements that are used to trigger actions. They communicate calls to action to the user and allow users to interact with pages in a variety of ways. Button labels express what action will occur when the user interacts with it.
@@ -1,7 +1,7 @@
1
1
  import { ComponentType, JSX, ReactNode, Ref } from "react";
2
2
  import { Size } from "../../../common";
3
3
  import { ButtonCommonProps } from "../shared/ButtonProps";
4
- export interface IconButtonProps extends ButtonCommonProps {
4
+ export interface IconButtonProps extends Omit<ButtonCommonProps, "size"> {
5
5
  /**
6
6
  * The icon to display.
7
7
  */
@@ -15,7 +15,7 @@ export interface IconButtonProps extends ButtonCommonProps {
15
15
  /**
16
16
  * The size of the button. Defaults to "medium".
17
17
  */
18
- size?: Size;
18
+ size?: "extraSmall" | Size;
19
19
  /**
20
20
  * A ref for the component
21
21
  */
@@ -1,6 +1,6 @@
1
1
  export declare const cvaButton: (props?: ({
2
2
  variant?: "primary" | "primary-danger" | "secondary" | "secondary-danger" | "ghost" | "ghost-neutral" | null | undefined;
3
- size?: "small" | "medium" | "large" | null | undefined;
3
+ size?: "extraSmall" | "small" | "medium" | "large" | null | undefined;
4
4
  rounded?: boolean | null | undefined;
5
5
  fullWidth?: boolean | null | undefined;
6
6
  square?: boolean | null | undefined;
@@ -12,9 +12,9 @@ export declare const cvaButtonSpinner: (props?: ({
12
12
  variant?: "primary" | "primary-danger" | "secondary" | "secondary-danger" | "ghost" | "ghost-neutral" | null | undefined;
13
13
  } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
14
14
  export declare const cvaButtonPrefixSuffix: (props?: ({
15
- size?: "small" | "medium" | "large" | null | undefined;
15
+ size?: "extraSmall" | "small" | "medium" | "large" | null | undefined;
16
16
  variant?: "primary" | "primary-danger" | "secondary" | "secondary-danger" | "ghost" | "ghost-neutral" | null | undefined;
17
17
  } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
18
18
  export declare const cvaIconButton: (props?: ({
19
- size?: "small" | "medium" | "large" | null | undefined;
19
+ size?: "extraSmall" | "small" | "medium" | "large" | null | undefined;
20
20
  } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
@@ -10,6 +10,7 @@ export * from "./useHover";
10
10
  export * from "./useIsFirstRender";
11
11
  export * from "./useIsFullScreen";
12
12
  export * from "./useIsTextTruncated";
13
+ export * from "./useModifierKey";
13
14
  export * from "./useResize";
14
15
  export * from "./useScrollDetection";
15
16
  export * from "./useSelfUpdatingRef";
@@ -0,0 +1,16 @@
1
+ type ModifierKey = "Control" | "Alt" | "Shift" | "Meta";
2
+ interface UseModifierKeyProps {
3
+ /**
4
+ * Array of modifier keys to exclude from detection
5
+ */
6
+ exclude?: ModifierKey[];
7
+ }
8
+ /**
9
+ * Hook that returns true if any modifier key (Ctrl, Alt, Shift, Meta/Cmd) is pressed
10
+ *
11
+ * @param props Configuration options
12
+ * @param props.exclude Array of modifier keys to exclude from detection
13
+ * @returns {boolean} Indicates if any non-excluded modifier key is pressed
14
+ */
15
+ export declare const useModifierKey: ({ exclude }?: UseModifierKeyProps) => boolean;
16
+ export {};