{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "facet-filter",
  "type": "registry:ui",
  "title": "Facet filter",
  "description": "A titled checkbox facet group for sidebar search filters in React. Each option can show a result count, and the selected values come back as an array.",
  "dependencies": [],
  "registryDependencies": [
    "https://ui.minidev.pro/r/checkbox.json",
    "https://ui.minidev.pro/r/label.json",
    "utils"
  ],
  "files": [
    {
      "path": "registry/ui/facet-filter.tsx",
      "type": "registry:ui",
      "target": "components/ui/facet-filter.tsx",
      "content": "\"use client\"\nimport * as React from \"react\"\nimport { cn } from \"@/lib/utils\"\nimport { Checkbox } from \"@/components/ui/checkbox\"\nimport { Label } from \"@/components/ui/label\"\n\n/** A titled group of checkbox facets with result counts, for a filter sidebar. */\ntype Facet = { value: string; label: string; count?: number }\n\nconst SAMPLE_OPTIONS: Facet[] = [\n  { value: \"paid\", label: \"Paid\", count: 128 },\n  { value: \"open\", label: \"Open\", count: 42 },\n  { value: \"overdue\", label: \"Overdue\", count: 9 },\n  { value: \"draft\", label: \"Draft\", count: 14 },\n  { value: \"void\", label: \"Void\", count: 3 },\n]\nconst SAMPLE_SELECTED = [\"open\", \"overdue\"]\n\ntype FacetFilterProps = {\n  /** Group heading. */\n  title?: string\n  /** Facets to list. Defaults to invoice statuses with counts. */\n  options?: Facet[]\n  /** Controlled selection. */\n  value?: string[]\n  /** Selection when uncontrolled. With the sample options, \"Open\" and \"Overdue\" start checked. */\n  defaultValue?: string[]\n  onChange?: (value: string[]) => void\n  className?: string\n}\n\nfunction FacetFilter({\n  title = \"Status\",\n  options = SAMPLE_OPTIONS,\n  value: valueProp,\n  defaultValue,\n  onChange,\n  className,\n}: FacetFilterProps) {\n  const [inner, setInner] = React.useState<string[]>(() => defaultValue ?? (options === SAMPLE_OPTIONS ? SAMPLE_SELECTED : []))\n  const value = valueProp ?? inner\n  const toggle = (v: string) => {\n    const next = value.includes(v) ? value.filter((x) => x !== v) : [...value, v]\n    if (valueProp === undefined) setInner(next)\n    onChange?.(next)\n  }\n  return (\n    <div data-slot=\"facet-filter\" className={cn(\"min-w-48 space-y-2\", className)}>\n      <p className=\"text-xs font-medium tracking-[0.01em] text-fg-muted uppercase\">{title}</p>\n      <ul className=\"space-y-1.5\">\n        {options.map((o) => {\n          const id = `facet-${title}-${o.value}`\n          return (\n            <li key={o.value} className=\"flex items-center gap-2\">\n              <Checkbox\n                id={id}\n                checked={value.includes(o.value)}\n                onCheckedChange={() => toggle(o.value)}\n              />\n              <Label htmlFor={id} className=\"flex flex-1 cursor-pointer justify-between font-normal\">\n                <span>{o.label}</span>\n                {o.count != null ? <span className=\"text-fg-muted tabular-nums\">{o.count}</span> : null}\n              </Label>\n            </li>\n          )\n        })}\n      </ul>\n    </div>\n  )\n}\nexport { FacetFilter }\nexport type { FacetFilterProps, Facet }\n"
    }
  ]
}
