@justeattakeaway/pie-modal 0.34.1 → 0.35.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 CHANGED
@@ -29,6 +29,10 @@ export declare const headingLevels: readonly ["h1", "h2", "h3", "h4", "h5", "h6"
29
29
 
30
30
  export declare type ModalActionType = 'leading' | 'supporting';
31
31
 
32
+ export declare interface ModalEventDetail {
33
+ targetModal: PieModal;
34
+ }
35
+
32
36
  export declare type ModalProps = {
33
37
  /**
34
38
  * The ARIA labels used for the modal close and back buttons, as well as loading state.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { LitElement as P, nothing as r, unsafeCSS as T } from "lit";
2
- import { html as c, unsafeStatic as F } from "lit/static-html.js";
1
+ import { LitElement as P, nothing as s, unsafeCSS as T } from "lit";
2
+ import { html as m, unsafeStatic as F } from "lit/static-html.js";
3
3
  import { property as d, query as N } from "lit/decorators.js";
4
4
  import "@justeattakeaway/pie-button";
5
5
  import "@justeattakeaway/pie-icon-button";
@@ -25,26 +25,26 @@ if (typeof window < "u") {
25
25
  };
26
26
  window.addEventListener("testPassive", null, A), window.removeEventListener("testPassive", null, A);
27
27
  }
28
- var B = typeof window < "u" && window.navigator && window.navigator.platform && (/iP(ad|hone|od)/.test(window.navigator.platform) || window.navigator.platform === "MacIntel" && window.navigator.maxTouchPoints > 1), p = [], b = !1, S = -1, g = void 0, h = void 0, L = function(e) {
28
+ var B = typeof window < "u" && window.navigator && window.navigator.platform && (/iP(ad|hone|od)/.test(window.navigator.platform) || window.navigator.platform === "MacIntel" && window.navigator.maxTouchPoints > 1), p = [], k = !1, S = -1, h = void 0, u = void 0, L = function(e) {
29
29
  return p.some(function(o) {
30
30
  return !!(o.options.allowTouchMove && o.options.allowTouchMove(e));
31
31
  });
32
- }, k = function(e) {
32
+ }, w = function(e) {
33
33
  var o = e || window.event;
34
34
  return L(o.target) || o.touches.length > 1 ? !0 : (o.preventDefault && o.preventDefault(), !1);
35
35
  }, Y = function(e) {
36
- if (h === void 0) {
36
+ if (u === void 0) {
37
37
  var o = !!e && e.reserveScrollBarGap === !0, i = window.innerWidth - document.documentElement.clientWidth;
38
- o && i > 0 && (h = document.body.style.paddingRight, document.body.style.paddingRight = i + "px");
38
+ o && i > 0 && (u = document.body.style.paddingRight, document.body.style.paddingRight = i + "px");
39
39
  }
40
- g === void 0 && (g = document.body.style.overflow, document.body.style.overflow = "hidden");
40
+ h === void 0 && (h = document.body.style.overflow, document.body.style.overflow = "hidden");
41
41
  }, V = function() {
42
- h !== void 0 && (document.body.style.paddingRight = h, h = void 0), g !== void 0 && (document.body.style.overflow = g, g = void 0);
42
+ u !== void 0 && (document.body.style.paddingRight = u, u = void 0), h !== void 0 && (document.body.style.overflow = h, h = void 0);
43
43
  }, q = function(e) {
44
44
  return e ? e.scrollHeight - e.scrollTop <= e.clientHeight : !1;
45
45
  }, H = function(e, o) {
46
46
  var i = e.targetTouches[0].clientY - S;
47
- return L(e.target) ? !1 : o && o.scrollTop === 0 && i > 0 || q(o) && i < 0 ? k(e) : (e.stopPropagation(), !0);
47
+ return L(e.target) ? !1 : o && o.scrollTop === 0 && i > 0 || q(o) && i < 0 ? w(e) : (e.stopPropagation(), !0);
48
48
  }, U = function(e, o) {
49
49
  if (!e) {
50
50
  console.error("disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.");
@@ -61,7 +61,7 @@ var B = typeof window < "u" && window.navigator && window.navigator.platform &&
61
61
  t.targetTouches.length === 1 && (S = t.targetTouches[0].clientY);
62
62
  }, e.ontouchmove = function(t) {
63
63
  t.targetTouches.length === 1 && H(t, e);
64
- }, b || (document.addEventListener("touchmove", k, C ? { passive: !1 } : void 0), b = !0)) : Y(o);
64
+ }, k || (document.addEventListener("touchmove", w, C ? { passive: !1 } : void 0), k = !0)) : Y(o);
65
65
  }
66
66
  }, K = function(e) {
67
67
  if (!e) {
@@ -70,46 +70,40 @@ var B = typeof window < "u" && window.navigator && window.navigator.platform &&
70
70
  }
71
71
  p = p.filter(function(o) {
72
72
  return o.targetElement !== e;
73
- }), B ? (e.ontouchstart = null, e.ontouchmove = null, b && p.length === 0 && (document.removeEventListener("touchmove", k, C ? { passive: !1 } : void 0), b = !1)) : p.length || V();
73
+ }), B ? (e.ontouchstart = null, e.ontouchmove = null, k && p.length === 0 && (document.removeEventListener("touchmove", w, C ? { passive: !1 } : void 0), k = !1)) : p.length || V();
74
74
  };
75
75
  const G = `dialog{position:absolute;left:0;right:0;width:-moz-fit-content;width:-webkit-fit-content;width:fit-content;height:-moz-fit-content;height:-webkit-fit-content;height:fit-content;margin:auto;border:solid;padding:1em;background:white;color:#000;display:block}dialog:not([open]){display:none}dialog+.backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background:rgba(0,0,0,.1)}._dialog_overlay{position:fixed;top:0;right:0;bottom:0;left:0}dialog.fixed{position:fixed;top:50%;transform:translateY(-50%)}*,*:before,*:after{box-sizing:border-box}.c-modal{--modal-size-s: 450px;--modal-size-m: 600px;--modal-size-l: 1080px;--modal-border-radius: var(--dt-radius-rounded-d);--modal-font: var(--dt-font-interactive-m-family);--modal-bg-color: var(--dt-color-container-default);--modal-elevation: var(--dt-elevation-04);border-radius:var(--modal-border-radius);border:none;box-shadow:var(--modal-elevation);font-family:var(--modal-font);background-color:var(--modal-bg-color);padding:0;--modal-margin-none: var(--dt-spacing-none);--modal-margin-small: var(--dt-spacing-g);--modal-margin-large: var(--dt-spacing-j);--modal-margin-block: var(--modal-margin-small);--modal-block-size: fit-content;--modal-inline-size: 75%;--modal-max-block-size: calc(100vh - calc(var(--modal-margin-block) * 2));--modal-max-inline-size: var(--modal-size-m);block-size:var(--modal-block-size);inline-size:var(--modal-inline-size);max-block-size:var(--modal-max-block-size);max-inline-size:var(--modal-max-inline-size)}.c-modal:focus-visible{outline:none}@media (max-width: 767px){.c-modal pie-icon-button{--btn-dimension: 40px}}.c-modal[open]{display:flex;flex-direction:column}@media (min-width: 768px){.c-modal{--modal-margin-block: var(--modal-margin-large)}}.c-modal[size=small]{--modal-max-inline-size: var(--modal-size-s)}@media (min-width: 768px){.c-modal[size=small]{--modal-margin-block: var(--modal-margin-large)}}@media (max-width: 767px){.c-modal[size=medium][isfullwidthbelowmid]{--modal-margin-block: var(--modal-margin-none);--modal-border-radius: var(--dt-radius-rounded-none);--modal-block-size: 100%;--modal-inline-size: 100%;--modal-max-inline-size: 100%}.c-modal[size=medium][isfullwidthbelowmid]>.c-modal-scrollContainer{block-size:100%}}.c-modal[size=large]{--modal-inline-size: 75%;--modal-max-inline-size: var(--modal-size-l);--modal-margin-block: var(--modal-margin-large)}@media (max-width: 767px){.c-modal[size=large]{--modal-margin-block: var(--modal-margin-none);--modal-border-radius: var(--dt-radius-rounded-none);--modal-block-size: 100%;--modal-inline-size: 100%}}.c-modal[position=top]{margin-block-start:var(--dt-spacing-j);max-block-size:calc(100% - var(--dt-spacing-j) * 2)}@media (max-width: 767px){.c-modal[position=top][size=large],.c-modal[position=top][isfullwidthbelowmid][size=medium]{margin-block-start:var(--dt-spacing-none);max-block-size:100%}}.c-modal::backdrop{background:rgba(0,0,0,.55)}.c-modal .c-modal-footer{--modal-button-spacing: var(--dt-spacing-d);--modal-footer-padding: var(--dt-spacing-d);display:flex;flex-flow:row-reverse;flex-wrap:wrap;gap:var(--modal-button-spacing);padding:var(--modal-footer-padding)}@media (min-width: 768px){.c-modal .c-modal-footer{--modal-footer-padding: var(--dt-spacing-e)}}@media (max-width: 767px){.c-modal[hasstackedactions] .c-modal-footer{flex-direction:column}}.c-modal .c-modal-header{display:grid;grid-template-areas:"back heading close";grid-template-columns:minmax(0,max-content) minmax(0,1fr) minmax(0,max-content);align-items:start}.c-modal .c-modal-heading{--modal-header-font-size: calc(var(--dt-font-heading-m-size--narrow) * 1px);--modal-header-font-line-height: calc(var(--dt-font-heading-m-line-height--narrow) * 1px);--modal-header-font-weight: var(--dt-font-heading-m-weight);font-size:var(--modal-header-font-size);line-height:var(--modal-header-font-line-height);font-weight:var(--modal-header-font-weight);margin:0;grid-area:heading;margin-inline:var(--dt-spacing-d);margin-block:14px}@media (min-width: 768px){.c-modal .c-modal-heading{--modal-header-font-size: calc(var(--dt-font-heading-m-size--wide) * 1px);--modal-header-font-line-height: calc(var(--dt-font-heading-m-line-height--wide) * 1px);margin-inline:var(--dt-spacing-e);margin-block:20px}}.c-modal[hasbackbutton] .c-modal-heading{margin-inline-start:var(--dt-spacing-b)}@media (min-width: 768px){.c-modal[hasbackbutton] .c-modal-heading{margin-inline-start:var(--dt-spacing-c)}}.c-modal[isdismissible] .c-modal-heading{margin-inline-end:var(--dt-spacing-d)}@media (min-width: 768px){.c-modal[isdismissible] .c-modal-heading{margin-inline-end:var(--dt-spacing-e)}}.c-modal .c-modal-backBtn{grid-area:back;margin-block:var(--dt-spacing-b);margin-inline:var(--dt-spacing-b) var(--dt-spacing-none)}@media (min-width: 768px){.c-modal .c-modal-backBtn{margin-block:var(--dt-spacing-c);margin-inline:var(--dt-spacing-c) var(--dt-spacing-none)}}.c-modal .c-modal-closeBtn{grid-area:close;margin-block:var(--dt-spacing-b);margin-inline:var(--dt-spacing-none) var(--dt-spacing-b)}@media (min-width: 768px){.c-modal .c-modal-closeBtn{margin-block:var(--dt-spacing-c);margin-inline:var(--dt-spacing-none) var(--dt-spacing-c)}}.c-modal .c-modal-content{--modal-content-font-size: calc(var(--dt-font-size-16) * 1px);--modal-content-font-weight: var(--dt-font-weight-regular);--modal-content-line-height: calc(var(--dt-font-size-16-line-height) * 1px);--modal-content-padding-block: var(--dt-spacing-a);--modal-content-padding-inline: var(--dt-spacing-d);position:relative;min-block-size:var(--dt-spacing-j);font-size:var(--modal-content-font-size);line-height:var(--modal-content-line-height);font-weight:var(--modal-content-font-weight);padding-inline:var(--modal-content-padding-inline);padding-block:var(--modal-content-padding-block);flex-grow:1}@media (min-width: 768px){.c-modal .c-modal-content{--modal-content-padding-inline: var(--dt-spacing-e)}}.c-modal .c-modal-content--scrollable{background:linear-gradient(to bottom,transparent,var(--dt-color-container-default) 75%) center bottom,linear-gradient(transparent,var(--dt-color-border-strong)) center bottom;background-repeat:no-repeat;background-size:100% 48px,100% 12px;background-attachment:local,scroll}.c-modal>.c-modal-scrollContainer{display:flex;flex-direction:column;block-size:auto;overflow-y:auto;--bg-scroll-end: linear-gradient(rgba(255, 255, 255, 0), var(--dt-color-container-default) 70%) 0 100%;--bg-scroll-bottom: radial-gradient(farthest-corner at 50% 100%, rgba(0, 0, 0, .3), rgba(0, 0, 0, 0)) 0 100%;--bg-size-scroll-end: 100% 40px;--bg-size-scroll-bottom: 100% 8px;background:var(--bg-scroll-end),var(--bg-scroll-bottom);background-repeat:no-repeat;background-size:var(--bg-size-scroll-end),var(--bg-size-scroll-bottom);background-attachment:local,scroll}.c-modal>.c-modal-scrollContainer .c-modal-content{flex-shrink:0}.c-modal[isfooterpinned] .c-modal-content{overflow-y:auto}.c-modal[isLoading] .c-modal-content pie-spinner{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%)}.c-modal[isLoading] .c-modal-content .c-modal-contentInner{display:none}@supports not (aspect-ratio: 1/1){.c-modal .c-modal-scrollContainer{background:none}}
76
- `, X = ["h1", "h2", "h3", "h4", "h5", "h6"], J = ["small", "medium", "large"], Q = ["top", "center"], x = "pie-modal-close", v = "pie-modal-open", _ = "pie-modal-back", Z = "pie-modal-leading-action-click", ee = "pie-modal-supporting-action-click";
76
+ `, X = ["h1", "h2", "h3", "h4", "h5", "h6"], J = ["small", "medium", "large"], Q = ["top", "center"], x = "pie-modal-close", b = "pie-modal-open", _ = "pie-modal-back", Z = "pie-modal-leading-action-click", ee = "pie-modal-supporting-action-click";
77
77
  var oe = Object.defineProperty, ie = Object.getOwnPropertyDescriptor, l = (n, e, o, i) => {
78
- for (var t = i > 1 ? void 0 : i ? ie(e, o) : e, s = n.length - 1, m; s >= 0; s--)
79
- (m = n[s]) && (t = (i ? m(e, o, t) : m(t)) || t);
78
+ for (var t = i > 1 ? void 0 : i ? ie(e, o) : e, r = n.length - 1, c; r >= 0; r--)
79
+ (c = n[r]) && (t = (i ? c(e, o, t) : c(t)) || t);
80
80
  return i && t && oe(e, o, t), t;
81
81
  };
82
- const u = "pie-modal";
82
+ const f = "pie-modal";
83
83
  class a extends I(P) {
84
84
  constructor() {
85
85
  super(...arguments), this.headingLevel = "h2", this.hasBackButton = !1, this.hasStackedActions = !1, this.isDismissible = !1, this.isFooterPinned = !0, this.isFullWidthBelowMid = !1, this.isLoading = !1, this.isOpen = !1, this.position = "center", this.size = "medium", this._backButtonClicked = !1, this._handleDialogCancelEvent = (e) => {
86
86
  this.isDismissible || e.preventDefault();
87
87
  }, this._handleDialogLightDismiss = (e) => {
88
- var f;
88
+ var v;
89
89
  if (!this.isDismissible)
90
90
  return;
91
- const o = (f = this._dialog) == null ? void 0 : f.getBoundingClientRect(), {
91
+ const o = (v = this._dialog) == null ? void 0 : v.getBoundingClientRect(), {
92
92
  top: i = 0,
93
93
  bottom: t = 0,
94
- left: s = 0,
95
- right: m = 0
94
+ left: r = 0,
95
+ right: c = 0
96
96
  } = o || {};
97
- if (i === 0 && t === 0 && s === 0 && m === 0)
97
+ if (i === 0 && t === 0 && r === 0 && c === 0)
98
98
  return;
99
- (e.clientY < i || e.clientY > t || e.clientX < s || e.clientX > m) && (this.isOpen = !1);
100
- }, this._dispatchModalCustomEvent = (e) => {
101
- const o = new CustomEvent(e, {
102
- bubbles: !0,
103
- composed: !0
104
- });
105
- this.dispatchEvent(o);
99
+ (e.clientY < i || e.clientY > t || e.clientX < r || e.clientX > c) && (this.isOpen = !1);
106
100
  };
107
101
  }
108
102
  connectedCallback() {
109
- super.connectedCallback(), this.addEventListener("click", (e) => this._handleDialogLightDismiss(e)), document.addEventListener(v, this._handleModalOpened.bind(this)), document.addEventListener(x, this._handleModalClosed.bind(this)), document.addEventListener(_, this._handleModalClosed.bind(this));
103
+ super.connectedCallback(), this.addEventListener("click", (e) => this._handleDialogLightDismiss(e)), document.addEventListener(b, (e) => this._handleModalOpened(e)), document.addEventListener(x, (e) => this._handleModalClosed(e)), document.addEventListener(_, (e) => this._handleModalClosed(e));
110
104
  }
111
105
  disconnectedCallback() {
112
- document.removeEventListener(v, this._handleModalOpened.bind(this)), document.removeEventListener(x, this._handleModalClosed.bind(this)), document.removeEventListener(_, this._handleModalClosed.bind(this)), super.disconnectedCallback();
106
+ document.removeEventListener(b, (e) => this._handleModalOpened(e)), document.removeEventListener(x, (e) => this._handleModalClosed(e)), document.removeEventListener(_, (e) => this._handleModalClosed(e)), super.disconnectedCallback();
113
107
  }
114
108
  async firstUpdated(e) {
115
109
  super.firstUpdated(e), this._dialog && ((await import("./dialog-polyfill.esm-29edb142.js").then((i) => i.default)).registerDialog(this._dialog), this._dialog.addEventListener("cancel", (i) => this._handleDialogCancelEvent(i)), this._dialog.addEventListener("close", () => {
@@ -122,27 +116,35 @@ class a extends I(P) {
122
116
  /**
123
117
  * Opens the dialog element and disables page scrolling
124
118
  */
125
- _handleModalOpened() {
126
- var o, i, t, s;
127
- const e = (o = this._dialog) == null ? void 0 : o.querySelector(".c-modal-scrollContainer");
128
- e && U(e), !((i = this._dialog) != null && i.hasAttribute("open") || !((t = this._dialog) != null && t.isConnected)) && ((s = this._dialog) == null || s.showModal());
119
+ _handleModalOpened(e) {
120
+ var i, t, r, c;
121
+ const { targetModal: o } = e.detail;
122
+ if (o === this) {
123
+ const g = (i = this._dialog) == null ? void 0 : i.querySelector(".c-modal-scrollContainer");
124
+ if (g && U(g), (t = this._dialog) != null && t.hasAttribute("open") || !((r = this._dialog) != null && r.isConnected))
125
+ return;
126
+ (c = this._dialog) == null || c.showModal();
127
+ }
129
128
  }
130
129
  /**
131
130
  * Closes the dialog element and re-enables page scrolling
132
131
  */
133
- _handleModalClosed() {
134
- var o, i;
135
- const e = (o = this._dialog) == null ? void 0 : o.querySelector(".c-modal-scrollContainer");
136
- e && K(e), (i = this._dialog) == null || i.close(), this._returnFocus();
132
+ _handleModalClosed(e) {
133
+ var i, t;
134
+ const { targetModal: o } = e.detail;
135
+ if (o === this) {
136
+ const r = (i = this._dialog) == null ? void 0 : i.querySelector(".c-modal-scrollContainer");
137
+ r && K(r), (t = this._dialog) == null || t.close(), this._returnFocus();
138
+ }
137
139
  }
138
140
  // Handles the value of the isOpen property on first render of the component
139
141
  _handleModalOpenStateOnFirstRender(e) {
140
- e.get("isOpen") === void 0 && this.isOpen && this._dispatchModalCustomEvent(v);
142
+ e.get("isOpen") === void 0 && this.isOpen && this._dispatchModalCustomEvent(b);
141
143
  }
142
144
  // Handles changes to the modal isOpen property by dispatching any appropriate events
143
145
  _handleModalOpenStateChanged(e) {
144
146
  const o = e.get("isOpen");
145
- o !== void 0 && (o ? this._backButtonClicked ? (this._backButtonClicked = !1, this._dispatchModalCustomEvent(_)) : this._dispatchModalCustomEvent(x) : this._dispatchModalCustomEvent(v));
147
+ o !== void 0 && (o ? this._backButtonClicked ? (this._backButtonClicked = !1, this._dispatchModalCustomEvent(_)) : this._dispatchModalCustomEvent(x) : this._dispatchModalCustomEvent(b));
146
148
  }
147
149
  _handleActionClick(e) {
148
150
  var o, i;
@@ -165,14 +167,14 @@ class a extends I(P) {
165
167
  */
166
168
  renderCloseButton() {
167
169
  var e;
168
- return c`
170
+ return m`
169
171
  <pie-icon-button
170
172
  @click="${() => {
171
173
  this.isOpen = !1;
172
174
  }}"
173
175
  variant="ghost-secondary"
174
176
  class="c-modal-closeBtn"
175
- aria-label="${((e = this.aria) == null ? void 0 : e.close) || r}"
177
+ aria-label="${((e = this.aria) == null ? void 0 : e.close) || s}"
176
178
  data-test-id="modal-close-button">
177
179
  <icon-close></icon-close>
178
180
  </pie-icon-button>`;
@@ -185,16 +187,16 @@ class a extends I(P) {
185
187
  */
186
188
  renderBackButton() {
187
189
  var e;
188
- return c`
190
+ return m`
189
191
  <pie-icon-button
190
192
  @click="${() => {
191
193
  this._backButtonClicked = !0, this.isOpen = !1;
192
194
  }}"
193
195
  variant="ghost-secondary"
194
196
  class="c-modal-backBtn"
195
- aria-label="${((e = this.aria) == null ? void 0 : e.back) || r}"
197
+ aria-label="${((e = this.aria) == null ? void 0 : e.back) || s}"
196
198
  data-test-id="modal-back-button">
197
- ${this.isRTL ? c`<icon-chevron-right></icon-chevron-right>` : c`<icon-chevron-left></icon-chevron-left>`}
199
+ ${this.isRTL ? m`<icon-chevron-right></icon-chevron-right>` : m`<icon-chevron-left></icon-chevron-left>`}
198
200
  </pie-icon-button>
199
201
  `;
200
202
  }
@@ -209,17 +211,17 @@ class a extends I(P) {
209
211
  */
210
212
  renderLeadingAction() {
211
213
  const { text: e, variant: o = "primary", ariaLabel: i } = this.leadingAction;
212
- return e ? c`
214
+ return e ? m`
213
215
  <pie-button
214
216
  variant="${o}"
215
- aria-label="${i || r}"
217
+ aria-label="${i || s}"
216
218
  type="submit"
217
219
  ?isFullWidth="${this.hasStackedActions}"
218
220
  @click="${() => this._handleActionClick("leading")}"
219
221
  data-test-id="modal-leading-action">
220
222
  ${e}
221
223
  </pie-button>
222
- ` : r;
224
+ ` : s;
223
225
  }
224
226
  /**
225
227
  * Render supportingAction button depending on prop availability.
@@ -234,33 +236,33 @@ class a extends I(P) {
234
236
  */
235
237
  renderSupportingAction() {
236
238
  const { text: e, variant: o = "ghost", ariaLabel: i } = this.supportingAction;
237
- return e ? this.leadingAction ? c`
239
+ return e ? this.leadingAction ? m`
238
240
  <pie-button
239
241
  variant="${o}"
240
- aria-label="${i || r}"
242
+ aria-label="${i || s}"
241
243
  type="reset"
242
244
  ?isFullWidth="${this.hasStackedActions}"
243
245
  @click="${() => this._handleActionClick("supporting")}"
244
246
  data-test-id="modal-supporting-action">
245
247
  ${e}
246
248
  </pie-button>
247
- ` : (console.warn("Use `leadingAction` instead of `supportingAction`. `supportingAction` is being ignored."), r) : r;
249
+ ` : (console.warn("Use `leadingAction` instead of `supportingAction`. `supportingAction` is being ignored."), s) : s;
248
250
  }
249
251
  /**
250
252
  * Renders the modal inner content and footer of the modal.
251
253
  * @private
252
254
  */
253
255
  renderModalContentAndFooter() {
254
- return c`
256
+ return m`
255
257
  <article class="c-modal-scrollContainer c-modal-content c-modal-content--scrollable">
256
258
  <div class="c-modal-contentInner">
257
259
  <slot></slot>
258
260
  </div>
259
- ${this.isLoading ? c`<pie-spinner size="xlarge" variant="secondary"></pie-spinner>` : r}
261
+ ${this.isLoading ? m`<pie-spinner size="xlarge" variant="secondary"></pie-spinner>` : s}
260
262
  </article>
261
263
  <footer class="c-modal-footer">
262
- ${this.leadingAction ? this.renderLeadingAction() : r}
263
- ${this.supportingAction ? this.renderSupportingAction() : r}
264
+ ${this.leadingAction ? this.renderLeadingAction() : s}
265
+ ${this.supportingAction ? this.renderSupportingAction() : s}
264
266
  </footer>`;
265
267
  }
266
268
  render() {
@@ -269,17 +271,17 @@ class a extends I(P) {
269
271
  hasBackButton: o,
270
272
  hasStackedActions: i,
271
273
  heading: t,
272
- headingLevel: s = "h2",
273
- isDismissible: m,
274
- isFooterPinned: w,
275
- isFullWidthBelowMid: f,
274
+ headingLevel: r = "h2",
275
+ isDismissible: c,
276
+ isFooterPinned: g,
277
+ isFullWidthBelowMid: v,
276
278
  isLoading: y,
277
279
  leadingAction: M,
278
280
  position: $,
279
281
  size: E,
280
282
  supportingAction: D
281
- } = this, O = F(s);
282
- return c`
283
+ } = this, O = F(r);
284
+ return m`
283
285
  <dialog
284
286
  id="dialog"
285
287
  class="c-modal"
@@ -288,28 +290,47 @@ class a extends I(P) {
288
290
  ?hasActions=${M || D}
289
291
  ?hasBackButton=${o}
290
292
  ?hasStackedActions=${i}
291
- ?isDismissible=${m}
292
- ?isFooterPinned=${w}
293
- ?isFullWidthBelowMid=${f}
293
+ ?isDismissible=${c}
294
+ ?isFooterPinned=${g}
295
+ ?isFullWidthBelowMid=${v}
294
296
  ?isLoading=${y}
295
297
  aria-busy="${y ? "true" : "false"}"
296
- aria-label="${y && (e == null ? void 0 : e.loading) || r}"
298
+ aria-label="${y && (e == null ? void 0 : e.loading) || s}"
297
299
  data-test-id="pie-modal">
298
300
  <header class="c-modal-header">
299
- ${o ? this.renderBackButton() : r}
301
+ ${o ? this.renderBackButton() : s}
300
302
  <${O} class="c-modal-heading">
301
303
  ${t}
302
304
  </${O}>
303
- ${m ? this.renderCloseButton() : r}
305
+ ${c ? this.renderCloseButton() : s}
304
306
  </header>
305
307
  ${// We need to wrap the remaining content in a shared scrollable container if the footer is not pinned
306
- w ? this.renderModalContentAndFooter() : c`
308
+ g ? this.renderModalContentAndFooter() : m`
307
309
  <div class="c-modal-scrollContainer">
308
310
  ${this.renderModalContentAndFooter()}
309
311
  </div>
310
312
  `}
311
313
  </dialog>`;
312
314
  }
315
+ /**
316
+ * Note: We should aim to have a shareable event helper system to allow
317
+ * us to share this across components in-future.
318
+ *
319
+ * Dispatch a custom event.
320
+ *
321
+ * To be used whenever we have behavioural events we want to
322
+ * bubble up through the modal.
323
+ *
324
+ * @param {string} eventType
325
+ */
326
+ _dispatchModalCustomEvent(e) {
327
+ const o = new CustomEvent(e, {
328
+ bubbles: !0,
329
+ composed: !0,
330
+ detail: { targetModal: this }
331
+ });
332
+ this.dispatchEvent(o);
333
+ }
313
334
  }
314
335
  a.styles = T(G);
315
336
  l([
@@ -317,11 +338,11 @@ l([
317
338
  ], a.prototype, "aria", 2);
318
339
  l([
319
340
  d({ type: String }),
320
- R(u)
341
+ R(f)
321
342
  ], a.prototype, "heading", 2);
322
343
  l([
323
344
  d(),
324
- z(u, X, "h2")
345
+ z(f, X, "h2")
325
346
  ], a.prototype, "headingLevel", 2);
326
347
  l([
327
348
  d({ type: Boolean })
@@ -349,14 +370,14 @@ l([
349
370
  ], a.prototype, "leadingAction", 2);
350
371
  l([
351
372
  d(),
352
- z(u, Q, "center")
373
+ z(f, Q, "center")
353
374
  ], a.prototype, "position", 2);
354
375
  l([
355
376
  d()
356
377
  ], a.prototype, "returnFocusAfterCloseSelector", 2);
357
378
  l([
358
379
  d(),
359
- z(u, J, "medium")
380
+ z(f, J, "medium")
360
381
  ], a.prototype, "size", 2);
361
382
  l([
362
383
  d({ type: Object })
@@ -364,12 +385,12 @@ l([
364
385
  l([
365
386
  N("dialog")
366
387
  ], a.prototype, "_dialog", 2);
367
- j(u, a);
388
+ j(f, a);
368
389
  export {
369
390
  _ as ON_MODAL_BACK_EVENT,
370
391
  x as ON_MODAL_CLOSE_EVENT,
371
392
  Z as ON_MODAL_LEADING_ACTION_CLICK,
372
- v as ON_MODAL_OPEN_EVENT,
393
+ b as ON_MODAL_OPEN_EVENT,
373
394
  ee as ON_MODAL_SUPPORTING_ACTION_CLICK,
374
395
  a as PieModal,
375
396
  X as headingLevels,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@justeattakeaway/pie-modal",
3
- "version": "0.34.1",
3
+ "version": "0.35.0",
4
4
  "description": "PIE design system modal built using web components",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -37,7 +37,7 @@
37
37
  },
38
38
  "dependencies": {
39
39
  "@justeattakeaway/pie-button": "0.40.1",
40
- "@justeattakeaway/pie-icon-button": "0.23.0",
40
+ "@justeattakeaway/pie-icon-button": "0.24.0",
41
41
  "@justeattakeaway/pie-icons-webc": "0.12.0",
42
42
  "@justeattakeaway/pie-spinner": "0.3.1",
43
43
  "@justeattakeaway/pie-webc-core": "0.13.0",
package/src/index.ts CHANGED
@@ -36,6 +36,10 @@ export * from './defs';
36
36
 
37
37
  const componentSelector = 'pie-modal';
38
38
 
39
+ export interface ModalEventDetail {
40
+ targetModal: PieModal;
41
+ }
42
+
39
43
  /**
40
44
  * @tagname pie-modal
41
45
  * @event {CustomEvent} pie-modal-open - when the modal is opened.
@@ -105,15 +109,15 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
105
109
  connectedCallback () : void {
106
110
  super.connectedCallback();
107
111
  this.addEventListener('click', (event) => this._handleDialogLightDismiss(event));
108
- document.addEventListener(ON_MODAL_OPEN_EVENT, this._handleModalOpened.bind(this));
109
- document.addEventListener(ON_MODAL_CLOSE_EVENT, this._handleModalClosed.bind(this));
110
- document.addEventListener(ON_MODAL_BACK_EVENT, this._handleModalClosed.bind(this));
112
+ document.addEventListener(ON_MODAL_OPEN_EVENT, (event) => this._handleModalOpened(<CustomEvent>event));
113
+ document.addEventListener(ON_MODAL_CLOSE_EVENT, (event) => this._handleModalClosed(<CustomEvent>event));
114
+ document.addEventListener(ON_MODAL_BACK_EVENT, (event) => this._handleModalClosed(<CustomEvent>event));
111
115
  }
112
116
 
113
117
  disconnectedCallback () : void {
114
- document.removeEventListener(ON_MODAL_OPEN_EVENT, this._handleModalOpened.bind(this));
115
- document.removeEventListener(ON_MODAL_CLOSE_EVENT, this._handleModalClosed.bind(this));
116
- document.removeEventListener(ON_MODAL_BACK_EVENT, this._handleModalClosed.bind(this));
118
+ document.removeEventListener(ON_MODAL_OPEN_EVENT, (event) => this._handleModalOpened(<CustomEvent>event));
119
+ document.removeEventListener(ON_MODAL_CLOSE_EVENT, (event) => this._handleModalClosed(<CustomEvent>event));
120
+ document.removeEventListener(ON_MODAL_BACK_EVENT, (event) => this._handleModalClosed(<CustomEvent>event));
117
121
  super.disconnectedCallback();
118
122
  }
119
123
 
@@ -140,32 +144,41 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
140
144
  /**
141
145
  * Opens the dialog element and disables page scrolling
142
146
  */
143
- private _handleModalOpened () : void {
144
- const modalScrollContainer = this._dialog?.querySelector('.c-modal-scrollContainer');
147
+ private _handleModalOpened (event: CustomEvent): void {
148
+ const { targetModal } = event.detail;
145
149
 
146
- if (modalScrollContainer) {
147
- disableBodyScroll(modalScrollContainer);
148
- }
150
+ if (targetModal === this) {
151
+ const modalScrollContainer = this._dialog?.querySelector('.c-modal-scrollContainer');
149
152
 
150
- if (this._dialog?.hasAttribute('open') || !this._dialog?.isConnected) {
151
- return;
153
+ if (modalScrollContainer) {
154
+ disableBodyScroll(modalScrollContainer);
155
+ }
156
+
157
+ if (this._dialog?.hasAttribute('open') || !this._dialog?.isConnected) {
158
+ return;
159
+ }
160
+
161
+ // The ::backdrop pseudoelement is only shown if the modal is opened via JS
162
+ this._dialog?.showModal();
152
163
  }
153
- // The ::backdrop pseudoelement is only shown if the modal is opened via JS
154
- this._dialog?.showModal();
155
164
  }
156
165
 
157
166
  /**
158
167
  * Closes the dialog element and re-enables page scrolling
159
168
  */
160
- private _handleModalClosed () : void {
161
- const modalScrollContainer = this._dialog?.querySelector('.c-modal-scrollContainer');
169
+ private _handleModalClosed (event: CustomEvent): void {
170
+ const { targetModal } = event.detail;
162
171
 
163
- if (modalScrollContainer) {
164
- enableBodyScroll(modalScrollContainer);
165
- }
172
+ if (targetModal === this) {
173
+ const modalScrollContainer = this._dialog?.querySelector('.c-modal-scrollContainer');
174
+
175
+ if (modalScrollContainer) {
176
+ enableBodyScroll(modalScrollContainer);
177
+ }
166
178
 
167
- this._dialog?.close();
168
- this._returnFocus();
179
+ this._dialog?.close();
180
+ this._returnFocus();
181
+ }
169
182
  }
170
183
 
171
184
  /**
@@ -448,14 +461,15 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
448
461
  *
449
462
  * @param {string} eventType
450
463
  */
451
- private _dispatchModalCustomEvent = (eventType: string) : void => {
452
- const event = new CustomEvent(eventType, {
464
+ private _dispatchModalCustomEvent (eventType: string): void {
465
+ const event = new CustomEvent<ModalEventDetail>(eventType, {
453
466
  bubbles: true,
454
467
  composed: true,
468
+ detail: { targetModal: this },
455
469
  });
456
470
 
457
471
  this.dispatchEvent(event);
458
- };
472
+ }
459
473
  }
460
474
 
461
475
  defineCustomElement(componentSelector, PieModal);