Vize

Phone Field

Phone number field with consumer-supplied country metadata, pattern formatting, and E.164 output.

Package @vizejs/ui/phone-field
Maturity stable
Own the source vize lib pull phone-field
Requires context, controllable-state, id, input-mask, native-select
Aliases phone input, telephone field, international phone, e164 input
Covers HTML tel input, libphonenumber (metadata supplied by consumer), react-phone-number-input

Usage

import { PhoneField, PhoneFieldInput, PhoneFieldCountrySelect } from "@vizejs/ui/phone-field";

Or copy the source into your project with vize lib pull phone-field (see Source Distribution).

API

PhoneField<Code extends string>

Source: src/families/form/phone-field/phone-field.vue

Props

Prop Type Default Description
countries (required) readonly PhoneCountry<Code>[] required Supported countries; their code literals type v-model:country.
modelValue string undefined Controlled E.164 value (+819012345678); "" is empty. undefined selects uncontrolled use.
defaultValue string "" Initial uncontrolled value (E.164 or national text), also restored by form reset.
country Code undefined Controlled country code (v-model:country).
defaultCountry Code countries[0].code Initial uncontrolled country.
id string | null undefined Id of the number input. null and undefined select a deterministic fallback.
name string undefined Native form field name; a hidden input submits the E.164 value.
disabled boolean false Disable the input, the country select, and form submission.
required boolean false Mark the number as required for native constraint validation.
ariaLabel string undefined Accessible name of the number input.
ariaLabelledby string undefined Ids that label the number input.
ariaDescribedby string undefined Ids that describe the number input.
ariaErrormessage string undefined Id of the validation error message used while invalid.
ariaInvalid PhoneFieldAriaInvalid false Invalid state announced to assistive technology.

Events

Event Payload Description
update:modelValue [value: string] Fired when the E.164 value requests a change.
update:country [code: Code] Fired when the country requests a change (v-model:country).
complete [e164: string, country: PhoneCountry<Code>] Fired when the national number fills the country pattern.

Slots

Slot Slot props Description
default PhoneFieldSlotState<Code> Renders the country select, number input, and any hints with typed phone state.

Exposed

Member Type Description
country PhoneCountry<Code> Selected country.
nationalNumber string National significant number (digits only).
e164 string E.164 value (+819012345678), or "" while empty.
formatted string National number formatted with the country pattern.
international string International display form (+81 90-1234-5678), or "" while empty.
complete boolean Whether every slot of the country pattern is filled.
disabled boolean Whether the field is disabled.
state PhoneFieldState Stable state token.
setCountry (code: Code) => boolean Select a country, keeping the national digits.
setValue (text: string) => boolean Parse and store any national or international text; returns whether it was understood.
clear () => void Clear the number.
root —

PhoneFieldInput

Source: src/families/form/phone-field/phone-field-input.vue

Props

Prop Type Default Description
placeholder string undefined Native placeholder; defaults to nothing so consumers can show a sample number.
autocomplete string "tel-national" Autocomplete token: tel-national beside a country select, tel when international text is expected.

PhoneFieldCountrySelect

Source: src/families/form/phone-field/phone-field-country-select.vue

Props

Prop Type Default Description
ariaLabel string "Country" Accessible name of the country select.
getOptionLabel (country: PhoneCountry) => string (country) => ${country.name} (+${country.dialCode}) Option text for a country.

Behavior

Normative state x input -> outcome table for phone-field.vue, phone-field-input.vue, and phone-field-country-select.vue (@vizejs/ui/phone-field). No country data is bundled: consumers pass countries (typed with definePhoneCountries), whose code literals type v-model:country. Formatting reuses the input-mask engine; the country picker reuses NativeSelect. Every row is proven by the named test in phone-field.test.ts or phone-field-ssr.test.ts; compile-only assertions live in phone-field.types.test-d.ts.

# State Input Outcome Proven by
PH1 helpers parse / format / E.164 national text drops the trunk prefix; +/00 text picks the longest dial code (ties prefer the current country); full-width digits fold parses national and international text with trunk prefixes and dial-code matching
PH2 seeded, named render type="tel" input (inputmode="tel", tel-national), NativeSelect country picker with aria-controls, hidden E.164 value renders a tel input, a NativeSelect country picker, and a hidden E.164 value
PH3 empty typing digits format by the country pattern, the trunk prefix is stripped, complete(e164, country) fires when the pattern fills typing formats by the country pattern, strips the trunk prefix, and emits completion
PH4 number entered country select the national digits are kept and re-targeted to the new dial code; update:country fires choosing a country keeps the digits and re-targets the dial code
PH5 any international typing / paste +44… or pasted +1… switches the country and fills the national number international input and paste switch the country automatically
PH6 controlled / API model / expose a stored number's country wins over the selected country; setValue, setCountry, clear controlled values from another country win, and the API sets, switches, and clears
PH7 in a form / disabled reset / edits form reset restores defaults; disabled fields disable input and select and ignore edits form reset restores defaults and disabled fields ignore input
PH8 invalid setup empty countries / no root throws VIZE_UI_PHONE_FIELD_COUNTRIES or VIZE_UI_CONTEXT_MISSING: PhoneField rejects empty country lists and parts outside a PhoneField
PH9 SSR / hydration isolated requests byte-identical markup with the formatted number and selected country; hydration without diagnostics renders byte-identical phone markup and hydrates without mismatches

Public extension contract

Surface Contract
Parts root (group), input, country-select.
Data attributes data-vize-ui, root data-state (empty/incomplete/complete/disabled) and data-country; input data-dial-code.
Metadata PhoneCountry { code, name, dialCode, pattern?, trunkPrefix? }, supplied by the consumer.

The subpath is tree-shakable and ships no CSS; those package contracts are pinned by distribution.test.ts, check:size, and check:tree-shaking.