101 lines
2.8 KiB
Vue
101 lines
2.8 KiB
Vue
<template>
|
|
<v-text-field
|
|
v-model="localValue"
|
|
:type="inputHtmlType"
|
|
:inputmode="inputMode"
|
|
:label="opcoes?.rotulo"
|
|
:placeholder="opcoes?.placeholder"
|
|
:counter="opcoes?.limiteCaracteres"
|
|
:maxlength="opcoes?.limiteCaracteres"
|
|
v-bind="attrs"
|
|
@focus="() => emit('focus')"
|
|
@blur="() => emit('blur')"
|
|
@input="onInput"
|
|
/>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { computed, defineComponent, PropType } from "vue";
|
|
import type { PadroesEntradas } from "./tiposEntradas";
|
|
import { formatarCpfCnpj } from "./utils/cpfCnpj";
|
|
import { formatTelefone } from "./utils/telefone";
|
|
import { formatarCep } from "./utils/cep";
|
|
|
|
type EntradaTexto = PadroesEntradas["texto"];
|
|
|
|
export default defineComponent({
|
|
name: "EliEntradaTexto",
|
|
inheritAttrs: false,
|
|
props: {
|
|
/** Interface padrão (EliEntrada): value + opcoes. */
|
|
value: {
|
|
type: [String, null] as unknown as PropType<EntradaTexto["value"]>,
|
|
default: undefined,
|
|
},
|
|
opcoes: {
|
|
type: Object as PropType<EntradaTexto["opcoes"]>,
|
|
required: true,
|
|
},
|
|
},
|
|
emits: {
|
|
"update:value": (_v: EntradaTexto["value"]) => true,
|
|
/** Compat Vue2 (v-model padrão: value + input) */
|
|
input: (_v: EntradaTexto["value"]) => true,
|
|
change: (_v: EntradaTexto["value"]) => true,
|
|
focus: () => true,
|
|
blur: () => true,
|
|
},
|
|
setup(props, { attrs, emit }) {
|
|
const formato = computed(() => props.opcoes?.formato ?? "texto");
|
|
|
|
const localValue = computed<EntradaTexto["value"]>({
|
|
get: () => props.value,
|
|
set: (v) => {
|
|
emit("update:value", v);
|
|
emit("input", v);
|
|
emit("change", v);
|
|
},
|
|
});
|
|
|
|
const inputHtmlType = computed(() => {
|
|
if (formato.value === "email") return "email";
|
|
if (formato.value === "url") return "url";
|
|
return "text";
|
|
});
|
|
|
|
const inputMode = computed<string | undefined>(() => {
|
|
if (formato.value === "telefone") return "tel";
|
|
if (formato.value === "cpfCnpj" || formato.value === "cep") return "numeric";
|
|
return undefined;
|
|
});
|
|
|
|
function aplicarFormato(valor: string) {
|
|
switch (formato.value) {
|
|
case "telefone":
|
|
return formatTelefone(valor);
|
|
case "cpfCnpj":
|
|
return formatarCpfCnpj(valor);
|
|
case "cep":
|
|
return formatarCep(valor);
|
|
default:
|
|
return valor;
|
|
}
|
|
}
|
|
|
|
function onInput(e: Event) {
|
|
const target = e.target as HTMLInputElement;
|
|
const resultado = aplicarFormato(target.value);
|
|
|
|
// garante que o input mostre o valor formatado
|
|
target.value = resultado;
|
|
|
|
// regra do projeto: value sempre igual ao que aparece
|
|
localValue.value = resultado;
|
|
}
|
|
|
|
return { attrs, emit, localValue, inputHtmlType, inputMode, onInput };
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<style scoped></style>
|