{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "scatter",
  "type": "registry:component",
  "title": "Scatter",
  "description": "Two measures per item, as dots. Sample data: 30-day return against volatility for BTC, ETH and tokens in layer 1, DeFi and meme groups.",
  "registryDependencies": [
    "@chartory/core",
    "@chartory/plot-scatter"
  ],
  "files": [
    {
      "path": "registry/chartory/components/scatter.tsx",
      "type": "registry:component",
      "target": "components/chartory/scatter.tsx",
      "content": "// SPDX-License-Identifier: MIT · Copyright (c) 2026 BEY AGENCY LTD · Chartory, usechartory.com\n// Scatter (Chartory chart 034): 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/scatter\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/034-scatter/data\"\nimport { def } from \"@/lib/chartory/charts/types/034-scatter/layout\"\n\nregisterChart(def, sample)\n\nexport type ScatterData = typeof sample\nexport type ScatterProps = Omit<ChartViewProps, \"def\" | \"data\" | \"states\"> & {\n  /** the data to draw (default: the sample) */\n  data?: ScatterData\n  /** further data states: the chart morphs to them (update) or ticks through them (live, with interval) */\n  states?: ScatterData[]\n}\n\nexport function Scatter(props: ScatterProps) {\n  return <ChartView def={def} {...props} />\n}\n"
    },
    {
      "path": "registry/chartory/charts/types/034-scatter/data.ts",
      "type": "registry:lib",
      "target": "lib/chartory/charts/types/034-scatter/data.ts",
      "content": "// SPDX-License-Identifier: MIT · Copyright (c) 2026 BEY AGENCY LTD · Chartory, usechartory.com\n// 034 Scatter · sample data (Figma chart/034, crypto: 30-day return against volatility per token; bubble size from the kit sample).\nimport type { ScatterData } from \"../../plots/scatter\";\n\nexport const data: ScatterData = {\n  xmin: 20, xmax: 125, ymin: -20, ymax: 40,\n  ticks: [\"+40%\", \"+20%\", \"0\", \"−20%\"],\n  xt: [[30, \"30% VOL\"], [60, \"60%\"], [90, \"90%\"], [120, \"120%\"]],\n  smax: 28,\n  pts: [\n    [38, 6, 28, \"data/cat-1\", \"BTC\"], [52, 9, 14, \"data/cat-1\", \"ETH\"], [74, 14, 4.2, \"data/cat-1\", \"SOL\"], [88, -6, 0.7, \"data/cat-1\", \"AVAX\"],\n    [70, 3, 0.6, \"data/cat-2\", \"LINK\"], [82, -2, 0.5, \"data/cat-2\", \"UNI\"], [78, 18, 0.45, \"data/cat-2\", \"AAVE\"], [66, -9, 0.3, \"data/cat-2\", \"MKR\"],\n    [96, 22, 1.8, \"data/cat-6\", \"DOGE\"], [118, 34, 0.9, \"data/cat-6\", \"PEPE\"], [104, -12, 0.6, \"data/cat-6\", \"SHIB\"], [114, -15, 0.4, \"data/cat-6\", \"BONK\"],\n  ],\n};\n"
    },
    {
      "path": "registry/chartory/charts/types/034-scatter/layout.ts",
      "type": "registry:lib",
      "target": "lib/chartory/charts/types/034-scatter/layout.ts",
      "content": "// SPDX-License-Identifier: MIT · Copyright (c) 2026 BEY AGENCY LTD · Chartory, usechartory.com\n// 034 Scatter (Figma chart/034): C.scatter on the 30-day return / volatility sample.\nimport type { ChartDef, TooltipSpec } from \"../../core/shell\";\nimport { scatter } from \"../../plots/scatter\";\nimport { data } from \"./data\";\n\nconst legend: [string, string][] = [[\"data/cat-1\", \"Layer 1\"], [\"data/cat-2\", \"DeFi\"], [\"data/cat-6\", \"Meme\"]];\nconst group = (tok: string) => legend.find((l) => l[0] === tok)![1];\nconst pct = (v: number) => (v > 0 ? \"+\" : v < 0 ? \"−\" : \"\") + Math.abs(v) + \"%\";\nconst best = [...data.pts].sort((a, b) => b[1] - a[1])[0];\n\n/** Tooltip for one bubble (group = the token's rank by volatility, left to right): its return and volatility. */\nfunction tipOf(o: typeof data, g: number): TooltipSpec | null {\n  const q = [...o.pts].sort((a, b) => a[0] - b[0])[g];\n  if (!q) return null;\n  return { kind: \"value\", text: `${q[4]} (${group(q[3])}) · ${pct(q[1])} return · ${q[0]}% vol` };\n}\n\nexport const def: ChartDef = {\n  no: 34,\n  slug: \"scatter\",\n  legend,\n  // update: the next 30 days; volatility moves ±8 points and return ±6 points per token (whole numbers, inside the\n  // axes), bubble sizes move together by a few % so their order (draw order) and which bubbles carry a label stay\n  update: (d, step) => {\n    const o = d as typeof data;\n    const k = 1 + 0.05 * Math.sin(step * 1.3);\n    const cl = (v: number, lo: number, hi: number) => Math.max(lo, Math.min(hi, v));\n    return {\n      ...o,\n      pts: o.pts.map(([x, y, s, tok, label], i) => [\n        cl(Math.round(x + 8 * Math.sin(step * 1.7 + i * 1.3)), o.xmin + 4, o.xmax - 4),\n        cl(Math.round(y + 6 * Math.sin(step * 2.3 + i * 0.8)), o.ymin + 2, o.ymax - 2),\n        +(s * k).toFixed(2), tok, label,\n      ] as typeof o.pts[number]),\n    };\n  },\n  plot: (K, p, w, d) => scatter(K, p, w, (d as typeof data | undefined) ?? data),\n  tip: (d, g) => tipOf(d as typeof data, g),\n  describe: {\n    title: \"Return vs volatility · 30 d\",\n    summary: `30-day return against volatility for ${data.pts.length} tokens in 3 groups; ${best[4]} has the highest return at ${pct(best[1])} with ${best[0]}% volatility.`,\n    table: { head: [\"Token\", \"Group\", \"Volatility\", \"Return\", \"Bubble size\"], rows: data.pts.map((q) => [q[4], group(q[3]), q[0] + \"%\", pct(q[1]), q[2]]) },\n  },\n};\n"
    }
  ],
  "categories": [
    "charts",
    "relationship"
  ],
  "meta": {
    "access": "free",
    "no": 34,
    "family": "Relationship"
  }
}
