PercentPond = ({ config = {}, className, style }) => {
  const domRef = useRef(null)

  const { gradientId1, gradientId2 } = useRef({
    gradientId1: `percent-pond-gradientId1-${uuid()}`,
    gradientId2: `percent-pond-gradientId2-${uuid()}`
  }).current

  const [{ width, height, mergedConfig }, setState] = useState({
    width: 0,
    height: 0,

    mergedConfig: null
  })

  const rectWidth = useMemo(() => {
    if (!mergedConfig) return 0

    const { borderWidth } = mergedConfig

    return width - borderWidth
  }, [mergedConfig, width])

  const rectHeight = useMemo(() => {
    if (!mergedConfig) return 0

    const { borderWidth } = mergedConfig

    return height - borderWidth
  }, [mergedConfig, height])

  const points = useMemo(() => {
    const halfHeight = height / 2

    if (!mergedConfig) return `0, ${halfHeight} 0, ${halfHeight}`

    const { borderWidth, borderGap, value } = mergedConfig

    const polylineLength =
      ((width - (borderWidth + borderGap) * 2) / 100) * value

    return `
      ${borderWidth + borderGap}, ${halfHeight}
      ${borderWidth + borderGap + polylineLength}, ${halfHeight + 0.001}
    `
  }, [mergedConfig, width, height])

  const polylineWidth = useMemo(() => {
    if (!mergedConfig) return 0

    const { borderWidth, borderGap } = mergedConfig

    return height - (borderWidth + borderGap) * 2
  }, [mergedConfig, height])

  const linearGradient = useMemo(() => {
    if (!mergedConfig) return []

    const { colors } = mergedConfig

    const colorNum = colors.length

    const colorOffsetGap = 100 / (colorNum - 1)

    return colors.map((c, i) => [colorOffsetGap * i, c])
  }, [mergedConfig])

  const polylineGradient = useMemo(() => {
    if (!mergedConfig) return gradientId2

    if (mergedConfig.localGradient) return gradientId1

    return gradientId2
  }, [gradientId1, gradientId2, mergedConfig])

  const gradient2XPos = useMemo(() => {
    if (!mergedConfig) return '100%'

    const { value } = mergedConfig

    return `${200 - value}%`
  }, [mergedConfig])

  const details = useMemo(() => {
    if (!mergedConfig) return ''

    const { value, formatter } = mergedConfig

    return formatter.replace('{value}', value)
  }, [mergedConfig])

  useEffect(() => {
    const { clientWidth: width, clientHeight: height } = domRef.current

    setState({
      width,
      height,
      mergedConfig: deepMerge(deepClone(defaultConfig, true), config || {})
    })
  }, [config])

  const classNames = useMemo(() => classnames('dv-percent-pond', className), [
    className
  ])

  return (
    <div className={classNames} style={style} ref={domRef}>
      <svg>
        <defs>
          <linearGradient id={gradientId1} x1='0%' y1='0%' x2='100%' y2='0%'>
            {linearGradient.map(lc => (
              <stop key={lc[0]} offset={`${lc[0]}%`} stopColor={lc[1]} />
            ))}
          </linearGradient>

          <linearGradient
            id={gradientId2}
            x1='0%'
            y1='0%'
            x2={gradient2XPos}
            y2='0%'
          >
            {linearGradient.map(lc => (
              <stop key={lc[0]} offset={`${lc[0]}%`} stopColor={lc[1]} />
            ))}
          </linearGradient>
        </defs>
        <rect
          x={mergedConfig ? mergedConfig.borderWidth / 2 : '0'}
          y={mergedConfig ? mergedConfig.borderWidth / 2 : '0'}
          rx={mergedConfig ? mergedConfig.borderRadius : '0'}
          ry={mergedConfig ? mergedConfig.borderRadius : '0'}
          fill='transparent'
          strokeWidth={mergedConfig ? mergedConfig.borderWidth : '0'}
          stroke={`url(#${gradientId1})`}
          width={rectWidth > 0 ? rectWidth : 0}
          height={rectHeight > 0 ? rectHeight : 0}
        />
        <polyline
          strokeWidth={polylineWidth}
          strokeDasharray={mergedConfig ? mergedConfig.lineDash.join(',') : '0'}
          stroke={`url(#${polylineGradient})`}
          points={points}
        />
        <text
          stroke={mergedConfig ? mergedConfig.textColor : '#fff'}
          fill={mergedConfig ? mergedConfig.textColor : '#fff'}
          x={width / 2}
          y={height / 2}
        >
          {details}
        </text>
      </svg>
    </div>
  )
}
@description Formatter
@type {String}
@default formatter = '{value}%'