Warren UI

Heatmap

Density grid with tone-mixed cell fills.

Source
"use client"

import { Heatmap } from "@/registry/warren/heatmap/heatmap"

/** Deterministic PRNG so the density grid is stable across renders. */
function mulberry32(seed: number) {
  return () => {
    seed |= 0
    seed = (seed + 0x6d2b79f5) | 0
    let t = Math.imul(seed ^ (seed >>> 15), 1 | seed)
    t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t
    return ((t ^ (t >>> 14)) >>> 0) / 4294967296
  }
}

const rng = mulberry32(0x5743)
const ROWS = 12
const COLS = 32

const data: (number | undefined)[][] = Array.from({ length: ROWS }, (_, r) =>
  Array.from({ length: COLS }, (_, c) => {
    // Day-shaped envelope peaks mid-grid; each channel has its own baseline.
    const envelope = Math.sin((c / (COLS - 1)) * Math.PI)
    const channel = 0.55 + 0.45 * Math.sin((r / ROWS) * Math.PI * 2 + 1.2)
    const noise = rng()
    // ~28% of cells stay empty (bg-track); the rest spread over mid/hot steps.
    if (noise < 0.28) return 0
    return Math.round(envelope * channel * (0.6 + 0.6 * noise) * 100) / 100
  }),
)

export default function HeatmapDemo() {
  return <Heatmap data={data} />
}

Installation

npx shadcn@latest add https://warren.eduard3v.com/r/heatmap.json

Usage

import { Heatmap } from "@/components/ui/heatmap"
<Heatmap data={matrix} />

Values

Cells render three stepped fills: empty/0 cells are bg-track, 0 < v < 0.6 renders the soft mid step, and v >= 0.6 renders the hot solid tone. Each tone's mid step is a solid *-soft token (bg-primary-soft, bg-success-soft, bg-danger-soft, bg-warning-soft, bg-accent-soft, bg-teal-soft; muted reuses its well fill) — flat fills, never a wash. The computed aria-label summarizes the row/column counts, the populated percentage, and the hot/mid/empty tallies, so dense grids stay screen-reader friendly while the grid itself scrolls in a horizontal well.

Long-range hit

Source
"use client"

import { Heatmap } from "@/registry/warren/heatmap/heatmap"

/** Deterministic PRNG so the density grid is stable across renders. */
function mulberry32(seed: number) {
  return () => {
    seed |= 0
    seed = (seed + 0x6d2b79f5) | 0
    let t = Math.imul(seed ^ (seed >>> 15), 1 | seed)
    t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t
    return ((t ^ (t >>> 14)) >>> 0) / 4294967296
  }
}

const rng = mulberry32(0x5743)
const ROWS = 12
const COLS = 32

const data: (number | undefined)[][] = Array.from({ length: ROWS }, (_, r) =>
  Array.from({ length: COLS }, (_, c) => {
    // Day-shaped envelope peaks mid-grid; each channel has its own baseline.
    const envelope = Math.sin((c / (COLS - 1)) * Math.PI)
    const channel = 0.55 + 0.45 * Math.sin((r / ROWS) * Math.PI * 2 + 1.2)
    const noise = rng()
    // ~28% of cells stay empty (bg-track); the rest spread over mid/hot steps.
    if (noise < 0.28) return 0
    return Math.round(envelope * channel * (0.6 + 0.6 * noise) * 100) / 100
  }),
)

export default function HeatmapHit() {
  return <Heatmap data={data} hit={{ row: 4, col: 22 }} />
}

hit takes a 0-indexed { row, col } and draws the orange warning outline (outline-2 outline-warning) over that cell — regardless of its value — marking a long-range detection in the field.

API Reference

Prop

Type

On this page