'use client' import React, { forwardRef, useEffect, useImperativeHandle, useRef, InputHTMLAttributes, } from 'react' import { createIntlTelInput, IntlTelInputInstance } from '../../utils/phoneUtils' export type TelephoneInputHandle = { getNumber: () => string isValid: () => boolean } interface TelephoneInputProps extends Omit, 'type'> { /** e.g. "de" */ initialCountry?: string } /** * Reusable telephone input with intl-tel-input. * Always takes full available width. */ const TelephoneInput = forwardRef( ({ initialCountry = (process.env.NEXT_PUBLIC_GEO_FALLBACK_COUNTRY || 'DE').toLowerCase(), ...rest }, ref) => { const inputRef = useRef(null) const itiRef = useRef(null) useEffect(() => { let disposed = false let instance: IntlTelInputInstance | null = null const setup = async () => { try { console.log('[TelephoneInput] setup() start for', { id: rest.id, name: rest.name, initialCountry, }) if (!inputRef.current) { console.warn('[TelephoneInput] setup() aborted: inputRef is null', { id: rest.id, name: rest.name, }) return } instance = await createIntlTelInput(inputRef.current, { initialCountry, nationalMode: true, strictMode: true, autoPlaceholder: 'aggressive', validationNumberTypes: ['MOBILE'], }) if (disposed) { console.log('[TelephoneInput] setup() finished but component is disposed, destroying instance', { id: rest.id, name: rest.name, }) instance.destroy() return } itiRef.current = instance console.log('[TelephoneInput] intl-tel-input instance attached to input', { id: rest.id, name: rest.name, }) } catch (e) { console.error('[TelephoneInput] Failed to init intl-tel-input:', e) } } setup() return () => { disposed = true if (instance) { console.log('[TelephoneInput] Destroying intl-tel-input instance for', { id: rest.id, name: rest.name, }) instance.destroy() if (itiRef.current === instance) itiRef.current = null } } }, [initialCountry, rest.id, rest.name]) useImperativeHandle(ref, () => ({ getNumber: () => { const raw = inputRef.current?.value || '' if (itiRef.current) { const intl = itiRef.current.getNumber() console.log('[TelephoneInput] getNumber()', { id: rest.id, name: rest.name, raw, intl, }) return intl } console.warn( '[TelephoneInput] getNumber() called before intl-tel-input ready, returning raw value', { id: rest.id, name: rest.name, raw } ) return raw }, isValid: () => { if (!itiRef.current) { const raw = inputRef.current?.value || '' console.warn('[TelephoneInput] isValid() called before intl-tel-input ready', { id: rest.id, name: rest.name, raw, }) return false } const instance = itiRef.current const intl = instance.getNumber() const valid = instance.isValidNumber() const errorCode = typeof instance.getValidationError === 'function' ? instance.getValidationError() : undefined const country = typeof instance.getSelectedCountryData === 'function' ? instance.getSelectedCountryData() : undefined console.log('[TelephoneInput] isValid() check', { id: rest.id, name: rest.name, intl, valid, errorCode, country, }) return valid }, })) return (
) } ) TelephoneInput.displayName = 'TelephoneInput' export default TelephoneInput