diff --git a/packages/field/src/components/TimePicker/index.tsx b/packages/field/src/components/TimePicker/index.tsx
index 6a57f27b3ecf..0e62aaebd652 100644
--- a/packages/field/src/components/TimePicker/index.tsx
+++ b/packages/field/src/components/TimePicker/index.tsx
@@ -134,7 +134,7 @@ const FieldTimePicker: ProFieldFC<
const FieldTimeRangePickerComponents: ProFieldFC<{
text: string[] | number[];
format: string;
-}> = ({ text, mode, format, render, renderFormItem, plain, fieldProps }) => {
+}> = ({ text, mode, format, render, renderFormItem, plain, fieldProps }, ref) => {
const finalFormat = fieldProps?.format || format || 'HH:mm:ss';
const [startText, endText] = Array.isArray(text) ? text : [];
const startTextIsNumberOrMoment = dayjs.isDayjs(startText) || typeof startText === 'number';
@@ -149,7 +149,7 @@ const FieldTimeRangePickerComponents: ProFieldFC<{
if (mode === 'read') {
const dom = (
-
+
{parsedStartText || '-'}
{parsedEndText || '-'}
@@ -165,6 +165,7 @@ const FieldTimeRangePickerComponents: ProFieldFC<{
const dom = (
= (pr
return wrapSSR(
{
{
{
message.success('提交成功');
return true;
@@ -90,7 +90,7 @@ export default () => {
{
message.success('提交成功');
return true;
diff --git a/packages/form/src/layouts/DrawerForm/index.tsx b/packages/form/src/layouts/DrawerForm/index.tsx
index fd0104c87a05..6dd26a1dcbb2 100644
--- a/packages/form/src/layouts/DrawerForm/index.tsx
+++ b/packages/form/src/layouts/DrawerForm/index.tsx
@@ -1,6 +1,6 @@
-import { useRefFunction } from '@ant-design/pro-utils';
+import { compareVersions, useRefFunction } from '@ant-design/pro-utils';
import type { DrawerProps, FormProps } from 'antd';
-import { ConfigProvider, Drawer } from 'antd';
+import { ConfigProvider, version, Drawer } from 'antd';
import merge from 'lodash.merge';
import useMergedState from 'rc-util/lib/hooks/useMergedState';
import { noteOnce } from 'rc-util/lib/warning';
@@ -31,19 +31,20 @@ export type DrawerFormProps> = Omit void;
+ /**
+ * @deprecated use open replace
+ */
+ visible?: boolean;
/** @name 受控的打开关闭 */
open?: DrawerProps['open'];
/**
* @name 打开关闭的事件 */
- onVisibleChange?: (visible: boolean) => void;
- /**
- * @name 打开关闭的事件 */
- afterOpenChange?: (visible: boolean) => void;
+ onOpenChange?: (visible: boolean) => void;
/**
* 不支持 'visible',请使用全局的 visible
*
@@ -67,8 +68,9 @@ function DrawerForm>({
submitTimeout,
title,
width,
+ onOpenChange,
visible: propVisible,
- open: propOpen,
+ open: propsOpen,
...rest
}: DrawerFormProps) {
noteOnce(
@@ -81,9 +83,9 @@ function DrawerForm>({
const [, forceUpdate] = useState([]);
const [loading, setLoading] = useState(false);
- const [visible, setVisible] = useMergedState(!!propVisible, {
- value: propOpen || propVisible,
- onChange: onVisibleChange,
+ const [open, setOpen] = useMergedState(!!propVisible, {
+ value: propsOpen || propVisible,
+ onChange: onOpenChange || onVisibleChange,
});
const footerRef = useRef(null);
@@ -106,11 +108,12 @@ function DrawerForm>({
}, [drawerProps?.destroyOnClose, rest.form, rest.formRef]);
useEffect(() => {
- if (visible && propVisible) {
+ if (open && (propsOpen || propVisible)) {
+ onOpenChange?.(true);
onVisibleChange?.(true);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [propVisible, visible]);
+ }, [propVisible, open]);
const triggerDom = useMemo(() => {
if (!trigger) {
@@ -121,11 +124,11 @@ function DrawerForm>({
key: 'trigger',
...trigger.props,
onClick: async (e: any) => {
- setVisible(!visible);
+ setOpen(!open);
trigger.props?.onClick?.(e);
},
});
- }, [setVisible, trigger, visible]);
+ }, [setOpen, trigger, open]);
const submitterConfig = useMemo(() => {
if (rest.submitter === false) {
@@ -143,7 +146,7 @@ function DrawerForm>({
// 提交表单loading时,不可关闭弹框
disabled: submitTimeout ? loading : undefined,
onClick: (e: any) => {
- setVisible(false);
+ setOpen(false);
resetFields();
drawerProps?.onClose?.(e);
},
@@ -157,7 +160,7 @@ function DrawerForm>({
context.locale?.Modal?.cancelText,
submitTimeout,
loading,
- setVisible,
+ setOpen,
resetFields,
drawerProps,
]);
@@ -184,24 +187,32 @@ function DrawerForm>({
const result = await response;
// 返回真值,关闭弹框
if (result) {
- setVisible(false);
+ setOpen(false);
}
return result;
});
+ const drawerOpenProps = compareVersions(version, '4.23.0')
+ ? {
+ open: open,
+ onOpenChange: onVisibleChange,
+ }
+ : {
+ visible: open,
+ onVisibleChange: onVisibleChange,
+ };
+
return (
<>
{
// 提交表单loading时,阻止弹框关闭
if (submitTimeout && loading) return;
- setVisible(false);
+ setOpen(false);
drawerProps?.onClose?.(e);
resetFields();
}}
@@ -236,7 +247,9 @@ function DrawerForm>({
submitter={submitterConfig}
onFinish={async (values) => {
const result = await onFinishHandle(values);
- resetFields();
+ if (result === true) {
+ resetFields();
+ }
return result;
}}
contentRender={contentRender}
diff --git a/packages/form/src/layouts/LightFilter/index.tsx b/packages/form/src/layouts/LightFilter/index.tsx
index 76f768546d99..c7af3d861736 100644
--- a/packages/form/src/layouts/LightFilter/index.tsx
+++ b/packages/form/src/layouts/LightFilter/index.tsx
@@ -160,8 +160,8 @@ const LightFilterContainer: React.FC<{
> = Omit, 'onFini
/** @name 用于触发抽屉打开的 dom */
trigger?: JSX.Element;
- /** @name 受控的打开关闭 */
- visible?: ModalProps['open'];
/** @name 受控的打开关闭 */
open?: ModalProps['open'];
- /** @name 打开关闭的事件 */
+ /**
+ * @deprecated use onOpenChange replace
+ */
onVisibleChange?: (visible: boolean) => void;
+ /**
+ * @deprecated use open replace
+ */
+ visible?: boolean;
+ /** @name 打开关闭的事件 */
+ onOpenChange?: (visible: boolean) => void;
/**
* 不支持 'visible',请使用全局的 visible
*
@@ -55,6 +63,7 @@ function ModalForm>({
children,
trigger,
onVisibleChange,
+ onOpenChange,
modalProps,
onFinish,
submitTimeout,
@@ -77,7 +86,7 @@ function ModalForm>({
const [open, setOpen] = useMergedState(!!propVisible, {
value: propsOpen || propVisible,
- onChange: onVisibleChange,
+ onChange: onOpenChange || onVisibleChange,
});
const footerRef = useRef(null);
@@ -100,11 +109,12 @@ function ModalForm>({
}, [modalProps?.destroyOnClose, rest.form, rest.formRef]);
useEffect(() => {
- if (open && propVisible) {
+ if (open && (propsOpen || propVisible)) {
+ onOpenChange?.(true);
onVisibleChange?.(true);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [propVisible, open]);
+ }, [propVisible, propsOpen, open]);
const triggerDom = useMemo(() => {
if (!trigger) {
@@ -188,15 +198,21 @@ function ModalForm>({
[onFinish, setOpen, submitTimeout],
);
+ const modalOpenProps = compareVersions(version, '4.23.0')
+ ? {
+ open,
+ }
+ : {
+ visible: open,
+ };
+
return (
<>
{
// 提交表单loading时,阻止弹框关闭
if (submitTimeout && loading) return;
@@ -205,6 +221,7 @@ function ModalForm>({
}}
afterClose={() => {
resetFields();
+ setOpen(false);
modalProps?.afterClose?.();
}}
footer={
@@ -227,7 +244,9 @@ function ModalForm>({
submitter={submitterConfig}
onFinish={async (values) => {
const result = await onFinishHandle(values);
- resetFields();
+ if (result === true) {
+ resetFields();
+ }
return result;
}}
contentRender={contentRender}
diff --git a/packages/layout/src/components/AppsLogoComponents/index.tsx b/packages/layout/src/components/AppsLogoComponents/index.tsx
index 0efce073c51d..1bc0fe364a4d 100644
--- a/packages/layout/src/components/AppsLogoComponents/index.tsx
+++ b/packages/layout/src/components/AppsLogoComponents/index.tsx
@@ -1,4 +1,5 @@
-import { Popover } from 'antd';
+import { compareVersions } from '@ant-design/pro-utils';
+import { Popover, version } from 'antd';
import classNames from 'classnames';
import React, { useMemo, useState } from 'react';
import { AppsLogo } from './AppsLogo';
@@ -67,6 +68,14 @@ export const AppsLogoComponents: React.FC<{
if (!props?.appList?.length) return null;
+ const popoverOpenProps = compareVersions(version, '4.23.0')
+ ? {
+ onOpenChange: setOpen,
+ }
+ : {
+ onVisibleChange: () => setOpen,
+ };
+
return wrapSSR(
<>
@@ -75,8 +84,7 @@ export const AppsLogoComponents: React.FC<{
trigger={['click']}
zIndex={9999}
arrowPointAtCenter
- onVisibleChange={setOpen}
- onOpenChange={setOpen}
+ {...popoverOpenProps}
overlayClassName={`${baseClassName}-popover ${hashId}`}
content={popoverContent}
getPopupContainer={() => ref.current || document.body}
diff --git a/packages/layout/src/components/SettingDrawer/index.tsx b/packages/layout/src/components/SettingDrawer/index.tsx
index 2b60c258f062..038fece450d2 100644
--- a/packages/layout/src/components/SettingDrawer/index.tsx
+++ b/packages/layout/src/components/SettingDrawer/index.tsx
@@ -4,14 +4,14 @@ import {
NotificationOutlined,
SettingOutlined,
} from '@ant-design/icons';
-import { isBrowser, merge } from '@ant-design/pro-utils';
+import { compareVersions, isBrowser, merge } from '@ant-design/pro-utils';
import {
disable as darkreaderDisable,
enable as darkreaderEnable,
setFetchMethod as setFetch,
} from '@umijs/ssr-darkreader';
import { useUrlSearchParams } from '@umijs/use-params';
-import { Alert, Button, Divider, Drawer, List, message, Switch } from 'antd';
+import { Alert, Button, Divider, Drawer, List, message, Switch, version } from 'antd';
import omit from 'omit.js';
import useMergedState from 'rc-util/lib/hooks/useMergedState';
import React, { useEffect, useRef, useState } from 'react';
@@ -219,7 +219,7 @@ export const SettingDrawer: React.FC = (props) => {
} = props;
const firstRender = useRef(true);
- const [show, setShow] = useMergedState(false, {
+ const [open, setOpen] = useMergedState(false, {
value: props.collapse,
onChange: props.onCollapseChange,
});
@@ -333,17 +333,27 @@ export const SettingDrawer: React.FC = (props) => {
const baseClassName = `${prefixCls}-setting-drawer`;
const { wrapSSR, hashId } = useStyle(baseClassName);
+ const drawerOpenProps = compareVersions(version, '4.23.0')
+ ? {
+ open: open,
+ onClose: () => setOpen(false),
+ }
+ : {
+ visible: open,
+ onClose: () => setOpen(false),
+ };
+
return wrapSSR(
<>
setShow(!show)}
+ onClick={() => setOpen(!open)}
style={{
width: 48,
height: 48,
}}
>
- {show ? (
+ {open ? (
= (props) => {
)}
setShow(false)}
placement="right"
getContainer={getContainer}
style={{
diff --git a/packages/layout/src/components/SiderMenu/index.tsx b/packages/layout/src/components/SiderMenu/index.tsx
index 474e360bbdc9..ebc3eee7b266 100644
--- a/packages/layout/src/components/SiderMenu/index.tsx
+++ b/packages/layout/src/components/SiderMenu/index.tsx
@@ -1,5 +1,6 @@
+import { compareVersions } from '@ant-design/pro-utils';
import { getFlatMenus } from '@umijs/route-utils';
-import { Drawer } from 'antd';
+import { Drawer, version } from 'antd';
import classNames from 'classnames';
import Omit from 'omit.js';
import React, { useEffect } from 'react';
@@ -53,15 +54,22 @@ const SiderMenuWrapper: React.FC = (prop
return null;
}
+ const drawerOpenProps = compareVersions(version, '4.23.0')
+ ? {
+ open: !collapsed,
+ onClose: () => onCollapse?.(true),
+ }
+ : {
+ visible: !collapsed,
+ onClose: () => onCollapse?.(true),
+ };
+
return wrapSSR(
isMobile ? (
onCollapse?.(true)}
+ {...drawerOpenProps}
style={{
padding: 0,
height: '100vh',
diff --git a/packages/layout/src/demos/siteMenu.tsx b/packages/layout/src/demos/siteMenu.tsx
index 8446bc486fe2..bdcba34e391a 100644
--- a/packages/layout/src/demos/siteMenu.tsx
+++ b/packages/layout/src/demos/siteMenu.tsx
@@ -10,8 +10,9 @@ import {
import ProCard from '@ant-design/pro-card';
import type { ProSettings } from '@ant-design/pro-layout';
import { PageContainer, ProLayout } from '@ant-design/pro-layout';
+import { compareVersions } from '@ant-design/pro-utils';
import { css } from '@emotion/css';
-import { Divider, Dropdown, Input } from 'antd';
+import { Divider, Dropdown, Input, version } from 'antd';
import React, { useState } from 'react';
import defaultProps from './_defaultProps';
@@ -175,6 +176,17 @@ export default () => {
return defaultDom;
}
if (_.isMobile) return defaultDom;
+
+ const dropdownOpenProps = compareVersions(version, '4.23.0')
+ ? {
+ open: dropdownVisible,
+ onOpenChange: setDropdownVisible,
+ }
+ : {
+ visible: dropdownVisible,
+ onVisibleChange: dropdownVisible,
+ };
+
return (
<>
{
/>
{
return {
hashId: '',
@@ -270,8 +270,6 @@ const CacheClean = () => {
return null;
};
-const AntdConfigProvider = antd.ConfigProvider;
-
/**
* 如果没有配置 locale,这里组件会根据 antd 的 key 来自动选择
*
diff --git a/packages/utils/src/compareVersions/index.ts b/packages/utils/src/compareVersions/index.ts
new file mode 100644
index 000000000000..ab842c6d7f21
--- /dev/null
+++ b/packages/utils/src/compareVersions/index.ts
@@ -0,0 +1,170 @@
+const semver =
+ /^[v^~<>=]*?(\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+))?(?:-([\da-z\-]+(?:\.[\da-z\-]+)*))?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i;
+
+const isWildcard = (s: string) => s === '*' || s === 'x' || s === 'X';
+
+const tryParse = (v: string) => {
+ const n = parseInt(v, 10);
+ return isNaN(n) ? v : n;
+};
+
+const operatorResMap = {
+ '>': [1],
+ '>=': [0, 1],
+ '=': [0],
+ '<=': [-1, 0],
+ '<': [-1],
+};
+
+const allowedOperators = Object.keys(operatorResMap);
+
+const assertValidOperator = (op: string) => {
+ if (typeof op !== 'string') {
+ throw new TypeError(`Invalid operator type, expected string but got ${typeof op}`);
+ }
+ if (allowedOperators.indexOf(op) === -1) {
+ throw new Error(`Invalid operator, expected one of ${allowedOperators.join('|')}`);
+ }
+};
+
+const forceType = (a: string | number, b: string | number) =>
+ typeof a !== typeof b ? [String(a), String(b)] : [a, b];
+
+const compareStrings = (a: string, b: string) => {
+ if (isWildcard(a) || isWildcard(b)) return 0;
+ const [ap, bp] = forceType(tryParse(a), tryParse(b));
+ if (ap > bp) return 1;
+ if (ap < bp) return -1;
+ return 0;
+};
+
+const compareSegments = (a: string | RegExpMatchArray, b: string | RegExpMatchArray) => {
+ for (let i = 0; i < Math.max(a.length, b.length); i++) {
+ const r = compareStrings(a[i] || '0', b[i] || '0');
+ if (r !== 0) return r;
+ }
+ return 0;
+};
+
+const validateAndParse = (version: string) => {
+ if (typeof version !== 'string') {
+ throw new TypeError('Invalid argument expected string');
+ }
+ const match = version.match(semver);
+ if (!match) {
+ throw new Error(`Invalid argument not valid semver ('${version}' received)`);
+ }
+ match.shift();
+ return match;
+};
+
+/**
+ * Compare [semver](https://semver.org/) version strings to find greater, equal or lesser.
+ * This library supports the full semver specification, including comparing versions with different number of digits like `1.0.0`, `1.0`, `1`, and pre-release versions like `1.0.0-alpha`.
+ * @param v1 - First version to compare
+ * @param v2 - Second version to compare
+ * @returns Numeric value compatible with the [Array.sort(fn) interface](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Parameters).
+ */
+export const compareVersions = (v1: string, v2: string) => {
+ // validate input and split into segments
+ const n1 = validateAndParse(v1);
+ const n2 = validateAndParse(v2);
+
+ // pop off the patch
+ const p1 = n1.pop();
+ const p2 = n2.pop();
+
+ // validate numbers
+ const r = compareSegments(n1, n2);
+ if (r !== 0) return r;
+
+ // validate pre-release
+ if (p1 && p2) {
+ return compareSegments(p1.split('.'), p2.split('.'));
+ } else if (p1 || p2) {
+ return p1 ? -1 : 1;
+ }
+
+ return 0;
+};
+
+/**
+ * Validate [semver](https://semver.org/) version strings.
+ *
+ * @param version Version number to validate
+ * @returns `true` if the version number is a valid semver version number, `false` otherwise.
+ *
+ * @example
+ * ```
+ * validate('1.0.0-rc.1'); // return true
+ * validate('1.0-rc.1'); // return false
+ * validate('foo'); // return false
+ * ```
+ */
+export const validate = (version: string) =>
+ typeof version === 'string' && /^[v\d]/.test(version) && semver.test(version);
+
+/**
+ * Allowed arithmetic operators
+ */
+export type CompareOperator = '>' | '>=' | '=' | '<' | '<=';
+
+/**
+ * Compare [semver](https://semver.org/) version strings using the specified operator.
+ *
+ * @param v1 First version to compare
+ * @param v2 Second version to compare
+ * @param operator Allowed arithmetic operator to use
+ * @returns `true` if the comparison between the firstVersion and the secondVersion satisfies the operator, `false` otherwise.
+ *
+ * @example
+ * ```
+ * compare('10.1.8', '10.0.4', '>'); // return true
+ * compare('10.0.1', '10.0.1', '='); // return true
+ * compare('10.1.1', '10.2.2', '<'); // return true
+ * compare('10.1.1', '10.2.2', '<='); // return true
+ * compare('10.1.1', '10.2.2', '>='); // return false
+ * ```
+ */
+export const compare = (v1: string, v2: string, operator: CompareOperator) => {
+ // validate input operator
+ assertValidOperator(operator);
+
+ // since result of compareVersions can only be -1 or 0 or 1
+ // a simple map can be used to replace switch
+ const res = compareVersions(v1, v2);
+
+ return operatorResMap[operator].includes(res);
+};
+
+/**
+ * Match [npm semver](https://docs.npmjs.com/cli/v6/using-npm/semver) version range.
+ *
+ * @param version Version number to match
+ * @param range Range pattern for version
+ * @returns `true` if the version number is within the range, `false` otherwise.
+ *
+ * @example
+ * ```
+ * satisfies('1.1.0', '^1.0.0'); // return true
+ * satisfies('1.1.0', '~1.0.0'); // return false
+ * ```
+ */
+export const satisfies = (version: string, range: string) => {
+ // if no range operator then "="
+ const m = range.match(/^([<>=~^]+)/);
+ const op = m ? m[1] : '=';
+
+ // if gt/lt/eq then operator compare
+ if (op !== '^' && op !== '~') return compare(version, range, op as CompareOperator);
+
+ // else range of either "~" or "^" is assumed
+ const [v1, v2, v3] = validateAndParse(version);
+ const [r1, r2, r3] = validateAndParse(range);
+ if (compareStrings(v1, r1) !== 0) return false;
+ if (op === '^') {
+ return compareSegments([v2, v3], [r2, r3]) >= 0;
+ }
+ if (compareStrings(v2, r2) !== 0) return false;
+ return compareStrings(v3, r3) >= 0;
+};
diff --git a/packages/utils/src/components/FilterDropdown/index.tsx b/packages/utils/src/components/FilterDropdown/index.tsx
index 4980e7ca7f99..b8315b48b8ae 100644
--- a/packages/utils/src/components/FilterDropdown/index.tsx
+++ b/packages/utils/src/components/FilterDropdown/index.tsx
@@ -1,7 +1,9 @@
-import { ConfigProvider, Dropdown } from 'antd';
+import { ConfigProvider, Dropdown, version } from 'antd';
import React, { useContext } from 'react';
import type { DropdownFooterProps } from '../DropdownFooter';
import { DropdownFooter } from '../DropdownFooter';
+import { compareVersions } from '../../compareVersions';
+
import { useStyle } from './style';
import 'antd/es/dropdown/style';
@@ -29,29 +31,52 @@ export type DropdownProps = {
footerRender?: FooterRender;
padding?: number;
disabled?: boolean;
+ /**
+ * @deprecated use onOpenChange replace
+ */
onVisibleChange?: (visible: boolean) => void;
+ /**
+ * @deprecated use open replace
+ */
visible?: boolean;
+ onOpenChange?: (visible: boolean) => void;
+ open?: boolean;
placement?: Placement;
children?: React.ReactNode;
};
-
const FilterDropdown: React.FC = (props) => {
- const { children, label, footer, disabled, onVisibleChange, visible, footerRender, placement } =
- props;
+ const {
+ children,
+ label,
+ footer,
+ open,
+ onOpenChange,
+ disabled,
+ onVisibleChange,
+ visible,
+ footerRender,
+ placement,
+ } = props;
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
const prefixCls = getPrefixCls('pro-core-field-dropdown');
const { wrapSSR, hashId } = useStyle(prefixCls);
+ const dropdownOpenProps = compareVersions(version, '4.23.0')
+ ? {
+ visible: open || visible,
+ onVisibleChange: onOpenChange || onVisibleChange,
+ }
+ : {
+ open: open || visible,
+ onOpenChange: onOpenChange || onVisibleChange,
+ };
+
return wrapSSR(
{children}
diff --git a/packages/utils/src/components/InlineErrorFormItem/index.tsx b/packages/utils/src/components/InlineErrorFormItem/index.tsx
index 03cf66d13b9c..53cc044d3022 100644
--- a/packages/utils/src/components/InlineErrorFormItem/index.tsx
+++ b/packages/utils/src/components/InlineErrorFormItem/index.tsx
@@ -1,5 +1,7 @@
import { LoadingOutlined } from '@ant-design/icons';
+import { compareVersions } from '@ant-design/pro-utils';
import type { FormItemProps, PopoverProps } from 'antd';
+import { version } from 'antd';
import { ConfigProvider, Form, Popover } from 'antd';
import type { NamePath } from 'rc-field-form/lib/interface';
import React, { useContext, useEffect, useState } from 'react';
@@ -31,7 +33,7 @@ const InlineErrorFormItemPopover: React.FC<{
extra: JSX.Element;
popoverProps?: PopoverProps;
}> = ({ inputProps, input, extra, errorList, popoverProps }) => {
- const [visible, setVisible] = useState(false);
+ const [open, setOpen] = useState(false);
const [errorStringList, setErrorList] = useState([]);
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
const prefixCls = getPrefixCls();
@@ -44,21 +46,27 @@ const InlineErrorFormItemPopover: React.FC<{
}
}, [inputProps.errors, inputProps.validateStatus]);
+ const drawerOpenProps = compareVersions(version, '4.23.0')
+ ? {
+ open: errorStringList.length < 1 ? false : open,
+ onOpenChange: (changeOpen: boolean) => {
+ if (changeOpen === open) return;
+ setOpen(changeOpen);
+ },
+ }
+ : {
+ visible: errorStringList.length < 1 ? false : open,
+ onVisibleChange: (changeOpen: boolean) => {
+ if (changeOpen === open) return;
+ setOpen(changeOpen);
+ },
+ };
return (
{
- if (visibleParams === visible) return;
- setVisible(visibleParams);
- }}
- onVisibleChange={(visibleParams) => {
- if (visibleParams === visible) return;
- setVisible(visibleParams);
- }}
+ {...drawerOpenProps}
getPopupContainer={popoverProps?.getPopupContainer}
getTooltipContainer={popoverProps?.getTooltipContainer}
content={wrapSSR(
diff --git a/packages/utils/src/index.tsx b/packages/utils/src/index.tsx
index ba922d418fd8..c9f6805788dd 100644
--- a/packages/utils/src/index.tsx
+++ b/packages/utils/src/index.tsx
@@ -75,6 +75,7 @@ import { editableRowByKey, recordKeyToString, useEditableArray } from './useEdit
import type { UseEditableMapType, UseEditableMapUtilType } from './useEditableMap';
import { useEditableMap } from './useEditableMap';
import { useMountMergeState } from './useMountMergeState';
+import { compareVersions } from './compareVersions';
export type {
SearchConvertKeyFn,
@@ -146,6 +147,7 @@ export {
nanoid,
editableRowByKey,
recordKeyToString,
+ compareVersions,
// hooks
useEditableArray,
useEditableMap,
diff --git a/packages/utils/src/useStyle/index.ts b/packages/utils/src/useStyle/index.ts
index 09fb6eacd6bd..f81e0f6e3889 100644
--- a/packages/utils/src/useStyle/index.ts
+++ b/packages/utils/src/useStyle/index.ts
@@ -2,7 +2,7 @@ import type { CSSInterpolation, CSSObject } from '@ant-design/cssinjs';
import { useStyleRegister } from '@ant-design/cssinjs';
import { TinyColor } from '@ctrl/tinycolor';
-import * as antd from 'antd';
+import { theme as antdTheme, ConfigProvider } from 'antd';
import type React from 'react';
import { useContext } from 'react';
@@ -40,7 +40,7 @@ export type GenerateStyle<
const { useToken } = {
...batToken,
// @ts-ignore
- ...antd.antdTheme,
+ ...(antdTheme || {}),
} as unknown as typeof batToken;
export { useToken };
@@ -92,8 +92,6 @@ export const operationUnit = (token: ProAliasToken): CSSObject => ({
},
});
-const { ConfigProvider } = antd;
-
/**
* 封装了一下 antd 的 useStyle,支持了一下antd@4
* @param componentName {string} 组件的名字
diff --git a/tests/form/drawerForm.test.tsx b/tests/form/drawerForm.test.tsx
index 33652119831d..99538a695773 100644
--- a/tests/form/drawerForm.test.tsx
+++ b/tests/form/drawerForm.test.tsx
@@ -93,7 +93,7 @@ describe('DrawerForm', () => {
it('📦 DrawerForm destroyOnClose', async () => {
const wrapper = render(
-
+
{
act(() => {
wrapper.rerender(
-
+
{
act(() => {
wrapper.rerender(
-
+
{
initialValues={{
name: '1234',
}}
- visible={false}
+ open={false}
trigger={}
>
{
initialValues={{
name: '1234',
}}
- visible={undefined}
+ open={undefined}
trigger={}
>
{
initialValues={{
name: '1234',
}}
- visible={false}
+ open={false}
modalProps={{ destroyOnClose: true }}
onVisibleChange={(visible) => fn(visible)}
>
@@ -215,13 +215,13 @@ describe('ModalForm', () => {
expect(fn).toBeCalledTimes(2);
});
- it('📦 modal visible=true simulate onVisibleChange', async () => {
+ it('📦 modal open=true simulate onVisibleChange', async () => {
const fn = jest.fn();
const wrapper = render(
新建}
- onVisibleChange={(visible) => fn(visible)}
+ onOpenChange={(visible) => fn(visible)}
>
,
diff --git a/tests/form/schemaForm.test.tsx b/tests/form/schemaForm.test.tsx
index bc3829969075..7f456c4cf2a2 100644
--- a/tests/form/schemaForm.test.tsx
+++ b/tests/form/schemaForm.test.tsx
@@ -653,7 +653,7 @@ describe('SchemaForm', () => {
const formRef = React.createRef();
const wrapper = render(