/** * Vue consent components: ConsentProvider, ConsentGate, ConsentPlaceholder, * ConsentBanner. * * Phase 4: extracted from vue/index.ts. */ import { computed, defineComponent, h, type PropType } from 'vue'; import type { ConsentCategory, ConsentConfig } from '../types'; import { provideConsent, useConsent } from './composables'; /** * ConsentProvider - Wrapper-Komponente. */ export const ConsentProvider = defineComponent({ name: 'ConsentProvider', props: { config: { type: Object as PropType, required: true, }, }, setup(props, { slots }) { provideConsent(props.config); return () => slots.default?.(); }, }); /** * ConsentGate - Zeigt Inhalt nur bei Consent. */ export const ConsentGate = defineComponent({ name: 'ConsentGate', props: { category: { type: String as PropType, required: true, }, }, setup(props, { slots }) { const { hasConsent, isLoading } = useConsent(); return () => { if (isLoading.value) { return slots.fallback?.() ?? null; } if (!hasConsent(props.category)) { return slots.placeholder?.() ?? null; } return slots.default?.(); }; }, }); /** * ConsentPlaceholder - Placeholder fuer blockierten Inhalt. */ export const ConsentPlaceholder = defineComponent({ name: 'ConsentPlaceholder', props: { category: { type: String as PropType, required: true, }, message: { type: String, default: '', }, buttonText: { type: String, default: 'Cookie-Einstellungen öffnen', }, }, setup(props) { const { showSettings } = useConsent(); const categoryNames: Record = { essential: 'Essentielle Cookies', functional: 'Funktionale Cookies', analytics: 'Statistik-Cookies', marketing: 'Marketing-Cookies', social: 'Social Media-Cookies', }; const displayMessage = computed(() => { return ( props.message || `Dieser Inhalt erfordert ${categoryNames[props.category]}.` ); }); return () => h('div', { class: 'bp-consent-placeholder' }, [ h('p', displayMessage.value), h( 'button', { type: 'button', onClick: showSettings, }, props.buttonText ), ]); }, }); /** * ConsentBanner - Cookie-Banner Komponente (headless with default UI). */ export const ConsentBanner = defineComponent({ name: 'ConsentBanner', setup(_, { slots }) { const { consent, isBannerVisible, needsConsent, acceptAll, rejectAll, saveSelection, showSettings, hideBanner, } = useConsent(); const slotProps = computed(() => ({ isVisible: isBannerVisible.value, consent: consent.value, needsConsent: needsConsent.value, onAcceptAll: acceptAll, onRejectAll: rejectAll, onSaveSelection: saveSelection, onShowSettings: showSettings, onClose: hideBanner, })); return () => { if (slots.default) { return slots.default(slotProps.value); } if (!isBannerVisible.value) { return null; } return h( 'div', { class: 'bp-consent-banner', role: 'dialog', 'aria-modal': 'true', 'aria-label': 'Cookie-Einstellungen', }, [ h('div', { class: 'bp-consent-banner-content' }, [ h('h2', 'Datenschutzeinstellungen'), h( 'p', 'Wir nutzen Cookies und ähnliche Technologien, um Ihnen ein optimales Nutzererlebnis zu bieten.' ), h('div', { class: 'bp-consent-banner-actions' }, [ h( 'button', { type: 'button', class: 'bp-consent-btn bp-consent-btn-reject', onClick: rejectAll, }, 'Alle ablehnen' ), h( 'button', { type: 'button', class: 'bp-consent-btn bp-consent-btn-settings', onClick: showSettings, }, 'Einstellungen' ), h( 'button', { type: 'button', class: 'bp-consent-btn bp-consent-btn-accept', onClick: acceptAll, }, 'Alle akzeptieren' ), ]), ]), ] ); }; }, });