@justeattakeaway/pie-modal 1.20.1 → 1.22.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
@@ -16,6 +16,7 @@
16
16
  - [Properties](#properties)
17
17
  - [Slots](#slots)
18
18
  - [CSS Variables](#css-variables)
19
+ - [CSS Parts](#css-parts)
19
20
  - [Events](#events)
20
21
  - [Legacy browser support](#legacy-browser-support)
21
22
  - [Usage Examples](#usage-examples)
@@ -54,18 +55,40 @@ Ideally, you should install the component using the **`@justeattakeaway/pie-webc
54
55
  | `position` | `"center"`, `"top"` | The position of the modal; this controls where it will appear on the page. | `"center"` |
55
56
  | `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
57
  | `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"` |
58
+ | `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"` |
59
+ | `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. | — |
60
+ | `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
61
 
59
62
  ### Slots
60
63
  | Slot | Description |
61
64
  |-----------|--------------------------------------------------------------------|
62
65
  | `default` | The default slot is used to pass content into the modal component. |
66
+ | `image` | Used to pass optional content to the modal component image area. |
63
67
  | `headerContent` | Used to pass additional content to the modal header that scrolls with the heading and controls. |
64
68
  | `footer` | Used to pass optional content to the modal component footer area. |
65
69
 
70
+ #### Slots display order
71
+
72
+ The order of content rendering is as follows:
73
+ 1. `image` slot (if provided)
74
+ 2. Modal header (including `heading` prop and `headerContent` slot, if provided)
75
+ 3. `default` slot (main content of the modal)
76
+ 4. `footer` slot (if provided)
77
+
78
+ #### Image Slot Guidelines
79
+ > The `image` slot is designed to accommodate various types of visual content, such as images or illustrations.
80
+ > When using the image slot, please ensure the content is appropriately styled to fit within one of the `imageSlotMode`.
81
+ > The image slot can handle any type of content, such as IMG tags, SVGs, or other HTML elements.
82
+ > Animations or videos can be used, however be cautious about performance implications.
83
+
66
84
  ### CSS Variables
67
85
  This component does not expose any CSS variables for style overrides.
68
86
 
87
+ ### CSS Parts
88
+ | Part | Description |
89
+ |-----------|--------------------------------------------------------------|
90
+ | `heading` | This part allows consumers to fully rewrite the styles of the heading element. |
91
+
69
92
  ### Events
70
93
  | Event | Type | Description |
71
94
  |---------------------------------------|---------------|-----------------------------------------------------------|
@@ -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,86 +1,86 @@
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.1";
18
- let B = w;
19
- function W(e) {
20
- if (Array.isArray(e)) {
21
- for (var o = 0, t = Array(e.length); o < e.length; o++)
22
- t[o] = e[o];
23
- return t;
17
+ _.v = "1.22.0";
18
+ let x = _;
19
+ function V(t) {
20
+ if (Array.isArray(t)) {
21
+ for (var o = 0, e = Array(t.length); o < t.length; o++)
22
+ e[o] = t[o];
23
+ return e;
24
24
  } else
25
- return Array.from(e);
25
+ return Array.from(t);
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) {
37
- return g.some(function(t) {
38
- return !!(t.options.allowTouchMove && t.options.allowTouchMove(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
+ return g.some(function(e) {
38
+ return !!(e.options.allowTouchMove && e.options.allowTouchMove(o));
39
39
  });
40
- }, k = function(o) {
41
- var t = o || window.event;
42
- return D(t.target) || t.touches.length > 1 ? !0 : (t.preventDefault && t.preventDefault(), !1);
43
- }, V = function(o) {
44
- if (f === void 0) {
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");
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) {
40
+ }, w = function(o) {
41
+ var e = o || window.event;
42
+ return D(e.target) || e.touches.length > 1 ? !0 : (e.preventDefault && e.preventDefault(), !1);
43
+ }, j = function(o) {
44
+ if (v === void 0) {
45
+ var e = !1, a = window.innerWidth - document.documentElement.clientWidth;
46
+ e && a > 0 && (v = document.body.style.paddingRight, document.body.style.paddingRight = a + "px");
47
+ }
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, e) {
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 : e && e.scrollTop === 0 && a > 0 || q(e) && a < 0 ? w(o) : (o.stopPropagation(), !0);
56
+ }, X = function(o, e) {
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
- g = g.filter(function(t) {
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();
79
+ g = g.filter(function(e) {
80
+ return e.targetElement !== o;
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);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-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"], to = ["small", "medium", "large"], eo = [
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,63 +107,64 @@ 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 = (t, o, e, a) => {
114
+ for (var i = a > 1 ? void 0 : a ? lo(o, e) : o, m = t.length - 1, p; m >= 0; m--)
115
+ (p = t[m]) && (i = (a ? p(o, e, i) : p(i)) || i);
116
+ return a && i && no(o, e, 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
- e.key === "Escape" && e.preventDefault();
122
- }, this._handleDialogLightDismiss = (e) => {
123
- if (!this.isDismissible || e.target !== e.currentTarget)
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 = (t) => {
122
+ t.key === "Escape" && t.preventDefault();
123
+ }, this._handleDialogLightDismiss = (t) => {
124
+ if (!this.isDismissible || t.target !== t.currentTarget)
124
125
  return;
125
126
  const o = this._dialog.getBoundingClientRect(), {
126
- top: t = 0,
127
+ top: e = 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 (e === 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
+ (t.clientY < e || t.clientY > a || t.clientX < i || t.clientX > m) && (this.isOpen = !1);
134
135
  };
135
136
  }
136
137
  get _modalScrollContainer() {
137
- var e;
138
- return this._scrollableContainer || (this._scrollableContainer = (e = this._dialog) == null ? void 0 : e.querySelector(".c-modal-scrollContainer")), this._scrollableContainer;
138
+ var t;
139
+ return this._scrollableContainer || (this._scrollableContainer = (t = this._dialog) == null ? void 0 : t.querySelector(".c-modal-scrollContainer")), this._scrollableContainer;
139
140
  }
140
141
  connectedCallback() {
141
142
  super.connectedCallback(), this._abortController = new AbortController();
142
- 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 });
143
+ const { signal: t } = this._abortController;
144
+ this.addEventListener("click", (o) => this._handleDialogLightDismiss(o)), this._setupEscKeyListener(), document.addEventListener(C, (o) => this._handleModalOpened(o), { signal: t }), document.addEventListener(L, (o) => this._handleModalClosed(o), { signal: t }), document.addEventListener(M, (o) => this._handleModalClosed(o), { signal: t });
144
145
  }
145
146
  disconnectedCallback() {
146
147
  super.disconnectedCallback(), this._abortController.abort(), this._enableBodyScroll(), this._removeEscKeyEventListener();
147
148
  }
148
- async firstUpdated(e) {
149
+ async firstUpdated(t) {
149
150
  (await import("./dialog-polyfill.esm-CbjBMXAG.js").then((a) => a.default)).registerDialog(this._dialog);
150
- const { signal: t } = this._abortController;
151
+ const { signal: e } = this._abortController;
151
152
  this._dialog.addEventListener("close", () => {
152
153
  this.isOpen = !1;
153
- }, { signal: t }), this._handleModalOpenStateOnFirstRender(e);
154
+ }, { signal: e }), this._handleModalOpenStateOnFirstRender(t);
154
155
  }
155
- updated(e) {
156
- this._handleModalOpenStateChanged(e), this._handleIsDismissibleChanged(e);
156
+ updated(t) {
157
+ this._handleModalOpenStateChanged(t), this._handleIsDismissibleChanged(t);
157
158
  }
158
- _handleIsDismissibleChanged(e) {
159
- const o = e.get("isDismissible"), t = this.isDismissible;
160
- !o && t && this._removeEscKeyEventListener(), o && !t && this._setupEscKeyListener();
159
+ _handleIsDismissibleChanged(t) {
160
+ const o = t.get("isDismissible"), e = this.isDismissible;
161
+ !o && e && this._removeEscKeyEventListener(), o && !e && this._setupEscKeyListener();
161
162
  }
162
163
  /**
163
164
  * Opens the dialog element and disables page scrolling
164
165
  */
165
- _handleModalOpened(e) {
166
- const { targetModal: o } = e.detail;
166
+ _handleModalOpened(t) {
167
+ const { targetModal: o } = t.detail;
167
168
  if (o === this) {
168
169
  if (this._dialog.hasAttribute("open") || !this._dialog.isConnected)
169
170
  return;
@@ -175,8 +176,8 @@ let i = class extends B {
175
176
  /**
176
177
  * Closes the dialog element and re-enables page scrolling
177
178
  */
178
- _handleModalClosed(e) {
179
- const { targetModal: o } = e.detail;
179
+ _handleModalClosed(t) {
180
+ const { targetModal: o } = t.detail;
180
181
  o === this && (this._enableBodyScroll(), this._dialog.close(), this._returnFocus(), this._removeEscKeyEventListener());
181
182
  }
182
183
  /**
@@ -185,52 +186,53 @@ let i = class extends B {
185
186
  _setupEscKeyListener() {
186
187
  if (!this._escKeyAbortController && !this.isDismissible) {
187
188
  this._escKeyAbortController = new AbortController();
188
- const { signal: e } = this._escKeyAbortController;
189
- document.addEventListener("keydown", (o) => this._preventModalKeyboardDismissal(o), { signal: e });
189
+ const { signal: t } = this._escKeyAbortController;
190
+ document.addEventListener("keydown", (o) => this._preventModalKeyboardDismissal(o), { signal: t });
190
191
  }
191
192
  }
192
193
  /**
193
194
  * Removes any event listeners set up that are listening to keyboard events and nulls the existing AbortController.
194
195
  */
195
196
  _removeEscKeyEventListener() {
196
- var e;
197
- (e = this._escKeyAbortController) == null || e.abort(), this._escKeyAbortController = null;
197
+ var t;
198
+ (t = this._escKeyAbortController) == null || t.abort(), this._escKeyAbortController = null;
198
199
  }
199
200
  // Handles the value of the isOpen property on first render of the component
200
- _handleModalOpenStateOnFirstRender(e) {
201
- e.get("isOpen") === void 0 && this.isOpen && u(this, x, { targetModal: this });
201
+ _handleModalOpenStateOnFirstRender(t) {
202
+ t.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
- _handleModalOpenStateChanged(e) {
205
- 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 }));
205
+ _handleModalOpenStateChanged(t) {
206
+ const o = t.get("isOpen");
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
- _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 }));
209
+ _handleActionClick(t) {
210
+ t === "leading" ? (this._dialog.close("leading"), u(this, ao, { targetModal: this })) : t === "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
213
214
  * and the chosen element can be found.
214
215
  */
215
216
  _returnFocus() {
216
- var o, t;
217
- const e = (o = this.returnFocusAfterCloseSelector) == null ? void 0 : o.trim();
218
- e && ((t = document.querySelector(e)) == null || t.focus());
217
+ var o, e;
218
+ const t = (o = this.returnFocusAfterCloseSelector) == null ? void 0 : o.trim();
219
+ t && ((e = document.querySelector(t)) == null || e.focus());
219
220
  }
220
221
  /**
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: t, backgroundColor: o } = this, e = !!t, a = !!o && o !== "default", i = o === "brand-06";
235
+ return e ? t === "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
@@ -239,22 +241,31 @@ let i = class extends B {
239
241
  * @private
240
242
  */
241
243
  renderCloseButton() {
242
- var o, t;
244
+ var o, e;
243
245
  if (!this.isDismissible)
244
- return m;
245
- const e = this._getHeaderButtonVariant();
246
+ return c;
247
+ const t = this._getHeaderButtonVariant();
246
248
  return s`
247
249
  <pie-icon-button
248
250
  @click="${() => {
249
251
  this.isOpen = !1;
250
252
  }}"
251
- variant="${e}"
253
+ variant="${t}"
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: (e = this.aria) == null ? void 0 : e.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: t, imageSlotAspectRatio: o } = this;
262
+ return t ? s`
263
+ <div class="c-modal-imageSlot c-modal-imageSlot--${t} 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.
@@ -262,18 +273,18 @@ let i = class extends B {
262
273
  * @private
263
274
  */
264
275
  renderBackButton() {
265
- var o, t;
276
+ var o, e;
266
277
  if (!this.hasBackButton)
267
- return m;
268
- const e = this._getHeaderButtonVariant();
278
+ return c;
279
+ const t = this._getHeaderButtonVariant();
269
280
  return s`
270
281
  <pie-icon-button
271
282
  @click="${() => {
272
283
  this._backButtonClicked = !0, this.isOpen = !1;
273
284
  }}"
274
- variant="${e}"
285
+ variant="${t}"
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: (e = this.aria) == null ? void 0 : e.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>
@@ -289,18 +300,18 @@ let i = class extends B {
289
300
  * @private
290
301
  */
291
302
  renderLeadingAction() {
292
- const { ariaLabel: e, text: o, variant: t = "primary" } = this.leadingAction || {};
303
+ const { ariaLabel: t, text: o, variant: e = "primary" } = this.leadingAction || {};
293
304
  return o ? s`
294
305
  <pie-button
295
- variant="${t}"
296
- aria-label="${h(e)}"
306
+ variant="${e}"
307
+ aria-label="${h(t)}"
297
308
  type="submit"
298
309
  ?isFullWidth="${this.hasStackedActions}"
299
310
  @click="${() => this._handleActionClick("leading")}"
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.
@@ -314,11 +325,11 @@ let i = class extends B {
314
325
  */
315
326
  renderSupportingAction() {
316
327
  var a;
317
- const { ariaLabel: e, text: o, variant: t = "ghost" } = this.supportingAction || {};
318
- return !o || !((a = this.leadingAction) != null && a.text) ? m : s`
328
+ const { ariaLabel: t, text: o, variant: e = "ghost" } = this.supportingAction || {};
329
+ return !o || !((a = this.leadingAction) != null && a.text) ? c : s`
319
330
  <pie-button
320
- variant="${t}"
321
- aria-label="${h(e)}"
331
+ variant="${e}"
332
+ aria-label="${h(t)}"
322
333
  type="reset"
323
334
  ?isFullWidth="${this.hasStackedActions}"
324
335
  @click="${() => this._handleActionClick("supporting")}"
@@ -334,20 +345,20 @@ let i = class extends B {
334
345
  * @private
335
346
  */
336
347
  renderModalFooter() {
337
- var a, n;
338
- 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.");
348
+ var a, i;
349
+ const t = (a = this.leadingAction) == null ? void 0 : a.text;
350
+ t || (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
- }, t = e ? s`
344
- <footer class="${C(o)}" data-test-id="pie-modal-footer">
354
+ }, e = t ? s`
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
- ${t}
361
+ ${e}
351
362
  </slot>`;
352
363
  }
353
364
  /**
@@ -356,9 +367,9 @@ let i = class extends B {
356
367
  */
357
368
  renderLoadingSpinner() {
358
369
  if (!this.isLoading)
359
- return m;
360
- const e = this.backgroundColor === "brand-06" ? "inverse" : "secondary";
361
- return s`<pie-spinner size="xlarge" variant="${e}"></pie-spinner>`;
370
+ return c;
371
+ const t = this.backgroundColor === "brand-06" ? "inverse" : "secondary";
372
+ return s`<pie-spinner size="xlarge" variant="${t}"></pie-spinner>`;
362
373
  }
363
374
  /**
364
375
  * Renders the modal inner content and footer of the modal.
@@ -379,132 +390,143 @@ 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: t, headingLevel: o, isHeadingEmphasised: e } = 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
- "c-modal-heading--emphasised": t
387
- })}">
388
- ${e}
397
+ "c-modal-heading--emphasised": e
398
+ })}" part="heading" data-test-id="modal-heading">
399
+ ${t}
389
400
  </${a}>
390
401
  `;
391
402
  }
392
403
  render() {
393
404
  const {
394
- aria: e,
405
+ aria: t,
395
406
  isDismissible: o,
396
- isFooterPinned: t,
407
+ isFooterPinned: e,
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,
408
- "c-modal--pinnedFooter": t,
419
+ "c-modal--loading": i,
420
+ "c-modal--pinnedFooter": e,
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 && (t == null ? void 0 : t.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
428
- t ? this.renderModalContentAndFooter() : s`
441
+ e ? this.renderModalContentAndFooter() : s`
429
442
  <div class="c-modal-scrollContainer">
430
443
  ${this.renderModalContentAndFooter()}
431
444
  </div>`}
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, eo, 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, to, 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
+ eo as backgroundColors,
506
526
  r as defaultProps,
507
- G as headingLevels,
508
- Q as positions,
509
- J as sizes
527
+ Q as headingLevels,
528
+ to 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.1",
3
+ "version": "1.22.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,7 @@ import {
29
29
  sizes,
30
30
  backgroundColors,
31
31
  defaultProps,
32
+ imageSlotAspectRatios,
32
33
  ON_MODAL_BACK_EVENT,
33
34
  ON_MODAL_CLOSE_EVENT,
34
35
  ON_MODAL_OPEN_EVENT,
@@ -114,6 +115,13 @@ export class PieModal extends PieElement implements ModalProps {
114
115
  @validPropertyValues(componentSelector, backgroundColors, defaultProps.backgroundColor)
115
116
  public backgroundColor = defaultProps.backgroundColor;
116
117
 
118
+ @property({ type: String })
119
+ public imageSlotMode: ModalProps['imageSlotMode'];
120
+
121
+ @property({ type: String })
122
+ @validPropertyValues(componentSelector, imageSlotAspectRatios, defaultProps.imageSlotAspectRatio)
123
+ public imageSlotAspectRatio = defaultProps.imageSlotAspectRatio;
124
+
117
125
  @query('dialog')
118
126
  private _dialog!: HTMLDialogElement;
119
127
 
@@ -347,11 +355,24 @@ export class PieModal extends PieElement implements ModalProps {
347
355
  }
348
356
  }
349
357
 
350
- private _getHeaderButtonVariant (): 'ghost-secondary' | 'ghost-inverse' {
351
- const isInverted = this.backgroundColor === 'brand-06';
352
- const variant = isInverted ? 'ghost-inverse' : 'ghost-secondary';
358
+ private _getHeaderButtonVariant (): 'ghost-secondary' | 'ghost-inverse' | 'secondary' {
359
+ const { imageSlotMode, backgroundColor } = this;
353
360
 
354
- return variant;
361
+ // Handle the combinations of image slot and background color
362
+ const hasImageSlot = Boolean(imageSlotMode);
363
+ const hasBackgroundColor = Boolean(backgroundColor) && backgroundColor !== 'default';
364
+ const isInverted = backgroundColor === 'brand-06';
365
+
366
+ // default case: image slot is not present
367
+ if (!hasImageSlot) {
368
+ return isInverted ? 'ghost-inverse' : 'ghost-secondary';
369
+ }
370
+
371
+ // image slot is present
372
+ if (imageSlotMode === 'illustration' && !hasBackgroundColor) {
373
+ return 'ghost-secondary';
374
+ }
375
+ return isInverted ? 'ghost-inverse' : 'secondary';
355
376
  }
356
377
 
357
378
  /**
@@ -378,6 +399,18 @@ export class PieModal extends PieElement implements ModalProps {
378
399
  </pie-icon-button>`;
379
400
  }
380
401
 
402
+ private renderModalImageSlot (): TemplateResult | typeof nothing {
403
+ const { imageSlotMode, imageSlotAspectRatio } = this;
404
+ if (!imageSlotMode) return nothing;
405
+
406
+ return html`
407
+ <div class="c-modal-imageSlot c-modal-imageSlot--${imageSlotMode} c-modal-imageSlot--${imageSlotAspectRatio}" data-test-id="modal-image">
408
+ <slot name="image"></slot>
409
+ ${this.renderCloseButton()}
410
+ </div>
411
+ `;
412
+ }
413
+
381
414
  /**
382
415
  * Template for the back button element. Called within the
383
416
  * main render function.
@@ -534,7 +567,7 @@ export class PieModal extends PieElement implements ModalProps {
534
567
  };
535
568
 
536
569
  return html`
537
- <${headingTag} id="modal-heading" class="${classMap(headingClasses)}">
570
+ <${headingTag} id="modal-heading" class="${classMap(headingClasses)}" part="heading" data-test-id="modal-heading">
538
571
  ${heading}
539
572
  </${headingTag}>
540
573
  `;
@@ -550,8 +583,12 @@ export class PieModal extends PieElement implements ModalProps {
550
583
  position,
551
584
  size,
552
585
  backgroundColor,
586
+ imageSlotMode,
553
587
  } = this;
554
588
 
589
+ const hasImageSlot = Boolean(imageSlotMode);
590
+ const hasCloseButtonInHeader = !hasImageSlot;
591
+
555
592
  const modalClasses = {
556
593
  'c-modal': true,
557
594
  [`c-modal--${size}`]: true,
@@ -574,10 +611,11 @@ export class PieModal extends PieElement implements ModalProps {
574
611
  aria-live="polite"
575
612
  aria-busy="${isLoading ? 'true' : 'false'}"
576
613
  data-test-id="pie-modal">
614
+ ${this.renderModalImageSlot()}
577
615
  <header class="c-modal-header" data-test-id="modal-header">
578
616
  ${this.renderBackButton()}
579
617
  ${this.renderHeading()}
580
- ${this.renderCloseButton()}
618
+ ${hasCloseButtonInHeader ? this.renderCloseButton() : nothing}
581
619
  <slot name="headerContent"></slot>
582
620
  </header>
583
621
  ${
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);
@@ -248,21 +308,6 @@
248
308
  }
249
309
  }
250
310
 
251
- & .c-modal-closeBtn {
252
- grid-area: close;
253
- margin-block-start: var(--dt-spacing-b);
254
- margin-block-end: var(--dt-spacing-b);
255
- margin-inline-start: var(--dt-spacing-none);
256
- margin-inline-end: var(--dt-spacing-b);
257
-
258
- @include media('>md') {
259
- margin-block-start: var(--dt-spacing-c);
260
- margin-block-end: var(--dt-spacing-c);
261
- margin-inline-start: var(--dt-spacing-none);
262
- margin-inline-end: var(--dt-spacing-c);
263
- }
264
- }
265
-
266
311
  & .c-modal-content {
267
312
  // Modal content Custom Props
268
313
  --modal-content-font-size: calc(var(--dt-font-body-l-size) * 1px);
@@ -378,8 +423,7 @@
378
423
  }
379
424
 
380
425
  // Additional background colors
381
- // TODO: This will be implemented by DSW-3541 since this color only applies to image slot background, not the whole modal
382
- // &.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); }
383
427
 
384
428
  &.c-modal--bg-brand-01 { --modal-bg-color: var(--dt-color-support-brand-01); }
385
429