@consenti/ui 0.1.0 → 0.2.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/dist/angular.d.ts CHANGED
@@ -1,13 +1,54 @@
1
+ type NonEmptyArray<T> = [T, ...T[]];
2
+ 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 ? {
3
+ [Key in keyof T]?: DeepPartial<T[Key]>;
4
+ } : T;
5
+
6
+ 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"];
7
+
8
+ /**
9
+ * Compliance-related literal types, derived from the regulation/group ID data
10
+ * that lives in @consenti/utils (packages/utils/src/compliance.ts).
11
+ *
12
+ * This import is type-only and fully erased at compile time — @consenti/types
13
+ * has no runtime dependency on @consenti/utils. The actual data (COMPLIANCE_GROUPS,
14
+ * EMBEDDED_COMPLIANCE_MAP, COMPLIANCE_VALIDATION_RULES, GPC_OPTIONS, etc.) lives in
15
+ * @consenti/utils; import it from there.
16
+ *
17
+ * HOW TO ADD A NEW REGULATION OR COMPLIANCE GROUP: see the header comment in
18
+ * packages/utils/src/compliance.ts — these types auto-update from that data.
19
+ */
20
+
21
+ type ComplianceGroupId = typeof COMPLIANCE_GROUP_IDS[number];
22
+
23
+ interface ComplianceMapData {
24
+ version: string;
25
+ countries: Record<string, CountryComplianceEntry>;
26
+ }
27
+ interface CountryComplianceEntry {
28
+ complianceGroup: ComplianceGroupId;
29
+ default: ComplianceGroupId;
30
+ description: string;
31
+ overriddenRegions?: Record<string, {
32
+ complianceGroup: ComplianceGroupId;
33
+ description: string;
34
+ }>;
35
+ }
36
+
1
37
  type ConsentStatus = 'granted' | 'denied' | 'objected';
38
+ type ConsentAction = 'accept_all' | 'reject_all' | 'custom' | 'update';
2
39
  type ConsentValue = Record<string, ConsentStatus>;
3
40
  interface Cookie {
4
41
  id: string;
5
- type?: 'consent' | 'legitimate_interest';
42
+ legalBasis?: 'mandatory' | 'consent' | 'legitimate_interest';
43
+ /** @deprecated use legalBasis: 'mandatory' */
6
44
  mandatory?: boolean;
45
+ /** @deprecated use legalBasis */
46
+ type?: 'consent' | 'legitimate_interest';
7
47
  listenGpc?: boolean;
8
48
  expiry?: number;
9
49
  tcfVendorId?: number;
10
50
  tcfPurposes?: number[];
51
+ tcfSpecialFeatures?: number[];
11
52
  cpraCategory?: 'sale' | 'sharing' | 'sensitive';
12
53
  }
13
54
  type ButtonStyle = 'primary' | 'secondary' | 'text' | 'accent';
@@ -18,6 +59,7 @@ interface Button {
18
59
  action: ButtonAction;
19
60
  cookies?: string[] | '*' | '!';
20
61
  url?: string;
62
+ type?: string;
21
63
  }
22
64
  interface MainBanner {
23
65
  position: 'top' | 'bottom' | 'middle' | 'left-bottom' | 'right-bottom';
@@ -43,18 +85,13 @@ interface Category {
43
85
  };
44
86
  cookies: string[];
45
87
  }
46
- interface PreferenceModal {
88
+ interface PreferenceModal extends Omit<MainBanner, "position"> {
47
89
  position?: 'left' | 'right' | 'center';
48
- overlayOpacity?: number;
49
- showClose?: boolean;
50
- showLocaleSwitcher?: boolean;
51
- heading?: string;
52
- headingTag?: string;
53
90
  subheading?: string;
54
- htmlText?: string;
55
- buttons: Button[];
56
91
  categories: Category[];
57
92
  persistent?: boolean;
93
+ /** Screen width in px below which the modal expands to full screen. Default: 576. Set to 0 to disable. */
94
+ mobileFullScreenBreakpoint?: number;
58
95
  }
59
96
  interface DpdpaConfig {
60
97
  dataFiduciary: string;
@@ -63,6 +100,7 @@ interface DpdpaConfig {
63
100
  }
64
101
  interface ResolvedProfile {
65
102
  id: number;
103
+ profileUuid?: string;
66
104
  version: number;
67
105
  defaultLocale: string;
68
106
  locales?: string[];
@@ -73,6 +111,26 @@ interface ResolvedProfile {
73
111
  cookieSigningKey?: string;
74
112
  dpdpa?: DpdpaConfig;
75
113
  darkMode?: boolean;
114
+ gpcMode?: 'ignore' | 'honor' | 'strict';
115
+ complianceGroup?: string;
116
+ complianceConfig?: Record<string, string>;
117
+ }
118
+ type WidgetCountryResolverFn = () => Promise<{
119
+ country: string | null;
120
+ region: string | null;
121
+ confidence: number;
122
+ }>;
123
+ interface AgeGateWidgetConfig {
124
+ enabled: boolean;
125
+ minimumAge: number;
126
+ requireParentalConsent?: boolean;
127
+ }
128
+ interface ComplianceWidgetConfig {
129
+ type?: 'auto' | ComplianceGroupId | string;
130
+ geoDataProvider?: 'default' | WidgetCountryResolverFn;
131
+ autoComplianceMap?: 'default' | ComplianceMapData | 'auto';
132
+ complianceMapUrl?: string;
133
+ ageGate?: AgeGateWidgetConfig;
76
134
  }
77
135
  interface GtmConfig {
78
136
  containerId?: string;
@@ -88,6 +146,9 @@ interface ApiConfig {
88
146
  enabled?: boolean;
89
147
  baseUrl?: string;
90
148
  authToken?: string;
149
+ tenantId?: string;
150
+ complianceGroup?: string;
151
+ trustDomain?: boolean;
91
152
  }
92
153
  interface ThemeConfig {
93
154
  bgColor?: string;
@@ -109,35 +170,52 @@ interface ThemeConfig {
109
170
  accentTextColor?: string;
110
171
  }
111
172
  interface CoreConfig {
112
- profileId?: number;
173
+ tenantId?: string;
113
174
  autoHonorGPC?: boolean | 'strict';
114
175
  locale?: string;
115
176
  disableCssTemplate?: boolean;
116
- signCookies?: boolean;
117
177
  cookieSigningKey?: string;
118
178
  allowReceipt?: boolean;
119
179
  cookieDomains?: string;
120
180
  storage?: 'cookie' | 'localStorage';
121
181
  theme?: ThemeConfig;
122
- privacyPolicyUrl?: string;
123
- regulation?: 'gdpr' | 'ccpa' | 'cpra' | 'dpdpa' | 'uk-gdpr' | 'lgpd' | 'pipeda' | 'popia' | 'pdpa-th' | 'appi' | 'kvkk';
124
182
  userId?: string;
183
+ usePrebuiltProfiles?: 'all' | NonEmptyArray<ComplianceGroupId>;
184
+ cacheResolvedProfiles?: boolean;
185
+ console?: Array<'info' | 'log' | 'warning' | 'error'>;
125
186
  }
126
187
  interface ConsentiConfig {
127
188
  core: CoreConfig;
189
+ compliance?: ComplianceWidgetConfig;
128
190
  rootEl?: string | HTMLElement;
129
191
  darkMode?: boolean;
130
192
  autoInit?: boolean;
131
193
  api?: ApiConfig;
132
194
  utils?: UtilsConfig;
133
195
  plugins?: ConsentiPlugin[];
134
- profileOverride?: Partial<ResolvedProfile>;
196
+ profileOverride?: DeepPartial<ResolvedProfile>;
197
+ /** When true, suppresses the "Powered by Consenti" footer link in the banner and modal. */
198
+ hidePoweredBy?: boolean;
135
199
  }
200
+ type ConsentiEventName = 'bannerInitialized' | 'consenti:bannerInitialized' | 'bannerVisibility' | 'consenti:bannerVisibility' | 'modalVisibility' | 'consenti:modalVisibility' | 'consentBeingSubmitted' | 'consenti:consentBeingSubmitted' | 'consentSubmitted' | 'consenti:consentSubmitted';
136
201
  interface ConsentiWidgetAPI {
137
202
  hasConsent(): boolean;
138
203
  getConsent(): ConsentValue | null;
139
204
  getConsentDate(): Date | false;
140
205
  getGTMConsent(): Record<string, string> | null;
206
+ isCookieGranted(cookieId: string, requestValue?: boolean): boolean | ConsentStatus;
207
+ isCategoryGranted(categoryId: string, requestValue?: boolean): boolean | {
208
+ [cookieId: string]: ConsentStatus;
209
+ }[];
210
+ grantAll(onlyMandatory?: boolean): Promise<void>;
211
+ denyAll(includingMandatory?: boolean): Promise<void>;
212
+ on(event: ConsentiEventName, handler: (data: ConsentEvent) => void): void;
213
+ off(event: ConsentiEventName, handler: (data: ConsentEvent) => void): void;
214
+ version(): {
215
+ package: string;
216
+ profileVersion: number | null;
217
+ consentVersion: number;
218
+ };
141
219
  bannerVisibility(): 'main' | 'gpc' | false;
142
220
  modalVisibility(): 'preference' | false;
143
221
  getProfile(): ResolvedProfile | null;
@@ -152,6 +230,10 @@ interface ConsentiWidgetAPI {
152
230
  getBannerElement(): HTMLElement | null;
153
231
  getModalElement(): HTMLElement | null;
154
232
  switchLocale(locale: string): void;
233
+ setDarkMode(enable?: boolean): void;
234
+ setTheme(theme: Partial<ThemeConfig>): void;
235
+ setConfig(config: DeepPartial<ConsentiConfig>): void;
236
+ setProfile(override: DeepPartial<ResolvedProfile>): void;
155
237
  init(): Promise<void>;
156
238
  onReady(callback: () => void): void;
157
239
  destroy(): void;
@@ -165,6 +247,19 @@ declare abstract class ConsentiPlugin {
165
247
  onModalShow?(): void | Promise<void>;
166
248
  onModalHide?(): void | Promise<void>;
167
249
  }
250
+ interface ConsentEvent {
251
+ profileId?: number;
252
+ consent?: ConsentValue;
253
+ hasExistingConsent?: boolean;
254
+ show?: boolean;
255
+ action?: boolean;
256
+ consentAction?: ConsentAction;
257
+ consentId?: string;
258
+ pageUrl?: string;
259
+ apiResponse?: unknown;
260
+ fromBroadcast?: boolean;
261
+ gpcDetected?: boolean;
262
+ }
168
263
 
169
264
  /**
170
265
  * Main entry point for the Consenti widget.
@@ -176,7 +271,7 @@ declare abstract class ConsentiPlugin {
176
271
  * @example
177
272
  * ```ts
178
273
  * const widget = new ConsentiSetup({
179
- * core: { profileId: 0 },
274
+ * compliance: { type: 'opt-in' },
180
275
  * })
181
276
  * await widget.ready
182
277
  * console.log(widget.hasConsent())
@@ -188,6 +283,7 @@ declare class ConsentiSetup implements ConsentiWidgetAPI {
188
283
  private initialized;
189
284
  private initializing;
190
285
  private profile;
286
+ private resolvedBase;
191
287
  private consentStore;
192
288
  private eventBus;
193
289
  private banner;
@@ -201,6 +297,8 @@ declare class ConsentiSetup implements ConsentiWidgetAPI {
201
297
  private lastSignature;
202
298
  /** Tracks which banner variant is currently visible, or null when hidden. */
203
299
  private _bannerVariant;
300
+ /** Maps original handler functions to their DOM-wrapped listeners for on/off bookkeeping. */
301
+ private _eventHandlers;
204
302
  /**
205
303
  * Creates and initialises the consent widget.
206
304
  *
@@ -233,6 +331,8 @@ declare class ConsentiSetup implements ConsentiWidgetAPI {
233
331
  * @param invoke - Function that calls the desired hook method on a single plugin.
234
332
  */
235
333
  private callPluginHook;
334
+ private _buildGrantAllConsent;
335
+ private _buildDenyAllConsent;
236
336
  private buildHandlers;
237
337
  /**
238
338
  * Classifies a consent submission as `accept_all`, `reject_all`, `custom`, or `update`.
@@ -381,6 +481,93 @@ declare class ConsentiSetup implements ConsentiWidgetAPI {
381
481
  * @param locale - BCP 47 locale code to switch to (e.g. `'fr'`, `'de-AT'`).
382
482
  */
383
483
  switchLocale(locale: string): void;
484
+ /**
485
+ * Returns `true` if the named cookie's consent is `'granted'`.
486
+ * When `requestValue` is `true`, returns the raw `ConsentStatus` string instead of a boolean,
487
+ * or `false` if the cookie is not in the consent map.
488
+ */
489
+ isCookieGranted(cookieId: string, requestValue?: boolean): boolean | 'granted' | 'denied' | 'objected';
490
+ /**
491
+ * Checks consent for all cookies belonging to the given category.
492
+ *
493
+ * With `requestValue = false` (default): returns `true` only when every cookie in the
494
+ * category is `'granted'`, `false` otherwise.
495
+ *
496
+ * With `requestValue = true`: returns an array of one-key records — one per cookie in the
497
+ * category — e.g. `[{ analytics: 'granted' }, { pixel: 'denied' }]`.
498
+ *
499
+ * Returns `false` / `[]` if the category is not found or the widget is not yet initialized.
500
+ */
501
+ isCategoryGranted(categoryId: string, requestValue?: boolean): boolean | {
502
+ [cookieId: string]: 'granted' | 'denied' | 'objected';
503
+ }[];
504
+ /**
505
+ * Programmatically accepts cookies and hides the banner.
506
+ *
507
+ * @param onlyMandatory - When `true`, only mandatory cookies are granted and all others
508
+ * are set to `'denied'`. Defaults to `false` (grant everything).
509
+ */
510
+ grantAll(onlyMandatory?: boolean): Promise<void>;
511
+ /**
512
+ * Programmatically denies cookies and hides the banner.
513
+ *
514
+ * @param includingMandatory - When `true`, mandatory cookies are also denied. Defaults to
515
+ * `false` (mandatory cookies remain `'granted'`). Passing `true`
516
+ * logs a warning — ensure this is intentional.
517
+ */
518
+ denyAll(includingMandatory?: boolean): Promise<void>;
519
+ /**
520
+ * Subscribes to a Consenti widget event. The `consenti:` prefix is optional —
521
+ * both `'consentSubmitted'` and `'consenti:consentSubmitted'` are accepted.
522
+ *
523
+ * The same handler reference must be passed to `off()` to unsubscribe.
524
+ *
525
+ * @example
526
+ * ```ts
527
+ * const handler = (data) => console.log(data)
528
+ * widget.on('consentSubmitted', handler)
529
+ * // later:
530
+ * widget.off('consentSubmitted', handler)
531
+ * ```
532
+ */
533
+ on(event: ConsentiEventName, handler: (data: ConsentEvent) => void): void;
534
+ /**
535
+ * Removes a previously registered event handler. The same function reference passed to
536
+ * `on()` must be used here.
537
+ */
538
+ off(event: ConsentiEventName, handler: (data: ConsentEvent) => void): void;
539
+ /**
540
+ * Returns the current version of the package and the active profile/consent versions.
541
+ * Useful for debugging and support diagnostics.
542
+ */
543
+ version(): {
544
+ package: string;
545
+ profileVersion: number | null;
546
+ consentVersion: number;
547
+ };
548
+ /**
549
+ * Toggles or sets dark mode at runtime without re-initialising the widget.
550
+ * When `enable` is omitted, the current dark mode state is toggled.
551
+ */
552
+ setDarkMode(enable?: boolean): void;
553
+ /**
554
+ * Applies partial theme token overrides at runtime, merging them into the current theme.
555
+ * CSS custom properties on the root element are updated immediately.
556
+ */
557
+ setTheme(theme: Partial<ThemeConfig>): void;
558
+ /**
559
+ * Deep-merges a partial config into the current widget config.
560
+ * Theme and dark mode side-effects are re-applied immediately.
561
+ * Changes to locale or profile require an explicit `switchLocale()` or `init()` call.
562
+ */
563
+ setConfig(config: DeepPartial<ConsentiConfig>): void;
564
+ /**
565
+ * Merges a partial profile override into the current profile and re-renders any visible UI.
566
+ * Does not make a network request — the resolved base profile from the last `init()` is reused.
567
+ *
568
+ * No-op before `init()` completes (while `resolvedBase` is null).
569
+ */
570
+ setProfile(override: DeepPartial<ResolvedProfile>): void;
384
571
  /**
385
572
  * Destroys the widget — removes all DOM elements, disconnects the BroadcastChannel,
386
573
  * and calls `destroy()` on all registered plugins.
@@ -413,25 +600,26 @@ declare class ConsentiSetup implements ConsentiWidgetAPI {
413
600
  * private widget!: ConsentiSetup
414
601
  *
415
602
  * ngOnInit() {
416
- * this.widget = new ConsentiSetup({ core: { profileId: 0 } })
603
+ * this.widget = new ConsentiSetup({
604
+ * api: { enabled: true, baseUrl: environment.apiUrl },
605
+ * })
417
606
  * setConsentiWidget(this.widget)
418
607
  * }
419
608
  *
420
- * ngOnDestroy() {
421
- * this.widget.destroy()
422
- * }
609
+ * ngOnDestroy() { this.widget.destroy() }
423
610
  * }
424
611
  *
425
612
  * // any-component.ts
426
613
  * import { Component, ChangeDetectorRef, OnInit, OnDestroy } from '@angular/core'
427
614
  * import { injectConsent } from '@consenti/ui/angular'
428
615
  *
429
- * @Component({ selector: 'app-cookie-status', template: `
430
- * <p *ngIf="consent.hasConsent()">Consent given on {{ consent.getConsentDate() | date }}</p>
431
- * <button *ngIf="!consent.hasConsent()" (click)="consent.submitConsent({ analytics_storage: 'granted' })">
432
- * Accept Analytics
433
- * </button>
434
- * ` })
616
+ * @Component({
617
+ * selector: 'app-cookie-status',
618
+ * template: `
619
+ * <p *ngIf="consent.hasConsent()">Consent given on {{ consent.getConsentDate() | date }}</p>
620
+ * <button *ngIf="!consent.hasConsent()" (click)="consent.showModal()">Manage Cookies</button>
621
+ * `,
622
+ * })
435
623
  * export class CookieStatusComponent implements OnInit, OnDestroy {
436
624
  * consent = injectConsent()
437
625
  * private unsub!: () => void
@@ -442,9 +630,7 @@ declare class ConsentiSetup implements ConsentiWidgetAPI {
442
630
  * this.unsub = this.consent.onConsentChange(() => this.cdr.markForCheck())
443
631
  * }
444
632
  *
445
- * ngOnDestroy() {
446
- * this.unsub()
447
- * }
633
+ * ngOnDestroy() { this.unsub() }
448
634
  * }
449
635
  * ```
450
636
  */
@@ -461,21 +647,34 @@ declare function setConsentiWidget(widget: ConsentiSetup): void;
461
647
  * Returns a consent accessor object for use in Angular components and services.
462
648
  *
463
649
  * Unlike the React and Vue integrations, Angular uses its `ChangeDetectorRef` to
464
- * trigger UI updates rather than a reactive primitive. Call `onConsentChange()` in
465
- * `ngOnInit` to subscribe to consent changes and `cdr.markForCheck()` inside the
466
- * callback to schedule re-renders in `OnPush` components.
650
+ * trigger UI updates rather than a reactive primitive. Use the `onConsentChange`,
651
+ * `onBannerChange`, and `onModalChange` helpers in `ngOnInit` to subscribe and
652
+ * call `cdr.markForCheck()` inside the callback.
467
653
  *
468
654
  * Returns SSR-safe fallback values when `window` is not defined (Angular Universal).
469
655
  *
470
- * @returns An object with `hasConsent`, `getConsent`, `submitConsent`, `getConsentDate`,
471
- * and `onConsentChange` (subscription helper).
656
+ * @returns An object with state accessors, widget actions, and change-subscription helpers.
472
657
  */
473
658
  declare function injectConsent(): {
474
659
  hasConsent: () => boolean;
475
660
  getConsent: () => ConsentValue | null;
476
- submitConsent: (_consent: Partial<ConsentValue>) => Promise<void>;
477
661
  getConsentDate: () => Date | false;
662
+ bannerVisibility: () => "main" | "gpc" | false;
663
+ modalVisibility: () => "preference" | false;
664
+ showBanner: (_gpc?: boolean) => void;
665
+ hideBanner: () => void;
666
+ showModal: () => void;
667
+ hideModal: () => void;
668
+ grantAll: (_onlyMandatory?: boolean) => Promise<void>;
669
+ denyAll: (_includingMandatory?: boolean) => Promise<void>;
670
+ submitConsent: (_consent: Partial<ConsentValue>) => Promise<void>;
671
+ reConsent: () => Promise<void>;
672
+ isCookieGranted: (_id: string) => boolean;
673
+ isCategoryGranted: (_id: string) => boolean;
674
+ switchLocale: (_locale: string) => void;
478
675
  onConsentChange: (_cb: () => void) => () => void;
676
+ onBannerChange: (_cb: () => void) => () => void;
677
+ onModalChange: (_cb: () => void) => () => void;
479
678
  };
480
679
 
481
680
  export { injectConsent, setConsentiWidget };
package/dist/angular.js CHANGED
@@ -1,74 +1,2 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/angular.ts
21
- var angular_exports = {};
22
- __export(angular_exports, {
23
- injectConsent: () => injectConsent,
24
- setConsentiWidget: () => setConsentiWidget
25
- });
26
- module.exports = __toCommonJS(angular_exports);
27
- var _widget = null;
28
- function setConsentiWidget(widget) {
29
- _widget = widget;
30
- }
31
- function injectConsent() {
32
- const isServer = typeof window === "undefined";
33
- if (isServer) {
34
- return {
35
- hasConsent: () => false,
36
- getConsent: () => null,
37
- submitConsent: async (_consent) => {
38
- },
39
- getConsentDate: () => false,
40
- onConsentChange: (_cb) => () => {
41
- }
42
- };
43
- }
44
- return {
45
- /** Returns `true` if the visitor has saved consent. */
46
- hasConsent: () => _widget?.hasConsent() ?? false,
47
- /** Returns the stored consent map, or `null`. */
48
- getConsent: () => _widget?.getConsent() ?? null,
49
- /** Saves the given partial consent map. Missing keys default to `'denied'`. */
50
- submitConsent: (consent) => _widget?.submitConsent(consent) ?? Promise.resolve(),
51
- /** Returns the `Date` of last consent submission, or `false`. */
52
- getConsentDate: () => _widget?.getConsentDate() ?? false,
53
- /**
54
- * Subscribes to consent change events and calls `callback` each time consent is
55
- * saved. Returns an unsubscribe function — call it in `ngOnDestroy` to avoid leaks.
56
- *
57
- * @param callback - Function to call when `consenti:consentSubmitted` fires.
58
- * @returns A no-arg teardown function.
59
- *
60
- * @example
61
- * ```ts
62
- * ngOnInit() {
63
- * this.unsub = this.consent.onConsentChange(() => this.cdr.markForCheck())
64
- * }
65
- * ngOnDestroy() { this.unsub() }
66
- * ```
67
- */
68
- onConsentChange: (callback) => {
69
- window.addEventListener("consenti:consentSubmitted", callback);
70
- return () => window.removeEventListener("consenti:consentSubmitted", callback);
71
- }
72
- };
73
- }
1
+ "use strict";var t=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var r=Object.getOwnPropertyNames;var d=Object.prototype.hasOwnProperty;var C=(o,e)=>{for(var s in e)t(o,s,{get:e[s],enumerable:!0})},b=(o,e,s,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of r(e))!d.call(o,i)&&i!==s&&t(o,i,{get:()=>e[i],enumerable:!(a=l(e,i))||a.enumerable});return o};var g=o=>b(t({},"__esModule",{value:!0}),o);var u={};C(u,{injectConsent:()=>m,setConsentiWidget:()=>v});module.exports=g(u);var n=null;function v(o){n=o}function m(){return typeof window>"u"?{hasConsent:()=>!1,getConsent:()=>null,getConsentDate:()=>!1,bannerVisibility:()=>!1,modalVisibility:()=>!1,showBanner:e=>{},hideBanner:()=>{},showModal:()=>{},hideModal:()=>{},grantAll:e=>Promise.resolve(),denyAll:e=>Promise.resolve(),submitConsent:e=>Promise.resolve(),reConsent:()=>Promise.resolve(),isCookieGranted:e=>!1,isCategoryGranted:e=>!1,switchLocale:e=>{},onConsentChange:e=>()=>{},onBannerChange:e=>()=>{},onModalChange:e=>()=>{}}:{hasConsent:()=>n?.hasConsent()??!1,getConsent:()=>n?.getConsent()??null,getConsentDate:()=>n?.getConsentDate()??!1,bannerVisibility:()=>n?.bannerVisibility()??!1,modalVisibility:()=>n?.modalVisibility()??!1,showBanner:e=>n?.showBanner(e),hideBanner:()=>n?.hideBanner(),showModal:()=>n?.showModal(),hideModal:()=>n?.hideModal(),grantAll:e=>n?.grantAll(e)??Promise.resolve(),denyAll:e=>n?.denyAll(e)??Promise.resolve(),submitConsent:e=>n?.submitConsent(e)??Promise.resolve(),reConsent:()=>n?.reConsent()??Promise.resolve(),isCookieGranted:e=>n?.isCookieGranted(e)??!1,isCategoryGranted:e=>n?.isCategoryGranted(e)??!1,switchLocale:e=>n?.switchLocale(e),onConsentChange:e=>(window.addEventListener("consenti:consentSubmitted",e),()=>window.removeEventListener("consenti:consentSubmitted",e)),onBannerChange:e=>(window.addEventListener("consenti:bannerVisibility",e),()=>window.removeEventListener("consenti:bannerVisibility",e)),onModalChange:e=>(window.addEventListener("consenti:modalVisibility",e),()=>window.removeEventListener("consenti:modalVisibility",e))}}
74
2
  //# sourceMappingURL=angular.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/angular.ts"],"sourcesContent":["/**\n * Angular integration for `@consenti/ui`.\n *\n * Import from the `@consenti/ui/angular` subpath to keep this module\n * tree-shaken out of vanilla JS, React, and Vue bundles.\n *\n * Designed for **Angular 15+** with standalone components or NgModule-based projects.\n * Initialise `ConsentiSetup` once (typically in `app.component.ts` or a root service)\n * and call `setConsentiWidget()` so that `injectConsent()` can read from it in any\n * component or service.\n *\n * @example\n * ```ts\n * // app.component.ts\n * import { Component, OnInit, OnDestroy } from '@angular/core'\n * import { ConsentiSetup } from '@consenti/ui'\n * import { setConsentiWidget } from '@consenti/ui/angular'\n *\n * @Component({ selector: 'app-root', template: '<router-outlet />' })\n * export class AppComponent implements OnInit, OnDestroy {\n * private widget!: ConsentiSetup\n *\n * ngOnInit() {\n * this.widget = new ConsentiSetup({ core: { profileId: 0 } })\n * setConsentiWidget(this.widget)\n * }\n *\n * ngOnDestroy() {\n * this.widget.destroy()\n * }\n * }\n *\n * // any-component.ts\n * import { Component, ChangeDetectorRef, OnInit, OnDestroy } from '@angular/core'\n * import { injectConsent } from '@consenti/ui/angular'\n *\n * @Component({ selector: 'app-cookie-status', template: `\n * <p *ngIf=\"consent.hasConsent()\">Consent given on {{ consent.getConsentDate() | date }}</p>\n * <button *ngIf=\"!consent.hasConsent()\" (click)=\"consent.submitConsent({ analytics_storage: 'granted' })\">\n * Accept Analytics\n * </button>\n * ` })\n * export class CookieStatusComponent implements OnInit, OnDestroy {\n * consent = injectConsent()\n * private unsub!: () => void\n *\n * constructor(private cdr: ChangeDetectorRef) {}\n *\n * ngOnInit() {\n * this.unsub = this.consent.onConsentChange(() => this.cdr.markForCheck())\n * }\n *\n * ngOnDestroy() {\n * this.unsub()\n * }\n * }\n * ```\n */\n\nimport type { ConsentValue } from './types'\nimport type { ConsentiSetup } from './core/consenti-setup'\n\n/**\n * Module-level singleton — the active `ConsentiSetup` instance.\n * Using a module-level variable keeps the integration zero-configuration:\n * no Angular injection token or `forRoot()` call is required.\n */\nlet _widget: ConsentiSetup | null = null\n\n/**\n * Registers the active `ConsentiSetup` instance so `injectConsent()` can read from it.\n * Call this once after creating your widget, typically in `AppComponent.ngOnInit()` or\n * a root-level Angular service.\n *\n * @param widget - The `ConsentiSetup` instance to register.\n */\nexport function setConsentiWidget(widget: ConsentiSetup): void {\n _widget = widget\n}\n\n/**\n * Returns a consent accessor object for use in Angular components and services.\n *\n * Unlike the React and Vue integrations, Angular uses its `ChangeDetectorRef` to\n * trigger UI updates rather than a reactive primitive. Call `onConsentChange()` in\n * `ngOnInit` to subscribe to consent changes and `cdr.markForCheck()` inside the\n * callback to schedule re-renders in `OnPush` components.\n *\n * Returns SSR-safe fallback values when `window` is not defined (Angular Universal).\n *\n * @returns An object with `hasConsent`, `getConsent`, `submitConsent`, `getConsentDate`,\n * and `onConsentChange` (subscription helper).\n */\nexport function injectConsent() {\n const isServer = typeof window === 'undefined'\n\n if (isServer) {\n return {\n hasConsent: () => false as boolean,\n getConsent: () => null as ConsentValue | null,\n submitConsent: async (_consent: Partial<ConsentValue>) => {},\n getConsentDate: () => false as Date | false,\n onConsentChange: (_cb: () => void) => () => {},\n }\n }\n\n return {\n /** Returns `true` if the visitor has saved consent. */\n hasConsent: () => _widget?.hasConsent() ?? false,\n\n /** Returns the stored consent map, or `null`. */\n getConsent: () => _widget?.getConsent() ?? null,\n\n /** Saves the given partial consent map. Missing keys default to `'denied'`. */\n submitConsent: (consent: Partial<ConsentValue>) =>\n _widget?.submitConsent(consent) ?? Promise.resolve(),\n\n /** Returns the `Date` of last consent submission, or `false`. */\n getConsentDate: () => _widget?.getConsentDate() ?? false,\n\n /**\n * Subscribes to consent change events and calls `callback` each time consent is\n * saved. Returns an unsubscribe function — call it in `ngOnDestroy` to avoid leaks.\n *\n * @param callback - Function to call when `consenti:consentSubmitted` fires.\n * @returns A no-arg teardown function.\n *\n * @example\n * ```ts\n * ngOnInit() {\n * this.unsub = this.consent.onConsentChange(() => this.cdr.markForCheck())\n * }\n * ngOnDestroy() { this.unsub() }\n * ```\n */\n onConsentChange: (callback: () => void): (() => void) => {\n window.addEventListener('consenti:consentSubmitted', callback)\n return () => window.removeEventListener('consenti:consentSubmitted', callback)\n },\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmEA,IAAI,UAAgC;AAS7B,SAAS,kBAAkB,QAA6B;AAC7D,YAAU;AACZ;AAeO,SAAS,gBAAgB;AAC9B,QAAM,WAAW,OAAO,WAAW;AAEnC,MAAI,UAAU;AACZ,WAAO;AAAA,MACL,YAAY,MAAM;AAAA,MAClB,YAAY,MAAM;AAAA,MAClB,eAAe,OAAO,aAAoC;AAAA,MAAC;AAAA,MAC3D,gBAAgB,MAAM;AAAA,MACtB,iBAAiB,CAAC,QAAoB,MAAM;AAAA,MAAC;AAAA,IAC/C;AAAA,EACF;AAEA,SAAO;AAAA;AAAA,IAEL,YAAY,MAAM,SAAS,WAAW,KAAK;AAAA;AAAA,IAG3C,YAAY,MAAM,SAAS,WAAW,KAAK;AAAA;AAAA,IAG3C,eAAe,CAAC,YACd,SAAS,cAAc,OAAO,KAAK,QAAQ,QAAQ;AAAA;AAAA,IAGrD,gBAAgB,MAAM,SAAS,eAAe,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAiBnD,iBAAiB,CAAC,aAAuC;AACvD,aAAO,iBAAiB,6BAA6B,QAAQ;AAC7D,aAAO,MAAM,OAAO,oBAAoB,6BAA6B,QAAQ;AAAA,IAC/E;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/angular.ts"],"sourcesContent":["/**\n * Angular integration for `@consenti/ui`.\n *\n * Import from the `@consenti/ui/angular` subpath to keep this module\n * tree-shaken out of vanilla JS, React, and Vue bundles.\n *\n * Designed for **Angular 15+** with standalone components or NgModule-based projects.\n * Initialise `ConsentiSetup` once (typically in `app.component.ts` or a root service)\n * and call `setConsentiWidget()` so that `injectConsent()` can read from it in any\n * component or service.\n *\n * @example\n * ```ts\n * // app.component.ts\n * import { Component, OnInit, OnDestroy } from '@angular/core'\n * import { ConsentiSetup } from '@consenti/ui'\n * import { setConsentiWidget } from '@consenti/ui/angular'\n *\n * @Component({ selector: 'app-root', template: '<router-outlet />' })\n * export class AppComponent implements OnInit, OnDestroy {\n * private widget!: ConsentiSetup\n *\n * ngOnInit() {\n * this.widget = new ConsentiSetup({\n * api: { enabled: true, baseUrl: environment.apiUrl },\n * })\n * setConsentiWidget(this.widget)\n * }\n *\n * ngOnDestroy() { this.widget.destroy() }\n * }\n *\n * // any-component.ts\n * import { Component, ChangeDetectorRef, OnInit, OnDestroy } from '@angular/core'\n * import { injectConsent } from '@consenti/ui/angular'\n *\n * @Component({\n * selector: 'app-cookie-status',\n * template: `\n * <p *ngIf=\"consent.hasConsent()\">Consent given on {{ consent.getConsentDate() | date }}</p>\n * <button *ngIf=\"!consent.hasConsent()\" (click)=\"consent.showModal()\">Manage Cookies</button>\n * `,\n * })\n * export class CookieStatusComponent implements OnInit, OnDestroy {\n * consent = injectConsent()\n * private unsub!: () => void\n *\n * constructor(private cdr: ChangeDetectorRef) {}\n *\n * ngOnInit() {\n * this.unsub = this.consent.onConsentChange(() => this.cdr.markForCheck())\n * }\n *\n * ngOnDestroy() { this.unsub() }\n * }\n * ```\n */\n\nimport type { ConsentValue } from './types'\nimport type { ConsentiSetup } from './core/consenti-setup'\n\n/**\n * Module-level singleton — the active `ConsentiSetup` instance.\n * Using a module-level variable keeps the integration zero-configuration:\n * no Angular injection token or `forRoot()` call is required.\n */\nlet _widget: ConsentiSetup | null = null\n\n/**\n * Registers the active `ConsentiSetup` instance so `injectConsent()` can read from it.\n * Call this once after creating your widget, typically in `AppComponent.ngOnInit()` or\n * a root-level Angular service.\n *\n * @param widget - The `ConsentiSetup` instance to register.\n */\nexport function setConsentiWidget(widget: ConsentiSetup): void {\n _widget = widget\n}\n\n/**\n * Returns a consent accessor object for use in Angular components and services.\n *\n * Unlike the React and Vue integrations, Angular uses its `ChangeDetectorRef` to\n * trigger UI updates rather than a reactive primitive. Use the `onConsentChange`,\n * `onBannerChange`, and `onModalChange` helpers in `ngOnInit` to subscribe and\n * call `cdr.markForCheck()` inside the callback.\n *\n * Returns SSR-safe fallback values when `window` is not defined (Angular Universal).\n *\n * @returns An object with state accessors, widget actions, and change-subscription helpers.\n */\nexport function injectConsent() {\n const isServer = typeof window === 'undefined'\n\n // ── SSR-safe fallback ──────────────────────────────────────────────────────\n if (isServer) {\n return {\n hasConsent: () => false as boolean,\n getConsent: () => null as ConsentValue | null,\n getConsentDate: () => false as Date | false,\n bannerVisibility: () => false as 'main' | 'gpc' | false,\n modalVisibility: () => false as 'preference' | false,\n showBanner: (_gpc?: boolean) => {},\n hideBanner: () => {},\n showModal: () => {},\n hideModal: () => {},\n grantAll: (_onlyMandatory?: boolean) => Promise.resolve(),\n denyAll: (_includingMandatory?: boolean) => Promise.resolve(),\n submitConsent: (_consent: Partial<ConsentValue>) => Promise.resolve(),\n reConsent: () => Promise.resolve(),\n isCookieGranted: (_id: string) => false as boolean,\n isCategoryGranted: (_id: string) => false as boolean,\n switchLocale: (_locale: string) => {},\n onConsentChange: (_cb: () => void) => () => {},\n onBannerChange: (_cb: () => void) => () => {},\n onModalChange: (_cb: () => void) => () => {},\n }\n }\n\n // ── Client ────────────────────────────────────────────────────────────────\n return {\n /** Returns `true` if the visitor has saved a valid consent record. */\n hasConsent: () => _widget?.hasConsent() ?? false,\n\n /** Returns the stored consent map, or `null`. */\n getConsent: () => _widget?.getConsent() ?? null,\n\n /** Returns the `Date` of the last consent submission, or `false`. */\n getConsentDate: () => _widget?.getConsentDate() ?? false,\n\n /** Returns the current banner state: `'main'`, `'gpc'`, or `false` (hidden). */\n bannerVisibility: () => _widget?.bannerVisibility() ?? (false as 'main' | 'gpc' | false),\n\n /** Returns the current modal state: `'preference'` or `false` (hidden). */\n modalVisibility: () => _widget?.modalVisibility() ?? (false as 'preference' | false),\n\n /** Shows the consent banner. Pass `true` to force the GPC variant. */\n showBanner: (gpc?: boolean) => _widget?.showBanner(gpc),\n\n /** Hides the consent banner. */\n hideBanner: () => _widget?.hideBanner(),\n\n /** Opens the preference modal. */\n showModal: () => _widget?.showModal(),\n\n /** Closes the preference modal. */\n hideModal: () => _widget?.hideModal(),\n\n /** Grants all non-mandatory cookies. Pass `true` to grant only mandatory ones and deny the rest. */\n grantAll: (onlyMandatory?: boolean) => _widget?.grantAll(onlyMandatory) ?? Promise.resolve(),\n\n /** Denies all non-mandatory cookies. Pass `true` to deny mandatory ones too (use with care). */\n denyAll: (includingMandatory?: boolean) => _widget?.denyAll(includingMandatory) ?? Promise.resolve(),\n\n /** Saves the given partial consent map. Missing cookie IDs default to their current stored value. */\n submitConsent: (consent: Partial<ConsentValue>) =>\n _widget?.submitConsent(consent) ?? Promise.resolve(),\n\n /** Deletes the current consent record and re-shows the banner. */\n reConsent: () => _widget?.reConsent() ?? Promise.resolve(),\n\n /** Returns `true` if the given cookie ID is `'granted'`. */\n isCookieGranted: (id: string) => (_widget?.isCookieGranted(id) ?? false) as boolean,\n\n /** Returns `true` if every cookie in the given category is `'granted'`. */\n isCategoryGranted: (id: string) => (_widget?.isCategoryGranted(id) ?? false) as boolean,\n\n /** Switches the active locale and re-renders the banner and modal. */\n switchLocale: (locale: string) => _widget?.switchLocale(locale),\n\n /**\n * Subscribes to consent change events. Call in `ngOnInit`; return value unsubscribes\n * in `ngOnDestroy`.\n *\n * @example\n * ```ts\n * ngOnInit() { this.unsub = this.consent.onConsentChange(() => this.cdr.markForCheck()) }\n * ngOnDestroy() { this.unsub() }\n * ```\n */\n onConsentChange: (callback: () => void): (() => void) => {\n window.addEventListener('consenti:consentSubmitted', callback)\n return () => window.removeEventListener('consenti:consentSubmitted', callback)\n },\n\n /**\n * Subscribes to banner visibility changes. Call in `ngOnInit`; return value unsubscribes\n * in `ngOnDestroy`.\n */\n onBannerChange: (callback: () => void): (() => void) => {\n window.addEventListener('consenti:bannerVisibility', callback)\n return () => window.removeEventListener('consenti:bannerVisibility', callback)\n },\n\n /**\n * Subscribes to modal visibility changes. Call in `ngOnInit`; return value unsubscribes\n * in `ngOnDestroy`.\n */\n onModalChange: (callback: () => void): (() => void) => {\n window.addEventListener('consenti:modalVisibility', callback)\n return () => window.removeEventListener('consenti:modalVisibility', callback)\n },\n }\n}\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,mBAAAE,EAAA,sBAAAC,IAAA,eAAAC,EAAAJ,GAkEA,IAAIK,EAAgC,KAS7B,SAASF,EAAkBG,EAA6B,CAC7DD,EAAUC,CACZ,CAcO,SAASJ,GAAgB,CAI9B,OAHiB,OAAO,OAAW,IAI1B,CACL,WAAc,IAAM,GACpB,WAAc,IAAM,KACpB,eAAgB,IAAM,GACtB,iBAAkB,IAAM,GACxB,gBAAkB,IAAM,GACxB,WAAeK,GAAmB,CAAC,EACnC,WAAc,IAAM,CAAC,EACrB,UAAc,IAAM,CAAC,EACrB,UAAc,IAAM,CAAC,EACrB,SAAeC,GAA6B,QAAQ,QAAQ,EAC5D,QAAeC,GAAkC,QAAQ,QAAQ,EACjE,cAAgBC,GAAoC,QAAQ,QAAQ,EACpE,UAAc,IAAM,QAAQ,QAAQ,EACpC,gBAAoBC,GAAgB,GACpC,kBAAoBA,GAAgB,GACpC,aAAeC,GAAoB,CAAC,EACpC,gBAAkBC,GAAoB,IAAM,CAAC,EAC7C,eAAkBA,GAAoB,IAAM,CAAC,EAC7C,cAAkBA,GAAoB,IAAM,CAAC,CAC/C,EAIK,CAEL,WAAY,IAAMR,GAAS,WAAW,GAAK,GAG3C,WAAY,IAAMA,GAAS,WAAW,GAAK,KAG3C,eAAgB,IAAMA,GAAS,eAAe,GAAK,GAGnD,iBAAkB,IAAMA,GAAS,iBAAiB,GAAM,GAGxD,gBAAiB,IAAMA,GAAS,gBAAgB,GAAM,GAGtD,WAAaS,GAAkBT,GAAS,WAAWS,CAAG,EAGtD,WAAY,IAAMT,GAAS,WAAW,EAGtC,UAAW,IAAMA,GAAS,UAAU,EAGpC,UAAW,IAAMA,GAAS,UAAU,EAGpC,SAAWU,GAA4BV,GAAS,SAASU,CAAa,GAAK,QAAQ,QAAQ,EAG3F,QAAUC,GAAiCX,GAAS,QAAQW,CAAkB,GAAK,QAAQ,QAAQ,EAGnG,cAAgBC,GACdZ,GAAS,cAAcY,CAAO,GAAK,QAAQ,QAAQ,EAGrD,UAAW,IAAMZ,GAAS,UAAU,GAAK,QAAQ,QAAQ,EAGzD,gBAAkBa,GAAgBb,GAAS,gBAAgBa,CAAE,GAAK,GAGlE,kBAAoBA,GAAgBb,GAAS,kBAAkBa,CAAE,GAAK,GAGtE,aAAeC,GAAmBd,GAAS,aAAac,CAAM,EAY9D,gBAAkBC,IAChB,OAAO,iBAAiB,4BAA6BA,CAAQ,EACtD,IAAM,OAAO,oBAAoB,4BAA6BA,CAAQ,GAO/E,eAAiBA,IACf,OAAO,iBAAiB,4BAA6BA,CAAQ,EACtD,IAAM,OAAO,oBAAoB,4BAA6BA,CAAQ,GAO/E,cAAgBA,IACd,OAAO,iBAAiB,2BAA4BA,CAAQ,EACrD,IAAM,OAAO,oBAAoB,2BAA4BA,CAAQ,EAEhF,CACF","names":["angular_exports","__export","injectConsent","setConsentiWidget","__toCommonJS","_widget","widget","_gpc","_onlyMandatory","_includingMandatory","_consent","_id","_locale","_cb","gpc","onlyMandatory","includingMandatory","consent","id","locale","callback"]}
package/dist/angular.mjs CHANGED
@@ -1,53 +1,2 @@
1
- // src/angular.ts
2
- var _widget = null;
3
- function setConsentiWidget(widget) {
4
- _widget = widget;
5
- }
6
- function injectConsent() {
7
- const isServer = typeof window === "undefined";
8
- if (isServer) {
9
- return {
10
- hasConsent: () => false,
11
- getConsent: () => null,
12
- submitConsent: async (_consent) => {
13
- },
14
- getConsentDate: () => false,
15
- onConsentChange: (_cb) => () => {
16
- }
17
- };
18
- }
19
- return {
20
- /** Returns `true` if the visitor has saved consent. */
21
- hasConsent: () => _widget?.hasConsent() ?? false,
22
- /** Returns the stored consent map, or `null`. */
23
- getConsent: () => _widget?.getConsent() ?? null,
24
- /** Saves the given partial consent map. Missing keys default to `'denied'`. */
25
- submitConsent: (consent) => _widget?.submitConsent(consent) ?? Promise.resolve(),
26
- /** Returns the `Date` of last consent submission, or `false`. */
27
- getConsentDate: () => _widget?.getConsentDate() ?? false,
28
- /**
29
- * Subscribes to consent change events and calls `callback` each time consent is
30
- * saved. Returns an unsubscribe function — call it in `ngOnDestroy` to avoid leaks.
31
- *
32
- * @param callback - Function to call when `consenti:consentSubmitted` fires.
33
- * @returns A no-arg teardown function.
34
- *
35
- * @example
36
- * ```ts
37
- * ngOnInit() {
38
- * this.unsub = this.consent.onConsentChange(() => this.cdr.markForCheck())
39
- * }
40
- * ngOnDestroy() { this.unsub() }
41
- * ```
42
- */
43
- onConsentChange: (callback) => {
44
- window.addEventListener("consenti:consentSubmitted", callback);
45
- return () => window.removeEventListener("consenti:consentSubmitted", callback);
46
- }
47
- };
48
- }
49
- export {
50
- injectConsent,
51
- setConsentiWidget
52
- };
1
+ var n=null;function i(o){n=o}function s(){return typeof window>"u"?{hasConsent:()=>!1,getConsent:()=>null,getConsentDate:()=>!1,bannerVisibility:()=>!1,modalVisibility:()=>!1,showBanner:e=>{},hideBanner:()=>{},showModal:()=>{},hideModal:()=>{},grantAll:e=>Promise.resolve(),denyAll:e=>Promise.resolve(),submitConsent:e=>Promise.resolve(),reConsent:()=>Promise.resolve(),isCookieGranted:e=>!1,isCategoryGranted:e=>!1,switchLocale:e=>{},onConsentChange:e=>()=>{},onBannerChange:e=>()=>{},onModalChange:e=>()=>{}}:{hasConsent:()=>n?.hasConsent()??!1,getConsent:()=>n?.getConsent()??null,getConsentDate:()=>n?.getConsentDate()??!1,bannerVisibility:()=>n?.bannerVisibility()??!1,modalVisibility:()=>n?.modalVisibility()??!1,showBanner:e=>n?.showBanner(e),hideBanner:()=>n?.hideBanner(),showModal:()=>n?.showModal(),hideModal:()=>n?.hideModal(),grantAll:e=>n?.grantAll(e)??Promise.resolve(),denyAll:e=>n?.denyAll(e)??Promise.resolve(),submitConsent:e=>n?.submitConsent(e)??Promise.resolve(),reConsent:()=>n?.reConsent()??Promise.resolve(),isCookieGranted:e=>n?.isCookieGranted(e)??!1,isCategoryGranted:e=>n?.isCategoryGranted(e)??!1,switchLocale:e=>n?.switchLocale(e),onConsentChange:e=>(window.addEventListener("consenti:consentSubmitted",e),()=>window.removeEventListener("consenti:consentSubmitted",e)),onBannerChange:e=>(window.addEventListener("consenti:bannerVisibility",e),()=>window.removeEventListener("consenti:bannerVisibility",e)),onModalChange:e=>(window.addEventListener("consenti:modalVisibility",e),()=>window.removeEventListener("consenti:modalVisibility",e))}}export{s as injectConsent,i as setConsentiWidget};
53
2
  //# sourceMappingURL=angular.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/angular.ts"],"sourcesContent":["/**\n * Angular integration for `@consenti/ui`.\n *\n * Import from the `@consenti/ui/angular` subpath to keep this module\n * tree-shaken out of vanilla JS, React, and Vue bundles.\n *\n * Designed for **Angular 15+** with standalone components or NgModule-based projects.\n * Initialise `ConsentiSetup` once (typically in `app.component.ts` or a root service)\n * and call `setConsentiWidget()` so that `injectConsent()` can read from it in any\n * component or service.\n *\n * @example\n * ```ts\n * // app.component.ts\n * import { Component, OnInit, OnDestroy } from '@angular/core'\n * import { ConsentiSetup } from '@consenti/ui'\n * import { setConsentiWidget } from '@consenti/ui/angular'\n *\n * @Component({ selector: 'app-root', template: '<router-outlet />' })\n * export class AppComponent implements OnInit, OnDestroy {\n * private widget!: ConsentiSetup\n *\n * ngOnInit() {\n * this.widget = new ConsentiSetup({ core: { profileId: 0 } })\n * setConsentiWidget(this.widget)\n * }\n *\n * ngOnDestroy() {\n * this.widget.destroy()\n * }\n * }\n *\n * // any-component.ts\n * import { Component, ChangeDetectorRef, OnInit, OnDestroy } from '@angular/core'\n * import { injectConsent } from '@consenti/ui/angular'\n *\n * @Component({ selector: 'app-cookie-status', template: `\n * <p *ngIf=\"consent.hasConsent()\">Consent given on {{ consent.getConsentDate() | date }}</p>\n * <button *ngIf=\"!consent.hasConsent()\" (click)=\"consent.submitConsent({ analytics_storage: 'granted' })\">\n * Accept Analytics\n * </button>\n * ` })\n * export class CookieStatusComponent implements OnInit, OnDestroy {\n * consent = injectConsent()\n * private unsub!: () => void\n *\n * constructor(private cdr: ChangeDetectorRef) {}\n *\n * ngOnInit() {\n * this.unsub = this.consent.onConsentChange(() => this.cdr.markForCheck())\n * }\n *\n * ngOnDestroy() {\n * this.unsub()\n * }\n * }\n * ```\n */\n\nimport type { ConsentValue } from './types'\nimport type { ConsentiSetup } from './core/consenti-setup'\n\n/**\n * Module-level singleton — the active `ConsentiSetup` instance.\n * Using a module-level variable keeps the integration zero-configuration:\n * no Angular injection token or `forRoot()` call is required.\n */\nlet _widget: ConsentiSetup | null = null\n\n/**\n * Registers the active `ConsentiSetup` instance so `injectConsent()` can read from it.\n * Call this once after creating your widget, typically in `AppComponent.ngOnInit()` or\n * a root-level Angular service.\n *\n * @param widget - The `ConsentiSetup` instance to register.\n */\nexport function setConsentiWidget(widget: ConsentiSetup): void {\n _widget = widget\n}\n\n/**\n * Returns a consent accessor object for use in Angular components and services.\n *\n * Unlike the React and Vue integrations, Angular uses its `ChangeDetectorRef` to\n * trigger UI updates rather than a reactive primitive. Call `onConsentChange()` in\n * `ngOnInit` to subscribe to consent changes and `cdr.markForCheck()` inside the\n * callback to schedule re-renders in `OnPush` components.\n *\n * Returns SSR-safe fallback values when `window` is not defined (Angular Universal).\n *\n * @returns An object with `hasConsent`, `getConsent`, `submitConsent`, `getConsentDate`,\n * and `onConsentChange` (subscription helper).\n */\nexport function injectConsent() {\n const isServer = typeof window === 'undefined'\n\n if (isServer) {\n return {\n hasConsent: () => false as boolean,\n getConsent: () => null as ConsentValue | null,\n submitConsent: async (_consent: Partial<ConsentValue>) => {},\n getConsentDate: () => false as Date | false,\n onConsentChange: (_cb: () => void) => () => {},\n }\n }\n\n return {\n /** Returns `true` if the visitor has saved consent. */\n hasConsent: () => _widget?.hasConsent() ?? false,\n\n /** Returns the stored consent map, or `null`. */\n getConsent: () => _widget?.getConsent() ?? null,\n\n /** Saves the given partial consent map. Missing keys default to `'denied'`. */\n submitConsent: (consent: Partial<ConsentValue>) =>\n _widget?.submitConsent(consent) ?? Promise.resolve(),\n\n /** Returns the `Date` of last consent submission, or `false`. */\n getConsentDate: () => _widget?.getConsentDate() ?? false,\n\n /**\n * Subscribes to consent change events and calls `callback` each time consent is\n * saved. Returns an unsubscribe function — call it in `ngOnDestroy` to avoid leaks.\n *\n * @param callback - Function to call when `consenti:consentSubmitted` fires.\n * @returns A no-arg teardown function.\n *\n * @example\n * ```ts\n * ngOnInit() {\n * this.unsub = this.consent.onConsentChange(() => this.cdr.markForCheck())\n * }\n * ngOnDestroy() { this.unsub() }\n * ```\n */\n onConsentChange: (callback: () => void): (() => void) => {\n window.addEventListener('consenti:consentSubmitted', callback)\n return () => window.removeEventListener('consenti:consentSubmitted', callback)\n },\n }\n}\n"],"mappings":";AAmEA,IAAI,UAAgC;AAS7B,SAAS,kBAAkB,QAA6B;AAC7D,YAAU;AACZ;AAeO,SAAS,gBAAgB;AAC9B,QAAM,WAAW,OAAO,WAAW;AAEnC,MAAI,UAAU;AACZ,WAAO;AAAA,MACL,YAAY,MAAM;AAAA,MAClB,YAAY,MAAM;AAAA,MAClB,eAAe,OAAO,aAAoC;AAAA,MAAC;AAAA,MAC3D,gBAAgB,MAAM;AAAA,MACtB,iBAAiB,CAAC,QAAoB,MAAM;AAAA,MAAC;AAAA,IAC/C;AAAA,EACF;AAEA,SAAO;AAAA;AAAA,IAEL,YAAY,MAAM,SAAS,WAAW,KAAK;AAAA;AAAA,IAG3C,YAAY,MAAM,SAAS,WAAW,KAAK;AAAA;AAAA,IAG3C,eAAe,CAAC,YACd,SAAS,cAAc,OAAO,KAAK,QAAQ,QAAQ;AAAA;AAAA,IAGrD,gBAAgB,MAAM,SAAS,eAAe,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAiBnD,iBAAiB,CAAC,aAAuC;AACvD,aAAO,iBAAiB,6BAA6B,QAAQ;AAC7D,aAAO,MAAM,OAAO,oBAAoB,6BAA6B,QAAQ;AAAA,IAC/E;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/angular.ts"],"sourcesContent":["/**\n * Angular integration for `@consenti/ui`.\n *\n * Import from the `@consenti/ui/angular` subpath to keep this module\n * tree-shaken out of vanilla JS, React, and Vue bundles.\n *\n * Designed for **Angular 15+** with standalone components or NgModule-based projects.\n * Initialise `ConsentiSetup` once (typically in `app.component.ts` or a root service)\n * and call `setConsentiWidget()` so that `injectConsent()` can read from it in any\n * component or service.\n *\n * @example\n * ```ts\n * // app.component.ts\n * import { Component, OnInit, OnDestroy } from '@angular/core'\n * import { ConsentiSetup } from '@consenti/ui'\n * import { setConsentiWidget } from '@consenti/ui/angular'\n *\n * @Component({ selector: 'app-root', template: '<router-outlet />' })\n * export class AppComponent implements OnInit, OnDestroy {\n * private widget!: ConsentiSetup\n *\n * ngOnInit() {\n * this.widget = new ConsentiSetup({\n * api: { enabled: true, baseUrl: environment.apiUrl },\n * })\n * setConsentiWidget(this.widget)\n * }\n *\n * ngOnDestroy() { this.widget.destroy() }\n * }\n *\n * // any-component.ts\n * import { Component, ChangeDetectorRef, OnInit, OnDestroy } from '@angular/core'\n * import { injectConsent } from '@consenti/ui/angular'\n *\n * @Component({\n * selector: 'app-cookie-status',\n * template: `\n * <p *ngIf=\"consent.hasConsent()\">Consent given on {{ consent.getConsentDate() | date }}</p>\n * <button *ngIf=\"!consent.hasConsent()\" (click)=\"consent.showModal()\">Manage Cookies</button>\n * `,\n * })\n * export class CookieStatusComponent implements OnInit, OnDestroy {\n * consent = injectConsent()\n * private unsub!: () => void\n *\n * constructor(private cdr: ChangeDetectorRef) {}\n *\n * ngOnInit() {\n * this.unsub = this.consent.onConsentChange(() => this.cdr.markForCheck())\n * }\n *\n * ngOnDestroy() { this.unsub() }\n * }\n * ```\n */\n\nimport type { ConsentValue } from './types'\nimport type { ConsentiSetup } from './core/consenti-setup'\n\n/**\n * Module-level singleton — the active `ConsentiSetup` instance.\n * Using a module-level variable keeps the integration zero-configuration:\n * no Angular injection token or `forRoot()` call is required.\n */\nlet _widget: ConsentiSetup | null = null\n\n/**\n * Registers the active `ConsentiSetup` instance so `injectConsent()` can read from it.\n * Call this once after creating your widget, typically in `AppComponent.ngOnInit()` or\n * a root-level Angular service.\n *\n * @param widget - The `ConsentiSetup` instance to register.\n */\nexport function setConsentiWidget(widget: ConsentiSetup): void {\n _widget = widget\n}\n\n/**\n * Returns a consent accessor object for use in Angular components and services.\n *\n * Unlike the React and Vue integrations, Angular uses its `ChangeDetectorRef` to\n * trigger UI updates rather than a reactive primitive. Use the `onConsentChange`,\n * `onBannerChange`, and `onModalChange` helpers in `ngOnInit` to subscribe and\n * call `cdr.markForCheck()` inside the callback.\n *\n * Returns SSR-safe fallback values when `window` is not defined (Angular Universal).\n *\n * @returns An object with state accessors, widget actions, and change-subscription helpers.\n */\nexport function injectConsent() {\n const isServer = typeof window === 'undefined'\n\n // ── SSR-safe fallback ──────────────────────────────────────────────────────\n if (isServer) {\n return {\n hasConsent: () => false as boolean,\n getConsent: () => null as ConsentValue | null,\n getConsentDate: () => false as Date | false,\n bannerVisibility: () => false as 'main' | 'gpc' | false,\n modalVisibility: () => false as 'preference' | false,\n showBanner: (_gpc?: boolean) => {},\n hideBanner: () => {},\n showModal: () => {},\n hideModal: () => {},\n grantAll: (_onlyMandatory?: boolean) => Promise.resolve(),\n denyAll: (_includingMandatory?: boolean) => Promise.resolve(),\n submitConsent: (_consent: Partial<ConsentValue>) => Promise.resolve(),\n reConsent: () => Promise.resolve(),\n isCookieGranted: (_id: string) => false as boolean,\n isCategoryGranted: (_id: string) => false as boolean,\n switchLocale: (_locale: string) => {},\n onConsentChange: (_cb: () => void) => () => {},\n onBannerChange: (_cb: () => void) => () => {},\n onModalChange: (_cb: () => void) => () => {},\n }\n }\n\n // ── Client ────────────────────────────────────────────────────────────────\n return {\n /** Returns `true` if the visitor has saved a valid consent record. */\n hasConsent: () => _widget?.hasConsent() ?? false,\n\n /** Returns the stored consent map, or `null`. */\n getConsent: () => _widget?.getConsent() ?? null,\n\n /** Returns the `Date` of the last consent submission, or `false`. */\n getConsentDate: () => _widget?.getConsentDate() ?? false,\n\n /** Returns the current banner state: `'main'`, `'gpc'`, or `false` (hidden). */\n bannerVisibility: () => _widget?.bannerVisibility() ?? (false as 'main' | 'gpc' | false),\n\n /** Returns the current modal state: `'preference'` or `false` (hidden). */\n modalVisibility: () => _widget?.modalVisibility() ?? (false as 'preference' | false),\n\n /** Shows the consent banner. Pass `true` to force the GPC variant. */\n showBanner: (gpc?: boolean) => _widget?.showBanner(gpc),\n\n /** Hides the consent banner. */\n hideBanner: () => _widget?.hideBanner(),\n\n /** Opens the preference modal. */\n showModal: () => _widget?.showModal(),\n\n /** Closes the preference modal. */\n hideModal: () => _widget?.hideModal(),\n\n /** Grants all non-mandatory cookies. Pass `true` to grant only mandatory ones and deny the rest. */\n grantAll: (onlyMandatory?: boolean) => _widget?.grantAll(onlyMandatory) ?? Promise.resolve(),\n\n /** Denies all non-mandatory cookies. Pass `true` to deny mandatory ones too (use with care). */\n denyAll: (includingMandatory?: boolean) => _widget?.denyAll(includingMandatory) ?? Promise.resolve(),\n\n /** Saves the given partial consent map. Missing cookie IDs default to their current stored value. */\n submitConsent: (consent: Partial<ConsentValue>) =>\n _widget?.submitConsent(consent) ?? Promise.resolve(),\n\n /** Deletes the current consent record and re-shows the banner. */\n reConsent: () => _widget?.reConsent() ?? Promise.resolve(),\n\n /** Returns `true` if the given cookie ID is `'granted'`. */\n isCookieGranted: (id: string) => (_widget?.isCookieGranted(id) ?? false) as boolean,\n\n /** Returns `true` if every cookie in the given category is `'granted'`. */\n isCategoryGranted: (id: string) => (_widget?.isCategoryGranted(id) ?? false) as boolean,\n\n /** Switches the active locale and re-renders the banner and modal. */\n switchLocale: (locale: string) => _widget?.switchLocale(locale),\n\n /**\n * Subscribes to consent change events. Call in `ngOnInit`; return value unsubscribes\n * in `ngOnDestroy`.\n *\n * @example\n * ```ts\n * ngOnInit() { this.unsub = this.consent.onConsentChange(() => this.cdr.markForCheck()) }\n * ngOnDestroy() { this.unsub() }\n * ```\n */\n onConsentChange: (callback: () => void): (() => void) => {\n window.addEventListener('consenti:consentSubmitted', callback)\n return () => window.removeEventListener('consenti:consentSubmitted', callback)\n },\n\n /**\n * Subscribes to banner visibility changes. Call in `ngOnInit`; return value unsubscribes\n * in `ngOnDestroy`.\n */\n onBannerChange: (callback: () => void): (() => void) => {\n window.addEventListener('consenti:bannerVisibility', callback)\n return () => window.removeEventListener('consenti:bannerVisibility', callback)\n },\n\n /**\n * Subscribes to modal visibility changes. Call in `ngOnInit`; return value unsubscribes\n * in `ngOnDestroy`.\n */\n onModalChange: (callback: () => void): (() => void) => {\n window.addEventListener('consenti:modalVisibility', callback)\n return () => window.removeEventListener('consenti:modalVisibility', callback)\n },\n }\n}\n"],"mappings":"AAkEA,IAAIA,EAAgC,KAS7B,SAASC,EAAkBC,EAA6B,CAC7DF,EAAUE,CACZ,CAcO,SAASC,GAAgB,CAI9B,OAHiB,OAAO,OAAW,IAI1B,CACL,WAAc,IAAM,GACpB,WAAc,IAAM,KACpB,eAAgB,IAAM,GACtB,iBAAkB,IAAM,GACxB,gBAAkB,IAAM,GACxB,WAAeC,GAAmB,CAAC,EACnC,WAAc,IAAM,CAAC,EACrB,UAAc,IAAM,CAAC,EACrB,UAAc,IAAM,CAAC,EACrB,SAAeC,GAA6B,QAAQ,QAAQ,EAC5D,QAAeC,GAAkC,QAAQ,QAAQ,EACjE,cAAgBC,GAAoC,QAAQ,QAAQ,EACpE,UAAc,IAAM,QAAQ,QAAQ,EACpC,gBAAoBC,GAAgB,GACpC,kBAAoBA,GAAgB,GACpC,aAAeC,GAAoB,CAAC,EACpC,gBAAkBC,GAAoB,IAAM,CAAC,EAC7C,eAAkBA,GAAoB,IAAM,CAAC,EAC7C,cAAkBA,GAAoB,IAAM,CAAC,CAC/C,EAIK,CAEL,WAAY,IAAMV,GAAS,WAAW,GAAK,GAG3C,WAAY,IAAMA,GAAS,WAAW,GAAK,KAG3C,eAAgB,IAAMA,GAAS,eAAe,GAAK,GAGnD,iBAAkB,IAAMA,GAAS,iBAAiB,GAAM,GAGxD,gBAAiB,IAAMA,GAAS,gBAAgB,GAAM,GAGtD,WAAaW,GAAkBX,GAAS,WAAWW,CAAG,EAGtD,WAAY,IAAMX,GAAS,WAAW,EAGtC,UAAW,IAAMA,GAAS,UAAU,EAGpC,UAAW,IAAMA,GAAS,UAAU,EAGpC,SAAWY,GAA4BZ,GAAS,SAASY,CAAa,GAAK,QAAQ,QAAQ,EAG3F,QAAUC,GAAiCb,GAAS,QAAQa,CAAkB,GAAK,QAAQ,QAAQ,EAGnG,cAAgBC,GACdd,GAAS,cAAcc,CAAO,GAAK,QAAQ,QAAQ,EAGrD,UAAW,IAAMd,GAAS,UAAU,GAAK,QAAQ,QAAQ,EAGzD,gBAAkBe,GAAgBf,GAAS,gBAAgBe,CAAE,GAAK,GAGlE,kBAAoBA,GAAgBf,GAAS,kBAAkBe,CAAE,GAAK,GAGtE,aAAeC,GAAmBhB,GAAS,aAAagB,CAAM,EAY9D,gBAAkBC,IAChB,OAAO,iBAAiB,4BAA6BA,CAAQ,EACtD,IAAM,OAAO,oBAAoB,4BAA6BA,CAAQ,GAO/E,eAAiBA,IACf,OAAO,iBAAiB,4BAA6BA,CAAQ,EACtD,IAAM,OAAO,oBAAoB,4BAA6BA,CAAQ,GAO/E,cAAgBA,IACd,OAAO,iBAAiB,2BAA4BA,CAAQ,EACrD,IAAM,OAAO,oBAAoB,2BAA4BA,CAAQ,EAEhF,CACF","names":["_widget","setConsentiWidget","widget","injectConsent","_gpc","_onlyMandatory","_includingMandatory","_consent","_id","_locale","_cb","gpc","onlyMandatory","includingMandatory","consent","id","locale","callback"]}
@@ -0,0 +1,2 @@
1
+ async function i(e,s={},n){let r={"Content-Type":"application/json",...s.headers};n&&(r.Authorization=`Bearer ${n}`);let t=await fetch(e,{...s,headers:r});if(!t.ok)throw new Error(`[Consenti] HTTP ${t.status} ${t.statusText} \u2014 ${e}`);return t.json()}export{i as a};
2
+ //# sourceMappingURL=chunk-K2UN3O67.mjs.map