Skip to content

Commit

Permalink
feat: support panelRef (#363)
Browse files Browse the repository at this point in the history
* chore: support ref

* test: add test case
  • Loading branch information
zombieJ committed Aug 8, 2023
1 parent 76f3e5d commit c88bc55
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 30 deletions.
12 changes: 9 additions & 3 deletions src/Dialog/Content/Panel.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import React, { useRef } from 'react';
import classNames from 'classnames';
import MemoChildren from './MemoChildren';
import { useComposeRef } from 'rc-util/lib/ref';
import React, { useRef } from 'react';
import { RefContext } from '../../context';
import type { IDialogPropTypes } from '../../IDialogPropTypes';
import MemoChildren from './MemoChildren';

const sentinelStyle = { width: 0, height: 0, overflow: 'hidden', outline: 'none' };

Expand Down Expand Up @@ -43,6 +45,10 @@ const Panel = React.forwardRef<ContentRef, PanelProps>((props, ref) => {
} = props;

// ================================= Refs =================================
const { panel: panelRef } = React.useContext(RefContext);

const mergedRef = useComposeRef(holderRef, panelRef);

const sentinelStartRef = useRef<HTMLDivElement>();
const sentinelEndRef = useRef<HTMLDivElement>();

Expand Down Expand Up @@ -112,7 +118,7 @@ const Panel = React.forwardRef<ContentRef, PanelProps>((props, ref) => {
role="dialog"
aria-labelledby={title ? ariaId : null}
aria-modal="true"
ref={holderRef}
ref={mergedRef}
style={{
...style,
...contentStyle,
Expand Down
56 changes: 29 additions & 27 deletions src/DialogWrap.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from 'react';
import Portal from '@rc-component/portal';
import * as React from 'react';
import { RefContext } from './context';
import Dialog from './Dialog';
import type { IDialogPropTypes } from './IDialogPropTypes';

Expand All @@ -13,46 +14,47 @@ import type { IDialogPropTypes } from './IDialogPropTypes';
* */

const DialogWrap: React.FC<IDialogPropTypes> = (props: IDialogPropTypes) => {
const { visible, getContainer, forceRender, destroyOnClose = false, afterClose } = props;
const {
visible,
getContainer,
forceRender,
destroyOnClose = false,
afterClose,
panelRef,
} = props;
const [animatedVisible, setAnimatedVisible] = React.useState<boolean>(visible);

const refContext = React.useMemo(() => ({ panel: panelRef }), [panelRef]);

React.useEffect(() => {
if (visible) {
setAnimatedVisible(true);
}
}, [visible]);

// // 渲染在当前 dom 里;
// if (getContainer === false) {
// return (
// <Dialog
// {...props}
// getOpenCount={() => 2} // 不对 body 做任何操作。。
// />
// );
// }

// Destroy on close will remove wrapped div
if (!forceRender && destroyOnClose && !animatedVisible) {
return null;
}

return (
<Portal
open={visible || forceRender || animatedVisible}
autoDestroy={false}
getContainer={getContainer}
autoLock={visible || animatedVisible}
>
<Dialog
{...props}
destroyOnClose={destroyOnClose}
afterClose={() => {
afterClose?.();
setAnimatedVisible(false);
}}
/>
</Portal>
<RefContext.Provider value={refContext}>
<Portal
open={visible || forceRender || animatedVisible}
autoDestroy={false}
getContainer={getContainer}
autoLock={visible || animatedVisible}
>
<Dialog
{...props}
destroyOnClose={destroyOnClose}
afterClose={() => {
afterClose?.();
setAnimatedVisible(false);
}}
/>
</Portal>
</RefContext.Provider>
);
};

Expand Down
3 changes: 3 additions & 0 deletions src/IDialogPropTypes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,7 @@ export type IDialogPropTypes = {
// https://github.com/ant-design/ant-design/issues/19771
// https://github.com/react-component/dialog/issues/95
focusTriggerAfterClose?: boolean;

// Refs
panelRef?: React.Ref<HTMLDivElement>;
};
7 changes: 7 additions & 0 deletions src/context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import * as React from 'react';

export interface RefContextProps {
panel?: React.Ref<HTMLDivElement>;
}

export const RefContext = React.createContext<RefContextProps>({});
28 changes: 28 additions & 0 deletions tests/ref.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* 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 React from 'react';
import Dialog from '../src';

describe('Dialog.ref', () => {
beforeEach(() => {
jest.useFakeTimers();
});

afterEach(() => {
jest.clearAllTimers();
jest.useRealTimers();
});

it('support panelRef', () => {
const panelRef = React.createRef<HTMLDivElement>();

render(
<Provider motion={false}>
<Dialog panelRef={panelRef} visible />
</Provider>,
);

expect(panelRef.current).toHaveClass('rc-dialog');
});
});

0 comments on commit c88bc55

Please sign in to comment.