// UI-Bausteine: Header, Footer, Marquee, Buttons, Wireframe-Helfer
const { useState, useEffect, useRef, useMemo, useCallback } = React;
// ============ Hash-Routing ============
function useHashRoute() {
const parse = () => {
const h = (window.location.hash || '#/').replace(/^#/, '');
const [path, query = ''] = h.split('?');
const params = Object.fromEntries(new URLSearchParams(query));
const segs = path.split('/').filter(Boolean);
return { path, segs, params };
};
const [route, setRoute] = useState(parse);
useEffect(() => {
const onHash = () => { setRoute(parse()); window.scrollTo(0, 0); };
window.addEventListener('hashchange', onHash);
return () => window.removeEventListener('hashchange', onHash);
}, []);
return route;
}
function navigate(to) {
if (!to.startsWith('#')) to = '#' + to;
window.location.hash = to.replace(/^#/, '');
}
// ============ Header ============
function Header({ route }) {
const [scrolled, setScrolled] = useState(false);
const [open, setOpen] = useState(false);
useEffect(() => {
const onScroll = () => setScrolled(window.scrollY > 20);
onScroll();
window.addEventListener('scroll', onScroll);
return () => window.removeEventListener('scroll', onScroll);
}, []);
const links = [
{ to: '/anlaesse', label: 'Anlässe' },
{ to: '/leistungen', label: 'Leistungen' },
{ to: '/galerie', label: 'Galerie' },
{ to: '/ueber-uns', label: 'Über uns' },
{ to: '/kontakt', label: 'Kontakt' },
];
return (
);
}
// ============ Marquee ============
function Marquee({ items, speed = 60 }) {
const text = items.join(' · ');
return (
{Array.from({ length: 4 }).map((_, i) => (
{text} ·
))}
);
}
// ============ Footer ============
function Footer() {
return (
);
}
// ============ Wireframe-Note ============
function WFNote({ children }) {
return (
{children}
);
}
// ============ Section ============
function Section({ children, label, title, eyebrow, bg, py = 120, ...rest }) {
return (
{(label || eyebrow) && (
{label && {label}}
{eyebrow && }
)}
{title && (
{title}
)}
{children}
);
}
// ============ Button ============
function Btn({ children, variant = 'primary', size = 'md', icon, ...props }) {
const sizes = {
sm: { padding: '10px 18px', fontSize: 11 },
md: { padding: '14px 28px', fontSize: 12 },
lg: { padding: '20px 36px', fontSize: 13 },
};
const variants = {
primary: { background: 'var(--navy)', color: 'var(--cream)', border: '1px solid var(--navy)' },
ghost: { background: 'transparent', color: 'var(--navy)', border: '1px solid var(--navy)' },
cream: { background: 'var(--cream)', color: 'var(--navy)', border: '1px solid var(--navy)' },
light: { background: 'transparent', color: 'var(--cream)', border: '1px solid var(--cream)' },
};
return (
);
}
// ============ Placeholder Block ============
function PH({ label, h = 200, w, style, ...rest }) {
return (
{label}
);
}
window.UI = { useHashRoute, navigate, Header, Footer, Marquee, WFNote, Section, Btn, PH };