/** * React UI components for the consent SDK. * * Phase 4: extracted from index.tsx to keep the main file under 500 LOC. * Exports ConsentGate, ConsentPlaceholder, and ConsentBanner (all headless). */ import type { FC, ReactNode } from 'react'; import type { ConsentCategories, ConsentCategory, ConsentState, } from '../types'; import { useConsent } from './hooks'; // ============================================================================= // ConsentGate // ============================================================================= interface ConsentGateProps { /** Erforderliche Kategorie */ category: ConsentCategory; /** Inhalt bei Consent */ children: ReactNode; /** Inhalt ohne Consent */ placeholder?: ReactNode; /** Fallback waehrend Laden */ fallback?: ReactNode; } /** * ConsentGate - zeigt Inhalt nur bei Consent. */ export const ConsentGate: FC = ({ category, children, placeholder = null, fallback = null, }) => { const { hasConsent, isLoading } = useConsent(); if (isLoading) { return <>{fallback}; } if (!hasConsent(category)) { return <>{placeholder}; } return <>{children}; }; // ============================================================================= // ConsentPlaceholder // ============================================================================= interface ConsentPlaceholderProps { category: ConsentCategory; message?: string; buttonText?: string; className?: string; } /** * ConsentPlaceholder - Placeholder fuer blockierten Inhalt. */ export const ConsentPlaceholder: FC = ({ category, message, buttonText, className = '', }) => { const { showSettings } = useConsent(); const categoryNames: Record = { essential: 'Essentielle Cookies', functional: 'Funktionale Cookies', analytics: 'Statistik-Cookies', marketing: 'Marketing-Cookies', social: 'Social Media-Cookies', }; const defaultMessage = `Dieser Inhalt erfordert ${categoryNames[category]}.`; return (

{message || defaultMessage}

); }; // ============================================================================= // ConsentBanner (headless) // ============================================================================= export interface ConsentBannerRenderProps { isVisible: boolean; consent: ConsentState | null; needsConsent: boolean; onAcceptAll: () => void; onRejectAll: () => void; onSaveSelection: (categories: Partial) => void; onShowSettings: () => void; onClose: () => void; } interface ConsentBannerProps { render?: (props: ConsentBannerRenderProps) => ReactNode; className?: string; } /** * ConsentBanner - Headless Banner-Komponente. * Kann mit eigener UI gerendert werden oder nutzt Default-UI. */ export const ConsentBanner: FC = ({ render, className }) => { const { consent, isBannerVisible, needsConsent, acceptAll, rejectAll, saveSelection, showSettings, hideBanner, } = useConsent(); const renderProps: ConsentBannerRenderProps = { isVisible: isBannerVisible, consent, needsConsent, onAcceptAll: acceptAll, onRejectAll: rejectAll, onSaveSelection: saveSelection, onShowSettings: showSettings, onClose: hideBanner, }; if (render) { return <>{render(renderProps)}; } if (!isBannerVisible) { return null; } return (

Datenschutzeinstellungen

Wir nutzen Cookies und aehnliche Technologien, um Ihnen ein optimales Nutzererlebnis zu bieten.

); };