vcc-ui
Version:
VCC UI is a collection of React UI Components that can be used for developing front-end applications at Volvo Car Corporation.
332 lines (314 loc) • 11.8 kB
JavaScript
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
import React from 'react';
import PropTypes from 'prop-types';
import { useFela } from 'react-fela';
import { Click } from '../click';
import { Block } from '../block';
import { Arrow } from '../arrow';
import { Icon } from '../icon';
import { Inline } from '../inline';
import { Spinner } from '../spinner';
import { getThemeStyle } from '../../get-theme-style';
import { sizeToRem } from '../../size-to-rem';
import { deprecate } from '../../deprecate';
var padding = function padding(x, y) {
return {
padding: "".concat(x, "px ").concat(y, "px")
};
};
var intentStyleMap = function intentStyleMap(_ref) {
var tokens = _ref.tokens;
return {
primary: {
color: tokens.buttonPrimaryColor,
defaultForeground: tokens.buttonPrimaryForeground,
highlight: tokens.buttonPrimaryHoverBackground,
activeBackground: tokens.buttonPrimaryActiveBackground
},
// deprecated, remove primary light in in 2.x
'primary-light': {
color: tokens.buttonPrimaryLightColor,
defaultForeground: tokens.buttonPrimaryLightForeground,
activeBackground: tokens.buttonPrimaryLightActiveBackground
},
secondary: {
color: tokens.buttonSecondaryColor,
defaultForeground: tokens.buttonSecondaryForeground,
activeBackground: tokens.buttonSecondaryActiveBackground
},
destructive: {
color: tokens.buttonDestructiveColor,
defaultForeground: tokens.buttonDestructiveForeground,
highlight: tokens.buttonDestructiveHoverBackground,
activeBackground: tokens.buttonDestructiveActiveBackground
}
};
};
var arrowTransform = {
up: 'translateY(-3px)',
down: 'translateY(3px)',
right: 'translateX(5px)',
left: 'translateX(-5px)'
};
var button = function button(_ref2) {
var disabled = _ref2.disabled,
intent = _ref2.intent,
variant = _ref2.variant,
size = _ref2.size,
loading = _ref2.loading,
arrow = _ref2.arrow,
theme = _ref2.theme;
var _intentStyleMap$inten = intentStyleMap(theme)[intent],
color = _intentStyleMap$inten.color,
defaultForeground = _intentStyleMap$inten.defaultForeground,
activeBackground = _intentStyleMap$inten.activeBackground,
highlight = _intentStyleMap$inten.highlight;
return _objectSpread({
display: 'inline-flex',
flexShrink: 0,
justifyContent: 'center',
alignItems: 'baseline'
}, padding(theme.tokens.buttonPaddingVertical, theme.tokens.buttonPaddingHorizontal), {
textAlign: 'center',
fontSize: sizeToRem(2),
lineHeight: 1.2,
transitionDuration: disabled ? 0 : '300ms',
transitionTimingFunction: 'ease-out',
transitionProperty: 'background, fill, stroke, color, border-color',
borderColor: 'transparent',
borderStyle: 'solid',
borderWidth: 1,
fontWeight: 400,
':focus': {
outline: "2px solid ".concat(color, "33"),
':active': {
background: activeBackground
}
},
extend: [{
condition: size === 'small',
style: _objectSpread({
fontSize: sizeToRem(1.5)
}, padding(theme.tokens.buttonPaddingVertical - theme.baselineGrid, theme.tokens.buttonPaddingHorizontal - theme.baselineGrid * 3), {
'> div svg': {
height: theme.baselineGrid * 3,
width: theme.baselineGrid * 3
}
})
}, {
condition: size === 'large',
style: _objectSpread({
fontSize: sizeToRem(3)
}, padding(theme.tokens.buttonPaddingVertical + theme.baselineGrid, theme.tokens.buttonPaddingHorizontal + theme.baselineGrid * 2), {
'> div svg': {
height: theme.baselineGrid * 5,
width: theme.baselineGrid * 5
}
})
}, {
condition: loading,
style: {
justifyContent: 'center',
alignItems: 'center'
}
}, {
condition: !disabled,
style: {
extend: [{
condition: variant === 'default',
style: {
borderColor: color,
background: color,
color: defaultForeground,
fill: defaultForeground,
stroke: defaultForeground,
':hover': {
borderColor: highlight,
background: highlight
}
}
}, {
condition: variant === 'outline',
style: {
borderColor: color,
color: color,
fill: color,
stroke: color,
':hover': {
background: color,
color: defaultForeground,
borderColor: highlight,
fill: defaultForeground,
stroke: defaultForeground
}
}
}, {
condition: variant === 'text',
style: {
borderColor: 'transparent',
fill: color,
color: color,
stroke: color,
':hover': {
color: highlight
}
}
}, {
condition: arrow,
style: {
':hover svg': {
transform: arrowTransform[arrow]
}
}
}]
}
}, {
condition: loading,
style: {
pointerEvents: 'none'
}
}, {
condition: disabled,
style: {
cursor: 'not-allowed',
fill: theme.color.foreground.secondary,
color: theme.color.foreground.secondary,
stroke: theme.color.foreground.secondary,
':focus': {
outline: '2px solid #CCCCCC33'
},
extend: [{
condition: variant === 'default',
style: {
borderColor: 'lightgrey',
background: 'lightgrey',
color: 'grey',
stroke: 'grey',
fill: 'grey'
}
}, {
condition: variant === 'outline',
style: {
borderColor: 'lightgrey'
}
}]
}
}]
});
};
export var Button = React.forwardRef(function (_ref3, ref) {
var children = _ref3.children,
loading = _ref3.loading,
arrow = _ref3.arrow,
iconBefore = _ref3.iconBefore,
iconAfter = _ref3.iconAfter,
disabled = _ref3.disabled,
_ref3$intent = _ref3.intent,
intent = _ref3$intent === void 0 ? 'primary' : _ref3$intent,
_ref3$variant = _ref3.variant,
variant = _ref3$variant === void 0 ? 'default' : _ref3$variant,
_ref3$size = _ref3.size,
size = _ref3$size === void 0 ? 'medium' : _ref3$size,
props = _objectWithoutProperties(_ref3, ["children", "loading", "arrow", "iconBefore", "iconAfter", "disabled", "intent", "variant", "size"]);
var _useFela = useFela(),
theme = _useFela.theme;
var styleProps = {
disabled: disabled,
intent: intent,
variant: variant,
loading: loading,
size: size,
theme: theme,
arrow: arrow
};
deprecate('intent=primary-light deprecated, use dark theme instead', intent === 'primary-light');
deprecate('iconBefore deprecated, use Icon component and pass as child', iconBefore);
deprecate('iconAfter deprecated, use Icon component and pass as child', iconAfter);
deprecate('Arrow deprecated, arrows will no longer be part of new button component design', arrow);
return React.createElement(Click, _extends({
ref: ref
}, props, {
disabled: disabled || loading,
extend: [button(styleProps), getThemeStyle('button', theme, styleProps)]
}), loading && React.createElement(Block, {
extend: {
position: 'absolute',
margin: '0 auto'
}
}, React.createElement(Spinner, {
color: "inherit",
size: theme.baselineGrid * 4
})), loading ? React.createElement(Inline, {
extend: {
visibility: 'hidden'
}
}, React.createElement(InnerButton, {
iconBefore: iconBefore,
iconAfter: iconAfter,
arrow: arrow
}, children)) : React.createElement(InnerButton, {
iconBefore: iconBefore,
iconAfter: iconAfter,
arrow: arrow
}, children));
});
var InnerButton = function InnerButton(_ref4) {
var children = _ref4.children,
iconBefore = _ref4.iconBefore,
iconAfter = _ref4.iconAfter,
arrow = _ref4.arrow;
return React.createElement(React.Fragment, null, iconBefore && React.createElement(Inline, {
extend: {
marginRight: 12,
position: 'relative',
bottom: '-3px'
}
}, React.createElement(Icon, {
size: "m",
type: iconBefore
})), arrow && arrow === 'left' && React.createElement(Inline, {
extend: {
marginRight: 8
}
}, React.createElement(Arrow, {
direction: 'left'
})), children, arrow && arrow !== 'left' && React.createElement(Inline, {
extend: {
marginLeft: 8
}
}, React.createElement(Arrow, {
direction: arrow
})), iconAfter && React.createElement(Inline, {
extend: {
marginLeft: 12,
position: 'relative',
bottom: '-3px'
}
}, React.createElement(Icon, {
size: "m",
type: iconAfter
})));
};
Button.displayName = 'Button';
Button.propTypes = {
/** A JSX node */
children: PropTypes.node,
intent: PropTypes.oneOf(['primary', 'primary-light', // deprecated
'secondary', 'destructive']),
variant: PropTypes.oneOf(['default', 'outline', 'text']),
loading: PropTypes.bool,
disabled: PropTypes.bool,
arrow: PropTypes.oneOf(['up', 'down', 'right', 'left']),
/** Add an icon before button text */
iconBefore: PropTypes.string,
/** Add an icon after button text */
iconAfter: PropTypes.string,
/** Changes the rendered element from `<button>` to `<a>` */
href: PropTypes.string,
size: PropTypes.oneOf(['small', 'medium', 'large'])
};