This commit is contained in:
Luiz Silva 2026-02-15 15:17:08 -03:00
parent 8a5596e860
commit 57325f6744
100 changed files with 16153 additions and 4623 deletions

25
IA.md
View file

@ -370,6 +370,31 @@ filtroAvancado: [
] ]
``` ```
### Botões de Ação da Tabela (`acoesTabela`)
Além das ações por linha, você pode adicionar botões de ação globais à tabela.
```ts
acoesTabela: [
{
rotulo: "Novo Usuário",
icone: Plus,
posicao: "superior", // Ao lado da busca
acao: () => console.log("Criar novo")
},
{
rotulo: "Exportar Relatório",
icone: Download,
posicao: "inferior", // No rodapé, alinhado à esquerda
acao: () => console.log("Exportar")
}
]
```
- **`posicao: 'superior'`**: Exibidos à direita da caixa de busca.
- **`posicao: 'inferior'`**: Exibidos no rodapé da tabela, **alinhados à esquerda** (enquanto a paginação fica à direita).
- **Estilo**: Por padrão, botões inferiores possuem fundo branco, **borda verde** (`outline`) e texto verde. Caso uma `cor` personalizada seja informada, ela será usada para a borda e texto.
### Processando a Consulta ### Processando a Consulta
A função `consulta` recebe um objeto com todos os parâmetros necessários para buscar os dados corretamente. A função `consulta` recebe um objeto com todos os parâmetros necessários para buscar os dados corretamente.

17
biome.json Executable file
View file

@ -0,0 +1,17 @@
{
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
"extends": ["./node_modules/p-comuns/Documentos/biome.json"],
"files": {
"includes": ["src/**/*.{js,ts,jsx,tsx,vue}"]
},
"linter": {
"rules": {
"suspicious": {
"noExplicitAny": "error"
},
"style": {
"noNonNullAssertion": "error"
}
}
}
}

15086
dist/eli-vue.es.js vendored

File diff suppressed because one or more lines are too long

73
dist/eli-vue.umd.js vendored

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,4 @@
import { PropType } from "vue"; import { type PropType } from "vue";
import type { CampoDensidade, CampoVariante } from "../../tipos"; import type { CampoDensidade, CampoVariante } from "../../tipos";
import type { PadroesEntradas } from "./tiposEntradas"; import type { PadroesEntradas } from "./tiposEntradas";
type EntradaDataHora = PadroesEntradas["dataHora"]; type EntradaDataHora = PadroesEntradas["dataHora"];
@ -17,6 +17,8 @@ type PropsAntigas = {
min?: string; min?: string;
max?: string; max?: string;
}; };
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
value: { value: {
type: PropType<EntradaDataHora["value"]>; type: PropType<EntradaDataHora["value"]>;
@ -186,15 +188,15 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
default: undefined; default: undefined;
}; };
}>> & Readonly<{ }>> & Readonly<{
"onUpdate:value"?: ((_v: string | null) => any) | undefined;
onInput?: ((_v: string | null) => any) | undefined; onInput?: ((_v: string | null) => any) | undefined;
"onUpdate:value"?: ((_v: string | null) => any) | undefined;
onChange?: ((_v: string | null) => any) | undefined; onChange?: ((_v: string | null) => any) | undefined;
onFocus?: (() => any) | undefined;
onBlur?: (() => any) | undefined;
"onUpdate:modelValue"?: ((_v: string | null) => any) | undefined; "onUpdate:modelValue"?: ((_v: string | null) => any) | undefined;
onAlterar?: ((_v: string | null) => any) | undefined; onAlterar?: ((_v: string | null) => any) | undefined;
onFoco?: (() => any) | undefined; onFoco?: (() => any) | undefined;
onDesfoco?: (() => any) | undefined; onDesfoco?: (() => any) | undefined;
onFocus?: (() => any) | undefined;
onBlur?: (() => any) | undefined;
}>, { }>, {
modo: "data" | "dataHora" | undefined; modo: "data" | "dataHora" | undefined;
limpavel: boolean; limpavel: boolean;
@ -222,10 +224,8 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
variante?: import("../../tipos").CampoVariante; variante?: import("../../tipos").CampoVariante;
}; };
value: string | null | undefined; value: string | null | undefined;
placeholder: string;
modelValue: string | null; modelValue: string | null;
rotulo: string; rotulo: string;
placeholder: string;
desabilitado: boolean; desabilitado: boolean;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: typeof __VLS_export;
export default _default;

View file

@ -1,6 +1,8 @@
import { PropType } from "vue"; import { type PropType } from "vue";
import type { PadroesEntradas } from "./tiposEntradas"; import type { PadroesEntradas } from "./tiposEntradas";
type EntradaNumero = PadroesEntradas["numero"]; type EntradaNumero = PadroesEntradas["numero"];
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
/** Interface padrão (EliEntrada): value + opcoes. */ /** Interface padrão (EliEntrada): value + opcoes. */
value: { value: {
@ -15,7 +17,7 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
attrs: { attrs: {
[x: string]: unknown; [x: string]: unknown;
}; };
emit: ((event: "update:value", _v: number | null | undefined) => void) & ((event: "input", _v: number | null | undefined) => void) & ((event: "change", _v: number | null | undefined) => void) & ((event: "focus") => void) & ((event: "blur") => void); emit: ((event: "input", _v: number | null | undefined) => void) & ((event: "update:value", _v: number | null | undefined) => void) & ((event: "change", _v: number | null | undefined) => void) & ((event: "focus") => void) & ((event: "blur") => void);
displayValue: import("vue").Ref<string, string>; displayValue: import("vue").Ref<string, string>;
isInteiro: import("vue").ComputedRef<boolean>; isInteiro: import("vue").ComputedRef<boolean>;
onUpdateModelValue: (texto: string) => void; onUpdateModelValue: (texto: string) => void;
@ -37,13 +39,11 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
required: true; required: true;
}; };
}>> & Readonly<{ }>> & Readonly<{
"onUpdate:value"?: ((_v: number | null | undefined) => any) | undefined;
onInput?: ((_v: number | null | undefined) => any) | undefined; onInput?: ((_v: number | null | undefined) => any) | undefined;
"onUpdate:value"?: ((_v: number | null | undefined) => any) | undefined;
onChange?: ((_v: number | null | undefined) => any) | undefined; onChange?: ((_v: number | null | undefined) => any) | undefined;
onFocus?: (() => any) | undefined; onFocus?: (() => any) | undefined;
onBlur?: (() => any) | undefined; onBlur?: (() => any) | undefined;
}>, { }>, {
value: number | null | undefined; value: number | null | undefined;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: typeof __VLS_export;
export default _default;

View file

@ -1,6 +1,8 @@
import { PropType } from "vue"; import { type PropType } from "vue";
import type { PadroesEntradas } from "./tiposEntradas"; import type { PadroesEntradas } from "./tiposEntradas";
type EntradaParagrafo = PadroesEntradas["paragrafo"]; type EntradaParagrafo = PadroesEntradas["paragrafo"];
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
value: { value: {
type: PropType<EntradaParagrafo["value"]>; type: PropType<EntradaParagrafo["value"]>;
@ -14,22 +16,8 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
attrs: { attrs: {
[x: string]: unknown; [x: string]: unknown;
}; };
emit: ((event: "update:value", _v: string | null | undefined) => void) & ((event: "input", _v: string | null | undefined) => void) & ((event: "change", _v: string | null | undefined) => void) & ((event: "focus") => void) & ((event: "blur") => void); emit: ((event: "input", _v: string | null | undefined) => void) & ((event: "update:value", _v: string | null | undefined) => void) & ((event: "change", _v: string | null | undefined) => void) & ((event: "focus") => void) & ((event: "blur") => void);
localValue: import("vue").WritableComputedRef<string | null | undefined, string | null | undefined>; localValue: import("vue").WritableComputedRef<string | null | undefined, string | null | undefined>;
opcoes: {
rotulo: string;
placeholder?: string;
} & {
linhas?: number;
limiteCaracteres?: number;
limpavel?: boolean;
erro?: boolean;
mensagensErro?: string | string[];
dica?: string;
dicaPersistente?: boolean;
densidade?: import("../..").CampoDensidade;
variante?: import("../..").CampoVariante;
};
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, { }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
"update:value": (_v: EntradaParagrafo["value"]) => true; "update:value": (_v: EntradaParagrafo["value"]) => true;
input: (_v: EntradaParagrafo["value"]) => true; input: (_v: EntradaParagrafo["value"]) => true;
@ -46,8 +34,8 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
required: true; required: true;
}; };
}>> & Readonly<{ }>> & Readonly<{
"onUpdate:value"?: ((_v: string | null | undefined) => any) | undefined;
onInput?: ((_v: string | null | undefined) => any) | undefined; onInput?: ((_v: string | null | undefined) => any) | undefined;
"onUpdate:value"?: ((_v: string | null | undefined) => any) | undefined;
onChange?: ((_v: string | null | undefined) => any) | undefined; onChange?: ((_v: string | null | undefined) => any) | undefined;
onFocus?: (() => any) | undefined; onFocus?: (() => any) | undefined;
onBlur?: (() => any) | undefined; onBlur?: (() => any) | undefined;
@ -67,7 +55,6 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
hideSpinButtons: boolean; hideSpinButtons: boolean;
persistentHint: boolean; persistentHint: boolean;
messages: string | readonly string[]; messages: string | readonly string[];
direction: "horizontal" | "vertical";
clearable: boolean; clearable: boolean;
clearIcon: import("vuetify/lib/composables/icons.mjs").IconValue; clearIcon: import("vuetify/lib/composables/icons.mjs").IconValue;
active: boolean; active: boolean;
@ -455,7 +442,6 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
hideSpinButtons: boolean; hideSpinButtons: boolean;
persistentHint: boolean; persistentHint: boolean;
messages: string | readonly string[]; messages: string | readonly string[];
direction: "horizontal" | "vertical";
clearable: boolean; clearable: boolean;
clearIcon: import("vuetify/lib/composables/icons.mjs").IconValue; clearIcon: import("vuetify/lib/composables/icons.mjs").IconValue;
active: boolean; active: boolean;
@ -530,7 +516,6 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
hideSpinButtons: boolean; hideSpinButtons: boolean;
persistentHint: boolean; persistentHint: boolean;
messages: string | readonly string[]; messages: string | readonly string[];
direction: "horizontal" | "vertical";
clearable: boolean; clearable: boolean;
clearIcon: import("vuetify/lib/composables/icons.mjs").IconValue; clearIcon: import("vuetify/lib/composables/icons.mjs").IconValue;
active: boolean; active: boolean;
@ -912,7 +897,6 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
hideSpinButtons: boolean; hideSpinButtons: boolean;
persistentHint: boolean; persistentHint: boolean;
messages: string | readonly string[]; messages: string | readonly string[];
direction: "horizontal" | "vertical";
clearable: boolean; clearable: boolean;
clearIcon: import("vuetify/lib/composables/icons.mjs").IconValue; clearIcon: import("vuetify/lib/composables/icons.mjs").IconValue;
active: boolean; active: boolean;
@ -948,7 +932,6 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
hideSpinButtons: boolean; hideSpinButtons: boolean;
persistentHint: boolean; persistentHint: boolean;
messages: string | readonly string[]; messages: string | readonly string[];
direction: "horizontal" | "vertical";
clearable: boolean; clearable: boolean;
clearIcon: import("vuetify/lib/composables/icons.mjs").IconValue; clearIcon: import("vuetify/lib/composables/icons.mjs").IconValue;
active: boolean; active: boolean;
@ -1300,7 +1283,7 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
hint?: string | undefined; hint?: string | undefined;
"onClick:prepend"?: ((args_0: MouseEvent) => void) | undefined; "onClick:prepend"?: ((args_0: MouseEvent) => void) | undefined;
"onClick:append"?: ((args_0: MouseEvent) => void) | undefined; "onClick:append"?: ((args_0: MouseEvent) => void) | undefined;
}, "disabled" | "style" | "density" | "error" | "direction" | "reset" | "isValid" | "resetValidation" | "validate" | "centerAffix" | "errorMessages" | "focused" | "glow" | "hideSpinButtons" | "maxErrors" | "messages" | "persistentHint" | "readonly" | "rules"> & import("vue").ShallowUnwrapRef<{ }, "disabled" | "error" | "style" | "isValid" | "reset" | "resetValidation" | "validate" | "centerAffix" | "density" | "direction" | "errorMessages" | "focused" | "glow" | "hideSpinButtons" | "maxErrors" | "messages" | "persistentHint" | "readonly" | "rules"> & import("vue").ShallowUnwrapRef<{
reset: () => Promise<void>; reset: () => Promise<void>;
resetValidation: () => Promise<void>; resetValidation: () => Promise<void>;
validate: (silent?: boolean) => Promise<string[]>; validate: (silent?: boolean) => Promise<string[]>;
@ -1309,7 +1292,7 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
}> & import("vue").ComponentCustomProperties & import("vuetify/lib/util/defineComponent.mjs").GenericProps<{ }> & import("vue").ComponentCustomProperties & import("vuetify/lib/util/defineComponent.mjs").GenericProps<{
modelValue?: unknown; modelValue?: unknown;
"onUpdate:modelValue"?: ((value: unknown) => void) | undefined; "onUpdate:modelValue"?: ((value: unknown) => void) | undefined;
}, import("vuetify/lib/components/VInput/VInput.mjs").VInputSlots>, "name" | "color" | "disabled" | keyof import("vue").VNodeProps | "class" | "style" | "label" | "density" | "error" | "id" | "width" | "direction" | "theme" | "appendIcon" | "baseColor" | "prependIcon" | "modelValue" | "$children" | "v-slots" | "v-slot:append" | "v-slot:default" | "v-slot:prepend" | "onUpdate:modelValue" | "centerAffix" | "errorMessages" | "focused" | "glow" | "hideSpinButtons" | "maxErrors" | "messages" | "persistentHint" | "readonly" | "rules" | "onUpdate:focused" | "validateOn" | "validationValue" | "maxWidth" | "minWidth" | "iconColor" | "hideDetails" | "hint" | "onClick:prepend" | "onClick:append" | "v-slot:details" | "v-slot:message">, `$${any}`> & { }, import("vuetify/lib/components/VInput/VInput.mjs").VInputSlots>, "name" | "color" | "disabled" | "error" | "label" | "style" | "class" | keyof import("vue").VNodeProps | "modelValue" | "onUpdate:modelValue" | "centerAffix" | "density" | "direction" | "errorMessages" | "focused" | "glow" | "hideSpinButtons" | "maxErrors" | "messages" | "persistentHint" | "readonly" | "rules" | "theme" | "onUpdate:focused" | "validateOn" | "validationValue" | "maxWidth" | "minWidth" | "width" | "id" | "appendIcon" | "baseColor" | "iconColor" | "prependIcon" | "hideDetails" | "hint" | "onClick:prepend" | "onClick:append" | "$children" | "v-slot:append" | "v-slot:default" | "v-slot:details" | "v-slot:message" | "v-slot:prepend" | "v-slots">, `$${any}`> & {
_allExposed: { _allExposed: {
reset: () => Promise<void>; reset: () => Promise<void>;
resetValidation: () => Promise<void>; resetValidation: () => Promise<void>;
@ -1336,7 +1319,6 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
hideSpinButtons: boolean; hideSpinButtons: boolean;
persistentHint: boolean; persistentHint: boolean;
messages: string | readonly string[]; messages: string | readonly string[];
direction: "horizontal" | "vertical";
clearable: boolean; clearable: boolean;
clearIcon: import("vuetify/lib/composables/icons.mjs").IconValue; clearIcon: import("vuetify/lib/composables/icons.mjs").IconValue;
active: boolean; active: boolean;
@ -1446,11 +1428,6 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
type: PropType<string | readonly string[]>; type: PropType<string | readonly string[]>;
default: () => never[]; default: () => never[];
}; };
direction: {
type: PropType<"horizontal" | "vertical">;
default: string;
validator: (v: any) => boolean;
};
"onClick:prepend": PropType<(args_0: MouseEvent) => void>; "onClick:prepend": PropType<(args_0: MouseEvent) => void>;
"onClick:append": PropType<(args_0: MouseEvent) => void>; "onClick:append": PropType<(args_0: MouseEvent) => void>;
appendInnerIcon: PropType<import("vuetify/lib/composables/icons.mjs").IconValue>; appendInnerIcon: PropType<import("vuetify/lib/composables/icons.mjs").IconValue>;
@ -1568,11 +1545,6 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
type: PropType<string | readonly string[]>; type: PropType<string | readonly string[]>;
default: () => never[]; default: () => never[];
}; };
direction: {
type: PropType<"horizontal" | "vertical">;
default: string;
validator: (v: any) => boolean;
};
"onClick:prepend": PropType<(args_0: MouseEvent) => void>; "onClick:prepend": PropType<(args_0: MouseEvent) => void>;
"onClick:append": PropType<(args_0: MouseEvent) => void>; "onClick:append": PropType<(args_0: MouseEvent) => void>;
appendInnerIcon: PropType<import("vuetify/lib/composables/icons.mjs").IconValue>; appendInnerIcon: PropType<import("vuetify/lib/composables/icons.mjs").IconValue>;
@ -1638,5 +1610,3 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
modelModifiers: PropType<Record<string, boolean>>; modelModifiers: PropType<Record<string, boolean>>;
}>>; }>>;
}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: typeof __VLS_export;
export default _default;

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,8 @@
import { PropType } from "vue"; import { type PropType } from "vue";
import type { PadroesEntradas } from "./tiposEntradas"; import type { PadroesEntradas } from "./tiposEntradas";
type EntradaTexto = PadroesEntradas["texto"]; type EntradaTexto = PadroesEntradas["texto"];
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
/** Interface padrão (EliEntrada): value + opcoes. */ /** Interface padrão (EliEntrada): value + opcoes. */
value: { value: {
@ -15,7 +17,7 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
attrs: { attrs: {
[x: string]: unknown; [x: string]: unknown;
}; };
emit: ((event: "update:value", _v: string | null | undefined) => void) & ((event: "input", _v: string | null | undefined) => void) & ((event: "change", _v: string | null | undefined) => void) & ((event: "focus") => void) & ((event: "blur") => void); emit: ((event: "input", _v: string | null | undefined) => void) & ((event: "update:value", _v: string | null | undefined) => void) & ((event: "change", _v: string | null | undefined) => void) & ((event: "focus") => void) & ((event: "blur") => void);
localValue: import("vue").WritableComputedRef<string | null | undefined, string | null | undefined>; localValue: import("vue").WritableComputedRef<string | null | undefined, string | null | undefined>;
inputHtmlType: import("vue").ComputedRef<"text" | "email" | "url">; inputHtmlType: import("vue").ComputedRef<"text" | "email" | "url">;
inputMode: import("vue").ComputedRef<string | undefined>; inputMode: import("vue").ComputedRef<string | undefined>;
@ -38,13 +40,11 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
required: true; required: true;
}; };
}>> & Readonly<{ }>> & Readonly<{
"onUpdate:value"?: ((_v: string | null | undefined) => any) | undefined;
onInput?: ((_v: string | null | undefined) => any) | undefined; onInput?: ((_v: string | null | undefined) => any) | undefined;
"onUpdate:value"?: ((_v: string | null | undefined) => any) | undefined;
onChange?: ((_v: string | null | undefined) => any) | undefined; onChange?: ((_v: string | null | undefined) => any) | undefined;
onFocus?: (() => any) | undefined; onFocus?: (() => any) | undefined;
onBlur?: (() => any) | undefined; onBlur?: (() => any) | undefined;
}>, { }>, {
value: string | null | undefined; value: string | null | undefined;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: typeof __VLS_export;
export default _default;

View file

@ -1,7 +1,7 @@
import EliEntradaTexto from "./EliEntradaTexto.vue";
import EliEntradaNumero from "./EliEntradaNumero.vue";
import EliEntradaDataHora from "./EliEntradaDataHora.vue"; import EliEntradaDataHora from "./EliEntradaDataHora.vue";
import EliEntradaNumero from "./EliEntradaNumero.vue";
import EliEntradaParagrafo from "./EliEntradaParagrafo.vue"; import EliEntradaParagrafo from "./EliEntradaParagrafo.vue";
import EliEntradaSelecao from "./EliEntradaSelecao.vue"; import EliEntradaSelecao from "./EliEntradaSelecao.vue";
export { EliEntradaTexto, EliEntradaNumero, EliEntradaDataHora, EliEntradaParagrafo, EliEntradaSelecao }; import EliEntradaTexto from "./EliEntradaTexto.vue";
export { EliEntradaTexto, EliEntradaNumero, EliEntradaDataHora, EliEntradaParagrafo, EliEntradaSelecao, };
export type { PadroesEntradas, TipoEntrada } from "./tiposEntradas"; export type { PadroesEntradas, TipoEntrada } from "./tiposEntradas";

File diff suppressed because one or more lines are too long

View file

@ -137,7 +137,10 @@ export type PadroesEntradas = {
* Ex.: "texto" | "numero" * Ex.: "texto" | "numero"
*/ */
export type TipoEntrada = keyof PadroesEntradas; export type TipoEntrada = keyof PadroesEntradas;
export type PadraoComponenteEntrada<T extends TipoEntrada> = readonly [T, PadroesEntradas[T]['opcoes']]; export type PadraoComponenteEntrada<T extends TipoEntrada> = readonly [
T,
PadroesEntradas[T]["opcoes"]
];
export type ComponenteEntrada = { export type ComponenteEntrada = {
[K in TipoEntrada]: PadraoComponenteEntrada<K>; [K in TipoEntrada]: PadraoComponenteEntrada<K>;
}[TipoEntrada]; }[TipoEntrada];

View file

@ -1,13 +1,10 @@
/**
* EliTabela
* Componente de tabela consultável com busca, paginação, ordenação e ações por linha.
*/
/** Dependências do Vue (Composition API) */ /** Dependências do Vue (Composition API) */
import { PropType } from "vue"; import { type PropType } from "vue";
import type { tipoEliColuna } from "./types-eli-tabela";
/** Tipos da configuração/contrato da tabela */
import type { tipoEliTabelaConsulta } from "./types-eli-tabela";
import { type EliTabelaColunasConfig } from "./colunasStorage"; import { type EliTabelaColunasConfig } from "./colunasStorage";
/** Tipos da configuração/contrato da tabela */
import type { parametrosConsulta, tipoEliColuna, tipoEliTabelaConsulta } from "./types-eli-tabela";
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
/** Configuração principal da tabela (colunas, consulta e ações) */ /** Configuração principal da tabela (colunas, consulta e ações) */
tabela: { tabela: {
@ -24,7 +21,7 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
filtrosAvancadosAtivos: import("vue").ComputedRef<{ filtrosAvancadosAtivos: import("vue").ComputedRef<{
coluna: string; coluna: string;
valor: any; valor: any;
operador: "in" | "=" | "!=" | ">" | ">=" | "<" | "<=" | "like" | "isNull"; operador: "=" | "!=" | ">" | ">=" | "<" | "<=" | "like" | "in" | "isNull";
ou?: boolean | undefined; ou?: boolean | undefined;
}[]>; }[]>;
quantidadeFiltrada: import("vue").ComputedRef<number>; quantidadeFiltrada: import("vue").ComputedRef<number>;
@ -38,15 +35,27 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
registrosPorConsulta: import("vue").ComputedRef<number>; registrosPorConsulta: import("vue").ComputedRef<number>;
exibirBusca: import("vue").ComputedRef<boolean>; exibirBusca: import("vue").ComputedRef<boolean>;
exibirFiltroAvancado: import("vue").ComputedRef<boolean>; exibirFiltroAvancado: import("vue").ComputedRef<boolean>;
acoesCabecalho: import("vue").ComputedRef<{ acoesSuperiores: import("vue").ComputedRef<{
posicao: "superior" | "inferior";
icone?: import("lucide-vue-next").LucideIcon; icone?: import("lucide-vue-next").LucideIcon;
cor?: string; cor?: string;
rotulo: string; rotulo: string;
acao: () => void; acao: (parametrosConsulta?: parametrosConsulta<any> | undefined) => void;
atualizarConsulta?: () => Promise<void>; atualizarConsulta?: () => Promise<void>;
editarLista?: ((lista: any[]) => Promise<any[]>) | undefined; editarLista?: ((lista: any[]) => Promise<any[]>) | undefined;
}[]>; }[]>;
temAcoesCabecalho: import("vue").ComputedRef<boolean>; temAcoesSuperiores: import("vue").ComputedRef<boolean>;
acoesInferiores: import("vue").ComputedRef<{
posicao: "superior" | "inferior";
icone?: import("lucide-vue-next").LucideIcon;
cor?: string;
rotulo: string;
acao: (parametrosConsulta?: parametrosConsulta<any> | undefined) => void;
atualizarConsulta?: () => Promise<void>;
editarLista?: ((lista: any[]) => Promise<any[]>) | undefined;
}[]>;
temAcoesInferiores: import("vue").ComputedRef<boolean>;
parametrosConsultaAtuais: import("vue").ComputedRef<parametrosConsulta<any>>;
temAcoes: import("vue").ComputedRef<boolean>; temAcoes: import("vue").ComputedRef<boolean>;
totalColunas: import("vue").ComputedRef<number>; totalColunas: import("vue").ComputedRef<number>;
colunasEfetivas: import("vue").ComputedRef<any[]>; colunasEfetivas: import("vue").ComputedRef<any[]>;
@ -140,6 +149,10 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
type: StringConstructor; type: StringConstructor;
required: true; required: true;
}; };
parametrosConsulta: {
type: PropType<any>;
required: false;
};
acoesCabecalho: { acoesCabecalho: {
type: PropType<Array<{ type: PropType<Array<{
icone icone
@ -147,17 +160,23 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
* EliTabela * EliTabela
* Componente de tabela consultável com busca, paginação, ordenação e ações por linha. * Componente de tabela consultável com busca, paginação, ordenação e ações por linha.
*/ */
/** Dependências do Vue (Composition API) */ /** Enum de códigos de resposta utilizado na consulta */
?: any; ?: any;
cor cor
/** /**
* EliTabela * EliTabela
* Componente de tabela consultável com busca, paginação, ordenação e ações por linha. * Componente de tabela consultável com busca, paginação, ordenação e ações por linha.
*/ */
/** Dependências do Vue (Composition API) */ /** Enum de códigos de resposta utilizado na consulta */
?: string; ?: string;
rotulo: string; rotulo: string;
acao: () => void; acao: (params
/**
* EliTabela
* Componente de tabela consultável com busca, paginação, ordenação e ações por linha.
*/
/** Enum de códigos de resposta utilizado na consulta */
?: any) => void;
}>>; }>>;
required: true; required: true;
}; };
@ -189,6 +208,10 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
type: StringConstructor; type: StringConstructor;
required: true; required: true;
}; };
parametrosConsulta: {
type: PropType<any>;
required: false;
};
acoesCabecalho: { acoesCabecalho: {
type: PropType<Array<{ type: PropType<Array<{
icone icone
@ -196,23 +219,29 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
* EliTabela * EliTabela
* Componente de tabela consultável com busca, paginação, ordenação e ações por linha. * Componente de tabela consultável com busca, paginação, ordenação e ações por linha.
*/ */
/** Dependências do Vue (Composition API) */ /** Enum de códigos de resposta utilizado na consulta */
?: any; ?: any;
cor cor
/** /**
* EliTabela * EliTabela
* Componente de tabela consultável com busca, paginação, ordenação e ações por linha. * Componente de tabela consultável com busca, paginação, ordenação e ações por linha.
*/ */
/** Dependências do Vue (Composition API) */ /** Enum de códigos de resposta utilizado na consulta */
?: string; ?: string;
rotulo: string; rotulo: string;
acao: () => void; acao: (params
/**
* EliTabela
* Componente de tabela consultável com busca, paginação, ordenação e ações por linha.
*/
/** Enum de códigos de resposta utilizado na consulta */
?: any) => void;
}>>; }>>;
required: true; required: true;
}; };
}>> & Readonly<{ }>> & Readonly<{
onBuscar?: ((valor: string) => any) | undefined;
onColunas?: (() => any) | undefined; onColunas?: (() => any) | undefined;
onBuscar?: ((valor: string) => any) | undefined;
onFiltroAvancado?: (() => any) | undefined; onFiltroAvancado?: (() => any) | undefined;
}>, { }>, {
exibirBotaoColunas: boolean; exibirBotaoColunas: boolean;
@ -474,21 +503,21 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
* EliTabela * EliTabela
* Componente de tabela consultável com busca, paginação, ordenação e ações por linha. * Componente de tabela consultável com busca, paginação, ordenação e ações por linha.
*/ */
/** Dependências do Vue (Composition API) */ /** Enum de códigos de resposta utilizado na consulta */
?: string; ?: string;
icone icone
/** /**
* EliTabela * EliTabela
* Componente de tabela consultável com busca, paginação, ordenação e ações por linha. * Componente de tabela consultável com busca, paginação, ordenação e ações por linha.
*/ */
/** Dependências do Vue (Composition API) */ /** Enum de códigos de resposta utilizado na consulta */
?: import("lucide-vue-next").LucideIcon; ?: import("lucide-vue-next").LucideIcon;
acao acao
/** /**
* EliTabela * EliTabela
* Componente de tabela consultável com busca, paginação, ordenação e ações por linha. * Componente de tabela consultável com busca, paginação, ordenação e ações por linha.
*/ */
/** Dependências do Vue (Composition API) */ /** Enum de códigos de resposta utilizado na consulta */
?: () => void; ?: () => void;
}[]; }[];
} | { } | {
@ -547,21 +576,21 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
* EliTabela * EliTabela
* Componente de tabela consultável com busca, paginação, ordenação e ações por linha. * Componente de tabela consultável com busca, paginação, ordenação e ações por linha.
*/ */
/** Dependências do Vue (Composition API) */ /** Enum de códigos de resposta utilizado na consulta */
?: string; ?: string;
icone icone
/** /**
* EliTabela * EliTabela
* Componente de tabela consultável com busca, paginação, ordenação e ações por linha. * Componente de tabela consultável com busca, paginação, ordenação e ações por linha.
*/ */
/** Dependências do Vue (Composition API) */ /** Enum de códigos de resposta utilizado na consulta */
?: import("lucide-vue-next").LucideIcon; ?: import("lucide-vue-next").LucideIcon;
acao acao
/** /**
* EliTabela * EliTabela
* Componente de tabela consultável com busca, paginação, ordenação e ações por linha. * Componente de tabela consultável com busca, paginação, ordenação e ações por linha.
*/ */
/** Dependências do Vue (Composition API) */ /** Enum de códigos de resposta utilizado na consulta */
?: () => void; ?: () => void;
}[]; }[];
} | { } | {
@ -658,6 +687,38 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
type: NumberConstructor; type: NumberConstructor;
required: false; required: false;
}; };
acoes: {
type: PropType<Array<{
icone
/**
* EliTabela
* Componente de tabela consultável com busca, paginação, ordenação e ações por linha.
*/
/** Enum de códigos de resposta utilizado na consulta */
?: any;
cor
/**
* EliTabela
* Componente de tabela consultável com busca, paginação, ordenação e ações por linha.
*/
/** Enum de códigos de resposta utilizado na consulta */
?: string;
rotulo: string;
acao: (params
/**
* EliTabela
* Componente de tabela consultável com busca, paginação, ordenação e ações por linha.
*/
/** Enum de códigos de resposta utilizado na consulta */
?: any) => void;
}>>;
required: false;
default: () => never[];
};
parametrosConsulta: {
type: PropType<any>;
required: false;
};
}>, { }>, {
botoes: import("vue").ComputedRef<{ botoes: import("vue").ComputedRef<{
label: string; label: string;
@ -685,9 +746,54 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
type: NumberConstructor; type: NumberConstructor;
required: false; required: false;
}; };
acoes: {
type: PropType<Array<{
icone
/**
* EliTabela
* Componente de tabela consultável com busca, paginação, ordenação e ações por linha.
*/
/** Enum de códigos de resposta utilizado na consulta */
?: any;
cor
/**
* EliTabela
* Componente de tabela consultável com busca, paginação, ordenação e ações por linha.
*/
/** Enum de códigos de resposta utilizado na consulta */
?: string;
rotulo: string;
acao: (params
/**
* EliTabela
* Componente de tabela consultável com busca, paginação, ordenação e ações por linha.
*/
/** Enum de códigos de resposta utilizado na consulta */
?: any) => void;
}>>;
required: false;
default: () => never[];
};
parametrosConsulta: {
type: PropType<any>;
required: false;
};
}>> & Readonly<{ }>> & Readonly<{
onAlterar?: ((pagina: number) => any) | undefined; onAlterar?: ((pagina: number) => any) | undefined;
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }>, {
acoes: {
icone?: any;
cor?: string;
rotulo: string;
acao: (params
/**
* EliTabela
* Componente de tabela consultável com busca, paginação, ordenação e ações por linha.
*/
/** Enum de códigos de resposta utilizado na consulta */
?: any) => void;
}[];
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
EliTabelaModalColunas: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ EliTabelaModalColunas: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
aberto: { aberto: {
type: BooleanConstructor; type: BooleanConstructor;
@ -746,7 +852,7 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
type: PropType<Array<{ type: PropType<Array<{
coluna: string | number | symbol; coluna: string | number | symbol;
operador: import("p-comuns").operadores | keyof typeof import("p-comuns").operadores; operador: import("p-comuns").operadores | keyof typeof import("p-comuns").operadores;
entrada: import("../EliEntrada/tiposEntradas.js").ComponenteEntrada; entrada: import("../EliEntrada/tiposEntradas").ComponenteEntrada;
}>>; }>>;
required: true; required: true;
}; };
@ -773,8 +879,8 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
dicaPersistente?: boolean | undefined; dicaPersistente?: boolean | undefined;
min?: string | undefined; min?: string | undefined;
max?: string | undefined; max?: string | undefined;
densidade?: import("../../index.js").CampoDensidade | undefined; densidade?: import("../..").CampoDensidade | undefined;
variante?: import("../../index.js").CampoVariante | undefined; variante?: import("../..").CampoVariante | undefined;
}] | readonly ["numero", { }] | readonly ["numero", {
rotulo: string; rotulo: string;
placeholder?: string | undefined; placeholder?: string | undefined;
@ -791,8 +897,8 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
mensagensErro?: string | string[] | undefined; mensagensErro?: string | string[] | undefined;
dica?: string | undefined; dica?: string | undefined;
dicaPersistente?: boolean | undefined; dicaPersistente?: boolean | undefined;
densidade?: import("../../index.js").CampoDensidade | undefined; densidade?: import("../..").CampoDensidade | undefined;
variante?: import("../../index.js").CampoVariante | undefined; variante?: import("../..").CampoVariante | undefined;
}] | readonly ["selecao", { }] | readonly ["selecao", {
rotulo: string; rotulo: string;
placeholder?: string | undefined; placeholder?: string | undefined;
@ -808,14 +914,14 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
mensagensErro?: string | string[] | undefined; mensagensErro?: string | string[] | undefined;
dica?: string | undefined; dica?: string | undefined;
dicaPersistente?: boolean | undefined; dicaPersistente?: boolean | undefined;
densidade?: import("../../index.js").CampoDensidade | undefined; densidade?: import("../..").CampoDensidade | undefined;
variante?: import("../../index.js").CampoVariante | undefined; variante?: import("../..").CampoVariante | undefined;
}]; }];
operador: string; operador: string;
valor: any; valor: any;
}[], { }[], {
coluna: string | number | symbol; coluna: string | number | symbol;
entrada: import("../EliEntrada/tiposEntradas.js").ComponenteEntrada; entrada: import("../EliEntrada/tiposEntradas").ComponenteEntrada;
operador: string; operador: string;
valor: any; valor: any;
}[] | { }[] | {
@ -836,8 +942,8 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
dicaPersistente?: boolean | undefined; dicaPersistente?: boolean | undefined;
min?: string | undefined; min?: string | undefined;
max?: string | undefined; max?: string | undefined;
densidade?: import("../../index.js").CampoDensidade | undefined; densidade?: import("../..").CampoDensidade | undefined;
variante?: import("../../index.js").CampoVariante | undefined; variante?: import("../..").CampoVariante | undefined;
}] | readonly ["numero", { }] | readonly ["numero", {
rotulo: string; rotulo: string;
placeholder?: string | undefined; placeholder?: string | undefined;
@ -854,8 +960,8 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
mensagensErro?: string | string[] | undefined; mensagensErro?: string | string[] | undefined;
dica?: string | undefined; dica?: string | undefined;
dicaPersistente?: boolean | undefined; dicaPersistente?: boolean | undefined;
densidade?: import("../../index.js").CampoDensidade | undefined; densidade?: import("../..").CampoDensidade | undefined;
variante?: import("../../index.js").CampoVariante | undefined; variante?: import("../..").CampoVariante | undefined;
}] | readonly ["selecao", { }] | readonly ["selecao", {
rotulo: string; rotulo: string;
placeholder?: string | undefined; placeholder?: string | undefined;
@ -871,8 +977,8 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
mensagensErro?: string | string[] | undefined; mensagensErro?: string | string[] | undefined;
dica?: string | undefined; dica?: string | undefined;
dicaPersistente?: boolean | undefined; dicaPersistente?: boolean | undefined;
densidade?: import("../../index.js").CampoDensidade | undefined; densidade?: import("../..").CampoDensidade | undefined;
variante?: import("../../index.js").CampoVariante | undefined; variante?: import("../..").CampoVariante | undefined;
}]; }];
operador: string; operador: string;
valor: any; valor: any;
@ -880,117 +986,10 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
opcoesParaAdicionar: import("vue").ComputedRef<{ opcoesParaAdicionar: import("vue").ComputedRef<{
coluna: string | number | symbol; coluna: string | number | symbol;
operador: import("p-comuns").operadores | keyof typeof import("p-comuns").operadores; operador: import("p-comuns").operadores | keyof typeof import("p-comuns").operadores;
entrada: import("../EliEntrada/tiposEntradas.js").ComponenteEntrada; entrada: import("../EliEntrada/tiposEntradas").ComponenteEntrada;
}[]>; }[]>;
colunaParaAdicionar: import("vue").Ref<string, string>; colunaParaAdicionar: import("vue").Ref<string, string>;
componenteEntrada: (entrada: import("../EliEntrada/tiposEntradas.js").ComponenteEntrada) => import("vue").DefineComponent<import("vue").ExtractPropTypes<{ componenteEntrada: (entrada: import("../EliEntrada/tiposEntradas").ComponenteEntrada) => import("vue").DefineComponent<import("vue").ExtractPropTypes<{
value: {
type: PropType<string | null | undefined>;
default: undefined;
};
opcoes: {
type: PropType<{
rotulo: string;
placeholder?: string;
} & {
limiteCaracteres?: number;
formato?: "texto" | "email" | "url" | "telefone" | "cpfCnpj" | "cep";
}>;
required: true;
};
}>, {
attrs: {
[x: string]: unknown;
};
emit: ((event: "update:value", _v: string | null | undefined) => void) & ((event: "input", _v: string | null | undefined) => void) & ((event: "change", _v: string | null | undefined) => void) & ((event: "focus") => void) & ((event: "blur") => void);
localValue: import("vue").WritableComputedRef<string | null | undefined, string | null | undefined>;
inputHtmlType: import("vue").ComputedRef<"text" | "email" | "url">;
inputMode: import("vue").ComputedRef<string | undefined>;
onInput: (e: Event) => void;
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
"update:value": (_v: string | null | undefined) => true;
input: (_v: string | null | undefined) => true;
change: (_v: string | null | undefined) => true;
focus: () => true;
blur: () => true;
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
value: {
type: PropType<string | null | undefined>;
default: undefined;
};
opcoes: {
type: PropType<{
rotulo: string;
placeholder?: string;
} & {
limiteCaracteres?: number;
formato?: "texto" | "email" | "url" | "telefone" | "cpfCnpj" | "cep";
}>;
required: true;
};
}>> & Readonly<{
"onUpdate:value"?: ((_v: string | null | undefined) => any) | undefined;
onInput?: ((_v: string | null | undefined) => any) | undefined;
onChange?: ((_v: string | null | undefined) => any) | undefined;
onFocus?: (() => any) | undefined;
onBlur?: (() => any) | undefined;
}>, {
value: string | null | undefined;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any> | import("vue").DefineComponent<import("vue").ExtractPropTypes<{
value: {
type: PropType<number | null | undefined>;
default: undefined;
};
opcoes: {
type: PropType<{
rotulo: string;
placeholder?: string;
} & {
sufixo?: string;
prefixo?: string;
precisao?: number;
}>;
required: true;
};
}>, {
attrs: {
[x: string]: unknown;
};
emit: ((event: "update:value", _v: number | null | undefined) => void) & ((event: "input", _v: number | null | undefined) => void) & ((event: "change", _v: number | null | undefined) => void) & ((event: "focus") => void) & ((event: "blur") => void);
displayValue: import("vue").Ref<string, string>;
isInteiro: import("vue").ComputedRef<boolean>;
onUpdateModelValue: (texto: string) => void;
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
"update:value": (_v: number | null | undefined) => true;
input: (_v: number | null | undefined) => true;
change: (_v: number | null | undefined) => true;
focus: () => true;
blur: () => true;
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
value: {
type: PropType<number | null | undefined>;
default: undefined;
};
opcoes: {
type: PropType<{
rotulo: string;
placeholder?: string;
} & {
sufixo?: string;
prefixo?: string;
precisao?: number;
}>;
required: true;
};
}>> & Readonly<{
"onUpdate:value"?: ((_v: number | null | undefined) => any) | undefined;
onInput?: ((_v: number | null | undefined) => any) | undefined;
onChange?: ((_v: number | null | undefined) => any) | undefined;
onFocus?: (() => any) | undefined;
onBlur?: (() => any) | undefined;
}>, {
value: number | null | undefined;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any> | import("vue").DefineComponent<import("vue").ExtractPropTypes<{
value: { value: {
type: PropType<string | null | undefined>; type: PropType<string | null | undefined>;
default: undefined; default: undefined;
@ -1008,8 +1007,8 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
dicaPersistente?: boolean; dicaPersistente?: boolean;
min?: string; min?: string;
max?: string; max?: string;
densidade?: import("../../index.js").CampoDensidade; densidade?: import("../..").CampoDensidade;
variante?: import("../../index.js").CampoVariante; variante?: import("../..").CampoVariante;
}>; }>;
required: false; required: false;
default: undefined; default: undefined;
@ -1055,11 +1054,11 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
default: undefined; default: undefined;
}; };
densidade: { densidade: {
type: PropType<import("../../index.js").CampoDensidade>; type: PropType<import("../..").CampoDensidade>;
default: undefined; default: undefined;
}; };
variante: { variante: {
type: PropType<import("../../index.js").CampoVariante>; type: PropType<import("../..").CampoVariante>;
default: undefined; default: undefined;
}; };
min: { min: {
@ -1090,8 +1089,8 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
dicaPersistente?: boolean; dicaPersistente?: boolean;
min?: string; min?: string;
max?: string; max?: string;
densidade?: import("../../index.js").CampoDensidade; densidade?: import("../..").CampoDensidade;
variante?: import("../../index.js").CampoVariante; variante?: import("../..").CampoVariante;
}>; }>;
desabilitadoEfetivo: import("vue").ComputedRef<boolean>; desabilitadoEfetivo: import("vue").ComputedRef<boolean>;
emitCompatFocus: () => void; emitCompatFocus: () => void;
@ -1124,8 +1123,8 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
dicaPersistente?: boolean; dicaPersistente?: boolean;
min?: string; min?: string;
max?: string; max?: string;
densidade?: import("../../index.js").CampoDensidade; densidade?: import("../..").CampoDensidade;
variante?: import("../../index.js").CampoVariante; variante?: import("../..").CampoVariante;
}>; }>;
required: false; required: false;
default: undefined; default: undefined;
@ -1171,11 +1170,11 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
default: undefined; default: undefined;
}; };
densidade: { densidade: {
type: PropType<import("../../index.js").CampoDensidade>; type: PropType<import("../..").CampoDensidade>;
default: undefined; default: undefined;
}; };
variante: { variante: {
type: PropType<import("../../index.js").CampoVariante>; type: PropType<import("../..").CampoVariante>;
default: undefined; default: undefined;
}; };
min: { min: {
@ -1187,15 +1186,15 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
default: undefined; default: undefined;
}; };
}>> & Readonly<{ }>> & Readonly<{
"onUpdate:value"?: ((_v: string | null) => any) | undefined;
onInput?: ((_v: string | null) => any) | undefined; onInput?: ((_v: string | null) => any) | undefined;
"onUpdate:value"?: ((_v: string | null) => any) | undefined;
onChange?: ((_v: string | null) => any) | undefined; onChange?: ((_v: string | null) => any) | undefined;
onFocus?: (() => any) | undefined;
onBlur?: (() => any) | undefined;
"onUpdate:modelValue"?: ((_v: string | null) => any) | undefined; "onUpdate:modelValue"?: ((_v: string | null) => any) | undefined;
onAlterar?: ((_v: string | null) => any) | undefined; onAlterar?: ((_v: string | null) => any) | undefined;
onFoco?: (() => any) | undefined; onFoco?: (() => any) | undefined;
onDesfoco?: (() => any) | undefined; onDesfoco?: (() => any) | undefined;
onFocus?: (() => any) | undefined;
onBlur?: (() => any) | undefined;
}>, { }>, {
modo: "data" | "dataHora" | undefined; modo: "data" | "dataHora" | undefined;
limpavel: boolean; limpavel: boolean;
@ -1205,8 +1204,8 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
dicaPersistente: boolean; dicaPersistente: boolean;
min: string | undefined; min: string | undefined;
max: string | undefined; max: string | undefined;
densidade: import("../../index.js").CampoDensidade; densidade: import("../..").CampoDensidade;
variante: import("../../index.js").CampoVariante; variante: import("../..").CampoVariante;
opcoes: { opcoes: {
rotulo: string; rotulo: string;
placeholder?: string; placeholder?: string;
@ -1219,16 +1218,123 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
dicaPersistente?: boolean; dicaPersistente?: boolean;
min?: string; min?: string;
max?: string; max?: string;
densidade?: import("../../index.js").CampoDensidade; densidade?: import("../..").CampoDensidade;
variante?: import("../../index.js").CampoVariante; variante?: import("../..").CampoVariante;
}; };
value: string | null | undefined; value: string | null | undefined;
placeholder: string;
modelValue: string | null; modelValue: string | null;
rotulo: string; rotulo: string;
placeholder: string;
desabilitado: boolean; desabilitado: boolean;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any> | import("vue").DefineComponent<import("vue").ExtractPropTypes<{
value: {
type: PropType<number | null | undefined>;
default: undefined;
};
opcoes: {
type: PropType<{
rotulo: string;
placeholder?: string;
} & {
sufixo?: string;
prefixo?: string;
precisao?: number;
}>;
required: true;
};
}>, {
attrs: {
[x: string]: unknown;
};
emit: ((event: "input", _v: number | null | undefined) => void) & ((event: "update:value", _v: number | null | undefined) => void) & ((event: "change", _v: number | null | undefined) => void) & ((event: "focus") => void) & ((event: "blur") => void);
displayValue: import("vue").Ref<string, string>;
isInteiro: import("vue").ComputedRef<boolean>;
onUpdateModelValue: (texto: string) => void;
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
"update:value": (_v: number | null | undefined) => true;
input: (_v: number | null | undefined) => true;
change: (_v: number | null | undefined) => true;
focus: () => true;
blur: () => true;
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
value: {
type: PropType<number | null | undefined>;
default: undefined;
};
opcoes: {
type: PropType<{
rotulo: string;
placeholder?: string;
} & {
sufixo?: string;
prefixo?: string;
precisao?: number;
}>;
required: true;
};
}>> & Readonly<{
onInput?: ((_v: number | null | undefined) => any) | undefined;
"onUpdate:value"?: ((_v: number | null | undefined) => any) | undefined;
onChange?: ((_v: number | null | undefined) => any) | undefined;
onFocus?: (() => any) | undefined;
onBlur?: (() => any) | undefined;
}>, {
value: number | null | undefined;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any> | import("vue").DefineComponent<import("vue").ExtractPropTypes<{
value: {
type: PropType<string | null | undefined>;
default: undefined;
};
opcoes: {
type: PropType<{
rotulo: string;
placeholder?: string;
} & {
limiteCaracteres?: number;
formato?: "texto" | "email" | "url" | "telefone" | "cpfCnpj" | "cep";
}>;
required: true;
};
}>, {
attrs: {
[x: string]: unknown;
};
emit: ((event: "input", _v: string | null | undefined) => void) & ((event: "update:value", _v: string | null | undefined) => void) & ((event: "change", _v: string | null | undefined) => void) & ((event: "focus") => void) & ((event: "blur") => void);
localValue: import("vue").WritableComputedRef<string | null | undefined, string | null | undefined>;
inputHtmlType: import("vue").ComputedRef<"text" | "email" | "url">;
inputMode: import("vue").ComputedRef<string | undefined>;
onInput: (e: Event) => void;
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
"update:value": (_v: string | null | undefined) => true;
input: (_v: string | null | undefined) => true;
change: (_v: string | null | undefined) => true;
focus: () => true;
blur: () => true;
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
value: {
type: PropType<string | null | undefined>;
default: undefined;
};
opcoes: {
type: PropType<{
rotulo: string;
placeholder?: string;
} & {
limiteCaracteres?: number;
formato?: "texto" | "email" | "url" | "telefone" | "cpfCnpj" | "cep";
}>;
required: true;
};
}>> & Readonly<{
onInput?: ((_v: string | null | undefined) => any) | undefined;
"onUpdate:value"?: ((_v: string | null | undefined) => any) | undefined;
onChange?: ((_v: string | null | undefined) => any) | undefined;
onFocus?: (() => any) | undefined;
onBlur?: (() => any) | undefined;
}>, {
value: string | null | undefined;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
opcoesEntrada: (entrada: import("../EliEntrada/tiposEntradas.js").ComponenteEntrada) => any; opcoesEntrada: (entrada: import("../EliEntrada/tiposEntradas").ComponenteEntrada) => any;
adicionar: () => void; adicionar: () => void;
remover: (idx: number) => void; remover: (idx: number) => void;
emitFechar: () => void; emitFechar: () => void;
@ -1237,7 +1343,7 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
rotuloDoFiltro: (f: { rotuloDoFiltro: (f: {
coluna: string | number | symbol; coluna: string | number | symbol;
operador: import("p-comuns").operadores | keyof typeof import("p-comuns").operadores; operador: import("p-comuns").operadores | keyof typeof import("p-comuns").operadores;
entrada: import("../EliEntrada/tiposEntradas.js").ComponenteEntrada; entrada: import("../EliEntrada/tiposEntradas").ComponenteEntrada;
}) => string; }) => string;
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, { }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
fechar: () => true; fechar: () => true;
@ -1252,7 +1358,7 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
type: PropType<Array<{ type: PropType<Array<{
coluna: string | number | symbol; coluna: string | number | symbol;
operador: import("p-comuns").operadores | keyof typeof import("p-comuns").operadores; operador: import("p-comuns").operadores | keyof typeof import("p-comuns").operadores;
entrada: import("../EliEntrada/tiposEntradas.js").ComponenteEntrada; entrada: import("../EliEntrada/tiposEntradas").ComponenteEntrada;
}>>; }>>;
required: true; required: true;
}; };
@ -1266,5 +1372,3 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
onLimpar?: (() => any) | undefined; onLimpar?: (() => any) | undefined;
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: typeof __VLS_export;
export default _default;

View file

@ -1,5 +1,7 @@
import { PropType } from "vue"; import { type PropType } from "vue";
import type { tipoEliColuna } from "./types-eli-tabela"; import type { tipoEliColuna } from "./types-eli-tabela";
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
colunas: { colunas: {
type: PropType<Array<tipoEliColuna<any>>>; type: PropType<Array<tipoEliColuna<any>>>;
@ -182,5 +184,3 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
ChevronRight: import("vue").FunctionalComponent<import("lucide-vue-next").LucideProps, {}, any, {}>; ChevronRight: import("vue").FunctionalComponent<import("lucide-vue-next").LucideProps, {}, any, {}>;
ChevronDown: import("vue").FunctionalComponent<import("lucide-vue-next").LucideProps, {}, any, {}>; ChevronDown: import("vue").FunctionalComponent<import("lucide-vue-next").LucideProps, {}, any, {}>;
}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: typeof __VLS_export;
export default _default;

View file

@ -1,4 +1,6 @@
import { PropType } from "vue"; import { type PropType } from "vue";
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
exibirBusca: { exibirBusca: {
type: BooleanConstructor; type: BooleanConstructor;
@ -18,12 +20,16 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
type: StringConstructor; type: StringConstructor;
required: true; required: true;
}; };
parametrosConsulta: {
type: PropType<any>;
required: false;
};
acoesCabecalho: { acoesCabecalho: {
type: PropType<Array<{ type: PropType<Array<{
icone?: any; icone?: any;
cor?: string; cor?: string;
rotulo: string; rotulo: string;
acao: () => void; acao: (params?: any) => void;
}>>; }>>;
required: true; required: true;
}; };
@ -55,18 +61,22 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
type: StringConstructor; type: StringConstructor;
required: true; required: true;
}; };
parametrosConsulta: {
type: PropType<any>;
required: false;
};
acoesCabecalho: { acoesCabecalho: {
type: PropType<Array<{ type: PropType<Array<{
icone?: any; icone?: any;
cor?: string; cor?: string;
rotulo: string; rotulo: string;
acao: () => void; acao: (params?: any) => void;
}>>; }>>;
required: true; required: true;
}; };
}>> & Readonly<{ }>> & Readonly<{
onBuscar?: ((valor: string) => any) | undefined;
onColunas?: (() => any) | undefined; onColunas?: (() => any) | undefined;
onBuscar?: ((valor: string) => any) | undefined;
onFiltroAvancado?: (() => any) | undefined; onFiltroAvancado?: (() => any) | undefined;
}>, { }>, {
exibirBotaoColunas: boolean; exibirBotaoColunas: boolean;
@ -97,5 +107,3 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
Search: import("vue").FunctionalComponent<import("lucide-vue-next").LucideProps, {}, any, {}>; Search: import("vue").FunctionalComponent<import("lucide-vue-next").LucideProps, {}, any, {}>;
}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: typeof __VLS_export;
export default _default;

View file

@ -1,3 +1,5 @@
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
modelo: { modelo: {
type: StringConstructor; type: StringConstructor;
@ -22,5 +24,3 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
}, {}, { }, {}, {
Search: import("vue").FunctionalComponent<import("lucide-vue-next").LucideProps, {}, any, {}>; Search: import("vue").FunctionalComponent<import("lucide-vue-next").LucideProps, {}, any, {}>;
}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: typeof __VLS_export;
export default _default;

View file

@ -1,4 +1,6 @@
import { PropType } from "vue"; import { type PropType } from "vue";
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
isDev: { isDev: {
type: BooleanConstructor; type: BooleanConstructor;
@ -32,5 +34,3 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
required: true; required: true;
}; };
}>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: typeof __VLS_export;
export default _default;

View file

@ -1,5 +1,7 @@
import { PropType } from "vue"; import { type PropType } from "vue";
import type { tipoEliColuna } from "./types-eli-tabela"; import type { tipoEliColuna } from "./types-eli-tabela";
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
linha: { linha: {
type: PropType<unknown>; type: PropType<unknown>;
@ -56,5 +58,3 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
}; };
}>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: typeof __VLS_export;
export default _default;

View file

@ -1,4 +1,6 @@
import { PropType } from "vue"; import { type PropType } from "vue";
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
carregando: { carregando: {
type: BooleanConstructor; type: BooleanConstructor;
@ -30,5 +32,3 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
}>> & Readonly<{}>, { }>> & Readonly<{}>, {
mensagemVazio: string | undefined; mensagemVazio: string | undefined;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: typeof __VLS_export;
export default _default;

View file

@ -1,5 +1,7 @@
import { PropType } from "vue"; import { type PropType } from "vue";
import type { tipoEliColuna } from "./types-eli-tabela"; import type { tipoEliColuna } from "./types-eli-tabela";
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
colunas: { colunas: {
type: PropType<Array<tipoEliColuna<any>>>; type: PropType<Array<tipoEliColuna<any>>>;
@ -55,5 +57,3 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
ArrowUp: import("vue").FunctionalComponent<import("lucide-vue-next").LucideProps, {}, any, {}>; ArrowUp: import("vue").FunctionalComponent<import("lucide-vue-next").LucideProps, {}, any, {}>;
ArrowDown: import("vue").FunctionalComponent<import("lucide-vue-next").LucideProps, {}, any, {}>; ArrowDown: import("vue").FunctionalComponent<import("lucide-vue-next").LucideProps, {}, any, {}>;
}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: typeof __VLS_export;
export default _default;

View file

@ -1,10 +1,12 @@
import { PropType } from "vue"; import { type PropType } from "vue";
import type { tipoEliTabelaAcao } from "./types-eli-tabela"; import type { tipoEliTabelaAcao } from "./types-eli-tabela";
type ItemAcao<T> = { type ItemAcao<T> = {
acao: tipoEliTabelaAcao<T>; acao: tipoEliTabelaAcao<T>;
indice: number; indice: number;
visivel: boolean; visivel: boolean;
}; };
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
menuAberto: { menuAberto: {
type: PropType<number | null>; type: PropType<number | null>;
@ -62,5 +64,3 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
linha: unknown; linha: unknown;
}) => any) | undefined; }) => any) | undefined;
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: typeof __VLS_export;
export default _default;

View file

@ -1,7 +1,9 @@
import { PropType } from "vue"; import { type PropType } from "vue";
import type { EliTabelaColunasConfig } from "./colunasStorage"; import type { EliTabelaColunasConfig } from "./colunasStorage";
import type { tipoEliColuna } from "./types-eli-tabela"; import type { tipoEliColuna } from "./types-eli-tabela";
type OrigemLista = "visiveis" | "invisiveis"; type OrigemLista = "visiveis" | "invisiveis";
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
aberto: { aberto: {
type: BooleanConstructor; type: BooleanConstructor;
@ -51,5 +53,3 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
onFechar?: (() => any) | undefined; onFechar?: (() => any) | undefined;
onSalvar?: ((_config: EliTabelaColunasConfig) => any) | undefined; onSalvar?: ((_config: EliTabelaColunasConfig) => any) | undefined;
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: typeof __VLS_export;
export default _default;

View file

@ -1,4 +1,4 @@
import { PropType } from "vue"; import { type PropType } from "vue";
import type { ComponenteEntrada } from "../EliEntrada/tiposEntradas"; import type { ComponenteEntrada } from "../EliEntrada/tiposEntradas";
import type { tipoEliTabelaConsulta } from "./types-eli-tabela"; import type { tipoEliTabelaConsulta } from "./types-eli-tabela";
type FiltroBase<T> = NonNullable<tipoEliTabelaConsulta<T>["filtroAvancado"]>[number]; type FiltroBase<T> = NonNullable<tipoEliTabelaConsulta<T>["filtroAvancado"]>[number];
@ -9,6 +9,8 @@ type LinhaFiltro<T> = {
valor: any; valor: any;
}; };
declare function rotuloDoFiltro(f: FiltroBase<any>): string; declare function rotuloDoFiltro(f: FiltroBase<any>): string;
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
aberto: { aberto: {
type: BooleanConstructor; type: BooleanConstructor;
@ -147,113 +149,6 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
}[]>; }[]>;
colunaParaAdicionar: import("vue").Ref<string, string>; colunaParaAdicionar: import("vue").Ref<string, string>;
componenteEntrada: (entrada: ComponenteEntrada) => import("vue").DefineComponent<import("vue").ExtractPropTypes<{ componenteEntrada: (entrada: ComponenteEntrada) => import("vue").DefineComponent<import("vue").ExtractPropTypes<{
value: {
type: PropType<string | null | undefined>;
default: undefined;
};
opcoes: {
type: PropType<{
rotulo: string;
placeholder?: string;
} & {
limiteCaracteres?: number;
formato?: "texto" | "email" | "url" | "telefone" | "cpfCnpj" | "cep";
}>;
required: true;
};
}>, {
attrs: {
[x: string]: unknown;
};
emit: ((event: "update:value", _v: string | null | undefined) => void) & ((event: "input", _v: string | null | undefined) => void) & ((event: "change", _v: string | null | undefined) => void) & ((event: "focus") => void) & ((event: "blur") => void);
localValue: import("vue").WritableComputedRef<string | null | undefined, string | null | undefined>;
inputHtmlType: import("vue").ComputedRef<"text" | "email" | "url">;
inputMode: import("vue").ComputedRef<string | undefined>;
onInput: (e: Event) => void;
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
"update:value": (_v: string | null | undefined) => true;
input: (_v: string | null | undefined) => true;
change: (_v: string | null | undefined) => true;
focus: () => true;
blur: () => true;
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
value: {
type: PropType<string | null | undefined>;
default: undefined;
};
opcoes: {
type: PropType<{
rotulo: string;
placeholder?: string;
} & {
limiteCaracteres?: number;
formato?: "texto" | "email" | "url" | "telefone" | "cpfCnpj" | "cep";
}>;
required: true;
};
}>> & Readonly<{
"onUpdate:value"?: ((_v: string | null | undefined) => any) | undefined;
onInput?: ((_v: string | null | undefined) => any) | undefined;
onChange?: ((_v: string | null | undefined) => any) | undefined;
onFocus?: (() => any) | undefined;
onBlur?: (() => any) | undefined;
}>, {
value: string | null | undefined;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any> | import("vue").DefineComponent<import("vue").ExtractPropTypes<{
value: {
type: PropType<number | null | undefined>;
default: undefined;
};
opcoes: {
type: PropType<{
rotulo: string;
placeholder?: string;
} & {
sufixo?: string;
prefixo?: string;
precisao?: number;
}>;
required: true;
};
}>, {
attrs: {
[x: string]: unknown;
};
emit: ((event: "update:value", _v: number | null | undefined) => void) & ((event: "input", _v: number | null | undefined) => void) & ((event: "change", _v: number | null | undefined) => void) & ((event: "focus") => void) & ((event: "blur") => void);
displayValue: import("vue").Ref<string, string>;
isInteiro: import("vue").ComputedRef<boolean>;
onUpdateModelValue: (texto: string) => void;
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
"update:value": (_v: number | null | undefined) => true;
input: (_v: number | null | undefined) => true;
change: (_v: number | null | undefined) => true;
focus: () => true;
blur: () => true;
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
value: {
type: PropType<number | null | undefined>;
default: undefined;
};
opcoes: {
type: PropType<{
rotulo: string;
placeholder?: string;
} & {
sufixo?: string;
prefixo?: string;
precisao?: number;
}>;
required: true;
};
}>> & Readonly<{
"onUpdate:value"?: ((_v: number | null | undefined) => any) | undefined;
onInput?: ((_v: number | null | undefined) => any) | undefined;
onChange?: ((_v: number | null | undefined) => any) | undefined;
onFocus?: (() => any) | undefined;
onBlur?: (() => any) | undefined;
}>, {
value: number | null | undefined;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any> | import("vue").DefineComponent<import("vue").ExtractPropTypes<{
value: { value: {
type: PropType<string | null | undefined>; type: PropType<string | null | undefined>;
default: undefined; default: undefined;
@ -450,15 +345,15 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
default: undefined; default: undefined;
}; };
}>> & Readonly<{ }>> & Readonly<{
"onUpdate:value"?: ((_v: string | null) => any) | undefined;
onInput?: ((_v: string | null) => any) | undefined; onInput?: ((_v: string | null) => any) | undefined;
"onUpdate:value"?: ((_v: string | null) => any) | undefined;
onChange?: ((_v: string | null) => any) | undefined; onChange?: ((_v: string | null) => any) | undefined;
onFocus?: (() => any) | undefined;
onBlur?: (() => any) | undefined;
"onUpdate:modelValue"?: ((_v: string | null) => any) | undefined; "onUpdate:modelValue"?: ((_v: string | null) => any) | undefined;
onAlterar?: ((_v: string | null) => any) | undefined; onAlterar?: ((_v: string | null) => any) | undefined;
onFoco?: (() => any) | undefined; onFoco?: (() => any) | undefined;
onDesfoco?: (() => any) | undefined; onDesfoco?: (() => any) | undefined;
onFocus?: (() => any) | undefined;
onBlur?: (() => any) | undefined;
}>, { }>, {
modo: "data" | "dataHora" | undefined; modo: "data" | "dataHora" | undefined;
limpavel: boolean; limpavel: boolean;
@ -486,10 +381,117 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
variante?: import("../..").CampoVariante; variante?: import("../..").CampoVariante;
}; };
value: string | null | undefined; value: string | null | undefined;
placeholder: string;
modelValue: string | null; modelValue: string | null;
rotulo: string; rotulo: string;
placeholder: string;
desabilitado: boolean; desabilitado: boolean;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any> | import("vue").DefineComponent<import("vue").ExtractPropTypes<{
value: {
type: PropType<number | null | undefined>;
default: undefined;
};
opcoes: {
type: PropType<{
rotulo: string;
placeholder?: string;
} & {
sufixo?: string;
prefixo?: string;
precisao?: number;
}>;
required: true;
};
}>, {
attrs: {
[x: string]: unknown;
};
emit: ((event: "input", _v: number | null | undefined) => void) & ((event: "update:value", _v: number | null | undefined) => void) & ((event: "change", _v: number | null | undefined) => void) & ((event: "focus") => void) & ((event: "blur") => void);
displayValue: import("vue").Ref<string, string>;
isInteiro: import("vue").ComputedRef<boolean>;
onUpdateModelValue: (texto: string) => void;
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
"update:value": (_v: number | null | undefined) => true;
input: (_v: number | null | undefined) => true;
change: (_v: number | null | undefined) => true;
focus: () => true;
blur: () => true;
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
value: {
type: PropType<number | null | undefined>;
default: undefined;
};
opcoes: {
type: PropType<{
rotulo: string;
placeholder?: string;
} & {
sufixo?: string;
prefixo?: string;
precisao?: number;
}>;
required: true;
};
}>> & Readonly<{
onInput?: ((_v: number | null | undefined) => any) | undefined;
"onUpdate:value"?: ((_v: number | null | undefined) => any) | undefined;
onChange?: ((_v: number | null | undefined) => any) | undefined;
onFocus?: (() => any) | undefined;
onBlur?: (() => any) | undefined;
}>, {
value: number | null | undefined;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any> | import("vue").DefineComponent<import("vue").ExtractPropTypes<{
value: {
type: PropType<string | null | undefined>;
default: undefined;
};
opcoes: {
type: PropType<{
rotulo: string;
placeholder?: string;
} & {
limiteCaracteres?: number;
formato?: "texto" | "email" | "url" | "telefone" | "cpfCnpj" | "cep";
}>;
required: true;
};
}>, {
attrs: {
[x: string]: unknown;
};
emit: ((event: "input", _v: string | null | undefined) => void) & ((event: "update:value", _v: string | null | undefined) => void) & ((event: "change", _v: string | null | undefined) => void) & ((event: "focus") => void) & ((event: "blur") => void);
localValue: import("vue").WritableComputedRef<string | null | undefined, string | null | undefined>;
inputHtmlType: import("vue").ComputedRef<"text" | "email" | "url">;
inputMode: import("vue").ComputedRef<string | undefined>;
onInput: (e: Event) => void;
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
"update:value": (_v: string | null | undefined) => true;
input: (_v: string | null | undefined) => true;
change: (_v: string | null | undefined) => true;
focus: () => true;
blur: () => true;
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
value: {
type: PropType<string | null | undefined>;
default: undefined;
};
opcoes: {
type: PropType<{
rotulo: string;
placeholder?: string;
} & {
limiteCaracteres?: number;
formato?: "texto" | "email" | "url" | "telefone" | "cpfCnpj" | "cep";
}>;
required: true;
};
}>> & Readonly<{
onInput?: ((_v: string | null | undefined) => any) | undefined;
"onUpdate:value"?: ((_v: string | null | undefined) => any) | undefined;
onChange?: ((_v: string | null | undefined) => any) | undefined;
onFocus?: (() => any) | undefined;
onBlur?: (() => any) | undefined;
}>, {
value: string | null | undefined;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
opcoesEntrada: (entrada: ComponenteEntrada) => any; opcoesEntrada: (entrada: ComponenteEntrada) => any;
adicionar: () => void; adicionar: () => void;
@ -520,5 +522,3 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
onSalvar?: ((_linhas: any[]) => any) | undefined; onSalvar?: ((_linhas: any[]) => any) | undefined;
onLimpar?: (() => any) | undefined; onLimpar?: (() => any) | undefined;
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: typeof __VLS_export;
export default _default;

View file

@ -1,3 +1,6 @@
import { type PropType } from "vue";
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
pagina: { pagina: {
type: NumberConstructor; type: NumberConstructor;
@ -11,6 +14,20 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
type: NumberConstructor; type: NumberConstructor;
required: false; required: false;
}; };
acoes: {
type: PropType<Array<{
icone?: any;
cor?: string;
rotulo: string;
acao: (params?: any) => void;
}>>;
required: false;
default: () => never[];
};
parametrosConsulta: {
type: PropType<any>;
required: false;
};
}>, { }>, {
botoes: import("vue").ComputedRef<{ botoes: import("vue").ComputedRef<{
label: string; label: string;
@ -38,8 +55,27 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
type: NumberConstructor; type: NumberConstructor;
required: false; required: false;
}; };
acoes: {
type: PropType<Array<{
icone?: any;
cor?: string;
rotulo: string;
acao: (params?: any) => void;
}>>;
required: false;
default: () => never[];
};
parametrosConsulta: {
type: PropType<any>;
required: false;
};
}>> & Readonly<{ }>> & Readonly<{
onAlterar?: ((pagina: number) => any) | undefined; onAlterar?: ((pagina: number) => any) | undefined;
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }>, {
declare const _default: typeof __VLS_export; acoes: {
export default _default; icone?: any;
cor?: string;
rotulo: string;
acao: (params?: any) => void;
}[];
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;

View file

@ -1,6 +1,8 @@
import type { Component } from "vue"; import type { Component } from "vue";
import { PropType } from "vue"; import { type PropType } from "vue";
import type { tipoComponenteCelula } from "../types-eli-tabela"; import type { tipoComponenteCelula } from "../types-eli-tabela";
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
celula: { celula: {
type: PropType<tipoComponenteCelula>; type: PropType<tipoComponenteCelula>;
@ -37,5 +39,3 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
required: true; required: true;
}; };
}>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: typeof __VLS_export;
export default _default;

View file

@ -1,5 +1,7 @@
import { PropType } from "vue"; import { type PropType } from "vue";
import type { tiposTabelaCelulas } from "./tiposTabelaCelulas"; import type { tiposTabelaCelulas } from "./tiposTabelaCelulas";
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
dados: { dados: {
type: PropType<tiposTabelaCelulas["data"]>; type: PropType<tiposTabelaCelulas["data"]>;
@ -18,5 +20,3 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
required: false; required: false;
}; };
}>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: typeof __VLS_export;
export default _default;

View file

@ -1,5 +1,7 @@
import { PropType } from "vue"; import { type PropType } from "vue";
import type { tiposTabelaCelulas } from "./tiposTabelaCelulas"; import type { tiposTabelaCelulas } from "./tiposTabelaCelulas";
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
dados: { dados: {
type: PropType<tiposTabelaCelulas["numero"]>; type: PropType<tiposTabelaCelulas["numero"]>;
@ -17,5 +19,3 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
type: PropType<tiposTabelaCelulas["numero"]>; type: PropType<tiposTabelaCelulas["numero"]>;
}; };
}>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: typeof __VLS_export;
export default _default;

View file

@ -1,5 +1,7 @@
import { PropType } from "vue"; import { type PropType } from "vue";
import type { tiposTabelaCelulas } from "./tiposTabelaCelulas"; import type { tiposTabelaCelulas } from "./tiposTabelaCelulas";
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
dados: { dados: {
type: PropType<tiposTabelaCelulas["tags"]>; type: PropType<tiposTabelaCelulas["tags"]>;
@ -679,5 +681,3 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
onClickOnce: PropType<(args_0: MouseEvent) => void>; onClickOnce: PropType<(args_0: MouseEvent) => void>;
}>>; }>>;
}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: typeof __VLS_export;
export default _default;

View file

@ -1,5 +1,7 @@
import { PropType } from "vue"; import { type PropType } from "vue";
import type { tiposTabelaCelulas } from "./tiposTabelaCelulas"; import type { tiposTabelaCelulas } from "./tiposTabelaCelulas";
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
dados: { dados: {
type: PropType<tiposTabelaCelulas["textoSimples"]>; type: PropType<tiposTabelaCelulas["textoSimples"]>;
@ -14,5 +16,3 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
type: PropType<tiposTabelaCelulas["textoSimples"]>; type: PropType<tiposTabelaCelulas["textoSimples"]>;
}; };
}>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: typeof __VLS_export;
export default _default;

View file

@ -1,5 +1,7 @@
import { PropType } from "vue"; import { type PropType } from "vue";
import type { tiposTabelaCelulas } from "./tiposTabelaCelulas"; import type { tiposTabelaCelulas } from "./tiposTabelaCelulas";
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
dados: { dados: {
type: PropType<tiposTabelaCelulas["textoTruncado"]>; type: PropType<tiposTabelaCelulas["textoTruncado"]>;
@ -14,5 +16,3 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
type: PropType<tiposTabelaCelulas["textoTruncado"]>; type: PropType<tiposTabelaCelulas["textoTruncado"]>;
}; };
}>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: typeof __VLS_export;
export default _default;

View file

@ -1,4 +1,4 @@
export * from "./celulas/tiposTabelaCelulas";
export { default as EliTabela } from "./EliTabela.vue"; export { default as EliTabela } from "./EliTabela.vue";
export * from "./types-eli-tabela"; export * from "./types-eli-tabela";
export * from "./celulas/tiposTabelaCelulas";
export { celulaTabela } from "./types-eli-tabela"; export { celulaTabela } from "./types-eli-tabela";

View file

@ -1,10 +1,13 @@
import type { tipoResposta } from "p-respostas";
import type { LucideIcon } from "lucide-vue-next"; import type { LucideIcon } from "lucide-vue-next";
import type { tipoTabelaCelula, tiposTabelaCelulas } from "./celulas/tiposTabelaCelulas"; import type { operadores, zFiltro } from "p-comuns";
import { operadores, zFiltro } from "p-comuns"; import type { tipoResposta } from "p-respostas";
import { ComponenteEntrada } from "../EliEntrada/tiposEntradas"; import type { ComponenteEntrada } from "../EliEntrada/tiposEntradas";
import type { tiposTabelaCelulas, tipoTabelaCelula } from "./celulas/tiposTabelaCelulas";
export type tipoFiltro = ReturnType<(typeof zFiltro)["parse"]>; export type tipoFiltro = ReturnType<(typeof zFiltro)["parse"]>;
export type tipoComponenteCelulaBase<T extends tipoTabelaCelula> = readonly [T, tiposTabelaCelulas[T]]; export type tipoComponenteCelulaBase<T extends tipoTabelaCelula> = readonly [
T,
tiposTabelaCelulas[T]
];
export type tipoComponenteCelula = { export type tipoComponenteCelula = {
[K in tipoTabelaCelula]: tipoComponenteCelulaBase<K>; [K in tipoTabelaCelula]: tipoComponenteCelulaBase<K>;
}[tipoTabelaCelula]; }[tipoTabelaCelula];
@ -48,6 +51,15 @@ export type tipoEliTabelaAcao<T> = {
*/ */
exibir?: boolean | ((linha: T) => Promise<boolean> | boolean); exibir?: boolean | ((linha: T) => Promise<boolean> | boolean);
}; };
export type parametrosConsulta<T> = {
filtros?: tipoFiltro[];
coluna_ordem?: keyof T;
direcao_ordem?: "asc" | "desc";
offSet?: number;
limit?: number;
/** Texto digitado na caixa de busca, quando habilitada. */
texto_busca?: string;
};
/** /**
* Estrutura de dados para uma tabela alimentada por uma consulta. * Estrutura de dados para uma tabela alimentada por uma consulta.
* *
@ -68,15 +80,7 @@ export type tipoEliTabelaConsulta<T> = {
* Função responsável por buscar os dados. Recebe parâmetros opcionais de * Função responsável por buscar os dados. Recebe parâmetros opcionais de
* ordenação (`coluna_ordem`/`direcao_ordem`) e paginação (`offSet`/`limit`). * ordenação (`coluna_ordem`/`direcao_ordem`) e paginação (`offSet`/`limit`).
*/ */
consulta: (parametrosConsulta?: { consulta: (parametrosConsulta?: parametrosConsulta<T>) => Promise<tipoResposta<tipoEliConsultaPaginada<T>>>;
filtros?: tipoFiltro[];
coluna_ordem?: keyof T;
direcao_ordem?: "asc" | "desc";
offSet?: number;
limit?: number;
/** Texto digitado na caixa de busca, quando habilitada. */
texto_busca?: string;
}) => Promise<tipoResposta<tipoEliConsultaPaginada<T>>>;
/** Quantidade máxima de botões exibidos na paginação (padrão `7`). */ /** Quantidade máxima de botões exibidos na paginação (padrão `7`). */
maximo_botoes_paginacao?: number; maximo_botoes_paginacao?: number;
/** Mensagem exibida quando a consulta retorna ok porém sem dados. */ /** Mensagem exibida quando a consulta retorna ok porém sem dados. */
@ -88,6 +92,8 @@ export type tipoEliTabelaConsulta<T> = {
* Seu uso mais comum será para criar novos registros, mas poderá ter outras utilidades. * Seu uso mais comum será para criar novos registros, mas poderá ter outras utilidades.
*/ */
acoesTabela?: { acoesTabela?: {
/** superio será exibido a direita da caixa de busca, inferior a direita da paginação */
posicao: "superior" | "inferior";
/** Ícone (Lucide) exibido no botão */ /** Ícone (Lucide) exibido no botão */
icone?: LucideIcon; icone?: LucideIcon;
/** Cor aplicada ao botão. */ /** Cor aplicada ao botão. */
@ -95,7 +101,7 @@ export type tipoEliTabelaConsulta<T> = {
/** Texto descritivo da ação. */ /** Texto descritivo da ação. */
rotulo: string; rotulo: string;
/** Função executada ao clicar no botão. */ /** Função executada ao clicar no botão. */
acao: () => void; acao: (parametrosConsulta?: parametrosConsulta<T>) => void;
/** /**
* Callback opcional para forçar atualização da consulta. * Callback opcional para forçar atualização da consulta.
* Observação: o componente `EliTabela` pode ignorar isso dependendo do modo de uso. * Observação: o componente `EliTabela` pode ignorar isso dependendo do modo de uso.

View file

@ -1,5 +1,7 @@
import { PropType } from "vue"; import { type PropType } from "vue";
import type { BotaoTamanho, BotaoVariante } from "../../tipos"; import type { BotaoTamanho, BotaoVariante } from "../../tipos";
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
color: { color: {
type: StringConstructor; type: StringConstructor;
@ -49,5 +51,3 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
disabled: boolean; disabled: boolean;
loading: boolean; loading: boolean;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: typeof __VLS_export;
export default _default;

View file

@ -1,6 +1,17 @@
import { PropType } from "vue"; import { type PropType } from "vue";
import type { CartaoStatus } from "../../tipos"; import type { CartaoStatus } from "../../tipos";
type CartaoVariante = "outlined" | "flat" | "elevated" | "tonal"; type CartaoVariante = "outlined" | "flat" | "elevated" | "tonal";
/**
* EliCartao
*
* Um cartão de domínio para listas/pipelines (ex.: oportunidades/propostas) com:
* - título
* - status padronizado (novo/rascunho/vendido/cancelado)
* - slot padrão para conteúdo
* - slot opcional para ações
*/
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
/** Título de fallback caso o slot `titulo` não seja usado. */ /** Título de fallback caso o slot `titulo` não seja usado. */
titulo: { titulo: {
@ -135,14 +146,3 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
radius: import("../..").IndicadorPresetRaio | import("../..").CssLength; radius: import("../..").IndicadorPresetRaio | import("../..").CssLength;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
/**
* EliCartao
*
* Um cartão de domínio para listas/pipelines (ex.: oportunidades/propostas) com:
* - título
* - status padronizado (novo/rascunho/vendido/cancelado)
* - slot padrão para conteúdo
* - slot opcional para ações
*/
declare const _default: typeof __VLS_export;
export default _default;

View file

@ -1,5 +1,7 @@
import { PropType } from "vue"; import { type PropType } from "vue";
import type { CssLength, IndicadorLocalizacao, IndicadorOffset, IndicadorPresetRaio } from "../../tipos"; import type { CssLength, IndicadorLocalizacao, IndicadorOffset, IndicadorPresetRaio } from "../../tipos";
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
color: { color: {
type: StringConstructor; type: StringConstructor;
@ -83,5 +85,3 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
badge: string | number | undefined; badge: string | number | undefined;
radius: IndicadorPresetRaio | CssLength; radius: IndicadorPresetRaio | CssLength;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: typeof __VLS_export;
export default _default;

View file

@ -1,3 +1,5 @@
declare const _default: typeof __VLS_export;
export default _default;
declare const __VLS_export: import("vue").DefineComponent<{}, { declare const __VLS_export: import("vue").DefineComponent<{}, {
nome: import("vue").Ref<string, string>; nome: import("vue").Ref<string, string>;
email: import("vue").Ref<string, string>; email: import("vue").Ref<string, string>;
@ -154,7 +156,7 @@ declare const __VLS_export: import("vue").DefineComponent<{}, {
attrs: { attrs: {
[x: string]: unknown; [x: string]: unknown;
}; };
emit: ((event: "update:value", _v: string | null | undefined) => void) & ((event: "input", _v: string | null | undefined) => void) & ((event: "change", _v: string | null | undefined) => void) & ((event: "focus") => void) & ((event: "blur") => void); emit: ((event: "input", _v: string | null | undefined) => void) & ((event: "update:value", _v: string | null | undefined) => void) & ((event: "change", _v: string | null | undefined) => void) & ((event: "focus") => void) & ((event: "blur") => void);
localValue: import("vue").WritableComputedRef<string | null | undefined, string | null | undefined>; localValue: import("vue").WritableComputedRef<string | null | undefined, string | null | undefined>;
inputHtmlType: import("vue").ComputedRef<"text" | "email" | "url">; inputHtmlType: import("vue").ComputedRef<"text" | "email" | "url">;
inputMode: import("vue").ComputedRef<string | undefined>; inputMode: import("vue").ComputedRef<string | undefined>;
@ -181,8 +183,8 @@ declare const __VLS_export: import("vue").DefineComponent<{}, {
required: true; required: true;
}; };
}>> & Readonly<{ }>> & Readonly<{
"onUpdate:value"?: ((_v: string | null | undefined) => any) | undefined;
onInput?: ((_v: string | null | undefined) => any) | undefined; onInput?: ((_v: string | null | undefined) => any) | undefined;
"onUpdate:value"?: ((_v: string | null | undefined) => any) | undefined;
onChange?: ((_v: string | null | undefined) => any) | undefined; onChange?: ((_v: string | null | undefined) => any) | undefined;
onFocus?: (() => any) | undefined; onFocus?: (() => any) | undefined;
onBlur?: (() => any) | undefined; onBlur?: (() => any) | undefined;
@ -190,5 +192,3 @@ declare const __VLS_export: import("vue").DefineComponent<{}, {
value: string | null | undefined; value: string | null | undefined;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: typeof __VLS_export;
export default _default;

View file

@ -1,15 +1,15 @@
import type { Plugin } from "vue"; import type { Plugin } from "vue";
import "./styles/eli-vue-fonts.css"; import "./styles/eli-vue-fonts.css";
import { EliOlaMundo } from "./componentes/ola_mundo";
import { EliBotao } from "./componentes/botao"; import { EliBotao } from "./componentes/botao";
import { EliBadge } from "./componentes/indicador";
import { EliCartao } from "./componentes/cartao"; import { EliCartao } from "./componentes/cartao";
import { EliBadge } from "./componentes/indicador";
import { EliOlaMundo } from "./componentes/ola_mundo";
export { EliOlaMundo }; export { EliOlaMundo };
export { EliBotao }; export { EliBotao };
export { EliBadge }; export { EliBadge };
export { EliCartao }; export { EliCartao };
export * from "./componentes/EliTabela";
export * from "./componentes/EliEntrada"; export * from "./componentes/EliEntrada";
export * from "./componentes/EliTabela";
export * from "./tipos"; export * from "./tipos";
declare const EliVue: Plugin; declare const EliVue: Plugin;
export default EliVue; export default EliVue;

View file

@ -1,6 +1,6 @@
{ {
"name": "eli-vue", "name": "eli-vue",
"version": "0.1.91", "version": "0.1.94",
"private": false, "private": false,
"main": "./dist/eli-vue.umd.js", "main": "./dist/eli-vue.umd.js",
"module": "./dist/eli-vue.es.js", "module": "./dist/eli-vue.es.js",
@ -13,17 +13,21 @@
} }
}, },
"scripts": { "scripts": {
"biome": "pnpm exec biome check --write",
"check": "pnpm run biome && npx tsc --noEmit",
"prebuild": "npm version patch --no-git-tag-version", "prebuild": "npm version patch --no-git-tag-version",
"build:types": "vue-tsc -p tsconfig.build.json --declaration --emitDeclarationOnly", "build:types": "vue-tsc -p tsconfig.build.json --declaration --emitDeclarationOnly",
"build": "vite build && npm run build:types", "build": "pnpm run biome && vite build && npm run build:types",
"dev": "vite", "dev": "pnpm run biome && pnpm run fechar && vite",
"preview": "vite preview" "preview": "vite preview",
"fechar": "fuser -k 5555/tcp || true"
}, },
"peerDependencies": { "peerDependencies": {
"vue": "^3.4.0", "vue": "^3.4.0",
"vuetify": "^3.0.0" "vuetify": "^3.0.0"
}, },
"devDependencies": { "devDependencies": {
"@biomejs/biome": "2.4.0",
"@mdi/font": "^7.4.47", "@mdi/font": "^7.4.47",
"@vitejs/plugin-vue": "^5.0.0", "@vitejs/plugin-vue": "^5.0.0",
"sass": "^1.94.2", "sass": "^1.94.2",

790
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -23,28 +23,28 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, PropType } from "vue"; import { dayjsbr } from "p-comuns"
import dayjs from "dayjs"; import { computed, defineComponent, type PropType } from "vue"
import type { CampoDensidade, CampoVariante } from "../../tipos"; import type { CampoDensidade, CampoVariante } from "../../tipos"
import type { PadroesEntradas } from "./tiposEntradas"; import type { PadroesEntradas } from "./tiposEntradas"
type EntradaDataHora = PadroesEntradas["dataHora"]; type EntradaDataHora = PadroesEntradas["dataHora"]
type PropsAntigas = { type PropsAntigas = {
modo?: "data" | "dataHora"; modo?: "data" | "dataHora"
rotulo?: string; rotulo?: string
placeholder?: string; placeholder?: string
desabilitado?: boolean; desabilitado?: boolean
limpavel?: boolean; limpavel?: boolean
erro?: boolean; erro?: boolean
mensagensErro?: string | string[]; mensagensErro?: string | string[]
dica?: string; dica?: string
dicaPersistente?: boolean; dicaPersistente?: boolean
densidade?: CampoDensidade; densidade?: CampoDensidade
variante?: CampoVariante; variante?: CampoVariante
min?: string; min?: string
max?: string; max?: string
}; }
export default defineComponent({ export default defineComponent({
name: "EliEntradaDataHora", name: "EliEntradaDataHora",
@ -66,7 +66,10 @@ export default defineComponent({
type: String as PropType<string | null>, type: String as PropType<string | null>,
default: null, default: null,
}, },
modo: { type: String as PropType<PropsAntigas["modo"]>, default: undefined }, modo: {
type: String as PropType<PropsAntigas["modo"]>,
default: undefined,
},
rotulo: { type: String, default: undefined }, rotulo: { type: String, default: undefined },
placeholder: { type: String, default: undefined }, placeholder: { type: String, default: undefined },
desabilitado: { type: Boolean, default: undefined }, desabilitado: { type: Boolean, default: undefined },
@ -100,7 +103,7 @@ export default defineComponent({
setup(props, { emit, attrs }) { setup(props, { emit, attrs }) {
const opcoesEfetivas = computed<EntradaDataHora["opcoes"]>(() => { const opcoesEfetivas = computed<EntradaDataHora["opcoes"]>(() => {
// 1) se veio `opcoes` (novo), usa // 1) se veio `opcoes` (novo), usa
if (props.opcoes) return props.opcoes; if (props.opcoes) return props.opcoes
// 2) fallback: constrói a partir das props antigas // 2) fallback: constrói a partir das props antigas
return { return {
@ -116,86 +119,90 @@ export default defineComponent({
variante: props.variante, variante: props.variante,
min: props.min, min: props.min,
max: props.max, max: props.max,
}; }
}); })
const modoEfetivo = computed<"data" | "dataHora">( const modoEfetivo = computed<"data" | "dataHora">(
() => opcoesEfetivas.value.modo ?? "dataHora" () => opcoesEfetivas.value.modo ?? "dataHora",
); )
const desabilitadoEfetivo = computed<boolean>(() => Boolean(props.desabilitado)); const desabilitadoEfetivo = computed<boolean>(() =>
Boolean(props.desabilitado),
)
const tipoInput = computed<"date" | "datetime-local">(() => const tipoInput = computed<"date" | "datetime-local">(() =>
modoEfetivo.value === "data" ? "date" : "datetime-local" modoEfetivo.value === "data" ? "date" : "datetime-local",
); )
function isoParaInputDatetime(valorIso: string): string { function isoParaInputDatetime(valorIso: string): string {
if (modoEfetivo.value === "data") { if (modoEfetivo.value === "data") {
return dayjs(valorIso).format("YYYY-MM-DD"); return dayjsbr(valorIso).format("YYYY-MM-DD")
} }
return dayjs(valorIso).format("YYYY-MM-DDTHH:mm"); return dayjsbr(valorIso).format("YYYY-MM-DDTHH:mm")
} }
function inputDatetimeParaIsoLocal(valorInput: string): string { function inputDatetimeParaIsoLocal(valorInput: string): string {
if (modoEfetivo.value === "data") { if (modoEfetivo.value === "data") {
return dayjs(`${valorInput}T00:00`).format(); return dayjsbr(`${valorInput}T00:00`).format()
} }
return dayjs(valorInput).format(); return dayjsbr(valorInput).format()
} }
const effectiveModelValue = computed<string | null>(() => { const effectiveModelValue = computed<string | null>(() => {
// Prioridade: value (novo) se vier definido; senão usa modelValue (antigo) // Prioridade: value (novo) se vier definido; senão usa modelValue (antigo)
return props.value !== undefined ? (props.value ?? null) : props.modelValue; return props.value !== undefined
}); ? (props.value ?? null)
: props.modelValue
})
const valor = computed<string>({ const valor = computed<string>({
get: () => { get: () => {
if (!effectiveModelValue.value) return ""; if (!effectiveModelValue.value) return ""
return isoParaInputDatetime(effectiveModelValue.value); return isoParaInputDatetime(effectiveModelValue.value)
}, },
set: (v) => { set: (v) => {
const normalizado = v && v.length > 0 ? v : null; const normalizado = v && v.length > 0 ? v : null
if (!normalizado) { if (!normalizado) {
emit("update:value", null); emit("update:value", null)
emit("input", null); emit("input", null)
emit("change", null); emit("change", null)
emit("update:modelValue", null); emit("update:modelValue", null)
emit("alterar", null); emit("alterar", null)
return; return
} }
const valorEmitido = inputDatetimeParaIsoLocal(normalizado); const valorEmitido = inputDatetimeParaIsoLocal(normalizado)
emit("update:value", valorEmitido); emit("update:value", valorEmitido)
emit("input", valorEmitido); emit("input", valorEmitido)
emit("change", valorEmitido); emit("change", valorEmitido)
emit("update:modelValue", valorEmitido); emit("update:modelValue", valorEmitido)
emit("alterar", valorEmitido); emit("alterar", valorEmitido)
}, },
}); })
const minLocal = computed<string | undefined>(() => { const minLocal = computed<string | undefined>(() => {
const min = opcoesEfetivas.value.min; const min = opcoesEfetivas.value.min
if (!min) return undefined; if (!min) return undefined
return isoParaInputDatetime(min); return isoParaInputDatetime(min)
}); })
const maxLocal = computed<string | undefined>(() => { const maxLocal = computed<string | undefined>(() => {
const max = opcoesEfetivas.value.max; const max = opcoesEfetivas.value.max
if (!max) return undefined; if (!max) return undefined
return isoParaInputDatetime(max); return isoParaInputDatetime(max)
}); })
function emitCompatFocus() { function emitCompatFocus() {
emit("foco"); emit("foco")
emit("focus"); emit("focus")
} }
function emitCompatBlur() { function emitCompatBlur() {
emit("desfoco"); emit("desfoco")
emit("blur"); emit("blur")
} }
return { return {
@ -208,9 +215,9 @@ export default defineComponent({
desabilitadoEfetivo, desabilitadoEfetivo,
emitCompatFocus, emitCompatFocus,
emitCompatBlur, emitCompatBlur,
}; }
}, },
}); })
</script> </script>
<style> <style>

View file

@ -25,87 +25,90 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, PropType, ref, watch } from "vue"; import { computed, defineComponent, type PropType, ref, watch } from "vue"
import type { PadroesEntradas } from "./tiposEntradas"; import type { PadroesEntradas } from "./tiposEntradas"
type EntradaNumero = PadroesEntradas["numero"]; type EntradaNumero = PadroesEntradas["numero"]
function casasDecimaisFromPrecisao(precisao: number): number { function casasDecimaisFromPrecisao(precisao: number): number {
if (!Number.isFinite(precisao) || precisao <= 0) return 0; if (!Number.isFinite(precisao) || precisao <= 0) return 0
if (precisao >= 1) return 0; if (precisao >= 1) return 0
// Preferência por contar casas decimais na representação (ex.: 0.01 -> 2) // Preferência por contar casas decimais na representação (ex.: 0.01 -> 2)
const texto = precisao.toString(); const texto = precisao.toString()
if (texto.includes("e-")) { if (texto.includes("e-")) {
const [, exp] = texto.split("e-"); const [, exp] = texto.split("e-")
const n = Number(exp); const n = Number(exp)
return Number.isFinite(n) ? n : 0; return Number.isFinite(n) ? n : 0
} }
const idx = texto.indexOf("."); const idx = texto.indexOf(".")
if (idx === -1) return 0; if (idx === -1) return 0
const dec = texto.slice(idx + 1).replace(/0+$/, ""); const dec = texto.slice(idx + 1).replace(/0+$/, "")
return dec.length; return dec.length
} }
function parseNumero(texto: string): number | null { function parseNumero(texto: string): number | null {
const normalizado = (texto ?? "").trim().replace(/,/g, "."); const normalizado = (texto ?? "").trim().replace(/,/g, ".")
if (!normalizado) return null; if (!normalizado) return null
const n = Number(normalizado); const n = Number(normalizado)
if (Number.isNaN(n)) return null; if (Number.isNaN(n)) return null
return n; return n
} }
function formatarNumero(value: number | null | undefined, casas: number | null) { function formatarNumero(
if (value === null || value === undefined) return ""; value: number | null | undefined,
if (casas === null) return String(value); casas: number | null,
) {
if (value === null || value === undefined) return ""
if (casas === null) return String(value)
// Garantimos que o texto visual corresponda ao value (fixed). // Garantimos que o texto visual corresponda ao value (fixed).
const fixed = Number(value).toFixed(Math.max(0, casas)); const fixed = Number(value).toFixed(Math.max(0, casas))
// Exibe com vírgula (pt-BR) // Exibe com vírgula (pt-BR)
return fixed.replace(/\./g, ","); return fixed.replace(/\./g, ",")
} }
function somenteNumeros(texto: string) { function somenteNumeros(texto: string) {
return (texto ?? "").replace(/\D+/g, ""); return (texto ?? "").replace(/\D+/g, "")
} }
function somenteNumerosESeparadorDecimal(texto: string) { function somenteNumerosESeparadorDecimal(texto: string) {
// Mantém apenas números e UM separador decimal ("," ou "."), sem sinais. // Mantém apenas números e UM separador decimal ("," ou "."), sem sinais.
// Implementação baseada em regex + colapso de separadores. // Implementação baseada em regex + colapso de separadores.
const limpo = (texto ?? "").replace(/[^0-9.,]+/g, ""); const limpo = (texto ?? "").replace(/[^0-9.,]+/g, "")
const matchSep = limpo.match(/[.,]/); const matchSep = limpo.match(/[.,]/)
if (!matchSep) return limpo; if (!matchSep) return limpo
const sep = matchSep[0]; const sep = matchSep[0]
const idx = limpo.indexOf(sep); const idx = limpo.indexOf(sep)
const antesRaw = limpo.slice(0, idx).replace(/[.,]/g, ""); const antesRaw = limpo.slice(0, idx).replace(/[.,]/g, "")
const depois = limpo.slice(idx + 1).replace(/[.,]/g, ""); const depois = limpo.slice(idx + 1).replace(/[.,]/g, "")
// Se o usuário começa pelo separador (",4"), normalizamos para "0,4". // Se o usuário começa pelo separador (",4"), normalizamos para "0,4".
const antes = antesRaw.length ? antesRaw : "0"; const antes = antesRaw.length ? antesRaw : "0"
return `${antes}${sep}${depois}`; return `${antes}${sep}${depois}`
} }
function limitarCasasDecimais(texto: string, casas: number | null) { function limitarCasasDecimais(texto: string, casas: number | null) {
if (casas === null) return texto; if (casas === null) return texto
if (casas <= 0) return texto.replace(/[.,]/g, ""); if (casas <= 0) return texto.replace(/[.,]/g, "")
const matchSep = texto.match(/[.,]/); const matchSep = texto.match(/[.,]/)
if (!matchSep) return texto; if (!matchSep) return texto
const sep = matchSep[0]; const sep = matchSep[0]
const idx = texto.indexOf(sep); const idx = texto.indexOf(sep)
const inteiro = texto.slice(0, idx); const inteiro = texto.slice(0, idx)
const frac = texto.slice(idx + 1); const frac = texto.slice(idx + 1)
return `${inteiro}${sep}${frac.slice(0, casas)}`; return `${inteiro}${sep}${frac.slice(0, casas)}`
} }
function valorParcialDecimal(texto: string): number | null { function valorParcialDecimal(texto: string): number | null {
// Regra (B): se o usuário digitou "1," ou "1." emite 1. // Regra (B): se o usuário digitou "1," ou "1." emite 1.
const m = texto.match(/^(\d+)[.,]$/); const m = texto.match(/^(\d+)[.,]$/)
if (!m) return null; if (!m) return null
const n = Number(m[1]); const n = Number(m[1])
return Number.isNaN(n) ? null : n; return Number.isNaN(n) ? null : n
} }
export default defineComponent({ export default defineComponent({
@ -133,25 +136,25 @@ export default defineComponent({
setup(props, { attrs, emit }) { setup(props, { attrs, emit }) {
// Se `precisao` não existir => não limitamos casas (mas ainda bloqueamos caracteres inválidos). // Se `precisao` não existir => não limitamos casas (mas ainda bloqueamos caracteres inválidos).
const casasDecimais = computed<number | null>(() => { const casasDecimais = computed<number | null>(() => {
const p = props.opcoes?.precisao; const p = props.opcoes?.precisao
if (p === undefined || p === null) return null; if (p === undefined || p === null) return null
return casasDecimaisFromPrecisao(p); return casasDecimaisFromPrecisao(p)
}); })
const isInteiro = computed(() => { const isInteiro = computed(() => {
// quando não existe precisão, tratamos como decimal livre // quando não existe precisão, tratamos como decimal livre
return casasDecimais.value === 0; return casasDecimais.value === 0
}); })
const isFixedPoint = computed(() => { const isFixedPoint = computed(() => {
// Quando precisao existe e é < 1, controlamos a vírgula automaticamente. // Quando precisao existe e é < 1, controlamos a vírgula automaticamente.
const casas = casasDecimais.value; const casas = casasDecimais.value
return casas !== null && casas > 0; return casas !== null && casas > 0
}); })
// Controle do texto exibido: impede o campo de ficar com caracteres inválidos. // Controle do texto exibido: impede o campo de ficar com caracteres inválidos.
const displayValue = ref<string>(""); const displayValue = ref<string>("")
const ultimoEmitido = ref<EntradaNumero["value"] | undefined>(undefined); const ultimoEmitido = ref<EntradaNumero["value"] | undefined>(undefined)
watch( watch(
() => props.value, () => props.value,
@ -159,63 +162,71 @@ export default defineComponent({
// Se foi uma atualização resultante do que acabamos de emitir, não sobrescreve. // Se foi uma atualização resultante do que acabamos de emitir, não sobrescreve.
// Isso evita o efeito de "apagar" o texto ao digitar algo parcial (ex.: "1,") // Isso evita o efeito de "apagar" o texto ao digitar algo parcial (ex.: "1,")
// quando o valor emitido é `1` ou `null`. // quando o valor emitido é `1` ou `null`.
if (v === ultimoEmitido.value) return; if (v === ultimoEmitido.value) return
// biome-ignore lint/suspicious/noExplicitAny: dynamic format
displayValue.value = formatarNumero(v as any, casasDecimais.value); displayValue.value = formatarNumero(v as any, casasDecimais.value)
ultimoEmitido.value = v; ultimoEmitido.value = v
}, },
{ immediate: true } { immediate: true },
); )
function onUpdateModelValue(texto: string) { function onUpdateModelValue(texto: string) {
// Modo fixed-point: usuário digita números continuamente e a vírgula é inserida automaticamente. // Modo fixed-point: usuário digita números continuamente e a vírgula é inserida automaticamente.
if (isFixedPoint.value) { if (isFixedPoint.value) {
const casas = casasDecimais.value ?? 0; const casas = casasDecimais.value ?? 0
const digitos = somenteNumeros(texto); const digitos = somenteNumeros(texto)
// ex.: casas=2, "1" => 0.01 ; "123" => 1.23 // ex.: casas=2, "1" => 0.01 ; "123" => 1.23
const baseInt = digitos ? Number(digitos) : 0; const baseInt = digitos ? Number(digitos) : 0
const divisor = Math.pow(10, casas); const divisor = 10 ** casas
const n = digitos ? baseInt / divisor : null; const n = digitos ? baseInt / divisor : null
const out = (n === null ? null : n) as EntradaNumero["value"]; const out = (n === null ? null : n) as EntradaNumero["value"]
ultimoEmitido.value = out; ultimoEmitido.value = out
emit("update:value", out); emit("update:value", out)
emit("input", out); emit("input", out)
emit("change", out); emit("change", out)
// display deve ser sempre o reflexo do value // display deve ser sempre o reflexo do value
displayValue.value = formatarNumero(out as any, casas); // biome-ignore lint/suspicious/noExplicitAny: dynamic format
return; displayValue.value = formatarNumero(out as any, casas)
return
} }
// Modo livre (sem precisao) ou inteiro: aceita números e 1 separador (no caso livre) // Modo livre (sem precisao) ou inteiro: aceita números e 1 separador (no caso livre)
const base = isInteiro.value ? somenteNumeros(texto) : somenteNumerosESeparadorDecimal(texto); const base = isInteiro.value
const textoFiltrado = isInteiro.value ? base : limitarCasasDecimais(base, casasDecimais.value); ? somenteNumeros(texto)
: somenteNumerosESeparadorDecimal(texto)
const textoFiltrado = isInteiro.value
? base
: limitarCasasDecimais(base, casasDecimais.value)
// Emissão: // Emissão:
// - vazio => null // - vazio => null
// - decimal parcial ("1,") => 1 (regra B) // - decimal parcial ("1,") => 1 (regra B)
// - caso geral => parse normal // - caso geral => parse normal
let out: EntradaNumero["value"] = null; let out: EntradaNumero["value"] = null
if (textoFiltrado) { if (textoFiltrado) {
const parcial = isInteiro.value ? null : valorParcialDecimal(textoFiltrado); const parcial = isInteiro.value
const n = parcial ?? parseNumero(textoFiltrado); ? null
out = (n === null ? null : n) as EntradaNumero["value"]; : valorParcialDecimal(textoFiltrado)
const n = parcial ?? parseNumero(textoFiltrado)
out = (n === null ? null : n) as EntradaNumero["value"]
} }
ultimoEmitido.value = out; ultimoEmitido.value = out
emit("update:value", out); emit("update:value", out)
emit("input", out); emit("input", out)
emit("change", out); emit("change", out)
// display deve sempre corresponder ao value final // display deve sempre corresponder ao value final
displayValue.value = formatarNumero(out as any, casasDecimais.value); // biome-ignore lint/suspicious/noExplicitAny: dynamic format
displayValue.value = formatarNumero(out as any, casasDecimais.value)
} }
return { attrs, emit, displayValue, isInteiro, onUpdateModelValue }; return { attrs, emit, displayValue, isInteiro, onUpdateModelValue }
}, },
}); })
</script> </script>
<style> <style>

View file

@ -21,11 +21,11 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, PropType } from "vue"; import { computed, defineComponent, type PropType } from "vue"
import { VTextarea } from "vuetify/components"; import { VTextarea } from "vuetify/components"
import type { PadroesEntradas } from "./tiposEntradas"; import type { PadroesEntradas } from "./tiposEntradas"
type EntradaParagrafo = PadroesEntradas["paragrafo"]; type EntradaParagrafo = PadroesEntradas["paragrafo"]
export default defineComponent({ export default defineComponent({
name: "EliEntradaParagrafo", name: "EliEntradaParagrafo",
@ -52,15 +52,15 @@ export default defineComponent({
const localValue = computed<EntradaParagrafo["value"]>({ const localValue = computed<EntradaParagrafo["value"]>({
get: () => props.value, get: () => props.value,
set: (v) => { set: (v) => {
emit("update:value", v); emit("update:value", v)
emit("input", v); emit("input", v)
emit("change", v); emit("change", v)
}, },
}); })
return { attrs, emit, localValue, opcoes: props.opcoes }; return { attrs, emit, localValue }
}, },
}); })
</script> </script>
<style></style> <style></style>

View file

@ -23,12 +23,19 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, onMounted, PropType, ref, watch } from "vue"; import {
import { VSelect } from "vuetify/components"; computed,
import type { PadroesEntradas } from "./tiposEntradas"; defineComponent,
onMounted,
type PropType,
ref,
watch,
} from "vue"
import { VSelect } from "vuetify/components"
import type { PadroesEntradas } from "./tiposEntradas"
type EntradaSelecao = PadroesEntradas["selecao"]; type EntradaSelecao = PadroesEntradas["selecao"]
type ItemSelecao = { chave: string; rotulo: string }; type ItemSelecao = { chave: string; rotulo: string }
export default defineComponent({ export default defineComponent({
name: "EliEntradaSelecao", name: "EliEntradaSelecao",
@ -52,29 +59,29 @@ export default defineComponent({
blur: () => true, blur: () => true,
}, },
setup(props, { attrs, emit }) { setup(props, { attrs, emit }) {
const itens = ref<ItemSelecao[]>([]); const itens = ref<ItemSelecao[]>([])
const carregando = ref(false); const carregando = ref(false)
const localValue = computed<EntradaSelecao["value"]>({ const localValue = computed<EntradaSelecao["value"]>({
get: () => props.value, get: () => props.value,
set: (v) => { set: (v) => {
emit("update:value", v); emit("update:value", v)
emit("input", v); emit("input", v)
emit("change", v); emit("change", v)
}, },
}); })
async function carregarItens() { async function carregarItens() {
carregando.value = true; carregando.value = true
try { try {
const resultado = await props.opcoes.itens(); const resultado = await props.opcoes.itens()
const lista = Array.isArray(resultado) ? resultado : []; const lista = Array.isArray(resultado) ? resultado : []
// Força reatividade mesmo quando Vuetify mantém cache interno. // Força reatividade mesmo quando Vuetify mantém cache interno.
// (garante que `items` mude de referência) // (garante que `items` mude de referência)
itens.value = [...lista]; itens.value = [...lista]
} finally { } finally {
carregando.value = false; carregando.value = false
} }
} }
@ -82,27 +89,27 @@ export default defineComponent({
watch( watch(
() => props.opcoes.itens, () => props.opcoes.itens,
() => { () => {
void carregarItens(); void carregarItens()
} },
); )
onMounted(() => { onMounted(() => {
void carregarItens(); void carregarItens()
}); })
// Debug (playground): ajuda a identificar se os itens chegaram. // Debug (playground): ajuda a identificar se os itens chegaram.
watch( watch(
itens, itens,
(v) => { (v) => {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.debug("[EliEntradaSelecao] itens:", v); console.debug("[EliEntradaSelecao] itens:", v)
}, },
{ deep: true } { deep: true },
); )
return { attrs, emit, localValue, opcoes: props.opcoes, itens, carregando }; return { attrs, emit, localValue, itens, carregando }
}, },
}); })
</script> </script>
<style></style> <style></style>

View file

@ -15,13 +15,13 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, PropType } from "vue"; import { computed, defineComponent, type PropType } from "vue"
import type { PadroesEntradas } from "./tiposEntradas"; import type { PadroesEntradas } from "./tiposEntradas"
import { formatarCpfCnpj } from "./utils/cpfCnpj"; import { formatarCep } from "./utils/cep"
import { formatTelefone } from "./utils/telefone"; import { formatarCpfCnpj } from "./utils/cpfCnpj"
import { formatarCep } from "./utils/cep"; import { formatTelefone } from "./utils/telefone"
type EntradaTexto = PadroesEntradas["texto"]; type EntradaTexto = PadroesEntradas["texto"]
export default defineComponent({ export default defineComponent({
name: "EliEntradaTexto", name: "EliEntradaTexto",
@ -46,56 +46,57 @@ export default defineComponent({
blur: () => true, blur: () => true,
}, },
setup(props, { attrs, emit }) { setup(props, { attrs, emit }) {
const formato = computed(() => props.opcoes?.formato ?? "texto"); const formato = computed(() => props.opcoes?.formato ?? "texto")
const localValue = computed<EntradaTexto["value"]>({ const localValue = computed<EntradaTexto["value"]>({
get: () => props.value, get: () => props.value,
set: (v) => { set: (v) => {
emit("update:value", v); emit("update:value", v)
emit("input", v); emit("input", v)
emit("change", v); emit("change", v)
}, },
}); })
const inputHtmlType = computed(() => { const inputHtmlType = computed(() => {
if (formato.value === "email") return "email"; if (formato.value === "email") return "email"
if (formato.value === "url") return "url"; if (formato.value === "url") return "url"
return "text"; return "text"
}); })
const inputMode = computed<string | undefined>(() => { const inputMode = computed<string | undefined>(() => {
if (formato.value === "telefone") return "tel"; if (formato.value === "telefone") return "tel"
if (formato.value === "cpfCnpj" || formato.value === "cep") return "numeric"; if (formato.value === "cpfCnpj" || formato.value === "cep")
return undefined; return "numeric"
}); return undefined
})
function aplicarFormato(valor: string) { function aplicarFormato(valor: string) {
switch (formato.value) { switch (formato.value) {
case "telefone": case "telefone":
return formatTelefone(valor); return formatTelefone(valor)
case "cpfCnpj": case "cpfCnpj":
return formatarCpfCnpj(valor); return formatarCpfCnpj(valor)
case "cep": case "cep":
return formatarCep(valor); return formatarCep(valor)
default: default:
return valor; return valor
} }
} }
function onInput(e: Event) { function onInput(e: Event) {
const target = e.target as HTMLInputElement; const target = e.target as HTMLInputElement
const resultado = aplicarFormato(target.value); const resultado = aplicarFormato(target.value)
// garante que o input mostre o valor formatado // garante que o input mostre o valor formatado
target.value = resultado; target.value = resultado
// regra do projeto: value sempre igual ao que aparece // regra do projeto: value sempre igual ao que aparece
localValue.value = resultado; localValue.value = resultado
} }
return { attrs, emit, localValue, inputHtmlType, inputMode, onInput }; return { attrs, emit, localValue, inputHtmlType, inputMode, onInput }
}, },
}); })
</script> </script>
<style></style> <style></style>

View file

@ -1,8 +1,14 @@
import EliEntradaTexto from "./EliEntradaTexto.vue"; import EliEntradaDataHora from "./EliEntradaDataHora.vue"
import EliEntradaNumero from "./EliEntradaNumero.vue"; import EliEntradaNumero from "./EliEntradaNumero.vue"
import EliEntradaDataHora from "./EliEntradaDataHora.vue"; import EliEntradaParagrafo from "./EliEntradaParagrafo.vue"
import EliEntradaParagrafo from "./EliEntradaParagrafo.vue"; import EliEntradaSelecao from "./EliEntradaSelecao.vue"
import EliEntradaSelecao from "./EliEntradaSelecao.vue"; import EliEntradaTexto from "./EliEntradaTexto.vue"
export { EliEntradaTexto, EliEntradaNumero, EliEntradaDataHora, EliEntradaParagrafo, EliEntradaSelecao }; export {
export type { PadroesEntradas, TipoEntrada } from "./tiposEntradas"; EliEntradaTexto,
EliEntradaNumero,
EliEntradaDataHora,
EliEntradaParagrafo,
EliEntradaSelecao,
}
export type { PadroesEntradas, TipoEntrada } from "./tiposEntradas"

View file

@ -1,12 +1,11 @@
import type { Component } from "vue"; import type { Component } from "vue"
import EliEntradaDataHora from "./EliEntradaDataHora.vue"
import EliEntradaNumero from "./EliEntradaNumero.vue"
import EliEntradaParagrafo from "./EliEntradaParagrafo.vue"
import EliEntradaSelecao from "./EliEntradaSelecao.vue"
import EliEntradaTexto from "./EliEntradaTexto.vue"
import EliEntradaTexto from "./EliEntradaTexto.vue"; import type { TipoEntrada } from "./tiposEntradas"
import EliEntradaNumero from "./EliEntradaNumero.vue";
import EliEntradaDataHora from "./EliEntradaDataHora.vue";
import EliEntradaParagrafo from "./EliEntradaParagrafo.vue";
import EliEntradaSelecao from "./EliEntradaSelecao.vue";
import type { TipoEntrada } from "./tiposEntradas";
export const registryTabelaCelulas = { export const registryTabelaCelulas = {
texto: EliEntradaTexto, texto: EliEntradaTexto,
@ -14,4 +13,4 @@ export const registryTabelaCelulas = {
dataHora: EliEntradaDataHora, dataHora: EliEntradaDataHora,
paragrafo: EliEntradaParagrafo, paragrafo: EliEntradaParagrafo,
selecao: EliEntradaSelecao, selecao: EliEntradaSelecao,
} as const satisfies Record<TipoEntrada, Component>; } as const satisfies Record<TipoEntrada, Component>

View file

@ -59,8 +59,6 @@ export type PadroesEntradas = {
numero: tipoPadraoEntrada< numero: tipoPadraoEntrada<
number | null | undefined, number | null | undefined,
{ {
/** Unidade de medida (ex.: "kg", "m³") */ /** Unidade de medida (ex.: "kg", "m³") */
sufixo?: string sufixo?: string
@ -187,11 +185,10 @@ export type PadroesEntradas = {
*/ */
export type TipoEntrada = keyof PadroesEntradas export type TipoEntrada = keyof PadroesEntradas
export type PadraoComponenteEntrada<T extends TipoEntrada> = readonly [
T,
PadroesEntradas[T]["opcoes"],
export type PadraoComponenteEntrada<T extends TipoEntrada> = ]
readonly [T, PadroesEntradas[T]['opcoes']]
export type ComponenteEntrada = { export type ComponenteEntrada = {
[K in TipoEntrada]: PadraoComponenteEntrada<K> [K in TipoEntrada]: PadraoComponenteEntrada<K>

View file

@ -1,10 +1,10 @@
function somenteNumeros(valor: string) { function somenteNumeros(valor: string) {
return valor.replace(/\D+/g, ""); return valor.replace(/\D+/g, "")
} }
/** Formata CEP no padrão 00000-000 */ /** Formata CEP no padrão 00000-000 */
export function formatarCep(valor: string) { export function formatarCep(valor: string) {
const digitos = somenteNumeros(valor); const digitos = somenteNumeros(valor)
if (!digitos) return ""; if (!digitos) return ""
return digitos.replace(/^(\d{5})(\d)/, "$1-$2").slice(0, 9); return digitos.replace(/^(\d{5})(\d)/, "$1-$2").slice(0, 9)
} }

View file

@ -1,9 +1,9 @@
function somenteNumeros(v: string): string { function somenteNumeros(v: string): string {
return v.replace(/\D+/g, ""); return v.replace(/\D+/g, "")
} }
export function formatarCpfCnpj(v: string): string { export function formatarCpfCnpj(v: string): string {
const d = somenteNumeros(v); const d = somenteNumeros(v)
// CPF // CPF
if (d.length <= 11) { if (d.length <= 11) {
@ -11,7 +11,7 @@ export function formatarCpfCnpj(v: string): string {
.replace(/(\d{3})(\d)/, "$1.$2") .replace(/(\d{3})(\d)/, "$1.$2")
.replace(/(\d{3})(\d)/, "$1.$2") .replace(/(\d{3})(\d)/, "$1.$2")
.replace(/(\d{3})(\d{1,2})$/, "$1-$2") .replace(/(\d{3})(\d{1,2})$/, "$1-$2")
.slice(0, 14); .slice(0, 14)
} }
// CNPJ // CNPJ
@ -20,5 +20,5 @@ export function formatarCpfCnpj(v: string): string {
.replace(/^(\d{2})\.(\d{3})(\d)/, "$1.$2.$3") .replace(/^(\d{2})\.(\d{3})(\d)/, "$1.$2.$3")
.replace(/\.(\d{3})(\d)/, ".$1/$2") .replace(/\.(\d{3})(\d)/, ".$1/$2")
.replace(/(\d{4})(\d)/, "$1-$2") .replace(/(\d{4})(\d)/, "$1-$2")
.slice(0, 18); .slice(0, 18)
} }

View file

@ -2,28 +2,28 @@
* Remove tudo que não é número * Remove tudo que não é número
*/ */
export function sanitizeTelefone(value: string): string { export function sanitizeTelefone(value: string): string {
return value.replace(/\D+/g, ""); return value.replace(/\D+/g, "")
} }
/** /**
* Aplica máscara dinâmica de telefone BR * Aplica máscara dinâmica de telefone BR
*/ */
export function formatTelefone(value: string): string { export function formatTelefone(value: string): string {
const digits = sanitizeTelefone(value); const digits = sanitizeTelefone(value)
if (!digits) return ""; if (!digits) return ""
// (99) 9999-9999 // (99) 9999-9999
if (digits.length <= 10) { if (digits.length <= 10) {
return digits return digits
.replace(/^(\d{2})(\d)/, "($1) $2") .replace(/^(\d{2})(\d)/, "($1) $2")
.replace(/(\d{4})(\d)/, "$1-$2") .replace(/(\d{4})(\d)/, "$1-$2")
.slice(0, 14); .slice(0, 14)
} }
// (99) 99999-9999 // (99) 99999-9999
return digits return digits
.replace(/^(\d{2})(\d)/, "($1) $2") .replace(/^(\d{2})(\d)/, "($1) $2")
.replace(/(\d{5})(\d)/, "$1-$2") .replace(/(\d{5})(\d)/, "$1-$2")
.slice(0, 15); .slice(0, 15)
} }

View file

@ -147,6 +147,31 @@
z-index: 200; z-index: 200;
} }
.eli-tabela__rodape {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 12px;
margin-top: 12px;
flex-wrap: wrap;
}
.eli-tabela__paginacao {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 12px;
margin-top: 0;
flex-wrap: wrap;
}
.eli-tabela__acoes-inferiores {
display: inline-flex;
gap: 8px;
align-items: center;
flex-wrap: wrap;
}
.eli-tabela__cabecalho { .eli-tabela__cabecalho {
width: 100%; width: 100%;
box-sizing: border-box; box-sizing: border-box;

File diff suppressed because it is too large Load diff

View file

@ -73,11 +73,11 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, PropType } from "vue"; import { ChevronDown, ChevronRight, MoreVertical } from "lucide-vue-next"
import { ChevronDown, ChevronRight, MoreVertical } from "lucide-vue-next"; import { defineComponent, type PropType } from "vue"
import EliTabelaCelula from "./celulas/EliTabelaCelula.vue"; import EliTabelaCelula from "./celulas/EliTabelaCelula.vue"
import EliTabelaDetalhesLinha from "./EliTabelaDetalhesLinha.vue"; import EliTabelaDetalhesLinha from "./EliTabelaDetalhesLinha.vue"
import type { tipoEliColuna } from "./types-eli-tabela"; import type { tipoEliColuna } from "./types-eli-tabela"
export default defineComponent({ export default defineComponent({
name: "EliTabelaBody", name: "EliTabelaBody",
@ -90,10 +90,12 @@ export default defineComponent({
}, },
props: { props: {
colunas: { colunas: {
// biome-ignore lint/suspicious/noExplicitAny: dynamic column
type: Array as PropType<Array<tipoEliColuna<any>>>, type: Array as PropType<Array<tipoEliColuna<any>>>,
required: true, required: true,
}, },
colunasInvisiveis: { colunasInvisiveis: {
// biome-ignore lint/suspicious/noExplicitAny: dynamic column
type: Array as PropType<Array<tipoEliColuna<any>>>, type: Array as PropType<Array<tipoEliColuna<any>>>,
required: true, required: true,
}, },
@ -134,7 +136,7 @@ export default defineComponent({
return { return {
ChevronRight, ChevronRight,
ChevronDown, ChevronDown,
}; }
}, },
}); })
</script> </script>

View file

@ -30,7 +30,7 @@
type="button" type="button"
class="eli-tabela__acoes-cabecalho-botao" class="eli-tabela__acoes-cabecalho-botao"
:style="botao.cor ? { backgroundColor: botao.cor, color: '#fff' } : undefined" :style="botao.cor ? { backgroundColor: botao.cor, color: '#fff' } : undefined"
@click="botao.acao" @click="botao.acao(parametrosConsulta)"
> >
<component <component
v-if="botao.icone" v-if="botao.icone"
@ -46,8 +46,8 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, PropType } from "vue"; import { computed, defineComponent, type PropType } from "vue"
import EliTabelaCaixaDeBusca from "./EliTabelaCaixaDeBusca.vue"; import EliTabelaCaixaDeBusca from "./EliTabelaCaixaDeBusca.vue"
export default defineComponent({ export default defineComponent({
name: "EliTabelaCabecalho", name: "EliTabelaCabecalho",
@ -71,13 +71,20 @@ export default defineComponent({
type: String, type: String,
required: true, required: true,
}, },
parametrosConsulta: {
// biome-ignore lint/suspicious/noExplicitAny: dynamic params
type: Object as PropType<any>,
required: false,
},
acoesCabecalho: { acoesCabecalho: {
type: Array as PropType< type: Array as PropType<
Array<{ Array<{
icone?: any; // biome-ignore lint/suspicious/noExplicitAny: dynamic icon
cor?: string; icone?: any
rotulo: string; cor?: string
acao: () => void; rotulo: string
// biome-ignore lint/suspicious/noExplicitAny: dynamic action
acao: (params?: any) => void
}> }>
>, >,
required: true, required: true,
@ -85,33 +92,33 @@ export default defineComponent({
}, },
emits: { emits: {
buscar(valor: string) { buscar(valor: string) {
return typeof valor === "string"; return typeof valor === "string"
}, },
colunas() { colunas() {
return true; return true
}, },
filtroAvancado() { filtroAvancado() {
return true; return true
}, },
}, },
setup(props, { emit }) { setup(props, { emit }) {
const temAcoesCabecalho = computed(() => props.acoesCabecalho.length > 0); const temAcoesCabecalho = computed(() => props.acoesCabecalho.length > 0)
function emitBuscar(texto: string) { function emitBuscar(texto: string) {
emit("buscar", texto); emit("buscar", texto)
} }
function emitColunas() { function emitColunas() {
emit("colunas"); emit("colunas")
} }
function emitFiltroAvancado() { function emitFiltroAvancado() {
emit("filtroAvancado"); emit("filtroAvancado")
} }
return { temAcoesCabecalho, emitBuscar, emitColunas, emitFiltroAvancado }; return { temAcoesCabecalho, emitBuscar, emitColunas, emitFiltroAvancado }
}, },
}); })
</script> </script>
<style> <style>

View file

@ -23,8 +23,8 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, ref, watch } from "vue"; import { Search } from "lucide-vue-next"
import { Search } from "lucide-vue-next"; import { defineComponent, ref, watch } from "vue"
export default defineComponent({ export default defineComponent({
name: "EliTabelaCaixaDeBusca", name: "EliTabelaCaixaDeBusca",
@ -38,7 +38,7 @@ export default defineComponent({
}, },
emits: { emits: {
buscar(valor: string) { buscar(valor: string) {
return typeof valor === "string"; return typeof valor === "string"
}, },
}, },
setup(props, { emit }) { setup(props, { emit }) {
@ -46,24 +46,24 @@ export default defineComponent({
* Estado local da entrada para que o usuário possa digitar livremente antes * Estado local da entrada para que o usuário possa digitar livremente antes
* de disparar uma nova consulta. * de disparar uma nova consulta.
*/ */
const texto = ref(props.modelo ?? ""); const texto = ref(props.modelo ?? "")
watch( watch(
() => props.modelo, () => props.modelo,
(novo) => { (novo) => {
if (novo !== undefined && novo !== texto.value) { if (novo !== undefined && novo !== texto.value) {
texto.value = novo; texto.value = novo
} }
} },
); )
function emitirBusca() { function emitirBusca() {
emit("buscar", texto.value.trim()); emit("buscar", texto.value.trim())
} }
return { texto, emitirBusca }; return { texto, emitirBusca }
}, },
}); })
</script> </script>
<style> <style>

View file

@ -12,7 +12,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, PropType } from "vue"; import { defineComponent, type PropType } from "vue"
export default defineComponent({ export default defineComponent({
name: "EliTabelaDebug", name: "EliTabelaDebug",
@ -30,5 +30,5 @@ export default defineComponent({
required: true, required: true,
}, },
}, },
}); })
</script> </script>

View file

@ -10,9 +10,9 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, PropType } from "vue"; import { defineComponent, type PropType } from "vue"
import EliTabelaCelula from "./celulas/EliTabelaCelula.vue"; import EliTabelaCelula from "./celulas/EliTabelaCelula.vue"
import type { tipoEliColuna } from "./types-eli-tabela"; import type { tipoEliColuna } from "./types-eli-tabela"
export default defineComponent({ export default defineComponent({
name: "EliTabelaDetalhesLinha", name: "EliTabelaDetalhesLinha",
@ -23,11 +23,12 @@ export default defineComponent({
required: true, required: true,
}, },
colunasInvisiveis: { colunasInvisiveis: {
// biome-ignore lint/suspicious/noExplicitAny: dynamic column
type: Array as PropType<Array<tipoEliColuna<any>>>, type: Array as PropType<Array<tipoEliColuna<any>>>,
required: true, required: true,
}, },
}, },
}); })
</script> </script>
<style> <style>

View file

@ -17,7 +17,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, PropType } from "vue"; import { defineComponent, type PropType } from "vue"
export default defineComponent({ export default defineComponent({
name: "EliTabelaEstados", name: "EliTabelaEstados",
@ -36,5 +36,5 @@ export default defineComponent({
default: undefined, default: undefined,
}, },
}, },
}); })
</script> </script>

View file

@ -49,15 +49,16 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, PropType } from "vue"; import { ArrowDown, ArrowUp } from "lucide-vue-next"
import { ArrowDown, ArrowUp } from "lucide-vue-next"; import { defineComponent, type PropType } from "vue"
import type { tipoEliColuna } from "./types-eli-tabela"; import type { tipoEliColuna } from "./types-eli-tabela"
export default defineComponent({ export default defineComponent({
name: "EliTabelaHead", name: "EliTabelaHead",
components: { ArrowUp, ArrowDown }, components: { ArrowUp, ArrowDown },
props: { props: {
colunas: { colunas: {
// biome-ignore lint/suspicious/noExplicitAny: dynamic column
type: Array as PropType<Array<tipoEliColuna<any>>>, type: Array as PropType<Array<tipoEliColuna<any>>>,
required: true, required: true,
}, },
@ -80,16 +81,17 @@ export default defineComponent({
}, },
emits: { emits: {
alternarOrdenacao(chave: string) { alternarOrdenacao(chave: string) {
return typeof chave === "string" && chave.length > 0; return typeof chave === "string" && chave.length > 0
}, },
}, },
setup(_props, { emit }) { setup(_props, { emit }) {
// biome-ignore lint/suspicious/noExplicitAny: dynamic column
function isOrdenavel(coluna: any) { function isOrdenavel(coluna: any) {
return coluna?.coluna_ordem !== undefined && coluna?.coluna_ordem !== null; return coluna?.coluna_ordem !== undefined && coluna?.coluna_ordem !== null
} }
function emitAlternarOrdenacao(chave: string) { function emitAlternarOrdenacao(chave: string) {
emit("alternarOrdenacao", chave); emit("alternarOrdenacao", chave)
} }
return { return {
@ -97,7 +99,7 @@ export default defineComponent({
ArrowDown, ArrowDown,
isOrdenavel, isOrdenavel,
emitAlternarOrdenacao, emitAlternarOrdenacao,
}; }
}, },
}); })
</script> </script>

View file

@ -43,14 +43,14 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, PropType, ref } from "vue"; import { computed, defineComponent, type PropType, ref } from "vue"
import type { tipoEliTabelaAcao } from "./types-eli-tabela"; import type { tipoEliTabelaAcao } from "./types-eli-tabela"
type ItemAcao<T> = { type ItemAcao<T> = {
acao: tipoEliTabelaAcao<T>; acao: tipoEliTabelaAcao<T>
indice: number; indice: number
visivel: boolean; visivel: boolean
}; }
export default defineComponent({ export default defineComponent({
name: "EliTabelaMenuAcoes", name: "EliTabelaMenuAcoes",
@ -64,6 +64,7 @@ export default defineComponent({
required: true, required: true,
}, },
acoes: { acoes: {
// biome-ignore lint/suspicious/noExplicitAny: dynamic typing needed
type: Array as PropType<Array<ItemAcao<any>>>, type: Array as PropType<Array<ItemAcao<any>>>,
required: true, required: true,
}, },
@ -74,22 +75,24 @@ export default defineComponent({
}, },
}, },
emits: { emits: {
// biome-ignore lint/suspicious/noExplicitAny: dynamic typing needed
executar(payload: { acao: tipoEliTabelaAcao<any>; linha: unknown }) { executar(payload: { acao: tipoEliTabelaAcao<any>; linha: unknown }) {
return payload !== null && typeof payload === "object"; return payload !== null && typeof payload === "object"
}, },
}, },
setup(props, { emit, expose }) { setup(props, { emit, expose }) {
const menuEl = ref<HTMLElement | null>(null); const menuEl = ref<HTMLElement | null>(null)
expose({ menuEl }); expose({ menuEl })
const possuiAcoes = computed(() => props.acoes.length > 0); const possuiAcoes = computed(() => props.acoes.length > 0)
// biome-ignore lint/suspicious/noExplicitAny: dynamic typing needed
function emitExecutar(item: { acao: tipoEliTabelaAcao<any> }) { function emitExecutar(item: { acao: tipoEliTabelaAcao<any> }) {
if (!props.linha) return; if (!props.linha) return
emit("executar", { acao: item.acao, linha: props.linha }); emit("executar", { acao: item.acao, linha: props.linha })
} }
return { menuEl, possuiAcoes, emitExecutar }; return { menuEl, possuiAcoes, emitExecutar }
}, },
}); })
</script> </script>

View file

@ -72,19 +72,19 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, PropType, ref, watch } from "vue"; import { defineComponent, type PropType, ref, watch } from "vue"
import type { EliTabelaColunasConfig } from "./colunasStorage"; import type { EliTabelaColunasConfig } from "./colunasStorage"
import type { tipoEliColuna } from "./types-eli-tabela"; import type { tipoEliColuna } from "./types-eli-tabela"
type OrigemLista = "visiveis" | "invisiveis"; type OrigemLista = "visiveis" | "invisiveis"
type DragPayload = { type DragPayload = {
rotulo: string; rotulo: string
origem: OrigemLista; origem: OrigemLista
index: number; index: number
}; }
const DRAG_MIME = "application/x-eli-tabela-coluna"; const DRAG_MIME = "application/x-eli-tabela-coluna"
export default defineComponent({ export default defineComponent({
name: "EliTabelaModalColunas", name: "EliTabelaModalColunas",
@ -102,80 +102,89 @@ export default defineComponent({
required: true, required: true,
}, },
colunas: { colunas: {
// biome-ignore lint/suspicious/noExplicitAny: dynamic typing needed
type: Array as PropType<Array<tipoEliColuna<any>>>, type: Array as PropType<Array<tipoEliColuna<any>>>,
required: true, required: true,
}, },
}, },
emits: { emits: {
fechar() { fechar() {
return true; return true
}, },
salvar(_config: EliTabelaColunasConfig) { salvar(_config: EliTabelaColunasConfig) {
return true; return true
}, },
}, },
setup(props, { emit }) { setup(props, { emit }) {
const visiveisLocal = ref<string[]>([]); const visiveisLocal = ref<string[]>([])
const invisiveisLocal = ref<string[]>([]); const invisiveisLocal = ref<string[]>([])
function sincronizarEstado() { function sincronizarEstado() {
const todos = props.rotulosColunas; const todos = props.rotulosColunas
const configTemDados = const configTemDados =
(props.configInicial.visiveis?.length ?? 0) > 0 || (props.configInicial.visiveis?.length ?? 0) > 0 ||
(props.configInicial.invisiveis?.length ?? 0) > 0; (props.configInicial.invisiveis?.length ?? 0) > 0
const invisiveisPadraoSet = new Set( const invisiveisPadraoSet = new Set(
props.colunas.filter((c) => c.visivel === false).map((c) => c.rotulo) props.colunas.filter((c) => c.visivel === false).map((c) => c.rotulo),
); )
const invisiveisSet = configTemDados const invisiveisSet = configTemDados
? new Set(props.configInicial.invisiveis ?? []) ? new Set(props.configInicial.invisiveis ?? [])
: invisiveisPadraoSet; : invisiveisPadraoSet
const baseVisiveis = todos.filter((r) => !invisiveisSet.has(r)); const baseVisiveis = todos.filter((r) => !invisiveisSet.has(r))
// ordenação: aplica ordem salva (visiveis) e adiciona novas ao final // ordenação: aplica ordem salva (visiveis) e adiciona novas ao final
const ordemSalva = props.configInicial.visiveis ?? []; const ordemSalva = props.configInicial.visiveis ?? []
const setVis = new Set(baseVisiveis); const setVis = new Set(baseVisiveis)
const ordenadas: string[] = []; const ordenadas: string[] = []
for (const r of ordemSalva) { for (const r of ordemSalva) {
if (setVis.has(r)) ordenadas.push(r); if (setVis.has(r)) ordenadas.push(r)
} }
for (const r of baseVisiveis) { for (const r of baseVisiveis) {
if (!ordenadas.includes(r)) ordenadas.push(r); if (!ordenadas.includes(r)) ordenadas.push(r)
} }
visiveisLocal.value = ordenadas; visiveisLocal.value = ordenadas
// invisíveis: somente as que existem na tabela // invisíveis: somente as que existem na tabela
invisiveisLocal.value = todos.filter((r) => invisiveisSet.has(r)); invisiveisLocal.value = todos.filter((r) => invisiveisSet.has(r))
} }
watch( watch(
() => [props.aberto, props.rotulosColunas, props.configInicial, props.colunas] as const, () =>
[
props.aberto,
props.rotulosColunas,
props.configInicial,
props.colunas,
] as const,
() => { () => {
if (props.aberto) sincronizarEstado(); if (props.aberto) sincronizarEstado()
}, },
{ deep: true, immediate: true } { deep: true, immediate: true },
); )
function emitFechar() { function emitFechar() {
emit("fechar"); emit("fechar")
} }
function emitSalvar() { function emitSalvar() {
emit("salvar", { emit("salvar", {
visiveis: [...visiveisLocal.value], visiveis: [...visiveisLocal.value],
invisiveis: [...invisiveisLocal.value], invisiveis: [...invisiveisLocal.value],
}); })
} }
function writeDragData(e: DragEvent, payload: DragPayload) { function writeDragData(e: DragEvent, payload: DragPayload) {
try { try {
e.dataTransfer?.setData(DRAG_MIME, JSON.stringify(payload)); e.dataTransfer?.setData(DRAG_MIME, JSON.stringify(payload))
e.dataTransfer?.setData("text/plain", payload.rotulo); e.dataTransfer?.setData("text/plain", payload.rotulo)
e.dataTransfer!.effectAllowed = "move"; if (e.dataTransfer) {
e.dataTransfer.effectAllowed = "move"
}
} catch { } catch {
// ignore // ignore
} }
@ -183,72 +192,93 @@ export default defineComponent({
function readDragData(e: DragEvent): DragPayload | null { function readDragData(e: DragEvent): DragPayload | null {
try { try {
const raw = e.dataTransfer?.getData(DRAG_MIME); const raw = e.dataTransfer?.getData(DRAG_MIME)
if (!raw) return null; if (!raw) return null
const parsed = JSON.parse(raw); const parsed = JSON.parse(raw)
if (!parsed || typeof parsed.rotulo !== "string" || (parsed.origem !== "visiveis" && parsed.origem !== "invisiveis")) { if (
return null; !parsed ||
typeof parsed.rotulo !== "string" ||
(parsed.origem !== "visiveis" && parsed.origem !== "invisiveis")
) {
return null
} }
return parsed as DragPayload; return parsed as DragPayload
} catch { } catch {
return null; return null
} }
} }
function removerDaOrigem(payload: DragPayload) { function removerDaOrigem(payload: DragPayload) {
const origemArr = payload.origem === "visiveis" ? visiveisLocal.value : invisiveisLocal.value; const origemArr =
const idx = origemArr.indexOf(payload.rotulo); payload.origem === "visiveis"
if (idx >= 0) origemArr.splice(idx, 1); ? visiveisLocal.value
: invisiveisLocal.value
const idx = origemArr.indexOf(payload.rotulo)
if (idx >= 0) origemArr.splice(idx, 1)
} }
function inserirNoDestino(destino: OrigemLista, rotulo: string, index: number | null) { function inserirNoDestino(
const arr = destino === "visiveis" ? visiveisLocal.value : invisiveisLocal.value; destino: OrigemLista,
rotulo: string,
index: number | null,
) {
const arr =
destino === "visiveis" ? visiveisLocal.value : invisiveisLocal.value
// remove duplicatas // remove duplicatas
const existing = arr.indexOf(rotulo); const existing = arr.indexOf(rotulo)
if (existing >= 0) arr.splice(existing, 1); if (existing >= 0) arr.splice(existing, 1)
if (index === null || index < 0 || index > arr.length) { if (index === null || index < 0 || index > arr.length) {
arr.push(rotulo); arr.push(rotulo)
} else { } else {
arr.splice(index, 0, rotulo); arr.splice(index, 0, rotulo)
} }
} }
function onDragStart(e: DragEvent, rotulo: string, origem: OrigemLista, index: number) { function onDragStart(
writeDragData(e, { rotulo, origem, index }); e: DragEvent,
rotulo: string,
origem: OrigemLista,
index: number,
) {
writeDragData(e, { rotulo, origem, index })
} }
function onDropItem(e: DragEvent, destino: OrigemLista, index: number) { function onDropItem(e: DragEvent, destino: OrigemLista, index: number) {
const payload = readDragData(e); const payload = readDragData(e)
if (!payload) return; if (!payload) return
// remove da origem e insere no destino na posição do item // remove da origem e insere no destino na posição do item
removerDaOrigem(payload); removerDaOrigem(payload)
inserirNoDestino(destino, payload.rotulo, index); inserirNoDestino(destino, payload.rotulo, index)
// garante que uma coluna não fique nos 2 lados // garante que uma coluna não fique nos 2 lados
if (destino === "visiveis") { if (destino === "visiveis") {
const idxInv = invisiveisLocal.value.indexOf(payload.rotulo); const idxInv = invisiveisLocal.value.indexOf(payload.rotulo)
if (idxInv >= 0) invisiveisLocal.value.splice(idxInv, 1); if (idxInv >= 0) invisiveisLocal.value.splice(idxInv, 1)
} else { } else {
const idxVis = visiveisLocal.value.indexOf(payload.rotulo); const idxVis = visiveisLocal.value.indexOf(payload.rotulo)
if (idxVis >= 0) visiveisLocal.value.splice(idxVis, 1); if (idxVis >= 0) visiveisLocal.value.splice(idxVis, 1)
} }
} }
function onDropLista(e: DragEvent, destino: OrigemLista, _index: number | null) { function onDropLista(
const payload = readDragData(e); e: DragEvent,
if (!payload) return; destino: OrigemLista,
_index: number | null,
) {
const payload = readDragData(e)
if (!payload) return
removerDaOrigem(payload); removerDaOrigem(payload)
inserirNoDestino(destino, payload.rotulo, null); inserirNoDestino(destino, payload.rotulo, null)
if (destino === "visiveis") { if (destino === "visiveis") {
const idxInv = invisiveisLocal.value.indexOf(payload.rotulo); const idxInv = invisiveisLocal.value.indexOf(payload.rotulo)
if (idxInv >= 0) invisiveisLocal.value.splice(idxInv, 1); if (idxInv >= 0) invisiveisLocal.value.splice(idxInv, 1)
} else { } else {
const idxVis = visiveisLocal.value.indexOf(payload.rotulo); const idxVis = visiveisLocal.value.indexOf(payload.rotulo)
if (idxVis >= 0) visiveisLocal.value.splice(idxVis, 1); if (idxVis >= 0) visiveisLocal.value.splice(idxVis, 1)
} }
} }
@ -260,9 +290,9 @@ export default defineComponent({
onDragStart, onDragStart,
onDropItem, onDropItem,
onDropLista, onDropLista,
}; }
}, },
}); })
</script> </script>
<style> <style>

View file

@ -74,27 +74,39 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, PropType, ref, watch } from "vue"; import { computed, defineComponent, type PropType, ref, watch } from "vue"
import { EliEntradaTexto, EliEntradaNumero, EliEntradaDataHora } from "../EliEntrada"; import {
import type { ComponenteEntrada, TipoEntrada } from "../EliEntrada/tiposEntradas"; EliEntradaDataHora,
import type { tipoEliTabelaConsulta } from "./types-eli-tabela"; EliEntradaNumero,
EliEntradaTexto,
} from "../EliEntrada"
import type {
ComponenteEntrada,
TipoEntrada,
} from "../EliEntrada/tiposEntradas"
import type { tipoEliTabelaConsulta } from "./types-eli-tabela"
type FiltroBase<T> = NonNullable<tipoEliTabelaConsulta<T>["filtroAvancado"]>[number]; type FiltroBase<T> = NonNullable<
tipoEliTabelaConsulta<T>["filtroAvancado"]
>[number]
type LinhaFiltro<T> = { type LinhaFiltro<T> = {
coluna: keyof T; coluna: keyof T
entrada: ComponenteEntrada; entrada: ComponenteEntrada
operador: string; operador: string
valor: any; // biome-ignore lint/suspicious/noExplicitAny: dynamic value
}; valor: any
function isTipoEntrada(v: unknown): v is TipoEntrada {
return v === "texto" || v === "numero" || v === "dataHora";
} }
function isTipoEntrada(v: unknown): v is TipoEntrada {
return v === "texto" || v === "numero" || v === "dataHora"
}
// biome-ignore lint/suspicious/noExplicitAny: dynamic typing needed
function rotuloDoFiltro(f: FiltroBase<any>) { function rotuloDoFiltro(f: FiltroBase<any>) {
const rotulo = (f?.entrada?.[1] as any)?.rotulo; // biome-ignore lint/suspicious/noExplicitAny: dynamic access
return rotulo ? String(rotulo) : String(f?.coluna ?? "Filtro"); const rotulo = (f?.entrada?.[1] as any)?.rotulo
return rotulo ? String(rotulo) : String(f?.coluna ?? "Filtro")
} }
export default defineComponent({ export default defineComponent({
@ -102,10 +114,12 @@ export default defineComponent({
props: { props: {
aberto: { type: Boolean, required: true }, aberto: { type: Boolean, required: true },
filtrosBase: { filtrosBase: {
// biome-ignore lint/suspicious/noExplicitAny: dynamic filter type
type: Array as PropType<Array<FiltroBase<any>>>, type: Array as PropType<Array<FiltroBase<any>>>,
required: true, required: true,
}, },
modelo: { modelo: {
// biome-ignore lint/suspicious/noExplicitAny: dynamic model
type: Array as PropType<Array<any>>, type: Array as PropType<Array<any>>,
required: true, required: true,
}, },
@ -113,67 +127,82 @@ export default defineComponent({
emits: { emits: {
fechar: () => true, fechar: () => true,
limpar: () => true, limpar: () => true,
// biome-ignore lint/suspicious/noExplicitAny: dynamic lines
salvar: (_linhas: any[]) => true, salvar: (_linhas: any[]) => true,
}, },
setup(props, { emit }) { setup(props, { emit }) {
const linhas = ref<Array<LinhaFiltro<any>>>([]); // biome-ignore lint/suspicious/noExplicitAny: dynamic value
const linhas = ref<Array<LinhaFiltro<any>>>([])
const colunaParaAdicionar = ref<string>(""); const colunaParaAdicionar = ref<string>("")
const colunasDisponiveis = computed(() => (props.filtrosBase ?? []).map((b) => String(b.coluna))); const colunasDisponiveis = computed(() =>
(props.filtrosBase ?? []).map((b) => String(b.coluna)),
)
const opcoesParaAdicionar = computed(() => { const opcoesParaAdicionar = computed(() => {
const usadas = new Set(linhas.value.map((l) => String(l.coluna))); const usadas = new Set(linhas.value.map((l) => String(l.coluna)))
return (props.filtrosBase ?? []).filter((b) => !usadas.has(String(b.coluna))); return (props.filtrosBase ?? []).filter(
}); (b) => !usadas.has(String(b.coluna)),
)
})
function componenteEntrada(entrada: ComponenteEntrada) { function componenteEntrada(entrada: ComponenteEntrada) {
const tipo = entrada?.[0]; const tipo = entrada?.[0]
if (tipo === "numero") return EliEntradaNumero; if (tipo === "numero") return EliEntradaNumero
if (tipo === "dataHora") return EliEntradaDataHora; if (tipo === "dataHora") return EliEntradaDataHora
return EliEntradaTexto; return EliEntradaTexto
} }
function opcoesEntrada(entrada: ComponenteEntrada) { function opcoesEntrada(entrada: ComponenteEntrada) {
// o rótulo vem do próprio componente (entrada[1].rotulo) // o rótulo vem do próprio componente (entrada[1].rotulo)
return (entrada?.[1] as any) ?? { rotulo: "" }; // biome-ignore lint/suspicious/noExplicitAny: dynamic options
return (entrada?.[1] as any) ?? { rotulo: "" }
} }
function valorInicialPorEntrada(entrada: ComponenteEntrada) { function valorInicialPorEntrada(entrada: ComponenteEntrada) {
const tipo = entrada?.[0]; const tipo = entrada?.[0]
if (tipo === "numero") return null; if (tipo === "numero") return null
return ""; return ""
} }
function normalizarModelo() { function normalizarModelo() {
const base = props.filtrosBase ?? []; const base = props.filtrosBase ?? []
const modelo = Array.isArray(props.modelo) ? props.modelo : []; const modelo = Array.isArray(props.modelo) ? props.modelo : []
// biome-ignore lint/suspicious/noExplicitAny: dynamic model
linhas.value = modelo.map((m: any) => { linhas.value = modelo.map((m: any) => {
// operador vem travado no base // operador vem travado no base
const baseItem = base.find((b) => String(b.coluna) === String(m.coluna)) ?? base[0]; const baseItem =
const entrada = (baseItem?.entrada ?? m.entrada) as ComponenteEntrada; base.find((b) => String(b.coluna) === String(m.coluna)) ?? base[0]
const col = (baseItem?.coluna ?? m.coluna) as any; const entrada = (baseItem?.entrada ?? m.entrada) as ComponenteEntrada
const op = String(baseItem?.operador ?? "="); // biome-ignore lint/suspicious/noExplicitAny: dynamic column
const val = m.valor ?? valorInicialPorEntrada(entrada); const col = (baseItem?.coluna ?? m.coluna) as any
const op = String(baseItem?.operador ?? "=")
const val = m.valor ?? valorInicialPorEntrada(entrada)
return { return {
coluna: col, coluna: col,
operador: op, operador: op,
entrada, entrada,
valor: val, valor: val,
} as LinhaFiltro<any>; // biome-ignore lint/suspicious/noExplicitAny: dynamic cast
}); } as LinhaFiltro<any>
})
// se vazio e existe base, adiciona 1 linha default // se vazio e existe base, adiciona 1 linha default
// não auto-adiciona; usuário escolhe quais filtros quer usar // não auto-adiciona; usuário escolhe quais filtros quer usar
// se algum filtro mudou a coluna para valor inválido, ajusta // se algum filtro mudou a coluna para valor inválido, ajusta
for (const l of linhas.value) { for (const l of linhas.value) {
if (!colunasDisponiveis.value.includes(String(l.coluna))) continue; if (!colunasDisponiveis.value.includes(String(l.coluna))) continue
l.operador = String((base.find((b) => String(b.coluna) === String(l.coluna))?.operador ?? "=")); l.operador = String(
base.find((b) => String(b.coluna) === String(l.coluna))?.operador ??
"=",
)
// sanity // sanity
if (l.entrada && !isTipoEntrada(l.entrada[0])) { if (l.entrada && !isTipoEntrada(l.entrada[0])) {
l.entrada = ["texto", { rotulo: "Valor" }] as any; // biome-ignore lint/suspicious/noExplicitAny: dynamic sanity
l.entrada = ["texto", { rotulo: "Valor" }] as any
} }
} }
} }
@ -181,38 +210,42 @@ export default defineComponent({
watch( watch(
() => [props.aberto, props.filtrosBase, props.modelo] as const, () => [props.aberto, props.filtrosBase, props.modelo] as const,
() => { () => {
if (props.aberto) normalizarModelo(); if (props.aberto) normalizarModelo()
}, },
{ deep: true, immediate: true } { deep: true, immediate: true },
); )
function adicionar() { function adicionar() {
if (!colunaParaAdicionar.value) return; if (!colunaParaAdicionar.value) return
const b0 = (props.filtrosBase ?? []).find((b) => String(b.coluna) === String(colunaParaAdicionar.value)); const b0 = (props.filtrosBase ?? []).find(
if (!b0) return; (b) => String(b.coluna) === String(colunaParaAdicionar.value),
)
if (!b0) return
// evita repetição // evita repetição
if (linhas.value.some((l) => String(l.coluna) === String(b0.coluna))) return; if (linhas.value.some((l) => String(l.coluna) === String(b0.coluna)))
return
linhas.value.push({ linhas.value.push({
// biome-ignore lint/suspicious/noExplicitAny: dynamic column
coluna: b0.coluna as any, coluna: b0.coluna as any,
entrada: b0.entrada, entrada: b0.entrada,
operador: String(b0.operador ?? "="), operador: String(b0.operador ?? "="),
valor: valorInicialPorEntrada(b0.entrada), valor: valorInicialPorEntrada(b0.entrada),
}); })
colunaParaAdicionar.value = ""; colunaParaAdicionar.value = ""
} }
function remover(idx: number) { function remover(idx: number) {
linhas.value.splice(idx, 1); linhas.value.splice(idx, 1)
} }
function emitFechar() { function emitFechar() {
emit("fechar"); emit("fechar")
} }
function emitLimpar() { function emitLimpar() {
emit("limpar"); emit("limpar")
} }
function emitSalvar() { function emitSalvar() {
@ -221,8 +254,8 @@ export default defineComponent({
linhas.value.map((l) => ({ linhas.value.map((l) => ({
coluna: l.coluna, coluna: l.coluna,
valor: l.valor, valor: l.valor,
})) })),
); )
} }
return { return {
@ -238,9 +271,9 @@ export default defineComponent({
emitSalvar, emitSalvar,
emitLimpar, emitLimpar,
rotuloDoFiltro, rotuloDoFiltro,
}; }
}, },
}); })
</script> </script>
<style> <style>

View file

@ -1,56 +1,82 @@
<template> <template>
<nav <div class="eli-tabela__rodape">
v-if="totalPaginasExibidas > 1" <div
class="eli-tabela__paginacao" v-if="acoes.length > 0"
role="navigation" class="eli-tabela__acoes-inferiores"
aria-label="Paginação de resultados" style="margin-right: auto"
> >
<button <button
type="button" v-for="(botao, indice) in acoes"
class="eli-tabela__pagina-botao" :key="`${botao.rotulo}-${indice}`"
:disabled="anteriorDesabilitado" type="button"
aria-label="Página anterior" class="eli-tabela__acao-inferior"
@click="irParaPagina(paginaAtual - 1)" :style="botao.cor ? { borderColor: botao.cor, color: botao.cor } : undefined"
@click="botao.acao(parametrosConsulta)"
>
<component
v-if="botao.icone"
:is="botao.icone"
class="eli-tabela__acoes-cabecalho-icone"
:size="16"
:stroke-width="2"
/>
<span class="eli-tabela__acoes-cabecalho-rotulo">{{ botao.rotulo }}</span>
</button>
</div>
<nav
v-if="totalPaginasExibidas > 1"
class="eli-tabela__paginacao"
role="navigation"
aria-label="Paginação de resultados"
> >
<<
</button>
<template v-for="(item, index) in botoes" :key="`${item.label}-${index}`">
<span
v-if="item.ehEllipsis"
class="eli-tabela__pagina-ellipsis"
aria-hidden="true"
>
{{ item.label }}
</span>
<button <button
v-else
type="button" type="button"
class="eli-tabela__pagina-botao" class="eli-tabela__pagina-botao"
:class="item.ativo ? 'eli-tabela__pagina-botao--ativo' : undefined" :disabled="anteriorDesabilitado"
:disabled="item.ativo" aria-label="Página anterior"
:aria-current="item.ativo ? 'page' : undefined" @click="irParaPagina(paginaAtual - 1)"
:aria-label="`Ir para página ${item.label}`"
@click="irParaPagina(item.pagina)"
> >
{{ item.label }} &lt;&lt;
</button> </button>
</template>
<button <template v-for="(item, index) in botoes" :key="`${item.label}-${index}`">
type="button" <span
class="eli-tabela__pagina-botao" v-if="item.ehEllipsis"
:disabled="proximaDesabilitada" class="eli-tabela__pagina-ellipsis"
aria-label="Próxima página" aria-hidden="true"
@click="irParaPagina(paginaAtual + 1)" >
> {{ item.label }}
>> </span>
</button> <button
</nav> v-else
type="button"
class="eli-tabela__pagina-botao"
:class="item.ativo ? 'eli-tabela__pagina-botao--ativo' : undefined"
:disabled="item.ativo"
:aria-current="item.ativo ? 'page' : undefined"
:aria-label="`Ir para página ${item.label}`"
@click="irParaPagina(item.pagina)"
>
{{ item.label }}
</button>
</template>
<button
type="button"
class="eli-tabela__pagina-botao"
:disabled="proximaDesabilitada"
aria-label="Próxima página"
@click="irParaPagina(paginaAtual + 1)"
>
&gt;&gt;
</button>
</nav>
</div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent } from "vue"; import { computed, defineComponent, type PropType } from "vue"
export default defineComponent({ export default defineComponent({
name: "EliTabelaPaginacao", name: "EliTabelaPaginacao",
@ -67,10 +93,29 @@ export default defineComponent({
type: Number, type: Number,
required: false, required: false,
}, },
acoes: {
type: Array as PropType<
Array<{
// biome-ignore lint/suspicious/noExplicitAny: dynamic icon
icone?: any
cor?: string
rotulo: string
// biome-ignore lint/suspicious/noExplicitAny: dynamic action
acao: (params?: any) => void
}>
>,
required: false,
default: () => [],
},
parametrosConsulta: {
// biome-ignore lint/suspicious/noExplicitAny: dynamic params
type: Object as PropType<any>,
required: false,
},
}, },
emits: { emits: {
alterar(pagina: number) { alterar(pagina: number) {
return Number.isFinite(pagina); return Number.isFinite(pagina)
}, },
}, },
setup(props, { emit }) { setup(props, { emit }) {
@ -79,12 +124,12 @@ export default defineComponent({
* uma navegação confortável, mesmo quando o consumidor não informa o valor. * uma navegação confortável, mesmo quando o consumidor não informa o valor.
*/ */
const maximoBotoesVisiveis = computed(() => { const maximoBotoesVisiveis = computed(() => {
const valor = props.maximoBotoes; const valor = props.maximoBotoes
if (typeof valor === "number" && valor >= 5) { if (typeof valor === "number" && valor >= 5) {
return Math.floor(valor); return Math.floor(valor)
} }
return 7; return 7
}); })
/** /**
* Constrói a lista de botões/reticências que serão exibidos na paginação. * Constrói a lista de botões/reticências que serão exibidos na paginação.
@ -92,62 +137,62 @@ export default defineComponent({
* demais de forma dinâmica ao redor da página atual. * demais de forma dinâmica ao redor da página atual.
*/ */
const botoes = computed(() => { const botoes = computed(() => {
const total = props.totalPaginas; const total = props.totalPaginas
const atual = props.pagina; const atual = props.pagina
const limite = maximoBotoesVisiveis.value; const limite = maximoBotoesVisiveis.value
const resultado: Array<{ const resultado: Array<{
label: string; label: string
pagina?: number; pagina?: number
ativo?: boolean; ativo?: boolean
ehEllipsis?: boolean; ehEllipsis?: boolean
}> = []; }> = []
const adicionarPagina = (pagina: number) => { const adicionarPagina = (pagina: number) => {
resultado.push({ resultado.push({
label: String(pagina), label: String(pagina),
pagina, pagina,
ativo: pagina === atual, ativo: pagina === atual,
}); })
}; }
const adicionarReticencias = () => { const adicionarReticencias = () => {
resultado.push({ label: "…", ehEllipsis: true }); resultado.push({ label: "…", ehEllipsis: true })
}; }
if (total <= limite) { if (total <= limite) {
for (let pagina = 1; pagina <= total; pagina += 1) { for (let pagina = 1; pagina <= total; pagina += 1) {
adicionarPagina(pagina); adicionarPagina(pagina)
} }
return resultado; return resultado
} }
const visiveisCentrais = Math.max(3, limite - 2); const visiveisCentrais = Math.max(3, limite - 2)
let inicio = Math.max(2, atual - Math.floor(visiveisCentrais / 2)); let inicio = Math.max(2, atual - Math.floor(visiveisCentrais / 2))
let fim = inicio + visiveisCentrais - 1; let fim = inicio + visiveisCentrais - 1
if (fim >= total) { if (fim >= total) {
fim = total - 1; fim = total - 1
inicio = fim - visiveisCentrais + 1; inicio = fim - visiveisCentrais + 1
} }
adicionarPagina(1); adicionarPagina(1)
if (inicio > 2) { if (inicio > 2) {
adicionarReticencias(); adicionarReticencias()
} }
for (let pagina = inicio; pagina <= fim; pagina += 1) { for (let pagina = inicio; pagina <= fim; pagina += 1) {
adicionarPagina(pagina); adicionarPagina(pagina)
} }
if (fim < total - 1) { if (fim < total - 1) {
adicionarReticencias(); adicionarReticencias()
} }
adicionarPagina(total); adicionarPagina(total)
return resultado; return resultado
}); })
/** /**
* Emite a requisição de mudança de página garantindo que o valor esteja * Emite a requisição de mudança de página garantindo que o valor esteja
@ -155,18 +200,20 @@ export default defineComponent({
*/ */
function irParaPagina(pagina: number | undefined) { function irParaPagina(pagina: number | undefined) {
if (!pagina) { if (!pagina) {
return; return
} }
const alvo = Math.min(Math.max(1, pagina), props.totalPaginas); const alvo = Math.min(Math.max(1, pagina), props.totalPaginas)
if (alvo !== props.pagina) { if (alvo !== props.pagina) {
emit("alterar", alvo); emit("alterar", alvo)
} }
} }
const anteriorDesabilitado = computed(() => props.pagina <= 1); const anteriorDesabilitado = computed(() => props.pagina <= 1)
const proximaDesabilitada = computed(() => props.pagina >= props.totalPaginas); const proximaDesabilitada = computed(
const paginaAtual = computed(() => props.pagina); () => props.pagina >= props.totalPaginas,
const totalPaginasExibidas = computed(() => props.totalPaginas); )
const paginaAtual = computed(() => props.pagina)
const totalPaginasExibidas = computed(() => props.totalPaginas)
return { return {
botoes, botoes,
@ -175,9 +222,9 @@ export default defineComponent({
proximaDesabilitada, proximaDesabilitada,
paginaAtual, paginaAtual,
totalPaginasExibidas, totalPaginasExibidas,
}; }
}, },
}); })
</script> </script>
<style> <style>
@ -241,4 +288,31 @@ export default defineComponent({
color: rgba(107, 114, 128, 0.85); color: rgba(107, 114, 128, 0.85);
font-size: 0.9rem; font-size: 0.9rem;
} }
.eli-tabela__acao-inferior {
display: inline-flex;
align-items: center;
gap: 6px;
height: 34px;
padding: 0 14px;
border-radius: 8px;
border: 1px solid #16a34a; /* default green */
background: #ffffff;
color: #16a34a;
font-size: 0.875rem;
font-weight: 500;
line-height: 1;
cursor: pointer;
transition: background-color 0.2s ease, color 0.2s ease;
}
.eli-tabela__acao-inferior:hover,
.eli-tabela__acao-inferior:focus-visible {
background-color: #f0fdf4;
}
.eli-tabela__acao-inferior:focus-visible {
outline: 2px solid #16a34a;
outline-offset: 2px;
}
</style> </style>

View file

@ -8,11 +8,15 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import type { Component } from "vue"; import type { Component } from "vue"
import { computed, defineComponent, PropType } from "vue"; import { computed, defineComponent, type PropType } from "vue"
import type { tipoComponenteCelula, tipoTabelaCelula, tiposTabelaCelulas } from "../types-eli-tabela"; import type {
import { registryTabelaCelulas } from "./registryTabelaCelulas"; tipoComponenteCelula,
tiposTabelaCelulas,
tipoTabelaCelula,
} from "../types-eli-tabela"
import { registryTabelaCelulas } from "./registryTabelaCelulas"
export default defineComponent({ export default defineComponent({
name: "EliTabelaCelula", name: "EliTabelaCelula",
@ -24,16 +28,20 @@ export default defineComponent({
}, },
}, },
setup(props) { setup(props) {
const tipo = computed(() => props.celula[0] as tipoTabelaCelula); const tipo = computed(() => props.celula[0] as tipoTabelaCelula)
const dados = computed(() => props.celula[1] as tiposTabelaCelulas[tipoTabelaCelula]); const dados = computed(
() => props.celula[1] as tiposTabelaCelulas[tipoTabelaCelula],
)
// Observação: mantemos o registry tipado, mas o TS do template não consegue // Observação: mantemos o registry tipado, mas o TS do template não consegue
// fazer narrowing do componente com base em `tipo`, então tipamos como `Component`. // fazer narrowing do componente com base em `tipo`, então tipamos como `Component`.
const Componente = computed(() => registryTabelaCelulas[tipo.value] as unknown as Component); const Componente = computed(
() => registryTabelaCelulas[tipo.value] as unknown as Component,
)
const dadosParaComponente = computed(() => dados.value); const dadosParaComponente = computed(() => dados.value)
return { Componente, dadosParaComponente }; return { Componente, dadosParaComponente }
}, },
}); })
</script> </script>

View file

@ -12,14 +12,9 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, PropType } from "vue"; import { dayjsbr } from "p-comuns"
import dayjs from "dayjs"; import { computed, defineComponent, type PropType } from "vue"
import relativeTime from "dayjs/plugin/relativeTime"; import type { tiposTabelaCelulas } from "./tiposTabelaCelulas"
import type { tiposTabelaCelulas } from "./tiposTabelaCelulas";
// Necessário para `fromNow()`.
dayjs.extend(relativeTime);
export default defineComponent({ export default defineComponent({
name: "EliTabelaCelulaData", name: "EliTabelaCelulaData",
@ -31,27 +26,27 @@ export default defineComponent({
}, },
setup({ dados }) { setup({ dados }) {
const textoData = computed(() => { const textoData = computed(() => {
const valorIso = dados?.valor; const valorIso = dados?.valor
if (!valorIso) return ""; if (!valorIso) return ""
const formato = dados?.formato ?? "data"; const formato = dados?.formato ?? "data"
if (formato === "relativo") { if (formato === "relativo") {
return dayjs(valorIso).fromNow(); return dayjsbr(valorIso).fromNow()
} }
if (formato === "data_hora") { if (formato === "data_hora") {
// Padrão pt-BR simples (sem depender de locale do dayjs) // Padrão pt-BR simples (sem depender de locale do dayjsbr)
return dayjs(valorIso).format("DD/MM/YYYY HH:mm"); return dayjsbr(valorIso).format("DD/MM/YYYY HH:mm")
} }
// formato === "data" // formato === "data"
return dayjs(valorIso).format("DD/MM/YYYY"); return dayjsbr(valorIso).format("DD/MM/YYYY")
}); })
return { dados, textoData }; return { dados, textoData }
}, },
}); })
</script> </script>
<style> <style>

View file

@ -10,9 +10,22 @@
<span v-else>{{ textoNumero }}</span> <span v-else>{{ textoNumero }}</span>
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, PropType } from "vue" import { computed, defineComponent, type PropType } from "vue"
import type { tiposTabelaCelulas } from "./tiposTabelaCelulas"; import type { tiposTabelaCelulas } from "./tiposTabelaCelulas"
export default defineComponent({ export default defineComponent({
name: "EliTabelaCelulaNumero", name: "EliTabelaCelulaNumero",
@ -25,15 +38,15 @@ export default defineComponent({
setup({ dados }) { setup({ dados }) {
const textoNumero = computed(() => { const textoNumero = computed(() => {
// Mantemos o comportamento anterior (trocar "." por ","), mas agora suportamos prefixo/sufixo. // Mantemos o comportamento anterior (trocar "." por ","), mas agora suportamos prefixo/sufixo.
const numero = String(dados?.numero).replace(".", ","); const numero = String(dados?.numero).replace(".", ",")
const prefixo = dados?.prefixo?.trim(); const prefixo = dados?.prefixo?.trim()
const sufixo = dados?.sufixo?.trim(); const sufixo = dados?.sufixo?.trim()
const inicio = prefixo ? `${prefixo} ` : ""; const inicio = prefixo ? `${prefixo} ` : ""
const fim = sufixo ? ` ${sufixo}` : ""; const fim = sufixo ? ` ${sufixo}` : ""
return `${inicio}${numero}${fim}`; return `${inicio}${numero}${fim}`
}); })
return { dados, textoNumero } return { dados, textoNumero }
}, },

View file

@ -23,10 +23,10 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, PropType } from "vue"; import { defineComponent, type PropType } from "vue"
import { VChip } from "vuetify/components"; import { VChip } from "vuetify/components"
import type { tiposTabelaCelulas } from "./tiposTabelaCelulas"; import type { tiposTabelaCelulas } from "./tiposTabelaCelulas"
export default defineComponent({ export default defineComponent({
name: "EliTabelaCelulaTags", name: "EliTabelaCelulaTags",
@ -38,9 +38,9 @@ export default defineComponent({
}, },
}, },
setup({ dados }) { setup({ dados }) {
return { dados }; return { dados }
}, },
}); })
</script> </script>
<style> <style>

View file

@ -11,8 +11,8 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, PropType } from "vue" import { defineComponent, type PropType } from "vue"
import type { tiposTabelaCelulas } from "./tiposTabelaCelulas"; import type { tiposTabelaCelulas } from "./tiposTabelaCelulas"
export default defineComponent({ export default defineComponent({
name: "EliTabelaCelulaTextoSimples", name: "EliTabelaCelulaTextoSimples",
@ -23,12 +23,9 @@ export default defineComponent({
}, },
}, },
data() { data() {
return { return {}
}
},
methods: {
}, },
methods: {},
setup({ dados }) { setup({ dados }) {
return { dados } return { dados }
}, },

View file

@ -13,8 +13,8 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, PropType } from "vue"; import { defineComponent, type PropType } from "vue"
import type { tiposTabelaCelulas } from "./tiposTabelaCelulas"; import type { tiposTabelaCelulas } from "./tiposTabelaCelulas"
export default defineComponent({ export default defineComponent({
name: "EliTabelaCelulaTextoTruncado", name: "EliTabelaCelulaTextoTruncado",
@ -24,9 +24,9 @@ export default defineComponent({
}, },
}, },
setup({ dados }) { setup({ dados }) {
return { dados }; return { dados }
}, },
}); })
</script> </script>
<style> <style>

View file

@ -1,11 +1,10 @@
import type { Component } from "vue"; import type { Component } from "vue"
import EliTabelaCelulaData from "./EliTabelaCelulaData.vue"
import EliTabelaCelulaTextoSimples from "./EliTabelaCelulaTextoSimples.vue"; import EliTabelaCelulaNumero from "./EliTabelaCelulaNumero.vue"
import EliTabelaCelulaTextoTruncado from "./EliTabelaCelulaTextoTruncado.vue"; import EliTabelaCelulaTags from "./EliTabelaCelulaTags.vue"
import EliTabelaCelulaNumero from "./EliTabelaCelulaNumero.vue"; import EliTabelaCelulaTextoSimples from "./EliTabelaCelulaTextoSimples.vue"
import EliTabelaCelulaTags from "./EliTabelaCelulaTags.vue"; import EliTabelaCelulaTextoTruncado from "./EliTabelaCelulaTextoTruncado.vue"
import EliTabelaCelulaData from "./EliTabelaCelulaData.vue"; import type { tipoTabelaCelula } from "./tiposTabelaCelulas"
import type { tipoTabelaCelula } from "./tiposTabelaCelulas";
export const registryTabelaCelulas = { export const registryTabelaCelulas = {
textoSimples: EliTabelaCelulaTextoSimples, textoSimples: EliTabelaCelulaTextoSimples,
@ -13,4 +12,4 @@ export const registryTabelaCelulas = {
numero: EliTabelaCelulaNumero, numero: EliTabelaCelulaNumero,
tags: EliTabelaCelulaTags, tags: EliTabelaCelulaTags,
data: EliTabelaCelulaData, data: EliTabelaCelulaData,
} as const satisfies Record<tipoTabelaCelula, Component>; } as const satisfies Record<tipoTabelaCelula, Component>

View file

@ -2,48 +2,47 @@
* Tipagem dos dados de entrada dos componentes de celulas * Tipagem dos dados de entrada dos componentes de celulas
*/ */
import type { LucideIcon } from "lucide-vue-next"; import type { LucideIcon } from "lucide-vue-next"
export type tiposTabelaCelulas = { export type tiposTabelaCelulas = {
textoSimples: { textoSimples: {
texto: string; texto: string
acao?: () => void; acao?: () => void
}; }
textoTruncado: { textoTruncado: {
texto: string; texto: string
acao?: () => void; acao?: () => void
}; }
numero: { numero: {
numero: number; numero: number
/** Texto opcional exibido antes do número (ex.: "R$", "≈"). */ /** Texto opcional exibido antes do número (ex.: "R$", "≈"). */
prefixo?: string; prefixo?: string
/** Texto opcional exibido depois do número (ex.: "kg", "%"). */ /** Texto opcional exibido depois do número (ex.: "kg", "%"). */
sufixo?: string; sufixo?: string
acao?: () => void; acao?: () => void
}; }
tags: { tags: {
opcoes: { opcoes: {
/** Texto exibido dentro da tag. */ /** Texto exibido dentro da tag. */
rotulo: string; rotulo: string
/** Cor do chip (segue as cores do Vuetify, ex.: "primary", "success", "error"). */ /** Cor do chip (segue as cores do Vuetify, ex.: "primary", "success", "error"). */
cor?: string; cor?: string
/** Ícone (Lucide) opcional exibido antes do rótulo. */ /** Ícone (Lucide) opcional exibido antes do rótulo. */
icone?: LucideIcon; icone?: LucideIcon
/** Ação opcional da tag. Quando existir, o chip vira clicável. */ /** Ação opcional da tag. Quando existir, o chip vira clicável. */
acao?: () => void; acao?: () => void
}[]; }[]
}; }
data: { data: {
/** Valor em ISO 8601 (ex.: "2026-01-09T16:15:00Z"). */ /** Valor em ISO 8601 (ex.: "2026-01-09T16:15:00Z"). */
valor: string; valor: string
/** Define o formato de exibição. */ /** Define o formato de exibição. */
formato: "data" | "data_hora" | "relativo"; formato: "data" | "data_hora" | "relativo"
/** Ação opcional ao clicar no valor. */ /** Ação opcional ao clicar no valor. */
acao?: () => void; acao?: () => void
}; }
}; }
export type tipoTabelaCelula = keyof tiposTabelaCelulas;
export type tipoTabelaCelula = keyof tiposTabelaCelulas

View file

@ -1,40 +1,55 @@
export type EliTabelaColunasConfig = { export type EliTabelaColunasConfig = {
/** Rotulos das colunas visiveis (em ordem). */ /** Rotulos das colunas visiveis (em ordem). */
visiveis: string[]; visiveis: string[]
/** Rotulos das colunas invisiveis. */ /** Rotulos das colunas invisiveis. */
invisiveis: string[]; invisiveis: string[]
}; }
const STORAGE_PREFIX = "eli:tabela"; const STORAGE_PREFIX = "eli:tabela"
export function storageKeyColunas(nomeTabela: string) { export function storageKeyColunas(nomeTabela: string) {
return `${STORAGE_PREFIX}:${nomeTabela}:colunas`; return `${STORAGE_PREFIX}:${nomeTabela}:colunas`
} }
function normalizarConfig(valor: unknown): EliTabelaColunasConfig { function normalizarConfig(valor: unknown): EliTabelaColunasConfig {
if (!valor || typeof valor !== "object") { if (!valor || typeof valor !== "object") {
return { visiveis: [], invisiveis: [] }; return { visiveis: [], invisiveis: [] }
} }
const v = valor as any; // biome-ignore lint/suspicious/noExplicitAny: dynamic config
const visiveis = Array.isArray(v.visiveis) ? v.visiveis.filter((x: any) => typeof x === "string") : []; const v = valor as any
const invisiveis = Array.isArray(v.invisiveis) ? v.invisiveis.filter((x: any) => typeof x === "string") : []; const visiveis = Array.isArray(v.visiveis)
return { visiveis, invisiveis }; ? // biome-ignore lint/suspicious/noExplicitAny: dynamic array item
v.visiveis.filter((x: any) => typeof x === "string")
: []
const invisiveis = Array.isArray(v.invisiveis)
? // biome-ignore lint/suspicious/noExplicitAny: dynamic array item
v.invisiveis.filter((x: any) => typeof x === "string")
: []
return { visiveis, invisiveis }
} }
export function carregarConfigColunas(nomeTabela: string): EliTabelaColunasConfig { export function carregarConfigColunas(
nomeTabela: string,
): EliTabelaColunasConfig {
try { try {
const raw = window.localStorage.getItem(storageKeyColunas(nomeTabela)); const raw = window.localStorage.getItem(storageKeyColunas(nomeTabela))
if (!raw) return { visiveis: [], invisiveis: [] }; if (!raw) return { visiveis: [], invisiveis: [] }
return normalizarConfig(JSON.parse(raw)); return normalizarConfig(JSON.parse(raw))
} catch { } catch {
return { visiveis: [], invisiveis: [] }; return { visiveis: [], invisiveis: [] }
} }
} }
export function salvarConfigColunas(nomeTabela: string, config: EliTabelaColunasConfig) { export function salvarConfigColunas(
nomeTabela: string,
config: EliTabelaColunasConfig,
) {
try { try {
window.localStorage.setItem(storageKeyColunas(nomeTabela), JSON.stringify(normalizarConfig(config))); window.localStorage.setItem(
storageKeyColunas(nomeTabela),
JSON.stringify(normalizarConfig(config)),
)
} catch { } catch {
// ignore // ignore
} }
@ -42,7 +57,7 @@ export function salvarConfigColunas(nomeTabela: string, config: EliTabelaColunas
export function limparConfigColunas(nomeTabela: string) { export function limparConfigColunas(nomeTabela: string) {
try { try {
window.localStorage.removeItem(storageKeyColunas(nomeTabela)); window.localStorage.removeItem(storageKeyColunas(nomeTabela))
} catch { } catch {
// ignore // ignore
} }

View file

@ -1,26 +1,35 @@
export type EliTabelaFiltroAvancadoSalvo<T> = Array<{ export type EliTabelaFiltroAvancadoSalvo<T> = Array<{
coluna: keyof T coluna: keyof T
// biome-ignore lint/suspicious/noExplicitAny: dynamic value
valor: any valor: any
}>; }>
function key(nomeTabela: string) { function key(nomeTabela: string) {
return `eli_tabela:${nomeTabela}:filtro_avancado`; return `eli_tabela:${nomeTabela}:filtro_avancado`
} }
export function carregarFiltroAvancado<T>(nomeTabela: string): EliTabelaFiltroAvancadoSalvo<T> { export function carregarFiltroAvancado<T>(
nomeTabela: string,
): EliTabelaFiltroAvancadoSalvo<T> {
try { try {
const raw = localStorage.getItem(key(nomeTabela)); const raw = localStorage.getItem(key(nomeTabela))
if (!raw) return [] as unknown as EliTabelaFiltroAvancadoSalvo<T>; if (!raw) return [] as unknown as EliTabelaFiltroAvancadoSalvo<T>
const parsed = JSON.parse(raw); const parsed = JSON.parse(raw)
return Array.isArray(parsed) ? (parsed as EliTabelaFiltroAvancadoSalvo<T>) : ([] as any); return Array.isArray(parsed)
? (parsed as EliTabelaFiltroAvancadoSalvo<T>)
: // biome-ignore lint/suspicious/noExplicitAny: dynamic cast
([] as any)
} catch { } catch {
return [] as unknown as EliTabelaFiltroAvancadoSalvo<T>; return [] as unknown as EliTabelaFiltroAvancadoSalvo<T>
} }
} }
export function salvarFiltroAvancado<T>(nomeTabela: string, filtros: EliTabelaFiltroAvancadoSalvo<T>) { export function salvarFiltroAvancado<T>(
nomeTabela: string,
filtros: EliTabelaFiltroAvancadoSalvo<T>,
) {
try { try {
localStorage.setItem(key(nomeTabela), JSON.stringify(filtros ?? [])); localStorage.setItem(key(nomeTabela), JSON.stringify(filtros ?? []))
} catch { } catch {
// ignore // ignore
} }
@ -28,7 +37,7 @@ export function salvarFiltroAvancado<T>(nomeTabela: string, filtros: EliTabelaFi
export function limparFiltroAvancado(nomeTabela: string) { export function limparFiltroAvancado(nomeTabela: string) {
try { try {
localStorage.removeItem(key(nomeTabela)); localStorage.removeItem(key(nomeTabela))
} catch { } catch {
// ignore // ignore
} }

View file

@ -1,7 +1,6 @@
export { default as EliTabela } from "./EliTabela.vue"; export * from "./celulas/tiposTabelaCelulas"
export { default as EliTabela } from "./EliTabela.vue"
export * from "./types-eli-tabela"; export * from "./types-eli-tabela"
export * from "./celulas/tiposTabelaCelulas";
// Helper para construção de células tipadas. // Helper para construção de células tipadas.
export { celulaTabela } from "./types-eli-tabela"; export { celulaTabela } from "./types-eli-tabela"

View file

@ -1,18 +1,19 @@
import type { tipoResposta } from "p-respostas"; import type { LucideIcon } from "lucide-vue-next"
import type { LucideIcon } from "lucide-vue-next"; import type { operadores, zFiltro } from "p-comuns"
import type { tipoTabelaCelula, tiposTabelaCelulas } from "./celulas/tiposTabelaCelulas"; import type { tipoResposta } from "p-respostas"
import { operadores, zFiltro } from "p-comuns"; import type { ComponenteEntrada } from "../EliEntrada/tiposEntradas"
import { ComponenteEntrada } from "../EliEntrada/tiposEntradas"; import type {
tiposTabelaCelulas,
tipoTabelaCelula,
} from "./celulas/tiposTabelaCelulas"
// `p-comuns` expõe `zFiltro` (schema). Inferimos o tipo a partir do `parse`. // `p-comuns` expõe `zFiltro` (schema). Inferimos o tipo a partir do `parse`.
export type tipoFiltro = ReturnType<(typeof zFiltro)["parse"]> export type tipoFiltro = ReturnType<(typeof zFiltro)["parse"]>
export type tipoComponenteCelulaBase<T extends tipoTabelaCelula> = readonly [
T,
tiposTabelaCelulas[T],
]
export type tipoComponenteCelulaBase<T extends tipoTabelaCelula> =
readonly [T, tiposTabelaCelulas[T]]
export type tipoComponenteCelula = { export type tipoComponenteCelula = {
[K in tipoTabelaCelula]: tipoComponenteCelulaBase<K> [K in tipoTabelaCelula]: tipoComponenteCelulaBase<K>
@ -25,54 +26,60 @@ export const celulaTabela = <T extends tipoTabelaCelula>(
return [tipo, dados] as const return [tipo, dados] as const
} }
export type { tipoTabelaCelula, tiposTabelaCelulas }; export type { tipoTabelaCelula, tiposTabelaCelulas }
export type tipoEliColuna<T> = { export type tipoEliColuna<T> = {
/** Texto exibido no cabeçalho da coluna. */ /** Texto exibido no cabeçalho da coluna. */
rotulo: string; rotulo: string
/** Função responsável por renderizar o conteúdo da célula. */ /** Função responsável por renderizar o conteúdo da célula. */
celula: (linha: T) => tipoComponenteCelula; celula: (linha: T) => tipoComponenteCelula
/** Ação opcional disparada ao clicar na célula. */ /** Ação opcional disparada ao clicar na célula. */
/** /**
* Campo de ordenação associado à coluna. Caso informado, a coluna passa a * Campo de ordenação associado à coluna. Caso informado, a coluna passa a
* exibir controles de ordenação e utiliza o valor como chave para o backend. * exibir controles de ordenação e utiliza o valor como chave para o backend.
*/ */
coluna_ordem?: keyof T; coluna_ordem?: keyof T
/** /**
* indica que a coluna será visivel, se false incia em detalhe * indica que a coluna será visivel, se false incia em detalhe
* Caso tenha salvo a propriedade de visibilidade será adotado a propriedade salva * Caso tenha salvo a propriedade de visibilidade será adotado a propriedade salva
*/ */
visivel: boolean visivel: boolean
}; }
export type tipoEliConsultaPaginada<T> = { export type tipoEliConsultaPaginada<T> = {
/** Registros retornados na consulta. */ /** Registros retornados na consulta. */
valores: T[]; valores: T[]
/** Total de registros disponíveis no backend. */ /** Total de registros disponíveis no backend. */
quantidade: number; quantidade: number
}; }
export type tipoEliTabelaAcao<T> = { export type tipoEliTabelaAcao<T> = {
/** Ícone (Lucide) exibido para representar a ação. */ /** Ícone (Lucide) exibido para representar a ação. */
icone: LucideIcon; icone: LucideIcon
/** Cor aplicada ao ícone e rótulo. */ /** Cor aplicada ao ícone e rótulo. */
cor: string; cor: string
/** Texto descritivo da ação. */ /** Texto descritivo da ação. */
rotulo: string; rotulo: string
/** Função executada quando o usuário ativa a ação. */ /** Função executada quando o usuário ativa a ação. */
acao: (linha: T) => void; acao: (linha: T) => void
/** /**
* Define se a ação deve ser exibida para a linha. Pode ser um booleano fixo * Define se a ação deve ser exibida para a linha. Pode ser um booleano fixo
* ou uma função (sincrona/assíncrona) que recebe a linha para decisão dinâmica. * ou uma função (sincrona/assíncrona) que recebe a linha para decisão dinâmica.
*/ */
exibir?: boolean | ((linha: T) => Promise<boolean> | boolean); exibir?: boolean | ((linha: T) => Promise<boolean> | boolean)
}; }
export type parametrosConsulta<T> = {
filtros?: tipoFiltro[]
coluna_ordem?: keyof T
direcao_ordem?: "asc" | "desc"
offSet?: number
limit?: number
/** Texto digitado na caixa de busca, quando habilitada. */
texto_busca?: string
}
/** /**
* Estrutura de dados para uma tabela alimentada por uma consulta. * Estrutura de dados para uma tabela alimentada por uma consulta.
@ -85,45 +92,40 @@ export type tipoEliTabelaConsulta<T> = {
/** nome da tabela, um identificador unico */ /** nome da tabela, um identificador unico */
nome: string nome: string
/** Indica se a caixa de busca deve ser exibida acima da tabela. */ /** Indica se a caixa de busca deve ser exibida acima da tabela. */
mostrarCaixaDeBusca?: boolean; mostrarCaixaDeBusca?: boolean
/** Lista de colunas da tabela. */ /** Lista de colunas da tabela. */
colunas: tipoEliColuna<T>[]; colunas: tipoEliColuna<T>[]
/** Quantidade de registros solicitados por consulta (padrão `10`). */ /** Quantidade de registros solicitados por consulta (padrão `10`). */
registros_por_consulta?: number; registros_por_consulta?: number
/** /**
* Função responsável por buscar os dados. Recebe parâmetros opcionais de * Função responsável por buscar os dados. Recebe parâmetros opcionais de
* ordenação (`coluna_ordem`/`direcao_ordem`) e paginação (`offSet`/`limit`). * ordenação (`coluna_ordem`/`direcao_ordem`) e paginação (`offSet`/`limit`).
*/ */
consulta: (parametrosConsulta?: { consulta: (
parametrosConsulta?: parametrosConsulta<T>,
) => Promise<tipoResposta<tipoEliConsultaPaginada<T>>>
filtros?: tipoFiltro[]
coluna_ordem?: keyof T;
direcao_ordem?: "asc" | "desc";
offSet?: number;
limit?: number;
/** Texto digitado na caixa de busca, quando habilitada. */
texto_busca?: string;
}) => Promise<tipoResposta<tipoEliConsultaPaginada<T>>>;
/** Quantidade máxima de botões exibidos na paginação (padrão `7`). */ /** Quantidade máxima de botões exibidos na paginação (padrão `7`). */
maximo_botoes_paginacao?: number; maximo_botoes_paginacao?: number
/** Mensagem exibida quando a consulta retorna ok porém sem dados. */ /** Mensagem exibida quando a consulta retorna ok porém sem dados. */
mensagemVazio?: string; mensagemVazio?: string
/** Ações exibidas à direita de cada linha. */ /** Ações exibidas à direita de cada linha. */
acoesLinha?: tipoEliTabelaAcao<T>[]; acoesLinha?: tipoEliTabelaAcao<T>[]
/** /**
* Configurações dos botões que serão inseridos a direita da caixa de busca. * Configurações dos botões que serão inseridos a direita da caixa de busca.
* Seu uso mais comum será para criar novos registros, mas poderá ter outras utilidades. * Seu uso mais comum será para criar novos registros, mas poderá ter outras utilidades.
*/ */
acoesTabela?: { acoesTabela?: {
/** superio será exibido a direita da caixa de busca, inferior a direita da paginação */
posicao: "superior" | "inferior"
/** Ícone (Lucide) exibido no botão */ /** Ícone (Lucide) exibido no botão */
icone?: LucideIcon; icone?: LucideIcon
/** Cor aplicada ao botão. */ /** Cor aplicada ao botão. */
cor?: string; cor?: string
/** Texto descritivo da ação. */ /** Texto descritivo da ação. */
rotulo: string; rotulo: string
/** Função executada ao clicar no botão. */ /** Função executada ao clicar no botão. */
acao: () => void; acao: (parametrosConsulta?: parametrosConsulta<T>) => void
/** /**
* Callback opcional para forçar atualização da consulta. * Callback opcional para forçar atualização da consulta.
@ -135,14 +137,11 @@ export type tipoEliTabelaConsulta<T> = {
* Observação: o componente `EliTabela` pode ignorar isso dependendo do modo de uso. * Observação: o componente `EliTabela` pode ignorar isso dependendo do modo de uso.
*/ */
editarLista?: (lista: T[]) => Promise<T[]> editarLista?: (lista: T[]) => Promise<T[]>
}[];
filtroAvancado?: {
coluna: keyof T,
operador: operadores | keyof typeof operadores,
entrada: ComponenteEntrada
}[] }[]
filtroAvancado?: {
}; coluna: keyof T
operador: operadores | keyof typeof operadores
entrada: ComponenteEntrada
}[]
}

View file

@ -13,27 +13,27 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, PropType } from "vue"; import { defineComponent, type PropType } from "vue"
import type { BotaoTamanho, BotaoVariante } from "../../tipos"; import type { BotaoTamanho, BotaoVariante } from "../../tipos"
export default defineComponent({ export default defineComponent({
name: "EliBotao", name: "EliBotao",
inheritAttrs: false, inheritAttrs: false,
props: { props: {
color: { color: {
type: String, type: String,
default: "primary" default: "primary",
}, },
variant: { variant: {
type: String as PropType<BotaoVariante>, type: String as PropType<BotaoVariante>,
default: "elevated", default: "elevated",
}, },
size: { size: {
type: String as PropType<BotaoTamanho>, type: String as PropType<BotaoTamanho>,
default: "default", default: "default",
}, },
@ -46,7 +46,6 @@ export default defineComponent({
type: Boolean, type: Boolean,
default: false, default: false,
}, },
} },
}) })
</script> </script>

View file

@ -1 +1 @@
export { default as EliBotao } from "./EliBotao.vue"; export { default as EliBotao } from "./EliBotao.vue"

View file

@ -35,11 +35,11 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, PropType } from "vue"; import { computed, defineComponent, type PropType } from "vue"
import type { CartaoStatus } from "../../tipos"; import type { CartaoStatus } from "../../tipos"
import { EliBadge } from "../indicador"; import { EliBadge } from "../indicador"
type CartaoVariante = "outlined" | "flat" | "elevated" | "tonal"; type CartaoVariante = "outlined" | "flat" | "elevated" | "tonal"
/** /**
* EliCartao * EliCartao
@ -83,27 +83,27 @@ export default defineComponent({
setup(props, { emit }) { setup(props, { emit }) {
const rotuloStatus = computed(() => { const rotuloStatus = computed(() => {
// Mantém label em PT-BR (não abreviar) // Mantém label em PT-BR (não abreviar)
return props.status; return props.status
}); })
const corStatus = computed(() => { const corStatus = computed(() => {
// Cor neutra por padrão e semântica por status // Cor neutra por padrão e semântica por status
switch (props.status) { switch (props.status) {
case "novo": case "novo":
return "primary"; return "primary"
case "rascunho": case "rascunho":
return "secondary"; return "secondary"
case "vendido": case "vendido":
return "success"; return "success"
case "cancelado": case "cancelado":
return "error"; return "error"
} }
}); })
const classeStatus = computed(() => `eli-cartao--${props.status}`); const classeStatus = computed(() => `eli-cartao--${props.status}`)
function onClick() { function onClick() {
emit("clicar", props.status); emit("clicar", props.status)
} }
return { return {
@ -111,9 +111,9 @@ export default defineComponent({
corStatus, corStatus,
classeStatus, classeStatus,
onClick, onClick,
}; }
}, },
}); })
</script> </script>
<style> <style>

View file

@ -1,2 +1 @@
export { default as EliCartao } from "./EliCartao.vue"; export { default as EliCartao } from "./EliCartao.vue"

View file

@ -20,18 +20,18 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, PropType } from "vue"; import { computed, defineComponent, type PropType } from "vue"
import type { import type {
CssLength, CssLength,
IndicadorLocalizacao, IndicadorLocalizacao,
IndicadorOffset, IndicadorOffset,
IndicadorPresetRaio, IndicadorPresetRaio,
} from "../../tipos"; } from "../../tipos"
const RADIUS_MAP: Record<IndicadorPresetRaio, string> = { const RADIUS_MAP: Record<IndicadorPresetRaio, string> = {
suave: "4px", suave: "4px",
pill: "10px", pill: "10px",
}; }
export default defineComponent({ export default defineComponent({
name: "EliBadge", name: "EliBadge",
@ -82,33 +82,32 @@ export default defineComponent({
}, },
setup(props) { setup(props) {
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 IndicadorPresetRaio]; return RADIUS_MAP[props.radius as IndicadorPresetRaio]
} }
// valor custom (ex: "8px", "50%", "0") // valor custom (ex: "8px", "50%", "0")
return props.radius; return props.radius
}); })
const showBadge = computed(() => { const showBadge = computed(() => {
// se for dot, respeita visible // se for dot, respeita visible
if (props.dot) return props.visible; if (props.dot) return props.visible
// se tiver badge, respeita visible // se tiver badge, respeita visible
if (props.badge !== undefined) return props.visible; if (props.badge !== undefined) return props.visible
return false; return false
}); })
const badgeStyle = computed(() => ({ const badgeStyle = computed(() => ({
"--eli-badge-radius": resolvedRadius.value, "--eli-badge-radius": resolvedRadius.value,
})); }))
return { showBadge, badgeStyle }; return { showBadge, badgeStyle }
}, },
}); })
</script> </script>
<style> <style>

View file

@ -1 +1 @@
export { default as EliBadge } from "./EliBadge.vue"; export { default as EliBadge } from "./EliBadge.vue"

View file

@ -49,10 +49,10 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, ref } from "vue"; import { defineComponent, ref } from "vue"
import EliBotao from "../botao/EliBotao.vue"; import EliBotao from "../botao/EliBotao.vue"
import EliBadge from "../indicador/EliBadge.vue"; import EliEntradaTexto from "../EliEntrada/EliEntradaTexto.vue"
import EliEntradaTexto from "../EliEntrada/EliEntradaTexto.vue"; import EliBadge from "../indicador/EliBadge.vue"
export default defineComponent({ export default defineComponent({
name: "EliOlaMundo", name: "EliOlaMundo",
@ -62,18 +62,18 @@ export default defineComponent({
EliEntradaTexto, EliEntradaTexto,
}, },
setup() { setup() {
const nome = ref(""); const nome = ref("")
const cep = ref(""); const cep = ref("")
const telefone = ref(""); const telefone = ref("")
const email = ref(""); const email = ref("")
const documento = ref(""); const documento = ref("")
return { return {
nome, nome,
email, email,
documento, documento,
telefone, telefone,
cep, cep,
}; }
}, },
}); })
</script> </script>

View file

@ -1 +1 @@
export { default as EliOlaMundo } from "./EliOlaMundo.vue"; export { default as EliOlaMundo } from "./EliOlaMundo.vue"

View file

@ -1 +1 @@
export const gif_quero_quero = 'https://paiol.idz.one/estaticos/quero-quero.gif' export const gif_quero_quero = "https://paiol.idz.one/estaticos/quero-quero.gif"

View file

@ -1,43 +1,43 @@
import type { App, Plugin } from "vue"; import type { App, Plugin } from "vue"
import "./styles/eli-vue-fonts.css"; import "./styles/eli-vue-fonts.css"
import { EliOlaMundo } from "./componentes/ola_mundo"; import { EliBotao } from "./componentes/botao"
import { EliBotao } from "./componentes/botao"; import { EliCartao } from "./componentes/cartao"
import { EliBadge } from "./componentes/indicador";
import { EliCartao } from "./componentes/cartao";
import { EliTabela } from "./componentes/EliTabela";
import { import {
EliEntradaTexto,
EliEntradaNumero,
EliEntradaDataHora, EliEntradaDataHora,
EliEntradaNumero,
EliEntradaParagrafo, EliEntradaParagrafo,
EliEntradaSelecao, EliEntradaSelecao,
} from "./componentes/EliEntrada"; EliEntradaTexto,
} from "./componentes/EliEntrada"
import { EliTabela } from "./componentes/EliTabela"
import { EliBadge } from "./componentes/indicador"
import { EliOlaMundo } from "./componentes/ola_mundo"
export { EliOlaMundo }; export { EliOlaMundo }
export { EliBotao }; export { EliBotao }
export { EliBadge }; export { EliBadge }
export { EliCartao }; export { EliCartao }
export * from "./componentes/EliEntrada"
// Exportar tudo (componentes + types + helpers) de Tabela e Entrada // Exportar tudo (componentes + types + helpers) de Tabela e Entrada
export * from "./componentes/EliTabela"; export * from "./componentes/EliTabela"
export * from "./componentes/EliEntrada";
// Exportar tipos compartilhados (ex: CartaoStatus) // Exportar tipos compartilhados (ex: CartaoStatus)
export * from "./tipos"; export * from "./tipos"
const EliVue: Plugin = { const EliVue: Plugin = {
install(app: App) { install(app: App) {
app.component("EliOlaMundo", EliOlaMundo); app.component("EliOlaMundo", EliOlaMundo)
app.component("EliBotao", EliBotao); app.component("EliBotao", EliBotao)
app.component("EliBadge", EliBadge); app.component("EliBadge", EliBadge)
app.component("EliCartao", EliCartao); app.component("EliCartao", EliCartao)
app.component("EliTabela", EliTabela); app.component("EliTabela", EliTabela)
app.component("EliEntradaTexto", EliEntradaTexto); app.component("EliEntradaTexto", EliEntradaTexto)
app.component("EliEntradaNumero", EliEntradaNumero); app.component("EliEntradaNumero", EliEntradaNumero)
app.component("EliEntradaDataHora", EliEntradaDataHora); app.component("EliEntradaDataHora", EliEntradaDataHora)
app.component("EliEntradaParagrafo", EliEntradaParagrafo); app.component("EliEntradaParagrafo", EliEntradaParagrafo)
app.component("EliEntradaSelecao", EliEntradaSelecao); app.component("EliEntradaSelecao", EliEntradaSelecao)
}, },
}; }
export default EliVue; export default EliVue

View file

@ -27,14 +27,14 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from "vue"; import { defineComponent } from "vue"
import BotaoPlayground from "./botao.playground.vue"; import BotaoPlayground from "./botao.playground.vue"
import IndicadorPlayground from "./indicador.playground.vue"; import CartaoPlayground from "./cartao.playground.vue"
import CartaoPlayground from "./cartao.playground.vue"; import DataHoraPlayground from "./data_hora.playground.vue"
import EntradasPlayground from "./entradas.playground.vue"; import EntradasPlayground from "./entradas.playground.vue"
import DataHoraPlayground from "./data_hora.playground.vue"; import IndicadorPlayground from "./indicador.playground.vue"
import TabelaPlayground from "./tabela.playground.vue"; import OlaMundoPlayground from "./ola_mundo.playground.vue"
import OlaMundoPlayground from "./ola_mundo.playground.vue"; import TabelaPlayground from "./tabela.playground.vue"
type AbaPlayground = type AbaPlayground =
| "botao" | "botao"
@ -43,7 +43,7 @@ type AbaPlayground =
| "entradas" | "entradas"
| "data_hora" | "data_hora"
| "tabela" | "tabela"
| "ola_mundo"; | "ola_mundo"
const mapaHashParaAba: Record<string, AbaPlayground> = { const mapaHashParaAba: Record<string, AbaPlayground> = {
botao: "botao", botao: "botao",
@ -53,7 +53,7 @@ const mapaHashParaAba: Record<string, AbaPlayground> = {
"data-hora": "data_hora", "data-hora": "data_hora",
tabela: "tabela", tabela: "tabela",
demo: "ola_mundo", demo: "ola_mundo",
}; }
const mapaAbaParaHash: Record<AbaPlayground, string> = { const mapaAbaParaHash: Record<AbaPlayground, string> = {
botao: "botao", botao: "botao",
@ -63,7 +63,7 @@ const mapaAbaParaHash: Record<AbaPlayground, string> = {
data_hora: "data-hora", data_hora: "data-hora",
tabela: "tabela", tabela: "tabela",
ola_mundo: "demo", ola_mundo: "demo",
}; }
export default defineComponent({ export default defineComponent({
name: "App", name: "App",
@ -85,61 +85,67 @@ export default defineComponent({
body: "", body: "",
}, },
googleSansCheck: "(checando...)" as string, googleSansCheck: "(checando...)" as string,
}; }
}, },
mounted() { mounted() {
this.sincronizarAbaComHash(); this.sincronizarAbaComHash()
window.addEventListener("hashchange", this.sincronizarAbaComHash); window.addEventListener("hashchange", this.sincronizarAbaComHash)
// Coleta variáveis de fonte e confirma carregamento via FontFaceSet. // Coleta variáveis de fonte e confirma carregamento via FontFaceSet.
this.fontVars.eli = getComputedStyle(document.documentElement).getPropertyValue("--eli-font-family").trim(); this.fontVars.eli = getComputedStyle(document.documentElement)
this.fontVars.v = getComputedStyle(document.documentElement).getPropertyValue("--v-font-family").trim(); .getPropertyValue("--eli-font-family")
this.fontVars.body = getComputedStyle(document.body).fontFamily; .trim()
this.fontVars.v = getComputedStyle(document.documentElement)
.getPropertyValue("--v-font-family")
.trim()
this.fontVars.body = getComputedStyle(document.body).fontFamily
// Espera fonts carregarem e então checa se o navegador considera Google Sans disponível // Espera fonts carregarem e então checa se o navegador considera Google Sans disponível
// (isso não garante 100% que TODOS pesos/estilos foram baixados, mas confirma que a face existe/foi carregada) // (isso não garante 100% que TODOS pesos/estilos foram baixados, mas confirma que a face existe/foi carregada)
document.fonts.ready document.fonts.ready
.then(() => { .then(() => {
this.googleSansCheck = String(document.fonts.check('12px "Google Sans"')); this.googleSansCheck = String(
document.fonts.check('12px "Google Sans"'),
)
// atualiza body depois do load, pois pode mudar após o font-face carregar // atualiza body depois do load, pois pode mudar após o font-face carregar
this.fontVars.body = getComputedStyle(document.body).fontFamily; this.fontVars.body = getComputedStyle(document.body).fontFamily
}) })
.catch(() => { .catch(() => {
this.googleSansCheck = "erro"; this.googleSansCheck = "erro"
}); })
}, },
beforeUnmount() { beforeUnmount() {
window.removeEventListener("hashchange", this.sincronizarAbaComHash); window.removeEventListener("hashchange", this.sincronizarAbaComHash)
}, },
watch: { watch: {
aba() { aba() {
this.sincronizarHashComAba(); this.sincronizarHashComAba()
}, },
}, },
methods: { methods: {
normalizarHash() { normalizarHash() {
const valor = window.location.hash.replace(/^#\/?/, "").trim(); const valor = window.location.hash.replace(/^#\/?/, "").trim()
return valor; return valor
}, },
sincronizarAbaComHash() { sincronizarAbaComHash() {
const hash = this.normalizarHash(); const hash = this.normalizarHash()
const aba = mapaHashParaAba[hash] ?? "botao"; const aba = mapaHashParaAba[hash] ?? "botao"
if (this.aba !== aba) { if (this.aba !== aba) {
this.aba = aba; this.aba = aba
} }
// Se a URL estiver vazia/fora do padrão, normalizamos. // Se a URL estiver vazia/fora do padrão, normalizamos.
this.sincronizarHashComAba(); this.sincronizarHashComAba()
}, },
sincronizarHashComAba() { sincronizarHashComAba() {
const destino = `#/${mapaAbaParaHash[this.aba]}`; const destino = `#/${mapaAbaParaHash[this.aba]}`
if (window.location.hash !== destino) { if (window.location.hash !== destino) {
window.location.hash = destino; window.location.hash = destino
} }
}, },
}, },
}); })
</script> </script>

View file

@ -17,17 +17,17 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, ref } from "vue"; import { defineComponent, ref } from "vue"
import { EliBotao } from "@/componentes/botao"; import { EliBotao } from "@/componentes/botao"
export default defineComponent({ export default defineComponent({
name: "BotaoPlayground", name: "BotaoPlayground",
components: { EliBotao }, components: { EliBotao },
setup() { setup() {
const contador = ref(0); const contador = ref(0)
return { contador }; return { contador }
}, },
}); })
</script> </script>
<style scoped> <style scoped>

View file

@ -44,32 +44,32 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, ref } from "vue"; import { defineComponent, ref } from "vue"
import { EliBadge } from "@/componentes/indicador"; import { EliBotao } from "@/componentes/botao"
import { EliBotao } from "@/componentes/botao"; import { EliCartao } from "@/componentes/cartao"
import { EliEntradaTexto } from "@/componentes/EliEntrada"; import { EliEntradaTexto } from "@/componentes/EliEntrada"
import { EliCartao } from "@/componentes/cartao"; import { EliBadge } from "@/componentes/indicador"
import type { CartaoStatus } from "@/tipos"; import type { CartaoStatus } from "@/tipos"
type Card = { type Card = {
id: string; id: string
titulo: string; titulo: string
cliente: string; cliente: string
valor: string; valor: string
vencimento: string; vencimento: string
}; }
type Coluna = { type Coluna = {
status: CartaoStatus; status: CartaoStatus
titulo: string; titulo: string
itens: Card[]; itens: Card[]
}; }
export default defineComponent({ export default defineComponent({
name: "CartaoPlayground", name: "CartaoPlayground",
components: { EliBadge, EliBotao, EliEntradaTexto, EliCartao }, components: { EliBadge, EliBotao, EliEntradaTexto, EliCartao },
setup() { setup() {
const filtro = ref(""); const filtro = ref("")
const colunas = ref<Coluna[]>([ const colunas = ref<Coluna[]>([
{ {
@ -116,14 +116,14 @@ export default defineComponent({
}, },
], ],
}, },
]); ])
function itensFiltrados(itens: Card[]) { function itensFiltrados(itens: Card[]) {
const q = filtro.value.trim().toLowerCase(); const q = filtro.value.trim().toLowerCase()
if (!q) return itens; if (!q) return itens
return itens.filter((i) => return itens.filter((i) =>
`${i.titulo} ${i.cliente} ${i.valor}`.toLowerCase().includes(q) `${i.titulo} ${i.cliente} ${i.valor}`.toLowerCase().includes(q),
); )
} }
function criar() { function criar() {
@ -134,7 +134,7 @@ export default defineComponent({
cliente: "(definir)", cliente: "(definir)",
valor: "R$ 0,00", valor: "R$ 0,00",
vencimento: "--/--/----", vencimento: "--/--/----",
}); })
} }
function abrir(_item: Card) { function abrir(_item: Card) {
@ -145,9 +145,9 @@ export default defineComponent({
// Abrir modal/rota de edição // Abrir modal/rota de edição
} }
return { filtro, colunas, itensFiltrados, criar, abrir, editar }; return { filtro, colunas, itensFiltrados, criar, abrir, editar }
}, },
}); })
</script> </script>
<style scoped> <style scoped>

View file

@ -98,34 +98,34 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, ref } from "vue"; import { computed, defineComponent, ref } from "vue"
import { EliEntradaDataHora } from "@/componentes/EliEntrada"; import { VDivider } from "vuetify/components"
import { VDivider } from "vuetify/components"; import { EliEntradaDataHora } from "@/componentes/EliEntrada"
export default defineComponent({ export default defineComponent({
name: "DataHoraPlayground", name: "DataHoraPlayground",
components: { EliEntradaDataHora, VDivider }, components: { EliEntradaDataHora, VDivider },
setup() { setup() {
const dataHora = ref<string | null>("2026-01-09T13:15:00-03:00"); const dataHora = ref<string | null>("2026-01-09T13:15:00-03:00")
const somenteData = ref<string | null>("2026-01-09T00:00:00-03:00"); const somenteData = ref<string | null>("2026-01-09T00:00:00-03:00")
// Valor vindo do backend em UTC/Z (exibir local, manter como UTC no estado) // Valor vindo do backend em UTC/Z (exibir local, manter como UTC no estado)
const dataHoraUtcEntrada = ref<string | null>("2026-01-09T16:15:00Z"); const dataHoraUtcEntrada = ref<string | null>("2026-01-09T16:15:00Z")
// Exemplo com min/max // Exemplo com min/max
const min = ref("2026-01-09T08:00:00-03:00"); const min = ref("2026-01-09T08:00:00-03:00")
const max = ref("2026-01-09T18:00:00-03:00"); const max = ref("2026-01-09T18:00:00-03:00")
const dataHoraComLimite = ref<string | null>("2026-01-09T09:00:00-03:00"); const dataHoraComLimite = ref<string | null>("2026-01-09T09:00:00-03:00")
// Obrigatório (mostra erro quando null) // Obrigatório (mostra erro quando null)
const dataHoraObrigatoria = ref<string | null>(null); const dataHoraObrigatoria = ref<string | null>(null)
// Desabilitado // Desabilitado
const dataHoraDesabilitado = ref<string | null>("2026-01-09T10:30:00-03:00"); const dataHoraDesabilitado = ref<string | null>("2026-01-09T10:30:00-03:00")
// Saída: sempre ISO com offset local // Saída: sempre ISO com offset local
const dataHoraUtcEmitida = ref<string | null>("2026-01-09T16:15:00Z"); const dataHoraUtcEmitida = ref<string | null>("2026-01-09T16:15:00Z")
const debug = computed(() => const debug = computed(() =>
JSON.stringify( JSON.stringify(
@ -141,9 +141,9 @@ export default defineComponent({
max: max.value, max: max.value,
}, },
null, null,
2 2,
) ),
); )
return { return {
dataHora, dataHora,
@ -156,9 +156,9 @@ export default defineComponent({
dataHoraDesabilitado, dataHoraDesabilitado,
dataHoraUtcEmitida, dataHoraUtcEmitida,
debug, debug,
}; }
}, },
}); })
</script> </script>
<style scoped> <style scoped>

View file

@ -112,8 +112,13 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from "vue"; import { defineComponent } from "vue"
import { EliEntradaNumero, EliEntradaParagrafo, EliEntradaSelecao, EliEntradaTexto } from "../index"; import {
EliEntradaNumero,
EliEntradaParagrafo,
EliEntradaSelecao,
EliEntradaTexto,
} from "../index"
export default defineComponent({ export default defineComponent({
name: "EntradasPlayground", name: "EntradasPlayground",
@ -126,12 +131,12 @@ export default defineComponent({
methods: { methods: {
async itensCategorias() { async itensCategorias() {
// Exemplo async (simula consulta) // Exemplo async (simula consulta)
await new Promise((r) => setTimeout(r, 600)); await new Promise((r) => setTimeout(r, 600))
return [ return [
{ chave: "a", rotulo: "Categoria A" }, { chave: "a", rotulo: "Categoria A" },
{ chave: "b", rotulo: "Categoria B" }, { chave: "b", rotulo: "Categoria B" },
{ chave: "c", rotulo: "Categoria C" }, { chave: "c", rotulo: "Categoria C" },
]; ]
}, },
}, },
data() { data() {
@ -141,7 +146,7 @@ export default defineComponent({
selecao: null as string | null, selecao: null as string | null,
numero: null as number | null, numero: null as number | null,
numeroDecimal: null as number | null, numeroDecimal: null as number | null,
}; }
}, },
}); })
</script> </script>

View file

@ -29,18 +29,18 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, ref } from "vue"; import { defineComponent, ref } from "vue"
import { EliBadge } from "@/componentes/indicador"; import { EliBotao } from "@/componentes/botao"
import { EliBotao } from "@/componentes/botao"; import { EliBadge } from "@/componentes/indicador"
export default defineComponent({ export default defineComponent({
name: "IndicadorPlayground", name: "IndicadorPlayground",
components: { EliBadge, EliBotao }, components: { EliBadge, EliBotao },
setup() { setup() {
const mostrar = ref(true); const mostrar = ref(true)
return { mostrar }; return { mostrar }
}, },
}); })
</script> </script>
<style scoped> <style scoped>

View file

@ -1,16 +1,16 @@
import { createApp } from "vue"; import { createApp } from "vue"
import App from "./App.vue"; import App from "./App.vue"
// Vuetify // Vuetify
import "vuetify/styles"; import "vuetify/styles"
import "@mdi/font/css/materialdesignicons.css"; import "@mdi/font/css/materialdesignicons.css"
import { createVuetify } from "vuetify"; import { createVuetify } from "vuetify"
import * as components from "vuetify/components"; import * as components from "vuetify/components"
import * as directives from "vuetify/directives"; import * as directives from "vuetify/directives"
// Estilos globais da lib (font-face + variáveis de fonte) // Estilos globais da lib (font-face + variáveis de fonte)
// Importamos DEPOIS do Vuetify para garantir que `--v-font-family` seja sobrescrito. // Importamos DEPOIS do Vuetify para garantir que `--v-font-family` seja sobrescrito.
import "../styles/eli-vue-fonts.css"; import "../styles/eli-vue-fonts.css"
const themeDefault = { const themeDefault = {
dark: false, dark: false,
@ -152,7 +152,7 @@ const themeDefault = {
"cyan-800": "#055160", "cyan-800": "#055160",
"cyan-900": "#032830", "cyan-900": "#032830",
}, },
}; }
const vuetify = createVuetify({ const vuetify = createVuetify({
components, components,
@ -163,19 +163,32 @@ const vuetify = createVuetify({
themeDefault, themeDefault,
}, },
}, },
}); })
const app = createApp(App); const app = createApp(App)
// Debug rápido: confirma fonte efetiva no playground (ver no DevTools console) // Debug rápido: confirma fonte efetiva no playground (ver no DevTools console)
// Observação: isso é só para o playground, não afeta o build da lib. // Observação: isso é só para o playground, não afeta o build da lib.
if (import.meta.env.DEV) { if (import.meta.env.DEV) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log("[eli-vue] --v-font-family:", getComputedStyle(document.documentElement).getPropertyValue("--v-font-family")); console.log(
"[eli-vue] --v-font-family:",
getComputedStyle(document.documentElement).getPropertyValue(
"--v-font-family",
),
)
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log("[eli-vue] --eli-font-family:", getComputedStyle(document.documentElement).getPropertyValue("--eli-font-family")); console.log(
"[eli-vue] --eli-font-family:",
getComputedStyle(document.documentElement).getPropertyValue(
"--eli-font-family",
),
)
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log("[eli-vue] body font-family:", getComputedStyle(document.body).fontFamily); console.log(
"[eli-vue] body font-family:",
getComputedStyle(document.body).fontFamily,
)
} }
app.use(vuetify).mount("#app"); app.use(vuetify).mount("#app")

View file

@ -12,13 +12,13 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from "vue"; import { defineComponent } from "vue"
import { EliOlaMundo } from "@/componentes/ola_mundo"; import { EliOlaMundo } from "@/componentes/ola_mundo"
export default defineComponent({ export default defineComponent({
name: "OlaMundoPlayground", name: "OlaMundoPlayground",
components: { EliOlaMundo }, components: { EliOlaMundo },
}); })
</script> </script>
<style scoped> <style scoped>

View file

@ -12,25 +12,25 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, ref } from "vue"; import { BadgeCheck, Eye, Pencil, Plus, Trash2 } from "lucide-vue-next"
import { codigosResposta } from "p-respostas"; import { codigosResposta } from "p-respostas"
import { BadgeCheck, Eye, Pencil, Plus, Trash2 } from "lucide-vue-next"; import { defineComponent, ref } from "vue"
import { celulaTabela, EliTabela } from "@/componentes/EliTabela"; import type { ComponenteEntrada } from "@/componentes/EliEntrada/tiposEntradas"
import type { ComponenteEntrada } from "@/componentes/EliEntrada/tiposEntradas"; import type { tipoEliTabelaConsulta } from "@/componentes/EliTabela"
import type { tipoEliTabelaConsulta } from "@/componentes/EliTabela"; import { celulaTabela, EliTabela } from "@/componentes/EliTabela"
import type { tipoFiltro } from "@/componentes/EliTabela/types-eli-tabela"; import type { tipoFiltro } from "@/componentes/EliTabela/types-eli-tabela"
type Linha = { type Linha = {
empreendedor: string; empreendedor: string
empreendimento: string; empreendimento: string
documento: string; documento: string
email: string; email: string
telefone: string; telefone: string
faturamento: number; faturamento: number
peso_kg: number; peso_kg: number
criado_em: string; criado_em: string
atualizado_em: string; atualizado_em: string
}; }
export default defineComponent({ export default defineComponent({
name: "TabelaPlayground", name: "TabelaPlayground",
@ -42,7 +42,7 @@ export default defineComponent({
cor: "#2563eb", cor: "#2563eb",
rotulo: "Detalhes", rotulo: "Detalhes",
acao: (linha) => { acao: (linha) => {
console.log("Visualizar detalhes de", linha.empreendedor); console.log("Visualizar detalhes de", linha.empreendedor)
}, },
}, },
{ {
@ -50,18 +50,19 @@ export default defineComponent({
cor: "#dc2626", cor: "#dc2626",
rotulo: "Remover", rotulo: "Remover",
acao: (linha) => { acao: (linha) => {
console.log("Remover cadastro de", linha.empreendedor); console.log("Remover cadastro de", linha.empreendedor)
}, },
exibir: (linha) => !linha.empreendimento.toLowerCase().includes("café"), exibir: (linha) => !linha.empreendimento.toLowerCase().includes("café"),
}, },
]; ]
const linhasPadrao = ref<Linha[]>([ const linhasPadrao = ref<Linha[]>([
{ {
empreendedor: "Maria Silva", empreendedor: "Maria Silva",
empreendimento: "Doces da Maria", empreendimento: "Doces da Maria",
documento: "12.345.678/0001-90", documento: "12.345.678/0001-90",
email: "contato.comercial.super.longo@doces-da-maria-exemplo-muito-grande.com.br", email:
"contato.comercial.super.longo@doces-da-maria-exemplo-muito-grande.com.br",
telefone: "(11) 91234-5678", telefone: "(11) 91234-5678",
faturamento: 12500.5, faturamento: 12500.5,
peso_kg: 12.4, peso_kg: 12.4,
@ -288,14 +289,16 @@ export default defineComponent({
criado_em: "2026-01-01T09:00:00-03:00", criado_em: "2026-01-01T09:00:00-03:00",
atualizado_em: "2026-01-17T09:30:00-03:00", atualizado_em: "2026-01-17T09:30:00-03:00",
}, },
]); ])
// Incrementamos a chave para forçar o EliTabela a recarregar a consulta. // Incrementamos a chave para forçar o EliTabela a recarregar a consulta.
// (Como o componente não expõe um método público de refresh) // (Como o componente não expõe um método público de refresh)
const versaoTabelaOk = ref(0); const versaoTabelaOk = ref(0)
function adicionarLinha() { // biome-ignore lint/suspicious/noExplicitAny: playground
const proximo = linhasPadrao.value.length + 1; function adicionarLinha(params?: any) {
if (params) console.log("Adicionar Linha, parametros:", params)
const proximo = linhasPadrao.value.length + 1
linhasPadrao.value.unshift({ linhasPadrao.value.unshift({
empreendedor: `Novo Empreendedor ${proximo}`, empreendedor: `Novo Empreendedor ${proximo}`,
@ -307,42 +310,47 @@ export default defineComponent({
peso_kg: 0, peso_kg: 0,
criado_em: new Date().toISOString(), criado_em: new Date().toISOString(),
atualizado_em: new Date().toISOString(), atualizado_em: new Date().toISOString(),
}); })
versaoTabelaOk.value++; versaoTabelaOk.value++
} }
const filtrarPorBusca = (linhas: Linha[], texto?: string) => { const filtrarPorBusca = (linhas: Linha[], texto?: string) => {
const termo = texto?.trim().toLowerCase(); const termo = texto?.trim().toLowerCase()
if (!termo) { if (!termo) {
return [...linhas]; return [...linhas]
} }
return linhas.filter((linha) => { return linhas.filter((linha) => {
const campos = [linha.empreendedor, linha.empreendimento]; const campos = [linha.empreendedor, linha.empreendimento]
return campos.some((valor) => valor.toLowerCase().includes(termo)); return campos.some((valor) => valor.toLowerCase().includes(termo))
}); })
}; }
const compararOperador = (operador: string, valorLinha: any, valorFiltro: any): boolean => { const compararOperador = (
operador: string,
// biome-ignore lint/suspicious/noExplicitAny: playground
valorLinha: any,
// biome-ignore lint/suspicious/noExplicitAny: playground
valorFiltro: any,
): boolean => {
switch (operador) { switch (operador) {
case "=": case "=":
return valorLinha == valorFiltro; return valorLinha == valorFiltro
case "!=": case "!=":
return valorLinha != valorFiltro; return valorLinha != valorFiltro
case ">": case ">":
return Number(valorLinha) > Number(valorFiltro); return Number(valorLinha) > Number(valorFiltro)
case ">=": case ">=":
return Number(valorLinha) >= Number(valorFiltro); return Number(valorLinha) >= Number(valorFiltro)
case "<": case "<":
return Number(valorLinha) < Number(valorFiltro); return Number(valorLinha) < Number(valorFiltro)
case "<=": case "<=":
return Number(valorLinha) <= Number(valorFiltro); return Number(valorLinha) <= Number(valorFiltro)
case "like": { case "like": {
const a = String(valorLinha ?? "").toLowerCase(); const a = String(valorLinha ?? "").toLowerCase()
const b = String(valorFiltro ?? "").toLowerCase(); const b = String(valorFiltro ?? "").toLowerCase()
return a.includes(b); return a.includes(b)
} }
case "in": { case "in": {
const arr = Array.isArray(valorFiltro) const arr = Array.isArray(valorFiltro)
@ -350,93 +358,129 @@ export default defineComponent({
: String(valorFiltro ?? "") : String(valorFiltro ?? "")
.split(",") .split(",")
.map((s) => s.trim()) .map((s) => s.trim())
.filter(Boolean); .filter(Boolean)
return arr.includes(String(valorLinha)); return arr.includes(String(valorLinha))
} }
case "isNull": case "isNull":
return valorLinha === null || valorLinha === undefined || valorLinha === ""; return (
valorLinha === null || valorLinha === undefined || valorLinha === ""
)
default: default:
return true; return true
} }
}; }
const filtrarPorFiltrosAvancados = (linhas: Linha[], filtros?: tipoFiltro[]) => { const filtrarPorFiltrosAvancados = (
const lista = [...linhas]; linhas: Linha[],
if (!filtros?.length) return lista; filtros?: tipoFiltro[],
) => {
const lista = [...linhas]
if (!filtros?.length) return lista
// biome-ignore lint/suspicious/noExplicitAny: playground
return lista.filter((linha: any) => { return lista.filter((linha: any) => {
return filtros.every((f) => { return filtros.every((f) => {
const vLinha = linha?.[String((f as any).coluna)]; // biome-ignore lint/suspicious/noExplicitAny: playground
return compararOperador(String((f as any).operador), vLinha, (f as any).valor); const vLinha = linha?.[String((f as any).coluna)]
}); return compararOperador(
}); // biome-ignore lint/suspicious/noExplicitAny: playground
}; String((f as any).operador),
vLinha,
// biome-ignore lint/suspicious/noExplicitAny: playground
(f as any).valor,
)
})
})
}
const ordenarLinhas = (linhas: Linha[], parametros?: { coluna_ordem?: keyof Linha; direcao_ordem?: "asc" | "desc" }) => { const ordenarLinhas = (
if (!parametros?.coluna_ordem) return [...linhas]; linhas: Linha[],
parametros?: {
coluna_ordem?: keyof Linha
direcao_ordem?: "asc" | "desc"
},
) => {
if (!parametros?.coluna_ordem) return [...linhas]
const direcao = parametros.direcao_ordem ?? "asc"; const direcao = parametros.direcao_ordem ?? "asc"
const chave = parametros.coluna_ordem; const chave = parametros.coluna_ordem
const multiplicador = direcao === "asc" ? 1 : -1; const multiplicador = direcao === "asc" ? 1 : -1
return [...linhas].sort((a, b) => { return [...linhas].sort((a, b) => {
const valorA = a[chave]; const valorA = a[chave]
const valorB = b[chave]; const valorB = b[chave]
return ( return (
multiplicador * multiplicador *
String(valorA ?? "").localeCompare(String(valorB ?? ""), "pt-BR", { String(valorA ?? "").localeCompare(String(valorB ?? ""), "pt-BR", {
sensitivity: "base", sensitivity: "base",
}) })
); )
}); })
}; }
const tabelaOk: tipoEliTabelaConsulta<Linha> = { const tabelaOk: tipoEliTabelaConsulta<Linha> = {
nome: 'Exemplo', nome: "Exemplo",
registros_por_consulta: 10, registros_por_consulta: 10,
mostrarCaixaDeBusca: true, mostrarCaixaDeBusca: true,
acoesTabela: [ acoesTabela: [
{ {
posicao: "superior",
icone: Plus, icone: Plus,
cor: "#16a34a", cor: "#16a34a",
rotulo: "Novo", rotulo: "Novo (Superior)",
acao: adicionarLinha, acao: adicionarLinha,
}, },
{
posicao: "inferior",
icone: Plus,
cor: "#2563eb",
rotulo: "Novo (Inferior)",
// biome-ignore lint/suspicious/noExplicitAny: playground
acao: (params: any) => {
console.log("Ação inferior clicada com params:", params)
adicionarLinha(params)
},
},
], ],
colunas: [ colunas: [
{ {
rotulo: "Empreendedor", rotulo: "Empreendedor",
celula: (l) => celulaTabela('textoSimples', { texto: l.empreendedor }), celula: (l) =>
celulaTabela("textoSimples", { texto: l.empreendedor }),
coluna_ordem: "empreendedor", coluna_ordem: "empreendedor",
visivel: true, visivel: true,
}, },
{ {
rotulo: "Empreendimento", rotulo: "Empreendimento",
celula: (l) => celulaTabela('textoSimples', { texto: l.empreendimento }), celula: (l) =>
celulaTabela("textoSimples", { texto: l.empreendimento }),
coluna_ordem: "empreendimento", coluna_ordem: "empreendimento",
visivel: true, visivel: true,
}, },
{ {
rotulo: "Documento", rotulo: "Documento",
celula: (l) => celulaTabela('textoSimples', { texto: l.documento }), celula: (l) => celulaTabela("textoSimples", { texto: l.documento }),
coluna_ordem: "documento", coluna_ordem: "documento",
visivel: false, visivel: false,
}, },
{ {
rotulo: "E-mail", rotulo: "E-mail",
celula: (l) => celulaTabela('textoTruncado', { celula: (l) =>
texto: l.email, acao: () => { celulaTabela("textoTruncado", {
// Exemplo de ação: poderia abrir detalhes texto: l.email,
alert(`Clicou em ${l.email}`); acao: () => {
} // Exemplo de ação: poderia abrir detalhes
}), alert(`Clicou em ${l.email}`)
},
}),
coluna_ordem: "email", coluna_ordem: "email",
visivel: true, visivel: true,
}, },
{ {
rotulo: "Telefone", rotulo: "Telefone",
celula: (l) => celulaTabela('textoSimples', { texto: l.telefone }), celula: (l) => celulaTabela("textoSimples", { texto: l.telefone }),
coluna_ordem: "telefone", coluna_ordem: "telefone",
visivel: true, visivel: true,
}, },
@ -447,7 +491,8 @@ export default defineComponent({
numero: l.faturamento, numero: l.faturamento,
prefixo: "R$", prefixo: "R$",
// Exemplo de ação (clicável) // Exemplo de ação (clicável)
acao: () => alert(`Faturamento de ${l.empreendedor}: R$ ${l.faturamento}`), acao: () =>
alert(`Faturamento de ${l.empreendedor}: R$ ${l.faturamento}`),
}), }),
visivel: true, visivel: true,
}, },
@ -475,7 +520,7 @@ export default defineComponent({
cor: "primary", cor: "primary",
icone: Pencil, icone: Pencil,
acao: () => { acao: () => {
alert(`Editar ${l.empreendedor}`); alert(`Editar ${l.empreendedor}`)
}, },
}, },
], ],
@ -508,39 +553,46 @@ export default defineComponent({
coluna: "empreendedor", coluna: "empreendedor",
operador: "like", operador: "like",
entrada: ["texto", { rotulo: "Empreendedor" }] as ComponenteEntrada, entrada: ["texto", { rotulo: "Empreendedor" }] as ComponenteEntrada,
}, },
{ {
coluna: "documento", coluna: "documento",
operador: "like", operador: "like",
entrada: ["texto", { rotulo: "Documento", formato: "cpfCnpj" }] as ComponenteEntrada, entrada: [
"texto",
{ rotulo: "Documento", formato: "cpfCnpj" },
] as ComponenteEntrada,
}, },
{ {
coluna: "email", coluna: "email",
operador: "like", operador: "like",
entrada: ["texto", { rotulo: "E-mail", formato: "email" }] as ComponenteEntrada, entrada: [
"texto",
{ rotulo: "E-mail", formato: "email" },
] as ComponenteEntrada,
}, },
], ],
consulta: async (parametrosConsulta) => { consulta: async (parametrosConsulta) => {
// Agora a EliTabela envia paginação/ordenação/busca OU filtros avançados para a consulta. // Agora a EliTabela envia paginação/ordenação/busca OU filtros avançados para a consulta.
// (busca tem prioridade; quando existe texto_busca, filtros não vêm no payload) // (busca tem prioridade; quando existe texto_busca, filtros não vêm no payload)
const limite = Math.max(1, Number(parametrosConsulta?.limit ?? 10)); const limite = Math.max(1, Number(parametrosConsulta?.limit ?? 10))
const offset = Math.max(0, Number(parametrosConsulta?.offSet ?? 0)); const offset = Math.max(0, Number(parametrosConsulta?.offSet ?? 0))
// 1) filtra (busca OU filtro avançado) // 1) filtra (busca OU filtro avançado)
const base = [...linhasPadrao.value]; const base = [...linhasPadrao.value]
const filtradas = parametrosConsulta?.texto_busca const filtradas = parametrosConsulta?.texto_busca
? filtrarPorBusca(base, parametrosConsulta.texto_busca) ? filtrarPorBusca(base, parametrosConsulta.texto_busca)
: filtrarPorFiltrosAvancados(base, (parametrosConsulta as any)?.filtros); : filtrarPorFiltrosAvancados(
base,
// biome-ignore lint/suspicious/noExplicitAny: playground
(parametrosConsulta as any)?.filtros,
)
// 2) ordena // 2) ordena
const ordenadas = ordenarLinhas(filtradas, parametrosConsulta); const ordenadas = ordenarLinhas(filtradas, parametrosConsulta)
// 3) pagina // 3) pagina
const valores = ordenadas.slice(offset, offset + limite); const valores = ordenadas.slice(offset, offset + limite)
return { return {
cod: codigosResposta.sucesso, cod: codigosResposta.sucesso,
@ -551,9 +603,9 @@ export default defineComponent({
quantidade: ordenadas.length, quantidade: ordenadas.length,
valores, valores,
}, },
}; }
}, },
}; }
const tabelaVazia: tipoEliTabelaConsulta<Linha> = { const tabelaVazia: tipoEliTabelaConsulta<Linha> = {
nome: "Exemplo", nome: "Exemplo",
@ -570,11 +622,11 @@ export default defineComponent({
quantidade: 0, quantidade: 0,
valores: [], valores: [],
}, },
}; }
}, },
mensagemVazio: "Nada para mostrar aqui.", mensagemVazio: "Nada para mostrar aqui.",
acoesLinha: acoesLinha, acoesLinha: acoesLinha,
}; }
const tabelaErro: tipoEliTabelaConsulta<Linha> = { const tabelaErro: tipoEliTabelaConsulta<Linha> = {
nome: "Exemplo", nome: "Exemplo",
@ -589,13 +641,13 @@ export default defineComponent({
eErro: true, eErro: true,
mensagem: "Falha ao buscar dados", mensagem: "Falha ao buscar dados",
valor: undefined, valor: undefined,
}; }
}, },
}; }
return { tabelaOk, tabelaVazia, tabelaErro, versaoTabelaOk }; return { tabelaOk, tabelaVazia, tabelaErro, versaoTabelaOk }
}, },
}); })
</script> </script>
<style scoped> <style scoped>

View file

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

View file

@ -2,5 +2,4 @@
* Tipos do componente EliCartao. * Tipos do componente EliCartao.
*/ */
export type CartaoStatus = "novo" | "rascunho" | "vendido" | "cancelado"; export type CartaoStatus = "novo" | "rascunho" | "vendido" | "cancelado"

View file

@ -13,6 +13,6 @@ export type CampoVariante =
| "solo" | "solo"
| "solo-filled" | "solo-filled"
| "solo-inverted" | "solo-inverted"
| "underlined"; | "underlined"
export type CampoDensidade = "default" | "comfortable" | "compact"; export type CampoDensidade = "default" | "comfortable" | "compact"

View file

@ -1,4 +1,4 @@
export * from "./botao"; export * from "./botao"
export * from "./cartao"; export * from "./cartao"
export * from "./entrada"; export * from "./entrada"
export * from "./indicador"; export * from "./indicador"

View file

@ -10,7 +10,7 @@ export type IndicadorLocalizacao =
| "bottom center" | "bottom center"
| "top left" | "top left"
| "left center" | "left center"
| "bottom left"; | "bottom left"
export type IndicadorOffset = export type IndicadorOffset =
| "-20" | "-20"
@ -21,9 +21,8 @@ export type IndicadorOffset =
| "20" | "20"
| "15" | "15"
| "10" | "10"
| "5"; | "5"
export type IndicadorPresetRaio = "suave" | "pill"; export type IndicadorPresetRaio = "suave" | "pill"
export type CssLength = `${number}px` | `${number}rem` | `${number}%` | "0";
export type CssLength = `${number}px` | `${number}rem` | `${number}%` | "0"

View file

@ -18,6 +18,10 @@ export default defineConfig({
"@": path.resolve(__dirname, "./src"), "@": path.resolve(__dirname, "./src"),
}, },
}, },
server: {
port: 5555,
strictPort: true,
},
build: { build: {
lib: { lib: {
entry: path.resolve(__dirname, "src/index.ts"), entry: path.resolve(__dirname, "src/index.ts"),