<commit_before>import React from 'react';
import _ from 'underscore';

import {remote, clipboard} from 'electron';
import {Utils, Contact, ContactStore, RegExpUtils} from 'nylas-exports';
import {TokenizingTextField, Menu, InjectedComponent, InjectedComponentSet} from 'nylas-component-kit';

const TokenRenderer = (props) => {
  const {email, name} = props.token
  let chipText = email;
  if (name && (name.length > 0) && (name !== email)) {
    chipText = name;
  }
  return (
    <div className="participant">
      <InjectedComponentSet
        matching={{role: "Composer:RecipientChip"}}
        exposedProps={{contact: props.token, collapsed: false}}
        direction="row"
        inline
      />
      <span className="participant-primary">{chipText}</span>
    </div>
  );
};

TokenRenderer.propTypes = {
  token: React.PropTypes.object,
};

export default class ParticipantsTextField extends React.Component {
  static displayName = 'ParticipantsTextField';

  static propTypes = {
    // The name of the field, used for both display purposes and also
    // to modify the `participants` provided.
    field: React.PropTypes.string,

    // An object containing arrays of participants. Typically, this is
    // {to: [], cc: [], bcc: []}. Each ParticipantsTextField needs all of
    // the values, because adding an element to one field may remove it
    // from another.
    participants: React.PropTypes.object.isRequired,

    // The function to call with an updated `participants` object when
    // changes are made.
    change: React.PropTypes.func.isRequired,

    className: React.PropTypes.string,

    onEmptied: React.PropTypes.func,

    onFocus: React.PropTypes.func,

    draft: React.PropTypes.object,

    session: React.PropTypes.object,
  }

  static defaultProps = {
    visible: true,
  }

  shouldComponentUpdate(nextProps, nextState) {
    return !Utils.isEqualReact(nextProps, this.props) || !Utils.isEqualReact(nextState, this.state);
  }

  // Public. Can be called by any component that has a ref to this one to
  // focus the input field.
  focus = () => {
    this.refs.textField.focus();
  }

  _completionNode = (p) => {
    if (p instanceof Contact) {
      return (
        <Menu.NameEmailItem name={p.name} email={p.email} key={p.id} />
      );
    }
    return (
      <InjectedComponentSet
        ref="textField"
        matching={{role: 'ContactSearchResults'}}
        exposedProps={{token: p}}
        direction="row"
        inline
      />
    )
  }

  _tokensForString = (string, options = {}) => {
    // If the input is a string, parse out email addresses and build
    // an array of contact objects. For each email address wrapped in
    // parentheses, look for a preceding name, if one exists.
    if (string.length === 0) {
      return Promise.resolve([]);
    }

    return ContactStore.parseContactsInString(string, options).then((contacts) => {<commit_msg>feat(composer): render suggestion via custom component<commit_after>import React from 'react';
import _ from 'underscore';

import {remote, clipboard} from 'electron';
import {Utils, Contact, ContactStore, RegExpUtils} from 'nylas-exports';
import {TokenizingTextField, Menu, InjectedComponent, InjectedComponentSet} from 'nylas-component-kit';

const TokenRenderer = (props) => {
  const {email, name} = props.token
  let chipText = email;
  if (name && (name.length > 0) && (name !== email)) {
    chipText = name;
  }
  return (
    <div className="participant">
      <InjectedComponentSet
        matching={{role: "Composer:RecipientChip"}}
        exposedProps={{contact: props.token, collapsed: false}}
        direction="row"
        inline
      />
      <span className="participant-primary">{chipText}</span>
    </div>
  );
};

TokenRenderer.propTypes = {
  token: React.PropTypes.object,
};

export default class ParticipantsTextField extends React.Component {
  static displayName = 'ParticipantsTextField';

  static propTypes = {
    // The name of the field, used for both display purposes and also
    // to modify the `participants` provided.
    field: React.PropTypes.string,

    // An object containing arrays of participants. Typically, this is
    // {to: [], cc: [], bcc: []}. Each ParticipantsTextField needs all of
    // the values, because adding an element to one field may remove it
    // from another.
    participants: React.PropTypes.object.isRequired,

    // The function to call with an updated `participants` object when
    // changes are made.
    change: React.PropTypes.func.isRequired,

    className: React.PropTypes.string,

    onEmptied: React.PropTypes.func,

    onFocus: React.PropTypes.func,

    draft: React.PropTypes.object,

    session: React.PropTypes.object,
  }

  static defaultProps = {
    visible: true,
  }

  shouldComponentUpdate(nextProps, nextState) {
    return !Utils.isEqualReact(nextProps, this.props) || !Utils.isEqualReact(nextState, this.state);
  }

  // Public. Can be called by any component that has a ref to this one to
  // focus the input field.
  focus = () => {
    this.refs.textField.focus();
  }

  _completionNode = (p) => {
    const CustomComponent = p.customComponent
    if (CustomComponent) return (<CustomComponent token={p} />)
    return (
      <Menu.NameEmailItem name={p.name} email={p.email} key={p.id} />
    );
  }

  _tokensForString = (string, options = {}) => {
    // If the input is a string, parse out email addresses and build
    // an array of contact objects. For each email address wrapped in
    // parentheses, look for a preceding name, if one exists.
    if (string.length === 0) {
      return Promise.resolve([]);
    }

    return ContactStore.parseContactsInString(string, options).then((contacts) => {
{'fraction_non_alphanumeric': 0.12008353637312913, 'fraction_numerical': 0.0006961364427427776, 'mean_word_length': 3.197954711468225, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 29, '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': '5775204', 'n_tokens_mistral': 1694, 'n_tokens_neox': 1638, 'n_words': 490}