<commit_before>/** ****************************************************************************
 * Button
 *
 * @author       <NAME> <<EMAIL>>
 * @file         Material Design Button
 ******************************************************************************/

// External Modules
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import HighlightClick from 'ship-components-highlight-click';
import { CSSTransitionGroup } from 'react-transition-group';

import Tooltip from './Tooltip';

// Local
import css from './button.css';

export default class Button extends Component {
  /**
   * Base Button
   * @param  {Object} props
   */
  constructor(props) {
    super(props);
    this.state = {
      hoverSize: void 0,
      hover: false,
      pressed: false
    };
    this.handleMouseEnter = this.handleMouseEnter.bind(this);
    this.handleMouseLeave = this.handleMouseLeave.bind(this);
    this.handleClick = this.handleClick.bind(this);
  }

  /**
   * First mount, get a starting width
   */
  componentDidMount() {
    this.calculateWidth();
  }

  /**
   * Prevent excessive updates
   * @param  {Object} nextProps
   * @param  {Object} nextState
   * @return {Boolean}
   */
  shouldComponentUpdate(nextProps, nextState) {
    const propsToCheck = ['className', 'iconClass', 'disabled'];
    const statesToCheck = ['hover', 'pressed', 'hoverSize'];
    return (
      nextProps.forceUpdate ||
      propsToCheck.some(key => this.props[key] !== nextProps[key]) ||
      statesToCheck.some(key => this.state[key] !== nextState[key])
    );
  }

  /**
   * Called after the DOM is rendered. Updates the state
   */
  componentDidUpdate() {
    this.calculateWidth();
  }

  /**
   * Clean up
   */
  componentWillUnmount() {
    clearTimeout(this.pressedTimeout);
  }

  /**
   * Get the width of the button so so we ensure the hover effect fits
   */
  calculateWidth() {
    if (!this.refs.container) {
      return;
    }

    const nextHoverSize = Math.max(
      this.refs.container.offsetWidth,
      this.refs.container.offsetHeight
    );
    const currHoverSize = this.state.hoverSize;
    const hoverSizeChanged = nextHoverSize !== currHoverSize;

    // Only update the hoverSize state if
    // it's not the same as the current state.hoverSize
    if (hoverSizeChanged) {
      this.setState({
        hoverSize: nextHoverSize
      });
    }
  }

  /**
   * Let the button now the mouse is here
   */
  handleMouseEnter() {
    if (this.props.disabled) {
      return;
    }
    this.setState({
      hover: true
    });
  }

  /**
   * Let the button know the mouse is gone
   */
  handleMouseLeave() {
    this.setState({
      hover: false
    });
  }

  /**
   * Handle the clicks. Toggles pressed state
   * @param  {Event]} event
   */
  handleClick(event) {

    if (this.props.disabled) {
      event.stopPropagation();
      event.preventDefault();
      return;
    }

    // Blur so the button loses focus and doesn't
    // quietly interfere with keyboard shortcuts
    event.target.blur();

    if (this.props.onClick) {
      this.props.onClick(event);
    }

    if (!this.props.sticky) {
      this.setState({
        pressed: true
      }, () => {
        clearTimeout(this.pressedTimeout);
        this.pressedTimeout = setTimeout(() => {
          this.setState({
            pressed: false
          });
        }, this.props.pressedTimeout);
      });
    } else {
      let currentPressedState = !!this.state.pressed;
      this.setState({
        pressed: !currentPressedState
      });
    }
  }

  /**
   * The tag devirved from the propTypes
   * @return {String}
   */
  getTag() {
    if (typeof this.props.href === 'string' && this.props.href.length > 0) {
      return 'a';
    } else {
      return this.props.tag; // FF isn't triggereing on <buttons>
    }
  }

  /**
   * Get the icon
   * @return {React}
   */
  renderIcon() {
    if (typeof this.props.iconClass === 'string') {
      return <span className={css.icon + ' ' + this.props.iconClass} />;
    } else if (typeof this.props.icon === 'string') {
      return <span className={css.icon + ' ' + this.props.iconPrefix + this.props.icon} />;
    } else {
      return null;
    }
  }

  /**
   * Render
   * @return {React}
   */
  render() {
    let btnClasses = classNames(
      'ship-components-btn',
      css.btn,
      css[this.props.type],
      {
        [css.disabled] : this.props.disabled,
        [css.pressed] : this.state.pressed
      },
      this.props.sticky ? css.sticky : null
    );

    let hoverStyles = {};
    if (this.state.hoverSize) {
      // Ensure it covers the button
      hoverStyles.width = this.state.hoverSize * 1.3;
      hoverStyles.height = hoverStyles.width;

      // Center it
      hoverStyles.marginLeft = hoverStyles.width / -2;
      hoverStyles.marginTop = hoverStyles.marginLeft;
    }

    // Store it on `this` so JSX reads it properly
    const ButtonComponent = this.getTag();<commit_msg>reduced cyclomatic complexity for lint<commit_after>/** ****************************************************************************
 * Button
 *
 * @author       <NAME> <<EMAIL>>
 * @file         Material Design Button
 ******************************************************************************/

// External Modules
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import HighlightClick from 'ship-components-highlight-click';
import { CSSTransitionGroup } from 'react-transition-group';

import Tooltip from './Tooltip';

// Local
import css from './button.css';

export default class Button extends Component {
  /**
   * Base Button
   * @param  {Object} props
   */
  constructor(props) {
    super(props);
    this.state = {
      hoverSize: void 0,
      hover: false,
      pressed: false
    };
    this.handleMouseEnter = this.handleMouseEnter.bind(this);
    this.handleMouseLeave = this.handleMouseLeave.bind(this);
    this.handleClick = this.handleClick.bind(this);
  }

  /**
   * First mount, get a starting width
   */
  componentDidMount() {
    this.calculateWidth();
  }

  /**
   * Prevent excessive updates
   * @param  {Object} nextProps
   * @param  {Object} nextState
   * @return {Boolean}
   */
  shouldComponentUpdate(nextProps, nextState) {
    const propsToCheck = ['className', 'iconClass', 'disabled'];
    const statesToCheck = ['hover', 'pressed', 'hoverSize'];
    return (
      nextProps.forceUpdate ||
      propsToCheck.some(key => this.props[key] !== nextProps[key]) ||
      statesToCheck.some(key => this.state[key] !== nextState[key])
    );
  }

  /**
   * Called after the DOM is rendered. Updates the state
   */
  componentDidUpdate() {
    this.calculateWidth();
  }

  /**
   * Clean up
   */
  componentWillUnmount() {
    clearTimeout(this.pressedTimeout);
  }

  /**
   * Get the width of the button so so we ensure the hover effect fits
   */
  calculateWidth() {
    if (!this.refs.container) {
      return;
    }

    const nextHoverSize = Math.max(
      this.refs.container.offsetWidth,
      this.refs.container.offsetHeight
    );
    const currHoverSize = this.state.hoverSize;
    const hoverSizeChanged = nextHoverSize !== currHoverSize;

    // Only update the hoverSize state if
    // it's not the same as the current state.hoverSize
    if (hoverSizeChanged) {
      this.setState({
        hoverSize: nextHoverSize
      });
    }
  }

  /**
   * Let the button now the mouse is here
   */
  handleMouseEnter() {
    if (this.props.disabled) {
      return;
    }
    this.setState({
      hover: true
    });
  }

  /**
   * Let the button know the mouse is gone
   */
  handleMouseLeave() {
    this.setState({
      hover: false
    });
  }

  /**
   * Handle the clicks. Toggles pressed state
   * @param  {Event]} event
   */
  handleClick(event) {

    if (this.props.disabled) {
      event.stopPropagation();
      event.preventDefault();
      return;
    }

    // Blur so the button loses focus and doesn't
    // quietly interfere with keyboard shortcuts
    event.target.blur();

    if (this.props.onClick) {
      this.props.onClick(event);
    }

    if (!this.props.sticky) {
      this.setState({
        pressed: true
      }, () => {
        clearTimeout(this.pressedTimeout);
        this.pressedTimeout = setTimeout(() => {
          this.setState({
            pressed: false
          });
        }, this.props.pressedTimeout);
      });
    } else {
      let currentPressedState = !!this.state.pressed;
      this.setState({
        pressed: !currentPressedState
      });
    }
  }

  /**
   * The tag devirved from the propTypes
   * @return {String}
   */
  getTag() {
    if (typeof this.props.href === 'string' && this.props.href.length > 0) {
      return 'a';
    } else {
      return this.props.tag; // FF isn't triggereing on <buttons>
    }
  }

  /**
   * Get the icon
   * @return {React}
   */
  renderIcon() {
    if (typeof this.props.iconClass === 'string') {
      return <span className={css.icon + ' ' + this.props.iconClass} />;
    } else if (typeof this.props.icon === 'string') {
      return <span className={css.icon + ' ' + this.props.iconPrefix + this.props.icon} />;
    } else {
      return null;
    }
  }

  /**
   * Render
   * @return {React}
   */
  render() {
    let btnClasses = classNames(
      'ship-components-btn',
      css.btn,
      css[this.props.type],
      {
        [css.disabled] : this.props.disabled,
        [css.pressed]: this.state.pressed,
        [css.sticky]: this.props.sticky
      }
    );

    let hoverStyles = {};
    if (this.state.hoverSize) {
      // Ensure it covers the button
      hoverStyles.width = this.state.hoverSize * 1.3;
      hoverStyles.height = hoverStyles.width;

      // Center it
      hoverStyles.marginLeft = hoverStyles.width / -2;
      hoverStyles.marginTop = hoverStyles.marginLeft;
    }

    // Store it on `this` so JSX reads it properly
    const ButtonComponent = this.getTag();
{'fraction_non_alphanumeric': 0.16047297297297297, 'fraction_numerical': 0.0009936406995230524, 'mean_word_length': 2.4363263912598154, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5061698', 'n_tokens_mistral': 3070, 'n_tokens_neox': 3023, 'n_words': 704}