import { defaultJSXConverters, RichText } from '@payloadcms/richtext-lexical/react';
import type { JSXConverters } from '@payloadcms/richtext-lexical/react';
import Image from 'next/image';
import { Suspense } from 'react';
// Import all custom React components that were previously mapped via Markdown
import StickyNarrative from '@/components/blog/StickyNarrative';
import ComparisonGrid from '@/components/blog/ComparisonGrid';
import VisualLinkPreview from '@/components/blog/VisualLinkPreview';
import TechnicalGrid from '@/components/blog/TechnicalGrid';
import HighlightBox from '@/components/blog/HighlightBox';
import AnimatedImage from '@/components/blog/AnimatedImage';
import ChatBubble from '@/components/blog/ChatBubble';
import PowerCTA from '@/components/blog/PowerCTA';
import { Callout } from '@/components/ui/Callout';
import Stats from '@/components/blog/Stats';
import SplitHeading from '@/components/blog/SplitHeading';
import ProductTabs from '@/components/ProductTabs';
import ProductTechnicalData from '@/components/ProductTechnicalData';
import ContactForm from '@/components/ContactForm';
import ContactMap from '@/components/ContactMap';
import Gallery from '@/components/team/Gallery';
import Reveal from '@/components/Reveal';
import { Badge, Container, Heading, Section, Card } from '@/components/ui';
import TrackedLink from '@/components/analytics/TrackedLink';
import { useLocale } from 'next-intl';
import HomeHero from '@/components/home/Hero';
import ProductCategories from '@/components/home/ProductCategories';
import WhatWeDo from '@/components/home/WhatWeDo';
import RecentPosts from '@/components/home/RecentPosts';
import Experience from '@/components/home/Experience';
import WhyChooseUs from '@/components/home/WhyChooseUs';
import MeetTheTeam from '@/components/home/MeetTheTeam';
import GallerySection from '@/components/home/GallerySection';
import VideoSection from '@/components/home/VideoSection';
import CTA from '@/components/home/CTA';
const jsxConverters: JSXConverters = {
...defaultJSXConverters,
// Let the default converters handle text nodes to preserve valid formatting
// Use div instead of p for paragraphs to allow nested block elements (like the lists above)
paragraph: ({ node, nodesToJSX }: any) => {
return (
{nodesToJSX({ nodes: node.children })}
);
},
// Scale headings to prevent multiple H1s (H1 -> H2, etc) and style natively
heading: ({ node, nodesToJSX }: any) => {
const children = nodesToJSX({ nodes: node.children });
const tag = node?.tag;
// Extract text to generate an ID for the TOC
// Lexical children might contain various nodes; we need a plain text representation
const textContent = node.children ? node.children.map((c: any) => c.text || '').join('') : '';
const id = textContent
? textContent
.toLowerCase()
.replace(/ä/g, 'ae')
.replace(/ö/g, 'oe')
.replace(/ü/g, 'ue')
.replace(/ß/g, 'ss')
.replace(/[*_`]/g, '')
.replace(/[^\w\s-]/g, '')
.replace(/\s+/g, '-')
.replace(/-+/g, '-')
.replace(/^-+|-+$/g, '')
: undefined;
if (tag === 'h1')
return (