{"name":"rhf-phone-field","title":"RHF Phone Field","description":"Phone input with country code and React Hook Form integration.","type":"registry:ui","docs":"/components/rhf-phone-field","categories":["forms"],"registryDependencies":["https://pb-ui-five.vercel.app/registry/rhf-base-controller","https://pb-ui-five.vercel.app/registry/input","https://pb-ui-five.vercel.app/registry/select"],"dependencies":["react-hook-form"],"files":[{"path":"components/ui/rhf-inputs/phone-field.tsx","target":"components/ui/rhf-inputs/phone-field.tsx","type":"registry:ui","content":"\"use client\";\n\nimport { cn } from \"@/lib/utils\";\nimport * as React from \"react\";\nimport { FieldValues } from \"react-hook-form\";\nimport { Input } from \"../input\";\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from \"../select\";\nimport { BaseController, BaseControllerProps } from \"./base-controller\";\n\n// Common country codes with their dial codes\nconst DEFAULT_COUNTRIES = [\n  { code: \"US\", dialCode: \"+1\", name: \"United States\" },\n  { code: \"GB\", dialCode: \"+44\", name: \"United Kingdom\" },\n  { code: \"DE\", dialCode: \"+49\", name: \"Germany\" },\n  { code: \"FR\", dialCode: \"+33\", name: \"France\" },\n  { code: \"IT\", dialCode: \"+39\", name: \"Italy\" },\n  { code: \"ES\", dialCode: \"+34\", name: \"Spain\" },\n  { code: \"NL\", dialCode: \"+31\", name: \"Netherlands\" },\n  { code: \"BE\", dialCode: \"+32\", name: \"Belgium\" },\n  { code: \"CH\", dialCode: \"+41\", name: \"Switzerland\" },\n  { code: \"AT\", dialCode: \"+43\", name: \"Austria\" },\n  { code: \"AU\", dialCode: \"+61\", name: \"Australia\" },\n  { code: \"CA\", dialCode: \"+1\", name: \"Canada\" },\n  { code: \"JP\", dialCode: \"+81\", name: \"Japan\" },\n  { code: \"CN\", dialCode: \"+86\", name: \"China\" },\n  { code: \"IN\", dialCode: \"+91\", name: \"India\" },\n  { code: \"BR\", dialCode: \"+55\", name: \"Brazil\" },\n  { code: \"MX\", dialCode: \"+52\", name: \"Mexico\" },\n  { code: \"KR\", dialCode: \"+82\", name: \"South Korea\" },\n  { code: \"RU\", dialCode: \"+7\", name: \"Russia\" },\n  { code: \"ZA\", dialCode: \"+27\", name: \"South Africa\" },\n];\n\nexport type Country = {\n  code: string;\n  dialCode: string;\n  name: string;\n};\n\ntype PhoneFieldProps<T extends FieldValues> = Omit<\n  BaseControllerProps<T>,\n  \"children\"\n> & {\n  countries?: Country[];\n  defaultCountry?: string;\n  placeholder?: string;\n  disabled?: boolean;\n  className?: string;\n};\n\nexport function PhoneField<T extends FieldValues>({\n  control,\n  name,\n  label,\n  description,\n  required,\n  disableFieldError = false,\n  countries = DEFAULT_COUNTRIES,\n  defaultCountry = \"US\",\n  placeholder = \"Phone number\",\n  disabled = false,\n  className,\n}: PhoneFieldProps<T>) {\n  const [selectedCountry, setSelectedCountry] = React.useState(\n    () => countries.find((c) => c.code === defaultCountry) ?? countries[0],\n  );\n\n  return (\n    <BaseController\n      control={control}\n      name={name}\n      label={label}\n      required={required}\n      description={description}\n      disableFieldError={disableFieldError}\n    >\n      {({ field, fieldState, ariaDescribedBy }) => {\n        // Parse the current value to extract country and number\n        const parsePhoneValue = (value: string | undefined) => {\n          if (!value) return { dialCode: selectedCountry.dialCode, number: \"\" };\n\n          // Find matching country code\n          for (const country of countries) {\n            if (value.startsWith(country.dialCode)) {\n              return {\n                dialCode: country.dialCode,\n                number: value.slice(country.dialCode.length).trim(),\n              };\n            }\n          }\n          return { dialCode: selectedCountry.dialCode, number: value };\n        };\n\n        const { number } = parsePhoneValue(field.value);\n\n        const handleCountryChange = (countryCode: string | null) => {\n          if (!countryCode) return;\n          const country = countries.find((c) => c.code === countryCode);\n          if (country) {\n            setSelectedCountry(country);\n            // Update the full phone number with new dial code\n            if (number) {\n              field.onChange(`${country.dialCode}${number}`);\n            }\n          }\n        };\n\n        const handleNumberChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n          const raw = e.target.value.replace(/[^0-9]/g, \"\");\n          if (raw) {\n            field.onChange(`${selectedCountry.dialCode}${raw}`);\n          } else {\n            field.onChange(\"\");\n          }\n        };\n\n        return (\n          <div className={cn(\"flex gap-2\", className)}>\n            <Select\n              value={selectedCountry.code}\n              onValueChange={handleCountryChange}\n              disabled={disabled}\n            >\n              <SelectTrigger className=\"w-24 shrink-0\">\n                <SelectValue>\n                  <span className=\"text-sm\">{selectedCountry.dialCode}</span>\n                </SelectValue>\n              </SelectTrigger>\n              <SelectContent>\n                {countries.map((country) => (\n                  <SelectItem key={country.code} value={country.code}>\n                    <span className=\"flex items-center gap-2\">\n                      <span className=\"text-muted-foreground\">\n                        {country.dialCode}\n                      </span>\n                      <span>{country.name}</span>\n                    </span>\n                  </SelectItem>\n                ))}\n              </SelectContent>\n            </Select>\n            <Input\n              id={field.name}\n              type=\"tel\"\n              inputMode=\"tel\"\n              value={number}\n              onChange={handleNumberChange}\n              placeholder={placeholder}\n              disabled={disabled}\n              aria-invalid={!!fieldState.error}\n              aria-required={required}\n              aria-describedby={ariaDescribedBy}\n              className=\"flex-1\"\n            />\n          </div>\n        );\n      }}\n    </BaseController>\n  );\n}\n"}]}