VxInputPhone

src/components/vx-input-phone/index.vue
Form high 6 usos

Input de telefone internacional com selector de país (bandeira + DDI) e validação via libphonenumber-js. Layout horizontal: selector de país (largura fixa ~120px) + campo numérico (flex-1). Baseado na biblioteca MazPhoneNumberInput customizada para o design Pedbot.

Com Label (padrão de formulário)

Variante dominante no codebase. Sempre usa label + :preferredCountries="['BR']" + @update="setInternational" + :reload sincronizado com o estado de abertura do componente pai (sidebar/popup).

Número de Telefone
🇧🇷 +55
Número de Telefone
🇧🇷 +55
✓ Número válido — isValid: true
Número de Telefone
🇧🇷 +55
✕ Campo é obrigatório / número inválido
Real src/views/customers/AddCustomerPopUp.vue:22
<vx-input-phone
  label="Número de Telefone"
  class="mt-5 w-full"
  name="telefone"
  v-model="customer.phone_number"
  :reload="isActive"
  :preferredCountries="['BR']"
  @update="setInternational"
  v-validate="'required'"
/>
<span class="text-danger text-sm" v-show="errors.has('telefone')">
  {{ errors.first('telefone') }}
</span>

Com Condição v-if

Exibido apenas para clientes sem messenger_id ou instagram_id (apenas WhatsApp). :reload sincronizado com o estado do sidebar para resetar o campo ao reabrir.

v-if="!customer.messenger_id && !customer.instagram_id"
Número de Telefone
🇧🇷 +55
Real src/views/customers/CustomersViewSidebar.vue:53
<vx-input-phone
  label="Número de Telefone"
  class="mt-5 w-full"
  name="telefone"
  v-if="!customer.messenger_id && !customer.instagram_id"
  v-model="customer.phone_number"
  :reload="isSidebarActiveLocal"
/>

Sem Bandeiras

Modo inline — exibido via v-else substituindo texto mascarado. :noFlags="true" remove bandeiras, :noUseBrowserLocale="true" evita detecção automática de país pelo browser.

+55
Real src/views/chat-attendance/new-chat/NewChatUserProfile.vue:118
<vx-input-phone
  v-else
  class="w-full"
  :noFlags="true"
  :noUseBrowserLocale="true"
  :preferredCountries="['BR']"
  v-model="customerData.phone_number"
  :reload="activeLocal"
  @update="setInternational"
  v-validate="'required'"
/>

Sem Seletor de País

Exibe apenas o InputTel — CountrySelector oculto. Útil quando o país já é conhecido e não deve ser alterado pelo usuário.

Número de Telefone
Sintético synthetic
<!-- Exemplo sintético — sem uso real encontrado no admin -->
<vx-input-phone
  label="Número de Telefone"
  v-model="phone"
  :noCountrySelector="true"
  :defaultCountryCode="'BR'"
/>

Dropdown de Países (estado aberto)

Ao clicar no CountrySelector, abre dropdown com lista de países, campo de busca e destaque dos preferredCountries no topo. Emite @onOpen e @onClose.

Número de Telefone
🇧🇷 +55
🇧🇷 Brasil +55
🇺🇸 Estados Unidos +1
🇵🇹 Portugal +351
🇦🇷 Argentina +54
Objeto @update — emitido a cada mudança no número:
{
  "countryCode": "BR",
  "isValid": true,
  "phoneNumber": "(11) 99876-5432",
  "countryCallingCode": "55",
  "e164": "+5511998765432",
  "nationalNumber": "11998765432",
  "formatInternational": "+55 11 99876-5432",
  "type": "MOBILE"
}

Estados

Todos os estados visuais controlados automaticamente por libphonenumber-js (valid, error) ou por props (:error, :disabled).

🇧🇷 +55

Default

🇧🇷 +55

Focused (.is-focused)

🇧🇷 +55

Valid (.is-valid)

🇧🇷 +55

Error (.has-error)

🇧🇷 +55

Disabled (.is-disabled)

🇧🇷 +55

Dark (:dark="true")

API

<!-- Exemplo com principais props -->
<!-- v-model: número digitado; @update: objeto completo do libphonenumber-js
     :reload — sincroniza reset com abertura de modal/sidebar -->
<vx-input-phone
  label="Número de Telefone"
  v-model="customer.phone_number"
  :reload="isModalActive"
  :preferredCountries="['BR']"
  :defaultCountryCode="'BR'"
  :noUseBrowserLocale="true"
  :noValidatorState="false"
  @update="setInternational"
  v-validate="'required'"
/>

Props principais

NomeTipoDefaultDescrição
valueStringv-model — número digitado (sem DDI). Emite via @input.
defaultCountryCodeStringCódigo ISO do país inicial. Ex: 'BR'. Auto-detectado pelo browser se omitido.
labelStringLabel acima do campo.
disabledBooleanfalseDesabilita CountrySelector e InputTel.
errorBooleanfalseEstado de erro manual — borda errorColor.
requiredBooleanfalseMarca o campo como obrigatório.
sizeString'sm' (110px) | 'lg' (130px). Afeta largura do CountrySelector.
noValidatorStateBooleanfalseQuando true, não exibe indicadores visuais de válido/inválido.
noFlagsBooleanfalseOculta bandeiras no CountrySelector.
noCountrySelectorBooleanfalseOculta o CountrySelector — apenas InputTel visível.
noExampleBooleanfalseOculta placeholder de exemplo do número.
preferredCountriesArrayPaíses no topo da lista. Ex: ['BR', 'US'].
onlyCountriesArrayWhitelist de países exibidos.
ignoredCountriesArray[]Blacklist de países.
colorString'dodgerblue'Cor de foco/ativo. Atenção: default não é primary — substituir manualmente.
validColorString'primary'Cor quando número é válido.
errorColorString'danger'Cor quando há erro.
darkBooleanfalseDark mode interno (independente do dark global).
darkColorString'#424242'Cor de fundo no dark mode.
noUseBrowserLocaleBooleanfalseQuando true, não detecta país pelo navigator.language.
reloadBooleanfalseToggle false→true reseta os valores do campo. Sincronizar com abertura do modal/sidebar.
borderRadiusNumber4Border radius dos campos em px.
countriesHeightNumber30Altura de cada item da lista em px.

Slots

NomeDescrição
arrowÍcone customizado para o toggle do CountrySelector. Default é um SVG de seta para baixo.

Eventos

EventoPayloadDescrição
@inputStringv-model. Número formatado AsYouType enquanto digita.
@update Object Resultado completo do libphonenumber-js: { countryCode, isValid, phoneNumber, countryCallingCode, formattedNumber, nationalNumber, type, formatInternational, formatNational, uri, e164 }. Capturar isValid e e164 para salvar no backend.
@onOpenDropdown de países aberto.
@onCloseDropdown de países fechado.
@phone-number-focusedCampo de número recebeu foco.
@phone-number-blurCampo de número perdeu foco.

Dependências

Ext: libphonenumber-jsparsePhoneNumberFromString, AsYouType
Assets: assets/js/phoneCodeCountries.js, assets/locales/
Sub-componentes: CountrySelector (dropdown com flags), InputTel (input numérico)

Onde é usado

src/views/customers/CustomersViewSidebar.vue
src/views/customers/AddCustomerPopUp.vue
src/views/chat-attendance/UserProfile.vue
src/views/chat-attendance/new-chat/NewChatUserProfile.vue
src/views/schedules/NewSchedulesListPopup.vue
⚠ Atenção — cor padrão

A prop color tem default 'dodgerblue', não 'primary'. Nos 6 usos do codebase essa prop nunca foi sobrescrita — o design system usa azul primário (#0491FF), mas o foco dos campos mostra azul dodger browser. Para corrigir: :color="'primary'".