'use client'; import React, { useEffect, useState } from 'react'; interface TocItem { label: string; href: string; subItems?: TocItem[]; } interface TableOfContentsProps { items?: TocItem[]; className?: string; } export const TableOfContents: React.FC = ({ items, className = '' }) => { // Falls props rein kommen, diese nutzen, ansonsten leeres Array const initialItems = items || []; const [dynamicItems, setDynamicItems] = useState(initialItems); useEffect(() => { if (initialItems.length > 0) return; // Auto-discover headings if no items were passed const headings = document.querySelectorAll('h2, h3'); const newItems: TocItem[] = []; let currentH2: TocItem | null = null; headings.forEach((heading) => { // Ensure the heading has an ID if (!heading.id) { heading.id = heading.textContent?.toLowerCase().replace(/[^a-z0-9]+/g, '-') || `heading-${Math.random().toString(36).substring(2, 9)}`; } const item: TocItem = { label: heading.textContent || '', href: `#${heading.id}`, }; if (heading.tagName === 'H2') { currentH2 = { ...item, subItems: [] }; newItems.push(currentH2); } else if (heading.tagName === 'H3' && currentH2) { currentH2.subItems?.push(item); } else if (heading.tagName === 'H3' && !currentH2) { // If an H3 appears before any H2, just add it to root newItems.push(item); } }); // Verhindern vom loop via prev state check setDynamicItems(prev => { if (JSON.stringify(prev) === JSON.stringify(newItems)) return prev; return newItems; }); // Wir brauchen hier keine deps, da wir nur einmal beim Mount des Beitrags scannen wollen. // Sollte items sich ändern, ist das ein Bug der AI, aber als Fallback ok. }, []); const displayItems = dynamicItems; if (displayItems.length === 0) return null; // JSON-LD for SiteNavigationElement const jsonLd = { "@context": "https://schema.org", "@type": "ItemList", "itemListElement": displayItems.map((item, index) => ({ "@type": "SiteNavigationElement", "position": index + 1, "name": item.label, "url": `https://mintel.me${item.href}` })) }; return (