{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "slope",
  "type": "registry:component",
  "title": "Slope",
  "description": "Before and after, one line per item. Sample data: store conversion by channel, September to October, email 4.1% to 5.2%.",
  "registryDependencies": [
    "@chartory/core",
    "@chartory/plot-slope"
  ],
  "files": [
    {
      "path": "registry/chartory/components/slope.tsx",
      "type": "registry:component",
      "target": "components/chartory/slope.tsx",
      "content": "// SPDX-License-Identifier: MIT · Copyright (c) 2026 BEY AGENCY LTD · Chartory, usechartory.com\n// Slope (Chartory chart 044): 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/slope\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/044-slope/data\"\nimport { def } from \"@/lib/chartory/charts/types/044-slope/layout\"\n\nregisterChart(def, sample)\n\nexport type SlopeData = typeof sample\nexport type SlopeProps = Omit<ChartViewProps, \"def\" | \"data\" | \"states\"> & {\n  /** the data to draw (default: the sample) */\n  data?: SlopeData\n  /** further data states: the chart morphs to them (update) or ticks through them (live, with interval) */\n  states?: SlopeData[]\n}\n\nexport function Slope(props: SlopeProps) {\n  return <ChartView def={def} {...props} />\n}\n"
    },
    {
      "path": "registry/chartory/charts/types/044-slope/data.ts",
      "type": "registry:lib",
      "target": "lib/chartory/charts/types/044-slope/data.ts",
      "content": "// SPDX-License-Identifier: MIT · Copyright (c) 2026 BEY AGENCY LTD · Chartory, usechartory.com\n// 044 Slope · sample data (Figma chart/044, e-commerce: store conversion by channel, September → October).\nimport type { SlopeData } from \"../../plots/slope\";\n\nexport const data: SlopeData = {\n  left: \"SEP\",\n  right: \"OCT\",\n  min: 1.2,\n  max: 5.6,\n  fmt: (v) => v.toFixed(1) + \"%\",\n  rows: [\n    { label: \"Email\", a: 4.1, b: 5.2 },\n    { label: \"Search\", a: 3.2, b: 3.6 },\n    { label: \"Direct\", a: 2.7, b: 3.1 },\n    { label: \"Social\", a: 2.2, b: 1.9 },\n    { label: \"Affiliate\", a: 1.6, b: 2.3 },\n  ],\n};\n"
    },
    {
      "path": "registry/chartory/charts/types/044-slope/layout.ts",
      "type": "registry:lib",
      "target": "lib/chartory/charts/types/044-slope/layout.ts",
      "content": "// SPDX-License-Identifier: MIT · Copyright (c) 2026 BEY AGENCY LTD · Chartory, usechartory.com\n// 044 Slope (Figma chart/044): C.slope on the channel conversion sample.\nimport type { ChartDef, TooltipSpec } from \"../../core/shell\";\nimport { slope } from \"../../plots/slope\";\nimport { data } from \"./data\";\n\nconst up = data.rows.filter((r) => r.b >= r.a), down = data.rows.filter((r) => r.b < r.a);\n\n/** Tooltip for one channel (group = its line, dots and labels): the right-hand month against the left-hand one. */\nfunction tipOf(o: typeof data, g: number): TooltipSpec | null {\n  const r = o.rows[g];\n  if (!r) return null;\n  const d = Math.round((r.b - r.a) * 10) / 10;\n  return {\n    kind: \"compare\", caps: `${r.label.toUpperCase()} · ${o.right}`, value: o.fmt(r.b),\n    delta: { text: (d > 0 ? \"+\" : d < 0 ? \"−\" : \"±\") + Math.abs(d).toFixed(1) + \" pts\", tone: r.b >= r.a ? \"success\" : \"danger\" }, comparison: `VS ${o.left} ${o.fmt(r.a)}`,\n  };\n}\n\nexport const def: ChartDef = {\n  no: 44,\n  slug: \"slope\",\n  legend: [[\"status/success\", \"Improved\"], [\"status/danger\", \"Declined\"]],\n  // update: a revised read of both months; each channel moves ±0.4 points per month (one decimal, inside the axis),\n  // the direction (improved / declined) is kept\n  update: (d, step) => {\n    const o = d as typeof data;\n    const cl = (v: number) => Math.round(Math.max(o.min + 0.1, Math.min(o.max - 0.1, v)) * 10) / 10;\n    return {\n      ...o,\n      rows: o.rows.map((r, i) => {\n        const a = cl(r.a + 0.4 * Math.sin(step * 1.7 + i * 1.3));\n        let b = cl(r.b + 0.4 * Math.sin(step * 2.3 + i * 0.9));\n        if (r.b >= r.a && b < a) b = a;\n        if (r.b < r.a && b >= a) b = cl(a - 0.1);\n        return { ...r, a, b };\n      }),\n    };\n  },\n  plot: (K, p, w, d) => slope(K, p, w, (d as typeof data | undefined) ?? data),\n  tip: (d, g) => tipOf(d as typeof data, g),\n  describe: {\n    title: \"Conversion by channel, September to October\",\n    summary: `Store conversion by channel: ${up.length} of ${data.rows.length} channels improved, ${data.rows[0].label} from ${data.fmt(data.rows[0].a)} to ${data.fmt(data.rows[0].b)}; ${down.map((r) => `${r.label} fell from ${data.fmt(r.a)} to ${data.fmt(r.b)}`).join(\", \")}.`,\n    table: { head: [\"Channel\", \"September\", \"October\"], rows: data.rows.map((r) => [r.label, data.fmt(r.a), data.fmt(r.b)]) },\n  },\n};\n"
    }
  ],
  "categories": [
    "charts",
    "compare-items"
  ],
  "meta": {
    "access": "free",
    "no": 44,
    "family": "Compare items"
  }
}
