@c15t/svelte 3.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +88 -0
- package/README.md +136 -0
- package/SKILL.md +14 -0
- package/dist/actions/focus-trap.d.ts +8 -0
- package/dist/actions/focus-trap.js +23 -0
- package/dist/actions/portal.d.ts +8 -0
- package/dist/actions/portal.js +39 -0
- package/dist/actions/scroll-lock.d.ts +8 -0
- package/dist/actions/scroll-lock.js +23 -0
- package/dist/components/action-button.svelte +119 -0
- package/dist/components/action-button.svelte.d.ts +18 -0
- package/dist/components/branding.svelte +139 -0
- package/dist/components/branding.svelte.d.ts +13 -0
- package/dist/components/consent-dev-tools.svelte +58 -0
- package/dist/components/consent-dev-tools.svelte.d.ts +4 -0
- package/dist/components/frame.svelte +95 -0
- package/dist/components/frame.svelte.d.ts +12 -0
- package/dist/components/iab-panel.svelte +542 -0
- package/dist/components/iab-panel.svelte.d.ts +16 -0
- package/dist/components/iab-prompt.svelte +304 -0
- package/dist/components/iab-prompt.svelte.d.ts +14 -0
- package/dist/components/iab-purpose-item.svelte +511 -0
- package/dist/components/iab-purpose-item.svelte.d.ts +26 -0
- package/dist/components/iab-stack-item.svelte +146 -0
- package/dist/components/iab-stack-item.svelte.d.ts +19 -0
- package/dist/components/iab-vendor-list.svelte +900 -0
- package/dist/components/iab-vendor-list.svelte.d.ts +19 -0
- package/dist/components/icons/c15-t-icon-only.svelte +27 -0
- package/dist/components/icons/c15-t-icon-only.svelte.d.ts +9 -0
- package/dist/components/icons/chevron-down-icon.svelte +30 -0
- package/dist/components/icons/chevron-down-icon.svelte.d.ts +10 -0
- package/dist/components/icons/chevron-right-icon.svelte +36 -0
- package/dist/components/icons/chevron-right-icon.svelte.d.ts +12 -0
- package/dist/components/icons/close-icon.svelte +40 -0
- package/dist/components/icons/close-icon.svelte.d.ts +10 -0
- package/dist/components/icons/consent-icon-only.svelte +36 -0
- package/dist/components/icons/consent-icon-only.svelte.d.ts +9 -0
- package/dist/components/icons/external-link-icon.svelte +30 -0
- package/dist/components/icons/external-link-icon.svelte.d.ts +8 -0
- package/dist/components/icons/globe-icon.svelte +39 -0
- package/dist/components/icons/globe-icon.svelte.d.ts +9 -0
- package/dist/components/icons/info-icon.svelte +42 -0
- package/dist/components/icons/info-icon.svelte.d.ts +9 -0
- package/dist/components/icons/inth-logo.svelte +38 -0
- package/dist/components/icons/inth-logo.svelte.d.ts +9 -0
- package/dist/components/icons/layers-icon.svelte +25 -0
- package/dist/components/icons/layers-icon.svelte.d.ts +8 -0
- package/dist/components/icons/legitimate-interest-icon.svelte +29 -0
- package/dist/components/icons/legitimate-interest-icon.svelte.d.ts +10 -0
- package/dist/components/icons/lock-icon.svelte +31 -0
- package/dist/components/icons/lock-icon.svelte.d.ts +8 -0
- package/dist/components/icons/search-icon.svelte +33 -0
- package/dist/components/icons/search-icon.svelte.d.ts +8 -0
- package/dist/components/inline-legal-links.svelte +95 -0
- package/dist/components/inline-legal-links.svelte.d.ts +10 -0
- package/dist/components/manager-provider.svelte +459 -0
- package/dist/components/manager-provider.svelte.d.ts +27 -0
- package/dist/components/overlay.svelte +79 -0
- package/dist/components/overlay.svelte.d.ts +7 -0
- package/dist/components/panel-link.svelte +33 -0
- package/dist/components/panel-link.svelte.d.ts +10 -0
- package/dist/components/panel-trigger.svelte +237 -0
- package/dist/components/panel-trigger.svelte.d.ts +16 -0
- package/dist/components/panel.svelte +258 -0
- package/dist/components/panel.svelte.d.ts +22 -0
- package/dist/components/policy-actions-renderer.svelte +79 -0
- package/dist/components/policy-actions-renderer.svelte.d.ts +19 -0
- package/dist/components/preferences.svelte +320 -0
- package/dist/components/preferences.svelte.d.ts +8 -0
- package/dist/components/prompt.svelte +514 -0
- package/dist/components/prompt.svelte.d.ts +43 -0
- package/dist/context.svelte.d.ts +125 -0
- package/dist/context.svelte.js +354 -0
- package/dist/devtools-options.d.ts +7 -0
- package/dist/devtools-options.js +1 -0
- package/dist/devtools.d.ts +9 -0
- package/dist/devtools.js +7 -0
- package/dist/headless.d.ts +10 -0
- package/dist/headless.js +7 -0
- package/dist/iab/styles.css +11 -0
- package/dist/iab-loader.d.ts +30 -0
- package/dist/iab-loader.js +33 -0
- package/dist/iab-translations.d.ts +84 -0
- package/dist/iab-translations.js +45 -0
- package/dist/iab-types.d.ts +62 -0
- package/dist/iab-types.js +43 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +21 -0
- package/dist/kit/app.d.ts +35 -0
- package/dist/kit/handle.d.ts +34 -0
- package/dist/kit/handle.js +87 -0
- package/dist/kit/index.d.ts +30 -0
- package/dist/kit/index.js +5 -0
- package/dist/kit/load-consent.d.ts +57 -0
- package/dist/kit/load-consent.js +144 -0
- package/dist/kit/routes.d.ts +46 -0
- package/dist/kit/routes.js +203 -0
- package/dist/kit/types.d.ts +56 -0
- package/dist/kit/types.js +1 -0
- package/dist/primitives/accordion/accordion-item-content.svelte +35 -0
- package/dist/primitives/accordion/accordion-item-content.svelte.d.ts +9 -0
- package/dist/primitives/accordion/accordion-item-trigger.svelte +54 -0
- package/dist/primitives/accordion/accordion-item-trigger.svelte.d.ts +10 -0
- package/dist/primitives/accordion/accordion-item.svelte +61 -0
- package/dist/primitives/accordion/accordion-item.svelte.d.ts +11 -0
- package/dist/primitives/accordion/accordion-root.svelte +61 -0
- package/dist/primitives/accordion/accordion-root.svelte.d.ts +13 -0
- package/dist/primitives/accordion/context.d.ts +18 -0
- package/dist/primitives/accordion/context.js +23 -0
- package/dist/primitives/accordion/index.d.ts +29 -0
- package/dist/primitives/accordion/index.js +11 -0
- package/dist/primitives/collapsible/collapsible-content.svelte +36 -0
- package/dist/primitives/collapsible/collapsible-content.svelte.d.ts +9 -0
- package/dist/primitives/collapsible/collapsible-indicator.svelte +29 -0
- package/dist/primitives/collapsible/collapsible-indicator.svelte.d.ts +9 -0
- package/dist/primitives/collapsible/collapsible-root.svelte +70 -0
- package/dist/primitives/collapsible/collapsible-root.svelte.d.ts +11 -0
- package/dist/primitives/collapsible/collapsible-trigger.svelte +52 -0
- package/dist/primitives/collapsible/collapsible-trigger.svelte.d.ts +10 -0
- package/dist/primitives/collapsible/context.d.ts +10 -0
- package/dist/primitives/collapsible/context.js +12 -0
- package/dist/primitives/collapsible/index.d.ts +26 -0
- package/dist/primitives/collapsible/index.js +11 -0
- package/dist/primitives/dialog/context.d.ts +14 -0
- package/dist/primitives/dialog/context.js +12 -0
- package/dist/primitives/dialog/dialog-backdrop.svelte +39 -0
- package/dist/primitives/dialog/dialog-backdrop.svelte.d.ts +7 -0
- package/dist/primitives/dialog/dialog-close-trigger.svelte +48 -0
- package/dist/primitives/dialog/dialog-close-trigger.svelte.d.ts +11 -0
- package/dist/primitives/dialog/dialog-content.svelte +81 -0
- package/dist/primitives/dialog/dialog-content.svelte.d.ts +9 -0
- package/dist/primitives/dialog/dialog-description.svelte +28 -0
- package/dist/primitives/dialog/dialog-description.svelte.d.ts +9 -0
- package/dist/primitives/dialog/dialog-positioner.svelte +33 -0
- package/dist/primitives/dialog/dialog-positioner.svelte.d.ts +9 -0
- package/dist/primitives/dialog/dialog-root.svelte +117 -0
- package/dist/primitives/dialog/dialog-root.svelte.d.ts +14 -0
- package/dist/primitives/dialog/dialog-title.svelte +28 -0
- package/dist/primitives/dialog/dialog-title.svelte.d.ts +9 -0
- package/dist/primitives/dialog/index.d.ts +50 -0
- package/dist/primitives/dialog/index.js +19 -0
- package/dist/primitives/index.d.ts +7 -0
- package/dist/primitives/index.js +7 -0
- package/dist/primitives/portal/index.d.ts +4 -0
- package/dist/primitives/portal/index.js +2 -0
- package/dist/primitives/portal/portal.svelte +23 -0
- package/dist/primitives/portal/portal.svelte.d.ts +9 -0
- package/dist/primitives/preference-item/context.d.ts +11 -0
- package/dist/primitives/preference-item/context.js +12 -0
- package/dist/primitives/preference-item/index.d.ts +54 -0
- package/dist/primitives/preference-item/index.js +21 -0
- package/dist/primitives/preference-item/preference-item-auxiliary.svelte +33 -0
- package/dist/primitives/preference-item/preference-item-auxiliary.svelte.d.ts +9 -0
- package/dist/primitives/preference-item/preference-item-content.svelte +68 -0
- package/dist/primitives/preference-item/preference-item-content.svelte.d.ts +14 -0
- package/dist/primitives/preference-item/preference-item-control.svelte +33 -0
- package/dist/primitives/preference-item/preference-item-control.svelte.d.ts +9 -0
- package/dist/primitives/preference-item/preference-item-header.svelte +33 -0
- package/dist/primitives/preference-item/preference-item-header.svelte.d.ts +9 -0
- package/dist/primitives/preference-item/preference-item-leading.svelte +33 -0
- package/dist/primitives/preference-item/preference-item-leading.svelte.d.ts +9 -0
- package/dist/primitives/preference-item/preference-item-meta.svelte +33 -0
- package/dist/primitives/preference-item/preference-item-meta.svelte.d.ts +9 -0
- package/dist/primitives/preference-item/preference-item-root.svelte +82 -0
- package/dist/primitives/preference-item/preference-item-root.svelte.d.ts +12 -0
- package/dist/primitives/preference-item/preference-item-title.svelte +33 -0
- package/dist/primitives/preference-item/preference-item-title.svelte.d.ts +9 -0
- package/dist/primitives/preference-item/preference-item-trigger.svelte +62 -0
- package/dist/primitives/preference-item/preference-item-trigger.svelte.d.ts +10 -0
- package/dist/primitives/switch/context.d.ts +7 -0
- package/dist/primitives/switch/context.js +12 -0
- package/dist/primitives/switch/index.d.ts +25 -0
- package/dist/primitives/switch/index.js +11 -0
- package/dist/primitives/switch/switch-control.svelte +21 -0
- package/dist/primitives/switch/switch-control.svelte.d.ts +9 -0
- package/dist/primitives/switch/switch-hidden-input.svelte +31 -0
- package/dist/primitives/switch/switch-hidden-input.svelte.d.ts +8 -0
- package/dist/primitives/switch/switch-root.svelte +86 -0
- package/dist/primitives/switch/switch-root.svelte.d.ts +12 -0
- package/dist/primitives/switch/switch-thumb.svelte +14 -0
- package/dist/primitives/switch/switch-thumb.svelte.d.ts +7 -0
- package/dist/primitives/tabs/context.d.ts +11 -0
- package/dist/primitives/tabs/context.js +12 -0
- package/dist/primitives/tabs/index.d.ts +32 -0
- package/dist/primitives/tabs/index.js +11 -0
- package/dist/primitives/tabs/tabs-content.svelte +45 -0
- package/dist/primitives/tabs/tabs-content.svelte.d.ts +11 -0
- package/dist/primitives/tabs/tabs-list.svelte +38 -0
- package/dist/primitives/tabs/tabs-list.svelte.d.ts +10 -0
- package/dist/primitives/tabs/tabs-root.svelte +67 -0
- package/dist/primitives/tabs/tabs-root.svelte.d.ts +14 -0
- package/dist/primitives/tabs/tabs-trigger.svelte +108 -0
- package/dist/primitives/tabs/tabs-trigger.svelte.d.ts +11 -0
- package/dist/server/headers.d.ts +13 -0
- package/dist/server/headers.js +37 -0
- package/dist/server/index.d.ts +8 -0
- package/dist/server/index.js +116 -0
- package/dist/server/normalize-url.d.ts +23 -0
- package/dist/server/normalize-url.js +46 -0
- package/dist/server/types.d.ts +25 -0
- package/dist/server/types.js +1 -0
- package/dist/styles.css +10 -0
- package/dist/transports/offline.d.ts +14 -0
- package/dist/transports/offline.js +22 -0
- package/dist/types.d.ts +70 -0
- package/dist/types.js +1 -0
- package/dist/use-banner-visibility.svelte.d.ts +25 -0
- package/dist/use-banner-visibility.svelte.js +108 -0
- package/dist/utils.d.ts +25 -0
- package/dist/utils.js +32 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +2 -0
- package/docs/README.md +88 -0
- package/docs/assets/v3/brand-bar.png +0 -0
- package/docs/assets/v3/brand-card.png +0 -0
- package/docs/assets/v3/choice-wall.png +0 -0
- package/docs/assets/v3/mobile-card.png +0 -0
- package/docs/assets/v3/preferences.png +0 -0
- package/docs/customization/overview.md +45 -0
- package/docs/customization/recipes.md +79 -0
- package/docs/customization/slots.md +55 -0
- package/docs/customization/tokens.md +76 -0
- package/docs/customization/translations.md +49 -0
- package/docs/frameworks/svelte/quickstart.md +133 -0
- package/docs/frameworks/sveltekit/quickstart.md +144 -0
- package/docs/guides/consent-state.md +60 -0
- package/docs/guides/data-fetching.md +163 -0
- package/docs/guides/deployment-modes.md +63 -0
- package/docs/guides/troubleshooting.md +68 -0
- package/docs/guides/verify-consent.md +62 -0
- package/docs/integrations/adobe-analytics.md +294 -0
- package/docs/integrations/ahrefs-analytics.md +291 -0
- package/docs/integrations/amplitude.md +292 -0
- package/docs/integrations/building-integrations.md +47 -0
- package/docs/integrations/clearbit.md +291 -0
- package/docs/integrations/cloudflare-web-analytics.md +292 -0
- package/docs/integrations/crisp.md +294 -0
- package/docs/integrations/databuddy.md +311 -0
- package/docs/integrations/fathom-analytics.md +293 -0
- package/docs/integrations/google-maps.md +384 -0
- package/docs/integrations/google-tag-manager.md +306 -0
- package/docs/integrations/google-tag.md +305 -0
- package/docs/integrations/heap.md +292 -0
- package/docs/integrations/hightouch.md +293 -0
- package/docs/integrations/hotjar.md +292 -0
- package/docs/integrations/intercom.md +285 -0
- package/docs/integrations/linkedin-insights.md +291 -0
- package/docs/integrations/logrocket.md +293 -0
- package/docs/integrations/matomo-analytics.md +316 -0
- package/docs/integrations/meta-pixel.md +285 -0
- package/docs/integrations/microsoft-clarity.md +292 -0
- package/docs/integrations/microsoft-uet.md +291 -0
- package/docs/integrations/mixpanel-analytics.md +295 -0
- package/docs/integrations/openai-pixel.md +441 -0
- package/docs/integrations/overview.md +111 -0
- package/docs/integrations/pirsch.md +295 -0
- package/docs/integrations/plausible-analytics.md +295 -0
- package/docs/integrations/posthog.md +397 -0
- package/docs/integrations/promptwatch.md +291 -0
- package/docs/integrations/reddit-pixel.md +294 -0
- package/docs/integrations/rudderstack.md +328 -0
- package/docs/integrations/rybbit-analytics.md +296 -0
- package/docs/integrations/segment.md +292 -0
- package/docs/integrations/snapchat-pixel.md +293 -0
- package/docs/integrations/tiktok-pixel.md +291 -0
- package/docs/integrations/umami-analytics.md +295 -0
- package/docs/integrations/vercel-analytics.md +293 -0
- package/docs/integrations/x-pixel.md +291 -0
- package/docs/integrations/youtube.md +405 -0
- package/docs/upgrade-v3.md +334 -0
- package/iab/styles.css +1 -0
- package/package.json +153 -0
- package/readme.json +36 -0
- package/styles.css +1 -0
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type {
|
|
3
|
+
LegalLinks as LegalLinksType,
|
|
4
|
+
Model,
|
|
5
|
+
PromptPosition,
|
|
6
|
+
PromptVariant,
|
|
7
|
+
} from '@c15t/core';
|
|
8
|
+
import {
|
|
9
|
+
defaultTranslationConfig,
|
|
10
|
+
resolveConsentPresentation,
|
|
11
|
+
} from '@c15t/core';
|
|
12
|
+
import type { PolicyRight } from '@c15t/schema/types';
|
|
13
|
+
import styles from '@c15t/ui/styles/components/consent-banner';
|
|
14
|
+
import { getTextDirection, resolveTranslations } from '@c15t/ui/utils';
|
|
15
|
+
|
|
16
|
+
import { focusTrap } from '../actions/focus-trap';
|
|
17
|
+
// Banner uses custom portal/focus-trap/scroll-lock actions (not Ark UI's built-in)
|
|
18
|
+
// because the banner is not an Ark Dialog - it's a simpler container that
|
|
19
|
+
// conditionally acts as a dialog. The ConsentDialog uses Ark's Dialog which
|
|
20
|
+
// includes its own focus trap and scroll prevention. When transitioning from
|
|
21
|
+
// banner to dialog, the banner unmounts (removing its focus trap) before
|
|
22
|
+
// the dialog mounts (establishing Ark's focus trap), so they don't compete.
|
|
23
|
+
import { portal } from '../actions/portal';
|
|
24
|
+
import { scrollLock } from '../actions/scroll-lock';
|
|
25
|
+
import { getConsentContext, getThemeContext } from '../context.svelte';
|
|
26
|
+
import { useBannerVisibility } from '../use-banner-visibility.svelte';
|
|
27
|
+
import { resolveComponentStyles, resolveConsentActionStyle } from '../utils';
|
|
28
|
+
import ConsentButton from './action-button.svelte';
|
|
29
|
+
import Branding from './branding.svelte';
|
|
30
|
+
import InlineLegalLinks from './inline-legal-links.svelte';
|
|
31
|
+
import Overlay from './overlay.svelte';
|
|
32
|
+
import PolicyActionsRenderer from './policy-actions-renderer.svelte';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Button identifiers for the consent banner layout.
|
|
36
|
+
*/
|
|
37
|
+
type ConsentBannerButton = 'reject' | 'accept' | 'customize' | 'dismiss';
|
|
38
|
+
type ConsentBannerLayout = (ConsentBannerButton | ConsentBannerButton[])[];
|
|
39
|
+
|
|
40
|
+
let {
|
|
41
|
+
noStyle: localNoStyle,
|
|
42
|
+
disableAnimation: localDisableAnimation,
|
|
43
|
+
scrollLock: localScrollLock,
|
|
44
|
+
trapFocus: localTrapFocus,
|
|
45
|
+
title,
|
|
46
|
+
description,
|
|
47
|
+
rejectButtonText,
|
|
48
|
+
customizeButtonText,
|
|
49
|
+
acceptButtonText,
|
|
50
|
+
dismissButtonText,
|
|
51
|
+
hideBranding = false,
|
|
52
|
+
legalLinks,
|
|
53
|
+
layout,
|
|
54
|
+
primaryButton,
|
|
55
|
+
variant,
|
|
56
|
+
position,
|
|
57
|
+
blocking,
|
|
58
|
+
models = ['opt-in', 'opt-out', 'iab'] as Model[],
|
|
59
|
+
class: className,
|
|
60
|
+
}: {
|
|
61
|
+
noStyle?: boolean;
|
|
62
|
+
disableAnimation?: boolean;
|
|
63
|
+
scrollLock?: boolean;
|
|
64
|
+
trapFocus?: boolean;
|
|
65
|
+
title?: string;
|
|
66
|
+
description?: string;
|
|
67
|
+
rejectButtonText?: string;
|
|
68
|
+
customizeButtonText?: string;
|
|
69
|
+
acceptButtonText?: string;
|
|
70
|
+
dismissButtonText?: string;
|
|
71
|
+
hideBranding?: boolean;
|
|
72
|
+
legalLinks?: (keyof LegalLinksType)[] | null;
|
|
73
|
+
layout?: ConsentBannerLayout;
|
|
74
|
+
primaryButton?: ConsentBannerButton | ConsentBannerButton[];
|
|
75
|
+
/**
|
|
76
|
+
* Shape of the prompt. Overrides the host presentation.
|
|
77
|
+
* A notice defaults to `bar`, a choice prompt to `floating`.
|
|
78
|
+
*/
|
|
79
|
+
variant?: PromptVariant;
|
|
80
|
+
/**
|
|
81
|
+
* Where the prompt sits. Must be valid for the resolved variant;
|
|
82
|
+
* an invalid value falls back to the variant default with a
|
|
83
|
+
* development diagnostic.
|
|
84
|
+
*/
|
|
85
|
+
position?: PromptPosition;
|
|
86
|
+
/**
|
|
87
|
+
* Backdrop, scroll lock, focus trap, and no dismissal from outside,
|
|
88
|
+
* as one value. `wall` is always blocking; a notice never is.
|
|
89
|
+
*/
|
|
90
|
+
blocking?: boolean;
|
|
91
|
+
models?: Model[];
|
|
92
|
+
class?: string;
|
|
93
|
+
} = $props();
|
|
94
|
+
|
|
95
|
+
/** Corner mirror for right-to-left text when the host set no position. */
|
|
96
|
+
const MIRRORED_POSITIONS: Partial<Record<PromptPosition, PromptPosition>> = {
|
|
97
|
+
'bottom-left': 'bottom-right',
|
|
98
|
+
'bottom-right': 'bottom-left',
|
|
99
|
+
'top-left': 'top-right',
|
|
100
|
+
'top-right': 'top-left',
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const consent = getConsentContext();
|
|
104
|
+
const theme = getThemeContext();
|
|
105
|
+
|
|
106
|
+
const noStyle = $derived(localNoStyle ?? theme.noStyle ?? false);
|
|
107
|
+
const disableAnimation = $derived(
|
|
108
|
+
localDisableAnimation ?? theme.disableAnimation ?? false
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
// Translations
|
|
112
|
+
const translations = $derived(
|
|
113
|
+
resolveTranslations(
|
|
114
|
+
consent.state.translationConfig,
|
|
115
|
+
defaultTranslationConfig
|
|
116
|
+
)
|
|
117
|
+
);
|
|
118
|
+
const textDirection = $derived(
|
|
119
|
+
getTextDirection(consent.state.translationConfig?.defaultLanguage)
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
// Visibility logic
|
|
123
|
+
const shouldShowBanner = $derived(
|
|
124
|
+
consent.state.hasConsentUi &&
|
|
125
|
+
consent.state.activeUI === 'banner' &&
|
|
126
|
+
consent.snapshot.promptRequirement.kind !== 'none' &&
|
|
127
|
+
models.includes(consent.state.model)
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
const visibility = useBannerVisibility(
|
|
131
|
+
() => shouldShowBanner,
|
|
132
|
+
() => disableAnimation
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
// Styling - per-element theme key resolution shared across framework adapters.
|
|
136
|
+
const rootStyle = $derived(
|
|
137
|
+
resolveComponentStyles(
|
|
138
|
+
'consentBanner',
|
|
139
|
+
theme.theme,
|
|
140
|
+
{
|
|
141
|
+
baseClassName: styles.root,
|
|
142
|
+
className,
|
|
143
|
+
noStyle,
|
|
144
|
+
},
|
|
145
|
+
noStyle
|
|
146
|
+
)
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
const cardStyle = $derived(
|
|
150
|
+
resolveComponentStyles(
|
|
151
|
+
'consentBannerCard',
|
|
152
|
+
theme.theme,
|
|
153
|
+
{ baseClassName: styles.card, noStyle },
|
|
154
|
+
noStyle
|
|
155
|
+
)
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
const headerStyle = $derived(
|
|
159
|
+
resolveComponentStyles(
|
|
160
|
+
'consentBannerHeader',
|
|
161
|
+
theme.theme,
|
|
162
|
+
{ baseClassName: styles.header, noStyle },
|
|
163
|
+
noStyle
|
|
164
|
+
)
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
const titleStyle = $derived(
|
|
168
|
+
resolveComponentStyles(
|
|
169
|
+
'consentBannerTitle',
|
|
170
|
+
theme.theme,
|
|
171
|
+
{ baseClassName: styles.title, noStyle },
|
|
172
|
+
noStyle
|
|
173
|
+
)
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
const descriptionStyle = $derived(
|
|
177
|
+
resolveComponentStyles(
|
|
178
|
+
'consentBannerDescription',
|
|
179
|
+
theme.theme,
|
|
180
|
+
{ baseClassName: styles.description, noStyle },
|
|
181
|
+
noStyle
|
|
182
|
+
)
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
const footerStyle = $derived(
|
|
186
|
+
resolveComponentStyles(
|
|
187
|
+
'consentBannerFooter',
|
|
188
|
+
theme.theme,
|
|
189
|
+
{ baseClassName: styles.footer, noStyle },
|
|
190
|
+
noStyle
|
|
191
|
+
)
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
const footerSubGroupStyle = $derived(
|
|
195
|
+
resolveComponentStyles(
|
|
196
|
+
'consentBannerFooterSubGroup',
|
|
197
|
+
theme.theme,
|
|
198
|
+
{ noStyle },
|
|
199
|
+
noStyle
|
|
200
|
+
)
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
const rightsStyle = $derived(
|
|
204
|
+
resolveComponentStyles(
|
|
205
|
+
'consentBannerRights',
|
|
206
|
+
theme.theme,
|
|
207
|
+
{ baseClassName: styles.rights, noStyle },
|
|
208
|
+
noStyle
|
|
209
|
+
)
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
const rightLinkStyle = $derived(
|
|
213
|
+
resolveComponentStyles(
|
|
214
|
+
'consentBannerRightLink',
|
|
215
|
+
theme.theme,
|
|
216
|
+
{ baseClassName: styles.rightLink, noStyle },
|
|
217
|
+
noStyle
|
|
218
|
+
)
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
// A right control opens the preference center without recording a choice.
|
|
222
|
+
const openPreferences = function openPreferences() {
|
|
223
|
+
consent.state.setActiveUI('dialog');
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
const finalClassName = $derived(
|
|
227
|
+
noStyle
|
|
228
|
+
? rootStyle.className || ''
|
|
229
|
+
: `${rootStyle.className || ''} ${visibility.isVisible ? styles.bannerVisible : styles.bannerHidden}`
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
const localPrimaryActions = $derived.by(() => {
|
|
233
|
+
if (primaryButton === undefined) {
|
|
234
|
+
return undefined;
|
|
235
|
+
}
|
|
236
|
+
return Array.isArray(primaryButton) ? primaryButton : [primaryButton];
|
|
237
|
+
});
|
|
238
|
+
// Button helpers
|
|
239
|
+
const themedActions = $derived({
|
|
240
|
+
accept: resolveConsentActionStyle(theme.theme, 'accept'),
|
|
241
|
+
customize: resolveConsentActionStyle(theme.theme, 'customize'),
|
|
242
|
+
dismiss: resolveConsentActionStyle(theme.theme, 'dismiss'),
|
|
243
|
+
reject: resolveConsentActionStyle(theme.theme, 'reject'),
|
|
244
|
+
save: resolveConsentActionStyle(theme.theme, 'save'),
|
|
245
|
+
});
|
|
246
|
+
const presentation = $derived(
|
|
247
|
+
resolveConsentPresentation({
|
|
248
|
+
actionAppearance: themedActions,
|
|
249
|
+
override: {
|
|
250
|
+
blocking,
|
|
251
|
+
layout,
|
|
252
|
+
position,
|
|
253
|
+
primaryActions: localPrimaryActions,
|
|
254
|
+
scrollLock: localScrollLock,
|
|
255
|
+
trapFocus: localTrapFocus,
|
|
256
|
+
variant,
|
|
257
|
+
},
|
|
258
|
+
policy: consent.snapshot.policyRule,
|
|
259
|
+
presentation: {
|
|
260
|
+
...consent.state.presentation,
|
|
261
|
+
prompt: {
|
|
262
|
+
scrollLock: theme.scrollLock,
|
|
263
|
+
trapFocus: theme.trapFocus,
|
|
264
|
+
...consent.state.presentation?.prompt,
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
surface: 'prompt',
|
|
268
|
+
})
|
|
269
|
+
);
|
|
270
|
+
const actionGroups = $derived(presentation.actionGroups);
|
|
271
|
+
const primaryActions = $derived(presentation.primaryActions);
|
|
272
|
+
// Additional buttons that open preferences, styled as underlined text.
|
|
273
|
+
const preferenceControls = $derived(presentation.preferenceControls);
|
|
274
|
+
// A notice offers dismiss alone; with no primary resolved it takes the lead.
|
|
275
|
+
const dismissIsPrimary = $derived(
|
|
276
|
+
primaryActions.length === 0 &&
|
|
277
|
+
presentation.orderedActions.length === 1 &&
|
|
278
|
+
presentation.orderedActions[0] === 'dismiss'
|
|
279
|
+
);
|
|
280
|
+
const promptKind = $derived(consent.snapshot.policyRule.prompt);
|
|
281
|
+
const isNotice = $derived(promptKind === 'notice');
|
|
282
|
+
const direction = $derived(presentation.direction);
|
|
283
|
+
const shouldFillActions = $derived(presentation.shouldFillActions);
|
|
284
|
+
const shouldTrapFocus = $derived(presentation.trapFocus);
|
|
285
|
+
const shouldScrollLock = $derived(presentation.scrollLock);
|
|
286
|
+
const resolvedVariant = $derived(presentation.variant);
|
|
287
|
+
const isBlocking = $derived(presentation.blocking);
|
|
288
|
+
// A defaulted corner follows the text direction; a host position is
|
|
289
|
+
// physical and stays put.
|
|
290
|
+
const resolvedPosition = $derived.by(() => {
|
|
291
|
+
const { position: resolved, positionSource } = presentation;
|
|
292
|
+
const corner =
|
|
293
|
+
resolvedVariant === 'floating' || resolvedVariant === 'widget';
|
|
294
|
+
if (textDirection === 'rtl' && positionSource === 'default' && corner) {
|
|
295
|
+
return MIRRORED_POSITIONS[resolved] ?? resolved;
|
|
296
|
+
}
|
|
297
|
+
return resolved;
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
$effect(() => {
|
|
301
|
+
if (
|
|
302
|
+
typeof process === 'undefined' ||
|
|
303
|
+
process.env?.NODE_ENV !== 'production'
|
|
304
|
+
) {
|
|
305
|
+
for (const diagnostic of presentation.diagnostics) {
|
|
306
|
+
console.warn(diagnostic.message);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
// Resolved texts. A notice has its own copy: it informs and points at
|
|
312
|
+
// the opt-out instead of asking for permission.
|
|
313
|
+
const englishTranslations = defaultTranslationConfig.translations.en;
|
|
314
|
+
const resolvedTitle = $derived(
|
|
315
|
+
title ??
|
|
316
|
+
(isNotice
|
|
317
|
+
? (translations.cookieBanner.noticeTitle ??
|
|
318
|
+
englishTranslations?.cookieBanner?.noticeTitle)
|
|
319
|
+
: translations.cookieBanner.title)
|
|
320
|
+
);
|
|
321
|
+
const resolvedDescription = $derived(
|
|
322
|
+
description ??
|
|
323
|
+
(isNotice
|
|
324
|
+
? (translations.cookieBanner.noticeDescription ??
|
|
325
|
+
englishTranslations?.cookieBanner?.noticeDescription)
|
|
326
|
+
: translations.cookieBanner.description)
|
|
327
|
+
);
|
|
328
|
+
// Acknowledgement records no category choice.
|
|
329
|
+
const resolvedDismissText = $derived(
|
|
330
|
+
dismissButtonText ??
|
|
331
|
+
translations.common.acknowledge ??
|
|
332
|
+
translations.common.dismiss ??
|
|
333
|
+
englishTranslations?.common?.acknowledge
|
|
334
|
+
);
|
|
335
|
+
const rightLabels = $derived<
|
|
336
|
+
Partial<Record<PolicyRight, string | undefined>>
|
|
337
|
+
>({
|
|
338
|
+
'opt-out':
|
|
339
|
+
translations.rights?.optOut ?? englishTranslations?.rights?.optOut,
|
|
340
|
+
preferences:
|
|
341
|
+
translations.rights?.preferences ??
|
|
342
|
+
englishTranslations?.rights?.preferences,
|
|
343
|
+
});
|
|
344
|
+
const resolvedRejectText = $derived(
|
|
345
|
+
rejectButtonText ?? translations.common.rejectAll
|
|
346
|
+
);
|
|
347
|
+
const resolvedAcceptText = $derived(
|
|
348
|
+
acceptButtonText ?? translations.common.acceptAll
|
|
349
|
+
);
|
|
350
|
+
const resolvedCustomizeText = $derived(
|
|
351
|
+
customizeButtonText ?? translations.common.customize
|
|
352
|
+
);
|
|
353
|
+
</script>
|
|
354
|
+
|
|
355
|
+
{#if visibility.isMounted && visibility.shouldRender}
|
|
356
|
+
<div use:portal>
|
|
357
|
+
{#if shouldScrollLock}
|
|
358
|
+
<Overlay visible={visibility.isVisible} />
|
|
359
|
+
{/if}
|
|
360
|
+
<div
|
|
361
|
+
bind:this={visibility.bannerEl}
|
|
362
|
+
class={finalClassName}
|
|
363
|
+
dir={textDirection}
|
|
364
|
+
data-variant={resolvedVariant}
|
|
365
|
+
data-position={resolvedPosition}
|
|
366
|
+
data-blocking={isBlocking ? 'true' : undefined}
|
|
367
|
+
data-prompt={promptKind}
|
|
368
|
+
data-model={consent.state.model}
|
|
369
|
+
data-testid="consent-banner-root"
|
|
370
|
+
use:scrollLock={shouldScrollLock}
|
|
371
|
+
>
|
|
372
|
+
<div class={noStyle ? '' : styles.cardShell || ''}>
|
|
373
|
+
<Branding
|
|
374
|
+
{hideBranding}
|
|
375
|
+
{noStyle}
|
|
376
|
+
variant="banner-tag"
|
|
377
|
+
themeKey="consentBannerTag"
|
|
378
|
+
data-testid="consent-banner-branding"
|
|
379
|
+
/>
|
|
380
|
+
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
381
|
+
<div
|
|
382
|
+
class={noStyle ? '' : cardStyle.className || ''}
|
|
383
|
+
data-testid="consent-banner-card"
|
|
384
|
+
tabindex="-1"
|
|
385
|
+
role={isBlocking ? 'dialog' : 'region'}
|
|
386
|
+
aria-modal={isBlocking ? 'true' : undefined}
|
|
387
|
+
aria-label={resolvedTitle}
|
|
388
|
+
use:focusTrap={shouldTrapFocus}
|
|
389
|
+
>
|
|
390
|
+
<div
|
|
391
|
+
class={noStyle ? '' : headerStyle.className || ''}
|
|
392
|
+
data-testid="consent-banner-header"
|
|
393
|
+
>
|
|
394
|
+
<h2
|
|
395
|
+
class={noStyle ? '' : titleStyle.className || ''}
|
|
396
|
+
data-testid="consent-banner-title"
|
|
397
|
+
>
|
|
398
|
+
{resolvedTitle}
|
|
399
|
+
</h2>
|
|
400
|
+
<div
|
|
401
|
+
class={noStyle ? '' : descriptionStyle.className || ''}
|
|
402
|
+
data-context="banner"
|
|
403
|
+
data-testid="consent-banner-description"
|
|
404
|
+
>
|
|
405
|
+
{resolvedDescription}
|
|
406
|
+
<InlineLegalLinks
|
|
407
|
+
links={legalLinks}
|
|
408
|
+
themeKey="consentBannerDescription"
|
|
409
|
+
testIdPrefix="consent-banner-legal-link"
|
|
410
|
+
/>
|
|
411
|
+
</div>
|
|
412
|
+
</div>
|
|
413
|
+
<PolicyActionsRenderer
|
|
414
|
+
{actionGroups}
|
|
415
|
+
{primaryActions}
|
|
416
|
+
{shouldFillActions}
|
|
417
|
+
{direction}
|
|
418
|
+
{noStyle}
|
|
419
|
+
footerClassName={noStyle ? '' : footerStyle.className || ''}
|
|
420
|
+
footerSubGroupClassName={noStyle
|
|
421
|
+
? ''
|
|
422
|
+
: footerSubGroupStyle.className || ''}
|
|
423
|
+
footerTestId="consent-banner-footer"
|
|
424
|
+
footerSubGroupTestId="consent-banner-footer-sub-group"
|
|
425
|
+
>
|
|
426
|
+
{#snippet leading()}
|
|
427
|
+
{#if preferenceControls.length > 0}
|
|
428
|
+
<div
|
|
429
|
+
class={noStyle ? '' : rightsStyle.className || ''}
|
|
430
|
+
style={rightsStyle.style
|
|
431
|
+
? Object.entries(rightsStyle.style)
|
|
432
|
+
.map(([key, value]) => `${key}:${value}`)
|
|
433
|
+
.join(';')
|
|
434
|
+
: undefined}
|
|
435
|
+
data-testid="consent-banner-rights"
|
|
436
|
+
>
|
|
437
|
+
{#each preferenceControls as right (right)}
|
|
438
|
+
<button
|
|
439
|
+
type="button"
|
|
440
|
+
class={noStyle ? '' : rightLinkStyle.className || ''}
|
|
441
|
+
style={rightLinkStyle.style
|
|
442
|
+
? Object.entries(rightLinkStyle.style)
|
|
443
|
+
.map(([key, value]) => `${key}:${value}`)
|
|
444
|
+
.join(';')
|
|
445
|
+
: undefined}
|
|
446
|
+
data-action="right"
|
|
447
|
+
data-right={right}
|
|
448
|
+
data-c15t-rights={consent.snapshot.policyRule.rights.join(
|
|
449
|
+
' '
|
|
450
|
+
)}
|
|
451
|
+
data-testid={`consent-banner-right-link-${right}`}
|
|
452
|
+
onclick={openPreferences}
|
|
453
|
+
>
|
|
454
|
+
{rightLabels[right] ?? right}
|
|
455
|
+
</button>
|
|
456
|
+
{/each}
|
|
457
|
+
</div>
|
|
458
|
+
{/if}
|
|
459
|
+
{/snippet}
|
|
460
|
+
{#snippet renderAction(action: string, isPrimary: boolean)}
|
|
461
|
+
{#if action === 'reject'}
|
|
462
|
+
<ConsentButton
|
|
463
|
+
action="reject-consent"
|
|
464
|
+
variant={themedActions.reject.variant ??
|
|
465
|
+
(isPrimary ? 'primary' : 'neutral')}
|
|
466
|
+
mode={themedActions.reject.mode ?? 'stroke'}
|
|
467
|
+
closeConsentBanner
|
|
468
|
+
data-action="reject"
|
|
469
|
+
data-testid="consent-banner-reject-button"
|
|
470
|
+
>
|
|
471
|
+
{resolvedRejectText}
|
|
472
|
+
</ConsentButton>
|
|
473
|
+
{:else if action === 'accept'}
|
|
474
|
+
<ConsentButton
|
|
475
|
+
action="accept-consent"
|
|
476
|
+
variant={themedActions.accept.variant ??
|
|
477
|
+
(isPrimary ? 'primary' : 'neutral')}
|
|
478
|
+
mode={themedActions.accept.mode ?? 'stroke'}
|
|
479
|
+
closeConsentBanner
|
|
480
|
+
data-action="accept"
|
|
481
|
+
data-testid="consent-banner-accept-button"
|
|
482
|
+
>
|
|
483
|
+
{resolvedAcceptText}
|
|
484
|
+
</ConsentButton>
|
|
485
|
+
{:else if action === 'dismiss'}
|
|
486
|
+
<ConsentButton
|
|
487
|
+
action="dismiss-notice"
|
|
488
|
+
variant={themedActions.dismiss.variant ??
|
|
489
|
+
(isPrimary || dismissIsPrimary ? 'primary' : 'neutral')}
|
|
490
|
+
mode={themedActions.dismiss.mode ?? 'stroke'}
|
|
491
|
+
data-action="dismiss"
|
|
492
|
+
data-testid="consent-banner-dismiss-button"
|
|
493
|
+
>
|
|
494
|
+
{resolvedDismissText}
|
|
495
|
+
</ConsentButton>
|
|
496
|
+
{:else if action === 'customize'}
|
|
497
|
+
<ConsentButton
|
|
498
|
+
action="open-consent-dialog"
|
|
499
|
+
variant={themedActions.customize.variant ??
|
|
500
|
+
(isPrimary ? 'primary' : 'neutral')}
|
|
501
|
+
mode={themedActions.customize.mode ?? 'stroke'}
|
|
502
|
+
data-action="customize"
|
|
503
|
+
data-testid="consent-banner-customize-button"
|
|
504
|
+
>
|
|
505
|
+
{resolvedCustomizeText}
|
|
506
|
+
</ConsentButton>
|
|
507
|
+
{/if}
|
|
508
|
+
{/snippet}
|
|
509
|
+
</PolicyActionsRenderer>
|
|
510
|
+
</div>
|
|
511
|
+
</div>
|
|
512
|
+
</div>
|
|
513
|
+
</div>
|
|
514
|
+
{/if}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { LegalLinks as LegalLinksType, Model, PromptPosition, PromptVariant } from '@c15t/core';
|
|
2
|
+
/**
|
|
3
|
+
* Button identifiers for the consent banner layout.
|
|
4
|
+
*/
|
|
5
|
+
type ConsentBannerButton = 'reject' | 'accept' | 'customize' | 'dismiss';
|
|
6
|
+
type ConsentBannerLayout = (ConsentBannerButton | ConsentBannerButton[])[];
|
|
7
|
+
type $$ComponentProps = {
|
|
8
|
+
noStyle?: boolean;
|
|
9
|
+
disableAnimation?: boolean;
|
|
10
|
+
scrollLock?: boolean;
|
|
11
|
+
trapFocus?: boolean;
|
|
12
|
+
title?: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
rejectButtonText?: string;
|
|
15
|
+
customizeButtonText?: string;
|
|
16
|
+
acceptButtonText?: string;
|
|
17
|
+
dismissButtonText?: string;
|
|
18
|
+
hideBranding?: boolean;
|
|
19
|
+
legalLinks?: (keyof LegalLinksType)[] | null;
|
|
20
|
+
layout?: ConsentBannerLayout;
|
|
21
|
+
primaryButton?: ConsentBannerButton | ConsentBannerButton[];
|
|
22
|
+
/**
|
|
23
|
+
* Shape of the prompt. Overrides the host presentation.
|
|
24
|
+
* A notice defaults to `bar`, a choice prompt to `floating`.
|
|
25
|
+
*/
|
|
26
|
+
variant?: PromptVariant;
|
|
27
|
+
/**
|
|
28
|
+
* Where the prompt sits. Must be valid for the resolved variant;
|
|
29
|
+
* an invalid value falls back to the variant default with a
|
|
30
|
+
* development diagnostic.
|
|
31
|
+
*/
|
|
32
|
+
position?: PromptPosition;
|
|
33
|
+
/**
|
|
34
|
+
* Backdrop, scroll lock, focus trap, and no dismissal from outside,
|
|
35
|
+
* as one value. `wall` is always blocking; a notice never is.
|
|
36
|
+
*/
|
|
37
|
+
blocking?: boolean;
|
|
38
|
+
models?: Model[];
|
|
39
|
+
class?: string;
|
|
40
|
+
};
|
|
41
|
+
declare const Prompt: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
42
|
+
type Prompt = ReturnType<typeof Prompt>;
|
|
43
|
+
export default Prompt;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import type { ActiveUI, AllConsentNames, ConsentKernel, ConsentPresentation, ResolvedConsentPresentation, ConsentSnapshot, ConsentState, ConsentType, HasCondition, KernelIABState, Model, TranslationConfig } from '@c15t/core';
|
|
2
|
+
import type { Theme, UIOptions } from '@c15t/ui/theme';
|
|
3
|
+
import type { ConsentManagerOptions } from './types';
|
|
4
|
+
export type SaveType = 'all' | 'custom' | 'necessary';
|
|
5
|
+
export interface SvelteIABState extends KernelIABState {
|
|
6
|
+
config: {
|
|
7
|
+
enabled: boolean;
|
|
8
|
+
cmpId: number | null;
|
|
9
|
+
};
|
|
10
|
+
isLoadingGVL: boolean;
|
|
11
|
+
nonIABVendors: KernelIABState['customVendors'];
|
|
12
|
+
preferenceCenterTab: 'purposes' | 'vendors';
|
|
13
|
+
setPreferenceCenterTab: (tab: 'purposes' | 'vendors') => void;
|
|
14
|
+
setVendorConsent: (vendorId: string | number, value: boolean) => void;
|
|
15
|
+
setVendorLegitimateInterest: (vendorId: string | number, value: boolean) => void;
|
|
16
|
+
setPurposeConsent: (purposeId: number, value: boolean) => void;
|
|
17
|
+
setPurposeLegitimateInterest: (purposeId: number, value: boolean) => void;
|
|
18
|
+
setSpecialFeatureOptIn: (featureId: number, value: boolean) => void;
|
|
19
|
+
acceptAll: () => void;
|
|
20
|
+
rejectAll: () => void;
|
|
21
|
+
save: () => Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
export interface ConsentDraftState {
|
|
24
|
+
readonly values: Partial<ConsentState>;
|
|
25
|
+
readonly isStale: boolean;
|
|
26
|
+
set: (name: AllConsentNames, value: boolean) => void;
|
|
27
|
+
reset: () => void;
|
|
28
|
+
save: (categories: readonly AllConsentNames[]) => Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
export interface ConsentManagerState extends Pick<ConsentSnapshot, 'explicitChoice' | 'effectivePermissions' | 'promptRequirement' | 'noticeDismissal' | 'privacySignals' | 'optOutDirectives' | 'resolution' | 'policyRule' | 'restrictions' | 'nextDeadline' | 'subject' | 'evaluatedAt' | 'evaluationPolicy' | 'policyPending' | 'location' | 'overrides' | 'revision' | 'translations' | 'user'> {
|
|
31
|
+
activeUI: ActiveUI;
|
|
32
|
+
branding: NonNullable<ConsentSnapshot['branding']>;
|
|
33
|
+
selectedConsents: Partial<ConsentState>;
|
|
34
|
+
selectedConsentTypes: Partial<ConsentState>;
|
|
35
|
+
presentation?: ConsentPresentation;
|
|
36
|
+
readonly draft: ConsentDraftState;
|
|
37
|
+
consentCategories: AllConsentNames[];
|
|
38
|
+
consentTypes: ConsentType[];
|
|
39
|
+
iab: SvelteIABState | null;
|
|
40
|
+
manager: null;
|
|
41
|
+
model: Model;
|
|
42
|
+
/**
|
|
43
|
+
* Whether a policy rule is resolved for this visitor. Every c15t consent
|
|
44
|
+
* surface renders nothing until one is: an unconfigured, failed, or
|
|
45
|
+
* unmatched resolution leaves nothing to consent to, and the surfaces
|
|
46
|
+
* appear on their own once a later init supplies a rule.
|
|
47
|
+
*/
|
|
48
|
+
hasPolicy: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Whether the resolved rule owes any consent UI. A prompt owes a banner
|
|
51
|
+
* and a preference center; rights owe a way back to preferences. A `none`
|
|
52
|
+
* rule with no rights owes neither, so every surface stays hidden while
|
|
53
|
+
* the permissions it grants apply. `false` until a rule is resolved.
|
|
54
|
+
*/
|
|
55
|
+
hasConsentUi: boolean;
|
|
56
|
+
legalLinks: ConsentManagerOptions['legalLinks'];
|
|
57
|
+
translationConfig: TranslationConfig;
|
|
58
|
+
getDisplayedConsents: () => ConsentType[];
|
|
59
|
+
has: (condition: HasCondition<AllConsentNames>) => boolean;
|
|
60
|
+
dismissNotice: () => Promise<unknown>;
|
|
61
|
+
saveConsents: (type: SaveType) => Promise<void>;
|
|
62
|
+
setActiveUI: (ui: ActiveUI, options?: {
|
|
63
|
+
force?: boolean;
|
|
64
|
+
}) => void;
|
|
65
|
+
setConsent: (name: AllConsentNames, value: boolean) => void;
|
|
66
|
+
setLanguage: (code: string) => void;
|
|
67
|
+
setSelectedConsent: (name: AllConsentNames, value: boolean) => void;
|
|
68
|
+
subscribeToConsentChanges: (listener: (state: ConsentState) => void) => () => void;
|
|
69
|
+
}
|
|
70
|
+
export interface ConsentContextValue {
|
|
71
|
+
readonly clearRecords: () => void;
|
|
72
|
+
readonly kernel: ConsentKernel;
|
|
73
|
+
readonly snapshot: ConsentSnapshot;
|
|
74
|
+
readonly state: ConsentManagerState;
|
|
75
|
+
readonly manager: ConsentKernel;
|
|
76
|
+
}
|
|
77
|
+
export interface ThemeContextValue {
|
|
78
|
+
readonly theme?: Theme;
|
|
79
|
+
readonly noStyle?: boolean;
|
|
80
|
+
readonly disableAnimation?: boolean;
|
|
81
|
+
readonly scrollLock?: boolean;
|
|
82
|
+
readonly trapFocus?: boolean;
|
|
83
|
+
readonly colorScheme?: UIOptions['colorScheme'];
|
|
84
|
+
readonly legalLinks?: ConsentManagerOptions['legalLinks'];
|
|
85
|
+
}
|
|
86
|
+
export interface ConsentControllerOptions {
|
|
87
|
+
clearRecords?: () => void;
|
|
88
|
+
getSnapshot: () => ConsentSnapshot;
|
|
89
|
+
getDraft: () => ConsentDraftState;
|
|
90
|
+
getIAB: () => SvelteIABState | null;
|
|
91
|
+
getConsentCategories: () => AllConsentNames[];
|
|
92
|
+
getLegalLinks: () => ConsentManagerOptions['legalLinks'];
|
|
93
|
+
getPresentation: () => ConsentPresentation | undefined;
|
|
94
|
+
}
|
|
95
|
+
export declare const setConsentContext: (kernel: ConsentKernel, options: ConsentControllerOptions) => void;
|
|
96
|
+
export declare const getConsentContext: () => ConsentContextValue;
|
|
97
|
+
export declare const getConsentKernel: () => ConsentKernel;
|
|
98
|
+
export declare const getSnapshot: () => ConsentSnapshot;
|
|
99
|
+
/**
|
|
100
|
+
* Returns the reactive consent manager controller for the current component.
|
|
101
|
+
*
|
|
102
|
+
* Exposes both readable state (`consents`, `activeUI`, `model`, …) and
|
|
103
|
+
* mutators (`setConsent`, `saveConsents`, `setActiveUI`, `setLanguage`, …).
|
|
104
|
+
* This is the primary API for reading and writing consent from inside your
|
|
105
|
+
* own components — equivalent to React's `useConsentManager()`.
|
|
106
|
+
*
|
|
107
|
+
* Must be called inside a component tree wrapped in `<ConsentManagerProvider>`.
|
|
108
|
+
*/
|
|
109
|
+
export declare const getConsentManager: () => ConsentManagerState;
|
|
110
|
+
export interface HeadlessConsentSurfaceState extends ResolvedConsentPresentation {
|
|
111
|
+
isVisible: boolean;
|
|
112
|
+
}
|
|
113
|
+
export declare const getHeadlessConsent: () => {
|
|
114
|
+
readonly activeUI: ActiveUI;
|
|
115
|
+
readonly banner: HeadlessConsentSurfaceState;
|
|
116
|
+
closeUI(): void;
|
|
117
|
+
readonly dialog: HeadlessConsentSurfaceState;
|
|
118
|
+
openBanner(): void;
|
|
119
|
+
openDialog(): void;
|
|
120
|
+
performAction(action: "accept" | "reject" | "customize" | "dismiss" | "save"): Promise<void>;
|
|
121
|
+
saveCustomPreferences(): Promise<void>;
|
|
122
|
+
};
|
|
123
|
+
export declare const getIAB: () => SvelteIABState | null;
|
|
124
|
+
export declare const setThemeContext: (value: ThemeContextValue) => void;
|
|
125
|
+
export declare const getThemeContext: () => ThemeContextValue;
|