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) => {
       >