@lobehub/ui 5.0.1 → 5.1.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.
Files changed (153) hide show
  1. package/es/Accordion/Accordion.d.mts +2 -2
  2. package/es/Accordion/AccordionItem.d.mts +2 -2
  3. package/es/ActionIcon/ActionIcon.d.mts +2 -2
  4. package/es/Alert/Alert.d.mts +2 -2
  5. package/es/AutoComplete/Select.d.mts +2 -2
  6. package/es/Burger/Burger.d.mts +2 -2
  7. package/es/CodeEditor/CodeEditor.d.mts +2 -2
  8. package/es/Collapse/Collapse.d.mts +2 -2
  9. package/es/ConfigProvider/index.d.mts +2 -2
  10. package/es/CopyButton/CopyButton.d.mts +2 -2
  11. package/es/DatePicker/DatePicker.d.mts +2 -2
  12. package/es/DraggablePanel/components/DraggablePanelBody.d.mts +2 -2
  13. package/es/DraggablePanel/components/DraggablePanelContainer.d.mts +2 -2
  14. package/es/DraggablePanel/components/DraggablePanelFooter.d.mts +2 -2
  15. package/es/DraggablePanel/components/DraggablePanelHeader.d.mts +2 -2
  16. package/es/DraggableSideNav/DraggableSideNav.d.mts +2 -2
  17. package/es/Drawer/Drawer.d.mts +2 -2
  18. package/es/Dropdown/Dropdown.d.mts +2 -2
  19. package/es/EditableText/EditableText.d.mts +2 -2
  20. package/es/EditorSlashMenu/atoms.d.mts +13 -13
  21. package/es/EmojiPicker/EmojiPicker.d.mts +2 -2
  22. package/es/Flex/FlexBasic.d.mts +2 -2
  23. package/es/FontLoader/index.d.mts +2 -2
  24. package/es/Footer/Footer.d.mts +2 -2
  25. package/es/Form/components/FormGroup.d.mts +2 -2
  26. package/es/Form/components/FormItem.d.mts +2 -2
  27. package/es/Form/components/FormSubmitFooter.d.mts +2 -2
  28. package/es/FormModal/FormModal.d.mts +2 -2
  29. package/es/Freeze/Freeze.d.mts +2 -2
  30. package/es/GuideCard/GuideCard.d.mts +2 -2
  31. package/es/Header/Header.d.mts +2 -2
  32. package/es/Highlighter/Highlighter.d.mts +2 -2
  33. package/es/Highlighter/SyntaxHighlighter/index.d.mts +2 -2
  34. package/es/Hotkey/Hotkey.d.mts +2 -2
  35. package/es/HotkeyInput/HotkeyInput.d.mts +2 -2
  36. package/es/Icon/Icon.d.mts +2 -2
  37. package/es/Icon/components/IconProvider.d.mts +3 -3
  38. package/es/Image/PreviewGroup.d.mts +2 -2
  39. package/es/ImageSelect/ImageSelect.d.mts +2 -2
  40. package/es/Input/Input.d.mts +2 -2
  41. package/es/Input/InputNumber.d.mts +2 -2
  42. package/es/Input/InputOPT.d.mts +2 -2
  43. package/es/Input/InputPassword.d.mts +2 -2
  44. package/es/Input/TextArea.d.mts +2 -2
  45. package/es/Layout/components/LayoutFooter.d.mts +2 -2
  46. package/es/Layout/components/LayoutHeader.d.mts +2 -2
  47. package/es/Layout/components/LayoutMain.d.mts +2 -2
  48. package/es/Layout/components/LayoutSidebar.d.mts +2 -2
  49. package/es/Layout/components/LayoutSidebarInner.d.mts +2 -2
  50. package/es/Layout/components/LayoutToc.d.mts +2 -2
  51. package/es/List/ListItem/index.d.mts +2 -2
  52. package/es/Markdown/Markdown.d.mts +2 -2
  53. package/es/Markdown/Typography.d.mts +2 -2
  54. package/es/Markdown/components/SearchResultCards/index.d.mts +2 -2
  55. package/es/MaskShadow/MaskShadow.d.mts +2 -2
  56. package/es/Menu/Menu.d.mts +2 -2
  57. package/es/Mermaid/Mermaid.d.mts +2 -2
  58. package/es/Mermaid/SyntaxMermaid/index.d.mts +2 -2
  59. package/es/Modal/Modal.d.mts +2 -2
  60. package/es/Modal/ModalProvider.d.mts +2 -2
  61. package/es/Modal/imperative.d.mts +2 -2
  62. package/es/MotionProvider/index.d.mts +2 -2
  63. package/es/Popover/ArrowIcon.d.mts +2 -2
  64. package/es/Popover/atoms.d.mts +9 -9
  65. package/es/Popover/context.d.mts +2 -2
  66. package/es/SearchBar/SearchBar.d.mts +2 -2
  67. package/es/Segmented/Segmented.d.mts +2 -2
  68. package/es/Select/Select.d.mts +2 -2
  69. package/es/SideNav/SideNav.d.mts +2 -2
  70. package/es/SliderWithInput/SliderWithInput.d.mts +2 -2
  71. package/es/SortableList/components/DragHandle.d.mts +2 -2
  72. package/es/SortableList/components/SortableItem.d.mts +2 -2
  73. package/es/ThemeProvider/ThemeProvider.d.mts +2 -2
  74. package/es/Toc/Toc.d.mts +2 -2
  75. package/es/Video/index.d.mts +2 -2
  76. package/es/awesome/AuroraBackground/AuroraBackground.d.mts +2 -2
  77. package/es/awesome/BottomGradientButton/BottomGradientButton.d.mts +2 -2
  78. package/es/awesome/Features/Features.d.mts +2 -2
  79. package/es/awesome/Giscus/Giscus.d.mts +2 -2
  80. package/es/awesome/GradientButton/GradientButton.d.mts +2 -2
  81. package/es/awesome/GridBackground/GridBackground.d.mts +2 -2
  82. package/es/awesome/GridBackground/GridShowcase.d.mts +2 -2
  83. package/es/awesome/Hero/Hero.d.mts +2 -2
  84. package/es/awesome/Spline/Spine.d.mts +2 -2
  85. package/es/awesome/Spotlight/Spotlight.d.mts +2 -2
  86. package/es/awesome/SpotlightCard/SpotlightCard.d.mts +2 -2
  87. package/es/awesome/TypewriterEffect/TypewriterEffect.d.mts +2 -2
  88. package/es/base-ui/ContextMenu/ContextMenuHost.d.mts +3 -3
  89. package/es/base-ui/DropdownMenu/DropdownMenu.d.mts +2 -2
  90. package/es/base-ui/DropdownMenu/atoms.d.mts +18 -18
  91. package/es/base-ui/Modal/Modal.d.mts +8 -0
  92. package/es/base-ui/Modal/Modal.mjs +230 -0
  93. package/es/base-ui/Modal/Modal.mjs.map +1 -0
  94. package/es/base-ui/Modal/atoms.d.mts +100 -0
  95. package/es/base-ui/Modal/atoms.mjs +187 -0
  96. package/es/base-ui/Modal/atoms.mjs.map +1 -0
  97. package/es/base-ui/Modal/constants.d.mts +10 -0
  98. package/es/base-ui/Modal/constants.mjs +27 -0
  99. package/es/base-ui/Modal/constants.mjs.map +1 -0
  100. package/es/base-ui/Modal/context.d.mts +9 -0
  101. package/es/base-ui/Modal/context.mjs +14 -0
  102. package/es/base-ui/Modal/context.mjs.map +1 -0
  103. package/es/base-ui/Modal/imperative.d.mts +25 -0
  104. package/es/base-ui/Modal/imperative.mjs +221 -0
  105. package/es/base-ui/Modal/imperative.mjs.map +1 -0
  106. package/es/base-ui/Modal/index.d.mts +6 -0
  107. package/es/base-ui/Modal/style.mjs +295 -0
  108. package/es/base-ui/Modal/style.mjs.map +1 -0
  109. package/es/base-ui/Modal/type.d.mts +110 -0
  110. package/es/base-ui/ScrollArea/atoms.d.mts +7 -7
  111. package/es/base-ui/Select/Select.d.mts +2 -2
  112. package/es/base-ui/Select/atoms.d.mts +19 -19
  113. package/es/base-ui/Switch/Switch.d.mts +2 -2
  114. package/es/base-ui/Toast/imperative.d.mts +2 -2
  115. package/es/base-ui/index.d.mts +8 -1
  116. package/es/base-ui/index.mjs +6 -1
  117. package/es/brand/LobeChat/index.d.mts +2 -2
  118. package/es/brand/LobeHub/index.d.mts +2 -2
  119. package/es/brand/LogoThree/LogoSpline.d.mts +2 -2
  120. package/es/brand/LogoThree/index.d.mts +2 -2
  121. package/es/chat/BackBottom/BackBottom.d.mts +2 -2
  122. package/es/chat/ChatInputArea/components/ChatInputAreaInner.d.mts +2 -2
  123. package/es/chat/ChatItem/ChatItem.d.mts +2 -2
  124. package/es/chat/ChatList/ChatList.d.mts +2 -2
  125. package/es/chat/EditableMessage/EditableMessage.d.mts +2 -2
  126. package/es/chat/EditableMessageList/EditableMessageList.d.mts +2 -2
  127. package/es/chat/MessageInput/MessageInput.d.mts +2 -2
  128. package/es/chat/MessageModal/MessageModal.d.mts +2 -2
  129. package/es/color/ColorScales/index.d.mts +2 -2
  130. package/es/color/CssVar/index.d.mts +2 -2
  131. package/es/i18n/context.d.mts +2 -2
  132. package/es/icons/lucideExtra/BotPromptIcon.d.mts +2 -2
  133. package/es/icons/lucideExtra/CreateBotIcon.d.mts +3 -3
  134. package/es/icons/lucideExtra/DiscordIcon.d.mts +2 -2
  135. package/es/icons/lucideExtra/GlobeOffIcon.d.mts +2 -2
  136. package/es/icons/lucideExtra/GroupBotIcon.d.mts +2 -2
  137. package/es/icons/lucideExtra/GroupBotSquareIcon.d.mts +3 -3
  138. package/es/icons/lucideExtra/LeftClickIcon.d.mts +3 -3
  139. package/es/icons/lucideExtra/LeftDoubleClickIcon.d.mts +3 -3
  140. package/es/icons/lucideExtra/McpIcon.d.mts +3 -3
  141. package/es/icons/lucideExtra/ProviderIcon.d.mts +3 -3
  142. package/es/icons/lucideExtra/RightClickIcon.d.mts +3 -3
  143. package/es/icons/lucideExtra/RightDoubleClickIcon.d.mts +3 -3
  144. package/es/icons/lucideExtra/ShapesUploadIcon.d.mts +3 -3
  145. package/es/icons/lucideExtra/SkillsIcon.d.mts +3 -3
  146. package/es/icons/lucideExtra/TreeDownRightIcon.d.mts +2 -2
  147. package/es/icons/lucideExtra/TreeUpDownRightIcon.d.mts +3 -3
  148. package/es/mdx/Mdx/index.d.mts +2 -2
  149. package/es/mobile/ChatHeader/ChatHeaderTitle.d.mts +2 -2
  150. package/es/mobile/ChatInputArea/components/ChatSendButton.d.mts +2 -2
  151. package/es/mobile/TabBar/TabBar.d.mts +2 -2
  152. package/es/storybook/StoryBook/index.d.mts +2 -2
  153. package/package.json +1 -1
@@ -0,0 +1,187 @@
1
+ 'use client';
2
+
3
+ import { useMotionComponent } from "../../MotionProvider/index.mjs";
4
+ import { useNativeButton } from "../../hooks/useNativeButton.mjs";
5
+ import { useAppElement } from "../../ThemeProvider/AppElementContext.mjs";
6
+ import { backdropTransition, modalMotionConfig } from "./constants.mjs";
7
+ import { styles } from "./style.mjs";
8
+ import { cloneElement, createContext, createElement, isValidElement, use, useCallback, useEffect, useMemo, useState } from "react";
9
+ import { jsx } from "react/jsx-runtime";
10
+ import { cx } from "antd-style";
11
+ import { AnimatePresence } from "motion/react";
12
+ import { mergeProps } from "@base-ui/react/merge-props";
13
+ import { mergeRefs } from "react-merge-refs";
14
+ import { X } from "lucide-react";
15
+ import { Dialog } from "@base-ui/react/dialog";
16
+
17
+ //#region src/base-ui/Modal/atoms.tsx
18
+ const mergeStateClassName = (base, className) => {
19
+ if (typeof className === "function") return (state) => cx(base, className(state));
20
+ return cx(base, className);
21
+ };
22
+ const ModalOpenContext = createContext(null);
23
+ const ModalActionsContext = createContext(null);
24
+ const useModalOpen = () => use(ModalOpenContext);
25
+ const useModalActions = () => use(ModalActionsContext);
26
+ const AnimatedModalRoot = ({ open, children, onExitComplete: onExitCompleteProp, ...rest }) => {
27
+ const [isPresent, setIsPresent] = useState(!!open);
28
+ useEffect(() => {
29
+ if (open) setIsPresent(true);
30
+ }, [open]);
31
+ const handleExitComplete = useCallback(() => {
32
+ setIsPresent(false);
33
+ onExitCompleteProp?.();
34
+ }, [onExitCompleteProp]);
35
+ const actions = useMemo(() => ({ onExitComplete: handleExitComplete }), [handleExitComplete]);
36
+ if (!isPresent) return null;
37
+ return /* @__PURE__ */ jsx(ModalOpenContext, {
38
+ value: open,
39
+ children: /* @__PURE__ */ jsx(ModalActionsContext, {
40
+ value: actions,
41
+ children: /* @__PURE__ */ jsx(Dialog.Root, {
42
+ modal: true,
43
+ open: true,
44
+ ...rest,
45
+ children
46
+ })
47
+ })
48
+ });
49
+ };
50
+ const ModalRoot = ({ open, onExitComplete, ...rest }) => {
51
+ if (open !== void 0) return /* @__PURE__ */ jsx(AnimatedModalRoot, {
52
+ open,
53
+ onExitComplete,
54
+ ...rest
55
+ });
56
+ return /* @__PURE__ */ jsx(Dialog.Root, {
57
+ modal: true,
58
+ ...rest
59
+ });
60
+ };
61
+ const ModalPortal = ({ container, ...rest }) => {
62
+ const appElement = useAppElement();
63
+ return /* @__PURE__ */ jsx(Dialog.Portal, {
64
+ container: container ?? appElement ?? void 0,
65
+ ...rest
66
+ });
67
+ };
68
+ const ModalViewport = ({ className, ...rest }) => /* @__PURE__ */ jsx(Dialog.Viewport, {
69
+ ...rest,
70
+ className: mergeStateClassName(styles.viewport, className)
71
+ });
72
+ const ModalBackdrop = ({ className, style, ...rest }) => {
73
+ const open = useModalOpen();
74
+ const Motion = useMotionComponent();
75
+ if (open !== null) return /* @__PURE__ */ jsx(Motion.div, {
76
+ animate: { opacity: open ? 1 : 0 },
77
+ className: cx(styles.backdrop, className),
78
+ initial: { opacity: 0 },
79
+ style: {
80
+ ...style,
81
+ transition: "none"
82
+ },
83
+ transition: backdropTransition
84
+ });
85
+ return /* @__PURE__ */ jsx(Dialog.Backdrop, {
86
+ ...rest,
87
+ className: mergeStateClassName(styles.backdrop, className),
88
+ style
89
+ });
90
+ };
91
+ const ModalPopup = ({ className, children, width, style, motionProps, panelClassName, popupStyle, ...rest }) => {
92
+ const open = useModalOpen();
93
+ const actions = useModalActions();
94
+ const Motion = useMotionComponent();
95
+ if (open !== null && actions) return /* @__PURE__ */ jsx(Dialog.Popup, {
96
+ ...rest,
97
+ className: cx(styles.popup, className),
98
+ style: popupStyle,
99
+ children: /* @__PURE__ */ jsx(AnimatePresence, {
100
+ onExitComplete: actions.onExitComplete,
101
+ children: open ? /* @__PURE__ */ createElement(Motion.div, {
102
+ ...modalMotionConfig,
103
+ ...motionProps,
104
+ className: cx(styles.popupInner, panelClassName),
105
+ key: "modal-popup-panel",
106
+ style: {
107
+ maxWidth: width ?? void 0,
108
+ transition: "none",
109
+ ...style
110
+ }
111
+ }, children) : null
112
+ })
113
+ });
114
+ return /* @__PURE__ */ jsx(Dialog.Popup, {
115
+ ...rest,
116
+ className: mergeStateClassName(styles.popup, className),
117
+ style: popupStyle,
118
+ children: /* @__PURE__ */ jsx("div", {
119
+ className: cx(styles.popupInner, panelClassName),
120
+ style: {
121
+ maxWidth: width ?? void 0,
122
+ ...style
123
+ },
124
+ children
125
+ })
126
+ });
127
+ };
128
+ const ModalHeader = ({ className, ...rest }) => /* @__PURE__ */ jsx("div", {
129
+ ...rest,
130
+ className: cx(styles.header, className)
131
+ });
132
+ const ModalTitle = ({ className, ...rest }) => /* @__PURE__ */ jsx(Dialog.Title, {
133
+ ...rest,
134
+ className: mergeStateClassName(styles.title, className)
135
+ });
136
+ const ModalDescription = Dialog.Description;
137
+ const ModalContent = ({ className, ...rest }) => /* @__PURE__ */ jsx("div", {
138
+ ...rest,
139
+ className: cx(styles.content, className)
140
+ });
141
+ const ModalFooter = ({ className, ...rest }) => /* @__PURE__ */ jsx("div", {
142
+ ...rest,
143
+ className: cx(styles.footer, className)
144
+ });
145
+ const ModalClose = ({ className, children, ...rest }) => /* @__PURE__ */ jsx(Dialog.Close, {
146
+ ...rest,
147
+ className: mergeStateClassName(styles.close, className),
148
+ children: children ?? /* @__PURE__ */ jsx(X, { size: 18 })
149
+ });
150
+ const ModalTrigger = ({ children, className, nativeButton, ref: refProp, ...rest }) => {
151
+ const { isNativeButtonTriggerElement, resolvedNativeButton } = useNativeButton({
152
+ children,
153
+ nativeButton
154
+ });
155
+ const renderer = (props) => {
156
+ const resolvedProps = (() => {
157
+ if (isNativeButtonTriggerElement) return props;
158
+ const { type, ...restProps } = props;
159
+ return restProps;
160
+ })();
161
+ return cloneElement(children, {
162
+ ...mergeProps(children.props, resolvedProps),
163
+ ref: mergeRefs([
164
+ children.ref,
165
+ props.ref,
166
+ refProp
167
+ ])
168
+ });
169
+ };
170
+ if (isValidElement(children)) return /* @__PURE__ */ jsx(Dialog.Trigger, {
171
+ ...rest,
172
+ className,
173
+ nativeButton: resolvedNativeButton,
174
+ render: renderer
175
+ });
176
+ return /* @__PURE__ */ jsx(Dialog.Trigger, {
177
+ ...rest,
178
+ className,
179
+ nativeButton: resolvedNativeButton,
180
+ ref: refProp,
181
+ children
182
+ });
183
+ };
184
+
185
+ //#endregion
186
+ export { ModalBackdrop, ModalClose, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalPopup, ModalPortal, ModalRoot, ModalTitle, ModalTrigger, ModalViewport, useModalActions, useModalOpen };
187
+ //# sourceMappingURL=atoms.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atoms.mjs","names":["ModalDescription: React.FC<ModalDescriptionProps>"],"sources":["../../../src/base-ui/Modal/atoms.tsx"],"sourcesContent":["'use client';\n\nimport { Dialog } from '@base-ui/react/dialog';\nimport { mergeProps } from '@base-ui/react/merge-props';\nimport { cx } from 'antd-style';\nimport { X } from 'lucide-react';\nimport { AnimatePresence } from 'motion/react';\nimport type React from 'react';\nimport {\n cloneElement,\n createContext,\n isValidElement,\n use,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport { mergeRefs } from 'react-merge-refs';\n\nimport { useNativeButton } from '@/hooks/useNativeButton';\nimport { useMotionComponent } from '@/MotionProvider';\nimport { useAppElement } from '@/ThemeProvider';\n\nimport { backdropTransition, modalMotionConfig } from './constants';\nimport { styles } from './style';\n\nconst mergeStateClassName = <TState,>(\n base: string,\n className: string | ((state: TState) => string | undefined) | undefined,\n) => {\n if (typeof className === 'function') return (state: TState) => cx(base, className(state));\n return cx(base, className);\n};\n\n// --- Animation Contexts (granular to minimize re-renders) ---\n\n// State: open boolean, null = non-animated mode\nconst ModalOpenContext = createContext<boolean | null>(null);\n\n// Actions: stable callbacks, null = non-animated mode\ninterface ModalAnimationActions {\n onExitComplete: () => void;\n}\nconst ModalActionsContext = createContext<ModalAnimationActions | null>(null);\n\nexport const useModalOpen = () => use(ModalOpenContext);\nexport const useModalActions = () => use(ModalActionsContext);\n\n// --- Root ---\nexport type ModalRootProps = Dialog.Root.Props & {\n onExitComplete?: () => void;\n};\n\nconst AnimatedModalRoot = ({\n open,\n children,\n onExitComplete: onExitCompleteProp,\n ...rest\n}: Omit<ModalRootProps, 'open'> & { open: boolean }) => {\n const [isPresent, setIsPresent] = useState(!!open);\n\n useEffect(() => {\n if (open) setIsPresent(true);\n }, [open]);\n\n const handleExitComplete = useCallback(() => {\n setIsPresent(false);\n onExitCompleteProp?.();\n }, [onExitCompleteProp]);\n\n const actions = useMemo(() => ({ onExitComplete: handleExitComplete }), [handleExitComplete]);\n\n if (!isPresent) return null;\n\n return (\n <ModalOpenContext value={open}>\n <ModalActionsContext value={actions}>\n <Dialog.Root modal open {...rest}>\n {children}\n </Dialog.Root>\n </ModalActionsContext>\n </ModalOpenContext>\n );\n};\n\nexport const ModalRoot = ({ open, onExitComplete, ...rest }: ModalRootProps) => {\n if (open !== undefined) {\n return <AnimatedModalRoot open={open} onExitComplete={onExitComplete} {...rest} />;\n }\n return <Dialog.Root modal {...rest} />;\n};\n\n// --- Portal ---\nexport type ModalPortalProps = React.ComponentProps<typeof Dialog.Portal> & {\n container?: HTMLElement | null;\n};\nexport const ModalPortal = ({ container, ...rest }: ModalPortalProps) => {\n const appElement = useAppElement();\n return <Dialog.Portal container={container ?? appElement ?? undefined} {...rest} />;\n};\n\n// --- Viewport ---\nexport type ModalViewportProps = React.ComponentProps<typeof Dialog.Viewport>;\nexport const ModalViewport = ({ className, ...rest }: ModalViewportProps) => (\n <Dialog.Viewport\n {...rest}\n className={mergeStateClassName(styles.viewport, className as any) as any}\n />\n);\n\n// --- Backdrop ---\nexport type ModalBackdropProps = React.ComponentProps<typeof Dialog.Backdrop>;\nexport const ModalBackdrop = ({ className, style, ...rest }: ModalBackdropProps) => {\n const open = useModalOpen();\n const Motion = useMotionComponent();\n\n if (open !== null) {\n return (\n <Motion.div\n animate={{ opacity: open ? 1 : 0 }}\n className={cx(styles.backdrop, className as string)}\n initial={{ opacity: 0 }}\n style={{ ...style, transition: 'none' }}\n transition={backdropTransition}\n />\n );\n }\n\n return (\n <Dialog.Backdrop\n {...rest}\n className={mergeStateClassName(styles.backdrop, className as any) as any}\n style={style}\n />\n );\n};\n\n// --- Popup ---\nexport type ModalPopupProps = React.ComponentProps<typeof Dialog.Popup> & {\n motionProps?: Record<string, any>;\n panelClassName?: string;\n popupStyle?: React.CSSProperties;\n width?: number | string;\n};\nexport const ModalPopup = ({\n className,\n children,\n width,\n style,\n motionProps,\n panelClassName,\n popupStyle,\n ...rest\n}: ModalPopupProps) => {\n const open = useModalOpen();\n const actions = useModalActions();\n const Motion = useMotionComponent();\n\n if (open !== null && actions) {\n return (\n <Dialog.Popup {...rest} className={cx(styles.popup, className as string)} style={popupStyle}>\n <AnimatePresence onExitComplete={actions.onExitComplete}>\n {open ? (\n <Motion.div\n {...modalMotionConfig}\n {...motionProps}\n className={cx(styles.popupInner, panelClassName)}\n key=\"modal-popup-panel\"\n style={{ maxWidth: width ?? undefined, transition: 'none', ...style }}\n >\n {children}\n </Motion.div>\n ) : null}\n </AnimatePresence>\n </Dialog.Popup>\n );\n }\n\n return (\n <Dialog.Popup\n {...rest}\n className={mergeStateClassName(styles.popup, className as any) as any}\n style={popupStyle}\n >\n <div\n className={cx(styles.popupInner, panelClassName)}\n style={{ maxWidth: width ?? undefined, ...style }}\n >\n {children}\n </div>\n </Dialog.Popup>\n );\n};\n\n// --- Header ---\nexport type ModalHeaderProps = React.HTMLAttributes<HTMLDivElement> & {\n ref?: React.Ref<HTMLDivElement>;\n};\nexport const ModalHeader = ({ className, ...rest }: ModalHeaderProps) => (\n <div {...rest} className={cx(styles.header, className)} />\n);\n\n// --- Title ---\nexport type ModalTitleProps = React.ComponentProps<typeof Dialog.Title>;\nexport const ModalTitle = ({ className, ...rest }: ModalTitleProps) => (\n <Dialog.Title {...rest} className={mergeStateClassName(styles.title, className as any) as any} />\n);\n\n// --- Description ---\nexport type ModalDescriptionProps = React.ComponentProps<typeof Dialog.Description>;\nexport const ModalDescription: React.FC<ModalDescriptionProps> = Dialog.Description;\n\n// --- Content ---\nexport type ModalContentProps = React.HTMLAttributes<HTMLDivElement> & {\n ref?: React.Ref<HTMLDivElement>;\n};\nexport const ModalContent = ({ className, ...rest }: ModalContentProps) => (\n <div {...rest} className={cx(styles.content, className)} />\n);\n\n// --- Footer ---\nexport type ModalFooterProps = React.HTMLAttributes<HTMLDivElement> & {\n ref?: React.Ref<HTMLDivElement>;\n};\nexport const ModalFooter = ({ className, ...rest }: ModalFooterProps) => (\n <div {...rest} className={cx(styles.footer, className)} />\n);\n\n// --- Close ---\nexport type ModalCloseProps = React.ComponentProps<typeof Dialog.Close>;\nexport const ModalClose = ({ className, children, ...rest }: ModalCloseProps) => (\n <Dialog.Close {...rest} className={mergeStateClassName(styles.close, className as any) as any}>\n {children ?? <X size={18} />}\n </Dialog.Close>\n);\n\n// --- Trigger ---\nexport type ModalTriggerProps = Omit<\n React.ComponentPropsWithRef<typeof Dialog.Trigger>,\n 'children' | 'render'\n> & {\n children?: React.ReactNode;\n nativeButton?: boolean;\n};\n\nexport const ModalTrigger = ({\n children,\n className,\n nativeButton,\n ref: refProp,\n ...rest\n}: ModalTriggerProps) => {\n const { isNativeButtonTriggerElement, resolvedNativeButton } = useNativeButton({\n children,\n nativeButton,\n });\n\n const renderer = (props: any) => {\n const resolvedProps = (() => {\n if (isNativeButtonTriggerElement) return props as any;\n // eslint-disable-next-line unused-imports/no-unused-vars\n const { type, ...restProps } = props as any;\n return restProps;\n })();\n\n const mergedProps = mergeProps((children as any).props, resolvedProps);\n return cloneElement(children as any, {\n ...mergedProps,\n ref: mergeRefs([(children as any).ref, (props as any).ref, refProp]),\n });\n };\n\n if (isValidElement(children)) {\n return (\n <Dialog.Trigger\n {...rest}\n className={className}\n nativeButton={resolvedNativeButton}\n render={renderer as any}\n />\n );\n }\n\n return (\n <Dialog.Trigger\n {...rest}\n className={className}\n nativeButton={resolvedNativeButton}\n ref={refProp as any}\n >\n {children}\n </Dialog.Trigger>\n );\n};\n"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { MotionProps } from "motion/react";
2
+
3
+ //#region src/base-ui/Modal/constants.d.ts
4
+ declare const modalMotionConfig: MotionProps;
5
+ declare const backdropTransition: {
6
+ duration: number;
7
+ };
8
+ //#endregion
9
+ export { backdropTransition, modalMotionConfig };
10
+ //# sourceMappingURL=constants.d.mts.map
@@ -0,0 +1,27 @@
1
+ //#region src/base-ui/Modal/constants.ts
2
+ const enterStyle = {
3
+ opacity: 1,
4
+ scale: 1
5
+ };
6
+ const initialStyle = {
7
+ opacity: 0,
8
+ scale: .96
9
+ };
10
+ const modalMotionConfig = {
11
+ animate: enterStyle,
12
+ exit: {
13
+ ...initialStyle,
14
+ transition: { duration: .15 }
15
+ },
16
+ initial: initialStyle,
17
+ transition: {
18
+ damping: 20,
19
+ stiffness: 300,
20
+ type: "spring"
21
+ }
22
+ };
23
+ const backdropTransition = { duration: .15 };
24
+
25
+ //#endregion
26
+ export { backdropTransition, modalMotionConfig };
27
+ //# sourceMappingURL=constants.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.mjs","names":["modalMotionConfig: MotionProps"],"sources":["../../../src/base-ui/Modal/constants.ts"],"sourcesContent":["import type { MotionProps } from 'motion/react';\n\nconst enterStyle = { opacity: 1, scale: 1 };\nconst initialStyle = { opacity: 0, scale: 0.96 };\n\nexport const modalMotionConfig: MotionProps = {\n animate: enterStyle,\n exit: {\n ...initialStyle,\n transition: { duration: 0.15 },\n },\n initial: initialStyle,\n transition: {\n damping: 20,\n stiffness: 300,\n type: 'spring',\n },\n};\n\nexport const backdropTransition = { duration: 0.15 };\n"],"mappings":";AAEA,MAAM,aAAa;CAAE,SAAS;CAAG,OAAO;CAAG;AAC3C,MAAM,eAAe;CAAE,SAAS;CAAG,OAAO;CAAM;AAEhD,MAAaA,oBAAiC;CAC5C,SAAS;CACT,MAAM;EACJ,GAAG;EACH,YAAY,EAAE,UAAU,KAAM;EAC/B;CACD,SAAS;CACT,YAAY;EACV,SAAS;EACT,WAAW;EACX,MAAM;EACP;CACF;AAED,MAAa,qBAAqB,EAAE,UAAU,KAAM"}
@@ -0,0 +1,9 @@
1
+ import { ModalContextValue } from "./type.mjs";
2
+ import * as react145 from "react";
3
+
4
+ //#region src/base-ui/Modal/context.d.ts
5
+ declare const ModalContext: react145.Context<ModalContextValue>;
6
+ declare const useModalContext: () => ModalContextValue;
7
+ //#endregion
8
+ export { ModalContext, useModalContext };
9
+ //# sourceMappingURL=context.d.mts.map
@@ -0,0 +1,14 @@
1
+ 'use client';
2
+
3
+ import { createContext, use } from "react";
4
+
5
+ //#region src/base-ui/Modal/context.ts
6
+ const ModalContext = createContext({
7
+ close: () => void 0,
8
+ setCanDismissByClickOutside: () => void 0
9
+ });
10
+ const useModalContext = () => use(ModalContext);
11
+
12
+ //#endregion
13
+ export { ModalContext, useModalContext };
14
+ //# sourceMappingURL=context.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.mjs","names":[],"sources":["../../../src/base-ui/Modal/context.ts"],"sourcesContent":["'use client';\n\nimport { createContext, use } from 'react';\n\nimport type { ModalContextValue } from './type';\n\nexport const ModalContext = createContext<ModalContextValue>({\n close: () => undefined,\n setCanDismissByClickOutside: () => undefined,\n});\n\nexport const useModalContext = () => use(ModalContext);\n"],"mappings":";;;;;AAMA,MAAa,eAAe,cAAiC;CAC3D,aAAa;CACb,mCAAmC;CACpC,CAAC;AAEF,MAAa,wBAAwB,IAAI,aAAa"}
@@ -0,0 +1,25 @@
1
+ import { ImperativeModalProps, ModalConfirmConfig, ModalInstance } from "./type.mjs";
2
+ import * as react146 from "react";
3
+
4
+ //#region src/base-ui/Modal/imperative.d.ts
5
+ interface ModalHostProps {
6
+ root?: HTMLElement | ShadowRoot | null;
7
+ }
8
+ interface ModalSystem {
9
+ confirmModal: (config: ModalConfirmConfig) => {
10
+ close: () => void;
11
+ destroy: () => void;
12
+ };
13
+ createModal: (props: ImperativeModalProps) => ModalInstance;
14
+ ModalHost: React.FC<ModalHostProps>;
15
+ }
16
+ declare function createModalSystem(): ModalSystem;
17
+ declare const ModalHost: react146.FC<ModalHostProps>;
18
+ declare const createModal: (props: ImperativeModalProps) => ModalInstance;
19
+ declare const confirmModal: (config: ModalConfirmConfig) => {
20
+ close: () => void;
21
+ destroy: () => void;
22
+ };
23
+ //#endregion
24
+ export { ModalHost, ModalHostProps, ModalSystem, confirmModal, createModal, createModalSystem };
25
+ //# sourceMappingURL=imperative.d.mts.map
@@ -0,0 +1,221 @@
1
+ 'use client';
2
+
3
+ import { useIsClient } from "../../hooks/useIsClient.mjs";
4
+ import { useAppElement } from "../../ThemeProvider/AppElementContext.mjs";
5
+ import { registerDevSingleton } from "../../utils/devSingleton.mjs";
6
+ import { styles } from "./style.mjs";
7
+ import { ModalBackdrop, ModalClose, ModalContent, ModalFooter, ModalHeader, ModalPopup, ModalPortal, ModalRoot, ModalTitle } from "./atoms.mjs";
8
+ import { ModalContext, useModalContext } from "./context.mjs";
9
+ import { memo, useCallback, useEffect, useState, useSyncExternalStore } from "react";
10
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
11
+ import { cx } from "antd-style";
12
+ import { createPortal } from "react-dom";
13
+
14
+ //#region src/base-ui/Modal/imperative.tsx
15
+ const ModalPortalWrapper = ({ children, root }) => {
16
+ const appElement = useAppElement();
17
+ return createPortal(children, root ?? appElement ?? document.body);
18
+ };
19
+ const ConfirmBody = ({ config }) => {
20
+ const { close } = useModalContext();
21
+ const [loading, setLoading] = useState(false);
22
+ const { cancelText = "Cancel", content, okButtonProps, okText = "OK", onCancel, onOk } = config;
23
+ const { danger, className: okUserCls, ...restOkProps } = okButtonProps ?? {};
24
+ const handleCancel = useCallback(() => {
25
+ close();
26
+ onCancel?.();
27
+ }, [close, onCancel]);
28
+ const handleOk = useCallback(async () => {
29
+ if (onOk) try {
30
+ const result = onOk();
31
+ if (result && typeof result.then === "function") {
32
+ setLoading(true);
33
+ await result;
34
+ setLoading(false);
35
+ }
36
+ } catch {
37
+ setLoading(false);
38
+ return;
39
+ }
40
+ close();
41
+ }, [close, onOk]);
42
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [content && /* @__PURE__ */ jsx("div", {
43
+ style: { padding: "16px 24px" },
44
+ children: content
45
+ }), /* @__PURE__ */ jsxs(ModalFooter, { children: [/* @__PURE__ */ jsx("button", {
46
+ className: cx(styles.buttonBase, styles.cancelButton),
47
+ type: "button",
48
+ onClick: handleCancel,
49
+ children: cancelText
50
+ }), /* @__PURE__ */ jsxs("button", {
51
+ ...restOkProps,
52
+ disabled: loading,
53
+ type: "button",
54
+ className: cx(styles.buttonBase, danger ? styles.dangerOkButton : styles.okButton, okUserCls),
55
+ onClick: handleOk,
56
+ children: [loading && /* @__PURE__ */ jsx("span", { className: styles.loadingSpinner }), okText]
57
+ })] })] });
58
+ };
59
+ ConfirmBody.displayName = "ConfirmBody";
60
+ let systemSeed = 0;
61
+ function createModalSystem() {
62
+ const systemId = systemSeed++;
63
+ const singletonName = systemId === 0 ? "BaseModalHost" : `BaseModalHost-${systemId}`;
64
+ let modalStack = [];
65
+ let modalSeed = 0;
66
+ const listeners = /* @__PURE__ */ new Set();
67
+ const notify = () => listeners.forEach((l) => l());
68
+ const subscribe = (l) => {
69
+ listeners.add(l);
70
+ return () => listeners.delete(l);
71
+ };
72
+ const EMPTY = [];
73
+ const getSnapshot = () => modalStack;
74
+ const getServerSnapshot = () => EMPTY;
75
+ const updateModal = (id, next) => {
76
+ let changed = false;
77
+ modalStack = modalStack.map((item) => {
78
+ if (item.id !== id) return item;
79
+ changed = true;
80
+ return {
81
+ ...item,
82
+ props: {
83
+ ...item.props,
84
+ ...next
85
+ }
86
+ };
87
+ });
88
+ if (changed) notify();
89
+ };
90
+ const closeModal = (id) => {
91
+ updateModal(id, { open: false });
92
+ };
93
+ const destroyModal = (id) => {
94
+ const next = modalStack.filter((item) => item.id !== id);
95
+ if (next.length === modalStack.length) return;
96
+ modalStack = next;
97
+ notify();
98
+ };
99
+ const StackItem = memo(({ entry }) => {
100
+ const { id, props } = entry;
101
+ const { children, classNames, content, footer, maskClosable, onOpenChange, onOpenChangeComplete, open, styles: semanticStyles, title, width } = props;
102
+ const isOpen = open ?? true;
103
+ const handleOpenChange = useCallback((nextOpen, eventDetails) => {
104
+ if (!nextOpen && maskClosable === false && eventDetails?.reason === "outside-press") return;
105
+ if (!nextOpen) closeModal(id);
106
+ onOpenChange?.(nextOpen);
107
+ }, [
108
+ id,
109
+ maskClosable,
110
+ onOpenChange
111
+ ]);
112
+ const handleExitComplete = useCallback(() => {
113
+ onOpenChangeComplete?.(false);
114
+ destroyModal(id);
115
+ }, [id, onOpenChangeComplete]);
116
+ const close = useCallback(() => closeModal(id), [id]);
117
+ const setCanDismissByClickOutside = useCallback((value) => updateModal(id, { maskClosable: value }), [id]);
118
+ const showTitle = title !== void 0 && title !== false && title !== null;
119
+ return /* @__PURE__ */ jsx(ModalContext, {
120
+ value: {
121
+ close,
122
+ setCanDismissByClickOutside
123
+ },
124
+ children: /* @__PURE__ */ jsx(ModalRoot, {
125
+ open: isOpen,
126
+ onExitComplete: handleExitComplete,
127
+ onOpenChange: handleOpenChange,
128
+ children: /* @__PURE__ */ jsxs(ModalPortal, { children: [/* @__PURE__ */ jsx(ModalBackdrop, {
129
+ className: classNames?.backdrop,
130
+ style: semanticStyles?.backdrop
131
+ }), /* @__PURE__ */ jsxs(ModalPopup, {
132
+ className: classNames?.popup,
133
+ popupStyle: semanticStyles?.popup,
134
+ width,
135
+ children: [
136
+ showTitle && /* @__PURE__ */ jsxs(ModalHeader, {
137
+ className: classNames?.header,
138
+ style: semanticStyles?.header,
139
+ children: [/* @__PURE__ */ jsx(ModalTitle, {
140
+ className: classNames?.title,
141
+ style: semanticStyles?.title,
142
+ children: title
143
+ }), /* @__PURE__ */ jsx(ModalClose, {
144
+ className: classNames?.close,
145
+ style: semanticStyles?.close
146
+ })]
147
+ }),
148
+ /* @__PURE__ */ jsx(ModalContent, {
149
+ className: classNames?.content,
150
+ style: semanticStyles?.content,
151
+ children: content ?? children
152
+ }),
153
+ footer
154
+ ]
155
+ })] })
156
+ })
157
+ });
158
+ });
159
+ StackItem.displayName = "ModalStackItem";
160
+ const StackRenderer = memo(({ stack }) => {
161
+ if (!useIsClient()) return null;
162
+ return stack.map((entry) => /* @__PURE__ */ jsx(StackItem, { entry }, entry.id));
163
+ });
164
+ StackRenderer.displayName = "ModalStackRenderer";
165
+ const Host = ({ root }) => {
166
+ const stack = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
167
+ const isClient = useIsClient();
168
+ useEffect(() => {
169
+ if (!isClient) return;
170
+ return registerDevSingleton(singletonName, root ?? document.body);
171
+ }, [isClient, root]);
172
+ if (!isClient) return null;
173
+ if (stack.length === 0) return null;
174
+ return /* @__PURE__ */ jsx(ModalPortalWrapper, {
175
+ root,
176
+ children: /* @__PURE__ */ jsx(StackRenderer, { stack })
177
+ });
178
+ };
179
+ const create = (props) => {
180
+ const id = `base-modal-${Date.now()}-${modalSeed++}`;
181
+ modalStack = [...modalStack, {
182
+ id,
183
+ props: {
184
+ ...props,
185
+ open: props.open ?? true
186
+ }
187
+ }];
188
+ notify();
189
+ return {
190
+ close: () => closeModal(id),
191
+ destroy: () => destroyModal(id),
192
+ setCanDismissByClickOutside: (value) => updateModal(id, { maskClosable: value }),
193
+ update: (nextProps) => updateModal(id, nextProps)
194
+ };
195
+ };
196
+ const confirm = (config) => {
197
+ const instance = create({
198
+ content: /* @__PURE__ */ jsx(ConfirmBody, { config }),
199
+ styles: { content: { padding: 0 } },
200
+ title: config.title,
201
+ width: 420
202
+ });
203
+ return {
204
+ close: instance.close,
205
+ destroy: instance.destroy
206
+ };
207
+ };
208
+ return {
209
+ ModalHost: Host,
210
+ confirmModal: confirm,
211
+ createModal: create
212
+ };
213
+ }
214
+ const defaultSystem = createModalSystem();
215
+ const ModalHost = defaultSystem.ModalHost;
216
+ const createModal = defaultSystem.createModal;
217
+ const confirmModal = defaultSystem.confirmModal;
218
+
219
+ //#endregion
220
+ export { ModalHost, confirmModal, createModal, createModalSystem };
221
+ //# sourceMappingURL=imperative.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imperative.mjs","names":["modalStack: ModalStackEntry[]","EMPTY: ModalStackEntry[]"],"sources":["../../../src/base-ui/Modal/imperative.tsx"],"sourcesContent":["'use client';\n\nimport { cx } from 'antd-style';\nimport type { ReactNode } from 'react';\nimport { memo, useCallback, useEffect, useState, useSyncExternalStore } from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { useIsClient } from '@/hooks/useIsClient';\nimport { useAppElement } from '@/ThemeProvider';\nimport { registerDevSingleton } from '@/utils/devSingleton';\n\nimport {\n ModalBackdrop,\n ModalClose,\n ModalContent,\n ModalFooter,\n ModalHeader,\n ModalPopup,\n ModalPortal,\n ModalRoot,\n ModalTitle,\n} from './atoms';\nimport { ModalContext, useModalContext } from './context';\nimport { styles } from './style';\nimport type { ImperativeModalProps, ModalConfirmConfig, ModalInstance } from './type';\n\n// --- Shared types ---\n\ntype ModalStackEntry = {\n id: string;\n props: ImperativeModalProps;\n};\n\n// --- Shared components (stack-independent) ---\n\nconst ModalPortalWrapper = ({\n children,\n root,\n}: {\n children: ReactNode;\n root?: HTMLElement | ShadowRoot | null;\n}) => {\n const appElement = useAppElement();\n const container = root ?? appElement ?? document.body;\n return createPortal(children, container);\n};\n\nconst ConfirmBody = ({ config }: { config: ModalConfirmConfig }) => {\n const { close } = useModalContext();\n const [loading, setLoading] = useState(false);\n\n const { cancelText = 'Cancel', content, okButtonProps, okText = 'OK', onCancel, onOk } = config;\n\n const { danger, className: okUserCls, ...restOkProps } = okButtonProps ?? {};\n\n const handleCancel = useCallback(() => {\n close();\n onCancel?.();\n }, [close, onCancel]);\n\n const handleOk = useCallback(async () => {\n if (onOk) {\n try {\n const result = onOk();\n if (result && typeof (result as any).then === 'function') {\n setLoading(true);\n await result;\n setLoading(false);\n }\n } catch {\n setLoading(false);\n return;\n }\n }\n close();\n }, [close, onOk]);\n\n return (\n <>\n {content && <div style={{ padding: '16px 24px' }}>{content}</div>}\n <ModalFooter>\n <button\n className={cx(styles.buttonBase, styles.cancelButton)}\n type=\"button\"\n onClick={handleCancel}\n >\n {cancelText}\n </button>\n <button\n {...restOkProps}\n disabled={loading}\n type=\"button\"\n className={cx(\n styles.buttonBase,\n danger ? styles.dangerOkButton : styles.okButton,\n okUserCls,\n )}\n onClick={handleOk}\n >\n {loading && <span className={styles.loadingSpinner} />}\n {okText}\n </button>\n </ModalFooter>\n </>\n );\n};\nConfirmBody.displayName = 'ConfirmBody';\n\n// --- Factory ---\n\nexport interface ModalHostProps {\n root?: HTMLElement | ShadowRoot | null;\n}\n\nexport interface ModalSystem {\n confirmModal: (config: ModalConfirmConfig) => { close: () => void; destroy: () => void };\n createModal: (props: ImperativeModalProps) => ModalInstance;\n ModalHost: React.FC<ModalHostProps>;\n}\n\nlet systemSeed = 0;\n\nexport function createModalSystem(): ModalSystem {\n const systemId = systemSeed++;\n const singletonName = systemId === 0 ? 'BaseModalHost' : `BaseModalHost-${systemId}`;\n\n // --- Stack state (isolated per system) ---\n let modalStack: ModalStackEntry[] = [];\n let modalSeed = 0;\n const listeners = new Set<() => void>();\n\n const notify = () => listeners.forEach((l) => l());\n const subscribe = (l: () => void) => {\n listeners.add(l);\n return () => listeners.delete(l);\n };\n const EMPTY: ModalStackEntry[] = [];\n const getSnapshot = () => modalStack;\n const getServerSnapshot = () => EMPTY;\n\n // --- Stack operations ---\n\n const updateModal = (id: string, next: Partial<ImperativeModalProps>) => {\n let changed = false;\n modalStack = modalStack.map((item) => {\n if (item.id !== id) return item;\n changed = true;\n return { ...item, props: { ...item.props, ...next } };\n });\n if (changed) notify();\n };\n\n const closeModal = (id: string) => {\n updateModal(id, { open: false });\n };\n\n const destroyModal = (id: string) => {\n const next = modalStack.filter((item) => item.id !== id);\n if (next.length === modalStack.length) return;\n modalStack = next;\n notify();\n };\n\n // --- Stack Item (captures operations via closure) ---\n\n const StackItem = memo(({ entry }: { entry: ModalStackEntry }) => {\n const { id, props } = entry;\n const {\n children,\n classNames,\n content,\n footer,\n maskClosable,\n onOpenChange,\n onOpenChangeComplete,\n open,\n styles: semanticStyles,\n title,\n width,\n } = props;\n\n const isOpen = open ?? true;\n\n const handleOpenChange = useCallback(\n (nextOpen: boolean, eventDetails?: { reason: string }) => {\n if (!nextOpen && maskClosable === false && eventDetails?.reason === 'outside-press') return;\n if (!nextOpen) closeModal(id);\n onOpenChange?.(nextOpen);\n },\n [id, maskClosable, onOpenChange],\n );\n\n const handleExitComplete = useCallback(() => {\n onOpenChangeComplete?.(false);\n destroyModal(id);\n }, [id, onOpenChangeComplete]);\n\n const close = useCallback(() => closeModal(id), [id]);\n const setCanDismissByClickOutside = useCallback(\n (value: boolean) => updateModal(id, { maskClosable: value }),\n [id],\n );\n\n const showTitle = title !== undefined && title !== false && title !== null;\n\n return (\n <ModalContext value={{ close, setCanDismissByClickOutside }}>\n <ModalRoot\n open={isOpen}\n onExitComplete={handleExitComplete}\n onOpenChange={handleOpenChange}\n >\n <ModalPortal>\n <ModalBackdrop className={classNames?.backdrop} style={semanticStyles?.backdrop} />\n <ModalPopup\n className={classNames?.popup}\n popupStyle={semanticStyles?.popup}\n width={width}\n >\n {showTitle && (\n <ModalHeader className={classNames?.header} style={semanticStyles?.header}>\n <ModalTitle className={classNames?.title} style={semanticStyles?.title}>\n {title}\n </ModalTitle>\n <ModalClose className={classNames?.close} style={semanticStyles?.close} />\n </ModalHeader>\n )}\n <ModalContent className={classNames?.content} style={semanticStyles?.content}>\n {content ?? children}\n </ModalContent>\n {footer}\n </ModalPopup>\n </ModalPortal>\n </ModalRoot>\n </ModalContext>\n );\n });\n StackItem.displayName = 'ModalStackItem';\n\n const StackRenderer = memo(({ stack }: { stack: ModalStackEntry[] }) => {\n const isClient = useIsClient();\n if (!isClient) return null;\n return stack.map((entry) => <StackItem entry={entry} key={entry.id} />);\n });\n StackRenderer.displayName = 'ModalStackRenderer';\n\n // --- ModalHost ---\n\n const Host = ({ root }: ModalHostProps) => {\n const stack = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n const isClient = useIsClient();\n\n useEffect(() => {\n if (!isClient) return;\n const scope = root ?? document.body;\n return registerDevSingleton(singletonName, scope);\n }, [isClient, root]);\n\n if (!isClient) return null;\n if (stack.length === 0) return null;\n\n return (\n <ModalPortalWrapper root={root}>\n <StackRenderer stack={stack} />\n </ModalPortalWrapper>\n );\n };\n\n // --- createModal ---\n\n const create = (props: ImperativeModalProps): ModalInstance => {\n const id = `base-modal-${Date.now()}-${modalSeed++}`;\n modalStack = [...modalStack, { id, props: { ...props, open: props.open ?? true } }];\n notify();\n\n return {\n close: () => closeModal(id),\n destroy: () => destroyModal(id),\n setCanDismissByClickOutside: (value) => updateModal(id, { maskClosable: value }),\n update: (nextProps) => updateModal(id, nextProps),\n };\n };\n\n // --- confirmModal ---\n\n const confirm = (config: ModalConfirmConfig) => {\n const instance = create({\n content: <ConfirmBody config={config} />,\n styles: { content: { padding: 0 } },\n title: config.title,\n width: 420,\n });\n\n return {\n close: instance.close,\n destroy: instance.destroy,\n };\n };\n\n return { ModalHost: Host, confirmModal: confirm, createModal: create };\n}\n\n// --- Default global instance (backward compatible) ---\n\nconst defaultSystem = createModalSystem();\nexport const ModalHost = defaultSystem.ModalHost;\nexport const createModal = defaultSystem.createModal;\nexport const confirmModal = defaultSystem.confirmModal;\n"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { ModalBackdrop, ModalBackdropProps, ModalClose, ModalCloseProps, ModalContent, ModalContentProps, ModalDescription, ModalDescriptionProps, ModalFooter, ModalFooterProps, ModalHeader, ModalHeaderProps, ModalPopup, ModalPopupProps, ModalPortal, ModalPortalProps, ModalRoot, ModalRootProps, ModalTitle, ModalTitleProps, ModalTrigger, ModalTriggerProps, ModalViewport, ModalViewportProps, useModalActions, useModalOpen } from "./atoms.mjs";
2
+ import { backdropTransition, modalMotionConfig } from "./constants.mjs";
3
+ import { BaseModalProps, ImperativeModalProps, ModalComponentProps, ModalConfirmConfig, ModalContextValue, ModalInstance } from "./type.mjs";
4
+ import { ModalContext, useModalContext } from "./context.mjs";
5
+ import { ModalHost, ModalHostProps, ModalSystem, confirmModal, createModal, createModalSystem } from "./imperative.mjs";
6
+ import { Modal } from "./Modal.mjs";