@consenti/ui 0.1.0 → 0.3.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/README.md +548 -151
- package/dist/angular.d.cts +486 -111
- package/dist/angular.d.ts +486 -111
- package/dist/angular.js +1 -73
- package/dist/angular.js.map +1 -1
- package/dist/angular.mjs +1 -52
- package/dist/angular.mjs.map +1 -1
- package/dist/chunk-3EXCD24H.mjs +2 -0
- package/dist/{chunk-ARALKXMB.mjs.map → chunk-3EXCD24H.mjs.map} +1 -1
- package/dist/chunk-J4BKXUD6.mjs +2 -0
- package/dist/chunk-J4BKXUD6.mjs.map +1 -0
- package/dist/hmac-UKMRMKN6.mjs +2 -0
- package/dist/{hmac-N6H7F2K2.mjs.map → hmac-UKMRMKN6.mjs.map} +1 -1
- package/dist/http-AQVVUCX6.mjs +2 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +806 -103
- package/dist/index.mjs +1 -2220
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +1 -2304
- package/dist/index.umd.js.map +1 -1
- package/dist/profiles-OEZAKEWL.mjs +2 -0
- package/dist/profiles-OEZAKEWL.mjs.map +1 -0
- package/dist/react.d.cts +470 -89
- package/dist/react.d.ts +470 -89
- package/dist/react.js +1 -60
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +1 -39
- package/dist/react.mjs.map +1 -1
- package/dist/testing.js +1 -94
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +1 -73
- package/dist/testing.mjs.map +1 -1
- package/dist/vue.d.cts +473 -82
- package/dist/vue.d.ts +473 -82
- package/dist/vue.js +1 -72
- package/dist/vue.js.map +1 -1
- package/dist/vue.mjs +1 -51
- package/dist/vue.mjs.map +1 -1
- package/package.json +15 -6
- package/dist/chunk-ARALKXMB.mjs +0 -20
- package/dist/hmac-N6H7F2K2.mjs +0 -26
- package/dist/http-VHOGZ6ZJ.mjs +0 -7
- /package/dist/{http-VHOGZ6ZJ.mjs.map → http-AQVVUCX6.mjs.map} +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,115 @@
|
|
|
1
|
+
type NonEmptyArray<T> = [T, ...T[]];
|
|
2
|
+
/**
|
|
3
|
+
* Deep-partial with JSON Merge Patch (RFC 7396) delete semantics: any key may be
|
|
4
|
+
* set to `null` instead of its usual type to signal "delete this key" when the
|
|
5
|
+
* partial is applied with `deepMerge()` — `undefined`/omitted keeps the base
|
|
6
|
+
* value, `null` removes it. Only meaningful for object/map keys (e.g. removing
|
|
7
|
+
* a `CategoryMap`/`CookieMap` entry via `profileOverride`); array elements are
|
|
8
|
+
* merged positionally and don't support deletion this way.
|
|
9
|
+
*/
|
|
10
|
+
type DeepPartial<T> = T extends Function ? T : T extends Array<infer InferredArrayType> ? Array<DeepPartial<InferredArrayType>> : T extends ReadonlyArray<infer InferredReadonlyArrayType> ? ReadonlyArray<DeepPartial<InferredReadonlyArrayType>> : T extends object ? {
|
|
11
|
+
[Key in keyof T]?: DeepPartial<T[Key]> | null;
|
|
12
|
+
} : T;
|
|
13
|
+
|
|
14
|
+
declare const COMPLIANCE_GROUP_IDS: readonly ["opt-in", "opt-out", "opt-out-strict", "opt-in-dpdpa", "opt-in-china", "opt-in-brazil", "general-privacy-consent", "notice-only"];
|
|
15
|
+
declare const COOKIE_PURPOSE_IDS: readonly ["necessary", "functional", "preferences", "analytics", "marketing"];
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Compliance-related literal types, derived from the regulation/group ID data
|
|
19
|
+
* that lives in @consenti/utils (packages/utils/src/compliance.ts).
|
|
20
|
+
*
|
|
21
|
+
* This import is type-only and fully erased at compile time — @consenti/types
|
|
22
|
+
* has no runtime dependency on @consenti/utils. The actual data (COMPLIANCE_GROUPS,
|
|
23
|
+
* EMBEDDED_COMPLIANCE_MAP, COMPLIANCE_VALIDATION_RULES, GPC_OPTIONS, etc.) lives in
|
|
24
|
+
* @consenti/utils; import it from there.
|
|
25
|
+
*
|
|
26
|
+
* HOW TO ADD A NEW REGULATION OR COMPLIANCE GROUP: see the header comment in
|
|
27
|
+
* packages/utils/src/compliance.ts — these types auto-update from that data.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
type ComplianceGroupId = typeof COMPLIANCE_GROUP_IDS[number];
|
|
31
|
+
/**
|
|
32
|
+
* `(string & {})` (rather than plain `string`) keeps IDE autocomplete for the
|
|
33
|
+
* known `ComplianceGroupId` literals while still allowing any other string —
|
|
34
|
+
* used to target a profile authored against a custom (non-built-in)
|
|
35
|
+
* `customComplianceGroup` instead of one of the 8 built-in groups.
|
|
36
|
+
*/
|
|
37
|
+
type ComplianceType = 'auto' | ComplianceGroupId | (string & {}) | Symbol;
|
|
38
|
+
|
|
39
|
+
interface ComplianceMapData {
|
|
40
|
+
version: string;
|
|
41
|
+
countries: Record<string, CountryComplianceEntry>;
|
|
42
|
+
}
|
|
43
|
+
interface CountryComplianceEntry {
|
|
44
|
+
complianceGroup: ComplianceGroupId;
|
|
45
|
+
default: ComplianceGroupId;
|
|
46
|
+
description: string;
|
|
47
|
+
overriddenRegions?: Record<string, {
|
|
48
|
+
complianceGroup: ComplianceGroupId;
|
|
49
|
+
description: string;
|
|
50
|
+
}>;
|
|
51
|
+
}
|
|
52
|
+
interface ConsentDbRecord {
|
|
53
|
+
id: string;
|
|
54
|
+
tenantId: string;
|
|
55
|
+
visitorId: string;
|
|
56
|
+
profileId: string;
|
|
57
|
+
locale: string;
|
|
58
|
+
consentJson: ConsentValue;
|
|
59
|
+
gpcDetected: boolean;
|
|
60
|
+
source: 'banner' | 'api' | 'import';
|
|
61
|
+
ageVerified?: boolean;
|
|
62
|
+
parentalConsentToken?: string;
|
|
63
|
+
tcfString?: string;
|
|
64
|
+
/** HMAC-SHA256 signature over the record's core fields, hex-encoded. Only present when
|
|
65
|
+
* `consentSigningKey` is configured — opt-in tamper-evidence for server-stored records,
|
|
66
|
+
* independent of the widget's own cookie-signing (`core.cookieSigningKey`). */
|
|
67
|
+
signature?: string;
|
|
68
|
+
createdAt: string;
|
|
69
|
+
updatedAt: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
1
72
|
type ConsentStatus = 'granted' | 'denied' | 'objected';
|
|
2
|
-
type ConsentAction = 'accept_all' | 'reject_all' | 'custom' | 'update';
|
|
73
|
+
type ConsentAction$1 = 'accept_all' | 'reject_all' | 'custom' | 'update';
|
|
3
74
|
type ConsentValue = Record<string, ConsentStatus>;
|
|
75
|
+
/**
|
|
76
|
+
* Output format for getConsent(type).
|
|
77
|
+
* 'default' → raw ConsentValue (existing behaviour)
|
|
78
|
+
* 'google-gtm' → Google Consent Mode v2 keys + ads_data_redaction, url_passthrough
|
|
79
|
+
* 'category' → consent per CookiePurpose category
|
|
80
|
+
* 'adobe' → { analytics, target, manager, optimizer }
|
|
81
|
+
* 'meta' → { pixel, api, plugins, facebookLogin }
|
|
82
|
+
* 'microsoft-clarity' → { session, heatmaps, performance }
|
|
83
|
+
* 'twilio-segment' → { identify, page, track, group, alias }
|
|
84
|
+
*/
|
|
85
|
+
type ConsentType = 'default' | 'google-gtm' | 'category' | 'adobe' | 'meta' | 'microsoft-clarity' | 'twilio-segment';
|
|
86
|
+
type GpcMode = 'ignore' | 'honor' | 'strict';
|
|
87
|
+
type LegalBasis = 'mandatory' | 'consent' | 'legitimate_interest';
|
|
88
|
+
type CookiePurpose = typeof COOKIE_PURPOSE_IDS[number];
|
|
89
|
+
/**
|
|
90
|
+
* A single consent parameter (tracker/cookie definition).
|
|
91
|
+
* Keyed by its own id inside `Record<string, Cookie>` — the map key IS the id,
|
|
92
|
+
* there is no `id` field on the value itself.
|
|
93
|
+
*/
|
|
4
94
|
interface Cookie {
|
|
5
|
-
|
|
6
|
-
type?: 'consent' | 'legitimate_interest';
|
|
7
|
-
mandatory?: boolean;
|
|
95
|
+
purpose?: CookiePurpose;
|
|
8
96
|
listenGpc?: boolean;
|
|
9
|
-
|
|
97
|
+
/**
|
|
98
|
+
* Pre-grant this parameter's default consent to 'granted' (instead of the
|
|
99
|
+
* compliance-group-driven default) when no stored decision exists yet.
|
|
100
|
+
* Only meaningful when the owning category's `legalBasis === 'consent'` —
|
|
101
|
+
* `mandatory`/`legitimate_interest` categories are already effectively
|
|
102
|
+
* pre-granted regardless of this flag. Never overrides an active GPC signal.
|
|
103
|
+
* Default: false.
|
|
104
|
+
*/
|
|
105
|
+
preGrant?: boolean;
|
|
10
106
|
tcfVendorId?: number;
|
|
11
107
|
tcfPurposes?: number[];
|
|
108
|
+
tcfSpecialFeatures?: number[];
|
|
12
109
|
cpraCategory?: 'sale' | 'sharing' | 'sensitive';
|
|
13
110
|
}
|
|
111
|
+
/** `Cookie` keyed by its own id — the standard shape used everywhere a parameter list is passed around. */
|
|
112
|
+
type CookieMap = Record<string, Cookie>;
|
|
14
113
|
type ButtonStyle = 'primary' | 'secondary' | 'text' | 'accent';
|
|
15
114
|
type ButtonAction = 'submit' | 'manage' | 'close' | 'custom' | 'link';
|
|
16
115
|
interface Button {
|
|
@@ -20,6 +119,10 @@ interface Button {
|
|
|
20
119
|
cookies?: string[] | '*' | '!';
|
|
21
120
|
url?: string;
|
|
22
121
|
}
|
|
122
|
+
/** `Button` keyed by its own id — e.g. `'accept-all'`. The map key IS the id, rendered as the DOM
|
|
123
|
+
* `id` (`consenti-btn-{id}`) so integrators can target specific buttons, and is what
|
|
124
|
+
* `profileOverride`'s `deepMerge` deletes by (`{ 'reject-optional': null }` removes one button). */
|
|
125
|
+
type ButtonMap = Record<string, Button>;
|
|
23
126
|
interface MainBanner {
|
|
24
127
|
position: 'top' | 'bottom' | 'middle' | 'left-bottom' | 'right-bottom';
|
|
25
128
|
overlayOpacity?: number;
|
|
@@ -28,39 +131,50 @@ interface MainBanner {
|
|
|
28
131
|
heading?: string;
|
|
29
132
|
headingTag?: string;
|
|
30
133
|
htmlText: string;
|
|
31
|
-
buttons:
|
|
134
|
+
buttons: ButtonMap;
|
|
135
|
+
/** Stack buttons vertically below this viewport width in px. 0 or undefined = disabled. Default: 576. */
|
|
136
|
+
stackButtonsOnBreakpoint?: number;
|
|
137
|
+
/** Trap keyboard Tab focus within the consent root while this banner is visible. */
|
|
138
|
+
trapFocus?: boolean;
|
|
32
139
|
}
|
|
33
140
|
type GpcBanner = MainBanner;
|
|
141
|
+
/**
|
|
142
|
+
* A consent category — the single source of legal basis for every parameter
|
|
143
|
+
* it lists in `cookies`. Keyed by its own id inside `Record<string, Category>` —
|
|
144
|
+
* the map key IS the id, there is no `id` field on the value itself.
|
|
145
|
+
*
|
|
146
|
+
* A parameter must belong to exactly one category (enforced at authoring time,
|
|
147
|
+
* not by this type) — that relationship is what `getCookieLegalBasis`/
|
|
148
|
+
* `isMandatoryCookie` (`@consenti/utils`) resolve at runtime.
|
|
149
|
+
*/
|
|
34
150
|
interface Category {
|
|
35
|
-
id: string;
|
|
36
151
|
heading: string;
|
|
37
152
|
headingTag?: string;
|
|
38
153
|
htmlText: string;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
description?: string;
|
|
44
|
-
};
|
|
154
|
+
legalBasis: LegalBasis;
|
|
155
|
+
/** Only meaningful when legalBasis === 'legitimate_interest' — the GDPR balancing-test justification shown to visitors. */
|
|
156
|
+
legitimateInterestDescription?: string;
|
|
157
|
+
/** IDs of the parameters (from the profile's `cookies` map) that belong to this category. */
|
|
45
158
|
cookies: string[];
|
|
46
159
|
}
|
|
47
|
-
|
|
160
|
+
/** `Category` keyed by its own id — the standard shape used everywhere a category list is passed around. */
|
|
161
|
+
type CategoryMap = Record<string, Category>;
|
|
162
|
+
interface PreferenceModal extends Omit<MainBanner, "position"> {
|
|
48
163
|
position?: 'left' | 'right' | 'center';
|
|
49
|
-
overlayOpacity?: number;
|
|
50
|
-
showClose?: boolean;
|
|
51
|
-
showLocaleSwitcher?: boolean;
|
|
52
|
-
heading?: string;
|
|
53
|
-
headingTag?: string;
|
|
54
164
|
subheading?: string;
|
|
55
|
-
|
|
56
|
-
buttons: Button[];
|
|
57
|
-
categories: Category[];
|
|
165
|
+
categories: CategoryMap;
|
|
58
166
|
persistent?: boolean;
|
|
167
|
+
/** Screen width in px below which the modal expands to full screen. Default: 576. Set to 0 to disable. */
|
|
168
|
+
mobileFullScreenBreakpoint?: number;
|
|
169
|
+
/** Label for the optional consent-receipt download checkbox (shown when `allowReceipt` is true). Falls back to a default when omitted. */
|
|
170
|
+
receiptLabel?: string;
|
|
171
|
+
/** Description shown beneath the consent-receipt checkbox. Falls back to a default when omitted. */
|
|
172
|
+
receiptDescription?: string;
|
|
59
173
|
}
|
|
60
174
|
interface LocaleTranslations {
|
|
61
|
-
mainBanner: MainBanner
|
|
62
|
-
gpcBanner?: GpcBanner
|
|
63
|
-
preferenceModal: PreferenceModal
|
|
175
|
+
mainBanner: DeepPartial<MainBanner>;
|
|
176
|
+
gpcBanner?: DeepPartial<GpcBanner>;
|
|
177
|
+
preferenceModal: DeepPartial<PreferenceModal>;
|
|
64
178
|
}
|
|
65
179
|
interface ProfileTranslations {
|
|
66
180
|
[locale: string]: LocaleTranslations;
|
|
@@ -72,53 +186,154 @@ interface DpdpaConfig {
|
|
|
72
186
|
}
|
|
73
187
|
interface LocaleTextContent {
|
|
74
188
|
mainBanner: {
|
|
75
|
-
heading
|
|
189
|
+
heading?: string;
|
|
76
190
|
htmlText: string;
|
|
77
|
-
|
|
191
|
+
/** Keyed by the linked UI template's button id — was a positional array matched to
|
|
192
|
+
* `buttons[i]` by index; now matched by key, robust against button reordering. */
|
|
193
|
+
buttonLabels?: Record<string, string>;
|
|
78
194
|
};
|
|
79
195
|
gpcBanner: {
|
|
80
|
-
heading
|
|
196
|
+
heading?: string;
|
|
81
197
|
htmlText: string;
|
|
82
|
-
buttonLabels
|
|
198
|
+
buttonLabels?: Record<string, string>;
|
|
83
199
|
};
|
|
84
200
|
preferenceModal: {
|
|
85
201
|
heading: string;
|
|
86
202
|
subheading?: string;
|
|
87
203
|
htmlText?: string;
|
|
88
|
-
buttonLabels
|
|
89
|
-
categories
|
|
90
|
-
|
|
204
|
+
buttonLabels?: Record<string, string>;
|
|
205
|
+
/** `legitimateInterestDescription` is only meaningful for categories whose legalBasis is 'legitimate_interest'; optional GDPR balancing-test text, translated per locale like heading/htmlText. */
|
|
206
|
+
categories: Record<string, {
|
|
91
207
|
heading: string;
|
|
92
208
|
htmlText: string;
|
|
209
|
+
legitimateInterestDescription?: string;
|
|
93
210
|
}>;
|
|
211
|
+
receiptLabel?: string;
|
|
212
|
+
receiptDescription?: string;
|
|
94
213
|
};
|
|
95
214
|
}
|
|
96
215
|
interface ProfileConfig {
|
|
97
|
-
|
|
216
|
+
id: string;
|
|
217
|
+
cookies?: CookieMap;
|
|
98
218
|
defaultLocale: string;
|
|
219
|
+
/** Days until consent expires and the visitor is asked again (profile-wide). Default: 365. */
|
|
220
|
+
expiryDays?: number;
|
|
99
221
|
translations?: ProfileTranslations;
|
|
100
|
-
|
|
222
|
+
mainBanner: MainBanner;
|
|
223
|
+
gpcBanner?: GpcBanner;
|
|
224
|
+
preferenceModal: PreferenceModal;
|
|
101
225
|
darkMode?: boolean;
|
|
102
226
|
allowedOrigins?: string[];
|
|
103
227
|
dpdpa?: DpdpaConfig;
|
|
104
228
|
regulation?: 'gdpr' | 'ccpa' | 'cpra' | 'dpdpa' | 'uk-gdpr' | 'lgpd' | 'pipeda' | 'popia' | 'pdpa-th' | 'appi' | 'kvkk';
|
|
105
229
|
regulations?: string[];
|
|
106
|
-
|
|
230
|
+
consentTemplateId?: string;
|
|
107
231
|
uiTemplateId?: string;
|
|
108
232
|
localeContents?: Record<string, LocaleTextContent>;
|
|
233
|
+
complianceGroup?: ComplianceGroupId;
|
|
234
|
+
/**
|
|
235
|
+
* Free-form identifier (lower-kebab-case) for profiles that don't map to one of the
|
|
236
|
+
* built-in `complianceGroup` values — the identifier the widget's `compliance.type`
|
|
237
|
+
* config targets to fetch this profile. Participates in activation, deactivation, and
|
|
238
|
+
* "one active profile per group" conflict detection the same way `complianceGroup` does;
|
|
239
|
+
* no `COMPLIANCE_GROUPS` validation rules or GPC defaults apply to it, since none exist
|
|
240
|
+
* for a free-form name.
|
|
241
|
+
*/
|
|
242
|
+
customComplianceGroup?: string;
|
|
243
|
+
/**
|
|
244
|
+
* Per-profile deltas applied on top of the consent template's authored `Cookie` values
|
|
245
|
+
* (e.g. an overridden `preGrant`) when resolving this profile — see the dashboard's Step 2
|
|
246
|
+
* pre-grant override UX. Keyed by cookie id; only the overridden fields need to be present.
|
|
247
|
+
*/
|
|
248
|
+
cookiesOverride?: Record<string, Partial<Cookie>>;
|
|
249
|
+
/**
|
|
250
|
+
* Reserved for a future phase — stored but not yet applied when resolving a profile.
|
|
251
|
+
* Intended to mirror `cookiesOverride` for per-category deltas.
|
|
252
|
+
*/
|
|
253
|
+
categoriesOverride?: Record<string, Partial<Category>>;
|
|
254
|
+
/**
|
|
255
|
+
* Reserved for a future phase — stored but not yet applied when resolving a profile.
|
|
256
|
+
* Intended to hold per-profile UI-template deltas.
|
|
257
|
+
*/
|
|
258
|
+
uiOverride?: Record<string, unknown>;
|
|
259
|
+
/**
|
|
260
|
+
* When registered via `registerProfile()` and `complianceGroup` matches one of
|
|
261
|
+
* Consenti's built-in groups: `false` (default) fully replaces the built-in
|
|
262
|
+
* embedded profile for that group; `true` deep-merges this config onto the
|
|
263
|
+
* built-in profile instead (only meaningful together with `complianceGroup`).
|
|
264
|
+
*/
|
|
265
|
+
deepMerge?: boolean;
|
|
266
|
+
gpcMode?: GpcMode;
|
|
267
|
+
isActive?: boolean;
|
|
268
|
+
hidePoweredBy?: boolean;
|
|
269
|
+
allowReceipt?: boolean;
|
|
270
|
+
/** Per-compliance extra config (e.g. DPDPA data fiduciary name). */
|
|
271
|
+
complianceConfig?: Record<string, string>;
|
|
272
|
+
/** Show a metadata footer strip in the banner/modal with Consent ID, Date, Version, Privacy Settings link. */
|
|
273
|
+
showFooterMetadata?: boolean;
|
|
274
|
+
/** Apply WCAG 2.1 AA button sizing (44px min-height), visible focus rings, and screen-reader labels. */
|
|
275
|
+
enhanceAccessibility?: boolean;
|
|
109
276
|
}
|
|
277
|
+
/**
|
|
278
|
+
* Input accepted by `registerProfile()`. Either a complete `ProfileConfig`
|
|
279
|
+
* (used as-is or, if `complianceGroup` matches a built-in group, fully replaces
|
|
280
|
+
* it), or a partial overlay explicitly opted into `deepMerge: true` — merged
|
|
281
|
+
* onto the built-in embedded profile for `complianceGroup` at resolution time.
|
|
282
|
+
*/
|
|
283
|
+
type RegisterableProfileConfig = ProfileConfig | (DeepPartial<ProfileConfig> & {
|
|
284
|
+
complianceGroup: ComplianceGroupId;
|
|
285
|
+
deepMerge: true;
|
|
286
|
+
});
|
|
110
287
|
interface ResolvedProfile {
|
|
111
|
-
id:
|
|
112
|
-
version
|
|
288
|
+
id: string;
|
|
289
|
+
/** Incremented in place on every save of this profile. Absent for embedded/local profiles that have no server-side version counter. */
|
|
290
|
+
version?: number;
|
|
113
291
|
defaultLocale: string;
|
|
114
292
|
locales?: string[];
|
|
115
|
-
cookies:
|
|
293
|
+
cookies: CookieMap;
|
|
294
|
+
/** Days until consent expires and the visitor is asked again (profile-wide). Default: 365. */
|
|
295
|
+
expiryDays?: number;
|
|
296
|
+
allowReceipt?: boolean;
|
|
116
297
|
mainBanner: MainBanner;
|
|
117
298
|
gpcBanner?: GpcBanner;
|
|
118
299
|
preferenceModal: PreferenceModal;
|
|
119
300
|
cookieSigningKey?: string;
|
|
120
301
|
dpdpa?: DpdpaConfig;
|
|
121
302
|
darkMode?: boolean;
|
|
303
|
+
gpcMode?: GpcMode;
|
|
304
|
+
complianceGroup?: ComplianceGroupId;
|
|
305
|
+
complianceConfig?: Record<string, string>;
|
|
306
|
+
/** Falls back to `true` (hidden) if neither the widget config nor the profile set it. */
|
|
307
|
+
hidePoweredBy?: boolean;
|
|
308
|
+
/** Show metadata footer strip (Consent ID, Date, Version, Privacy Settings link). */
|
|
309
|
+
showFooterMetadata?: boolean;
|
|
310
|
+
/** Apply WCAG 2.1 AA accessibility enhancements to the widget. */
|
|
311
|
+
enhanceAccessibility?: boolean;
|
|
312
|
+
}
|
|
313
|
+
type WidgetCountryResolverFn = () => Promise<{
|
|
314
|
+
country: string | null;
|
|
315
|
+
region: string | null;
|
|
316
|
+
confidence: number;
|
|
317
|
+
}>;
|
|
318
|
+
interface AgeGateWidgetConfig {
|
|
319
|
+
enabled: boolean;
|
|
320
|
+
minimumAge: number;
|
|
321
|
+
requireParentalConsent?: boolean;
|
|
322
|
+
}
|
|
323
|
+
/** Mirrors the server-side `TcfConfig` shape (`@consenti/api`) — `cmpId`/`cmpVersion` must match
|
|
324
|
+
* what the backend uses to encode `tcfString`, since both feed the same simplified TC string. */
|
|
325
|
+
interface TcfWidgetConfig {
|
|
326
|
+
enabled: boolean;
|
|
327
|
+
cmpId: number;
|
|
328
|
+
cmpVersion: number;
|
|
329
|
+
}
|
|
330
|
+
interface ComplianceWidgetConfig {
|
|
331
|
+
type?: ComplianceType;
|
|
332
|
+
geoDataProvider?: 'default' | WidgetCountryResolverFn;
|
|
333
|
+
autoComplianceMap?: 'default' | ComplianceMapData | 'auto';
|
|
334
|
+
complianceMapUrl?: string;
|
|
335
|
+
ageGate?: AgeGateWidgetConfig;
|
|
336
|
+
tcf?: TcfWidgetConfig;
|
|
122
337
|
}
|
|
123
338
|
interface GtmConfig {
|
|
124
339
|
containerId?: string;
|
|
@@ -126,6 +341,7 @@ interface GtmConfig {
|
|
|
126
341
|
dataLayer?: string;
|
|
127
342
|
urlPassthrough?: boolean;
|
|
128
343
|
adsDataRedaction?: boolean;
|
|
344
|
+
verbose?: boolean;
|
|
129
345
|
}
|
|
130
346
|
interface UtilsConfig {
|
|
131
347
|
gtm?: GtmConfig;
|
|
@@ -134,6 +350,9 @@ interface ApiConfig {
|
|
|
134
350
|
enabled?: boolean;
|
|
135
351
|
baseUrl?: string;
|
|
136
352
|
authToken?: string;
|
|
353
|
+
tenantId?: string;
|
|
354
|
+
complianceGroup?: ComplianceGroupId;
|
|
355
|
+
trustDomain?: boolean;
|
|
137
356
|
}
|
|
138
357
|
interface ThemeConfig {
|
|
139
358
|
bgColor?: string;
|
|
@@ -155,35 +374,60 @@ interface ThemeConfig {
|
|
|
155
374
|
accentTextColor?: string;
|
|
156
375
|
}
|
|
157
376
|
interface CoreConfig {
|
|
158
|
-
|
|
159
|
-
autoHonorGPC?: boolean | 'strict';
|
|
377
|
+
tenantId?: string;
|
|
160
378
|
locale?: string;
|
|
379
|
+
/** Text direction for the banner/modal root. `'auto'` (default) derives it from `locale`
|
|
380
|
+
* (Arabic, Hebrew, Persian, Urdu, ... → `rtl`); set explicitly to override. */
|
|
381
|
+
dir?: 'ltr' | 'rtl' | 'auto';
|
|
161
382
|
disableCssTemplate?: boolean;
|
|
162
|
-
signCookies?: boolean;
|
|
163
383
|
cookieSigningKey?: string;
|
|
164
384
|
allowReceipt?: boolean;
|
|
165
385
|
cookieDomains?: string;
|
|
166
386
|
storage?: 'cookie' | 'localStorage';
|
|
167
387
|
theme?: ThemeConfig;
|
|
168
|
-
privacyPolicyUrl?: string;
|
|
169
|
-
regulation?: 'gdpr' | 'ccpa' | 'cpra' | 'dpdpa' | 'uk-gdpr' | 'lgpd' | 'pipeda' | 'popia' | 'pdpa-th' | 'appi' | 'kvkk';
|
|
170
388
|
userId?: string;
|
|
389
|
+
usePrebuiltProfiles?: 'all' | NonEmptyArray<ComplianceGroupId>;
|
|
390
|
+
cacheResolvedProfiles?: boolean;
|
|
391
|
+
console?: Array<'info' | 'log' | 'warning' | 'error'>;
|
|
171
392
|
}
|
|
172
393
|
interface ConsentiConfig {
|
|
173
|
-
|
|
394
|
+
verbose?: boolean;
|
|
395
|
+
/** Optional — every field of `CoreConfig` is itself optional, so `new ConsentiSetup({})` and
|
|
396
|
+
* `new ConsentiSetup({ compliance: { type: 'opt-in' } })` (omitting `core` entirely) both work,
|
|
397
|
+
* matching the widget's own "Minimal config" documentation. */
|
|
398
|
+
core?: CoreConfig;
|
|
399
|
+
compliance?: ComplianceWidgetConfig;
|
|
174
400
|
rootEl?: string | HTMLElement;
|
|
175
401
|
darkMode?: boolean;
|
|
176
402
|
autoInit?: boolean;
|
|
177
403
|
api?: ApiConfig;
|
|
178
404
|
utils?: UtilsConfig;
|
|
179
405
|
plugins?: ConsentiPlugin$1[];
|
|
180
|
-
profileOverride?:
|
|
406
|
+
profileOverride?: DeepPartial<ResolvedProfile>;
|
|
407
|
+
/** When true, suppresses the "Powered by Consenti" footer link in the banner and modal. */
|
|
408
|
+
hidePoweredBy?: boolean;
|
|
181
409
|
}
|
|
410
|
+
type ConsentiEventName = 'bannerInitialized' | 'consenti:bannerInitialized' | 'bannerVisibility' | 'consenti:bannerVisibility' | 'modalVisibility' | 'consenti:modalVisibility' | 'consentBeingSubmitted' | 'consenti:consentBeingSubmitted' | 'consentSubmitted' | 'consenti:consentSubmitted' | 'parentalConsentRequired' | 'consenti:parentalConsentRequired';
|
|
182
411
|
interface ConsentiWidgetAPI {
|
|
183
412
|
hasConsent(): boolean;
|
|
184
413
|
getConsent(): ConsentValue | null;
|
|
414
|
+
getConsent(type: ConsentType): Record<string, string> | null;
|
|
415
|
+
getConsent(type?: ConsentType): ConsentValue | Record<string, string> | null;
|
|
185
416
|
getConsentDate(): Date | false;
|
|
186
417
|
getGTMConsent(): Record<string, string> | null;
|
|
418
|
+
isCookieGranted(cookieId: string, requestValue?: boolean): boolean | ConsentStatus;
|
|
419
|
+
isCategoryGranted(categoryId: string, requestValue?: boolean): boolean | {
|
|
420
|
+
[cookieId: string]: ConsentStatus;
|
|
421
|
+
}[];
|
|
422
|
+
grantAll(onlyMandatory?: boolean): Promise<void>;
|
|
423
|
+
denyAll(includingMandatory?: boolean): Promise<void>;
|
|
424
|
+
on(event: ConsentiEventName, handler: (data: ConsentEvent) => void): void;
|
|
425
|
+
off(event: ConsentiEventName, handler: (data: ConsentEvent) => void): void;
|
|
426
|
+
version(): {
|
|
427
|
+
package: string;
|
|
428
|
+
profileVersion: string | null;
|
|
429
|
+
consentVersion: string | null;
|
|
430
|
+
};
|
|
187
431
|
bannerVisibility(): 'main' | 'gpc' | false;
|
|
188
432
|
modalVisibility(): 'preference' | false;
|
|
189
433
|
getProfile(): ResolvedProfile | null;
|
|
@@ -191,13 +435,17 @@ interface ConsentiWidgetAPI {
|
|
|
191
435
|
hideBanner(): void;
|
|
192
436
|
showModal(triggerEl?: HTMLElement): void;
|
|
193
437
|
hideModal(): void;
|
|
194
|
-
submitConsent(consent: Partial<ConsentValue>): Promise<void>;
|
|
438
|
+
submitConsent(consent: Partial<ConsentValue>): Promise<ConsentDbRecord | void>;
|
|
195
439
|
deleteConsent(): Promise<void>;
|
|
196
440
|
reConsent(): Promise<void>;
|
|
197
441
|
getRootElement(): HTMLElement | null;
|
|
198
442
|
getBannerElement(): HTMLElement | null;
|
|
199
443
|
getModalElement(): HTMLElement | null;
|
|
200
444
|
switchLocale(locale: string): void;
|
|
445
|
+
setDarkMode(enable?: boolean): void;
|
|
446
|
+
setTheme(theme: Partial<ThemeConfig>): void;
|
|
447
|
+
setConfig(config: DeepPartial<ConsentiConfig>): void;
|
|
448
|
+
setProfile(override: DeepPartial<ResolvedProfile>): void;
|
|
201
449
|
init(): Promise<void>;
|
|
202
450
|
onReady(callback: () => void): void;
|
|
203
451
|
destroy(): void;
|
|
@@ -226,41 +474,67 @@ interface ParsedConsent {
|
|
|
226
474
|
interface ConsentRecord {
|
|
227
475
|
visitorId: string;
|
|
228
476
|
consentId?: string;
|
|
229
|
-
profileId:
|
|
230
|
-
profileVersion: number;
|
|
477
|
+
profileId: string;
|
|
231
478
|
consent: ConsentValue;
|
|
232
479
|
timestamp: string;
|
|
233
480
|
gpc?: boolean;
|
|
234
|
-
action?: ConsentAction;
|
|
481
|
+
action?: ConsentAction$1;
|
|
235
482
|
pageUrl?: string;
|
|
236
483
|
}
|
|
237
484
|
interface ConsentReceipt {
|
|
238
|
-
version:
|
|
485
|
+
version: string;
|
|
239
486
|
issuedAt: string;
|
|
240
487
|
visitorId: string;
|
|
241
|
-
profileId:
|
|
242
|
-
profileVersion: number;
|
|
488
|
+
profileId: string;
|
|
243
489
|
locale: string;
|
|
244
490
|
consent: ConsentValue;
|
|
245
491
|
signature?: string;
|
|
246
492
|
}
|
|
247
|
-
interface
|
|
248
|
-
profileId
|
|
249
|
-
|
|
250
|
-
hasExistingConsent
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
493
|
+
interface BannerInitializedDetail {
|
|
494
|
+
profileId: string;
|
|
495
|
+
complianceGroup?: ComplianceType;
|
|
496
|
+
hasExistingConsent: boolean;
|
|
497
|
+
gpcDetected: boolean;
|
|
498
|
+
willShow: boolean;
|
|
499
|
+
}
|
|
500
|
+
interface BannerVisibilityDetail {
|
|
501
|
+
visible: boolean;
|
|
502
|
+
variant: 'main' | 'gpc';
|
|
503
|
+
action: boolean;
|
|
504
|
+
}
|
|
505
|
+
interface ModalVisibilityDetail {
|
|
506
|
+
visible: boolean;
|
|
507
|
+
action: boolean;
|
|
508
|
+
}
|
|
509
|
+
interface ConsentBeingSubmitted {
|
|
510
|
+
consentId: string;
|
|
511
|
+
visitorId: string;
|
|
512
|
+
profileId: string;
|
|
513
|
+
consentJson: ConsentValue;
|
|
514
|
+
consentAction: ConsentAction$1;
|
|
515
|
+
gpcDetected: boolean;
|
|
516
|
+
pageUrl: string;
|
|
517
|
+
timestamp: number;
|
|
257
518
|
fromBroadcast?: boolean;
|
|
258
|
-
gpcDetected?: boolean;
|
|
259
519
|
}
|
|
520
|
+
interface ConsentSubmittedDetail extends ConsentBeingSubmitted {
|
|
521
|
+
apiResponse: ConsentDbRecord;
|
|
522
|
+
}
|
|
523
|
+
/** Dispatched when the age gate is declined and `requireParentalConsent` is set — see
|
|
524
|
+
* `AgeGateWidgetConfig`. A deny-all consent (mandatory cookies only) has already been
|
|
525
|
+
* submitted with `parentalConsentToken` attached; this event is the hook for the site
|
|
526
|
+
* owner to run their own out-of-band parental-consent verification. */
|
|
527
|
+
interface ParentalConsentRequiredDetail {
|
|
528
|
+
parentalConsentToken: string;
|
|
529
|
+
profileId: string;
|
|
530
|
+
visitorId: string;
|
|
531
|
+
timestamp: number;
|
|
532
|
+
}
|
|
533
|
+
type ConsentEvent = BannerInitializedDetail | BannerVisibilityDetail | ModalVisibilityDetail | ConsentBeingSubmitted | ConsentSubmittedDetail | ParentalConsentRequiredDetail;
|
|
260
534
|
type ConsentiMessage = {
|
|
261
535
|
type: 'consentUpdated';
|
|
262
536
|
consent: ConsentValue;
|
|
263
|
-
profileId:
|
|
537
|
+
profileId: string;
|
|
264
538
|
} | {
|
|
265
539
|
type: 'bannerClosed';
|
|
266
540
|
} | {
|
|
@@ -277,7 +551,7 @@ type ConsentiMessage = {
|
|
|
277
551
|
* @example
|
|
278
552
|
* ```ts
|
|
279
553
|
* const widget = new ConsentiSetup({
|
|
280
|
-
*
|
|
554
|
+
* compliance: { type: 'opt-in' },
|
|
281
555
|
* })
|
|
282
556
|
* await widget.ready
|
|
283
557
|
* console.log(widget.hasConsent())
|
|
@@ -285,15 +559,30 @@ type ConsentiMessage = {
|
|
|
285
559
|
*/
|
|
286
560
|
|
|
287
561
|
declare class ConsentiSetup implements ConsentiWidgetAPI {
|
|
288
|
-
private config;
|
|
289
562
|
private initialized;
|
|
290
563
|
private initializing;
|
|
291
564
|
private profile;
|
|
565
|
+
private resolvedBase;
|
|
566
|
+
/** cookieId → Category lookup, rebuilt whenever `profile` changes. Avoids rescanning categories on every consent action. */
|
|
567
|
+
private categoryIndex;
|
|
568
|
+
/** Watchers created by the declarative `data-consenti-*` DOM scan — destroyed alongside the widget since they have no other owner. */
|
|
569
|
+
private scannedScripts;
|
|
292
570
|
private consentStore;
|
|
571
|
+
/**
|
|
572
|
+
* Stable per-browser identifier. Created lazily the first time a consent decision actually
|
|
573
|
+
* happens (manual submit, GPC auto-response, or relaying a decision already made in another
|
|
574
|
+
* tab) — never minted before that, so an undecided visitor leaves nothing in storage. See
|
|
575
|
+
* `getOrCreateVisitorId()`.
|
|
576
|
+
*/
|
|
577
|
+
private visitorId;
|
|
293
578
|
private eventBus;
|
|
294
579
|
private banner;
|
|
295
580
|
private modal;
|
|
581
|
+
private ageGate;
|
|
296
582
|
private renderer;
|
|
583
|
+
/** Set once the age gate (if enabled) resolves; threaded onto every `submitConsent` call thereafter. */
|
|
584
|
+
private _ageVerified;
|
|
585
|
+
private _parentalConsentToken;
|
|
297
586
|
private broadcastChannel;
|
|
298
587
|
private readyResolve;
|
|
299
588
|
private readyPromise;
|
|
@@ -302,13 +591,23 @@ declare class ConsentiSetup implements ConsentiWidgetAPI {
|
|
|
302
591
|
private lastSignature;
|
|
303
592
|
/** Tracks which banner variant is currently visible, or null when hidden. */
|
|
304
593
|
private _bannerVariant;
|
|
594
|
+
/** Tracks which banner variant is currently mounted in the DOM (persists when banner is hidden). */
|
|
595
|
+
private _bannerMounted;
|
|
596
|
+
/** Active focus trap keydown listener — removed when modal closes. */
|
|
597
|
+
private _focusTrapListener;
|
|
598
|
+
/** Maps original handler functions to their DOM-wrapped listeners for on/off bookkeeping. */
|
|
599
|
+
private _eventHandlers;
|
|
600
|
+
/** `core` defaulted to `{}` in the constructor below — every one of its own fields is
|
|
601
|
+
* optional, so this narrows back to non-optional for every other method in this class. */
|
|
602
|
+
private config;
|
|
305
603
|
/**
|
|
306
604
|
* Creates and initialises the consent widget.
|
|
307
605
|
*
|
|
308
606
|
* Construction is synchronous; the async `init()` is launched in the background.
|
|
309
607
|
* Use `await widget.ready` or `widget.onReady(cb)` to run code after init completes.
|
|
310
608
|
*
|
|
311
|
-
* @param config - Widget configuration. See `ConsentiConfig` for all options.
|
|
609
|
+
* @param config - Widget configuration. See `ConsentiConfig` for all options. `core` may be
|
|
610
|
+
* omitted entirely — every one of its own fields is optional too.
|
|
312
611
|
*/
|
|
313
612
|
constructor(config: ConsentiConfig);
|
|
314
613
|
private profileId;
|
|
@@ -318,8 +617,53 @@ declare class ConsentiSetup implements ConsentiWidgetAPI {
|
|
|
318
617
|
* to re-initialise the same instance.
|
|
319
618
|
*/
|
|
320
619
|
init(): Promise<void>;
|
|
620
|
+
/**
|
|
621
|
+
* Everything after the "does consent already exist" check — GPC/CCPA/CPRA silent paths,
|
|
622
|
+
* then the normal opt-in banner. Extracted from `init()` so the age gate (when enabled and
|
|
623
|
+
* no consent exists yet) can defer this whole sequence until the visitor answers it via
|
|
624
|
+
* `resolveAgeGate()`, then resume here with `hasExisting` fixed at `false`.
|
|
625
|
+
*/
|
|
626
|
+
private continueInit;
|
|
627
|
+
/** Mounts the age-gate prompt (`compliance.ageGate`) in place of the normal banner flow. */
|
|
628
|
+
private showAgeGate;
|
|
629
|
+
/**
|
|
630
|
+
* Handles the visitor's age-gate answer.
|
|
631
|
+
* - Confirmed → records `ageVerified: true` for all future `submitConsent` calls and
|
|
632
|
+
* resumes the normal init flow via `continueInit()`.
|
|
633
|
+
* - Declined, no parental consent required → immediately submits a deny-all consent
|
|
634
|
+
* (mandatory cookies still granted), mirroring the GPC-strict silent-write pattern.
|
|
635
|
+
* - Declined, parental consent required → same deny-all submission, plus a
|
|
636
|
+
* `parentalConsentToken` and a `consenti:parentalConsentRequired` event so the site
|
|
637
|
+
* owner can wire their own out-of-band verification flow (no email infra exists in
|
|
638
|
+
* this package to do that here).
|
|
639
|
+
*/
|
|
640
|
+
private resolveAgeGate;
|
|
641
|
+
/**
|
|
642
|
+
* Marks the widget ready and runs the declarative DOM-scan for
|
|
643
|
+
* `data-consenti-consent-script`/`data-consenti-category-script` tags. Called from
|
|
644
|
+
* every exit path of `init()` so the scan always runs exactly once per init cycle,
|
|
645
|
+
* whether `init()` was triggered automatically (`autoInit !== false`) or explicitly
|
|
646
|
+
* by the caller (`autoInit: false`) — it never runs before the widget actually has
|
|
647
|
+
* a resolved profile to read consent from.
|
|
648
|
+
*/
|
|
649
|
+
private finishInit;
|
|
650
|
+
/** Sets the `dir` attribute on the root element from `core.dir` (default `'auto'`, derived from `core.locale`). */
|
|
651
|
+
private applyDirection;
|
|
321
652
|
/** Applies the `consenti-root--dark` class based on config or profile flag. */
|
|
322
653
|
private applyDarkMode;
|
|
654
|
+
/** Applies `consenti--enhanced-a11y` class when `profile.enhanceAccessibility` is set. */
|
|
655
|
+
private applyAccessibility;
|
|
656
|
+
/** Builds and appends the metadata footer strip to a banner or modal container. */
|
|
657
|
+
private _appendMetaFooter;
|
|
658
|
+
/**
|
|
659
|
+
* Injects a `<style>` element into the root for `stackButtonsOnBreakpoint`.
|
|
660
|
+
* Called once per profile load; a new style replaces the previous one.
|
|
661
|
+
*/
|
|
662
|
+
private applyStackButtonsBreakpoint;
|
|
663
|
+
/** Installs a keyboard focus trap on `container` while the modal is open. */
|
|
664
|
+
private _installFocusTrap;
|
|
665
|
+
/** Removes the active focus trap keyboard listener. */
|
|
666
|
+
private _removeFocusTrap;
|
|
323
667
|
/**
|
|
324
668
|
* Injects CSS custom property overrides supplied via `core.theme` into the
|
|
325
669
|
* Consenti root element so they cascade down to all widget elements.
|
|
@@ -334,6 +678,8 @@ declare class ConsentiSetup implements ConsentiWidgetAPI {
|
|
|
334
678
|
* @param invoke - Function that calls the desired hook method on a single plugin.
|
|
335
679
|
*/
|
|
336
680
|
private callPluginHook;
|
|
681
|
+
private _buildGrantAllConsent;
|
|
682
|
+
private _buildDenyAllConsent;
|
|
337
683
|
private buildHandlers;
|
|
338
684
|
/**
|
|
339
685
|
* Classifies a consent submission as `accept_all`, `reject_all`, `custom`, or `update`.
|
|
@@ -347,22 +693,23 @@ declare class ConsentiSetup implements ConsentiWidgetAPI {
|
|
|
347
693
|
*/
|
|
348
694
|
hasConsent(): boolean;
|
|
349
695
|
/**
|
|
350
|
-
* Returns the stored consent map,
|
|
351
|
-
*
|
|
696
|
+
* Returns the stored consent map, optionally transformed for a specific vendor.
|
|
697
|
+
* Pass `type` to get a vendor-ready object instead of the raw Consenti format.
|
|
698
|
+
* Always returns `null` during SSR or when no consent has been saved.
|
|
699
|
+
*
|
|
700
|
+
* @param type - Vendor format: 'google-gtm', 'category', 'adobe', 'meta',
|
|
701
|
+
* 'microsoft-clarity', 'twilio-segment', or omit for raw format.
|
|
352
702
|
*/
|
|
353
703
|
getConsent(): ConsentValue | null;
|
|
704
|
+
getConsent(type: ConsentType): Record<string, string> | null;
|
|
354
705
|
/**
|
|
355
706
|
* Returns the `Date` when consent was last saved, or `false` if no consent exists.
|
|
356
707
|
* Always returns `false` during SSR.
|
|
357
708
|
*/
|
|
358
709
|
getConsentDate(): Date | false;
|
|
359
710
|
/**
|
|
360
|
-
*
|
|
361
|
-
*
|
|
362
|
-
*
|
|
363
|
-
* Maps Consenti cookie IDs to the seven Google Consent Mode v2 parameters.
|
|
364
|
-
* Cookies whose IDs exactly match a GCM v2 key are forwarded directly.
|
|
365
|
-
* Non-GCM cookies are ignored by this method (they appear in `getConsent()` only).
|
|
711
|
+
* @deprecated Use `getConsent('google-gtm')` instead.
|
|
712
|
+
* Returns the consent map in Google Consent Mode v2 format.
|
|
366
713
|
*/
|
|
367
714
|
getGTMConsent(): Record<string, string> | null;
|
|
368
715
|
/**
|
|
@@ -374,7 +721,7 @@ declare class ConsentiSetup implements ConsentiWidgetAPI {
|
|
|
374
721
|
* @param consent - Partial or full map of cookie ID → status.
|
|
375
722
|
* @param gpcDerived - Internal flag set to `true` when called from the GPC strict path.
|
|
376
723
|
*/
|
|
377
|
-
submitConsent(consent: Partial<ConsentValue>, gpcDerived?: boolean): Promise<void>;
|
|
724
|
+
submitConsent(consent: Partial<ConsentValue>, gpcDerived?: boolean, source?: number): Promise<ConsentDbRecord | void>;
|
|
378
725
|
/**
|
|
379
726
|
* Returns the currently visible banner variant, or `false` if no banner is shown.
|
|
380
727
|
* Useful for programmatically checking state before calling `showBanner` / `hideBanner`.
|
|
@@ -482,6 +829,93 @@ declare class ConsentiSetup implements ConsentiWidgetAPI {
|
|
|
482
829
|
* @param locale - BCP 47 locale code to switch to (e.g. `'fr'`, `'de-AT'`).
|
|
483
830
|
*/
|
|
484
831
|
switchLocale(locale: string): void;
|
|
832
|
+
/**
|
|
833
|
+
* Returns `true` if the named cookie's consent is `'granted'`.
|
|
834
|
+
* When `requestValue` is `true`, returns the raw `ConsentStatus` string instead of a boolean,
|
|
835
|
+
* or `false` if the cookie is not in the consent map.
|
|
836
|
+
*/
|
|
837
|
+
isCookieGranted(cookieId: string, requestValue?: boolean): boolean | 'granted' | 'denied' | 'objected';
|
|
838
|
+
/**
|
|
839
|
+
* Checks consent for all cookies belonging to the given category.
|
|
840
|
+
*
|
|
841
|
+
* With `requestValue = false` (default): returns `true` only when every cookie in the
|
|
842
|
+
* category is `'granted'`, `false` otherwise.
|
|
843
|
+
*
|
|
844
|
+
* With `requestValue = true`: returns an array of one-key records — one per cookie in the
|
|
845
|
+
* category — e.g. `[{ analytics: 'granted' }, { pixel: 'denied' }]`.
|
|
846
|
+
*
|
|
847
|
+
* Returns `false` / `[]` if the category is not found or the widget is not yet initialized.
|
|
848
|
+
*/
|
|
849
|
+
isCategoryGranted(categoryId: string, requestValue?: boolean): boolean | {
|
|
850
|
+
[cookieId: string]: 'granted' | 'denied' | 'objected';
|
|
851
|
+
}[];
|
|
852
|
+
/**
|
|
853
|
+
* Programmatically accepts cookies and hides the banner.
|
|
854
|
+
*
|
|
855
|
+
* @param onlyMandatory - When `true`, only mandatory cookies are granted and all others
|
|
856
|
+
* are set to `'denied'`. Defaults to `false` (grant everything).
|
|
857
|
+
*/
|
|
858
|
+
grantAll(onlyMandatory?: boolean): Promise<void>;
|
|
859
|
+
/**
|
|
860
|
+
* Programmatically denies cookies and hides the banner.
|
|
861
|
+
*
|
|
862
|
+
* @param includingMandatory - When `true`, mandatory cookies are also denied. Defaults to
|
|
863
|
+
* `false` (mandatory cookies remain `'granted'`). Passing `true`
|
|
864
|
+
* logs a warning — ensure this is intentional.
|
|
865
|
+
*/
|
|
866
|
+
denyAll(includingMandatory?: boolean): Promise<void>;
|
|
867
|
+
/**
|
|
868
|
+
* Subscribes to a Consenti widget event. The `consenti:` prefix is optional —
|
|
869
|
+
* both `'consentSubmitted'` and `'consenti:consentSubmitted'` are accepted.
|
|
870
|
+
*
|
|
871
|
+
* The same handler reference must be passed to `off()` to unsubscribe.
|
|
872
|
+
*
|
|
873
|
+
* @example
|
|
874
|
+
* ```ts
|
|
875
|
+
* const handler = (data) => console.log(data)
|
|
876
|
+
* widget.on('consentSubmitted', handler)
|
|
877
|
+
* // later:
|
|
878
|
+
* widget.off('consentSubmitted', handler)
|
|
879
|
+
* ```
|
|
880
|
+
*/
|
|
881
|
+
on(event: ConsentiEventName, handler: (data: ConsentEvent) => void): void;
|
|
882
|
+
/**
|
|
883
|
+
* Removes a previously registered event handler. The same function reference passed to
|
|
884
|
+
* `on()` must be used here.
|
|
885
|
+
*/
|
|
886
|
+
off(event: ConsentiEventName, handler: (data: ConsentEvent) => void): void;
|
|
887
|
+
/**
|
|
888
|
+
* Returns the current version of the package and the active profile/consent versions.
|
|
889
|
+
* Useful for debugging and support diagnostics.
|
|
890
|
+
*/
|
|
891
|
+
version(): {
|
|
892
|
+
package: string;
|
|
893
|
+
profileVersion: string;
|
|
894
|
+
consentVersion: string | null;
|
|
895
|
+
};
|
|
896
|
+
/**
|
|
897
|
+
* Toggles or sets dark mode at runtime without re-initialising the widget.
|
|
898
|
+
* When `enable` is omitted, the current dark mode state is toggled.
|
|
899
|
+
*/
|
|
900
|
+
setDarkMode(enable?: boolean): void;
|
|
901
|
+
/**
|
|
902
|
+
* Applies partial theme token overrides at runtime, merging them into the current theme.
|
|
903
|
+
* CSS custom properties on the root element are updated immediately.
|
|
904
|
+
*/
|
|
905
|
+
setTheme(theme: Partial<ThemeConfig>): void;
|
|
906
|
+
/**
|
|
907
|
+
* Deep-merges a partial config into the current widget config.
|
|
908
|
+
* Theme and dark mode side-effects are re-applied immediately.
|
|
909
|
+
* Changes to locale or profile require an explicit `switchLocale()` or `init()` call.
|
|
910
|
+
*/
|
|
911
|
+
setConfig(config: DeepPartial<ConsentiConfig>): void;
|
|
912
|
+
/**
|
|
913
|
+
* Merges a partial profile override into the current profile and re-renders any visible UI.
|
|
914
|
+
* Does not make a network request — the resolved base profile from the last `init()` is reused.
|
|
915
|
+
*
|
|
916
|
+
* No-op before `init()` completes (while `resolvedBase` is null).
|
|
917
|
+
*/
|
|
918
|
+
setProfile(override: DeepPartial<ResolvedProfile>): void;
|
|
485
919
|
/**
|
|
486
920
|
* Destroys the widget — removes all DOM elements, disconnects the BroadcastChannel,
|
|
487
921
|
* and calls `destroy()` on all registered plugins.
|
|
@@ -580,28 +1014,36 @@ declare abstract class ConsentiPlugin {
|
|
|
580
1014
|
* import { ConsentiProfile, ConsentiSetup } from '@consenti/ui'
|
|
581
1015
|
*
|
|
582
1016
|
* const profile = new ConsentiProfile({
|
|
583
|
-
* cookies:
|
|
584
|
-
*
|
|
585
|
-
*
|
|
586
|
-
*
|
|
1017
|
+
* cookies: {
|
|
1018
|
+
* necessary: {},
|
|
1019
|
+
* analytics: {},
|
|
1020
|
+
* },
|
|
587
1021
|
* defaultLocale: 'en',
|
|
588
1022
|
* translations: {
|
|
589
1023
|
* en: {
|
|
590
1024
|
* mainBanner: {
|
|
591
1025
|
* position: 'bottom',
|
|
592
1026
|
* htmlText: 'We use cookies.',
|
|
593
|
-
* buttons:
|
|
1027
|
+
* buttons: { 'accept-all': { text: 'Accept All', style: 'primary', action: 'submit', cookies: '*' } },
|
|
594
1028
|
* },
|
|
595
1029
|
* preferenceModal: {
|
|
596
|
-
* categories:
|
|
597
|
-
*
|
|
1030
|
+
* categories: {
|
|
1031
|
+
* necessary: { heading: 'Necessary', htmlText: '...', legalBasis: 'mandatory', cookies: ['necessary'] },
|
|
1032
|
+
* },
|
|
1033
|
+
* buttons: { save: { text: 'Save', style: 'primary', action: 'submit' } },
|
|
598
1034
|
* },
|
|
599
1035
|
* },
|
|
600
1036
|
* },
|
|
601
1037
|
* })
|
|
602
1038
|
*
|
|
603
|
-
* const widget = new ConsentiSetup({ core: { profileId: profile.
|
|
1039
|
+
* const widget = new ConsentiSetup({ core: { profileId: profile.getType() } })
|
|
604
1040
|
* ```
|
|
1041
|
+
*
|
|
1042
|
+
* To instead patch one of Consenti's built-in profiles for a given `complianceGroup`
|
|
1043
|
+
* (rather than defining a full standalone profile), pass `complianceGroup` and
|
|
1044
|
+
* `deepMerge: true` with only the fields you want to override — see
|
|
1045
|
+
* `RegisterableProfileConfig` and the `complianceGroup`/`deepMerge` resolver behavior
|
|
1046
|
+
* in `profile-resolver.ts`.
|
|
605
1047
|
*/
|
|
606
1048
|
|
|
607
1049
|
/**
|
|
@@ -609,15 +1051,17 @@ declare abstract class ConsentiPlugin {
|
|
|
609
1051
|
*/
|
|
610
1052
|
declare class ConsentiProfile {
|
|
611
1053
|
private config;
|
|
612
|
-
private
|
|
1054
|
+
private type;
|
|
613
1055
|
/**
|
|
614
|
-
* @param config - Full profile configuration including cookies, locales, and UI text
|
|
1056
|
+
* @param config - Full profile configuration including cookies, locales, and UI text,
|
|
1057
|
+
* or a `{ complianceGroup, deepMerge: true, ... }` partial overlay to
|
|
1058
|
+
* patch a built-in profile instead of defining a standalone one.
|
|
615
1059
|
*/
|
|
616
|
-
constructor(config:
|
|
1060
|
+
constructor(config: RegisterableProfileConfig);
|
|
617
1061
|
/** Returns the auto-assigned numeric profile ID. Pass this to `core.profileId`. */
|
|
618
|
-
|
|
619
|
-
/** Returns the raw
|
|
620
|
-
toJSON():
|
|
1062
|
+
getType(): Symbol;
|
|
1063
|
+
/** Returns the raw config passed to the constructor. */
|
|
1064
|
+
toJSON(): RegisterableProfileConfig;
|
|
621
1065
|
}
|
|
622
1066
|
|
|
623
1067
|
/**
|
|
@@ -655,8 +1099,12 @@ interface ConsentScriptOptions {
|
|
|
655
1099
|
widget: ConsentiSetup;
|
|
656
1100
|
/** Remote script `src` URL to inject when consent is granted. */
|
|
657
1101
|
src?: string;
|
|
658
|
-
/**
|
|
659
|
-
|
|
1102
|
+
/**
|
|
1103
|
+
* Inline JavaScript to inject when consent is granted (e.g. a GTM snippet).
|
|
1104
|
+
* WARNING: this string is assigned directly to `script.innerHTML` — only
|
|
1105
|
+
* pass a static, trusted literal. Never pass user-supplied or remote content.
|
|
1106
|
+
*/
|
|
1107
|
+
unsafeInnerHTML?: string;
|
|
660
1108
|
/**
|
|
661
1109
|
* Additional HTML attributes applied to the injected `<script>` element.
|
|
662
1110
|
* Set a key to an empty string for boolean attributes (e.g. `{ async: '', defer: '' }`).
|
|
@@ -666,6 +1114,12 @@ interface ConsentScriptOptions {
|
|
|
666
1114
|
onLoad?: () => void;
|
|
667
1115
|
/** Called after the `<script>` element has been removed from the DOM. */
|
|
668
1116
|
onRevoke?: () => void;
|
|
1117
|
+
/**
|
|
1118
|
+
* When `true` (default), the script is automatically removed when consent is revoked and
|
|
1119
|
+
* re-injected when consent is re-granted. Set to `false` to evaluate consent only once at
|
|
1120
|
+
* construction time — no event listener is attached and the script is never auto-removed.
|
|
1121
|
+
*/
|
|
1122
|
+
bind?: boolean;
|
|
669
1123
|
}
|
|
670
1124
|
/**
|
|
671
1125
|
* Conditionally injects and removes a `<script>` element based on a specific
|
|
@@ -695,37 +1149,248 @@ declare class ConsentScript {
|
|
|
695
1149
|
}
|
|
696
1150
|
|
|
697
1151
|
/**
|
|
698
|
-
*
|
|
699
|
-
*
|
|
1152
|
+
* ConsentAction — runs a callback based on a specific consent parameter's grant status.
|
|
1153
|
+
*
|
|
1154
|
+
* Same lifecycle as `ConsentScript` (evaluates immediately on construction so
|
|
1155
|
+
* existing consent is honoured, re-evaluates on `consenti:consentSubmitted`,
|
|
1156
|
+
* `destroy()` to unbind) but fires `onGrant`/`onDeny` callbacks instead of
|
|
1157
|
+
* injecting a `<script>` element — for integrations that expose their own
|
|
1158
|
+
* `sdk.optIn()`/`sdk.optOut()` API (Segment, Mixpanel, Amplitude, Sentry, etc.)
|
|
1159
|
+
* rather than needing a script tag toggled. Use `ConsentScript` for that case instead.
|
|
1160
|
+
*
|
|
1161
|
+
* @example
|
|
1162
|
+
* ```ts
|
|
1163
|
+
* import { ConsentiSetup, ConsentAction } from '@consenti/ui'
|
|
1164
|
+
*
|
|
1165
|
+
* const widget = new ConsentiSetup({ core: { profileId: 0 } })
|
|
1166
|
+
* await widget.ready
|
|
1167
|
+
*
|
|
1168
|
+
* new ConsentAction({
|
|
1169
|
+
* id: 'analytics_storage',
|
|
1170
|
+
* widget,
|
|
1171
|
+
* onGrant: () => analyticsSdk.optIn(),
|
|
1172
|
+
* onDeny: () => analyticsSdk.optOut(),
|
|
1173
|
+
* })
|
|
1174
|
+
* ```
|
|
1175
|
+
*/
|
|
1176
|
+
|
|
1177
|
+
/** Passed to `onGrant`/`onDeny` — the resolved parameter's metadata plus the full current consent map. */
|
|
1178
|
+
interface ConsentActionParams {
|
|
1179
|
+
cookieId: string;
|
|
1180
|
+
status: ConsentStatus;
|
|
1181
|
+
cookie: Cookie | undefined;
|
|
1182
|
+
consent: ConsentValue | null;
|
|
1183
|
+
}
|
|
1184
|
+
/** Options for constructing a {@link ConsentAction} instance. */
|
|
1185
|
+
interface ConsentActionOptions {
|
|
1186
|
+
/** The consent parameter ID to watch (e.g. `'analytics_storage'`). */
|
|
1187
|
+
id: string;
|
|
1188
|
+
/** The `ConsentiSetup` widget instance to read consent from. */
|
|
1189
|
+
widget: ConsentiSetup;
|
|
1190
|
+
/**
|
|
1191
|
+
* When `true` (default), the callbacks re-fire automatically on every future consent
|
|
1192
|
+
* change. Set to `false` to evaluate consent only once at construction time — no
|
|
1193
|
+
* event listener is attached.
|
|
1194
|
+
*/
|
|
1195
|
+
bind?: boolean;
|
|
1196
|
+
/** Called when the parameter's status transitions to `'granted'`. */
|
|
1197
|
+
onGrant?: (params: ConsentActionParams) => void;
|
|
1198
|
+
/** Called when the parameter's status transitions away from `'granted'` (`'denied'` or `'objected'`). */
|
|
1199
|
+
onDeny?: (params: ConsentActionParams) => void;
|
|
1200
|
+
}
|
|
1201
|
+
/**
|
|
1202
|
+
* Watches a single consent parameter's grant status and fires `onGrant`/`onDeny`
|
|
1203
|
+
* callbacks on transitions. Call {@link ConsentAction.destroy} when no longer
|
|
1204
|
+
* needed to remove the event listener.
|
|
1205
|
+
*/
|
|
1206
|
+
declare class ConsentAction {
|
|
1207
|
+
private readonly options;
|
|
1208
|
+
private granted;
|
|
1209
|
+
private readonly handler;
|
|
1210
|
+
constructor(options: ConsentActionOptions);
|
|
1211
|
+
private evaluate;
|
|
1212
|
+
/** Removes the event listener (if bound). */
|
|
1213
|
+
destroy(): void;
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
/**
|
|
1217
|
+
* CategoryAction — runs a callback based on a category's rollup consent state.
|
|
1218
|
+
*
|
|
1219
|
+
* A category is considered "granted" only when *every* parameter it contains is
|
|
1220
|
+
* `'granted'` — matching the preference modal's tri-state rollup rule. `onDeny`
|
|
1221
|
+
* fires for both a fully-denied category and a partially-granted ("mixed") one,
|
|
1222
|
+
* since neither represents full consent for the category.
|
|
1223
|
+
*
|
|
1224
|
+
* Same lifecycle as `ConsentAction`: evaluates immediately on construction,
|
|
1225
|
+
* re-evaluates on `consenti:consentSubmitted`, `destroy()` to unbind.
|
|
1226
|
+
*
|
|
1227
|
+
* @example
|
|
1228
|
+
* ```ts
|
|
1229
|
+
* import { ConsentiSetup, CategoryAction } from '@consenti/ui'
|
|
1230
|
+
*
|
|
1231
|
+
* const widget = new ConsentiSetup({ core: { profileId: 0 } })
|
|
1232
|
+
* await widget.ready
|
|
1233
|
+
*
|
|
1234
|
+
* new CategoryAction({
|
|
1235
|
+
* id: 'marketing',
|
|
1236
|
+
* widget,
|
|
1237
|
+
* onGrant: () => adSdk.enableAll(),
|
|
1238
|
+
* onDeny: () => adSdk.disableAll(),
|
|
1239
|
+
* })
|
|
1240
|
+
* ```
|
|
1241
|
+
*/
|
|
1242
|
+
|
|
1243
|
+
/** Passed to `onGrant`/`onDeny` — the category's member parameter IDs plus the full current consent map. */
|
|
1244
|
+
interface CategoryActionParams {
|
|
1245
|
+
categoryId: string;
|
|
1246
|
+
cookieIds: string[];
|
|
1247
|
+
consent: ConsentValue | null;
|
|
1248
|
+
}
|
|
1249
|
+
/** Options for constructing a {@link CategoryAction} instance. */
|
|
1250
|
+
interface CategoryActionOptions {
|
|
1251
|
+
/** The category ID to watch (e.g. `'marketing'`). */
|
|
1252
|
+
id: string;
|
|
1253
|
+
/** The `ConsentiSetup` widget instance to read consent from. */
|
|
1254
|
+
widget: ConsentiSetup;
|
|
1255
|
+
/**
|
|
1256
|
+
* When `true` (default), the callbacks re-fire automatically on every future consent
|
|
1257
|
+
* change. Set to `false` to evaluate consent only once at construction time — no
|
|
1258
|
+
* event listener is attached.
|
|
1259
|
+
*/
|
|
1260
|
+
bind?: boolean;
|
|
1261
|
+
/** Called when every parameter in the category transitions to `'granted'`. */
|
|
1262
|
+
onGrant?: (params: CategoryActionParams) => void;
|
|
1263
|
+
/** Called when the category transitions away from fully-granted (any parameter denied/objected). */
|
|
1264
|
+
onDeny?: (params: CategoryActionParams) => void;
|
|
1265
|
+
}
|
|
1266
|
+
/**
|
|
1267
|
+
* Watches a category's rollup grant status and fires `onGrant`/`onDeny` callbacks
|
|
1268
|
+
* on transitions. Call {@link CategoryAction.destroy} when no longer needed to
|
|
1269
|
+
* remove the event listener.
|
|
1270
|
+
*/
|
|
1271
|
+
declare class CategoryAction {
|
|
1272
|
+
private readonly options;
|
|
1273
|
+
private granted;
|
|
1274
|
+
private readonly handler;
|
|
1275
|
+
constructor(options: CategoryActionOptions);
|
|
1276
|
+
private evaluate;
|
|
1277
|
+
/** Removes the event listener (if bound). */
|
|
1278
|
+
destroy(): void;
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
/**
|
|
1282
|
+
* CategoryScript — conditionally loads/unloads a third-party `<script>` tag
|
|
1283
|
+
* based on a whole category's rollup consent state, instead of one parameter.
|
|
1284
|
+
*
|
|
1285
|
+
* A category is considered "granted" only when *every* parameter it contains is
|
|
1286
|
+
* `'granted'` — matching the preference modal's tri-state rollup rule and
|
|
1287
|
+
* `CategoryAction`'s behavior. Injection mechanics (src validation, inline-script
|
|
1288
|
+
* escape hatch, attribute filtering) are identical to `ConsentScript` — both share
|
|
1289
|
+
* the same underlying `injectScript`/`revokeScript` helpers.
|
|
1290
|
+
*
|
|
1291
|
+
* @example
|
|
1292
|
+
* ```ts
|
|
1293
|
+
* import { ConsentiSetup, CategoryScript } from '@consenti/ui'
|
|
1294
|
+
*
|
|
1295
|
+
* const widget = new ConsentiSetup({ core: { profileId: 0 } })
|
|
1296
|
+
* await widget.ready
|
|
1297
|
+
*
|
|
1298
|
+
* new CategoryScript({
|
|
1299
|
+
* categoryId: 'marketing',
|
|
1300
|
+
* widget,
|
|
1301
|
+
* src: 'https://example.com/ad-pixel.js',
|
|
1302
|
+
* })
|
|
1303
|
+
* ```
|
|
1304
|
+
*/
|
|
1305
|
+
|
|
1306
|
+
/** Options for constructing a {@link CategoryScript} instance. */
|
|
1307
|
+
interface CategoryScriptOptions {
|
|
1308
|
+
/** The category ID to watch (e.g. `'marketing'`). */
|
|
1309
|
+
categoryId: string;
|
|
1310
|
+
/** The `ConsentiSetup` widget instance to read consent from. */
|
|
1311
|
+
widget: ConsentiSetup;
|
|
1312
|
+
/** Remote script `src` URL to inject when every parameter in the category is granted. */
|
|
1313
|
+
src?: string;
|
|
1314
|
+
/**
|
|
1315
|
+
* Inline JavaScript to inject when granted (e.g. a GTM snippet).
|
|
1316
|
+
* WARNING: this string is assigned directly to `script.innerHTML` — only
|
|
1317
|
+
* pass a static, trusted literal. Never pass user-supplied or remote content.
|
|
1318
|
+
*/
|
|
1319
|
+
unsafeInnerHTML?: string;
|
|
1320
|
+
/**
|
|
1321
|
+
* Additional HTML attributes applied to the injected `<script>` element.
|
|
1322
|
+
* Set a key to an empty string for boolean attributes (e.g. `{ async: '', defer: '' }`).
|
|
1323
|
+
*/
|
|
1324
|
+
attributes?: Record<string, string>;
|
|
1325
|
+
/** Called after the `<script>` element has been appended to `<head>`. */
|
|
1326
|
+
onLoad?: () => void;
|
|
1327
|
+
/** Called after the `<script>` element has been removed from the DOM. */
|
|
1328
|
+
onRevoke?: () => void;
|
|
1329
|
+
/**
|
|
1330
|
+
* When `true` (default), the script is automatically removed when the category is no
|
|
1331
|
+
* longer fully granted and re-injected when it becomes fully granted again. Set to
|
|
1332
|
+
* `false` to evaluate consent only once at construction time — no event listener is
|
|
1333
|
+
* attached and the script is never auto-removed.
|
|
1334
|
+
*/
|
|
1335
|
+
bind?: boolean;
|
|
1336
|
+
}
|
|
1337
|
+
/**
|
|
1338
|
+
* Conditionally injects and removes a `<script>` element based on a category's
|
|
1339
|
+
* rollup consent status (every member parameter granted).
|
|
1340
|
+
*
|
|
1341
|
+
* Call {@link CategoryScript.destroy} when the trigger is no longer needed
|
|
1342
|
+
* (e.g. on SPA route unmount) to remove the event listener and the injected element.
|
|
1343
|
+
*/
|
|
1344
|
+
declare class CategoryScript {
|
|
1345
|
+
private readonly options;
|
|
1346
|
+
private scriptEl;
|
|
1347
|
+
private readonly handler;
|
|
1348
|
+
constructor(options: CategoryScriptOptions);
|
|
1349
|
+
private evaluate;
|
|
1350
|
+
private inject;
|
|
1351
|
+
private revoke;
|
|
1352
|
+
/**
|
|
1353
|
+
* Removes the event listener and the injected `<script>` element (if present).
|
|
1354
|
+
* Call this when the widget is destroyed or the script is no longer needed.
|
|
1355
|
+
*/
|
|
1356
|
+
destroy(): void;
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
/**
|
|
1360
|
+
* BannerTrigger — a pre-built accessible UI element that reopens the Consenti
|
|
1361
|
+
* banner or preference modal when clicked.
|
|
700
1362
|
*
|
|
701
1363
|
* Use this to add a "Cookie Settings" link in your site footer or cookie policy
|
|
702
1364
|
* page without wiring up the click handler manually or importing the widget module
|
|
703
1365
|
* into your layout component.
|
|
704
1366
|
*
|
|
1367
|
+
* (Renamed from `CookieTrigger` — it was never scoped to a specific cookie, it
|
|
1368
|
+
* just opens the banner or modal.)
|
|
1369
|
+
*
|
|
705
1370
|
* @example
|
|
706
1371
|
* ```ts
|
|
707
|
-
* import { ConsentiSetup,
|
|
1372
|
+
* import { ConsentiSetup, BannerTrigger } from '@consenti/ui'
|
|
708
1373
|
*
|
|
709
1374
|
* const widget = new ConsentiSetup({ core: { profileId: 0 } })
|
|
710
1375
|
*
|
|
711
1376
|
* // Attach to an existing element
|
|
712
|
-
* new
|
|
1377
|
+
* new BannerTrigger({ widget, el: '#footer-cookie-settings' })
|
|
713
1378
|
*
|
|
714
1379
|
* // — or — create a new button and place it yourself
|
|
715
|
-
* const trigger = new
|
|
1380
|
+
* const trigger = new BannerTrigger({ widget, label: 'Cookie Settings' })
|
|
716
1381
|
* document.querySelector('.site-footer')?.appendChild(trigger.getElement())
|
|
717
1382
|
* ```
|
|
718
1383
|
*/
|
|
719
1384
|
|
|
720
|
-
/** Options for constructing a {@link
|
|
721
|
-
interface
|
|
1385
|
+
/** Options for constructing a {@link BannerTrigger} instance. */
|
|
1386
|
+
interface BannerTriggerOptions {
|
|
722
1387
|
/** The widget instance to control when the trigger is clicked. */
|
|
723
1388
|
widget: ConsentiSetup;
|
|
724
1389
|
/**
|
|
725
1390
|
* Element to attach the click handler to.
|
|
726
1391
|
* - `HTMLElement` — used directly.
|
|
727
1392
|
* - `string` — treated as a CSS selector; the first matching element is used.
|
|
728
|
-
* - Omitted — a new `<button>` is created. Retrieve it with {@link
|
|
1393
|
+
* - Omitted — a new `<button>` is created. Retrieve it with {@link BannerTrigger.getElement}
|
|
729
1394
|
* and append it to the DOM at the desired location.
|
|
730
1395
|
*/
|
|
731
1396
|
el?: HTMLElement | string;
|
|
@@ -748,12 +1413,12 @@ interface CookieTriggerOptions {
|
|
|
748
1413
|
* The created button uses the `.consenti-btn` and `.consenti-btn--text` classes so
|
|
749
1414
|
* it inherits the widget's theme automatically.
|
|
750
1415
|
*/
|
|
751
|
-
declare class
|
|
1416
|
+
declare class BannerTrigger {
|
|
752
1417
|
private readonly el;
|
|
753
1418
|
private readonly clickHandler;
|
|
754
1419
|
/** Whether this instance created the element (used to decide if `destroy()` removes it). */
|
|
755
1420
|
private readonly created;
|
|
756
|
-
constructor(options:
|
|
1421
|
+
constructor(options: BannerTriggerOptions);
|
|
757
1422
|
/**
|
|
758
1423
|
* Returns the trigger element.
|
|
759
1424
|
* When no `el` was provided, append the returned element to the desired location
|
|
@@ -767,4 +1432,42 @@ declare class CookieTrigger {
|
|
|
767
1432
|
destroy(): void;
|
|
768
1433
|
}
|
|
769
1434
|
|
|
770
|
-
|
|
1435
|
+
/**
|
|
1436
|
+
* Declarative DOM-scan bindings — a zero-JS integration path for gating
|
|
1437
|
+
* third-party scripts via `data-*` attributes instead of hand-written
|
|
1438
|
+
* `ConsentScript`/`CategoryScript` calls.
|
|
1439
|
+
*
|
|
1440
|
+
* ```html
|
|
1441
|
+
* <script type="text/plain" data-consenti-category-script="marketing" src="https://example.com/pixel.js"></script>
|
|
1442
|
+
* <script type="text/plain" data-consenti-consent-script="analytics_storage">/* inline snippet *\/</script>
|
|
1443
|
+
* <script type="text/plain" data-consenti-consent-script="ad_storage" data-consenti-bind="false" src="..."></script>
|
|
1444
|
+
* ```
|
|
1445
|
+
*
|
|
1446
|
+
* Scanned automatically once per `ConsentiSetup.init()` cycle (after `init()`
|
|
1447
|
+
* completes — so it respects `autoInit: false`, only running once the widget is
|
|
1448
|
+
* actually initialized, however `init()` was triggered). The scanned tags are
|
|
1449
|
+
* read-only config sources and stay inert (`type="text/plain"`) in the DOM
|
|
1450
|
+
* permanently — `ConsentScript`/`CategoryScript` inject their own separate
|
|
1451
|
+
* `<script>` element exactly as they do when constructed by hand.
|
|
1452
|
+
*/
|
|
1453
|
+
|
|
1454
|
+
/**
|
|
1455
|
+
* Scans the document for `<script type="text/plain">` tags carrying
|
|
1456
|
+
* `data-consenti-consent-script` or `data-consenti-category-script`, and
|
|
1457
|
+
* instantiates `ConsentScript`/`CategoryScript` for each. Called automatically
|
|
1458
|
+
* by `ConsentiSetup` at the end of every `init()` cycle.
|
|
1459
|
+
*
|
|
1460
|
+
* v1 scans once automatically; scripts injected into the DOM after that point
|
|
1461
|
+
* (e.g. by a late-loading CMS widget) are not picked up automatically — call this
|
|
1462
|
+
* function again manually after adding more tags dynamically if needed. Each element
|
|
1463
|
+
* is only ever scanned once (marked with `data-consenti-scanned`), so calling this
|
|
1464
|
+
* again is safe — it only processes newly-added tags, never re-instantiates a watcher
|
|
1465
|
+
* for one already scanned.
|
|
1466
|
+
*
|
|
1467
|
+
* Returns the created watchers — `ConsentiSetup` holds onto these and calls
|
|
1468
|
+
* `.destroy()` on each when the widget itself is destroyed, since a scanner-created
|
|
1469
|
+
* watcher has no other owner to release its `consenti:consentSubmitted` listener.
|
|
1470
|
+
*/
|
|
1471
|
+
declare function scanConsentScripts(widget: ConsentiSetup): Array<ConsentScript | CategoryScript>;
|
|
1472
|
+
|
|
1473
|
+
export { type AgeGateWidgetConfig, type ApiConfig, BannerTrigger, type BannerTriggerOptions, type Button, type ButtonAction, type ButtonStyle, type Category, CategoryAction, type CategoryActionOptions, type CategoryActionParams, type CategoryMap, CategoryScript, type CategoryScriptOptions, type ComplianceWidgetConfig, ConsentAction, type ConsentActionOptions, type ConsentActionParams, type ConsentAction$1 as ConsentActionType, type ConsentEvent, type ConsentReceipt, type ConsentRecord, ConsentScript, type ConsentScriptOptions, type ConsentStatus, type ConsentValue, type ConsentiConfig, type ConsentiEventName, type ConsentiMessage, ConsentiPlugin, ConsentiProfile, ConsentiSetup, type ConsentiWidgetAPI, type Cookie, type CookieMap, type CookieOptions, type CoreConfig, type GpcBanner, type GtmConfig, type LocaleTranslations, type MainBanner, type ParentalConsentRequiredDetail, type ParsedConsent, type PreferenceModal, type ProfileConfig, type ProfileTranslations, type RegisterableProfileConfig, type ResolvedProfile, type TcfWidgetConfig, type ThemeConfig, type UtilsConfig, scanConsentScripts };
|