<script setup lang="ts">
import { computed } from 'vue'

const props = withDefaults(defineProps<{
  points: number[]
  stroke?: string
  fill?: string
  grid?: boolean
}>(), {
  grid: true,
  stroke: '#22d3ee',
  fill: 'rgba(34, 211, 238, 0.16)',
})

const width = 220
const height = 52
const padding = 4

const normalizedPoints = computed(() => {
  const source = props.points.length ? props.points : [0, 0]
  const max = Math.max(...source, 100)
  const min = 0
  return source.map((value, index) => {
    const x = source.length === 1
      ? width / 2
      : padding + (index * (width - padding * 2)) / (source.length - 1)
    const y = height - padding - ((value - min) / (max - min || 1)) * (height - padding * 2)
    return { x, y }
  })
})

const linePath = computed(() => normalizedPoints.value
  .map((point, index) => `${index === 0 ? 'M' : 'L'} ${point.x} ${point.y}`)
  .join(' '))

const areaPath = computed(() => {
  const points = normalizedPoints.value
  if (!points.length) return ''
  const start = points[0]
  const end = points[points.length - 1]
  return `${linePath.value} L ${end.x} ${height - padding} L ${start.x} ${height - padding} Z`
})
</script>

<template>
  <svg class="sparkline" :viewBox="`0 0 ${width} ${height}`" preserveAspectRatio="none">
    <path v-if="grid" class="sparkline-grid" d="M 0 13 H 220 M 0 26 H 220 M 0 39 H 220" />
    <path :d="areaPath" class="sparkline-area" :fill="fill" />
    <path :d="linePath" class="sparkline-line" :stroke="stroke" />
  </svg>
</template>

<style scoped>
.sparkline {
  width: 100%;
  height: 52px;
  display: block;
}

.sparkline-grid {
  fill: none;
  stroke: rgba(148, 163, 184, 0.12);
  stroke-width: 1;
  stroke-dasharray: 3 5;
}

.sparkline-area {
  opacity: 0.9;
}

.sparkline-line {
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  filter: drop-shadow(0 0 6px currentColor);
}
</style>
