From 5d6312049993a07e0c928f4dc1a1500f4fcd4ee7 Mon Sep 17 00:00:00 2001
From: Jianan Li
Date: Sun, 18 May 2025 11:23:14 +0800
Subject: [PATCH 1/4] update destroyOnClose to destroyOnHidden
---
.gitignore | 3 +-
README.md | 59 +++++++++++++++++-------------------
docs/examples/ant-design.tsx | 10 +++---
docs/examples/bootstrap.tsx | 10 +++---
package.json | 7 +++--
src/Dialog/Content/Panel.tsx | 16 +++++++---
src/Dialog/Content/index.tsx | 16 +++++-----
src/Dialog/index.tsx | 8 ++---
src/DialogWrap.tsx | 6 ++--
src/IDialogPropTypes.tsx | 2 +-
tests/index.spec.tsx | 10 +++---
11 files changed, 76 insertions(+), 71 deletions(-)
diff --git a/.gitignore b/.gitignore
index 41ad2dce..a3cbef29 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,6 +34,7 @@ coverage
/android/
yarn.lock
package-lock.json
+pnpm-lock.yaml
.storybook
.doc
@@ -48,4 +49,4 @@ package-lock.json
.dumi/tmp
.dumi/tmp-production
-bun.lockb
\ No newline at end of file
+bun.lockb
diff --git a/README.md b/README.md
index 6d45b458..087792a5 100644
--- a/README.md
+++ b/README.md
@@ -49,34 +49,34 @@ ReactDOM.render(
### rc-dialog
-| Name | Type | Default | Description | Version |
-| ---------------------- | ------------------------------ | --------- | ------------------------------------------------------------------------------- | ------- |
-| prefixCls | String | rc-dialog | The dialog dom node's prefixCls | |
-| className | String | | additional className for dialog | |
-| classNames | { header?: string; body?: string; footer?: string; mask?: string; content?: string; wrapper?: string; } | | pass className to target area | |
-| styles | { header?: CSSProperties; body?: CSSProperties; footer?: CSSProperties; mask?: CSSProperties; content?: CSSProperties; wrapper?: CSSProperties; } | | pass styles to target area | |
-| style | Object | {} | Root style for dialog element.Such as width, height | |
-| zIndex | Number | | | |
-| visible | Boolean | false | current dialog's visible status | |
-| animation | String | | part of dialog animation css class name | |
-| maskAnimation | String | | part of dialog's mask animation css class name | |
-| transitionName | String | | dialog animation css class name | |
-| maskTransitionName | String | | mask animation css class name | |
-| title | String\|React.Element | | Title of the dialog | |
-| footer | React.Element | | footer of the dialog | |
-| closable | Boolean \| ({ closeIcon?: React.ReactNode; disabled?: boolean } & React.AriaAttributes | true | whether show close button | |
-| mask | Boolean | true | whether show mask | |
-| maskClosable | Boolean | true | whether click mask to close | |
-| keyboard | Boolean | true | whether support press esc to close | |
-| mousePosition | {x:number,y:number} | | set pageX and pageY of current mouse(it will cause transform origin to be set). | |
-| onClose | function() | | called when click close button or mask | |
-| afterClose | function() | | called when close animation end | |
-| getContainer | function(): HTMLElement | | to determine where Dialog will be mounted | |
-| destroyOnClose | Boolean | false | to unmount child compenents on onClose | |
-| closeIcon | ReactNode | | specific the close icon. | |
-| forceRender | Boolean | false | Create dialog dom node before dialog first show | |
-| focusTriggerAfterClose | Boolean | true | focus trigger element when dialog closed | |
-| modalRender | (node: ReactNode) => ReactNode | | Custom modal content render | 8.3.0 |
+| Name | Type | Default | Description | Version |
+| --- | --- | --- | --- | --- |
+| prefixCls | String | rc-dialog | The dialog dom node's prefixCls | |
+| className | String | | additional className for dialog | |
+| classNames | { header?: string; body?: string; footer?: string; mask?: string; content?: string; wrapper?: string; } | | pass className to target area | |
+| styles | { header?: CSSProperties; body?: CSSProperties; footer?: CSSProperties; mask?: CSSProperties; content?: CSSProperties; wrapper?: CSSProperties; } | | pass styles to target area | |
+| style | Object | {} | Root style for dialog element.Such as width, height | |
+| zIndex | Number | | | |
+| visible | Boolean | false | current dialog's visible status | |
+| animation | String | | part of dialog animation css class name | |
+| maskAnimation | String | | part of dialog's mask animation css class name | |
+| transitionName | String | | dialog animation css class name | |
+| maskTransitionName | String | | mask animation css class name | |
+| title | String\|React.Element | | Title of the dialog | |
+| footer | React.Element | | footer of the dialog | |
+| closable | Boolean \| ({ closeIcon?: React.ReactNode; disabled?: boolean } & React.AriaAttributes | true | whether show close button | |
+| mask | Boolean | true | whether show mask | |
+| maskClosable | Boolean | true | whether click mask to close | |
+| keyboard | Boolean | true | whether support press esc to close | |
+| mousePosition | {x:number,y:number} | | set pageX and pageY of current mouse(it will cause transform origin to be set). | |
+| onClose | function() | | called when click close button or mask | |
+| afterClose | function() | | called when close animation end | |
+| getContainer | function(): HTMLElement | | to determine where Dialog will be mounted | |
+| destroyOnHidden | Boolean | false | to unmount child compenents on onClose | |
+| closeIcon | ReactNode | | specific the close icon. | |
+| forceRender | Boolean | false | Create dialog dom node before dialog first show | |
+| focusTriggerAfterClose | Boolean | true | focus trigger element when dialog closed | |
+| modalRender | (node: ReactNode) => ReactNode | | Custom modal content render | 8.3.0 |
## Development
@@ -85,8 +85,6 @@ npm install
npm start
```
-
-
## Test Case
```
@@ -102,7 +100,6 @@ npm run coverage
open coverage/ dir
-
## License
rc-dialog is released under the MIT license.
diff --git a/docs/examples/ant-design.tsx b/docs/examples/ant-design.tsx
index d1ffab74..0030fd48 100644
--- a/docs/examples/ant-design.tsx
+++ b/docs/examples/ant-design.tsx
@@ -31,7 +31,7 @@ const MyControl: React.FC = () => {
const [visible2, setVisible2] = React.useState(false);
const [visible3, setVisible3] = React.useState(false);
const [width, setWidth] = React.useState(600);
- const [destroyOnClose, setDestroyOnClose] = React.useState(false);
+ const [destroyOnHidden, setDestroyOnHidden] = React.useState(false);
const [center, setCenter] = React.useState(false);
const [mousePosition, setMousePosition] = React.useState({ x: null, y: null });
const [useIcon, setUseIcon] = React.useState(false);
@@ -60,8 +60,8 @@ const MyControl: React.FC = () => {
setVisible3(false);
};
- const onDestroyOnCloseChange = (e: React.ChangeEvent) => {
- setDestroyOnClose(e.target.checked);
+ const onDestroyOnHiddenChange = (e: React.ChangeEvent) => {
+ setDestroyOnHidden(e.target.checked);
};
const onForceRenderChange = (e: React.ChangeEvent) => {
@@ -97,7 +97,7 @@ const MyControl: React.FC = () => {
style={style}
title="dialog1"
mousePosition={mousePosition}
- destroyOnClose={destroyOnClose}
+ destroyOnHidden={destroyOnHidden}
closeIcon={useIcon ? getSvg(clearPath, {}, true) : undefined}
forceRender={forceRender}
focusTriggerAfterClose={false}
@@ -211,7 +211,7 @@ const MyControl: React.FC = () => {
{dialog}
diff --git a/package.json b/package.json
index d1d6575b..35eadb99 100644
--- a/package.json
+++ b/package.json
@@ -57,15 +57,16 @@
},
"devDependencies": {
"@rc-component/drawer": "^1.0.0",
- "@rc-component/select": "^1.0.0",
"@rc-component/father-plugin": "^2.0.2",
"@rc-component/np": "^1.0.3",
+ "@rc-component/select": "^1.0.0",
"@testing-library/jest-dom": "^6.1.6",
"@testing-library/react": "^13.0.0",
"@types/jest": "^29.4.0",
"@types/keyv": "3.1.4",
- "@types/react": "^18.0.24",
- "@types/react-dom": "^18.0.8",
+ "@types/node": "^22.15.18",
+ "@types/react": "^19.1.4",
+ "@types/react-dom": "^19.1.5",
"@umijs/fabric": "^3.0.0",
"bootstrap": "^4.3.1",
"cheerio": "1.0.0-rc.12",
diff --git a/src/Dialog/Content/Panel.tsx b/src/Dialog/Content/Panel.tsx
index 2439fe7f..e06678c4 100644
--- a/src/Dialog/Content/Panel.tsx
+++ b/src/Dialog/Content/Panel.tsx
@@ -6,8 +6,16 @@ import type { IDialogPropTypes } from '../../IDialogPropTypes';
import MemoChildren from './MemoChildren';
import pickAttrs from '@rc-component/util/lib/pickAttrs';
-const sentinelStyle = { width: 0, height: 0, overflow: 'hidden', outline: 'none' };
-const entityStyle = { outline: 'none' };
+const sentinelStyle: React.CSSProperties = {
+ width: 0,
+ height: 0,
+ overflow: 'hidden',
+ outline: 'none',
+};
+
+const entityStyle: React.CSSProperties = {
+ outline: 'none',
+};
export interface PanelProps extends Omit {
prefixCls: string;
@@ -53,8 +61,8 @@ const Panel = React.forwardRef((props, ref) => {
const mergedRef = useComposeRef(holderRef, panelRef);
- const sentinelStartRef = useRef();
- const sentinelEndRef = useRef();
+ const sentinelStartRef = useRef(null);
+ const sentinelEndRef = useRef(null);
React.useImperativeHandle(ref, () => ({
focus: () => {
diff --git a/src/Dialog/Content/index.tsx b/src/Dialog/Content/index.tsx
index 4985a194..df6a97ea 100644
--- a/src/Dialog/Content/index.tsx
+++ b/src/Dialog/Content/index.tsx
@@ -25,20 +25,16 @@ const Content = React.forwardRef((props, ref) => {
className,
visible,
forceRender,
- destroyOnClose,
+ destroyOnHidden,
motionName,
ariaId,
onVisibleChanged,
mousePosition,
} = props;
- const dialogRef = useRef<
- {
- nativeElement: HTMLElement;
- } & CSSMotionStateRef
- >();
+ const dialogRef = useRef<{ nativeElement: HTMLElement } & CSSMotionStateRef>(null);
- const panelRef = useRef();
+ const panelRef = useRef(null);
// ============================== Refs ==============================
React.useImperativeHandle(ref, () => ({
@@ -74,7 +70,7 @@ const Content = React.forwardRef((props, ref) => {
onEnterPrepare={onPrepare}
forceRender={forceRender}
motionName={motionName}
- removeOnLeave={destroyOnClose}
+ removeOnLeave={destroyOnHidden}
ref={dialogRef}
>
{({ className: motionClassName, style: motionStyle }, motionRef) => (
@@ -93,6 +89,8 @@ const Content = React.forwardRef((props, ref) => {
);
});
-Content.displayName = 'Content';
+if (process.env.NODE_ENV !== 'production') {
+ Content.displayName = 'Content';
+}
export default Content;
diff --git a/src/Dialog/index.tsx b/src/Dialog/index.tsx
index 5f417657..3512e772 100644
--- a/src/Dialog/index.tsx
+++ b/src/Dialog/index.tsx
@@ -55,9 +55,9 @@ const Dialog: React.FC = (props) => {
}
}
- const lastOutSideActiveElementRef = useRef();
- const wrapperRef = useRef();
- const contentRef = useRef();
+ const lastOutSideActiveElementRef = useRef(null);
+ const wrapperRef = useRef(null);
+ const contentRef = useRef(null);
const [animatedVisible, setAnimatedVisible] = React.useState(visible);
@@ -115,7 +115,7 @@ const Dialog: React.FC = (props) => {
// >>> Content
const contentClickRef = useRef(false);
- const contentTimeoutRef = useRef>();
+ const contentTimeoutRef = useRef>(null);
// We need record content click incase content popup out of dialog
const onContentMouseDown: React.MouseEventHandler = () => {
diff --git a/src/DialogWrap.tsx b/src/DialogWrap.tsx
index 7d84fc4d..4fb31734 100644
--- a/src/DialogWrap.tsx
+++ b/src/DialogWrap.tsx
@@ -18,7 +18,7 @@ const DialogWrap: React.FC = (props) => {
visible,
getContainer,
forceRender,
- destroyOnClose = false,
+ destroyOnHidden = false,
afterClose,
panelRef,
} = props;
@@ -33,7 +33,7 @@ const DialogWrap: React.FC = (props) => {
}, [visible]);
// Destroy on close will remove wrapped div
- if (!forceRender && destroyOnClose && !animatedVisible) {
+ if (!forceRender && destroyOnHidden && !animatedVisible) {
return null;
}
@@ -47,7 +47,7 @@ const DialogWrap: React.FC = (props) => {
>