"use client" import type { FontPair, TemplateContent, TemplateDefinition } from "../../lib/types" import { useDemo } from "../shared/demo" import { TemplateShell } from "../shared/shell" import { blockComponents } from "./registry" import type { BrandData, NavLink } from "./types" // Anker aus dem Menütext: "Über uns" → "ueber-uns" function slug(text: string) { return text .toLowerCase() .replace(/ä/g, "ae").replace(/ö/g, "oe").replace(/ü/g, "ue").replace(/ß/g, "ss") .replace(/[^a-z0-9]+/g, "-") .replace(/^-+|-+$/g, "") } const menuOf = (data: Record) => (typeof data.menu === "string" ? data.menu.trim() : "") // Seite aus Bausteinen: Reihenfolge und Inhalte aus content.blocks, Marke & Kontakt aus content.data.brand. // Jeder Baustein steckt in einem Anker (id aus seinem Menüpunkt), data-block dient der Editor-Vorschau zum Hinscrollen. export function BlockPage({ def, content, fonts }: { def: TemplateDefinition; content: TemplateContent; fonts: FontPair }) { const demo = useDemo() const brand = content.data.brand as BrandData const blocks = content.blocks.filter((block) => !block.hidden && blockComponents[block.type]) const used = new Set(["top"]) const anchors = new Map() for (const block of blocks) { const base = slug(menuOf(block.data)) || block.id let anchor = base for (let n = 2; used.has(anchor); n++) anchor = `${base}-${n}` used.add(anchor) anchors.set(block.id, anchor) } const links: NavLink[] = blocks.flatMap((block) => { const menu = menuOf(block.data) return menu ? [{ href: `#${anchors.get(block.id)}`, label: menu }] : [] }) return ( {blocks.map((block) => { const Block = blockComponents[block.type] return (
) })} {blocks.length === 0 && demo && (

Noch keine Bausteine

Im Editor unter „Inhalte“ → „Baustein hinzufügen“ die Seite zusammenstellen.

)}
) }