mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-08-26 13:02:50 +00:00
refactor: improve PhoneInput digit normalization and update validation to trigger on blur
This commit is contained in:
@@ -111,6 +111,7 @@ export function SignupPage() {
|
||||
handleSubmit,
|
||||
watch,
|
||||
setValue,
|
||||
trigger,
|
||||
formState: { errors },
|
||||
} = useForm<FormValues>({
|
||||
resolver: zodResolver(schema),
|
||||
@@ -251,7 +252,8 @@ export function SignupPage() {
|
||||
label={t('signup.phoneLabel', 'Phone number')}
|
||||
placeholder={t('signup.phonePlaceholder', '9XX XXX XXX')}
|
||||
value={watch('phoneNumber') || ''}
|
||||
onChange={(val) => setValue('phoneNumber', val, { shouldValidate: true })}
|
||||
onChange={(val) => setValue('phoneNumber', val, { shouldValidate: !!errors.phoneNumber })}
|
||||
onBlur={() => trigger('phoneNumber')}
|
||||
error={errors.phoneNumber?.message}
|
||||
/>
|
||||
|
||||
|
||||
@@ -46,6 +46,8 @@ export interface PhoneInputProps {
|
||||
/** E.164 (`+14155552671`), or '' when empty. */
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
/** Fired when the number box loses focus — wire to the form's `trigger`. */
|
||||
onBlur?: () => void;
|
||||
label?: React.ReactNode;
|
||||
placeholder?: string;
|
||||
description?: React.ReactNode;
|
||||
@@ -69,6 +71,7 @@ export interface PhoneInputProps {
|
||||
export function PhoneInput({
|
||||
value,
|
||||
onChange,
|
||||
onBlur,
|
||||
label,
|
||||
placeholder,
|
||||
description,
|
||||
@@ -119,8 +122,12 @@ export function PhoneInput({
|
||||
}
|
||||
|
||||
function applyDigits(digits: string, forCountry: CountryCode) {
|
||||
setNational(new AsYouType(forCountry).input(digits));
|
||||
push(toE164(digits, forCountry));
|
||||
// Once the digits parse, show the true national number: someone who
|
||||
// types a trunk prefix (0911111111) or the country code (251911111111)
|
||||
// shouldn't end up with it doubled beside the "+251" selector.
|
||||
const parsed = parsePhoneNumberFromString(digits, forCountry);
|
||||
setNational(new AsYouType(forCountry).input(parsed?.nationalNumber ?? digits));
|
||||
push(parsed?.number ?? toE164(digits, forCountry));
|
||||
}
|
||||
|
||||
function handleText(text: string) {
|
||||
@@ -162,6 +169,7 @@ export function PhoneInput({
|
||||
placeholder={placeholder}
|
||||
value={national}
|
||||
onChange={(e) => handleText(e.currentTarget.value)}
|
||||
onBlur={onBlur}
|
||||
leftSectionWidth={92}
|
||||
leftSectionPointerEvents={disabled || readOnly ? 'none' : 'all'}
|
||||
leftSection={
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { nextNationalDigits, optionalPhoneNumber, phoneNumber, toE164, toNationalDigits } from './phone';
|
||||
import { AsYouType } from 'libphonenumber-js';
|
||||
import { AsYouType, parsePhoneNumberFromString } from 'libphonenumber-js';
|
||||
|
||||
describe('phoneNumber', () => {
|
||||
it('normalizes a legacy Ethiopian national number to E.164', () => {
|
||||
@@ -69,3 +69,25 @@ describe('typing helpers', () => {
|
||||
expect(toE164('', 'ET')).toBe('');
|
||||
});
|
||||
});
|
||||
|
||||
describe('trunk prefix and country code entered into the number box', () => {
|
||||
// The box holds the national part next to a "+251" selector, so a trunk 0
|
||||
// or a typed country code must be absorbed, not shown (and doubled) there.
|
||||
const cases: Array<[string, string]> = [
|
||||
['0911111111', '911111111'],
|
||||
['251911111111', '911111111'],
|
||||
['911111111', '911111111'],
|
||||
];
|
||||
it.each(cases)('normalizes %s to the national number %s', (typed, national) => {
|
||||
const parsed = parsePhoneNumberFromString(typed.replace(/\D/g, ''), 'ET');
|
||||
expect(parsed?.nationalNumber).toBe(national);
|
||||
});
|
||||
|
||||
it.each(cases)('yields a valid E.164 value for %s', (typed) => {
|
||||
expect(phoneNumber.parse(typed)).toBe('+251911111111');
|
||||
});
|
||||
|
||||
it('accepts a pasted +251 number', () => {
|
||||
expect(phoneNumber.parse('+251911666666')).toBe('+251911666666');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user