text: import * as array from 'd3-array'
  import * as scale from 'd3-scale'
  import * as shape from 'd3-shape'
  import PropTypes from 'prop-types'
  import React, { PureComponent } from 'react'
  import { View } from 'react-native'
  import Svg from 'expo'
  import Path from '../animated-path'
  
  class Chart extends PureComponent {
  
      state = {
          width: 0,
          height: 0,
      }
  
      _onLayout(event) {
          const { nativeEvent: { layout: { height, width } } } = event
          this.setState({ height, width })
      }
  
      createPaths() {
          throw 'Extending "Chart" requires you to override "createPaths'
      }
  
      render() {
  
          const {
              data,
              xAccessor,
              yAccessor,
              yScale,
              xScale,
              style,
              animate,
              animationDuration,
              numberOfTicks,
              contentInset: {
                  top = 0,
                  bottom = 0,
                  left = 0,
                  right = 0,
              },
              gridMax,
              gridMin,
              clampX,
              clampY,
              svg,
              children,
          } = this.props
  
          const { width, height } = this.state
  
          if (data.length === 0) {
              return <View style={ style }/>
          }
  
          const mappedData = data.map((item, index) => ({
              y: yAccessor({ item, index }),
              x: xAccessor({ item, index }),
          }))
  
          const yValues = mappedData.map(item => item.y)
          const xValues = mappedData.map(item => item.x)
  
          const yExtent = array.extent([ ...yValues, gridMin, gridMax ])
          const xExtent = array.extent([ ...xValues ])
  
          const {
              yMin = yExtent[ 0 ],
              yMax = yExtent[ 1 ],
              xMin = xExtent[ 0 ],
              xMax = xExtent[ 1 ],
          } = this.props
  
          //invert range to support svg coordinate system
          const y = yScale()
              .domain([ yMin, yMax ])
              .range([ height - bottom, top ])
              .clamp(clampY)
  
          const x = xScale()
              .domain([ xMin, xMax ])
              .range([ left, width - right ])
              .clamp(clampX)
  
          const paths = this.createPaths({
              data: mappedData,
              x,
              y,
          })
  
          const ticks = y.ticks(numberOfTicks)
  
          const extraProps = {
              x,
              y,
              data,
              ticks,
              width,
              height,
              ...paths,
          }
  
          return (
              <View style={ style }>
                  <View style={{ flex: 1 }} onLayout={ event => this._onLayout(event) }>
                      {
                          height > 0 && width > 0 &&
                          <Svg style={{ height, width }}>
                              {
                                  React.Children.map(children, child => {
                                      if (child && child.props.belowChart) {
                                          return React.cloneElement(child, extraProps)
                                      }
                                      return null
                                  })
                              }
                              <Path
                                  fill={ 'none' }
                                  { ...svg }
                                  d={ paths.path }
                                  animate={ animate }
                                  animationDuration={ animationDuration }
                              />
                              {
                                  React.Children.map(children, child => {
                                      if (child && !child.props.belowChart) {
                                          return React.cloneElement(child, extraProps)
                                      }
                                      return null
                                  })
                              }
                          </Svg>
                      }
                  </View>
              </View>
          )
      }
  }
  
  Chart.propTypes = {
      data: PropTypes.oneOfType([
          PropTypes.arrayOf(PropTypes.object),
          PropTypes.arrayOf(PropTypes.number),
          PropTypes.arrayOf(PropTypes.array),
      ]).isRequired,
      svg: PropTypes.object,
  
      style: PropTypes.any,
  
      animate: PropTypes.bool,
      animationDuration: PropTypes.number,
  
      curve: PropTypes.func,
      contentInset: PropTypes.shape({
          top: PropTypes.number,
          left: PropTypes.number,
          right: PropTypes.number,
          bottom: PropTypes.number,
      }),
      numberOfTicks: PropTypes.number,
  
      gridMin: PropTypes.number,
      gridMax: PropTypes.number,
  
      yMin: PropTypes.any,
      yMax: PropTypes.any,
      xMin: PropTypes.any,
      xMax: PropTypes.any,
      clampX: PropTypes.bool,
      clampY: PropTypes.bool,
  
      xScale: PropTypes.func,
      yScale: PropTypes.func,
  
      xAccessor: PropTypes.func,
      yAccessor: PropTypes.func,
  }
  
  Chart.defaultProps = {
      svg: {},
      width: 100,
      height: 100,
      curve: shape.curveLinear,
      contentInset: {},
      numberOfTicks: 10,
      xScale: scale.scaleLinear,
      yScale: scale.scaleLinear,
      xAccessor: ({ index }) => index,
      yAccessor: ({ item }) => item,
  }
  
  export default Chart
  