Esta especificação define o lote de trabalho req-034 (BATCH-034) para o Engenheiro Executor. O escopo abrange uma profunda reformulação de interface e funcionalidade no Editor HTML Visual (visualizador/previewer reativo), tornando a edição visual no conn2flow muito mais interativa, permissiva e integrada aos recursos e widgets do sistema.
Os arquivos modificados residem no editor visual que roda dentro do iframe de preview (html-editor.js), na interface que orquestra o modal na janela pai (html-editor-interface.js), no HTML do modal (html-editor-visual-modal.html em pt-br e en) e no backend PHP do editor (html-editor.php).
1. Expansão dos Elementos HTML Editáveis
Atualmente, o editor limita a identificação de elementos a listas estáticas pré-definidas de tags textuais e de mídia. Para tornar o editor permissivo a praticamente todo o espectro do HTML:
-
Lógica Permissiva: Qualquer tag no DOM do documento visualizado passa a ser elegível para hover e seleção, exceto se estiver listada em
config.ignoredTags(e.g.html,body,head,script,style,link,meta,noscript) ou se pertencer à interface do próprio editor (como overlays e modais). -
Tipos de Edição:
-
image: Aplicado se a tag for<img>. Permite editar osrcda imagem e interagir com o ImagePicker. -
text: Aplicado se a tag satisfizer as regras deisDirectlyTextEditable(tags de texto que contenham conteúdo de texto direto sem filhos estruturais bloqueantes). -
code: Qualquer outra tag detectada no DOM (ex:div,section,table,ul,ol,form,header,footer,nav,svg, etc.) que não seja de texto direto ou imagem terá o tipo de edição padrão'code'. Ao clicar no botão de editar, o editor abrirá a aba de código HTML exibindo oouterHTMLdo elemento para ser modificado diretamente via CodeMirror.
-
2. Isolamento de Hover e Seleção Persistente com Barra de Ferramentas
O comportamento atual de abrir o modal de edição imediatamente no clique é substituído por um fluxo de seleção persistente e interatividade:
-
Dual-Overlay: Criar e gerenciar dois overlays CSS independentes no iframe:
-
Hover Overlay (
#html-editor-hover-overlay): Destaca o elemento sobre o qual o mouse está flutuando de forma transitória. -
Selection Overlay (
#html-editor-selection-overlay): Fica fixado ao redor do elemento selecionado e persiste mesmo quando o mouse se move para fora dele.
-
-
Interação de Seleção:
-
Mover o mouse pelo iframe continua a exibir o hover overlay.
-
Clicar no hover overlay (ou no próprio elemento) remove a seleção do elemento anterior e fixa o overlay de seleção no elemento clicado.
-
Clicar fora de qualquer elemento editável (no fundo vazio) limpa a seleção.
-
-
Barra de Ferramentas Flutuante (
#html-editor-floating-toolbar):-
Exibida acoplada logo acima do topo do overlay de seleção.
-
A barra de ferramentas deve conter quatro botões de ação rápidos:
-
Arrastar/Mover (Drag Handle): Ícone
arrows alternate. Clicar e segurar permite arrastar o elemento. -
Duplicar (Duplicate): Ícone
copy. Duplica o elemento selecionado (usandocloneNode(true)) e insere o clone no DOM como próximo irmão adjacente (logo abaixo/depois dele). Atualiza o cache de elementos e transfere a seleção para o clone. -
Editar (Edit): Ícone
pencil. Abre o modal Fomantic UI de edição contendo os campos específicos para o tipo de edição correspondente (text,imageoucode). -
Deletar (Delete): Ícone
trash. Remove o elemento selecionado do DOM. Deve solicitar confirmação usando a função padrãoconfirm()do JavaScript (ex:confirm("Deseja realmente excluir este elemento?")). Se confirmado, o elemento é removido, os overlays e a barra de ferramentas são ocultados, e a seleção é resetada.
-
-
3. Mecanismo de Drag and Drop (DnD) no IFrame
Para permitir a reordenação visual dos elementos na página:
-
Início do Drag: Clicar e segurar no botão de Arrastar da barra de ferramentas inicia o estado de dragging.
-
Cálculo da Posição de Drop:
-
Conforme o mouse se move arrastando o elemento, varrer a posição do cursor sobre os outros elementos do iframe.
-
Exibir uma linha tracejada horizontal de placeholder (
.conn2flow-dnd-placeholder) indicando onde o elemento será inserido. -
A linha de placeholder deve aparecer:
-
Antes do elemento sob o mouse se o cursor estiver na metade superior/esquerda do seu retângulo delimitador.
-
Depois do elemento sob o mouse se o cursor estiver na metade inferior/direita.
-
Dentro (como primeiro filho) se o elemento sob o mouse for um contêiner vazio (
div,section, etc.).
-
-
Finalização: Ao soltar o botão do mouse, move o elemento selecionado para a posição do placeholder no DOM, remove a linha de placeholder, reposiciona o overlay de seleção e notifica a janela pai para sincronizar o CodeMirror do editor HTML principal.
4. Inclusão Dinâmica de Novos Elementos e Widgets
O usuário poderá expandir o layout inserindo novos elementos padrão ou blocos dinâmicos (widgets) registrados no sistema:
-
Botão de Inclusão ("+"): Adicionar um botão verde com o ícone
plusno cabeçalho do modal de visualização (janela pai), ao lado dos botões de controle de tela (desktop, tablet, mobile). -
Menu de Opções: Ao clicar no "+", abrir um popup/dropdown Fomantic UI categorizado:
-
Elementos HTML: Parágrafo (
p), Título (h1,h2,h3), Imagem (img), Link (a), Botão (button), Bloco (div), Seção (section). -
Widgets do Sistema: Destaques, Menus, Galerias, Índice.
-
-
Carga de Widgets via AJAX:
-
Ao abrir a seção de Widgets do menu, disparar uma requisição AJAX para o endpoint backend
html-editor-widgets-listpara recuperar a lista de slugs de widgets ativos no banco de dados. -
Exibir esses registros em um sub-menu estruturado para seleção do usuário.
-
-
Fluxo de "Carregar e Soltar" (Drop Insertion):
-
Ao selecionar um elemento ou widget do menu, o cursor do mouse no iframe entra em modo de inclusão (exibindo um preview fantasma ou contorno do elemento).
-
Mover o mouse pelo iframe exibe a linha tracejada de placeholder idêntica ao fluxo de DnD.
-
Se for selecionada a inserção de uma Imagem, abrir o ImagePicker para selecionar a URL da imagem.
-
Clicando em um ponto válido, insere o elemento no DOM:
-
Elementos HTML normais são inseridos com conteúdo padrão (ex:
<p>Novo parágrafo</p>). -
Widgets são inseridos estruturados como comentários wrapper reconhecidos pelo sistema. Ex:
<!-- widgets#menus->render({"grupo_slug": "slug-selecionado"}) < --> <!-- widgets#menus->render({"grupo_slug": "slug-selecionado"}) > --> -
Após a inserção, sai do modo de inclusão, re-sincroniza o CodeMirror com a janela pai e atualiza a pré-visualização.
-
5. Rota AJAX de Widgets no Backend (html-editor.php)
No arquivo gestor/bibliotecas/html-editor.php:
-
Implementar o caso
'html-editor-widgets-list'na funçãohtml_editor_ajax_interface(). -
Consultar as seguintes tabelas de banco de dados para coletar registros (trazendo as colunas
id/ slug enomede cada uma):-
menus -
galleries -
publisher_highlights -
publisher_index
-
-
Retornar a lista estruturada como JSON com cabeçalho apropriado:
{ "menus": [{"id": "menu-principal", "nome": "Menu Principal"}], "galleries": [{"id": "galeria-fotos", "nome": "Galeria de Fotos"}], "publisher-highlights": [{"id": "destaques-home", "nome": "Destaques Home"}], "publisher-index": [{"id": "indice-noticias", "nome": "Índice de Notícias"}] }
6. Recursos Premium do Editor Visual
6.1 Histórico de Ações (Desfazer / Refazer)
-
Pilhas de Estado: O
HtmlEditordeve manter dois arrays na instância:undoStackeredoStack. -
Configuração: Adicionar a chave
undoLimitnoconfig(tipo numérico, valor padrão30), permitindo sua parametrização futura. -
Salvar Estado: Toda vez que ocorrer uma alteração no DOM do iframe (drag and drop, duplicação, exclusão, edição ou inserção), o HTML atual do iframe deve ser inserido no topo da pilha
undoStacke oredoStackesvaziado. Se a pilha exceder o limite (undoLimit), o estado mais antigo deve ser removido. -
Controles:
-
Inserir dois botões com ícones de setas no cabeçalho do visual-modal da janela pai (Desfazer e Refazer).
-
Capturar atalhos de teclado
Ctrl + ZeCtrl + Y(ouCtrl + Shift + Z) no pai e propagar no iframe. -
Ao disparar o desfazer/refazer, aplicar o HTML do estado no DOM do iframe, atualizar o CodeMirror correspondente do pai e redesenhar os overlays.
-
6.2 Breadcrumb de Navegação do DOM
-
Posicionamento: Exibir uma trilha horizontal de tags logo abaixo ou integrada à borda inferior do
#html-editor-selection-overlay. -
Formatação: Exibir o caminho de seleção desde o contêiner raiz do iframe até o elemento atualmente selecionado (ex:
SECTION > DIV.container > DIV.flex-1 > DIV.card > P). -
Interatividade:
-
Passar o mouse sobre um segmento da trilha deve mostrar um destaque visual temporário (hover) sobre o elemento correspondente no iframe.
-
Clicar em um segmento deve mover a seleção principal diretamente para o elemento selecionado, atualizando a posição do overlay de seleção e a barra de ferramentas flutuante.
-
6.3 Editor Rápido de Classes Tailwind
-
Interface: Uma barra de texto compacta para classes, integrada à barra de ferramentas flutuante do overlay de seleção.
-
Visualização: Exibir as classes CSS atuais do elemento selecionado como "tags" estilizadas e removíveis (com um botão "x" de exclusão).
-
Entrada de Classes: Um input no final do contêiner que permite digitar novas classes separadas por espaço. Ao pressionar
Enterou perder o foco (blur), as classes inseridas são aplicadas ao elemento. -
Autocomplete: Integrar sugestão/auto-complete simples baseado nas classes padrão do Tailwind CSS para ajudar o operador a descobrir e preencher tags de forma intuitiva.
6.4 Ajuste Dinâmico de Largura do Preview (Handles de Redimensionamento)
-
Alças de Arraste: Adicionar duas alças verticais nas extremidades esquerda e direita do contêiner do
iframe-previewno visual-modal (.iframe-resize-handle-lefte.iframe-resize-handle-right). -
Comportamento: Arrastar as alças altera a largura (
width) do iframe dinamicamente. Um indicador flutuante deve exibir a largura corrente em pixels (ex:1024px) durante o redimensionamento. -
Sincronização: Clicar nos botões desktop/tablet/mobile pré-configurados (100%, 768px, 375px) aplica a largura correspondente e reposiciona as alças automaticamente.
6.5 Wrappers Virtuais para Widgets
-
Contêiner Virtual: No carregamento do HTML no iframe, buscar os comentários de widgets (
<!-- widgets#... < --> ... <!-- widgets#... > -->) e convertê-los dinamicamente em elementos<div class="conn2flow-widget-wrapper" data-widget-type="[tipo]" data-widget-slug="[slug]">. -
Estilo Diferenciado: Esse wrapper virtual de widget deve ter bordas tracejadas laranja/amarelo, fundo semi-transparente e exibir um pequeno indicador textual no topo: "Widget: [Módulo] - [Slug]".
-
Tratamento de Bloco Atômico: O hover e a seleção tratam o wrapper virtual como elemento único indivisível. O usuário não pode selecionar nem alterar os elementos internos gerados por ele (as imagens do carrossel ou os links do menu).
-
Ações: O arraste, duplicação e deleção operam no bloco inteiro. O botão de editar no toolbar do widget não abre o CodeMirror, e sim a modal apropriada para o widget do banco.
-
Persistência: Ao ler o HTML do iframe para salvar ou atualizar o CodeMirror do pai, converter as divs
.conn2flow-widget-wrapperde volta para os comentários estruturados originais do sistema.
7. Critérios de Aceitação e Validação
-
Expandido: Elementos estruturais e contêineres vazios/preenchidos (como
div,section) devem ser detectados sob o hover e se tornarem selecionáveis e editáveis via'code'. -
Seleção Persistente: Ao clicar, o contorno do elemento selecionado deve ficar azul/roxo e não sumir ao tirar o mouse dele. Outros elementos devem continuar mostrando o contorno mais fino de hover.
-
Barra de Ferramentas: A barra de ferramentas deve aparecer acima do elemento selecionado e seguir seu retângulo em redimensionamentos de tela.
-
Ações Rápidas:
-
Clicar em Duplicar deve criar um elemento irmão idêntico adjacente.
-
Clicar em Deletar e aceitar o
confirm()do navegador deve sumir com o elemento da página. -
Clicar em Editar deve abrir o modal de dados/código do editor.
-
-
Arrastar e Soltar (DnD): O arraste do elemento selecionado pelo handle de mover deve re-posicioná-lo no DOM na posição exata da linha tracejada de drop.
-
Inclusão: Clicar no "+" superior e selecionar um elemento ou widget do banco deve inseri-lo adequadamente no DOM no local indicado pela linha tracejada, atualizando dinamicamente o preview do editor.
-
Undo/Redo: Desfazer e refazer até 30 estados via botões e atalhos de teclado deve restaurar o DOM e o CodeMirror perfeitamente.
-
Tailwind Styler & Breadcrumb: Testar remoção de classes via tag "x", adição via input e mudança de seleção navegando pela árvore do breadcrumb.
-
Resize Handles: Confirmar redimensionamento livre do iframe nas laterais com indicador em tempo real de pixels.
-
Widget wrappers: Comprovar que blocos de widgets (galerias/menus) são encapsulados em divs tracejadas amarelas e tratados de forma atômica no DOM.
-
Linting: Garantir
php -lsem erros de sintaxe nos scripts PHP modificados enode --checknos JavaScripts.