{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "horizon",
  "type": "registry:component",
  "title": "Horizon",
  "description": "Many series, folded into thin rows. Sample data: daily volatility of four currency pairs against its average, Aug 11 to Oct 9.",
  "registryDependencies": [
    "@chartory/core",
    "@chartory/plot-horizon"
  ],
  "files": [
    {
      "path": "registry/chartory/components/horizon.tsx",
      "type": "registry:component",
      "target": "components/chartory/horizon.tsx",
      "content": "// SPDX-License-Identifier: MIT · Copyright (c) 2026 BEY AGENCY LTD · Chartory, usechartory.com\n// Horizon (Chartory chart 054): 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/horizon\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/054-horizon/data\"\nimport { def } from \"@/lib/chartory/charts/types/054-horizon/layout\"\n\nregisterChart(def, sample)\n\nexport type HorizonData = typeof sample\nexport type HorizonProps = Omit<ChartViewProps, \"def\" | \"data\" | \"states\"> & {\n  /** the data to draw (default: the sample) */\n  data?: HorizonData\n  /** further data states: the chart morphs to them (update) or ticks through them (live, with interval) */\n  states?: HorizonData[]\n}\n\nexport function Horizon(props: HorizonProps) {\n  return <ChartView def={def} {...props} />\n}\n"
    },
    {
      "path": "registry/chartory/charts/types/054-horizon/data.ts",
      "type": "registry:lib",
      "target": "lib/chartory/charts/types/054-horizon/data.ts",
      "content": "// SPDX-License-Identifier: MIT · Copyright (c) 2026 BEY AGENCY LTD · Chartory, usechartory.com\n// 054 FX volatility · sample data (Figma chart/054, from the Figma definition, seeded values expanded).\nimport type { HorizonData } from \"../../plots/horizon\";\n\nexport const data: HorizonData = {\n  rows: [\n    {\n      label: \"EUR / USD\",\n      vals: [-0.407, -0.794, -0.463, -0.744, -0.714, -0.788, -0.698, -0.747, -0.819, -0.446, -0.254, -0.437, -0.38, -0.344, -0.686, -0.807, -1.16, -1.534, -1.548, -1.903, -2.197, -1.924, -2.204, -2.171, -2.285, -2.084, -2.4, -2.212, -1.945, -1.879, -1.864, -1.499, -1.638, -1.495, -1.473, -1.402, -1.028, -0.711, -1.089, -1.403, -1.612, -1.505, -1.924, -1.857, -1.688, -2.02, -1.973, -1.723, -1.561, -1.487, -1.308, -1.546, -1.49, -1.334, -1.32, -0.998, -1.304, -1.302, -0.864, -0.958]\n    },\n    {\n      label: \"GBP / USD\",\n      vals: [-0.445, -0.814, -0.982, -1.397, -1.511, -1.746, -1.797, -1.405, -1.112, -0.826, -1.22, -1.178, -1.52, -1.718, -1.424, -1.619, -1.295, -1.701, -1.749, -1.778, -1.591, -1.485, -1.538, -1.313, -1.699, -2.125, -2.266, -2.481, -2.409, -2.577, -2.358, -2.719, -3, -3, -2.855, -2.783, -2.462, -2.721, -2.518, -2.217, -2.333, -1.965, -2.283, -2.327, -1.949, -2.37, -2.273, -2.268, -2.415, -2.123, -2.268, -2.541, -2.148, -2.204, -2.032, -2.097, -2.251, -2.155, -1.94, -1.924]\n    },\n    {\n      label: \"USD / JPY\",\n      vals: [0.031, -0.025, -0.21, 0.164, 0.667, 0.746, 0.922, 1.526, 1.657, 1.149, 0.9, 1.116, 0.922, 0.654, 0.926, 0.703, 0.92, 0.771, 0.136, -0.194, 0.001, 0.329, 0.909, 0.919, 1.315, 1.285, 1.072, 1.102, 0.652, 0.325, 0.831, 0.339, 0.653, 0.997, 0.427, 0.32, 0.004, 0.358, 0.901, 1.34, 1.687, 1.412, 1.66, 1.058, 1.275, 2.566, 2.7779999999999996, 3.2279999999999998, 3.79, 4.156, 3.524, 3.138, 1.84, 1.979, 2.285, 1.62, 2.146, 2.418, 2.63, 2.241]\n    },\n    {\n      label: \"USD / CHF\",\n      vals: [-0.006, -0.012, 0.077, 0.482, 0.385, 0.054, 0.05, -0.087, -0.353, -0.648, -1.014, -1.359, -1.497, -1.136, -0.823, -0.553, -0.221, -0.615, -0.97, -1.303, -1.205, -1.588, -1.832, -1.992, -1.943, -2.35, -1.954, -1.755, -2.095, -1.693, -2.103, -1.803, -1.743, -1.429, -1.349, -1.666, -2.035, -2.269, -2.426, -2.187, -2.553, -2.32, -2.333, -2.713, -2.309, -2.261, -2.171, -1.727, -2.155, -1.798, -1.446, -1.115, -1.231, -1.296, -1.26, -1.211, -1.011, -1.449, -1.204, -1.178]\n    }\n  ],\n  band: 1,\n  xl: { 0: \"AUG 11\", 30: \"SEP 10\", 59: \"OCT 9\" }\n};\n"
    },
    {
      "path": "registry/chartory/charts/types/054-horizon/layout.ts",
      "type": "registry:lib",
      "target": "lib/chartory/charts/types/054-horizon/layout.ts",
      "content": "// SPDX-License-Identifier: MIT · Copyright (c) 2026 BEY AGENCY LTD · Chartory, usechartory.com\n// 054 Horizon (Figma chart/054, \"FX volatility\"): C.horizon, four currency pairs over 60 days, 3 bands of 1 each.\nimport type { ChartDef, TooltipSpec } from \"../../core/shell\";\nimport { horizon } from \"../../plots/horizon\";\nimport { data } from \"./data\";\n\nconst f = (v: number) => (v > 0 ? \"+\" : \"\") + v.toFixed(2);\n\nconst r3 = (v: number) => Math.round(v * 1000) / 1000;\n\n// tooltip: one currency pair's row (group = row): its high, low and last value against the average\nconst tip = (o: typeof data, g: number): TooltipSpec | null => {\n  const r = o.rows[g];\n  if (!r || !r.vals.length) return null;\n  const hi = Math.max(...r.vals), lo = Math.min(...r.vals), last = r.vals[r.vals.length - 1];\n  const tok = (v: number) => (v > 0 ? \"data/primary\" : \"data/cat-2\");\n  const sg = (v: number) => (v > 0 ? \"+\" : v < 0 ? \"−\" : \"\") + Math.abs(v).toFixed(2);\n  return { kind: \"range\", caps: r.label.toUpperCase(), rows: [{ label: \"High\", value: sg(hi), swatch: tok(hi) }, { label: \"Low\", value: sg(lo), swatch: tok(lo) }, { label: \"Last\", value: sg(last), swatch: tok(last) }] };\n};\n\nexport const def: ChartDef = {\n  no: 54,\n  slug: \"horizon\",\n  legend: [[\"data/primary\", \"Above average\"], [\"data/cat-2\", \"Below average\"]],\n  plot: (K, p, w, d) => horizon(K, p, w, (d as typeof data | undefined) ?? data),\n  tip: (d, g) => tip(d as typeof data, g),\n  // the next 60 days: every value moves up to ±12 % (sign kept, inside the three bands)\n  update: (d, step) => {\n    const o = d as typeof data, top = 3 * o.band;\n    return { ...o, rows: o.rows.map((r, k) => ({ ...r, vals: r.vals.map((v, i) => Math.max(-top, Math.min(top, r3(v * (1 + 0.12 * Math.sin(i * 0.21 + k * 1.7 + step * 2.3)))))) })) };\n  },\n  describe: {\n    title: \"FX volatility\",\n    summary: `Daily volatility against its average for ${data.rows.length} currency pairs from Aug 11 to Oct 9: ${data.rows.map((r) => `${r.label} ends at ${f(r.vals[r.vals.length - 1])}`).join(\", \")}; USD / JPY peaks at ${f(Math.max(...data.rows[2].vals))}.`,\n    table: { head: [\"Day\", ...data.rows.map((r) => r.label)], rows: data.rows[0].vals.map((_, i) => [i + 1, ...data.rows.map((r) => f(r.vals[i]))]) },\n  },\n};\n"
    }
  ],
  "categories": [
    "charts",
    "change-over-time"
  ],
  "meta": {
    "access": "free",
    "no": 54,
    "family": "Change over time"
  }
}
