{
  "name": "phone-number-input-basic",
  "type": "registry:component",
  "registryDependencies": [
    "button",
    "input",
    "popover",
    "scroll-area",
    "command"
  ],
  "dependencies": [
    "lucide-react",
    "react-phone-number-input"
  ],
  "files": [
    {
      "type": "registry:component",
      "content": "\"use client\";\n\nimport { Button } 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\";\nimport { ScrollArea } from \"@/components/ui/scroll-area\";\nimport { cn } from \"@/lib/utils\";\nimport { CheckIcon, ChevronsUpDown } from \"lucide-react\";\nimport * as React from \"react\";\nimport RPNInput, {\n  Props,\n  Value,\n  Country,\n  FlagProps,\n  getCountryCallingCode,\n} from \"react-phone-number-input\";\nimport flags from \"react-phone-number-input/flags\";\n\ntype PhoneInputProps = Omit<\n  React.ComponentProps<\"input\">,\n  \"onChange\" | \"value\" | \"ref\"\n> &\n  Omit<Props<typeof RPNInput>, \"onChange\"> & {\n    onChange?: (value: Value) => void;\n  };\n\nconst PhoneInput: React.ForwardRefExoticComponent<PhoneInputProps> =\n  React.forwardRef<React.ComponentRef<typeof RPNInput>, PhoneInputProps>(\n    ({ className, onChange, value, ...props }, ref) => {\n      return (\n        <RPNInput\n          ref={ref}\n          className={cn(\"flex\", className)}\n          flagComponent={FlagComponent}\n          countrySelectComponent={CountrySelect}\n          inputComponent={InputComponent}\n          smartCaret={false}\n          value={value || undefined}\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) => onChange?.(value || (\"\" as Value))}\n          {...props}\n        />\n      );\n    }\n  );\nPhoneInput.displayName = \"PhoneInput\";\n\nconst InputComponent = React.forwardRef<\n  HTMLInputElement,\n  React.ComponentProps<\"input\">\n>(({ className, ...props }, ref) => (\n  <Input\n    className={cn(\"rounded-s-none rounded-e-lg\", className)}\n    {...props}\n    ref={ref}\n  />\n));\nInputComponent.displayName = \"InputComponent\";\n\ntype CountryEntry = { label: string; value: Country | undefined };\n\ntype CountrySelectProps = {\n  disabled?: boolean;\n  value: Country;\n  options: CountryEntry[];\n  onChange: (country: Country) => void;\n};\n\nconst CountrySelect = ({\n  disabled,\n  onChange,\n  options: countryList,\n  value: selectedCountry,\n}: CountrySelectProps) => {\n  const scrollAreaRef = React.useRef<HTMLDivElement>(null);\n  const [searchValue, setSearchValue] = React.useState(\"\");\n  const [isOpen, setIsOpen] = React.useState(false);\n\n  return (\n    <Popover open={isOpen} onOpenChange={setIsOpen} modal>\n      <PopoverTrigger asChild>\n        <Button\n          type=\"button\"\n          variant=\"outline\"\n          className=\"flex gap-1 rounded-s-lg rounded-e-none border-r-0 px-3 focus:z-10\"\n          disabled={disabled}\n        >\n          <FlagComponent\n            country={selectedCountry}\n            countryName={selectedCountry}\n          />\n          <ChevronsUpDown\n            className={cn(\n              \"-mr-2 size-4 opacity-50\",\n              disabled ? \"hidden\" : \"opacity-100\"\n            )}\n          />\n        </Button>\n      </PopoverTrigger>\n      <PopoverContent className=\"w-[300px] p-0\">\n        <Command>\n          <CommandInput\n            value={searchValue}\n            onValueChange={(value) => {\n              setSearchValue(value);\n              setTimeout(() => {\n                if (scrollAreaRef.current) {\n                  const viewportElement = scrollAreaRef.current.querySelector(\n                    \"[data-radix-scroll-area-viewport]\"\n                  );\n                  if (viewportElement) {\n                    viewportElement.scrollTop = 0;\n                  }\n                }\n              }, 0);\n            }}\n            placeholder=\"Search country...\"\n          />\n          <CommandList>\n            <ScrollArea ref={scrollAreaRef} className=\"h-72\">\n              <CommandEmpty>No country found.</CommandEmpty>\n              <CommandGroup>\n                {countryList.map(({ label, value }) =>\n                  value ? (\n                    <CountrySelectOption\n                      key={value}\n                      country={value}\n                      countryName={label}\n                      selectedCountry={selectedCountry}\n                      onChange={onChange}\n                      onSelectComplete={() => setIsOpen(false)}\n                    />\n                  ) : null\n                )}\n              </CommandGroup>\n            </ScrollArea>\n          </CommandList>\n        </Command>\n      </PopoverContent>\n    </Popover>\n  );\n};\n\ninterface CountrySelectOptionProps extends FlagProps {\n  selectedCountry: Country;\n  onChange: (country: Country) => void;\n  onSelectComplete: () => void;\n}\n\nconst CountrySelectOption = ({\n  country,\n  countryName,\n  onChange,\n  onSelectComplete,\n  selectedCountry,\n}: CountrySelectOptionProps) => {\n  const handleSelect = () => {\n    onChange(country);\n    onSelectComplete();\n  };\n\n  return (\n    <CommandItem className=\"gap-2\" onSelect={handleSelect}>\n      <FlagComponent country={country} countryName={countryName} />\n      <span className=\"flex-1 text-sm\">{countryName}</span>\n      <span className=\"text-foreground/50 text-sm\">{`+${getCountryCallingCode(\n        country\n      )}`}</span>\n      <CheckIcon\n        className={`ml-auto size-4 ${\n          country === selectedCountry ? \"opacity-100\" : \"opacity-0\"\n        }`}\n      />\n    </CommandItem>\n  );\n};\n\nconst FlagComponent = ({ country, countryName }: 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:not([class*='size-'])]:size-full\">\n      {Flag && <Flag title={countryName} />}\n    </span>\n  );\n};\n\nexport default PhoneInput;\n",
      "path": "/components/commerce-ui/components/phone-number-input/basic/phone-number-input-basic.tsx",
      "target": "components/commerce-ui/phone-number-input-basic.tsx"
    }
  ]
}