import React from 'react'
import ReactApexChart from 'react-apexcharts'
import ApexCharts from 'apexcharts'
import './styles.css'

function signal() {
  var out = []
  for (var i = 0; i < 40; i++) {
    var v = 50 + 22 * Math.sin(i / 4.0) + 9 * Math.sin(i / 1.4) + i * 0.4
    out.push([i, Math.round(v)])
  }
  return out
}

const ApexChart = () => {
  const [state, setState] = React.useState({
    series: [{ name: 'Signal', data: signal() }],
    options: {
      chart: {
        id: 'signal',
        type: 'line',
        height: 380,
        fontFamily: 'Helvetica, Arial, sans-serif',
        animations: { enabled: false },
        ink: { enabled: true, palette: true },
        history: { enabled: true },
        toolbar: { show: false },
        zoom: { enabled: false },
      },
      stroke: { width: 2, curve: 'smooth' },
      colors: ['#0EA5E9'],
      title: { text: 'Signal (drag the callouts)', align: 'left' },
      xaxis: { type: 'numeric', title: { text: 'Sample' } },
      yaxis: { title: { text: 'Value' } },
      annotations: {
        points: [
          {
            x: 6,
            y: 74,
            id: 'peak',
            marker: {
              size: 7,
              fillColor: '#fff',
              strokeColor: '#0EA5E9',
              strokeWidth: 3,
            },
            label: {
              text: 'Peak',
              borderColor: '#0EA5E9',
              style: { color: '#fff', background: '#0EA5E9' },
            },
          },
          {
            x: 20,
            y: 52,
            id: 'dip',
            marker: {
              size: 7,
              fillColor: '#fff',
              strokeColor: '#ef4444',
              strokeWidth: 3,
            },
            label: {
              text: 'Watch',
              borderColor: '#ef4444',
              style: { color: '#fff', background: '#ef4444' },
            },
          },
        ],
        xaxis: [
          {
            x: 10,
            x2: 16,
            id: 'window',
            fillColor: '#7DD3FC',
            opacity: 0.28,
            label: {
              text: 'Window',
              style: { color: '#fff', background: '#0EA5E9' },
            },
          },
        ],
        yaxis: [
          {
            y: 62,
            id: 'target',
            borderColor: '#f59e0b',
            strokeDashArray: 4,
            label: {
              text: 'Target',
              style: { color: '#fff', background: '#f59e0b' },
            },
          },
        ],
      },
    },
  })

  React.useEffect(() => {
    // The react-apexcharts wrapper owns the render, so reach the live instance by
    // its chart.id. Poll until it exists, then wire the same readout the vanilla
    // build does. The ink feature drives the chart instance directly (drag / edit
    // annotations), so no React state changes and the chart is not re-rendered.
    let chart
    const timer = window.setInterval(() => {
      chart = ApexCharts.getChartByID('signal')
      if (!chart) return
      window.clearInterval(timer)

      const readout = document.getElementById('ink-readout')

      chart.addEventListener('annotationDragged', (c, o) => {
        readout.textContent =
          "Moved '" +
          o.id +
          "' to x=" +
          Number(o.x).toFixed(2) +
          ', y=' +
          Number(o.y).toFixed(2)
      })
      chart.addEventListener('annotationStyled', (c, o) => {
        readout.textContent = "Restyled '" + o.id + "'"
      })
      chart.addEventListener('annotationDeleted', (c, o) => {
        readout.textContent = "Deleted '" + o.id + "' (Ctrl/Cmd+Z restores it)"
      })
    }, 50)

    return () => {
      window.clearInterval(timer)
    }
  }, [])

  return (
    <div>
      <div className="ink-wrap">
        <div className="ink-bar">
          <span className="readout" id="ink-readout">
            Drag a labelled point to reposition it
          </span>
        </div>

        <div id="chart">
          <ReactApexChart
            options={state.options}
            series={state.series}
            type="line"
            height={380}
          />
        </div>

        <div className="ink-note">
          The chart sets <code>chart.ink.enabled</code>, so its point
          annotations are
          <b>draggable</b>: grab a labelled marker and move it.{' '}
          <b>Click a note</b> to open its floating editor card: rename it
          inline, pick an accent color, toggle bold, step the text size,
          grow/shrink or reshape the <b>marker</b>, or <b>delete</b> the note
          (Enter commits, Escape closes; the swatches come from{' '}
          <code>chart.ink.noteColors</code>). On release of a drag the new
          position is converted back to data coordinates and written to
          <code>annotations.points[].x/y</code>, so the annotation stays glued
          to that data location on later zoom or resize. Use <b>+ Note</b> (the
          palette, from
          <code>chart.ink.palette</code>) then click the plot to drop a new
          labelled note. The x-axis <b>Window</b> band moves (drag its middle)
          or resizes (drag an edge), and the y-axis <b>Target</b> line drags
          vertically. Fires
          <code>annotationDragged</code> / <code>annotationEdited</code> /
          <code>annotationStyled</code> / <code>annotationCreated</code> /
          <code>annotationDeleted</code>. With the history (Rewind) feature
          enabled,
          <b>Ctrl/Cmd+Z</b> undoes any edit and Shift+Ctrl/Cmd+Z redoes it.
          Needs the
          <code>ink</code> feature. (Set <code>draggable:false</code> on a
          single annotation to pin it.)
        </div>
      </div>
    </div>
  )
}

export default ApexChart
Annotation Authoring (Ink) - React Interactivity | ApexCharts.js | ApexCharts.js