{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "gauge",
  "type": "registry:component",
  "title": "Gauge",
  "description": "One reading on a dial, with a limit marked. Sample data: fleet utilisation today, overload above 85%.",
  "registryDependencies": [
    "@chartory/core",
    "@chartory/plot-semi-gauge"
  ],
  "files": [
    {
      "path": "registry/chartory/components/gauge.tsx",
      "type": "registry:component",
      "target": "components/chartory/gauge.tsx",
      "content": "// SPDX-License-Identifier: MIT · Copyright (c) 2026 BEY AGENCY LTD · Chartory, usechartory.com\n// Gauge (Chartory chart 021): sizes xs | s | m | l, laid out again from the data at each\n// size; collection \"hearth\" (default) or \"signal\" (with @chartory/signal, Code and Complete). Data in the type's shape (default: the sample). Docs:\n// https://usechartory.com/docs/charts/gauge\nimport { ChartView, type ChartViewProps } from \"@/lib/chartory/charts/chart-view\"\nimport { registerChart } from \"@/lib/chartory/charts/defs\"\nimport { data as sample } from \"@/lib/chartory/charts/types/021-gauge/data\"\nimport { def } from \"@/lib/chartory/charts/types/021-gauge/layout\"\n\nregisterChart(def, sample)\n\nexport type GaugeData = typeof sample\nexport type GaugeProps = Omit<ChartViewProps, \"def\" | \"data\" | \"states\"> & {\n  /** the data to draw (default: the sample) */\n  data?: GaugeData\n  /** further data states: the chart morphs to them (update) or ticks through them (live, with interval) */\n  states?: GaugeData[]\n}\n\nexport function Gauge(props: GaugeProps) {\n  return <ChartView def={def} {...props} />\n}\n"
    },
    {
      "path": "registry/chartory/charts/types/021-gauge/data.ts",
      "type": "registry:lib",
      "target": "lib/chartory/charts/types/021-gauge/data.ts",
      "content": "// SPDX-License-Identifier: MIT · Copyright (c) 2026 BEY AGENCY LTD · Chartory, usechartory.com\n// 021 Gauge · sample data (Figma chart/021, logistics: fleet utilisation today, 64 vans out).\nimport type { SemiGaugeData } from \"../../plots/semi-gauge\";\n\nexport const data: SemiGaugeData = { v: 82, warn: 85, center: \"64\", caps: \"VANS\" };\n"
    },
    {
      "path": "registry/chartory/charts/types/021-gauge/layout.ts",
      "type": "registry:lib",
      "target": "lib/chartory/charts/types/021-gauge/layout.ts",
      "content": "// SPDX-License-Identifier: MIT · Copyright (c) 2026 BEY AGENCY LTD · Chartory, usechartory.com\n// 021 Gauge (Figma chart/021): C.semiGauge; no legend (the zones are marked on the ring).\nimport type { ChartDef, TooltipSpec } from \"../../core/shell\";\nimport { semiGauge } from \"../../plots/semi-gauge\";\nimport { data } from \"./data\";\nimport { frame, type Frame, type Text } from \"../../core/node\";\n\n/** A text is named by its characters, so an update state takes the sample's text names (same order): its value\n *  labels then stay the same marks and morph in place instead of reading as new ones. */\nfunction keepNames(pl: Frame, ref: Frame): Frame {\n  const texts = (f: Frame): Text[] => f.children.flatMap((c) => (c.removed ? [] : c.kind === \"text\" ? [c] : c.kind === \"frame\" ? texts(c) : []));\n  const a = texts(pl), b = texts(ref);\n  if (a.length === b.length) a.forEach((t, i) => { if (t.name === t.text.slice(0, 40)) t.name = b[i].name; });\n  return pl;\n}\n\n/** Hover tooltip: the needle (utilisation against the overload mark, in points). */\nconst tip = (d: unknown): TooltipSpec => {\n  const o = d as typeof data, gap = o.v - o.warn;\n  return {\n    kind: \"compare\",\n    caps: `UTILISATION · ${o.center} ${o.caps} OUT`,\n    value: o.v + \"%\",\n    delta: { text: (gap < 0 ? \"−\" : \"+\") + Math.abs(gap) + (Math.abs(gap) === 1 ? \" pt\" : \" pts\"), tone: gap > 0 ? \"danger\" : gap >= -5 ? \"warning\" : \"success\" },\n    comparison: `VS ${o.warn}% OVERLOAD`,\n  };\n};\n\nexport const def: ChartDef = {\n  no: 21,\n  slug: \"gauge\",\n  legend: null,\n  plot: (K, p, w, d) => {\n    const o = (d as typeof data | undefined) ?? data;\n    const pl = semiGauge(K, p, w, o);\n    return o === data ? pl : keepNames(pl, semiGauge(K, frame(null, \"sample\"), w, data));\n  },\n  tip,\n  update: (d, step) => {\n    const o = d as typeof data;\n    // other hours: utilisation 74 / 79 / 84 % of the 78-van fleet (the vans out follow); the overload mark holds\n    const v = [82, 74, 79, 84][Math.min(step, 3)] ?? 84;\n    return { ...o, v, center: String(Math.round((78 * v) / 100)) };\n  },\n  describe: {\n    title: \"Fleet utilisation\",\n    summary: `Fleet utilisation is at ${data.v}% with ${data.center} vans out; overload starts above ${data.warn}%.`,\n    table: { head: [\"Measure\", \"Value\"], rows: [[\"Utilisation\", data.v + \"%\"], [\"Overload threshold\", data.warn + \"%\"], [\"Vans\", data.center ?? \"\"]] },\n  },\n};\n"
    }
  ],
  "categories": [
    "charts",
    "compare-items"
  ],
  "meta": {
    "access": "free",
    "no": 21,
    "family": "Compare items"
  }
}
