@mirohq/design-system-dialog 0.1.0-dialog.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/dist/module.js ADDED
@@ -0,0 +1,688 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { createContext, useContext, useState, useRef, useEffect, forwardRef } from 'react';
3
+ import { useId } from '@mirohq/design-system-use-id';
4
+ import { useBrowserNavigation } from '@mirohq/design-system-use-browser-navigation';
5
+ import { isTopmostLayer, useOverlay, useOverlayExit } from '@mirohq/design-system-use-overlay';
6
+ import { Primitive } from '@mirohq/design-system-primitive';
7
+ import { composeHandlers, mergeRefs } from '@mirohq/design-system-utils';
8
+ import { createPortal } from 'react-dom';
9
+ import { useFocusTrap } from '@mirohq/design-system-use-focus-trap';
10
+ import { useScrollLock } from '@mirohq/design-system-use-scroll-lock';
11
+ import { keyframes, styled } from '@mirohq/design-system-stitches';
12
+
13
+ const DialogContext = createContext(
14
+ void 0
15
+ );
16
+ const useDialogContext = () => {
17
+ const context = useContext(DialogContext);
18
+ if (context === void 0) {
19
+ throw new Error("Dialog parts must be rendered within a <Dialog> root");
20
+ }
21
+ return context;
22
+ };
23
+
24
+ const Root = ({ children, ...options }) => {
25
+ var _a, _b, _c, _d, _e;
26
+ const depth = ((_b = (_a = useContext(DialogContext)) == null ? void 0 : _a.depth) != null ? _b : 0) + 1;
27
+ const generatedId = useId();
28
+ const id = (_c = options.id) != null ? _c : generatedId;
29
+ const role = (_d = options.role) != null ? _d : "dialog";
30
+ const modal = (_e = options.modal) != null ? _e : true;
31
+ const animated = options.animated === true;
32
+ const controlled = options.open !== void 0;
33
+ const [uncontrolledOpen, setUncontrolledOpen] = useState(
34
+ options.defaultOpen === true
35
+ );
36
+ const open = controlled ? options.open === true : uncontrolledOpen;
37
+ if (controlled && uncontrolledOpen !== open) setUncontrolledOpen(open);
38
+ const [exiting, setExiting] = useState(false);
39
+ const previousOpen = useRef(open);
40
+ if (previousOpen.current !== open) {
41
+ previousOpen.current = open;
42
+ if (open) {
43
+ if (exiting) setExiting(false);
44
+ } else if (animated) {
45
+ setExiting(true);
46
+ }
47
+ }
48
+ const state = open ? "open" : exiting ? "closing" : "closed";
49
+ const optionsRef = useRef(options);
50
+ optionsRef.current = options;
51
+ const reportedOpen = useRef(open);
52
+ const resolvedOpen = useRef(open);
53
+ useEffect(() => {
54
+ var _a2, _b2;
55
+ if (resolvedOpen.current === open) return;
56
+ resolvedOpen.current = open;
57
+ if (reportedOpen.current === open) return;
58
+ reportedOpen.current = open;
59
+ (_b2 = (_a2 = optionsRef.current).onOpenChange) == null ? void 0 : _b2.call(_a2, open);
60
+ });
61
+ const setOpen = (next) => {
62
+ var _a2, _b2;
63
+ if (open === next) return;
64
+ reportedOpen.current = next;
65
+ (_b2 = (_a2 = optionsRef.current).onOpenChange) == null ? void 0 : _b2.call(_a2, next);
66
+ if (!controlled) setUncontrolledOpen(next);
67
+ };
68
+ const onEscapeRef = useRef(() => {
69
+ });
70
+ onEscapeRef.current = (event) => {
71
+ var _a2, _b2;
72
+ if (!isTopmostLayer(id)) return;
73
+ (_b2 = (_a2 = optionsRef.current).onEscapeKeyDown) == null ? void 0 : _b2.call(_a2, event);
74
+ if (event.defaultPrevented) return;
75
+ if (optionsRef.current.closeOnEscape === false) return;
76
+ setOpen(false);
77
+ };
78
+ useEffect(() => {
79
+ if (!open) return;
80
+ const onKeyDown = (event) => {
81
+ if (event.key === "Escape") onEscapeRef.current(event);
82
+ };
83
+ document.addEventListener("keydown", onKeyDown, true);
84
+ return () => document.removeEventListener("keydown", onKeyDown, true);
85
+ }, [open]);
86
+ const onBackRef = useRef(() => false);
87
+ onBackRef.current = () => {
88
+ var _a2, _b2;
89
+ const payload = {
90
+ defaultPrevented: false,
91
+ preventDefault() {
92
+ payload.defaultPrevented = true;
93
+ }
94
+ };
95
+ (_b2 = (_a2 = optionsRef.current).onBackNavigation) == null ? void 0 : _b2.call(_a2, payload);
96
+ if (payload.defaultPrevented === true) return false;
97
+ setOpen(false);
98
+ return !controlled;
99
+ };
100
+ const onForwardRef = useRef(() => false);
101
+ onForwardRef.current = () => {
102
+ var _a2, _b2;
103
+ const payload = {
104
+ defaultPrevented: false,
105
+ preventDefault() {
106
+ payload.defaultPrevented = true;
107
+ }
108
+ };
109
+ (_b2 = (_a2 = optionsRef.current).onForwardNavigation) == null ? void 0 : _b2.call(_a2, payload);
110
+ if (payload.defaultPrevented === true) return false;
111
+ if (optionsRef.current.closeOnBack !== true) return false;
112
+ setOpen(true);
113
+ return !controlled;
114
+ };
115
+ useBrowserNavigation({
116
+ enabled: options.closeOnBack === true,
117
+ open,
118
+ onBack: () => onBackRef.current(),
119
+ onForward: () => onForwardRef.current(),
120
+ // The dialog's nesting depth is what a returning dialog recognizes its
121
+ // own spent entry by: the instance is new after a remount, but the
122
+ // position in the stack is the same.
123
+ claim: "dialog:".concat(depth)
124
+ });
125
+ const insidePressRef = useRef(false);
126
+ useEffect(() => {
127
+ if (!open) return;
128
+ const contentId = "".concat(id, "-content");
129
+ const onPointerDown = (event) => {
130
+ const content = document.getElementById(contentId);
131
+ insidePressRef.current = content !== null && event.target instanceof Node && content.contains(event.target);
132
+ };
133
+ document.addEventListener("pointerdown", onPointerDown, true);
134
+ return () => document.removeEventListener("pointerdown", onPointerDown, true);
135
+ }, [open, id]);
136
+ const interactOutside = (event) => {
137
+ var _a2, _b2;
138
+ if (insidePressRef.current) return;
139
+ (_a2 = options.onInteractOutside) == null ? void 0 : _a2.call(options, event);
140
+ if (event.defaultPrevented) return;
141
+ if (!((_b2 = options.closeOnInteractOutside) != null ? _b2 : role === "dialog")) return;
142
+ setOpen(false);
143
+ };
144
+ const interactOutsideRef = useRef(interactOutside);
145
+ interactOutsideRef.current = interactOutside;
146
+ const backdropRef = useRef(null);
147
+ const triggerRef = useRef(null);
148
+ const closeRef = useRef(null);
149
+ useEffect(() => {
150
+ if (!open || modal) return;
151
+ const contentId = "".concat(id, "-content");
152
+ const onClick = (event) => {
153
+ var _a2, _b2;
154
+ if (!isTopmostLayer(id)) return;
155
+ if (!(event.target instanceof Node)) return;
156
+ if (((_a2 = document.getElementById(contentId)) == null ? void 0 : _a2.contains(event.target)) === true)
157
+ return;
158
+ if (((_b2 = triggerRef.current) == null ? void 0 : _b2.contains(event.target)) === true) return;
159
+ interactOutsideRef.current(event);
160
+ };
161
+ document.addEventListener("click", onClick);
162
+ return () => document.removeEventListener("click", onClick);
163
+ }, [open, modal, id]);
164
+ const [parts, setParts] = useState({
165
+ title: false,
166
+ description: false
167
+ });
168
+ return /* @__PURE__ */ jsx(
169
+ DialogContext.Provider,
170
+ {
171
+ value: {
172
+ state,
173
+ open,
174
+ mounted: state !== "closed",
175
+ modal,
176
+ role,
177
+ id,
178
+ ids: {
179
+ content: "".concat(id, "-content"),
180
+ title: "".concat(id, "-title"),
181
+ description: "".concat(id, "-description")
182
+ },
183
+ depth,
184
+ container: null,
185
+ backdropRef,
186
+ triggerRef,
187
+ closeRef,
188
+ parts,
189
+ setParts,
190
+ toggle: () => setOpen(!open),
191
+ close: () => setOpen(false),
192
+ interactOutside,
193
+ exitComplete: () => setExiting(false)
194
+ },
195
+ children
196
+ }
197
+ );
198
+ };
199
+
200
+ const Trigger$1 = forwardRef(
201
+ ({ asChild = false, ...props }, forwardedRef) => {
202
+ const { open, state, ids, toggle, triggerRef } = useDialogContext();
203
+ const consumer = composeHandlers(
204
+ { onClick: toggle },
205
+ asChild ? props : { type: "button", ...props }
206
+ );
207
+ return /* @__PURE__ */ jsx(
208
+ Primitive.button,
209
+ {
210
+ ...consumer,
211
+ "aria-haspopup": "dialog",
212
+ "aria-expanded": open,
213
+ "aria-controls": open ? ids.content : void 0,
214
+ "data-state": state,
215
+ asChild,
216
+ ref: mergeRefs([triggerRef, forwardedRef])
217
+ }
218
+ );
219
+ }
220
+ );
221
+
222
+ const Portal$1 = ({ children, container }) => {
223
+ const context = useDialogContext();
224
+ if (!context.mounted || typeof document === "undefined") return null;
225
+ return createPortal(
226
+ /* @__PURE__ */ jsx(
227
+ DialogContext.Provider,
228
+ {
229
+ value: { ...context, container: container != null ? container : null },
230
+ children
231
+ }
232
+ ),
233
+ container != null ? container : document.body
234
+ );
235
+ };
236
+
237
+ const Backdrop$1 = forwardRef(
238
+ (props, forwardedRef) => {
239
+ const { modal, state, id, container, backdropRef, interactOutside } = useDialogContext();
240
+ if (!modal) return null;
241
+ const consumer = composeHandlers(
242
+ {
243
+ // Only the topmost dialog of a stack answers an outside press.
244
+ onClick: (event) => {
245
+ if (isTopmostLayer(id)) interactOutside(event.nativeEvent);
246
+ }
247
+ },
248
+ props
249
+ );
250
+ return (
251
+ // role=presentation: the backdrop is a purely visual layer; its press
252
+ // is the pointer half of an outside dismissal, with Escape as the
253
+ // keyboard path (jsx-a11y's keyboard pairing doesn't apply).
254
+ /* @__PURE__ */ jsx(
255
+ "div",
256
+ {
257
+ role: "presentation",
258
+ ...consumer,
259
+ "data-state": state,
260
+ "data-scoped": container === null ? void 0 : "",
261
+ ref: mergeRefs([backdropRef, forwardedRef])
262
+ }
263
+ )
264
+ );
265
+ }
266
+ );
267
+
268
+ const Viewport = forwardRef(
269
+ ({ fullScreen, ...props }, forwardedRef) => {
270
+ const { state, id, modal, container, interactOutside } = useDialogContext();
271
+ const consumer = composeHandlers(
272
+ {
273
+ // Box presses bubble up here — only a press that started on the
274
+ // viewport itself is an outside interaction, and only the topmost
275
+ // dialog of a stack answers it.
276
+ onClick: (event) => {
277
+ if (event.target !== event.currentTarget) return;
278
+ if (!isTopmostLayer(id)) return;
279
+ interactOutside(event.nativeEvent);
280
+ }
281
+ },
282
+ props
283
+ );
284
+ return (
285
+ // role=presentation: a purely presentational positioning wrapper — the
286
+ // press it answers is the pointer half of an outside dismissal, with
287
+ // Escape as the keyboard path.
288
+ /* @__PURE__ */ jsx(
289
+ "div",
290
+ {
291
+ role: "presentation",
292
+ ...consumer,
293
+ "data-state": state,
294
+ "data-scoped": container === null ? void 0 : "",
295
+ "data-modal": modal ? "" : void 0,
296
+ "data-full-screen": fullScreen === true ? "" : void 0,
297
+ ref: forwardedRef
298
+ }
299
+ )
300
+ );
301
+ }
302
+ );
303
+
304
+ const Content$1 = forwardRef(
305
+ ({ initialFocus, ...props }, forwardedRef) => {
306
+ const {
307
+ state,
308
+ open,
309
+ modal,
310
+ role,
311
+ id,
312
+ ids,
313
+ depth,
314
+ container,
315
+ backdropRef,
316
+ triggerRef,
317
+ closeRef,
318
+ parts,
319
+ exitComplete
320
+ } = useDialogContext();
321
+ const contentRef = useRef(null);
322
+ useOverlay(contentRef, {
323
+ enabled: open,
324
+ id,
325
+ depth,
326
+ modal,
327
+ backdrop: () => backdropRef.current,
328
+ initialFocus,
329
+ // A pointer press opens without focusing the trigger (the DS Button
330
+ // suppresses mousedown's native focus), so the close would find only
331
+ // the body to restore to — fall back to the trigger, the invoker APG
332
+ // says focus returns to.
333
+ restoreFocus: () => triggerRef.current
334
+ });
335
+ useOverlayExit(contentRef, {
336
+ exiting: !open,
337
+ boundary: container,
338
+ backdrop: () => backdropRef.current,
339
+ onExitComplete: exitComplete
340
+ });
341
+ useScrollLock(modal, container != null ? container : void 0);
342
+ useFocusTrap(contentRef, {
343
+ // Only a modal dialog traps, and only while topmost — a nested dialog
344
+ // owns focus while open.
345
+ enabled: () => modal && isTopmostLayer(id),
346
+ // The Close part is the cycle's last stop wherever it renders (SPEC).
347
+ last: () => closeRef.current
348
+ });
349
+ useEffect(() => {
350
+ if (!open) return;
351
+ const element = contentRef.current;
352
+ if (element === null) return;
353
+ if (parts.title || document.getElementById(ids.title) !== null) return;
354
+ if (element.hasAttribute("aria-label") || element.hasAttribute("aria-labelledby")) {
355
+ return;
356
+ }
357
+ console.warn(
358
+ "[Dialog] the dialog resolves no accessible name: render a <Dialog.Title>, or give Content an aria-label when it truly cannot have one."
359
+ );
360
+ }, [open, parts.title, ids.title]);
361
+ const labelling = {};
362
+ if (parts.title && props["aria-labelledby"] == null) {
363
+ labelling["aria-labelledby"] = ids.title;
364
+ }
365
+ if (parts.description && props["aria-describedby"] == null) {
366
+ labelling["aria-describedby"] = ids.description;
367
+ }
368
+ return (
369
+ // A neutral element with the role, not <dialog>: the window is the
370
+ // initial focus target, so it carries tabindex — which HTML forbids on
371
+ // <dialog> — and the native element only pays off via showModal(),
372
+ // which this contract deliberately doesn't use.
373
+ /* @__PURE__ */ jsx(
374
+ "div",
375
+ {
376
+ ...props,
377
+ ...labelling,
378
+ role,
379
+ id: ids.content,
380
+ "aria-modal": modal || void 0,
381
+ tabIndex: -1,
382
+ "data-state": state,
383
+ ref: mergeRefs([contentRef, forwardedRef])
384
+ }
385
+ )
386
+ );
387
+ }
388
+ );
389
+
390
+ const Title$1 = forwardRef(
391
+ ({ asChild = false, ...props }, forwardedRef) => {
392
+ const { ids, setParts } = useDialogContext();
393
+ useEffect(() => {
394
+ setParts((parts) => parts.title ? parts : { ...parts, title: true });
395
+ return () => setParts((parts) => parts.title ? { ...parts, title: false } : parts);
396
+ }, [setParts]);
397
+ return /* @__PURE__ */ jsx(
398
+ Primitive.h2,
399
+ {
400
+ ...props,
401
+ id: ids.title,
402
+ asChild,
403
+ ref: forwardedRef
404
+ }
405
+ );
406
+ }
407
+ );
408
+
409
+ const Description$1 = forwardRef(
410
+ ({ asChild = false, ...props }, forwardedRef) => {
411
+ const { ids, setParts } = useDialogContext();
412
+ useEffect(() => {
413
+ setParts(
414
+ (parts) => parts.description ? parts : { ...parts, description: true }
415
+ );
416
+ return () => setParts(
417
+ (parts) => parts.description ? { ...parts, description: false } : parts
418
+ );
419
+ }, [setParts]);
420
+ return /* @__PURE__ */ jsx(
421
+ Primitive.p,
422
+ {
423
+ ...props,
424
+ id: ids.description,
425
+ asChild,
426
+ ref: forwardedRef
427
+ }
428
+ );
429
+ }
430
+ );
431
+
432
+ const Close$1 = forwardRef(
433
+ ({ asChild = false, ...props }, forwardedRef) => {
434
+ const { close, closeRef } = useDialogContext();
435
+ const consumer = composeHandlers(
436
+ { onClick: close },
437
+ asChild ? props : { type: "button", ...props }
438
+ );
439
+ return /* @__PURE__ */ jsx(
440
+ Primitive.button,
441
+ {
442
+ ...consumer,
443
+ asChild,
444
+ ref: mergeRefs([closeRef, forwardedRef])
445
+ }
446
+ );
447
+ }
448
+ );
449
+
450
+ const useDialog = () => {
451
+ const context = useDialogContext();
452
+ return {
453
+ id: context.id,
454
+ isOpen: context.open,
455
+ state: context.state,
456
+ modal: context.modal,
457
+ // Idempotent: toggle() would close an already-open dialog.
458
+ open: () => {
459
+ if (!context.open) context.toggle();
460
+ },
461
+ close: context.close,
462
+ toggle: context.toggle
463
+ };
464
+ };
465
+
466
+ const ANIMATION_DURATION = "250ms";
467
+ const MOTION = "@media (prefers-reduced-motion: no-preference)";
468
+
469
+ const fadeIn = keyframes({
470
+ from: { opacity: 0 },
471
+ to: { opacity: 1 }
472
+ });
473
+ const fadeOut = keyframes({
474
+ from: { opacity: 1 },
475
+ to: { opacity: 0 }
476
+ });
477
+ const Backdrop = styled(Backdrop$1, {
478
+ position: "fixed",
479
+ inset: 0,
480
+ zIndex: "$dialog",
481
+ backgroundColor: "$background-alpha-neutrals-overlay",
482
+ // A scoped dialog (Portal container) pins to the container, not the page.
483
+ "&[data-scoped]": {
484
+ position: "absolute"
485
+ },
486
+ [MOTION]: {
487
+ animation: "".concat(fadeIn, " ").concat(ANIMATION_DURATION, " ease-out"),
488
+ // `forwards` holds the final frame until the unmount lands.
489
+ '&[data-state="closing"]': {
490
+ animation: "".concat(fadeOut, " ").concat(ANIMATION_DURATION, " ease-out forwards")
491
+ }
492
+ }
493
+ });
494
+
495
+ const Close = styled(Close$1, {
496
+ position: "absolute",
497
+ top: "$300",
498
+ right: "$300"
499
+ });
500
+
501
+ const Banner = styled(Primitive.div, {
502
+ margin: "-$500 -$500 0",
503
+ // The floor yields on short screens (text zoom, 400% reflow): the media
504
+ // must not eat the space the title and actions need.
505
+ minHeight: "min(300px, 40vh)",
506
+ borderTopLeftRadius: "$100",
507
+ borderTopRightRadius: "$100",
508
+ overflow: "hidden",
509
+ backgroundColor: "$background-primary-subtle",
510
+ // Media dropped in fills the slot with no hand-made styles.
511
+ "& > img, & > video": {
512
+ display: "block",
513
+ width: "100%",
514
+ height: "100%",
515
+ objectFit: "contain"
516
+ }
517
+ });
518
+ const Title = styled(Title$1, {
519
+ fontFamily: "$heading",
520
+ fontSize: "$300",
521
+ lineHeight: 1.35,
522
+ fontWeight: 400,
523
+ fontFeatureSettings: "'ss01'",
524
+ padding: "$400 $1200 $100 $500",
525
+ margin: "-$500 -$500 0",
526
+ // A banner before it already consumed the window's top inset, so the title
527
+ // must not escape it a second time.
528
+ ["".concat(Banner, " ~ &")]: {
529
+ marginTop: 0
530
+ }
531
+ });
532
+ const Description = styled(Description$1, {
533
+ fontFamily: "$body",
534
+ fontSize: "$200",
535
+ lineHeight: 1.5,
536
+ padding: "$200 $500",
537
+ margin: "0 -$500",
538
+ // As the last part, its own $200 plus the window's $500 would overshoot
539
+ // the $500 closing inset.
540
+ "&:last-child": {
541
+ marginBottom: "-$200"
542
+ }
543
+ });
544
+ const Actions = styled(Primitive.div, {
545
+ display: "flex",
546
+ gap: "$100",
547
+ // The window's inset supplies the $500 closing edge below the row.
548
+ padding: "$200 $500 0",
549
+ margin: "0 -$500"
550
+ });
551
+
552
+ const scaleIn = keyframes({
553
+ from: { opacity: 0, transform: "scale(0.8)" },
554
+ to: { opacity: 1, transform: "scale(1)" }
555
+ });
556
+ const scaleOut = keyframes({
557
+ from: { opacity: 1, transform: "scale(1)" },
558
+ to: { opacity: 0, transform: "scale(0.8)" }
559
+ });
560
+ const StyledViewport = styled(Viewport, {
561
+ position: "fixed",
562
+ inset: 0,
563
+ zIndex: "$dialog",
564
+ display: "flex",
565
+ overflow: "auto",
566
+ padding: "$300",
567
+ "&[data-scoped]": {
568
+ position: "absolute"
569
+ },
570
+ "&[data-full-screen]": {
571
+ padding: 0
572
+ },
573
+ "&:not([data-modal])": {
574
+ pointerEvents: "none"
575
+ }
576
+ });
577
+ const StyledContent = styled(Content$1, {
578
+ position: "relative",
579
+ margin: "auto",
580
+ boxSizing: "border-box",
581
+ width: "fit-content",
582
+ // The floors yield to the screen: WCAG 1.4.10 reflow requires the window
583
+ // to fit a 320px viewport (400% zoom), so neither bound may exceed the
584
+ // layer's width.
585
+ minWidth: "min(560px, 100%)",
586
+ maxWidth: "min(960px, 100%)",
587
+ backgroundColor: "$background-neutrals",
588
+ color: "$text-neutrals",
589
+ borderRadius: "$100",
590
+ boxShadow: "$elevation-300",
591
+ overflowWrap: "break-word",
592
+ outline: "none",
593
+ // The window stays interactive when its (non-modal) layer stops
594
+ // intercepting presses.
595
+ pointerEvents: "auto",
596
+ padding: "$500",
597
+ ["&:has(".concat(Title, ")")]: {
598
+ paddingTop: 0,
599
+ ["& ".concat(Banner)]: { marginTop: 0 },
600
+ ["& ".concat(Title)]: { marginTop: 0 }
601
+ },
602
+ ["&:has(".concat(Actions, ")")]: {
603
+ paddingBottom: 0,
604
+ ["& ".concat(Actions)]: { paddingBottom: "$500" },
605
+ ["& ".concat(Description, ":last-child")]: { marginBottom: 0, paddingBottom: "$500" }
606
+ },
607
+ [MOTION]: {
608
+ animation: "".concat(scaleIn, " ").concat(ANIMATION_DURATION, " ease-out"),
609
+ '&[data-state="closing"]': {
610
+ animation: "".concat(scaleOut, " ").concat(ANIMATION_DURATION, " ease-out forwards")
611
+ }
612
+ },
613
+ variants: {
614
+ scroll: {
615
+ viewport: {},
616
+ window: {
617
+ maxHeight: "100%",
618
+ overflow: "auto",
619
+ ["& ".concat(Title)]: {
620
+ position: "sticky",
621
+ top: 0,
622
+ backgroundColor: "$background-neutrals"
623
+ },
624
+ ["& ".concat(Close)]: {
625
+ position: "sticky",
626
+ top: "$300",
627
+ right: "auto",
628
+ float: "right",
629
+ marginRight: "-$200",
630
+ zIndex: 1
631
+ },
632
+ ["& ".concat(Banner)]: {
633
+ overflow: "visible"
634
+ }
635
+ }
636
+ },
637
+ flat: {
638
+ true: {
639
+ padding: 0,
640
+ overflow: "hidden",
641
+ ["& ".concat(Banner)]: { margin: 0 },
642
+ ["& ".concat(Title)]: { margin: 0 },
643
+ ["& ".concat(Description)]: { margin: 0 },
644
+ ["& ".concat(Description, ":last-child")]: { paddingBottom: "$500" },
645
+ ["& ".concat(Actions)]: { margin: 0, paddingBottom: "$500" }
646
+ }
647
+ },
648
+ fullScreen: {
649
+ true: {
650
+ width: "100%",
651
+ height: "100%",
652
+ minWidth: 0,
653
+ maxWidth: "none",
654
+ margin: 0,
655
+ borderRadius: 0
656
+ }
657
+ }
658
+ },
659
+ compoundVariants: [
660
+ {
661
+ flat: true,
662
+ scroll: "window",
663
+ css: { overflow: "auto" }
664
+ }
665
+ ],
666
+ defaultVariants: {
667
+ scroll: "viewport"
668
+ }
669
+ });
670
+ const Content = forwardRef(({ fullScreen, ...props }, forwardedRef) => /* @__PURE__ */ jsx(StyledViewport, { fullScreen: fullScreen === true, children: /* @__PURE__ */ jsx(StyledContent, { ...props, fullScreen, ref: forwardedRef }) }));
671
+
672
+ const Portal = Portal$1;
673
+
674
+ const Trigger = Trigger$1;
675
+
676
+ const Dialog = (props) => /* @__PURE__ */ jsx(Root, { ...props });
677
+ Dialog.Trigger = Trigger;
678
+ Dialog.Portal = Portal;
679
+ Dialog.Backdrop = Backdrop;
680
+ Dialog.Content = Content;
681
+ Dialog.Banner = Banner;
682
+ Dialog.Title = Title;
683
+ Dialog.Description = Description;
684
+ Dialog.Actions = Actions;
685
+ Dialog.Close = Close;
686
+
687
+ export { Dialog, useDialog };
688
+ //# sourceMappingURL=module.js.map