<commit_before>let React = require('react');
let WindowListenable = require('./mixins/window-listenable');
let CssEvent = require('./utils/css-event');
let KeyCode = require('./utils/key-code');
let Transitions = require('./styles/transitions');
let StylePropable = require('./mixins/style-propable');
let FlatButton = require('./flat-button');
let Overlay = require('./overlay');
let Paper = require('./paper');

let ReactTransitionGroup = React.addons.TransitionGroup;

let TransitionItem = React.createClass({
  mixins: [StylePropable],

  contextTypes: {
    muiTheme: React.PropTypes.object,
  },

  getInitialState() {
    return {
      style: {},
    };
  },

  componentWillEnter(callback) {
    let spacing = this.context.muiTheme.spacing;

    this.setState({
      style: {
        opacity: 1,
        transform: 'translate3d(0, ' + spacing.desktopKeylineIncrement + 'px, 0)',
      },
    });

    setTimeout(callback, 450); // matches transition duration
  },

  componentWillLeave(callback) {
    this.setState({
      style: {
        opacity: 0,
        transform: 'translate3d(0, 0, 0)',
      },
    });

    setTimeout(callback, 450); // matches transition duration
  },

  render() {
    let {
      style,
      ...other,
    } = this.props;

    return <div {...other} style={this.mergeAndPrefix(this.state.style, style)}>
        {this.props.children}
      </div>;
  },
});

let Dialog = React.createClass({

  mixins: [WindowListenable, StylePropable],

  contextTypes: {
    muiTheme: React.PropTypes.object,
  },

  propTypes: {
    actions: React.PropTypes.array,
    autoDetectWindowHeight: React.PropTypes.bool,
    autoScrollBodyContent: React.PropTypes.bool,
    bodyStyle: React.PropTypes.object,
    contentClassName: React.PropTypes.string,
    contentStyle: React.PropTypes.object,
    modal: React.PropTypes.bool,
    openImmediately: React.PropTypes.bool,
    onClickAway: React.PropTypes.func,
    onDismiss: React.PropTypes.func,
    onShow: React.PropTypes.func,
    repositionOnUpdate: React.PropTypes.bool,
    title: React.PropTypes.node,
  },

  windowListeners: {
    keyup: '_handleWindowKeyUp',
    resize: '_positionDialog',
  },

  getDefaultProps() {
    return {
      autoDetectWindowHeight: false,
      autoScrollBodyContent: false,
      actions: [],
      modal: false,
      repositionOnUpdate: true,
    };
  },

  getInitialState() {
    return {
      open: this.props.openImmediately || false,
    };
  },

  componentDidMount() {
    this._positionDialog();
    if (this.props.openImmediately) {
      this.refs.dialogOverlay.preventScrolling();
      this._onShow();
    }
  },

  componentDidUpdate() {
    this._positionDialog();
  },

  getStyles() {
    let spacing = this.context.muiTheme.spacing;

    let main = {
      position: 'fixed',
      boxSizing: 'border-box',
      WebkitTapHighlightColor: 'rgba(0,0,0,0)',
      zIndex: 10,
      top: 0,
      left: -10000,
      width: '100%',
      height: '100%',
      transition: Transitions.easeOut('0ms', 'left', '450ms'),
    };

    let content = {
      boxSizing: 'border-box',
      WebkitTapHighlightColor: 'rgba(0,0,0,0)',
      transition: Transitions.easeOut(),
      position: 'relative',
      width: '75%',
      maxWidth: spacing.desktopKeylineIncrement * 12,
      margin: '0 auto',
      zIndex: 10,
    };

    let body = {
      padding: spacing.desktopGutter,
      overflowY: this.props.autoScrollBodyContent ? 'auto' : 'hidden',
      overflowX: 'hidden',
    };

    let gutter = spacing.desktopGutter + 'px ';
    let title = {
        margin: 0,
        padding: gutter + gutter + '0 ' + gutter,
        color: this.context.muiTheme.palette.textColor,
        fontSize: 24,
        lineHeight: '32px',
        fontWeight: '400',
    };


    if (this.state.open) {
      main = this.mergeAndPrefix(main, {
        left: 0,
        transition: Transitions.easeOut('0ms', 'left', '0ms'),
      });
    }

    return {
      main: this.mergeAndPrefix(main, this.props.style),
      content: this.mergeAndPrefix(content, this.props.contentStyle),
      paper: {
        background: this.context.muiTheme.canvasColor,
      },
      body: this.mergeStyles(body, this.props.bodyStyle),
      title: this.mergeStyles(title, this.props.titleStyle),
    };
  },

  render() {
    let styles = this.getStyles();
    let actions = this._getActionsContainer(this.props.actions);
    let title;
    if (this.props.title) {
      // If the title is a string, wrap in an h3 tag.
      // If not, just use it as a node.
      title = Object.prototype.toString.call(this.props.title) === '[object String]' ?
        <h3 style={styles.title}>{this.props.title}</h3> :
        this.props.title;
    }

    return (
      <div ref="container" style={styles.main}>
        <ReactTransitionGroup component="div" ref="dialogWindow">
          {this.state.open &&
            <TransitionItem
              className={this.props.contentClassName}
              style={styles.content}>
              <Paper
                style={styles.paper}
                zDepth={4}>
                {title}

                <div ref="dialogContent" style={styles.body}>
                  {this.props.children}
                </div>

                {actions}
            </Paper>
          </TransitionItem>}
        </ReactTransitionGroup>
        <Overlay
          ref="dialogOverlay"
          show={this.state.open}
          autoLockScrolling={false}
          onTouchTap={this._handleOverlayTouchTap} />
      </div>
    );
  },

  isOpen() {
    return this.state.open;
  },

  dismiss() {
    CssEvent.onTransitionEnd(this.getDOMNode(), () => {
      this.refs.dialogOverlay.allowScrolling();
    }.bind(this));

    this.setState({ open: false });
    this._onDismiss();
  },

  show() {
    this.refs.dialogOverlay.preventScrolling();
    this.setState({ open: true });
    this._onShow();
  },

  _getAction(actionJSON, key) {
    let styles = {marginRight: 8};
    let props = {
      key: key,
      secondary: true,
      onClick: actionJSON.onClick,
      onTouchTap: () => {
        if (actionJSON.onTouchTap) {
          actionJSON.onTouchTap.call(undefined);
        }
        if (!(actionJSON.onClick || actionJSON.onTouchTap)) {
          this.dismiss();
        }
      },
      label: actionJSON.text,
      style: styles,
    };
    if (actionJSON.ref) {
      props.ref = actionJSON.ref;
      props.keyboardFocused = actionJSON.ref === this.props.actionFocus;
    }
<commit_msg>Use setState callback to ensure onShow is not called before children have been rendered<commit_after>let React = require('react');
let WindowListenable = require('./mixins/window-listenable');
let CssEvent = require('./utils/css-event');
let KeyCode = require('./utils/key-code');
let Transitions = require('./styles/transitions');
let StylePropable = require('./mixins/style-propable');
let FlatButton = require('./flat-button');
let Overlay = require('./overlay');
let Paper = require('./paper');

let ReactTransitionGroup = React.addons.TransitionGroup;

let TransitionItem = React.createClass({
  mixins: [StylePropable],

  contextTypes: {
    muiTheme: React.PropTypes.object,
  },

  getInitialState() {
    return {
      style: {},
    };
  },

  componentWillEnter(callback) {
    let spacing = this.context.muiTheme.spacing;

    this.setState({
      style: {
        opacity: 1,
        transform: 'translate3d(0, ' + spacing.desktopKeylineIncrement + 'px, 0)',
      },
    });

    setTimeout(callback, 450); // matches transition duration
  },

  componentWillLeave(callback) {
    this.setState({
      style: {
        opacity: 0,
        transform: 'translate3d(0, 0, 0)',
      },
    });

    setTimeout(callback, 450); // matches transition duration
  },

  render() {
    let {
      style,
      ...other,
    } = this.props;

    return <div {...other} style={this.mergeAndPrefix(this.state.style, style)}>
        {this.props.children}
      </div>;
  },
});

let Dialog = React.createClass({

  mixins: [WindowListenable, StylePropable],

  contextTypes: {
    muiTheme: React.PropTypes.object,
  },

  propTypes: {
    actions: React.PropTypes.array,
    autoDetectWindowHeight: React.PropTypes.bool,
    autoScrollBodyContent: React.PropTypes.bool,
    bodyStyle: React.PropTypes.object,
    contentClassName: React.PropTypes.string,
    contentStyle: React.PropTypes.object,
    modal: React.PropTypes.bool,
    openImmediately: React.PropTypes.bool,
    onClickAway: React.PropTypes.func,
    onDismiss: React.PropTypes.func,
    onShow: React.PropTypes.func,
    repositionOnUpdate: React.PropTypes.bool,
    title: React.PropTypes.node,
  },

  windowListeners: {
    keyup: '_handleWindowKeyUp',
    resize: '_positionDialog',
  },

  getDefaultProps() {
    return {
      autoDetectWindowHeight: false,
      autoScrollBodyContent: false,
      actions: [],
      modal: false,
      repositionOnUpdate: true,
    };
  },

  getInitialState() {
    return {
      open: this.props.openImmediately || false,
    };
  },

  componentDidMount() {
    this._positionDialog();
    if (this.props.openImmediately) {
      this.refs.dialogOverlay.preventScrolling();
      this._onShow();
    }
  },

  componentDidUpdate() {
    this._positionDialog();
  },

  getStyles() {
    let spacing = this.context.muiTheme.spacing;

    let main = {
      position: 'fixed',
      boxSizing: 'border-box',
      WebkitTapHighlightColor: 'rgba(0,0,0,0)',
      zIndex: 10,
      top: 0,
      left: -10000,
      width: '100%',
      height: '100%',
      transition: Transitions.easeOut('0ms', 'left', '450ms'),
    };

    let content = {
      boxSizing: 'border-box',
      WebkitTapHighlightColor: 'rgba(0,0,0,0)',
      transition: Transitions.easeOut(),
      position: 'relative',
      width: '75%',
      maxWidth: spacing.desktopKeylineIncrement * 12,
      margin: '0 auto',
      zIndex: 10,
    };

    let body = {
      padding: spacing.desktopGutter,
      overflowY: this.props.autoScrollBodyContent ? 'auto' : 'hidden',
      overflowX: 'hidden',
    };

    let gutter = spacing.desktopGutter + 'px ';
    let title = {
        margin: 0,
        padding: gutter + gutter + '0 ' + gutter,
        color: this.context.muiTheme.palette.textColor,
        fontSize: 24,
        lineHeight: '32px',
        fontWeight: '400',
    };


    if (this.state.open) {
      main = this.mergeAndPrefix(main, {
        left: 0,
        transition: Transitions.easeOut('0ms', 'left', '0ms'),
      });
    }

    return {
      main: this.mergeAndPrefix(main, this.props.style),
      content: this.mergeAndPrefix(content, this.props.contentStyle),
      paper: {
        background: this.context.muiTheme.canvasColor,
      },
      body: this.mergeStyles(body, this.props.bodyStyle),
      title: this.mergeStyles(title, this.props.titleStyle),
    };
  },

  render() {
    let styles = this.getStyles();
    let actions = this._getActionsContainer(this.props.actions);
    let title;
    if (this.props.title) {
      // If the title is a string, wrap in an h3 tag.
      // If not, just use it as a node.
      title = Object.prototype.toString.call(this.props.title) === '[object String]' ?
        <h3 style={styles.title}>{this.props.title}</h3> :
        this.props.title;
    }

    return (
      <div ref="container" style={styles.main}>
        <ReactTransitionGroup component="div" ref="dialogWindow">
          {this.state.open &&
            <TransitionItem
              className={this.props.contentClassName}
              style={styles.content}>
              <Paper
                style={styles.paper}
                zDepth={4}>
                {title}

                <div ref="dialogContent" style={styles.body}>
                  {this.props.children}
                </div>

                {actions}
            </Paper>
          </TransitionItem>}
        </ReactTransitionGroup>
        <Overlay
          ref="dialogOverlay"
          show={this.state.open}
          autoLockScrolling={false}
          onTouchTap={this._handleOverlayTouchTap} />
      </div>
    );
  },

  isOpen() {
    return this.state.open;
  },

  dismiss() {
    CssEvent.onTransitionEnd(this.getDOMNode(), () => {
      this.refs.dialogOverlay.allowScrolling();
    }.bind(this));

    this.setState({ open: false });
    this._onDismiss();
  },

  show() {
    this.refs.dialogOverlay.preventScrolling();
    this.setState({ open: true }, this._onShow);
  },

  _getAction(actionJSON, key) {
    let styles = {marginRight: 8};
    let props = {
      key: key,
      secondary: true,
      onClick: actionJSON.onClick,
      onTouchTap: () => {
        if (actionJSON.onTouchTap) {
          actionJSON.onTouchTap.call(undefined);
        }
        if (!(actionJSON.onClick || actionJSON.onTouchTap)) {
          this.dismiss();
        }
      },
      label: actionJSON.text,
      style: styles,
    };
    if (actionJSON.ref) {
      props.ref = actionJSON.ref;
      props.keyboardFocused = actionJSON.ref === this.props.actionFocus;
    }

{'fraction_non_alphanumeric': 0.14045801526717558, 'fraction_numerical': 0.009923664122137405, 'mean_word_length': 2.4259937238493725, 'pattern_counts': {'":': 0, '<': 33, '<?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': '4689105', 'n_tokens_mistral': 4194, 'n_tokens_neox': 4019, 'n_words': 753}