vcc-ui
Version:
A React library for building user interfaces at Volvo Cars
345 lines (344 loc) • 10.9 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Button = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _react = _interopRequireWildcard(require("react"));
var _useConfig = require("../../config/use-config");
var _sizeToRem = require("../../utils/size-to-rem");
var _block = require("../block");
var _click = require("../click");
var _inline = require("../inline");
var _spinner = require("../spinner");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
/**
* @deprecated Use a `<button>` or `<a>` element instead. See also [Button](https://developer.volvocars.com/design-system/web/?path=/docs/components-button-filled--docs)
*/
const Button = exports.Button = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
let {
children,
loading,
disabled,
intent = 'primary',
variant = 'default',
size = 'medium',
textTransform = 'first-letter-uppercase',
...props
} = _ref;
const {
v3Button
} = (0, _useConfig.useConfig)();
return /*#__PURE__*/_react.default.createElement(_block.Block, {
extend: {
width: '100%'
}
}, /*#__PURE__*/_react.default.createElement(_click.Click, (0, _extends2.default)({
ref: ref
}, props, {
onTouchStart: () => {},
disabled: disabled || loading,
extend: buttonCSS({
intent,
variant,
size,
disabled,
loading,
v3Button
})
}), loading && /*#__PURE__*/_react.default.createElement(_block.Block, {
extend: {
position: 'absolute',
margin: '0 auto'
}
}, /*#__PURE__*/_react.default.createElement(_spinner.Spinner, {
color: "inherit",
size: 24
})), loading ? /*#__PURE__*/_react.default.createElement(_inline.Inline, {
extend: {
...constrainedText({
textTransform
}),
visibility: 'hidden'
}
}, /*#__PURE__*/_react.default.createElement(InnerButton, null, children)) : /*#__PURE__*/_react.default.createElement(_inline.Inline, {
extend: constrainedText({
textTransform
})
}, /*#__PURE__*/_react.default.createElement(InnerButton, null, children))));
});
const InnerButton = _ref2 => {
let {
children
} = _ref2;
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, children);
};
Button.displayName = 'Button';
Button.propTypes = {
/** A JSX node */
children: _propTypes.default.node,
intent: _propTypes.default.oneOf(['primary', 'secondary', 'destructive']),
variant: _propTypes.default.oneOf(['default', 'outline', 'text']),
loading: _propTypes.default.bool,
disabled: _propTypes.default.bool,
/** Adding href changes the HTML element from `<button>` to `<a>` */
href: _propTypes.default.string,
size: _propTypes.default.oneOf(['small', 'medium']),
textTransform: _propTypes.default.oneOf(['none', 'capitalize', 'first-letter-uppercase'])
};
const padding = (x, y) => ({
padding: `${x}px ${y}px`
});
const getIntentStyleMap = _ref3 => {
let {
tokens
} = _ref3;
return {
primary: {
color: tokens.buttonPrimaryColor,
defaultForeground: tokens.buttonPrimaryForeground,
highlight: tokens.buttonPrimaryHoverBackground,
activeBackground: tokens.buttonPrimaryActiveBackground,
outlineColor: tokens.buttonPrimaryOutlineColor
},
secondary: {
color: tokens.buttonSecondaryColor,
defaultForeground: tokens.buttonSecondaryForeground,
highlight: tokens.buttonSecondaryHoverBackground,
activeBackground: tokens.buttonSecondaryActiveBackground
},
destructive: {
color: tokens.buttonDestructiveColor,
defaultForeground: tokens.buttonDestructiveForeground,
highlight: tokens.buttonDestructiveHoverBackground,
activeBackground: tokens.buttonDestructiveActiveBackground
}
};
};
const constrainedText = _ref4 => {
let {
textTransform
} = _ref4;
return {
display: 'inline',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
maxWidth: 'calc(100%)',
extend: [{
condition: textTransform === 'capitalize',
style: {
textTransform: 'capitalize'
}
}, {
condition: textTransform === 'none',
style: {
textTransform: 'none'
}
}, {
condition: textTransform === 'first-letter-uppercase',
style: {
'&::first-letter': {
textTransform: 'uppercase'
}
}
}]
};
};
const buttonCSS = _ref5 => {
let {
intent,
variant,
size,
disabled,
loading,
v3Button
} = _ref5;
return _ref6 => {
let {
theme
} = _ref6;
const intentStyleMap = getIntentStyleMap(theme);
const {
color,
// @ts-ignore
outlineColor,
defaultForeground,
highlight
} = intentStyleMap[intent] || intentStyleMap.primary;
return {
display: 'inline-flex',
minWidth: 96,
width: '100%',
justifyContent: 'center',
userSelect: 'none',
WebkitTouchCallout: 'none',
alignItems: 'baseline',
...padding(theme.tokens.buttonPaddingVertical, v3Button ? 24 : theme.tokens.buttonPaddingHorizontal),
fontFamily: theme.fontTypes.NOVUM,
textAlign: 'center',
fontSize: (0, _sizeToRem.sizeToRem)(2),
lineHeight: '22px',
transitionDuration: disabled ? '0ms' : '100ms, 300ms',
transitionTimingFunction: 'ease-out',
transitionProperty: 'transform, background, fill, stroke, color, border-color, box-shadow',
borderColor: 'transparent',
borderStyle: 'solid',
borderWidth: 1,
borderRadius: 4,
fontWeight: 500,
letterSpacing: '0.02em',
extend: [{
condition: v3Button,
style: {
fontSize: (0, _sizeToRem.sizeToRem)(1.75),
textTransform: 'uppercase'
}
}, {
condition: size === 'small',
style: {
fontSize: (0, _sizeToRem.sizeToRem)(1.5),
lineHeight: '20px',
...padding(theme.tokens.buttonPaddingVertical - theme.baselineGrid / 2 + 1, theme.tokens.buttonPaddingHorizontal - theme.baselineGrid),
'> div svg': {
height: theme.baselineGrid * 3,
width: theme.baselineGrid * 3
}
}
}, {
condition: size === 'large',
style: {
fontSize: (0, _sizeToRem.sizeToRem)(2),
lineHeight: '24px',
...padding(theme.tokens.buttonPaddingVertical * 2 - 1, theme.tokens.buttonPaddingHorizontal + theme.baselineGrid * 2),
'> div svg': {
height: theme.baselineGrid * 5,
width: theme.baselineGrid * 5
}
}
}, {
condition: loading,
style: {
justifyContent: 'center',
alignItems: 'center',
pointerEvents: 'none'
}
}, {
condition: !disabled,
style: {
'@media (hover: hover)': {
extend: [{
condition: variant === 'default',
style: {
':hover': {
borderColor: highlight,
background: highlight
}
}
}, {
condition: variant === 'outline',
style: {
':hover': {
background: color,
color: defaultForeground,
borderColor: color,
fill: defaultForeground,
stroke: defaultForeground
}
}
}, {
condition: variant === 'text',
style: {
':hover': {
color: highlight
}
}
}]
},
':active': {
extend: [{
condition: true,
style: {
transform: 'scale(0.95, 0.9)'
}
}, {
condition: variant === 'default',
style: {
borderColor: highlight,
background: highlight
}
}, {
condition: variant === 'outline',
style: {
background: color,
color: defaultForeground,
borderColor: color,
fill: defaultForeground,
stroke: defaultForeground
}
}, {
condition: variant === 'text',
style: {
color: highlight
}
}]
},
extend: [{
condition: variant === 'default',
style: {
borderColor: color,
background: color,
color: defaultForeground,
fill: defaultForeground,
stroke: defaultForeground
}
}, {
condition: variant === 'outline',
style: {
borderColor: outlineColor || color,
color: outlineColor || color,
fill: outlineColor || color,
stroke: outlineColor || color
}
}, {
condition: variant === 'text',
style: {
borderColor: 'transparent',
fill: color,
color: color,
stroke: color
}
}]
}
}, {
condition: disabled,
style: {
opacity: 0.3,
cursor: 'default',
fill: theme.color.foreground.secondary,
stroke: theme.color.foreground.secondary,
color: color,
':focus-visible': {
outlineWidth: 0
},
extend: [{
condition: variant === 'default',
style: {
borderColor: color,
background: color,
color: defaultForeground
}
}, {
condition: variant === 'outline',
style: {
borderColor: color
}
}]
}
}]
};
};
};