<commit_before>import React, { createClass, PropTypes } from 'react';
import tween from 'tweening';

const BarChart = createClass({
  propTypes: {
    barClassName: PropTypes.string,
    bars: PropTypes.array.isRequired,
    chartClassName: PropTypes.string,
    easing: PropTypes.oneOfType([ PropTypes.func, PropTypes.string ]),
    height: PropTypes.number,
    spacing: PropTypes.number,
    width: PropTypes.number,
  },

  getDefaultProps () {
    return {
      duration: 750,
      easing: 'easeOutBounce',
      height: 500,
      spacing: 10,
      width: 800,
    };
  },

  getInitialState () {
    return {
      bars: this.props.bars.map( b => ({ ...b, value: 0 })),
      barHeight: ( this.props.height - this.props.spacing * ( this.props.bars.length - 1 )) / this.props.bars.length,
    };
  },

  componentDidMount () {
    this.animateBars( this.state.bars, this.relativeBars( this.props.bars ));
  },

  componentWillReceiveProps ({ bars }) {
    const relativeBars = this.relativeBars( bars );
    if ( JSON.stringify( relativeBars ) !== JSON.stringify( this.state.bars )) {
      this.animateBars( this.state.bars, relativeBars );
    }
  },

  render () {
    return (
      <svg
        className={ this.props.chartClassName }
        height={ this.props.height }
        width={ this.props.width }
        viewBox={ `0 0 ${ this.props.width } ${ this.props.height }` }
      >
        { this.state.bars.map(( bar, i ) => (
          <rect
            className={ this.props.barClassName }
            height={ this.state.barHeight }
            key={ i }
            width={ bar.value }
            x={ 0 }
            y={( this.state.barHeight + this.props.spacing ) * i }
            fill="rgb(241,76,84)"
          />
        ))}
      </svg>
    );
  },

  animateBars ( from, to ) {
    tween({
      duration: this.props.duration,
      easing: this.props.easing,
      from,
      to,
      next: bars => this.setState({ bars }),
    });
  },

  relativeBars ( bars ) {
    const absolutePercent = this.props.width / 100;<commit_msg>feat(chart): allow preserveAspectRatio prop for bar chart<commit_after>import React, { createClass, PropTypes } from 'react';
import tween from 'tweening';

const BarChart = createClass({
  propTypes: {
    barClassName: PropTypes.string,
    bars: PropTypes.array.isRequired,
    chartClassName: PropTypes.string,
    easing: PropTypes.oneOfType([ PropTypes.func, PropTypes.string ]),
    height: PropTypes.number,
    preserveAspectRatio: PropTypes.string,
    spacing: PropTypes.number,
    width: PropTypes.number,
  },

  getDefaultProps () {
    return {
      duration: 750,
      easing: 'easeOutBounce',
      height: 500,
      preserveAspectRatio: 'xMidYMid meet',
      spacing: 10,
      width: 800,
    };
  },

  getInitialState () {
    return {
      bars: this.props.bars.map( b => ({ ...b, value: 0 })),
      barHeight: ( this.props.height - this.props.spacing * ( this.props.bars.length - 1 )) / this.props.bars.length,
    };
  },

  componentDidMount () {
    this.animateBars( this.state.bars, this.relativeBars( this.props.bars ));
  },

  componentWillReceiveProps ({ bars }) {
    const relativeBars = this.relativeBars( bars );
    if ( JSON.stringify( relativeBars ) !== JSON.stringify( this.state.bars )) {
      this.animateBars( this.state.bars, relativeBars );
    }
  },

  render () {
    return (
      <svg
        className={ this.props.chartClassName }
        height={ this.props.height }
        preserveAspectRatio={ this.props.preserveAspectRatio }
        width={ this.props.width }
        viewBox={ `0 0 ${ this.props.width } ${ this.props.height }` }
      >
        { this.state.bars.map(( bar, i ) => (
          <rect
            className={ this.props.barClassName }
            height={ this.state.barHeight }
            key={ i }
            width={ bar.value }
            x={ 0 }
            y={( this.state.barHeight + this.props.spacing ) * i }
            fill="rgb(241,76,84)"
          />
        ))}
      </svg>
    );
  },

  animateBars ( from, to ) {
    tween({
      duration: this.props.duration,
      easing: this.props.easing,
      from,
      to,
      next: bars => this.setState({ bars }),
    });
  },

  relativeBars ( bars ) {
    const absolutePercent = this.props.width / 100;
{'fraction_non_alphanumeric': 0.14328703703703705, 'fraction_numerical': 0.012037037037037037, 'mean_word_length': 2.2198211624441133, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 15, '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': '4391143', 'n_tokens_mistral': 1401, 'n_tokens_neox': 1347, 'n_words': 270}