<script setup lang="ts">
import { computed } from "vue";
const props = defineProps<{
data: { x: number[]; y: (number | undefined)[] };
}>();
const points = computed(() => {
const { x, y } = props.data;
if (!x?.length || !y?.length || x.length !== y.length) return "";
const minX = Math.min(...x);
const maxX = Math.max(...x);
const minY = Math.min(...y.filter((y) => y !== undefined));
const maxY = Math.max(...y.filter((y) => y !== undefined));
const dx = maxX - minX || 1;
const dy = maxY - minY;
// Add 10% padding so the line isn't cut off
const paddingY = 10;
const paddingX = 2;
const height = 100 - paddingY * 2;
const width = 100 - paddingX * 2;
return x
.map((val, i) => {
const yVal = y[i];
if (yVal === undefined) return null;
const px = 100 - paddingX - ((val - minX) / dx) * width;
const py = dy === 0 ? 50 : 100 - paddingY - ((yVal - minY) / dy) * height;
return `${px.toFixed(2)},${py.toFixed(2)}`;
})
.filter((p): p is string => p !== null)
.join(" ");
});
</script>
<template>
<div class="text-secondary-600 w-full overflow-hidden">
<svg viewBox="0 0 100 100" preserveAspectRatio="none" class="h-full w-full">
<defs>
<linearGradient id="grad" x1="0%" y1="100%" x2="0%" y2="0%">
<stop
offset="0%"
style="stop-color: var(--color-secondary-600); stop-opacity: 1"
/>
<stop
offset="100%"
style="stop-color: var(--color-secondary-300); stop-opacity: 1"
/>
</linearGradient>
</defs>
<polyline
fill="none"
stroke="url(#grad)"
stroke-width="3"
stroke-linecap="round"
stroke-linejoin="round"
vector-effect="non-scaling-stroke"
:points="points"
/>
</svg>
</div>
</template>