@stackone/malachite 2.74.0 → 2.76.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.
@@ -1,169 +1,184 @@
1
- import { jsx as r, jsxs as l, Fragment as j } from "react/jsx-runtime";
2
- import { useId as B, useState as h, useRef as n, useEffect as P, useCallback as V } from "react";
3
- import { createPortal as le } from "react-dom";
4
- import { ShadowRootWrapper as te } from "../ShadowRootWrapper.js";
5
- import ie from "./CalloutStrip.js";
6
- import ne from "./CustomIcons/DismissIcon.js";
7
- import { getDeepActiveElement as oe } from "./activeElement.js";
8
- import { GLASS_SURFACE_STYLE as se } from "./glassSurface.js";
9
- import { MODAL_TRAY_BACKGROUND as ce, MODAL_TRAY_CAPTION_COLOR as de } from "./modalTray.js";
10
- import { useOverlayBehaviour as me, OVERLAY_ICON_BUTTON_CLASSES as ue } from "./overlayBehaviour.js";
11
- import { OVERLAY_ELEVATED_ATTR as pe, overlayIdentity as F } from "./portalOverlay.js";
12
- const U = {
1
+ import { jsx as e, jsxs as l, Fragment as V } from "react/jsx-runtime";
2
+ import { useId as F, useState as b, useRef as n, useEffect as U, useCallback as W } from "react";
3
+ import { createPortal as ce } from "react-dom";
4
+ import { ShadowRootWrapper as de } from "../ShadowRootWrapper.js";
5
+ import me from "./CalloutStrip.js";
6
+ import ue from "./CustomIcons/DismissIcon.js";
7
+ import { getDeepActiveElement as pe } from "./activeElement.js";
8
+ import { GLASS_SURFACE_STYLE as fe } from "./glassSurface.js";
9
+ import { MODAL_TRAY_BACKGROUND as xe, MODAL_TRAY_CAPTION_COLOR as he } from "./modalTray.js";
10
+ import { useOverlayBehaviour as ve, OVERLAY_ICON_BUTTON_CLASSES as be } from "./overlayBehaviour.js";
11
+ import { OVERLAY_ELEVATED_ATTR as ge, overlayIdentity as z } from "./portalOverlay.js";
12
+ const G = {
13
13
  small: "420px",
14
14
  medium: "612px",
15
15
  large: "760px"
16
- }, v = 200, xe = "flex-[0_1_auto] h-[min(600px,calc(100dvh-160px))]", Ie = ({
16
+ }, g = 200, q = "flex-[0_1_auto] h-[min(600px,calc(100dvh-160px))]", Oe = ({
17
17
  open: c,
18
18
  onClose: d,
19
- title: u,
20
- subtitle: p,
21
- icon: b,
22
- headerExtra: g,
23
- titleAdornment: N,
24
- tray: e,
25
- headerDivider: w = !1,
26
- footer: R,
27
- size: _ = "medium",
28
- showCloseButton: W = !0,
29
- closeOnOverlayClick: z = !0,
30
- bodyPadding: A = !0,
31
- bodyHeight: G = "auto",
32
- callouts: x,
33
- renderLink: q,
34
- role: H = "dialog",
35
- "aria-label": K,
36
- "aria-labelledby": T,
37
- "aria-describedby": X,
19
+ title: p,
20
+ subtitle: f,
21
+ icon: N,
22
+ headerExtra: w,
23
+ titleAdornment: y,
24
+ tray: K,
25
+ headerDivider: R = !1,
26
+ footer: _,
27
+ size: A = "medium",
28
+ surface: X = "card",
29
+ showCloseButton: Z = !0,
30
+ closeOnOverlayClick: H = !0,
31
+ bodyPadding: T = !0,
32
+ bodyHeight: I = "auto",
33
+ callouts: J,
34
+ renderLink: Q,
35
+ role: ee = "dialog",
36
+ "aria-label": ae,
37
+ "aria-labelledby": $,
38
+ "aria-describedby": re,
38
39
  busy: o = !1,
39
- children: I
40
+ children: x
40
41
  }) => {
41
- const k = B(), S = B(), m = (x == null ? void 0 : x.filter((a) => a.message.trim())) ?? [], [f, $] = h(!1), [Z, O] = h(!1), [J, E] = h(!1), C = n(null), s = n(null), t = n(null), L = n(o), D = n(d);
42
- P(() => {
43
- L.current = o, D.current = d;
42
+ var P;
43
+ const k = F(), S = F(), m = X === "none", a = m ? void 0 : K, u = ((P = m ? void 0 : J) == null ? void 0 : P.filter((r) => r.message.trim())) ?? [], [h, O] = b(!1), [le, C] = b(!1), [te, E] = b(!1), L = n(null), s = n(null), t = n(null), D = n(o), M = n(d);
44
+ U(() => {
45
+ D.current = o, M.current = d;
44
46
  }, [o, d]);
45
- const M = V(() => {
46
- L.current || D.current();
47
- }, []), y = n(null), {
48
- ref: Y,
49
- isTopmost: Q,
50
- zIndex: ee,
51
- elevated: re
52
- } = me({
47
+ const B = W(() => {
48
+ D.current || M.current();
49
+ }, []), Y = n(null), {
50
+ ref: j,
51
+ isTopmost: ie,
52
+ zIndex: ne,
53
+ elevated: oe
54
+ } = ve({
53
55
  open: c,
54
56
  onClose: d,
55
- hostRef: y
56
- }), ae = V(
57
- (a) => {
58
- C.current = a, Y(a);
57
+ hostRef: Y
58
+ }), se = W(
59
+ (r) => {
60
+ L.current = r, j(r);
59
61
  },
60
- [Y]
62
+ [j]
61
63
  );
62
- return P(() => {
63
- var a;
64
+ if (U(() => {
65
+ var r;
64
66
  if (c)
65
- O(!0), E(!1), t.current && (clearTimeout(t.current), t.current = null), s.current = requestAnimationFrame(() => {
66
- s.current = null, $(!0);
67
+ C(!0), E(!1), t.current && (clearTimeout(t.current), t.current = null), s.current = requestAnimationFrame(() => {
68
+ s.current = null, O(!0);
67
69
  });
68
70
  else {
69
- const i = oe();
70
- i && ((a = C.current) != null && a.contains(i)) && i.blur(), E(!0), $(!1), t.current = setTimeout(() => {
71
- t.current = null, O(!1);
72
- }, v);
71
+ const i = pe();
72
+ i && ((r = L.current) != null && r.contains(i)) && i.blur(), E(!0), O(!1), t.current = setTimeout(() => {
73
+ t.current = null, C(!1);
74
+ }, g);
73
75
  }
74
76
  return () => {
75
77
  s.current !== null && (cancelAnimationFrame(s.current), s.current = null), t.current && (clearTimeout(t.current), t.current = null);
76
78
  };
77
- }, [c]), Z ? le(
79
+ }, [c]), !le)
80
+ return null;
81
+ let v = "relative flex max-h-full w-full flex-col overflow-hidden rounded-[20px] border border-solid border-[var(--malachite-card-border)] bg-[var(--malachite-card-background)] text-[var(--malachite-card-foreground)] outline-none [box-shadow:var(--malachite-shadow-glow,var(--malachite-shadow-lg))]";
82
+ return m ? v = "relative flex max-h-full w-full flex-col outline-none" : a && (v = "relative flex max-h-full w-full flex-col gap-[4px] rounded-[20px] p-[4px] text-[var(--malachite-card-foreground)] outline-none [box-shadow:var(--malachite-shadow-glow,var(--malachite-shadow-lg))]"), ce(
78
83
  // Host carries the stacking context — ShadowRootWrapper's `isolation` would otherwise
79
84
  // flatten our z-index. Not promoted to the top layer, so host dialogs can cover us.
80
- /* @__PURE__ */ r(
81
- te,
85
+ /* @__PURE__ */ e(
86
+ de,
82
87
  {
83
- hostRef: y,
84
- hostStyle: { position: "relative", zIndex: ee },
85
- hostProps: re ? { ...F("modal"), [pe]: "" } : F("modal"),
88
+ hostRef: Y,
89
+ hostStyle: { position: "relative", zIndex: ne },
90
+ hostProps: oe ? { ...z("modal"), [ge]: "" } : z("modal"),
86
91
  children: /* @__PURE__ */ l(
87
92
  "div",
88
93
  {
89
94
  className: `fixed inset-0 z-[1000] flex items-center justify-center p-[16px] ${c ? "" : "pointer-events-none"}`,
90
95
  children: [
91
- /* @__PURE__ */ r(
96
+ /* @__PURE__ */ e(
92
97
  "div",
93
98
  {
94
99
  "aria-hidden": "true",
95
- onClick: z ? M : void 0,
96
- className: `absolute inset-0 bg-[var(--malachite-overlay-scrim)] transition-opacity duration-200 ease-in-out ${f ? "opacity-100" : "opacity-0"}`
100
+ onClick: H ? B : void 0,
101
+ className: `absolute inset-0 bg-[var(--malachite-overlay-scrim)] transition-opacity duration-200 ease-in-out ${h ? "opacity-100" : "opacity-0"}`
97
102
  }
98
103
  ),
99
104
  /* @__PURE__ */ l(
100
105
  "div",
101
106
  {
102
- ref: ae,
103
- role: H,
104
- "aria-hidden": J ? "true" : void 0,
105
- "aria-modal": Q ? "true" : void 0,
107
+ ref: se,
108
+ role: ee,
109
+ "aria-hidden": te ? "true" : void 0,
110
+ "aria-modal": ie ? "true" : void 0,
106
111
  "aria-describedby": [
107
- ...m.map((a, i) => `${S}-${i}`),
108
- X,
109
- e != null && e.caption ? k : null
112
+ ...u.map((r, i) => `${S}-${i}`),
113
+ re,
114
+ a != null && a.caption ? k : null
110
115
  ].filter(Boolean).join(" ") || void 0,
111
116
  "aria-busy": o || void 0,
112
117
  tabIndex: -1,
113
- "aria-label": T ? void 0 : K ?? (typeof u == "string" ? u : void 0),
114
- "aria-labelledby": T,
115
- className: e ? "relative flex max-h-full w-full flex-col gap-[4px] rounded-[20px] p-[4px] text-[var(--malachite-card-foreground)] outline-none [box-shadow:var(--malachite-shadow-glow,var(--malachite-shadow-lg))]" : "relative flex max-h-full w-full flex-col overflow-hidden rounded-[20px] border border-solid border-[var(--malachite-card-border)] bg-[var(--malachite-card-background)] text-[var(--malachite-card-foreground)] outline-none [box-shadow:var(--malachite-shadow-glow,var(--malachite-shadow-lg))]",
118
+ "aria-label": $ ? void 0 : ae ?? (typeof p == "string" ? p : void 0),
119
+ "aria-labelledby": $,
120
+ className: v,
116
121
  style: {
117
- maxWidth: e ? `calc(${U[_]} + 8px)` : U[_],
118
- ...e ? {
119
- backgroundColor: ce[e.tone ?? "neutral"]
122
+ maxWidth: a ? `calc(${G[A]} + 8px)` : G[A],
123
+ ...a ? {
124
+ backgroundColor: xe[a.tone ?? "neutral"]
120
125
  } : {},
121
126
  // Inline: Tailwind scale/translate utilities silently break inside
122
127
  // shadow roots (see CLAUDE.md Shadow DOM caveats).
123
- transform: f ? "scale(1)" : "scale(0.96)",
124
- opacity: f ? 1 : 0,
125
- transition: `transform ${v}ms ease-out, opacity ${v}ms ease-out`
128
+ transform: h ? "scale(1)" : "scale(0.96)",
129
+ opacity: h ? 1 : 0,
130
+ transition: `transform ${g}ms ease-out, opacity ${g}ms ease-out`
126
131
  },
127
132
  children: [
128
- /* @__PURE__ */ l(
133
+ m ? (
134
+ // Still a scroll body: the page behind is locked, so content taller
135
+ // than the viewport has nowhere else to scroll.
136
+ /* @__PURE__ */ e(
137
+ "div",
138
+ {
139
+ className: `min-h-0 ${I === "tall" ? q : "flex-1"} overflow-y-auto`,
140
+ children: x
141
+ }
142
+ )
143
+ ) : /* @__PURE__ */ l(
129
144
  "div",
130
145
  {
131
- className: e ? "flex min-h-0 flex-col overflow-hidden rounded-[16px] border border-solid border-[var(--malachite-card-border)] bg-[var(--malachite-card-background)] [box-shadow:var(--malachite-shadow-glow-lg,var(--malachite-shadow-xl))]" : "contents",
146
+ className: a ? "flex min-h-0 flex-col overflow-hidden rounded-[16px] border border-solid border-[var(--malachite-card-border)] bg-[var(--malachite-card-background)] [box-shadow:var(--malachite-shadow-glow-lg,var(--malachite-shadow-xl))]" : "contents",
132
147
  children: [
133
148
  /* @__PURE__ */ l(
134
149
  "div",
135
150
  {
136
- className: `flex gap-[20px] p-[20px] ${p ? "items-start" : "items-center"} ${w ? "border-0 border-b border-solid border-[var(--malachite-card-border)]" : ""}`,
151
+ className: `flex gap-[20px] p-[20px] ${f ? "items-start" : "items-center"} ${R ? "border-0 border-b border-solid border-[var(--malachite-card-border)]" : ""}`,
137
152
  children: [
138
153
  /* @__PURE__ */ l("div", { className: "flex h-[18px] min-w-0 flex-1 items-center gap-[12px]", children: [
139
154
  /* @__PURE__ */ l("div", { className: "flex min-w-0 items-center gap-[8px]", children: [
140
- b ? /* @__PURE__ */ r("span", { className: "flex shrink-0 items-center", children: b }) : null,
155
+ N ? /* @__PURE__ */ e("span", { className: "flex shrink-0 items-center", children: N }) : null,
141
156
  /* @__PURE__ */ l("div", { className: "flex min-w-0 flex-col gap-[4px]", children: [
142
- /* @__PURE__ */ r("span", { className: "truncate text-[14px] font-medium leading-[1.25] tracking-[-0.14px] text-[var(--malachite-text-primary)]", children: u }),
143
- p ? /* @__PURE__ */ r("span", { className: "text-[13px] leading-[1.6] text-[var(--malachite-text-secondary)]", children: p }) : null
157
+ /* @__PURE__ */ e("span", { className: "truncate text-[14px] font-medium leading-[1.25] tracking-[-0.14px] text-[var(--malachite-text-primary)]", children: p }),
158
+ f ? /* @__PURE__ */ e("span", { className: "text-[13px] leading-[1.6] text-[var(--malachite-text-secondary)]", children: f }) : null
144
159
  ] })
145
160
  ] }),
146
- N ? /* @__PURE__ */ l(j, { children: [
147
- /* @__PURE__ */ r(
161
+ y ? /* @__PURE__ */ l(V, { children: [
162
+ /* @__PURE__ */ e(
148
163
  "span",
149
164
  {
150
165
  "aria-hidden": "true",
151
166
  className: "h-[12px] w-px shrink-0 bg-[var(--malachite-card-border)]"
152
167
  }
153
168
  ),
154
- /* @__PURE__ */ r("span", { className: "flex min-w-0 items-center overflow-hidden", children: N })
169
+ /* @__PURE__ */ e("span", { className: "flex min-w-0 items-center overflow-hidden", children: y })
155
170
  ] }) : null
156
171
  ] }),
157
- g ? /* @__PURE__ */ r("span", { className: "flex shrink-0 items-center", children: g }) : null,
158
- W ? /* @__PURE__ */ r(
172
+ w ? /* @__PURE__ */ e("span", { className: "flex shrink-0 items-center", children: w }) : null,
173
+ Z ? /* @__PURE__ */ e(
159
174
  "button",
160
175
  {
161
176
  type: "button",
162
177
  "aria-label": "Close",
163
- onClick: M,
178
+ onClick: B,
164
179
  disabled: o,
165
- className: ue,
166
- children: /* @__PURE__ */ r(ne, { size: 10 })
180
+ className: be,
181
+ children: /* @__PURE__ */ e(ue, { size: 10 })
167
182
  }
168
183
  ) : null
169
184
  ]
@@ -172,51 +187,51 @@ const U = {
172
187
  /* @__PURE__ */ l(
173
188
  "div",
174
189
  {
175
- className: `min-h-0 ${G === "tall" ? xe : "flex-1"} overflow-y-auto ${A && m.length === 0 ? "px-[20px]" : ""}`,
190
+ className: `min-h-0 ${I === "tall" ? q : "flex-1"} overflow-y-auto ${T && u.length === 0 ? "px-[20px]" : ""}`,
176
191
  children: [
177
- m.map((a, i) => /* @__PURE__ */ r(
178
- ie,
192
+ u.map((r, i) => /* @__PURE__ */ e(
193
+ me,
179
194
  {
180
195
  id: `${S}-${i}`,
181
- type: a.type,
182
- message: a.message,
183
- renderLink: q
196
+ type: r.type,
197
+ message: r.message,
198
+ renderLink: Q
184
199
  },
185
200
  i
186
201
  )),
187
- A ? /* @__PURE__ */ r(
202
+ T ? /* @__PURE__ */ e(
188
203
  "div",
189
204
  {
190
- className: m.length > 0 ? "px-[20px] pt-[18px] pb-[20px]" : `pb-[20px] ${w ? "pt-[18px]" : ""}`,
191
- children: I
205
+ className: u.length > 0 ? "px-[20px] pt-[18px] pb-[20px]" : `pb-[20px] ${R ? "pt-[18px]" : ""}`,
206
+ children: x
192
207
  }
193
- ) : I
208
+ ) : x
194
209
  ]
195
210
  }
196
211
  ),
197
- R ? /* @__PURE__ */ r(
212
+ _ ? /* @__PURE__ */ e(
198
213
  "div",
199
214
  {
200
215
  className: "flex min-h-[56px] shrink-0 items-center border-0 border-t border-solid border-[var(--malachite-card-border)] px-[12px]",
201
- style: se,
202
- children: R
216
+ style: fe,
217
+ children: _
203
218
  }
204
219
  ) : null
205
220
  ]
206
221
  }
207
222
  ),
208
- e != null && e.caption ? /* @__PURE__ */ r(
223
+ a != null && a.caption ? /* @__PURE__ */ e(
209
224
  "div",
210
225
  {
211
226
  id: k,
212
227
  className: "flex h-[48px] shrink-0 items-center justify-center px-[16px] text-[13px] tracking-[0.13px]",
213
- style: { color: de[e.tone ?? "neutral"] },
228
+ style: { color: he[a.tone ?? "neutral"] },
214
229
  children: /* @__PURE__ */ l("span", { children: [
215
- e.caption.label ? /* @__PURE__ */ l(j, { children: [
216
- /* @__PURE__ */ r("span", { className: "font-medium", children: e.caption.label }),
230
+ a.caption.label ? /* @__PURE__ */ l(V, { children: [
231
+ /* @__PURE__ */ e("span", { className: "font-medium", children: a.caption.label }),
217
232
  " "
218
233
  ] }) : null,
219
- e.caption.message
234
+ a.caption.message
220
235
  ] })
221
236
  }
222
237
  ) : null
@@ -229,10 +244,10 @@ const U = {
229
244
  }
230
245
  ),
231
246
  document.body
232
- ) : null;
247
+ );
233
248
  };
234
249
  export {
235
- Ie as Modal,
236
- Ie as default
250
+ Oe as Modal,
251
+ Oe as default
237
252
  };
238
253
  //# sourceMappingURL=Modal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Modal.js","sources":["../../src/components/Modal.tsx"],"sourcesContent":["import type React from 'react';\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { ShadowRootWrapper } from '../ShadowRootWrapper';\nimport type { AlertType } from './Alert';\nimport CalloutStrip from './CalloutStrip';\nimport DismissIcon from './CustomIcons/DismissIcon';\nimport type { RenderLink } from './PageLayout/types';\nimport { getDeepActiveElement } from './activeElement';\nimport { GLASS_SURFACE_STYLE } from './glassSurface';\nimport { MODAL_TRAY_BACKGROUND, MODAL_TRAY_CAPTION_COLOR, type ModalTrayTone } from './modalTray';\nimport { OVERLAY_ICON_BUTTON_CLASSES, useOverlayBehaviour } from './overlayBehaviour';\nimport { OVERLAY_ELEVATED_ATTR, overlayIdentity } from './portalOverlay';\n\nexport type ModalSize = 'small' | 'medium' | 'large';\n\n/** Widths keyed to the size union — a raw `width` prop would let a consumer off the scale. */\nconst SIZE_MAX_WIDTH: Record<ModalSize, string> = {\n small: '420px',\n medium: '612px',\n large: '760px',\n};\n\nconst TRANSITION_MS = 200;\n\n// A basis of its own: a `flex-1` body's zero basis would override the height in Chrome.\nconst TALL_BODY = 'flex-[0_1_auto] h-[min(600px,calc(100dvh-160px))]';\n\nexport interface ModalProps {\n open: boolean;\n /** Dismiss handler — close button, ESC, or overlay click. */\n onClose: () => void;\n title: React.ReactNode;\n /** Secondary line beneath the title. */\n subtitle?: React.ReactNode;\n /** Leading header slot, typically an icon or logo. */\n icon?: React.ReactNode;\n /** Content pinned right in the header, before the close button. */\n headerExtra?: React.ReactNode;\n titleAdornment?: React.ReactNode;\n tray?: { tone?: ModalTrayTone; caption?: { label?: string; message: string } };\n /** Divider under the header. Default: false. */\n headerDivider?: boolean;\n /** Pinned action row below the scrolling body. */\n footer?: React.ReactNode;\n size?: ModalSize;\n /** Default: true. */\n showCloseButton?: boolean;\n /** Default: true. Turn off for a dialog whose choice must be made deliberately. */\n closeOnOverlayClick?: boolean;\n /** Whether the body gets default padding. Default: true. */\n bodyPadding?: boolean;\n /** `tall`: 600px, or the viewport less 160px, for content that sizes to its box. */\n bodyHeight?: 'auto' | 'tall';\n /** Full-width Alert bands at the top of the body, above `children`, in order. Unaffected by\n * `bodyPadding`, and announced ahead of the dialog's description. The message is markdown. */\n callouts?: { type?: AlertType; message: string }[];\n /** Routes root-relative links in `callouts` through the app's router; see `MarkdownBlock`. */\n renderLink?: RenderLink;\n /**\n * `alertdialog` for a dialog interrupting the user over a consequential choice — it\n * tells assistive tech to announce the body, not just the name.\n */\n role?: 'dialog' | 'alertdialog';\n /** Accessible dialog name; required when `title` isn't a plain string. */\n 'aria-label'?: string;\n /** ID of a visible element naming the dialog (alternative to `aria-label`). */\n 'aria-labelledby'?: string;\n /** ID of the element describing what the dialog is asking. */\n 'aria-describedby'?: string;\n /**\n * Work is in flight: suppresses the pointer dismissal routes and announces the busy\n * state. Never ESC — that is the only guaranteed keyboard exit from a focus trap, so it\n * always reaches `onClose` and whether to abort is left to the caller.\n */\n busy?: boolean;\n children: React.ReactNode;\n}\n\nconst Modal: React.FC<ModalProps> = ({\n open,\n onClose,\n title,\n subtitle,\n icon,\n headerExtra,\n titleAdornment,\n tray,\n headerDivider = false,\n footer,\n size = 'medium',\n showCloseButton = true,\n closeOnOverlayClick = true,\n bodyPadding = true,\n bodyHeight = 'auto',\n callouts,\n renderLink,\n role = 'dialog',\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n busy = false,\n children,\n}) => {\n const captionId = useId();\n const calloutId = useId();\n const shownCallouts = callouts?.filter((callout) => callout.message.trim()) ?? [];\n const [isVisible, setIsVisible] = useState(false);\n // Starts false even when `open` does: portals are unsupported on the server, so the\n // dialog must reach `document.body` from the client effect below and nowhere else.\n const [isMounted, setIsMounted] = useState(false);\n // Distinct from `!isVisible`, which is also false on the frame the dialog opens.\n const [isExiting, setIsExiting] = useState(false);\n const panelRef = useRef<HTMLElement | null>(null);\n const frameRef = useRef<number | null>(null);\n const unmountTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const busyRef = useRef(busy);\n const onCloseRef = useRef(onClose);\n useEffect(() => {\n busyRef.current = busy;\n onCloseRef.current = onClose;\n }, [busy, onClose]);\n\n // Pointer routes only. Removing ESC too would leave a focus-trapped keyboard user no\n // exit while a request hangs (WCAG 2.1.2), so ESC always reaches onClose.\n const dismissByPointer = useCallback(() => {\n if (!busyRef.current) {\n onCloseRef.current();\n }\n }, []);\n const hostRef = useRef<HTMLDivElement | null>(null);\n // No prop of its own: it stays in the base band unless a SidePanel elevated the stack,\n // and follows it up when one has.\n const {\n ref: takePanelRef,\n isTopmost,\n zIndex,\n elevated,\n } = useOverlayBehaviour({\n open,\n onClose,\n hostRef,\n });\n const handlePanelRef = useCallback(\n (node: HTMLElement | null) => {\n panelRef.current = node;\n takePanelRef(node);\n },\n [takePanelRef],\n );\n\n // Mounted outlives `open` by one transition, so the dialog can animate out.\n useEffect(() => {\n if (open) {\n setIsMounted(true);\n setIsExiting(false);\n if (unmountTimerRef.current) {\n clearTimeout(unmountTimerRef.current);\n unmountTimerRef.current = null;\n }\n frameRef.current = requestAnimationFrame(() => {\n frameRef.current = null;\n setIsVisible(true);\n });\n } else {\n // A browser refuses `aria-hidden` on a subtree still holding focus, so the\n // attribute waits for this point — after useOverlayBehaviour's cleanup has\n // returned focus to the trigger — and blurs what is left if the trigger has gone.\n const active = getDeepActiveElement();\n if (active && panelRef.current?.contains(active)) {\n active.blur();\n }\n setIsExiting(true);\n setIsVisible(false);\n unmountTimerRef.current = setTimeout(() => {\n unmountTimerRef.current = null;\n setIsMounted(false);\n }, TRANSITION_MS);\n }\n return () => {\n if (frameRef.current !== null) {\n cancelAnimationFrame(frameRef.current);\n frameRef.current = null;\n }\n if (unmountTimerRef.current) {\n clearTimeout(unmountTimerRef.current);\n unmountTimerRef.current = null;\n }\n };\n }, [open]);\n\n if (!isMounted) {\n return null;\n }\n\n return createPortal(\n // Host carries the stacking context — ShadowRootWrapper's `isolation` would otherwise\n // flatten our z-index. Not promoted to the top layer, so host dialogs can cover us.\n <ShadowRootWrapper\n hostRef={hostRef}\n hostStyle={{ position: 'relative', zIndex }}\n hostProps={\n elevated\n ? { ...overlayIdentity('modal'), [OVERLAY_ELEVATED_ATTR]: '' }\n : overlayIdentity('modal')\n }\n >\n {/* The exit transition outlives `open`, so a closed-but-mounted dialog has to stop\n taking clicks and leave the a11y tree — a faded opacity does neither. */}\n <div\n className={`fixed inset-0 z-[1000] flex items-center justify-center p-[16px] ${\n open ? '' : 'pointer-events-none'\n }`}\n >\n <div\n aria-hidden=\"true\"\n onClick={closeOnOverlayClick ? dismissByPointer : undefined}\n className={`absolute inset-0 bg-[var(--malachite-overlay-scrim)] transition-opacity duration-200 ease-in-out ${\n isVisible ? 'opacity-100' : 'opacity-0'\n }`}\n />\n <div\n ref={handlePanelRef}\n role={role}\n aria-hidden={isExiting ? 'true' : undefined}\n aria-modal={isTopmost ? 'true' : undefined}\n aria-describedby={\n [\n ...shownCallouts.map((_, index) => `${calloutId}-${index}`),\n ariaDescribedBy,\n tray?.caption ? captionId : null,\n ]\n .filter(Boolean)\n .join(' ') || undefined\n }\n aria-busy={busy || undefined}\n tabIndex={-1}\n aria-label={\n ariaLabelledBy\n ? undefined\n : (ariaLabel ?? (typeof title === 'string' ? title : undefined))\n }\n aria-labelledby={ariaLabelledBy}\n className={\n tray\n ? 'relative flex max-h-full w-full flex-col gap-[4px] rounded-[20px] p-[4px] text-[var(--malachite-card-foreground)] outline-none [box-shadow:var(--malachite-shadow-glow,var(--malachite-shadow-lg))]'\n : 'relative flex max-h-full w-full flex-col overflow-hidden rounded-[20px] border border-solid border-[var(--malachite-card-border)] bg-[var(--malachite-card-background)] text-[var(--malachite-card-foreground)] outline-none [box-shadow:var(--malachite-shadow-glow,var(--malachite-shadow-lg))]'\n }\n style={{\n maxWidth: tray\n ? `calc(${SIZE_MAX_WIDTH[size]} + 8px)`\n : SIZE_MAX_WIDTH[size],\n ...(tray\n ? {\n backgroundColor: MODAL_TRAY_BACKGROUND[tray.tone ?? 'neutral'],\n }\n : {}),\n // Inline: Tailwind scale/translate utilities silently break inside\n // shadow roots (see CLAUDE.md Shadow DOM caveats).\n transform: isVisible ? 'scale(1)' : 'scale(0.96)',\n opacity: isVisible ? 1 : 0,\n transition: `transform ${TRANSITION_MS}ms ease-out, opacity ${TRANSITION_MS}ms ease-out`,\n }}\n >\n <div\n className={\n tray\n ? 'flex min-h-0 flex-col overflow-hidden rounded-[16px] border border-solid border-[var(--malachite-card-border)] bg-[var(--malachite-card-background)] [box-shadow:var(--malachite-shadow-glow-lg,var(--malachite-shadow-xl))]'\n : 'contents'\n }\n >\n <div\n className={`flex gap-[20px] p-[20px] ${\n subtitle ? 'items-start' : 'items-center'\n } ${\n headerDivider\n ? 'border-0 border-b border-solid border-[var(--malachite-card-border)]'\n : ''\n }`}\n >\n <div className=\"flex h-[18px] min-w-0 flex-1 items-center gap-[12px]\">\n <div className=\"flex min-w-0 items-center gap-[8px]\">\n {icon ? (\n <span className=\"flex shrink-0 items-center\">{icon}</span>\n ) : null}\n <div className=\"flex min-w-0 flex-col gap-[4px]\">\n <span className=\"truncate text-[14px] font-medium leading-[1.25] tracking-[-0.14px] text-[var(--malachite-text-primary)]\">\n {title}\n </span>\n {subtitle ? (\n <span className=\"text-[13px] leading-[1.6] text-[var(--malachite-text-secondary)]\">\n {subtitle}\n </span>\n ) : null}\n </div>\n </div>\n {titleAdornment ? (\n <>\n <span\n aria-hidden=\"true\"\n className=\"h-[12px] w-px shrink-0 bg-[var(--malachite-card-border)]\"\n />\n <span className=\"flex min-w-0 items-center overflow-hidden\">\n {titleAdornment}\n </span>\n </>\n ) : null}\n </div>\n {headerExtra ? (\n <span className=\"flex shrink-0 items-center\">{headerExtra}</span>\n ) : null}\n {showCloseButton ? (\n <button\n type=\"button\"\n aria-label=\"Close\"\n onClick={dismissByPointer}\n disabled={busy}\n className={OVERLAY_ICON_BUTTON_CLASSES}\n >\n <DismissIcon size={10} />\n </button>\n ) : null}\n </div>\n <div\n className={`min-h-0 ${bodyHeight === 'tall' ? TALL_BODY : 'flex-1'} overflow-y-auto ${\n bodyPadding && shownCallouts.length === 0 ? 'px-[20px]' : ''\n }`}\n >\n {shownCallouts.map((callout, index) => (\n <CalloutStrip\n key={index}\n id={`${calloutId}-${index}`}\n type={callout.type}\n message={callout.message}\n renderLink={renderLink}\n />\n ))}\n {bodyPadding ? (\n <div\n className={\n shownCallouts.length > 0\n ? 'px-[20px] pt-[18px] pb-[20px]'\n : `pb-[20px] ${headerDivider ? 'pt-[18px]' : ''}`\n }\n >\n {children}\n </div>\n ) : (\n children\n )}\n </div>\n {footer ? (\n <div\n className=\"flex min-h-[56px] shrink-0 items-center border-0 border-t border-solid border-[var(--malachite-card-border)] px-[12px]\"\n style={GLASS_SURFACE_STYLE}\n >\n {footer}\n </div>\n ) : null}\n </div>\n {tray?.caption ? (\n <div\n id={captionId}\n className=\"flex h-[48px] shrink-0 items-center justify-center px-[16px] text-[13px] tracking-[0.13px]\"\n style={{ color: MODAL_TRAY_CAPTION_COLOR[tray.tone ?? 'neutral'] }}\n >\n <span>\n {tray.caption.label ? (\n <>\n <span className=\"font-medium\">\n {tray.caption.label}\n </span>{' '}\n </>\n ) : null}\n {tray.caption.message}\n </span>\n </div>\n ) : null}\n </div>\n </div>\n </ShadowRootWrapper>,\n document.body,\n );\n};\n\nexport default Modal;\nexport { Modal };\n"],"names":["SIZE_MAX_WIDTH","TRANSITION_MS","TALL_BODY","Modal","open","onClose","title","subtitle","icon","headerExtra","titleAdornment","tray","headerDivider","footer","size","showCloseButton","closeOnOverlayClick","bodyPadding","bodyHeight","callouts","renderLink","role","ariaLabel","ariaLabelledBy","ariaDescribedBy","busy","children","captionId","useId","calloutId","shownCallouts","callout","isVisible","setIsVisible","useState","isMounted","setIsMounted","isExiting","setIsExiting","panelRef","useRef","frameRef","unmountTimerRef","busyRef","onCloseRef","useEffect","dismissByPointer","useCallback","hostRef","takePanelRef","isTopmost","zIndex","elevated","useOverlayBehaviour","handlePanelRef","node","active","getDeepActiveElement","_a","createPortal","jsx","ShadowRootWrapper","overlayIdentity","OVERLAY_ELEVATED_ATTR","jsxs","_","index","MODAL_TRAY_BACKGROUND","Fragment","OVERLAY_ICON_BUTTON_CLASSES","DismissIcon","CalloutStrip","GLASS_SURFACE_STYLE","MODAL_TRAY_CAPTION_COLOR"],"mappings":"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"}
1
+ {"version":3,"file":"Modal.js","sources":["../../src/components/Modal.tsx"],"sourcesContent":["import type React from 'react';\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { ShadowRootWrapper } from '../ShadowRootWrapper';\nimport type { AlertType } from './Alert';\nimport CalloutStrip from './CalloutStrip';\nimport DismissIcon from './CustomIcons/DismissIcon';\nimport type { RenderLink } from './PageLayout/types';\nimport { getDeepActiveElement } from './activeElement';\nimport { GLASS_SURFACE_STYLE } from './glassSurface';\nimport { MODAL_TRAY_BACKGROUND, MODAL_TRAY_CAPTION_COLOR, type ModalTrayTone } from './modalTray';\nimport { OVERLAY_ICON_BUTTON_CLASSES, useOverlayBehaviour } from './overlayBehaviour';\nimport { OVERLAY_ELEVATED_ATTR, overlayIdentity } from './portalOverlay';\n\nexport type ModalSize = 'small' | 'medium' | 'large';\nexport type ModalSurface = 'card' | 'none';\n\n/** Widths keyed to the size union — a raw `width` prop would let a consumer off the scale. */\nconst SIZE_MAX_WIDTH: Record<ModalSize, string> = {\n small: '420px',\n medium: '612px',\n large: '760px',\n};\n\nconst TRANSITION_MS = 200;\n\n// A basis of its own: a `flex-1` body's zero basis would override the height in Chrome.\nconst TALL_BODY = 'flex-[0_1_auto] h-[min(600px,calc(100dvh-160px))]';\n\nexport interface ModalProps {\n open: boolean;\n /** Dismiss handler — close button, ESC, or overlay click. */\n onClose: () => void;\n title: React.ReactNode;\n /** Secondary line beneath the title. */\n subtitle?: React.ReactNode;\n /** Leading header slot, typically an icon or logo. */\n icon?: React.ReactNode;\n /** Content pinned right in the header, before the close button. */\n headerExtra?: React.ReactNode;\n titleAdornment?: React.ReactNode;\n tray?: { tone?: ModalTrayTone; caption?: { label?: string; message: string } };\n /** Divider under the header. Default: false. */\n headerDivider?: boolean;\n /** Pinned action row below the scrolling body. */\n footer?: React.ReactNode;\n size?: ModalSize;\n /**\n * `none` draws no card: no header, close button, footer, callouts or tray, only the\n * overlay and a scroll body around content that brings its own chrome, such as the Hub.\n * `title` then only names the dialog for assistive tech. Default: `card`.\n */\n surface?: ModalSurface;\n /** Default: true. */\n showCloseButton?: boolean;\n /** Default: true. Turn off for a dialog whose choice must be made deliberately. */\n closeOnOverlayClick?: boolean;\n /** Whether the body gets default padding. Default: true. */\n bodyPadding?: boolean;\n /** `tall`: 600px, or the viewport less 160px, for content that sizes to its box. */\n bodyHeight?: 'auto' | 'tall';\n /** Full-width Alert bands at the top of the body, above `children`, in order. Unaffected by\n * `bodyPadding`, and announced ahead of the dialog's description. The message is markdown. */\n callouts?: { type?: AlertType; message: string }[];\n /** Routes root-relative links in `callouts` through the app's router; see `MarkdownBlock`. */\n renderLink?: RenderLink;\n /**\n * `alertdialog` for a dialog interrupting the user over a consequential choice — it\n * tells assistive tech to announce the body, not just the name.\n */\n role?: 'dialog' | 'alertdialog';\n /** Accessible dialog name; required when `title` isn't a plain string. */\n 'aria-label'?: string;\n /** ID of a visible element naming the dialog (alternative to `aria-label`). */\n 'aria-labelledby'?: string;\n /** ID of the element describing what the dialog is asking. */\n 'aria-describedby'?: string;\n /**\n * Work is in flight: suppresses the pointer dismissal routes and announces the busy\n * state. Never ESC — that is the only guaranteed keyboard exit from a focus trap, so it\n * always reaches `onClose` and whether to abort is left to the caller.\n */\n busy?: boolean;\n children: React.ReactNode;\n}\n\nconst Modal: React.FC<ModalProps> = ({\n open,\n onClose,\n title,\n subtitle,\n icon,\n headerExtra,\n titleAdornment,\n tray: trayProp,\n headerDivider = false,\n footer,\n size = 'medium',\n surface = 'card',\n showCloseButton = true,\n closeOnOverlayClick = true,\n bodyPadding = true,\n bodyHeight = 'auto',\n callouts,\n renderLink,\n role = 'dialog',\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n busy = false,\n children,\n}) => {\n const captionId = useId();\n const calloutId = useId();\n const isBare = surface === 'none';\n // A bare dialog has no card to ring or caption, so the tray is not drawn either.\n const tray = isBare ? undefined : trayProp;\n const shownCallouts =\n (isBare ? undefined : callouts)?.filter((callout) => callout.message.trim()) ?? [];\n const [isVisible, setIsVisible] = useState(false);\n // Starts false even when `open` does: portals are unsupported on the server, so the\n // dialog must reach `document.body` from the client effect below and nowhere else.\n const [isMounted, setIsMounted] = useState(false);\n // Distinct from `!isVisible`, which is also false on the frame the dialog opens.\n const [isExiting, setIsExiting] = useState(false);\n const panelRef = useRef<HTMLElement | null>(null);\n const frameRef = useRef<number | null>(null);\n const unmountTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const busyRef = useRef(busy);\n const onCloseRef = useRef(onClose);\n useEffect(() => {\n busyRef.current = busy;\n onCloseRef.current = onClose;\n }, [busy, onClose]);\n\n // Pointer routes only. Removing ESC too would leave a focus-trapped keyboard user no\n // exit while a request hangs (WCAG 2.1.2), so ESC always reaches onClose.\n const dismissByPointer = useCallback(() => {\n if (!busyRef.current) {\n onCloseRef.current();\n }\n }, []);\n const hostRef = useRef<HTMLDivElement | null>(null);\n // No prop of its own: it stays in the base band unless a SidePanel elevated the stack,\n // and follows it up when one has.\n const {\n ref: takePanelRef,\n isTopmost,\n zIndex,\n elevated,\n } = useOverlayBehaviour({\n open,\n onClose,\n hostRef,\n });\n const handlePanelRef = useCallback(\n (node: HTMLElement | null) => {\n panelRef.current = node;\n takePanelRef(node);\n },\n [takePanelRef],\n );\n\n // Mounted outlives `open` by one transition, so the dialog can animate out.\n useEffect(() => {\n if (open) {\n setIsMounted(true);\n setIsExiting(false);\n if (unmountTimerRef.current) {\n clearTimeout(unmountTimerRef.current);\n unmountTimerRef.current = null;\n }\n frameRef.current = requestAnimationFrame(() => {\n frameRef.current = null;\n setIsVisible(true);\n });\n } else {\n // A browser refuses `aria-hidden` on a subtree still holding focus, so the\n // attribute waits for this point — after useOverlayBehaviour's cleanup has\n // returned focus to the trigger — and blurs what is left if the trigger has gone.\n const active = getDeepActiveElement();\n if (active && panelRef.current?.contains(active)) {\n active.blur();\n }\n setIsExiting(true);\n setIsVisible(false);\n unmountTimerRef.current = setTimeout(() => {\n unmountTimerRef.current = null;\n setIsMounted(false);\n }, TRANSITION_MS);\n }\n return () => {\n if (frameRef.current !== null) {\n cancelAnimationFrame(frameRef.current);\n frameRef.current = null;\n }\n if (unmountTimerRef.current) {\n clearTimeout(unmountTimerRef.current);\n unmountTimerRef.current = null;\n }\n };\n }, [open]);\n\n if (!isMounted) {\n return null;\n }\n\n let panelClassName =\n 'relative flex max-h-full w-full flex-col overflow-hidden rounded-[20px] border border-solid border-[var(--malachite-card-border)] bg-[var(--malachite-card-background)] text-[var(--malachite-card-foreground)] outline-none [box-shadow:var(--malachite-shadow-glow,var(--malachite-shadow-lg))]';\n if (isBare) {\n panelClassName = 'relative flex max-h-full w-full flex-col outline-none';\n } else if (tray) {\n panelClassName =\n 'relative flex max-h-full w-full flex-col gap-[4px] rounded-[20px] p-[4px] text-[var(--malachite-card-foreground)] outline-none [box-shadow:var(--malachite-shadow-glow,var(--malachite-shadow-lg))]';\n }\n\n return createPortal(\n // Host carries the stacking context — ShadowRootWrapper's `isolation` would otherwise\n // flatten our z-index. Not promoted to the top layer, so host dialogs can cover us.\n <ShadowRootWrapper\n hostRef={hostRef}\n hostStyle={{ position: 'relative', zIndex }}\n hostProps={\n elevated\n ? { ...overlayIdentity('modal'), [OVERLAY_ELEVATED_ATTR]: '' }\n : overlayIdentity('modal')\n }\n >\n {/* The exit transition outlives `open`, so a closed-but-mounted dialog has to stop\n taking clicks and leave the a11y tree — a faded opacity does neither. */}\n <div\n className={`fixed inset-0 z-[1000] flex items-center justify-center p-[16px] ${\n open ? '' : 'pointer-events-none'\n }`}\n >\n <div\n aria-hidden=\"true\"\n onClick={closeOnOverlayClick ? dismissByPointer : undefined}\n className={`absolute inset-0 bg-[var(--malachite-overlay-scrim)] transition-opacity duration-200 ease-in-out ${\n isVisible ? 'opacity-100' : 'opacity-0'\n }`}\n />\n <div\n ref={handlePanelRef}\n role={role}\n aria-hidden={isExiting ? 'true' : undefined}\n aria-modal={isTopmost ? 'true' : undefined}\n aria-describedby={\n [\n ...shownCallouts.map((_, index) => `${calloutId}-${index}`),\n ariaDescribedBy,\n tray?.caption ? captionId : null,\n ]\n .filter(Boolean)\n .join(' ') || undefined\n }\n aria-busy={busy || undefined}\n tabIndex={-1}\n aria-label={\n ariaLabelledBy\n ? undefined\n : (ariaLabel ?? (typeof title === 'string' ? title : undefined))\n }\n aria-labelledby={ariaLabelledBy}\n className={panelClassName}\n style={{\n maxWidth: tray\n ? `calc(${SIZE_MAX_WIDTH[size]} + 8px)`\n : SIZE_MAX_WIDTH[size],\n ...(tray\n ? {\n backgroundColor: MODAL_TRAY_BACKGROUND[tray.tone ?? 'neutral'],\n }\n : {}),\n // Inline: Tailwind scale/translate utilities silently break inside\n // shadow roots (see CLAUDE.md Shadow DOM caveats).\n transform: isVisible ? 'scale(1)' : 'scale(0.96)',\n opacity: isVisible ? 1 : 0,\n transition: `transform ${TRANSITION_MS}ms ease-out, opacity ${TRANSITION_MS}ms ease-out`,\n }}\n >\n {isBare ? (\n // Still a scroll body: the page behind is locked, so content taller\n // than the viewport has nowhere else to scroll.\n <div\n className={`min-h-0 ${bodyHeight === 'tall' ? TALL_BODY : 'flex-1'} overflow-y-auto`}\n >\n {children}\n </div>\n ) : (\n <div\n className={\n tray\n ? 'flex min-h-0 flex-col overflow-hidden rounded-[16px] border border-solid border-[var(--malachite-card-border)] bg-[var(--malachite-card-background)] [box-shadow:var(--malachite-shadow-glow-lg,var(--malachite-shadow-xl))]'\n : 'contents'\n }\n >\n <div\n className={`flex gap-[20px] p-[20px] ${\n subtitle ? 'items-start' : 'items-center'\n } ${\n headerDivider\n ? 'border-0 border-b border-solid border-[var(--malachite-card-border)]'\n : ''\n }`}\n >\n <div className=\"flex h-[18px] min-w-0 flex-1 items-center gap-[12px]\">\n <div className=\"flex min-w-0 items-center gap-[8px]\">\n {icon ? (\n <span className=\"flex shrink-0 items-center\">\n {icon}\n </span>\n ) : null}\n <div className=\"flex min-w-0 flex-col gap-[4px]\">\n <span className=\"truncate text-[14px] font-medium leading-[1.25] tracking-[-0.14px] text-[var(--malachite-text-primary)]\">\n {title}\n </span>\n {subtitle ? (\n <span className=\"text-[13px] leading-[1.6] text-[var(--malachite-text-secondary)]\">\n {subtitle}\n </span>\n ) : null}\n </div>\n </div>\n {titleAdornment ? (\n <>\n <span\n aria-hidden=\"true\"\n className=\"h-[12px] w-px shrink-0 bg-[var(--malachite-card-border)]\"\n />\n <span className=\"flex min-w-0 items-center overflow-hidden\">\n {titleAdornment}\n </span>\n </>\n ) : null}\n </div>\n {headerExtra ? (\n <span className=\"flex shrink-0 items-center\">\n {headerExtra}\n </span>\n ) : null}\n {showCloseButton ? (\n <button\n type=\"button\"\n aria-label=\"Close\"\n onClick={dismissByPointer}\n disabled={busy}\n className={OVERLAY_ICON_BUTTON_CLASSES}\n >\n <DismissIcon size={10} />\n </button>\n ) : null}\n </div>\n <div\n className={`min-h-0 ${bodyHeight === 'tall' ? TALL_BODY : 'flex-1'} overflow-y-auto ${\n bodyPadding && shownCallouts.length === 0 ? 'px-[20px]' : ''\n }`}\n >\n {shownCallouts.map((callout, index) => (\n <CalloutStrip\n key={index}\n id={`${calloutId}-${index}`}\n type={callout.type}\n message={callout.message}\n renderLink={renderLink}\n />\n ))}\n {bodyPadding ? (\n <div\n className={\n shownCallouts.length > 0\n ? 'px-[20px] pt-[18px] pb-[20px]'\n : `pb-[20px] ${headerDivider ? 'pt-[18px]' : ''}`\n }\n >\n {children}\n </div>\n ) : (\n children\n )}\n </div>\n {footer ? (\n <div\n className=\"flex min-h-[56px] shrink-0 items-center border-0 border-t border-solid border-[var(--malachite-card-border)] px-[12px]\"\n style={GLASS_SURFACE_STYLE}\n >\n {footer}\n </div>\n ) : null}\n </div>\n )}\n {tray?.caption ? (\n <div\n id={captionId}\n className=\"flex h-[48px] shrink-0 items-center justify-center px-[16px] text-[13px] tracking-[0.13px]\"\n style={{ color: MODAL_TRAY_CAPTION_COLOR[tray.tone ?? 'neutral'] }}\n >\n <span>\n {tray.caption.label ? (\n <>\n <span className=\"font-medium\">\n {tray.caption.label}\n </span>{' '}\n </>\n ) : null}\n {tray.caption.message}\n </span>\n </div>\n ) : null}\n </div>\n </div>\n </ShadowRootWrapper>,\n document.body,\n );\n};\n\nexport default Modal;\nexport { Modal };\n"],"names":["SIZE_MAX_WIDTH","TRANSITION_MS","TALL_BODY","Modal","open","onClose","title","subtitle","icon","headerExtra","titleAdornment","trayProp","headerDivider","footer","size","surface","showCloseButton","closeOnOverlayClick","bodyPadding","bodyHeight","callouts","renderLink","role","ariaLabel","ariaLabelledBy","ariaDescribedBy","busy","children","captionId","useId","calloutId","isBare","tray","shownCallouts","_a","callout","isVisible","setIsVisible","useState","isMounted","setIsMounted","isExiting","setIsExiting","panelRef","useRef","frameRef","unmountTimerRef","busyRef","onCloseRef","useEffect","dismissByPointer","useCallback","hostRef","takePanelRef","isTopmost","zIndex","elevated","useOverlayBehaviour","handlePanelRef","node","active","getDeepActiveElement","panelClassName","createPortal","jsx","ShadowRootWrapper","overlayIdentity","OVERLAY_ELEVATED_ATTR","jsxs","_","index","MODAL_TRAY_BACKGROUND","Fragment","OVERLAY_ICON_BUTTON_CLASSES","DismissIcon","CalloutStrip","GLASS_SURFACE_STYLE","MODAL_TRAY_CAPTION_COLOR"],"mappings":"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"}