<commit_before>import d3 from 'd3';
import React from 'react';
import ReactDOM from 'react-dom';

import * as PropTypes from './PropTypes';
import cloneChildren from './utils/cloneChildren';
import transforms from './utils/transforms';

export default class ZoomArea extends React.Component {
  static propTypes = {
    zoom: React.PropTypes.func.isRequired,
    onZoom: React.PropTypes.func,
    region: PropTypes.region.isRequired,
    clipPathId: React.PropTypes.string,
    transform: React.PropTypes.string,
    children: React.PropTypes.node
  };

  static contextTypes = {
    width: React.PropTypes.number.isRequired,
    height: React.PropTypes.number.isRequired,
    marginTop: React.PropTypes.number.isRequired,
    marginRight: React.PropTypes.number.isRequired,
    marginBottom: React.PropTypes.number.isRequired,
    marginLeft: React.PropTypes.number.isRequired,
    redraw: React.PropTypes.func.isRequired
  };

  static defaultProps = {
    region: 'center'
  };

  constructor(props, context) {
    super(props, context);

    const {zoom} = props;
    const x = zoom.x();
    const y = zoom.y();

    if (x) {
      const xRange = x.range();
      this.xRangeSize = xRange[1] - xRange[0];
    } else {
      this.xRangeSize = null;
    }

    if (y) {
      const yRange = y.range();
      this.yRangeSize = yRange[0] - yRange[1];
    } else {
      this.yRangeSize = null;
    }

    // TODO: Handle when zoom object changes.
    zoom.on('zoom', () => {
      const {onZoom} = this.props;
      if (onZoom) {
        onZoom();
      }

      this.context.redraw();
    });
  }

  componentWillMount() {
    this.syncZoom();
  }

  componentDidMount() {
    d3.select(ReactDOM.findDOMNode(this)).call(this.props.zoom);
  }

  componentWillUpdate() {
    this.syncZoom();
  }

  syncZoom() {
    const {zoom} = this.props;

    // Setting zoom axes resets scale and translate, so we need to preserve the
    // old ones.
    const scale = zoom.scale();
    const translate = zoom.translate();

    zoom.scale(1);
    zoom.translate([0, 0]);

    const x = zoom.x();
    if (x) {
      // Translate is in range units; preserve domain translation here.
      const xRange = x.range();
      const nextXRangeSize = xRange[1] - xRange[0];
      if (this.xRangeSize) {
        translate[0] *= nextXRangeSize / this.xRangeSize;
      }
      this.xRangeSize = nextXRangeSize;

      zoom.x(x);
    }

    const y = zoom.y();
    if (y) {
      // Translate is in range units; preserve domain translation here.
      const yRange = y.range();
      const nextYRangeSize = yRange[0] - yRange[1];
      if (this.yRangeSize) {
        translate[1] *= nextYRangeSize / this.yRangeSize;
      }
      this.yRangeSize = nextYRangeSize;

      zoom.y(y);
    }

    // Restore the previous zoom settings.
    zoom.scale(scale);
    zoom.translate(translate);
  }

  calculatePosition() {
    const {region} = this.props;

    let {width, height} = this.context;
    if (region === 'center') {
      return {width, height};
    }

    let translateX = 0;
    let translateY = 0;

    if (region === 'top') {
      const {marginTop} = this.context;
      translateY = -marginTop;
      height = marginTop;
    } else if (region === 'right') {
      const {marginRight} = this.context;
      translateX = width;
      width = marginRight;
    } else if (region === 'bottom') {
      const {marginBottom} = this.context;
      translateY = height;
      height = marginBottom;
    } else if (region === 'left') {
      const {marginLeft} = this.context;
      translateX = -marginLeft;
      width = marginLeft;
    }

    return {
      positionTransform: `translate(${translateX},${translateY})`,
      width, height
    };
  }

  render() {
    const {clipPathId, transform, children, ...props} = this.props;
    const {positionTransform, width, height} = this.calculatePosition();

    let clipPath;
    let clipPathDef;
    if (clipPathId) {
      clipPath = `url(#${clipPathId})`;
      clipPathDef = (
        <defs>
          <clipPath id={clipPathId}>
            <rect width={width} height={height} />
          </clipPath>
        </defs>
      );
    }

    return (
      <g
        transform={transforms(transform, positionTransform)}
        clipPath={clipPath}
        {...props}
      >
        {clipPathDef}

        <rect
          width={width} height={height}
          fill="none" style={{pointerEvents: 'all'}}
        />

        {cloneChildren(children)}
      </g>
    );
  }
}
<commit_msg>Use namespaced zoom redraw handler<commit_after>import d3 from 'd3';
import React from 'react';
import ReactDOM from 'react-dom';

import * as PropTypes from './PropTypes';
import cloneChildren from './utils/cloneChildren';
import transforms from './utils/transforms';

export default class ZoomArea extends React.Component {
  static propTypes = {
    zoom: React.PropTypes.func.isRequired,
    region: PropTypes.region.isRequired,
    clipPathId: React.PropTypes.string,
    transform: React.PropTypes.string,
    children: React.PropTypes.node
  };

  static contextTypes = {
    width: React.PropTypes.number.isRequired,
    height: React.PropTypes.number.isRequired,
    marginTop: React.PropTypes.number.isRequired,
    marginRight: React.PropTypes.number.isRequired,
    marginBottom: React.PropTypes.number.isRequired,
    marginLeft: React.PropTypes.number.isRequired,
    redraw: React.PropTypes.func.isRequired
  };

  static defaultProps = {
    region: 'center'
  };

  constructor(props, context) {
    super(props, context);

    const {zoom} = props;
    const x = zoom.x();
    const y = zoom.y();

    if (x) {
      const xRange = x.range();
      this.xRangeSize = xRange[1] - xRange[0];
    } else {
      this.xRangeSize = null;
    }

    if (y) {
      const yRange = y.range();
      this.yRangeSize = yRange[0] - yRange[1];
    } else {
      this.yRangeSize = null;
    }

    // TODO: Handle when zoom object changes.
    zoom.on('zoom.redraw', this.context.redraw);
  }

  componentWillMount() {
    this.syncZoom();
  }

  componentDidMount() {
    d3.select(ReactDOM.findDOMNode(this)).call(this.props.zoom);
  }

  componentWillUpdate() {
    this.syncZoom();
  }

  syncZoom() {
    const {zoom} = this.props;

    // Setting zoom axes resets scale and translate, so we need to preserve the
    // old ones.
    const scale = zoom.scale();
    const translate = zoom.translate();

    zoom.scale(1);
    zoom.translate([0, 0]);

    const x = zoom.x();
    if (x) {
      // Translate is in range units; preserve domain translation here.
      const xRange = x.range();
      const nextXRangeSize = xRange[1] - xRange[0];
      if (this.xRangeSize) {
        translate[0] *= nextXRangeSize / this.xRangeSize;
      }
      this.xRangeSize = nextXRangeSize;

      zoom.x(x);
    }

    const y = zoom.y();
    if (y) {
      // Translate is in range units; preserve domain translation here.
      const yRange = y.range();
      const nextYRangeSize = yRange[0] - yRange[1];
      if (this.yRangeSize) {
        translate[1] *= nextYRangeSize / this.yRangeSize;
      }
      this.yRangeSize = nextYRangeSize;

      zoom.y(y);
    }

    // Restore the previous zoom settings.
    zoom.scale(scale);
    zoom.translate(translate);
  }

  calculatePosition() {
    const {region} = this.props;

    let {width, height} = this.context;
    if (region === 'center') {
      return {width, height};
    }

    let translateX = 0;
    let translateY = 0;

    if (region === 'top') {
      const {marginTop} = this.context;
      translateY = -marginTop;
      height = marginTop;
    } else if (region === 'right') {
      const {marginRight} = this.context;
      translateX = width;
      width = marginRight;
    } else if (region === 'bottom') {
      const {marginBottom} = this.context;
      translateY = height;
      height = marginBottom;
    } else if (region === 'left') {
      const {marginLeft} = this.context;
      translateX = -marginLeft;
      width = marginLeft;
    }

    return {
      positionTransform: `translate(${translateX},${translateY})`,
      width, height
    };
  }

  render() {
    const {clipPathId, transform, children, ...props} = this.props;
    const {positionTransform, width, height} = this.calculatePosition();

    let clipPath;
    let clipPathDef;
    if (clipPathId) {
      clipPath = `url(#${clipPathId})`;
      clipPathDef = (
        <defs>
          <clipPath id={clipPathId}>
            <rect width={width} height={height} />
          </clipPath>
        </defs>
      );
    }

    return (
      <g
        transform={transforms(transform, positionTransform)}
        clipPath={clipPath}
        {...props}
      >
        {clipPathDef}

        <rect
          width={width} height={height}
          fill="none" style={{pointerEvents: 'all'}}
        />

        {cloneChildren(children)}
      </g>
    );
  }
}

{'fraction_non_alphanumeric': 0.13448391796481005, 'fraction_numerical': 0.004034517538944301, 'mean_word_length': 2.404807325448302, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 20, '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': '7438079', 'n_tokens_mistral': 2832, 'n_tokens_neox': 2771, 'n_words': 646}