"use client" import { MotionConfig } from "motion/react" import { Children, isValidElement, useEffect, type CSSProperties, type ReactNode } from "react" import { cn } from "@/lib/utils" import { themeStyle } from "../../lib/theme" import type { FontPair, TemplateContent, TemplateDefinition, TemplateStyle } from "../../lib/types" import { libraryFont } from "../font-library" import { useDemo } from "./demo" const imageStyles: Record = { original: "", mono: "[&_img]:grayscale", warm: "[&_img]:sepia-[.3] [&_img]:saturate-[1.2]", soft: "[&_img]:saturate-[.75] [&_img]:brightness-[1.05] [&_img]:contrast-[.95]", contrast: "[&_img]:contrast-[1.2] [&_img]:saturate-[1.15]", } // Sektionen mit data-order="" tauschen ihre Plätze nach content.order; alle anderen bleiben, wo sie sind function arrange(children: ReactNode, order: string[]) { const items = Children.toArray(children) const keyOf = (node: ReactNode) => (isValidElement(node) ? (node.props as Record)["data-order"] : undefined) const slots = items.flatMap((node, i) => (typeof keyOf(node) === "string" ? [i] : [])) const rank = (node: ReactNode) => { const index = order.indexOf(keyOf(node) as string) return index < 0 ? order.length : index } const movable = slots.map((i) => items[i]).sort((a, b) => rank(a) - rank(b)) const arranged = [...items] slots.forEach((slot, n) => { arranged[slot] = movable[n] }) return arranged } // Rahmen jeder Vorlage: Palette und Schriften als CSS-Variablen (bg-t-*, font-t-*), Bildstil, Bewegung, // Sektions-Reihenfolge, sanftes Scrollen zu Ankern und – nur im Portal – Entwurfs-Hinweis und KI-Chat (shared/demo.tsx). // Fixe Leisten am unteren Rand (z. B. mobile CTA) schieben Badge und Chat über --t-safe-bottom nach oben. export function TemplateShell({ def, content, fonts, className, children }: { def: TemplateDefinition content: TemplateContent fonts: FontPair className?: string children: ReactNode }) { const demo = useDemo() useEffect(() => { const root = document.documentElement const previous = root.style.scrollBehavior root.style.scrollBehavior = "smooth" return () => { root.style.scrollBehavior = previous } }, []) const pair = (content.fonts.includes(":") && libraryFont(content.fonts)) || fonts const style = { ...themeStyle(def, content), "--t-display": pair.display, "--t-body": pair.body } as CSSProperties return (
{arrange(children, content.order)} {demo?.overlay}
) }