templates/editor: defer insercao pos-transicao + pointer-events na saida

Trava persistia mesmo apos fix anterior. Causa raiz: append no form
ocorria durante a transicao CSS do drawer (250ms slide out). Vue
reagia ao v-model -> Jodit re-renderia HTML com nova variavel ->
concorrencia entre repaint do drawer saindo + reflow do Jodit
mobile = trava.

Fix:
1. setTimeout(280ms) — append no form so executa DEPOIS que a
   transicao do drawer terminou. Drawer sai limpo, depois Jodit
   re-renderiza isolado.
2. CSS: .dte-mobile-drawer:not(.is-open) ganha pointer-events:none
   durante saida. Evita captura de touch/click "perdidos" que
   tentavam triggerar handlers no drawer ja saindo.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Leonardo
2026-05-21 17:42:40 -03:00
parent 6860628087
commit 87a1ac1358
@@ -66,28 +66,37 @@ const editorRodape = ref(null)
function insertVariable(varKey) {
const tag = `{{${varKey}}}`
// No mobile: 1) fecha drawer (imediato); 2) deferir append do form e
// re-render do Jodit pra DEPOIS da transição (250ms). Modificar o form
// durante a transição causa concorrência entre repaint do drawer
// saindo + Jodit re-rendering com novo HTML → trava.
if (isMobile.value) {
drawerOpen.value = false;
const field = cursorField.value;
// setTimeout > duração da transição CSS (.dte-mobile-drawer = 250ms)
setTimeout(() => {
form.value[field] = (form.value[field] || '') + tag;
if (!form.value.variaveis.includes(varKey)) {
form.value.variaveis = [...form.value.variaveis, varKey];
}
}, 280);
return;
}
// Desktop: insertHTML mantém posição do cursor
const editorMap = {
cabecalho_html: editorCabecalho,
corpo_html: editorCorpo,
rodape_html: editorRodape
}
const editorRef = editorMap[cursorField.value]
// No mobile: drawer está aberto, foco está nos botões do drawer.
// Tentar editor.insertHTML enquanto o cursor está fora do Jodit faz
// ele travar tentando resolver selection. Usamos o fallback (append
// direto no form via v-model) e fechamos o drawer ANTES — Jodit
// sincroniza com v-model na próxima tick.
if (isMobile.value) {
drawerOpen.value = false;
form.value[cursorField.value] = (form.value[cursorField.value] || '') + tag
} else if (editorRef?.value?.insertHTML) {
if (editorRef?.value?.insertHTML) {
editorRef.value.insertHTML(tag)
} else {
form.value[cursorField.value] = (form.value[cursorField.value] || '') + tag
}
// Adiciona a variavel na lista se nao estiver
if (!form.value.variaveis.includes(varKey)) {
form.value.variaveis = [...form.value.variaveis, varKey]
}
@@ -504,6 +513,9 @@ onBeforeUnmount(() => {
box-shadow: 4px 0 24px rgba(0, 0, 0, 0.18);
}
.dte-mobile-drawer.is-open { transform: translateX(0); }
/* Durante a transição de saída, drawer ignora eventos pra não capturar
touch/click "perdidos" e prevenir trava no Jodit. */
.dte-mobile-drawer:not(.is-open) { pointer-events: none; }
.dte-mobile-drawer__tabs {
display: flex;