From a5e8915855d14cb2b97a9b3932bd377acedad7a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Mon, 10 Feb 2025 20:28:17 +0800 Subject: [PATCH 1/6] chore: tmp of it --- docs/examples/multiple-Portal.tsx | 3 ++- package.json | 9 ++++----- src/Dialog/Content/index.tsx | 20 ++++++++++++++++---- src/Dialog/Mask.tsx | 2 +- tests/index.spec.tsx | 6 +++--- tests/ref.spec.tsx | 2 +- 6 files changed, 27 insertions(+), 15 deletions(-) diff --git a/docs/examples/multiple-Portal.tsx b/docs/examples/multiple-Portal.tsx index 3ae1c6ea..437dca01 100644 --- a/docs/examples/multiple-Portal.tsx +++ b/docs/examples/multiple-Portal.tsx @@ -24,6 +24,7 @@ const Demo: React.FC = () => { onClose={onToggleDialog} forceRender title="basic modal" + mask={false} >

{dialog} - {drawer} + {/* {drawer} */} ); }; diff --git a/package.json b/package.json index 35225444..d9544240 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.0" }, "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/index.tsx b/src/Dialog/Content/index.tsx index af966a6e..d666a1c5 100644 --- a/src/Dialog/Content/index.tsx +++ b/src/Dialog/Content/index.tsx @@ -1,11 +1,13 @@ 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 Panel from './Panel'; +console.log(CSSMotion); + export type ContentProps = { motionName: string; ariaId: string; @@ -27,7 +29,10 @@ const Content = React.forwardRef((props, ref) => { mousePosition, } = props; - const dialogRef = useRef(); + const dialogRef = useRef<{ + nativeElement: HTMLDivElement; + inMotion: () => boolean; + }>(); // ============================= Style ============================== const [transformOrigin, setTransformOrigin] = React.useState(); @@ -38,7 +43,8 @@ const Content = React.forwardRef((props, ref) => { } function onPrepare() { - const elementOffset = offset(dialogRef.current); + console.log('onPrepare', dialogRef.current); + const elementOffset = offset(dialogRef.current?.nativeElement); setTransformOrigin( mousePosition && (mousePosition.x || mousePosition.y) @@ -47,6 +53,12 @@ const Content = React.forwardRef((props, ref) => { ); } + const bbb = React.useCallback((aaa) => { + console.log('???', aaa); + dialogRef.current = aaa; + }, []); + console.log('render....'); + // ============================= Render ============================= return ( ((props, ref) => { forceRender={forceRender} motionName={motionName} removeOnLeave={destroyOnClose} - ref={dialogRef} + ref={bbb} > {({ className: motionClassName, style: motionStyle }, motionRef) => ( { +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) => { 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'; From 43adf5233800d8eb22bce1174e8f3694fed0f042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Tue, 11 Feb 2025 17:00:28 +0800 Subject: [PATCH 2/6] fix: motion lock --- docs/examples/multiple-Portal.tsx | 13 +++++++- package.json | 2 +- src/Dialog/Content/Panel.tsx | 4 +-- src/Dialog/Content/index.tsx | 29 ++++++++++-------- src/Dialog/index.tsx | 49 +++++++++++++++++++------------ tests/index.spec.tsx | 11 +++++-- 6 files changed, 72 insertions(+), 36 deletions(-) diff --git a/docs/examples/multiple-Portal.tsx b/docs/examples/multiple-Portal.tsx index 437dca01..2a8fe210 100644 --- a/docs/examples/multiple-Portal.tsx +++ b/docs/examples/multiple-Portal.tsx @@ -46,8 +46,19 @@ const Demo: React.FC = () => { + {dialog} - {/* {drawer} */} + {drawer} ); }; diff --git a/package.json b/package.json index d9544240..32cba92b 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "@rc-component/portal": "^1.0.0-8", "@rc-component/util": "^1.0.1", "classnames": "^2.2.6", - "@rc-component/motion": "^1.1.0" + "@rc-component/motion": "^1.1.3" }, "devDependencies": { "@rc-component/father-plugin": "^2.0.2", 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 d666a1c5..be029e3a 100644 --- a/src/Dialog/Content/index.tsx +++ b/src/Dialog/Content/index.tsx @@ -3,10 +3,13 @@ import { useRef } from 'react'; import classNames from 'classnames'; 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'; -console.log(CSSMotion); +export type ContentRef = PanelRef & { + inMotion: () => boolean; + enableMotion: () => boolean; +}; export type ContentProps = { motionName: string; @@ -34,6 +37,15 @@ const Content = React.forwardRef((props, ref) => { inMotion: () => boolean; }>(); + const panelRef = useRef(); + + // ============================== Refs ============================== + React.useImperativeHandle(ref, () => ({ + ...panelRef.current, + inMotion: dialogRef.current.inMotion, + enableMotion: dialogRef.current.enableMotion, + })); + // ============================= Style ============================== const [transformOrigin, setTransformOrigin] = React.useState(); const contentStyle: React.CSSProperties = {}; @@ -43,8 +55,7 @@ const Content = React.forwardRef((props, ref) => { } function onPrepare() { - console.log('onPrepare', dialogRef.current); - const elementOffset = offset(dialogRef.current?.nativeElement); + const elementOffset = offset(dialogRef.current.nativeElement); setTransformOrigin( mousePosition && (mousePosition.x || mousePosition.y) @@ -53,12 +64,6 @@ const Content = React.forwardRef((props, ref) => { ); } - const bbb = React.useCallback((aaa) => { - console.log('???', aaa); - dialogRef.current = aaa; - }, []); - console.log('render....'); - // ============================= Render ============================= return ( ((props, ref) => { forceRender={forceRender} motionName={motionName} removeOnLeave={destroyOnClose} - ref={bbb} + ref={dialogRef} > {({ 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?.(); - } + console.log('hide???'); + doClose(); } afterOpenChange?.(newVisible); } @@ -154,6 +161,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 6d5aba26..62ba47f1 100644 --- a/tests/index.spec.tsx +++ b/tests/index.spec.tsx @@ -515,10 +515,17 @@ describe('dialog', () => { const afterClose = jest.fn(); const { rerender } = render(

); - jest.runAllTimers(); + act(() => { + jest.runAllTimers(); + }); + console.log('~~~~~~false~~~~~~'); rerender(); - jest.runAllTimers(); + console.log('~~~~~~111~~~~~~'); + act(() => { + jest.runAllTimers(); + }); + console.log('~~~~~~222~~~~~~'); expect(afterClose).toHaveBeenCalledTimes(1); }); From f496b4c0a37859882e398751b06d6e57c0618a64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Tue, 11 Feb 2025 17:02:41 +0800 Subject: [PATCH 3/6] chore: revert demo --- docs/examples/multiple-Portal.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/examples/multiple-Portal.tsx b/docs/examples/multiple-Portal.tsx index 2a8fe210..91246734 100644 --- a/docs/examples/multiple-Portal.tsx +++ b/docs/examples/multiple-Portal.tsx @@ -24,7 +24,6 @@ const Demo: React.FC = () => { onClose={onToggleDialog} forceRender title="basic modal" - mask={false} >