mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-08-30 12:18:12 +00:00
refactor: maintain local state for PhoneInput typing to prevent input reset and add helper utilities for E.164 conversion.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { z } from 'zod';
|
||||
import { isValidPhoneNumber, parsePhoneNumberFromString } from 'libphonenumber-js';
|
||||
import { getCountryCallingCode, isValidPhoneNumber, parsePhoneNumberFromString, type CountryCode } from 'libphonenumber-js';
|
||||
|
||||
/**
|
||||
* Accepts any international number in E.164 (`+<country><number>`) or a
|
||||
@@ -16,3 +16,41 @@ export const phoneNumber = z
|
||||
|
||||
/** Same rules, but blank is allowed. */
|
||||
export const optionalPhoneNumber = z.union([z.literal(''), phoneNumber]).optional();
|
||||
|
||||
/**
|
||||
* Digits the field should hold after an edit. A keystroke that only removed
|
||||
* a formatting character (backspacing the ')' out of "(415)") leaves the
|
||||
* digits unchanged, which would otherwise make the caret stick — drop a real
|
||||
* digit in that case.
|
||||
*/
|
||||
export function nextNationalDigits(text: string, prevDisplay: string): string {
|
||||
const digits = text.replace(/\D/g, '');
|
||||
const deleting = text.length < prevDisplay.length;
|
||||
if (deleting && digits === prevDisplay.replace(/\D/g, '')) return digits.slice(0, -1);
|
||||
return digits;
|
||||
}
|
||||
|
||||
/** National digits of a stored value, for display in the number box. */
|
||||
export function toNationalDigits(value: string, country: CountryCode): string {
|
||||
if (!value) return '';
|
||||
const parsed = parsePhoneNumberFromString(value);
|
||||
if (parsed) return parsed.nationalNumber;
|
||||
if (value.startsWith('+')) {
|
||||
const prefix = `+${getCountryCallingCode(country)}`;
|
||||
if (value.startsWith(prefix)) return value.slice(prefix.length).replace(/\D/g, '');
|
||||
}
|
||||
return value.replace(/\D/g, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* E.164 for the digits typed so far. Incomplete numbers don't parse, so they
|
||||
* fall back to a plain dial-code concatenation rather than collapsing to ''
|
||||
* — the value has to survive mid-typing for the field to be usable.
|
||||
*/
|
||||
export function toE164(digits: string, country: CountryCode): string {
|
||||
if (!digits) return '';
|
||||
return (
|
||||
parsePhoneNumberFromString(digits, country)?.number ??
|
||||
`+${getCountryCallingCode(country)}${digits}`
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user