refactor(consent-sdk): split ConsentManager + framework adapters under 500 LOC

Phase 4: extract config defaults, Google Consent Mode helper, and framework
adapter internals into sibling files so every source file is under the
hard cap. Public API surface preserved; all 135 tests green, tsup build +
tsc typecheck clean.

- core/ConsentManager 525 -> 467 LOC (extract config + google helpers)
- react/index 511 LOC -> 199 LOC barrel + components/hooks/context
- vue/index 511 LOC -> 32 LOC barrel + components/composables/context/plugin
- angular/index 509 LOC -> 45 LOC barrel + interface/service/module/templates

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sharang Parnerkar
2026-04-11 22:25:44 +02:00
parent ef8284dff5
commit 4ed39d2616
17 changed files with 1341 additions and 1375 deletions
+191
View File
@@ -0,0 +1,191 @@
/**
* 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<ConsentConfig>,
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<ConsentCategory>,
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<ConsentCategory>,
required: true,
},
message: {
type: String,
default: '',
},
buttonText: {
type: String,
default: 'Cookie-Einstellungen öffnen',
},
},
setup(props) {
const { showSettings } = useConsent();
const categoryNames: Record<ConsentCategory, string> = {
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'
),
]),
]),
]
);
};
},
});