{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "range-slider-with-histogram",
  "type": "registry:ui",
  "title": "Range Slider with Histogram",
  "description": "A Range Slider with Histogram component for displaying a range slider with histogram.",
  "files": [
    {
      "path": "src/registry/ui/range-slider-with-histogram.tsx",
      "type": "registry:ui",
      "content": "\"use client\";\n\nimport { useState } from \"react\";\nimport { Slider } from \"@/components/ui/slider\";\nimport { cn } from \"@/lib/utils\";\n\nexport type RangeSliderWithHistogramProps = Omit<\n  React.ComponentProps<\"div\">,\n  \"defaultValue\" | \"onChange\"\n> & {\n  /** Bar heights, spread evenly from `min` to `max`. */\n  data: number[];\n  min?: number;\n  max?: number;\n  step?: number;\n  value?: [number, number];\n  defaultValue?: [number, number];\n  onValueChange?: (value: [number, number]) => void;\n  /** Called once when the user releases a thumb. */\n  onValueCommit?: (value: [number, number]) => void;\n  formatValue?: (value: number) => string;\n  disabled?: boolean;\n};\n\n// An explicit locale keeps server and client output identical.\nconst defaultFormat = (value: number) => value.toLocaleString(\"en-US\");\n\nexport function RangeSliderWithHistogram({\n  data,\n  min = 0,\n  max = 100,\n  step = 1,\n  value,\n  defaultValue,\n  onValueChange,\n  onValueCommit,\n  formatValue = defaultFormat,\n  disabled,\n  className,\n  ...props\n}: RangeSliderWithHistogramProps) {\n  const [uncontrolledValue, setUncontrolledValue] = useState<[number, number]>(\n    defaultValue ?? [min, max]\n  );\n  const [low, high] = value ?? uncontrolledValue;\n  const peak = Math.max(...data, 1);\n  const barSpan = (max - min) / Math.max(data.length, 1);\n\n  const handleChange = (next: number[]) => {\n    const range: [number, number] = [next[0], next[1]];\n    if (value === undefined) setUncontrolledValue(range);\n    onValueChange?.(range);\n  };\n\n  return (\n    <div data-slot=\"range-slider-with-histogram\" className={cn(\"w-full\", className)} {...props}>\n      <div className=\"flex justify-between text-sm font-medium tabular-nums\">\n        <output aria-live=\"polite\">{formatValue(low)}</output>\n        <output aria-live=\"polite\">{formatValue(high)}</output>\n      </div>\n\n      <div aria-hidden className=\"mt-3 flex h-24 items-end gap-px\">\n        {data.map((count, i) => {\n          const center = min + barSpan * (i + 0.5);\n          const inRange = center >= low && center <= high;\n          return (\n            <div\n              key={i}\n              className={cn(\n                \"flex-1 rounded-t-[2px] transition-colors duration-200\",\n                inRange ? \"bg-primary\" : \"bg-muted\"\n              )}\n              style={{ height: `${Math.max((count / peak) * 100, 2)}%` }}\n            />\n          );\n        })}\n      </div>\n\n      <Slider\n        min={min}\n        max={max}\n        step={step}\n        value={[low, high]}\n        onValueChange={handleChange}\n        onValueCommit={(next) => onValueCommit?.([next[0], next[1]])}\n        minStepsBetweenThumbs={1}\n        disabled={disabled}\n        className=\"-mt-px\"\n      />\n    </div>\n  );\n}\n"
    }
  ],
  "registryDependencies": [
    "slider"
  ]
}
