@justeattakeaway/pie-modal 1.12.0 → 1.14.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
@@ -56,6 +56,7 @@ Ideally, you should install the component using the **`@justeattakeaway/pie-webc
56
56
  | Slot | Description |
57
57
  |-----------|--------------------------------------------------------------------|
58
58
  | `default` | The default slot is used to pass content into the modal component. |
59
+ | `headerContent` | Used to pass additional content to the modal header that scrolls with the heading and controls. |
59
60
  | `footer` | Used to pass optional content to the modal component footer area. |
60
61
 
61
62
  ### CSS Variables
@@ -110,6 +111,18 @@ With a custom footer slot:
110
111
  </pie-modal>
111
112
  ```
112
113
 
114
+ With a custom header content slot:
115
+
116
+ ```html
117
+ <pie-modal heading='My Awesome Heading' headingLevel='h3'>
118
+ <div slot="headerContent">
119
+ <p>Custom header content!</p>
120
+ </div>
121
+ <!-- The default slot -->
122
+ <p>Click me!</p>
123
+ </pie-modal>
124
+ ```
125
+
113
126
  **For Native JS Applications, Vue, Angular, Svelte etc.:**
114
127
 
115
128
  ```js
@@ -175,11 +175,15 @@
175
175
  "name": "PieModal",
176
176
  "slots": [
177
177
  {
178
- "description": "The footer slot",
178
+ "description": "Used to pass additional content to the modal header that scrolls with the heading and controls.",
179
+ "name": "headerContent"
180
+ },
181
+ {
182
+ "description": "Used to pass optional content to the modal component footer area.",
179
183
  "name": "footer"
180
184
  },
181
185
  {
182
- "description": "Default slot",
186
+ "description": "The default slot is used to pass content into the modal component.",
183
187
  "name": ""
184
188
  }
185
189
  ],
package/dist/index.d.ts CHANGED
@@ -148,8 +148,9 @@ export declare const ON_MODAL_SUPPORTING_ACTION_CLICK = "pie-modal-supporting-ac
148
148
  * @event {CustomEvent} pie-modal-back - when the modal back button is clicked.
149
149
  * @event {CustomEvent} pie-modal-leading-action-click - when the modal leading action is clicked.
150
150
  * @event {CustomEvent} pie-modal-supporting-action-click - when the modal supporting action is clicked.
151
- * @slot footer - The footer slot
152
- * @slot - Default slot
151
+ * @slot headerContent - Used to pass additional content to the modal header that scrolls with the heading and controls.
152
+ * @slot footer - Used to pass optional content to the modal component footer area.
153
+ * @slot - The default slot is used to pass content into the modal component.
153
154
  */
154
155
  export declare class PieModal extends PieElement implements ModalProps {
155
156
  aria: ModalProps['aria'];
package/dist/index.js CHANGED
@@ -14,13 +14,13 @@ const k = class k extends F {
14
14
  this.getAttribute("v") || this.setAttribute("v", k.v);
15
15
  }
16
16
  };
17
- k.v = "1.12.0";
17
+ k.v = "1.14.0";
18
18
  let x = k;
19
19
  function W(e) {
20
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;
21
+ for (var t = 0, o = Array(e.length); t < e.length; t++)
22
+ o[t] = e[t];
23
+ return o;
24
24
  } else
25
25
  return Array.from(e);
26
26
  }
@@ -33,54 +33,54 @@ if (typeof window < "u") {
33
33
  };
34
34
  window.addEventListener("testPassive", null, A), window.removeEventListener("testPassive", null, A);
35
35
  }
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), m = [], v = !1, M = -1, u = void 0, f = void 0, D = function(o) {
37
- return m.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), m = [], v = !1, M = -1, u = void 0, f = void 0, D = function(t) {
37
+ return m.some(function(o) {
38
+ return !!(o.options.allowTouchMove && o.options.allowTouchMove(t));
39
39
  });
40
- }, y = function(o) {
41
- var t = o || window.event;
42
- return D(t.target) || t.touches.length > 1 ? !0 : (t.preventDefault && t.preventDefault(), !1);
43
- }, j = function(o) {
40
+ }, y = function(t) {
41
+ var o = t || window.event;
42
+ return D(o.target) || o.touches.length > 1 ? !0 : (o.preventDefault && o.preventDefault(), !1);
43
+ }, j = function(t) {
44
44
  if (f === void 0) {
45
- var t = !1, i = window.innerWidth - document.documentElement.clientWidth;
46
- t && i > 0 && (f = document.body.style.paddingRight, document.body.style.paddingRight = i + "px");
45
+ var o = !1, i = window.innerWidth - document.documentElement.clientWidth;
46
+ o && i > 0 && (f = document.body.style.paddingRight, document.body.style.paddingRight = i + "px");
47
47
  }
48
48
  u === void 0 && (u = document.body.style.overflow, document.body.style.overflow = "hidden");
49
49
  }, R = function() {
50
50
  f !== void 0 && (document.body.style.paddingRight = f, f = void 0), u !== void 0 && (document.body.style.overflow = u, u = void 0);
51
- }, V = function(o) {
52
- return o ? o.scrollHeight - o.scrollTop <= o.clientHeight : !1;
53
- }, Y = function(o, t) {
54
- var i = o.targetTouches[0].clientY - M;
55
- return D(o.target) ? !1 : t && t.scrollTop === 0 && i > 0 || V(t) && i < 0 ? y(o) : (o.stopPropagation(), !0);
56
- }, H = function(o, t) {
57
- if (!o) {
51
+ }, V = function(t) {
52
+ return t ? t.scrollHeight - t.scrollTop <= t.clientHeight : !1;
53
+ }, Y = function(t, o) {
54
+ var i = t.targetTouches[0].clientY - M;
55
+ return D(t.target) ? !1 : o && o.scrollTop === 0 && i > 0 || V(o) && i < 0 ? y(t) : (t.stopPropagation(), !0);
56
+ }, H = function(t, o) {
57
+ if (!t) {
58
58
  console.error("disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.");
59
59
  return;
60
60
  }
61
61
  if (!m.some(function(a) {
62
- return a.targetElement === o;
62
+ return a.targetElement === t;
63
63
  })) {
64
64
  var i = {
65
- targetElement: o,
65
+ targetElement: t,
66
66
  options: {}
67
67
  };
68
- m = [].concat(W(m), [i]), O ? (o.ontouchstart = function(a) {
68
+ m = [].concat(W(m), [i]), O ? (t.ontouchstart = function(a) {
69
69
  a.targetTouches.length === 1 && (M = a.targetTouches[0].clientY);
70
- }, o.ontouchmove = function(a) {
71
- a.targetTouches.length === 1 && Y(a, o);
70
+ }, t.ontouchmove = function(a) {
71
+ a.targetTouches.length === 1 && Y(a, t);
72
72
  }, v || (document.addEventListener("touchmove", y, B ? { passive: !1 } : void 0), v = !0)) : j();
73
73
  }
74
- }, q = function(o) {
75
- if (!o) {
74
+ }, q = function(t) {
75
+ if (!t) {
76
76
  console.error("enableBodyScroll unsuccessful - targetElement must be provided when calling enableBodyScroll on IOS devices.");
77
77
  return;
78
78
  }
79
- m = m.filter(function(t) {
80
- return t.targetElement !== o;
81
- }), O ? (o.ontouchstart = null, o.ontouchmove = null, v && m.length === 0 && (document.removeEventListener("touchmove", y, B ? { passive: !1 } : void 0), v = !1)) : m.length || R();
79
+ m = m.filter(function(o) {
80
+ return o.targetElement !== t;
81
+ }), O ? (t.ontouchstart = null, t.ontouchmove = null, v && m.length === 0 && (document.removeEventListener("touchmove", y, B ? { passive: !1 } : void 0), v = !1)) : m.length || R();
82
82
  };
83
- const U = '*,*:after,*:before{box-sizing:inherit}dialog{position:absolute;left:0;right:0;width:-moz-fit-content;width:-webkit-fit-content;width:fit-content;height:-moz-fit-content;height:-webkit-fit-content;height:fit-content;margin:auto;border:solid;padding:1em;background:#fff;color:#000;display:block}dialog:not([open]){display:none}dialog+.backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background:#0000001a}._dialog_overlay{position:fixed;top:0;right:0;bottom:0;left:0}dialog.fixed{position:fixed;top:50%;transform:translateY(-50%)}.c-modal{--modal-size-s: 450px;--modal-size-m: 600px;--modal-size-l: 1080px;--modal-border-radius: var(--dt-radius-rounded-d);--modal-font: var(--dt-font-interactive-l-family);--modal-bg-color: var(--dt-color-container-default);--modal-elevation: var(--dt-elevation-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(--dt-color-content-default);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 .c-modal-header{display:grid;grid-template-areas:"back heading close";grid-template-columns:minmax(0,max-content) minmax(0,1fr) minmax(0,max-content);align-items:start}.c-modal .c-modal-heading{--modal-header-font-size: calc(var(--dt-font-heading-m-size--narrow) * 1px);--modal-header-font-line-height: calc(var(--dt-font-heading-m-line-height--narrow) * 1px);--modal-header-font-weight: var(--dt-font-heading-m-weight);font-size:var(--modal-header-font-size);line-height:var(--modal-header-font-line-height);font-weight:var(--modal-header-font-weight);margin:0;grid-area:heading;margin-inline-start:var(--dt-spacing-d);margin-inline-end:var(--dt-spacing-d);margin-block:14px}@media (min-width: 769px){.c-modal .c-modal-heading{--modal-header-font-size: calc(var(--dt-font-heading-m-size--wide) * 1px);--modal-header-font-line-height: calc(var(--dt-font-heading-m-line-height--wide) * 1px);margin-inline-start:var(--dt-spacing-e);margin-inline-end:var(--dt-spacing-e);margin-block:20px}}.c-modal .c-modal-backBtn+.c-modal-heading{margin-inline-start:var(--dt-spacing-b)}@media (min-width: 769px){.c-modal .c-modal-backBtn+.c-modal-heading{margin-inline-start:var(--dt-spacing-c)}}.c-modal.c-modal--dismissible .c-modal-heading{margin-inline-end:var(--dt-spacing-d)}@media (min-width: 769px){.c-modal.c-modal--dismissible .c-modal-heading{margin-inline-end:var(--dt-spacing-e)}}.c-modal .c-modal-backBtn{grid-area:back;margin-block-start:var(--dt-spacing-b);margin-block-end:var(--dt-spacing-b);margin-inline-start:var(--dt-spacing-b);margin-inline-end:var(--dt-spacing-none)}@media (min-width: 769px){.c-modal .c-modal-backBtn{margin-block-start:var(--dt-spacing-c);margin-block-end:var(--dt-spacing-c);margin-inline-start:var(--dt-spacing-c);margin-inline-end:var(--dt-spacing-none)}}.c-modal .c-modal-closeBtn{grid-area:close;margin-block-start:var(--dt-spacing-b);margin-block-end:var(--dt-spacing-b);margin-inline-start:var(--dt-spacing-none);margin-inline-end:var(--dt-spacing-b)}@media (min-width: 769px){.c-modal .c-modal-closeBtn{margin-block-start:var(--dt-spacing-c);margin-block-end:var(--dt-spacing-c);margin-inline-start:var(--dt-spacing-none);margin-inline-end:var(--dt-spacing-c)}}.c-modal .c-modal-content{--modal-content-font-size: calc(var(--dt-font-size-16) * 1px);--modal-content-font-weight: var(--dt-font-weight-regular);--modal-content-line-height: calc(var(--dt-font-size-16-line-height) * 1px);--modal-content-padding-block: var(--dt-spacing-a);--modal-content-padding-inline: var(--dt-spacing-d);--modal-content-padding-block-end: var(--dt-spacing-e);--modal-content-min-block-size: var(--dt-spacing-j);position:relative;min-block-size:calc(var(--modal-content-min-block-size) + var(--modal-content-padding-block) + var(--modal-content-padding-block-end));font-size:var(--modal-content-font-size);line-height:var(--modal-content-line-height);font-weight:var(--modal-content-font-weight);padding-inline-start:var(--modal-content-padding-inline);padding-inline-end:var(--modal-content-padding-inline);padding-block-start:var(--modal-content-padding-block);padding-block-end:var(--modal-content-padding-block-end);flex-grow:1}@media (min-width: 769px){.c-modal .c-modal-content{--modal-content-padding-inline: var(--dt-spacing-e)}}.c-modal .c-modal-content: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(--dt-color-container-default) 70%) 0 100%;--bg-scroll-bottom: radial-gradient(farthest-corner at 50% 100%, rgba(0, 0, 0, .3), rgba(0, 0, 0, 0)) 0 100%;--bg-size-scroll-end: 100% 40px;--bg-size-scroll-bottom: 100% 8px;background:var(--bg-scroll-end),var(--bg-scroll-bottom);background-repeat:no-repeat;background-size:var(--bg-size-scroll-end),var(--bg-size-scroll-bottom);background-attachment:local,scroll}.c-modal>.c-modal-scrollContainer .c-modal-content{flex-shrink:0}.c-modal.c-modal--pinnedFooter .c-modal-content{overflow-y:auto}.c-modal.c-modal--loading .c-modal-content pie-spinner{position:absolute;left:50%;top:calc(50% - (var(--modal-content-padding-block-end) - var(--modal-content-padding-block)) / 2);transform:translate(-50%,-50%)}.c-modal.c-modal--loading .c-modal-content .c-modal-contentInner{display:none}.c-modal.c-modal--loading .c-modal-content:not(:last-child) pie-spinner{top:50%}@supports not (aspect-ratio: 1/1){.c-modal .c-modal-scrollContainer{background:none}}.c-modal .c-modal-backBtn-icon:dir(rtl){transform:rotate(180deg)}', X = ["h1", "h2", "h3", "h4", "h5", "h6"], G = ["small", "medium", "large"], J = ["top", "center"], S = "pie-modal-close", _ = "pie-modal-open", L = "pie-modal-back", Q = "pie-modal-leading-action-click", Z = "pie-modal-supporting-action-click", r = {
83
+ const U = '*,*:after,*:before{box-sizing:inherit}dialog{position:absolute;left:0;right:0;width:-moz-fit-content;width:-webkit-fit-content;width:fit-content;height:-moz-fit-content;height:-webkit-fit-content;height:fit-content;margin:auto;border:solid;padding:1em;background:#fff;color:#000;display:block}dialog:not([open]){display:none}dialog+.backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background:#0000001a}._dialog_overlay{position:fixed;top:0;right:0;bottom:0;left:0}dialog.fixed{position:fixed;top:50%;transform:translateY(-50%)}.c-modal{--modal-size-s: 450px;--modal-size-m: 600px;--modal-size-l: 1080px;--modal-border-radius: var(--dt-radius-rounded-d);--modal-font: var(--dt-font-interactive-l-family);--modal-bg-color: var(--dt-color-container-default);--modal-elevation: var(--dt-elevation-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(--dt-color-content-default);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);font-size:var(--modal-header-font-size);line-height:var(--modal-header-font-line-height);font-weight:var(--modal-header-font-weight);margin:0;grid-area:heading;margin-inline-start:var(--dt-spacing-d);margin-inline-end:var(--dt-spacing-d);margin-block:14px}@media (min-width: 769px){.c-modal .c-modal-heading{--modal-header-font-size: calc(var(--dt-font-heading-m-size--wide) * 1px);--modal-header-font-line-height: calc(var(--dt-font-heading-m-line-height--wide) * 1px);margin-inline-start:var(--dt-spacing-e);margin-inline-end:var(--dt-spacing-e);margin-block:20px}}.c-modal .c-modal-backBtn+.c-modal-heading{margin-inline-start:var(--dt-spacing-b)}@media (min-width: 769px){.c-modal .c-modal-backBtn+.c-modal-heading{margin-inline-start:var(--dt-spacing-c)}}.c-modal.c-modal--dismissible .c-modal-heading{margin-inline-end:var(--dt-spacing-d)}@media (min-width: 769px){.c-modal.c-modal--dismissible .c-modal-heading{margin-inline-end:var(--dt-spacing-e)}}.c-modal .c-modal-backBtn{grid-area:back;margin-block-start:var(--dt-spacing-b);margin-block-end:var(--dt-spacing-b);margin-inline-start:var(--dt-spacing-b);margin-inline-end:var(--dt-spacing-none)}@media (min-width: 769px){.c-modal .c-modal-backBtn{margin-block-start:var(--dt-spacing-c);margin-block-end:var(--dt-spacing-c);margin-inline-start:var(--dt-spacing-c);margin-inline-end:var(--dt-spacing-none)}}.c-modal .c-modal-closeBtn{grid-area:close;margin-block-start:var(--dt-spacing-b);margin-block-end:var(--dt-spacing-b);margin-inline-start:var(--dt-spacing-none);margin-inline-end:var(--dt-spacing-b)}@media (min-width: 769px){.c-modal .c-modal-closeBtn{margin-block-start:var(--dt-spacing-c);margin-block-end:var(--dt-spacing-c);margin-inline-start:var(--dt-spacing-none);margin-inline-end:var(--dt-spacing-c)}}.c-modal .c-modal-content{--modal-content-font-size: calc(var(--dt-font-size-16) * 1px);--modal-content-font-weight: var(--dt-font-weight-regular);--modal-content-line-height: calc(var(--dt-font-size-16-line-height) * 1px);--modal-content-padding-block: var(--dt-spacing-a);--modal-content-padding-inline: var(--dt-spacing-d);--modal-content-padding-block-end: var(--dt-spacing-e);--modal-content-min-block-size: var(--dt-spacing-j);position:relative;min-block-size:calc(var(--modal-content-min-block-size) + var(--modal-content-padding-block) + var(--modal-content-padding-block-end));font-size:var(--modal-content-font-size);line-height:var(--modal-content-line-height);font-weight:var(--modal-content-font-weight);padding-inline-start:var(--modal-content-padding-inline);padding-inline-end:var(--modal-content-padding-inline);padding-block-start:var(--modal-content-padding-block);padding-block-end:var(--modal-content-padding-block-end);flex-grow:1}@media (min-width: 769px){.c-modal .c-modal-content{--modal-content-padding-inline: var(--dt-spacing-e)}}.c-modal .c-modal-content: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(--dt-color-container-default) 70%) 0 100%;--bg-scroll-bottom: radial-gradient(farthest-corner at 50% 100%, rgba(0, 0, 0, .3), rgba(0, 0, 0, 0)) 0 100%;--bg-size-scroll-end: 100% 40px;--bg-size-scroll-bottom: 100% 8px;background:var(--bg-scroll-end),var(--bg-scroll-bottom);background-repeat:no-repeat;background-size:var(--bg-size-scroll-end),var(--bg-size-scroll-bottom);background-attachment:local,scroll}.c-modal>.c-modal-scrollContainer .c-modal-content{flex-shrink:0}.c-modal.c-modal--pinnedFooter .c-modal-content{overflow-y:auto}.c-modal.c-modal--loading .c-modal-content pie-spinner{position:absolute;left:50%;top:calc(50% - (var(--modal-content-padding-block-end) - var(--modal-content-padding-block)) / 2);transform:translate(-50%,-50%)}.c-modal.c-modal--loading .c-modal-content .c-modal-contentInner{display:none}.c-modal.c-modal--loading .c-modal-content:not(:last-child) pie-spinner{top:50%}@supports not (aspect-ratio: 1/1){.c-modal .c-modal-scrollContainer{background:none}}.c-modal .c-modal-backBtn-icon:dir(rtl){transform:rotate(180deg)}', X = ["h1", "h2", "h3", "h4", "h5", "h6"], G = ["small", "medium", "large"], J = ["top", "center"], S = "pie-modal-close", _ = "pie-modal-open", L = "pie-modal-back", Q = "pie-modal-leading-action-click", Z = "pie-modal-supporting-action-click", r = {
84
84
  hasBackButton: !1,
85
85
  hasStackedActions: !1,
86
86
  headingLevel: "h2",
@@ -92,10 +92,10 @@ const U = '*,*:after,*:before{box-sizing:inherit}dialog{position:absolute;left:0
92
92
  position: "center",
93
93
  size: "medium"
94
94
  };
95
- var ee = Object.defineProperty, oe = Object.getOwnPropertyDescriptor, l = (e, o, t, i) => {
96
- for (var a = i > 1 ? void 0 : i ? oe(o, t) : o, c = e.length - 1, p; c >= 0; c--)
97
- (p = e[c]) && (a = (i ? p(o, t, a) : p(a)) || a);
98
- return i && a && ee(o, t, a), a;
95
+ var ee = Object.defineProperty, te = Object.getOwnPropertyDescriptor, l = (e, t, o, i) => {
96
+ for (var a = i > 1 ? void 0 : i ? te(t, o) : t, c = e.length - 1, p; c >= 0; c--)
97
+ (p = e[c]) && (a = (i ? p(t, o, a) : p(a)) || a);
98
+ return i && a && ee(t, o, a), a;
99
99
  };
100
100
  const w = "pie-modal";
101
101
  let n = class extends x {
@@ -105,15 +105,15 @@ let n = class extends x {
105
105
  }, this._handleDialogLightDismiss = (e) => {
106
106
  if (!this.isDismissible || e.target !== e.currentTarget)
107
107
  return;
108
- const o = this._dialog.getBoundingClientRect(), {
109
- top: t = 0,
108
+ const t = this._dialog.getBoundingClientRect(), {
109
+ top: o = 0,
110
110
  bottom: i = 0,
111
111
  left: a = 0,
112
112
  right: c = 0
113
- } = o || {};
114
- if (t === 0 && i === 0 && a === 0 && c === 0)
113
+ } = t || {};
114
+ if (o === 0 && i === 0 && a === 0 && c === 0)
115
115
  return;
116
- (e.clientY < t || e.clientY > i || e.clientX < a || e.clientX > c) && (this.isOpen = !1);
116
+ (e.clientY < o || e.clientY > i || e.clientX < a || e.clientX > c) && (this.isOpen = !1);
117
117
  };
118
118
  }
119
119
  get _modalScrollContainer() {
@@ -123,31 +123,31 @@ let n = class extends x {
123
123
  connectedCallback() {
124
124
  super.connectedCallback(), this._abortController = new AbortController();
125
125
  const { signal: e } = this._abortController;
126
- this.addEventListener("click", (o) => this._handleDialogLightDismiss(o)), this._setupEscKeyListener(), document.addEventListener(_, (o) => this._handleModalOpened(o), { signal: e }), document.addEventListener(S, (o) => this._handleModalClosed(o), { signal: e }), document.addEventListener(L, (o) => this._handleModalClosed(o), { signal: e });
126
+ this.addEventListener("click", (t) => this._handleDialogLightDismiss(t)), this._setupEscKeyListener(), document.addEventListener(_, (t) => this._handleModalOpened(t), { signal: e }), document.addEventListener(S, (t) => this._handleModalClosed(t), { signal: e }), document.addEventListener(L, (t) => this._handleModalClosed(t), { signal: e });
127
127
  }
128
128
  disconnectedCallback() {
129
129
  super.disconnectedCallback(), this._abortController.abort(), this._enableBodyScroll(), this._removeEscKeyEventListener();
130
130
  }
131
131
  async firstUpdated(e) {
132
132
  (await import("./dialog-polyfill.esm-CbjBMXAG.js").then((i) => i.default)).registerDialog(this._dialog);
133
- const { signal: t } = this._abortController;
133
+ const { signal: o } = this._abortController;
134
134
  this._dialog.addEventListener("close", () => {
135
135
  this.isOpen = !1;
136
- }, { signal: t }), this._handleModalOpenStateOnFirstRender(e);
136
+ }, { signal: o }), this._handleModalOpenStateOnFirstRender(e);
137
137
  }
138
138
  updated(e) {
139
139
  this._handleModalOpenStateChanged(e), this._handleIsDismissibleChanged(e);
140
140
  }
141
141
  _handleIsDismissibleChanged(e) {
142
- const o = e.get("isDismissible"), t = this.isDismissible;
143
- !o && t && this._removeEscKeyEventListener(), o && !t && this._setupEscKeyListener();
142
+ const t = e.get("isDismissible"), o = this.isDismissible;
143
+ !t && o && this._removeEscKeyEventListener(), t && !o && this._setupEscKeyListener();
144
144
  }
145
145
  /**
146
146
  * Opens the dialog element and disables page scrolling
147
147
  */
148
148
  _handleModalOpened(e) {
149
- const { targetModal: o } = e.detail;
150
- if (o === this) {
149
+ const { targetModal: t } = e.detail;
150
+ if (t === this) {
151
151
  if (this._dialog.hasAttribute("open") || !this._dialog.isConnected)
152
152
  return;
153
153
  this._dialog.showModal(), requestAnimationFrame(() => {
@@ -159,8 +159,8 @@ let n = class extends x {
159
159
  * Closes the dialog element and re-enables page scrolling
160
160
  */
161
161
  _handleModalClosed(e) {
162
- const { targetModal: o } = e.detail;
163
- o === this && (this._enableBodyScroll(), this._dialog.close(), this._returnFocus(), this._removeEscKeyEventListener());
162
+ const { targetModal: t } = e.detail;
163
+ t === this && (this._enableBodyScroll(), this._dialog.close(), this._returnFocus(), this._removeEscKeyEventListener());
164
164
  }
165
165
  /**
166
166
  * Sets up an event listener on the Escape key to prevent dismissing the modal if isDismissible is false
@@ -169,7 +169,7 @@ let n = class extends x {
169
169
  if (!this._escKeyAbortController && !this.isDismissible) {
170
170
  this._escKeyAbortController = new AbortController();
171
171
  const { signal: e } = this._escKeyAbortController;
172
- document.addEventListener("keydown", (o) => this._preventModalKeyboardDismissal(o), { signal: e });
172
+ document.addEventListener("keydown", (t) => this._preventModalKeyboardDismissal(t), { signal: e });
173
173
  }
174
174
  }
175
175
  /**
@@ -185,8 +185,8 @@ let n = class extends x {
185
185
  }
186
186
  // Handles changes to the modal isOpen property by dispatching any appropriate events
187
187
  _handleModalOpenStateChanged(e) {
188
- const o = e.get("isOpen");
189
- o !== void 0 && (o ? this._backButtonClicked ? (this._backButtonClicked = !1, h(this, L, { targetModal: this })) : h(this, S, { targetModal: this }) : h(this, _, { targetModal: this }));
188
+ const t = e.get("isOpen");
189
+ t !== void 0 && (t ? this._backButtonClicked ? (this._backButtonClicked = !1, h(this, L, { targetModal: this })) : h(this, S, { targetModal: this }) : h(this, _, { targetModal: this }));
190
190
  }
191
191
  _handleActionClick(e) {
192
192
  e === "leading" ? (this._dialog.close("leading"), h(this, Q, { targetModal: this })) : e === "supporting" && (this._dialog.close("supporting"), h(this, Z, { targetModal: this }));
@@ -196,9 +196,9 @@ let n = class extends x {
196
196
  * and the chosen element can be found.
197
197
  */
198
198
  _returnFocus() {
199
- var o, t;
200
- const e = (o = this.returnFocusAfterCloseSelector) == null ? void 0 : o.trim();
201
- e && ((t = document.querySelector(e)) == null || t.focus());
199
+ var t, o;
200
+ const e = (t = this.returnFocusAfterCloseSelector) == null ? void 0 : t.trim();
201
+ e && ((o = document.querySelector(e)) == null || o.focus());
202
202
  }
203
203
  /**
204
204
  * Enables body scroll by unlocking the scroll container.
@@ -263,16 +263,16 @@ let n = class extends x {
263
263
  * @private
264
264
  */
265
265
  renderLeadingAction() {
266
- const { ariaLabel: e, text: o, variant: t = "primary" } = this.leadingAction || {};
267
- return o ? s`
266
+ const { ariaLabel: e, text: t, variant: o = "primary" } = this.leadingAction || {};
267
+ return t ? s`
268
268
  <pie-button
269
- variant="${t}"
269
+ variant="${o}"
270
270
  aria-label="${b(e)}"
271
271
  type="submit"
272
272
  ?isFullWidth="${this.hasStackedActions}"
273
273
  @click="${() => this._handleActionClick("leading")}"
274
274
  data-test-id="modal-leading-action">
275
- ${o}
275
+ ${t}
276
276
  </pie-button>
277
277
  ` : g;
278
278
  }
@@ -288,16 +288,16 @@ let n = class extends x {
288
288
  */
289
289
  renderSupportingAction() {
290
290
  var i;
291
- const { ariaLabel: e, text: o, variant: t = "ghost" } = this.supportingAction || {};
292
- return !o || !((i = this.leadingAction) != null && i.text) ? g : s`
291
+ const { ariaLabel: e, text: t, variant: o = "ghost" } = this.supportingAction || {};
292
+ return !t || !((i = this.leadingAction) != null && i.text) ? g : s`
293
293
  <pie-button
294
- variant="${t}"
294
+ variant="${o}"
295
295
  aria-label="${b(e)}"
296
296
  type="reset"
297
297
  ?isFullWidth="${this.hasStackedActions}"
298
298
  @click="${() => this._handleActionClick("supporting")}"
299
299
  data-test-id="modal-supporting-action">
300
- ${o}
300
+ ${t}
301
301
  </pie-button>
302
302
  `;
303
303
  }
@@ -311,17 +311,17 @@ let n = class extends x {
311
311
  var i, a;
312
312
  const e = (i = this.leadingAction) == null ? void 0 : i.text;
313
313
  e || (a = this.supportingAction) != null && a.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.");
314
- const o = {
314
+ const t = {
315
315
  "c-modal-footer": !0,
316
316
  "c-modal-footer--stackedActions": this.hasStackedActions
317
- }, t = e ? s`
318
- <footer class="${z(o)}" data-test-id="pie-modal-footer">
317
+ }, o = e ? s`
318
+ <footer class="${z(t)}" data-test-id="pie-modal-footer">
319
319
  ${this.renderLeadingAction()}
320
320
  ${this.renderSupportingAction()}
321
321
  </footer>` : g;
322
322
  return s`
323
323
  <slot name="footer">
324
- ${t}
324
+ ${o}
325
325
  </slot>`;
326
326
  }
327
327
  /**
@@ -350,18 +350,18 @@ let n = class extends x {
350
350
  * @private
351
351
  */
352
352
  renderHeading() {
353
- const { heading: e, headingLevel: o } = this, t = T(o);
353
+ const { heading: e, headingLevel: t } = this, o = T(t);
354
354
  return s`
355
- <${t} class="c-modal-heading">
355
+ <${o} class="c-modal-heading">
356
356
  ${e}
357
- </${t}>
357
+ </${o}>
358
358
  `;
359
359
  }
360
360
  render() {
361
361
  const {
362
362
  aria: e,
363
- isDismissible: o,
364
- isFooterPinned: t,
363
+ isDismissible: t,
364
+ isFooterPinned: o,
365
365
  isFullWidthBelowMid: i,
366
366
  isLoading: a,
367
367
  position: c,
@@ -370,9 +370,9 @@ let n = class extends x {
370
370
  "c-modal": !0,
371
371
  [`c-modal--${p}`]: !0,
372
372
  "c-modal--top": c === "top",
373
- "c-modal--dismissible": o,
373
+ "c-modal--dismissible": t,
374
374
  "c-modal--loading": a,
375
- "c-modal--pinnedFooter": t,
375
+ "c-modal--pinnedFooter": o,
376
376
  "c-modal--fullWidthBelowMid": i
377
377
  };
378
378
  return s`
@@ -386,9 +386,10 @@ let n = class extends x {
386
386
  ${this.renderBackButton()}
387
387
  ${this.renderHeading()}
388
388
  ${this.renderCloseButton()}
389
+ <slot name="headerContent"></slot>
389
390
  </header>
390
391
  ${// We need to wrap the remaining content in a shared scrollable container if the footer is not pinned
391
- t ? this.renderModalContentAndFooter() : s`
392
+ o ? this.renderModalContentAndFooter() : s`
392
393
  <div class="c-modal-scrollContainer">
393
394
  ${this.renderModalContentAndFooter()}
394
395
  </div>`}
package/dist/react.d.ts CHANGED
@@ -147,8 +147,9 @@ export declare const PieModal: React_2.ForwardRefExoticComponent<React_2.PropsWi
147
147
  * @event {CustomEvent} pie-modal-back - when the modal back button is clicked.
148
148
  * @event {CustomEvent} pie-modal-leading-action-click - when the modal leading action is clicked.
149
149
  * @event {CustomEvent} pie-modal-supporting-action-click - when the modal supporting action is clicked.
150
- * @slot footer - The footer slot
151
- * @slot - Default slot
150
+ * @slot headerContent - Used to pass additional content to the modal header that scrolls with the heading and controls.
151
+ * @slot footer - Used to pass optional content to the modal component footer area.
152
+ * @slot - The default slot is used to pass content into the modal component.
152
153
  */
153
154
  declare class PieModal_2 extends PieElement implements ModalProps {
154
155
  aria: ModalProps['aria'];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@justeattakeaway/pie-modal",
3
- "version": "1.12.0",
3
+ "version": "1.14.0",
4
4
  "description": "PIE design system modal built using web components",
5
5
  "repository": {
6
6
  "type": "git",
@@ -39,10 +39,10 @@
39
39
  "license": "Apache-2.0",
40
40
  "devDependencies": {
41
41
  "@custom-elements-manifest/analyzer": "0.9.0",
42
- "@justeat/pie-design-tokens": "7.3.0",
42
+ "@justeat/pie-design-tokens": "7.4.0",
43
43
  "@justeattakeaway/pie-button": "1.6.7",
44
44
  "@justeattakeaway/pie-components-config": "0.21.0",
45
- "@justeattakeaway/pie-css": "0.20.0",
45
+ "@justeattakeaway/pie-css": "0.21.0",
46
46
  "@justeattakeaway/pie-monorepo-utils": "0.7.0",
47
47
  "@justeattakeaway/pie-text-input": "0.28.12",
48
48
  "@justeattakeaway/pie-wrapper-react": "0.14.3",
package/src/index.ts CHANGED
@@ -51,8 +51,9 @@ export interface ModalEventDetail {
51
51
  * @event {CustomEvent} pie-modal-back - when the modal back button is clicked.
52
52
  * @event {CustomEvent} pie-modal-leading-action-click - when the modal leading action is clicked.
53
53
  * @event {CustomEvent} pie-modal-supporting-action-click - when the modal supporting action is clicked.
54
- * @slot footer - The footer slot
55
- * @slot - Default slot
54
+ * @slot headerContent - Used to pass additional content to the modal header that scrolls with the heading and controls.
55
+ * @slot footer - Used to pass optional content to the modal component footer area.
56
+ * @slot - The default slot is used to pass content into the modal component.
56
57
  */
57
58
  @safeCustomElement('pie-modal')
58
59
  export class PieModal extends PieElement implements ModalProps {
@@ -547,6 +548,7 @@ export class PieModal extends PieElement implements ModalProps {
547
548
  ${this.renderBackButton()}
548
549
  ${this.renderHeading()}
549
550
  ${this.renderCloseButton()}
551
+ <slot name="headerContent"></slot>
550
552
  </header>
551
553
  ${
552
554
  // We need to wrap the remaining content in a shared scrollable container if the footer is not pinned
package/src/modal.scss CHANGED
@@ -160,9 +160,18 @@
160
160
  width: 100%;
161
161
  }
162
162
 
163
+ ::slotted([slot="headerContent"]) {
164
+ grid-area: content;
165
+ padding-inline-start: var(--dt-spacing-e);
166
+ padding-inline-end: var(--dt-spacing-e);
167
+ margin-block-end: var(--dt-spacing-d);
168
+ }
169
+
163
170
  & .c-modal-header {
164
171
  display: grid;
165
- grid-template-areas: 'back heading close';
172
+ grid-template-areas:
173
+ 'back heading close'
174
+ 'content content content';
166
175
  grid-template-columns: minmax(0, max-content) minmax(0, 1fr) minmax(0, max-content);
167
176
  align-items: start;
168
177
  }