@alikhalilll/a-tel-input 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +585 -72
- package/dist/_chunks/types.d.ts +661 -0
- package/dist/_chunks/types.js +52 -0
- package/dist/_chunks/types.js.map +1 -0
- package/dist/_chunks/usePhoneValidation.js +539 -0
- package/dist/_chunks/usePhoneValidation.js.map +1 -0
- package/dist/index.cjs +444 -683
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +122 -587
- package/dist/index.d.ts +122 -587
- package/dist/index.js +427 -646
- package/dist/index.js.map +1 -1
- package/dist/styles.css +3 -2
- package/dist/vee-validate/index.cjs +113 -0
- package/dist/vee-validate/index.cjs.map +1 -0
- package/dist/vee-validate/index.d.cts +86 -0
- package/dist/vee-validate/index.d.ts +86 -0
- package/dist/vee-validate/index.js +112 -0
- package/dist/vee-validate/index.js.map +1 -0
- package/dist/zod/index.cjs +211 -0
- package/dist/zod/index.cjs.map +1 -0
- package/dist/zod/index.d.cts +65 -0
- package/dist/zod/index.d.ts +65 -0
- package/dist/zod/index.js +208 -0
- package/dist/zod/index.js.map +1 -0
- package/package.json +33 -3
- package/src/components/ATelInput.vue +206 -66
- package/src/composables/useCountryDetection.ts +28 -11
- package/src/composables/useCountryMatching.ts +160 -20
- package/src/composables/useCountrySelection.ts +71 -0
- package/src/composables/usePhoneValidation.ts +81 -18
- package/src/composables/useSyncedModel.ts +80 -0
- package/src/composables/useTelInputValidation.ts +50 -11
- package/src/index.ts +2 -0
- package/src/types.ts +80 -0
- package/src/vee-validate/index.ts +2 -0
- package/src/vee-validate/useTelField.ts +202 -0
- package/src/zod/index.ts +259 -0
- package/web-types.json +44 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePhoneValidation.js","names":[],"sources":["../../src/utils/digits.ts","../../src/composables/usePhoneValidation.ts"],"sourcesContent":["/**\n * Alternative-numeral support. Phone numbers are routinely entered with the digits of the\n * user's own script — Arabic-Indic, Persian/Urdu, Devanagari, Bengali. `libphonenumber-js`\n * and our own `\\d` cleanup only understand ASCII `0-9`, so anything else silently becomes\n * an empty number. `normalizeDigits` folds those scripts down to ASCII before validation.\n */\n\n/**\n * Base code points of contiguous decimal-digit blocks. Each block runs `base`‥`base+9`\n * for digit `0`‥`9`, so the ASCII digit is `codePoint - base`. Add a script by appending\n * one entry here.\n */\nexport const LOCALE_DIGIT_RANGES: { name: string; base: number }[] = [\n { name: 'arabic-indic', base: 0x0660 }, // ٠١٢٣٤٥٦٧٨٩\n { name: 'extended-arabic', base: 0x06f0 }, // ۰۱۲۳۴۵۶۷۸۹ — Persian / Urdu\n { name: 'devanagari', base: 0x0966 }, // ०१२३४५६७८९\n { name: 'bengali', base: 0x09e6 }, // ০১২৩৪৫৬৭৮৯\n];\n\n/** Lookup of every non-ASCII digit code point → its ASCII character. */\nconst DIGIT_MAP: Map<number, string> = (() => {\n const map = new Map<number, string>();\n for (const { base } of LOCALE_DIGIT_RANGES) {\n for (let d = 0; d <= 9; d++) map.set(base + d, String(d));\n }\n return map;\n})();\n\n/**\n * Replace any supported non-ASCII decimal digit with its ASCII equivalent. Every other\n * character (spaces, `+`, separators, letters) is left untouched — callers still run their\n * own `\\D` cleanup afterwards.\n */\nexport function normalizeDigits(input: string): string {\n const str = String(input ?? '');\n let out = '';\n for (const ch of str) {\n const cp = ch.codePointAt(0);\n out += (cp != null && DIGIT_MAP.get(cp)) || ch;\n }\n return out;\n}\n","/**\n * Country list + phone validation, framework-agnostic.\n *\n * Ported from the reference @pkgs/ui ATelInput composable with these cleanups:\n * - Drop Nuxt-only `process.client` checks → use plain `typeof window !== 'undefined'`.\n * - Drop Arabic default placeholder; let consumers pass their own.\n * - Expand the offline fallback list from 2 → ~20 of the most-populated countries.\n * - Keep REST Countries fetch + localStorage cache + libphonenumber-js examples + fast `search_key`.\n */\n\nimport { ref, type Ref } from 'vue';\nimport {\n type CountryCode,\n type Examples,\n getExampleNumber,\n isValidPhoneNumber,\n parsePhoneNumberFromString,\n} from 'libphonenumber-js';\nimport examples from 'libphonenumber-js/examples.mobile.json';\nimport { normalizeDigits } from '../utils/digits';\n\n/* -----------------------------------------------------------------------------\n * Public types\n * -------------------------------------------------------------------------- */\nexport interface RestCountry {\n name?: { common?: string };\n cca2?: string;\n idd?: { root?: string; suffixes?: string[] };\n flags?: { png?: string; svg?: string };\n}\n\nexport interface CountryOption<T = RestCountry> {\n /** Display label, e.g. \"Egypt (+20)\". */\n label: string;\n /** Stable unique ID — the ISO 3166-1 alpha-2 code, e.g. \"EG\". */\n value: string;\n /** Precomputed normalized string for fast substring search. */\n search_key: string;\n raw_data: {\n iso2: string;\n dial_code: string;\n dial_digits: string;\n name: string;\n flag: string | null;\n source: 'restcountries' | 'fallback';\n original: T;\n };\n}\n\nexport interface PhoneRequiredInfo {\n iso2: string;\n dial_code: string;\n /** Empty by default — consumer passes a placeholder via the component prop. */\n placeholder: string;\n example_national: string;\n example_e164: string;\n national_number_length: { min: number | null; max: number | null };\n format_hint: string;\n}\n\nexport type PhoneValidationReason =\n | 'missing_country'\n | 'country_not_supported'\n | 'phone_has_non_digits'\n | 'too_short'\n | 'too_long'\n | 'invalid_phone'\n | 'parse_failed';\n\nexport interface PhoneValidationResult {\n ok: boolean;\n reason: PhoneValidationReason | null;\n country: { iso2: string; dial_code: string } | null;\n phone: { raw: string | null; digits: string };\n full_phone: string | null;\n required: PhoneRequiredInfo | null;\n details?: Record<string, unknown>;\n}\n\nexport type ValidateArgs =\n | {\n country: { iso2: string; dial_code?: string } | null | undefined;\n phone?: undefined;\n /** BCP-47 locale — localizes the numerals in the returned `required.format_hint`. */\n locale?: string;\n }\n | {\n country: { iso2: string; dial_code?: string } | null | undefined;\n phone: string | null;\n /** BCP-47 locale — localizes the numerals in the returned `required.format_hint`. */\n locale?: string;\n };\n\nconst STORAGE_KEY = 'ali_ui_phone_countries_v1';\nconst REST_COUNTRIES_URL = 'https://restcountries.com/v3.1/all?fields=name,cca2,idd,flags';\n\n/* -----------------------------------------------------------------------------\n * Module-level singleton state for country data.\n *\n * `usePhoneValidation()` is called once per `<ATelInput>`, once per `<ACountrySelect>`,\n * once per `useTelField()`, once per `zPhone()` — so a single page can spin up four\n * or more instances. Without deduplication, each instance would independently:\n * - JSON.parse the localStorage cache,\n * - fire the REST Countries fetch (~80KB),\n * - parse + normalise the response.\n *\n * Sharing the result via these module-level slots collapses every concurrent call\n * to **one** network request and **one** cache parse for the lifetime of the page.\n * Each `usePhoneValidation()` instance still gets its own reactive `countries` ref,\n * so consumers can mutate their local view (e.g., `props.countries` override) without\n * affecting siblings — the singleton is only consulted as a data source.\n * -------------------------------------------------------------------------- */\nlet sharedCountries: CountryOption[] | null = null;\nlet inflightFetch: Promise<CountryOption[]> | null = null;\n\nconst EX = examples as unknown as Examples;\n\nconst isBrowser = () => typeof window !== 'undefined';\n\nfunction toDigits(v: unknown) {\n // Fold alternative numeral systems (Arabic-Indic, Persian, Devanagari, Bengali) down to\n // ASCII first, so a number typed in the user's own script still validates.\n return normalizeDigits(String(v ?? '')).replace(/\\D/g, '');\n}\n\n/**\n * Render an ASCII digit string in a locale's numeral system (e.g. `'ar'` → `٠-٩`).\n * Used only for display hints — falls back to ASCII if the locale is unknown.\n */\nfunction localizeDigits(digits: string, locale?: string): string {\n if (!locale) return digits;\n try {\n const fmt = new Intl.NumberFormat(locale, { useGrouping: false });\n return digits.replace(/[0-9]/g, (d) => fmt.format(Number(d)));\n } catch {\n return digits;\n }\n}\n\nfunction ensurePlusDial(dial: unknown) {\n const d = toDigits(dial);\n return d ? `+${d}` : '';\n}\n\nfunction normalizeIso2(iso2: unknown) {\n return String(iso2 ?? '')\n .trim()\n .toUpperCase();\n}\n\nfunction dropLeadingZeros(digits: string) {\n return String(digits ?? '').replace(/^0+/, '');\n}\n\nfunction buildFullE164(dial: string, digits: string) {\n const dialClean = ensurePlusDial(dial);\n const nsn = dropLeadingZeros(toDigits(digits));\n return dialClean && nsn ? `${dialClean}${nsn}` : null;\n}\n\nfunction inferLengthFromExample(national: string) {\n const d = toDigits(national);\n if (!d) return { min: null, max: null };\n const n = d.length;\n return { min: Math.max(4, n - 2), max: n + 2 };\n}\n\nfunction buildDialCode(idd?: RestCountry['idd']): string | null {\n const root = idd?.root?.trim();\n if (!root || !root.startsWith('+')) return null;\n const suffix = idd?.suffixes?.[0]?.trim() ?? '';\n const out = `${root}${suffix}`;\n return out.startsWith('+') ? out : null;\n}\n\nfunction normalizeSearchKey(input: string) {\n return (\n String(input ?? '')\n .toLowerCase()\n .replace(/\\s+/g, ' ')\n .trim()\n // Keep letters of every script (so localized names — Arabic, etc. — stay searchable),\n // digits, `+`, and spaces; drop punctuation/symbols.\n .replace(/[^\\p{L}\\p{N}+ ]/gu, '')\n );\n}\n\n/**\n * Return a copy of the country list with display names localized to `locale` via\n * `Intl.DisplayNames`. `search_key` is rebuilt (keeping the English name too) so search\n * still matches either spelling. Unknown locales / regions fall back to the English name.\n */\nexport function localizeCountries(list: CountryOption[], locale?: string): CountryOption[] {\n if (!locale) return list;\n let display: Intl.DisplayNames;\n try {\n display = new Intl.DisplayNames([locale], { type: 'region' });\n } catch {\n return list;\n }\n return list.map((c) => {\n let localized = c.raw_data.name;\n try {\n localized = display.of(c.raw_data.iso2) || c.raw_data.name;\n } catch {\n /* region not in CLDR data — keep English name */\n }\n if (localized === c.raw_data.name) return c;\n const dial = c.raw_data.dial_code;\n return {\n ...c,\n label: `${localized} (${dial})`,\n search_key: normalizeSearchKey(\n `${localized} ${c.raw_data.name} ${dial} ${c.raw_data.iso2} ${c.raw_data.dial_digits}`\n ),\n raw_data: { ...c.raw_data, name: localized },\n };\n });\n}\n\n/* -----------------------------------------------------------------------------\n * Offline fallback — used when the REST Countries fetch fails. ~20 most-populated\n * countries so the picker is still useful when offline.\n * -------------------------------------------------------------------------- */\nfunction makeFallback(iso2: string, name: string, dial: string): CountryOption {\n const dialDigits = toDigits(dial);\n return {\n label: `${name} (+${dialDigits})`,\n value: iso2,\n search_key: normalizeSearchKey(`${name} +${dialDigits} ${iso2}`),\n raw_data: {\n iso2,\n dial_code: `+${dialDigits}`,\n dial_digits: dialDigits,\n name,\n flag: `https://flagcdn.com/w40/${iso2.toLowerCase()}.png`,\n source: 'fallback',\n original: {},\n },\n };\n}\n\nconst FALLBACK_COUNTRIES: CountryOption[] = [\n makeFallback('SA', 'Saudi Arabia', '+966'),\n makeFallback('EG', 'Egypt', '+20'),\n makeFallback('AE', 'United Arab Emirates', '+971'),\n makeFallback('US', 'United States', '+1'),\n makeFallback('GB', 'United Kingdom', '+44'),\n makeFallback('DE', 'Germany', '+49'),\n makeFallback('FR', 'France', '+33'),\n makeFallback('ES', 'Spain', '+34'),\n makeFallback('IT', 'Italy', '+39'),\n makeFallback('TR', 'Turkey', '+90'),\n makeFallback('RU', 'Russia', '+7'),\n makeFallback('CN', 'China', '+86'),\n makeFallback('IN', 'India', '+91'),\n makeFallback('JP', 'Japan', '+81'),\n makeFallback('KR', 'South Korea', '+82'),\n makeFallback('BR', 'Brazil', '+55'),\n makeFallback('MX', 'Mexico', '+52'),\n makeFallback('CA', 'Canada', '+1'),\n makeFallback('AU', 'Australia', '+61'),\n makeFallback('NG', 'Nigeria', '+234'),\n makeFallback('PK', 'Pakistan', '+92'),\n makeFallback('ID', 'Indonesia', '+62'),\n];\n\n/* -----------------------------------------------------------------------------\n * Composable\n * -------------------------------------------------------------------------- */\nexport interface UsePhoneValidationReturn {\n countries: Ref<CountryOption[]>;\n isCountriesLoading: Ref<boolean>;\n getCountries(options?: { force?: boolean }): Promise<CountryOption[]>;\n searchCountries(keyword: string, limit?: number): CountryOption[];\n getCountryByValue(value: string): CountryOption | null;\n getCountriesByDial(dial: string): CountryOption[];\n getRequiredInfo(\n country: { iso2: string; dial_code?: string },\n locale?: string\n ): PhoneRequiredInfo | null;\n validate(input: ValidateArgs): PhoneValidationResult;\n}\n\nexport function usePhoneValidation(): UsePhoneValidationReturn {\n const countries = ref<CountryOption[]>([]);\n const isCountriesLoading = ref(false);\n\n // Pre-seed the lookup indexes with the bundled fallback (~22 most-populated countries).\n // This makes country *detection* (matchLeadingDialCode, getCountryByValue) work\n // synchronously from first paint — without it, typing a +20/+1/+44 etc. number while\n // the REST Countries fetch is in flight would silently fail every matcher tier because\n // `parsePhoneNumberFromString('+201066105963').country = 'EG'` can't resolve to a\n // `CountryOption` (empty index → null) and tier 3's `getCountriesByDial('20')` also\n // returns []. `countries.value` stays `[]` so `getCountries()` still runs its\n // localStorage → network upgrade path; once that resolves the indexes are rebuilt\n // wholesale with the full ~250-entry list.\n function buildIndexes(list: CountryOption[]) {\n const valueMap = new Map<string, CountryOption>();\n const dialMap = new Map<string, CountryOption[]>();\n for (const item of list) {\n valueMap.set(item.value, item);\n const dial = item.raw_data.dial_digits;\n if (dial) {\n const bucket = dialMap.get(dial) ?? [];\n bucket.push(item);\n dialMap.set(dial, bucket);\n }\n }\n return { valueMap, dialMap };\n }\n\n const _seed = buildIndexes(FALLBACK_COUNTRIES);\n const byValue = ref<Map<string, CountryOption>>(_seed.valueMap);\n const byDialDigits = ref<Map<string, CountryOption[]>>(_seed.dialMap);\n\n function rebuildIndexes(list: CountryOption[]) {\n const { valueMap, dialMap } = buildIndexes(list);\n byValue.value = valueMap;\n byDialDigits.value = dialMap;\n }\n\n function upsertCountries(list: CountryOption[]) {\n countries.value = list;\n rebuildIndexes(list);\n }\n\n function normalizeRestCountries(list: RestCountry[]): CountryOption[] {\n const out: CountryOption[] = [];\n for (const c of list) {\n const name = c?.name?.common?.trim();\n const iso2 = normalizeIso2(c?.cca2);\n const dial = buildDialCode(c?.idd);\n const flag = c?.flags?.png?.trim() || c?.flags?.svg?.trim() || null;\n if (!name || !iso2 || !dial) continue;\n const dialDigits = toDigits(dial);\n const search_key = normalizeSearchKey(`${name} ${dial} ${iso2} ${dialDigits}`);\n out.push({\n label: `${name} (${dial})`,\n value: iso2,\n search_key,\n raw_data: {\n iso2,\n dial_code: dial,\n dial_digits: dialDigits,\n name,\n flag,\n source: 'restcountries',\n original: c,\n },\n });\n }\n\n const map = new Map<string, CountryOption>();\n for (const item of out) {\n const prev = map.get(item.value);\n if (!prev) {\n map.set(item.value, item);\n continue;\n }\n const prevScore = (prev.raw_data.flag ? 1 : 0) + (prev.raw_data.dial_code ? 1 : 0);\n const nextScore = (item.raw_data.flag ? 1 : 0) + (item.raw_data.dial_code ? 1 : 0);\n if (nextScore > prevScore) map.set(item.value, item);\n }\n return Array.from(map.values()).sort((a, b) => a.raw_data.name.localeCompare(b.raw_data.name));\n }\n\n async function getCountries(options?: { force?: boolean }) {\n const force = Boolean(options?.force);\n if (!force && countries.value.length) return countries.value;\n\n // Shared module-level cache — if any sibling instance already loaded the list,\n // adopt it without re-parsing localStorage or hitting the network.\n if (!force && sharedCountries) {\n upsertCountries(sharedCountries);\n return countries.value;\n }\n\n // Shared in-flight promise — if another instance fired the fetch first, await\n // its result instead of starting a duplicate request.\n if (!force && inflightFetch) {\n isCountriesLoading.value = true;\n try {\n const list = await inflightFetch;\n upsertCountries(list);\n return countries.value;\n } finally {\n isCountriesLoading.value = false;\n }\n }\n\n if (!force && isBrowser()) {\n try {\n const cached = localStorage.getItem(STORAGE_KEY);\n if (cached) {\n const parsed = JSON.parse(cached) as CountryOption[];\n if (Array.isArray(parsed) && parsed.length) {\n sharedCountries = parsed;\n upsertCountries(parsed);\n return countries.value;\n }\n }\n } catch {\n /* ignore parse errors */\n }\n }\n\n isCountriesLoading.value = true;\n inflightFetch = (async (): Promise<CountryOption[]> => {\n try {\n const res = await fetch(REST_COUNTRIES_URL);\n if (!res.ok) throw new Error(`Failed to fetch countries: ${res.status}`);\n const data = (await res.json()) as RestCountry[];\n const normalized = normalizeRestCountries(data);\n const list = normalized.length ? normalized : FALLBACK_COUNTRIES;\n if (isBrowser()) {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(list));\n } catch {\n /* storage full or disabled */\n }\n }\n return list;\n } catch {\n return FALLBACK_COUNTRIES;\n }\n })();\n\n try {\n const list = await inflightFetch;\n sharedCountries = list;\n upsertCountries(list);\n return countries.value;\n } finally {\n isCountriesLoading.value = false;\n }\n }\n\n function searchCountries(keyword: string, limit = 50) {\n const q = normalizeSearchKey(keyword);\n if (!q) return countries.value.slice(0, limit);\n const res: CountryOption[] = [];\n for (const item of countries.value) {\n if (item.search_key.includes(q)) {\n res.push(item);\n if (res.length >= limit) break;\n }\n }\n return res;\n }\n\n function getCountryByValue(value: string) {\n return byValue.value.get(normalizeIso2(value)) ?? null;\n }\n\n function getCountriesByDial(dial: string) {\n return byDialDigits.value.get(toDigits(dial)) ?? [];\n }\n\n function getRequiredInfo(\n country: { iso2: string; dial_code?: string },\n locale?: string\n ): PhoneRequiredInfo | null {\n const iso2 = normalizeIso2(country.iso2);\n if (!iso2) return null;\n try {\n const example = getExampleNumber(iso2 as CountryCode, EX);\n const exampleNational = example?.formatNational?.() ?? '';\n const exampleE164 = example?.format?.('E.164') ?? '';\n const inferred = inferLengthFromExample(exampleNational);\n const dial_code = country.dial_code\n ? ensurePlusDial(country.dial_code)\n : exampleE164\n ? `+${example?.countryCallingCode}`\n : '';\n const digitsExample = toDigits(exampleNational);\n return {\n iso2,\n dial_code,\n placeholder: '',\n example_national: exampleNational,\n example_e164: exampleE164,\n national_number_length: inferred,\n format_hint: digitsExample ? `e.g. ${localizeDigits(digitsExample, locale)}` : '',\n };\n } catch {\n return null;\n }\n }\n\n function validate(input: ValidateArgs): PhoneValidationResult {\n const country = input.country ?? null;\n if (!country?.iso2) {\n return {\n ok: false,\n reason: 'missing_country',\n country: null,\n phone: { raw: ('phone' in input ? input.phone : null) ?? null, digits: '' },\n full_phone: null,\n required: null,\n };\n }\n\n const iso2 = normalizeIso2(country.iso2);\n const required = getRequiredInfo({ iso2, dial_code: country.dial_code }, input.locale);\n if (!required) {\n return {\n ok: false,\n reason: 'country_not_supported',\n country: { iso2, dial_code: ensurePlusDial(country.dial_code) },\n phone: { raw: ('phone' in input ? input.phone : null) ?? null, digits: '' },\n full_phone: null,\n required: null,\n };\n }\n\n if (!('phone' in input)) {\n return {\n ok: true,\n reason: null,\n country: { iso2: required.iso2, dial_code: required.dial_code },\n phone: { raw: null, digits: '' },\n full_phone: null,\n required,\n };\n }\n\n const raw = input.phone;\n const digits = toDigits(raw);\n\n if (!raw || !String(raw).trim()) {\n return {\n ok: true,\n reason: null,\n country: { iso2: required.iso2, dial_code: required.dial_code },\n phone: { raw: raw ?? null, digits: '' },\n full_phone: null,\n required,\n };\n }\n\n if (\n String(raw)\n .replace(/\\s+/g, '')\n .match(/[^\\d+]/)\n ) {\n return {\n ok: false,\n reason: 'phone_has_non_digits',\n country: { iso2: required.iso2, dial_code: required.dial_code },\n phone: { raw, digits },\n full_phone: buildFullE164(required.dial_code, digits),\n required,\n };\n }\n\n const nsn = dropLeadingZeros(digits);\n const { min, max } = required.national_number_length;\n\n if (min !== null && nsn.length < min) {\n return {\n ok: false,\n reason: 'too_short',\n country: { iso2: required.iso2, dial_code: required.dial_code },\n phone: { raw, digits },\n full_phone: buildFullE164(required.dial_code, digits),\n required,\n details: { min, actual: nsn.length },\n };\n }\n\n if (max !== null && nsn.length > max) {\n return {\n ok: false,\n reason: 'too_long',\n country: { iso2: required.iso2, dial_code: required.dial_code },\n phone: { raw, digits },\n full_phone: buildFullE164(required.dial_code, digits),\n required,\n details: { max, actual: nsn.length },\n };\n }\n\n const full = buildFullE164(required.dial_code, digits) ?? String(raw);\n\n try {\n const ok = isValidPhoneNumber(full, iso2 as CountryCode);\n if (!ok) {\n const parsed = parsePhoneNumberFromString(full, iso2 as CountryCode);\n return {\n ok: false,\n reason: 'invalid_phone',\n country: { iso2: required.iso2, dial_code: required.dial_code },\n phone: { raw, digits },\n full_phone: parsed?.number ?? null,\n required,\n details: {\n type: parsed?.getType?.() ?? null,\n possible: parsed?.isPossible?.() ?? null,\n country: parsed?.country ?? null,\n },\n };\n }\n const parsed = parsePhoneNumberFromString(full, iso2 as CountryCode);\n return {\n ok: true,\n reason: null,\n country: { iso2: required.iso2, dial_code: required.dial_code },\n phone: { raw, digits },\n full_phone: parsed?.number ?? full,\n required,\n };\n } catch (e) {\n return {\n ok: false,\n reason: 'parse_failed',\n country: { iso2: required.iso2, dial_code: required.dial_code },\n phone: { raw, digits },\n full_phone: buildFullE164(required.dial_code, digits),\n required,\n details: { error: (e as Error)?.message ?? String(e) },\n };\n }\n }\n\n return {\n countries,\n isCountriesLoading,\n getCountries,\n searchCountries,\n getCountryByValue,\n getCountriesByDial,\n getRequiredInfo,\n validate,\n };\n}\n"],"mappings":"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"}
|