<commit_before>var React = require('react/addons');
var Immutable = require('immutable');
var cx = require("classnames");

var cloneWithProps = React.addons.cloneWithProps;
var { object, func, instanceOf } = React.PropTypes;

var Menu = React.createClass({
  propTypes: {
    content: instanceOf(Immutable.Map),
    selection: object.isRequired,
    onChange: func
  },

  getDefaultProps() {
    return {
      onChange: Function.prototype
    };
  },

  getInitialState() {
    return {
      inputMode: false
    };
  },

  componentDidUpdate() {
    if (!this.state.inputMode) { return; }

    setTimeout( () => {
      React.findDOMNode(this.refs.linkInput).focus();
    }, 1);
  },

  // switch to allow input if button needs a value
  // create a snapshot of the selection so we can restore it if they close
  handleSetValue(obj, ref) {
    this.selSnapshot = this.props.selection;
    this.valueButton = this.refs[ref];
    this.setState({inputMode: true});
  },

  // handle typing in input
  handleOnKeyUp(e) {
    e.stopPropagation();
  },

  // handle enter key for input
  handleOnKeyDown(e) {
    var escapeKey = 27;
    if (e.keyCode === escapeKey) { this.handleCancelInput(); }

    var returnKey = 13;
    if (e.keyCode !== returnKey) { return; }

    e.stopPropagation();
    e.preventDefault();

    var value = e.target.value;
    this.valueButton.setValue(value);
    React.findDOMNode(this.refs.linkInput).value = "";
    this.setState({inputMode: false});
  },

  // pass the selection snapshot upstream to restore it
  handleCancelInput() {
    this.setState({inputMode: false});
    this.props.onChange(this.selSnapshot);
  },

  menuClasses() {
    return cx('arc-Editor-Menu', {
      'arc-Editor-Menu--active': this.props.selection.showMenuButtons(),
      'arc-Editor-Menu--link': this.state.inputMode
    });
  },
  itemsClasses() {
    return cx('arc-Editor-Menu__items', {
      'arc-Editor-Menu__items--active': !this.state.inputMode
    });
  },
  linkClasses() {
    return cx('arc-Editor-Menu__linkinput', {
      'arc-Editor-Menu__linkinput--active': this.state.inputMode
    });
  },

  // move menu to selected text
  menuStyles() {
    if (!this.props.selection.bounds) { return {}; }

    var selection = this.props.selection;
    var bounds = selection.bounds;
    if (!bounds.top && !bounds.left) { return {}; }

    var buttonHeight = 50;
    var menuWidth = Object.keys(this.renderButtons()).length * 43;

    return {
      top: window.pageYOffset + bounds.top - buttonHeight,
      left: bounds.left + (bounds.width / 2) - (menuWidth / 2)
    };
  },

  // build buttons from children
  renderButtons() {
    var buttons = [];
    React.Children.forEach(this.props.children, (child, i) => {
      var refName = `button_${child.props.type}`;
      var cloned = cloneWithProps(child, {
        content: this.props.content,
        selection: this.props.selection,
        onSetValue: this.handleSetValue.bind(this, child, refName),
        ref: refName
      });

      // some buttons may not be visible based on the selection
      if (cloned.type.isVisible(this.props.content, this.props.selection)) {
        buttons.push(
          <li className="arc-Editor-Menu__item" key={`button_${i}`}>
            {cloned}
          </li>
        );
      }
    });
    return buttons;
  },

  render() {
    return (
      <div ref="menu" className={this.menuClasses()} style={this.menuStyles()}>
        <div className="arc-Editor-Menu__inner">
          <ul className={this.itemsClasses()}>
            {this.renderButtons()}<commit_msg>remove deprecated cloneWithProps in favor of React.cloneElement<commit_after>var React = require('react/addons');
var Immutable = require('immutable');
var cx = require("classnames");

var { object, func, instanceOf } = React.PropTypes;

var Menu = React.createClass({
  propTypes: {
    content: instanceOf(Immutable.Map),
    selection: object.isRequired,
    onChange: func
  },

  getDefaultProps() {
    return {
      onChange: Function.prototype
    };
  },

  getInitialState() {
    return {
      inputMode: false
    };
  },

  componentDidUpdate() {
    if (!this.state.inputMode) { return; }

    setTimeout( () => {
      React.findDOMNode(this.refs.linkInput).focus();
    }, 1);
  },

  // switch to allow input if button needs a value
  // create a snapshot of the selection so we can restore it if they close
  handleSetValue(obj, ref) {
    this.selSnapshot = this.props.selection;
    this.valueButton = this.refs[ref];
    this.setState({inputMode: true});
  },

  // handle typing in input
  handleOnKeyUp(e) {
    e.stopPropagation();
  },

  // handle enter key for input
  handleOnKeyDown(e) {
    var escapeKey = 27;
    if (e.keyCode === escapeKey) { this.handleCancelInput(); }

    var returnKey = 13;
    if (e.keyCode !== returnKey) { return; }

    e.stopPropagation();
    e.preventDefault();

    var value = e.target.value;
    this.valueButton.setValue(value);
    React.findDOMNode(this.refs.linkInput).value = "";
    this.setState({inputMode: false});
  },

  // pass the selection snapshot upstream to restore it
  handleCancelInput() {
    this.setState({inputMode: false});
    this.props.onChange(this.selSnapshot);
  },

  menuClasses() {
    return cx('arc-Editor-Menu', {
      'arc-Editor-Menu--active': this.props.selection.showMenuButtons(),
      'arc-Editor-Menu--link': this.state.inputMode
    });
  },
  itemsClasses() {
    return cx('arc-Editor-Menu__items', {
      'arc-Editor-Menu__items--active': !this.state.inputMode
    });
  },
  linkClasses() {
    return cx('arc-Editor-Menu__linkinput', {
      'arc-Editor-Menu__linkinput--active': this.state.inputMode
    });
  },

  // move menu to selected text
  menuStyles() {
    if (!this.props.selection.bounds) { return {}; }

    var selection = this.props.selection;
    var bounds = selection.bounds;
    if (!bounds.top && !bounds.left) { return {}; }

    var buttonHeight = 50;
    var menuWidth = Object.keys(this.renderButtons()).length * 43;

    return {
      top: window.pageYOffset + bounds.top - buttonHeight,
      left: bounds.left + (bounds.width / 2) - (menuWidth / 2)
    };
  },

  // build buttons from children
  renderButtons() {
    var buttons = [];
    React.Children.forEach(this.props.children, (child, i) => {
      var refName = `button_${child.props.type}`;

      var cloned = React.cloneElement(child, {
        content: this.props.content,
        selection: this.props.selection,
        onSetValue: this.handleSetValue.bind(this, child, refName),
        ref: refName
      });

      // some buttons may not be visible based on the selection
      if (cloned.type.isVisible(this.props.content, this.props.selection)) {
        buttons.push(
          <li className="arc-Editor-Menu__item" key={`button_${i}`}>
            {cloned}
          </li>
        );
      }
    });
    return buttons;
  },

  render() {
    return (
      <div ref="menu" className={this.menuClasses()} style={this.menuStyles()}>
        <div className="arc-Editor-Menu__inner">
          <ul className={this.itemsClasses()}>
            {this.renderButtons()}
{'fraction_non_alphanumeric': 0.14546977523384058, 'fraction_numerical': 0.003071338824514868, 'mean_word_length': 2.7864693446088795, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 17, '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': '5494414', 'n_tokens_mistral': 2240, 'n_tokens_neox': 2214, 'n_words': 466}