<commit_before>import React, { Component, Children, PropTypes, createElement } from 'react'
import ReactDOM from 'react-dom'
import Tether from 'tether'

// TetherElement
// TetherTarget
// 
// <TetherElement
//   target={this.refs.trigger}
//   options={{}}
// >
//   <div>
//     I'm a cool box that's tethered to a trigger
//   </div>
// <TetherElement>

class TetheredElement {
  constructor(reactComponent, tetherOptions) {
    this.reactComponent = reactComponent

    this._node = document.createElement('div')
    this._node.style.position = 'absolute'
    
    document.body.appendChild(this._node)

    this.tether = new Tether({
      element: this._node,
      ...tetherOptions
    })

    this.update()
  }

  update() {
    ReactDOM.render(
      this.reactComponent,
      this._node,
      () => this.tether.position()
    )
  }

  destroy() {
    React.unmountComponentAtNode(this._node)
    this.domNode.parentNode.removeChild(this._node)
    this.tether.destroy()
  }
}

class TetherElement extends Component {
  static propTypes = {
    tethered: React.PropTypes.node.isRequired,
    tetherOptions: React.PropTypes.object.isRequired
  }

  state = {
    tooltipVisible: false
  }

  componentDidMount() {
    const tetherOptions = {
      target: ReactDOM.findDOMNode(this),
      ...this.props.tetherOptions
    }

    this._tethered = new TetheredElement(
      this.props.tethered, tetherOptions
    )
  }

  componentDidUpdate() {
    this._tethered.update()
  }

  componentWillUnmount() {
    this._tethered.destroy()
  }

  render() {
    const { tethered, tetherOptions, children, ...props } = this.props
    return Children.only(children)
  }
}

export default TetherElement<commit_msg>got it in a working state<commit_after>import React, { Component, Children, PropTypes, createElement } from 'react'
import ReactDOM from 'react-dom'
import shallowCompare from 'react-addons-shallow-compare'
import Tether from 'tether'

class TetherElement extends Component {
  static propTypes = {
    target: PropTypes.object,
    options: PropTypes.object.isRequired
  }

  _tetherInitialized = false

  componentDidMount() {
    this._node = document.createElement('div')
    this._node.style.position = 'absolute'
    
    // append node to end of body
    document.body.appendChild(this._node)

    // if target is available initialize tether
    if (this.props.target) {
      this._initTether(this.props)
    }
  }

  componentWillReceiveProps(nextProps) {
    if (!this._tetherInitialized) {
      this._initTether(nextProps)
    } else {
      this._update(nextProps)
    }
  }

  shouldComponentUpdate(nextProps, nextState) {
    return shallowCompare(this, nextProps, nextState)
  }

  componentWillUnmount() {
    ReactDOM.unmountComponentAtNode(this._node)
    this._node.parentNode.removeChild(this._node)
    this._tether.destroy()
  }

  _initTether(props) {
    // initialize tether with respective elements
    this._tether = new Tether({
      element: this._node,
      target: props.target,
      ...props.options
    })

    // update DOM
    this._update(props)

    this._tetherInitialized = true
  }

  _update(props) {
    const child = React.Children.only(props.children)

    // set options
    this._tether.setOptions({
      element: this._node,
      target: props.target,
      ...props.options
    })

    // render to DOM
    ReactDOM.render(
      child,
      this._node,
      () => this._tether.position()
    )
  }

  render() {
    return null
  }
}

export default TetherElement
{'fraction_non_alphanumeric': 0.11428571428571428, 'fraction_numerical': 0.0, 'mean_word_length': 2.8687089715536107, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, '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': '6909278', 'n_tokens_mistral': 1112, 'n_tokens_neox': 1096, 'n_words': 217}