<!--
  Tiny inline sparkline. Pure SVG so we don't pull ECharts into hot
  list-view paths just to draw a 12px-tall trend line. Values are expected
  pre-normalized to [0, 100]; out-of-range points clamp.
-->
<script lang="ts">
	interface Props {
		values: number[];
		width?: number;
		height?: number;
		color?: string;
		fill?: string;
		ariaLabel?: string;
	}

	const {
		values,
		width = 80,
		height = 14,
		color = 'currentColor',
		fill = 'transparent',
		ariaLabel = ''
	}: Props = $props();

	const points = $derived.by(() => {
		const n = values.length;
		if (n === 0) return '';
		if (n === 1) {
			const y = height - (clamp(values[0]) / 100) * height;
			return `0,${y.toFixed(2)} ${width},${y.toFixed(2)}`;
		}
		const step = width / (n - 1);
		return values
			.map((v, i) => {
				const x = (i * step).toFixed(2);
				const y = (height - (clamp(v) / 100) * height).toFixed(2);
				return `${x},${y}`;
			})
			.join(' ');
	});

	const fillPath = $derived.by(() => {
		if (!values.length || fill === 'transparent') return '';
		return `M0,${height} L${points.replace(/,/g, ' ').replace(/ /g, ',')} L${width},${height} Z`
			.replace(/L,/, 'L');
	});

	function clamp(v: number): number {
		if (!Number.isFinite(v)) return 0;
		if (v < 0) return 0;
		if (v > 100) return 100;
		return v;
	}
</script>

<svg
	{width}
	{height}
	viewBox="0 0 {width} {height}"
	preserveAspectRatio="none"
	role="img"
	aria-label={ariaLabel}
	class="block"
>
	{#if values.length > 0}
		{#if fill !== 'transparent'}
			<polygon points="0,{height} {points} {width},{height}" fill={fill} stroke="none" />
		{/if}
		<polyline points={points} fill="none" stroke={color} stroke-width="1.25" stroke-linejoin="round" stroke-linecap="round" />
	{/if}
</svg>
