{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "creance-chart",
  "title": "Creance chart helpers",
  "description": "Shared layout and styles for the chart components.",
  "registryDependencies": [
    "https://creance.pages.dev/r/creance-base.json"
  ],
  "files": [
    {
      "path": "creance-chart/chart.tsx",
      "content": "// Shared by the charts: scales, number formatting, the legend, and the table every chart carries for screen readers.\nimport type { ReactNode } from 'react';\nimport './chart.css';\n\n/** A round maximum at or above the data, with evenly spaced ticks up to it. */\nexport function niceScale(max: number, count = 4): { max: number; ticks: number[] } {\n  if (!(max > 0)) return { max: 1, ticks: [0, 1] };\n  const rough = max / count;\n  const power = 10 ** Math.floor(Math.log10(rough));\n  const step = [1, 2, 2.5, 3, 4, 5, 6, 8, 10].map((m) => m * power).find((s) => s * count >= max) ?? 10 * power;\n  // toPrecision trims binary noise such as 0.30000000000000004.\n  return { max: step * count, ticks: Array.from({ length: count + 1 }, (_, i) => Number((i * step).toPrecision(12))) };\n}\n\nexport interface ValueFormat {\n  /** Appended to every value, for example \"K\" or \"%\". */\n  unit?: string;\n  /** Replaces the default formatting. `unit` is then ignored. */\n  formatValue?: (value: number) => string;\n}\n\n/** The locale is fixed so the server and the browser print the same text. */\nexport const formatter =\n  ({ unit = '', formatValue }: ValueFormat) =>\n  (value: number) =>\n    formatValue ? formatValue(value) : `${value.toLocaleString('en-US')}${unit}`;\n\nexport type ChartTone = 'default' | 'danger';\n\n/** The fill for the nth series or slice: ink stepping down in strength, or red for a failure. */\nexport const seriesColor = (index: number, tone: ChartTone = 'default') => (tone === 'danger' ? 'var(--cr-chart-danger)' : `var(--cr-chart-${Math.min(index, 4) + 1})`);\n\nexport function ChartLegend({ items }: { items: { name: ReactNode; color: string; dashed?: boolean; value?: ReactNode; share?: ReactNode }[] }) {\n  return (\n    <ul className=\"cr-chart-legend\" aria-hidden=\"true\">\n      {items.map((item, i) => (\n        <li key={i} className=\"cr-chart-legend__item\">\n          <span className=\"cr-chart-legend__swatch\" data-dashed={item.dashed || undefined} style={{ color: item.color }} />\n          <span className=\"cr-chart-legend__name\">{item.name}</span>\n          {item.value !== undefined && <span className=\"cr-chart-legend__value\">{item.value}</span>}\n          {item.share !== undefined && <span className=\"cr-chart-legend__share\">{item.share}</span>}\n        </li>\n      ))}\n    </ul>\n  );\n}\n\n/** The chart's data as a table, for screen readers. The drawing itself is hidden from them. */\nexport function ChartTable({ caption, columns, rows }: { caption: string; columns: ReactNode[]; rows: ReactNode[][] }) {\n  return (\n    <table className=\"cr-visually-hidden\">\n      <caption>{caption}</caption>\n      <thead>\n        <tr>\n          {columns.map((c, i) => (\n            <th key={i} scope=\"col\">\n              {c}\n            </th>\n          ))}\n        </tr>\n      </thead>\n      <tbody>\n        {rows.map((row, r) => (\n          <tr key={r}>\n            {row.map((cell, i) => (i === 0 ? <th key={i} scope=\"row\">{cell}</th> : <td key={i}>{cell}</td>))}\n          </tr>\n        ))}\n      </tbody>\n    </table>\n  );\n}\n",
      "type": "registry:lib",
      "target": "@lib/creance/chart.tsx"
    },
    {
      "path": "creance-chart/chart.css",
      "content": "/* Series step down in ink, so they differ in lightness rather than hue. Red is for a failure. */\n.cr-chart {\n  --cr-chart-1: var(--cr-color-text-default);\n  --cr-chart-2: color-mix(in srgb, var(--cr-color-text-default) 50%, transparent);\n  --cr-chart-3: color-mix(in srgb, var(--cr-color-text-default) 30%, transparent);\n  --cr-chart-4: color-mix(in srgb, var(--cr-color-text-default) 18%, transparent);\n  --cr-chart-5: color-mix(in srgb, var(--cr-color-text-default) 10%, transparent);\n  --cr-chart-danger: var(--cr-color-danger-text);\n  --cr-chart-axis: 44px;\n  position: relative;\n  display: flex;\n  flex-direction: column;\n  gap: var(--cr-space-3);\n  margin: 0;\n  color: var(--cr-color-text-default);\n  font-family: var(--cr-font-family-sans);\n  font-variant-numeric: tabular-nums;\n}\n\n/* The plot sits to the right of the axis labels. Ticks are lines across it, with a label hanging off the left. */\n.cr-chart__plot {\n  position: relative;\n  margin-inline-start: var(--cr-chart-axis);\n}\n\n.cr-chart__tick {\n  position: absolute;\n  right: 0;\n  left: 0;\n  height: 1px;\n  background: var(--cr-color-border-default);\n}\n\n.cr-chart__tick-label {\n  position: absolute;\n  right: 100%;\n  top: 50%;\n  padding-inline-end: var(--cr-space-2);\n  color: var(--cr-color-text-muted);\n  font-size: 11px;\n  line-height: 1;\n  transform: translateY(-50%);\n  white-space: nowrap;\n}\n\n.cr-chart__labels {\n  position: relative;\n  height: 16px;\n  margin-inline-start: var(--cr-chart-axis);\n  color: var(--cr-color-text-muted);\n  font-size: 11px;\n}\n\n.cr-chart-legend {\n  display: flex;\n  flex-wrap: wrap;\n  gap: var(--cr-space-2) var(--cr-space-4);\n  margin: 0;\n  padding: 0;\n  list-style: none;\n  color: var(--cr-color-text-secondary);\n  font-size: var(--cr-font-size-sm);\n}\n\n.cr-chart-legend__item {\n  display: flex;\n  align-items: center;\n  gap: var(--cr-space-2);\n}\n\n.cr-chart-legend__swatch {\n  flex: none;\n  width: 10px;\n  height: 10px;\n  border-radius: 3px;\n  background: currentColor;\n}\n\n/* A dashed series shows a dashed key, so the legend matches the line and not only its shade. */\n.cr-chart-legend__swatch[data-dashed] {\n  width: 14px;\n  height: 0;\n  border-top: 2px dashed currentColor;\n  border-radius: 0;\n  background: none;\n}\n\n.cr-chart-legend__value {\n  margin-inline-start: auto;\n  color: var(--cr-color-text-default);\n  font-weight: var(--cr-font-weight-semibold);\n}\n\n.cr-chart-legend__share {\n  width: 36px;\n  color: var(--cr-color-text-muted);\n  text-align: end;\n}\n",
      "type": "registry:file",
      "target": "@lib/creance/chart.css"
    }
  ],
  "type": "registry:lib"
}