<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { scaleLinear, scaleBand, max } from 'd3';
import castArray from 'lodash/castArray';
import map from 'lodash/map';
import pick from 'lodash/pick';
import Bars from './bars';

import {
  isVertical,
  combineStyles,
  CommonDefaultProps,
  CommonPropTypes,
  memoizeByLastCall,
  propResolver,
  stackedDataArray,
} from '../../../utils';

export default class MultiBars extends React.PureComponent {
  constructor(props) {
    super(props);

    this.combineStyles = memoizeByLastCall(combineStyles);
    this.castSelectionAsArray = memoizeByLastCall((selection) => castArray(selection));
  }

  render() {
    const {
      barsClassName,
      barsStyle,
      className,
      clipPathId,
      colorScale,
      data,
      dataAccessors,
      fieldAccessors,
      layerDomain,
      layerOrdinal,
      orientation,
      scales,
      selection,
      style,
      stacked,
    } = this.props;

    const {
      layer: layerField,
      value: valueField,
      stack: stackField,
    } = dataAccessors;

    const {
      color: colorField,
      data: dataField,
      key: keyField
    } = fieldAccessors;

    // If stacked bar chart, the data must be transformed using d3.stack() function.
    const plotData = stacked
      ? stackedDataArray(data, layerField, valueField, stackField, dataField, layerDomain)
      : data;

    // Updates specific domains for each type of bar chart
    if (stacked) {
      const stackedDomain =
        [0, max(plotData, datum => max(datum, d => d[1]))];
      const linear = isVertical(orientation) ? scales.y : scales.x;
      linear.domain(stackedDomain);
    } else {
      const ordinal = isVertical(orientation) ? scales.x : scales.y;
      layerOrdinal.domain(layerDomain).range([0, ordinal.bandwidth()]);
    }

    const childProps = pick(this.props, [
      'align',
      'bandPadding',
      'bandPaddingInner',
      'bandPaddingOuter',
      'colorScale',
      'dataAccessors',
      'focus',
      'focusedClassName',
      'focusedStyle',
      'height',
      'layerOrdinal',
      'layerDomain',
      'onClick',
      'onMouseLeave',
      'onMouseMove',
      'onMouseOver',
      'orientation',
      'selectedClassName',
      'selectedStyle',
      'scales',
      'rectClassName',
      'rectStyle',
      'stacked',
      'grouped',
    ]);

    return (
      <g
        className={className && classNames(className)}
        clipPath={clipPathId && `url(#${clipPathId})`}
        style={this.combineStyles(style, data)}
      >
        {
          map(plotData, (datum) => {
            const key = propResolver(datum, keyField);
            const values = stacked ? datum : propResolver(datum, dataField);
            const color = colorScale(colorField ? propResolver(datum, colorField) : key);
            const outerOrdinal = isVertical(orientation) ? scales.x : scales.y;
            const translate = outerOrdinal(key);

            return (
              <Bars
                className={barsClassName}
                data={values}
                fill={color}
                key={`bars:${key}`}
                selection={this.castSelectionAsArray(selection)}
                style={barsStyle}
                categoryTranslate={translate}
                {...childProps}
              />
            );
          })
        }
      </g>
    );
  }
}

MultiBars.propTypes = {
  /**
   * className applied to `<Bars />`'s outermost wrapping `<g>`.
   */
  barsClassName: CommonPropTypes.className,

  /**
   * inline styles applied to `<Bars />`'s outermost wrapping `<g>`.
   */
  barsStyle: CommonDefaultProps.style,

  /**
   * className applied to outermost wrapping `<g>`.
   */
  className: CommonPropTypes.className,

  /**
   * If a clip path is applied to a container element (e.g., an `<AxisChart />`),<commit_msg>Multi-bars component: refactor anon fn as method renderBars.<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { scaleLinear, scaleBand, max } from 'd3';
import castArray from 'lodash/castArray';
import map from 'lodash/map';
import pick from 'lodash/pick';
import Bars from './bars';

import {
  isVertical,
  combineStyles,
  CommonDefaultProps,
  CommonPropTypes,
  memoizeByLastCall,
  propResolver,
  stackedDataArray,
} from '../../../utils';

export default class MultiBars extends React.PureComponent {
  constructor(props) {
    super(props);

    this.combineStyles = memoizeByLastCall(combineStyles);
    this.castSelectionAsArray = memoizeByLastCall((selection) => castArray(selection));
  }

  renderBars(childProps, datum) {
    const {
      barsClassName,
      barsStyle,
      colorScale,
      fieldAccessors: {
        color: colorField,
        data: dataField,
        key: keyField,
      },
      orientation,
      scales,
      selection,
      stacked,
    } = this.props;

    const key = propResolver(datum, keyField);
    const values = stacked ? datum : propResolver(datum, dataField);
    const color = colorScale(colorField ? propResolver(datum, colorField) : key);
    const outerOrdinal = isVertical(orientation) ? scales.x : scales.y;
    const translate = outerOrdinal(key);

    return (
      <Bars
        className={barsClassName}
        data={values}
        fill={color}
        key={`bars:${key}`}
        selection={this.castSelectionAsArray(selection)}
        style={barsStyle}
        categoryTranslate={translate}
        {...childProps}
      />
    );
  }

  render() {
    const {
      className,
      clipPathId,
      data,
      dataAccessors,
      fieldAccessors: {
        data: dataField,
      },
      layerDomain,
      layerOrdinal,
      orientation,
      scales,
      style,
      stacked,
    } = this.props;

    const {
      layer: layerField,
      value: valueField,
      stack: stackField,
    } = dataAccessors;

    // If stacked bar chart, the data must be transformed using d3.stack() function.
    const plotData = stacked
      ? stackedDataArray(data, layerField, valueField, stackField, dataField, layerDomain)
      : data;

    // Updates specific domains for each type of bar chart
    if (stacked) {
      const stackedDomain =
        [0, max(plotData, datum => max(datum, d => d[1]))];
      const linear = isVertical(orientation) ? scales.y : scales.x;
      linear.domain(stackedDomain);
    } else {
      const ordinal = isVertical(orientation) ? scales.x : scales.y;
      layerOrdinal.domain(layerDomain).range([0, ordinal.bandwidth()]);
    }

    const childProps = pick(this.props, [
      'align',
      'bandPadding',
      'bandPaddingInner',
      'bandPaddingOuter',
      'colorScale',
      'dataAccessors',
      'focus',
      'focusedClassName',
      'focusedStyle',
      'height',
      'layerOrdinal',
      'layerDomain',
      'onClick',
      'onMouseLeave',
      'onMouseMove',
      'onMouseOver',
      'orientation',
      'selectedClassName',
      'selectedStyle',
      'scales',
      'rectClassName',
      'rectStyle',
      'stacked',
      'grouped',
    ]);

    return (
      <g
        className={className && classNames(className)}
        clipPath={clipPathId && `url(#${clipPathId})`}
        style={this.combineStyles(style, data)}
      >
        {map(plotData, this.renderBars.bind(this, childProps))}
      </g>
    );
  }
}

MultiBars.propTypes = {
  /**
   * className applied to `<Bars />`'s outermost wrapping `<g>`.
   */
  barsClassName: CommonPropTypes.className,

  /**
   * inline styles applied to `<Bars />`'s outermost wrapping `<g>`.
   */
  barsStyle: CommonDefaultProps.style,

  /**
   * className applied to outermost wrapping `<g>`.
   */
  className: CommonPropTypes.className,

  /**
   * If a clip path is applied to a container element (e.g., an `<AxisChart />`),
{'fraction_non_alphanumeric': 0.12244640605296343, 'fraction_numerical': 0.0012610340479192938, 'mean_word_length': 2.4602966841186737, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 28, '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': '6587332', 'n_tokens_mistral': 2387, 'n_tokens_neox': 2329, 'n_words': 538}