UNPKG

parcel-react-ui-button

Version:

The parcel-react-ui-button component provides users a way to trigger actions in the UI.

286 lines (240 loc) 10.4 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _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; }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _bind = require('classnames/bind'); var _bind2 = _interopRequireDefault(_bind); require('terra-base/lib/baseStyles'); var _ButtonModule = require('./Button.module.scss'); var _ButtonModule2 = _interopRequireDefault(_ButtonModule); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var cx = _bind2.default.bind(_ButtonModule2.default); var KEYCODES = { ENTER: 13, SPACE: 32, TAB: 9 }; var ButtonVariants = { NEUTRAL: 'neutral', EMPHASIS: 'emphasis', // TODO: this should be removed on the next major version bump 'DE-EMPHSASIS': 'de-emphasis', 'DE-EMPHASIS': 'de-emphasis', ACTION: 'action', UTILITY: 'utility' }; var ButtonTypes = { BUTTON: 'button', SUBMIT: 'submit', RESET: 'reset' }; var propTypes = { /** * Sets the href. When set will render the component as an anchor tag. */ href: _propTypes2.default.string, /** * An optional icon. Nested inline with the text when provided. */ icon: _propTypes2.default.element, /** * Whether or not the button should only display as an icon. */ isIconOnly: _propTypes2.default.bool, /** * Whether or not the button should display as a block. */ isBlock: _propTypes2.default.bool, /** * Whether or not the button has reduced padding */ isCompact: _propTypes2.default.bool, /** * Whether or not the button should be disabled. */ isDisabled: _propTypes2.default.bool, /** * Reverses the position of the icon and text. */ isReversed: _propTypes2.default.bool, /** * Callback function triggered when clicked. */ onClick: _propTypes2.default.func, /** * Callback function triggered when button loses focus. */ onBlur: _propTypes2.default.func, /** * Callback function triggered when button gains focus. */ onFocus: _propTypes2.default.func, /** * Callback function triggered when key is pressed. */ onKeyDown: _propTypes2.default.func, /** * Callback function triggered when key is released. */ onKeyUp: _propTypes2.default.func, /** * Sets the button text. If the button `isIconOnly` or of variant `Button.Opts.Variants.UTILITY`, this text is set as the aria-label for accessibility. */ text: _propTypes2.default.string.isRequired, /** * Sets the button type. One of `Button.Opts.Types.BUTTON`, `Button.Opts.Types.SUBMIT`, or `Button.Opts.Types.RESET`. */ type: _propTypes2.default.oneOf([ButtonTypes.BUTTON, ButtonTypes.SUBMIT, ButtonTypes.RESET]), /** * Sets the button variant. One of `Button.Opts.Variants.NEUTRAL`, `Button.Opts.Variants.EMPHASIS`, `Button.Opts.Variants['DE-EMPHASIS']`, `Button.Opts.Variants.ACTION` or `Button.Opts.Variants.UTILITY`. */ variant: _propTypes2.default.oneOf([ButtonVariants.NEUTRAL, ButtonVariants.EMPHASIS, ButtonVariants['DE-EMPHASIS'], ButtonVariants.ACTION, ButtonVariants.UTILITY]) }; var defaultProps = { isBlock: false, isCompact: false, isDisabled: false, isIconOnly: false, isReversed: false, type: ButtonTypes.BUTTON, variant: ButtonVariants.NEUTRAL }; var Button = function (_React$Component) { _inherits(Button, _React$Component); function Button(props) { _classCallCheck(this, Button); var _this = _possibleConstructorReturn(this, (Button.__proto__ || Object.getPrototypeOf(Button)).call(this, props)); _this.state = { active: false, focused: false, mouseWasClicked: false }; _this.handleKeyDown = _this.handleKeyDown.bind(_this); _this.handleKeyUp = _this.handleKeyUp.bind(_this); _this.handleOnBlur = _this.handleOnBlur.bind(_this); return _this; } _createClass(Button, [{ key: 'handleOnBlur', value: function handleOnBlur(event) { this.setState({ focused: false }); if (this.props.onBlur) { this.props.onBlur(event); } } }, { key: 'handleKeyDown', value: function handleKeyDown(event) { // Add active state to FF browsers if (event.nativeEvent.keyCode === KEYCODES.SPACE) { this.setState({ active: true }); // Follow href on space keydown when rendered as an anchor tag if (this.props.href) { // Prevent window scrolling event.preventDefault(); window.location.href = this.props.href; } } // Add focus styles for keyboard navigation if (event.nativeEvent.keyCode === KEYCODES.SPACE || event.nativeEvent.keyCode === KEYCODES.ENTER) { this.setState({ focused: true }); } if (this.props.onKeyDown) { this.props.onKeyDown(event); } } }, { key: 'handleKeyUp', value: function handleKeyUp(event) { // Remove active state from FF broswers if (event.nativeEvent.keyCode === KEYCODES.SPACE) { this.setState({ active: false }); } // Apply focus styles for keyboard navigation if (event.nativeEvent.keyCode === KEYCODES.TAB) { this.setState({ focused: true }); } if (this.props.onKeyUp) { this.props.onKeyUp(event); } } }, { key: 'render', value: function render() { var _props = this.props, icon = _props.icon, isBlock = _props.isBlock, isCompact = _props.isCompact, isDisabled = _props.isDisabled, isIconOnly = _props.isIconOnly, isReversed = _props.isReversed, text = _props.text, type = _props.type, variant = _props.variant, href = _props.href, onClick = _props.onClick, onBlur = _props.onBlur, onFocus = _props.onFocus, onKeyDown = _props.onKeyDown, onKeyUp = _props.onKeyUp, customProps = _objectWithoutProperties(_props, ['icon', 'isBlock', 'isCompact', 'isDisabled', 'isIconOnly', 'isReversed', 'text', 'type', 'variant', 'href', 'onClick', 'onBlur', 'onFocus', 'onKeyDown', 'onKeyUp']); var buttonClasses = cx(['button', variant, { 'is-disabled': isDisabled }, { block: isBlock }, { compact: isCompact }, { 'is-active': this.state.active }, { 'is-focused': this.state.focused }, customProps.className]); var buttonLabelClasses = cx([{ 'text-and-icon': icon && !isIconOnly }, { 'icon-only': isIconOnly || variant === 'utility' }, { 'text-only': !icon }]); var buttonTextClasses = cx([{ 'text-first': icon && isReversed }]); var iconClasses = cx(['icon', { 'icon-first': !isIconOnly && variant !== 'utility' && !isReversed }]); var buttonText = !isIconOnly && variant !== 'utility' ? _react2.default.createElement( 'span', { className: buttonTextClasses }, text ) : null; var buttonIcon = null; if (icon) { var iconSvgClasses = icon.props.className ? icon.props.className + ' ' + cx('icon-svg') : cx('icon-svg'); var cloneIcon = _react2.default.cloneElement(icon, { className: iconSvgClasses }); buttonIcon = _react2.default.createElement( 'span', { className: iconClasses }, cloneIcon ); } var buttonLabel = _react2.default.createElement( 'span', { className: buttonLabelClasses }, isReversed ? buttonText : buttonIcon, isReversed ? buttonIcon : buttonText ); var ComponentType = href ? 'a' : 'button'; return _react2.default.createElement( ComponentType, _extends({}, customProps, { className: buttonClasses, type: type, disabled: isDisabled, tabIndex: isDisabled ? '-1' : undefined, 'aria-disabled': isDisabled, 'aria-label': isIconOnly || variant === 'utility' ? text : null, onKeyDown: this.handleKeyDown, onKeyUp: this.handleKeyUp, onBlur: this.handleOnBlur, onClick: onClick, onFocus: onFocus, href: href }), buttonLabel ); } }]); return Button; }(_react2.default.Component); Button.propTypes = propTypes; Button.defaultProps = defaultProps; Button.Opts = {}; Button.Opts.Types = ButtonTypes; Button.Opts.Variants = ButtonVariants; exports.default = Button;