{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "likert",
  "type": "registry:component",
  "title": "Likert",
  "description": "Agree and disagree, statement by statement. Sample data: five statements, easy to set up 12% disagree and 74% agree.",
  "registryDependencies": [
    "@chartory/core",
    "@chartory/plot-likert"
  ],
  "files": [
    {
      "path": "registry/chartory/components/likert.tsx",
      "type": "registry:component",
      "target": "components/chartory/likert.tsx",
      "content": "// SPDX-License-Identifier: MIT · Copyright (c) 2026 BEY AGENCY LTD · Chartory, usechartory.com\n// Likert (Chartory chart 063): 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/likert\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/063-likert/data\"\nimport { def } from \"@/lib/chartory/charts/types/063-likert/layout\"\n\nregisterChart(def, sample)\n\nexport type LikertData = typeof sample\nexport type LikertProps = Omit<ChartViewProps, \"def\" | \"data\" | \"states\"> & {\n  /** the data to draw (default: the sample) */\n  data?: LikertData\n  /** further data states: the chart morphs to them (update) or ticks through them (live, with interval) */\n  states?: LikertData[]\n}\n\nexport function Likert(props: LikertProps) {\n  return <ChartView def={def} {...props} />\n}\n"
    },
    {
      "path": "registry/chartory/charts/types/063-likert/data.ts",
      "type": "registry:lib",
      "target": "lib/chartory/charts/types/063-likert/data.ts",
      "content": "// SPDX-License-Identifier: MIT · Copyright (c) 2026 BEY AGENCY LTD · Chartory, usechartory.com\n// 063 Likert · sample data (Figma chart/063, Q3 customer survey: share of answers per statement, strongly disagree → strongly agree, %).\nimport type { LikertData } from \"../../plots/likert\";\n\nexport const data: LikertData = {\n  rows: [\n    { label: \"Easy to set up\", v: [4, 8, 14, 42, 32] },\n    { label: \"Worth the price\", v: [9, 17, 22, 34, 18] },\n    { label: \"Reports are clear\", v: [3, 7, 18, 45, 27] },\n    { label: \"Support is fast\", v: [6, 12, 20, 37, 25] },\n    { label: \"Would recommend\", v: [5, 9, 16, 38, 32] },\n  ],\n};\n"
    },
    {
      "path": "registry/chartory/charts/types/063-likert/layout.ts",
      "type": "registry:lib",
      "target": "lib/chartory/charts/types/063-likert/layout.ts",
      "content": "// SPDX-License-Identifier: MIT · Copyright (c) 2026 BEY AGENCY LTD · Chartory, usechartory.com\n// 063 Likert (Figma chart/063, \"Customer survey\"): C.likert on five survey statements.\nimport type { ChartDef, TooltipSpec } from \"../../core/shell\";\nimport { likert } from \"../../plots/likert\";\nimport { data } from \"./data\";\n\nconst pct = (v: number) => v + \"%\";\n\nconst answers: [string, string][] = [[\"Strongly disagree\", \"status/danger\"], [\"Disagree\", \"status/danger\"], [\"Neutral\", \"data/track\"], [\"Agree\", \"status/success\"], [\"Strongly agree\", \"status/success\"]];\n\n// tooltip: one statement (group = row): the share of each answer, adding up to all answers\nconst tip = (o: typeof data, g: number): TooltipSpec | null => {\n  const r = o.rows[g];\n  if (!r) return null;\n  return {\n    kind: \"series\",\n    caps: r.label.toUpperCase(),\n    rows: answers.map(([label, swatch], j) => ({ label, value: pct(r.v[j]), swatch })),\n    total: { label: \"All answers\", value: pct(r.v.reduce((a, b) => a + b, 0)) },\n  };\n};\n\nexport const def: ChartDef = {\n  no: 63,\n  slug: \"likert\",\n  legend: [[\"status/danger\", \"Disagree\"], [\"data/track\", \"Neutral\"], [\"status/success\", \"Agree\"]],\n  plot: (K, p, w, d) => likert(K, p, w, (d as typeof data | undefined) ?? data),\n  tip: (d, g) => tip(d as typeof data, g),\n  // the next quarter: points move between disagree and agree and between neutral and agree (each row still sums to 100)\n  update: (d, step) => {\n    const o = d as typeof data;\n    return {\n      ...o,\n      rows: o.rows.map((r, k) => {\n        const v = [...r.v] as typeof r.v;\n        const t = Math.max(1 - v[3], Math.min(v[1] - 1, Math.round(3 * Math.sin(k * 1.7 + step * 2.2))));\n        v[1] -= t; v[3] += t;\n        const u = Math.max(1 - v[4], Math.min(v[2] - 1, Math.round(2 * Math.sin(k * 0.9 + step * 1.3))));\n        v[2] -= u; v[4] += u;\n        return { ...r, v };\n      }),\n    };\n  },\n  describe: {\n    title: \"Q3 survey\",\n    summary: `Answers to ${data.rows.length} survey statements: agreement ranges from 52% (Worth the price) to 74% (Easy to set up); disagreement from 10% to 26%.`,\n    table: {\n      head: [\"Statement\", \"Strongly disagree\", \"Disagree\", \"Neutral\", \"Agree\", \"Strongly agree\"],\n      rows: data.rows.map((r) => [r.label, ...r.v.map(pct)]),\n    },\n  },\n};\n"
    }
  ],
  "categories": [
    "charts",
    "distribution"
  ],
  "meta": {
    "access": "free",
    "no": 63,
    "family": "Distribution"
  }
}
