{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "view-switcher",
  "type": "registry:component",
  "title": "View Switcher",
  "description": "URL param-based toggle between named views with pill/tab styling.",
  "dependencies": [
    "@vllnt/ui@^0.2.1"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/default/view-switcher/view-switcher.tsx",
      "content": "\"use client\";\n\nimport { memo, Suspense } from \"react\";\n\nimport { usePathname, useRouter, useSearchParams } from \"next/navigation\";\n\nimport { cn } from \"@vllnt/ui\";\n\ntype ViewOption = {\n  key: string;\n  label: string;\n};\n\ntype ViewSwitcherProps = {\n  className?: string;\n  defaultKey?: string;\n  options: ViewOption[];\n  paramName?: string;\n};\n\nfunction ViewSwitcherInner({\n  className,\n  defaultKey,\n  options,\n  paramName: parameterName = \"view\",\n}: ViewSwitcherProps) {\n  const router = useRouter();\n  const pathname = usePathname();\n  const searchParameters = useSearchParams();\n\n  const resolvedDefault = defaultKey ?? options[0]?.key ?? \"\";\n  const currentKey = searchParameters.get(parameterName) ?? resolvedDefault;\n\n  function handleSelect(key: string): void {\n    const parameters = new URLSearchParams(searchParameters.toString());\n    if (key === resolvedDefault) {\n      parameters.delete(parameterName);\n    } else {\n      parameters.set(parameterName, key);\n    }\n    const query = parameters.toString();\n    router.push(query ? `${pathname}?${query}` : pathname, { scroll: false });\n  }\n\n  return (\n    <div\n      className={cn(\n        \"inline-flex items-center rounded-lg border bg-muted p-1\",\n        className,\n      )}\n      role=\"tablist\"\n    >\n      {options.map((option) => (\n        <button\n          aria-selected={currentKey === option.key}\n          className={cn(\n            \"rounded-md px-3 py-1.5 text-sm font-medium transition-colors\",\n            currentKey === option.key\n              ? \"bg-background text-foreground shadow-sm\"\n              : \"text-muted-foreground hover:text-foreground\",\n          )}\n          key={option.key}\n          onClick={() => {\n            handleSelect(option.key);\n          }}\n          role=\"tab\"\n          type=\"button\"\n        >\n          {option.label}\n        </button>\n      ))}\n    </div>\n  );\n}\n\nfunction ViewSwitcherFallback({\n  className,\n  defaultKey,\n  options,\n}: ViewSwitcherProps) {\n  const resolvedDefault = defaultKey ?? options[0]?.key ?? \"\";\n\n  return (\n    <div\n      className={cn(\n        \"inline-flex items-center rounded-lg border bg-muted p-1\",\n        className,\n      )}\n      role=\"tablist\"\n    >\n      {options.map((option) => (\n        <button\n          aria-selected={resolvedDefault === option.key}\n          className={cn(\n            \"rounded-md px-3 py-1.5 text-sm font-medium transition-colors\",\n            resolvedDefault === option.key\n              ? \"bg-background text-foreground shadow-sm\"\n              : \"text-muted-foreground hover:text-foreground\",\n          )}\n          key={option.key}\n          role=\"tab\"\n          type=\"button\"\n        >\n          {option.label}\n        </button>\n      ))}\n    </div>\n  );\n}\n\nconst ViewSwitcher = memo(function ViewSwitcher(props: ViewSwitcherProps) {\n  return (\n    <Suspense fallback={<ViewSwitcherFallback {...props} />}>\n      <ViewSwitcherInner {...props} />\n    </Suspense>\n  );\n});\n\nViewSwitcher.displayName = \"ViewSwitcher\";\n\nexport { ViewSwitcher };\nexport type { ViewOption, ViewSwitcherProps };\n",
      "type": "registry:component"
    }
  ],
  "version": "0.2.1",
  "stability": "stable"
}
