{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "box-plot",
  "type": "registry:component",
  "title": "Box plot",
  "description": "The spread of each group in five numbers. Sample data: response latency of five models, Atlas 3 to Nova, on a 0 to 1.2 s scale.",
  "registryDependencies": [
    "@chartory/core",
    "@chartory/plot-box-plot"
  ],
  "files": [
    {
      "path": "registry/chartory/components/box-plot.tsx",
      "type": "registry:component",
      "target": "components/chartory/box-plot.tsx",
      "content": "// SPDX-License-Identifier: MIT · Copyright (c) 2026 BEY AGENCY LTD · Chartory, usechartory.com\n// Box plot (Chartory chart 043): 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/box-plot\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/043-box-plot/data\"\nimport { def } from \"@/lib/chartory/charts/types/043-box-plot/layout\"\n\nregisterChart(def, sample)\n\nexport type BoxPlotData = typeof sample\nexport type BoxPlotProps = Omit<ChartViewProps, \"def\" | \"data\" | \"states\"> & {\n  /** the data to draw (default: the sample) */\n  data?: BoxPlotData\n  /** further data states: the chart morphs to them (update) or ticks through them (live, with interval) */\n  states?: BoxPlotData[]\n}\n\nexport function BoxPlot(props: BoxPlotProps) {\n  return <ChartView def={def} {...props} />\n}\n"
    },
    {
      "path": "registry/chartory/charts/types/043-box-plot/data.ts",
      "type": "registry:lib",
      "target": "lib/chartory/charts/types/043-box-plot/data.ts",
      "content": "// SPDX-License-Identifier: MIT · Copyright (c) 2026 BEY AGENCY LTD · Chartory, usechartory.com\n// 043 Box plot · sample data (Figma chart/043, AI: response latency by model in ms, last 7 days).\nimport type { BoxPlotData } from \"../../plots/box-plot\";\n\nexport const data: BoxPlotData = {\n  max: 1200,\n  ticks: [\"1.2S\", \"900\", \"600\", \"300\", \"0\"],\n  rows: [\n    { label: \"ATLAS 3\", q: [180, 260, 320, 410, 620], out: [760] },\n    { label: \"KITE 2\", q: [150, 210, 260, 330, 480] },\n    { label: \"ORION\", q: [320, 480, 590, 760, 1040], out: [1150] },\n    { label: \"VEGA\", q: [120, 170, 200, 240, 330], out: [420] },\n    { label: \"NOVA\", q: [210, 300, 380, 520, 880] },\n  ],\n};\n"
    },
    {
      "path": "registry/chartory/charts/types/043-box-plot/layout.ts",
      "type": "registry:lib",
      "target": "lib/chartory/charts/types/043-box-plot/layout.ts",
      "content": "// SPDX-License-Identifier: MIT · Copyright (c) 2026 BEY AGENCY LTD · Chartory, usechartory.com\n// 043 Box plot (Figma chart/043): C.boxPlot on the model latency sample.\nimport type { ChartDef, TooltipSpec } from \"../../core/shell\";\nimport { boxPlot } from \"../../plots/box-plot\";\nimport { data } from \"./data\";\n\nconst name = (s: string) => s.charAt(0) + s.slice(1).toLowerCase();\nconst byMedian = [...data.rows].sort((a, b) => a.q[2] - b.q[2]);\nconst lo = byMedian[0], hi = byMedian[byMedian.length - 1];\n\n/** Tooltip for one model (group = its whisker, caps, box, median and outliers): the five quartiles and outliers. */\nfunction tipOf(o: typeof data, g: number): TooltipSpec | null {\n  const r = o.rows[g];\n  if (!r) return null;\n  const [mn, q1, md, q3, mx] = r.q, ms = (v: number) => v + \" ms\";\n  const rows = [\n    { label: \"Max\", value: ms(mx), swatch: \"text/action\" }, { label: \"Q3\", value: ms(q3), swatch: \"data/primary\" }, { label: \"Median\", value: ms(md), swatch: \"text/strong\" },\n    { label: \"Q1\", value: ms(q1), swatch: \"data/primary\" }, { label: \"Min\", value: ms(mn), swatch: \"text/action\" },\n  ];\n  if (r.out?.length) rows.push({ label: r.out.length > 1 ? \"Outliers\" : \"Outlier\", value: r.out.join(\", \") + \" ms\", swatch: \"text/action\" });\n  return { kind: \"range\", caps: r.label + \" · LATENCY\", rows };\n}\n\nexport const def: ChartDef = {\n  no: 43,\n  slug: \"box-plot\",\n  legend: [[\"data/primary\", \"Middle 50%\"], [\"text/strong\", \"Median\"], [\"text/action\", \"Range and outliers\"]],\n  // update: the next 7 days; each model gets faster or slower by up to ±12 % (all five quartiles and its outliers\n  // alike, whole 10 ms), kept under the axis top\n  update: (d, step) => {\n    const o = d as typeof data;\n    return {\n      ...o,\n      rows: o.rows.map((r, i) => {\n        const top = Math.max(...r.q, ...(r.out ?? []));\n        const k = Math.min(1 + 0.12 * Math.sin(step * 1.9 + i * 1.7), (o.max - 20) / top);\n        const m = (v: number) => Math.round((v * k) / 10) * 10;\n        return { ...r, q: r.q.map(m) as typeof r.q, out: r.out?.map(m) };\n      }),\n    };\n  },\n  plot: (K, p, w, d) => boxPlot(K, p, w, (d as typeof data | undefined) ?? data),\n  tip: (d, g) => tipOf(d as typeof data, g),\n  describe: {\n    title: \"Latency spread by model\",\n    summary: `Response latency over the last 7 days for ${data.rows.length} models: median from ${lo.q[2]} ms (${name(lo.label)}) to ${hi.q[2]} ms (${name(hi.label)}).`,\n    table: {\n      head: [\"Model\", \"Min (ms)\", \"Q1 (ms)\", \"Median (ms)\", \"Q3 (ms)\", \"Max (ms)\", \"Outliers (ms)\"],\n      rows: data.rows.map((r) => [name(r.label), ...r.q, (r.out ?? []).join(\", \")]),\n    },\n  },\n};\n"
    }
  ],
  "categories": [
    "charts",
    "distribution"
  ],
  "meta": {
    "access": "free",
    "no": 43,
    "family": "Distribution"
  }
}
