<script lang="ts">
  interface Datum {
    label: string;
    value: number;
  }
  interface Props {
    data: Datum[];
    height?: number;
    format?: (n: number) => string;
  }
  let { data, height = 180, format = (n) => n.toLocaleString() }: Props = $props();

  let safeData = $derived(data ?? []);
  let max = $derived(Math.max(1, ...safeData.map((d) => d.value)));
</script>

<div class="bars" style="--h: {height}px;">
  {#each safeData as d (d.label)}
    <div class="row">
      <div class="lbl" title={d.label}>{d.label}</div>
      <div class="track">
        <div class="fill" style="width: {(d.value / max) * 100}%"></div>
      </div>
      <div class="val">{format(d.value)}</div>
    </div>
  {:else}
    <div class="empty">No data yet.</div>
  {/each}
</div>

<style>
  .bars {
    display: flex;
    flex-direction: column;
    gap: 6px;
    max-height: var(--h);
    overflow-y: auto;
  }
  .row {
    display: grid;
    grid-template-columns: 160px 1fr 90px;
    gap: 10px;
    align-items: center;
    font-size: 12px;
  }
  .lbl {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--fg-dim);
  }
  .track {
    background: var(--bg-alt);
    border: 1px solid var(--border);
    height: 10px;
    border-radius: 4px;
    overflow: hidden;
  }
  .fill {
    background: var(--accent);
    height: 100%;
  }
  .val {
    text-align: right;
    font-family: var(--mono);
    color: var(--fg-dim);
  }
  .empty {
    color: var(--muted);
    font-style: italic;
    font-size: 12px;
  }
</style>
