UNPKG

v-phone-input

Version:

International phone field for Vuetify 3 and Vue 3.

464 lines (463 loc) 15 kB
import { ParsedPhoneNumber } from 'awesome-phonenumber'; import { ComputedRef, ExtractPropTypes, MaybeRef, Ref, ShallowRef, VNode, WritableComputedRef } from 'vue'; import { ComponentSlots } from 'vue-component-type-helpers'; import { VAutocomplete, VSelect, VTextField } from 'vuetify/components'; import { default as makePhoneInputComposableProps } from './props/makePhoneInputComposableProps.ts'; import { default as makePhoneInputCountryDisplayProps } from './props/makePhoneInputCountryDisplayProps.ts'; import { default as makePhoneInputCountryProps } from './props/makePhoneInputCountryProps.ts'; import { default as makePhoneInputMessagesProps } from './props/makePhoneInputMessagesProps.ts'; import { default as makePhoneInputProps } from './props/makePhoneInputProps.ts'; /** * Convert an options interface to a composable options interface. * * @internal */ export type VPhoneInputExtractComposableOptions<Props extends {}> = { [K in keyof Props]?: MaybeRef<Props[K]> | undefined; }; /** * Country object. */ export interface VPhoneInputCountryObject { /** * Human-readable name. */ readonly name: string; /** * Two-letter code. * * @see https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 */ readonly iso2: string; /** * Dial code (without the `+` symbol prefix). * * @see https://en.wikipedia.org/wiki/List_of_telephone_country_codes */ readonly dialCode: string; } /** * Country object or valid two-letter code. * * @internal */ export type VPhoneInputCountryObjectOrIso2 = VPhoneInputCountryObject | VPhoneInputCountryObject["iso2"]; /** * Country guesser function result. * * @internal */ export type VPhoneInputCountryGuesserResult = VPhoneInputCountryObjectOrIso2 | null | undefined; /** * Country guesser function. * * @internal */ export interface VPhoneInputCountryGuesser { /** * Guess a country. */ (): Promise<VPhoneInputCountryGuesserResult> | VPhoneInputCountryGuesserResult; /** * Previously memoized country two-letter code. * * @remarks * Property should only be available when the country guesser function supports memoization. * It is set to memoize the currently selected country. * It is retrieved to avoid running guesser function when a memoized country is available. */ memoized?: MaybeRef<string | null | undefined>; } /** * Props to customize country related features. * * @internal */ export interface VPhoneInputCountryProps<Country extends VPhoneInputCountryObject> extends Readonly<Partial<ExtractPropTypes<ReturnType<typeof makePhoneInputCountryProps<Country>>>>> { } /** * Options for `usePhoneInputCountries` composable. * * @internal */ export interface VPhoneInputCountryComposableOptions<Country extends VPhoneInputCountryObject> extends VPhoneInputExtractComposableOptions<VPhoneInputCountryProps<Country>> { } /** * `usePhoneInputCountries` composable. * * @internal */ export interface VPhoneInputCountryComposable<Country extends VPhoneInputCountryObject> { /** * List of available countries. */ readonly countries: ComputedRef<Country[]>; /** * List of available preferred countries. */ readonly preferredCountries: ComputedRef<Country[]>; /** * List of available unpreferred countries. */ readonly unpreferredCountries: ComputedRef<Country[]>; /** * Default country to use. */ readonly defaultCountry: ComputedRef<Country | null>; /** * Fallback country to use. */ readonly fallbackCountry: ComputedRef<Country>; /** * Find a country object using a country object or two-letter code. */ readonly findCountry: ComputedRef<(value: VPhoneInputCountryObjectOrIso2 | null | undefined) => Country | null>; } /** * Message factory context. * * @remarks * Context may vary depending on the message to build. * * @internal */ export interface VPhoneInputMessageFactoryContext<Country extends VPhoneInputCountryObject, Label extends string | undefined = string, Example extends string | undefined = string> { /** * Current country. */ readonly country: Country; /** * Current country's phone number example. */ readonly example: Example; /** * Current phone input's label. */ readonly label: Label; } /** * Build a message for a given context. * * @internal */ export type VPhoneInputMessageFactory<Country extends VPhoneInputCountryObject, Label extends string | undefined = string, Example extends string | undefined = string> = (context: VPhoneInputMessageFactoryContext<Country, Label, Example>) => string; /** * Message string or factory. * * @internal */ export type VPhoneInputMessage<Country extends VPhoneInputCountryObject, Label extends string | undefined = string, Example extends string | undefined = string> = string | VPhoneInputMessageFactory<Country, Label, Example>; /** * Props to customize localization related features. * * @internal */ export interface VPhoneInputMessagesProps<Country extends VPhoneInputCountryObject> extends Readonly<Partial<ExtractPropTypes<ReturnType<typeof makePhoneInputMessagesProps<Country>>>>> { } /** * Options for `usePhoneInputMessages` composable. * * @internal */ export interface VPhoneInputMessagesComposableOptions<Country extends VPhoneInputCountryObject> extends VPhoneInputExtractComposableOptions<VPhoneInputMessagesProps<Country>> { /** * Country to resolve messages with. */ readonly country: MaybeRef<Country>; } /** * `usePhoneInputMessages` composable. * * @internal */ export interface VPhoneInputMessagesComposable<Country extends VPhoneInputCountryObject> { /** * Formatted example of phone number for current country. */ readonly example: ComputedRef<string>; /** * Label for phone input. */ readonly label: ComputedRef<string | undefined>; /** * `aria-label` for phone input. */ readonly ariaLabel: ComputedRef<string | undefined>; /** * Label for country input. */ readonly countryLabel: ComputedRef<string | undefined>; /** * `aria-label` for country input. */ readonly countryAriaLabel: ComputedRef<string | undefined>; /** * Placeholder for phone input. */ readonly placeholder: ComputedRef<string | undefined>; /** * Invalid message for phone input. */ readonly invalidMessage: ComputedRef<string | undefined>; /** * Resolve a message using current context. */ readonly resolveMessage: ComputedRef<(<Message extends VPhoneInputMessage<Country> | null | undefined>(message: Message) => Message extends null | undefined ? string | undefined : string)>; } /** * Options for `usePhoneInput` composable. * * @internal */ export interface VPhoneInputComposableOptions<Country extends VPhoneInputCountryObject> extends VPhoneInputExtractComposableOptions<Readonly<Partial<ExtractPropTypes<ReturnType<typeof makePhoneInputComposableProps<Country>>>>>> { /** * Phone model value ref, formatted using `modelFormat`. */ readonly modelValue: Ref<string | null | undefined>; /** * Country model value ref. */ readonly country?: Ref<string | null | undefined>; /** * Country input component or element ref to bind listeners to. */ readonly countryInputRef?: Ref<{ $el: HTMLElement; } | HTMLElement | null | undefined>; /** * Phone input component or element ref to bind listeners to. */ readonly phoneInputRef?: Ref<{ $el: HTMLElement; } | HTMLElement | null | undefined>; } /** * `usePhoneInput` composable. * * @internal */ export interface VPhoneInputComposable<Country extends VPhoneInputCountryObject> extends VPhoneInputCountryComposable<Country>, VPhoneInputMessagesComposable<Country> { /** * Country input component or element ref on which listeners are bound. */ countryInputRef: Ref<{ $el: HTMLElement; } | HTMLElement | null | undefined>; /** * Phone input component or element ref on which listeners are bound. */ phoneInputRef: Ref<{ $el: HTMLElement; } | HTMLElement | null | undefined>; /** * Phone input value. */ phone: Ref<string | null>; /** * Country object value (computed from country input value). */ countryObject: WritableComputedRef<Country>; /** * Phone object value (computed from phone input value). */ phoneObject: ComputedRef<ParsedPhoneNumber | null>; /** * Phone object valid state (might be null if validation is disabled). */ phoneValid: ComputedRef<boolean | null>; /** * Tells if a country is currently guessing. */ countryGuessing: Readonly<Ref<boolean>>; /** * Trigger phone input value formatting. */ formatPhoneInputValue: () => void; } /** * Available implementation for country input component (either `VSelect` or `VAutocomplete`). * * @internal */ export type VPhoneCountryInputComponent = typeof VSelect | typeof VAutocomplete; /** * Component properties for country display components. * * @internal */ export interface VPhoneCountryDisplayProps<Country extends VPhoneInputCountryObject> extends Readonly<ExtractPropTypes<ReturnType<typeof makePhoneInputCountryDisplayProps<Country>>>> { } /** * Component props for `VPhoneInput` (without models properties). * * @internal */ export interface VPhoneInputNonModelProps<Country extends VPhoneInputCountryObject, CountryInputComponent extends VPhoneCountryInputComponent> extends Readonly<Partial<ExtractPropTypes<ReturnType<typeof makePhoneInputProps<Country, CountryInputComponent>>>>> { } /** * Component props for `VPhoneInput`. * * @internal */ export interface VPhoneInputProps<Country extends VPhoneInputCountryObject, CountryInputComponent extends VPhoneCountryInputComponent> extends VPhoneInputNonModelProps<Country, CountryInputComponent> { /** * Current phone number, formatted using `modelFormat`. */ modelValue?: string | null | undefined; /** * Currently selected country. */ country?: string | null | undefined; } /** * Component events for `VPhoneInput` (without models events). * * @internal */ export interface VPhoneInputNonModelEmits<Country extends VPhoneInputCountryObject> { /** * Country object value has been updated (computed from country input value). */ "update:country-object": [value: Country]; /** * Phone object value has been updated (computed from phone input value). */ "update:phone-object": [value: ParsedPhoneNumber | null]; } /** * Component events for `VPhoneInput`. * * @internal */ export interface VPhoneInputEmits<Country extends VPhoneInputCountryObject> extends VPhoneInputNonModelEmits<Country> { /** * Current phone number has been updated. */ "update:model-value": [string | null | undefined]; /** * Currently selected country has been updated. */ "update:country": [string]; } /** * Component slots forwarded to `VSelect` or `VAutocomplete`. * * @interface * * @internal */ export type VPhoneInputForwardedSlots<CountryInputComponent extends VPhoneCountryInputComponent> = { [K in keyof ComponentSlots<CountryInputComponent> as K extends string ? `country-input:${K}` : never]: ComponentSlots<CountryInputComponent>[K]; } & { [K in keyof ComponentSlots<typeof VTextField>]: ComponentSlots<typeof VTextField>[K]; }; /** * Component direct slots for `VPhoneInput`. * * @interface * * @internal */ export interface VPhoneInputCountrySlots<Country extends VPhoneInputCountryObject> { /** * Country display. * * @remarks * `decorative` tells if the display should be ignored by screen readers or * if it must have an accessible name (e.g. through `title` attribute). * * @defaultValue * Country display component from `countryDisplayComponent` property if available, * `'+<country.dialCode>'` otherwise. */ readonly "country-display": ((scope: { country: Country; decorative: boolean; }) => VNode[]) | undefined; /** * Country list item title. * * @defaultValue * `'<country.name>'` */ readonly "country-name": ((scope: { country: Country; }) => VNode[]) | undefined; /** * Country list item prepended content. * * @defaultValue * Use the `country-display` slot with a decorative purpose. */ readonly "country-prepend": ((scope: { country: Country; }) => VNode[]) | undefined; /** * Country list item appended content. * * @defaultValue * `'+<country.dialCode>'` if `countryIconMode` property, `country-display` or * `country-prepend` is defined, nothing otherwise. */ readonly "country-append": ((scope: { country: Country; }) => VNode[]) | undefined; } /** * Component slots for `VPhoneInput`. * * @interface * * @internal */ export type VPhoneInputSlots<Country extends VPhoneInputCountryObject, CountryComponent extends VPhoneCountryInputComponent> = Readonly<Partial<VPhoneInputCountrySlots<Country> & VPhoneInputForwardedSlots<CountryComponent>>>; /** * Component exposed values for `VPhoneInput`. * * @internal */ export interface VPhoneInputExposed<Country extends VPhoneInputCountryObject, CountryComponent extends VPhoneCountryInputComponent> { /** * Ref to the country input component. */ readonly countryInputRef: ShallowRef<CountryComponent | undefined>; /** * Ref to the phone input component. */ readonly phoneInputRef: ShallowRef<VTextField | undefined>; /** * Current phone object value. */ readonly countryObject: ComputedRef<Country>; /** * Current phone object value. */ readonly phoneObject: ComputedRef<ParsedPhoneNumber | null>; /** * Forwarded phone input's `VTextField.isValid` exposed value. */ readonly isValid: ComputedRef<boolean | null>; /** * Forwarded phone input's `VTextField.errorMessages` exposed value. */ readonly errorMessages: ComputedRef<string[]>; /** * Forwarded phone input's `VTextField.reset` exposed function. */ readonly reset: () => Promise<void>; /** * Forwarded phone input's `VTextField.resetValidation` exposed function. */ readonly resetValidation: () => Promise<void>; /** * Forwarded phone input's `VTextField.validate` exposed function. */ readonly validate: (silent?: boolean) => Promise<string[]>; } /** * Injectable options for `VPhoneInput` and `usePhoneInput`. * * @internal */ export interface VPhoneInputPluginOptions<Country extends VPhoneInputCountryObject, CountryInputComponent extends VPhoneCountryInputComponent> extends VPhoneInputNonModelProps<Country, CountryInputComponent> { }