@c15t/browser 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.
Files changed (93) hide show
  1. package/AGENTS.md +64 -0
  2. package/CHANGELOG.md +27 -0
  3. package/README.md +128 -0
  4. package/dist/861.js +1079 -0
  5. package/dist/925.js +649 -0
  6. package/dist/c15t.css +213 -0
  7. package/dist/c15t.devtools.js +1 -0
  8. package/dist/c15t.headless.js +1 -0
  9. package/dist/c15t.iab.css +190 -0
  10. package/dist/c15t.iab.js +221 -0
  11. package/dist/c15t.js +30 -0
  12. package/dist/devtools.js +11 -0
  13. package/dist/headless.js +17 -0
  14. package/dist/iab.js +784 -0
  15. package/dist/index.js +17 -0
  16. package/dist-types/auto-init.d.ts +42 -0
  17. package/dist-types/client.d.ts +51 -0
  18. package/dist-types/deferred.d.ts +13 -0
  19. package/dist-types/devtools.d.ts +32 -0
  20. package/dist-types/entries/cdn-devtools.d.ts +13 -0
  21. package/dist-types/entries/cdn-headless.d.ts +8 -0
  22. package/dist-types/entries/cdn-iab.d.ts +1 -0
  23. package/dist-types/entries/cdn.d.ts +8 -0
  24. package/dist-types/gated-scripts.d.ts +35 -0
  25. package/dist-types/generated/iab-styles.d.ts +144 -0
  26. package/dist-types/generated/styles.d.ts +137 -0
  27. package/dist-types/global.d.ts +112 -0
  28. package/dist-types/headless.d.ts +41 -0
  29. package/dist-types/iab/mount.d.ts +8 -0
  30. package/dist-types/iab/preferences.d.ts +9 -0
  31. package/dist-types/iab/styles.d.ts +2 -0
  32. package/dist-types/iab/surface.d.ts +4 -0
  33. package/dist-types/iab/vendor-disclosures.d.ts +14 -0
  34. package/dist-types/iab.d.ts +20 -0
  35. package/dist-types/index.d.ts +43 -0
  36. package/dist-types/transports/manifest.d.ts +62 -0
  37. package/dist-types/transports/offline.d.ts +18 -0
  38. package/dist-types/types.d.ts +290 -0
  39. package/dist-types/ui/actions.d.ts +29 -0
  40. package/dist-types/ui/banner.d.ts +13 -0
  41. package/dist-types/ui/branding.d.ts +25 -0
  42. package/dist-types/ui/copy.d.ts +28 -0
  43. package/dist-types/ui/dialog.d.ts +14 -0
  44. package/dist-types/ui/dom.d.ts +48 -0
  45. package/dist-types/ui/mount.d.ts +27 -0
  46. package/dist-types/ui/surface.d.ts +43 -0
  47. package/dist-types/ui/trigger.d.ts +14 -0
  48. package/dist-types/ui/widget.d.ts +27 -0
  49. package/dist-types/version.d.ts +1 -0
  50. package/docs/README.md +64 -0
  51. package/docs/frameworks/javascript/script-loader.md +47 -0
  52. package/docs/frameworks/javascript/script-tag.md +375 -0
  53. package/docs/integrations/adobe-analytics.md +294 -0
  54. package/docs/integrations/ahrefs-analytics.md +291 -0
  55. package/docs/integrations/amplitude.md +292 -0
  56. package/docs/integrations/building-integrations.md +47 -0
  57. package/docs/integrations/clearbit.md +291 -0
  58. package/docs/integrations/cloudflare-web-analytics.md +292 -0
  59. package/docs/integrations/crisp.md +294 -0
  60. package/docs/integrations/databuddy.md +311 -0
  61. package/docs/integrations/fathom-analytics.md +293 -0
  62. package/docs/integrations/google-maps.md +384 -0
  63. package/docs/integrations/google-tag-manager.md +306 -0
  64. package/docs/integrations/google-tag.md +305 -0
  65. package/docs/integrations/heap.md +292 -0
  66. package/docs/integrations/hightouch.md +293 -0
  67. package/docs/integrations/hotjar.md +292 -0
  68. package/docs/integrations/intercom.md +285 -0
  69. package/docs/integrations/linkedin-insights.md +291 -0
  70. package/docs/integrations/logrocket.md +293 -0
  71. package/docs/integrations/matomo-analytics.md +316 -0
  72. package/docs/integrations/meta-pixel.md +285 -0
  73. package/docs/integrations/microsoft-clarity.md +292 -0
  74. package/docs/integrations/microsoft-uet.md +291 -0
  75. package/docs/integrations/mixpanel-analytics.md +295 -0
  76. package/docs/integrations/openai-pixel.md +441 -0
  77. package/docs/integrations/overview.md +111 -0
  78. package/docs/integrations/pirsch.md +295 -0
  79. package/docs/integrations/plausible-analytics.md +295 -0
  80. package/docs/integrations/posthog.md +397 -0
  81. package/docs/integrations/promptwatch.md +291 -0
  82. package/docs/integrations/reddit-pixel.md +294 -0
  83. package/docs/integrations/rudderstack.md +328 -0
  84. package/docs/integrations/rybbit-analytics.md +296 -0
  85. package/docs/integrations/segment.md +292 -0
  86. package/docs/integrations/snapchat-pixel.md +293 -0
  87. package/docs/integrations/tiktok-pixel.md +291 -0
  88. package/docs/integrations/umami-analytics.md +295 -0
  89. package/docs/integrations/vercel-analytics.md +293 -0
  90. package/docs/integrations/x-pixel.md +291 -0
  91. package/docs/integrations/youtube.md +405 -0
  92. package/package.json +117 -0
  93. package/readme.json +44 -0
@@ -0,0 +1,41 @@
1
+ /**
2
+ * `@c15t/browser/headless` — the client without any UI or CSS.
3
+ *
4
+ * For sites that render their own banner: subscribe to the client, call
5
+ * `acceptAll()` / `rejectAll()` / `save()`, or mark page elements with
6
+ * `data-c15t-action` and let the client wire them.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { init } from '@c15t/browser/headless';
11
+ *
12
+ * const c15t = init({ backendURL: 'https://your-instance.c15t.dev' });
13
+ * c15t.on('ui', (surface) => banner.hidden = surface !== 'banner');
14
+ * ```
15
+ */
16
+ import type { ConsentClient, ConsentClientOptions } from './types';
17
+ /**
18
+ * Create the page's client without starting it. `mountUI()` throws.
19
+ *
20
+ * @param options - Client options.
21
+ * @returns The client.
22
+ */
23
+ export declare const createConsentClient: (options?: ConsentClientOptions) => ConsentClient;
24
+ /**
25
+ * Create and start the page's client with no UI.
26
+ *
27
+ * @param options - Client options.
28
+ * @returns The started client.
29
+ */
30
+ export declare const init: (options?: ConsentClientOptions) => ConsentClient;
31
+ export { ACTION_ATTRIBUTE, custom, hosted, PREFERENCES_HASH } from './client';
32
+ export type { PageAction } from './client';
33
+ export { resolveRules } from './client';
34
+ export { ACTIVATED_ATTRIBUTE, activateGatedScripts, CATEGORY_ATTRIBUTE, } from './gated-scripts';
35
+ export { manifest, manifestNeedsLocation } from './transports/manifest';
36
+ export type { ManifestModeOptions } from './transports/manifest';
37
+ export { offline } from './transports/offline';
38
+ export type { OfflineModeOptions } from './transports/offline';
39
+ export type { ConsentClient, ConsentClientEventMap, ConsentClientOptions, ConsentModeName, PolicyPresetName, } from './types';
40
+ export { version } from './version';
41
+ export type { ConsentSnapshot, ConsentState } from '@c15t/core';
@@ -0,0 +1,8 @@
1
+ import type { ConsentClient, ConsentUIHandle, ConsentUIOptions } from '../types';
2
+ /**
3
+ * Mount IAB UI alongside the ordinary UI for non-IAB policy regions.
4
+ * @param client - The IAB-capable client to render.
5
+ * @param options - Theme, CSS, and mount settings.
6
+ * @returns The shared UI host and its teardown.
7
+ */
8
+ export declare const mountIABConsentUI: (client: ConsentClient, options?: ConsentUIOptions) => ConsentUIHandle;
@@ -0,0 +1,9 @@
1
+ import type { ConsentSnapshot } from '@c15t/core';
2
+ import type { SurfaceContext } from '../ui/surface';
3
+ /** Preference content preserves focused controls while the IAB draft changes. */
4
+ export interface IABPreferences {
5
+ element: HTMLElement;
6
+ sync: (snapshot: ConsentSnapshot) => void;
7
+ }
8
+ /** Render purpose, special-feature, and vendor choices from the shared model. */
9
+ export declare const createIABPreferences: (ctx: SurfaceContext, vendorsFirst: boolean, moreVendorsText?: string) => IABPreferences;
@@ -0,0 +1,2 @@
1
+ /** Native disclosure and touch-target adjustments for the IAB DOM adapter. */
2
+ export declare const adapterStyles = "\n[data-testid=\"iab-consent-banner-root\"], [data-testid=\"iab-consent-dialog-root\"] { pointer-events: none; }\n[data-testid=\"iab-consent-banner-card\"], [data-testid=\"iab-consent-dialog-card\"] { pointer-events: auto; }\n[data-testid=\"iab-consent-banner-root\"][data-variant=\"floating\"][data-position^=\"top\"] { align-items: flex-start; }\n[data-testid=\"iab-consent-banner-root\"][data-variant=\"floating\"][data-position^=\"bottom\"] { align-items: flex-end; }\n[data-testid=\"iab-consent-banner-root\"][data-variant=\"floating\"][data-position$=\"left\"] { justify-content: flex-start; }\n[data-testid=\"iab-consent-banner-root\"][data-variant=\"floating\"][data-position$=\"right\"] { justify-content: flex-end; }\n[data-testid=\"iab-consent-banner-root\"][data-variant=\"bar\"] { --iab-consent-banner-max-width: 100%; align-items: flex-end; }\n[data-testid=\"iab-consent-banner-root\"][data-variant=\"bar\"][data-position=\"top\"] { align-items: flex-start; }\n[data-testid=\"iab-consent-banner-card\"] { max-height: calc(100dvh - 4rem); overflow-y: auto; }\n[data-c15t-iab-disclosure] > summary { box-sizing: border-box; min-height: 44px; cursor: pointer; list-style: none; justify-content: flex-start; align-items: center; }\n[data-c15t-iab-disclosure] > summary > :last-child { flex: 1; }\n[data-c15t-iab-disclosure] > summary::-webkit-details-marker { display: none; }\n[data-c15t-iab-chevron] { display: inline-block; color: var(--c15t-text-muted); }\n[data-c15t-iab-disclosure][open] > summary [data-c15t-iab-chevron] { transform: rotate(90deg); }\n[data-testid^=\"iab-consent-\"] button { min-height: 44px; touch-action: manipulation; }\n[data-c15t-iab-toggle] { width: 44px; height: 44px; padding: 12px 6px; }\n[data-c15t-iab-vendor-details] { display: block; padding: 0 0.75rem 0.75rem; font-size: 0.875rem; line-height: 1.5; }\n[data-c15t-iab-vendor-details] h3 { margin: 1rem 0 0.375rem; font-size: 0.875rem; font-weight: 600; }\n[data-c15t-iab-vendor-details] p { margin: 0.5rem 0; }\n[data-c15t-iab-vendor-details] ul { margin: 0.375rem 0; padding-inline-start: 1.25rem; }\n[data-testid^=\"iab-consent-\"] summary:focus-visible { outline: 2px solid var(--c15t-primary); outline-offset: 2px; }\n[data-testid=\"iab-consent-dialog-root\"] input[type=\"search\"] { font-size: 16px; }\n";
@@ -0,0 +1,4 @@
1
+ import type { ConsentUIOptions } from '../types';
2
+ import type { Surface, SurfaceContext } from '../ui/surface';
3
+ /** One IAB banner/dialog lifecycle on the client's existing kernel. */
4
+ export declare const createIABSurface: (ctx: SurfaceContext, options: ConsentUIOptions) => Surface;
@@ -0,0 +1,14 @@
1
+ import type { ConsentSnapshot, GlobalVendorList, NonIABVendor } from '@c15t/core';
2
+ import type { SurfaceCopy } from '../ui/copy';
3
+ type Vendor = GlobalVendorList['vendors'][number] | NonIABVendor;
4
+ /**
5
+ * Render the vendor's declared policies, data use, storage, and retention.
6
+ * Missing durations remain undisclosed rather than becoming zero days.
7
+ *
8
+ * @param snapshot - Current consent state containing the GVL definitions.
9
+ * @param vendor - Registered or custom vendor to describe.
10
+ * @param copy - Resolved translations and preferred language.
11
+ * @returns Disclosure content to append after the vendor's consent controls.
12
+ */
13
+ export declare const createVendorDisclosures: (snapshot: ConsentSnapshot, vendor: Vendor, copy: SurfaceCopy) => DocumentFragment;
14
+ export {};
@@ -0,0 +1,20 @@
1
+ import type { ConsentClient, ConsentClientOptions } from './types';
2
+ /**
3
+ * Create an IAB-capable browser client without starting it.
4
+ * @param options - Transport, CMP, and presentation settings.
5
+ * @returns The client, with one runtime shared by ordinary and IAB UI.
6
+ */
7
+ export declare const createConsentClient: (options?: ConsentClientOptions) => ConsentClient;
8
+ /**
9
+ * Create and start an IAB-capable browser client.
10
+ * @param options - Transport, CMP, and presentation settings.
11
+ * @returns The started client. CMP controls are on `client.runtime.iab`.
12
+ */
13
+ export declare const init: (options?: ConsentClientOptions) => ConsentClient;
14
+ export { custom, hosted } from './client';
15
+ export { offline } from './transports/offline';
16
+ export { manifest } from './transports/manifest';
17
+ export { mountIABConsentUI } from './iab/mount';
18
+ export type { ConsentClient, ConsentClientOptions, ConsentUIOptions, } from './types';
19
+ export { iab } from '@c15t/iab';
20
+ export { version } from './version';
@@ -0,0 +1,43 @@
1
+ /**
2
+ * `@c15t/browser` — consent for sites without a build step.
3
+ *
4
+ * Most sites load `dist/c15t.js` from a CDN and never import this module.
5
+ * Bundler users get the same client and UI as ES modules here; the
6
+ * headless subset lives at `@c15t/browser/headless`.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { init } from '@c15t/browser';
11
+ * import '@c15t/browser/styles.css'; // only with `ui: { shadow: false }`
12
+ *
13
+ * const c15t = init({ backendURL: 'https://your-instance.c15t.dev' });
14
+ * c15t.on('consent', (snapshot) => console.log(snapshot.effectivePermissions));
15
+ * ```
16
+ */
17
+ import type { ConsentClient, ConsentClientOptions } from './types';
18
+ /**
19
+ * Create the page's client without starting it.
20
+ *
21
+ * @param options - Client options.
22
+ * @returns The client. Call `start()` to resolve the policy and mount.
23
+ */
24
+ export declare const createConsentClient: (options?: ConsentClientOptions) => ConsentClient;
25
+ /**
26
+ * Create and start the page's client, mounting the UI unless `ui: false`.
27
+ *
28
+ * @param options - Client options.
29
+ * @returns The started client.
30
+ */
31
+ export declare const init: (options?: ConsentClientOptions) => ConsentClient;
32
+ export { ACTION_ATTRIBUTE, custom, hosted, PREFERENCES_HASH } from './client';
33
+ export type { PageAction } from './client';
34
+ export { resolveRules } from './client';
35
+ export { ACTIVATED_ATTRIBUTE, activateGatedScripts, CATEGORY_ATTRIBUTE, } from './gated-scripts';
36
+ export { manifest, manifestNeedsLocation } from './transports/manifest';
37
+ export type { ManifestModeOptions } from './transports/manifest';
38
+ export { offline } from './transports/offline';
39
+ export type { OfflineModeOptions } from './transports/offline';
40
+ export type { ConsentBannerOptions, ConsentClient, ConsentClientEventMap, ConsentClientOptions, ConsentDialogOptions, ConsentModeName, PolicyPresetName, ConsentTriggerOptions, ConsentUIHandle, ConsentUIOptions, TriggerPosition, } from './types';
41
+ export { mountConsentUI } from './ui/mount';
42
+ export { version } from './version';
43
+ export type { ConsentSnapshot, ConsentState } from '@c15t/core';
@@ -0,0 +1,62 @@
1
+ import type { ProviderTransportFactory } from '@c15t/core';
2
+ import type { ConsentManifest, ResolveInitFromManifestInputs } from '@c15t/schema/types';
3
+ /** Options for {@link manifest}. */
4
+ export interface ManifestModeOptions {
5
+ /**
6
+ * The manifest itself, inlined. With it the first render needs no
7
+ * request at all for a policy that does not depend on location.
8
+ */
9
+ manifest?: ConsentManifest;
10
+ /** Where to fetch the manifest when it is not inlined. */
11
+ manifestURL?: string;
12
+ /**
13
+ * Backend origin for `POST /subjects`, and for `GET /init` when the
14
+ * policy depends on a location the browser does not know. Derived only
15
+ * from a `manifestURL` ending in `/manifest`. Required for other URLs
16
+ * and inline-only manifests. Use `''` for this origin.
17
+ */
18
+ backendURL?: string;
19
+ /**
20
+ * Decision inputs known ahead of time, typically the country an edge
21
+ * worker injected into the page. Kernel overrides win over these.
22
+ */
23
+ inputs?: ResolveInitFromManifestInputs;
24
+ /** Fetch implementation. Defaults to `globalThis.fetch`. */
25
+ fetch?: typeof globalThis.fetch;
26
+ }
27
+ /**
28
+ * Whether resolving this manifest needs to know where the visitor is.
29
+ *
30
+ * A manifest whose packs all match by default or fallback — "one banner
31
+ * for everyone" — resolves the same everywhere, so the browser can do it
32
+ * without a round trip. Anything keyed by country or region, or the
33
+ * jurisdiction defaults that apply without packs, needs a location.
34
+ *
35
+ * @param manifest - The manifest.
36
+ * @returns `true` when a country is required for a faithful answer.
37
+ */
38
+ export declare const manifestNeedsLocation: (manifest: ConsentManifest) => boolean;
39
+ /**
40
+ * Resolve `/init` in the browser from the backend's consent manifest.
41
+ *
42
+ * The manifest is the geo-independent half of the backend's decision:
43
+ * policy packs, translations, branding. Inlining it into the page (or
44
+ * fetching it once, cached at the CDN) lets the banner render without a
45
+ * per-visitor `/init` round trip. Saves still go to the backend.
46
+ *
47
+ * When the policy depends on location and no country is known, the
48
+ * transport falls back to `GET /init` so the answer stays faithful.
49
+ *
50
+ * @param options - Manifest source and backend.
51
+ * @returns A transport factory for `mode`.
52
+ * @throws {Error} When neither `manifest` nor `manifestURL` is given,
53
+ * or a backend cannot be derived and `backendURL` is omitted.
54
+ *
55
+ * @example
56
+ * ```ts
57
+ * init({
58
+ * mode: manifest({ manifest: window.__c15tManifest, backendURL: 'https://x.c15t.dev' }),
59
+ * });
60
+ * ```
61
+ */
62
+ export declare const manifest: (options: ManifestModeOptions) => ProviderTransportFactory;
@@ -0,0 +1,18 @@
1
+ import type { ProviderTransportFactory } from '@c15t/core';
2
+ import type { PolicyRule } from '@c15t/schema/types';
3
+ /** Policy rules evaluated locally when initialization runs. */
4
+ export interface OfflineModeOptions {
5
+ /**
6
+ * Rules to resolve locally. Omit them to use `recommendedPolicyRules()`:
7
+ * strict opt-in for Europe, the UK, Quebec and unknown locations, opt-out
8
+ * for the US states with a privacy law, and `none` everywhere else.
9
+ * Passing rules replaces that pack entirely.
10
+ */
11
+ policyRules?: PolicyRule[];
12
+ }
13
+ /**
14
+ * Resolve local rules outside render and hydration.
15
+ * @param options - Explicit policy rules; absence resolves the recommended pack.
16
+ * @returns A provider transport with no network requests.
17
+ */
18
+ export declare const offline: (options?: OfflineModeOptions) => ProviderTransportFactory;
@@ -0,0 +1,290 @@
1
+ import type { AllConsentNames, Callbacks, ConsentPresentation, SaveResult, NoticeDismissResult, ConsentKernel, ConsentSnapshot, ConsentState, HasCondition, I18nConfig, KernelActiveUI, KernelConfig, KernelOverrides, KernelUser, LegalLinks, PolicyRule, policyRulePresets, ProviderTransportFactory, Script, StorageConfig, Unsubscribe } from '@c15t/core';
2
+ import type { ConsentRuntime, ConsentRuntimeOptions, RuntimeNetworkBlockerOptions } from '@c15t/core/runtime';
3
+ import type { ConsentManifest } from '@c15t/schema/types';
4
+ import type { Theme } from '@c15t/ui/theme';
5
+ /**
6
+ * The transports a script-tag site can name without importing anything.
7
+ *
8
+ * - `hosted` — `GET /init` and `POST /subjects` against `backendURL`.
9
+ * - `offline` — no backend; policy resolved from `policies` (or a default
10
+ * opt-in banner) and consent kept in the browser only.
11
+ * - `manifest` — the backend's cacheable `/manifest` inlined or fetched,
12
+ * resolved locally so the banner can render without waiting on `/init`.
13
+ */
14
+ export type ConsentModeName = 'hosted' | 'offline' | 'manifest';
15
+ /** A built-in policy pack, by the name `policyRulePresets` exports it under. */
16
+ export type PolicyPresetName = keyof typeof policyRulePresets;
17
+ /** Corner the floating preferences button docks to. */
18
+ export type TriggerPosition = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
19
+ /** Copy and behaviour overrides for the cookie banner. */
20
+ export interface ConsentBannerOptions {
21
+ /** Heading. Defaults to the resolved translation. */
22
+ title?: string;
23
+ /** Body copy. Defaults to the resolved translation. */
24
+ description?: string;
25
+ /** "Accept all" label. */
26
+ acceptButtonText?: string;
27
+ /** "Reject all" label. */
28
+ rejectButtonText?: string;
29
+ /** "Customize" label. */
30
+ customizeButtonText?: string;
31
+ /** Drop the "Secured by c15t" tag. The IAB banner always retains its tag. */
32
+ hideBranding?: boolean;
33
+ /** Which legal links to render inline. `null` renders none. */
34
+ legalLinks?: (keyof LegalLinks)[] | null;
35
+ /** Dim the page and stop it scrolling while the banner is up. */
36
+ scrollLock?: boolean;
37
+ /** Legacy blocking override. Prefer `presentation.prompt.blocking`. */
38
+ trapFocus?: boolean;
39
+ }
40
+ /** Overrides for the preference centre dialog. */
41
+ export interface ConsentDialogOptions {
42
+ /** Drop the "Secured by c15t" tag. */
43
+ hideBranding?: boolean;
44
+ /** Which legal links to render inline. `null` renders none. */
45
+ legalLinks?: (keyof LegalLinks)[] | null;
46
+ }
47
+ /** The floating button that reopens the preference centre. */
48
+ export interface ConsentTriggerOptions {
49
+ /** Corner to dock to. Defaults to `bottom-right`. */
50
+ position?: TriggerPosition;
51
+ /** Button size. Defaults to `md`. */
52
+ size?: 'sm' | 'md' | 'lg';
53
+ /**
54
+ * When to show it. `always` (default) whenever no other surface is
55
+ * open; `after-consent` only once the visitor has decided.
56
+ */
57
+ showWhen?: 'always' | 'after-consent';
58
+ /** Accessible name. */
59
+ ariaLabel?: string;
60
+ /** Remember a dragged-to corner in localStorage. Defaults to `true`. */
61
+ persistPosition?: boolean;
62
+ }
63
+ /** How and where the prebuilt UI mounts. */
64
+ export interface ConsentUIOptions {
65
+ /** Copy for browser-specific IAB loading, saving, and pagination states. */
66
+ iab?: {
67
+ loadErrorText?: string;
68
+ saveErrorText?: string;
69
+ moreVendorsText?: string;
70
+ };
71
+ /**
72
+ * Element (or selector) to append the UI host to. Defaults to
73
+ * `document.body`.
74
+ */
75
+ container?: HTMLElement | string;
76
+ /**
77
+ * Render inside a shadow root so the host page's CSS cannot restyle the
78
+ * banner and vice versa. Defaults to `true`; set `false` when you want
79
+ * to override the styles with your own stylesheet.
80
+ */
81
+ shadow?: boolean;
82
+ /** Colour scheme. Defaults to `system`. */
83
+ colorScheme?: 'light' | 'dark' | 'system';
84
+ /** Theme token overrides, the same shape `@c15t/react` accepts. */
85
+ theme?: Theme;
86
+ /** Extra CSS appended after the bundled stylesheet. */
87
+ css?: string;
88
+ /**
89
+ * Include the bundled stylesheet. Defaults to `true`. With `shadow: false`,
90
+ * set `false` when the page loads `@c15t/browser/styles.css`.
91
+ */
92
+ styles?: boolean;
93
+ /** Ship the DOM without any class names, for fully custom CSS. */
94
+ noStyle?: boolean;
95
+ /** Skip enter and exit transitions. */
96
+ disableAnimation?: boolean;
97
+ /** Render the banner. Defaults to `true`. */
98
+ banner?: boolean | ConsentBannerOptions;
99
+ /** Render the preference centre. Defaults to `true`. */
100
+ dialog?: boolean | ConsentDialogOptions;
101
+ /** Render the floating reopen button. Defaults to `false`. */
102
+ trigger?: boolean | ConsentTriggerOptions;
103
+ }
104
+ /**
105
+ * Everything `init()` accepts. Queue serializable options, transport
106
+ * factories, callbacks, and DOM containers through `c15t.push(['config', {...}])` on a no-code site.
107
+ */
108
+ export interface ConsentClientOptions {
109
+ /** IAB configuration. Requires the `@c15t/browser/iab` entry. */
110
+ iab?: ConsentRuntimeOptions['iab'];
111
+ /**
112
+ * Transport. A name picks one of the built-in modes; a factory from
113
+ * `hosted()`, `offline()`, `manifest()` or `custom()` is used as is.
114
+ * Defaults to `manifest` when a manifest is given, `hosted` when a
115
+ * `backendURL` is given, otherwise `offline`.
116
+ */
117
+ mode?: ProviderTransportFactory | ConsentModeName;
118
+ /** Backend origin for `hosted` and `manifest` modes. */
119
+ backendURL?: string;
120
+ /** Inline consent manifest for `manifest` mode. */
121
+ manifest?: ConsentManifest;
122
+ /**
123
+ * Manifest URL for `manifest` mode. URLs other than the backend's
124
+ * `/manifest` endpoint require an explicit `backendURL`.
125
+ */
126
+ manifestURL?: string;
127
+ /**
128
+ * Policy rules for `offline` mode. A preset name such as
129
+ * `'europeOptIn'` stands in for `policyRulePresets.europeOptIn()`, so a
130
+ * JSON config or a `data-policy-rules` attribute can name them.
131
+ */
132
+ policyRules?: (PolicyRule | PolicyPresetName)[];
133
+ /** Categories the UI offers. Defaults to every category the policy allows. */
134
+ consentCategories?: AllConsentNames[];
135
+ /** Third-party scripts to load once their category is granted. */
136
+ scripts?: Script[];
137
+ /** Lifecycle callbacks. */
138
+ callbacks?: Callbacks;
139
+ /** Cookie and storage settings. */
140
+ storageConfig?: StorageConfig;
141
+ /** Known country, region, language or GPC signal. */
142
+ overrides?: KernelOverrides;
143
+ /**
144
+ * A server-resolved init answer. When it carries a policy and a
145
+ * decision the runtime renders from it and never calls `/init`.
146
+ */
147
+ prefetch?: KernelConfig;
148
+ /** Identified visitor. */
149
+ user?: KernelUser;
150
+ /** Locale and custom messages. */
151
+ i18n?: Partial<I18nConfig>;
152
+ /** Privacy policy, cookie policy and terms links. */
153
+ legalLinks?: LegalLinks;
154
+ /** Block network requests by URL until consent. */
155
+ networkBlocker?: RuntimeNetworkBlockerOptions | false;
156
+ /** Gate iframes by category. On by default. */
157
+ iframeBlocker?: ConsentRuntimeOptions['iframeBlocker'];
158
+ /** `false` grants every category and mounts nothing. */
159
+ enabled?: boolean;
160
+ /** Host layout and behavior, resolved under the active policy constraints. */
161
+ presentation?: ConsentPresentation;
162
+ /** UI options, or `false` for headless use. */
163
+ ui?: ConsentUIOptions | false;
164
+ /** Package name reported on `window.c15t`. */
165
+ pkg?: string;
166
+ }
167
+ /** Handle on a mounted UI. */
168
+ export interface ConsentUIHandle {
169
+ /** The element appended to the container. */
170
+ readonly host: HTMLElement;
171
+ /** Where the surfaces render: the shadow root, or the host itself. */
172
+ readonly root: ShadowRoot | HTMLElement;
173
+ /** Re-render against the current snapshot. */
174
+ update: () => void;
175
+ /** Remove every surface and the host. */
176
+ destroy: () => void;
177
+ }
178
+ /** Mounts the prebuilt UI for a client. */
179
+ export type ConsentUIMounter = (client: ConsentClient, options?: ConsentUIOptions) => ConsentUIHandle;
180
+ /** Events a client emits, and their payloads. */
181
+ export interface ConsentClientEventMap {
182
+ /** The policy resolved and the runtime is ready to render. */
183
+ ready: ConsentSnapshot;
184
+ /** A consent value changed. */
185
+ consent: ConsentSnapshot;
186
+ /** The surface the runtime wants shown changed. */
187
+ ui: KernelActiveUI;
188
+ /** A transport call failed. */
189
+ error: unknown;
190
+ }
191
+ /** The page's consent client. */
192
+ export interface ConsentClient {
193
+ /** The runtime that owns this page's kernel. */
194
+ readonly runtime: ConsentRuntime;
195
+ /** The kernel: snapshot, commands and events. */
196
+ readonly kernel: ConsentKernel;
197
+ /** The options the client was created with. */
198
+ readonly options: ConsentClientOptions;
199
+ /** Which transport is in use. */
200
+ readonly mode: ConsentModeName | 'custom';
201
+ /** Categories the UI should offer, after policy filtering. */
202
+ readonly consentCategories: AllConsentNames[];
203
+ /** The mounted UI, if any. */
204
+ readonly ui: ConsentUIHandle | null;
205
+ /** Whether `start()` has run. */
206
+ readonly started: boolean;
207
+ /** The current consent snapshot. */
208
+ getSnapshot: () => ConsentSnapshot;
209
+ /**
210
+ * Observe every snapshot change.
211
+ *
212
+ * @param listener - Called with each new snapshot.
213
+ * @returns An unsubscribe function.
214
+ */
215
+ subscribe: (listener: (snapshot: ConsentSnapshot) => void) => Unsubscribe;
216
+ /**
217
+ * Resolves once the policy is resolved and the UI can render. A
218
+ * returning visitor with stored consent resolves as soon as init lands
219
+ * too, so callers can rely on `hasConsented()` afterwards.
220
+ */
221
+ ready: () => Promise<ConsentSnapshot>;
222
+ /**
223
+ * Whether the given category (or condition) is granted.
224
+ *
225
+ * @param condition - A category name or a `has()` condition.
226
+ */
227
+ has: (condition: HasCondition<AllConsentNames>) => boolean;
228
+ /** Whether the visitor has already made a choice. */
229
+ hasConsented: () => boolean;
230
+ /** Grant every offered category and close the UI. */
231
+ acceptAll: () => Promise<SaveResult>;
232
+ /** Grant only strictly necessary and close the UI. */
233
+ rejectAll: () => Promise<SaveResult>;
234
+ /**
235
+ * Persist a specific set of consents and close the UI.
236
+ *
237
+ * @param consents - Categories to grant or deny.
238
+ */
239
+ save: (consents: Partial<ConsentState>) => Promise<SaveResult>;
240
+ /** Confirm the current IAB vendor/purpose draft through the CMP. */
241
+ saveIAB: () => Promise<SaveResult>;
242
+ /** Acknowledge a notice without recording category choices. */
243
+ dismissNotice: () => Promise<NoticeDismissResult>;
244
+ /** Show the banner. */
245
+ showBanner: () => void;
246
+ /** Open the preference centre. */
247
+ openDialog: () => void;
248
+ /** Close the preference centre (or banner). */
249
+ closeDialog: () => void;
250
+ /**
251
+ * Switch language and re-resolve translations.
252
+ *
253
+ * @param code - A BCP 47 language tag.
254
+ */
255
+ setLanguage: (code: string) => void;
256
+ /**
257
+ * Replace the geo, language and GPC context.
258
+ *
259
+ * @param overrides - The new context.
260
+ */
261
+ setOverrides: (overrides: KernelOverrides) => void;
262
+ /**
263
+ * Associate the consent record with an external identity.
264
+ *
265
+ * @param user - The external user.
266
+ */
267
+ identify: (user: KernelUser) => Promise<void>;
268
+ /**
269
+ * Listen for a client event.
270
+ *
271
+ * Once the policy is resolved, a new `ready` listener runs at once and
272
+ * a new `ui` listener receives the surface currently up, so wiring
273
+ * attached after a fast init misses nothing.
274
+ *
275
+ * @param event - The event name.
276
+ * @param listener - Called with the event payload.
277
+ * @returns An unsubscribe function.
278
+ */
279
+ on: <EventName extends keyof ConsentClientEventMap>(event: EventName, listener: (payload: ConsentClientEventMap[EventName]) => void) => Unsubscribe;
280
+ /**
281
+ * Mount the prebuilt UI. Throws in the headless build.
282
+ *
283
+ * @param options - UI options; defaults to `options.ui`.
284
+ */
285
+ mountUI: (options?: ConsentUIOptions) => ConsentUIHandle;
286
+ /** Start the runtime and mount the UI. Idempotent. */
287
+ start: () => void;
288
+ /** Tear everything down. */
289
+ dispose: () => void;
290
+ }
@@ -0,0 +1,29 @@
1
+ import type { ConsentSnapshot, ConsentPresentation, PromptPresentation, PresentationAction, ResolvedConsentPresentation } from '@c15t/core';
2
+ /** Resolve buttons and geometry with the same policy constraints as React. */
3
+ export declare const resolveActions: (snapshot: ConsentSnapshot, surface: 'prompt' | 'preferences', presentation?: ConsentPresentation, override?: PromptPresentation) => ResolvedConsentPresentation;
4
+ /** What {@link renderActionFooter} needs. */
5
+ export interface ActionFooterParams {
6
+ /** The resolved actions. */
7
+ actions: ResolvedConsentPresentation;
8
+ /** Extra class on the footer root (the surface's `footer`). */
9
+ footerClassName: string;
10
+ /** Ship the DOM without class names. */
11
+ noStyle: boolean;
12
+ /** Test id for the footer. */
13
+ testId: string;
14
+ /** Test id for each sub group. */
15
+ subGroupTestId: string;
16
+ /** Label for an action. */
17
+ label: (action: PresentationAction) => string;
18
+ /** Test id for an action's button. */
19
+ buttonTestId: (action: PresentationAction) => string;
20
+ /** Click handler. */
21
+ onAction: (action: PresentationAction) => void;
22
+ }
23
+ /**
24
+ * Render a surface's button footer.
25
+ *
26
+ * @param params - Actions, classes and handlers.
27
+ * @returns The footer element.
28
+ */
29
+ export declare const renderActionFooter: (params: ActionFooterParams) => HTMLElement;
@@ -0,0 +1,13 @@
1
+ import type { ConsentBannerOptions } from '../types';
2
+ import type { Surface, SurfaceContext } from './surface';
3
+ /**
4
+ * The cookie banner.
5
+ *
6
+ * Reuses the framework banners' stylesheet classes and test IDs.
7
+ * Shows when the kernel requests a category choice or notice prompt.
8
+ *
9
+ * @param ctx - The mount context.
10
+ * @param options - Copy and behaviour overrides.
11
+ * @returns The surface.
12
+ */
13
+ export declare const createBanner: (ctx: SurfaceContext, options: ConsentBannerOptions) => Surface;
@@ -0,0 +1,25 @@
1
+ import type { ConsentSnapshot } from '@c15t/core';
2
+ /** Which surface a branding tag belongs to. */
3
+ export type BrandingVariant = 'footer' | 'dialog-tag' | 'banner-tag';
4
+ /** What {@link renderBranding} needs. */
5
+ export interface BrandingParams {
6
+ /** The brand the transport resolved. */
7
+ branding: ConsentSnapshot['branding'];
8
+ /** Which surface the tag belongs to. */
9
+ variant: BrandingVariant;
10
+ /** "Secured by", already translated. */
11
+ securedBy: string;
12
+ /** Drop the tag. */
13
+ hide: boolean;
14
+ /** Ship the DOM without class names. */
15
+ noStyle: boolean;
16
+ /** Test id, so each surface keeps its own. */
17
+ testId: string;
18
+ }
19
+ /**
20
+ * Render the "Secured by c15t" tag, or nothing.
21
+ *
22
+ * @param params - Branding, placement and copy.
23
+ * @returns The anchor, or `null` when hidden.
24
+ */
25
+ export declare const renderBranding: (params: BrandingParams) => HTMLElement | null;
@@ -0,0 +1,28 @@
1
+ import type { ConsentSnapshot } from '@c15t/core';
2
+ import type { CompleteTranslations } from '@c15t/translations';
3
+ /** The copy a surface renders from. */
4
+ export interface SurfaceCopy {
5
+ /** The resolved bundle, bundled English filling any gaps. */
6
+ t: CompleteTranslations;
7
+ /** The resolved language, if the transport reported one. */
8
+ language: string | undefined;
9
+ /** Text direction for the resolved language. */
10
+ dir: 'ltr' | 'rtl';
11
+ }
12
+ /**
13
+ * Resolve the translations a surface should render.
14
+ *
15
+ * Mirrors what the React and Svelte surfaces do: the snapshot's resolved
16
+ * bundle wins, bundled English fills anything it lacks.
17
+ *
18
+ * @param snapshot - The kernel snapshot.
19
+ * @returns The copy.
20
+ */
21
+ export declare const resolveCopy: (snapshot: ConsentSnapshot) => SurfaceCopy;
22
+ /**
23
+ * Title-case a category name for categories without a translation.
24
+ *
25
+ * @param name - The category name.
26
+ * @returns A readable label.
27
+ */
28
+ export declare const formatCategoryName: (name: string) => string;
@@ -0,0 +1,14 @@
1
+ import type { ConsentDialogOptions } from '../types';
2
+ import type { Surface, SurfaceContext } from './surface';
3
+ /**
4
+ * The preference centre dialog.
5
+ *
6
+ * Opens when the kernel says `activeUI === 'dialog'`. Modal: focus is
7
+ * trapped, the page stops scrolling, Escape closes. Clicking the backdrop
8
+ * does not, matching the other adapters.
9
+ *
10
+ * @param ctx - The mount context.
11
+ * @param options - Dialog options.
12
+ * @returns The surface.
13
+ */
14
+ export declare const createDialog: (ctx: SurfaceContext, options: ConsentDialogOptions) => Surface;