@edux-design/modals 0.1.2 → 0.2.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/CHANGELOG.md +18 -1
- package/README.md +14 -0
- package/dist/index.d.mts +78 -0
- package/dist/index.d.ts +78 -0
- package/dist/index.js +258 -67
- package/dist/index.mjs +264 -68
- package/docs/confirmation.md +117 -0
- package/package.json +11 -18
- package/src/demos/Modal.stories.jsx +0 -304
- package/src/elements/Modal.jsx +0 -228
- package/src/elements/Modal.test.jsx +0 -139
- package/src/index.js +0 -13
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,27 @@
|
|
|
1
1
|
# @edux-design/modals
|
|
2
2
|
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Add controlled confirmation dialog and anchored popover compositions with pending dismissal policy, error/retry content and safe focus handling. Generate declared public types for both packages.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies
|
|
12
|
+
- @edux-design/buttons@0.3.0
|
|
13
|
+
|
|
14
|
+
## 0.1.3
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- Rebuilt distribution artifacts.
|
|
19
|
+
|
|
3
20
|
## 0.1.2
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
|
6
23
|
|
|
7
|
-
- Updated design tokens
|
|
24
|
+
- Updated design tokens.
|
|
8
25
|
|
|
9
26
|
## 0.1.1
|
|
10
27
|
|
package/README.md
CHANGED
|
@@ -63,3 +63,17 @@ export function PublishModal() {
|
|
|
63
63
|
Passing `onClose` to `Modal` also enables the default close icon inside `ModalHeader`.
|
|
64
64
|
|
|
65
65
|
`ModalContent` accepts `size`, `backdropProps`, the legacy alias `backDropProps`, `className`, and `contentProps`. Storybook examples live in `src/demos/Modal.stories.jsx`.
|
|
66
|
+
|
|
67
|
+
### Size contracts
|
|
68
|
+
|
|
69
|
+
The `small`, `medium`, `large`, and `full` values are named component-owned width
|
|
70
|
+
contracts. They intentionally use responsive `min()` and viewport constraints so
|
|
71
|
+
the modal keeps its current geometry across screen sizes. These values are not
|
|
72
|
+
global width tokens: the design-token standards keep calculated, component-specific
|
|
73
|
+
surface dimensions local until multiple unrelated components share the same role.
|
|
74
|
+
|
|
75
|
+
Unknown `size` values fall back to `medium` for compatibility.
|
|
76
|
+
|
|
77
|
+
## Additional components
|
|
78
|
+
|
|
79
|
+
[Confirmation dialogs](./docs/confirmation.md).
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import * as _radix_ui_react_dialog from '@radix-ui/react-dialog';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
/** @type {React.FC<ModalProps>} */
|
|
5
|
+
declare const Modal: React.FC<ModalProps>;
|
|
6
|
+
declare const ModalTrigger: React.ForwardRefExoticComponent<_radix_ui_react_dialog.DialogTriggerProps & React.RefAttributes<HTMLButtonElement>>;
|
|
7
|
+
declare const ModalClose: React.ForwardRefExoticComponent<_radix_ui_react_dialog.DialogCloseProps & React.RefAttributes<HTMLButtonElement>>;
|
|
8
|
+
declare const ModalPortal: React.FC<_radix_ui_react_dialog.DialogPortalProps>;
|
|
9
|
+
/** @type {React.ForwardRefExoticComponent<ModalOverlayProps & React.RefAttributes<HTMLDivElement>>} */
|
|
10
|
+
declare const ModalOverlay: React.ForwardRefExoticComponent<ModalOverlayProps & React.RefAttributes<HTMLDivElement>>;
|
|
11
|
+
/** @type {React.ForwardRefExoticComponent<ModalContentProps & React.RefAttributes<HTMLDivElement>>} */
|
|
12
|
+
declare const ModalContent: React.ForwardRefExoticComponent<ModalContentProps & React.RefAttributes<HTMLDivElement>>;
|
|
13
|
+
/** @type {React.ForwardRefExoticComponent<ModalHeaderProps & React.RefAttributes<HTMLDivElement>>} */
|
|
14
|
+
declare const ModalHeader: React.ForwardRefExoticComponent<ModalHeaderProps & React.RefAttributes<HTMLDivElement>>;
|
|
15
|
+
/** @type {React.ForwardRefExoticComponent<ModalBodyProps & React.RefAttributes<HTMLDivElement>>} */
|
|
16
|
+
declare const ModalBody: React.ForwardRefExoticComponent<ModalBodyProps & React.RefAttributes<HTMLDivElement>>;
|
|
17
|
+
/** @type {React.ForwardRefExoticComponent<ModalFooterProps & React.RefAttributes<HTMLDivElement>>} */
|
|
18
|
+
declare const ModalFooter: React.ForwardRefExoticComponent<ModalFooterProps & React.RefAttributes<HTMLDivElement>>;
|
|
19
|
+
/** @type {React.ForwardRefExoticComponent<ModalTitleProps & React.RefAttributes<HTMLHeadingElement>>} */
|
|
20
|
+
declare const ModalTitle: React.ForwardRefExoticComponent<ModalTitleProps & React.RefAttributes<HTMLHeadingElement>>;
|
|
21
|
+
/** @type {React.ForwardRefExoticComponent<ModalDescriptionProps & React.RefAttributes<HTMLParagraphElement>>} */
|
|
22
|
+
declare const ModalDescription: React.ForwardRefExoticComponent<ModalDescriptionProps & React.RefAttributes<HTMLParagraphElement>>;
|
|
23
|
+
type ModalProps = _radix_ui_react_dialog.DialogProps & {
|
|
24
|
+
onOpen?: () => void;
|
|
25
|
+
onClose?: () => void;
|
|
26
|
+
};
|
|
27
|
+
type ModalContentProps = _radix_ui_react_dialog.DialogContentProps & {
|
|
28
|
+
size?: "small" | "medium" | "large" | "full";
|
|
29
|
+
backdropProps?: _radix_ui_react_dialog.DialogOverlayProps;
|
|
30
|
+
backDropProps?: _radix_ui_react_dialog.DialogOverlayProps;
|
|
31
|
+
contentProps?: _radix_ui_react_dialog.DialogContentProps;
|
|
32
|
+
portalProps?: _radix_ui_react_dialog.DialogPortalProps;
|
|
33
|
+
};
|
|
34
|
+
type ModalOverlayProps = _radix_ui_react_dialog.DialogOverlayProps;
|
|
35
|
+
type ModalHeaderProps = React.HTMLAttributes<HTMLDivElement>;
|
|
36
|
+
type ModalBodyProps = React.HTMLAttributes<HTMLDivElement>;
|
|
37
|
+
type ModalFooterProps = React.HTMLAttributes<HTMLDivElement>;
|
|
38
|
+
type ModalTitleProps = _radix_ui_react_dialog.DialogTitleProps;
|
|
39
|
+
type ModalDescriptionProps = _radix_ui_react_dialog.DialogDescriptionProps;
|
|
40
|
+
|
|
41
|
+
type ConfirmationDialogActionProps = Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "children" | "disabled"> & React.RefAttributes<HTMLButtonElement>;
|
|
42
|
+
interface ConfirmationDialogProps {
|
|
43
|
+
open?: boolean;
|
|
44
|
+
defaultOpen?: boolean;
|
|
45
|
+
onOpenChange?: (open: boolean) => void;
|
|
46
|
+
modal?: boolean;
|
|
47
|
+
title: React.ReactNode;
|
|
48
|
+
description?: React.ReactNode;
|
|
49
|
+
children?: React.ReactNode;
|
|
50
|
+
/** A single ref-forwarding button. Omit for an externally opened dialog. */
|
|
51
|
+
trigger?: React.ReactElement;
|
|
52
|
+
onConfirm: React.MouseEventHandler<HTMLButtonElement>;
|
|
53
|
+
onCancel?: React.MouseEventHandler<HTMLButtonElement>;
|
|
54
|
+
confirmLabel?: React.ReactNode;
|
|
55
|
+
cancelLabel?: React.ReactNode;
|
|
56
|
+
pendingLabel?: React.ReactNode;
|
|
57
|
+
pending?: boolean;
|
|
58
|
+
error?: React.ReactNode;
|
|
59
|
+
confirmDisabled?: boolean;
|
|
60
|
+
cancelDisabled?: boolean;
|
|
61
|
+
/** Locks user dismissal. The controlled host may still close explicitly. */
|
|
62
|
+
dismissible?: boolean;
|
|
63
|
+
/** Explicit return target, useful when confirmation removes its own trigger. */
|
|
64
|
+
returnFocusRef?: React.RefObject<HTMLElement | null>;
|
|
65
|
+
isDanger?: boolean;
|
|
66
|
+
/** Pending confirmations block every user dismissal unless explicitly enabled. */
|
|
67
|
+
allowDismissWhilePending?: boolean;
|
|
68
|
+
size?: "small" | "medium" | "large" | "full";
|
|
69
|
+
contentProps?: Omit<_radix_ui_react_dialog.DialogContentProps, "children" | "asChild">;
|
|
70
|
+
backdropProps?: _radix_ui_react_dialog.DialogOverlayProps;
|
|
71
|
+
portalProps?: _radix_ui_react_dialog.DialogPortalProps;
|
|
72
|
+
confirmButtonProps?: ConfirmationDialogActionProps;
|
|
73
|
+
cancelButtonProps?: ConfirmationDialogActionProps;
|
|
74
|
+
}
|
|
75
|
+
/** Controlled confirmation. The host owns mutations, pending/error state and success closure. */
|
|
76
|
+
declare const ConfirmationDialog: React.ForwardRefExoticComponent<ConfirmationDialogProps & React.RefAttributes<HTMLDivElement>>;
|
|
77
|
+
|
|
78
|
+
export { ConfirmationDialog, type ConfirmationDialogActionProps, type ConfirmationDialogProps, Modal, ModalBody, type ModalBodyProps, ModalClose, ModalContent, type ModalContentProps, ModalDescription, type ModalDescriptionProps, ModalFooter, type ModalFooterProps, ModalHeader, type ModalHeaderProps, ModalOverlay, type ModalOverlayProps, ModalPortal, type ModalProps, ModalTitle, type ModalTitleProps, ModalTrigger };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import * as _radix_ui_react_dialog from '@radix-ui/react-dialog';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
/** @type {React.FC<ModalProps>} */
|
|
5
|
+
declare const Modal: React.FC<ModalProps>;
|
|
6
|
+
declare const ModalTrigger: React.ForwardRefExoticComponent<_radix_ui_react_dialog.DialogTriggerProps & React.RefAttributes<HTMLButtonElement>>;
|
|
7
|
+
declare const ModalClose: React.ForwardRefExoticComponent<_radix_ui_react_dialog.DialogCloseProps & React.RefAttributes<HTMLButtonElement>>;
|
|
8
|
+
declare const ModalPortal: React.FC<_radix_ui_react_dialog.DialogPortalProps>;
|
|
9
|
+
/** @type {React.ForwardRefExoticComponent<ModalOverlayProps & React.RefAttributes<HTMLDivElement>>} */
|
|
10
|
+
declare const ModalOverlay: React.ForwardRefExoticComponent<ModalOverlayProps & React.RefAttributes<HTMLDivElement>>;
|
|
11
|
+
/** @type {React.ForwardRefExoticComponent<ModalContentProps & React.RefAttributes<HTMLDivElement>>} */
|
|
12
|
+
declare const ModalContent: React.ForwardRefExoticComponent<ModalContentProps & React.RefAttributes<HTMLDivElement>>;
|
|
13
|
+
/** @type {React.ForwardRefExoticComponent<ModalHeaderProps & React.RefAttributes<HTMLDivElement>>} */
|
|
14
|
+
declare const ModalHeader: React.ForwardRefExoticComponent<ModalHeaderProps & React.RefAttributes<HTMLDivElement>>;
|
|
15
|
+
/** @type {React.ForwardRefExoticComponent<ModalBodyProps & React.RefAttributes<HTMLDivElement>>} */
|
|
16
|
+
declare const ModalBody: React.ForwardRefExoticComponent<ModalBodyProps & React.RefAttributes<HTMLDivElement>>;
|
|
17
|
+
/** @type {React.ForwardRefExoticComponent<ModalFooterProps & React.RefAttributes<HTMLDivElement>>} */
|
|
18
|
+
declare const ModalFooter: React.ForwardRefExoticComponent<ModalFooterProps & React.RefAttributes<HTMLDivElement>>;
|
|
19
|
+
/** @type {React.ForwardRefExoticComponent<ModalTitleProps & React.RefAttributes<HTMLHeadingElement>>} */
|
|
20
|
+
declare const ModalTitle: React.ForwardRefExoticComponent<ModalTitleProps & React.RefAttributes<HTMLHeadingElement>>;
|
|
21
|
+
/** @type {React.ForwardRefExoticComponent<ModalDescriptionProps & React.RefAttributes<HTMLParagraphElement>>} */
|
|
22
|
+
declare const ModalDescription: React.ForwardRefExoticComponent<ModalDescriptionProps & React.RefAttributes<HTMLParagraphElement>>;
|
|
23
|
+
type ModalProps = _radix_ui_react_dialog.DialogProps & {
|
|
24
|
+
onOpen?: () => void;
|
|
25
|
+
onClose?: () => void;
|
|
26
|
+
};
|
|
27
|
+
type ModalContentProps = _radix_ui_react_dialog.DialogContentProps & {
|
|
28
|
+
size?: "small" | "medium" | "large" | "full";
|
|
29
|
+
backdropProps?: _radix_ui_react_dialog.DialogOverlayProps;
|
|
30
|
+
backDropProps?: _radix_ui_react_dialog.DialogOverlayProps;
|
|
31
|
+
contentProps?: _radix_ui_react_dialog.DialogContentProps;
|
|
32
|
+
portalProps?: _radix_ui_react_dialog.DialogPortalProps;
|
|
33
|
+
};
|
|
34
|
+
type ModalOverlayProps = _radix_ui_react_dialog.DialogOverlayProps;
|
|
35
|
+
type ModalHeaderProps = React.HTMLAttributes<HTMLDivElement>;
|
|
36
|
+
type ModalBodyProps = React.HTMLAttributes<HTMLDivElement>;
|
|
37
|
+
type ModalFooterProps = React.HTMLAttributes<HTMLDivElement>;
|
|
38
|
+
type ModalTitleProps = _radix_ui_react_dialog.DialogTitleProps;
|
|
39
|
+
type ModalDescriptionProps = _radix_ui_react_dialog.DialogDescriptionProps;
|
|
40
|
+
|
|
41
|
+
type ConfirmationDialogActionProps = Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "children" | "disabled"> & React.RefAttributes<HTMLButtonElement>;
|
|
42
|
+
interface ConfirmationDialogProps {
|
|
43
|
+
open?: boolean;
|
|
44
|
+
defaultOpen?: boolean;
|
|
45
|
+
onOpenChange?: (open: boolean) => void;
|
|
46
|
+
modal?: boolean;
|
|
47
|
+
title: React.ReactNode;
|
|
48
|
+
description?: React.ReactNode;
|
|
49
|
+
children?: React.ReactNode;
|
|
50
|
+
/** A single ref-forwarding button. Omit for an externally opened dialog. */
|
|
51
|
+
trigger?: React.ReactElement;
|
|
52
|
+
onConfirm: React.MouseEventHandler<HTMLButtonElement>;
|
|
53
|
+
onCancel?: React.MouseEventHandler<HTMLButtonElement>;
|
|
54
|
+
confirmLabel?: React.ReactNode;
|
|
55
|
+
cancelLabel?: React.ReactNode;
|
|
56
|
+
pendingLabel?: React.ReactNode;
|
|
57
|
+
pending?: boolean;
|
|
58
|
+
error?: React.ReactNode;
|
|
59
|
+
confirmDisabled?: boolean;
|
|
60
|
+
cancelDisabled?: boolean;
|
|
61
|
+
/** Locks user dismissal. The controlled host may still close explicitly. */
|
|
62
|
+
dismissible?: boolean;
|
|
63
|
+
/** Explicit return target, useful when confirmation removes its own trigger. */
|
|
64
|
+
returnFocusRef?: React.RefObject<HTMLElement | null>;
|
|
65
|
+
isDanger?: boolean;
|
|
66
|
+
/** Pending confirmations block every user dismissal unless explicitly enabled. */
|
|
67
|
+
allowDismissWhilePending?: boolean;
|
|
68
|
+
size?: "small" | "medium" | "large" | "full";
|
|
69
|
+
contentProps?: Omit<_radix_ui_react_dialog.DialogContentProps, "children" | "asChild">;
|
|
70
|
+
backdropProps?: _radix_ui_react_dialog.DialogOverlayProps;
|
|
71
|
+
portalProps?: _radix_ui_react_dialog.DialogPortalProps;
|
|
72
|
+
confirmButtonProps?: ConfirmationDialogActionProps;
|
|
73
|
+
cancelButtonProps?: ConfirmationDialogActionProps;
|
|
74
|
+
}
|
|
75
|
+
/** Controlled confirmation. The host owns mutations, pending/error state and success closure. */
|
|
76
|
+
declare const ConfirmationDialog: React.ForwardRefExoticComponent<ConfirmationDialogProps & React.RefAttributes<HTMLDivElement>>;
|
|
77
|
+
|
|
78
|
+
export { ConfirmationDialog, type ConfirmationDialogActionProps, type ConfirmationDialogProps, Modal, ModalBody, type ModalBodyProps, ModalClose, ModalContent, type ModalContentProps, ModalDescription, type ModalDescriptionProps, ModalFooter, type ModalFooterProps, ModalHeader, type ModalHeaderProps, ModalOverlay, type ModalOverlayProps, ModalPortal, type ModalProps, ModalTitle, type ModalTitleProps, ModalTrigger };
|
package/dist/index.js
CHANGED
|
@@ -29,6 +29,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
29
29
|
// src/index.js
|
|
30
30
|
var index_exports = {};
|
|
31
31
|
__export(index_exports, {
|
|
32
|
+
ConfirmationDialog: () => ConfirmationDialog,
|
|
32
33
|
Modal: () => Modal,
|
|
33
34
|
ModalBody: () => ModalBody,
|
|
34
35
|
ModalClose: () => ModalClose,
|
|
@@ -47,20 +48,49 @@ module.exports = __toCommonJS(index_exports);
|
|
|
47
48
|
var import_react = __toESM(require("react"));
|
|
48
49
|
var DialogPrimitive = __toESM(require("@radix-ui/react-dialog"));
|
|
49
50
|
var import_utils = require("@edux-design/utils");
|
|
51
|
+
var import_buttons = require("@edux-design/buttons");
|
|
52
|
+
var import_icons = require("@edux-design/icons");
|
|
53
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
50
54
|
var MODAL_OVERLAY_Z_INDEX = 2147483645;
|
|
51
55
|
var MODAL_CONTENT_Z_INDEX = 2147483646;
|
|
56
|
+
var ModalContext = (0, import_react.createContext)({ hasOnClose: false });
|
|
57
|
+
var MODAL_SECTION_PADDING_X = "px-16";
|
|
58
|
+
var MODAL_SECTION_PADDING_Y = "py-16";
|
|
59
|
+
var MODAL_SURFACE_CLASSES = [
|
|
60
|
+
"fixed left-1/2 top-1/2 max-h-[92vh] -translate-x-1/2 -translate-y-1/2",
|
|
61
|
+
"bg-bg-base text-fg-base shadow-xl outline-none rounded-md border-2 border-border-subtle",
|
|
62
|
+
"flex flex-col overflow-hidden",
|
|
63
|
+
"data-[state=open]:animate-fade-in data-[state=closed]:animate-fade-out"
|
|
64
|
+
].join(" ");
|
|
65
|
+
var MODAL_HEADER_CLASSES = [
|
|
66
|
+
"flex justify-between gap-12",
|
|
67
|
+
MODAL_SECTION_PADDING_X,
|
|
68
|
+
MODAL_SECTION_PADDING_Y,
|
|
69
|
+
"border-b border-border-subtle"
|
|
70
|
+
].join(" ");
|
|
71
|
+
var MODAL_HEADER_CONTENT_CLASSES = "flex min-w-0 flex-1 flex-col gap-4";
|
|
72
|
+
var MODAL_BODY_CLASSES = [
|
|
73
|
+
"flex-1 overflow-auto",
|
|
74
|
+
MODAL_SECTION_PADDING_X,
|
|
75
|
+
MODAL_SECTION_PADDING_Y
|
|
76
|
+
].join(" ");
|
|
77
|
+
var MODAL_FOOTER_CLASSES = [
|
|
78
|
+
"flex items-center justify-end gap-8",
|
|
79
|
+
MODAL_SECTION_PADDING_X,
|
|
80
|
+
MODAL_SECTION_PADDING_Y,
|
|
81
|
+
"border-t border-border-subtle"
|
|
82
|
+
].join(" ");
|
|
83
|
+
var MODAL_TITLE_CLASSES = "text-lg font-semibold text-fg-base";
|
|
84
|
+
var MODAL_DESCRIPTION_CLASSES = "text-sm text-fg-subtle";
|
|
85
|
+
var MODAL_CLOSE_LABEL = "Close modal";
|
|
86
|
+
var MODAL_SIZE_CLASSES = {
|
|
87
|
+
small: "w-[min(92vw,420px)]",
|
|
88
|
+
medium: "w-[min(92vw,640px)]",
|
|
89
|
+
large: "w-[min(92vw,840px)]",
|
|
90
|
+
full: "w-[min(96vw,1200px)] h-[min(92vh,900px)]"
|
|
91
|
+
};
|
|
52
92
|
var getSizeClasses = (size) => {
|
|
53
|
-
|
|
54
|
-
case "small":
|
|
55
|
-
return "w-[min(92vw,420px)]";
|
|
56
|
-
case "large":
|
|
57
|
-
return "w-[min(92vw,840px)]";
|
|
58
|
-
case "full":
|
|
59
|
-
return "w-[min(96vw,1200px)] h-[min(92vh,900px)]";
|
|
60
|
-
case "medium":
|
|
61
|
-
default:
|
|
62
|
-
return "w-[min(92vw,640px)]";
|
|
63
|
-
}
|
|
93
|
+
return MODAL_SIZE_CLASSES[size] ?? MODAL_SIZE_CLASSES.medium;
|
|
64
94
|
};
|
|
65
95
|
var Modal = ({
|
|
66
96
|
open,
|
|
@@ -71,33 +101,46 @@ var Modal = ({
|
|
|
71
101
|
children,
|
|
72
102
|
...props
|
|
73
103
|
}) => {
|
|
104
|
+
const contextValue = (0, import_react.useMemo)(
|
|
105
|
+
() => ({ hasOnClose: typeof onClose === "function" }),
|
|
106
|
+
[onClose]
|
|
107
|
+
);
|
|
74
108
|
const handleOpenChange = (0, import_react.useCallback)(
|
|
75
109
|
(nextOpen) => {
|
|
76
|
-
onOpenChange
|
|
110
|
+
onOpenChange?.(nextOpen);
|
|
77
111
|
if (nextOpen) {
|
|
78
|
-
onOpen
|
|
112
|
+
onOpen?.();
|
|
79
113
|
return;
|
|
80
114
|
}
|
|
81
|
-
onClose
|
|
115
|
+
onClose?.();
|
|
82
116
|
},
|
|
83
117
|
[onClose, onOpen, onOpenChange]
|
|
84
118
|
);
|
|
85
|
-
return /* @__PURE__ */
|
|
119
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ModalContext.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
86
120
|
DialogPrimitive.Root,
|
|
87
121
|
{
|
|
88
122
|
open,
|
|
89
123
|
defaultOpen,
|
|
90
124
|
onOpenChange: handleOpenChange,
|
|
91
|
-
...props
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
);
|
|
125
|
+
...props,
|
|
126
|
+
children
|
|
127
|
+
}
|
|
128
|
+
) });
|
|
95
129
|
};
|
|
96
130
|
var ModalTrigger = DialogPrimitive.Trigger;
|
|
97
131
|
var ModalClose = DialogPrimitive.Close;
|
|
98
132
|
var ModalPortal = DialogPrimitive.Portal;
|
|
133
|
+
var ModalHeaderCloseButton = () => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ModalClose, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
134
|
+
import_buttons.IconButton,
|
|
135
|
+
{
|
|
136
|
+
size: "small",
|
|
137
|
+
isBare: true,
|
|
138
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.Close, { "aria-hidden": "true" }),
|
|
139
|
+
"aria-label": MODAL_CLOSE_LABEL
|
|
140
|
+
}
|
|
141
|
+
) });
|
|
99
142
|
var ModalOverlay = (0, import_react.forwardRef)(
|
|
100
|
-
({ className, style, ...props }, ref) => /* @__PURE__ */
|
|
143
|
+
({ className, style, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
101
144
|
DialogPrimitive.Overlay,
|
|
102
145
|
{
|
|
103
146
|
ref,
|
|
@@ -121,90 +164,238 @@ var ModalContent = (0, import_react.forwardRef)(
|
|
|
121
164
|
backdropProps,
|
|
122
165
|
backDropProps,
|
|
123
166
|
contentProps = {},
|
|
167
|
+
portalProps = {},
|
|
124
168
|
...restProps
|
|
125
169
|
}, ref) => {
|
|
126
170
|
const resolvedBackdropProps = backdropProps ?? backDropProps ?? {};
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
171
|
+
const { className: backdropClassName, style: backdropStyle, ...overlayProps } = resolvedBackdropProps;
|
|
172
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ModalPortal, { ...portalProps, children: [
|
|
173
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
174
|
+
ModalOverlay,
|
|
175
|
+
{
|
|
176
|
+
...overlayProps,
|
|
177
|
+
className: (0, import_utils.cx)(backdropClassName),
|
|
178
|
+
style: { ...backdropStyle }
|
|
179
|
+
}
|
|
180
|
+
),
|
|
181
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
182
|
+
DialogPrimitive.Content,
|
|
183
|
+
{
|
|
184
|
+
ref,
|
|
185
|
+
className: (0, import_utils.cx)(
|
|
186
|
+
MODAL_SURFACE_CLASSES,
|
|
187
|
+
getSizeClasses(size),
|
|
188
|
+
className
|
|
189
|
+
),
|
|
190
|
+
style: { zIndex: MODAL_CONTENT_Z_INDEX, ...style },
|
|
191
|
+
...contentProps,
|
|
192
|
+
...restProps,
|
|
193
|
+
children
|
|
194
|
+
}
|
|
195
|
+
)
|
|
196
|
+
] });
|
|
152
197
|
}
|
|
153
198
|
);
|
|
154
199
|
ModalContent.displayName = "ModalContent";
|
|
155
|
-
var ModalHeader = (0, import_react.forwardRef)(({ className, ...props }, ref) =>
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
className
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
))
|
|
200
|
+
var ModalHeader = (0, import_react.forwardRef)(({ className, children, ...props }, ref) => {
|
|
201
|
+
const { hasOnClose } = (0, import_react.useContext)(ModalContext);
|
|
202
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
203
|
+
"div",
|
|
204
|
+
{
|
|
205
|
+
ref,
|
|
206
|
+
className: (0, import_utils.cx)(MODAL_HEADER_CLASSES, className),
|
|
207
|
+
...props,
|
|
208
|
+
children: [
|
|
209
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: MODAL_HEADER_CONTENT_CLASSES, children }),
|
|
210
|
+
hasOnClose ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ModalHeaderCloseButton, {}) : null
|
|
211
|
+
]
|
|
212
|
+
}
|
|
213
|
+
);
|
|
214
|
+
});
|
|
166
215
|
ModalHeader.displayName = "ModalHeader";
|
|
167
|
-
var ModalBody = (0, import_react.forwardRef)(({ className, ...props }, ref) => /* @__PURE__ */
|
|
216
|
+
var ModalBody = (0, import_react.forwardRef)(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
168
217
|
"div",
|
|
169
218
|
{
|
|
170
219
|
ref,
|
|
171
|
-
className: (0, import_utils.cx)(
|
|
220
|
+
className: (0, import_utils.cx)(MODAL_BODY_CLASSES, className),
|
|
172
221
|
...props
|
|
173
222
|
}
|
|
174
223
|
));
|
|
175
224
|
ModalBody.displayName = "ModalBody";
|
|
176
|
-
var ModalFooter = (0, import_react.forwardRef)(({ className, ...props }, ref) => /* @__PURE__ */
|
|
225
|
+
var ModalFooter = (0, import_react.forwardRef)(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
177
226
|
"div",
|
|
178
227
|
{
|
|
179
228
|
ref,
|
|
180
|
-
className: (0, import_utils.cx)(
|
|
181
|
-
"flex items-center justify-end gap-8 px-20 py-16 border-t border-border-subtle",
|
|
182
|
-
className
|
|
183
|
-
),
|
|
229
|
+
className: (0, import_utils.cx)(MODAL_FOOTER_CLASSES, className),
|
|
184
230
|
...props
|
|
185
231
|
}
|
|
186
232
|
));
|
|
187
233
|
ModalFooter.displayName = "ModalFooter";
|
|
188
|
-
var ModalTitle = (0, import_react.forwardRef)(({ className, ...props }, ref) => /* @__PURE__ */
|
|
234
|
+
var ModalTitle = (0, import_react.forwardRef)(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
189
235
|
DialogPrimitive.Title,
|
|
190
236
|
{
|
|
191
237
|
ref,
|
|
192
|
-
className: (0, import_utils.cx)(
|
|
238
|
+
className: (0, import_utils.cx)(MODAL_TITLE_CLASSES, className),
|
|
193
239
|
...props
|
|
194
240
|
}
|
|
195
241
|
));
|
|
196
242
|
ModalTitle.displayName = "ModalTitle";
|
|
197
|
-
var ModalDescription = (0, import_react.forwardRef)(({ className, ...props }, ref) => /* @__PURE__ */
|
|
243
|
+
var ModalDescription = (0, import_react.forwardRef)(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
198
244
|
DialogPrimitive.Description,
|
|
199
245
|
{
|
|
200
246
|
ref,
|
|
201
|
-
className: (0, import_utils.cx)(
|
|
247
|
+
className: (0, import_utils.cx)(MODAL_DESCRIPTION_CLASSES, className),
|
|
202
248
|
...props
|
|
203
249
|
}
|
|
204
250
|
));
|
|
205
251
|
ModalDescription.displayName = "ModalDescription";
|
|
252
|
+
|
|
253
|
+
// src/elements/ConfirmationDialog.tsx
|
|
254
|
+
var import_react2 = require("react");
|
|
255
|
+
var import_buttons2 = require("@edux-design/buttons");
|
|
256
|
+
var import_utils2 = require("@edux-design/utils");
|
|
257
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
258
|
+
var ConfirmationDialog = (0, import_react2.forwardRef)(function ConfirmationDialog2({
|
|
259
|
+
open,
|
|
260
|
+
defaultOpen = false,
|
|
261
|
+
onOpenChange,
|
|
262
|
+
modal = true,
|
|
263
|
+
title,
|
|
264
|
+
description,
|
|
265
|
+
children,
|
|
266
|
+
trigger,
|
|
267
|
+
onConfirm,
|
|
268
|
+
onCancel,
|
|
269
|
+
confirmLabel = "Confirm",
|
|
270
|
+
cancelLabel = "Cancel",
|
|
271
|
+
pendingLabel = "Working\u2026",
|
|
272
|
+
pending = false,
|
|
273
|
+
error,
|
|
274
|
+
confirmDisabled = false,
|
|
275
|
+
cancelDisabled = false,
|
|
276
|
+
dismissible = true,
|
|
277
|
+
returnFocusRef,
|
|
278
|
+
isDanger = false,
|
|
279
|
+
allowDismissWhilePending = false,
|
|
280
|
+
size = "small",
|
|
281
|
+
contentProps = {},
|
|
282
|
+
backdropProps,
|
|
283
|
+
portalProps,
|
|
284
|
+
confirmButtonProps = {},
|
|
285
|
+
cancelButtonProps = {}
|
|
286
|
+
}, ref) {
|
|
287
|
+
const [uncontrolledOpen, setUncontrolledOpen] = (0, import_react2.useState)(defaultOpen);
|
|
288
|
+
const resolvedOpen = open ?? uncontrolledOpen;
|
|
289
|
+
const cancelRef = (0, import_react2.useRef)(null);
|
|
290
|
+
const previousFocusRef = (0, import_react2.useRef)(null);
|
|
291
|
+
const statusId = (0, import_react2.useId)();
|
|
292
|
+
const locked = !dismissible || pending && !allowDismissWhilePending;
|
|
293
|
+
const hasBody = children != null || Boolean(error) || pending;
|
|
294
|
+
const {
|
|
295
|
+
onClick: onCancelClick,
|
|
296
|
+
ref: actionRef,
|
|
297
|
+
...cancelProps
|
|
298
|
+
} = cancelButtonProps;
|
|
299
|
+
const { onClick: onConfirmClick, ...confirmProps } = confirmButtonProps;
|
|
300
|
+
const requestOpen = (next) => {
|
|
301
|
+
if (!next && locked) return;
|
|
302
|
+
if (open === void 0) setUncontrolledOpen(next);
|
|
303
|
+
onOpenChange?.(next);
|
|
304
|
+
};
|
|
305
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Modal, { open: resolvedOpen, onOpenChange: requestOpen, modal, children: [
|
|
306
|
+
trigger && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ModalTrigger, { asChild: true, children: trigger }),
|
|
307
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
308
|
+
ModalContent,
|
|
309
|
+
{
|
|
310
|
+
...contentProps,
|
|
311
|
+
ref,
|
|
312
|
+
size,
|
|
313
|
+
backdropProps,
|
|
314
|
+
portalProps,
|
|
315
|
+
...!description && !contentProps["aria-describedby"] ? { "aria-describedby": void 0 } : {},
|
|
316
|
+
"aria-busy": pending || void 0,
|
|
317
|
+
className: (0, import_utils2.cx)("motion-reduce:animate-none", contentProps.className),
|
|
318
|
+
onOpenAutoFocus: (event) => {
|
|
319
|
+
previousFocusRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
320
|
+
contentProps.onOpenAutoFocus?.(event);
|
|
321
|
+
if (!event.defaultPrevented) {
|
|
322
|
+
event.preventDefault();
|
|
323
|
+
if (!locked && !cancelDisabled) cancelRef.current?.focus();
|
|
324
|
+
else if (event.target instanceof HTMLElement) event.target.focus();
|
|
325
|
+
}
|
|
326
|
+
},
|
|
327
|
+
onCloseAutoFocus: (event) => {
|
|
328
|
+
contentProps.onCloseAutoFocus?.(event);
|
|
329
|
+
const target = returnFocusRef?.current ?? (!trigger ? previousFocusRef.current : null);
|
|
330
|
+
if (!event.defaultPrevented && target?.isConnected) {
|
|
331
|
+
event.preventDefault();
|
|
332
|
+
target.focus();
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
onEscapeKeyDown: (event) => {
|
|
336
|
+
contentProps.onEscapeKeyDown?.(event);
|
|
337
|
+
if (locked) event.preventDefault();
|
|
338
|
+
},
|
|
339
|
+
onInteractOutside: (event) => {
|
|
340
|
+
contentProps.onInteractOutside?.(event);
|
|
341
|
+
if (locked) event.preventDefault();
|
|
342
|
+
},
|
|
343
|
+
children: [
|
|
344
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(ModalHeader, { className: !hasBody ? "border-b-0" : void 0, children: [
|
|
345
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ModalTitle, { children: title }),
|
|
346
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ModalDescription, { children: description })
|
|
347
|
+
] }),
|
|
348
|
+
hasBody && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(ModalBody, { className: "min-h-0 text-sm text-fg-base", children: [
|
|
349
|
+
children,
|
|
350
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { role: "alert", className: "mt-8 text-fg-danger-emphasis", children: error }),
|
|
351
|
+
pending && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { id: statusId, role: "status", className: "sr-only", children: pendingLabel })
|
|
352
|
+
] }),
|
|
353
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(ModalFooter, { className: "flex-wrap", children: [
|
|
354
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
355
|
+
import_buttons2.Button,
|
|
356
|
+
{
|
|
357
|
+
...cancelProps,
|
|
358
|
+
ref: (node) => {
|
|
359
|
+
cancelRef.current = node;
|
|
360
|
+
if (typeof actionRef === "function") actionRef(node);
|
|
361
|
+
else if (actionRef) actionRef.current = node;
|
|
362
|
+
},
|
|
363
|
+
type: "button",
|
|
364
|
+
size: "small",
|
|
365
|
+
isSecondary: true,
|
|
366
|
+
disabled: locked || cancelDisabled,
|
|
367
|
+
onClick: (event) => {
|
|
368
|
+
onCancelClick?.(event);
|
|
369
|
+
if (!event.defaultPrevented) onCancel?.(event);
|
|
370
|
+
if (!event.defaultPrevented) requestOpen(false);
|
|
371
|
+
},
|
|
372
|
+
children: cancelLabel
|
|
373
|
+
}
|
|
374
|
+
),
|
|
375
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
376
|
+
import_buttons2.Button,
|
|
377
|
+
{
|
|
378
|
+
...confirmProps,
|
|
379
|
+
type: "button",
|
|
380
|
+
size: "small",
|
|
381
|
+
isDanger,
|
|
382
|
+
disabled: pending || confirmDisabled,
|
|
383
|
+
onClick: (event) => {
|
|
384
|
+
onConfirmClick?.(event);
|
|
385
|
+
if (!event.defaultPrevented) onConfirm(event);
|
|
386
|
+
},
|
|
387
|
+
children: pending ? pendingLabel : confirmLabel
|
|
388
|
+
}
|
|
389
|
+
)
|
|
390
|
+
] })
|
|
391
|
+
]
|
|
392
|
+
}
|
|
393
|
+
)
|
|
394
|
+
] });
|
|
395
|
+
});
|
|
206
396
|
// Annotate the CommonJS export names for ESM import in node:
|
|
207
397
|
0 && (module.exports = {
|
|
398
|
+
ConfirmationDialog,
|
|
208
399
|
Modal,
|
|
209
400
|
ModalBody,
|
|
210
401
|
ModalClose,
|