<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import { DragDropContext } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import Suggestions from './Suggestions';
import Tag from './Tag';

// Constants
const Keys = {
  ENTER: 13,
  TAB: 9,
  BACKSPACE: 8,
  UP_ARROW: 38,
  DOWN_ARROW: 40,
  ESCAPE: 27
};

const DefaultClassNames = {
  tags: 'ReactTags__tags',
  tagInput: 'ReactTags__tagInput',
  selected: 'ReactTags__selected',
  tag: 'ReactTags__tag',
  remove: 'ReactTags__remove',
  suggestions: 'ReactTags__suggestions'
};

var ReactTags = React.createClass({
  propTypes: {
    tags: React.PropTypes.array,
    placeholder: React.PropTypes.string,
    labelField: React.PropTypes.string,
    suggestions: React.PropTypes.array,
    delimiters: React.PropTypes.array,
    autofocus: React.PropTypes.bool,
    inline: React.PropTypes.bool,
    handleDelete: React.PropTypes.func.isRequired,
    handleAddition: React.PropTypes.func.isRequired,
    handleDrag: React.PropTypes.func,
    handleFilterSuggestions: React.PropTypes.func,
    allowDeleteFromEmptyInput: React.PropTypes.bool,
    handleInputChange: React.PropTypes.func,
    handleInputBlur: React.PropTypes.func,
    minQueryLength: React.PropTypes.number,
    shouldRenderSuggestions: React.PropTypes.func,
    removeComponent: React.PropTypes.func,
    autocomplete: React.PropTypes.oneOfType([React.PropTypes.bool, React.PropTypes.number]),
    readOnly: React.PropTypes.bool,
    classNames: React.PropTypes.object
  },
  getDefaultProps: function() {
    return {
      placeholder: 'Add new tag',
      tags: [],
      suggestions: [],
      delimiters: [Keys.ENTER, Keys.TAB],
      autofocus: true,
      inline: true,
      allowDeleteFromEmptyInput: true,
      minQueryLength: 2,
      autocomplete: false,
      readOnly: false,
    }
  },
  componentWillMount: function() {
    this.setState({
      classNames: {...DefaultClassNames, ...this.props.classNames}
    });
  },
  componentDidMount: function() {
    if (this.props.autofocus && !this.props.readOnly) {
      this.refs.input.focus();
    }
  },
  getInitialState: function() {
    return {
      suggestions: this.props.suggestions,
      query: "",
      selectedIndex: -1,
      selectionMode: false
    }
  },
  filteredSuggestions(query, suggestions) {
    if (this.props.handleFilterSuggestions) {
      return this.props.handleFilterSuggestions(query, suggestions)
    }

    return suggestions.filter(function(item) {
      return item.toLowerCase().indexOf(query.toLowerCase()) === 0;
    });
  },
  componentWillReceiveProps(props) {
    var suggestions = this.filteredSuggestions(this.state.query, props.suggestions);
    this.setState({
      suggestions: suggestions,
      classNames: {...DefaultClassNames, ...props.classNames}
    });
  },
  handleDelete: function(i, e) {
    this.props.handleDelete(i);
    this.setState({ query: "" });
  },
  handleChange: function(e) {
    if (this.props.handleInputChange){
      this.props.handleInputChange(e.target.value.trim())
    }

    var query = e.target.value.trim();
    var suggestions = this.filteredSuggestions(query, this.props.suggestions);
    var selectedIndex = this.state.selectedIndex;
    // if our selected entry is gonna disappear, select the last entry we will have
    if ( selectedIndex >= suggestions.length ) {
      selectedIndex = suggestions.length - 1;
    }
    this.setState({
      query: query,
      suggestions: suggestions,
      selectedIndex: selectedIndex
    });
  },
  handleBlur: function(e) {
    var value = e.target.value.trim();
    if (this.props.handleInputBlur && value.length){
      this.props.handleInputBlur(value);
      this.refs.input.value = "";
    }
  },
  handleKeyDown: function(e) {
    var { query, selectedIndex, suggestions } = this.state;

    // hide suggestions menu on escape
    if (e.keyCode === Keys.ESCAPE) {
      e.preventDefault();
      e.stopPropagation();
      this.setState({
        selectedIndex: -1,
        selectionMode: false,
        suggestions: []
      });
    }

    // When one of the terminating keys is pressed, add current query to the tags.
    // If no text is typed in so far, ignore the action - so we don't end up with a terminating
    // character typed in.
    if (this.props.delimiters.indexOf(e.keyCode) !== -1) {
      if (e.keyCode !== Keys.TAB || query !== "") {
        e.preventDefault();
      }

      if (query !== "") {
        if (this.state.selectionMode) {
          query = this.state.suggestions[this.state.selectedIndex];
        }
        this.addTag(query);
      }
    }

    // when backspace key is pressed and query is blank, delete tag
    if (e.keyCode === Keys.BACKSPACE && query == "" && this.props.allowDeleteFromEmptyInput) {
      this.handleDelete(this.props.tags.length - 1);
    }

    // up arrow
    if (e.keyCode === Keys.UP_ARROW) {
      e.preventDefault();
      var selectedIndex = this.state.selectedIndex;
      // last item, cycle to the top
      if (selectedIndex <= 0) {
        this.setState({
          selectedIndex: this.state.suggestions.length - 1,
          selectionMode: true
        });
      } else {
        this.setState({
          selectedIndex: selectedIndex - 1,
          selectionMode: true<commit_msg>Asserting that the shift key isn't being held down<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import { DragDropContext } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import Suggestions from './Suggestions';
import Tag from './Tag';

// Constants
const Keys = {
  ENTER: 13,
  TAB: 9,
  BACKSPACE: 8,
  UP_ARROW: 38,
  DOWN_ARROW: 40,
  ESCAPE: 27
};

const DefaultClassNames = {
  tags: 'ReactTags__tags',
  tagInput: 'ReactTags__tagInput',
  selected: 'ReactTags__selected',
  tag: 'ReactTags__tag',
  remove: 'ReactTags__remove',
  suggestions: 'ReactTags__suggestions'
};

var ReactTags = React.createClass({
  propTypes: {
    tags: React.PropTypes.array,
    placeholder: React.PropTypes.string,
    labelField: React.PropTypes.string,
    suggestions: React.PropTypes.array,
    delimiters: React.PropTypes.array,
    autofocus: React.PropTypes.bool,
    inline: React.PropTypes.bool,
    handleDelete: React.PropTypes.func.isRequired,
    handleAddition: React.PropTypes.func.isRequired,
    handleDrag: React.PropTypes.func,
    handleFilterSuggestions: React.PropTypes.func,
    allowDeleteFromEmptyInput: React.PropTypes.bool,
    handleInputChange: React.PropTypes.func,
    handleInputBlur: React.PropTypes.func,
    minQueryLength: React.PropTypes.number,
    shouldRenderSuggestions: React.PropTypes.func,
    removeComponent: React.PropTypes.func,
    autocomplete: React.PropTypes.oneOfType([React.PropTypes.bool, React.PropTypes.number]),
    readOnly: React.PropTypes.bool,
    classNames: React.PropTypes.object
  },
  getDefaultProps: function() {
    return {
      placeholder: 'Add new tag',
      tags: [],
      suggestions: [],
      delimiters: [Keys.ENTER, Keys.TAB],
      autofocus: true,
      inline: true,
      allowDeleteFromEmptyInput: true,
      minQueryLength: 2,
      autocomplete: false,
      readOnly: false,
    }
  },
  componentWillMount: function() {
    this.setState({
      classNames: {...DefaultClassNames, ...this.props.classNames}
    });
  },
  componentDidMount: function() {
    if (this.props.autofocus && !this.props.readOnly) {
      this.refs.input.focus();
    }
  },
  getInitialState: function() {
    return {
      suggestions: this.props.suggestions,
      query: "",
      selectedIndex: -1,
      selectionMode: false
    }
  },
  filteredSuggestions(query, suggestions) {
    if (this.props.handleFilterSuggestions) {
      return this.props.handleFilterSuggestions(query, suggestions)
    }

    return suggestions.filter(function(item) {
      return item.toLowerCase().indexOf(query.toLowerCase()) === 0;
    });
  },
  componentWillReceiveProps(props) {
    var suggestions = this.filteredSuggestions(this.state.query, props.suggestions);
    this.setState({
      suggestions: suggestions,
      classNames: {...DefaultClassNames, ...props.classNames}
    });
  },
  handleDelete: function(i, e) {
    this.props.handleDelete(i);
    this.setState({ query: "" });
  },
  handleChange: function(e) {
    if (this.props.handleInputChange){
      this.props.handleInputChange(e.target.value.trim())
    }

    var query = e.target.value.trim();
    var suggestions = this.filteredSuggestions(query, this.props.suggestions);
    var selectedIndex = this.state.selectedIndex;
    // if our selected entry is gonna disappear, select the last entry we will have
    if ( selectedIndex >= suggestions.length ) {
      selectedIndex = suggestions.length - 1;
    }
    this.setState({
      query: query,
      suggestions: suggestions,
      selectedIndex: selectedIndex
    });
  },
  handleBlur: function(e) {
    var value = e.target.value.trim();
    if (this.props.handleInputBlur && value.length){
      this.props.handleInputBlur(value);
      this.refs.input.value = "";
    }
  },
  handleKeyDown: function(e) {
    var { query, selectedIndex, suggestions } = this.state;

    // hide suggestions menu on escape
    if (e.keyCode === Keys.ESCAPE) {
      e.preventDefault();
      e.stopPropagation();
      this.setState({
        selectedIndex: -1,
        selectionMode: false,
        suggestions: []
      });
    }

    // When one of the terminating keys is pressed, add current query to the tags.
    // If no text is typed in so far, ignore the action - so we don't end up with a terminating
    // character typed in.
    if (this.props.delimiters.indexOf(e.keyCode) !== -1 && !e.shiftKey) {
      if (e.keyCode !== Keys.TAB || query !== "") {
        e.preventDefault();
      }

      if (query !== "") {
        if (this.state.selectionMode) {
          query = this.state.suggestions[this.state.selectedIndex];
        }
        this.addTag(query);
      }
    }

    // when backspace key is pressed and query is blank, delete tag
    if (e.keyCode === Keys.BACKSPACE && query == "" && this.props.allowDeleteFromEmptyInput) {
      this.handleDelete(this.props.tags.length - 1);
    }

    // up arrow
    if (e.keyCode === Keys.UP_ARROW) {
      e.preventDefault();
      var selectedIndex = this.state.selectedIndex;
      // last item, cycle to the top
      if (selectedIndex <= 0) {
        this.setState({
          selectedIndex: this.state.suggestions.length - 1,
          selectionMode: true
        });
      } else {
        this.setState({
          selectedIndex: selectedIndex - 1,
          selectionMode: true
{'fraction_non_alphanumeric': 0.125, 'fraction_numerical': 0.004113687359760658, 'mean_word_length': 2.8926491994177583, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, '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': '6463327', 'n_tokens_mistral': 3300, 'n_tokens_neox': 3238, 'n_words': 706}