sparkline function

BloomNode sparkline({
  1. required List<double> values,
  2. double width = 120,
  3. double height = 32,
  4. String? color,
  5. String extraClassName = '',
})

Lightweight inline SVG sparkline component.

Renders a concise trend visualization polyline.

Implementation

BloomNode sparkline({
  required List<double> values,
  double width = 120,
  double height = 32,
  String? color,
  String extraClassName = '',
}) {
  if (values.isEmpty) {
    return Div(
      className: cn(['h-8 w-28 bg-[var(--bg-muted)] rounded', extraClassName]),
    );
  }

  final minVal = values.reduce(math.min);
  final maxVal = values.reduce(math.max);
  final range = (maxVal - minVal) == 0 ? 1.0 : (maxVal - minVal);

  final padding = 3.0;
  final availableW = width - (padding * 2);
  final availableH = height - (padding * 2);

  final stepX = values.length > 1 ? availableW / (values.length - 1) : 0.0;

  final points = <String>[];
  for (var i = 0; i < values.length; i++) {
    final x = padding + (i * stepX);
    final normalized = (values[i] - minVal) / range;
    final y = height - padding - (normalized * availableH);
    points.add('${x.toStringAsFixed(1)},${y.toStringAsFixed(1)}');
  }

  final pointsStr = points.join(' ');
  final lineColor = color ?? 'var(--primary)';

  return El(
    'svg',
    attrs: {
      'data-slot': 'sparkline',
      'viewBox': '0 0 $width $height',
      'width': '$width',
      'height': '$height',
      'aria-hidden': 'true',
    },
    className: cn(['shrink-0 overflow-visible', extraClassName]),
    children: [
      El(
        'polyline',
        attrs: {
          'points': pointsStr,
          'fill': 'none',
          'stroke': lineColor,
          'stroke-width': '2',
          'stroke-linecap': 'round',
          'stroke-linejoin': 'round',
        },
      ),
    ],
  );
}