<commit_before>import _ from 'lodash'
import React from 'react'

import Search from '02-molecules/Search.jsx'

import dom from '00-utilities/dom'

export default React.createClass({

  propTypes: {
    onSearch: React.PropTypes.func,
    onBlur: React.PropTypes.func,
    searchable: React.PropTypes.bool,
    x: React.PropTypes.number,
    y: React.PropTypes.number,
    children: React.PropTypes.array,
    search: React.PropTypes.oneOfType([
      React.PropTypes.string,
      React.PropTypes.bool
    ])
  },

  getDefaultProps: function () {
    return {
      onSearch: _.noop,
      onBlur: _.noop,
      searchable: false,
      x: 0,
      y: 0
    }
  },

  getInitialState: function () {
    return {
      maxHeight: 'none',
      marginLeft: 0,
      orientation: 'center',
      pattern: ''
    }
  },

  componentDidMount: function () {
    window.addEventListener('resize', this._onResize)

    this._onResize()
    if (this.props.search) {
      React.findDOMNode(this.refs.search).focus()
    } else {
      React.findDOMNode(this).focus()
    }
  },

  componentDidUpdate: function () {
    this._onResize()
  },

  componentWillUnmount: function () {
    window.removeEventListener('resize', this._onResize)
  },

  shouldComponentUpdate: function (nextProps, nextState) {
    return !_.isEqual(nextProps, this.props) // || !_.isEqual(nextState, this.state)
  },

  _onResize: function () {
    var menu = dom.dimensions(React.findDOMNode(this.refs.menu))
    var items = (this.refs.itemlist ? dom.dimensions(React.findDOMNode(this.refs.itemlist)) : {height: 0})

    // Compute offset relative to the viewport
    var x = this.props.x - window.pageXOffset
    var y = this.props.y - window.pageYOffset

    // Default position is centered
    var orientation = 'center'
    var marginLeft = -menu.width / 2

    // Calculate the edges based on a centered menu
    var rightEdge = x + (menu.width / 2)
    var leftEdge = x - (menu.width / 2)

    if (menu.width > window.innerWidth || leftEdge < 0) {
      orientation = 'left'
      marginLeft = 0
    } else if (rightEdge > window.innerWidth) {
      orientation = 'right'
      marginLeft = 0
    }

    this.setState({
      orientation: orientation,
      maxHeight: Math.floor(window.innerHeight - y - (menu.height - items.height)),
      marginLeft: Math.floor(marginLeft)
    })
  },

  render: function () {
    var itemlistStyle = { maxHeight: this.state.maxHeight }
    var containerStyle = { marginLeft: this.state.marginLeft }
    var position = {
      position: 'absolute',
      left: this.props.x,
      top: this.props.y
    }

    var search = this.props.searchable ? (<Search onChange={this.props.onSearch} onBlur={this.onBlur} />) : null

    return (
      <div className='menu' style={position} tabIndex='-1' onBlur={this.onBlur}>
        <div className={this.state.orientation + ' container'}
          style={containerStyle}
          ref='menu'>

          <div className='background'>
            <div className='arrow'></div>
            {search}
            <ul ref='itemlist' style={itemlistStyle}>
              {this.props.children}
            </ul>
          </div>
<commit_msg>round the maxHeight to the nearest 10 - so as to try and fix the stack trace exceeded issue in menu.jsx<commit_after>import _ from 'lodash'
import React from 'react'

import Search from '02-molecules/Search.jsx'

import dom from '00-utilities/dom'

export default React.createClass({

  propTypes: {
    onSearch: React.PropTypes.func,
    onBlur: React.PropTypes.func,
    searchable: React.PropTypes.bool,
    x: React.PropTypes.number,
    y: React.PropTypes.number,
    children: React.PropTypes.array,
    search: React.PropTypes.oneOfType([
      React.PropTypes.string,
      React.PropTypes.bool
    ])
  },

  getDefaultProps: function () {
    return {
      onSearch: _.noop,
      onBlur: _.noop,
      searchable: false,
      x: 0,
      y: 0
    }
  },

  getInitialState: function () {
    return {
      maxHeight: 'none',
      marginLeft: 0,
      orientation: 'center',
      pattern: ''
    }
  },

  componentDidMount: function () {
    window.addEventListener('resize', this._onResize)

    this._onResize()
    if (this.props.search) {
      React.findDOMNode(this.refs.search).focus()
    } else {
      React.findDOMNode(this).focus()
    }
  },

  componentDidUpdate: function () {
    this._onResize()
  },

  componentWillUnmount: function () {
    window.removeEventListener('resize', this._onResize)
  },

  shouldComponentUpdate: function (nextProps, nextState) {
    return !_.isEqual(nextProps, this.props) || !_.isEqual(nextState, this.state)
  },

  _onResize: function () {
    var menu = dom.dimensions(React.findDOMNode(this.refs.menu))
    var items = (this.refs.itemlist ? dom.dimensions(React.findDOMNode(this.refs.itemlist)) : {height: 0})

    // Compute offset relative to the viewport
    var x = this.props.x - window.pageXOffset
    var y = this.props.y - window.pageYOffset

    // Default position is centered
    var orientation = 'center'
    var marginLeft = -menu.width / 2

    // Calculate the edges based on a centered menu
    var rightEdge = x + (menu.width / 2)
    var leftEdge = x - (menu.width / 2)

    if (menu.width > window.innerWidth || leftEdge < 0) {
      orientation = 'left'
      marginLeft = 0
    } else if (rightEdge > window.innerWidth) {
      orientation = 'right'
      marginLeft = 0
    }

    this.setState({
      orientation: orientation,
      maxHeight: Math.round(Math.floor(window.innerHeight - y - (menu.height - items.height)) / 10) * 10,
      marginLeft: Math.floor(marginLeft)
    })
  },

  render: function () {
    var itemlistStyle = { maxHeight: this.state.maxHeight }
    var containerStyle = { marginLeft: this.state.marginLeft }
    var position = {
      position: 'absolute',
      left: this.props.x,
      top: this.props.y
    }

    var search = this.props.searchable ? (<Search onChange={this.props.onSearch} onBlur={this.onBlur} />) : null

    return (
      <div className='menu' style={position} tabIndex='-1' onBlur={this.onBlur}>
        <div className={this.state.orientation + ' container'}
          style={containerStyle}
          ref='menu'>

          <div className='background'>
            <div className='arrow'></div>
            {search}
            <ul ref='itemlist' style={itemlistStyle}>
              {this.props.children}
            </ul>
          </div>

{'fraction_non_alphanumeric': 0.12833976833976835, 'fraction_numerical': 0.0055598455598455596, 'mean_word_length': 2.581858407079646, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 25, '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': '3615675', 'n_tokens_mistral': 2071, 'n_tokens_neox': 2003, 'n_words': 445}