@justeattakeaway/pie-modal 0.47.0 → 0.48.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.
@@ -285,7 +285,7 @@
285
285
  "kind": "field",
286
286
  "name": "_dialog",
287
287
  "type": {
288
- "text": "HTMLDialogElement | undefined"
288
+ "text": "HTMLDialogElement"
289
289
  },
290
290
  "privacy": "private"
291
291
  },
@@ -298,6 +298,23 @@
298
298
  "privacy": "private",
299
299
  "default": "false"
300
300
  },
301
+ {
302
+ "kind": "field",
303
+ "name": "_abortController",
304
+ "type": {
305
+ "text": "AbortController"
306
+ },
307
+ "privacy": "private"
308
+ },
309
+ {
310
+ "kind": "field",
311
+ "name": "_modalScrollContainer",
312
+ "type": {
313
+ "text": "Element | null"
314
+ },
315
+ "privacy": "private",
316
+ "readonly": true
317
+ },
301
318
  {
302
319
  "kind": "method",
303
320
  "name": "_handleModalOpened",
@@ -416,6 +433,28 @@
416
433
  },
417
434
  "description": "Return focus to the specified element, providing the selector is valid\nand the chosen element can be found."
418
435
  },
436
+ {
437
+ "kind": "method",
438
+ "name": "_enableBodyScroll",
439
+ "privacy": "private",
440
+ "return": {
441
+ "type": {
442
+ "text": "void"
443
+ }
444
+ },
445
+ "description": "Enables body scroll by unlocking the scroll container."
446
+ },
447
+ {
448
+ "kind": "method",
449
+ "name": "_disableBodyScroll",
450
+ "privacy": "private",
451
+ "return": {
452
+ "type": {
453
+ "text": "void"
454
+ }
455
+ },
456
+ "description": "Disables body scroll by locking the scroll container."
457
+ },
419
458
  {
420
459
  "kind": "method",
421
460
  "name": "renderCloseButton",
package/dist/index.d.ts CHANGED
@@ -167,8 +167,10 @@ export declare class PieModal extends PieModal_base implements ModalProps {
167
167
  returnFocusAfterCloseSelector: ModalProps['returnFocusAfterCloseSelector'];
168
168
  size: "medium" | "large" | "small";
169
169
  supportingAction: ModalProps['supportingAction'];
170
- private _dialog?;
170
+ private _dialog;
171
171
  private _backButtonClicked;
172
+ private _abortController;
173
+ private get _modalScrollContainer();
172
174
  static styles: CSSResult;
173
175
  connectedCallback(): void;
174
176
  disconnectedCallback(): void;
@@ -197,6 +199,14 @@ export declare class PieModal extends PieModal_base implements ModalProps {
197
199
  * and the chosen element can be found.
198
200
  */
199
201
  private _returnFocus;
202
+ /**
203
+ * Enables body scroll by unlocking the scroll container.
204
+ */
205
+ private _enableBodyScroll;
206
+ /**
207
+ * Disables body scroll by locking the scroll container.
208
+ */
209
+ private _disableBodyScroll;
200
210
  /**
201
211
  * Template for the close button element. Called within the
202
212
  * main render function.
package/dist/index.js CHANGED
@@ -1,80 +1,80 @@
1
- import { LitElement as I, unsafeCSS as N, nothing as h } from "lit";
2
- import { html as c, unsafeStatic as W } from "lit/static-html.js";
3
- import { property as r, query as R } from "lit/decorators.js";
4
- import { classMap as M } from "lit/directives/class-map.js";
5
- import { ifDefined as y } from "lit/directives/if-defined.js";
1
+ import { LitElement as I, unsafeCSS as N, nothing as p } from "lit";
2
+ import { html as s, unsafeStatic as W } from "lit/static-html.js";
3
+ import { property as d, query as R } from "lit/decorators.js";
4
+ import { classMap as S } from "lit/directives/class-map.js";
5
+ import { ifDefined as k } from "lit/directives/if-defined.js";
6
6
  import "@justeattakeaway/pie-button";
7
7
  import "@justeattakeaway/pie-icon-button";
8
- import { RtlMixin as j, dispatchCustomEvent as u, requiredProperty as Y, validPropertyValues as B, defineCustomElement as V } from "@justeattakeaway/pie-webc-core";
8
+ import { RtlMixin as j, dispatchCustomEvent as h, requiredProperty as Y, validPropertyValues as _, defineCustomElement as V } from "@justeattakeaway/pie-webc-core";
9
9
  import "@justeattakeaway/pie-icons-webc/dist/IconClose.js";
10
10
  import "@justeattakeaway/pie-icons-webc/dist/IconChevronLeft.js";
11
11
  import "@justeattakeaway/pie-icons-webc/dist/IconChevronRight.js";
12
12
  import "@justeattakeaway/pie-spinner";
13
13
  function q(n) {
14
14
  if (Array.isArray(n)) {
15
- for (var e = 0, o = Array(n.length); e < n.length; e++)
16
- o[e] = n[e];
17
- return o;
15
+ for (var o = 0, e = Array(n.length); o < n.length; o++)
16
+ e[o] = n[o];
17
+ return e;
18
18
  } else
19
19
  return Array.from(n);
20
20
  }
21
- var O = !1;
21
+ var C = !1;
22
22
  if (typeof window < "u") {
23
- var A = {
23
+ var O = {
24
24
  get passive() {
25
- O = !0;
25
+ C = !0;
26
26
  }
27
27
  };
28
- window.addEventListener("testPassive", null, A), window.removeEventListener("testPassive", null, A);
28
+ window.addEventListener("testPassive", null, O), window.removeEventListener("testPassive", null, O);
29
29
  }
30
- var $ = typeof window < "u" && window.navigator && window.navigator.platform && (/iP(ad|hone|od)/.test(window.navigator.platform) || window.navigator.platform === "MacIntel" && window.navigator.maxTouchPoints > 1), g = [], x = !1, D = -1, f = void 0, v = void 0, F = function(e) {
31
- return g.some(function(o) {
32
- return !!(o.options.allowTouchMove && o.options.allowTouchMove(e));
30
+ var M = typeof window < "u" && window.navigator && window.navigator.platform && (/iP(ad|hone|od)/.test(window.navigator.platform) || window.navigator.platform === "MacIntel" && window.navigator.maxTouchPoints > 1), m = [], y = !1, $ = -1, u = void 0, f = void 0, D = function(o) {
31
+ return m.some(function(e) {
32
+ return !!(e.options.allowTouchMove && e.options.allowTouchMove(o));
33
33
  });
34
- }, _ = function(e) {
35
- var o = e || window.event;
36
- return F(o.target) || o.touches.length > 1 ? !0 : (o.preventDefault && o.preventDefault(), !1);
37
- }, H = function(e) {
38
- if (v === void 0) {
39
- var o = !!e, t = window.innerWidth - document.documentElement.clientWidth;
40
- o && t > 0 && (v = document.body.style.paddingRight, document.body.style.paddingRight = t + "px");
34
+ }, w = function(o) {
35
+ var e = o || window.event;
36
+ return D(e.target) || e.touches.length > 1 ? !0 : (e.preventDefault && e.preventDefault(), !1);
37
+ }, H = function(o) {
38
+ if (f === void 0) {
39
+ var e = !!o, t = window.innerWidth - document.documentElement.clientWidth;
40
+ e && t > 0 && (f = document.body.style.paddingRight, document.body.style.paddingRight = t + "px");
41
41
  }
42
- f === void 0 && (f = document.body.style.overflow, document.body.style.overflow = "hidden");
42
+ u === void 0 && (u = document.body.style.overflow, document.body.style.overflow = "hidden");
43
43
  }, K = function() {
44
- v !== void 0 && (document.body.style.paddingRight = v, v = void 0), f !== void 0 && (document.body.style.overflow = f, f = void 0);
45
- }, U = function(e) {
46
- return e ? e.scrollHeight - e.scrollTop <= e.clientHeight : !1;
47
- }, X = function(e, o) {
48
- var t = e.targetTouches[0].clientY - D;
49
- return F(e.target) ? !1 : o && o.scrollTop === 0 && t > 0 || U(o) && t < 0 ? _(e) : (e.stopPropagation(), !0);
50
- }, G = function(e, o) {
51
- if (!e) {
44
+ f !== void 0 && (document.body.style.paddingRight = f, f = void 0), u !== void 0 && (document.body.style.overflow = u, u = void 0);
45
+ }, U = function(o) {
46
+ return o ? o.scrollHeight - o.scrollTop <= o.clientHeight : !1;
47
+ }, X = function(o, e) {
48
+ var t = o.targetTouches[0].clientY - $;
49
+ return D(o.target) ? !1 : e && e.scrollTop === 0 && t > 0 || U(e) && t < 0 ? w(o) : (o.stopPropagation(), !0);
50
+ }, G = function(o, e) {
51
+ if (!o) {
52
52
  console.error("disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.");
53
53
  return;
54
54
  }
55
- if (!g.some(function(i) {
56
- return i.targetElement === e;
55
+ if (!m.some(function(i) {
56
+ return i.targetElement === o;
57
57
  })) {
58
58
  var t = {
59
- targetElement: e,
59
+ targetElement: o,
60
60
  options: {}
61
61
  };
62
- g = [].concat(q(g), [t]), $ ? (e.ontouchstart = function(i) {
63
- i.targetTouches.length === 1 && (D = i.targetTouches[0].clientY);
64
- }, e.ontouchmove = function(i) {
65
- i.targetTouches.length === 1 && X(i, e);
66
- }, x || (document.addEventListener("touchmove", _, O ? { passive: !1 } : void 0), x = !0)) : H(o);
62
+ m = [].concat(q(m), [t]), M ? (o.ontouchstart = function(i) {
63
+ i.targetTouches.length === 1 && ($ = i.targetTouches[0].clientY);
64
+ }, o.ontouchmove = function(i) {
65
+ i.targetTouches.length === 1 && X(i, o);
66
+ }, y || (document.addEventListener("touchmove", w, C ? { passive: !1 } : void 0), y = !0)) : H(e);
67
67
  }
68
- }, J = function(e) {
69
- if (!e) {
68
+ }, J = function(o) {
69
+ if (!o) {
70
70
  console.error("enableBodyScroll unsuccessful - targetElement must be provided when calling enableBodyScroll on IOS devices.");
71
71
  return;
72
72
  }
73
- g = g.filter(function(o) {
74
- return o.targetElement !== e;
75
- }), $ ? (e.ontouchstart = null, e.ontouchmove = null, x && g.length === 0 && (document.removeEventListener("touchmove", _, O ? { passive: !1 } : void 0), x = !1)) : g.length || K();
73
+ m = m.filter(function(e) {
74
+ return e.targetElement !== o;
75
+ }), M ? (o.ontouchstart = null, o.ontouchmove = null, y && m.length === 0 && (document.removeEventListener("touchmove", w, C ? { passive: !1 } : void 0), y = !1)) : m.length || K();
76
76
  };
77
- const Q = '*,*:after,*:before{box-sizing:inherit}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:#fff;color:#000;display:block}dialog:not([open]){display:none}dialog+.backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background:#0000001a}._dialog_overlay{position:fixed;top:0;right:0;bottom:0;left:0}dialog.fixed{position:fixed;top:50%;transform:translateY(-50%)}.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-l-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: 769px){.c-modal{--modal-margin-block: var(--modal-margin-large)}}.c-modal.c-modal--small{--modal-max-inline-size: var(--modal-size-s)}@media (min-width: 769px){.c-modal.c-modal--small{--modal-margin-block: var(--modal-margin-large)}}.c-modal.c-modal--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.c-modal--large,.c-modal.c-modal--medium.c-modal--fullWidthBelowMid{--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.c-modal--large>.c-modal-scrollContainer,.c-modal.c-modal--medium.c-modal--fullWidthBelowMid>.c-modal-scrollContainer{block-size:100%}}.c-modal.c-modal--top{margin-block-start:var(--dt-spacing-j);max-block-size:calc(100% - var(--dt-spacing-j) * 2)}@media (max-width: 767px){.c-modal.c-modal--top.c-modal--large,.c-modal.c-modal--top.c-modal--fullWidthBelowMid.c-modal--medium{margin-block-start:var(--dt-spacing-none);max-block-size:100%}}.c-modal::backdrop{background:var(--dt-color-overlay)}@supports (hanging-punctuation: first) and (font: -apple-system-body) and (-webkit-appearance: none){.c-modal::backdrop{background:#0000008c}}.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: 769px){.c-modal .c-modal-footer{--modal-footer-padding: var(--dt-spacing-e)}}@media (max-width: 767px){.c-modal .c-modal-footer.c-modal-footer--stackedActions{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-start:var(--dt-spacing-d);margin-inline-end:var(--dt-spacing-d);margin-block:14px}@media (min-width: 769px){.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-start:var(--dt-spacing-e);margin-inline-end:var(--dt-spacing-e);margin-block:20px}}.c-modal .c-modal-backBtn+.c-modal-heading{margin-inline-start:var(--dt-spacing-b)}@media (min-width: 769px){.c-modal .c-modal-backBtn+.c-modal-heading{margin-inline-start:var(--dt-spacing-c)}}.c-modal.c-modal--dismissible .c-modal-heading{margin-inline-end:var(--dt-spacing-d)}@media (min-width: 769px){.c-modal.c-modal--dismissible .c-modal-heading{margin-inline-end:var(--dt-spacing-e)}}.c-modal .c-modal-backBtn{grid-area:back;margin-block-start:var(--dt-spacing-b);margin-block-end:var(--dt-spacing-b);margin-inline-start:var(--dt-spacing-b);margin-inline-end:var(--dt-spacing-none)}@media (min-width: 769px){.c-modal .c-modal-backBtn{margin-block-start:var(--dt-spacing-c);margin-block-end:var(--dt-spacing-c);margin-inline-start:var(--dt-spacing-c);margin-inline-end:var(--dt-spacing-none)}}.c-modal .c-modal-closeBtn{grid-area:close;margin-block-start:var(--dt-spacing-b);margin-block-end:var(--dt-spacing-b);margin-inline-start:var(--dt-spacing-none);margin-inline-end:var(--dt-spacing-b)}@media (min-width: 769px){.c-modal .c-modal-closeBtn{margin-block-start:var(--dt-spacing-c);margin-block-end:var(--dt-spacing-c);margin-inline-start:var(--dt-spacing-none);margin-inline-end: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);--modal-content-padding-block-end: var(--dt-spacing-e);--modal-content-min-block-size: var(--dt-spacing-j);position:relative;min-block-size:calc(var(--modal-content-min-block-size) + var(--modal-content-padding-block) + var(--modal-content-padding-block-end));font-size:var(--modal-content-font-size);line-height:var(--modal-content-line-height);font-weight:var(--modal-content-font-weight);padding-inline-start:var(--modal-content-padding-inline);padding-inline-end:var(--modal-content-padding-inline);padding-block-start:var(--modal-content-padding-block);padding-block-end:var(--modal-content-padding-block-end);flex-grow:1}@media (min-width: 769px){.c-modal .c-modal-content{--modal-content-padding-inline: var(--dt-spacing-e)}}.c-modal .c-modal-content:not(:last-child){padding-block-end:var(--modal-content-padding-block);min-block-size:var(--modal-content-min-block-size)}.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;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.c-modal--pinnedFooter .c-modal-content{overflow-y:auto}.c-modal.c-modal--loading .c-modal-content pie-spinner{position:absolute;left:50%;top:calc(50% - (var(--modal-content-padding-block-end) - var(--modal-content-padding-block)) / 2);transform:translate(-50%,-50%)}.c-modal.c-modal--loading .c-modal-content .c-modal-contentInner{display:none}.c-modal.c-modal--loading .c-modal-content:not(:last-child) pie-spinner{top:50%}@supports not (aspect-ratio: 1/1){.c-modal .c-modal-scrollContainer{background:none}}', Z = ["h1", "h2", "h3", "h4", "h5", "h6"], ee = ["small", "medium", "large"], oe = ["top", "center"], z = "pie-modal-close", w = "pie-modal-open", C = "pie-modal-back", te = "pie-modal-leading-action-click", ie = "pie-modal-supporting-action-click", s = {
77
+ const Q = '*,*:after,*:before{box-sizing:inherit}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:#fff;color:#000;display:block}dialog:not([open]){display:none}dialog+.backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background:#0000001a}._dialog_overlay{position:fixed;top:0;right:0;bottom:0;left:0}dialog.fixed{position:fixed;top:50%;transform:translateY(-50%)}.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-l-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: 769px){.c-modal{--modal-margin-block: var(--modal-margin-large)}}.c-modal.c-modal--small{--modal-max-inline-size: var(--modal-size-s)}@media (min-width: 769px){.c-modal.c-modal--small{--modal-margin-block: var(--modal-margin-large)}}.c-modal.c-modal--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.c-modal--large,.c-modal.c-modal--medium.c-modal--fullWidthBelowMid{--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.c-modal--large>.c-modal-scrollContainer,.c-modal.c-modal--medium.c-modal--fullWidthBelowMid>.c-modal-scrollContainer{block-size:100%}}.c-modal.c-modal--top{margin-block-start:var(--dt-spacing-j);max-block-size:calc(100% - var(--dt-spacing-j) * 2)}@media (max-width: 767px){.c-modal.c-modal--top.c-modal--large,.c-modal.c-modal--top.c-modal--fullWidthBelowMid.c-modal--medium{margin-block-start:var(--dt-spacing-none);max-block-size:100%}}.c-modal::backdrop{background:var(--dt-color-overlay)}@supports (hanging-punctuation: first) and (font: -apple-system-body) and (-webkit-appearance: none){.c-modal::backdrop{background:#0000008c}}.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: 769px){.c-modal .c-modal-footer{--modal-footer-padding: var(--dt-spacing-e)}}@media (max-width: 767px){.c-modal .c-modal-footer.c-modal-footer--stackedActions{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-start:var(--dt-spacing-d);margin-inline-end:var(--dt-spacing-d);margin-block:14px}@media (min-width: 769px){.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-start:var(--dt-spacing-e);margin-inline-end:var(--dt-spacing-e);margin-block:20px}}.c-modal .c-modal-backBtn+.c-modal-heading{margin-inline-start:var(--dt-spacing-b)}@media (min-width: 769px){.c-modal .c-modal-backBtn+.c-modal-heading{margin-inline-start:var(--dt-spacing-c)}}.c-modal.c-modal--dismissible .c-modal-heading{margin-inline-end:var(--dt-spacing-d)}@media (min-width: 769px){.c-modal.c-modal--dismissible .c-modal-heading{margin-inline-end:var(--dt-spacing-e)}}.c-modal .c-modal-backBtn{grid-area:back;margin-block-start:var(--dt-spacing-b);margin-block-end:var(--dt-spacing-b);margin-inline-start:var(--dt-spacing-b);margin-inline-end:var(--dt-spacing-none)}@media (min-width: 769px){.c-modal .c-modal-backBtn{margin-block-start:var(--dt-spacing-c);margin-block-end:var(--dt-spacing-c);margin-inline-start:var(--dt-spacing-c);margin-inline-end:var(--dt-spacing-none)}}.c-modal .c-modal-closeBtn{grid-area:close;margin-block-start:var(--dt-spacing-b);margin-block-end:var(--dt-spacing-b);margin-inline-start:var(--dt-spacing-none);margin-inline-end:var(--dt-spacing-b)}@media (min-width: 769px){.c-modal .c-modal-closeBtn{margin-block-start:var(--dt-spacing-c);margin-block-end:var(--dt-spacing-c);margin-inline-start:var(--dt-spacing-none);margin-inline-end: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);--modal-content-padding-block-end: var(--dt-spacing-e);--modal-content-min-block-size: var(--dt-spacing-j);position:relative;min-block-size:calc(var(--modal-content-min-block-size) + var(--modal-content-padding-block) + var(--modal-content-padding-block-end));font-size:var(--modal-content-font-size);line-height:var(--modal-content-line-height);font-weight:var(--modal-content-font-weight);padding-inline-start:var(--modal-content-padding-inline);padding-inline-end:var(--modal-content-padding-inline);padding-block-start:var(--modal-content-padding-block);padding-block-end:var(--modal-content-padding-block-end);flex-grow:1}@media (min-width: 769px){.c-modal .c-modal-content{--modal-content-padding-inline: var(--dt-spacing-e)}}.c-modal .c-modal-content:not(:last-child){padding-block-end:var(--modal-content-padding-block);min-block-size:var(--modal-content-min-block-size)}.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;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.c-modal--pinnedFooter .c-modal-content{overflow-y:auto}.c-modal.c-modal--loading .c-modal-content pie-spinner{position:absolute;left:50%;top:calc(50% - (var(--modal-content-padding-block-end) - var(--modal-content-padding-block)) / 2);transform:translate(-50%,-50%)}.c-modal.c-modal--loading .c-modal-content .c-modal-contentInner{display:none}.c-modal.c-modal--loading .c-modal-content:not(:last-child) pie-spinner{top:50%}@supports not (aspect-ratio: 1/1){.c-modal .c-modal-scrollContainer{background:none}}', Z = ["h1", "h2", "h3", "h4", "h5", "h6"], oo = ["small", "medium", "large"], eo = ["top", "center"], A = "pie-modal-close", x = "pie-modal-open", L = "pie-modal-back", to = "pie-modal-leading-action-click", io = "pie-modal-supporting-action-click", r = {
78
78
  hasBackButton: !1,
79
79
  hasStackedActions: !1,
80
80
  headingLevel: "h2",
@@ -86,89 +86,103 @@ const Q = '*,*:after,*:before{box-sizing:inherit}dialog{position:absolute;left:0
86
86
  position: "center",
87
87
  size: "medium"
88
88
  };
89
- var ae = Object.defineProperty, l = (n, e, o, t) => {
90
- for (var i = void 0, d = n.length - 1, m; d >= 0; d--)
91
- (m = n[d]) && (i = m(e, o, i) || i);
92
- return i && ae(e, o, i), i;
89
+ var ao = Object.defineProperty, l = (n, o, e, t) => {
90
+ for (var i = void 0, c = n.length - 1, g; c >= 0; c--)
91
+ (g = n[c]) && (i = g(o, e, i) || i);
92
+ return i && ao(o, e, i), i;
93
93
  };
94
- const b = "pie-modal", L = class L extends j(I) {
94
+ const v = "pie-modal", z = class z extends j(I) {
95
95
  constructor() {
96
- super(...arguments), this.headingLevel = s.headingLevel, this.hasBackButton = s.hasBackButton, this.hasStackedActions = s.hasStackedActions, this.isDismissible = s.isDismissible, this.isFooterPinned = s.isFooterPinned, this.isFullWidthBelowMid = s.isFullWidthBelowMid, this.isLoading = s.isLoading, this.isOpen = s.isOpen, this.position = s.position, this.size = s.size, this._backButtonClicked = !1, this._handleDialogCancelEvent = (e) => {
97
- this.isDismissible || e.preventDefault();
98
- }, this._handleDialogLightDismiss = (e) => {
99
- var k;
96
+ super(...arguments), this.headingLevel = r.headingLevel, this.hasBackButton = r.hasBackButton, this.hasStackedActions = r.hasStackedActions, this.isDismissible = r.isDismissible, this.isFooterPinned = r.isFooterPinned, this.isFullWidthBelowMid = r.isFullWidthBelowMid, this.isLoading = r.isLoading, this.isOpen = r.isOpen, this.position = r.position, this.size = r.size, this._backButtonClicked = !1, this._handleDialogCancelEvent = (o) => {
97
+ this.isDismissible || o.preventDefault();
98
+ }, this._handleDialogLightDismiss = (o) => {
100
99
  if (!this.isDismissible)
101
100
  return;
102
- const o = (k = this._dialog) == null ? void 0 : k.getBoundingClientRect(), {
101
+ const e = this._dialog.getBoundingClientRect(), {
103
102
  top: t = 0,
104
103
  bottom: i = 0,
105
- left: d = 0,
106
- right: m = 0
107
- } = o || {};
108
- if (t === 0 && i === 0 && d === 0 && m === 0)
104
+ left: c = 0,
105
+ right: g = 0
106
+ } = e || {};
107
+ if (t === 0 && i === 0 && c === 0 && g === 0)
109
108
  return;
110
- (e.clientY < t || e.clientY > i || e.clientX < d || e.clientX > m) && (this.isOpen = !1);
109
+ (o.clientY < t || o.clientY > i || o.clientX < c || o.clientX > g) && (this.isOpen = !1);
111
110
  };
112
111
  }
112
+ get _modalScrollContainer() {
113
+ return this._dialog.querySelector(".c-modal-scrollContainer");
114
+ }
113
115
  connectedCallback() {
114
- super.connectedCallback(), this.addEventListener("click", (e) => this._handleDialogLightDismiss(e)), document.addEventListener(w, (e) => this._handleModalOpened(e)), document.addEventListener(z, (e) => this._handleModalClosed(e)), document.addEventListener(C, (e) => this._handleModalClosed(e));
116
+ super.connectedCallback(), this._abortController = new AbortController();
117
+ const { signal: o } = this._abortController;
118
+ this.addEventListener("click", (e) => this._handleDialogLightDismiss(e)), document.addEventListener(x, (e) => this._handleModalOpened(e), { signal: o }), document.addEventListener(A, (e) => this._handleModalClosed(e), { signal: o }), document.addEventListener(L, (e) => this._handleModalClosed(e), { signal: o });
115
119
  }
116
120
  disconnectedCallback() {
117
- document.removeEventListener(w, (e) => this._handleModalOpened(e)), document.removeEventListener(z, (e) => this._handleModalClosed(e)), document.removeEventListener(C, (e) => this._handleModalClosed(e)), super.disconnectedCallback();
121
+ this._abortController.abort(), this._enableBodyScroll(), super.disconnectedCallback();
118
122
  }
119
- async firstUpdated(e) {
120
- super.firstUpdated(e), this._dialog && ((await import("./dialog-polyfill.esm-CbjBMXAG.js").then((t) => t.default)).registerDialog(this._dialog), this._dialog.addEventListener("cancel", (t) => this._handleDialogCancelEvent(t)), this._dialog.addEventListener("close", () => {
121
- this.isOpen = !1;
122
- })), this._handleModalOpenStateOnFirstRender(e);
123
+ async firstUpdated(o) {
124
+ if (super.firstUpdated(o), this._dialog) {
125
+ (await import("./dialog-polyfill.esm-CbjBMXAG.js").then((i) => i.default)).registerDialog(this._dialog);
126
+ const { signal: t } = this._abortController;
127
+ this._dialog.addEventListener("cancel", (i) => this._handleDialogCancelEvent(i), { signal: t }), this._dialog.addEventListener("close", () => {
128
+ this.isOpen = !1;
129
+ }, { signal: t });
130
+ }
131
+ this._handleModalOpenStateOnFirstRender(o);
123
132
  }
124
- updated(e) {
125
- super.updated(e), this._handleModalOpenStateChanged(e);
133
+ updated(o) {
134
+ super.updated(o), this._handleModalOpenStateChanged(o);
126
135
  }
127
136
  /**
128
137
  * Opens the dialog element and disables page scrolling
129
138
  */
130
- _handleModalOpened(e) {
131
- var t, i, d, m;
132
- const { targetModal: o } = e.detail;
133
- if (o === this) {
134
- const p = (t = this._dialog) == null ? void 0 : t.querySelector(".c-modal-scrollContainer");
135
- if (p && ("scrollTo" in window && window.scrollTo(0, 0), G(p)), (i = this._dialog) != null && i.hasAttribute("open") || !((d = this._dialog) != null && d.isConnected))
139
+ _handleModalOpened(o) {
140
+ const { targetModal: e } = o.detail;
141
+ if (e === this) {
142
+ if (this._disableBodyScroll(), this._dialog.hasAttribute("open") || !this._dialog.isConnected)
136
143
  return;
137
- (m = this._dialog) == null || m.showModal();
144
+ this._dialog.showModal();
138
145
  }
139
146
  }
140
147
  /**
141
148
  * Closes the dialog element and re-enables page scrolling
142
149
  */
143
- _handleModalClosed(e) {
144
- var t, i;
145
- const { targetModal: o } = e.detail;
146
- if (o === this) {
147
- const d = (t = this._dialog) == null ? void 0 : t.querySelector(".c-modal-scrollContainer");
148
- d && J(d), (i = this._dialog) == null || i.close(), this._returnFocus();
149
- }
150
+ _handleModalClosed(o) {
151
+ const { targetModal: e } = o.detail;
152
+ e === this && (this._enableBodyScroll(), this._dialog.close(), this._returnFocus());
150
153
  }
151
154
  // Handles the value of the isOpen property on first render of the component
152
- _handleModalOpenStateOnFirstRender(e) {
153
- e.get("isOpen") === void 0 && this.isOpen && u(this, w, { targetModal: this });
155
+ _handleModalOpenStateOnFirstRender(o) {
156
+ o.get("isOpen") === void 0 && this.isOpen && h(this, x, { targetModal: this });
154
157
  }
155
158
  // Handles changes to the modal isOpen property by dispatching any appropriate events
156
- _handleModalOpenStateChanged(e) {
157
- const o = e.get("isOpen");
158
- o !== void 0 && (o ? this._backButtonClicked ? (this._backButtonClicked = !1, u(this, C, { targetModal: this })) : u(this, z, { targetModal: this }) : u(this, w, { targetModal: this }));
159
+ _handleModalOpenStateChanged(o) {
160
+ const e = o.get("isOpen");
161
+ e !== void 0 && (e ? this._backButtonClicked ? (this._backButtonClicked = !1, h(this, L, { targetModal: this })) : h(this, A, { targetModal: this }) : h(this, x, { targetModal: this }));
159
162
  }
160
- _handleActionClick(e) {
161
- var o, t;
162
- e === "leading" ? ((o = this._dialog) == null || o.close("leading"), u(this, te, { targetModal: this })) : e === "supporting" && ((t = this._dialog) == null || t.close("supporting"), u(this, ie, { targetModal: this }));
163
+ _handleActionClick(o) {
164
+ o === "leading" ? (this._dialog.close("leading"), h(this, to, { targetModal: this })) : o === "supporting" && (this._dialog.close("supporting"), h(this, io, { targetModal: this }));
163
165
  }
164
166
  /**
165
167
  * Return focus to the specified element, providing the selector is valid
166
168
  * and the chosen element can be found.
167
169
  */
168
170
  _returnFocus() {
169
- var o, t;
170
- const e = (o = this.returnFocusAfterCloseSelector) == null ? void 0 : o.trim();
171
- e && ((t = document.querySelector(e)) == null || t.focus());
171
+ var e, t;
172
+ const o = (e = this.returnFocusAfterCloseSelector) == null ? void 0 : e.trim();
173
+ o && ((t = document.querySelector(o)) == null || t.focus());
174
+ }
175
+ /**
176
+ * Enables body scroll by unlocking the scroll container.
177
+ */
178
+ _enableBodyScroll() {
179
+ this._modalScrollContainer && J(this._modalScrollContainer);
180
+ }
181
+ /**
182
+ * Disables body scroll by locking the scroll container.
183
+ */
184
+ _disableBodyScroll() {
185
+ this._modalScrollContainer && ("scrollTo" in window && window.scrollTo(0, 0), G(this._modalScrollContainer));
172
186
  }
173
187
  /**
174
188
  * Template for the close button element. Called within the
@@ -177,18 +191,18 @@ const b = "pie-modal", L = class L extends j(I) {
177
191
  * @private
178
192
  */
179
193
  renderCloseButton() {
180
- var e;
181
- return this.isDismissible ? c`
194
+ var o;
195
+ return this.isDismissible ? s`
182
196
  <pie-icon-button
183
197
  @click="${() => {
184
198
  this.isOpen = !1;
185
199
  }}"
186
200
  variant="ghost-secondary"
187
201
  class="c-modal-closeBtn"
188
- aria-label="${((e = this.aria) == null ? void 0 : e.close) || h}"
202
+ aria-label="${((o = this.aria) == null ? void 0 : o.close) || p}"
189
203
  data-test-id="modal-close-button">
190
204
  <icon-close></icon-close>
191
- </pie-icon-button>` : h;
205
+ </pie-icon-button>` : p;
192
206
  }
193
207
  /**
194
208
  * Template for the back button element. Called within the
@@ -197,19 +211,19 @@ const b = "pie-modal", L = class L extends j(I) {
197
211
  * @private
198
212
  */
199
213
  renderBackButton() {
200
- var e;
201
- return this.hasBackButton ? c`
214
+ var o;
215
+ return this.hasBackButton ? s`
202
216
  <pie-icon-button
203
217
  @click="${() => {
204
218
  this._backButtonClicked = !0, this.isOpen = !1;
205
219
  }}"
206
220
  variant="ghost-secondary"
207
221
  class="c-modal-backBtn"
208
- aria-label="${y((e = this.aria) == null ? void 0 : e.back)}"
222
+ aria-label="${k((o = this.aria) == null ? void 0 : o.back)}"
209
223
  data-test-id="modal-back-button">
210
- ${this.isRTL ? c`<icon-chevron-right></icon-chevron-right>` : c`<icon-chevron-left></icon-chevron-left>`}
224
+ ${this.isRTL ? s`<icon-chevron-right></icon-chevron-right>` : s`<icon-chevron-left></icon-chevron-left>`}
211
225
  </pie-icon-button>
212
- ` : h;
226
+ ` : p;
213
227
  }
214
228
  /**
215
229
  * Renders the "leadingAction" button if the text is provided.
@@ -221,18 +235,18 @@ const b = "pie-modal", L = class L extends j(I) {
221
235
  * @private
222
236
  */
223
237
  renderLeadingAction() {
224
- const { ariaLabel: e, text: o, variant: t = "primary" } = this.leadingAction || {};
225
- return o ? c`
238
+ const { ariaLabel: o, text: e, variant: t = "primary" } = this.leadingAction || {};
239
+ return e ? s`
226
240
  <pie-button
227
241
  variant="${t}"
228
- aria-label="${y(e)}"
242
+ aria-label="${k(o)}"
229
243
  type="submit"
230
244
  ?isFullWidth="${this.hasStackedActions}"
231
245
  @click="${() => this._handleActionClick("leading")}"
232
246
  data-test-id="modal-leading-action">
233
- ${o}
247
+ ${e}
234
248
  </pie-button>
235
- ` : h;
249
+ ` : p;
236
250
  }
237
251
  /**
238
252
  * Renders the "supportingAction" button if the text is provided.
@@ -246,16 +260,16 @@ const b = "pie-modal", L = class L extends j(I) {
246
260
  */
247
261
  renderSupportingAction() {
248
262
  var i;
249
- const { ariaLabel: e, text: o, variant: t = "ghost" } = this.supportingAction || {};
250
- return !o || !((i = this.leadingAction) != null && i.text) ? h : c`
263
+ const { ariaLabel: o, text: e, variant: t = "ghost" } = this.supportingAction || {};
264
+ return !e || !((i = this.leadingAction) != null && i.text) ? p : s`
251
265
  <pie-button
252
266
  variant="${t}"
253
- aria-label="${y(e)}"
267
+ aria-label="${k(o)}"
254
268
  type="reset"
255
269
  ?isFullWidth="${this.hasStackedActions}"
256
270
  @click="${() => this._handleActionClick("supporting")}"
257
271
  data-test-id="modal-supporting-action">
258
- ${o}
272
+ ${e}
259
273
  </pie-button>
260
274
  `;
261
275
  }
@@ -266,15 +280,15 @@ const b = "pie-modal", L = class L extends j(I) {
266
280
  * @private
267
281
  */
268
282
  renderModalFooter() {
269
- var o, t;
270
- if (!((o = this.leadingAction) != null && o.text))
271
- return (t = this.supportingAction) != null && t.text && console.warn("You cannot have a supporting action without a leading action. If you only need one button then use a leading action instead."), h;
272
- const e = {
283
+ var e, t;
284
+ if (!((e = this.leadingAction) != null && e.text))
285
+ return (t = this.supportingAction) != null && t.text && console.warn("You cannot have a supporting action without a leading action. If you only need one button then use a leading action instead."), p;
286
+ const o = {
273
287
  "c-modal-footer": !0,
274
288
  "c-modal-footer--stackedActions": this.hasStackedActions
275
289
  };
276
- return c`
277
- <footer class="${M(e)}" data-test-id="pie-modal-footer">
290
+ return s`
291
+ <footer class="${S(o)}" data-test-id="pie-modal-footer">
278
292
  ${this.renderLeadingAction()}
279
293
  ${this.renderSupportingAction()}
280
294
  </footer>`;
@@ -284,14 +298,14 @@ const b = "pie-modal", L = class L extends j(I) {
284
298
  * @private
285
299
  */
286
300
  renderLoadingSpinner() {
287
- return this.isLoading ? c`<pie-spinner size="xlarge" variant="secondary"></pie-spinner>` : h;
301
+ return this.isLoading ? s`<pie-spinner size="xlarge" variant="secondary"></pie-spinner>` : p;
288
302
  }
289
303
  /**
290
304
  * Renders the modal inner content and footer of the modal.
291
305
  * @private
292
306
  */
293
307
  renderModalContentAndFooter() {
294
- return c`
308
+ return s`
295
309
  <article class="c-modal-scrollContainer c-modal-content c-modal-content--scrollable">
296
310
  <div class="c-modal-contentInner" data-test-id="modal-content-inner">
297
311
  <slot></slot>
@@ -302,111 +316,111 @@ const b = "pie-modal", L = class L extends j(I) {
302
316
  }
303
317
  render() {
304
318
  const {
305
- aria: e,
306
- heading: o,
319
+ aria: o,
320
+ heading: e,
307
321
  headingLevel: t,
308
322
  isDismissible: i,
309
- isFooterPinned: d,
310
- isFullWidthBelowMid: m,
311
- isLoading: p,
312
- position: k,
313
- size: E
314
- } = this, S = W(t), T = p && (e == null ? void 0 : e.loading) || void 0, P = {
323
+ isFooterPinned: c,
324
+ isFullWidthBelowMid: g,
325
+ isLoading: b,
326
+ position: F,
327
+ size: T
328
+ } = this, B = W(t), E = b && (o == null ? void 0 : o.loading) || void 0, P = {
315
329
  "c-modal": !0,
316
- [`c-modal--${E}`]: !0,
317
- "c-modal--top": k === "top",
330
+ [`c-modal--${T}`]: !0,
331
+ "c-modal--top": F === "top",
318
332
  "c-modal--dismissible": i,
319
- "c-modal--loading": p,
320
- "c-modal--pinnedFooter": d,
321
- "c-modal--fullWidthBelowMid": m
333
+ "c-modal--loading": b,
334
+ "c-modal--pinnedFooter": c,
335
+ "c-modal--fullWidthBelowMid": g
322
336
  };
323
- return c`
337
+ return s`
324
338
  <dialog
325
339
  id="dialog"
326
- class="${M(P)}"
327
- aria-busy="${p ? "true" : "false"}"
328
- aria-label="${y(T)}"
340
+ class="${S(P)}"
341
+ aria-busy="${b ? "true" : "false"}"
342
+ aria-label="${k(E)}"
329
343
  data-test-id="pie-modal">
330
344
  <header class="c-modal-header"
331
345
  data-test-id="modal-header">
332
346
  ${this.renderBackButton()}
333
- <${S} class="c-modal-heading">
334
- ${o}
335
- </${S}>
347
+ <${B} class="c-modal-heading">
348
+ ${e}
349
+ </${B}>
336
350
  ${this.renderCloseButton()}
337
351
  </header>
338
352
  ${// We need to wrap the remaining content in a shared scrollable container if the footer is not pinned
339
- d ? this.renderModalContentAndFooter() : c`
353
+ c ? this.renderModalContentAndFooter() : s`
340
354
  <div class="c-modal-scrollContainer">
341
355
  ${this.renderModalContentAndFooter()}
342
356
  </div>`}
343
357
  </dialog>`;
344
358
  }
345
359
  };
346
- L.styles = N(Q);
347
- let a = L;
360
+ z.styles = N(Q);
361
+ let a = z;
348
362
  l([
349
- r({ type: Object })
363
+ d({ type: Object })
350
364
  ], a.prototype, "aria");
351
365
  l([
352
- r({ type: String }),
353
- Y(b)
366
+ d({ type: String }),
367
+ Y(v)
354
368
  ], a.prototype, "heading");
355
369
  l([
356
- r(),
357
- B(b, Z, s.headingLevel)
370
+ d(),
371
+ _(v, Z, r.headingLevel)
358
372
  ], a.prototype, "headingLevel");
359
373
  l([
360
- r({ type: Boolean })
374
+ d({ type: Boolean })
361
375
  ], a.prototype, "hasBackButton");
362
376
  l([
363
- r({ type: Boolean })
377
+ d({ type: Boolean })
364
378
  ], a.prototype, "hasStackedActions");
365
379
  l([
366
- r({ type: Boolean, reflect: !0 })
380
+ d({ type: Boolean, reflect: !0 })
367
381
  ], a.prototype, "isDismissible");
368
382
  l([
369
- r({ type: Boolean })
383
+ d({ type: Boolean })
370
384
  ], a.prototype, "isFooterPinned");
371
385
  l([
372
- r({ type: Boolean })
386
+ d({ type: Boolean })
373
387
  ], a.prototype, "isFullWidthBelowMid");
374
388
  l([
375
- r({ type: Boolean, reflect: !0 })
389
+ d({ type: Boolean, reflect: !0 })
376
390
  ], a.prototype, "isLoading");
377
391
  l([
378
- r({ type: Boolean })
392
+ d({ type: Boolean })
379
393
  ], a.prototype, "isOpen");
380
394
  l([
381
- r({ type: Object })
395
+ d({ type: Object })
382
396
  ], a.prototype, "leadingAction");
383
397
  l([
384
- r(),
385
- B(b, oe, s.position)
398
+ d(),
399
+ _(v, eo, r.position)
386
400
  ], a.prototype, "position");
387
401
  l([
388
- r()
402
+ d()
389
403
  ], a.prototype, "returnFocusAfterCloseSelector");
390
404
  l([
391
- r(),
392
- B(b, ee, s.size)
405
+ d(),
406
+ _(v, oo, r.size)
393
407
  ], a.prototype, "size");
394
408
  l([
395
- r({ type: Object })
409
+ d({ type: Object })
396
410
  ], a.prototype, "supportingAction");
397
411
  l([
398
412
  R("dialog")
399
413
  ], a.prototype, "_dialog");
400
- V(b, a);
414
+ V(v, a);
401
415
  export {
402
- C as ON_MODAL_BACK_EVENT,
403
- z as ON_MODAL_CLOSE_EVENT,
404
- te as ON_MODAL_LEADING_ACTION_CLICK,
405
- w as ON_MODAL_OPEN_EVENT,
406
- ie as ON_MODAL_SUPPORTING_ACTION_CLICK,
416
+ L as ON_MODAL_BACK_EVENT,
417
+ A as ON_MODAL_CLOSE_EVENT,
418
+ to as ON_MODAL_LEADING_ACTION_CLICK,
419
+ x as ON_MODAL_OPEN_EVENT,
420
+ io as ON_MODAL_SUPPORTING_ACTION_CLICK,
407
421
  a as PieModal,
408
- s as defaultProps,
422
+ r as defaultProps,
409
423
  Z as headingLevels,
410
- oe as positions,
411
- ee as sizes
424
+ eo as positions,
425
+ oo as sizes
412
426
  };
package/dist/react.d.ts CHANGED
@@ -166,8 +166,10 @@ declare class PieModal_2 extends PieModal_base implements ModalProps {
166
166
  returnFocusAfterCloseSelector: ModalProps['returnFocusAfterCloseSelector'];
167
167
  size: "medium" | "large" | "small";
168
168
  supportingAction: ModalProps['supportingAction'];
169
- private _dialog?;
169
+ private _dialog;
170
170
  private _backButtonClicked;
171
+ private _abortController;
172
+ private get _modalScrollContainer();
171
173
  static styles: CSSResult;
172
174
  connectedCallback(): void;
173
175
  disconnectedCallback(): void;
@@ -196,6 +198,14 @@ declare class PieModal_2 extends PieModal_base implements ModalProps {
196
198
  * and the chosen element can be found.
197
199
  */
198
200
  private _returnFocus;
201
+ /**
202
+ * Enables body scroll by unlocking the scroll container.
203
+ */
204
+ private _enableBodyScroll;
205
+ /**
206
+ * Disables body scroll by locking the scroll container.
207
+ */
208
+ private _disableBodyScroll;
199
209
  /**
200
210
  * Template for the close button element. Called within the
201
211
  * main render function.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@justeattakeaway/pie-modal",
3
- "version": "0.47.0",
3
+ "version": "0.48.0",
4
4
  "description": "PIE design system modal built using web components",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -47,11 +47,11 @@
47
47
  "extends": "../../../package.json"
48
48
  },
49
49
  "dependencies": {
50
- "@justeattakeaway/pie-button": "0.49.1",
51
- "@justeattakeaway/pie-icon-button": "0.28.12",
52
- "@justeattakeaway/pie-icons-webc": "0.25.1",
53
- "@justeattakeaway/pie-spinner": "0.7.0",
54
- "@justeattakeaway/pie-webc-core": "0.24.0",
50
+ "@justeattakeaway/pie-button": "0.49.2",
51
+ "@justeattakeaway/pie-icon-button": "0.28.13",
52
+ "@justeattakeaway/pie-icons-webc": "0.25.2",
53
+ "@justeattakeaway/pie-spinner": "0.7.1",
54
+ "@justeattakeaway/pie-webc-core": "0.24.1",
55
55
  "body-scroll-lock": "3.1.5",
56
56
  "dialog-polyfill": "0.5.6"
57
57
  },
package/src/index.ts CHANGED
@@ -104,44 +104,56 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
104
104
  public supportingAction: ModalProps['supportingAction'];
105
105
 
106
106
  @query('dialog')
107
- private _dialog?: HTMLDialogElement;
107
+ private _dialog!: HTMLDialogElement;
108
108
 
109
109
  private _backButtonClicked = false;
110
110
 
111
+ private _abortController!: AbortController;
112
+
113
+ private get _modalScrollContainer (): Element | null {
114
+ return this._dialog.querySelector('.c-modal-scrollContainer');
115
+ }
116
+
111
117
  // Renders a `CSSResult` generated from SCSS by Vite
112
118
  static styles = unsafeCSS(styles);
113
119
 
114
- connectedCallback () : void {
120
+ connectedCallback (): void {
115
121
  super.connectedCallback();
122
+ this._abortController = new AbortController();
123
+ const { signal } = this._abortController;
124
+
116
125
  this.addEventListener('click', (event) => this._handleDialogLightDismiss(event));
117
- document.addEventListener(ON_MODAL_OPEN_EVENT, (event) => this._handleModalOpened(<CustomEvent>event));
118
- document.addEventListener(ON_MODAL_CLOSE_EVENT, (event) => this._handleModalClosed(<CustomEvent>event));
119
- document.addEventListener(ON_MODAL_BACK_EVENT, (event) => this._handleModalClosed(<CustomEvent>event));
126
+ document.addEventListener(ON_MODAL_OPEN_EVENT, (event) => this._handleModalOpened(<CustomEvent>event), { signal });
127
+ document.addEventListener(ON_MODAL_CLOSE_EVENT, (event) => this._handleModalClosed(<CustomEvent>event), { signal });
128
+ document.addEventListener(ON_MODAL_BACK_EVENT, (event) => this._handleModalClosed(<CustomEvent>event), { signal });
120
129
  }
121
130
 
122
- disconnectedCallback () : void {
123
- document.removeEventListener(ON_MODAL_OPEN_EVENT, (event) => this._handleModalOpened(<CustomEvent>event));
124
- document.removeEventListener(ON_MODAL_CLOSE_EVENT, (event) => this._handleModalClosed(<CustomEvent>event));
125
- document.removeEventListener(ON_MODAL_BACK_EVENT, (event) => this._handleModalClosed(<CustomEvent>event));
131
+ disconnectedCallback (): void {
132
+ // Aborts all event listeners
133
+ this._abortController.abort();
134
+
135
+ this._enableBodyScroll();
126
136
  super.disconnectedCallback();
127
137
  }
128
138
 
129
- async firstUpdated (changedProperties: PropertyValues<this>) : Promise<void> {
139
+ async firstUpdated (changedProperties: PropertyValues<this>): Promise<void> {
130
140
  super.firstUpdated(changedProperties);
131
141
 
132
142
  if (this._dialog) {
133
143
  const dialogPolyfill = await import('dialog-polyfill').then((module) => module.default);
134
144
  dialogPolyfill.registerDialog(this._dialog);
135
- this._dialog.addEventListener('cancel', (event) => this._handleDialogCancelEvent(event));
145
+ const { signal } = this._abortController;
146
+
147
+ this._dialog.addEventListener('cancel', (event) => this._handleDialogCancelEvent(event), { signal });
136
148
  this._dialog.addEventListener('close', () => {
137
149
  this.isOpen = false;
138
- });
150
+ }, { signal });
139
151
  }
140
152
 
141
153
  this._handleModalOpenStateOnFirstRender(changedProperties);
142
154
  }
143
155
 
144
- updated (changedProperties: PropertyValues<this>) : void {
156
+ updated (changedProperties: PropertyValues<this>): void {
145
157
  super.updated(changedProperties);
146
158
  this._handleModalOpenStateChanged(changedProperties);
147
159
  }
@@ -153,22 +165,14 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
153
165
  const { targetModal } = event.detail;
154
166
 
155
167
  if (targetModal === this) {
156
- const modalScrollContainer = this._dialog?.querySelector('.c-modal-scrollContainer');
168
+ this._disableBodyScroll();
157
169
 
158
- if (modalScrollContainer) {
159
- // Hack to prevent Safari rendering the modal outside the viewport
160
- // when the body scroll lock is active
161
- if ('scrollTo' in window) window.scrollTo(0, 0);
162
-
163
- disableBodyScroll(modalScrollContainer);
164
- }
165
-
166
- if (this._dialog?.hasAttribute('open') || !this._dialog?.isConnected) {
170
+ if (this._dialog.hasAttribute('open') || !this._dialog.isConnected) {
167
171
  return;
168
172
  }
169
173
 
170
174
  // The ::backdrop pseudoelement is only shown if the modal is opened via JS
171
- this._dialog?.showModal();
175
+ this._dialog.showModal();
172
176
  }
173
177
  }
174
178
 
@@ -179,13 +183,8 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
179
183
  const { targetModal } = event.detail;
180
184
 
181
185
  if (targetModal === this) {
182
- const modalScrollContainer = this._dialog?.querySelector('.c-modal-scrollContainer');
183
-
184
- if (modalScrollContainer) {
185
- enableBodyScroll(modalScrollContainer);
186
- }
187
-
188
- this._dialog?.close();
186
+ this._enableBodyScroll();
187
+ this._dialog.close();
189
188
  this._returnFocus();
190
189
  }
191
190
  }
@@ -196,14 +195,14 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
196
195
  *
197
196
  * @param {Event} event - The event object.
198
197
  */
199
- private _handleDialogCancelEvent = (event: Event) : void => {
198
+ private _handleDialogCancelEvent = (event: Event): void => {
200
199
  if (!this.isDismissible) {
201
200
  event.preventDefault();
202
201
  }
203
202
  };
204
203
 
205
204
  // Handles the value of the isOpen property on first render of the component
206
- private _handleModalOpenStateOnFirstRender (changedProperties: PropertyValues<this>) : void {
205
+ private _handleModalOpenStateOnFirstRender (changedProperties: PropertyValues<this>): void {
207
206
  // This ensures if the modal is open on first render, the scroll lock and backdrop are applied
208
207
  const previousValue = changedProperties.get('isOpen');
209
208
 
@@ -213,7 +212,7 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
213
212
  }
214
213
 
215
214
  // Handles changes to the modal isOpen property by dispatching any appropriate events
216
- private _handleModalOpenStateChanged (changedProperties: PropertyValues<this>) : void {
215
+ private _handleModalOpenStateChanged (changedProperties: PropertyValues<this>): void {
217
216
  const wasPreviouslyOpen = changedProperties.get('isOpen');
218
217
 
219
218
  if (wasPreviouslyOpen !== undefined) {
@@ -231,12 +230,12 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
231
230
  }
232
231
  }
233
232
 
234
- private _handleActionClick (actionType: ModalActionType) : void {
233
+ private _handleActionClick (actionType: ModalActionType): void {
235
234
  if (actionType === 'leading') {
236
- this._dialog?.close('leading');
235
+ this._dialog.close('leading');
237
236
  dispatchCustomEvent(this, ON_MODAL_LEADING_ACTION_CLICK, { targetModal: this });
238
237
  } else if (actionType === 'supporting') {
239
- this._dialog?.close('supporting');
238
+ this._dialog.close('supporting');
240
239
  dispatchCustomEvent(this, ON_MODAL_SUPPORTING_ACTION_CLICK, { targetModal: this });
241
240
  }
242
241
  }
@@ -245,7 +244,7 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
245
244
  * Return focus to the specified element, providing the selector is valid
246
245
  * and the chosen element can be found.
247
246
  */
248
- private _returnFocus () : void {
247
+ private _returnFocus (): void {
249
248
  const selector = this.returnFocusAfterCloseSelector?.trim();
250
249
 
251
250
  if (selector) {
@@ -253,6 +252,28 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
253
252
  }
254
253
  }
255
254
 
255
+ /**
256
+ * Enables body scroll by unlocking the scroll container.
257
+ */
258
+ private _enableBodyScroll (): void {
259
+ if (this._modalScrollContainer) {
260
+ enableBodyScroll(this._modalScrollContainer);
261
+ }
262
+ }
263
+
264
+ /**
265
+ * Disables body scroll by locking the scroll container.
266
+ */
267
+ private _disableBodyScroll (): void {
268
+ if (this._modalScrollContainer) {
269
+ // Hack to prevent Safari rendering the modal outside the viewport
270
+ // when the body scroll lock is active
271
+ if ('scrollTo' in window) window.scrollTo(0, 0);
272
+
273
+ disableBodyScroll(this._modalScrollContainer);
274
+ }
275
+ }
276
+
256
277
  /**
257
278
  * Template for the close button element. Called within the
258
279
  * main render function.
@@ -281,7 +302,7 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
281
302
  *
282
303
  * @private
283
304
  */
284
- private renderBackButton () : TemplateResult | typeof nothing {
305
+ private renderBackButton (): TemplateResult | typeof nothing {
285
306
  if (!this.hasBackButton) {
286
307
  return nothing;
287
308
  }
@@ -307,7 +328,7 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
307
328
  *
308
329
  * @private
309
330
  */
310
- private renderLeadingAction () : TemplateResult | typeof nothing {
331
+ private renderLeadingAction (): TemplateResult | typeof nothing {
311
332
  const { ariaLabel, text, variant = 'primary' } = this.leadingAction || {};
312
333
 
313
334
  if (!text) return nothing;
@@ -361,7 +382,7 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
361
382
  *
362
383
  * @private
363
384
  */
364
- private renderModalFooter () : TemplateResult | typeof nothing {
385
+ private renderModalFooter (): TemplateResult | typeof nothing {
365
386
  if (!this.leadingAction?.text) {
366
387
  if (this.supportingAction?.text) {
367
388
  console.warn('You cannot have a supporting action without a leading action. If you only need one button then use a leading action instead.');
@@ -385,7 +406,7 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
385
406
  * Renders the loading spinner if `isLoading` is true.
386
407
  * @private
387
408
  */
388
- private renderLoadingSpinner () : TemplateResult | typeof nothing {
409
+ private renderLoadingSpinner (): TemplateResult | typeof nothing {
389
410
  if (!this.isLoading) {
390
411
  return nothing;
391
412
  }
@@ -397,7 +418,7 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
397
418
  * Renders the modal inner content and footer of the modal.
398
419
  * @private
399
420
  */
400
- private renderModalContentAndFooter () : TemplateResult {
421
+ private renderModalContentAndFooter (): TemplateResult {
401
422
  return html`
402
423
  <article class="c-modal-scrollContainer c-modal-content c-modal-content--scrollable">
403
424
  <div class="c-modal-contentInner" data-test-id="modal-content-inner">
@@ -465,12 +486,12 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
465
486
  * Dismisses the modal on backdrop click if `isDismissible` is `true`.
466
487
  * @param {MouseEvent} event - the click event targetting the modal/backdrop
467
488
  */
468
- private _handleDialogLightDismiss = (event: MouseEvent) : void => {
489
+ private _handleDialogLightDismiss = (event: MouseEvent): void => {
469
490
  if (!this.isDismissible) {
470
491
  return;
471
492
  }
472
493
 
473
- const rect = this._dialog?.getBoundingClientRect();
494
+ const rect = this._dialog.getBoundingClientRect();
474
495
 
475
496
  const {
476
497
  top = 0, bottom = 0, left = 0, right = 0,