{# Inline SVG chart helpers. No JS deps; everything renders at request time. The SVGs scale via the .chart-svg width:100% rule in brains.css. #} {% macro bar_histogram(data, height=160, max_value=None, label_field='label', value_field='value', show_values=True) %} {# data = list of {label, value}. Renders a vertical bar chart. #} {% set n = data|length %} {% if n %} {% set _max = max_value if max_value is not none else (data|map(attribute=value_field)|max) %} {% set _max = _max if _max else 1 %} {% set _padding_top = 18 %} {% set _padding_bottom = 28 %} {% set _chart_h = height - _padding_top - _padding_bottom %} {% set _gap = 4 %} {% set _viewbox_w = 480 %} {% set _bar_w = ((_viewbox_w - (_gap * (n + 1))) / n) | round(2) %} {% else %}
No data to chart.
{% endif %} {% endmacro %} {% macro sparkline(values, width=120, height=28) %} {# values = list of numbers. Renders a simple area + line sparkline. #} {% if values and values|length > 1 %} {% set _max = (values|max) %} {% set _max = _max if _max else 1 %} {% set n = values|length %} {% set _step = (width / (n - 1)) | round(3) %} {% set _pts = [] %} {% for v in values %} {% set x = (loop.index0 * _step) | round(2) %} {% set y = (height - (v / _max) * (height - 2) - 1) | round(2) %} {% set _ = _pts.append(x ~ ',' ~ y) %} {% endfor %} {% set line = ' '.join(_pts) %} {% set area = 'M0,' ~ height ~ ' L' ~ line ~ ' L' ~ width ~ ',' ~ height ~ ' Z' %} {% else %} — {% endif %} {% endmacro %}