diff --git a/src/componentes/EliEntrada/EliEntradaDataHora/Calendario.css b/src/componentes/EliEntrada/EliEntradaDataHora/Calendario.css
index 3d91a5e..09e1985 100644
--- a/src/componentes/EliEntrada/EliEntradaDataHora/Calendario.css
+++ b/src/componentes/EliEntrada/EliEntradaDataHora/Calendario.css
@@ -3,10 +3,8 @@
───────────────────────────────────────────── */
.eli-dh__popover {
- position: absolute;
- top: calc(100% + 6px);
- left: 0;
- z-index: 2000;
+ position: fixed;
+ z-index: 99999;
background: var(--cor-eli-superficie, #fff);
border: 1.5px solid var(--cor-eli-borda, #D5D8CC);
border-radius: 14px;
diff --git a/src/componentes/EliEntrada/EliEntradaDataHora/Calendario.vue b/src/componentes/EliEntrada/EliEntradaDataHora/Calendario.vue
index 6e275b3..6044ac8 100644
--- a/src/componentes/EliEntrada/EliEntradaDataHora/Calendario.vue
+++ b/src/componentes/EliEntrada/EliEntradaDataHora/Calendario.vue
@@ -67,6 +67,7 @@
:aria-selected="cell.selecionado"
:aria-label="`${cell.dia} de ${nomeMesAtual} de ${anoAtual}`"
@click="$emit('selecionarDia', cell)"
+ @dblclick="$emit('confirmar')"
>
{{ cell.dia }}
@@ -91,6 +92,8 @@
@input="onHoraInput"
@blur="onHoraBlur"
@keydown="onHoraKeydown"
+ @focus="onInputFocusSelect"
+ @click.stop
/>
:
@@ -214,6 +219,10 @@ export default defineComponent({
)
}
}
+ function onInputFocusSelect(e: Event) {
+ ;(e.target as HTMLInputElement).select()
+ }
+
return {
diasSemana,
MESES,
@@ -225,6 +234,7 @@ export default defineComponent({
onMinutoInput,
onMinutoBlur,
onMinutoKeydown,
+ onInputFocusSelect,
}
},
})
diff --git a/src/componentes/EliEntrada/EliEntradaDataHora/EliEntradaDataHora.css b/src/componentes/EliEntrada/EliEntradaDataHora/EliEntradaDataHora.css
index 02efb49..1f048a0 100644
--- a/src/componentes/EliEntrada/EliEntradaDataHora/EliEntradaDataHora.css
+++ b/src/componentes/EliEntrada/EliEntradaDataHora/EliEntradaDataHora.css
@@ -44,18 +44,29 @@
opacity: 0.6;
}
-.eli-dh__icone {
- flex-shrink: 0;
- width: 20px;
- height: 20px;
+.eli-dh__icone-btn {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 0;
+ border: none;
+ background: none;
+ cursor: pointer;
color: var(--cor-eli-neutro, #5E6553);
transition: color 0.18s;
+ border-radius: 4px;
+ flex-shrink: 0;
}
-.eli-dh__campo--focado .eli-dh__icone {
+.eli-dh__icone-btn:hover:not(:disabled) {
color: var(--cor-eli-primaria, #688C00);
}
+.eli-dh__icone {
+ width: 20px;
+ height: 20px;
+}
+
.eli-dh__conteudo {
flex: 1;
display: flex;
@@ -72,23 +83,35 @@
letter-spacing: 0.02em;
text-transform: uppercase;
transition: color 0.18s;
+ cursor: pointer;
}
.eli-dh__campo--focado .eli-dh__rotulo { color: var(--cor-eli-primaria, #688C00); }
.eli-dh__campo--erro .eli-dh__rotulo { color: var(--cor-eli-erro, #C62828); }
-.eli-dh__valor {
+.eli-dh__input {
+ width: 100%;
+ border: none;
+ background: transparent;
+ outline: none;
font-size: 15px;
font-weight: 500;
+ font-family: inherit;
color: var(--cor-eli-neutro-escuro, #3E4436);
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
+ padding: 0;
+ margin: 0;
+ line-height: 1.2;
}
-.eli-dh__valor--vazio {
+.eli-dh__input::placeholder {
color: var(--cor-eli-borda-forte, #B5BAA8);
font-weight: 400;
+ opacity: 1;
+}
+
+.eli-dh__input:disabled {
+ cursor: not-allowed;
+ color: var(--cor-eli-neutro, #5E6553);
}
.eli-dh__limpar {
diff --git a/src/componentes/EliEntrada/EliEntradaDataHora/calendarioHelpers.ts b/src/componentes/EliEntrada/EliEntradaDataHora/calendarioHelpers.ts
index a8240a9..1965b06 100644
--- a/src/componentes/EliEntrada/EliEntradaDataHora/calendarioHelpers.ts
+++ b/src/componentes/EliEntrada/EliEntradaDataHora/calendarioHelpers.ts
@@ -67,7 +67,71 @@ export function formatarValor(
modo: EntradaDataHora["opcoes"]["modo"],
): string {
if (!valor) return ""
- return modo === "data"
- ? dayjs(valor).format("DD/MM/YYYY")
- : dayjs(valor).format("DD/MM/YYYY HH:mm")
+ const d = dayjs(valor)
+ if (!d.isValid()) return ""
+ return modo === "data" ? d.format("DD/MM/YYYY") : d.format("DD/MM/YYYY HH:mm")
+}
+
+/**
+ * Aplica máscara visual de data/hora (DD/MM/YYYY ou DD/MM/YYYY HH:mm) em texto digitado.
+ */
+export function aplicarMascaraDataHora(valor: string, modo: "data" | "dataHora"): string {
+ const digitos = valor.replace(/\D/g, "")
+ if (!digitos) return ""
+
+ const dia = digitos.slice(0, 2)
+ const mes = digitos.slice(2, 4)
+ const ano = digitos.slice(4, 8)
+ const hora = digitos.slice(8, 10)
+ const minuto = digitos.slice(10, 12)
+
+ let res = dia
+ if (mes) res += `/${mes}`
+ if (ano) res += `/${ano}`
+
+ if (modo === "dataHora") {
+ if (hora) res += ` ${hora}`
+ if (minuto) res += `:${minuto}`
+ }
+
+ return res
+}
+
+/**
+ * Converte um texto mascarado (ex: "15/08/2026 14:30") em string ISO 8601 com fuso local.
+ */
+export function converterTextoParaIso(
+ texto: string,
+ modo: "data" | "dataHora",
+ horaMinutoPadrao?: { hora: string; minuto: string },
+): string | null {
+ const digitos = texto.replace(/\D/g, "")
+ if (digitos.length < 8) return null
+
+ const d = Number.parseInt(digitos.slice(0, 2), 10)
+ const m = Number.parseInt(digitos.slice(2, 4), 10)
+ const y = Number.parseInt(digitos.slice(4, 8), 10)
+
+ if (m < 1 || m > 12 || d < 1 || d > 31 || y < 1900 || y > 2100) return null
+
+ let h = 0
+ let min = 0
+
+ if (modo === "dataHora") {
+ if (digitos.length >= 10) {
+ h = Math.min(23, Number.parseInt(digitos.slice(8, 10), 10) || 0)
+ } else if (horaMinutoPadrao) {
+ h = Number.parseInt(horaMinutoPadrao.hora, 10) || 0
+ }
+
+ if (digitos.length >= 12) {
+ min = Math.min(59, Number.parseInt(digitos.slice(10, 12), 10) || 0)
+ } else if (horaMinutoPadrao) {
+ min = Number.parseInt(horaMinutoPadrao.minuto, 10) || 0
+ }
+ }
+
+ const strIso = `${y}-${String(m).padStart(2, "0")}-${String(d).padStart(2, "0")}T${String(h).padStart(2, "0")}:${String(min).padStart(2, "0")}:00`
+ const dt = dayjs(strIso)
+ return dt.isValid() ? dt.format() : null
}
diff --git a/src/componentes/EliEntrada/EliEntradaDataHora/index.vue b/src/componentes/EliEntrada/EliEntradaDataHora/index.vue
index 3d811bb..63bf663 100644
--- a/src/componentes/EliEntrada/EliEntradaDataHora/index.vue
+++ b/src/componentes/EliEntrada/EliEntradaDataHora/index.vue
@@ -5,30 +5,49 @@
:id="`eli-dh-campo-${uid}`"
class="eli-dh__campo"
:class="{
- 'eli-dh__campo--focado': aberto,
+ 'eli-dh__campo--focado': aberto || focado,
'eli-dh__campo--erro': Boolean(opcoesEfetivas.erro),
'eli-dh__campo--desabilitado': desabilitadoEfetivo,
}"
- role="button"
- :tabindex="desabilitadoEfetivo ? -1 : 0"
- :aria-haspopup="true"
- :aria-expanded="aberto"
- :aria-label="opcoesEfetivas.rotulo"
@click="abrirSeHabilitado"
- @keydown.enter.prevent="abrirSeHabilitado"
- @keydown.space.prevent="abrirSeHabilitado"
- @keydown.escape="fechar"
>
-
+
+
- {{ opcoesEfetivas.rotulo }}
-
- {{ valorFormatado || opcoesEfetivas.placeholder || 'Selecione...' }}
-
+
+
+