From cde0449c77051e43cd084be792c18de48e4c1a62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E7=88=B1=E5=90=83=E7=99=BD=E8=90=9D?= =?UTF-8?q?=E5=8D=9C?= Date: Tue, 14 Mar 2023 17:01:37 +0800 Subject: [PATCH 01/23] fix: SSR should not break (#409) * test: driven * test: test driven * fix: ssr should not break * chore: clean up --- package.json | 10 +++++----- src/Drawer.tsx | 19 ++++++++++++------ tests/ssr.spec.tsx | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 11 deletions(-) create mode 100755 tests/ssr.spec.tsx diff --git a/package.json b/package.json index c0e77bf..4cdcfcf 100644 --- a/package.json +++ b/package.json @@ -54,12 +54,12 @@ "devDependencies": { "@ant-design/icons": "^4.7.0", "@testing-library/jest-dom": "^5.11.9", - "@testing-library/react": "^12.1.5", + "@testing-library/react": "^13.0.0", "@types/classnames": "^2.2.9", "@types/jest": "^27.0.2", "@types/raf": "^3.4.0", - "@types/react": "^17.0.9", - "@types/react-dom": "^17.0.6", + "@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", @@ -72,8 +72,8 @@ "less": "^3.10.3", "np": "^7.5.0", "prettier": "^2.6.2", - "react": "^16.10.2", - "react-dom": "^16.10.2", + "react": "^18.0.0", + "react-dom": "^18.0.0", "typescript": "^4.6.4" } } diff --git a/src/Drawer.tsx b/src/Drawer.tsx index 8c528b0..9cff779 100644 --- a/src/Drawer.tsx +++ b/src/Drawer.tsx @@ -40,15 +40,22 @@ const Drawer: React.FC = props => { warnCheck(props); } + // ============================= Open ============================= + const [internalOpen, setInternalOpen] = React.useState(false); + + useLayoutEffect(() => { + setInternalOpen(open); + }, [open]); + // ============================ Focus ============================= const panelRef = React.useRef(); const lastActiveRef = React.useRef(); useLayoutEffect(() => { - if (open) { + if (internalOpen) { lastActiveRef.current = document.activeElement as HTMLElement; } - }, [open]); + }, [internalOpen]); // ============================= Open ============================= const internalAfterOpenChange: DrawerProps['afterOpenChange'] = @@ -66,13 +73,13 @@ const Drawer: React.FC = props => { }; // ============================ Render ============================ - if (!forceRender && !animatedVisible && !open && destroyOnClose) { + if (!forceRender && !animatedVisible && !internalOpen && destroyOnClose) { return null; } const drawerPopupProps = { ...props, - open, + open: internalOpen, prefixCls, placement, autoFocus, @@ -87,10 +94,10 @@ const Drawer: React.FC = props => { return ( diff --git a/tests/ssr.spec.tsx b/tests/ssr.spec.tsx new file mode 100755 index 0000000..4b6039d --- /dev/null +++ b/tests/ssr.spec.tsx @@ -0,0 +1,50 @@ +import { render } from '@testing-library/react'; +import { renderToString } from 'react-dom/server'; +import React from 'react'; +import Drawer from '../src'; +// import canUseDom from 'rc-util/lib/Dom/canUseDom' + +global.canUseDom = true; + +jest.mock('rc-util/lib/Dom/canUseDom', () => { + // const canUseDom = jest.requireActual('rc-util/lib/Dom/canUseDom'); + return () => global.canUseDom; +}); + +describe('SSR', () => { + beforeEach(() => { + global.canUseDom = true; + jest.useFakeTimers(); + }); + + afterEach(() => { + jest.useRealTimers(); + }); + + it('hydrate should not crash', () => { + const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + + const Demo = () => ( + +
+ + ); + + global.canUseDom = false; + const html = renderToString(); + + expect(html).toBeFalsy(); + + global.canUseDom = true; + + const container = document.createElement('div'); + container.innerHTML = html; + document.body.appendChild(container); + + render(, { container, hydrate: true }); + + expect(errSpy).not.toHaveBeenCalled(); + + errSpy.mockRestore(); + }); +}); From adbc9a1701c48c5a5e789f44da00c26eaa987753 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, 14 Mar 2023 17:02:11 +0800 Subject: [PATCH 02/23] 6.1.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4cdcfcf..2c6aa8d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rc-drawer", - "version": "6.1.3", + "version": "6.1.4", "description": "drawer component for react", "keywords": [ "react", From 4700884636697f3dae60d9e61aa5c7eca8ef9f5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E7=88=B1=E5=90=83=E7=99=BD=E8=90=9D?= =?UTF-8?q?=E5=8D=9C?= Date: Fri, 24 Mar 2023 17:05:27 +0800 Subject: [PATCH 03/23] fix: client render should keep sync (#412) --- src/Drawer.tsx | 20 +++++++++++--------- src/util.ts | 6 ++++++ tests/ssr.spec.tsx | 30 +++++++++++++++++++++++++++++- 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/Drawer.tsx b/src/Drawer.tsx index 9cff779..2d92697 100644 --- a/src/Drawer.tsx +++ b/src/Drawer.tsx @@ -41,21 +41,23 @@ const Drawer: React.FC = props => { } // ============================= Open ============================= - const [internalOpen, setInternalOpen] = React.useState(false); + const [mounted, setMounted] = React.useState(false); useLayoutEffect(() => { - setInternalOpen(open); - }, [open]); + setMounted(true); + }, []); + + const mergedOpen = mounted ? open : false; // ============================ Focus ============================= const panelRef = React.useRef(); const lastActiveRef = React.useRef(); useLayoutEffect(() => { - if (internalOpen) { + if (mergedOpen) { lastActiveRef.current = document.activeElement as HTMLElement; } - }, [internalOpen]); + }, [mergedOpen]); // ============================= Open ============================= const internalAfterOpenChange: DrawerProps['afterOpenChange'] = @@ -73,13 +75,13 @@ const Drawer: React.FC = props => { }; // ============================ Render ============================ - if (!forceRender && !animatedVisible && !internalOpen && destroyOnClose) { + if (!forceRender && !animatedVisible && !mergedOpen && destroyOnClose) { return null; } const drawerPopupProps = { ...props, - open: internalOpen, + open: mergedOpen, prefixCls, placement, autoFocus, @@ -94,10 +96,10 @@ const Drawer: React.FC = props => { return ( diff --git a/src/util.ts b/src/util.ts index 9f8eb22..b28f88c 100644 --- a/src/util.ts +++ b/src/util.ts @@ -1,4 +1,5 @@ import warning from 'rc-util/lib/warning'; +import canUseDom from 'rc-util/lib/Dom/canUseDom'; import type { DrawerProps } from './Drawer'; export function parseWidthHeight(value?: number | string) { @@ -18,4 +19,9 @@ export function warnCheck(props: DrawerProps) { !('wrapperClassName' in props), `'wrapperClassName' is removed. Please use 'rootClassName' instead.`, ); + + warning( + canUseDom() || !props.open, + `Drawer with 'open' in SSR is not work since no place to createPortal. Please move to 'useEffect' instead.`, + ); } diff --git a/tests/ssr.spec.tsx b/tests/ssr.spec.tsx index 4b6039d..af34004 100755 --- a/tests/ssr.spec.tsx +++ b/tests/ssr.spec.tsx @@ -43,8 +43,36 @@ describe('SSR', () => { render(, { container, hydrate: true }); - expect(errSpy).not.toHaveBeenCalled(); + expect(errSpy).toHaveBeenCalledWith( + "Warning: Drawer with 'open' in SSR is not work since no place to createPortal. Please move to 'useEffect' instead.", + ); + expect(errSpy).toBeCalledTimes(1); errSpy.mockRestore(); }); + + // Since we use `useLayoutEffect` to avoid SSR warning. + // This may affect ref call. Let's check this also. + it('should not block ref', done => { + const Demo = ({ open }: any = {}) => { + const ref = React.useRef(); + + React.useEffect(() => { + if (open) { + expect(ref.current).toBeTruthy(); + done(); + } + }, [open]); + + return ( + +
+ + ); + }; + + const { rerender } = render(); + + rerender(); + }); }); From e44c3057231c1aa27042d94b0fdff9abf468cf45 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: Fri, 24 Mar 2023 17:11:01 +0800 Subject: [PATCH 04/23] 6.1.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2c6aa8d..c03edb3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rc-drawer", - "version": "6.1.4", + "version": "6.1.5", "description": "drawer component for react", "keywords": [ "react", From b4472f7fddbeabb0592f9f9ea8eae3ec7ec2d5ed Mon Sep 17 00:00:00 2001 From: Amumu Date: Wed, 12 Apr 2023 09:22:07 +0800 Subject: [PATCH 05/23] chore: fix npm license (#416) --- LICENSE.md => LICENSE | 0 package.json | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename LICENSE.md => LICENSE (100%) diff --git a/LICENSE.md b/LICENSE similarity index 100% rename from LICENSE.md rename to LICENSE diff --git a/package.json b/package.json index c03edb3..c8334ff 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "assets/*.css", "es" ], - "licenses": "MIT", + "license": "MIT", "main": "./lib/index", "module": "./es/index", "scripts": { From 962dfc4783f1b205156319fb7abb1ac06960cff6 Mon Sep 17 00:00:00 2001 From: afc163 Date: Sat, 27 May 2023 18:12:19 +0800 Subject: [PATCH 06/23] fix: prevent scroll when drawer close and focus (#417) --- src/Drawer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Drawer.tsx b/src/Drawer.tsx index 2d92697..a87985f 100644 --- a/src/Drawer.tsx +++ b/src/Drawer.tsx @@ -70,7 +70,7 @@ const Drawer: React.FC = props => { lastActiveRef.current && !panelRef.current?.contains(lastActiveRef.current) ) { - lastActiveRef.current?.focus(); + lastActiveRef.current?.focus({ preventScroll: true }); } }; From 9afe196bce067a33309e5b4bd970b169569e19d7 Mon Sep 17 00:00:00 2001 From: afc163 Date: Sat, 27 May 2023 18:13:48 +0800 Subject: [PATCH 07/23] 6.1.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c8334ff..0792ddd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rc-drawer", - "version": "6.1.5", + "version": "6.1.6", "description": "drawer component for react", "keywords": [ "react", From d1d81b705eac24296c585b32d42cc4311c065794 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?kiner-tang=28=E6=96=87=E8=BE=89=29?= <1127031143@qq.com> Date: Mon, 29 May 2023 13:58:12 +0800 Subject: [PATCH 08/23] feat: update dumi (#418) --- .dumirc.ts | 15 +++++++++++++++ .gitignore | 4 ++++ .umirc.ts | 19 ------------------- docs/changelog.md | 3 +++ docs/demo/base.md | 9 +++++++-- docs/demo/change-remove.md | 10 ++++++++-- docs/demo/change.md | 10 ++++++++-- docs/demo/forceRender.md | 10 ++++++++-- docs/demo/getContainer.md | 12 +++++++++--- docs/demo/multiple.md | 10 ++++++++-- docs/demo/no-mask.md | 10 ++++++++-- docs/demo/placement.md | 10 ++++++++-- docs/examples/base.tsx | 6 ------ docs/examples/{motion.ts => motion.tsx} | 0 docs/index.md | 4 +++- now.json | 2 +- package.json | 4 ++-- tsconfig.json | 3 ++- 18 files changed, 94 insertions(+), 47 deletions(-) create mode 100644 .dumirc.ts delete mode 100644 .umirc.ts create mode 100644 docs/changelog.md rename docs/examples/{motion.ts => motion.tsx} (100%) diff --git a/.dumirc.ts b/.dumirc.ts new file mode 100644 index 0000000..27e1990 --- /dev/null +++ b/.dumirc.ts @@ -0,0 +1,15 @@ +import { defineConfig } from 'dumi'; +import path from 'path'; + +export default defineConfig({ + alias: { + 'rc-drawer$': path.resolve('src'), + 'rc-drawer/es': path.resolve('src'), + }, + mfsu: false, + favicons: ['https://avatars0.githubusercontent.com/u/9441414?s=200&v=4'], + themeConfig: { + name: 'Image', + logo: 'https://avatars0.githubusercontent.com/u/9441414?s=200&v=4', + }, +}); diff --git a/.gitignore b/.gitignore index 316b8cf..76d4008 100755 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,7 @@ storybook .umi-production .umi-test .env.local + +# dumi +.dumi/tmp +.dumi/tmp-production \ No newline at end of file diff --git a/.umirc.ts b/.umirc.ts deleted file mode 100644 index f456278..0000000 --- a/.umirc.ts +++ /dev/null @@ -1,19 +0,0 @@ -// more config: https://d.umijs.org/config -import { defineConfig } from 'dumi'; - -export default defineConfig({ - title: 'rc-drawer', - favicon: - 'https://avatars0.githubusercontent.com/u/9441414?s=200&v=4', - logo: - 'https://avatars0.githubusercontent.com/u/9441414?s=200&v=4', - outputPath: '.doc', - exportStatic: {}, - styles: [ - ` - .markdown table { - width: auto !important; - } - `, - ] -}); diff --git a/docs/changelog.md b/docs/changelog.md new file mode 100644 index 0000000..94e06c8 --- /dev/null +++ b/docs/changelog.md @@ -0,0 +1,3 @@ +# ChangeLog + + diff --git a/docs/demo/base.md b/docs/demo/base.md index edb074a..9768420 100644 --- a/docs/demo/base.md +++ b/docs/demo/base.md @@ -1,3 +1,8 @@ -## base +--- +title: base +nav: + title: Demo + path: /demo +--- - + diff --git a/docs/demo/change-remove.md b/docs/demo/change-remove.md index cc07bae..9f3fdab 100644 --- a/docs/demo/change-remove.md +++ b/docs/demo/change-remove.md @@ -1,3 +1,9 @@ -## change-remove +--- +title: change-remove +nav: + title: Demo + path: /demo +--- - + + diff --git a/docs/demo/change.md b/docs/demo/change.md index 215e5f6..f2c94fd 100644 --- a/docs/demo/change.md +++ b/docs/demo/change.md @@ -1,3 +1,9 @@ -## change +--- +title: change +nav: + title: Demo + path: /demo +--- - + + diff --git a/docs/demo/forceRender.md b/docs/demo/forceRender.md index 9f12a05..1b2837a 100644 --- a/docs/demo/forceRender.md +++ b/docs/demo/forceRender.md @@ -1,3 +1,9 @@ -## Force Render +--- +title: Force Render +nav: + title: Demo + path: /demo +--- - + + diff --git a/docs/demo/getContainer.md b/docs/demo/getContainer.md index 64ec2a1..671e2ee 100644 --- a/docs/demo/getContainer.md +++ b/docs/demo/getContainer.md @@ -1,4 +1,10 @@ -## getContainer +--- +title: getContainer +nav: + title: Demo + path: /demo +--- - - + + + diff --git a/docs/demo/multiple.md b/docs/demo/multiple.md index 26c79bc..d604622 100644 --- a/docs/demo/multiple.md +++ b/docs/demo/multiple.md @@ -1,3 +1,9 @@ -## multiple +--- +title: multiple +nav: + title: Demo + path: /demo +--- - + + diff --git a/docs/demo/no-mask.md b/docs/demo/no-mask.md index f7baddf..37ecff4 100644 --- a/docs/demo/no-mask.md +++ b/docs/demo/no-mask.md @@ -1,3 +1,9 @@ -## no-mask +--- +title: no-mask +nav: + title: Demo + path: /demo +--- - + + diff --git a/docs/demo/placement.md b/docs/demo/placement.md index ec4beae..50278f2 100644 --- a/docs/demo/placement.md +++ b/docs/demo/placement.md @@ -1,3 +1,9 @@ -## placement +--- +title: placement +nav: + title: Demo + path: /demo +--- - + + diff --git a/docs/examples/base.tsx b/docs/examples/base.tsx index c6966a5..1a411b1 100755 --- a/docs/examples/base.tsx +++ b/docs/examples/base.tsx @@ -5,9 +5,6 @@ import motionProps from './motion'; const Demo = () => { const [open, setOpen] = useState(false); - const onChange = (bool: boolean) => { - // console.log('change: ', bool); - }; const onTouchEnd = () => { setOpen(false); }; @@ -17,12 +14,9 @@ const Demo = () => { return (
{ console.log('transitionEnd: ', c); }} diff --git a/docs/examples/motion.ts b/docs/examples/motion.tsx similarity index 100% rename from docs/examples/motion.ts rename to docs/examples/motion.tsx diff --git a/docs/index.md b/docs/index.md index 595be25..9c1a609 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,5 +1,7 @@ --- -title: rc-drawer +hero: + title: rc-drawer + description: React Drawer Component --- diff --git a/now.json b/now.json index 620a430..715b941 100644 --- a/now.json +++ b/now.json @@ -6,7 +6,7 @@ { "src": "package.json", "use": "@now/static-build", - "config": { "distDir": ".doc" } + "config": { "distDir": "dist" } } ], "routes": [ diff --git a/package.json b/package.json index 0792ddd..37941e6 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ }, "dependencies": { "@babel/runtime": "^7.10.1", - "@rc-component/portal": "^1.0.0-6", + "@rc-component/portal": "^1.1.1", "classnames": "^2.2.6", "rc-motion": "^2.6.1", "rc-util": "^5.21.2" @@ -64,7 +64,7 @@ "@umijs/fabric": "^2.0.0", "@umijs/test": "^3.5.23", "antd": "^4.20.2", - "dumi": "^1.1.40", + "dumi": "^2.2.0", "eslint": "^7.0.0", "father": "^2.30.21", "father-build": "^1.22.1", diff --git a/tsconfig.json b/tsconfig.json index 503d249..3e5cc41 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,5 +12,6 @@ "@@/*": ["src/.umi/*"], "rc-drawer": ["src/index.ts"] } - } + }, + "include": [".dumi/**/*", ".dumirc.ts", "**/*.ts", "**/*.tsx"] } From 3ec3caf3b3859feb707a29f5792b1072240cd1aa Mon Sep 17 00:00:00 2001 From: Robert Kuykendall Date: Mon, 29 May 2023 02:53:44 -0400 Subject: [PATCH 09/23] feat: support data-* (#404) * feat: support data-* Used https://github.com/react-component/dialog/pull/259as reference. * Add test --- src/DrawerPopup.tsx | 2 ++ tests/index.spec.tsx | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/src/DrawerPopup.tsx b/src/DrawerPopup.tsx index a043fff..69412bd 100644 --- a/src/DrawerPopup.tsx +++ b/src/DrawerPopup.tsx @@ -6,6 +6,7 @@ import DrawerPanel from './DrawerPanel'; import DrawerContext from './context'; import type { DrawerContextProps } from './context'; import KeyCode from 'rc-util/lib/KeyCode'; +import pickAttrs from 'rc-util/lib/pickAttrs'; import { parseWidthHeight } from './util'; const sentinelStyle: React.CSSProperties = { @@ -273,6 +274,7 @@ function DrawerPopup(props: DrawerPopupProps, ref: React.Ref) { ...motionStyle, ...contentWrapperStyle, }} + {...pickAttrs(props, { data: true })} > { ); errSpy.mockRestore(); }); + + it('pass data props to internal div', () => { + const value = 'bamboo'; + const { unmount } = render(); + expect(document.querySelector('.rc-drawer-content-wrapper')).toHaveAttribute('data-attr',value); + unmount(); + }); }); From 2e8b67ada81fd6857a6fb3c6959f704088b2c41d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?kiner-tang=28=E6=96=87=E8=BE=89=29?= <1127031143@qq.com> Date: Tue, 30 May 2023 10:10:18 +0800 Subject: [PATCH 10/23] feat: Support body props (#419) * feat: support bodyProps * feat: support bodyProps * feat: optimize code * feat: optimize code * feat: optimize code * feat: optimize code --- .dumirc.ts | 2 +- README.md | 11 +- docs/changelog.md | 2 +- docs/demo/bodyProps.md | 8 ++ docs/examples/bodyProps.tsx | 43 ++++++ docs/examples/change-remove.tsx | 168 ++++++++++++------------ docs/examples/change.tsx | 56 ++++---- docs/examples/{motion.tsx => motion.ts} | 0 docs/examples/multiple.tsx | 146 ++++++++++---------- docs/examples/no-mask.tsx | 30 ++--- docs/examples/placement.tsx | 59 ++++----- package.json | 2 +- src/Drawer.tsx | 18 ++- src/DrawerPanel.tsx | 37 +++++- src/DrawerPopup.tsx | 28 +++- tests/index.spec.tsx | 20 ++- 16 files changed, 367 insertions(+), 263 deletions(-) create mode 100644 docs/demo/bodyProps.md create mode 100755 docs/examples/bodyProps.tsx rename docs/examples/{motion.tsx => motion.ts} (100%) diff --git a/.dumirc.ts b/.dumirc.ts index 27e1990..263f416 100644 --- a/.dumirc.ts +++ b/.dumirc.ts @@ -9,7 +9,7 @@ export default defineConfig({ mfsu: false, favicons: ['https://avatars0.githubusercontent.com/u/9441414?s=200&v=4'], themeConfig: { - name: 'Image', + name: 'Drawer', logo: 'https://avatars0.githubusercontent.com/u/9441414?s=200&v=4', }, }); diff --git a/README.md b/README.md index 8c008d3..70d396a 100755 --- a/README.md +++ b/README.md @@ -59,12 +59,17 @@ ReactDom.render( | showMask | boolean | true | mask is show | | maskClosable | boolean | true | Clicking on the mask (area outside the Drawer) to close the Drawer or not. | | maskStyle | CSSProperties | null | mask style | -| onChange | func | null | change callback(open) | | afterVisibleChange | func | null | transition end callback(open) | | onClose | func | null | close click function | -| keyboard | Boolean | true | Whether support press esc to close | +| keyboard | boolean | true | Whether support press esc to close | | contentWrapperStyle | CSSProperties | null | content wrapper style | -| autoFocus | Boolean | true | Whether focusing on the drawer after it opened | +| autoFocus | boolean | true | Whether focusing on the drawer after it opened | +| onMouseEnter | React.MouseEventHandler\ | - | Trigger when mouse enter drawer panel | +| onMouseOver | React.MouseEventHandler\ | - | Trigger when mouse over drawer panel | +| onMouseLeave | React.MouseEventHandler\ | - | Trigger when mouse leave drawer panel | +| onClick | React.MouseEventHandler\ | - | Trigger when mouse click drawer panel | +| onKeyDown | React.MouseEventHandler\ | - | Trigger when mouse keydown on drawer panel | +| onKeyUp | React.MouseEventHandler\ | - | Trigger when mouse keyup on drawer panel | > 2.0 Rename `onMaskClick` -> `onClose`, add `maskClosable`. diff --git a/docs/changelog.md b/docs/changelog.md index 94e06c8..1d72283 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,3 +1,3 @@ # ChangeLog - + diff --git a/docs/demo/bodyProps.md b/docs/demo/bodyProps.md new file mode 100644 index 0000000..d312520 --- /dev/null +++ b/docs/demo/bodyProps.md @@ -0,0 +1,8 @@ +--- +title: bodyProps +nav: + title: Demo + path: /demo +--- + + diff --git a/docs/examples/bodyProps.tsx b/docs/examples/bodyProps.tsx new file mode 100755 index 0000000..1521693 --- /dev/null +++ b/docs/examples/bodyProps.tsx @@ -0,0 +1,43 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import React, { useState } from 'react'; +import Drawer from 'rc-drawer'; +import motionProps from './motion'; + +const Demo = () => { + const [open, setOpen] = useState(false); + const onTouchEnd = () => { + setOpen(false); + }; + const onSwitch = () => { + setOpen(c => !c); + }; + return ( +
+ { + console.log('transitionEnd: ', c); + }} + placement="right" + // width={400} + width="60%" + // Motion + {...motionProps} + onMouseEnter={() => { + console.log('mouseEnter'); + }} + onMouseLeave={() => { + console.log('mouseLeave'); + }} + > + content + +
+ +
+
+ ); +}; +export default Demo; diff --git a/docs/examples/change-remove.tsx b/docs/examples/change-remove.tsx index 4257f1d..5f70d8c 100755 --- a/docs/examples/change-remove.tsx +++ b/docs/examples/change-remove.tsx @@ -14,97 +14,93 @@ import motionProps from './motion'; const SubMenu = Menu.SubMenu; const MenuItemGroup = Menu.ItemGroup; -class Demo extends React.Component { - public state = { - show: true, - }; - public componentDidMount() { + +function Demo() { + const [show, setShow] = React.useState(true); + React.useEffect(() => { setTimeout(() => { - this.setState({ - show: false, - }); + setShow(false); }, 2000); - } - public render() { - return ( -
- {this.state.show && ( - + {show && ( + + - + + Navigation One + + } > - - - Navigation One - - } - > - - Option 1 - Option 2 - - - Option 3 - Option 4 - - - - - Navigation Two - - } - > - Option 5 - Option 6 - - Option 7 - Option 8 - - - - - Navigation Three - - } - > - Option 9 - Option 10 - Option 11 - Option 12 + + Option 1 + Option 2 + + + Option 3 + Option 4 + + + + + Navigation Two + + } + > + Option 5 + Option 6 + + Option 7 + Option 8 - - - )} -
- 内容区块 -
+ + + + Navigation Three + + } + > + Option 9 + Option 10 + Option 11 + Option 12 + +
+
+ )} +
+ 内容区块
- ); - } +
+ ); } + export default Demo; diff --git a/docs/examples/change.tsx b/docs/examples/change.tsx index 5768816..7f09356 100755 --- a/docs/examples/change.tsx +++ b/docs/examples/change.tsx @@ -17,40 +17,30 @@ import motionProps from './motion'; const SubMenu = Menu.SubMenu; const MenuItemGroup = Menu.ItemGroup; -class Demo extends React.Component { - public state = { - open: true, - }; - public componentDidMount() { + +function Demo() { + const [open, setOpen] = React.useState(true); + + React.useEffect(() => { setTimeout(() => { - this.setState({ - open: false, - }); + setOpen(false); }, 2000); - } - public onChange = (bool: boolean) => { - console.log('change: ', bool); - }; - public onTouchEnd = () => { - this.setState({ - open: false, - }); - }; - public onSwitch = () => { - this.setState({ - open: !this.state.open, - }); + }, []); + + const onTouchEnd = () => { + setOpen(false); }; - public render() { - return ( -
+ + const onSwitch = () => { + this.setState(p => !p); + } + + return ( +
{ + open={open} + onClose={onTouchEnd} + afterOpenChange={(c: boolean) => { console.log('transitionEnd: ', c); }} width="20vw" @@ -124,7 +114,7 @@ class Demo extends React.Component { > 内容区块
- ); - } + ); } + export default Demo; diff --git a/docs/examples/motion.tsx b/docs/examples/motion.ts similarity index 100% rename from docs/examples/motion.tsx rename to docs/examples/motion.ts diff --git a/docs/examples/multiple.tsx b/docs/examples/multiple.tsx index 77c0481..04eab18 100755 --- a/docs/examples/multiple.tsx +++ b/docs/examples/multiple.tsx @@ -11,83 +11,77 @@ import '../../assets/index.less'; import './assets/index.less'; import motionProps from './motion'; -class Demo extends React.Component { - public state = { - open: true, - openChild: true, - openChildren: true, - }; - public onClick = () => { - this.setState({ - open: !this.state.open, - }); - }; - public onChildClick = () => { - this.setState({ - openChild: !this.state.openChild, - }); - }; - public onChildrenClick = e => { - this.setState({ - openChildren: e.currentTarget instanceof HTMLButtonElement, - }); - }; +function Demo() { + const [open, setOpen] = React.useState(true); + const [openChild, setOpenChild] = React.useState(true); + const [openChildren, setOpenChildren] = React.useState(true); - public render() { - return ( -
-
- -
- -
- - -
- 二级抽屉 - - -
三级抽屉
-
-
-
-
-
-
- ); + function onClick() { + setOpen(!open); + } + + function onChildClick() { + setOpenChild(!openChild); + } + + function onChildrenClick(e) { + setOpenChildren(e.currentTarget instanceof HTMLButtonElement); } + + return ( +
+
+ +
+ +
+ + +
+ 二级抽屉 + + +
三级抽屉
+
+
+
+
+
+
+ ); } + export default Demo; diff --git a/docs/examples/no-mask.tsx b/docs/examples/no-mask.tsx index 8940dd2..3e6a3c7 100755 --- a/docs/examples/no-mask.tsx +++ b/docs/examples/no-mask.tsx @@ -16,21 +16,16 @@ import './assets/index.less'; const { SubMenu } = Menu; const MenuItemGroup = Menu.ItemGroup; -class Demo extends React.Component { - public state = { - open: false, - }; - public onSwitch = () => { - const { open } = this.state; - this.setState({ - open: !open, - }); - }; +function Demo() { + const [open, setOpen] = React.useState(true); - public render() { - return ( -
+ const onSwitch = () => { + setOpen(!open); + } + + return ( +
内容区块
- ); - } + ); } export default Demo; diff --git a/docs/examples/placement.tsx b/docs/examples/placement.tsx index 14b075d..7563ae4 100755 --- a/docs/examples/placement.tsx +++ b/docs/examples/placement.tsx @@ -11,41 +11,35 @@ import 'antd/lib/style'; import '../../assets/index.less'; import './assets/index.less'; +import type { Placement } from '@/Drawer'; const SubMenu = Menu.SubMenu; const MenuItemGroup = Menu.ItemGroup; const Option = Select.Option; -class Demo extends React.Component { - public state = { - placement: 'right', - childShow: true, - width: '20vw', - height: null, - }; - public onChange = (value: string) => { - this.setState( - { - placement: value, - width: value === 'right' || value === 'left' ? '20vw' : null, - height: value === 'right' || value === 'left' ? null : '20vh', - childShow: false, // 删除子级,删除切换时的过渡动画。。。 - }, - () => { - this.setState({ - childShow: true, - }); - }, - ); - }; - public render() { - return ( -
- {this.state.childShow && ( +function Demo() { + const [placement, setPlacement] = React.useState('right'); + const [childShow, setChildShow] = React.useState(true); + const [width, setWidth] = React.useState('20vw'); + const [height, setHeight] = React.useState(null); + + const onChange = (value: string) => { + setPlacement(value as Placement); + setWidth(value === 'right' || value === 'left' ? '20vw' : null); + setHeight(value === 'right' || value === 'left' ? null : '20vh'); + setChildShow(false); // 删除子级,删除切换时的过渡动画。。。 + setTimeout(() => { + setChildShow(true); + }); + } + + return ( +
+ {childShow && ( @@ -126,8 +120,7 @@ class Demo extends React.Component {
- ); - } + ); } export default Demo; diff --git a/package.json b/package.json index 37941e6..0b1385e 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "devDependencies": { "@ant-design/icons": "^4.7.0", "@testing-library/jest-dom": "^5.11.9", - "@testing-library/react": "^13.0.0", + "@testing-library/react": "^14.0.0", "@types/classnames": "^2.2.9", "@types/jest": "^27.0.2", "@types/raf": "^3.4.0", diff --git a/src/Drawer.tsx b/src/Drawer.tsx index a87985f..4879e15 100644 --- a/src/Drawer.tsx +++ b/src/Drawer.tsx @@ -5,11 +5,12 @@ import useLayoutEffect from 'rc-util/lib/hooks/useLayoutEffect'; import DrawerPopup from './DrawerPopup'; import type { DrawerPopupProps } from './DrawerPopup'; import { warnCheck } from './util'; +import type { DrawerPanelEvents } from './DrawerPanel'; export type Placement = 'left' | 'top' | 'right' | 'bottom'; export interface DrawerProps - extends Omit { + extends Omit, DrawerPanelEvents { prefixCls?: string; open?: boolean; onClose?: (e: React.MouseEvent | React.KeyboardEvent) => void; @@ -31,6 +32,12 @@ const Drawer: React.FC = props => { forceRender, afterOpenChange, destroyOnClose, + onMouseEnter, + onMouseOver, + onMouseLeave, + onClick, + onKeyDown, + onKeyUp, } = props; const [animatedVisible, setAnimatedVisible] = React.useState(false); @@ -79,6 +86,14 @@ const Drawer: React.FC = props => { return null; } + const eventHandlers = { + onMouseEnter, + onMouseOver, + onMouseLeave, + onClick, + onKeyDown, + onKeyUp, + }; const drawerPopupProps = { ...props, open: mergedOpen, @@ -92,6 +107,7 @@ const Drawer: React.FC = props => { inline: getContainer === false, afterOpenChange: internalAfterOpenChange, ref: panelRef, + ...eventHandlers, }; return ( diff --git a/src/DrawerPanel.tsx b/src/DrawerPanel.tsx index db5a3e4..b610a60 100644 --- a/src/DrawerPanel.tsx +++ b/src/DrawerPanel.tsx @@ -1,11 +1,20 @@ -import * as React from 'react'; import classNames from 'classnames'; +import * as React from 'react'; export interface DrawerPanelRef { focus: VoidFunction; } -export interface DrawerPanelProps { +export interface DrawerPanelEvents { + onMouseEnter?: React.MouseEventHandler; + onMouseOver?: React.MouseEventHandler; + onMouseLeave?: React.MouseEventHandler; + onClick?: React.MouseEventHandler; + onKeyDown?: React.KeyboardEventHandler; + onKeyUp?: React.KeyboardEventHandler; +} + +export interface DrawerPanelProps extends DrawerPanelEvents { prefixCls: string; className?: string; style?: React.CSSProperties; @@ -14,7 +23,28 @@ export interface DrawerPanelProps { } const DrawerPanel = (props: DrawerPanelProps) => { - const { prefixCls, className, style, children, containerRef } = props; + const { + prefixCls, + className, + style, + children, + containerRef, + onMouseEnter, + onMouseOver, + onMouseLeave, + onClick, + onKeyDown, + onKeyUp, + } = props; + + const eventHandlers = { + onMouseEnter, + onMouseOver, + onMouseLeave, + onClick, + onKeyDown, + onKeyUp, + }; // =============================== Render =============================== @@ -28,6 +58,7 @@ const DrawerPanel = (props: DrawerPanelProps) => { aria-modal="true" role="dialog" ref={containerRef} + {...eventHandlers} > {children}
diff --git a/src/DrawerPopup.tsx b/src/DrawerPopup.tsx index 69412bd..a6cbe34 100644 --- a/src/DrawerPopup.tsx +++ b/src/DrawerPopup.tsx @@ -1,12 +1,12 @@ -import * as React from 'react'; import classNames from 'classnames'; -import CSSMotion from 'rc-motion'; import type { CSSMotionProps } from 'rc-motion'; -import DrawerPanel from './DrawerPanel'; -import DrawerContext from './context'; -import type { DrawerContextProps } from './context'; +import CSSMotion from 'rc-motion'; import KeyCode from 'rc-util/lib/KeyCode'; import pickAttrs from 'rc-util/lib/pickAttrs'; +import * as React from 'react'; +import type { DrawerContextProps } from './context'; +import DrawerContext from './context'; +import DrawerPanel, { DrawerPanelEvents } from './DrawerPanel'; import { parseWidthHeight } from './util'; const sentinelStyle: React.CSSProperties = { @@ -23,7 +23,7 @@ export interface PushConfig { distance?: number | string; } -export interface DrawerPopupProps { +export interface DrawerPopupProps extends DrawerPanelEvents { prefixCls: string; open?: boolean; inline?: boolean; @@ -98,6 +98,12 @@ function DrawerPopup(props: DrawerPopupProps, ref: React.Ref) { // Events afterOpenChange, onClose, + onMouseEnter, + onMouseOver, + onMouseLeave, + onClick, + onKeyDown, + onKeyUp, } = props; // ================================ Refs ================================ @@ -250,6 +256,15 @@ function DrawerPopup(props: DrawerPopupProps, ref: React.Ref) { wrapperStyle.height = parseWidthHeight(height); } + const eventHandlers = { + onMouseEnter, + onMouseOver, + onMouseLeave, + onClick, + onKeyDown, + onKeyUp, + }; + const panelNode: React.ReactNode = ( ) { prefixCls={prefixCls} className={className} style={style} + {...eventHandlers} > {children}
diff --git a/tests/index.spec.tsx b/tests/index.spec.tsx index 550703e..8596a48 100755 --- a/tests/index.spec.tsx +++ b/tests/index.spec.tsx @@ -359,11 +359,29 @@ describe('rc-drawer-menu', () => { ); errSpy.mockRestore(); }); - + + it('pass data props to internal div', () => { const value = 'bamboo'; const { unmount } = render(); expect(document.querySelector('.rc-drawer-content-wrapper')).toHaveAttribute('data-attr',value); unmount(); }); + + it('support bodyProps', () => { + const enter = jest.fn(); + const leave = jest.fn(); + const { baseElement } = render( + , + ); + fireEvent.mouseOver(baseElement.querySelector('.rc-drawer-content')); + expect(enter).toHaveBeenCalled(); + fireEvent.mouseLeave(baseElement.querySelector('.rc-drawer-content')); + expect(leave).toHaveBeenCalled(); + }); }); From 58be061d580ccc935a42bddb696f3a680bec8e13 Mon Sep 17 00:00:00 2001 From: MadCcc <1075746765@qq.com> Date: Tue, 30 May 2023 10:14:54 +0800 Subject: [PATCH 11/23] v6.2.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0b1385e..7ffdfc6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rc-drawer", - "version": "6.1.6", + "version": "6.2.0", "description": "drawer component for react", "keywords": [ "react", From f2d8b7c9e174ef60e16fc77866662715f6c19aa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?kiner-tang=28=E6=96=87=E8=BE=89=29?= <1127031143@qq.com> Date: Tue, 30 May 2023 16:13:14 +0800 Subject: [PATCH 12/23] feat: update demo (#420) --- docs/examples/change.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/examples/change.tsx b/docs/examples/change.tsx index 7f09356..ec03731 100755 --- a/docs/examples/change.tsx +++ b/docs/examples/change.tsx @@ -32,7 +32,7 @@ function Demo() { }; const onSwitch = () => { - this.setState(p => !p); + setOpen(c => !c); } return ( @@ -123,7 +123,7 @@ function Demo() { lineHeight: '24px', }} > - {!this.state.open ? '打开' : '关闭'} + {!open ? '打开' : '关闭'}
From 96b6aa8571a87903cdc4204d4366664bf8ea5108 Mon Sep 17 00:00:00 2001 From: muxin Date: Tue, 20 Jun 2023 15:24:30 +0800 Subject: [PATCH 13/23] feat: support id prop (#421) * featL support id prop * test: add test * fix: pass id to panel --- src/DrawerPanel.tsx | 3 +++ src/DrawerPopup.tsx | 6 +++++- tests/index.spec.tsx | 11 +++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/DrawerPanel.tsx b/src/DrawerPanel.tsx index b610a60..f668f8c 100644 --- a/src/DrawerPanel.tsx +++ b/src/DrawerPanel.tsx @@ -17,6 +17,7 @@ export interface DrawerPanelEvents { export interface DrawerPanelProps extends DrawerPanelEvents { prefixCls: string; className?: string; + id?: string; style?: React.CSSProperties; children?: React.ReactNode; containerRef?: React.Ref; @@ -29,6 +30,7 @@ const DrawerPanel = (props: DrawerPanelProps) => { style, children, containerRef, + id, onMouseEnter, onMouseOver, onMouseLeave, @@ -51,6 +53,7 @@ const DrawerPanel = (props: DrawerPanelProps) => { return ( <>
) { // Drawer className, + id, style, motion, width, @@ -292,6 +295,7 @@ function DrawerPopup(props: DrawerPopupProps, ref: React.Ref) { {...pickAttrs(props, { data: true })} > { fireEvent.mouseLeave(baseElement.querySelector('.rc-drawer-content')); expect(leave).toHaveBeenCalled(); }); + + it('pass id & className props to Panel', () => { + const { unmount } = render(); + expect( + document.querySelector('.rc-drawer-content') + ).toHaveClass('customer-className'); + expect( + document.querySelector('.rc-drawer-content') + ).toHaveAttribute('id', 'customer-id'); + unmount(); + }); }); From 6ca942c8a285c850c97b8c6197555dc099d095c8 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, 20 Jun 2023 15:44:46 +0800 Subject: [PATCH 14/23] 6.3.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7ffdfc6..53ec433 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rc-drawer", - "version": "6.2.0", + "version": "6.3.0", "description": "drawer component for react", "keywords": [ "react", From 7d05f7ccf8d8449b5c259b7699614d9631a95ac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E7=88=B1=E5=90=83=E7=99=BD=E8=90=9D?= =?UTF-8?q?=E5=8D=9C?= Date: Tue, 8 Aug 2023 14:13:45 +0800 Subject: [PATCH 15/23] feat: drawer support panelRef (#424) * feat: drawer support panelRef * chore: fix lint * chore: bump father --- .fatherrc.js | 14 +++++-------- package.json | 43 ++++++++++++++++++++-------------------- src/Drawer.tsx | 48 ++++++++++++++++++++++++++++++--------------- src/DrawerPanel.tsx | 7 ++++++- src/context.ts | 6 ++++++ tests/ref.spec.tsx | 25 +++++++++++++++++++++++ 6 files changed, 95 insertions(+), 48 deletions(-) create mode 100755 tests/ref.spec.tsx diff --git a/.fatherrc.js b/.fatherrc.js index 558df7e..4ddbafd 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 53ec433..a0486a8 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 4879e15..70210dc 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 f668f8c..2e19d76 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 010335a..1a05408 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 0000000..ec1c8cf --- /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'); + }); +}); From 97118acb69fa0be132ae360e57178757f147ed4a 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, 8 Aug 2023 14:14:52 +0800 Subject: [PATCH 16/23] 6.4.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a0486a8..7df947e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rc-drawer", - "version": "6.3.0", + "version": "6.4.0", "description": "drawer component for react", "keywords": [ "react", From 77de1ca12420a0b00ca056614c3b04b9c045bea8 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, 8 Aug 2023 14:31:47 +0800 Subject: [PATCH 17/23] 6.4.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7df947e..6306c4b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rc-drawer", - "version": "6.4.0", + "version": "6.4.1", "description": "drawer component for react", "keywords": [ "react", From c57edaa4111032c5b2fe0081357965b23a9936b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?kiner-tang=28=E6=96=87=E8=BE=89=29?= <1127031143@qq.com> Date: Mon, 18 Sep 2023 14:56:43 +0800 Subject: [PATCH 18/23] feat: support classNames (#426) * feat: support classNames * docs: update docs * docs: remove wrapperClassName in document --- README.md | 2 +- src/Drawer.tsx | 2 ++ src/DrawerPopup.tsx | 8 ++++++++ src/inter.ts | 4 ++++ tests/index.spec.tsx | 16 ++++++++++++++++ 5 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/inter.ts diff --git a/README.md b/README.md index 70d396a..7312ba4 100755 --- a/README.md +++ b/README.md @@ -44,8 +44,8 @@ ReactDom.render( | props | type | default | description | |------------|----------------|---------|----------------| | className | string | null | - | +| classNames | { mask?: string; wrapper?: string; } | - | pass className to target area | | prefixCls | string | 'drawer' | prefix class | -| wrapperClassName | string | null | wrapper class name | | width | string \| number | null | drawer content wrapper width, drawer level transition width | | height | string \| number | null | drawer content wrapper height, drawer level transition height | | open | boolean | false | open or close menu | diff --git a/src/Drawer.tsx b/src/Drawer.tsx index 70210dc..4dfe644 100644 --- a/src/Drawer.tsx +++ b/src/Drawer.tsx @@ -7,6 +7,7 @@ import type { DrawerPanelEvents } from './DrawerPanel'; import type { DrawerPopupProps } from './DrawerPopup'; import DrawerPopup from './DrawerPopup'; import { warnCheck } from './util'; +import type { DrawerClassNames } from './inter'; export type Placement = 'left' | 'top' | 'right' | 'bottom'; @@ -19,6 +20,7 @@ export interface DrawerProps destroyOnClose?: boolean; getContainer?: PortalProps['getContainer']; panelRef?: React.Ref; + classNames?: DrawerClassNames; } const Drawer: React.FC = props => { diff --git a/src/DrawerPopup.tsx b/src/DrawerPopup.tsx index b37566e..b15fdde 100644 --- a/src/DrawerPopup.tsx +++ b/src/DrawerPopup.tsx @@ -9,6 +9,7 @@ import DrawerContext from './context'; import type { DrawerPanelEvents } from './DrawerPanel'; import DrawerPanel from './DrawerPanel'; import { parseWidthHeight } from './util'; +import type { DrawerClassNames } from './inter'; const sentinelStyle: React.CSSProperties = { width: 0, @@ -63,6 +64,9 @@ export interface DrawerPopupProps extends DrawerPanelEvents { onClose?: ( event: React.MouseEvent | React.KeyboardEvent, ) => void; + + // classNames + classNames?: DrawerClassNames; } function DrawerPopup(props: DrawerPopupProps, ref: React.Ref) { @@ -76,6 +80,8 @@ function DrawerPopup(props: DrawerPopupProps, ref: React.Ref) { autoFocus, keyboard, + // classNames + classNames: drawerClassNames, // Root rootClassName, rootStyle, @@ -216,6 +222,7 @@ function DrawerPopup(props: DrawerPopupProps, ref: React.Ref) { className={classNames( `${prefixCls}-mask`, motionMaskClassName, + drawerClassNames?.mask, maskClassName, )} style={{ @@ -285,6 +292,7 @@ function DrawerPopup(props: DrawerPopupProps, ref: React.Ref) {
{ ).toHaveAttribute('id', 'customer-id'); unmount(); }); + + it('should support classNames', () => { + const { unmount } = render( + + ); + expect( + document.querySelector('.rc-drawer-content-wrapper') + ).toHaveClass('customer-wrapper'); + expect( + document.querySelector('.rc-drawer-mask') + ).toHaveClass('customer-mask'); + unmount(); + }); }); From 3287d622935f375611678bbea182d6c3a1995ec6 Mon Sep 17 00:00:00 2001 From: MadCcc <1075746765@qq.com> Date: Mon, 18 Sep 2023 16:04:41 +0800 Subject: [PATCH 19/23] v6.5.0 --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 6306c4b..f61a5ea 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rc-drawer", - "version": "6.4.1", + "version": "6.5.0", "description": "drawer component for react", "keywords": [ "react", @@ -48,8 +48,8 @@ "rc-util": "^5.36.0" }, "devDependencies": { - "@rc-component/father-plugin": "^1.0.0", "@ant-design/icons": "^4.7.0", + "@rc-component/father-plugin": "^1.0.0", "@testing-library/jest-dom": "^5.11.9", "@testing-library/react": "^14.0.0", "@types/classnames": "^2.2.9", @@ -58,7 +58,6 @@ "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", "@types/warning": "^3.0.0", - "rc-test": "^7.0.9", "antd": "^4.20.2", "dumi": "^2.2.0", "eslint": "^7.0.0", @@ -67,6 +66,7 @@ "less": "^3.10.3", "np": "^7.5.0", "prettier": "^3.0.0", + "rc-test": "^7.0.9", "react": "^18.0.0", "react-dom": "^18.0.0", "typescript": "^4.6.4" From d3087c113a65b4605831066cf489c63419283ca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?kiner-tang=28=E6=96=87=E8=BE=89=29?= <1127031143@qq.com> Date: Fri, 22 Sep 2023 15:50:48 +0800 Subject: [PATCH 20/23] feat: support styles (#427) --- README.md | 1 + src/Drawer.tsx | 3 ++- src/DrawerPopup.tsx | 9 ++++++- src/inter.ts | 5 ++++ tests/index.spec.tsx | 61 +++++++++++++++++++++++++++----------------- 5 files changed, 54 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 7312ba4..8369acb 100755 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ ReactDom.render( |------------|----------------|---------|----------------| | className | string | null | - | | classNames | { mask?: string; wrapper?: string; } | - | pass className to target area | +| styles | { mask?: CSSProperties; wrapper?: CSSProperties; } | - | pass style to target area | | prefixCls | string | 'drawer' | prefix class | | width | string \| number | null | drawer content wrapper width, drawer level transition width | | height | string \| number | null | drawer content wrapper height, drawer level transition height | diff --git a/src/Drawer.tsx b/src/Drawer.tsx index 4dfe644..a75b67e 100644 --- a/src/Drawer.tsx +++ b/src/Drawer.tsx @@ -7,7 +7,7 @@ import type { DrawerPanelEvents } from './DrawerPanel'; import type { DrawerPopupProps } from './DrawerPopup'; import DrawerPopup from './DrawerPopup'; import { warnCheck } from './util'; -import type { DrawerClassNames } from './inter'; +import type { DrawerClassNames, DrawerStyles } from './inter'; export type Placement = 'left' | 'top' | 'right' | 'bottom'; @@ -21,6 +21,7 @@ export interface DrawerProps getContainer?: PortalProps['getContainer']; panelRef?: React.Ref; classNames?: DrawerClassNames; + styles?: DrawerStyles; } const Drawer: React.FC = props => { diff --git a/src/DrawerPopup.tsx b/src/DrawerPopup.tsx index b15fdde..144718b 100644 --- a/src/DrawerPopup.tsx +++ b/src/DrawerPopup.tsx @@ -9,7 +9,7 @@ import DrawerContext from './context'; import type { DrawerPanelEvents } from './DrawerPanel'; import DrawerPanel from './DrawerPanel'; import { parseWidthHeight } from './util'; -import type { DrawerClassNames } from './inter'; +import type { DrawerClassNames, DrawerStyles } from './inter'; const sentinelStyle: React.CSSProperties = { width: 0, @@ -67,6 +67,9 @@ export interface DrawerPopupProps extends DrawerPanelEvents { // classNames classNames?: DrawerClassNames; + + // styles + styles?: DrawerStyles; } function DrawerPopup(props: DrawerPopupProps, ref: React.Ref) { @@ -113,6 +116,8 @@ function DrawerPopup(props: DrawerPopupProps, ref: React.Ref) { onClick, onKeyDown, onKeyUp, + + styles, } = props; // ================================ Refs ================================ @@ -228,6 +233,7 @@ function DrawerPopup(props: DrawerPopupProps, ref: React.Ref) { style={{ ...motionMaskStyle, ...maskStyle, + ...styles?.mask, }} onClick={maskClosable && open ? onClose : undefined} ref={maskRef} @@ -299,6 +305,7 @@ function DrawerPopup(props: DrawerPopupProps, ref: React.Ref) { ...wrapperStyle, ...motionStyle, ...contentWrapperStyle, + ...styles?.wrapper, }} {...pickAttrs(props, { data: true })} > diff --git a/src/inter.ts b/src/inter.ts index 0d2b2b5..0d40dff 100644 --- a/src/inter.ts +++ b/src/inter.ts @@ -2,3 +2,8 @@ export interface DrawerClassNames { mask?: string; wrapper?: string; } + +export interface DrawerStyles { + mask?: React.CSSProperties; + wrapper?: React.CSSProperties; +} \ No newline at end of file diff --git a/tests/index.spec.tsx b/tests/index.spec.tsx index 142e680..5a54aa3 100755 --- a/tests/index.spec.tsx +++ b/tests/index.spec.tsx @@ -61,23 +61,23 @@ describe('rc-drawer-menu', () => { placement: DrawerProps['placement']; transform: string; }[] = [ - { - placement: 'left', - transform: 'translateX(903px)', - }, - { - placement: 'right', - transform: 'translateX(-903px)', - }, - { - placement: 'top', - transform: 'translateY(903px)', - }, - { - placement: 'bottom', - transform: 'translateY(-903px)', - }, - ]; + { + placement: 'left', + transform: 'translateX(903px)', + }, + { + placement: 'right', + transform: 'translateX(-903px)', + }, + { + placement: 'top', + transform: 'translateY(903px)', + }, + { + placement: 'bottom', + transform: 'translateY(-903px)', + }, + ]; placementList.forEach(({ placement, transform }) => { it(placement, () => { @@ -359,15 +359,15 @@ describe('rc-drawer-menu', () => { ); errSpy.mockRestore(); }); - - + + it('pass data props to internal div', () => { const value = 'bamboo'; const { unmount } = render(); - expect(document.querySelector('.rc-drawer-content-wrapper')).toHaveAttribute('data-attr',value); + expect(document.querySelector('.rc-drawer-content-wrapper')).toHaveAttribute('data-attr', value); unmount(); }); - + it('support bodyProps', () => { const enter = jest.fn(); const leave = jest.fn(); @@ -386,7 +386,7 @@ describe('rc-drawer-menu', () => { }); it('pass id & className props to Panel', () => { - const { unmount } = render(); + const { unmount } = render(); expect( document.querySelector('.rc-drawer-content') ).toHaveClass('customer-className'); @@ -401,7 +401,7 @@ describe('rc-drawer-menu', () => { + }} open /> ); expect( document.querySelector('.rc-drawer-content-wrapper') @@ -411,4 +411,19 @@ describe('rc-drawer-menu', () => { ).toHaveClass('customer-mask'); unmount(); }); + it('should support styles', () => { + const { unmount } = render( + + ); + expect( + document.querySelector('.rc-drawer-content-wrapper') + ).toHaveStyle('background: red'); + expect( + document.querySelector('.rc-drawer-mask') + ).toHaveStyle('background: blue'); + unmount(); + }); }); From 0b0d4a0f165bbf989b48caa7871fb12e30c35691 Mon Sep 17 00:00:00 2001 From: MadCcc <1075746765@qq.com> Date: Fri, 22 Sep 2023 15:58:11 +0800 Subject: [PATCH 21/23] v6.5.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f61a5ea..43e4faf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rc-drawer", - "version": "6.5.0", + "version": "6.5.1", "description": "drawer component for react", "keywords": [ "react", From 2ea873091523851f492fae6646a1a43bbd1bdc16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?kiner-tang=28=E6=96=87=E8=BE=89=29?= <1127031143@qq.com> Date: Fri, 22 Sep 2023 19:31:34 +0800 Subject: [PATCH 22/23] feat: classNames & styles support content (#428) --- src/DrawerPopup.tsx | 7 +++++-- src/inter.ts | 2 ++ tests/index.spec.tsx | 8 ++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/DrawerPopup.tsx b/src/DrawerPopup.tsx index 144718b..bf6d552 100644 --- a/src/DrawerPopup.tsx +++ b/src/DrawerPopup.tsx @@ -313,8 +313,11 @@ function DrawerPopup(props: DrawerPopupProps, ref: React.Ref) { id={id} containerRef={motionRef} prefixCls={prefixCls} - className={className} - style={style} + className={classNames(className, drawerClassNames?.content)} + style={{ + ...style, + ...styles?.content, + }} {...eventHandlers} > {children} diff --git a/src/inter.ts b/src/inter.ts index 0d40dff..614eddb 100644 --- a/src/inter.ts +++ b/src/inter.ts @@ -1,9 +1,11 @@ export interface DrawerClassNames { mask?: string; wrapper?: string; + content?: string; } export interface DrawerStyles { mask?: React.CSSProperties; wrapper?: React.CSSProperties; + content?: React.CSSProperties; } \ No newline at end of file diff --git a/tests/index.spec.tsx b/tests/index.spec.tsx index 5a54aa3..e4d89c4 100755 --- a/tests/index.spec.tsx +++ b/tests/index.spec.tsx @@ -401,6 +401,7 @@ describe('rc-drawer-menu', () => { ); expect( @@ -409,6 +410,9 @@ describe('rc-drawer-menu', () => { expect( document.querySelector('.rc-drawer-mask') ).toHaveClass('customer-mask'); + expect( + document.querySelector('.rc-drawer-content') + ).toHaveClass('customer-content'); unmount(); }); it('should support styles', () => { @@ -416,6 +420,7 @@ describe('rc-drawer-menu', () => { ); expect( @@ -424,6 +429,9 @@ describe('rc-drawer-menu', () => { expect( document.querySelector('.rc-drawer-mask') ).toHaveStyle('background: blue'); + expect( + document.querySelector('.rc-drawer-content') + ).toHaveStyle('background: green'); unmount(); }); }); From 304a7ca77de51f4fcbc46023cf6d48bcd6fd0f29 Mon Sep 17 00:00:00 2001 From: MadCcc <1075746765@qq.com> Date: Fri, 22 Sep 2023 19:33:12 +0800 Subject: [PATCH 23/23] v6.5.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 43e4faf..4f21346 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rc-drawer", - "version": "6.5.1", + "version": "6.5.2", "description": "drawer component for react", "keywords": [ "react",