UNPKG

vcc-ui

Version:

A React library for building user interfaces at Volvo Cars

345 lines (344 loc) 10.9 kB
"use strict"; 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 } }] } }] }; }; };