@hitachivantara/uikit-react-core 5.78.0 → 5.80.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.
@@ -3,28 +3,31 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const React = require("react");
5
5
  const uikitReactUtils = require("@hitachivantara/uikit-react-utils");
6
+ const uikitStyles = require("@hitachivantara/uikit-styles");
6
7
  const generic = require("../types/generic.cjs");
7
8
  const Button_styles = require("./Button.styles.cjs");
8
- const mapVariant = (variant, theme) => {
9
- if (theme === "ds3") return variant;
10
- const deprecatedVariantMap = {
11
- secondary: "secondarySubtle",
12
- ghost: "primaryGhost"
13
- };
14
- const mappedVariant = deprecatedVariantMap[variant];
15
- return mappedVariant || variant;
16
- };
9
+ function parseVariant(variant) {
10
+ if (variant === "semantic") return ["inherit", "ghost"];
11
+ if (variant === "secondary") return ["secondary", "subtle"];
12
+ if (variant === "ghost") return ["primary", "ghost"];
13
+ if (variant === "contained" || variant === "subtle") {
14
+ return ["secondary", variant];
15
+ }
16
+ const result = variant.split(/(?=[A-Z])/);
17
+ if (!result[1]) return [result[0], "contained"];
18
+ return result.map((x) => x.toLowerCase());
19
+ }
17
20
  const HvButton = generic.fixedForwardRef(function HvButton2(props, ref) {
18
21
  const {
19
22
  classes: classesProp,
20
23
  children,
21
- variant: variantProp,
22
- // TODO - should we split into two props (color and type) in v6?
24
+ icon = false,
25
+ variant: variantProp = icon ? "secondaryGhost" : "primary",
26
+ color: colorProp,
23
27
  disabled = false,
24
28
  className,
25
29
  startIcon,
26
30
  endIcon,
27
- icon = false,
28
31
  size,
29
32
  radius,
30
33
  overrideIconColors = true,
@@ -37,11 +40,8 @@ const HvButton = generic.fixedForwardRef(function HvButton2(props, ref) {
37
40
  ...others
38
41
  } = uikitReactUtils.useDefaultProps("HvButton", props);
39
42
  const { classes, css, cx } = Button_styles.useClasses(classesProp);
40
- const { activeTheme } = uikitReactUtils.useTheme();
41
- const variant = mapVariant(
42
- variantProp ?? (icon ? "secondaryGhost" : "primary"),
43
- activeTheme?.base
44
- );
43
+ const [parsedColor, variant] = parseVariant(variantProp);
44
+ const color = colorProp ?? parsedColor;
45
45
  const handleClick = (e) => {
46
46
  if (disabled) return;
47
47
  onClickProp?.(e);
@@ -50,31 +50,24 @@ const HvButton = generic.fixedForwardRef(function HvButton2(props, ref) {
50
50
  if (disabled) return;
51
51
  onMouseDownProp?.(e);
52
52
  };
53
- const [color, type] = React.useMemo(() => {
54
- const result = variant.split(/(?=[A-Z])/);
55
- if (result[0] === "ghost" || result[0] === "semantic" || result[0] === "secondary" && !result[1])
56
- return [];
57
- return result.map((x) => x.toLowerCase());
58
- }, [variant]);
59
53
  const sizeStyles = React.useMemo(
60
- () => size ? icon ? Button_styles.getIconSizeStyles(size) : Button_styles.getSizeStyles(size) : void 0,
54
+ () => size && (icon ? Button_styles.getIconSizeStyles(size) : Button_styles.getSizeStyles(size)),
61
55
  [size, icon]
62
56
  );
63
57
  return /* @__PURE__ */ jsxRuntime.jsxs(
64
58
  Component,
65
59
  {
66
60
  ref,
67
- style: {
68
- ...style,
69
- "--HvButton-height": sizeStyles ? sizeStyles.height : "32px"
70
- },
61
+ style: uikitReactUtils.mergeStyles(style, {
62
+ "--color": color && uikitStyles.getColor(color),
63
+ "--radius": radius && uikitStyles.theme.radii[radius],
64
+ "--HvButton-height": sizeStyles?.height ?? "32px"
65
+ }),
71
66
  className: cx(
72
67
  classes.root,
73
- type && classes[type],
74
- color && css(Button_styles.getColoringStyle(color, type)),
75
68
  classes[variant],
69
+ classes[variantProp],
76
70
  // Placed after type and color CSS for DS3 override
77
- radius && css(Button_styles.getRadiusStyles(radius)),
78
71
  overrideIconColors && css(Button_styles.getOverrideColors()),
79
72
  {
80
73
  [classes.icon]: icon,
@@ -4,6 +4,9 @@ const uikitReactUtils = require("@hitachivantara/uikit-react-utils");
4
4
  const uikitStyles = require("@hitachivantara/uikit-styles");
5
5
  const focusUtils = require("../utils/focusUtils.cjs");
6
6
  const { staticClasses, useClasses } = uikitReactUtils.createClasses("HvButton", {
7
+ /**
8
+ * Classes applied to the root element
9
+ */
7
10
  root: {
8
11
  display: "inline-flex",
9
12
  alignItems: "center",
@@ -12,19 +15,22 @@ const { staticClasses, useClasses } = uikitReactUtils.createClasses("HvButton",
12
15
  cursor: "pointer",
13
16
  whiteSpace: "nowrap",
14
17
  // Background color common for almost all variants
15
- "&:hover": {
16
- backgroundColor: uikitStyles.theme.colors.containerBackgroundHover
18
+ ":where(:not($disabled))": {
19
+ ":hover, :focus-visible": {
20
+ backgroundColor: uikitStyles.theme.colors.containerBackgroundHover
21
+ }
17
22
  },
18
- "&:focus-visible": {
19
- ...focusUtils.outlineStyles,
20
- backgroundColor: uikitStyles.theme.colors.containerBackgroundHover
23
+ ":focus-visible": {
24
+ ...focusUtils.outlineStyles
21
25
  },
22
26
  // Default button - no size specified
23
27
  fontFamily: uikitStyles.theme.fontFamily.body,
24
28
  ...uikitStyles.theme.typography.label,
29
+ color: "var(--color, currentcolor)",
30
+ backgroundColor: "transparent",
25
31
  height: "var(--HvButton-height)",
26
- border: "1px solid currentcolor",
27
- borderRadius: uikitStyles.theme.radii.base,
32
+ border: "1px solid transparent",
33
+ borderRadius: `var(--radius, ${uikitStyles.theme.radii.base})`,
28
34
  padding: uikitStyles.theme.spacing(0, "sm")
29
35
  },
30
36
  startIcon: {
@@ -37,11 +43,11 @@ const { staticClasses, useClasses } = uikitReactUtils.createClasses("HvButton",
37
43
  disabled: {
38
44
  cursor: "not-allowed",
39
45
  color: uikitStyles.theme.colors.secondary_60,
40
- borderColor: uikitStyles.theme.colors.atmo3,
41
- backgroundColor: uikitStyles.theme.colors.atmo3,
42
- "&:hover, &:focus-visible": {
43
- backgroundColor: uikitStyles.theme.colors.atmo3,
44
- borderColor: uikitStyles.theme.colors.atmo3
46
+ backgroundColor: "transparent",
47
+ borderColor: "transparent",
48
+ ":hover, :focus-visible": {
49
+ backgroundColor: "transparent",
50
+ borderColor: "transparent"
45
51
  }
46
52
  },
47
53
  icon: {
@@ -52,27 +58,23 @@ const { staticClasses, useClasses } = uikitReactUtils.createClasses("HvButton",
52
58
  margin: -1
53
59
  }
54
60
  },
55
- subtle: {
56
- backgroundColor: "transparent",
57
- "&$disabled": {
58
- backgroundColor: "transparent",
59
- "&:hover, &:focus-visible": {
60
- backgroundColor: "transparent"
61
+ contained: {
62
+ color: uikitStyles.theme.colors.atmo1,
63
+ // `color-contrast(var(--color) vs ${colors.atmo1}, ${colors.base_light}, ${colors.base_dark})`,
64
+ backgroundColor: "var(--color)",
65
+ ":where(:not($disabled))": {
66
+ ":hover, :focus-visible": {
67
+ backgroundColor: "color-mix(in srgb, var(--color), black 20%)"
68
+ },
69
+ ":active": {
70
+ backgroundColor: "color-mix(in srgb, var(--color), black 30%)"
61
71
  }
62
72
  }
63
73
  },
64
- ghost: {
65
- borderColor: "transparent",
66
- backgroundColor: "transparent",
67
- "&$disabled": {
68
- borderColor: "transparent",
69
- backgroundColor: "transparent",
70
- "&:hover, &:focus-visible": {
71
- borderColor: "transparent",
72
- backgroundColor: "transparent"
73
- }
74
- }
74
+ subtle: {
75
+ borderColor: "currentcolor"
75
76
  },
77
+ ghost: {},
76
78
  semantic: {
77
79
  color: uikitStyles.theme.colors.base_dark,
78
80
  backgroundColor: "transparent",
@@ -93,40 +95,19 @@ const { staticClasses, useClasses } = uikitReactUtils.createClasses("HvButton",
93
95
  // Deprecated (DS3)
94
96
  secondary: {}
95
97
  });
96
- const getColoringStyle = (color, type) => {
97
- if (type)
98
- return {
99
- color: uikitStyles.theme.colors[color !== "warning" ? color : `${color}_140`]
100
- };
101
- const bg = uikitStyles.theme.colors[color !== "warning" ? color : `${color}_120`];
102
- const hoverBg = uikitStyles.theme.colors[color !== "warning" ? `${color}_80` : `${color}_140`];
103
- return {
104
- color: uikitStyles.theme.colors.atmo1,
105
- backgroundColor: bg,
106
- borderColor: bg,
107
- "&:hover, &:focus-visible": {
108
- backgroundColor: hoverBg,
109
- borderColor: hoverBg
110
- }
111
- };
112
- };
113
- const getRadiusStyles = (radius) => ({
114
- borderRadius: uikitStyles.theme.radii[radius]
115
- });
116
98
  const sizes = {
117
- xs: { height: "24px", space: "sm", typography: "captionLabel" },
118
- sm: { height: "24px", space: "sm", typography: "captionLabel" },
119
- md: { height: "32px", space: "sm", typography: "label" },
120
- lg: { height: "48px", space: "md", typography: "label" },
121
- xl: { height: "48px", space: "md", typography: "label" }
99
+ xs: { height: "24px", fontSize: "sm" },
100
+ sm: { height: "24px", fontSize: "sm" },
101
+ md: { height: "32px" },
102
+ lg: { height: "48px", space: "md" },
103
+ xl: { height: "48px", space: "md" }
122
104
  };
123
105
  const getSizeStyles = (size) => {
124
- const { height, space, typography } = sizes[size];
125
- const { color, ...typoProps } = uikitStyles.theme.typography[typography];
106
+ const { height, space = "sm", fontSize } = sizes[size];
126
107
  return {
127
108
  height,
128
109
  padding: uikitStyles.theme.spacing(0, space),
129
- ...typoProps
110
+ fontSize: fontSize && uikitStyles.theme.fontSizes[fontSize]
130
111
  };
131
112
  };
132
113
  const getIconSizeStyles = (size) => {
@@ -141,10 +122,8 @@ const getOverrideColors = () => ({
141
122
  fill: "currentcolor"
142
123
  }
143
124
  });
144
- exports.getColoringStyle = getColoringStyle;
145
125
  exports.getIconSizeStyles = getIconSizeStyles;
146
126
  exports.getOverrideColors = getOverrideColors;
147
- exports.getRadiusStyles = getRadiusStyles;
148
127
  exports.getSizeStyles = getSizeStyles;
149
128
  exports.staticClasses = staticClasses;
150
129
  exports.useClasses = useClasses;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const React = require("react");
5
5
  const uikitReactUtils = require("@hitachivantara/uikit-react-utils");
6
+ const uikitStyles = require("@hitachivantara/uikit-styles");
6
7
  const validationStates = require("../Forms/FormElement/validationStates.cjs");
7
8
  const useControlled = require("../hooks/useControlled.cjs");
8
9
  const useUniqueId = require("../hooks/useUniqueId.cjs");
@@ -12,6 +13,7 @@ const BaseSwitch = require("../BaseSwitch/BaseSwitch.cjs");
12
13
  const FormElement = require("../Forms/FormElement/FormElement.cjs");
13
14
  const Label = require("../Forms/Label/Label.cjs");
14
15
  const WarningText = require("../Forms/WarningText/WarningText.cjs");
16
+ const isSemantical = (color) => ["positive", "negative", "warning"].includes(color);
15
17
  const HvSwitch = React.forwardRef(
16
18
  (props, ref) => {
17
19
  const {
@@ -35,9 +37,10 @@ const HvSwitch = React.forwardRef(
35
37
  statusMessage,
36
38
  "aria-errormessage": ariaErrorMessage,
37
39
  inputProps,
40
+ color,
38
41
  ...others
39
42
  } = uikitReactUtils.useDefaultProps("HvSwitch", props);
40
- const { classes, cx } = Switch_styles.useClasses(classesProp);
43
+ const { classes, cx, css } = Switch_styles.useClasses(classesProp);
41
44
  const elementId = useUniqueId.useUniqueId(id);
42
45
  const [isChecked, setIsChecked] = useControlled.useControlled(
43
46
  checked,
@@ -115,6 +118,16 @@ const HvSwitch = React.forwardRef(
115
118
  "aria-describedby": ariaDescribedBy,
116
119
  ...inputProps
117
120
  },
121
+ ...color && {
122
+ classes: {
123
+ switchBase: css({
124
+ "&&&+.HvBaseSwitch-track,&&&.HvBaseSwitch-checked+.HvBaseSwitch-track": {
125
+ backgroundColor: uikitStyles.getColor(color),
126
+ borderColor: isSemantical(color) ? uikitStyles.getColor(`${color}_120`) : "#00000032"
127
+ }
128
+ })
129
+ }
130
+ },
118
131
  ...others
119
132
  }
120
133
  )
@@ -7,8 +7,12 @@ const Tabs_styles = require("./Tabs.styles.cjs");
7
7
  const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
8
8
  const Tabs__default = /* @__PURE__ */ _interopDefault(Tabs);
9
9
  const HvTabs = (props) => {
10
- const { classes: classesProp, ...others } = uikitReactUtils.useDefaultProps("HvTabs", props);
11
- const { classes } = Tabs_styles.useClasses(classesProp);
10
+ const {
11
+ classes: classesProp,
12
+ floating = false,
13
+ ...others
14
+ } = uikitReactUtils.useDefaultProps("HvTabs", props);
15
+ const { classes, cx } = Tabs_styles.useClasses(classesProp);
12
16
  return /* @__PURE__ */ jsxRuntime.jsx(
13
17
  Tabs__default.default,
14
18
  {
@@ -19,6 +23,7 @@ const HvTabs = (props) => {
19
23
  scroller: classes.scroller
20
24
  },
21
25
  TabIndicatorProps: { children: /* @__PURE__ */ jsxRuntime.jsx("div", {}) },
26
+ className: cx(floating && classes.floating),
22
27
  ...others
23
28
  }
24
29
  );
@@ -24,7 +24,8 @@ const { staticClasses, useClasses } = uikitReactUtils.createClasses("HvTabs", {
24
24
  "& button:first-of-type": {
25
25
  marginLeft: "3px"
26
26
  }
27
- }
27
+ },
28
+ floating: {}
28
29
  });
29
30
  exports.staticClasses = staticClasses;
30
31
  exports.useClasses = useClasses;
@@ -118,7 +118,6 @@ const BulkActions_styles = require("./BulkActions/BulkActions.styles.cjs");
118
118
  const BulkActions = require("./BulkActions/BulkActions.cjs");
119
119
  const Button = require("./Button/Button.cjs");
120
120
  const Button_styles = require("./Button/Button.styles.cjs");
121
- const types = require("./Button/types.cjs");
122
121
  const Calendar_styles = require("./Calendar/Calendar.styles.cjs");
123
122
  const Calendar = require("./Calendar/Calendar.cjs");
124
123
  const CalendarHeader_styles = require("./Calendar/CalendarHeader/CalendarHeader.styles.cjs");
@@ -503,9 +502,6 @@ exports.bulkActionsClasses = BulkActions_styles.staticClasses;
503
502
  exports.HvBulkActions = BulkActions.HvBulkActions;
504
503
  exports.HvButton = Button.HvButton;
505
504
  exports.buttonClasses = Button_styles.staticClasses;
506
- exports.buttonRadius = types.buttonRadius;
507
- exports.buttonSize = types.buttonSize;
508
- exports.buttonVariant = types.buttonVariant;
509
505
  exports.calendarClasses = Calendar_styles.staticClasses;
510
506
  exports.HvCalendar = Calendar.HvCalendar;
511
507
  exports.calendarHeaderClasses = CalendarHeader_styles.staticClasses;
@@ -1,29 +1,32 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import { useMemo } from "react";
3
- import { useDefaultProps, useTheme } from "@hitachivantara/uikit-react-utils";
3
+ import { useDefaultProps, mergeStyles } from "@hitachivantara/uikit-react-utils";
4
+ import { getColor, theme } from "@hitachivantara/uikit-styles";
4
5
  import { fixedForwardRef } from "../types/generic.js";
5
- import { useClasses, getIconSizeStyles, getSizeStyles, getColoringStyle, getRadiusStyles, getOverrideColors } from "./Button.styles.js";
6
+ import { useClasses, getIconSizeStyles, getSizeStyles, getOverrideColors } from "./Button.styles.js";
6
7
  import { staticClasses } from "./Button.styles.js";
7
- const mapVariant = (variant, theme) => {
8
- if (theme === "ds3") return variant;
9
- const deprecatedVariantMap = {
10
- secondary: "secondarySubtle",
11
- ghost: "primaryGhost"
12
- };
13
- const mappedVariant = deprecatedVariantMap[variant];
14
- return mappedVariant || variant;
15
- };
8
+ function parseVariant(variant) {
9
+ if (variant === "semantic") return ["inherit", "ghost"];
10
+ if (variant === "secondary") return ["secondary", "subtle"];
11
+ if (variant === "ghost") return ["primary", "ghost"];
12
+ if (variant === "contained" || variant === "subtle") {
13
+ return ["secondary", variant];
14
+ }
15
+ const result = variant.split(/(?=[A-Z])/);
16
+ if (!result[1]) return [result[0], "contained"];
17
+ return result.map((x) => x.toLowerCase());
18
+ }
16
19
  const HvButton = fixedForwardRef(function HvButton2(props, ref) {
17
20
  const {
18
21
  classes: classesProp,
19
22
  children,
20
- variant: variantProp,
21
- // TODO - should we split into two props (color and type) in v6?
23
+ icon = false,
24
+ variant: variantProp = icon ? "secondaryGhost" : "primary",
25
+ color: colorProp,
22
26
  disabled = false,
23
27
  className,
24
28
  startIcon,
25
29
  endIcon,
26
- icon = false,
27
30
  size,
28
31
  radius,
29
32
  overrideIconColors = true,
@@ -36,11 +39,8 @@ const HvButton = fixedForwardRef(function HvButton2(props, ref) {
36
39
  ...others
37
40
  } = useDefaultProps("HvButton", props);
38
41
  const { classes, css, cx } = useClasses(classesProp);
39
- const { activeTheme } = useTheme();
40
- const variant = mapVariant(
41
- variantProp ?? (icon ? "secondaryGhost" : "primary"),
42
- activeTheme?.base
43
- );
42
+ const [parsedColor, variant] = parseVariant(variantProp);
43
+ const color = colorProp ?? parsedColor;
44
44
  const handleClick = (e) => {
45
45
  if (disabled) return;
46
46
  onClickProp?.(e);
@@ -49,31 +49,24 @@ const HvButton = fixedForwardRef(function HvButton2(props, ref) {
49
49
  if (disabled) return;
50
50
  onMouseDownProp?.(e);
51
51
  };
52
- const [color, type] = useMemo(() => {
53
- const result = variant.split(/(?=[A-Z])/);
54
- if (result[0] === "ghost" || result[0] === "semantic" || result[0] === "secondary" && !result[1])
55
- return [];
56
- return result.map((x) => x.toLowerCase());
57
- }, [variant]);
58
52
  const sizeStyles = useMemo(
59
- () => size ? icon ? getIconSizeStyles(size) : getSizeStyles(size) : void 0,
53
+ () => size && (icon ? getIconSizeStyles(size) : getSizeStyles(size)),
60
54
  [size, icon]
61
55
  );
62
56
  return /* @__PURE__ */ jsxs(
63
57
  Component,
64
58
  {
65
59
  ref,
66
- style: {
67
- ...style,
68
- "--HvButton-height": sizeStyles ? sizeStyles.height : "32px"
69
- },
60
+ style: mergeStyles(style, {
61
+ "--color": color && getColor(color),
62
+ "--radius": radius && theme.radii[radius],
63
+ "--HvButton-height": sizeStyles?.height ?? "32px"
64
+ }),
70
65
  className: cx(
71
66
  classes.root,
72
- type && classes[type],
73
- color && css(getColoringStyle(color, type)),
74
67
  classes[variant],
68
+ classes[variantProp],
75
69
  // Placed after type and color CSS for DS3 override
76
- radius && css(getRadiusStyles(radius)),
77
70
  overrideIconColors && css(getOverrideColors()),
78
71
  {
79
72
  [classes.icon]: icon,
@@ -1 +1 @@
1
- {"version":3,"file":"Button.js","sources":["../../../src/Button/Button.tsx"],"sourcesContent":["import { useMemo } from \"react\";\nimport {\n useDefaultProps,\n useTheme,\n type ExtractNames,\n} from \"@hitachivantara/uikit-react-utils\";\nimport { HvBaseTheme } from \"@hitachivantara/uikit-styles\";\n\nimport {\n fixedForwardRef,\n PolymorphicComponentRef,\n PolymorphicRef,\n} from \"../types/generic\";\nimport {\n staticClasses as buttonClasses,\n getColoringStyle,\n getIconSizeStyles,\n getOverrideColors,\n getRadiusStyles,\n getSizeStyles,\n useClasses,\n} from \"./Button.styles\";\nimport { HvButtonRadius, HvButtonSize, HvButtonVariant } from \"./types\";\n\nexport { buttonClasses };\n\nexport type HvButtonClasses = ExtractNames<typeof useClasses>;\n\nexport type HvButtonProps<C extends React.ElementType = \"button\"> =\n PolymorphicComponentRef<\n C,\n {\n /** Use the variant prop to change the visual style of the button. */\n variant?: HvButtonVariant;\n /** Whether the button is an icon-only button. */\n icon?: boolean;\n /** Whether the button is disabled or not. */\n disabled?: boolean;\n /** Class names to be applied. */\n className?: string;\n /** Element placed before the children. */\n startIcon?: React.ReactNode;\n /** Element placed after the children. */\n endIcon?: React.ReactNode;\n /** Button size. */\n size?: HvButtonSize;\n /** Button border radius. */\n radius?: HvButtonRadius;\n /** Defines the default colors of the button are forced into the icon. */\n overrideIconColors?: boolean;\n /** A Jss Object used to override or extend the styles applied. */\n classes?: HvButtonClasses;\n /** Whether the button is selected or not. */\n selected?: boolean;\n /**\n * Whether the button is focusable when disabled.\n * Without this property, the accessibility of the button decreases when disabled since it's not read by screen readers.\n * Set this property to `true` when you need the button to still be focusable when disabled for accessibility purposes.\n */\n focusableWhenDisabled?: boolean;\n }\n >;\n\n/**\n * Normalize the button variant. It's meant to give us some retro-compatibility with\n * the DS 3.6 API.\n * @returns the normalized variant in DS 5 API\n */\nconst mapVariant = (\n variant: HvButtonVariant,\n theme?: HvBaseTheme,\n): HvButtonVariant => {\n if (theme === \"ds3\") return variant;\n\n const deprecatedVariantMap: Record<string, HvButtonVariant> = {\n secondary: \"secondarySubtle\",\n ghost: \"primaryGhost\",\n };\n\n const mappedVariant = deprecatedVariantMap[variant];\n\n if (import.meta.env.DEV && mappedVariant) {\n // eslint-disable-next-line no-console\n console.warn(\n `Button variant '${variant}' is deprecated. Please use '${mappedVariant}'.`,\n );\n }\n\n return mappedVariant || variant;\n};\n\n/**\n * Button component is used to trigger an action or event.\n */\nexport const HvButton = fixedForwardRef(function HvButton<\n C extends React.ElementType = \"button\",\n>(props: HvButtonProps<C>, ref: PolymorphicRef<C>) {\n const {\n classes: classesProp,\n children,\n variant: variantProp, // TODO - should we split into two props (color and type) in v6?\n disabled = false,\n className,\n startIcon,\n endIcon,\n icon = false,\n size,\n radius,\n overrideIconColors = true,\n component: Component = \"button\",\n focusableWhenDisabled,\n onClick: onClickProp,\n onMouseDown: onMouseDownProp,\n selected,\n style,\n ...others\n } = useDefaultProps(\"HvButton\", props);\n const { classes, css, cx } = useClasses(classesProp);\n const { activeTheme } = useTheme();\n const variant = mapVariant(\n variantProp ?? (icon ? \"secondaryGhost\" : \"primary\"),\n activeTheme?.base,\n );\n\n const handleClick: HvButtonProps[\"onClick\"] = (e) => {\n if (disabled) return;\n onClickProp?.(e);\n };\n\n const handleMouseDown: HvButtonProps[\"onMouseDown\"] = (e) => {\n if (disabled) return;\n onMouseDownProp?.(e);\n };\n\n const [color, type] = useMemo(() => {\n const result = variant.split(/(?=[A-Z])/);\n if (\n result[0] === \"ghost\" ||\n result[0] === \"semantic\" ||\n (result[0] === \"secondary\" && !result[1])\n )\n return [];\n return result.map((x) => x.toLowerCase());\n }, [variant]);\n\n const sizeStyles = useMemo(\n () =>\n size ? (icon ? getIconSizeStyles(size) : getSizeStyles(size)) : undefined,\n [size, icon],\n );\n\n return (\n <Component\n ref={ref}\n style={{\n ...style,\n \"--HvButton-height\": sizeStyles ? sizeStyles.height : \"32px\",\n }}\n className={cx(\n classes.root,\n type && classes[type as keyof HvButtonClasses],\n color && css(getColoringStyle(color, type)),\n classes[variant as keyof HvButtonClasses], // Placed after type and color CSS for DS3 override\n radius && css(getRadiusStyles(radius)),\n overrideIconColors && css(getOverrideColors()),\n {\n [classes.icon]: icon,\n [classes.disabled]: disabled,\n },\n sizeStyles && css(sizeStyles),\n className,\n )}\n data-color={color}\n onClick={handleClick}\n onMouseDown={handleMouseDown}\n {...(Component === \"button\" && { type: \"button\" })}\n {...(disabled && {\n disabled: !focusableWhenDisabled,\n tabIndex: focusableWhenDisabled ? 0 : -1,\n \"aria-disabled\": true,\n })}\n {...(selected && { \"aria-pressed\": selected })}\n {...others}\n >\n {startIcon && <span className={classes.startIcon}>{startIcon}</span>}\n {children}\n {endIcon && <span className={classes.endIcon}>{endIcon}</span>}\n </Component>\n );\n});\n"],"names":["HvButton"],"mappings":";;;;;;AAoEA,MAAM,aAAa,CACjB,SACA,UACoB;AAChB,MAAA,UAAU,MAAc,QAAA;AAE5B,QAAM,uBAAwD;AAAA,IAC5D,WAAW;AAAA,IACX,OAAO;AAAA,EAAA;AAGH,QAAA,gBAAgB,qBAAqB,OAAO;AASlD,SAAO,iBAAiB;AAC1B;AAKO,MAAM,WAAW,gBAAgB,SAASA,UAE/C,OAAyB,KAAwB;AAC3C,QAAA;AAAA,IACJ,SAAS;AAAA,IACT;AAAA,IACA,SAAS;AAAA;AAAA,IACT,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA,qBAAqB;AAAA,IACrB,WAAW,YAAY;AAAA,IACvB;AAAA,IACA,SAAS;AAAA,IACT,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,IACD,gBAAgB,YAAY,KAAK;AACrC,QAAM,EAAE,SAAS,KAAK,GAAG,IAAI,WAAW,WAAW;AAC7C,QAAA,EAAE,gBAAgB;AACxB,QAAM,UAAU;AAAA,IACd,gBAAgB,OAAO,mBAAmB;AAAA,IAC1C,aAAa;AAAA,EAAA;AAGT,QAAA,cAAwC,CAAC,MAAM;AACnD,QAAI,SAAU;AACd,kBAAc,CAAC;AAAA,EAAA;AAGX,QAAA,kBAAgD,CAAC,MAAM;AAC3D,QAAI,SAAU;AACd,sBAAkB,CAAC;AAAA,EAAA;AAGrB,QAAM,CAAC,OAAO,IAAI,IAAI,QAAQ,MAAM;AAC5B,UAAA,SAAS,QAAQ,MAAM,WAAW;AACxC,QACE,OAAO,CAAC,MAAM,WACd,OAAO,CAAC,MAAM,cACb,OAAO,CAAC,MAAM,eAAe,CAAC,OAAO,CAAC;AAEvC,aAAO;AACT,WAAO,OAAO,IAAI,CAAC,MAAM,EAAE,aAAa;AAAA,EAAA,GACvC,CAAC,OAAO,CAAC;AAEZ,QAAM,aAAa;AAAA,IACjB,MACE,OAAQ,OAAO,kBAAkB,IAAI,IAAI,cAAc,IAAI,IAAK;AAAA,IAClE,CAAC,MAAM,IAAI;AAAA,EAAA;AAIX,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,OAAO;AAAA,QACL,GAAG;AAAA,QACH,qBAAqB,aAAa,WAAW,SAAS;AAAA,MACxD;AAAA,MACA,WAAW;AAAA,QACT,QAAQ;AAAA,QACR,QAAQ,QAAQ,IAA6B;AAAA,QAC7C,SAAS,IAAI,iBAAiB,OAAO,IAAI,CAAC;AAAA,QAC1C,QAAQ,OAAgC;AAAA;AAAA,QACxC,UAAU,IAAI,gBAAgB,MAAM,CAAC;AAAA,QACrC,sBAAsB,IAAI,mBAAmB;AAAA,QAC7C;AAAA,UACE,CAAC,QAAQ,IAAI,GAAG;AAAA,UAChB,CAAC,QAAQ,QAAQ,GAAG;AAAA,QACtB;AAAA,QACA,cAAc,IAAI,UAAU;AAAA,QAC5B;AAAA,MACF;AAAA,MACA,cAAY;AAAA,MACZ,SAAS;AAAA,MACT,aAAa;AAAA,MACZ,GAAI,cAAc,YAAY,EAAE,MAAM,SAAS;AAAA,MAC/C,GAAI,YAAY;AAAA,QACf,UAAU,CAAC;AAAA,QACX,UAAU,wBAAwB,IAAI;AAAA,QACtC,iBAAiB;AAAA,MACnB;AAAA,MACC,GAAI,YAAY,EAAE,gBAAgB,SAAS;AAAA,MAC3C,GAAG;AAAA,MAEH,UAAA;AAAA,QAAA,aAAc,oBAAA,QAAA,EAAK,WAAW,QAAQ,WAAY,UAAU,WAAA;AAAA,QAC5D;AAAA,QACA,WAAY,oBAAA,QAAA,EAAK,WAAW,QAAQ,SAAU,UAAQ,SAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAG7D,CAAC;"}
1
+ {"version":3,"file":"Button.js","sources":["../../../src/Button/Button.tsx"],"sourcesContent":["import { useMemo } from \"react\";\nimport {\n mergeStyles,\n useDefaultProps,\n type ExtractNames,\n} from \"@hitachivantara/uikit-react-utils\";\nimport {\n getColor,\n HvColorAny,\n HvRadius,\n HvSize,\n theme,\n} from \"@hitachivantara/uikit-styles\";\n\nimport {\n fixedForwardRef,\n PolymorphicComponentRef,\n PolymorphicRef,\n} from \"../types/generic\";\nimport {\n getIconSizeStyles,\n getOverrideColors,\n getSizeStyles,\n staticClasses,\n useClasses,\n} from \"./Button.styles\";\nimport { HvButtonVariant } from \"./types\";\n\ntype Variant = \"contained\" | \"subtle\" | \"ghost\";\n\nexport { staticClasses as buttonClasses };\n\nexport type HvButtonClasses = ExtractNames<typeof useClasses>;\n\nexport type HvButtonProps<C extends React.ElementType = \"button\"> =\n PolymorphicComponentRef<\n C,\n {\n /** Use the variant prop to change the visual style of the button. */\n variant?: HvButtonVariant;\n /** Whether the button is an icon-only button. */\n icon?: boolean;\n /** Whether the button is disabled or not. */\n disabled?: boolean;\n /** Class names to be applied. */\n className?: string;\n /** Element placed before the children. */\n startIcon?: React.ReactNode;\n /** Element placed after the children. */\n endIcon?: React.ReactNode;\n /** Color of the button. */\n color?: HvColorAny;\n /** Button size. */\n size?: HvSize;\n /** Button border radius. */\n radius?: HvRadius;\n /** Defines the default colors of the button are forced into the icon. */\n overrideIconColors?: boolean;\n /** A Jss Object used to override or extend the styles applied. */\n classes?: HvButtonClasses;\n /** Whether the button is selected or not. */\n selected?: boolean;\n /**\n * Whether the button is focusable when disabled.\n * Without this property, the accessibility of the button decreases when disabled since it's not read by screen readers.\n * Set this property to `true` when you need the button to still be focusable when disabled for accessibility purposes.\n */\n focusableWhenDisabled?: boolean;\n }\n >;\n\nfunction parseVariant(variant: HvButtonVariant): [HvColorAny, Variant] {\n const deprecatedVariantMap: Record<string, HvButtonVariant> = {\n secondary: \"secondarySubtle\",\n };\n\n const mappedVariant = deprecatedVariantMap[variant];\n\n if (import.meta.env.DEV && mappedVariant) {\n // eslint-disable-next-line no-console\n console.warn(\n `HvButton variant '${variant}' is deprecated. Please use '${mappedVariant}'.`,\n );\n }\n\n if (variant === \"semantic\") return [\"inherit\", \"ghost\"];\n if (variant === \"secondary\") return [\"secondary\", \"subtle\"];\n if (variant === \"ghost\") return [\"primary\", \"ghost\"];\n if (variant === \"contained\" || variant === \"subtle\") {\n return [\"secondary\", variant];\n }\n\n const result = variant.split(/(?=[A-Z])/);\n if (!result[1]) return [result[0], \"contained\"];\n\n return result.map((x) => x.toLowerCase()) as [HvColorAny, Variant];\n}\n/**\n * Button component is used to trigger an action or event.\n */\nexport const HvButton = fixedForwardRef(function HvButton<\n C extends React.ElementType = \"button\",\n>(props: HvButtonProps<C>, ref: PolymorphicRef<C>) {\n const {\n classes: classesProp,\n children,\n icon = false,\n variant: variantProp = icon ? \"secondaryGhost\" : \"primary\",\n color: colorProp,\n disabled = false,\n className,\n startIcon,\n endIcon,\n size,\n radius,\n overrideIconColors = true,\n component: Component = \"button\",\n focusableWhenDisabled,\n onClick: onClickProp,\n onMouseDown: onMouseDownProp,\n selected,\n style,\n ...others\n } = useDefaultProps(\"HvButton\", props);\n const { classes, css, cx } = useClasses(classesProp);\n const [parsedColor, variant] = parseVariant(variantProp);\n const color = colorProp ?? parsedColor;\n\n const handleClick: HvButtonProps[\"onClick\"] = (e) => {\n if (disabled) return;\n onClickProp?.(e);\n };\n\n const handleMouseDown: HvButtonProps[\"onMouseDown\"] = (e) => {\n if (disabled) return;\n onMouseDownProp?.(e);\n };\n\n const sizeStyles = useMemo(\n () => size && (icon ? getIconSizeStyles(size) : getSizeStyles(size)),\n [size, icon],\n );\n\n return (\n <Component\n ref={ref}\n style={mergeStyles(style, {\n \"--color\": color && getColor(color),\n \"--radius\": radius && theme.radii[radius],\n \"--HvButton-height\": sizeStyles?.height ?? \"32px\",\n })}\n className={cx(\n classes.root,\n classes[variant],\n classes[variantProp as keyof HvButtonClasses], // Placed after type and color CSS for DS3 override\n overrideIconColors && css(getOverrideColors()),\n {\n [classes.icon]: icon,\n [classes.disabled]: disabled,\n },\n sizeStyles && css(sizeStyles),\n className,\n )}\n data-color={color}\n onClick={handleClick}\n onMouseDown={handleMouseDown}\n {...(Component === \"button\" && { type: \"button\" })}\n {...(disabled && {\n disabled: !focusableWhenDisabled,\n tabIndex: focusableWhenDisabled ? 0 : -1,\n \"aria-disabled\": true,\n })}\n {...(selected && { \"aria-pressed\": selected })}\n {...others}\n >\n {startIcon && <span className={classes.startIcon}>{startIcon}</span>}\n {children}\n {endIcon && <span className={classes.endIcon}>{endIcon}</span>}\n </Component>\n );\n});\n"],"names":["HvButton"],"mappings":";;;;;;;AAuEA,SAAS,aAAa,SAAiD;AAcrE,MAAI,YAAY,WAAmB,QAAA,CAAC,WAAW,OAAO;AACtD,MAAI,YAAY,YAAoB,QAAA,CAAC,aAAa,QAAQ;AAC1D,MAAI,YAAY,QAAgB,QAAA,CAAC,WAAW,OAAO;AAC/C,MAAA,YAAY,eAAe,YAAY,UAAU;AAC5C,WAAA,CAAC,aAAa,OAAO;AAAA,EAC9B;AAEM,QAAA,SAAS,QAAQ,MAAM,WAAW;AACpC,MAAA,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,WAAW;AAE9C,SAAO,OAAO,IAAI,CAAC,MAAM,EAAE,aAAa;AAC1C;AAIO,MAAM,WAAW,gBAAgB,SAASA,UAE/C,OAAyB,KAAwB;AAC3C,QAAA;AAAA,IACJ,SAAS;AAAA,IACT;AAAA,IACA,OAAO;AAAA,IACP,SAAS,cAAc,OAAO,mBAAmB;AAAA,IACjD,OAAO;AAAA,IACP,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,qBAAqB;AAAA,IACrB,WAAW,YAAY;AAAA,IACvB;AAAA,IACA,SAAS;AAAA,IACT,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,IACD,gBAAgB,YAAY,KAAK;AACrC,QAAM,EAAE,SAAS,KAAK,GAAG,IAAI,WAAW,WAAW;AACnD,QAAM,CAAC,aAAa,OAAO,IAAI,aAAa,WAAW;AACvD,QAAM,QAAQ,aAAa;AAErB,QAAA,cAAwC,CAAC,MAAM;AACnD,QAAI,SAAU;AACd,kBAAc,CAAC;AAAA,EAAA;AAGX,QAAA,kBAAgD,CAAC,MAAM;AAC3D,QAAI,SAAU;AACd,sBAAkB,CAAC;AAAA,EAAA;AAGrB,QAAM,aAAa;AAAA,IACjB,MAAM,SAAS,OAAO,kBAAkB,IAAI,IAAI,cAAc,IAAI;AAAA,IAClE,CAAC,MAAM,IAAI;AAAA,EAAA;AAIX,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,OAAO,YAAY,OAAO;AAAA,QACxB,WAAW,SAAS,SAAS,KAAK;AAAA,QAClC,YAAY,UAAU,MAAM,MAAM,MAAM;AAAA,QACxC,qBAAqB,YAAY,UAAU;AAAA,MAAA,CAC5C;AAAA,MACD,WAAW;AAAA,QACT,QAAQ;AAAA,QACR,QAAQ,OAAO;AAAA,QACf,QAAQ,WAAoC;AAAA;AAAA,QAC5C,sBAAsB,IAAI,mBAAmB;AAAA,QAC7C;AAAA,UACE,CAAC,QAAQ,IAAI,GAAG;AAAA,UAChB,CAAC,QAAQ,QAAQ,GAAG;AAAA,QACtB;AAAA,QACA,cAAc,IAAI,UAAU;AAAA,QAC5B;AAAA,MACF;AAAA,MACA,cAAY;AAAA,MACZ,SAAS;AAAA,MACT,aAAa;AAAA,MACZ,GAAI,cAAc,YAAY,EAAE,MAAM,SAAS;AAAA,MAC/C,GAAI,YAAY;AAAA,QACf,UAAU,CAAC;AAAA,QACX,UAAU,wBAAwB,IAAI;AAAA,QACtC,iBAAiB;AAAA,MACnB;AAAA,MACC,GAAI,YAAY,EAAE,gBAAgB,SAAS;AAAA,MAC3C,GAAG;AAAA,MAEH,UAAA;AAAA,QAAA,aAAc,oBAAA,QAAA,EAAK,WAAW,QAAQ,WAAY,UAAU,WAAA;AAAA,QAC5D;AAAA,QACA,WAAY,oBAAA,QAAA,EAAK,WAAW,QAAQ,SAAU,UAAQ,SAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAG7D,CAAC;"}
@@ -2,6 +2,9 @@ import { createClasses } from "@hitachivantara/uikit-react-utils";
2
2
  import { theme } from "@hitachivantara/uikit-styles";
3
3
  import { outlineStyles } from "../utils/focusUtils.js";
4
4
  const { staticClasses, useClasses } = createClasses("HvButton", {
5
+ /**
6
+ * Classes applied to the root element
7
+ */
5
8
  root: {
6
9
  display: "inline-flex",
7
10
  alignItems: "center",
@@ -10,19 +13,22 @@ const { staticClasses, useClasses } = createClasses("HvButton", {
10
13
  cursor: "pointer",
11
14
  whiteSpace: "nowrap",
12
15
  // Background color common for almost all variants
13
- "&:hover": {
14
- backgroundColor: theme.colors.containerBackgroundHover
16
+ ":where(:not($disabled))": {
17
+ ":hover, :focus-visible": {
18
+ backgroundColor: theme.colors.containerBackgroundHover
19
+ }
15
20
  },
16
- "&:focus-visible": {
17
- ...outlineStyles,
18
- backgroundColor: theme.colors.containerBackgroundHover
21
+ ":focus-visible": {
22
+ ...outlineStyles
19
23
  },
20
24
  // Default button - no size specified
21
25
  fontFamily: theme.fontFamily.body,
22
26
  ...theme.typography.label,
27
+ color: "var(--color, currentcolor)",
28
+ backgroundColor: "transparent",
23
29
  height: "var(--HvButton-height)",
24
- border: "1px solid currentcolor",
25
- borderRadius: theme.radii.base,
30
+ border: "1px solid transparent",
31
+ borderRadius: `var(--radius, ${theme.radii.base})`,
26
32
  padding: theme.spacing(0, "sm")
27
33
  },
28
34
  startIcon: {
@@ -35,11 +41,11 @@ const { staticClasses, useClasses } = createClasses("HvButton", {
35
41
  disabled: {
36
42
  cursor: "not-allowed",
37
43
  color: theme.colors.secondary_60,
38
- borderColor: theme.colors.atmo3,
39
- backgroundColor: theme.colors.atmo3,
40
- "&:hover, &:focus-visible": {
41
- backgroundColor: theme.colors.atmo3,
42
- borderColor: theme.colors.atmo3
44
+ backgroundColor: "transparent",
45
+ borderColor: "transparent",
46
+ ":hover, :focus-visible": {
47
+ backgroundColor: "transparent",
48
+ borderColor: "transparent"
43
49
  }
44
50
  },
45
51
  icon: {
@@ -50,27 +56,23 @@ const { staticClasses, useClasses } = createClasses("HvButton", {
50
56
  margin: -1
51
57
  }
52
58
  },
53
- subtle: {
54
- backgroundColor: "transparent",
55
- "&$disabled": {
56
- backgroundColor: "transparent",
57
- "&:hover, &:focus-visible": {
58
- backgroundColor: "transparent"
59
+ contained: {
60
+ color: theme.colors.atmo1,
61
+ // `color-contrast(var(--color) vs ${colors.atmo1}, ${colors.base_light}, ${colors.base_dark})`,
62
+ backgroundColor: "var(--color)",
63
+ ":where(:not($disabled))": {
64
+ ":hover, :focus-visible": {
65
+ backgroundColor: "color-mix(in srgb, var(--color), black 20%)"
66
+ },
67
+ ":active": {
68
+ backgroundColor: "color-mix(in srgb, var(--color), black 30%)"
59
69
  }
60
70
  }
61
71
  },
62
- ghost: {
63
- borderColor: "transparent",
64
- backgroundColor: "transparent",
65
- "&$disabled": {
66
- borderColor: "transparent",
67
- backgroundColor: "transparent",
68
- "&:hover, &:focus-visible": {
69
- borderColor: "transparent",
70
- backgroundColor: "transparent"
71
- }
72
- }
72
+ subtle: {
73
+ borderColor: "currentcolor"
73
74
  },
75
+ ghost: {},
74
76
  semantic: {
75
77
  color: theme.colors.base_dark,
76
78
  backgroundColor: "transparent",
@@ -91,40 +93,19 @@ const { staticClasses, useClasses } = createClasses("HvButton", {
91
93
  // Deprecated (DS3)
92
94
  secondary: {}
93
95
  });
94
- const getColoringStyle = (color, type) => {
95
- if (type)
96
- return {
97
- color: theme.colors[color !== "warning" ? color : `${color}_140`]
98
- };
99
- const bg = theme.colors[color !== "warning" ? color : `${color}_120`];
100
- const hoverBg = theme.colors[color !== "warning" ? `${color}_80` : `${color}_140`];
101
- return {
102
- color: theme.colors.atmo1,
103
- backgroundColor: bg,
104
- borderColor: bg,
105
- "&:hover, &:focus-visible": {
106
- backgroundColor: hoverBg,
107
- borderColor: hoverBg
108
- }
109
- };
110
- };
111
- const getRadiusStyles = (radius) => ({
112
- borderRadius: theme.radii[radius]
113
- });
114
96
  const sizes = {
115
- xs: { height: "24px", space: "sm", typography: "captionLabel" },
116
- sm: { height: "24px", space: "sm", typography: "captionLabel" },
117
- md: { height: "32px", space: "sm", typography: "label" },
118
- lg: { height: "48px", space: "md", typography: "label" },
119
- xl: { height: "48px", space: "md", typography: "label" }
97
+ xs: { height: "24px", fontSize: "sm" },
98
+ sm: { height: "24px", fontSize: "sm" },
99
+ md: { height: "32px" },
100
+ lg: { height: "48px", space: "md" },
101
+ xl: { height: "48px", space: "md" }
120
102
  };
121
103
  const getSizeStyles = (size) => {
122
- const { height, space, typography } = sizes[size];
123
- const { color, ...typoProps } = theme.typography[typography];
104
+ const { height, space = "sm", fontSize } = sizes[size];
124
105
  return {
125
106
  height,
126
107
  padding: theme.spacing(0, space),
127
- ...typoProps
108
+ fontSize: fontSize && theme.fontSizes[fontSize]
128
109
  };
129
110
  };
130
111
  const getIconSizeStyles = (size) => {
@@ -140,10 +121,8 @@ const getOverrideColors = () => ({
140
121
  }
141
122
  });
142
123
  export {
143
- getColoringStyle,
144
124
  getIconSizeStyles,
145
125
  getOverrideColors,
146
- getRadiusStyles,
147
126
  getSizeStyles,
148
127
  staticClasses,
149
128
  useClasses