57 lines
3.3 KiB
JavaScript
57 lines
3.3 KiB
JavaScript
import { blockLabel } from './editor-model.js';
|
||
|
||
/** Editing aids are created only in the preview DOM, never in a saved block or public HTML. */
|
||
export function decorateContainers(preview, content) {
|
||
const visit = (blocks, parent = null) => {
|
||
blocks.forEach((block, index) => {
|
||
const node = preview.getElementById(block.id);
|
||
// Editing must expose the body without changing the visitor's saved open/closed state.
|
||
if (node && block.type === 'accordionitem') node.open = true;
|
||
if (node && ['section', 'row', 'column', 'accordion', 'accordionitem'].includes(block.type)) {
|
||
const label = block.type === 'column' && parent?.type === 'row'
|
||
? `Spalte ${index + 1} von ${blocks.length}` : block.type === 'accordionitem'
|
||
? `Eintrag „${block.props?.title || 'Ohne Titel'}“` : blockLabel(block);
|
||
node.classList.add('editor-container');
|
||
node.dataset.editorLabel = label;
|
||
if (!block.children?.length || ['accordion', 'accordionitem'].includes(block.type)) {
|
||
const compact = Boolean(block.children?.length);
|
||
if (!compact) node.classList.add('editor-empty-container');
|
||
const host = block.type === 'section' ? node.querySelector(':scope > .section-inner')
|
||
: block.type === 'accordionitem' ? node.querySelector(':scope > .accordion-body') : node;
|
||
if (!host) return;
|
||
const empty = preview.createElement('div');
|
||
empty.className = compact ? 'editor-empty editor-add-content' : 'editor-empty';
|
||
const name = preview.createElement('span');
|
||
name.className = 'editor-empty-name'; name.textContent = label;
|
||
const hint = preview.createElement('span');
|
||
hint.className = 'editor-empty-hint';
|
||
hint.textContent = block.type === 'row' ? 'Spalte hierher ziehen oder hinzufügen'
|
||
: block.type === 'accordion' ? 'Eintrag hinzufügen und darin Inhalte gestalten' : 'Element hierher ziehen oder hinzufügen';
|
||
const actions = preview.createElement('div'); actions.className = 'editor-empty-actions';
|
||
const add = (text, attribute, value, accessibleName) => {
|
||
const button = preview.createElement('button');
|
||
button.type = 'button'; button.textContent = text;
|
||
button.dataset.editorTarget = block.id;
|
||
button.setAttribute(attribute, value);
|
||
button.setAttribute('aria-label', accessibleName);
|
||
actions.append(button);
|
||
};
|
||
add(block.type === 'row' ? '+ Spalte hinzufügen' : '+ Inhalt hinzufügen', 'data-editor-insert', '', `${label}: ${block.type === 'row' ? 'Spalte' : 'Inhalt'} hinzufügen`);
|
||
if (block.type === 'accordion') {
|
||
actions.replaceChildren();
|
||
add('+ Eintrag hinzufügen', 'data-editor-add-entry', '', 'Akkordeon: Eintrag hinzufügen');
|
||
}
|
||
if (block.type === 'section') {
|
||
for (const count of [1, 2, 3, 4]) add(`${count} ${count === 1 ? 'Spalte' : 'Spalten'}`, 'data-editor-row', String(count), `${count} ${count === 1 ? 'Spalte' : 'Spalten'} in dieser Sektion anlegen`);
|
||
}
|
||
if (!compact) empty.append(name, hint);
|
||
empty.append(actions);
|
||
host.append(empty);
|
||
}
|
||
}
|
||
visit(block.children ?? [], block);
|
||
});
|
||
};
|
||
visit(content.blocks);
|
||
}
|