diff --git a/docs/examples/multiple-Portal.tsx b/docs/examples/multiple-Portal.tsx
index 3ae1c6ea..91246734 100644
--- a/docs/examples/multiple-Portal.tsx
+++ b/docs/examples/multiple-Portal.tsx
@@ -45,6 +45,17 @@ const Demo: React.FC = () => {
+
{dialog}
{drawer}
diff --git a/package.json b/package.json
index 35225444..32cba92b 100644
--- a/package.json
+++ b/package.json
@@ -37,7 +37,7 @@
"lint:tsc": "tsc -p tsconfig.json --noEmit",
"now-build": "npm run docs:build",
"prepare": "husky install",
- "prepublishOnly": "npm run compile && np --yolo --no-publish",
+ "prepublishOnly": "npm run compile && rc-np",
"prettier": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"",
"start": "dumi dev",
"test": "rc-test"
@@ -49,14 +49,14 @@
]
},
"dependencies": {
- "@babel/runtime": "^7.10.1",
"@rc-component/portal": "^1.0.0-8",
"@rc-component/util": "^1.0.1",
"classnames": "^2.2.6",
- "rc-motion": "^2.3.0"
+ "@rc-component/motion": "^1.1.3"
},
"devDependencies": {
- "@rc-component/father-plugin": "^2.0.1",
+ "@rc-component/father-plugin": "^2.0.2",
+ "@rc-component/np": "^1.0.3",
"@testing-library/jest-dom": "^6.1.6",
"@testing-library/react": "^13.0.0",
"@types/jest": "^29.4.0",
@@ -77,7 +77,6 @@
"husky": "^8.0.3",
"less": "^4.1.3",
"lint-staged": "^15.2.0",
- "np": "^10.0.5",
"prettier": "^3.2.1",
"rc-drawer": "^7.0.0",
"rc-select": "^14.11.0",
diff --git a/src/Dialog/Content/Panel.tsx b/src/Dialog/Content/Panel.tsx
index 8e2cfb1f..2439fe7f 100644
--- a/src/Dialog/Content/Panel.tsx
+++ b/src/Dialog/Content/Panel.tsx
@@ -17,12 +17,12 @@ export interface PanelProps extends Omit {
holderRef?: React.Ref;
}
-export type ContentRef = {
+export type PanelRef = {
focus: () => void;
changeActive: (next: boolean) => void;
};
-const Panel = React.forwardRef((props, ref) => {
+const Panel = React.forwardRef((props, ref) => {
const {
prefixCls,
className,
diff --git a/src/Dialog/Content/index.tsx b/src/Dialog/Content/index.tsx
index af966a6e..4985a194 100644
--- a/src/Dialog/Content/index.tsx
+++ b/src/Dialog/Content/index.tsx
@@ -1,10 +1,15 @@
import * as React from 'react';
import { useRef } from 'react';
import classNames from 'classnames';
-import CSSMotion from 'rc-motion';
+import CSSMotion from '@rc-component/motion';
import { offset } from '../../util';
-import type { PanelProps, ContentRef } from './Panel';
+import type { PanelProps, PanelRef } from './Panel';
import Panel from './Panel';
+import type { CSSMotionRef } from '@rc-component/motion/es/CSSMotion';
+
+export type CSSMotionStateRef = Pick;
+
+export type ContentRef = PanelRef & CSSMotionStateRef;
export type ContentProps = {
motionName: string;
@@ -27,7 +32,20 @@ const Content = React.forwardRef((props, ref) => {
mousePosition,
} = props;
- const dialogRef = useRef();
+ const dialogRef = useRef<
+ {
+ nativeElement: HTMLElement;
+ } & CSSMotionStateRef
+ >();
+
+ const panelRef = useRef();
+
+ // ============================== Refs ==============================
+ React.useImperativeHandle(ref, () => ({
+ ...panelRef.current,
+ inMotion: dialogRef.current.inMotion,
+ enableMotion: dialogRef.current.enableMotion,
+ }));
// ============================= Style ==============================
const [transformOrigin, setTransformOrigin] = React.useState();
@@ -38,7 +56,7 @@ const Content = React.forwardRef((props, ref) => {
}
function onPrepare() {
- const elementOffset = offset(dialogRef.current);
+ const elementOffset = offset(dialogRef.current.nativeElement);
setTransformOrigin(
mousePosition && (mousePosition.x || mousePosition.y)
@@ -62,7 +80,7 @@ const Content = React.forwardRef((props, ref) => {
{({ className: motionClassName, style: motionStyle }, motionRef) => (
= (props) => {
}
// ========================= Events =========================
+ // Close action will trigger by:
+ // 1. When hide motion end
+ // 2. Controlled `open` to `false` immediately after set to `true` which will not trigger motion
+ function doClose() {
+ // Clean up scroll bar & focus back
+ setAnimatedVisible(false);
+
+ if (mask && lastOutSideActiveElementRef.current && focusTriggerAfterClose) {
+ try {
+ lastOutSideActiveElementRef.current.focus({ preventScroll: true });
+ } catch (e) {
+ // Do nothing
+ }
+ lastOutSideActiveElementRef.current = null;
+ }
+
+ // Trigger afterClose only when change visible from true to false
+ if (animatedVisible) {
+ afterClose?.();
+ }
+ }
+
function onDialogVisibleChanged(newVisible: boolean) {
// Try to focus
if (newVisible) {
focusDialogContent();
} else {
- // Clean up scroll bar & focus back
- setAnimatedVisible(false);
-
- if (mask && lastOutSideActiveElementRef.current && focusTriggerAfterClose) {
- try {
- lastOutSideActiveElementRef.current.focus({ preventScroll: true });
- } catch (e) {
- // Do nothing
- }
- lastOutSideActiveElementRef.current = null;
- }
-
- // Trigger afterClose only when change visible from true to false
- if (animatedVisible) {
- afterClose?.();
- }
+ doClose();
}
afterOpenChange?.(newVisible);
}
@@ -154,6 +160,12 @@ const Dialog: React.FC = (props) => {
if (visible) {
setAnimatedVisible(true);
saveLastOutSideActiveElementRef();
+ } else if (
+ animatedVisible &&
+ contentRef.current.enableMotion() &&
+ !contentRef.current.inMotion()
+ ) {
+ doClose();
}
}, [visible]);
diff --git a/tests/index.spec.tsx b/tests/index.spec.tsx
index f160d3ac..e54f0def 100644
--- a/tests/index.spec.tsx
+++ b/tests/index.spec.tsx
@@ -1,14 +1,14 @@
/* eslint-disable react/no-render-return-value, max-classes-per-file, func-names, no-console */
import { fireEvent, render, act } from '@testing-library/react';
-import { Provider } from 'rc-motion';
+import { Provider } from '@rc-component/motion';
import KeyCode from '@rc-component/util/lib/KeyCode';
import React, { cloneElement, useEffect } from 'react';
import type { DialogProps } from '../src';
import Dialog from '../src';
-jest.mock('rc-motion', () => {
+jest.mock('@rc-component/motion', () => {
const OriReact = jest.requireActual('react');
- const origin = jest.requireActual('rc-motion');
+ const origin = jest.requireActual('@rc-component/motion');
const OriCSSMotion = origin.default;
const ProxyCSSMotion = OriReact.forwardRef((props: any, ref: any) => {
@@ -515,10 +515,14 @@ describe('dialog', () => {
const afterClose = jest.fn();
const { rerender } = render();
- jest.runAllTimers();
+ act(() => {
+ jest.runAllTimers();
+ });
rerender();
- jest.runAllTimers();
+ act(() => {
+ jest.runAllTimers();
+ });
expect(afterClose).toHaveBeenCalledTimes(1);
});
diff --git a/tests/ref.spec.tsx b/tests/ref.spec.tsx
index d8e37e8c..368846f6 100644
--- a/tests/ref.spec.tsx
+++ b/tests/ref.spec.tsx
@@ -1,6 +1,6 @@
/* eslint-disable react/no-render-return-value, max-classes-per-file, func-names, no-console */
import { render } from '@testing-library/react';
-import { Provider } from 'rc-motion';
+import { Provider } from '@rc-component/motion';
import React from 'react';
import Dialog from '../src';