@justeattakeaway/pie-cookie-banner 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +103 -1
- package/dist/index.js +182 -12
- package/dist/react.d.ts +110 -2
- package/dist/react.js +53 -36
- package/package.json +6 -3
- package/src/cookie-banner.scss +39 -7
- package/src/defs.ts +69 -0
- package/src/index.ts +193 -7
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,115 @@
|
|
|
1
1
|
import type { CSSResult } from 'lit';
|
|
2
2
|
import type { LitElement } from 'lit';
|
|
3
|
-
import
|
|
3
|
+
import { PieToggleSwitch } from '@justeattakeaway/pie-toggle-switch';
|
|
4
|
+
import type { TemplateResult } from 'lit';
|
|
4
5
|
|
|
5
6
|
export declare interface CookieBannerProps {
|
|
6
7
|
}
|
|
7
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Event name for when all cookies are accepted.
|
|
11
|
+
*
|
|
12
|
+
* @constant
|
|
13
|
+
*/
|
|
14
|
+
export declare const ON_COOKIE_BANNER_ACCEPT_ALL = "pie-cookie-banner-accept-all";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Event name for when a user clicks manage preferences.
|
|
18
|
+
*
|
|
19
|
+
* @constant
|
|
20
|
+
*/
|
|
21
|
+
export declare const ON_COOKIE_BANNER_MANAGE_PREFS = "pie-cookie-banner-manage-prefs";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Event name for when all only necessary cookies are accepted.
|
|
25
|
+
*
|
|
26
|
+
* @constant
|
|
27
|
+
*/
|
|
28
|
+
export declare const ON_COOKIE_BANNER_NECESSARY_ONLY = "pie-cookie-banner-necessary-only";
|
|
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
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @event {CustomEvent} pie-cookie-banner-accept-all - when all cookies are accepted.
|
|
39
|
+
* @event {CustomEvent} pie-cookie-banner-necessary-only - when all only necessary cookies are accepted.
|
|
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.
|
|
42
|
+
*/
|
|
8
43
|
export declare class PieCookieBanner extends LitElement implements CookieBannerProps {
|
|
44
|
+
private _isCookieBannerHidden;
|
|
45
|
+
private _isModalOpen;
|
|
46
|
+
_preferencesNodes: NodeListOf<PieToggleSwitch>;
|
|
47
|
+
/**
|
|
48
|
+
* Handles closing the modal and re-displaying the cookie banner
|
|
49
|
+
* and making the cookie banner visible
|
|
50
|
+
*/
|
|
51
|
+
private _displayCookieBanner;
|
|
52
|
+
/**
|
|
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
|
+
* }
|
|
60
|
+
*/
|
|
61
|
+
private _handlePreferencesSaved;
|
|
62
|
+
/**
|
|
63
|
+
* Note: We should aim to have a shareable event helper system to allow
|
|
64
|
+
* us to share this across components in-future.
|
|
65
|
+
*
|
|
66
|
+
* Dispatch a custom event.
|
|
67
|
+
*
|
|
68
|
+
* To be used whenever we have behavioral events we want to
|
|
69
|
+
* bubble up through the cookie banner.
|
|
70
|
+
*
|
|
71
|
+
* @param {string} eventType
|
|
72
|
+
* @param {any} detail
|
|
73
|
+
*/
|
|
74
|
+
private _dispatchCookieBannerCustomEvent;
|
|
75
|
+
/**
|
|
76
|
+
* Opens the manage preferences modal and emits an event letting users know
|
|
77
|
+
*/
|
|
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;
|
|
9
98
|
render(): TemplateResult<1>;
|
|
10
99
|
static styles: CSSResult;
|
|
11
100
|
}
|
|
12
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
|
+
|
|
13
115
|
export { }
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,147 @@
|
|
|
1
|
-
import { unsafeCSS as
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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;
|
|
38
|
+
};
|
|
39
|
+
const C = "pie-cookie-banner";
|
|
40
|
+
class s extends g {
|
|
41
|
+
constructor() {
|
|
42
|
+
super(...arguments), this._isCookieBannerHidden = !1, this._isModalOpen = !1, this._dispatchCookieBannerCustomEvent = (e, t) => {
|
|
43
|
+
const n = new CustomEvent(e, {
|
|
44
|
+
bubbles: !0,
|
|
45
|
+
composed: !0,
|
|
46
|
+
detail: t
|
|
47
|
+
});
|
|
48
|
+
this.dispatchEvent(n);
|
|
49
|
+
}, this._openManagePreferencesModal = () => {
|
|
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);
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Handles closing the modal and re-displaying the cookie banner
|
|
64
|
+
* and making the cookie banner visible
|
|
65
|
+
*/
|
|
66
|
+
_displayCookieBanner() {
|
|
67
|
+
this._isModalOpen = !1, this._isCookieBannerHidden = !1;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
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
|
+
* }
|
|
77
|
+
*/
|
|
78
|
+
_handlePreferencesSaved() {
|
|
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
|
+
)}`;
|
|
125
|
+
}
|
|
5
126
|
render() {
|
|
6
|
-
|
|
7
|
-
|
|
127
|
+
const e = {
|
|
128
|
+
text: "Save",
|
|
129
|
+
variant: "primary",
|
|
130
|
+
ariaLabel: "Save your cookie preferences"
|
|
131
|
+
};
|
|
132
|
+
return r`
|
|
133
|
+
<pie-modal
|
|
134
|
+
.isOpen="${this._isModalOpen}"
|
|
135
|
+
hasBackButton
|
|
136
|
+
hasStackedActions
|
|
137
|
+
isFullWidthBelowMid
|
|
138
|
+
heading="Manage your preferences"
|
|
139
|
+
.leadingAction="${e}"
|
|
140
|
+
@pie-modal-leading-action-click="${this._handlePreferencesSaved}"
|
|
141
|
+
@pie-modal-back="${this._displayCookieBanner}">
|
|
142
|
+
${this.renderModalContent()}
|
|
143
|
+
</pie-modal>
|
|
144
|
+
<aside data-test-id="pie-cookie-banner" class="c-cookieBanner" ?isCookieBannerHidden=${this._isCookieBannerHidden}>
|
|
8
145
|
<h2 class="c-cookieBanner-title">Cookies</h2>
|
|
9
146
|
<div class="c-cookieBanner-body">
|
|
10
147
|
<p>We use our own and third party cookies and other tech to enhance and personalise your user experience,
|
|
@@ -16,21 +153,54 @@ class e extends n {
|
|
|
16
153
|
</div>
|
|
17
154
|
|
|
18
155
|
<div class="c-cookieBanner-actions">
|
|
19
|
-
<pie-button
|
|
156
|
+
<pie-button
|
|
157
|
+
data-test-id="accept-all"
|
|
158
|
+
@click="${() => {
|
|
159
|
+
this._dispatchCookieBannerCustomEvent(v), this._isCookieBannerHidden = !0;
|
|
160
|
+
}}"
|
|
161
|
+
variant="primary"
|
|
162
|
+
isFullWidth
|
|
163
|
+
size="small-expressive">
|
|
20
164
|
Accept all
|
|
21
165
|
</pie-button>
|
|
22
|
-
<pie-button
|
|
166
|
+
<pie-button
|
|
167
|
+
data-test-id="necessary-only"
|
|
168
|
+
@click="${() => {
|
|
169
|
+
this._dispatchCookieBannerCustomEvent(u), this._isCookieBannerHidden = !0;
|
|
170
|
+
}}"
|
|
171
|
+
variant="outline-inverse"
|
|
172
|
+
isFullWidth
|
|
173
|
+
size="small-expressive">
|
|
23
174
|
Necessary only
|
|
24
175
|
</pie-button>
|
|
25
|
-
<pie-link
|
|
176
|
+
<pie-link
|
|
177
|
+
data-test-id="manage-prefs"
|
|
178
|
+
@click="${this._openManagePreferencesModal}"
|
|
179
|
+
tag="button"
|
|
180
|
+
variant="inverse"
|
|
181
|
+
isBold="true">
|
|
26
182
|
Manage preferences
|
|
27
183
|
</pie-link>
|
|
28
184
|
</div>
|
|
29
185
|
</aside>`;
|
|
30
186
|
}
|
|
31
187
|
}
|
|
32
|
-
|
|
33
|
-
|
|
188
|
+
s.styles = p(k);
|
|
189
|
+
d([
|
|
190
|
+
h()
|
|
191
|
+
], s.prototype, "_isCookieBannerHidden", 2);
|
|
192
|
+
d([
|
|
193
|
+
h()
|
|
194
|
+
], s.prototype, "_isModalOpen", 2);
|
|
195
|
+
d([
|
|
196
|
+
f("pie-toggle-switch")
|
|
197
|
+
], s.prototype, "_preferencesNodes", 2);
|
|
198
|
+
customElements.define(C, s);
|
|
34
199
|
export {
|
|
35
|
-
|
|
200
|
+
v as ON_COOKIE_BANNER_ACCEPT_ALL,
|
|
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
|
|
36
206
|
};
|
package/dist/react.d.ts
CHANGED
|
@@ -1,16 +1,124 @@
|
|
|
1
1
|
import type { CSSResult } from 'lit';
|
|
2
|
+
import type { EventName } from '@lit-labs/react';
|
|
2
3
|
import type { LitElement } from 'lit';
|
|
4
|
+
import { PieToggleSwitch } from '@justeattakeaway/pie-toggle-switch';
|
|
3
5
|
import type { ReactWebComponent } from '@lit-labs/react';
|
|
4
|
-
import type { TemplateResult } from 'lit
|
|
6
|
+
import type { TemplateResult } from 'lit';
|
|
5
7
|
|
|
6
8
|
export declare interface CookieBannerProps {
|
|
7
9
|
}
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Event name for when all cookies are accepted.
|
|
13
|
+
*
|
|
14
|
+
* @constant
|
|
15
|
+
*/
|
|
16
|
+
export declare const ON_COOKIE_BANNER_ACCEPT_ALL = "pie-cookie-banner-accept-all";
|
|
10
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Event name for when a user clicks manage preferences.
|
|
20
|
+
*
|
|
21
|
+
* @constant
|
|
22
|
+
*/
|
|
23
|
+
export declare const ON_COOKIE_BANNER_MANAGE_PREFS = "pie-cookie-banner-manage-prefs";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Event name for when all only necessary cookies are accepted.
|
|
27
|
+
*
|
|
28
|
+
* @constant
|
|
29
|
+
*/
|
|
30
|
+
export declare const ON_COOKIE_BANNER_NECESSARY_ONLY = "pie-cookie-banner-necessary-only";
|
|
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
|
+
|
|
39
|
+
export declare const PieCookieBanner: ReactWebComponent<PieCookieBanner_2, {
|
|
40
|
+
onPieCookieBannerAcceptAll: EventName<CustomEvent<any>>;
|
|
41
|
+
onPieCookieBannerNecessaryOnly: EventName<CustomEvent<any>>;
|
|
42
|
+
onPieCookieBannerManagePrefs: EventName<CustomEvent<any>>;
|
|
43
|
+
onPieCookieBannerPrefsSaved: EventName<CustomEvent<any>>;
|
|
44
|
+
}>;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @event {CustomEvent} pie-cookie-banner-accept-all - when all cookies are accepted.
|
|
48
|
+
* @event {CustomEvent} pie-cookie-banner-necessary-only - when all only necessary cookies are accepted.
|
|
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.
|
|
51
|
+
*/
|
|
11
52
|
declare class PieCookieBanner_2 extends LitElement implements CookieBannerProps {
|
|
53
|
+
private _isCookieBannerHidden;
|
|
54
|
+
private _isModalOpen;
|
|
55
|
+
_preferencesNodes: NodeListOf<PieToggleSwitch>;
|
|
56
|
+
/**
|
|
57
|
+
* Handles closing the modal and re-displaying the cookie banner
|
|
58
|
+
* and making the cookie banner visible
|
|
59
|
+
*/
|
|
60
|
+
private _displayCookieBanner;
|
|
61
|
+
/**
|
|
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
|
+
* }
|
|
69
|
+
*/
|
|
70
|
+
private _handlePreferencesSaved;
|
|
71
|
+
/**
|
|
72
|
+
* Note: We should aim to have a shareable event helper system to allow
|
|
73
|
+
* us to share this across components in-future.
|
|
74
|
+
*
|
|
75
|
+
* Dispatch a custom event.
|
|
76
|
+
*
|
|
77
|
+
* To be used whenever we have behavioral events we want to
|
|
78
|
+
* bubble up through the cookie banner.
|
|
79
|
+
*
|
|
80
|
+
* @param {string} eventType
|
|
81
|
+
* @param {any} detail
|
|
82
|
+
*/
|
|
83
|
+
private _dispatchCookieBannerCustomEvent;
|
|
84
|
+
/**
|
|
85
|
+
* Opens the manage preferences modal and emits an event letting users know
|
|
86
|
+
*/
|
|
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;
|
|
12
107
|
render(): TemplateResult<1>;
|
|
13
108
|
static styles: CSSResult;
|
|
14
109
|
}
|
|
15
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
|
+
|
|
16
124
|
export { }
|
package/dist/react.js
CHANGED
|
@@ -1,36 +1,39 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import { PieCookieBanner as
|
|
1
|
+
import * as O from "react";
|
|
2
|
+
import { PieCookieBanner as k } 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";
|
|
3
4
|
import "lit";
|
|
5
|
+
import "lit/decorators.js";
|
|
6
|
+
import "lit/directives/repeat.js";
|
|
4
7
|
/**
|
|
5
8
|
* @license
|
|
6
9
|
* Copyright 2018 Google LLC
|
|
7
10
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
8
11
|
*/
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
let s =
|
|
13
|
-
s === void 0 &&
|
|
14
|
-
let a = s.get(
|
|
15
|
-
|
|
16
|
-
})(
|
|
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());
|
|
17
|
+
let a = s.get(n);
|
|
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);
|
|
17
20
|
};
|
|
18
|
-
function
|
|
19
|
-
let
|
|
21
|
+
function P(p = window.React, r, d, m, N) {
|
|
22
|
+
let t, i, n;
|
|
20
23
|
if (r === void 0) {
|
|
21
|
-
const l =
|
|
22
|
-
({ tagName:
|
|
24
|
+
const l = p;
|
|
25
|
+
({ tagName: i, elementClass: n, events: m, displayName: N } = l), t = l.react;
|
|
23
26
|
} else
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
class
|
|
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 {
|
|
27
30
|
constructor() {
|
|
28
31
|
super(...arguments), this.o = null;
|
|
29
32
|
}
|
|
30
33
|
t(e) {
|
|
31
34
|
if (this.o !== null)
|
|
32
|
-
for (const
|
|
33
|
-
|
|
35
|
+
for (const f in this.i)
|
|
36
|
+
A(this.o, f, this.props[f], e ? e[f] : void 0, m);
|
|
34
37
|
}
|
|
35
38
|
componentDidMount() {
|
|
36
39
|
this.t();
|
|
@@ -39,29 +42,43 @@ function B(d = window.React, r, m, p, h) {
|
|
|
39
42
|
this.t(e);
|
|
40
43
|
}
|
|
41
44
|
render() {
|
|
42
|
-
const { _$Gl: e, ...
|
|
43
|
-
this.h !== e && (this.u = (
|
|
44
|
-
e !== null && ((c,
|
|
45
|
-
typeof c == "function" ? c(
|
|
46
|
-
})(e,
|
|
45
|
+
const { _$Gl: e, ...f } = this.props;
|
|
46
|
+
this.h !== e && (this.u = (o) => {
|
|
47
|
+
e !== null && ((c, C) => {
|
|
48
|
+
typeof c == "function" ? c(C) : c.current = C;
|
|
49
|
+
})(e, o), this.o = o, this.h = e;
|
|
47
50
|
}), this.i = {};
|
|
48
|
-
const
|
|
49
|
-
for (const [
|
|
50
|
-
|
|
51
|
-
return s(
|
|
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);
|
|
52
55
|
}
|
|
53
56
|
}
|
|
54
|
-
|
|
55
|
-
const
|
|
56
|
-
return
|
|
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;
|
|
57
60
|
}
|
|
58
|
-
const
|
|
61
|
+
const g = P({
|
|
59
62
|
displayName: "PieCookieBanner",
|
|
60
|
-
elementClass:
|
|
61
|
-
react:
|
|
63
|
+
elementClass: k,
|
|
64
|
+
react: O,
|
|
62
65
|
tagName: "pie-cookie-banner",
|
|
63
|
-
events: {
|
|
66
|
+
events: {
|
|
67
|
+
onPieCookieBannerAcceptAll: "pie-cookie-banner-accept-all",
|
|
68
|
+
// when all cookies are accepted.
|
|
69
|
+
onPieCookieBannerNecessaryOnly: "pie-cookie-banner-necessary-only",
|
|
70
|
+
// when all only necessary cookies are accepted.
|
|
71
|
+
onPieCookieBannerManagePrefs: "pie-cookie-banner-manage-prefs",
|
|
72
|
+
// when a user clicks manage preferences.
|
|
73
|
+
onPieCookieBannerPrefsSaved: "pie-cookie-banner-prefs-saved"
|
|
74
|
+
// when a user clicks save preferences.
|
|
75
|
+
}
|
|
64
76
|
});
|
|
65
77
|
export {
|
|
66
|
-
|
|
78
|
+
M as ON_COOKIE_BANNER_ACCEPT_ALL,
|
|
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
|
|
67
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.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -28,9 +28,12 @@
|
|
|
28
28
|
"author": "JustEatTakeaway.com - Design System Web Team",
|
|
29
29
|
"license": "Apache-2.0",
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@justeattakeaway/pie-button": "0.
|
|
31
|
+
"@justeattakeaway/pie-button": "0.28.0",
|
|
32
32
|
"@justeattakeaway/pie-components-config": "0.4.0",
|
|
33
|
-
"@justeattakeaway/pie-
|
|
33
|
+
"@justeattakeaway/pie-icon-button": "0.14.0",
|
|
34
|
+
"@justeattakeaway/pie-link": "0.3.0",
|
|
35
|
+
"@justeattakeaway/pie-modal": "0.19.0",
|
|
36
|
+
"@justeattakeaway/pie-toggle-switch": "0.6.0"
|
|
34
37
|
},
|
|
35
38
|
"dependencies": {
|
|
36
39
|
"@justeattakeaway/pie-webc-core": "0.8.0"
|
package/src/cookie-banner.scss
CHANGED
|
@@ -41,6 +41,10 @@ $breakpoint-wide: 700px;
|
|
|
41
41
|
border-bottom-left-radius: var(--dt-radius-rounded-c);
|
|
42
42
|
border-bottom-right-radius: var(--dt-radius-rounded-c);
|
|
43
43
|
}
|
|
44
|
+
|
|
45
|
+
&[isCookieBannerHidden] {
|
|
46
|
+
display: none;
|
|
47
|
+
}
|
|
44
48
|
}
|
|
45
49
|
|
|
46
50
|
.c-cookieBanner-title,
|
|
@@ -101,9 +105,8 @@ $breakpoint-wide: 700px;
|
|
|
101
105
|
flex-direction: var(--cb-actions-flex-dir);
|
|
102
106
|
|
|
103
107
|
> pie-link {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
margin-inline-end: auto;
|
|
108
|
+
text-align: center;
|
|
109
|
+
align-self: center;
|
|
107
110
|
}
|
|
108
111
|
|
|
109
112
|
@media (min-width: $breakpoint-wide) and (orientation: landscape) {
|
|
@@ -111,10 +114,39 @@ $breakpoint-wide: 700px;
|
|
|
111
114
|
|
|
112
115
|
justify-content: flex-start;
|
|
113
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
|
+
}
|
|
114
148
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
margin-inline-end: 0;
|
|
118
|
-
}
|
|
149
|
+
&:last-child {
|
|
150
|
+
margin-block-end: 0;
|
|
119
151
|
}
|
|
120
152
|
}
|
package/src/defs.ts
CHANGED
|
@@ -1,3 +1,72 @@
|
|
|
1
1
|
// TODO - please remove the eslint disable comment below when you add props to this interface
|
|
2
2
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
3
3
|
export interface CookieBannerProps {}
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Event name for when all cookies are accepted.
|
|
7
|
+
*
|
|
8
|
+
* @constant
|
|
9
|
+
*/
|
|
10
|
+
export const ON_COOKIE_BANNER_ACCEPT_ALL = 'pie-cookie-banner-accept-all';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Event name for when all only necessary cookies are accepted.
|
|
14
|
+
*
|
|
15
|
+
* @constant
|
|
16
|
+
*/
|
|
17
|
+
export const ON_COOKIE_BANNER_NECESSARY_ONLY = 'pie-cookie-banner-necessary-only';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Event name for when a user clicks manage preferences.
|
|
21
|
+
*
|
|
22
|
+
* @constant
|
|
23
|
+
*/
|
|
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,17 +1,188 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
LitElement, html, unsafeCSS, TemplateResult, nothing,
|
|
3
|
+
} from 'lit';
|
|
4
|
+
import { state, queryAll } from 'lit/decorators.js';
|
|
5
|
+
import { repeat } from 'lit/directives/repeat.js';
|
|
6
|
+
import { PieToggleSwitch } from '@justeattakeaway/pie-toggle-switch';
|
|
3
7
|
import styles from './cookie-banner.scss?inline';
|
|
4
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
CookieBannerProps,
|
|
10
|
+
ON_COOKIE_BANNER_ACCEPT_ALL,
|
|
11
|
+
ON_COOKIE_BANNER_NECESSARY_ONLY,
|
|
12
|
+
ON_COOKIE_BANNER_MANAGE_PREFS,
|
|
13
|
+
ON_COOKIE_BANNER_PREFS_SAVED,
|
|
14
|
+
preferences,
|
|
15
|
+
type Preference,
|
|
16
|
+
type PreferenceIds,
|
|
17
|
+
} from './defs';
|
|
5
18
|
|
|
6
19
|
// Valid values available to consumers
|
|
7
20
|
export * from './defs';
|
|
8
21
|
|
|
9
22
|
const componentSelector = 'pie-cookie-banner';
|
|
10
23
|
|
|
24
|
+
/**
|
|
25
|
+
* @event {CustomEvent} pie-cookie-banner-accept-all - when all cookies are accepted.
|
|
26
|
+
* @event {CustomEvent} pie-cookie-banner-necessary-only - when all only necessary cookies are accepted.
|
|
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.
|
|
29
|
+
*/
|
|
11
30
|
export class PieCookieBanner extends LitElement implements CookieBannerProps {
|
|
31
|
+
@state()
|
|
32
|
+
private _isCookieBannerHidden = false;
|
|
33
|
+
|
|
34
|
+
@state()
|
|
35
|
+
private _isModalOpen = false;
|
|
36
|
+
|
|
37
|
+
@queryAll('pie-toggle-switch')
|
|
38
|
+
_preferencesNodes!: NodeListOf<PieToggleSwitch>;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Handles closing the modal and re-displaying the cookie banner
|
|
42
|
+
* and making the cookie banner visible
|
|
43
|
+
*/
|
|
44
|
+
private _displayCookieBanner () : void {
|
|
45
|
+
this._isModalOpen = false;
|
|
46
|
+
this._isCookieBannerHidden = false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
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
|
+
* }
|
|
57
|
+
*/
|
|
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);
|
|
68
|
+
this._isModalOpen = false;
|
|
69
|
+
this._isCookieBannerHidden = true;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Note: We should aim to have a shareable event helper system to allow
|
|
74
|
+
* us to share this across components in-future.
|
|
75
|
+
*
|
|
76
|
+
* Dispatch a custom event.
|
|
77
|
+
*
|
|
78
|
+
* To be used whenever we have behavioral events we want to
|
|
79
|
+
* bubble up through the cookie banner.
|
|
80
|
+
*
|
|
81
|
+
* @param {string} eventType
|
|
82
|
+
* @param {any} detail
|
|
83
|
+
*/
|
|
84
|
+
private _dispatchCookieBannerCustomEvent = (eventType: string, detail?: CustomEventInit['detail']) : void => {
|
|
85
|
+
const event = new CustomEvent(eventType, {
|
|
86
|
+
bubbles: true,
|
|
87
|
+
composed: true,
|
|
88
|
+
detail,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
this.dispatchEvent(event);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Opens the manage preferences modal and emits an event letting users know
|
|
96
|
+
*/
|
|
97
|
+
private _openManagePreferencesModal = () : void => {
|
|
98
|
+
this._isCookieBannerHidden = true;
|
|
99
|
+
this._dispatchCookieBannerCustomEvent(ON_COOKIE_BANNER_MANAGE_PREFS);
|
|
100
|
+
this._isModalOpen = true;
|
|
101
|
+
};
|
|
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
|
+
|
|
12
166
|
render () {
|
|
167
|
+
const modalActionProps = {
|
|
168
|
+
text: 'Save',
|
|
169
|
+
variant: 'primary',
|
|
170
|
+
ariaLabel: 'Save your cookie preferences',
|
|
171
|
+
};
|
|
172
|
+
|
|
13
173
|
return html`
|
|
14
|
-
<
|
|
174
|
+
<pie-modal
|
|
175
|
+
.isOpen="${this._isModalOpen}"
|
|
176
|
+
hasBackButton
|
|
177
|
+
hasStackedActions
|
|
178
|
+
isFullWidthBelowMid
|
|
179
|
+
heading="Manage your preferences"
|
|
180
|
+
.leadingAction="${modalActionProps}"
|
|
181
|
+
@pie-modal-leading-action-click="${this._handlePreferencesSaved}"
|
|
182
|
+
@pie-modal-back="${this._displayCookieBanner}">
|
|
183
|
+
${this.renderModalContent()}
|
|
184
|
+
</pie-modal>
|
|
185
|
+
<aside data-test-id="pie-cookie-banner" class="c-cookieBanner" ?isCookieBannerHidden=${this._isCookieBannerHidden}>
|
|
15
186
|
<h2 class="c-cookieBanner-title">Cookies</h2>
|
|
16
187
|
<div class="c-cookieBanner-body">
|
|
17
188
|
<p>We use our own and third party cookies and other tech to enhance and personalise your user experience,
|
|
@@ -23,13 +194,28 @@ export class PieCookieBanner extends LitElement implements CookieBannerProps {
|
|
|
23
194
|
</div>
|
|
24
195
|
|
|
25
196
|
<div class="c-cookieBanner-actions">
|
|
26
|
-
<pie-button
|
|
197
|
+
<pie-button
|
|
198
|
+
data-test-id="accept-all"
|
|
199
|
+
@click="${() => { this._dispatchCookieBannerCustomEvent(ON_COOKIE_BANNER_ACCEPT_ALL); this._isCookieBannerHidden = true; }}"
|
|
200
|
+
variant="primary"
|
|
201
|
+
isFullWidth
|
|
202
|
+
size="small-expressive">
|
|
27
203
|
Accept all
|
|
28
204
|
</pie-button>
|
|
29
|
-
<pie-button
|
|
205
|
+
<pie-button
|
|
206
|
+
data-test-id="necessary-only"
|
|
207
|
+
@click="${() => { this._dispatchCookieBannerCustomEvent(ON_COOKIE_BANNER_NECESSARY_ONLY); this._isCookieBannerHidden = true; }}"
|
|
208
|
+
variant="outline-inverse"
|
|
209
|
+
isFullWidth
|
|
210
|
+
size="small-expressive">
|
|
30
211
|
Necessary only
|
|
31
212
|
</pie-button>
|
|
32
|
-
<pie-link
|
|
213
|
+
<pie-link
|
|
214
|
+
data-test-id="manage-prefs"
|
|
215
|
+
@click="${this._openManagePreferencesModal}"
|
|
216
|
+
tag="button"
|
|
217
|
+
variant="inverse"
|
|
218
|
+
isBold="true">
|
|
33
219
|
Manage preferences
|
|
34
220
|
</pie-link>
|
|
35
221
|
</div>
|