Painel - Editor Visual
Esta nota mostra o editor visual como um sistema de composição de blocos, e não apenas uma tela com drag-and-drop.
Leitura pensada para explicar responsabilidades, ordem de execução e trechos reais do código com foco no fluxo da implementação.
O que você encontra aqui
Esta nota mostra o editor visual como um sistema de composição de blocos, e não apenas uma tela com drag-and-drop.
Arquivos principais
src/features/ecommpanel/components/SiteEditorManager.tsxsrc/features/ecommpanel/components/SitePagePreview.tsx
Trecho 1 - inserir bloco por drag
function insertBlockByDrag(payload: DragPayload, targetSlotId: string, targetIndex: number) {
setSlots((current) => {
const snapshot = current.map((slot) => ({ ...slot, blocks: [...slot.blocks] }));
let blockToInsert: SiteBlock | null = null;
if (payload.kind === 'new') {
blockToInsert = makeDefaultBlock(payload.blockType);
} else {
const fromSlot = snapshot.find((slot) => slot.id === payload.fromSlotId);
const sourceIndex = fromSlot.blocks.findIndex((block) => block.id === payload.blockId);
const [movedBlock] = fromSlot.blocks.splice(sourceIndex, 1);
blockToInsert = movedBlock;
}
const targetSlot = snapshot.find((slot) => slot.id === targetSlotId);
targetSlot.blocks.splice(clamped, 0, blockToInsert);
return snapshot;
});
}Leitura guiada
Esse é o coração da interação.
A função aceita dois mundos:
- bloco novo vindo da toolbox;
- bloco existente sendo movido.
Em termos didáticos, isso é muito bom para mostrar um estado imutável controlado:
- cria snapshot;
- calcula origem;
- calcula destino;
- devolve um novo estado.
Trecho 2 - salvar rascunho
body: JSON.stringify({
title,
slug,
description,
seo: { ... },
theme: {
backgroundColor: themeBackgroundColor,
textColor: themeTextColor,
accentColor: themeAccentColor,
},
layoutPreset,
slots,
}),O que isso ensina
O editor não salva só blocos.
Ele salva um documento composto por:
- identidade da página;
- rota;
- SEO;
- tema local da página;
- preset de layout;
- slots e blocos.
Ou seja, a página dinâmica é tratada como entidade completa.
Trecho 3 - namespace dentro do editor
const [namespaceId, setNamespaceId] = useState<SiteRouteNamespaceId>('landing');
const [customPrefix, setCustomPrefix] = useState('');
const [leafPath, setLeafPath] = useState('');
const composedSlug = useMemo(
() => buildNamespacedRoutePath({ namespaceId, customPrefix, leafPath }),
[customPrefix, leafPath, namespaceId],
);Leitura técnica
O editor reaproveita a mesma lógica de namespace do cadastro de rotas.
Isso evita um problema comum de painel administrativo:
- criar em uma tela com uma regra;
- editar em outra com uma regra diferente.
Ordem de execução do editor
- carrega rotas e páginas;
- seleciona a página atual;
- hidrata namespace, slug, preset, slots e blocos;
- o operador move e edita blocos;
saveDraftpersiste o documento;publishOrDraftmuda o estado público da página.
Explicando de forma simples
"O editor visual é um composer. Ele não é um CMS WYSIWYG solto. Ele manipula uma estrutura declarativa de slots e blocos. O drag-and-drop é só a UX por cima dessa estrutura."