<commit_before>import React, { PropTypes, Component } from 'react';
import ReactDOM from 'react-dom';

export default class StayScrolled extends Component {

  static propTypes = {
    component: PropTypes.oneOfType([PropTypes.string, PropTypes.func, PropTypes.element]),
    children: React.PropTypes.node,
    startScrolled: PropTypes.bool,
    onStayScrolled: PropTypes.func,
    onScrolled: PropTypes.func,
    stayInaccuracy: PropTypes.number,
    Velocity: PropTypes.func,
    debug: PropTypes.func,
  };

  static defaultProps = {
    component: 'div',
    startScrolled: true,
    stayInaccuracy: 0,
    debug: () => {},
  }

  static childContextTypes = {
    scrollBottom: PropTypes.func,
    stayScrolled: PropTypes.func,
  };

  constructor(props) {
    super(props);

    this.wasScrolled = props.startScrolled;
  }

  getChildContext() {
    return {
      scrollBottom: this.scrollBottom,
      stayScrolled: this.stayScrolled,
    };
  }

  componentDidMount() {
    const { startScrolled } = this.props;

    if (startScrolled) {
      this.scrollBottom();
    }
  }

  onScroll = () => {
    this.wasScrolled = this.isScrolled();

    if (this.wasScrolled && this.props.onScrolled) {
      this.props.onScrolled();
    }
  }

  getDOM = () => ReactDOM.findDOMNode(this.dom)

  storeDOM = (dom) => { this.dom = dom; }

  isScrolled() {
    const { stayInaccuracy, debug } = this.props;
    const dom = this.getDOM();
    const { scrollTop, clientHeight, scrollHeight } = dom;

    debug(`isScrolled: scollTop=${scrollTop}, clientHeight=${clientHeight}, scrollHeight=${scrollHeight}`);

    // scrollTop is a floating point, the rest are integers rounded up
    // naively: actualScrollHeight = scrollHeight - (Math.ceil(scrollTop) - scrollTop)
    return Math.ceil(scrollTop) + clientHeight >= (scrollHeight) - stayInaccuracy;
  }

  stayScrolled = (notify = true) => {
    const { onStayScrolled } = this.props;

    if (this.wasScrolled) {
      this.scrollBottom();
    }

    if (notify && onStayScrolled) {
      onStayScrolled(this.wasScrolled);
    }
  }

  scrollBottom = () => {
    const { Velocity, onScrolled, debug } = this.props;
    const dom = this.getDOM();

    if (!dom) return; // Necessary in case this method is called before the component rendered

    const { scrollHeight } = dom;

    debug(`Scrolling bottom: scrollHeight=${scrollHeight}`);

    if (Velocity) { // Use smooth scrolling if available
      Velocity(
        dom.firstChild,
        'scroll',
        {
          container: dom,
          offset: scrollHeight,
          duration: 300,
          easing: 'ease-out',
          complete: onScrolled,
        }
      );
    } else {
      dom.scrollTop = scrollHeight;

      if (onScrolled) {
        onScrolled();
      }
    }
  }

  render() {
    const { component, children, ...rest } = this.props;

    return (
      <component
        ref={this.storeDOM}
        onScroll={this.onScroll}
        {...rest}
      >
        {children}
      </component>
    );
  }

}<commit_msg>Fix wrapper component jsx<commit_after>import React, { PropTypes, Component } from 'react';
import ReactDOM from 'react-dom';

export default class StayScrolled extends Component {

  static propTypes = {
    component: PropTypes.oneOfType([PropTypes.string, PropTypes.func, PropTypes.element]),
    children: React.PropTypes.node,
    startScrolled: PropTypes.bool,
    onStayScrolled: PropTypes.func,
    onScrolled: PropTypes.func,
    stayInaccuracy: PropTypes.number,
    Velocity: PropTypes.func,
    debug: PropTypes.func,
  };

  static defaultProps = {
    component: 'div',
    startScrolled: true,
    stayInaccuracy: 0,
    debug: () => {},
  }

  static childContextTypes = {
    scrollBottom: PropTypes.func,
    stayScrolled: PropTypes.func,
  };

  constructor(props) {
    super(props);

    this.wasScrolled = props.startScrolled;
  }

  getChildContext() {
    return {
      scrollBottom: this.scrollBottom,
      stayScrolled: this.stayScrolled,
    };
  }

  componentDidMount() {
    const { startScrolled } = this.props;

    if (startScrolled) {
      this.scrollBottom();
    }
  }

  onScroll = () => {
    this.wasScrolled = this.isScrolled();

    if (this.wasScrolled && this.props.onScrolled) {
      this.props.onScrolled();
    }
  }

  getDOM = () => ReactDOM.findDOMNode(this.dom)

  storeDOM = (dom) => { this.dom = dom; }

  isScrolled() {
    const { stayInaccuracy, debug } = this.props;
    const dom = this.getDOM();
    const { scrollTop, clientHeight, scrollHeight } = dom;

    debug(`isScrolled: scollTop=${scrollTop}, clientHeight=${clientHeight}, scrollHeight=${scrollHeight}`);

    // scrollTop is a floating point, the rest are integers rounded up
    // naively: actualScrollHeight = scrollHeight - (Math.ceil(scrollTop) - scrollTop)
    return Math.ceil(scrollTop) + clientHeight >= (scrollHeight) - stayInaccuracy;
  }

  stayScrolled = (notify = true) => {
    const { onStayScrolled } = this.props;

    if (this.wasScrolled) {
      this.scrollBottom();
    }

    if (notify && onStayScrolled) {
      onStayScrolled(this.wasScrolled);
    }
  }

  scrollBottom = () => {
    const { Velocity, onScrolled, debug } = this.props;
    const dom = this.getDOM();

    if (!dom) return; // Necessary in case this method is called before the component rendered

    const { scrollHeight } = dom;

    debug(`Scrolling bottom: scrollHeight=${scrollHeight}`);

    if (Velocity) { // Use smooth scrolling if available
      Velocity(
        dom.firstChild,
        'scroll',
        {
          container: dom,
          offset: scrollHeight,
          duration: 300,
          easing: 'ease-out',
          complete: onScrolled,
        }
      );
    } else {
      dom.scrollTop = scrollHeight;

      if (onScrolled) {
        onScrolled();
      }
    }
  }

  render() {
    const { component, children, ...rest } = this.props;
    const WrapperComponent = component; // Upper case for jsx

    return (
      <WrapperComponent
        ref={this.storeDOM}
        onScroll={this.onScroll}
        {...rest}
      >
        {children}
      </WrapperComponent>
    );
  }

}
{'fraction_non_alphanumeric': 0.12512155591572124, 'fraction_numerical': 0.0012965964343598054, 'mean_word_length': 2.6193548387096772, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 21, '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': '1944977', 'n_tokens_mistral': 1934, 'n_tokens_neox': 1886, 'n_words': 410}