{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "floating-range-bars",
  "type": "registry:component",
  "title": "Floating range bars",
  "description": "A window per item, from start to end. Sample data: delivery windows of eight routes, R1 to R8, between 06:00 and 18:00.",
  "registryDependencies": [
    "@chartory/core",
    "@chartory/plot-floating"
  ],
  "files": [
    {
      "path": "registry/chartory/components/floating-range-bars.tsx",
      "type": "registry:component",
      "target": "components/chartory/floating-range-bars.tsx",
      "content": "// SPDX-License-Identifier: MIT · Copyright (c) 2026 BEY AGENCY LTD · Chartory, usechartory.com\n// Floating range bars (Chartory chart 005): 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/floating-range-bars\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/005-floating-range-bars/data\"\nimport { def } from \"@/lib/chartory/charts/types/005-floating-range-bars/layout\"\n\nregisterChart(def, sample)\n\nexport type FloatingRangeBarsData = typeof sample\nexport type FloatingRangeBarsProps = Omit<ChartViewProps, \"def\" | \"data\" | \"states\"> & {\n  /** the data to draw (default: the sample) */\n  data?: FloatingRangeBarsData\n  /** further data states: the chart morphs to them (update) or ticks through them (live, with interval) */\n  states?: FloatingRangeBarsData[]\n}\n\nexport function FloatingRangeBars(props: FloatingRangeBarsProps) {\n  return <ChartView def={def} {...props} />\n}\n"
    },
    {
      "path": "registry/chartory/charts/types/005-floating-range-bars/data.ts",
      "type": "registry:lib",
      "target": "lib/chartory/charts/types/005-floating-range-bars/data.ts",
      "content": "// SPDX-License-Identifier: MIT · Copyright (c) 2026 BEY AGENCY LTD · Chartory, usechartory.com\n// 005 · sample data (Figma chart/005-floating-range-bars, logistics: delivery window per route as [low, high, median] hour of day; SLA 10:30).\nimport type { FloatingData } from \"../../plots/floating\";\n\nexport const data: FloatingData = {\n  cats: [\"R1\", \"R2\", \"R3\", \"R4\", \"R5\", \"R6\", \"R7\", \"R8\"],\n  vals: [[8, 11, 9.5], [9, 13, 11], [7.5, 10, 8.5], [10, 15, 12.5], [8, 12, 10], [11, 16, 13], [9, 12, 10.5], [12, 17, 14]],\n  sla: 10.5,\n  min: 6,\n  max: 18,\n  ticks: [\"18:00\", \"14:00\", \"10:00\", \"06:00\"],\n};\n"
    },
    {
      "path": "registry/chartory/charts/types/005-floating-range-bars/layout.ts",
      "type": "registry:lib",
      "target": "lib/chartory/charts/types/005-floating-range-bars/layout.ts",
      "content": "// SPDX-License-Identifier: MIT · Copyright (c) 2026 BEY AGENCY LTD · Chartory, usechartory.com\n// 005 Floating range bars (Figma chart/005-floating-range-bars): C.floating on delivery windows per route.\nimport type { ChartDef, TooltipSpec } from \"../../core/shell\";\nimport { floating } from \"../../plots/floating\";\nimport { data } from \"./data\";\n\n/** Deterministic wave in [-1, 1] per index and update step (no randomness: the same step gives the same period). */\nconst wave = (i: number, step: number, f = 1.7) => Math.sin(step * 2.3 + i * f + 0.5);\nconst clamp = (v: number, lo: number, hi: number) => Math.min(hi, Math.max(lo, v));\n\nconst hm = (v: number) => String(Math.floor(v)).padStart(2, \"0\") + \":\" + String(Math.round((v % 1) * 60)).padStart(2, \"0\");\nconst over = data.vals.filter(([lo]) => lo >= data.sla).length;\n\n/** Hover tooltip: one route's window (latest, median, earliest) in the bar's SLA colour. */\nconst tip = (d: unknown, g: number): TooltipSpec => {\n  const o = d as typeof data, [lo, hi, med] = o.vals[g], within = lo < o.sla, tok = within ? \"data/primary\" : \"status/warning\";\n  return {\n    kind: \"range\",\n    caps: `ROUTE ${o.cats[g]} · ${within ? \"WITHIN\" : \"OVER\"} SLA`,\n    rows: [\n      { label: \"Latest\", value: hm(hi), swatch: tok },\n      { label: \"Median\", value: hm(med), swatch: \"text/strong\" },\n      { label: \"Earliest\", value: hm(lo), swatch: tok },\n    ],\n  };\n};\n\nexport const def: ChartDef = {\n  no: 5,\n  slug: \"floating-range-bars\",\n  legend: [[\"data/primary\", \"Within SLA\"], [\"status/warning\", \"Over SLA\"]],\n  plot: (K, p, w, d) => floating(K, p, w, (d as typeof data | undefined) ?? data),\n  tip,\n  update: (d, step) => {\n    const o = d as typeof data;\n    // windows shift by up to ±45 min in quarter hours; a route stays on its side of the SLA, the median inside its window\n    const q = (i: number, k: number) => 0.25 * Math.round(3 * wave(i * 3 + k, step));\n    return {\n      ...o,\n      vals: o.vals.map(([lo, hi, med], i) => {\n        let l = lo + q(i, 0);\n        l = lo < o.sla ? clamp(l, o.min + 0.5, o.sla - 0.25) : Math.max(l, o.sla);\n        const h = clamp(Math.max(hi + q(i, 1), l + 1.5), l + 1.5, o.max - 0.25);\n        const m = clamp(med + q(i, 2), l + 0.5, h - 0.5);\n        return [l, h, m] as [number, number, number];\n      }),\n    };\n  },\n  describe: {\n    title: \"Delivery windows by route\",\n    summary: `Delivery window per route (earliest to latest arrival, with the median), 8 routes; ${over} routes start at or after the ${hm(data.sla)} SLA; R8 runs ${hm(data.vals[7][0])} to ${hm(data.vals[7][1])}.`,\n    table: { head: [\"Route\", \"Earliest\", \"Latest\", \"Median\", \"SLA\"], rows: data.cats.map((c, i) => [c, hm(data.vals[i][0]), hm(data.vals[i][1]), hm(data.vals[i][2]), data.vals[i][0] < data.sla ? \"Within\" : \"Over\"]) },\n  },\n};\n"
    }
  ],
  "categories": [
    "charts",
    "distribution"
  ],
  "meta": {
    "access": "free",
    "no": 5,
    "family": "Distribution"
  }
}
