@justeattakeaway/pie-modal 0.43.5 → 0.45.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.
@@ -178,7 +178,7 @@
178
178
  "kind": "field",
179
179
  "name": "aria",
180
180
  "type": {
181
- "text": "AriaProps"
181
+ "text": "ModalProps['aria']"
182
182
  },
183
183
  "privacy": "public",
184
184
  "attribute": "aria"
@@ -195,9 +195,6 @@
195
195
  {
196
196
  "kind": "field",
197
197
  "name": "headingLevel",
198
- "type": {
199
- "text": "ModalProps['headingLevel']"
200
- },
201
198
  "privacy": "public",
202
199
  "attribute": "headingLevel"
203
200
  },
@@ -249,7 +246,7 @@
249
246
  "kind": "field",
250
247
  "name": "leadingAction",
251
248
  "type": {
252
- "text": "ActionProps"
249
+ "text": "ModalProps['leadingAction']"
253
250
  },
254
251
  "privacy": "public",
255
252
  "attribute": "leadingAction"
@@ -257,9 +254,6 @@
257
254
  {
258
255
  "kind": "field",
259
256
  "name": "position",
260
- "type": {
261
- "text": "ModalProps['position']"
262
- },
263
257
  "privacy": "public",
264
258
  "attribute": "position"
265
259
  },
@@ -267,7 +261,7 @@
267
261
  "kind": "field",
268
262
  "name": "returnFocusAfterCloseSelector",
269
263
  "type": {
270
- "text": "string | undefined"
264
+ "text": "ModalProps['returnFocusAfterCloseSelector']"
271
265
  },
272
266
  "privacy": "public",
273
267
  "attribute": "returnFocusAfterCloseSelector"
@@ -275,9 +269,6 @@
275
269
  {
276
270
  "kind": "field",
277
271
  "name": "size",
278
- "type": {
279
- "text": "ModalProps['size']"
280
- },
281
272
  "privacy": "public",
282
273
  "attribute": "size"
283
274
  },
@@ -285,7 +276,7 @@
285
276
  "kind": "field",
286
277
  "name": "supportingAction",
287
278
  "type": {
288
- "text": "ActionProps"
279
+ "text": "ModalProps['supportingAction']"
289
280
  },
290
281
  "privacy": "public",
291
282
  "attribute": "supportingAction"
@@ -431,7 +422,7 @@
431
422
  "privacy": "private",
432
423
  "return": {
433
424
  "type": {
434
- "text": "TemplateResult"
425
+ "text": "TemplateResult | typeof nothing"
435
426
  }
436
427
  },
437
428
  "description": "Template for the close button element. Called within the\nmain render function."
@@ -442,7 +433,7 @@
442
433
  "privacy": "private",
443
434
  "return": {
444
435
  "type": {
445
- "text": "TemplateResult"
436
+ "text": "TemplateResult | typeof nothing"
446
437
  }
447
438
  },
448
439
  "description": "Template for the back button element. Called within the\nmain render function."
@@ -456,7 +447,7 @@
456
447
  "text": "TemplateResult | typeof nothing"
457
448
  }
458
449
  },
459
- "description": "Render leadingAction button depending on prop availability.\n\n1. If the prop `leadingAction` is not provided, the button is not rendered.\n2. If the prop `leadingAction` is provided but any of the optional properties\nare not provided, they fall back to their default values."
450
+ "description": "Renders the \"leadingAction\" button if the text is provided.\n\nIf `leadingAction.text` is not provided, the button is not rendered.\nIf `leadingAction.variant` is not provided, the default value of \"primary\" is used.\nThe (optional) aria-label is read from `leadingAction.ariaLabel`."
460
451
  },
461
452
  {
462
453
  "kind": "method",
@@ -467,7 +458,7 @@
467
458
  "text": "TemplateResult | typeof nothing"
468
459
  }
469
460
  },
470
- "description": "Render supportingAction button depending on prop availability.\n\n1. If the prop `supportingAction` is not provided, the button is not rendered.\n2. If the prop `supportingAction` is provided but any of the optional properties\nare not provided, they fall back to their default values.\n3. If `supportingAction` is provided but not `leadingAction`, log a warning and do\nnot render `supportingAction`."
461
+ "description": "Renders the \"supportingAction\" button if the text is provided.\nYou cannot have a supporting action without a leading action.\n\nIf either `supportingAction.text` or `leadingAction.text` are not provided, the button is not rendered.\nIf `supportingAction.variant` is not provided, the default value of \"ghost\" is used.\nThe (optional) aria-label is read from `supportingAction.ariaLabel`."
471
462
  },
472
463
  {
473
464
  "kind": "method",
@@ -537,7 +528,7 @@
537
528
  {
538
529
  "name": "aria",
539
530
  "type": {
540
- "text": "AriaProps"
531
+ "text": "ModalProps['aria']"
541
532
  },
542
533
  "fieldName": "aria"
543
534
  },
@@ -550,9 +541,6 @@
550
541
  },
551
542
  {
552
543
  "name": "headingLevel",
553
- "type": {
554
- "text": "ModalProps['headingLevel']"
555
- },
556
544
  "fieldName": "headingLevel"
557
545
  },
558
546
  {
@@ -586,35 +574,29 @@
586
574
  {
587
575
  "name": "leadingAction",
588
576
  "type": {
589
- "text": "ActionProps"
577
+ "text": "ModalProps['leadingAction']"
590
578
  },
591
579
  "fieldName": "leadingAction"
592
580
  },
593
581
  {
594
582
  "name": "position",
595
- "type": {
596
- "text": "ModalProps['position']"
597
- },
598
583
  "fieldName": "position"
599
584
  },
600
585
  {
601
586
  "name": "returnFocusAfterCloseSelector",
602
587
  "type": {
603
- "text": "string | undefined"
588
+ "text": "ModalProps['returnFocusAfterCloseSelector']"
604
589
  },
605
590
  "fieldName": "returnFocusAfterCloseSelector"
606
591
  },
607
592
  {
608
593
  "name": "size",
609
- "type": {
610
- "text": "ModalProps['size']"
611
- },
612
594
  "fieldName": "size"
613
595
  },
614
596
  {
615
597
  "name": "supportingAction",
616
598
  "type": {
617
- "text": "ActionProps"
599
+ "text": "ModalProps['supportingAction']"
618
600
  },
619
601
  "fieldName": "supportingAction"
620
602
  }
package/dist/index.d.ts CHANGED
@@ -7,7 +7,7 @@ import type { RTLInterface } from '@justeattakeaway/pie-webc-core';
7
7
  import type { TemplateResult } from 'lit';
8
8
  import { Variant } from '@justeattakeaway/pie-button/src/defs.ts';
9
9
 
10
- export declare type ActionProps = {
10
+ declare type ActionProps = {
11
11
  /**
12
12
  * The text to display inside the button.
13
13
  */
@@ -17,7 +17,7 @@ export declare type ActionProps = {
17
17
  */
18
18
  variant?: Variant;
19
19
  /**
20
- * The ARIA label for the button.
20
+ * The aria label for the button.
21
21
  */
22
22
  ariaLabel?: string;
23
23
  };
@@ -42,7 +42,7 @@ export declare interface ModalEventDetail {
42
42
 
43
43
  export declare type ModalProps = {
44
44
  /**
45
- * The ARIA labels used for the modal close and back buttons, as well as loading state.
45
+ * The ARIA labels used for the modal close and back buttons, as well as for the loading state.
46
46
  */
47
47
  aria?: AriaProps;
48
48
  /**
@@ -152,9 +152,9 @@ export declare const ON_MODAL_SUPPORTING_ACTION_CLICK = "pie-modal-supporting-ac
152
152
  * @event {CustomEvent} pie-modal-supporting-action-click - when the modal supporting action is clicked.
153
153
  */
154
154
  export declare class PieModal extends PieModal_base implements ModalProps {
155
- aria: AriaProps;
155
+ aria: ModalProps['aria'];
156
156
  heading: string;
157
- headingLevel: ModalProps['headingLevel'];
157
+ headingLevel: "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
158
158
  hasBackButton: boolean;
159
159
  hasStackedActions: boolean;
160
160
  isDismissible: boolean;
@@ -162,11 +162,11 @@ export declare class PieModal extends PieModal_base implements ModalProps {
162
162
  isFullWidthBelowMid: boolean;
163
163
  isLoading: boolean;
164
164
  isOpen: boolean;
165
- leadingAction: ActionProps;
166
- position: ModalProps['position'];
167
- returnFocusAfterCloseSelector?: string;
168
- size: ModalProps['size'];
169
- supportingAction: ActionProps;
165
+ leadingAction: ModalProps['leadingAction'];
166
+ position: "top" | "center";
167
+ returnFocusAfterCloseSelector: ModalProps['returnFocusAfterCloseSelector'];
168
+ size: "medium" | "large" | "small";
169
+ supportingAction: ModalProps['supportingAction'];
170
170
  private _dialog?;
171
171
  private _backButtonClicked;
172
172
  static styles: CSSResult;
@@ -212,23 +212,22 @@ export declare class PieModal extends PieModal_base implements ModalProps {
212
212
  */
213
213
  private renderBackButton;
214
214
  /**
215
- * Render leadingAction button depending on prop availability.
215
+ * Renders the "leadingAction" button if the text is provided.
216
216
  *
217
- * 1. If the prop `leadingAction` is not provided, the button is not rendered.
218
- * 2. If the prop `leadingAction` is provided but any of the optional properties
219
- * are not provided, they fall back to their default values.
217
+ * If `leadingAction.text` is not provided, the button is not rendered.
218
+ * If `leadingAction.variant` is not provided, the default value of "primary" is used.
219
+ * The (optional) aria-label is read from `leadingAction.ariaLabel`.
220
220
  *
221
221
  * @private
222
222
  */
223
223
  private renderLeadingAction;
224
224
  /**
225
- * Render supportingAction button depending on prop availability.
225
+ * Renders the "supportingAction" button if the text is provided.
226
+ * You cannot have a supporting action without a leading action.
226
227
  *
227
- * 1. If the prop `supportingAction` is not provided, the button is not rendered.
228
- * 2. If the prop `supportingAction` is provided but any of the optional properties
229
- * are not provided, they fall back to their default values.
230
- * 3. If `supportingAction` is provided but not `leadingAction`, log a warning and do
231
- * not render `supportingAction`.
228
+ * If either `supportingAction.text` or `leadingAction.text` are not provided, the button is not rendered.
229
+ * If `supportingAction.variant` is not provided, the default value of "ghost" is used.
230
+ * The (optional) aria-label is read from `supportingAction.ariaLabel`.
232
231
  *
233
232
  * @private
234
233
  */
package/dist/index.js CHANGED
@@ -1,14 +1,16 @@
1
- import { LitElement as T, nothing as c, unsafeCSS as N } from "lit";
2
- import { html as g, unsafeStatic as I } from "lit/static-html.js";
3
- import { property as r, query as R } from "lit/decorators.js";
1
+ import { LitElement as I, nothing as g, unsafeCSS as N } from "lit";
2
+ import { html as m, unsafeStatic as R } from "lit/static-html.js";
3
+ import { property as d, query as W } from "lit/decorators.js";
4
+ import { classMap as j } from "lit/directives/class-map.js";
5
+ import { ifDefined as B } from "lit/directives/if-defined.js";
4
6
  import "@justeattakeaway/pie-button";
5
7
  import "@justeattakeaway/pie-icon-button";
6
- import { RtlMixin as W, dispatchCustomEvent as u, requiredProperty as j, validPropertyValues as B, defineCustomElement as Y } from "@justeattakeaway/pie-webc-core";
8
+ import { RtlMixin as Y, dispatchCustomEvent as u, requiredProperty as V, validPropertyValues as S, defineCustomElement as q } from "@justeattakeaway/pie-webc-core";
7
9
  import "@justeattakeaway/pie-icons-webc/dist/IconClose.js";
8
10
  import "@justeattakeaway/pie-icons-webc/dist/IconChevronLeft.js";
9
11
  import "@justeattakeaway/pie-icons-webc/dist/IconChevronRight.js";
10
12
  import "@justeattakeaway/pie-spinner";
11
- function V(n) {
13
+ function H(n) {
12
14
  if (Array.isArray(n)) {
13
15
  for (var e = 0, i = Array(n.length); e < n.length; e++)
14
16
  i[e] = n[e];
@@ -18,34 +20,34 @@ function V(n) {
18
20
  }
19
21
  var A = !1;
20
22
  if (typeof window < "u") {
21
- var L = {
23
+ var $ = {
22
24
  get passive() {
23
25
  A = !0;
24
26
  }
25
27
  };
26
- window.addEventListener("testPassive", null, L), window.removeEventListener("testPassive", null, L);
28
+ window.addEventListener("testPassive", null, $), window.removeEventListener("testPassive", null, $);
27
29
  }
28
- var S = 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 = [], y = !1, M = -1, f = void 0, v = void 0, $ = function(e) {
30
+ var D = 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 = [], y = !1, F = -1, f = void 0, v = void 0, P = function(e) {
29
31
  return p.some(function(i) {
30
32
  return !!(i.options.allowTouchMove && i.options.allowTouchMove(e));
31
33
  });
32
34
  }, x = function(e) {
33
35
  var i = e || window.event;
34
- return $(i.target) || i.touches.length > 1 ? !0 : (i.preventDefault && i.preventDefault(), !1);
35
- }, q = function(e) {
36
+ return P(i.target) || i.touches.length > 1 ? !0 : (i.preventDefault && i.preventDefault(), !1);
37
+ }, K = function(e) {
36
38
  if (v === void 0) {
37
39
  var i = !!e && e.reserveScrollBarGap === !0, o = window.innerWidth - document.documentElement.clientWidth;
38
40
  i && o > 0 && (v = document.body.style.paddingRight, document.body.style.paddingRight = o + "px");
39
41
  }
40
42
  f === void 0 && (f = document.body.style.overflow, document.body.style.overflow = "hidden");
41
- }, H = function() {
43
+ }, U = function() {
42
44
  v !== void 0 && (document.body.style.paddingRight = v, v = void 0), f !== void 0 && (document.body.style.overflow = f, f = void 0);
43
- }, U = function(e) {
45
+ }, G = function(e) {
44
46
  return e ? e.scrollHeight - e.scrollTop <= e.clientHeight : !1;
45
- }, K = function(e, i) {
46
- var o = e.targetTouches[0].clientY - M;
47
- return $(e.target) ? !1 : i && i.scrollTop === 0 && o > 0 || U(i) && o < 0 ? x(e) : (e.stopPropagation(), !0);
48
- }, G = function(e, i) {
47
+ }, X = function(e, i) {
48
+ var o = e.targetTouches[0].clientY - F;
49
+ return P(e.target) ? !1 : i && i.scrollTop === 0 && o > 0 || G(i) && o < 0 ? x(e) : (e.stopPropagation(), !0);
50
+ }, J = function(e, i) {
49
51
  if (!e) {
50
52
  console.error("disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.");
51
53
  return;
@@ -57,23 +59,23 @@ var S = typeof window < "u" && window.navigator && window.navigator.platform &&
57
59
  targetElement: e,
58
60
  options: i || {}
59
61
  };
60
- p = [].concat(V(p), [o]), S ? (e.ontouchstart = function(t) {
61
- t.targetTouches.length === 1 && (M = t.targetTouches[0].clientY);
62
+ p = [].concat(H(p), [o]), D ? (e.ontouchstart = function(t) {
63
+ t.targetTouches.length === 1 && (F = t.targetTouches[0].clientY);
62
64
  }, e.ontouchmove = function(t) {
63
- t.targetTouches.length === 1 && K(t, e);
64
- }, y || (document.addEventListener("touchmove", x, A ? { passive: !1 } : void 0), y = !0)) : q(i);
65
+ t.targetTouches.length === 1 && X(t, e);
66
+ }, y || (document.addEventListener("touchmove", x, A ? { passive: !1 } : void 0), y = !0)) : K(i);
65
67
  }
66
- }, X = function(e) {
68
+ }, Q = function(e) {
67
69
  if (!e) {
68
70
  console.error("enableBodyScroll unsuccessful - targetElement must be provided when calling enableBodyScroll on IOS devices.");
69
71
  return;
70
72
  }
71
73
  p = p.filter(function(i) {
72
74
  return i.targetElement !== e;
73
- }), S ? (e.ontouchstart = null, e.ontouchmove = null, y && p.length === 0 && (document.removeEventListener("touchmove", x, A ? { passive: !1 } : void 0), y = !1)) : p.length || H();
75
+ }), D ? (e.ontouchstart = null, e.ontouchmove = null, y && p.length === 0 && (document.removeEventListener("touchmove", x, A ? { passive: !1 } : void 0), y = !1)) : p.length || U();
74
76
  };
75
- const J = `*,*: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: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%)}.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 (width < 768px){.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)}}.c-modal[size=large]{--modal-inline-size: 75%;--modal-max-inline-size: var(--modal-size-l);--modal-margin-block: var(--modal-margin-large)}@media (width < 768px){.c-modal[size=large],.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=large]>.c-modal-scrollContainer,.c-modal[size=medium][isfullwidthbelowmid]>.c-modal-scrollContainer{block-size:100%}}.c-modal[position=top]{margin-block-start:var(--dt-spacing-j);max-block-size:calc(100% - var(--dt-spacing-j) * 2)}@media (width < 768px){.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 (width < 768px){.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-start:var(--dt-spacing-d);margin-inline-end: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-start:var(--dt-spacing-e);margin-inline-end: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-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: 768px){.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: 768px){.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);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-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: 768px){.c-modal .c-modal-content{--modal-content-padding-inline: var(--dt-spacing-e)}}.c-modal .c-modal-content.c-modal-hasFooterActions{padding-block-end:var(--modal-content-padding-block)}.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[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
- `, Q = ["h1", "h2", "h3", "h4", "h5", "h6"], Z = ["small", "medium", "large"], ee = ["top", "center"], _ = "pie-modal-close", w = "pie-modal-open", C = "pie-modal-back", ie = "pie-modal-leading-action-click", oe = "pie-modal-supporting-action-click", d = {
77
+ const Z = `*,*: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: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%)}.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 (width < 768px){.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)}}.c-modal[size=large]{--modal-inline-size: 75%;--modal-max-inline-size: var(--modal-size-l);--modal-margin-block: var(--modal-margin-large)}@media (width < 768px){.c-modal[size=large],.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=large]>.c-modal-scrollContainer,.c-modal[size=medium][isfullwidthbelowmid]>.c-modal-scrollContainer{block-size:100%}}.c-modal[position=top]{margin-block-start:var(--dt-spacing-j);max-block-size:calc(100% - var(--dt-spacing-j) * 2)}@media (width < 768px){.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 (width < 768px){.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-start:var(--dt-spacing-d);margin-inline-end: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-start:var(--dt-spacing-e);margin-inline-end: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-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: 768px){.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: 768px){.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: 768px){.c-modal .c-modal-content{--modal-content-padding-inline: var(--dt-spacing-e)}}.c-modal .c-modal-content.c-modal-hasFooterActions{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[isfooterpinned] .c-modal-content{overflow-y:auto}.c-modal[isLoading] .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[isLoading] .c-modal-content .c-modal-contentInner{display:none}.c-modal[isLoading] .c-modal-content.c-modal-hasFooterActions pie-spinner{top:50%}@supports not (aspect-ratio: 1/1){.c-modal .c-modal-scrollContainer{background:none}}
78
+ `, ee = ["h1", "h2", "h3", "h4", "h5", "h6"], ie = ["small", "medium", "large"], oe = ["top", "center"], O = "pie-modal-close", w = "pie-modal-open", L = "pie-modal-back", te = "pie-modal-leading-action-click", ae = "pie-modal-supporting-action-click", s = {
77
79
  hasBackButton: !1,
78
80
  hasStackedActions: !1,
79
81
  headingLevel: "h2",
@@ -85,15 +87,15 @@ const J = `*,*:after,*:before{box-sizing:inherit}dialog{position:absolute;left:0
85
87
  position: "center",
86
88
  size: "medium"
87
89
  };
88
- var te = Object.defineProperty, ae = Object.getOwnPropertyDescriptor, l = (n, e, i, o) => {
89
- for (var t = o > 1 ? void 0 : o ? ae(e, i) : e, s = n.length - 1, m; s >= 0; s--)
90
- (m = n[s]) && (t = (o ? m(e, i, t) : m(t)) || t);
91
- return o && t && te(e, i, t), t;
90
+ var ne = Object.defineProperty, le = Object.getOwnPropertyDescriptor, l = (n, e, i, o) => {
91
+ for (var t = o > 1 ? void 0 : o ? le(e, i) : e, r = n.length - 1, c; r >= 0; r--)
92
+ (c = n[r]) && (t = (o ? c(e, i, t) : c(t)) || t);
93
+ return o && t && ne(e, i, t), t;
92
94
  };
93
95
  const b = "pie-modal";
94
- class a extends W(T) {
96
+ class a extends Y(I) {
95
97
  constructor() {
96
- super(...arguments), this.headingLevel = d.headingLevel, this.hasBackButton = d.hasBackButton, this.hasStackedActions = d.hasStackedActions, this.isDismissible = d.isDismissible, this.isFooterPinned = d.isFooterPinned, this.isFullWidthBelowMid = d.isFullWidthBelowMid, this.isLoading = d.isLoading, this.isOpen = d.isOpen, this.position = d.position, this.size = d.size, this._backButtonClicked = !1, this._handleDialogCancelEvent = (e) => {
98
+ 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
99
  this.isDismissible || e.preventDefault();
98
100
  }, this._handleDialogLightDismiss = (e) => {
99
101
  var k;
@@ -102,19 +104,19 @@ class a extends W(T) {
102
104
  const i = (k = this._dialog) == null ? void 0 : k.getBoundingClientRect(), {
103
105
  top: o = 0,
104
106
  bottom: t = 0,
105
- left: s = 0,
106
- right: m = 0
107
+ left: r = 0,
108
+ right: c = 0
107
109
  } = i || {};
108
- if (o === 0 && t === 0 && s === 0 && m === 0)
110
+ if (o === 0 && t === 0 && r === 0 && c === 0)
109
111
  return;
110
- (e.clientY < o || e.clientY > t || e.clientX < s || e.clientX > m) && (this.isOpen = !1);
112
+ (e.clientY < o || e.clientY > t || e.clientX < r || e.clientX > c) && (this.isOpen = !1);
111
113
  };
112
114
  }
113
115
  connectedCallback() {
114
- super.connectedCallback(), this.addEventListener("click", (e) => this._handleDialogLightDismiss(e)), document.addEventListener(w, (e) => this._handleModalOpened(e)), document.addEventListener(_, (e) => this._handleModalClosed(e)), document.addEventListener(C, (e) => this._handleModalClosed(e));
116
+ super.connectedCallback(), this.addEventListener("click", (e) => this._handleDialogLightDismiss(e)), document.addEventListener(w, (e) => this._handleModalOpened(e)), document.addEventListener(O, (e) => this._handleModalClosed(e)), document.addEventListener(L, (e) => this._handleModalClosed(e));
115
117
  }
116
118
  disconnectedCallback() {
117
- document.removeEventListener(w, (e) => this._handleModalOpened(e)), document.removeEventListener(_, (e) => this._handleModalClosed(e)), document.removeEventListener(C, (e) => this._handleModalClosed(e)), super.disconnectedCallback();
119
+ document.removeEventListener(w, (e) => this._handleModalOpened(e)), document.removeEventListener(O, (e) => this._handleModalClosed(e)), document.removeEventListener(L, (e) => this._handleModalClosed(e)), super.disconnectedCallback();
118
120
  }
119
121
  async firstUpdated(e) {
120
122
  super.firstUpdated(e), this._dialog && ((await import("./dialog-polyfill.esm-209f54f8.js").then((o) => o.default)).registerDialog(this._dialog), this._dialog.addEventListener("cancel", (o) => this._handleDialogCancelEvent(o)), this._dialog.addEventListener("close", () => {
@@ -128,13 +130,13 @@ class a extends W(T) {
128
130
  * Opens the dialog element and disables page scrolling
129
131
  */
130
132
  _handleModalOpened(e) {
131
- var o, t, s, m;
133
+ var o, t, r, c;
132
134
  const { targetModal: i } = e.detail;
133
135
  if (i === this) {
134
136
  const h = (o = this._dialog) == null ? void 0 : o.querySelector(".c-modal-scrollContainer");
135
- if (h && ("scrollTo" in window && window.scrollTo(0, 0), G(h)), (t = this._dialog) != null && t.hasAttribute("open") || !((s = this._dialog) != null && s.isConnected))
137
+ if (h && ("scrollTo" in window && window.scrollTo(0, 0), J(h)), (t = this._dialog) != null && t.hasAttribute("open") || !((r = this._dialog) != null && r.isConnected))
136
138
  return;
137
- (m = this._dialog) == null || m.showModal();
139
+ (c = this._dialog) == null || c.showModal();
138
140
  }
139
141
  }
140
142
  /**
@@ -144,8 +146,8 @@ class a extends W(T) {
144
146
  var o, t;
145
147
  const { targetModal: i } = e.detail;
146
148
  if (i === this) {
147
- const s = (o = this._dialog) == null ? void 0 : o.querySelector(".c-modal-scrollContainer");
148
- s && X(s), (t = this._dialog) == null || t.close(), this._returnFocus();
149
+ const r = (o = this._dialog) == null ? void 0 : o.querySelector(".c-modal-scrollContainer");
150
+ r && Q(r), (t = this._dialog) == null || t.close(), this._returnFocus();
149
151
  }
150
152
  }
151
153
  // Handles the value of the isOpen property on first render of the component
@@ -155,11 +157,11 @@ class a extends W(T) {
155
157
  // Handles changes to the modal isOpen property by dispatching any appropriate events
156
158
  _handleModalOpenStateChanged(e) {
157
159
  const i = e.get("isOpen");
158
- i !== void 0 && (i ? this._backButtonClicked ? (this._backButtonClicked = !1, u(this, C, { targetModal: this })) : u(this, _, { targetModal: this }) : u(this, w, { targetModal: this }));
160
+ i !== void 0 && (i ? this._backButtonClicked ? (this._backButtonClicked = !1, u(this, L, { targetModal: this })) : u(this, O, { targetModal: this }) : u(this, w, { targetModal: this }));
159
161
  }
160
162
  _handleActionClick(e) {
161
163
  var i, o;
162
- e === "leading" ? ((i = this._dialog) == null || i.close("leading"), u(this, ie, { targetModal: this })) : e === "supporting" && ((o = this._dialog) == null || o.close("supporting"), u(this, oe, { targetModal: this }));
164
+ e === "leading" ? ((i = this._dialog) == null || i.close("leading"), u(this, te, { targetModal: this })) : e === "supporting" && ((o = this._dialog) == null || o.close("supporting"), u(this, ae, { targetModal: this }));
163
165
  }
164
166
  /**
165
167
  * Return focus to the specified element, providing the selector is valid
@@ -178,17 +180,17 @@ class a extends W(T) {
178
180
  */
179
181
  renderCloseButton() {
180
182
  var e;
181
- return g`
183
+ return this.isDismissible ? m`
182
184
  <pie-icon-button
183
185
  @click="${() => {
184
186
  this.isOpen = !1;
185
187
  }}"
186
188
  variant="ghost-secondary"
187
189
  class="c-modal-closeBtn"
188
- aria-label="${((e = this.aria) == null ? void 0 : e.close) || c}"
190
+ aria-label="${((e = this.aria) == null ? void 0 : e.close) || g}"
189
191
  data-test-id="modal-close-button">
190
192
  <icon-close></icon-close>
191
- </pie-icon-button>`;
193
+ </pie-icon-button>` : g;
192
194
  }
193
195
  /**
194
196
  * Template for the back button element. Called within the
@@ -198,88 +200,91 @@ class a extends W(T) {
198
200
  */
199
201
  renderBackButton() {
200
202
  var e;
201
- return g`
203
+ return this.hasBackButton ? m`
202
204
  <pie-icon-button
203
205
  @click="${() => {
204
206
  this._backButtonClicked = !0, this.isOpen = !1;
205
207
  }}"
206
208
  variant="ghost-secondary"
207
209
  class="c-modal-backBtn"
208
- aria-label="${((e = this.aria) == null ? void 0 : e.back) || c}"
210
+ aria-label="${B((e = this.aria) == null ? void 0 : e.back)}"
209
211
  data-test-id="modal-back-button">
210
- ${this.isRTL ? g`<icon-chevron-right></icon-chevron-right>` : g`<icon-chevron-left></icon-chevron-left>`}
212
+ ${this.isRTL ? m`<icon-chevron-right></icon-chevron-right>` : m`<icon-chevron-left></icon-chevron-left>`}
211
213
  </pie-icon-button>
212
- `;
214
+ ` : g;
213
215
  }
214
216
  /**
215
- * Render leadingAction button depending on prop availability.
217
+ * Renders the "leadingAction" button if the text is provided.
216
218
  *
217
- * 1. If the prop `leadingAction` is not provided, the button is not rendered.
218
- * 2. If the prop `leadingAction` is provided but any of the optional properties
219
- * are not provided, they fall back to their default values.
219
+ * If `leadingAction.text` is not provided, the button is not rendered.
220
+ * If `leadingAction.variant` is not provided, the default value of "primary" is used.
221
+ * The (optional) aria-label is read from `leadingAction.ariaLabel`.
220
222
  *
221
223
  * @private
222
224
  */
223
225
  renderLeadingAction() {
224
- const { text: e, variant: i = "primary", ariaLabel: o } = this.leadingAction;
225
- return e ? g`
226
+ const { ariaLabel: e, text: i, variant: o = "primary" } = this.leadingAction || {};
227
+ return i ? m`
226
228
  <pie-button
227
- variant="${i}"
228
- aria-label="${o || c}"
229
+ variant="${o}"
230
+ aria-label="${B(e)}"
229
231
  type="submit"
230
232
  ?isFullWidth="${this.hasStackedActions}"
231
233
  @click="${() => this._handleActionClick("leading")}"
232
234
  data-test-id="modal-leading-action">
233
- ${e}
235
+ ${i}
234
236
  </pie-button>
235
- ` : c;
237
+ ` : g;
236
238
  }
237
239
  /**
238
- * Render supportingAction button depending on prop availability.
240
+ * Renders the "supportingAction" button if the text is provided.
241
+ * You cannot have a supporting action without a leading action.
239
242
  *
240
- * 1. If the prop `supportingAction` is not provided, the button is not rendered.
241
- * 2. If the prop `supportingAction` is provided but any of the optional properties
242
- * are not provided, they fall back to their default values.
243
- * 3. If `supportingAction` is provided but not `leadingAction`, log a warning and do
244
- * not render `supportingAction`.
243
+ * If either `supportingAction.text` or `leadingAction.text` are not provided, the button is not rendered.
244
+ * If `supportingAction.variant` is not provided, the default value of "ghost" is used.
245
+ * The (optional) aria-label is read from `supportingAction.ariaLabel`.
245
246
  *
246
247
  * @private
247
248
  */
248
249
  renderSupportingAction() {
249
- const { text: e, variant: i = "ghost", ariaLabel: o } = this.supportingAction;
250
- return e ? this.leadingAction ? g`
250
+ var t;
251
+ const { ariaLabel: e, text: i, variant: o = "ghost" } = this.supportingAction || {};
252
+ return i ? (t = this.leadingAction) != null && t.text ? m`
251
253
  <pie-button
252
- variant="${i}"
253
- aria-label="${o || c}"
254
+ variant="${o}"
255
+ aria-label="${B(e)}"
254
256
  type="reset"
255
257
  ?isFullWidth="${this.hasStackedActions}"
256
258
  @click="${() => this._handleActionClick("supporting")}"
257
259
  data-test-id="modal-supporting-action">
258
- ${e}
260
+ ${i}
259
261
  </pie-button>
260
- ` : (console.warn("Use `leadingAction` instead of `supportingAction`. `supportingAction` is being ignored."), c) : c;
262
+ ` : (console.warn("You cannot have a supporting action without a leading action. If you only need one button then use a leading action instead."), g) : g;
261
263
  }
262
264
  /**
263
265
  * Renders the modal inner content and footer of the modal.
264
266
  * @private
265
267
  */
266
268
  renderModalContentAndFooter() {
267
- var i, o;
268
- const e = (i = this.leadingAction) == null ? void 0 : i.text;
269
- return g`
270
- <article class="c-modal-scrollContainer c-modal-content c-modal-content--scrollable ${e ? "c-modal-hasFooterActions" : ""}">
271
- <div class="c-modal-contentInner"
272
- data-test-id="modal-content-inner">
269
+ var o;
270
+ const e = !!((o = this.leadingAction) != null && o.text);
271
+ return m`
272
+ <article class=${j({
273
+ "c-modal-scrollContainer": !0,
274
+ "c-modal-content": !0,
275
+ "c-modal-content--scrollable": !0,
276
+ "c-modal-hasFooterActions": e
277
+ })}>
278
+ <div class="c-modal-contentInner" data-test-id="modal-content-inner">
273
279
  <slot></slot>
274
280
  </div>
275
- ${this.isLoading ? g`<pie-spinner size="xlarge" variant="secondary"></pie-spinner>` : c}
281
+ ${this.isLoading ? m`<pie-spinner size="xlarge" variant="secondary"></pie-spinner>` : g}
276
282
  </article>
277
- ${e ? g`
278
- <footer class="c-modal-footer"
279
- data-test-id="pie-modal-footer">
283
+ ${e ? m`
284
+ <footer class="c-modal-footer" data-test-id="pie-modal-footer">
280
285
  ${this.renderLeadingAction()}
281
- ${(o = this.supportingAction) != null && o.text ? this.renderSupportingAction() : c}
282
- </footer>` : c}`;
286
+ ${this.renderSupportingAction()}
287
+ </footer>` : g}`;
283
288
  }
284
289
  render() {
285
290
  const {
@@ -287,42 +292,42 @@ class a extends W(T) {
287
292
  hasBackButton: i,
288
293
  hasStackedActions: o,
289
294
  heading: t,
290
- headingLevel: s = "h2",
291
- isDismissible: m,
295
+ headingLevel: r,
296
+ isDismissible: c,
292
297
  isFooterPinned: h,
293
298
  isFullWidthBelowMid: k,
294
299
  isLoading: z,
295
- leadingAction: D,
296
- position: F,
297
- size: P,
298
- supportingAction: E
299
- } = this, O = I(s);
300
- return g`
300
+ leadingAction: _,
301
+ position: E,
302
+ size: T,
303
+ supportingAction: C
304
+ } = this, M = R(r);
305
+ return m`
301
306
  <dialog
302
307
  id="dialog"
303
308
  class="c-modal"
304
- size="${P || d.size}"
305
- position="${F || d.position}"
306
- ?hasActions=${D || E}
309
+ size="${T}"
310
+ position="${E}"
311
+ ?hasActions=${(_ == null ? void 0 : _.text) || (C == null ? void 0 : C.text)}
307
312
  ?hasBackButton=${i}
308
313
  ?hasStackedActions=${o}
309
- ?isDismissible=${m}
314
+ ?isDismissible=${c}
310
315
  ?isFooterPinned=${h}
311
316
  ?isFullWidthBelowMid=${k}
312
317
  ?isLoading=${z}
313
318
  aria-busy="${z ? "true" : "false"}"
314
- aria-label="${z && (e == null ? void 0 : e.loading) || c}"
319
+ aria-label="${z && (e == null ? void 0 : e.loading) || g}"
315
320
  data-test-id="pie-modal">
316
321
  <header class="c-modal-header"
317
322
  data-test-id="modal-header">
318
- ${i ? this.renderBackButton() : c}
319
- <${O} class="c-modal-heading">
323
+ ${this.renderBackButton()}
324
+ <${M} class="c-modal-heading">
320
325
  ${t}
321
- </${O}>
322
- ${m ? this.renderCloseButton() : c}
326
+ </${M}>
327
+ ${this.renderCloseButton()}
323
328
  </header>
324
329
  ${// We need to wrap the remaining content in a shared scrollable container if the footer is not pinned
325
- h ? this.renderModalContentAndFooter() : g`
330
+ h ? this.renderModalContentAndFooter() : m`
326
331
  <div class="c-modal-scrollContainer">
327
332
  ${this.renderModalContentAndFooter()}
328
333
  </div>
@@ -330,69 +335,69 @@ class a extends W(T) {
330
335
  </dialog>`;
331
336
  }
332
337
  }
333
- a.styles = N(J);
338
+ a.styles = N(Z);
334
339
  l([
335
- r({ type: Object })
340
+ d({ type: Object })
336
341
  ], a.prototype, "aria", 2);
337
342
  l([
338
- r({ type: String }),
339
- j(b)
343
+ d({ type: String }),
344
+ V(b)
340
345
  ], a.prototype, "heading", 2);
341
346
  l([
342
- r(),
343
- B(b, Q, d.headingLevel)
347
+ d(),
348
+ S(b, ee, s.headingLevel)
344
349
  ], a.prototype, "headingLevel", 2);
345
350
  l([
346
- r({ type: Boolean })
351
+ d({ type: Boolean })
347
352
  ], a.prototype, "hasBackButton", 2);
348
353
  l([
349
- r({ type: Boolean })
354
+ d({ type: Boolean })
350
355
  ], a.prototype, "hasStackedActions", 2);
351
356
  l([
352
- r({ type: Boolean, reflect: !0 })
357
+ d({ type: Boolean, reflect: !0 })
353
358
  ], a.prototype, "isDismissible", 2);
354
359
  l([
355
- r({ type: Boolean })
360
+ d({ type: Boolean })
356
361
  ], a.prototype, "isFooterPinned", 2);
357
362
  l([
358
- r({ type: Boolean })
363
+ d({ type: Boolean })
359
364
  ], a.prototype, "isFullWidthBelowMid", 2);
360
365
  l([
361
- r({ type: Boolean, reflect: !0 })
366
+ d({ type: Boolean, reflect: !0 })
362
367
  ], a.prototype, "isLoading", 2);
363
368
  l([
364
- r({ type: Boolean })
369
+ d({ type: Boolean })
365
370
  ], a.prototype, "isOpen", 2);
366
371
  l([
367
- r({ type: Object })
372
+ d({ type: Object })
368
373
  ], a.prototype, "leadingAction", 2);
369
374
  l([
370
- r(),
371
- B(b, ee, d.position)
375
+ d(),
376
+ S(b, oe, s.position)
372
377
  ], a.prototype, "position", 2);
373
378
  l([
374
- r()
379
+ d()
375
380
  ], a.prototype, "returnFocusAfterCloseSelector", 2);
376
381
  l([
377
- r(),
378
- B(b, Z, d.size)
382
+ d(),
383
+ S(b, ie, s.size)
379
384
  ], a.prototype, "size", 2);
380
385
  l([
381
- r({ type: Object })
386
+ d({ type: Object })
382
387
  ], a.prototype, "supportingAction", 2);
383
388
  l([
384
- R("dialog")
389
+ W("dialog")
385
390
  ], a.prototype, "_dialog", 2);
386
- Y(b, a);
391
+ q(b, a);
387
392
  export {
388
- C as ON_MODAL_BACK_EVENT,
389
- _ as ON_MODAL_CLOSE_EVENT,
390
- ie as ON_MODAL_LEADING_ACTION_CLICK,
393
+ L as ON_MODAL_BACK_EVENT,
394
+ O as ON_MODAL_CLOSE_EVENT,
395
+ te as ON_MODAL_LEADING_ACTION_CLICK,
391
396
  w as ON_MODAL_OPEN_EVENT,
392
- oe as ON_MODAL_SUPPORTING_ACTION_CLICK,
397
+ ae as ON_MODAL_SUPPORTING_ACTION_CLICK,
393
398
  a as PieModal,
394
- d as defaultProps,
395
- Q as headingLevels,
396
- ee as positions,
397
- Z as sizes
399
+ s as defaultProps,
400
+ ee as headingLevels,
401
+ oe as positions,
402
+ ie as sizes
398
403
  };
package/dist/react.d.ts CHANGED
@@ -8,7 +8,7 @@ import type { RTLInterface } from '@justeattakeaway/pie-webc-core';
8
8
  import type { TemplateResult } from 'lit';
9
9
  import { Variant } from '@justeattakeaway/pie-button/src/defs.ts';
10
10
 
11
- export declare type ActionProps = {
11
+ declare type ActionProps = {
12
12
  /**
13
13
  * The text to display inside the button.
14
14
  */
@@ -18,7 +18,7 @@ export declare type ActionProps = {
18
18
  */
19
19
  variant?: Variant;
20
20
  /**
21
- * The ARIA label for the button.
21
+ * The aria label for the button.
22
22
  */
23
23
  ariaLabel?: string;
24
24
  };
@@ -39,7 +39,7 @@ export declare type ModalActionType = 'leading' | 'supporting';
39
39
 
40
40
  export declare type ModalProps = {
41
41
  /**
42
- * The ARIA labels used for the modal close and back buttons, as well as loading state.
42
+ * The ARIA labels used for the modal close and back buttons, as well as for the loading state.
43
43
  */
44
44
  aria?: AriaProps;
45
45
  /**
@@ -151,9 +151,9 @@ export declare const PieModal: React_2.ForwardRefExoticComponent<ModalProps & Re
151
151
  * @event {CustomEvent} pie-modal-supporting-action-click - when the modal supporting action is clicked.
152
152
  */
153
153
  declare class PieModal_2 extends PieModal_base implements ModalProps {
154
- aria: AriaProps;
154
+ aria: ModalProps['aria'];
155
155
  heading: string;
156
- headingLevel: ModalProps['headingLevel'];
156
+ headingLevel: "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
157
157
  hasBackButton: boolean;
158
158
  hasStackedActions: boolean;
159
159
  isDismissible: boolean;
@@ -161,11 +161,11 @@ declare class PieModal_2 extends PieModal_base implements ModalProps {
161
161
  isFullWidthBelowMid: boolean;
162
162
  isLoading: boolean;
163
163
  isOpen: boolean;
164
- leadingAction: ActionProps;
165
- position: ModalProps['position'];
166
- returnFocusAfterCloseSelector?: string;
167
- size: ModalProps['size'];
168
- supportingAction: ActionProps;
164
+ leadingAction: ModalProps['leadingAction'];
165
+ position: "top" | "center";
166
+ returnFocusAfterCloseSelector: ModalProps['returnFocusAfterCloseSelector'];
167
+ size: "medium" | "large" | "small";
168
+ supportingAction: ModalProps['supportingAction'];
169
169
  private _dialog?;
170
170
  private _backButtonClicked;
171
171
  static styles: CSSResult;
@@ -211,23 +211,22 @@ declare class PieModal_2 extends PieModal_base implements ModalProps {
211
211
  */
212
212
  private renderBackButton;
213
213
  /**
214
- * Render leadingAction button depending on prop availability.
214
+ * Renders the "leadingAction" button if the text is provided.
215
215
  *
216
- * 1. If the prop `leadingAction` is not provided, the button is not rendered.
217
- * 2. If the prop `leadingAction` is provided but any of the optional properties
218
- * are not provided, they fall back to their default values.
216
+ * If `leadingAction.text` is not provided, the button is not rendered.
217
+ * If `leadingAction.variant` is not provided, the default value of "primary" is used.
218
+ * The (optional) aria-label is read from `leadingAction.ariaLabel`.
219
219
  *
220
220
  * @private
221
221
  */
222
222
  private renderLeadingAction;
223
223
  /**
224
- * Render supportingAction button depending on prop availability.
224
+ * Renders the "supportingAction" button if the text is provided.
225
+ * You cannot have a supporting action without a leading action.
225
226
  *
226
- * 1. If the prop `supportingAction` is not provided, the button is not rendered.
227
- * 2. If the prop `supportingAction` is provided but any of the optional properties
228
- * are not provided, they fall back to their default values.
229
- * 3. If `supportingAction` is provided but not `leadingAction`, log a warning and do
230
- * not render `supportingAction`.
227
+ * If either `supportingAction.text` or `leadingAction.text` are not provided, the button is not rendered.
228
+ * If `supportingAction.variant` is not provided, the default value of "ghost" is used.
229
+ * The (optional) aria-label is read from `supportingAction.ariaLabel`.
231
230
  *
232
231
  * @private
233
232
  */
package/dist/react.js CHANGED
@@ -1,10 +1,12 @@
1
1
  import * as o from "react";
2
2
  import { createComponent as i } from "@lit/react";
3
3
  import { PieModal as e } from "./index.js";
4
- import { ON_MODAL_BACK_EVENT as A, ON_MODAL_CLOSE_EVENT as L, ON_MODAL_LEADING_ACTION_CLICK as E, ON_MODAL_OPEN_EVENT as g, ON_MODAL_SUPPORTING_ACTION_CLICK as k, defaultProps as D, headingLevels as I, positions as T, sizes as f } from "./index.js";
4
+ import { ON_MODAL_BACK_EVENT as E, ON_MODAL_CLOSE_EVENT as g, ON_MODAL_LEADING_ACTION_CLICK as k, ON_MODAL_OPEN_EVENT as D, ON_MODAL_SUPPORTING_ACTION_CLICK as I, defaultProps as T, headingLevels as f, positions as u, sizes as K } from "./index.js";
5
5
  import "lit";
6
6
  import "lit/static-html.js";
7
7
  import "lit/decorators.js";
8
+ import "lit/directives/class-map.js";
9
+ import "lit/directives/if-defined.js";
8
10
  import "@justeattakeaway/pie-button";
9
11
  import "@justeattakeaway/pie-icon-button";
10
12
  import "@justeattakeaway/pie-webc-core";
@@ -29,16 +31,16 @@ const a = i({
29
31
  onPieModalSupportingActionClick: "pie-modal-supporting-action-click"
30
32
  // when the modal supporting action is clicked.
31
33
  }
32
- }), N = a;
34
+ }), C = a;
33
35
  export {
34
- A as ON_MODAL_BACK_EVENT,
35
- L as ON_MODAL_CLOSE_EVENT,
36
- E as ON_MODAL_LEADING_ACTION_CLICK,
37
- g as ON_MODAL_OPEN_EVENT,
38
- k as ON_MODAL_SUPPORTING_ACTION_CLICK,
39
- N as PieModal,
40
- D as defaultProps,
41
- I as headingLevels,
42
- T as positions,
43
- f as sizes
36
+ E as ON_MODAL_BACK_EVENT,
37
+ g as ON_MODAL_CLOSE_EVENT,
38
+ k as ON_MODAL_LEADING_ACTION_CLICK,
39
+ D as ON_MODAL_OPEN_EVENT,
40
+ I as ON_MODAL_SUPPORTING_ACTION_CLICK,
41
+ C as PieModal,
42
+ T as defaultProps,
43
+ f as headingLevels,
44
+ u as positions,
45
+ K as sizes
44
46
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@justeattakeaway/pie-modal",
3
- "version": "0.43.5",
3
+ "version": "0.45.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,8 @@
37
37
  "devDependencies": {
38
38
  "@custom-elements-manifest/analyzer": "0.9.0",
39
39
  "@justeat/pie-design-tokens": "6.3.1",
40
- "@justeattakeaway/pie-components-config": "0.16.0",
40
+ "@justeattakeaway/pie-components-config": "0.17.0",
41
+ "@justeattakeaway/pie-css": "0.12.1",
41
42
  "@justeattakeaway/pie-wrapper-react": "0.14.1",
42
43
  "@types/body-scroll-lock": "3.1.2",
43
44
  "cem-plugin-module-file-extensions": "0.0.5"
@@ -46,10 +47,10 @@
46
47
  "extends": "../../../package.json"
47
48
  },
48
49
  "dependencies": {
49
- "@justeattakeaway/pie-button": "0.48.0",
50
- "@justeattakeaway/pie-icon-button": "0.28.9",
51
- "@justeattakeaway/pie-icons-webc": "0.24.2",
52
- "@justeattakeaway/pie-spinner": "0.6.6",
50
+ "@justeattakeaway/pie-button": "0.48.1",
51
+ "@justeattakeaway/pie-icon-button": "0.28.10",
52
+ "@justeattakeaway/pie-icons-webc": "0.25.0",
53
+ "@justeattakeaway/pie-spinner": "0.6.7",
53
54
  "@justeattakeaway/pie-webc-core": "0.24.0",
54
55
  "body-scroll-lock": "3.1.5",
55
56
  "dialog-polyfill": "0.5.6"
package/src/defs.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { type ComponentDefaultProps } from '@justeattakeaway/pie-webc-core';
2
2
 
3
- import { Variant } from '@justeattakeaway/pie-button/src/defs.ts';
3
+ import { type Variant as ButtonVariant } from '@justeattakeaway/pie-button/src/defs.ts';
4
4
 
5
5
  export const headingLevels = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] as const;
6
6
  export const sizes = ['small', 'medium', 'large'] as const;
@@ -12,26 +12,26 @@ export type AriaProps = {
12
12
  loading?: string;
13
13
  };
14
14
 
15
- export type ActionProps = {
16
- /**
17
- * The text to display inside the button.
18
- */
19
- text: string;
20
-
21
- /**
22
- * The button variant.
23
- */
24
- variant?: Variant;
25
-
26
- /**
27
- * The ARIA label for the button.
28
- */
29
- ariaLabel?: string;
15
+ type ActionProps = {
16
+ /**
17
+ * The text to display inside the button.
18
+ */
19
+ text: string;
20
+
21
+ /**
22
+ * The button variant.
23
+ */
24
+ variant?: ButtonVariant;
25
+
26
+ /**
27
+ * The aria label for the button.
28
+ */
29
+ ariaLabel?: string;
30
30
  };
31
31
 
32
32
  export type ModalProps = {
33
33
  /**
34
- * The ARIA labels used for the modal close and back buttons, as well as loading state.
34
+ * The ARIA labels used for the modal close and back buttons, as well as for the loading state.
35
35
  */
36
36
  aria?: AriaProps;
37
37
 
package/src/index.ts CHANGED
@@ -3,6 +3,8 @@ import {
3
3
  } from 'lit';
4
4
  import { html, unsafeStatic } from 'lit/static-html.js';
5
5
  import { property, query } from 'lit/decorators.js';
6
+ import { classMap } from 'lit/directives/class-map.js';
7
+ import { ifDefined } from 'lit/directives/if-defined.js';
6
8
  import { disableBodyScroll, enableBodyScroll } from 'body-scroll-lock';
7
9
 
8
10
  import '@justeattakeaway/pie-button';
@@ -21,8 +23,6 @@ import '@justeattakeaway/pie-spinner';
21
23
 
22
24
  import styles from './modal.scss?inline';
23
25
  import {
24
- type AriaProps,
25
- type ActionProps,
26
26
  type ModalProps,
27
27
  type ModalActionType,
28
28
  headingLevels,
@@ -55,7 +55,7 @@ export interface ModalEventDetail {
55
55
  */
56
56
  export class PieModal extends RtlMixin(LitElement) implements ModalProps {
57
57
  @property({ type: Object })
58
- public aria!: AriaProps;
58
+ public aria: ModalProps['aria'];
59
59
 
60
60
  @property({ type: String })
61
61
  @requiredProperty(componentSelector)
@@ -63,7 +63,7 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
63
63
 
64
64
  @property()
65
65
  @validPropertyValues(componentSelector, headingLevels, defaultProps.headingLevel)
66
- public headingLevel: ModalProps['headingLevel'] = defaultProps.headingLevel;
66
+ public headingLevel = defaultProps.headingLevel;
67
67
 
68
68
  @property({ type: Boolean })
69
69
  public hasBackButton = defaultProps.hasBackButton;
@@ -87,21 +87,21 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
87
87
  public isOpen = defaultProps.isOpen;
88
88
 
89
89
  @property({ type: Object })
90
- public leadingAction!: ActionProps;
90
+ public leadingAction: ModalProps['leadingAction'];
91
91
 
92
92
  @property()
93
93
  @validPropertyValues(componentSelector, positions, defaultProps.position)
94
- public position: ModalProps['position'] = defaultProps.position;
94
+ public position = defaultProps.position;
95
95
 
96
96
  @property()
97
- public returnFocusAfterCloseSelector?: string;
97
+ public returnFocusAfterCloseSelector: ModalProps['returnFocusAfterCloseSelector'];
98
98
 
99
99
  @property()
100
100
  @validPropertyValues(componentSelector, sizes, defaultProps.size)
101
- public size: ModalProps['size'] = defaultProps.size;
101
+ public size = defaultProps.size;
102
102
 
103
103
  @property({ type: Object })
104
- public supportingAction!: ActionProps;
104
+ public supportingAction: ModalProps['supportingAction'];
105
105
 
106
106
  @query('dialog')
107
107
  private _dialog?: HTMLDialogElement;
@@ -259,7 +259,11 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
259
259
  *
260
260
  * @private
261
261
  */
262
- private renderCloseButton (): TemplateResult {
262
+ private renderCloseButton (): TemplateResult | typeof nothing {
263
+ if (!this.isDismissible) {
264
+ return nothing;
265
+ }
266
+
263
267
  return html`
264
268
  <pie-icon-button
265
269
  @click="${() => { this.isOpen = false; }}"
@@ -277,13 +281,17 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
277
281
  *
278
282
  * @private
279
283
  */
280
- private renderBackButton () : TemplateResult {
284
+ private renderBackButton () : TemplateResult | typeof nothing {
285
+ if (!this.hasBackButton) {
286
+ return nothing;
287
+ }
288
+
281
289
  return html`
282
290
  <pie-icon-button
283
291
  @click="${() => { this._backButtonClicked = true; this.isOpen = false; }}"
284
292
  variant="ghost-secondary"
285
293
  class="c-modal-backBtn"
286
- aria-label="${this.aria?.back || nothing}"
294
+ aria-label="${ifDefined(this.aria?.back)}"
287
295
  data-test-id="modal-back-button">
288
296
  ${this.isRTL ? html`<icon-chevron-right></icon-chevron-right>` : html`<icon-chevron-left></icon-chevron-left>`}
289
297
  </pie-icon-button>
@@ -291,25 +299,23 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
291
299
  }
292
300
 
293
301
  /**
294
- * Render leadingAction button depending on prop availability.
302
+ * Renders the "leadingAction" button if the text is provided.
295
303
  *
296
- * 1. If the prop `leadingAction` is not provided, the button is not rendered.
297
- * 2. If the prop `leadingAction` is provided but any of the optional properties
298
- * are not provided, they fall back to their default values.
304
+ * If `leadingAction.text` is not provided, the button is not rendered.
305
+ * If `leadingAction.variant` is not provided, the default value of "primary" is used.
306
+ * The (optional) aria-label is read from `leadingAction.ariaLabel`.
299
307
  *
300
308
  * @private
301
309
  */
302
310
  private renderLeadingAction () : TemplateResult | typeof nothing {
303
- const { text, variant = 'primary', ariaLabel } = this.leadingAction;
311
+ const { ariaLabel, text, variant = 'primary' } = this.leadingAction || {};
304
312
 
305
- if (!text) {
306
- return nothing;
307
- }
313
+ if (!text) return nothing;
308
314
 
309
315
  return html`
310
316
  <pie-button
311
317
  variant="${variant}"
312
- aria-label="${ariaLabel || nothing}"
318
+ aria-label="${ifDefined(ariaLabel)}"
313
319
  type="submit"
314
320
  ?isFullWidth="${this.hasStackedActions}"
315
321
  @click="${() => this._handleActionClick('leading')}"
@@ -320,32 +326,29 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
320
326
  }
321
327
 
322
328
  /**
323
- * Render supportingAction button depending on prop availability.
329
+ * Renders the "supportingAction" button if the text is provided.
330
+ * You cannot have a supporting action without a leading action.
324
331
  *
325
- * 1. If the prop `supportingAction` is not provided, the button is not rendered.
326
- * 2. If the prop `supportingAction` is provided but any of the optional properties
327
- * are not provided, they fall back to their default values.
328
- * 3. If `supportingAction` is provided but not `leadingAction`, log a warning and do
329
- * not render `supportingAction`.
332
+ * If either `supportingAction.text` or `leadingAction.text` are not provided, the button is not rendered.
333
+ * If `supportingAction.variant` is not provided, the default value of "ghost" is used.
334
+ * The (optional) aria-label is read from `supportingAction.ariaLabel`.
330
335
  *
331
336
  * @private
332
337
  */
333
338
  private renderSupportingAction (): TemplateResult | typeof nothing {
334
- const { text, variant = 'ghost', ariaLabel } = this.supportingAction;
339
+ const { ariaLabel, text, variant = 'ghost' } = this.supportingAction || {};
335
340
 
336
- if (!text) {
337
- return nothing;
338
- }
341
+ if (!text) return nothing;
339
342
 
340
- if (!this.leadingAction) {
341
- console.warn('Use `leadingAction` instead of `supportingAction`. `supportingAction` is being ignored.');
343
+ if (!this.leadingAction?.text) {
344
+ console.warn('You cannot have a supporting action without a leading action. If you only need one button then use a leading action instead.');
342
345
  return nothing;
343
346
  }
344
347
 
345
348
  return html`
346
349
  <pie-button
347
350
  variant="${variant}"
348
- aria-label="${ariaLabel || nothing}"
351
+ aria-label="${ifDefined(ariaLabel)}"
349
352
  type="reset"
350
353
  ?isFullWidth="${this.hasStackedActions}"
351
354
  @click="${() => this._handleActionClick('supporting')}"
@@ -360,21 +363,26 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
360
363
  * @private
361
364
  */
362
365
  private renderModalContentAndFooter (): TemplateResult {
363
- const hasFooterLeadingAction = this.leadingAction?.text;
366
+ const hasFooterLeadingAction = Boolean(this.leadingAction?.text);
367
+
368
+ const scrollContainerClasses = {
369
+ 'c-modal-scrollContainer': true,
370
+ 'c-modal-content': true,
371
+ 'c-modal-content--scrollable': true,
372
+ 'c-modal-hasFooterActions': hasFooterLeadingAction,
373
+ };
364
374
 
365
375
  return html`
366
- <article class="c-modal-scrollContainer c-modal-content c-modal-content--scrollable ${hasFooterLeadingAction ? 'c-modal-hasFooterActions' : ''}">
367
- <div class="c-modal-contentInner"
368
- data-test-id="modal-content-inner">
376
+ <article class=${classMap(scrollContainerClasses)}>
377
+ <div class="c-modal-contentInner" data-test-id="modal-content-inner">
369
378
  <slot></slot>
370
379
  </div>
371
380
  ${this.isLoading ? html`<pie-spinner size="xlarge" variant="secondary"></pie-spinner>` : nothing}
372
381
  </article>
373
382
  ${hasFooterLeadingAction ? html`
374
- <footer class="c-modal-footer"
375
- data-test-id="pie-modal-footer">
383
+ <footer class="c-modal-footer" data-test-id="pie-modal-footer">
376
384
  ${this.renderLeadingAction()}
377
- ${this.supportingAction?.text ? this.renderSupportingAction() : nothing}
385
+ ${this.renderSupportingAction()}
378
386
  </footer>` : nothing}`;
379
387
  }
380
388
 
@@ -384,7 +392,7 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
384
392
  hasBackButton,
385
393
  hasStackedActions,
386
394
  heading,
387
- headingLevel = 'h2',
395
+ headingLevel,
388
396
  isDismissible,
389
397
  isFooterPinned,
390
398
  isFullWidthBelowMid,
@@ -401,9 +409,9 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
401
409
  <dialog
402
410
  id="dialog"
403
411
  class="c-modal"
404
- size="${size || defaultProps.size}"
405
- position="${position || defaultProps.position}"
406
- ?hasActions=${leadingAction || supportingAction}
412
+ size="${size}"
413
+ position="${position}"
414
+ ?hasActions=${leadingAction?.text || supportingAction?.text}
407
415
  ?hasBackButton=${hasBackButton}
408
416
  ?hasStackedActions=${hasStackedActions}
409
417
  ?isDismissible=${isDismissible}
@@ -415,11 +423,11 @@ export class PieModal extends RtlMixin(LitElement) implements ModalProps {
415
423
  data-test-id="pie-modal">
416
424
  <header class="c-modal-header"
417
425
  data-test-id="modal-header">
418
- ${hasBackButton ? this.renderBackButton() : nothing}
426
+ ${this.renderBackButton()}
419
427
  <${headingTag} class="c-modal-heading">
420
428
  ${heading}
421
429
  </${headingTag}>
422
- ${isDismissible ? this.renderCloseButton() : nothing}
430
+ ${this.renderCloseButton()}
423
431
  </header>
424
432
  ${
425
433
  // We need to wrap the remaining content in a shared scrollable container if the footer is not pinned
package/src/modal.scss CHANGED
@@ -235,13 +235,16 @@
235
235
  --modal-content-line-height: calc(var(--dt-font-size-16-line-height) * 1px);
236
236
  --modal-content-padding-block: var(--dt-spacing-a);
237
237
  --modal-content-padding-inline: var(--dt-spacing-d);
238
+ --modal-content-padding-block-end: var(--dt-spacing-e);
239
+ --modal-content-min-block-size: var(--dt-spacing-j);
240
+
238
241
 
239
242
  @media (min-width: $breakpoint-wide) {
240
243
  --modal-content-padding-inline: var(--dt-spacing-e);
241
244
  }
242
245
 
243
246
  position: relative;
244
- min-block-size: var(--dt-spacing-j);
247
+ min-block-size: calc(var(--modal-content-min-block-size) + var(--modal-content-padding-block) + var(--modal-content-padding-block-end)); // The sum of the minimum height and block paddings, when footerActions aren't rendered
245
248
 
246
249
  font-size: var(--modal-content-font-size);
247
250
  line-height: var(--modal-content-line-height);
@@ -255,6 +258,7 @@
255
258
 
256
259
  &.c-modal-hasFooterActions {
257
260
  padding-block-end: var(--modal-content-padding-block);
261
+ min-block-size: var(--modal-content-min-block-size);
258
262
  }
259
263
 
260
264
  &--scrollable {
@@ -307,13 +311,21 @@
307
311
  pie-spinner {
308
312
  position: absolute;
309
313
  left: 50%;
310
- top: 50%;
314
+
315
+ // Compensates different block paddings, when footerActions aren't rendered
316
+ top: calc(50% - (var(--modal-content-padding-block-end) - var(--modal-content-padding-block)) / 2);
311
317
  transform: translate(-50%, -50%);
312
318
  }
313
319
 
314
320
  & .c-modal-contentInner {
315
321
  display: none;
316
322
  }
323
+
324
+ &.c-modal-hasFooterActions {
325
+ pie-spinner {
326
+ top: 50%;
327
+ }
328
+ }
317
329
  }
318
330
 
319
331
  // removes the scroll shadow effect if "background-attachment" isn't supported.