diff --git a/components/modal/ConfirmDialog.tsx b/components/modal/ConfirmDialog.tsx
index ca9dd2f7db..a7f8106249 100644
--- a/components/modal/ConfirmDialog.tsx
+++ b/components/modal/ConfirmDialog.tsx
@@ -1,19 +1,23 @@
+import * as React from 'react';
import CheckCircleFilled from '@ant-design/icons/CheckCircleFilled';
import CloseCircleFilled from '@ant-design/icons/CloseCircleFilled';
import ExclamationCircleFilled from '@ant-design/icons/ExclamationCircleFilled';
import InfoCircleFilled from '@ant-design/icons/InfoCircleFilled';
import classNames from 'classnames';
-import * as React from 'react';
-import ActionButton from '../_util/ActionButton';
+
import { getTransitionName } from '../_util/motion';
import warning from '../_util/warning';
import type { ThemeConfig } from '../config-provider';
import ConfigProvider from '../config-provider';
import { useLocale } from '../locale';
-import Dialog from './Modal';
+import CancelBtn from './components/ConfirmCancelBtn';
+import OkBtn from './components/ConfirmOkBtn';
+import type { ModalContextProps } from './context';
+import { ModalContextProvider } from './context';
import type { ModalFuncProps, ModalLocale } from './interface';
+import Dialog from './Modal';
-interface ConfirmDialogProps extends ModalFuncProps {
+export interface ConfirmDialogProps extends ModalFuncProps {
afterClose?: () => void;
close?: (...args: any[]) => void;
/**
@@ -23,7 +27,7 @@ interface ConfirmDialogProps extends ModalFuncProps {
*/
onConfirm?: (confirmed: boolean) => void;
autoFocusButton?: null | 'ok' | 'cancel';
- rootPrefixCls: string;
+ rootPrefixCls?: string;
iconPrefixCls?: string;
theme?: ThemeConfig;
@@ -43,22 +47,15 @@ export function ConfirmContent(
) {
const {
icon,
- onCancel,
- onOk,
- close,
- onConfirm,
- isSilent,
okText,
- okButtonProps,
cancelText,
- cancelButtonProps,
confirmPrefixCls,
- rootPrefixCls,
type,
okCancel,
footer,
// Legacy for static function usage
locale: staticLocale,
+ ...resetProps
} = props;
warning(
@@ -90,7 +87,6 @@ export function ConfirmContent(
}
}
- const okType = props.okType || 'primary';
// 默认为 true,保持向下兼容
const mergedOkCancel = okCancel ?? type === 'confirm';
@@ -100,20 +96,26 @@ export function ConfirmContent(
const mergedLocale = staticLocale || locale;
- const cancelButton = mergedOkCancel && (
- {
- close?.(...args);
- onConfirm?.(false);
- }}
- autoFocus={autoFocusButton === 'cancel'}
- buttonProps={cancelButtonProps}
- prefixCls={`${rootPrefixCls}-btn`}
- >
- {cancelText || mergedLocale?.cancelText}
-
+ // ================== Locale Text ==================
+ const okTextLocale = okText || (mergedOkCancel ? mergedLocale?.okText : mergedLocale?.justOkText);
+ const cancelTextLocale = cancelText || mergedLocale?.cancelText;
+
+ // ================= Context Value =================
+ const btnCtxValue: ModalContextProps = {
+ autoFocusButton,
+ cancelTextLocale,
+ okTextLocale,
+ mergedOkCancel,
+ ...resetProps,
+ };
+ const btnCtxValueMemo = React.useMemo(() => btnCtxValue, [...Object.values(btnCtxValue)]);
+
+ // ====================== Footer Origin Node ======================
+ const footerOriginNode = (
+ <>
+
+
+ >
);
return (
@@ -125,24 +127,18 @@ export function ConfirmContent(
)}
{props.content}
- {footer === undefined ? (
-
- {cancelButton}
-
{
- close?.(...args);
- onConfirm?.(true);
- }}
- autoFocus={autoFocusButton === 'ok'}
- buttonProps={okButtonProps}
- prefixCls={`${rootPrefixCls}-btn`}
- >
- {okText || (mergedOkCancel ? mergedLocale?.okText : mergedLocale?.justOkText)}
-
-
+
+ {footer === undefined || typeof footer === 'function' ? (
+
+
+ {typeof footer === 'function'
+ ? footer(footerOriginNode, {
+ OkBtn,
+ CancelBtn,
+ })
+ : footerOriginNode}
+
+
) : (
footer
)}
@@ -215,8 +211,12 @@ const ConfirmDialog: React.FC = (props) => {
open={open}
title=""
footer={null}
- transitionName={getTransitionName(rootPrefixCls, 'zoom', props.transitionName)}
- maskTransitionName={getTransitionName(rootPrefixCls, 'fade', props.maskTransitionName)}
+ transitionName={getTransitionName(rootPrefixCls || '', 'zoom', props.transitionName)}
+ maskTransitionName={getTransitionName(
+ rootPrefixCls || '',
+ 'fade',
+ props.maskTransitionName,
+ )}
mask={mask}
maskClosable={maskClosable}
maskStyle={maskStyle}
diff --git a/components/modal/Modal.tsx b/components/modal/Modal.tsx
index 7a5138ab5f..6bb5ad1ef7 100644
--- a/components/modal/Modal.tsx
+++ b/components/modal/Modal.tsx
@@ -1,7 +1,8 @@
+import * as React from 'react';
import CloseOutlined from '@ant-design/icons/CloseOutlined';
import classNames from 'classnames';
import Dialog from 'rc-dialog';
-import * as React from 'react';
+
import useClosable from '../_util/hooks/useClosable';
import { getTransitionName } from '../_util/motion';
import { canUseDocElement } from '../_util/styleChecker';
@@ -9,10 +10,10 @@ import warning from '../_util/warning';
import { ConfigContext } from '../config-provider';
import { NoFormStyle } from '../form/context';
import { NoCompactStyle } from '../space/Compact';
+import { usePanelRef } from '../watermark/context';
import type { ModalProps, MousePosition } from './interface';
import { Footer, renderCloseIcon } from './shared';
import useStyle from './style';
-import { usePanelRef } from '../watermark/context';
let mousePosition: MousePosition;
@@ -93,9 +94,9 @@ const Modal: React.FC = (props) => {
warning(!('visible' in props), 'Modal', '`visible` is deprecated, please use `open` instead.');
}
- const dialogFooter =
- footer === undefined ? : footer;
-
+ const dialogFooter = footer !== null && (
+
+ );
const [mergedClosable, mergedCloseIcon] = useClosable(
closable,
closeIcon,
diff --git a/components/modal/__tests__/Modal.test.tsx b/components/modal/__tests__/Modal.test.tsx
index 4fddef8553..8c78fde801 100644
--- a/components/modal/__tests__/Modal.test.tsx
+++ b/components/modal/__tests__/Modal.test.tsx
@@ -1,10 +1,11 @@
import React, { useEffect } from 'react';
+
import type { ModalProps } from '..';
import Modal from '..';
+import { resetWarned } from '../../_util/warning';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
import { fireEvent, render } from '../../../tests/utils';
-import { resetWarned } from '../../_util/warning';
jest.mock('rc-util/lib/Portal');
@@ -133,4 +134,20 @@ describe('Modal', () => {
render(footer} />);
expect(document.querySelector('.custom-footer')).toBeTruthy();
});
+
+ it('Should custom footer function work', () => {
+ render(
+ (
+ <>
+
+
+ footer-ele
+ >
+ )}
+ />,
+ );
+ expect(document.querySelector('.custom-footer-ele')).toBeTruthy();
+ });
});
diff --git a/components/modal/__tests__/__snapshots__/demo-extend.test.ts.snap b/components/modal/__tests__/__snapshots__/demo-extend.test.ts.snap
index 6646278edb..96ba794fa4 100644
--- a/components/modal/__tests__/__snapshots__/demo-extend.test.ts.snap
+++ b/components/modal/__tests__/__snapshots__/demo-extend.test.ts.snap
@@ -483,6 +483,40 @@ exports[`renders components/modal/demo/footer.tsx extend context correctly 1`] =
exports[`renders components/modal/demo/footer.tsx extend context correctly 2`] = `[]`;
+exports[`renders components/modal/demo/footer-render.tsx extend context correctly 1`] = `
+
+
+
+
+
+
+
+
+`;
+
+exports[`renders components/modal/demo/footer-render.tsx extend context correctly 2`] = `[]`;
+
exports[`renders components/modal/demo/hooks.tsx extend context correctly 1`] = `
`;
+exports[`renders components/modal/demo/footer-render.tsx correctly 1`] = `
+
+
+
+
+
+
+
+
+`;
+
exports[`renders components/modal/demo/hooks.tsx correctly 1`] = `
{
warnSpy.mockRestore();
});
+
+ it('Should custom footer function work width confirm', async () => {
+ Modal.confirm({
+ content: 'hai',
+ footer: (_, { OkBtn, CancelBtn }) => (
+ <>
+
+
+
footer-ele
+ >
+ ),
+ });
+
+ await waitFakeTimer();
+
+ expect(document.querySelector('.custom-footer-ele')).toBeTruthy();
+ });
});
diff --git a/components/modal/components/ConfirmCancelBtn.tsx b/components/modal/components/ConfirmCancelBtn.tsx
new file mode 100644
index 0000000000..a3dd1211c7
--- /dev/null
+++ b/components/modal/components/ConfirmCancelBtn.tsx
@@ -0,0 +1,54 @@
+import type { FC } from 'react';
+import React, { useContext } from 'react';
+
+import ActionButton from '../../_util/ActionButton';
+import type { ConfirmDialogProps } from '../ConfirmDialog';
+import { ModalContext } from '../context';
+
+export interface ConfirmCancelBtnProps
+ extends Pick<
+ ConfirmDialogProps,
+ 'cancelButtonProps' | 'isSilent' | 'rootPrefixCls' | 'close' | 'onConfirm' | 'onCancel'
+ > {
+ autoFocusButton?: false | 'ok' | 'cancel' | null;
+ cancelTextLocale?:
+ | string
+ | number
+ | true
+ | React.ReactElement
>
+ | Iterable;
+ mergedOkCancel?: boolean;
+}
+
+const ConfirmCancelBtn: FC = () => {
+ const {
+ autoFocusButton,
+ cancelButtonProps,
+ cancelTextLocale,
+ isSilent,
+ mergedOkCancel,
+ rootPrefixCls,
+ close,
+ onCancel,
+ onConfirm,
+ } = useContext(ModalContext);
+ return (
+ mergedOkCancel && (
+ {
+ close?.(...args);
+ onConfirm?.(false);
+ }}
+ autoFocus={autoFocusButton === 'cancel'}
+ buttonProps={cancelButtonProps}
+ prefixCls={`${rootPrefixCls}-btn`}
+ >
+ {cancelTextLocale}
+
+ )
+ );
+};
+
+export default ConfirmCancelBtn;
diff --git a/components/modal/components/ConfirmOkBtn.tsx b/components/modal/components/ConfirmOkBtn.tsx
new file mode 100644
index 0000000000..4a15c77e39
--- /dev/null
+++ b/components/modal/components/ConfirmOkBtn.tsx
@@ -0,0 +1,52 @@
+import type { FC } from 'react';
+import React, { useContext } from 'react';
+
+import ActionButton from '../../_util/ActionButton';
+import type { ConfirmDialogProps } from '../ConfirmDialog';
+import { ModalContext } from '../context';
+
+export interface ConfirmOkBtnProps
+ extends Pick<
+ ConfirmDialogProps,
+ 'close' | 'isSilent' | 'okType' | 'okButtonProps' | 'rootPrefixCls' | 'onConfirm' | 'onOk'
+ > {
+ autoFocusButton?: false | 'ok' | 'cancel' | null;
+ okTextLocale?:
+ | string
+ | number
+ | true
+ | React.ReactElement>
+ | Iterable;
+}
+
+const ConfirmOkBtn: FC = () => {
+ const {
+ autoFocusButton,
+ close,
+ isSilent,
+ okButtonProps,
+ rootPrefixCls,
+ okTextLocale,
+ okType,
+ onConfirm,
+ onOk,
+ } = useContext(ModalContext);
+ return (
+ {
+ close?.(...args);
+ onConfirm?.(true);
+ }}
+ autoFocus={autoFocusButton === 'ok'}
+ buttonProps={okButtonProps}
+ prefixCls={`${rootPrefixCls}-btn`}
+ >
+ {okTextLocale}
+
+ );
+};
+
+export default ConfirmOkBtn;
diff --git a/components/modal/components/NormalCancelBtn.tsx b/components/modal/components/NormalCancelBtn.tsx
new file mode 100644
index 0000000000..d8891ad1d3
--- /dev/null
+++ b/components/modal/components/NormalCancelBtn.tsx
@@ -0,0 +1,26 @@
+import type { FC } from 'react';
+import React, { useContext } from 'react';
+
+import Button from '../../button';
+import { ModalContext } from '../context';
+import type { ModalProps } from '../interface';
+
+export interface NormalCancelBtnProps extends Pick {
+ cancelTextLocale?:
+ | string
+ | number
+ | true
+ | React.ReactElement>
+ | Iterable;
+}
+
+const NormalCancelBtn: FC = () => {
+ const { cancelButtonProps, cancelTextLocale, onCancel } = useContext(ModalContext);
+ return (
+
+ );
+};
+
+export default NormalCancelBtn;
diff --git a/components/modal/components/NormalOkBtn.tsx b/components/modal/components/NormalOkBtn.tsx
new file mode 100644
index 0000000000..9a31d405ff
--- /dev/null
+++ b/components/modal/components/NormalOkBtn.tsx
@@ -0,0 +1,33 @@
+import type { FC } from 'react';
+import React, { useContext } from 'react';
+
+import Button from '../../button';
+import { convertLegacyProps } from '../../button/button';
+import { ModalContext } from '../context';
+import type { ModalProps } from '../interface';
+
+export interface NormalOkBtnProps
+ extends Pick {
+ okTextLocale?:
+ | string
+ | number
+ | true
+ | React.ReactElement>
+ | Iterable;
+}
+
+const NormalOkBtn: FC = () => {
+ const { confirmLoading, okButtonProps, okType, okTextLocale, onOk } = useContext(ModalContext);
+ return (
+
+ );
+};
+
+export default NormalOkBtn;
diff --git a/components/modal/context.ts b/components/modal/context.ts
new file mode 100644
index 0000000000..2051d72652
--- /dev/null
+++ b/components/modal/context.ts
@@ -0,0 +1,15 @@
+import React from 'react';
+
+import type { ConfirmCancelBtnProps } from './components/ConfirmCancelBtn';
+import type { ConfirmOkBtnProps } from './components/ConfirmOkBtn';
+import type { NormalCancelBtnProps } from './components/NormalCancelBtn';
+import type { NormalOkBtnProps } from './components/NormalOkBtn';
+
+export type ModalContextProps = NormalCancelBtnProps &
+ NormalOkBtnProps &
+ ConfirmOkBtnProps &
+ ConfirmCancelBtnProps;
+
+export const ModalContext = React.createContext({} as ModalContextProps);
+
+export const { Provider: ModalContextProvider } = ModalContext;
diff --git a/components/modal/demo/footer-render.md b/components/modal/demo/footer-render.md
new file mode 100644
index 0000000000..3101357339
--- /dev/null
+++ b/components/modal/demo/footer-render.md
@@ -0,0 +1,7 @@
+## zh-CN
+
+自定义页脚渲染函数,支持在原有基础上进行扩展。
+
+## en-US
+
+Customize the footer rendering function to support extensions on top of the original.
diff --git a/components/modal/demo/footer-render.tsx b/components/modal/demo/footer-render.tsx
new file mode 100644
index 0000000000..c5a01521cc
--- /dev/null
+++ b/components/modal/demo/footer-render.tsx
@@ -0,0 +1,65 @@
+import React, { useState } from 'react';
+import { Button, Modal, Space } from 'antd';
+
+const App: React.FC = () => {
+ const [open, setOpen] = useState(false);
+
+ const showModal = () => {
+ setOpen(true);
+ };
+ const handleOk = () => {
+ setOpen(false);
+ };
+
+ const handleCancel = () => {
+ setOpen(false);
+ };
+ return (
+ <>
+
+
+
+
+ (
+ <>
+ Custom Button
+
+
+ >
+ )}
+ >
+ Some contents...
+ Some contents...
+ Some contents...
+ Some contents...
+ Some contents...
+
+ >
+ );
+};
+
+export default App;
diff --git a/components/modal/index.en-US.md b/components/modal/index.en-US.md
index d89cb556e2..6982369b4f 100644
--- a/components/modal/index.en-US.md
+++ b/components/modal/index.en-US.md
@@ -22,6 +22,7 @@ Additionally, if you need show a simple confirmation dialog, you can use [`App.u
Basic
Asynchronously close
Customized Footer
+Customized Footer render function
Use hooks to get context
Internationalization
Manual to update destroy
@@ -53,7 +54,7 @@ Common props ref:[Common props](/docs/react/common-props)
| confirmLoading | Whether to apply loading visual effect for OK button or not | boolean | false | |
| destroyOnClose | Whether to unmount child components on onClose | boolean | false | |
| focusTriggerAfterClose | Whether need to focus trigger element after dialog is closed | boolean | true | 4.9.0 |
-| footer | Footer content, set as `footer={null}` when you don't need default buttons | ReactNode | (OK and Cancel buttons) | |
+| footer | Footer content, set as `footer={null}` when you don't need default buttons | (params:[footerRenderParams](/components/modal-cn#footerrenderparams))=> React.ReactNode \| React.ReactNode | (OK and Cancel buttons) | |
| forceRender | Force render Modal | boolean | false | |
| getContainer | The mounted node for Modal but still display at fullscreen | HTMLElement \| () => HTMLElement \| Selectors \| false | document.body | |
| keyboard | Whether support press esc to close | boolean | true | |
@@ -103,7 +104,7 @@ The items listed above are all functions, expecting a settings object as paramet
| className | The className of container | string | - | |
| closeIcon | Custom close icon. 5.7.0: close button will be hidden when setting to `null` or `false` | boolean \| ReactNode | <CloseOutlined /> | |
| content | Content | ReactNode | - | |
-| footer | Footer content, set as `footer: null` when you don't need default buttons | ReactNode | - | 5.1.0 |
+| footer | Footer content, set as `footer: null` when you don't need default buttons | (params:[footerRenderParams](/components/modal-cn#footerrenderparams))=> React.ReactNode \| React.ReactNode | - | 5.9.0 |
| getContainer | Return the mount node for Modal | HTMLElement \| () => HTMLElement \| Selectors \| false | document.body | |
| icon | Custom icon | ReactNode | <ExclamationCircleFilled /> | |
| keyboard | Whether support press esc to close | boolean | true | |
@@ -180,6 +181,14 @@ return {contextHolder}
;
const confirmed = await modal.confirm({ ... });
```
+## footerRenderParams
+
+
+| Property | Description | Type | Default |
+| --- | --- | --- | --- |
+| originNode | default node | React.ReactNode | - |
+| extra | extended options | { OkBtn: FC; CancelBtn: FC } | - |
+
## Design Token
diff --git a/components/modal/index.zh-CN.md b/components/modal/index.zh-CN.md
index a293e7b146..a12cf85467 100644
--- a/components/modal/index.zh-CN.md
+++ b/components/modal/index.zh-CN.md
@@ -23,6 +23,7 @@ demo:
基本
异步关闭
自定义页脚
+自定义页脚渲染函数
使用 hooks 获得上下文
国际化
手动更新和移除
@@ -54,7 +55,7 @@ demo:
| confirmLoading | 确定按钮 loading | boolean | false | |
| destroyOnClose | 关闭时销毁 Modal 里的子元素 | boolean | false | |
| focusTriggerAfterClose | 对话框关闭后是否需要聚焦触发元素 | boolean | true | 4.9.0 |
-| footer | 底部内容,当不需要默认底部按钮时,可以设为 `footer={null}` | ReactNode | (确定取消按钮) | |
+| footer | 底部内容,当不需要默认底部按钮时,可以设为 `footer={null}` | (params:[footerRenderParams](/components/modal-cn#footerrenderparams))=> React.ReactNode \| React.ReactNode | (确定取消按钮) | 5.9.0 |
| forceRender | 强制渲染 Modal | boolean | false | |
| getContainer | 指定 Modal 挂载的节点,但依旧为全屏展示,`false` 为挂载在当前位置 | HTMLElement \| () => HTMLElement \| Selectors \| false | document.body | |
| keyboard | 是否支持键盘 esc 关闭 | boolean | true | |
@@ -104,7 +105,7 @@ demo:
| className | 容器类名 | string | - | |
| closeIcon | 自定义关闭图标。5.7.0:设置为 `null` 或 `false` 时隐藏关闭按钮 | boolean \| ReactNode | <CloseOutlined /> | |
| content | 内容 | ReactNode | - | |
-| footer | 底部内容,当不需要默认底部按钮时,可以设为 `footer: null` | ReactNode | - | 5.1.0 |
+| footer | 底部内容,当不需要默认底部按钮时,可以设为 `footer: null` | (params:[footerRenderParams](/components/modal-cn#footerrenderparams))=> React.ReactNode \| React.ReactNode | - | 5.9.0 |
| getContainer | 指定 Modal 挂载的 HTML 节点, false 为挂载在当前 dom | HTMLElement \| () => HTMLElement \| Selectors \| false | document.body | |
| icon | 自定义图标 | ReactNode | <ExclamationCircleFilled /> | |
| keyboard | 是否支持键盘 esc 关闭 | boolean | true | |
@@ -181,6 +182,14 @@ return {contextHolder}
;
const confirmed = await modal.confirm({ ... });
```
+## footerRenderParams
+
+
+| 参数 | 说明 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| originNode | 默认节点 | React.ReactNode | - |
+| extra | 扩展选项 | { OkBtn: FC; CancelBtn: FC } | - |
+
## Design Token
diff --git a/components/modal/interface.ts b/components/modal/interface.ts
index 57bda8bac8..d4ac596c53 100644
--- a/components/modal/interface.ts
+++ b/components/modal/interface.ts
@@ -1,6 +1,12 @@
+import type { FC } from 'react';
+
import type { ButtonProps, LegacyButtonType } from '../button/button';
import type { DirectionType } from '../config-provider';
+export type ModalFooterRender = (
+ originNode: React.ReactNode,
+ extra: { OkBtn: FC; CancelBtn: FC },
+) => React.ReactNode;
export interface ModalProps {
/** Whether the modal dialog is visible or not */
open?: boolean;
@@ -22,7 +28,7 @@ export interface ModalProps {
/** Width of the modal dialog */
width?: string | number;
/** Footer content */
- footer?: React.ReactNode;
+ footer?: ModalFooterRender | React.ReactNode;
/** Text of the OK button */
okText?: React.ReactNode;
/** Button `type` of the OK button */
@@ -101,7 +107,7 @@ export interface ModalFuncProps {
direction?: DirectionType;
bodyStyle?: React.CSSProperties;
closeIcon?: React.ReactNode;
- footer?: React.ReactNode;
+ footer?: ModalProps['footer'];
modalRender?: (node: React.ReactNode) => React.ReactNode;
focusTriggerAfterClose?: boolean;
}
diff --git a/components/modal/shared.tsx b/components/modal/shared.tsx
index 4f998c49cd..9e6cd41fcc 100644
--- a/components/modal/shared.tsx
+++ b/components/modal/shared.tsx
@@ -1,9 +1,12 @@
-import CloseOutlined from '@ant-design/icons/CloseOutlined';
import React from 'react';
-import Button from '../button';
-import { convertLegacyProps } from '../button/button';
+import CloseOutlined from '@ant-design/icons/CloseOutlined';
+
import { DisabledContextProvider } from '../config-provider/DisabledContext';
import { useLocale } from '../locale';
+import NormalCancelBtn from './components/NormalCancelBtn';
+import NormalOkBtn from './components/NormalOkBtn';
+import type { ModalContextProps } from './context';
+import { ModalContextProvider } from './context';
import type { ModalProps } from './interface';
import { getConfirmLocale } from './locale';
@@ -42,23 +45,48 @@ export const Footer: React.FC<
onCancel,
okButtonProps,
cancelButtonProps,
+ footer,
} = props;
const [locale] = useLocale('Modal', getConfirmLocale());
- return (
+ // ================== Locale Text ==================
+ const okTextLocale = okText || locale?.okText;
+ const cancelTextLocale = cancelText || locale?.cancelText;
+
+ // ================= Context Value =================
+ const btnCtxValue: ModalContextProps = {
+ confirmLoading,
+ okButtonProps,
+ cancelButtonProps,
+ okTextLocale,
+ cancelTextLocale,
+ okType,
+ onOk,
+ onCancel,
+ };
+
+ const btnCtxValueMemo = React.useMemo(() => btnCtxValue, [...Object.values(btnCtxValue)]);
+
+ const footerOriginNode = (
+ <>
+
+
+ >
+ );
+
+ return footer === undefined || typeof footer === 'function' ? (
-
- {cancelText || locale?.cancelText}
-
-
- {okText || locale?.okText}
-
+
+ {typeof footer === 'function'
+ ? footer(footerOriginNode, {
+ OkBtn: NormalOkBtn,
+ CancelBtn: NormalCancelBtn,
+ })
+ : footerOriginNode}
+
+ ) : (
+ footer
);
};