mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-09-02 13:53:49 +00:00
feat: implement input length constraints and enhanced validation for international phone numbers
This commit is contained in:
@@ -8,7 +8,7 @@ import {
|
||||
type CountryCode,
|
||||
} from 'libphonenumber-js';
|
||||
import { CountryFlag, getCountryName, resolveLang } from './CountrySelect';
|
||||
import { formatNational, nextNationalDigits, toE164, toNationalDigits } from './phone';
|
||||
import { exceedsMaxLength, formatNational, maxNationalLength, nextNationalDigits, toE164, toNationalDigits } from './phone';
|
||||
|
||||
// Static list, computed once at module load — same as CountrySelect's dataset.
|
||||
const COUNTRY_CODES = getCountries();
|
||||
@@ -45,7 +45,11 @@ 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`. */
|
||||
/**
|
||||
* Fired when focus leaves a field that has digits in it — wire to the
|
||||
* form's `trigger`. A blank field is left to submit-time validation, like
|
||||
* the form's other inputs, so tabbing past it doesn't raise an error.
|
||||
*/
|
||||
onBlur?: () => void;
|
||||
label?: React.ReactNode;
|
||||
placeholder?: string;
|
||||
@@ -124,6 +128,8 @@ export function PhoneInput({
|
||||
}
|
||||
|
||||
function applyDigits(digits: string, forCountry: CountryCode) {
|
||||
// Keystroke past the longest possible number is ignored, not stored.
|
||||
if (exceedsMaxLength(digits, forCountry)) return;
|
||||
// Once the number is valid, show the true national part: someone who
|
||||
// types a trunk prefix (0911111111) or the country code (251911111111)
|
||||
// shouldn't end up with it doubled beside the "+251" selector. Not
|
||||
@@ -155,7 +161,8 @@ export function PhoneInput({
|
||||
if (!next) return;
|
||||
const code = next as CountryCode;
|
||||
setCountry(code);
|
||||
applyDigits(national.replace(/\D/g, ''), code);
|
||||
// A number carried over from a longer plan is cut to fit the new one.
|
||||
applyDigits(national.replace(/\D/g, '').slice(0, maxNationalLength(code)), code);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -177,7 +184,7 @@ export function PhoneInput({
|
||||
// country select mustn't validate a half-typed number.
|
||||
wrapperProps={{
|
||||
onBlur: (e: React.FocusEvent<HTMLDivElement>) => {
|
||||
if (!e.currentTarget.contains(e.relatedTarget)) onBlur?.();
|
||||
if (national && !e.currentTarget.contains(e.relatedTarget)) onBlur?.();
|
||||
},
|
||||
}}
|
||||
leftSectionWidth={92}
|
||||
|
||||
Reference in New Issue
Block a user