{{-- Dependency-free SVG chart. Renders line+area or bars from a series. @param array $series [['label' => string, 'value' => float], ...] @param string $type 'line' | 'bar' @param int $height @param string $format 'money' | 'number' | 'percent' | 'bytes' --}} @php $type = $type ?? 'line'; $height = $height ?? 190; $format = $format ?? 'number'; $labelsKey = $labelsKey ?? 'label'; $valueKey = $valueKey ?? 'value'; $values = collect($series)->map(fn ($p) => (float) (is_array($p) ? ($p[$valueKey] ?? 0) : $p))->all(); $labels = collect($series)->map(fn ($p) => is_array($p) ? ($p[$labelsKey] ?? '') : '')->all(); $w = 720; $h = $height; $padL = 46; $padR = 12; $padT = 12; $padB = 26; $plotW = $w - $padL - $padR; $plotH = $h - $padT - $padB; $max = count($values) ? max(max($values), 0.0001) : 1; $min = min(0, count($values) ? min($values) : 0); $range = ($max - $min) ?: 1; $fmt = function ($v) use ($format) { return match ($format) { 'money' => money($v), 'percent' => number_format($v, 1).'%', 'bytes' => human_bytes($v), default => $v >= 1000 ? number_format($v / 1000, 1).'k' : number_format($v, $v < 10 ? 1 : 0), }; }; $x = fn ($i) => count($values) > 1 ? $padL + ($i / (count($values) - 1)) * $plotW : $padL + $plotW / 2; $y = fn ($v) => $padT + $plotH - ((($v - $min) / $range) * $plotH); $points = []; foreach ($values as $i => $v) { $points[] = round($x($i), 2).','.round($y($v), 2); } $polyline = implode(' ', $points); $areaPath = $polyline ? 'M '.round($x(0), 2).','.round($padT + $plotH, 2).' L '.$polyline.' L '.round($x(count($values) - 1), 2).','.round($padT + $plotH, 2).' Z' : ''; $barW = count($values) ? max(3, ($plotW / count($values)) * 0.62) : 10; $gridLines = 4; @endphp @if (count($series) === 0)