{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "search-field",
  "title": "Search Field",
  "description": "Search input with a leading icon and a clear button.",
  "dependencies": [
    "@vllnt/ui@^0.2.1"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/default/search-field/search-field.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { Search, X } from \"lucide-react\";\n\nimport { cn } from \"@vllnt/ui\";\n\nfunction useSearchValue(\n  value: string | undefined,\n  defaultValue: string,\n  onValueChange?: (value: string) => void,\n) {\n  const [internalValue, setInternalValue] = React.useState(defaultValue);\n  const currentValue = value ?? internalValue;\n\n  const setValue = (nextValue: string) => {\n    if (value === undefined) {\n      setInternalValue(nextValue);\n    }\n\n    onValueChange?.(nextValue);\n  };\n\n  return [currentValue, setValue] as const;\n}\n\n/** Search input with a leading icon and a clear button. */\nexport type SearchFieldProps = Omit<\n  React.ComponentPropsWithoutRef<\"input\">,\n  \"defaultValue\" | \"onChange\" | \"type\" | \"value\"\n> & {\n  defaultValue?: string;\n  onValueChange?: (value: string) => void;\n  value?: string;\n};\n\nconst SearchField = ({\n  className,\n  defaultValue = \"\",\n  onValueChange,\n  placeholder = \"Search...\",\n  ref,\n  value,\n  ...props\n}: SearchFieldProps & { ref?: React.Ref<HTMLInputElement> }) => {\n  const [currentValue, setValue] = useSearchValue(\n    value,\n    defaultValue,\n    onValueChange,\n  );\n\n  return (\n    <div className=\"relative w-full\">\n      <Search className=\"pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground\" />\n      <input\n        {...props}\n        className={cn(\n          \"flex h-10 w-full rounded-md border border-input bg-background px-9 py-2 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm [&::-webkit-search-cancel-button]:appearance-none\",\n          className,\n        )}\n        onChange={(event) => {\n          setValue(event.target.value);\n        }}\n        placeholder={placeholder}\n        ref={ref}\n        type=\"search\"\n        value={currentValue}\n      />\n      {currentValue ? (\n        <button\n          aria-label=\"Clear search\"\n          className=\"absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n          onClick={() => {\n            setValue(\"\");\n          }}\n          type=\"button\"\n        >\n          <X className=\"size-4\" />\n        </button>\n      ) : null}\n    </div>\n  );\n};\nSearchField.displayName = \"SearchField\";\n\nexport { SearchField };\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component",
  "version": "0.2.1",
  "stability": "stable"
}
