{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "phone-input",
  "title": "Phone Input",
  "description": "International phone number input with a searchable country picker and flags.",
  "dependencies": [
    "react-phone-number-input",
    "lucide-react"
  ],
  "registryDependencies": [
    "button",
    "command",
    "input",
    "popover",
    "scroll-area"
  ],
  "files": [
    {
      "path": "components/ui/phone-input.tsx",
      "content": "import { CheckIcon, ChevronsUpDown } from 'lucide-react'\n\nimport * as React from 'react'\n\nimport * as RPNInput from 'react-phone-number-input'\n\nimport flags from 'react-phone-number-input/flags'\n\nimport { buttonVariants } from '@/components/ui/button'\nimport {\n  Command,\n  CommandEmpty,\n  CommandGroup,\n  CommandInput,\n  CommandItem,\n  CommandList,\n} from '@/components/ui/command'\nimport { Input } from '@/components/ui/input'\nimport {\n  Popover,\n  PopoverContent,\n  PopoverTrigger,\n} from '@/components/ui/popover'\n\nimport { cn } from '@/lib/utils'\nimport { ScrollArea } from '@/components/ui/scroll-area'\n\ntype PhoneInputProps = Omit<\n  React.InputHTMLAttributes<HTMLInputElement>,\n  'onChange' | 'value'\n> &\n  Omit<RPNInput.Props<typeof RPNInput.default>, 'onChange'> & {\n    onChange?: (value: RPNInput.Value) => void\n  }\n\nconst PhoneInput: React.ForwardRefExoticComponent<PhoneInputProps> =\n  React.forwardRef<React.ElementRef<typeof RPNInput.default>, PhoneInputProps>(\n    ({ className, onChange, ...props }, ref) => {\n      return (\n        <RPNInput.default\n          ref={ref}\n          className={cn('flex', className)}\n          flagComponent={FlagComponent}\n          countrySelectComponent={CountrySelect}\n          inputComponent={InputComponent}\n          smartCaret={false}\n          /**\n           * Handles the onChange event.\n           *\n           * react-phone-number-input might trigger the onChange event as undefined\n           * when a valid phone number is not entered. To prevent this,\n           * the value is coerced to an empty string.\n           *\n           * @param {E164Number | undefined} value - The entered value\n           */\n          onChange={(value) => {\n            if (value) onChange?.(value)\n          }}\n          {...props}\n        />\n      )\n    },\n  )\nPhoneInput.displayName = 'PhoneInput'\n\nconst InputComponent = React.forwardRef<HTMLInputElement, React.ComponentProps<'input'>>(\n  ({ className, ...props }, ref) => (\n    <Input\n      className={cn('rounded-e-lg rounded-s-none', className)}\n      {...props}\n      ref={ref}\n    />\n  ),\n)\nInputComponent.displayName = 'InputComponent'\n\ntype CountrySelectOption = { label: string; value: RPNInput.Country }\n\ntype CountrySelectProps = {\n  disabled?: boolean\n  value: RPNInput.Country\n  onChange: (value: RPNInput.Country) => void\n  options: CountrySelectOption[]\n}\n\nconst CountrySelect = ({\n  disabled,\n  value,\n  onChange,\n  options,\n}: CountrySelectProps) => {\n  const handleSelect = React.useCallback(\n    (country: RPNInput.Country) => {\n      onChange(country)\n    },\n    [onChange],\n  )\n\n  return (\n    <Popover>\n      <PopoverTrigger\n        type=\"button\"\n        className={cn(\n          buttonVariants({ variant: 'outline' }),\n          'flex gap-1 rounded-e-none rounded-s-lg border-r-0 px-3 focus:z-10',\n        )}\n        disabled={disabled}\n      >\n        <FlagComponent country={value} countryName={value} />\n        <ChevronsUpDown\n          className={cn(\n            '-mr-2 h-4 w-4 opacity-50',\n            disabled ? 'hidden' : 'opacity-100',\n          )}\n        />\n      </PopoverTrigger>\n      <PopoverContent className=\"w-[300px] p-0\">\n        <Command>\n          <CommandInput placeholder=\"Search country...\" />\n          <CommandList>\n            <ScrollArea className=\"h-72\">\n              <CommandEmpty>No country found.</CommandEmpty>\n              <CommandGroup>\n                {options\n                  .filter((x) => x.value)\n                  .map((option) => (\n                    <CommandItem\n                      className=\"gap-2\"\n                      key={option.value}\n                      onSelect={() => handleSelect(option.value)}\n                    >\n                      <FlagComponent\n                        country={option.value}\n                        countryName={option.label}\n                      />\n                      <span className=\"flex-1 text-sm\">{option.label}</span>\n                      {option.value && (\n                        <span className=\"text-foreground/50 text-sm\">\n                          {`+${RPNInput.getCountryCallingCode(option.value)}`}\n                        </span>\n                      )}\n                      <CheckIcon\n                        className={cn(\n                          'ml-auto h-4 w-4',\n                          option.value === value ? 'opacity-100' : 'opacity-0',\n                        )}\n                      />\n                    </CommandItem>\n                  ))}\n              </CommandGroup>\n            </ScrollArea>\n          </CommandList>\n        </Command>\n      </PopoverContent>\n    </Popover>\n  )\n}\n\nconst FlagComponent = ({ country, countryName }: RPNInput.FlagProps) => {\n  const Flag = flags[country]\n\n  return (\n    <span className=\"bg-foreground/20 flex h-4 w-6 overflow-hidden rounded-sm [&_svg]:size-full\">\n      {Flag && <Flag title={countryName} />}\n    </span>\n  )\n}\nFlagComponent.displayName = 'FlagComponent'\n\nexport { PhoneInput }\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "input"
  ],
  "type": "registry:ui"
}