@justeattakeaway/pie-modal 1.20.0 → 1.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -54,15 +54,32 @@ Ideally, you should install the component using the **`@justeattakeaway/pie-webc
54
54
  | `position` | `"center"`, `"top"` | The position of the modal; this controls where it will appear on the page. | `"center"` |
55
55
  | `returnFocusAfterCloseSelector` | — | If provided, focus will be sent to the first element that matches this selector when the modal is closed. If not provided, the `dialog` element will return focus to the element that opened the modal. | — |
56
56
  | `size` | `"small"`, `"medium"`, `"large"` | Determines the maximum width of the modal. Large modals will expand to fill the entire page at narrow viewports. | `"medium"` |
57
- | `backgroundColor` | `"default"`, `"subtle"`, `"brand-01"`, `"brand-02"`, `"brand-03"`, `"brand-03-subtle"`, `"brand-04"`, `"brand-04-subtle"`, `"brand-05"`, `"brand-05-subtle"`, `"brand-06"`, `"brand-06-subtle"`, `"brand-08"`, `"brand-08-subtle"` | Sets the background color for the modal. | `"default"` |
57
+ | `backgroundColor` | `"default"`, `"subtle"`, `"brand-01"`, `"brand-02"`, `"brand-03"`, `"brand-03-subtle"`, `"brand-04"`, `"brand-04-subtle"`, `"brand-05"`, `"brand-05-subtle"`, `"brand-06"`, `"brand-06-subtle"`, `"brand-08"`, `"brand-08-subtle"` | Sets the background color for the modal. | `"default"` |
58
+ | `imageSlotMode` | `"image"`, `"illustration"` | This property controls if and how the image slot will display its content. `"image"` will display the slot content in a rectangle, covering the entire width of the modal, while `"illustration"` will display the slot content inside a square container. If not specified it will not display the image slot content. | — |
59
+ | `imageSlotAspectRatio` | `"small"`, `"medium"`, `"large"` | If the `imageSlotMode` is set to `image`, this property controls the aspect ratio of the image container. The aspect ratios are the following: `"small"` : `4:1`, `"medium"` : `3:1`, `"large"` : `21:9`. | `"medium"` |
58
60
 
59
61
  ### Slots
60
62
  | Slot | Description |
61
63
  |-----------|--------------------------------------------------------------------|
62
64
  | `default` | The default slot is used to pass content into the modal component. |
65
+ | `image` | Used to pass optional content to the modal component image area. |
63
66
  | `headerContent` | Used to pass additional content to the modal header that scrolls with the heading and controls. |
64
67
  | `footer` | Used to pass optional content to the modal component footer area. |
65
68
 
69
+ #### Slots display order
70
+
71
+ The order of content rendering is as follows:
72
+ 1. `image` slot (if provided)
73
+ 2. Modal header (including `heading` prop and `headerContent` slot, if provided)
74
+ 3. `default` slot (main content of the modal)
75
+ 4. `footer` slot (if provided)
76
+
77
+ #### Image Slot Guidelines
78
+ > The `image` slot is designed to accommodate various types of visual content, such as images or illustrations.
79
+ > When using the image slot, please ensure the content is appropriately styled to fit within one of the `imageSlotMode`.
80
+ > The image slot can handle any type of content, such as IMG tags, SVGs, or other HTML elements.
81
+ > Animations or videos can be used, however be cautious about performance implications.
82
+
66
83
  ### CSS Variables
67
84
  This component does not expose any CSS variables for style overrides.
68
85
 
@@ -36,6 +36,22 @@
36
36
  },
37
37
  "default": "['top', 'center']"
38
38
  },
39
+ {
40
+ "kind": "variable",
41
+ "name": "imageSlotModes",
42
+ "type": {
43
+ "text": "['image', 'illustration']"
44
+ },
45
+ "default": "['image', 'illustration']"
46
+ },
47
+ {
48
+ "kind": "variable",
49
+ "name": "imageSlotAspectRatios",
50
+ "type": {
51
+ "text": "['small', 'medium', 'large']"
52
+ },
53
+ "default": "['small', 'medium', 'large']"
54
+ },
39
55
  {
40
56
  "kind": "variable",
41
57
  "name": "backgroundColors",
@@ -95,7 +111,7 @@
95
111
  "type": {
96
112
  "text": "DefaultProps"
97
113
  },
98
- "default": "{\n hasBackButton: false,\n hasStackedActions: false,\n headingLevel: 'h2',\n isOpen: false,\n isDismissible: false,\n isHeadingEmphasised: false,\n isFooterPinned: true,\n isFullWidthBelowMid: false,\n isLoading: false,\n position: 'center',\n size: 'medium',\n backgroundColor: 'default',\n}"
114
+ "default": "{\n hasBackButton: false,\n hasStackedActions: false,\n headingLevel: 'h2',\n isOpen: false,\n isDismissible: false,\n isHeadingEmphasised: false,\n isFooterPinned: true,\n isFullWidthBelowMid: false,\n isLoading: false,\n position: 'center',\n size: 'medium',\n backgroundColor: 'default',\n imageSlotAspectRatio: 'medium',\n}"
99
115
  }
100
116
  ],
101
117
  "exports": [
@@ -123,6 +139,22 @@
123
139
  "module": "src/defs.js"
124
140
  }
125
141
  },
142
+ {
143
+ "kind": "js",
144
+ "name": "imageSlotModes",
145
+ "declaration": {
146
+ "name": "imageSlotModes",
147
+ "module": "src/defs.js"
148
+ }
149
+ },
150
+ {
151
+ "kind": "js",
152
+ "name": "imageSlotAspectRatios",
153
+ "declaration": {
154
+ "name": "imageSlotAspectRatios",
155
+ "module": "src/defs.js"
156
+ }
157
+ },
126
158
  {
127
159
  "kind": "js",
128
160
  "name": "backgroundColors",
@@ -304,6 +336,19 @@
304
336
  "name": "backgroundColor",
305
337
  "privacy": "public"
306
338
  },
339
+ {
340
+ "kind": "field",
341
+ "name": "imageSlotMode",
342
+ "type": {
343
+ "text": "ModalProps['imageSlotMode']"
344
+ },
345
+ "privacy": "public"
346
+ },
347
+ {
348
+ "kind": "field",
349
+ "name": "imageSlotAspectRatio",
350
+ "privacy": "public"
351
+ },
307
352
  {
308
353
  "kind": "field",
309
354
  "name": "_dialog",
@@ -532,7 +577,7 @@
532
577
  "privacy": "private",
533
578
  "return": {
534
579
  "type": {
535
- "text": "'ghost-secondary' | 'ghost-inverse'"
580
+ "text": "'ghost-secondary' | 'ghost-inverse' | 'secondary'"
536
581
  }
537
582
  }
538
583
  },
@@ -547,6 +592,16 @@
547
592
  },
548
593
  "description": "Template for the close button element. Called within the\nmain render function."
549
594
  },
595
+ {
596
+ "kind": "method",
597
+ "name": "renderModalImageSlot",
598
+ "privacy": "private",
599
+ "return": {
600
+ "type": {
601
+ "text": "TemplateResult | typeof nothing"
602
+ }
603
+ }
604
+ },
550
605
  {
551
606
  "kind": "method",
552
607
  "name": "renderBackButton",
package/dist/index.d.ts CHANGED
@@ -28,12 +28,16 @@ declare type AriaProps = {
28
28
 
29
29
  export declare const backgroundColors: readonly ["default", "subtle", "brand-01", "brand-02", "brand-03", "brand-03-subtle", "brand-04", "brand-04-subtle", "brand-05", "brand-05-subtle", "brand-06", "brand-06-subtle", "brand-08", "brand-08-subtle"];
30
30
 
31
- export declare type DefaultProps = ComponentDefaultProps<ModalProps, keyof Omit<ModalProps, 'aria' | 'heading' | 'leadingAction' | 'supportingAction' | 'returnFocusAfterCloseSelector'>>;
31
+ export declare type DefaultProps = ComponentDefaultProps<ModalProps, keyof Omit<ModalProps, 'aria' | 'heading' | 'leadingAction' | 'supportingAction' | 'returnFocusAfterCloseSelector' | 'imageSlotMode'>>;
32
32
 
33
33
  export declare const defaultProps: DefaultProps;
34
34
 
35
35
  export declare const headingLevels: readonly ["h1", "h2", "h3", "h4", "h5", "h6"];
36
36
 
37
+ export declare const imageSlotAspectRatios: readonly ["small", "medium", "large"];
38
+
39
+ export declare const imageSlotModes: readonly ["image", "illustration"];
40
+
37
41
  export declare type ModalActionType = 'leading' | 'supporting';
38
42
 
39
43
  export declare interface ModalEventDetail {
@@ -114,6 +118,14 @@ export declare type ModalProps = {
114
118
  * The background color for the modal.
115
119
  */
116
120
  backgroundColor?: typeof backgroundColors[number];
121
+ /**
122
+ * The mode of the image slot; this controls whether the slot is treated as an image or an illustration.
123
+ */
124
+ imageSlotMode?: typeof imageSlotModes[number];
125
+ /**
126
+ * The aspect ratio of the image slot; applies only when `imageSlotMode` is set to `image`.
127
+ */
128
+ imageSlotAspectRatio?: typeof imageSlotAspectRatios[number];
117
129
  };
118
130
 
119
131
  /**
@@ -180,6 +192,8 @@ export declare class PieModal extends PieElement implements ModalProps {
180
192
  size: "medium" | "large" | "small";
181
193
  supportingAction: ModalProps['supportingAction'];
182
194
  backgroundColor: "default" | "subtle" | "brand-01" | "brand-02" | "brand-03" | "brand-03-subtle" | "brand-04" | "brand-04-subtle" | "brand-05" | "brand-05-subtle" | "brand-06" | "brand-06-subtle" | "brand-08" | "brand-08-subtle";
195
+ imageSlotMode: ModalProps['imageSlotMode'];
196
+ imageSlotAspectRatio: "medium" | "large" | "small";
183
197
  private _dialog;
184
198
  private _scrollableContainer;
185
199
  private _backButtonClicked;
@@ -239,6 +253,7 @@ export declare class PieModal extends PieElement implements ModalProps {
239
253
  * @private
240
254
  */
241
255
  private renderCloseButton;
256
+ private renderModalImageSlot;
242
257
  /**
243
258
  * Template for the back button element. Called within the
244
259
  * main render function.
package/dist/index.js CHANGED
@@ -1,22 +1,22 @@
1
- import { LitElement as P, unsafeCSS as T, nothing as m } from "lit";
2
- import { html as s, unsafeStatic as K } from "lit/static-html.js";
3
- import { property as d, query as I } from "lit/decorators.js";
4
- import { classMap as C } from "lit/directives/class-map.js";
1
+ import { LitElement as T, unsafeCSS as K, nothing as c } from "lit";
2
+ import { html as s, unsafeStatic as H } 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
5
  import { ifDefined as h } from "lit/directives/if-defined.js";
6
6
  import "@justeattakeaway/pie-button";
7
7
  import "@justeattakeaway/pie-icon-button";
8
- import { requiredProperty as H, validPropertyValues as _, safeCustomElement as N, dispatchCustomEvent as u } from "@justeattakeaway/pie-webc-core";
8
+ import { requiredProperty as N, validPropertyValues as y, safeCustomElement as W, dispatchCustomEvent as u } 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-spinner";
12
- const w = class w extends P {
12
+ const _ = class _ extends T {
13
13
  willUpdate() {
14
- this.getAttribute("v") || this.setAttribute("v", w.v);
14
+ this.getAttribute("v") || this.setAttribute("v", _.v);
15
15
  }
16
16
  };
17
- w.v = "1.20.0";
18
- let B = w;
19
- function W(e) {
17
+ _.v = "1.21.0";
18
+ let x = _;
19
+ function V(e) {
20
20
  if (Array.isArray(e)) {
21
21
  for (var o = 0, t = Array(e.length); o < e.length; o++)
22
22
  t[o] = e[o];
@@ -24,63 +24,63 @@ function W(e) {
24
24
  } else
25
25
  return Array.from(e);
26
26
  }
27
- var z = !1;
27
+ var B = !1;
28
28
  if (typeof window < "u") {
29
- var S = {
29
+ var z = {
30
30
  get passive() {
31
- z = !0;
31
+ B = !0;
32
32
  }
33
33
  };
34
- window.addEventListener("testPassive", null, S), window.removeEventListener("testPassive", null, S);
34
+ window.addEventListener("testPassive", null, z), window.removeEventListener("testPassive", null, z);
35
35
  }
36
- 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), g = [], y = !1, $ = -1, b = void 0, f = void 0, D = function(o) {
36
+ var O = 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 = [], k = !1, $ = -1, f = void 0, v = void 0, D = function(o) {
37
37
  return g.some(function(t) {
38
38
  return !!(t.options.allowTouchMove && t.options.allowTouchMove(o));
39
39
  });
40
- }, k = function(o) {
40
+ }, w = function(o) {
41
41
  var t = o || window.event;
42
42
  return D(t.target) || t.touches.length > 1 ? !0 : (t.preventDefault && t.preventDefault(), !1);
43
- }, V = function(o) {
44
- if (f === void 0) {
43
+ }, j = function(o) {
44
+ if (v === void 0) {
45
45
  var t = !1, a = window.innerWidth - document.documentElement.clientWidth;
46
- t && a > 0 && (f = document.body.style.paddingRight, document.body.style.paddingRight = a + "px");
46
+ t && a > 0 && (v = document.body.style.paddingRight, document.body.style.paddingRight = a + "px");
47
47
  }
48
- b === void 0 && (b = document.body.style.overflow, document.body.style.overflow = "hidden");
49
- }, j = function() {
50
- f !== void 0 && (document.body.style.paddingRight = f, f = void 0), b !== void 0 && (document.body.style.overflow = b, b = void 0);
51
- }, R = function(o) {
48
+ f === void 0 && (f = document.body.style.overflow, document.body.style.overflow = "hidden");
49
+ }, Y = function() {
50
+ v !== void 0 && (document.body.style.paddingRight = v, v = void 0), f !== void 0 && (document.body.style.overflow = f, f = void 0);
51
+ }, q = function(o) {
52
52
  return o ? o.scrollHeight - o.scrollTop <= o.clientHeight : !1;
53
- }, Y = function(o, t) {
53
+ }, U = function(o, t) {
54
54
  var a = o.targetTouches[0].clientY - $;
55
- return D(o.target) ? !1 : t && t.scrollTop === 0 && a > 0 || R(t) && a < 0 ? k(o) : (o.stopPropagation(), !0);
56
- }, q = function(o, t) {
55
+ return D(o.target) ? !1 : t && t.scrollTop === 0 && a > 0 || q(t) && a < 0 ? w(o) : (o.stopPropagation(), !0);
56
+ }, X = function(o, t) {
57
57
  if (!o) {
58
58
  console.error("disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.");
59
59
  return;
60
60
  }
61
- if (!g.some(function(n) {
62
- return n.targetElement === o;
61
+ if (!g.some(function(i) {
62
+ return i.targetElement === o;
63
63
  })) {
64
64
  var a = {
65
65
  targetElement: o,
66
66
  options: {}
67
67
  };
68
- g = [].concat(W(g), [a]), M ? (o.ontouchstart = function(n) {
69
- n.targetTouches.length === 1 && ($ = n.targetTouches[0].clientY);
70
- }, o.ontouchmove = function(n) {
71
- n.targetTouches.length === 1 && Y(n, o);
72
- }, y || (document.addEventListener("touchmove", k, z ? { passive: !1 } : void 0), y = !0)) : V();
68
+ g = [].concat(V(g), [a]), O ? (o.ontouchstart = function(i) {
69
+ i.targetTouches.length === 1 && ($ = i.targetTouches[0].clientY);
70
+ }, o.ontouchmove = function(i) {
71
+ i.targetTouches.length === 1 && U(i, o);
72
+ }, k || (document.addEventListener("touchmove", w, B ? { passive: !1 } : void 0), k = !0)) : j();
73
73
  }
74
- }, U = function(o) {
74
+ }, G = function(o) {
75
75
  if (!o) {
76
76
  console.error("enableBodyScroll unsuccessful - targetElement must be provided when calling enableBodyScroll on IOS devices.");
77
77
  return;
78
78
  }
79
79
  g = g.filter(function(t) {
80
80
  return t.targetElement !== o;
81
- }), M ? (o.ontouchstart = null, o.ontouchmove = null, y && g.length === 0 && (document.removeEventListener("touchmove", k, z ? { passive: !1 } : void 0), y = !1)) : g.length || j();
81
+ }), O ? (o.ontouchstart = null, o.ontouchmove = null, k && g.length === 0 && (document.removeEventListener("touchmove", w, B ? { passive: !1 } : void 0), k = !1)) : g.length || Y();
82
82
  };
83
- const X = '*,*: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-content-color: var(--dt-color-content-default);--modal-bg-color: var(--dt-color-container-default);--modal-elevation: var(--dt-elevation-below-20);position:fixed;top:0;border-radius:var(--modal-border-radius);border:none;box-shadow:var(--modal-elevation);font-family:var(--modal-font);color:var(--modal-content-color);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 ::slotted([slot=footer]){display:flex;width:100%}.c-modal ::slotted([slot=headerContent]){grid-area:content;padding-inline-start:var(--dt-spacing-e);padding-inline-end:var(--dt-spacing-e);margin-block-end:var(--dt-spacing-d)}.c-modal .c-modal-header{display:grid;grid-template-areas:"back heading close" "content content content";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);--modal-header-font-style: normal;font-size:var(--modal-header-font-size);line-height:var(--modal-header-font-line-height);font-weight:var(--modal-header-font-weight);font-style:var(--modal-header-font-style);margin:0;grid-area:heading;margin-inline-start:var(--dt-spacing-d);margin-inline-end:var(--dt-spacing-d);margin-block:16px}@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:22px}}.c-modal .c-modal-heading.c-modal-heading--emphasised{--modal-header-font-size: calc(var(--dt-font-heading-l-italic-size--narrow) * 1px);--modal-header-font-line-height: calc(var(--dt-font-heading-m-italic-line-height--narrow) * 1px);--modal-header-font-weight: var(--dt-font-heading-l-italic-weight);--modal-header-font-style: var(--dt-font-heading-l-italic-font-style)}@media (min-width: 769px){.c-modal .c-modal-heading.c-modal-heading--emphasised{--modal-header-font-size: calc(var(--dt-font-heading-l-italic-size--wide) * 1px);--modal-header-font-line-height: calc(var(--dt-font-heading-l-italic-line-height--wide) * 1px)}}.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-body-l-size) * 1px);--modal-content-font-weight: var(--dt-font-body-l-weight);--modal-content-line-height: calc(var(--dt-font-body-l-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:has(+slot>footer){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(--modal-bg-color) 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}}.c-modal .c-modal-backBtn-icon:dir(rtl){transform:rotate(180deg)}.c-modal.c-modal--bg-brand-01{--modal-bg-color: var(--dt-color-support-brand-01)}.c-modal.c-modal--bg-brand-02{--modal-bg-color: var(--dt-color-support-brand-02)}.c-modal.c-modal--bg-brand-03{--modal-bg-color: var(--dt-color-support-brand-03)}.c-modal.c-modal--bg-brand-03-subtle{--modal-bg-color: var(--dt-color-support-brand-03-subtle)}.c-modal.c-modal--bg-brand-04{--modal-bg-color: var(--dt-color-support-brand-04)}.c-modal.c-modal--bg-brand-04-subtle{--modal-bg-color: var(--dt-color-support-brand-04-subtle)}.c-modal.c-modal--bg-brand-05{--modal-bg-color: var(--dt-color-support-brand-05)}.c-modal.c-modal--bg-brand-05-subtle{--modal-bg-color: var(--dt-color-support-brand-05-subtle)}.c-modal.c-modal--bg-brand-06{--modal-content-color: var(--dt-color-content-inverse);--modal-bg-color: var(--dt-color-support-brand-06)}.c-modal.c-modal--bg-brand-06-subtle{--modal-bg-color: var(--dt-color-support-brand-06-subtle)}.c-modal.c-modal--bg-brand-08{--modal-bg-color: var(--dt-color-support-brand-08)}.c-modal.c-modal--bg-brand-08-subtle{--modal-bg-color: var(--dt-color-support-brand-08-subtle)}', G = ["h1", "h2", "h3", "h4", "h5", "h6"], J = ["small", "medium", "large"], Q = ["top", "center"], Z = [
83
+ 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:#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-content-color: var(--dt-color-content-default);--modal-bg-color: var(--dt-color-container-default);--modal-elevation: var(--dt-elevation-below-20);--modal-image-slot-bg-color: none;position:fixed;top:0;border-radius:var(--modal-border-radius);border:none;box-shadow:var(--modal-elevation);font-family:var(--modal-font);color:var(--modal-content-color);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-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-imageSlot.c-modal-imageSlot--illustration{display:flex;justify-content:center;align-items:center;height:200px;background-color:var(--modal-image-slot-bg-color)}.c-modal .c-modal-imageSlot.c-modal-imageSlot--illustration ::slotted([slot=image]){width:168px;height:168px;overflow:hidden}.c-modal .c-modal-imageSlot.c-modal-imageSlot--image{overflow:hidden;aspect-ratio:3/1}.c-modal .c-modal-imageSlot.c-modal-imageSlot--image.c-modal-imageSlot--small{aspect-ratio:4/1}.c-modal .c-modal-imageSlot.c-modal-imageSlot--image.c-modal-imageSlot--large{aspect-ratio:21/9}.c-modal .c-modal-imageSlot.c-modal-imageSlot--image ::slotted([slot=image]){width:100%}.c-modal .c-modal-imageSlot .c-modal-closeBtn{position:absolute;inset-block-start:0;inset-inline-end:0;margin-block-start:var(--dt-spacing-d);margin-inline-end:var(--dt-spacing-d)}.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 ::slotted([slot=footer]){display:flex;width:100%}.c-modal ::slotted([slot=headerContent]){grid-area:content;padding-inline-start:var(--dt-spacing-e);padding-inline-end:var(--dt-spacing-e);margin-block-end:var(--dt-spacing-d)}.c-modal .c-modal-header{display:grid;grid-template-areas:"back heading close" "content content content";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);--modal-header-font-style: normal;font-size:var(--modal-header-font-size);line-height:var(--modal-header-font-line-height);font-weight:var(--modal-header-font-weight);font-style:var(--modal-header-font-style);margin:0;grid-area:heading;margin-inline-start:var(--dt-spacing-d);margin-inline-end:var(--dt-spacing-d);margin-block:16px}@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:22px}}.c-modal .c-modal-heading.c-modal-heading--emphasised{--modal-header-font-size: calc(var(--dt-font-heading-l-italic-size--narrow) * 1px);--modal-header-font-line-height: calc(var(--dt-font-heading-m-italic-line-height--narrow) * 1px);--modal-header-font-weight: var(--dt-font-heading-l-italic-weight);--modal-header-font-style: var(--dt-font-heading-l-italic-font-style);font-variation-settings:"slnt" -20}@media (min-width: 769px){.c-modal .c-modal-heading.c-modal-heading--emphasised{--modal-header-font-size: calc(var(--dt-font-heading-l-italic-size--wide) * 1px);--modal-header-font-line-height: calc(var(--dt-font-heading-l-italic-line-height--wide) * 1px)}}.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-content{--modal-content-font-size: calc(var(--dt-font-body-l-size) * 1px);--modal-content-font-weight: var(--dt-font-body-l-weight);--modal-content-line-height: calc(var(--dt-font-body-l-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:has(+slot>footer){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(--modal-bg-color) 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}}.c-modal .c-modal-backBtn-icon:dir(rtl){transform:rotate(180deg)}.c-modal.c-modal--bg-subtle{--modal-image-slot-bg-color: var(--dt-color-container-subtle)}.c-modal.c-modal--bg-brand-01{--modal-bg-color: var(--dt-color-support-brand-01)}.c-modal.c-modal--bg-brand-02{--modal-bg-color: var(--dt-color-support-brand-02)}.c-modal.c-modal--bg-brand-03{--modal-bg-color: var(--dt-color-support-brand-03)}.c-modal.c-modal--bg-brand-03-subtle{--modal-bg-color: var(--dt-color-support-brand-03-subtle)}.c-modal.c-modal--bg-brand-04{--modal-bg-color: var(--dt-color-support-brand-04)}.c-modal.c-modal--bg-brand-04-subtle{--modal-bg-color: var(--dt-color-support-brand-04-subtle)}.c-modal.c-modal--bg-brand-05{--modal-bg-color: var(--dt-color-support-brand-05)}.c-modal.c-modal--bg-brand-05-subtle{--modal-bg-color: var(--dt-color-support-brand-05-subtle)}.c-modal.c-modal--bg-brand-06{--modal-content-color: var(--dt-color-content-inverse);--modal-bg-color: var(--dt-color-support-brand-06)}.c-modal.c-modal--bg-brand-06-subtle{--modal-bg-color: var(--dt-color-support-brand-06-subtle)}.c-modal.c-modal--bg-brand-08{--modal-bg-color: var(--dt-color-support-brand-08)}.c-modal.c-modal--bg-brand-08-subtle{--modal-bg-color: var(--dt-color-support-brand-08-subtle)}', Q = ["h1", "h2", "h3", "h4", "h5", "h6"], Z = ["small", "medium", "large"], oo = ["top", "center"], ko = ["image", "illustration"], eo = ["small", "medium", "large"], to = [
84
84
  "default",
85
85
  "subtle",
86
86
  "brand-01",
@@ -95,7 +95,7 @@ const X = '*,*:after,*:before{box-sizing:inherit}dialog{position:absolute;left:0
95
95
  "brand-06-subtle",
96
96
  "brand-08",
97
97
  "brand-08-subtle"
98
- ], L = "pie-modal-close", x = "pie-modal-open", O = "pie-modal-back", oo = "pie-modal-leading-action-click", eo = "pie-modal-supporting-action-click", r = {
98
+ ], L = "pie-modal-close", C = "pie-modal-open", M = "pie-modal-back", ao = "pie-modal-leading-action-click", io = "pie-modal-supporting-action-click", r = {
99
99
  hasBackButton: !1,
100
100
  hasStackedActions: !1,
101
101
  headingLevel: "h2",
@@ -107,17 +107,18 @@ const X = '*,*:after,*:before{box-sizing:inherit}dialog{position:absolute;left:0
107
107
  isLoading: !1,
108
108
  position: "center",
109
109
  size: "medium",
110
- backgroundColor: "default"
110
+ backgroundColor: "default",
111
+ imageSlotAspectRatio: "medium"
111
112
  };
112
- var to = Object.defineProperty, ao = Object.getOwnPropertyDescriptor, l = (e, o, t, a) => {
113
- for (var n = a > 1 ? void 0 : a ? ao(o, t) : o, c = e.length - 1, p; c >= 0; c--)
114
- (p = e[c]) && (n = (a ? p(o, t, n) : p(n)) || n);
115
- return a && n && to(o, t, n), n;
113
+ var no = Object.defineProperty, lo = Object.getOwnPropertyDescriptor, l = (e, o, t, a) => {
114
+ for (var i = a > 1 ? void 0 : a ? lo(o, t) : o, m = e.length - 1, p; m >= 0; m--)
115
+ (p = e[m]) && (i = (a ? p(o, t, i) : p(i)) || i);
116
+ return a && i && no(o, t, i), i;
116
117
  };
117
- const v = "pie-modal";
118
- let i = class extends B {
118
+ const b = "pie-modal";
119
+ let n = class extends x {
119
120
  constructor() {
120
- super(...arguments), this.headingLevel = r.headingLevel, this.hasBackButton = r.hasBackButton, this.hasStackedActions = r.hasStackedActions, this.isDismissible = r.isDismissible, this.isHeadingEmphasised = r.isHeadingEmphasised, 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.backgroundColor = r.backgroundColor, this._scrollableContainer = null, this._backButtonClicked = !1, this._escKeyAbortController = null, this._preventModalKeyboardDismissal = (e) => {
121
+ super(...arguments), this.headingLevel = r.headingLevel, this.hasBackButton = r.hasBackButton, this.hasStackedActions = r.hasStackedActions, this.isDismissible = r.isDismissible, this.isHeadingEmphasised = r.isHeadingEmphasised, 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.backgroundColor = r.backgroundColor, this.imageSlotAspectRatio = r.imageSlotAspectRatio, this._scrollableContainer = null, this._backButtonClicked = !1, this._escKeyAbortController = null, this._preventModalKeyboardDismissal = (e) => {
121
122
  e.key === "Escape" && e.preventDefault();
122
123
  }, this._handleDialogLightDismiss = (e) => {
123
124
  if (!this.isDismissible || e.target !== e.currentTarget)
@@ -125,12 +126,12 @@ let i = class extends B {
125
126
  const o = this._dialog.getBoundingClientRect(), {
126
127
  top: t = 0,
127
128
  bottom: a = 0,
128
- left: n = 0,
129
- right: c = 0
129
+ left: i = 0,
130
+ right: m = 0
130
131
  } = o || {};
131
- if (t === 0 && a === 0 && n === 0 && c === 0)
132
+ if (t === 0 && a === 0 && i === 0 && m === 0)
132
133
  return;
133
- (e.clientY < t || e.clientY > a || e.clientX < n || e.clientX > c) && (this.isOpen = !1);
134
+ (e.clientY < t || e.clientY > a || e.clientX < i || e.clientX > m) && (this.isOpen = !1);
134
135
  };
135
136
  }
136
137
  get _modalScrollContainer() {
@@ -140,7 +141,7 @@ let i = class extends B {
140
141
  connectedCallback() {
141
142
  super.connectedCallback(), this._abortController = new AbortController();
142
143
  const { signal: e } = this._abortController;
143
- this.addEventListener("click", (o) => this._handleDialogLightDismiss(o)), this._setupEscKeyListener(), document.addEventListener(x, (o) => this._handleModalOpened(o), { signal: e }), document.addEventListener(L, (o) => this._handleModalClosed(o), { signal: e }), document.addEventListener(O, (o) => this._handleModalClosed(o), { signal: e });
144
+ this.addEventListener("click", (o) => this._handleDialogLightDismiss(o)), this._setupEscKeyListener(), document.addEventListener(C, (o) => this._handleModalOpened(o), { signal: e }), document.addEventListener(L, (o) => this._handleModalClosed(o), { signal: e }), document.addEventListener(M, (o) => this._handleModalClosed(o), { signal: e });
144
145
  }
145
146
  disconnectedCallback() {
146
147
  super.disconnectedCallback(), this._abortController.abort(), this._enableBodyScroll(), this._removeEscKeyEventListener();
@@ -198,15 +199,15 @@ let i = class extends B {
198
199
  }
199
200
  // Handles the value of the isOpen property on first render of the component
200
201
  _handleModalOpenStateOnFirstRender(e) {
201
- e.get("isOpen") === void 0 && this.isOpen && u(this, x, { targetModal: this });
202
+ e.get("isOpen") === void 0 && this.isOpen && u(this, C, { targetModal: this });
202
203
  }
203
204
  // Handles changes to the modal isOpen property by dispatching any appropriate events
204
205
  _handleModalOpenStateChanged(e) {
205
206
  const o = e.get("isOpen");
206
- o !== void 0 && (o ? this._backButtonClicked ? (this._backButtonClicked = !1, u(this, O, { targetModal: this })) : u(this, L, { targetModal: this }) : u(this, x, { targetModal: this }));
207
+ o !== void 0 && (o ? this._backButtonClicked ? (this._backButtonClicked = !1, u(this, M, { targetModal: this })) : u(this, L, { targetModal: this }) : u(this, C, { targetModal: this }));
207
208
  }
208
209
  _handleActionClick(e) {
209
- e === "leading" ? (this._dialog.close("leading"), u(this, oo, { targetModal: this })) : e === "supporting" && (this._dialog.close("supporting"), u(this, eo, { targetModal: this }));
210
+ e === "leading" ? (this._dialog.close("leading"), u(this, ao, { targetModal: this })) : e === "supporting" && (this._dialog.close("supporting"), u(this, io, { targetModal: this }));
210
211
  }
211
212
  /**
212
213
  * Return focus to the specified element, providing the selector is valid
@@ -221,16 +222,17 @@ let i = class extends B {
221
222
  * Enables body scroll by unlocking the scroll container.
222
223
  */
223
224
  _enableBodyScroll() {
224
- this._scrollableContainer && U(this._scrollableContainer);
225
+ this._scrollableContainer && G(this._scrollableContainer);
225
226
  }
226
227
  /**
227
228
  * Disables body scroll by locking the scroll container.
228
229
  */
229
230
  _disableBodyScroll() {
230
- this._modalScrollContainer && q(this._modalScrollContainer);
231
+ this._modalScrollContainer && X(this._modalScrollContainer);
231
232
  }
232
233
  _getHeaderButtonVariant() {
233
- return this.backgroundColor === "brand-06" ? "ghost-inverse" : "ghost-secondary";
234
+ const { imageSlotMode: e, backgroundColor: o } = this, t = !!e, a = !!o && o !== "default", i = o === "brand-06";
235
+ return t ? e === "illustration" && !a ? "ghost-secondary" : i ? "ghost-inverse" : "secondary" : i ? "ghost-inverse" : "ghost-secondary";
234
236
  }
235
237
  /**
236
238
  * Template for the close button element. Called within the
@@ -241,7 +243,7 @@ let i = class extends B {
241
243
  renderCloseButton() {
242
244
  var o, t;
243
245
  if (!this.isDismissible)
244
- return m;
246
+ return c;
245
247
  const e = this._getHeaderButtonVariant();
246
248
  return s`
247
249
  <pie-icon-button
@@ -250,11 +252,20 @@ let i = class extends B {
250
252
  }}"
251
253
  variant="${e}"
252
254
  class="c-modal-closeBtn"
253
- .aria=${h((o = this.aria) == null ? void 0 : o.close) ? { label: (t = this.aria) == null ? void 0 : t.close } : m}
255
+ .aria=${h((o = this.aria) == null ? void 0 : o.close) ? { label: (t = this.aria) == null ? void 0 : t.close } : c}
254
256
  data-test-id="modal-close-button">
255
257
  <icon-close></icon-close>
256
258
  </pie-icon-button>`;
257
259
  }
260
+ renderModalImageSlot() {
261
+ const { imageSlotMode: e, imageSlotAspectRatio: o } = this;
262
+ return e ? s`
263
+ <div class="c-modal-imageSlot c-modal-imageSlot--${e} c-modal-imageSlot--${o}" data-test-id="modal-image">
264
+ <slot name="image"></slot>
265
+ ${this.renderCloseButton()}
266
+ </div>
267
+ ` : c;
268
+ }
258
269
  /**
259
270
  * Template for the back button element. Called within the
260
271
  * main render function.
@@ -264,7 +275,7 @@ let i = class extends B {
264
275
  renderBackButton() {
265
276
  var o, t;
266
277
  if (!this.hasBackButton)
267
- return m;
278
+ return c;
268
279
  const e = this._getHeaderButtonVariant();
269
280
  return s`
270
281
  <pie-icon-button
@@ -273,7 +284,7 @@ let i = class extends B {
273
284
  }}"
274
285
  variant="${e}"
275
286
  class="c-modal-backBtn"
276
- .aria=${h((o = this.aria) == null ? void 0 : o.back) ? { label: (t = this.aria) == null ? void 0 : t.back } : m}
287
+ .aria=${h((o = this.aria) == null ? void 0 : o.back) ? { label: (t = this.aria) == null ? void 0 : t.back } : c}
277
288
  data-test-id="modal-back-button">
278
289
  <icon-chevron-left class="c-modal-backBtn-icon"></icon-chevron-left>
279
290
  </pie-icon-button>
@@ -300,7 +311,7 @@ let i = class extends B {
300
311
  data-test-id="modal-leading-action">
301
312
  ${o}
302
313
  </pie-button>
303
- ` : m;
314
+ ` : c;
304
315
  }
305
316
  /**
306
317
  * Renders the "supportingAction" button if the text is provided.
@@ -315,7 +326,7 @@ let i = class extends B {
315
326
  renderSupportingAction() {
316
327
  var a;
317
328
  const { ariaLabel: e, text: o, variant: t = "ghost" } = this.supportingAction || {};
318
- return !o || !((a = this.leadingAction) != null && a.text) ? m : s`
329
+ return !o || !((a = this.leadingAction) != null && a.text) ? c : s`
319
330
  <pie-button
320
331
  variant="${t}"
321
332
  aria-label="${h(e)}"
@@ -334,17 +345,17 @@ let i = class extends B {
334
345
  * @private
335
346
  */
336
347
  renderModalFooter() {
337
- var a, n;
348
+ var a, i;
338
349
  const e = (a = this.leadingAction) == null ? void 0 : a.text;
339
- e || (n = this.supportingAction) != null && n.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.");
350
+ e || (i = this.supportingAction) != null && i.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.");
340
351
  const o = {
341
352
  "c-modal-footer": !0,
342
353
  "c-modal-footer--stackedActions": this.hasStackedActions
343
354
  }, t = e ? s`
344
- <footer class="${C(o)}" data-test-id="pie-modal-footer">
355
+ <footer class="${S(o)}" data-test-id="pie-modal-footer">
345
356
  ${this.renderLeadingAction()}
346
357
  ${this.renderSupportingAction()}
347
- </footer>` : m;
358
+ </footer>` : c;
348
359
  return s`
349
360
  <slot name="footer">
350
361
  ${t}
@@ -356,7 +367,7 @@ let i = class extends B {
356
367
  */
357
368
  renderLoadingSpinner() {
358
369
  if (!this.isLoading)
359
- return m;
370
+ return c;
360
371
  const e = this.backgroundColor === "brand-06" ? "inverse" : "secondary";
361
372
  return s`<pie-spinner size="xlarge" variant="${e}"></pie-spinner>`;
362
373
  }
@@ -379,9 +390,9 @@ let i = class extends B {
379
390
  * @private
380
391
  */
381
392
  renderHeading() {
382
- const { heading: e, headingLevel: o, isHeadingEmphasised: t } = this, a = K(o);
393
+ const { heading: e, headingLevel: o, isHeadingEmphasised: t } = this, a = H(o);
383
394
  return s`
384
- <${a} id="modal-heading" class="${C({
395
+ <${a} id="modal-heading" class="${S({
385
396
  "c-modal-heading": !0,
386
397
  "c-modal-heading--emphasised": t
387
398
  })}">
@@ -395,33 +406,35 @@ let i = class extends B {
395
406
  isDismissible: o,
396
407
  isFooterPinned: t,
397
408
  isFullWidthBelowMid: a,
398
- isLoading: n,
399
- position: c,
409
+ isLoading: i,
410
+ position: m,
400
411
  size: p,
401
- backgroundColor: E
402
- } = this, F = {
412
+ backgroundColor: E,
413
+ imageSlotMode: F
414
+ } = this, P = !!!F, I = {
403
415
  "c-modal": !0,
404
416
  [`c-modal--${p}`]: !0,
405
- "c-modal--top": c === "top",
417
+ "c-modal--top": m === "top",
406
418
  "c-modal--dismissible": o,
407
- "c-modal--loading": n,
419
+ "c-modal--loading": i,
408
420
  "c-modal--pinnedFooter": t,
409
421
  "c-modal--fullWidthBelowMid": a,
410
422
  [`c-modal--bg-${E}`]: !0
411
- }, A = n && (e == null ? void 0 : e.loading) || void 0;
423
+ }, A = i && (e == null ? void 0 : e.loading) || void 0;
412
424
  return s`
413
425
  <dialog
414
426
  id="dialog"
415
427
  aria-label="${h(A)}"
416
428
  aria-labelledby="${h(A ? void 0 : "modal-heading")}"
417
- class="${C(F)}"
429
+ class="${S(I)}"
418
430
  aria-live="polite"
419
- aria-busy="${n ? "true" : "false"}"
431
+ aria-busy="${i ? "true" : "false"}"
420
432
  data-test-id="pie-modal">
433
+ ${this.renderModalImageSlot()}
421
434
  <header class="c-modal-header" data-test-id="modal-header">
422
435
  ${this.renderBackButton()}
423
436
  ${this.renderHeading()}
424
- ${this.renderCloseButton()}
437
+ ${P ? this.renderCloseButton() : c}
425
438
  <slot name="headerContent"></slot>
426
439
  </header>
427
440
  ${// We need to wrap the remaining content in a shared scrollable container if the footer is not pinned
@@ -432,79 +445,88 @@ let i = class extends B {
432
445
  </dialog>`;
433
446
  }
434
447
  };
435
- i.styles = T(X);
448
+ n.styles = K(J);
436
449
  l([
437
450
  d({ type: Object })
438
- ], i.prototype, "aria", 2);
451
+ ], n.prototype, "aria", 2);
439
452
  l([
440
453
  d({ type: String }),
441
- H(v)
442
- ], i.prototype, "heading", 2);
454
+ N(b)
455
+ ], n.prototype, "heading", 2);
443
456
  l([
444
457
  d({ type: String }),
445
- _(v, G, r.headingLevel)
446
- ], i.prototype, "headingLevel", 2);
458
+ y(b, Q, r.headingLevel)
459
+ ], n.prototype, "headingLevel", 2);
447
460
  l([
448
461
  d({ type: Boolean })
449
- ], i.prototype, "hasBackButton", 2);
462
+ ], n.prototype, "hasBackButton", 2);
450
463
  l([
451
464
  d({ type: Boolean })
452
- ], i.prototype, "hasStackedActions", 2);
465
+ ], n.prototype, "hasStackedActions", 2);
453
466
  l([
454
467
  d({ type: Boolean, reflect: !0 })
455
- ], i.prototype, "isDismissible", 2);
468
+ ], n.prototype, "isDismissible", 2);
456
469
  l([
457
470
  d({ type: Boolean })
458
- ], i.prototype, "isHeadingEmphasised", 2);
471
+ ], n.prototype, "isHeadingEmphasised", 2);
459
472
  l([
460
473
  d({ type: Boolean })
461
- ], i.prototype, "isFooterPinned", 2);
474
+ ], n.prototype, "isFooterPinned", 2);
462
475
  l([
463
476
  d({ type: Boolean })
464
- ], i.prototype, "isFullWidthBelowMid", 2);
477
+ ], n.prototype, "isFullWidthBelowMid", 2);
465
478
  l([
466
479
  d({ type: Boolean, reflect: !0 })
467
- ], i.prototype, "isLoading", 2);
480
+ ], n.prototype, "isLoading", 2);
468
481
  l([
469
482
  d({ type: Boolean })
470
- ], i.prototype, "isOpen", 2);
483
+ ], n.prototype, "isOpen", 2);
471
484
  l([
472
485
  d({ type: Object })
473
- ], i.prototype, "leadingAction", 2);
486
+ ], n.prototype, "leadingAction", 2);
474
487
  l([
475
488
  d({ type: String }),
476
- _(v, Q, r.position)
477
- ], i.prototype, "position", 2);
489
+ y(b, oo, r.position)
490
+ ], n.prototype, "position", 2);
478
491
  l([
479
492
  d({ type: String })
480
- ], i.prototype, "returnFocusAfterCloseSelector", 2);
493
+ ], n.prototype, "returnFocusAfterCloseSelector", 2);
481
494
  l([
482
495
  d({ type: String }),
483
- _(v, J, r.size)
484
- ], i.prototype, "size", 2);
496
+ y(b, Z, r.size)
497
+ ], n.prototype, "size", 2);
485
498
  l([
486
499
  d({ type: Object })
487
- ], i.prototype, "supportingAction", 2);
500
+ ], n.prototype, "supportingAction", 2);
501
+ l([
502
+ d({ type: String }),
503
+ y(b, to, r.backgroundColor)
504
+ ], n.prototype, "backgroundColor", 2);
505
+ l([
506
+ d({ type: String })
507
+ ], n.prototype, "imageSlotMode", 2);
488
508
  l([
489
509
  d({ type: String }),
490
- _(v, Z, r.backgroundColor)
491
- ], i.prototype, "backgroundColor", 2);
510
+ y(b, eo, r.imageSlotAspectRatio)
511
+ ], n.prototype, "imageSlotAspectRatio", 2);
492
512
  l([
493
- I("dialog")
494
- ], i.prototype, "_dialog", 2);
495
- i = l([
496
- N("pie-modal")
497
- ], i);
513
+ R("dialog")
514
+ ], n.prototype, "_dialog", 2);
515
+ n = l([
516
+ W("pie-modal")
517
+ ], n);
498
518
  export {
499
- O as ON_MODAL_BACK_EVENT,
519
+ M as ON_MODAL_BACK_EVENT,
500
520
  L as ON_MODAL_CLOSE_EVENT,
501
- oo as ON_MODAL_LEADING_ACTION_CLICK,
502
- x as ON_MODAL_OPEN_EVENT,
503
- eo as ON_MODAL_SUPPORTING_ACTION_CLICK,
504
- i as PieModal,
505
- Z as backgroundColors,
521
+ ao as ON_MODAL_LEADING_ACTION_CLICK,
522
+ C as ON_MODAL_OPEN_EVENT,
523
+ io as ON_MODAL_SUPPORTING_ACTION_CLICK,
524
+ n as PieModal,
525
+ to as backgroundColors,
506
526
  r as defaultProps,
507
- G as headingLevels,
508
- Q as positions,
509
- J as sizes
527
+ Q as headingLevels,
528
+ eo as imageSlotAspectRatios,
529
+ ko as imageSlotModes,
530
+ oo as positions,
531
+ Z as sizes
510
532
  };
package/dist/react.d.ts CHANGED
@@ -29,12 +29,16 @@ declare type AriaProps = {
29
29
 
30
30
  export declare const backgroundColors: readonly ["default", "subtle", "brand-01", "brand-02", "brand-03", "brand-03-subtle", "brand-04", "brand-04-subtle", "brand-05", "brand-05-subtle", "brand-06", "brand-06-subtle", "brand-08", "brand-08-subtle"];
31
31
 
32
- export declare type DefaultProps = ComponentDefaultProps<ModalProps, keyof Omit<ModalProps, 'aria' | 'heading' | 'leadingAction' | 'supportingAction' | 'returnFocusAfterCloseSelector'>>;
32
+ export declare type DefaultProps = ComponentDefaultProps<ModalProps, keyof Omit<ModalProps, 'aria' | 'heading' | 'leadingAction' | 'supportingAction' | 'returnFocusAfterCloseSelector' | 'imageSlotMode'>>;
33
33
 
34
34
  export declare const defaultProps: DefaultProps;
35
35
 
36
36
  export declare const headingLevels: readonly ["h1", "h2", "h3", "h4", "h5", "h6"];
37
37
 
38
+ export declare const imageSlotAspectRatios: readonly ["small", "medium", "large"];
39
+
40
+ export declare const imageSlotModes: readonly ["image", "illustration"];
41
+
38
42
  export declare type ModalActionType = 'leading' | 'supporting';
39
43
 
40
44
  export declare type ModalProps = {
@@ -111,6 +115,14 @@ export declare type ModalProps = {
111
115
  * The background color for the modal.
112
116
  */
113
117
  backgroundColor?: typeof backgroundColors[number];
118
+ /**
119
+ * The mode of the image slot; this controls whether the slot is treated as an image or an illustration.
120
+ */
121
+ imageSlotMode?: typeof imageSlotModes[number];
122
+ /**
123
+ * The aspect ratio of the image slot; applies only when `imageSlotMode` is set to `image`.
124
+ */
125
+ imageSlotAspectRatio?: typeof imageSlotAspectRatios[number];
114
126
  };
115
127
 
116
128
  /**
@@ -179,6 +191,8 @@ declare class PieModal_2 extends PieElement implements ModalProps {
179
191
  size: "medium" | "large" | "small";
180
192
  supportingAction: ModalProps['supportingAction'];
181
193
  backgroundColor: "default" | "subtle" | "brand-01" | "brand-02" | "brand-03" | "brand-03-subtle" | "brand-04" | "brand-04-subtle" | "brand-05" | "brand-05-subtle" | "brand-06" | "brand-06-subtle" | "brand-08" | "brand-08-subtle";
194
+ imageSlotMode: ModalProps['imageSlotMode'];
195
+ imageSlotAspectRatio: "medium" | "large" | "small";
182
196
  private _dialog;
183
197
  private _scrollableContainer;
184
198
  private _backButtonClicked;
@@ -238,6 +252,7 @@ declare class PieModal_2 extends PieElement implements ModalProps {
238
252
  * @private
239
253
  */
240
254
  private renderCloseButton;
255
+ private renderModalImageSlot;
241
256
  /**
242
257
  * Template for the back button element. Called within the
243
258
  * main render function.
package/dist/react.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as o from "react";
2
2
  import { createComponent as e } from "@lit/react";
3
3
  import { PieModal as a } from "./index.js";
4
- import { ON_MODAL_BACK_EVENT as c, ON_MODAL_CLOSE_EVENT as s, ON_MODAL_LEADING_ACTION_CLICK as m, ON_MODAL_OPEN_EVENT as _, ON_MODAL_SUPPORTING_ACTION_CLICK as r, backgroundColors as O, defaultProps as M, headingLevels as N, positions as C, sizes as P } from "./index.js";
4
+ import { ON_MODAL_BACK_EVENT as c, ON_MODAL_CLOSE_EVENT as s, ON_MODAL_LEADING_ACTION_CLICK as m, ON_MODAL_OPEN_EVENT as _, ON_MODAL_SUPPORTING_ACTION_CLICK as r, backgroundColors as M, defaultProps as O, headingLevels as N, imageSlotAspectRatios as C, imageSlotModes as P, positions as A, sizes as L } from "./index.js";
5
5
  const i = e({
6
6
  displayName: "PieModal",
7
7
  elementClass: a,
@@ -19,17 +19,19 @@ const i = e({
19
19
  onPieModalSupportingActionClick: "pie-modal-supporting-action-click"
20
20
  // when the modal supporting action is clicked.
21
21
  }
22
- }), t = i;
22
+ }), n = i;
23
23
  export {
24
24
  c as ON_MODAL_BACK_EVENT,
25
25
  s as ON_MODAL_CLOSE_EVENT,
26
26
  m as ON_MODAL_LEADING_ACTION_CLICK,
27
27
  _ as ON_MODAL_OPEN_EVENT,
28
28
  r as ON_MODAL_SUPPORTING_ACTION_CLICK,
29
- t as PieModal,
30
- O as backgroundColors,
31
- M as defaultProps,
29
+ n as PieModal,
30
+ M as backgroundColors,
31
+ O as defaultProps,
32
32
  N as headingLevels,
33
- C as positions,
34
- P as sizes
33
+ C as imageSlotAspectRatios,
34
+ P as imageSlotModes,
35
+ A as positions,
36
+ L as sizes
35
37
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@justeattakeaway/pie-modal",
3
- "version": "1.20.0",
3
+ "version": "1.21.0",
4
4
  "description": "PIE design system modal built using web components",
5
5
  "repository": {
6
6
  "type": "git",
package/src/defs.ts CHANGED
@@ -5,6 +5,8 @@ import { type Variant as ButtonVariant } from '@justeattakeaway/pie-button/src/d
5
5
  export const headingLevels = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] as const;
6
6
  export const sizes = ['small', 'medium', 'large'] as const;
7
7
  export const positions = ['top', 'center'] as const;
8
+ export const imageSlotModes = ['image', 'illustration'] as const;
9
+ export const imageSlotAspectRatios = ['small', 'medium', 'large'] as const;
8
10
 
9
11
  type AriaProps = {
10
12
  close?: string;
@@ -139,6 +141,16 @@ export type ModalProps = {
139
141
  * The background color for the modal.
140
142
  */
141
143
  backgroundColor?: typeof backgroundColors[number];
144
+
145
+ /**
146
+ * The mode of the image slot; this controls whether the slot is treated as an image or an illustration.
147
+ */
148
+ imageSlotMode?: typeof imageSlotModes[number];
149
+
150
+ /**
151
+ * The aspect ratio of the image slot; applies only when `imageSlotMode` is set to `image`.
152
+ */
153
+ imageSlotAspectRatio?: typeof imageSlotAspectRatios[number];
142
154
  };
143
155
 
144
156
  /**
@@ -178,7 +190,7 @@ export const ON_MODAL_SUPPORTING_ACTION_CLICK = 'pie-modal-supporting-action-cli
178
190
 
179
191
  export type ModalActionType = 'leading' | 'supporting';
180
192
 
181
- export type DefaultProps = ComponentDefaultProps<ModalProps, keyof Omit<ModalProps, 'aria' | 'heading' | 'leadingAction' | 'supportingAction' | 'returnFocusAfterCloseSelector'>>;
193
+ export type DefaultProps = ComponentDefaultProps<ModalProps, keyof Omit<ModalProps, 'aria' | 'heading' | 'leadingAction' | 'supportingAction' | 'returnFocusAfterCloseSelector' | 'imageSlotMode'>>;
182
194
 
183
195
  export const defaultProps: DefaultProps = {
184
196
  hasBackButton: false,
@@ -193,4 +205,5 @@ export const defaultProps: DefaultProps = {
193
205
  position: 'center',
194
206
  size: 'medium',
195
207
  backgroundColor: 'default',
208
+ imageSlotAspectRatio: 'medium',
196
209
  };
package/src/index.ts CHANGED
@@ -29,6 +29,8 @@ import {
29
29
  sizes,
30
30
  backgroundColors,
31
31
  defaultProps,
32
+ imageSlotModes,
33
+ imageSlotAspectRatios,
32
34
  ON_MODAL_BACK_EVENT,
33
35
  ON_MODAL_CLOSE_EVENT,
34
36
  ON_MODAL_OPEN_EVENT,
@@ -114,6 +116,13 @@ export class PieModal extends PieElement implements ModalProps {
114
116
  @validPropertyValues(componentSelector, backgroundColors, defaultProps.backgroundColor)
115
117
  public backgroundColor = defaultProps.backgroundColor;
116
118
 
119
+ @property({ type: String })
120
+ public imageSlotMode: ModalProps['imageSlotMode'];
121
+
122
+ @property({ type: String })
123
+ @validPropertyValues(componentSelector, imageSlotAspectRatios, defaultProps.imageSlotAspectRatio)
124
+ public imageSlotAspectRatio = defaultProps.imageSlotAspectRatio;
125
+
117
126
  @query('dialog')
118
127
  private _dialog!: HTMLDialogElement;
119
128
 
@@ -347,11 +356,24 @@ export class PieModal extends PieElement implements ModalProps {
347
356
  }
348
357
  }
349
358
 
350
- private _getHeaderButtonVariant (): 'ghost-secondary' | 'ghost-inverse' {
351
- const isInverted = this.backgroundColor === 'brand-06';
352
- const variant = isInverted ? 'ghost-inverse' : 'ghost-secondary';
359
+ private _getHeaderButtonVariant (): 'ghost-secondary' | 'ghost-inverse' | 'secondary' {
360
+ const { imageSlotMode, backgroundColor } = this;
353
361
 
354
- return variant;
362
+ // Handle the combinations of image slot and background color
363
+ const hasImageSlot = Boolean(imageSlotMode);
364
+ const hasBackgroundColor = Boolean(backgroundColor) && backgroundColor !== 'default';
365
+ const isInverted = backgroundColor === 'brand-06';
366
+
367
+ // default case: image slot is not present
368
+ if (!hasImageSlot) {
369
+ return isInverted ? 'ghost-inverse' : 'ghost-secondary';
370
+ }
371
+
372
+ // image slot is present
373
+ if (imageSlotMode === 'illustration' && !hasBackgroundColor) {
374
+ return 'ghost-secondary';
375
+ }
376
+ return isInverted ? 'ghost-inverse' : 'secondary';
355
377
  }
356
378
 
357
379
  /**
@@ -378,6 +400,18 @@ export class PieModal extends PieElement implements ModalProps {
378
400
  </pie-icon-button>`;
379
401
  }
380
402
 
403
+ private renderModalImageSlot (): TemplateResult | typeof nothing {
404
+ const { imageSlotMode, imageSlotAspectRatio } = this;
405
+ if (!imageSlotMode) return nothing;
406
+
407
+ return html`
408
+ <div class="c-modal-imageSlot c-modal-imageSlot--${imageSlotMode} c-modal-imageSlot--${imageSlotAspectRatio}" data-test-id="modal-image">
409
+ <slot name="image"></slot>
410
+ ${this.renderCloseButton()}
411
+ </div>
412
+ `;
413
+ }
414
+
381
415
  /**
382
416
  * Template for the back button element. Called within the
383
417
  * main render function.
@@ -550,8 +584,12 @@ export class PieModal extends PieElement implements ModalProps {
550
584
  position,
551
585
  size,
552
586
  backgroundColor,
587
+ imageSlotMode,
553
588
  } = this;
554
589
 
590
+ const hasImageSlot = Boolean(imageSlotMode);
591
+ const hasCloseButtonInHeader = !hasImageSlot;
592
+
555
593
  const modalClasses = {
556
594
  'c-modal': true,
557
595
  [`c-modal--${size}`]: true,
@@ -574,10 +612,11 @@ export class PieModal extends PieElement implements ModalProps {
574
612
  aria-live="polite"
575
613
  aria-busy="${isLoading ? 'true' : 'false'}"
576
614
  data-test-id="pie-modal">
615
+ ${this.renderModalImageSlot()}
577
616
  <header class="c-modal-header" data-test-id="modal-header">
578
617
  ${this.renderBackButton()}
579
618
  ${this.renderHeading()}
580
- ${this.renderCloseButton()}
619
+ ${hasCloseButtonInHeader ? this.renderCloseButton() : nothing}
581
620
  <slot name="headerContent"></slot>
582
621
  </header>
583
622
  ${
package/src/modal.scss CHANGED
@@ -16,6 +16,7 @@
16
16
  --modal-content-color: var(--dt-color-content-default);
17
17
  --modal-bg-color: var(--dt-color-container-default);
18
18
  --modal-elevation: var(--dt-elevation-below-20);
19
+ --modal-image-slot-bg-color: none;
19
20
 
20
21
  &:focus-visible {
21
22
  outline: none;
@@ -134,6 +135,65 @@
134
135
  }
135
136
  }
136
137
 
138
+ & .c-modal-closeBtn {
139
+ grid-area: close;
140
+ margin-block-start: var(--dt-spacing-b);
141
+ margin-block-end: var(--dt-spacing-b);
142
+ margin-inline-start: var(--dt-spacing-none);
143
+ margin-inline-end: var(--dt-spacing-b);
144
+
145
+ @include media('>md') {
146
+ margin-block-start: var(--dt-spacing-c);
147
+ margin-block-end: var(--dt-spacing-c);
148
+ margin-inline-start: var(--dt-spacing-none);
149
+ margin-inline-end: var(--dt-spacing-c);
150
+ }
151
+ }
152
+
153
+ & .c-modal-imageSlot {
154
+ &.c-modal-imageSlot--illustration {
155
+ display: flex;
156
+ justify-content: center;
157
+ align-items: center;
158
+ height: 200px;
159
+ background-color:var(--modal-image-slot-bg-color);
160
+
161
+ ::slotted([slot="image"]) {
162
+ width: 168px;
163
+ height: 168px;
164
+ overflow: hidden;
165
+ }
166
+ }
167
+
168
+ &.c-modal-imageSlot--image {
169
+ overflow: hidden;
170
+
171
+ // imageSlot--medium = default
172
+ aspect-ratio: 3/1;
173
+
174
+ &.c-modal-imageSlot--small {
175
+ aspect-ratio: 4/1;
176
+ }
177
+
178
+ &.c-modal-imageSlot--large {
179
+ aspect-ratio: 21/9;
180
+ }
181
+
182
+ ::slotted([slot="image"]) {
183
+ width: 100%;
184
+ }
185
+ }
186
+
187
+ & .c-modal-closeBtn {
188
+ position: absolute;
189
+ inset-block-start: 0;
190
+ inset-inline-end: 0;
191
+
192
+ margin-block-start: var(--dt-spacing-d);
193
+ margin-inline-end: var(--dt-spacing-d);
194
+ }
195
+ }
196
+
137
197
  & .c-modal-footer {
138
198
  --modal-button-spacing: var(--dt-spacing-d);
139
199
  --modal-footer-padding: var(--dt-spacing-d);
@@ -207,6 +267,7 @@
207
267
  --modal-header-font-line-height: calc(var(--dt-font-heading-m-italic-line-height--narrow) * 1px);
208
268
  --modal-header-font-weight: var(--dt-font-heading-l-italic-weight);
209
269
  --modal-header-font-style: var(--dt-font-heading-l-italic-font-style);
270
+ font-variation-settings: "slnt" -20;
210
271
 
211
272
  @include media('>md') {
212
273
  --modal-header-font-size: calc(var(--dt-font-heading-l-italic-size--wide) * 1px);
@@ -247,21 +308,6 @@
247
308
  }
248
309
  }
249
310
 
250
- & .c-modal-closeBtn {
251
- grid-area: close;
252
- margin-block-start: var(--dt-spacing-b);
253
- margin-block-end: var(--dt-spacing-b);
254
- margin-inline-start: var(--dt-spacing-none);
255
- margin-inline-end: var(--dt-spacing-b);
256
-
257
- @include media('>md') {
258
- margin-block-start: var(--dt-spacing-c);
259
- margin-block-end: var(--dt-spacing-c);
260
- margin-inline-start: var(--dt-spacing-none);
261
- margin-inline-end: var(--dt-spacing-c);
262
- }
263
- }
264
-
265
311
  & .c-modal-content {
266
312
  // Modal content Custom Props
267
313
  --modal-content-font-size: calc(var(--dt-font-body-l-size) * 1px);
@@ -377,8 +423,7 @@
377
423
  }
378
424
 
379
425
  // Additional background colors
380
- // TODO: This will be implemented by DSW-3541 since this color only applies to image slot background, not the whole modal
381
- // &.c-modal--bg-subtle { --modal-bg-color: var(--dt-color-container-subtle); }
426
+ &.c-modal--bg-subtle { --modal-image-slot-bg-color: var(--dt-color-container-subtle); }
382
427
 
383
428
  &.c-modal--bg-brand-01 { --modal-bg-color: var(--dt-color-support-brand-01); }
384
429