239 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			239 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
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; };
 | 
						|
 | 
						|
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; }
 | 
						|
 | 
						|
//  weak
 | 
						|
 | 
						|
import React from 'react';
 | 
						|
 | 
						|
import { findDOMNode } from 'react-dom';
 | 
						|
import classNames from 'classnames';
 | 
						|
import keycode from 'keycode';
 | 
						|
import withStyles from '../styles/withStyles';
 | 
						|
import { listenForFocusKeys, detectKeyboardFocus, focusKeyPressed } from '../utils/keyboardFocus';
 | 
						|
import TouchRipple from './TouchRipple';
 | 
						|
import createRippleHandler from './createRippleHandler';
 | 
						|
 | 
						|
export const styles = theme => ({
 | 
						|
  root: {
 | 
						|
    display: 'inline-flex',
 | 
						|
    alignItems: 'center',
 | 
						|
    justifyContent: 'center',
 | 
						|
    position: 'relative',
 | 
						|
    // Remove grey highlight
 | 
						|
    WebkitTapHighlightColor: theme.palette.common.transparent,
 | 
						|
    backgroundColor: 'transparent', // Reset default value
 | 
						|
    outline: 'none',
 | 
						|
    border: 0,
 | 
						|
    borderRadius: 0,
 | 
						|
    cursor: 'pointer',
 | 
						|
    userSelect: 'none',
 | 
						|
    appearance: 'none',
 | 
						|
    textDecoration: 'none',
 | 
						|
    // So we take precedent over the style of a native <a /> element.
 | 
						|
    color: 'inherit',
 | 
						|
    '&::-moz-focus-inner': {
 | 
						|
      borderStyle: 'none' // Remove Firefox dotted outline.
 | 
						|
    }
 | 
						|
  },
 | 
						|
  disabled: {
 | 
						|
    pointerEvents: 'none', // Disable link interactions
 | 
						|
    cursor: 'default'
 | 
						|
  }
 | 
						|
});
 | 
						|
 | 
						|
class ButtonBase extends React.Component {
 | 
						|
  constructor(...args) {
 | 
						|
    var _temp;
 | 
						|
 | 
						|
    return _temp = super(...args), this.state = {
 | 
						|
      keyboardFocused: false
 | 
						|
    }, this.onKeyboardFocusHandler = event => {
 | 
						|
      this.keyDown = false;
 | 
						|
      this.setState({ keyboardFocused: true });
 | 
						|
 | 
						|
      if (this.props.onKeyboardFocus) {
 | 
						|
        this.props.onKeyboardFocus(event);
 | 
						|
      }
 | 
						|
    }, this.ripple = null, this.keyDown = false, this.button = null, this.keyboardFocusTimeout = null, this.keyboardFocusCheckTime = 30, this.keyboardFocusMaxCheckTimes = 5, this.handleKeyDown = event => {
 | 
						|
      const { component, focusRipple, onKeyDown, onClick } = this.props;
 | 
						|
      const key = keycode(event);
 | 
						|
 | 
						|
      // Check if key is already down to avoid repeats being counted as multiple activations
 | 
						|
      if (focusRipple && !this.keyDown && this.state.keyboardFocused && key === 'space') {
 | 
						|
        this.keyDown = true;
 | 
						|
        event.persist();
 | 
						|
        this.ripple.stop(event, () => {
 | 
						|
          this.ripple.start(event);
 | 
						|
        });
 | 
						|
      }
 | 
						|
 | 
						|
      if (onKeyDown) {
 | 
						|
        onKeyDown(event);
 | 
						|
      }
 | 
						|
 | 
						|
      // Keyboard accessibility for non interactive elements
 | 
						|
      if (event.target === this.button && onClick && component && component !== 'a' && component !== 'button' && (key === 'space' || key === 'enter')) {
 | 
						|
        event.preventDefault();
 | 
						|
        onClick(event);
 | 
						|
      }
 | 
						|
    }, this.handleKeyUp = event => {
 | 
						|
      if (this.props.focusRipple && keycode(event) === 'space' && this.state.keyboardFocused) {
 | 
						|
        this.keyDown = false;
 | 
						|
        event.persist();
 | 
						|
        this.ripple.stop(event, () => this.ripple.pulsate(event));
 | 
						|
      }
 | 
						|
      if (this.props.onKeyUp) {
 | 
						|
        this.props.onKeyUp(event);
 | 
						|
      }
 | 
						|
    }, this.handleMouseDown = createRippleHandler(this, 'MouseDown', 'start', () => {
 | 
						|
      clearTimeout(this.keyboardFocusTimeout);
 | 
						|
      focusKeyPressed(false);
 | 
						|
      if (this.state.keyboardFocused) {
 | 
						|
        this.setState({ keyboardFocused: false });
 | 
						|
      }
 | 
						|
    }), this.handleMouseUp = createRippleHandler(this, 'MouseUp', 'stop'), this.handleMouseLeave = createRippleHandler(this, 'MouseLeave', 'stop', event => {
 | 
						|
      if (this.state.keyboardFocused) {
 | 
						|
        event.preventDefault();
 | 
						|
      }
 | 
						|
    }), this.handleTouchStart = createRippleHandler(this, 'TouchStart', 'start'), this.handleTouchEnd = createRippleHandler(this, 'TouchEnd', 'stop'), this.handleTouchMove = createRippleHandler(this, 'TouchEnd', 'stop'), this.handleBlur = createRippleHandler(this, 'Blur', 'stop', () => {
 | 
						|
      clearTimeout(this.keyboardFocusTimeout);
 | 
						|
      focusKeyPressed(false);
 | 
						|
      this.setState({ keyboardFocused: false });
 | 
						|
    }), this.handleFocus = event => {
 | 
						|
      if (this.props.disabled) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      // Fix for https://github.com/facebook/react/issues/7769
 | 
						|
      if (!this.button) {
 | 
						|
        this.button = event.currentTarget;
 | 
						|
      }
 | 
						|
 | 
						|
      event.persist();
 | 
						|
      const keyboardFocusCallback = this.onKeyboardFocusHandler.bind(this, event);
 | 
						|
      detectKeyboardFocus(this, this.button, keyboardFocusCallback);
 | 
						|
 | 
						|
      if (this.props.onFocus) {
 | 
						|
        this.props.onFocus(event);
 | 
						|
      }
 | 
						|
    }, _temp;
 | 
						|
  }
 | 
						|
 | 
						|
  componentDidMount() {
 | 
						|
    this.button = findDOMNode(this);
 | 
						|
    listenForFocusKeys();
 | 
						|
  }
 | 
						|
 | 
						|
  componentWillUpdate(nextProps, nextState) {
 | 
						|
    if (this.props.focusRipple && nextState.keyboardFocused && !this.state.keyboardFocused && !this.props.disableRipple) {
 | 
						|
      this.ripple.pulsate();
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  componentWillUnmount() {
 | 
						|
    this.button = null;
 | 
						|
    clearTimeout(this.keyboardFocusTimeout);
 | 
						|
  } // Used to help track keyboard activation keyDown
 | 
						|
 | 
						|
 | 
						|
  renderRipple() {
 | 
						|
    if (!this.props.disableRipple && !this.props.disabled) {
 | 
						|
      return React.createElement(TouchRipple, {
 | 
						|
        innerRef: node => {
 | 
						|
          this.ripple = node;
 | 
						|
        },
 | 
						|
        center: this.props.centerRipple
 | 
						|
      });
 | 
						|
    }
 | 
						|
 | 
						|
    return null;
 | 
						|
  }
 | 
						|
 | 
						|
  render() {
 | 
						|
    const _props = this.props,
 | 
						|
          {
 | 
						|
      centerRipple,
 | 
						|
      children,
 | 
						|
      classes,
 | 
						|
      className: classNameProp,
 | 
						|
      component,
 | 
						|
      disabled,
 | 
						|
      disableRipple,
 | 
						|
      focusRipple,
 | 
						|
      keyboardFocusedClassName,
 | 
						|
      onBlur,
 | 
						|
      onFocus,
 | 
						|
      onKeyboardFocus,
 | 
						|
      onKeyDown,
 | 
						|
      onKeyUp,
 | 
						|
      onMouseDown,
 | 
						|
      onMouseLeave,
 | 
						|
      onMouseUp,
 | 
						|
      onTouchEnd,
 | 
						|
      onTouchMove,
 | 
						|
      onTouchStart,
 | 
						|
      rootRef,
 | 
						|
      tabIndex,
 | 
						|
      type
 | 
						|
    } = _props,
 | 
						|
          other = _objectWithoutProperties(_props, ['centerRipple', 'children', 'classes', 'className', 'component', 'disabled', 'disableRipple', 'focusRipple', 'keyboardFocusedClassName', 'onBlur', 'onFocus', 'onKeyboardFocus', 'onKeyDown', 'onKeyUp', 'onMouseDown', 'onMouseLeave', 'onMouseUp', 'onTouchEnd', 'onTouchMove', 'onTouchStart', 'rootRef', 'tabIndex', 'type']);
 | 
						|
 | 
						|
    const className = classNames(classes.root, {
 | 
						|
      [classes.disabled]: disabled,
 | 
						|
      [keyboardFocusedClassName || '']: this.state.keyboardFocused
 | 
						|
    }, classNameProp);
 | 
						|
 | 
						|
    const buttonProps = {};
 | 
						|
 | 
						|
    let ComponentProp = component;
 | 
						|
 | 
						|
    if (!ComponentProp) {
 | 
						|
      if (other.href) {
 | 
						|
        ComponentProp = 'a';
 | 
						|
      } else {
 | 
						|
        ComponentProp = 'button';
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (ComponentProp === 'button') {
 | 
						|
      buttonProps.type = type || 'button';
 | 
						|
    }
 | 
						|
 | 
						|
    if (ComponentProp !== 'a') {
 | 
						|
      buttonProps.role = buttonProps.role || 'button';
 | 
						|
      buttonProps.disabled = disabled;
 | 
						|
    }
 | 
						|
 | 
						|
    return React.createElement(
 | 
						|
      ComponentProp,
 | 
						|
      _extends({
 | 
						|
        onBlur: this.handleBlur,
 | 
						|
        onFocus: this.handleFocus,
 | 
						|
        onKeyDown: this.handleKeyDown,
 | 
						|
        onKeyUp: this.handleKeyUp,
 | 
						|
        onMouseDown: this.handleMouseDown,
 | 
						|
        onMouseLeave: this.handleMouseLeave,
 | 
						|
        onMouseUp: this.handleMouseUp,
 | 
						|
        onTouchEnd: this.handleTouchEnd,
 | 
						|
        onTouchMove: this.handleTouchMove,
 | 
						|
        onTouchStart: this.handleTouchStart,
 | 
						|
        tabIndex: disabled ? -1 : tabIndex,
 | 
						|
        className: className
 | 
						|
      }, buttonProps, other, {
 | 
						|
        ref: rootRef
 | 
						|
      }),
 | 
						|
      children,
 | 
						|
      this.renderRipple()
 | 
						|
    );
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
ButtonBase.defaultProps = {
 | 
						|
  centerRipple: false,
 | 
						|
  focusRipple: false,
 | 
						|
  disableRipple: false,
 | 
						|
  tabIndex: 0,
 | 
						|
  type: 'button'
 | 
						|
};
 | 
						|
export default withStyles(styles, { name: 'MuiButtonBase' })(ButtonBase); |