@justeattakeaway/pie-cookie-banner 0.2.0 → 0.3.1

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/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { CSSResult } from 'lit';
2
2
  import type { LitElement } from 'lit';
3
- import type { TemplateResult } from 'lit-html';
3
+ import { PieToggleSwitch } from '@justeattakeaway/pie-toggle-switch';
4
+ import type { TemplateResult } from 'lit';
4
5
 
5
6
  export declare interface CookieBannerProps {
6
7
  }
@@ -17,7 +18,7 @@ export declare const ON_COOKIE_BANNER_ACCEPT_ALL = "pie-cookie-banner-accept-all
17
18
  *
18
19
  * @constant
19
20
  */
20
- export declare const ON_COOKIE_BANNER_MANAGE_PREFS = "pie-cookie-manage-prefs";
21
+ export declare const ON_COOKIE_BANNER_MANAGE_PREFS = "pie-cookie-banner-manage-prefs";
21
22
 
22
23
  /**
23
24
  * Event name for when all only necessary cookies are accepted.
@@ -26,16 +27,23 @@ export declare const ON_COOKIE_BANNER_MANAGE_PREFS = "pie-cookie-manage-prefs";
26
27
  */
27
28
  export declare const ON_COOKIE_BANNER_NECESSARY_ONLY = "pie-cookie-banner-necessary-only";
28
29
 
30
+ /**
31
+ * Event name for when a user clicks save preferences.
32
+ *
33
+ * @constant
34
+ */
35
+ export declare const ON_COOKIE_BANNER_PREFS_SAVED = "pie-cookie-banner-prefs-saved";
36
+
29
37
  /**
30
38
  * @event {CustomEvent} pie-cookie-banner-accept-all - when all cookies are accepted.
31
39
  * @event {CustomEvent} pie-cookie-banner-necessary-only - when all only necessary cookies are accepted.
32
- * @event {CustomEvent} pie-cookie-manage-prefs - when a user clicks manage preferences.
40
+ * @event {CustomEvent} pie-cookie-banner-manage-prefs - when a user clicks manage preferences.
41
+ * @event {CustomEvent} pie-cookie-banner-prefs-saved - when a user clicks save preferences.
33
42
  */
34
43
  export declare class PieCookieBanner extends LitElement implements CookieBannerProps {
35
44
  private _isCookieBannerHidden;
36
45
  private _isModalOpen;
37
- connectedCallback(): void;
38
- disconnectedCallback(): void;
46
+ _preferencesNodes: NodeListOf<PieToggleSwitch>;
39
47
  /**
40
48
  * Handles closing the modal and re-displaying the cookie banner
41
49
  * and making the cookie banner visible
@@ -43,6 +51,12 @@ export declare class PieCookieBanner extends LitElement implements CookieBannerP
43
51
  private _displayCookieBanner;
44
52
  /**
45
53
  * Handles saving the user cookie preferences, closing the modal and the cookie banner
54
+ * Creates a state object for the save event, indicating the isChecked status
55
+ * of each preference except for the `all` preference.
56
+ * @example {
57
+ * functional: false,
58
+ * necessary: true
59
+ * }
46
60
  */
47
61
  private _handlePreferencesSaved;
48
62
  /**
@@ -55,14 +69,47 @@ export declare class PieCookieBanner extends LitElement implements CookieBannerP
55
69
  * bubble up through the cookie banner.
56
70
  *
57
71
  * @param {string} eventType
72
+ * @param {any} detail
58
73
  */
59
74
  private _dispatchCookieBannerCustomEvent;
60
75
  /**
61
76
  * Opens the manage preferences modal and emits an event letting users know
62
77
  */
63
78
  private _openManagePreferencesModal;
79
+ /**
80
+ * Handles the logic of the toggle switch nodes (preferences).
81
+ * Clicking the “all” toggle switch should turn on all preferences.
82
+ * When the “all” toggle is checked, and one of the other preferences is clicked,
83
+ * then the “all” toggle should be unchecked.
84
+ * if all toggle switches are checked, the `all` toggle switch should
85
+ * be turned on automatically
86
+ */
87
+ private _handleToggleStates;
88
+ /**
89
+ * Renders the content of the preference item.
90
+ * @private
91
+ */
92
+ private renderPreference;
93
+ /**
94
+ * Renders the modal content.
95
+ * @private
96
+ */
97
+ private renderModalContent;
64
98
  render(): TemplateResult<1>;
65
99
  static styles: CSSResult;
66
100
  }
67
101
 
102
+ export declare interface Preference {
103
+ id: PreferenceIds;
104
+ title: string;
105
+ description?: string;
106
+ isDisabled?: boolean;
107
+ isChecked?: boolean;
108
+ hasDivider?: boolean;
109
+ }
110
+
111
+ export declare type PreferenceIds = 'all' | 'necessary' | 'functional' | 'analytical' | 'personalized';
112
+
113
+ export declare const preferences: Preference[];
114
+
68
115
  export { }
package/dist/index.js CHANGED
@@ -1,31 +1,64 @@
1
- import { unsafeCSS as l, LitElement as p, html as h } from "lit";
2
- import { state as c } from "lit/decorators.js";
3
- const b = `*{margin:0}.c-cookieBanner{--cb-font-family: var(--dt-font-interactive-m-family);--cb-font-size: calc(var(--dt-font-body-l-size) * 1px);--cb-line-height: calc(var(--dt-font-body-l-line-height) * 1px);--cb-font-weight: var(--dt-font-body-l-weight);--cb-padding-inline: var(--dt-spacing-d);--cb-padding-block: var(--dt-spacing-d);--cb-offset: 0;color-scheme:only dark;background-color:var(--dt-color-background-dark);color:var(--dt-color-content-inverse);font-family:var(--cb-font-family);font-size:var(--cb-font-size);line-height:var(--cb-line-height);font-weight:var(--cb-font-weight);padding-block-start:var(--cb-padding-block);padding-block-end:var(--cb-padding-block);max-height:432px;position:fixed;bottom:var(--cb-offset);left:var(--cb-offset);right:var(--cb-offset);border-top-left-radius:var(--dt-radius-rounded-c);border-top-right-radius:var(--dt-radius-rounded-c)}@media (min-width: 700px) and (orientation: landscape){.c-cookieBanner{--cb-padding-inline: var(--dt-spacing-f);--cb-offset: var(--dt-spacing-d);max-height:90%;border-bottom-left-radius:var(--dt-radius-rounded-c);border-bottom-right-radius:var(--dt-radius-rounded-c)}}.c-cookieBanner[isCookieBannerHidden]{display:none}.c-cookieBanner-title,.c-cookieBanner-body,.c-cookieBanner-actions{padding-inline-start:var(--cb-padding-inline);padding-inline-end:var(--cb-padding-inline)}.c-cookieBanner-title{--cb-title-font-size: var(--dt-font-heading-s-size--narrow);--cb-title-line-height: var(--dt-font-heading-s-line-height--narrow);font-size:calc(var(--cb-title-font-size) * 1px);font-weight:var(--dt-font-heading-s-weight);line-height:calc(var(--cb-title-line-height) * 1px)}@media (min-width: 700px) and (orientation: landscape){.c-cookieBanner-title{--cb-title-font-size: var(--dt-font-heading-s-size--wide);--cb-title-line-height: var(--dt-font-heading-s-line-height--wide)}}.c-cookieBanner-body{--cb-scroll-shadow-color: var(--dt-color-black);margin-block-start:var(--dt-spacing-a);max-height:200px;overflow-y:auto;background:linear-gradient(to bottom,transparent,var(--dt-color-background-dark) 75%) center bottom,linear-gradient(transparent,var(--cb-scroll-shadow-color)) center bottom;background-repeat:no-repeat;background-size:100% 48px,100% 8px;background-attachment:local,scroll}@media (min-width: 700px) and (orientation: landscape){.c-cookieBanner-body{max-height:150px}}.c-cookieBanner-actions{--cb-actions-flex-dir: column;margin-block-start:var(--dt-spacing-d);display:flex;gap:var(--dt-spacing-d);flex-direction:var(--cb-actions-flex-dir)}.c-cookieBanner-actions>pie-link{width:max-content;margin-inline-start:auto;margin-inline-end:auto}@media (min-width: 700px) and (orientation: landscape){.c-cookieBanner-actions{--cb-actions-flex-dir: row-reverse;justify-content:flex-start;align-items:center}.c-cookieBanner-actions>pie-link{margin-inline-start:0;margin-inline-end:0}}
4
- `, v = "pie-cookie-banner-accept-all", k = "pie-cookie-banner-necessary-only", g = "pie-cookie-manage-prefs";
5
- var f = Object.defineProperty, m = Object.getOwnPropertyDescriptor, d = (o, e, n, a) => {
6
- for (var i = a > 1 ? void 0 : a ? m(e, n) : e, r = o.length - 1, s; r >= 0; r--)
7
- (s = o[r]) && (i = (a ? s(e, n, i) : s(i)) || i);
8
- return a && i && f(e, n, i), i;
1
+ import { unsafeCSS as p, LitElement as g, html as r, nothing as l } from "lit";
2
+ import { state as h, queryAll as f } from "lit/decorators.js";
3
+ import { repeat as b } from "lit/directives/repeat.js";
4
+ const k = `*{margin:0}.c-cookieBanner{--cb-font-family: var(--dt-font-interactive-m-family);--cb-font-size: calc(var(--dt-font-body-l-size) * 1px);--cb-line-height: calc(var(--dt-font-body-l-line-height) * 1px);--cb-font-weight: var(--dt-font-body-l-weight);--cb-padding-inline: var(--dt-spacing-d);--cb-padding-block: var(--dt-spacing-d);--cb-offset: 0;color-scheme:only dark;background-color:var(--dt-color-background-dark);color:var(--dt-color-content-inverse);font-family:var(--cb-font-family);font-size:var(--cb-font-size);line-height:var(--cb-line-height);font-weight:var(--cb-font-weight);padding-block-start:var(--cb-padding-block);padding-block-end:var(--cb-padding-block);max-height:432px;position:fixed;bottom:var(--cb-offset);left:var(--cb-offset);right:var(--cb-offset);border-top-left-radius:var(--dt-radius-rounded-c);border-top-right-radius:var(--dt-radius-rounded-c)}@media (min-width: 700px) and (orientation: landscape){.c-cookieBanner{--cb-padding-inline: var(--dt-spacing-f);--cb-offset: var(--dt-spacing-d);max-height:90%;border-bottom-left-radius:var(--dt-radius-rounded-c);border-bottom-right-radius:var(--dt-radius-rounded-c)}}.c-cookieBanner[isCookieBannerHidden]{display:none}.c-cookieBanner-title,.c-cookieBanner-body,.c-cookieBanner-actions{padding-inline-start:var(--cb-padding-inline);padding-inline-end:var(--cb-padding-inline)}.c-cookieBanner-title{--cb-title-font-size: var(--dt-font-heading-s-size--narrow);--cb-title-line-height: var(--dt-font-heading-s-line-height--narrow);font-size:calc(var(--cb-title-font-size) * 1px);font-weight:var(--dt-font-heading-s-weight);line-height:calc(var(--cb-title-line-height) * 1px)}@media (min-width: 700px) and (orientation: landscape){.c-cookieBanner-title{--cb-title-font-size: var(--dt-font-heading-s-size--wide);--cb-title-line-height: var(--dt-font-heading-s-line-height--wide)}}.c-cookieBanner-body{--cb-scroll-shadow-color: var(--dt-color-black);margin-block-start:var(--dt-spacing-a);max-height:200px;overflow-y:auto;background:linear-gradient(to bottom,transparent,var(--dt-color-background-dark) 75%) center bottom,linear-gradient(transparent,var(--cb-scroll-shadow-color)) center bottom;background-repeat:no-repeat;background-size:100% 48px,100% 8px;background-attachment:local,scroll}@media (min-width: 700px) and (orientation: landscape){.c-cookieBanner-body{max-height:150px}}.c-cookieBanner-actions{--cb-actions-flex-dir: column;margin-block-start:var(--dt-spacing-d);display:flex;gap:var(--dt-spacing-d);flex-direction:var(--cb-actions-flex-dir)}.c-cookieBanner-actions>pie-link{text-align:center;align-self:center}@media (min-width: 700px) and (orientation: landscape){.c-cookieBanner-actions{--cb-actions-flex-dir: row-reverse;justify-content:flex-start;align-items:center}}.c-cookieBanner-subheading{--cb-subheading-font-size: var(--dt-font-heading-s-size--narrow);--cb-subheading-line-height: var(--dt-font-heading-s-line-height--narrow);font-size:calc(var(--cb-subheading-font-size) * 1px);font-weight:var(--dt-font-heading-s-weight);line-height:calc(var(--cb-subheading-line-height) * 1px)}@media (min-width: 700px) and (orientation: landscape){.c-cookieBanner-subheading{--cb-subheading-font-size: var(--dt-font-heading-s-size--wide);--cb-subheading-line-height: var(--dt-font-heading-s-line-height--wide)}}.c-cookieBanner-description{font-size:calc(var(--dt-font-body-s-size) * 1px);line-height:calc(var(--dt-font-body-s-line-height) * 1px)}.c-cookieBanner-preference{display:flex;gap:var(--dt-spacing-d);justify-content:space-between;margin-block:var(--dt-spacing-e)}.c-cookieBanner-preference p{margin-block-start:var(--dt-spacing-b)}.c-cookieBanner-preference:last-child{margin-block-end:0}
5
+ `, v = "pie-cookie-banner-accept-all", u = "pie-cookie-banner-necessary-only", m = "pie-cookie-banner-manage-prefs", y = "pie-cookie-banner-prefs-saved", _ = [
6
+ {
7
+ id: "all",
8
+ title: "Turn on all",
9
+ hasDivider: !0
10
+ },
11
+ {
12
+ id: "necessary",
13
+ title: "Necessary",
14
+ description: "These cookies are necessary to ensure that the website and its features function properly. Services you have asked for cannot be provided without these cookies.",
15
+ isDisabled: !0,
16
+ isChecked: !0
17
+ },
18
+ {
19
+ id: "functional",
20
+ title: "Functional",
21
+ description: "These cookies allow the website to remember the choices you make to give you better functionality and personal features."
22
+ },
23
+ {
24
+ id: "analytical",
25
+ title: "Analytical",
26
+ description: "These analytical cookies, including statistics, are used to understand how visitors interact with the website and we can measure and improve the performance of our website."
27
+ },
28
+ {
29
+ id: "personalized",
30
+ title: "Personalized (targeting and advertising)",
31
+ description: "These marketing cookies are used to tailor the delivery of information to you based upon your interest and to measure the effectiveness of such advertisements, both on our website and our advertising partners' websites."
32
+ }
33
+ ];
34
+ var B = Object.defineProperty, w = Object.getOwnPropertyDescriptor, d = (c, e, t, n) => {
35
+ for (var i = n > 1 ? void 0 : n ? w(e, t) : e, a = c.length - 1, o; a >= 0; a--)
36
+ (o = c[a]) && (i = (n ? o(e, t, i) : o(i)) || i);
37
+ return n && i && B(e, t, i), i;
9
38
  };
10
- const u = "pie-cookie-banner";
11
- class t extends p {
39
+ const C = "pie-cookie-banner";
40
+ class s extends g {
12
41
  constructor() {
13
- super(...arguments), this._isCookieBannerHidden = !1, this._isModalOpen = !1, this._dispatchCookieBannerCustomEvent = (e) => {
42
+ super(...arguments), this._isCookieBannerHidden = !1, this._isModalOpen = !1, this._dispatchCookieBannerCustomEvent = (e, t) => {
14
43
  const n = new CustomEvent(e, {
15
44
  bubbles: !0,
16
- composed: !0
45
+ composed: !0,
46
+ detail: t
17
47
  });
18
48
  this.dispatchEvent(n);
19
49
  }, this._openManagePreferencesModal = () => {
20
- this._isCookieBannerHidden = !0, this._dispatchCookieBannerCustomEvent(g), this._isModalOpen = !0;
50
+ this._isCookieBannerHidden = !0, this._dispatchCookieBannerCustomEvent(m), this._isModalOpen = !0;
51
+ }, this._handleToggleStates = (e) => {
52
+ const { id: t } = e == null ? void 0 : e.currentTarget, n = [...this._preferencesNodes].find(({ id: i }) => i === "all");
53
+ if (t === n.id) {
54
+ const i = e.detail;
55
+ this._preferencesNodes.forEach((a) => {
56
+ a.isChecked = a.isDisabled ? a.isChecked : i;
57
+ });
58
+ } else
59
+ n.isChecked = [...this._preferencesNodes].filter(({ id: i }) => i !== "all").every(({ isChecked: i }) => i);
21
60
  };
22
61
  }
23
- connectedCallback() {
24
- super.connectedCallback(), document.addEventListener("pie-modal-back", this._displayCookieBanner.bind(this)), document.addEventListener("pie-modal-leading-action-click", this._handlePreferencesSaved.bind(this));
25
- }
26
- disconnectedCallback() {
27
- document.removeEventListener("pie-modal-back", this._displayCookieBanner.bind(this)), document.removeEventListener("pie-modal-leading-action-click", this._handlePreferencesSaved.bind(this)), super.disconnectedCallback();
28
- }
29
62
  /**
30
63
  * Handles closing the modal and re-displaying the cookie banner
31
64
  * and making the cookie banner visible
@@ -35,9 +68,60 @@ class t extends p {
35
68
  }
36
69
  /**
37
70
  * Handles saving the user cookie preferences, closing the modal and the cookie banner
71
+ * Creates a state object for the save event, indicating the isChecked status
72
+ * of each preference except for the `all` preference.
73
+ * @example {
74
+ * functional: false,
75
+ * necessary: true
76
+ * }
38
77
  */
39
78
  _handlePreferencesSaved() {
40
- this._isModalOpen = !1, this._isCookieBannerHidden = !0, console.info("Cookie Preferences saved");
79
+ let e = {};
80
+ [...this._preferencesNodes].filter(({ id: t }) => t !== "all").forEach(({ id: t, isChecked: n }) => {
81
+ e = { ...e, [t]: n };
82
+ }), this._dispatchCookieBannerCustomEvent(y, e), this._isModalOpen = !1, this._isCookieBannerHidden = !0;
83
+ }
84
+ /**
85
+ * Renders the content of the preference item.
86
+ * @private
87
+ */
88
+ renderPreference({
89
+ id: e,
90
+ title: t,
91
+ description: n,
92
+ isChecked: i,
93
+ isDisabled: a,
94
+ hasDivider: o
95
+ }) {
96
+ return r`
97
+ <div class="c-cookieBanner-preference">
98
+ <div>
99
+ <h3 class="c-cookieBanner-subheading">${t}</h3>
100
+ ${n ? r`<p class="c-cookieBanner-description">${n}</p>` : l}
101
+ </div>
102
+ <pie-toggle-switch
103
+ id="${e}"
104
+ ?isChecked="${i}"
105
+ ?isDisabled="${a}"
106
+ @pie-toggle-switch-changed="${this._handleToggleStates}"/>
107
+ </div>
108
+ ${o ? r`<pie-divider></pie-divider>` : l}`;
109
+ }
110
+ /**
111
+ * Renders the modal content.
112
+ * @private
113
+ */
114
+ renderModalContent() {
115
+ return r`
116
+ <p class="c-cookieBanner-description">You can find all the information in the
117
+ <pie-link href="#" size="small" target="_blank">Cookie Statement</pie-link> and
118
+ <pie-link href="#" size="small" target="_blank">Cookie technology list</pie-link>.
119
+ </p>
120
+ ${b(
121
+ _,
122
+ ({ id: e }) => e,
123
+ (e) => this.renderPreference(e)
124
+ )}`;
41
125
  }
42
126
  render() {
43
127
  const e = {
@@ -45,15 +129,18 @@ class t extends p {
45
129
  variant: "primary",
46
130
  ariaLabel: "Save your cookie preferences"
47
131
  };
48
- return h`
132
+ return r`
49
133
  <pie-modal
50
134
  .isOpen="${this._isModalOpen}"
51
135
  hasBackButton
52
136
  hasStackedActions
53
- size="large"
137
+ isFullWidthBelowMid
54
138
  heading="Manage your preferences"
55
139
  .leadingAction="${e}"
56
- ></pie-modal>
140
+ @pie-modal-leading-action-click="${this._handlePreferencesSaved}"
141
+ @pie-modal-back="${this._displayCookieBanner}">
142
+ ${this.renderModalContent()}
143
+ </pie-modal>
57
144
  <aside data-test-id="pie-cookie-banner" class="c-cookieBanner" ?isCookieBannerHidden=${this._isCookieBannerHidden}>
58
145
  <h2 class="c-cookieBanner-title">Cookies</h2>
59
146
  <div class="c-cookieBanner-body">
@@ -79,7 +166,7 @@ class t extends p {
79
166
  <pie-button
80
167
  data-test-id="necessary-only"
81
168
  @click="${() => {
82
- this._dispatchCookieBannerCustomEvent(k), this._isCookieBannerHidden = !0;
169
+ this._dispatchCookieBannerCustomEvent(u), this._isCookieBannerHidden = !0;
83
170
  }}"
84
171
  variant="outline-inverse"
85
172
  isFullWidth
@@ -88,7 +175,7 @@ class t extends p {
88
175
  </pie-button>
89
176
  <pie-link
90
177
  data-test-id="manage-prefs"
91
- @click="${() => this._openManagePreferencesModal()}"
178
+ @click="${this._openManagePreferencesModal}"
92
179
  tag="button"
93
180
  variant="inverse"
94
181
  isBold="true">
@@ -98,17 +185,22 @@ class t extends p {
98
185
  </aside>`;
99
186
  }
100
187
  }
101
- t.styles = l(b);
188
+ s.styles = p(k);
189
+ d([
190
+ h()
191
+ ], s.prototype, "_isCookieBannerHidden", 2);
102
192
  d([
103
- c()
104
- ], t.prototype, "_isCookieBannerHidden", 2);
193
+ h()
194
+ ], s.prototype, "_isModalOpen", 2);
105
195
  d([
106
- c()
107
- ], t.prototype, "_isModalOpen", 2);
108
- customElements.define(u, t);
196
+ f("pie-toggle-switch")
197
+ ], s.prototype, "_preferencesNodes", 2);
198
+ customElements.define(C, s);
109
199
  export {
110
200
  v as ON_COOKIE_BANNER_ACCEPT_ALL,
111
- g as ON_COOKIE_BANNER_MANAGE_PREFS,
112
- k as ON_COOKIE_BANNER_NECESSARY_ONLY,
113
- t as PieCookieBanner
201
+ m as ON_COOKIE_BANNER_MANAGE_PREFS,
202
+ u as ON_COOKIE_BANNER_NECESSARY_ONLY,
203
+ y as ON_COOKIE_BANNER_PREFS_SAVED,
204
+ s as PieCookieBanner,
205
+ _ as preferences
114
206
  };
package/dist/react.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import type { CSSResult } from 'lit';
2
2
  import type { EventName } from '@lit-labs/react';
3
3
  import type { LitElement } from 'lit';
4
+ import { PieToggleSwitch } from '@justeattakeaway/pie-toggle-switch';
4
5
  import type { ReactWebComponent } from '@lit-labs/react';
5
- import type { TemplateResult } from 'lit-html';
6
+ import type { TemplateResult } from 'lit';
6
7
 
7
8
  export declare interface CookieBannerProps {
8
9
  }
@@ -19,7 +20,7 @@ export declare const ON_COOKIE_BANNER_ACCEPT_ALL = "pie-cookie-banner-accept-all
19
20
  *
20
21
  * @constant
21
22
  */
22
- export declare const ON_COOKIE_BANNER_MANAGE_PREFS = "pie-cookie-manage-prefs";
23
+ export declare const ON_COOKIE_BANNER_MANAGE_PREFS = "pie-cookie-banner-manage-prefs";
23
24
 
24
25
  /**
25
26
  * Event name for when all only necessary cookies are accepted.
@@ -28,22 +29,30 @@ export declare const ON_COOKIE_BANNER_MANAGE_PREFS = "pie-cookie-manage-prefs";
28
29
  */
29
30
  export declare const ON_COOKIE_BANNER_NECESSARY_ONLY = "pie-cookie-banner-necessary-only";
30
31
 
32
+ /**
33
+ * Event name for when a user clicks save preferences.
34
+ *
35
+ * @constant
36
+ */
37
+ export declare const ON_COOKIE_BANNER_PREFS_SAVED = "pie-cookie-banner-prefs-saved";
38
+
31
39
  export declare const PieCookieBanner: ReactWebComponent<PieCookieBanner_2, {
32
40
  onPieCookieBannerAcceptAll: EventName<CustomEvent<any>>;
33
41
  onPieCookieBannerNecessaryOnly: EventName<CustomEvent<any>>;
34
- onPieCookieManagePrefs: EventName<CustomEvent<any>>;
42
+ onPieCookieBannerManagePrefs: EventName<CustomEvent<any>>;
43
+ onPieCookieBannerPrefsSaved: EventName<CustomEvent<any>>;
35
44
  }>;
36
45
 
37
46
  /**
38
47
  * @event {CustomEvent} pie-cookie-banner-accept-all - when all cookies are accepted.
39
48
  * @event {CustomEvent} pie-cookie-banner-necessary-only - when all only necessary cookies are accepted.
40
- * @event {CustomEvent} pie-cookie-manage-prefs - when a user clicks manage preferences.
49
+ * @event {CustomEvent} pie-cookie-banner-manage-prefs - when a user clicks manage preferences.
50
+ * @event {CustomEvent} pie-cookie-banner-prefs-saved - when a user clicks save preferences.
41
51
  */
42
52
  declare class PieCookieBanner_2 extends LitElement implements CookieBannerProps {
43
53
  private _isCookieBannerHidden;
44
54
  private _isModalOpen;
45
- connectedCallback(): void;
46
- disconnectedCallback(): void;
55
+ _preferencesNodes: NodeListOf<PieToggleSwitch>;
47
56
  /**
48
57
  * Handles closing the modal and re-displaying the cookie banner
49
58
  * and making the cookie banner visible
@@ -51,6 +60,12 @@ declare class PieCookieBanner_2 extends LitElement implements CookieBannerProps
51
60
  private _displayCookieBanner;
52
61
  /**
53
62
  * Handles saving the user cookie preferences, closing the modal and the cookie banner
63
+ * Creates a state object for the save event, indicating the isChecked status
64
+ * of each preference except for the `all` preference.
65
+ * @example {
66
+ * functional: false,
67
+ * necessary: true
68
+ * }
54
69
  */
55
70
  private _handlePreferencesSaved;
56
71
  /**
@@ -63,14 +78,47 @@ declare class PieCookieBanner_2 extends LitElement implements CookieBannerProps
63
78
  * bubble up through the cookie banner.
64
79
  *
65
80
  * @param {string} eventType
81
+ * @param {any} detail
66
82
  */
67
83
  private _dispatchCookieBannerCustomEvent;
68
84
  /**
69
85
  * Opens the manage preferences modal and emits an event letting users know
70
86
  */
71
87
  private _openManagePreferencesModal;
88
+ /**
89
+ * Handles the logic of the toggle switch nodes (preferences).
90
+ * Clicking the “all” toggle switch should turn on all preferences.
91
+ * When the “all” toggle is checked, and one of the other preferences is clicked,
92
+ * then the “all” toggle should be unchecked.
93
+ * if all toggle switches are checked, the `all` toggle switch should
94
+ * be turned on automatically
95
+ */
96
+ private _handleToggleStates;
97
+ /**
98
+ * Renders the content of the preference item.
99
+ * @private
100
+ */
101
+ private renderPreference;
102
+ /**
103
+ * Renders the modal content.
104
+ * @private
105
+ */
106
+ private renderModalContent;
72
107
  render(): TemplateResult<1>;
73
108
  static styles: CSSResult;
74
109
  }
75
110
 
111
+ export declare interface Preference {
112
+ id: PreferenceIds;
113
+ title: string;
114
+ description?: string;
115
+ isDisabled?: boolean;
116
+ isChecked?: boolean;
117
+ hasDivider?: boolean;
118
+ }
119
+
120
+ export declare type PreferenceIds = 'all' | 'necessary' | 'functional' | 'analytical' | 'personalized';
121
+
122
+ export declare const preferences: Preference[];
123
+
76
124
  export { }
package/dist/react.js CHANGED
@@ -1,38 +1,39 @@
1
- import * as _ from "react";
1
+ import * as O from "react";
2
2
  import { PieCookieBanner as k } from "./index.js";
3
- import { ON_COOKIE_BANNER_ACCEPT_ALL as M, ON_COOKIE_BANNER_MANAGE_PREFS as S, ON_COOKIE_BANNER_NECESSARY_ONLY as x } from "./index.js";
3
+ import { ON_COOKIE_BANNER_ACCEPT_ALL as M, ON_COOKIE_BANNER_MANAGE_PREFS as I, ON_COOKIE_BANNER_NECESSARY_ONLY as K, ON_COOKIE_BANNER_PREFS_SAVED as x, preferences as D } from "./index.js";
4
4
  import "lit";
5
5
  import "lit/decorators.js";
6
+ import "lit/directives/repeat.js";
6
7
  /**
7
8
  * @license
8
9
  * Copyright 2018 Google LLC
9
10
  * SPDX-License-Identifier: BSD-3-Clause
10
11
  */
11
- const O = /* @__PURE__ */ new Set(["children", "localName", "ref", "style", "className"]), y = /* @__PURE__ */ new WeakMap(), A = (p, r, d, m, h) => {
12
- const o = h == null ? void 0 : h[r];
13
- o === void 0 || d === m ? d == null && r in HTMLElement.prototype ? p.removeAttribute(r) : p[r] = d : ((i, n, N) => {
14
- let s = y.get(i);
15
- s === void 0 && y.set(i, s = /* @__PURE__ */ new Map());
12
+ const y = /* @__PURE__ */ new Set(["children", "localName", "ref", "style", "className"]), _ = /* @__PURE__ */ new WeakMap(), A = (p, r, d, m, N) => {
13
+ const t = N == null ? void 0 : N[r];
14
+ t === void 0 || d === m ? d == null && r in HTMLElement.prototype ? p.removeAttribute(r) : p[r] = d : ((i, n, h) => {
15
+ let s = _.get(i);
16
+ s === void 0 && _.set(i, s = /* @__PURE__ */ new Map());
16
17
  let a = s.get(n);
17
- N !== void 0 ? a === void 0 ? (s.set(n, a = { handleEvent: N }), i.addEventListener(n, a)) : a.handleEvent = N : a !== void 0 && (s.delete(n), i.removeEventListener(n, a));
18
- })(p, o, d);
18
+ h !== void 0 ? a === void 0 ? (s.set(n, a = { handleEvent: h }), i.addEventListener(n, a)) : a.handleEvent = h : a !== void 0 && (s.delete(n), i.removeEventListener(n, a));
19
+ })(p, t, d);
19
20
  };
20
- function P(p = window.React, r, d, m, h) {
21
- let o, i, n;
21
+ function P(p = window.React, r, d, m, N) {
22
+ let t, i, n;
22
23
  if (r === void 0) {
23
24
  const l = p;
24
- ({ tagName: i, elementClass: n, events: m, displayName: h } = l), o = l.react;
25
+ ({ tagName: i, elementClass: n, events: m, displayName: N } = l), t = l.react;
25
26
  } else
26
- o = p, n = d, i = r;
27
- const N = o.Component, s = o.createElement, a = new Set(Object.keys(m ?? {}));
28
- class f extends N {
27
+ t = p, n = d, i = r;
28
+ const h = t.Component, s = t.createElement, a = new Set(Object.keys(m ?? {}));
29
+ class u extends h {
29
30
  constructor() {
30
31
  super(...arguments), this.o = null;
31
32
  }
32
33
  t(e) {
33
34
  if (this.o !== null)
34
- for (const u in this.i)
35
- A(this.o, u, this.props[u], e ? e[u] : void 0, m);
35
+ for (const f in this.i)
36
+ A(this.o, f, this.props[f], e ? e[f] : void 0, m);
36
37
  }
37
38
  componentDidMount() {
38
39
  this.t();
@@ -41,39 +42,43 @@ function P(p = window.React, r, d, m, h) {
41
42
  this.t(e);
42
43
  }
43
44
  render() {
44
- const { _$Gl: e, ...u } = this.props;
45
- this.h !== e && (this.u = (t) => {
45
+ const { _$Gl: e, ...f } = this.props;
46
+ this.h !== e && (this.u = (o) => {
46
47
  e !== null && ((c, C) => {
47
48
  typeof c == "function" ? c(C) : c.current = C;
48
- })(e, t), this.o = t, this.h = e;
49
+ })(e, o), this.o = o, this.h = e;
49
50
  }), this.i = {};
50
- const v = { ref: this.u };
51
- for (const [t, c] of Object.entries(u))
52
- O.has(t) ? v[t === "className" ? "class" : t] = c : a.has(t) || t in n.prototype ? this.i[t] = c : v[t] = c;
53
- return s(i, v);
51
+ const E = { ref: this.u };
52
+ for (const [o, c] of Object.entries(f))
53
+ y.has(o) ? E[o === "className" ? "class" : o] = c : a.has(o) || o in n.prototype ? this.i[o] = c : E[o] = c;
54
+ return s(i, E);
54
55
  }
55
56
  }
56
- f.displayName = h ?? n.name;
57
- const E = o.forwardRef((l, e) => s(f, { ...l, _$Gl: e }, l == null ? void 0 : l.children));
58
- return E.displayName = f.displayName, E;
57
+ u.displayName = N ?? n.name;
58
+ const v = t.forwardRef((l, e) => s(u, { ...l, _$Gl: e }, l == null ? void 0 : l.children));
59
+ return v.displayName = u.displayName, v;
59
60
  }
60
- const w = P({
61
+ const g = P({
61
62
  displayName: "PieCookieBanner",
62
63
  elementClass: k,
63
- react: _,
64
+ react: O,
64
65
  tagName: "pie-cookie-banner",
65
66
  events: {
66
67
  onPieCookieBannerAcceptAll: "pie-cookie-banner-accept-all",
67
68
  // when all cookies are accepted.
68
69
  onPieCookieBannerNecessaryOnly: "pie-cookie-banner-necessary-only",
69
70
  // when all only necessary cookies are accepted.
70
- onPieCookieManagePrefs: "pie-cookie-manage-prefs"
71
+ onPieCookieBannerManagePrefs: "pie-cookie-banner-manage-prefs",
71
72
  // when a user clicks manage preferences.
73
+ onPieCookieBannerPrefsSaved: "pie-cookie-banner-prefs-saved"
74
+ // when a user clicks save preferences.
72
75
  }
73
76
  });
74
77
  export {
75
78
  M as ON_COOKIE_BANNER_ACCEPT_ALL,
76
- S as ON_COOKIE_BANNER_MANAGE_PREFS,
77
- x as ON_COOKIE_BANNER_NECESSARY_ONLY,
78
- w as PieCookieBanner
79
+ I as ON_COOKIE_BANNER_MANAGE_PREFS,
80
+ K as ON_COOKIE_BANNER_NECESSARY_ONLY,
81
+ x as ON_COOKIE_BANNER_PREFS_SAVED,
82
+ g as PieCookieBanner,
83
+ D as preferences
79
84
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@justeattakeaway/pie-cookie-banner",
3
3
  "description": "PIE Design System Cookie Banner built using Web Components",
4
- "version": "0.2.0",
4
+ "version": "0.3.1",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
@@ -28,11 +28,13 @@
28
28
  "author": "JustEatTakeaway.com - Design System Web Team",
29
29
  "license": "Apache-2.0",
30
30
  "devDependencies": {
31
- "@justeattakeaway/pie-button": "0.27.0",
31
+ "@justeat/pie-design-tokens": "5.7.0",
32
+ "@justeattakeaway/pie-button": "0.28.1",
32
33
  "@justeattakeaway/pie-components-config": "0.4.0",
33
- "@justeattakeaway/pie-icon-button": "0.14.0",
34
+ "@justeattakeaway/pie-icon-button": "0.14.1",
34
35
  "@justeattakeaway/pie-link": "0.3.0",
35
- "@justeattakeaway/pie-modal": "0.19.0"
36
+ "@justeattakeaway/pie-modal": "0.19.1",
37
+ "@justeattakeaway/pie-toggle-switch": "0.7.0"
36
38
  },
37
39
  "dependencies": {
38
40
  "@justeattakeaway/pie-webc-core": "0.8.0"
@@ -105,9 +105,8 @@ $breakpoint-wide: 700px;
105
105
  flex-direction: var(--cb-actions-flex-dir);
106
106
 
107
107
  > pie-link {
108
- width: max-content;
109
- margin-inline-start: auto;
110
- margin-inline-end: auto;
108
+ text-align: center;
109
+ align-self: center;
111
110
  }
112
111
 
113
112
  @media (min-width: $breakpoint-wide) and (orientation: landscape) {
@@ -115,10 +114,39 @@ $breakpoint-wide: 700px;
115
114
 
116
115
  justify-content: flex-start;
117
116
  align-items: center;
117
+ }
118
+ }
119
+
120
+ .c-cookieBanner-subheading {
121
+ --cb-subheading-font-size: var(--dt-font-heading-s-size--narrow);
122
+ --cb-subheading-line-height: var(--dt-font-heading-s-line-height--narrow);
123
+
124
+ @include p.font-size(--cb-subheading-font-size);
125
+ font-weight: var(--dt-font-heading-s-weight);
126
+ line-height: calc(var(--cb-subheading-line-height) * 1px);
127
+
128
+ @media (min-width: $breakpoint-wide) and (orientation: landscape) {
129
+ --cb-subheading-font-size: var(--dt-font-heading-s-size--wide);
130
+ --cb-subheading-line-height: var(--dt-font-heading-s-line-height--wide);
131
+ }
132
+ }
133
+
134
+ .c-cookieBanner-description {
135
+ @include p.font-size(--dt-font-body-s-size);
136
+ line-height: calc(var(--dt-font-body-s-line-height) * 1px);
137
+ }
138
+
139
+ .c-cookieBanner-preference {
140
+ display: flex;
141
+ gap: var(--dt-spacing-d);
142
+ justify-content: space-between;
143
+ margin-block: var(--dt-spacing-e);
144
+
145
+ p {
146
+ margin-block-start: var(--dt-spacing-b);
147
+ }
118
148
 
119
- > pie-link {
120
- margin-inline-start: 0;
121
- margin-inline-end: 0;
122
- }
149
+ &:last-child {
150
+ margin-block-end: 0;
123
151
  }
124
152
  }
package/src/defs.ts CHANGED
@@ -21,4 +21,52 @@ export const ON_COOKIE_BANNER_NECESSARY_ONLY = 'pie-cookie-banner-necessary-only
21
21
  *
22
22
  * @constant
23
23
  */
24
- export const ON_COOKIE_BANNER_MANAGE_PREFS = 'pie-cookie-manage-prefs';
24
+ export const ON_COOKIE_BANNER_MANAGE_PREFS = 'pie-cookie-banner-manage-prefs';
25
+
26
+ /**
27
+ * Event name for when a user clicks save preferences.
28
+ *
29
+ * @constant
30
+ */
31
+ export const ON_COOKIE_BANNER_PREFS_SAVED = 'pie-cookie-banner-prefs-saved';
32
+
33
+ export type PreferenceIds = 'all' | 'necessary' | 'functional' | 'analytical' | 'personalized';
34
+
35
+ export interface Preference {
36
+ id: PreferenceIds;
37
+ title: string;
38
+ description?: string;
39
+ isDisabled?: boolean,
40
+ isChecked?: boolean,
41
+ hasDivider?: boolean
42
+ }
43
+
44
+ export const preferences: Preference[] = [
45
+ {
46
+ id: 'all',
47
+ title: 'Turn on all',
48
+ hasDivider: true,
49
+ },
50
+ {
51
+ id: 'necessary',
52
+ title: 'Necessary',
53
+ description: 'These cookies are necessary to ensure that the website and its features function properly. Services you have asked for cannot be provided without these cookies.',
54
+ isDisabled: true,
55
+ isChecked: true,
56
+ },
57
+ {
58
+ id: 'functional',
59
+ title: 'Functional',
60
+ description: 'These cookies allow the website to remember the choices you make to give you better functionality and personal features.',
61
+ },
62
+ {
63
+ id: 'analytical',
64
+ title: 'Analytical',
65
+ description: 'These analytical cookies, including statistics, are used to understand how visitors interact with the website and we can measure and improve the performance of our website.',
66
+ },
67
+ {
68
+ id: 'personalized',
69
+ title: 'Personalized (targeting and advertising)',
70
+ description: 'These marketing cookies are used to tailor the delivery of information to you based upon your interest and to measure the effectiveness of such advertisements, both on our website and our advertising partners\' websites.',
71
+ }
72
+ ];
package/src/index.ts CHANGED
@@ -1,13 +1,19 @@
1
1
  import {
2
- LitElement, html, unsafeCSS,
2
+ LitElement, html, unsafeCSS, TemplateResult, nothing,
3
3
  } from 'lit';
4
- import { state } from 'lit/decorators.js';
4
+ import { state, queryAll } from 'lit/decorators.js';
5
+ import { repeat } from 'lit/directives/repeat.js';
6
+ import { PieToggleSwitch } from '@justeattakeaway/pie-toggle-switch';
5
7
  import styles from './cookie-banner.scss?inline';
6
8
  import {
7
9
  CookieBannerProps,
8
10
  ON_COOKIE_BANNER_ACCEPT_ALL,
9
11
  ON_COOKIE_BANNER_NECESSARY_ONLY,
10
12
  ON_COOKIE_BANNER_MANAGE_PREFS,
13
+ ON_COOKIE_BANNER_PREFS_SAVED,
14
+ preferences,
15
+ type Preference,
16
+ type PreferenceIds,
11
17
  } from './defs';
12
18
 
13
19
  // Valid values available to consumers
@@ -18,7 +24,8 @@ const componentSelector = 'pie-cookie-banner';
18
24
  /**
19
25
  * @event {CustomEvent} pie-cookie-banner-accept-all - when all cookies are accepted.
20
26
  * @event {CustomEvent} pie-cookie-banner-necessary-only - when all only necessary cookies are accepted.
21
- * @event {CustomEvent} pie-cookie-manage-prefs - when a user clicks manage preferences.
27
+ * @event {CustomEvent} pie-cookie-banner-manage-prefs - when a user clicks manage preferences.
28
+ * @event {CustomEvent} pie-cookie-banner-prefs-saved - when a user clicks save preferences.
22
29
  */
23
30
  export class PieCookieBanner extends LitElement implements CookieBannerProps {
24
31
  @state()
@@ -27,17 +34,8 @@ export class PieCookieBanner extends LitElement implements CookieBannerProps {
27
34
  @state()
28
35
  private _isModalOpen = false;
29
36
 
30
- connectedCallback () : void {
31
- super.connectedCallback();
32
- document.addEventListener('pie-modal-back', this._displayCookieBanner.bind(this));
33
- document.addEventListener('pie-modal-leading-action-click', this._handlePreferencesSaved.bind(this));
34
- }
35
-
36
- disconnectedCallback () : void {
37
- document.removeEventListener('pie-modal-back', this._displayCookieBanner.bind(this));
38
- document.removeEventListener('pie-modal-leading-action-click', this._handlePreferencesSaved.bind(this));
39
- super.disconnectedCallback();
40
- }
37
+ @queryAll('pie-toggle-switch')
38
+ _preferencesNodes!: NodeListOf<PieToggleSwitch>;
41
39
 
42
40
  /**
43
41
  * Handles closing the modal and re-displaying the cookie banner
@@ -50,11 +48,25 @@ export class PieCookieBanner extends LitElement implements CookieBannerProps {
50
48
 
51
49
  /**
52
50
  * Handles saving the user cookie preferences, closing the modal and the cookie banner
51
+ * Creates a state object for the save event, indicating the isChecked status
52
+ * of each preference except for the `all` preference.
53
+ * @example {
54
+ * functional: false,
55
+ * necessary: true
56
+ * }
53
57
  */
54
58
  private _handlePreferencesSaved () : void {
59
+ let state: Partial<{ [x in PreferenceIds]: boolean }> = {};
60
+
61
+ [...this._preferencesNodes]
62
+ .filter(({ id }) => id !== 'all')
63
+ .forEach(({ id, isChecked }) => {
64
+ state = { ...state, [id]: isChecked };
65
+ });
66
+
67
+ this._dispatchCookieBannerCustomEvent(ON_COOKIE_BANNER_PREFS_SAVED, state);
55
68
  this._isModalOpen = false;
56
69
  this._isCookieBannerHidden = true;
57
- console.info('Cookie Preferences saved');
58
70
  }
59
71
 
60
72
  /**
@@ -67,11 +79,13 @@ export class PieCookieBanner extends LitElement implements CookieBannerProps {
67
79
  * bubble up through the cookie banner.
68
80
  *
69
81
  * @param {string} eventType
82
+ * @param {any} detail
70
83
  */
71
- private _dispatchCookieBannerCustomEvent = (eventType: string) : void => {
84
+ private _dispatchCookieBannerCustomEvent = (eventType: string, detail?: CustomEventInit['detail']) : void => {
72
85
  const event = new CustomEvent(eventType, {
73
86
  bubbles: true,
74
87
  composed: true,
88
+ detail,
75
89
  });
76
90
 
77
91
  this.dispatchEvent(event);
@@ -86,6 +100,69 @@ export class PieCookieBanner extends LitElement implements CookieBannerProps {
86
100
  this._isModalOpen = true;
87
101
  };
88
102
 
103
+ /**
104
+ * Handles the logic of the toggle switch nodes (preferences).
105
+ * Clicking the “all” toggle switch should turn on all preferences.
106
+ * When the “all” toggle is checked, and one of the other preferences is clicked,
107
+ * then the “all” toggle should be unchecked.
108
+ * if all toggle switches are checked, the `all` toggle switch should
109
+ * be turned on automatically
110
+ */
111
+ private _handleToggleStates = (e: CustomEvent) : void => {
112
+ const { id } = e?.currentTarget as HTMLInputElement;
113
+ const toggleAllNode = [...this._preferencesNodes].find(({ id }) => id === 'all') as PieToggleSwitch;
114
+
115
+ if (id === toggleAllNode.id) {
116
+ const isChecked = e.detail;
117
+ this._preferencesNodes.forEach((node) => {
118
+ node.isChecked = node.isDisabled ? node.isChecked : isChecked;
119
+ });
120
+ } else {
121
+ toggleAllNode.isChecked = [...this._preferencesNodes]
122
+ .filter(({ id }) => id !== 'all')
123
+ .every(({ isChecked }) => isChecked);
124
+ }
125
+ };
126
+
127
+ /**
128
+ * Renders the content of the preference item.
129
+ * @private
130
+ */
131
+ private renderPreference ({
132
+ id, title, description, isChecked, isDisabled, hasDivider,
133
+ }: Preference): TemplateResult {
134
+ return html`
135
+ <div class="c-cookieBanner-preference">
136
+ <div>
137
+ <h3 class="c-cookieBanner-subheading">${title}</h3>
138
+ ${description ? html`<p class="c-cookieBanner-description">${description}</p>` : nothing}
139
+ </div>
140
+ <pie-toggle-switch
141
+ id="${id}"
142
+ ?isChecked="${isChecked}"
143
+ ?isDisabled="${isDisabled}"
144
+ @pie-toggle-switch-changed="${this._handleToggleStates}"/>
145
+ </div>
146
+ ${hasDivider ? html`<pie-divider></pie-divider>` : nothing}`;
147
+ }
148
+
149
+ /**
150
+ * Renders the modal content.
151
+ * @private
152
+ */
153
+ private renderModalContent (): TemplateResult {
154
+ return html`
155
+ <p class="c-cookieBanner-description">You can find all the information in the
156
+ <pie-link href="#" size="small" target="_blank">Cookie Statement</pie-link> and
157
+ <pie-link href="#" size="small" target="_blank">Cookie technology list</pie-link>.
158
+ </p>
159
+ ${repeat(
160
+ preferences,
161
+ ({ id }) => id,
162
+ (preference) => this.renderPreference(preference),
163
+ )}`;
164
+ }
165
+
89
166
  render () {
90
167
  const modalActionProps = {
91
168
  text: 'Save',
@@ -98,10 +175,13 @@ export class PieCookieBanner extends LitElement implements CookieBannerProps {
98
175
  .isOpen="${this._isModalOpen}"
99
176
  hasBackButton
100
177
  hasStackedActions
101
- size="large"
178
+ isFullWidthBelowMid
102
179
  heading="Manage your preferences"
103
180
  .leadingAction="${modalActionProps}"
104
- ></pie-modal>
181
+ @pie-modal-leading-action-click="${this._handlePreferencesSaved}"
182
+ @pie-modal-back="${this._displayCookieBanner}">
183
+ ${this.renderModalContent()}
184
+ </pie-modal>
105
185
  <aside data-test-id="pie-cookie-banner" class="c-cookieBanner" ?isCookieBannerHidden=${this._isCookieBannerHidden}>
106
186
  <h2 class="c-cookieBanner-title">Cookies</h2>
107
187
  <div class="c-cookieBanner-body">
@@ -132,7 +212,7 @@ export class PieCookieBanner extends LitElement implements CookieBannerProps {
132
212
  </pie-button>
133
213
  <pie-link
134
214
  data-test-id="manage-prefs"
135
- @click="${() => this._openManagePreferencesModal()}"
215
+ @click="${this._openManagePreferencesModal}"
136
216
  tag="button"
137
217
  variant="inverse"
138
218
  isBold="true">