<commit_before>import { Component } from 'react';
import PropTypes from 'prop-types';
import Mousetrap from 'mousetrap';

const propTypes = {
  children: PropTypes.func.isRequired,
  highlightedIndex: PropTypes.number.isRequired,
  onChange: PropTypes.func.isRequired,
  onSelect: PropTypes.func.isRequired,
  onRemove: PropTypes.func.isRequired,
};

class Highlighter extends Component {
  componentDidMount() {
    Mousetrap.prototype.stopCallback = () => false;

    Object.keys(this.keyHandlers).forEach(key => {
      Mousetrap.bind(key, this.keyHandlers[key]);
    });
  }

  componentWillUnmount() {
    Mousetrap.reset();
  }

  getItemProps = ({ item, index, ...rest }) => {
    this.items[index] = item;

    return {
      onMouseEnter: () => this.changeHighlightedIndex(index),
      onClick: () => this.selectItem(item),
      ...rest,
    };
  };

  changeHighlightedIndex = highlightedIndex => {
    this.props.onChange(highlightedIndex);
  };

  moveHighlightedIndex = amount => {
    const { highlightedIndex } = this.props;
    const listSize = this.items.length;

    let newIndex = (highlightedIndex + amount) % listSize;

    if (newIndex < 0) {
      newIndex += listSize;
    }

    this.changeHighlightedIndex(newIndex);
  };

  selectItem = item => {
    this.props.onSelect(item);
  };

  selectHighlightedItem = () => {
    if (this.items.length === 0) return;

    const { highlightedIndex } = this.props;

    this.selectItem(this.items[highlightedIndex]);
  };

  removeItem = (item, index) => {
    if (index === this.items.length - 1) {
      this.changeHighlightedIndex(index - 1);
    }

    this.props.onRemove(item);
  };

  removeHighlightedItem = () => {
    if (this.items.length === 0) return;

    const { highlightedIndex } = this.props;

    this.removeItem(this.items[highlightedIndex], highlightedIndex);
  };

  keyHandlers = {
    down: event => {
      this.moveHighlightedIndex(1);
      event.preventDefault();
    },

    up: event => {
      this.moveHighlightedIndex(-1);
      event.preventDefault();
    },

    tab: event => {
      this.moveHighlightedIndex(1);
      event.preventDefault();
    },

    'shift+tab': event => {
      this.moveHighlightedIndex(-1);
      event.preventDefault();
    },

    enter: event => {
      this.selectHighlightedItem();
      event.preventDefault();
    },

    'shift+backspace': event => {
      this.removeHighlightedItem();
      event.preventDefault();
    },
  };

  render() {
    this.items = [];

    return this.props.children({
      // state
      highlightedIndex: this.props.highlightedIndex,

      // prop getters
      getItemProps: this.getItemProps,

      // actions
      changeHighlightedIndex: this.changeHighlightedIndex,
      selectItem: this.selectItem,
      removeItem: this.removeItem,
    });
  }
}

Highlighter.propTypes = propTypes;

export default Highlighter;
<commit_msg>Move propTypes declaration inside component<commit_after>import { Component } from 'react';
import PropTypes from 'prop-types';
import Mousetrap from 'mousetrap';

class Highlighter extends Component {
  propTypes = {
    children: PropTypes.func.isRequired,
    highlightedIndex: PropTypes.number.isRequired,
    onChange: PropTypes.func.isRequired,
    onSelect: PropTypes.func.isRequired,
    onRemove: PropTypes.func.isRequired,
  };

  componentDidMount() {
    Mousetrap.prototype.stopCallback = () => false;

    Object.keys(this.keyHandlers).forEach(key => {
      Mousetrap.bind(key, this.keyHandlers[key]);
    });
  }

  componentWillUnmount() {
    Mousetrap.reset();
  }

  getItemProps = ({ item, index, ...rest }) => {
    this.items[index] = item;

    return {
      onMouseEnter: () => this.changeHighlightedIndex(index),
      onClick: () => this.selectItem(item),
      ...rest,
    };
  };

  changeHighlightedIndex = highlightedIndex => {
    this.props.onChange(highlightedIndex);
  };

  moveHighlightedIndex = amount => {
    const { highlightedIndex } = this.props;
    const listSize = this.items.length;

    let newIndex = (highlightedIndex + amount) % listSize;

    if (newIndex < 0) {
      newIndex += listSize;
    }

    this.changeHighlightedIndex(newIndex);
  };

  selectItem = item => {
    this.props.onSelect(item);
  };

  selectHighlightedItem = () => {
    if (this.items.length === 0) return;

    const { highlightedIndex } = this.props;

    this.selectItem(this.items[highlightedIndex]);
  };

  removeItem = (item, index) => {
    if (index === this.items.length - 1) {
      this.changeHighlightedIndex(index - 1);
    }

    this.props.onRemove(item);
  };

  removeHighlightedItem = () => {
    if (this.items.length === 0) return;

    const { highlightedIndex } = this.props;

    this.removeItem(this.items[highlightedIndex], highlightedIndex);
  };

  keyHandlers = {
    down: event => {
      this.moveHighlightedIndex(1);
      event.preventDefault();
    },

    up: event => {
      this.moveHighlightedIndex(-1);
      event.preventDefault();
    },

    tab: event => {
      this.moveHighlightedIndex(1);
      event.preventDefault();
    },

    'shift+tab': event => {
      this.moveHighlightedIndex(-1);
      event.preventDefault();
    },

    enter: event => {
      this.selectHighlightedItem();
      event.preventDefault();
    },

    'shift+backspace': event => {
      this.removeHighlightedItem();
      event.preventDefault();
    },
  };

  render() {
    this.items = [];

    return this.props.children({
      // state
      highlightedIndex: this.props.highlightedIndex,

      // prop getters
      getItemProps: this.getItemProps,

      // actions
      changeHighlightedIndex: this.changeHighlightedIndex,
      selectItem: this.selectItem,
      removeItem: this.removeItem,
    });
  }
}

export default Highlighter;

{'fraction_non_alphanumeric': 0.13885065381968342, 'fraction_numerical': 0.0030970406056434964, 'mean_word_length': 2.888294314381271, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 37, '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': '6621691', 'n_tokens_mistral': 1845, 'n_tokens_neox': 1771, 'n_words': 301}