refactor(tipos): centralizar tipagens em src/tipos

This commit is contained in:
Luiz Silva 2026-01-02 21:24:44 -03:00
parent eb4538f4ba
commit 7c274583ec
8 changed files with 138 additions and 99 deletions

10
.agent
View file

@ -120,6 +120,16 @@ Evitar comentários óbvios (“isso é um botão”).
- Padronizar nomes de tipos em português: - Padronizar nomes de tipos em português:
- `tipoOpcao`, `tipoTamanho`, `tipoEstado`, `tipoTema` - `tipoOpcao`, `tipoTamanho`, `tipoEstado`, `tipoTema`
### Centralização de tipos (padrão do repositório)
- Tipos compartilhados (uniões, enums, aliases) devem ficar em `src/tipos/`.
- Cada domínio pode ter seu arquivo:
- `src/tipos/botao.ts`
- `src/tipos/campo.ts`
- `src/tipos/indicador.ts`
- Re-export central em `src/tipos/index.ts`.
- Componentes importam tipagens de `src/tipos`.
--- ---
## Padrão defineComponent (obrigatório) ## Padrão defineComponent (obrigatório)

View file

@ -14,19 +14,7 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, PropType } from "vue"; import { defineComponent, PropType } from "vue";
import type { BotaoTamanho, BotaoVariante } from "../../tipos";
type BotaoVariant =
| "elevated"
| "flat"
| "outlined"
| "text"
| "tonal"
type BotaoSize =
| "x-small"
| "small"
| "default"
| "large"
export default defineComponent({ export default defineComponent({
name: "EliBotao", name: "EliBotao",
@ -40,12 +28,12 @@ export default defineComponent({
}, },
variant: { variant: {
type: String as PropType<BotaoVariant>, type: String as PropType<BotaoVariante>,
default: "elevated", default: "elevated",
}, },
size: { size: {
type: String as PropType<BotaoSize>, type: String as PropType<BotaoTamanho>,
default: "default", default: "default",
}, },

View file

@ -99,63 +99,20 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, ref, computed, PropType } from "vue"; import { defineComponent, ref, computed, PropType } from "vue";
import type {
CampoDensidade,
CampoOpcao,
CampoOpcaoBruta,
CampoTipo,
CampoValor,
CampoValorMultiplo,
CampoVariante,
} from "../../tipos";
import { formatarCpfCnpj } from "./utils/cpfCnpj"; import { formatarCpfCnpj } from "./utils/cpfCnpj";
import { formatTelefone } from "./utils/telefone"; import { formatTelefone } from "./utils/telefone";
import { formatarDecimal, formatarMoeda, somenteNumeros } from "./utils/numerico" import { formatarDecimal, formatarMoeda, somenteNumeros } from "./utils/numerico"
import { formatarCep } from "./utils/cep"; import { formatarCep } from "./utils/cep";
/**
* Tipos base do EliInput.
* Mantidos aqui para evitar exports internos não documentados.
*/
type ValorCampo = string | number | boolean | null;
type ValorCampoMultiplo = ValorCampo[];
type OpcaoCampo<TValor extends ValorCampo = ValorCampo> = {
label: string;
value: TValor;
disabled?: boolean;
};
type OpcaoBruta<TValor extends ValorCampo = ValorCampo> =
| TValor
| {
label?: string;
value: TValor;
disabled?: boolean;
};
type InputVariant =
| "outlined"
| "filled"
| "plain"
| "solo"
| "solo-filled"
| "solo-inverted"
| "underlined";
type Density = "default" | "comfortable" | "compact";
type TipoNumerico =
| "numericoInteiro"
| "numericoDecimal"
| "numericoMoeda";
type InputType =
| "text"
| "password"
| "email"
| "search"
| "url"
| "textarea"
| "radio"
| "checkbox"
| "telefone"
| "cpfCnpj"
| "cep"
| "select"
| TipoNumerico;
export default defineComponent({ export default defineComponent({
name: "EliInput", name: "EliInput",
inheritAttrs: false, inheritAttrs: false,
@ -166,10 +123,10 @@ export default defineComponent({
* O componente não converte tipos automaticamente: mantém o que receber. * O componente não converte tipos automaticamente: mantém o que receber.
*/ */
modelValue: { modelValue: {
type: [String, Number, Boolean, Array] as PropType<ValorCampo | ValorCampoMultiplo>, type: [String, Number, Boolean, Array] as PropType<CampoValor | CampoValorMultiplo>,
default: "", default: "",
}, },
type: { type: String as PropType<InputType>, default: "text" }, type: { type: String as PropType<CampoTipo>, default: "text" },
label: String, label: String,
placeholder: String, placeholder: String,
disabled: Boolean, disabled: Boolean,
@ -186,12 +143,12 @@ export default defineComponent({
* Aceita lista normalizada ({ label, value }) ou valores primitivos. * Aceita lista normalizada ({ label, value }) ou valores primitivos.
*/ */
options: { options: {
type: Array as PropType<Array<OpcaoBruta>>, type: Array as PropType<Array<CampoOpcaoBruta>>,
default: () => [], default: () => [],
}, },
clearable: Boolean, clearable: Boolean,
variant: { type: String as PropType<InputVariant>, default: "outlined" }, variant: { type: String as PropType<CampoVariante>, default: "outlined" },
density: { type: String as PropType<Density>, default: "comfortable" }, density: { type: String as PropType<CampoDensidade>, default: "comfortable" },
color: { type: String, default: "primary" }, color: { type: String, default: "primary" },
row: Boolean, row: Boolean,
showPasswordToggle: Boolean, showPasswordToggle: Boolean,
@ -207,7 +164,7 @@ export default defineComponent({
const value = computed({ const value = computed({
get: () => props.modelValue, get: () => props.modelValue,
set: (v: ValorCampo | ValorCampoMultiplo) => { set: (v: CampoValor | CampoValorMultiplo) => {
emit("update:modelValue", v); emit("update:modelValue", v);
emit("change", v); emit("change", v);
}, },
@ -287,11 +244,11 @@ export default defineComponent({
} }
// --- Helpers para select / radio / checkbox (aceita objetos ou primitivos) --- // --- Helpers para select / radio / checkbox (aceita objetos ou primitivos) ---
const computedItems = computed<Array<OpcaoCampo>>(() => { const computedItems = computed<Array<CampoOpcao>>(() => {
// Normaliza options para [{ label, value, disabled? }] // Normaliza options para [{ label, value, disabled? }]
return (props.options || []).map((o) => { return (props.options || []).map((o) => {
if (o && typeof o === "object" && "value" in o) { if (o && typeof o === "object" && "value" in o) {
const valor = o.value as ValorCampo; const valor = o.value as CampoValor;
return { return {
label: o.label ?? String(valor), label: o.label ?? String(valor),
value: valor, value: valor,
@ -299,7 +256,7 @@ export default defineComponent({
}; };
} }
const valor = o as ValorCampo; const valor = o as CampoValor;
return { label: String(valor), value: valor }; return { label: String(valor), value: valor };
}); });
}); });

View file

@ -20,24 +20,14 @@
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, PropType } from "vue"; import { computed, defineComponent, PropType } from "vue";
import type {
CssLength,
IndicadorLocalizacao,
IndicadorOffset,
IndicadorPresetRaio,
} from "../../tipos";
type LocalBadge = const RADIUS_MAP: Record<IndicadorPresetRaio, string> = {
| "top right"
| "right center"
| "bottom right"
| "top center"
| "bottom center"
| "top left"
| "left center"
| "bottom left";
type Offset = "-20" | "-15" | "-10" | "-5" | "0" | "20" | "15" | "10" | "5";
type BadgeRadiusPreset = "suave" | "pill";
type CssLength = `${number}px` | `${number}rem` | `${number}%` | "0";
const RADIUS_MAP: Record<BadgeRadiusPreset, string> = {
suave: "4px", suave: "4px",
pill: "10px", pill: "10px",
}; };
@ -54,17 +44,17 @@ export default defineComponent({
}, },
location: { location: {
type: String as PropType<LocalBadge>, type: String as PropType<IndicadorLocalizacao>,
default: "top right", default: "top right",
}, },
offsetX: { offsetX: {
type: String as PropType<Offset>, type: String as PropType<IndicadorOffset>,
default: "0", default: "0",
}, },
offsetY: { offsetY: {
type: String as PropType<Offset>, type: String as PropType<IndicadorOffset>,
default: "0", default: "0",
}, },
@ -85,7 +75,7 @@ export default defineComponent({
/** 🔥 NOVO: controla só o radius */ /** 🔥 NOVO: controla só o radius */
radius: { radius: {
type: String as PropType<BadgeRadiusPreset | CssLength>, type: String as PropType<IndicadorPresetRaio | CssLength>,
default: "suave", default: "suave",
}, },
}, },
@ -95,7 +85,7 @@ export default defineComponent({
const resolvedRadius = computed(() => { const resolvedRadius = computed(() => {
// preset conhecido // preset conhecido
if (props.radius in RADIUS_MAP) { if (props.radius in RADIUS_MAP) {
return RADIUS_MAP[props.radius as BadgeRadiusPreset]; return RADIUS_MAP[props.radius as IndicadorPresetRaio];
} }
// valor custom (ex: "8px", "50%", "0") // valor custom (ex: "8px", "50%", "0")

9
src/tipos/botao.ts Normal file
View file

@ -0,0 +1,9 @@
/**
* Tipos do componente EliBotao.
* Mantidos separados do componente para facilitar reuso e padronização.
*/
export type BotaoVariante = "elevated" | "flat" | "outlined" | "text" | "tonal";
export type BotaoTamanho = "x-small" | "small" | "default" | "large";

52
src/tipos/campo.ts Normal file
View file

@ -0,0 +1,52 @@
/**
* Tipos do componente EliInput (campo).
*/
export type CampoValor = string | number | boolean | null;
export type CampoValorMultiplo = CampoValor[];
export type CampoOpcao<TValor extends CampoValor = CampoValor> = {
label: string;
value: TValor;
disabled?: boolean;
};
export type CampoOpcaoBruta<TValor extends CampoValor = CampoValor> =
| TValor
| {
label?: string;
value: TValor;
disabled?: boolean;
};
export type CampoVariante =
| "outlined"
| "filled"
| "plain"
| "solo"
| "solo-filled"
| "solo-inverted"
| "underlined";
export type CampoDensidade = "default" | "comfortable" | "compact";
export type CampoTipoNumerico =
| "numericoInteiro"
| "numericoDecimal"
| "numericoMoeda";
export type CampoTipo =
| "text"
| "password"
| "email"
| "search"
| "url"
| "textarea"
| "radio"
| "checkbox"
| "telefone"
| "cpfCnpj"
| "cep"
| "select"
| CampoTipoNumerico;

4
src/tipos/index.ts Normal file
View file

@ -0,0 +1,4 @@
export * from "./botao";
export * from "./campo";
export * from "./indicador";

29
src/tipos/indicador.ts Normal file
View file

@ -0,0 +1,29 @@
/**
* Tipos do componente EliBadge (indicador).
*/
export type IndicadorLocalizacao =
| "top right"
| "right center"
| "bottom right"
| "top center"
| "bottom center"
| "top left"
| "left center"
| "bottom left";
export type IndicadorOffset =
| "-20"
| "-15"
| "-10"
| "-5"
| "0"
| "20"
| "15"
| "10"
| "5";
export type IndicadorPresetRaio = "suave" | "pill";
export type CssLength = `${number}px` | `${number}rem` | `${number}%` | "0";