diff --git a/.fatherrc.js b/.fatherrc.js index 558df7ee..4ddbafd1 100644 --- a/.fatherrc.js +++ b/.fatherrc.js @@ -1,9 +1,5 @@ -export default { - cjs: 'babel', - esm: { type: 'babel', importLibToEs: true }, - preCommit: { - eslint: true, - prettier: true, - }, - runtimeHelpers: true, -}; \ No newline at end of file +import { defineConfig } from 'father'; + +export default defineConfig({ + plugins: ['@rc-component/father-plugin'], +}); \ No newline at end of file diff --git a/package.json b/package.json index 53ec4333..a0486a8b 100644 --- a/package.json +++ b/package.json @@ -15,43 +15,40 @@ "drawer-animation" ], "homepage": "https://github.com/react-component/drawer", - "author": "155259966@qq.com", + "bugs": { + "url": "https://github.com/react-component/drawer/issues" + }, "repository": { "type": "git", "url": "https://github.com/react-component/drawer.git" }, - "bugs": { - "url": "https://github.com/react-component/drawer/issues" - }, + "license": "MIT", + "author": "155259966@qq.com", + "main": "./lib/index", + "module": "./es/index", "files": [ "lib", "assets/*.css", "es" ], - "license": "MIT", - "main": "./lib/index", - "module": "./es/index", "scripts": { - "start": "dumi dev", "build": "dumi build", - "compile": "father-build && lessc assets/index.less assets/index.css", - "prepublishOnly": "npm run compile && np --no-cleanup --yolo --no-publish", + "compile": "father build && lessc assets/index.less assets/index.css", "lint": "eslint src/ --ext .tsx,.ts", - "test": "umi-test", - "now-build": "npm run build" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" + "now-build": "npm run build", + "prepublishOnly": "npm run compile && np --no-cleanup --yolo --no-publish", + "start": "dumi dev", + "test": "rc-test" }, "dependencies": { "@babel/runtime": "^7.10.1", "@rc-component/portal": "^1.1.1", "classnames": "^2.2.6", "rc-motion": "^2.6.1", - "rc-util": "^5.21.2" + "rc-util": "^5.36.0" }, "devDependencies": { + "@rc-component/father-plugin": "^1.0.0", "@ant-design/icons": "^4.7.0", "@testing-library/jest-dom": "^5.11.9", "@testing-library/react": "^14.0.0", @@ -61,19 +58,21 @@ "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", "@types/warning": "^3.0.0", - "@umijs/fabric": "^2.0.0", - "@umijs/test": "^3.5.23", + "rc-test": "^7.0.9", "antd": "^4.20.2", "dumi": "^2.2.0", "eslint": "^7.0.0", - "father": "^2.30.21", - "father-build": "^1.22.1", + "father": "^4.0.0", "glob": "^7.1.6", "less": "^3.10.3", "np": "^7.5.0", - "prettier": "^2.6.2", + "prettier": "^3.0.0", "react": "^18.0.0", "react-dom": "^18.0.0", "typescript": "^4.6.4" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" } } diff --git a/src/Drawer.tsx b/src/Drawer.tsx index 4879e150..70210dcd 100644 --- a/src/Drawer.tsx +++ b/src/Drawer.tsx @@ -1,21 +1,24 @@ -import * as React from 'react'; -import Portal from '@rc-component/portal'; import type { PortalProps } from '@rc-component/portal'; +import Portal from '@rc-component/portal'; import useLayoutEffect from 'rc-util/lib/hooks/useLayoutEffect'; -import DrawerPopup from './DrawerPopup'; +import * as React from 'react'; +import { RefContext } from './context'; +import type { DrawerPanelEvents } from './DrawerPanel'; import type { DrawerPopupProps } from './DrawerPopup'; +import DrawerPopup from './DrawerPopup'; import { warnCheck } from './util'; -import type { DrawerPanelEvents } from './DrawerPanel'; export type Placement = 'left' | 'top' | 'right' | 'bottom'; export interface DrawerProps - extends Omit, DrawerPanelEvents { + extends Omit, + DrawerPanelEvents { prefixCls?: string; open?: boolean; onClose?: (e: React.MouseEvent | React.KeyboardEvent) => void; destroyOnClose?: boolean; getContainer?: PortalProps['getContainer']; + panelRef?: React.Ref; } const Drawer: React.FC = props => { @@ -38,6 +41,9 @@ const Drawer: React.FC = props => { onClick, onKeyDown, onKeyUp, + + // Refs + panelRef, } = props; const [animatedVisible, setAnimatedVisible] = React.useState(false); @@ -57,7 +63,7 @@ const Drawer: React.FC = props => { const mergedOpen = mounted ? open : false; // ============================ Focus ============================= - const panelRef = React.useRef(); + const popupRef = React.useRef(); const lastActiveRef = React.useRef(); useLayoutEffect(() => { @@ -75,12 +81,20 @@ const Drawer: React.FC = props => { if ( !nextVisible && lastActiveRef.current && - !panelRef.current?.contains(lastActiveRef.current) + !popupRef.current?.contains(lastActiveRef.current) ) { lastActiveRef.current?.focus({ preventScroll: true }); } }; + // =========================== Context ============================ + const refContext = React.useMemo( + () => ({ + panel: panelRef, + }), + [panelRef], + ); + // ============================ Render ============================ if (!forceRender && !animatedVisible && !mergedOpen && destroyOnClose) { return null; @@ -106,19 +120,21 @@ const Drawer: React.FC = props => { maskClosable, inline: getContainer === false, afterOpenChange: internalAfterOpenChange, - ref: panelRef, + ref: popupRef, ...eventHandlers, }; return ( - - - + + + + + ); }; diff --git a/src/DrawerPanel.tsx b/src/DrawerPanel.tsx index f668f8c0..2e19d765 100644 --- a/src/DrawerPanel.tsx +++ b/src/DrawerPanel.tsx @@ -1,5 +1,7 @@ import classNames from 'classnames'; +import { useComposeRef } from 'rc-util'; import * as React from 'react'; +import { RefContext } from './context'; export interface DrawerPanelRef { focus: VoidFunction; @@ -48,6 +50,9 @@ const DrawerPanel = (props: DrawerPanelProps) => { onKeyUp, }; + const { panel: panelRef } = React.useContext(RefContext); + const mergedRef = useComposeRef(panelRef, containerRef); + // =============================== Render =============================== return ( @@ -60,7 +65,7 @@ const DrawerPanel = (props: DrawerPanelProps) => { }} aria-modal="true" role="dialog" - ref={containerRef} + ref={mergedRef} {...eventHandlers} > {children} diff --git a/src/context.ts b/src/context.ts index 010335ae..1a054089 100644 --- a/src/context.ts +++ b/src/context.ts @@ -8,4 +8,10 @@ export interface DrawerContextProps { const DrawerContext = React.createContext(null); +export interface RefContextProps { + panel?: React.Ref; +} + +export const RefContext = React.createContext({}); + export default DrawerContext; diff --git a/tests/ref.spec.tsx b/tests/ref.spec.tsx new file mode 100755 index 00000000..ec1c8cff --- /dev/null +++ b/tests/ref.spec.tsx @@ -0,0 +1,25 @@ +import { act, cleanup, render } from '@testing-library/react'; +import React from 'react'; +import Drawer from '../src'; + +describe('Drawer.ref', () => { + beforeEach(() => { + jest.useFakeTimers(); + }); + + afterEach(() => { + jest.useRealTimers(); + cleanup(); + }); + + it('support panelRef', () => { + const panelRef = React.createRef(); + render(); + + act(() => { + jest.runAllTimers(); + }); + + expect(panelRef.current).toHaveClass('rc-drawer-content'); + }); +});