Skip to content

Commit

Permalink
feat: Watermark support nest Modal & Drawer (ant-design#44104)
Browse files Browse the repository at this point in the history
* docs: add demo

* refactor: init

* refactor: of it

* refactor: simple content

* chore: unique func

* chore: refactor

* chore: support modal watermark

* feat: support nest watermark

* test: add test case

* chore: fix lint

* chore: bump rc-image

* test: add test case

* refactor: use same func
  • Loading branch information
zombieJ authored Aug 8, 2023
1 parent 4fe27ba commit 8a3870f
Show file tree
Hide file tree
Showing 20 changed files with 571 additions and 203 deletions.
2 changes: 1 addition & 1 deletion components/_util/wave/useWave.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import useEvent from 'rc-util/lib/hooks/useEvent';
import { useEvent } from 'rc-util';
import raf from 'rc-util/lib/raf';
import showWaveEffect from './WaveEffect';
import { ConfigContext } from '../../config-provider';
Expand Down
2 changes: 1 addition & 1 deletion components/anchor/Anchor.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import classNames from 'classnames';
import useEvent from 'rc-util/lib/hooks/useEvent';
import { useEvent } from 'rc-util';
import * as React from 'react';
import scrollIntoView from 'scroll-into-view-if-needed';

Expand Down
6 changes: 6 additions & 0 deletions components/drawer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import DrawerPanel from './DrawerPanel';
// CSSINJS
import { NoCompactStyle } from '../space/Compact';
import useStyle from './style';
import { usePanelRef } from '../watermark/context';

const SizeTypes = ['default', 'large'] as const;
type sizeType = typeof SizeTypes[number];
Expand Down Expand Up @@ -137,6 +138,10 @@ const Drawer: React.FC<DrawerProps> & {
motionDeadline: 500,
});

// ============================ Refs ============================
// Select `ant-modal-content` by `panelRef`
const panelRef = usePanelRef();

// =========================== Render ===========================
return wrapSSR(
<NoCompactStyle>
Expand All @@ -157,6 +162,7 @@ const Drawer: React.FC<DrawerProps> & {
rootClassName={drawerClassName}
getContainer={getContainer}
afterOpenChange={afterOpenChange ?? afterVisibleChange}
panelRef={panelRef}
>
<DrawerPanel prefixCls={prefixCls} {...rest} onClose={onClose} />
</RcDrawer>
Expand Down
4 changes: 2 additions & 2 deletions components/dropdown/dropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import RightOutlined from '@ant-design/icons/RightOutlined';
import classNames from 'classnames';
import RcDropdown from 'rc-dropdown';
import useEvent from 'rc-util/lib/hooks/useEvent';
import { useEvent } from 'rc-util';
import useMergedState from 'rc-util/lib/hooks/useMergedState';
import omit from 'rc-util/lib/omit';
import * as React from 'react';
Expand All @@ -28,7 +28,7 @@ const Placements = [
'bottom',
] as const;

type Placement = (typeof Placements)[number];
type Placement = typeof Placements[number];
type DropdownPlacement = Exclude<Placement, 'topCenter' | 'bottomCenter'>;

type OverlayFunc = () => React.ReactElement;
Expand Down
2 changes: 1 addition & 1 deletion components/menu/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import EllipsisOutlined from '@ant-design/icons/EllipsisOutlined';
import classNames from 'classnames';
import type { MenuProps as RcMenuProps, MenuRef as RcMenuRef } from 'rc-menu';
import RcMenu from 'rc-menu';
import useEvent from 'rc-util/lib/hooks/useEvent';
import { useEvent } from 'rc-util';
import omit from 'rc-util/lib/omit';
import * as React from 'react';
import { forwardRef } from 'react';
Expand Down
7 changes: 7 additions & 0 deletions components/modal/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { NoCompactStyle } from '../space/Compact';
import type { ModalProps, MousePosition } from './interface';
import { Footer, renderCloseIcon } from './shared';
import useStyle from './style';
import { usePanelRef } from '../watermark/context';

let mousePosition: MousePosition;

Expand Down Expand Up @@ -103,6 +104,11 @@ const Modal: React.FC<ModalProps> = (props) => {
true,
);

// ============================ Refs ============================
// Select `ant-modal-content` by `panelRef`
const panelRef = usePanelRef(`.${prefixCls}-content`);

// =========================== Render ===========================
return wrapSSR(
<NoCompactStyle>
<NoFormStyle status override>
Expand All @@ -124,6 +130,7 @@ const Modal: React.FC<ModalProps> = (props) => {
maskTransitionName={getTransitionName(rootPrefixCls, 'fade', props.maskTransitionName)}
className={classNames(hashId, className, modal?.className)}
style={{ ...modal?.style, ...style }}
panelRef={panelRef}
/>
</NoFormStyle>
</NoCompactStyle>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1233,3 +1233,47 @@ exports[`renders components/watermark/demo/multi-line.tsx extend context correct
`;

exports[`renders components/watermark/demo/multi-line.tsx extend context correctly 2`] = `[]`;

exports[`renders components/watermark/demo/portal.tsx extend context correctly 1`] = `
Array [
<div
class="ant-space ant-space-horizontal ant-space-align-center"
>
<div
class="ant-space-item"
style="margin-right: 8px;"
>
<button
class="ant-btn ant-btn-default"
type="button"
>
<span>
Show Modal
</span>
</button>
</div>
<div
class="ant-space-item"
>
<button
class="ant-btn ant-btn-default"
type="button"
>
<span>
Show Drawer
</span>
</button>
</div>
</div>,
<div
class=""
style="position: relative;"
>
<div
style="z-index: 9; position: absolute; left: 0; top: 0; width: 100%; height: 100%; pointer-events: none; background-repeat: repeat; background-position: 0px 0px; background-image: url('data:image/png;base64,00'); background-size: 220px;"
/>
</div>,
]
`;

exports[`renders components/watermark/demo/portal.tsx extend context correctly 2`] = `[]`;
38 changes: 38 additions & 0 deletions components/watermark/__tests__/__snapshots__/demo.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -795,3 +795,41 @@ exports[`renders components/watermark/demo/multi-line.tsx correctly 1`] = `
/>
</div>
`;

exports[`renders components/watermark/demo/portal.tsx correctly 1`] = `
Array [
<div
class="ant-space ant-space-horizontal ant-space-align-center"
>
<div
class="ant-space-item"
style="margin-right:8px"
>
<button
class="ant-btn ant-btn-default"
type="button"
>
<span>
Show Modal
</span>
</button>
</div>
<div
class="ant-space-item"
>
<button
class="ant-btn ant-btn-default"
type="button"
>
<span>
Show Drawer
</span>
</button>
</div>
</div>,
<div
class=""
style="position:relative"
/>,
]
`;
32 changes: 32 additions & 0 deletions components/watermark/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React from 'react';
import Watermark from '..';
import Modal from '../../modal';
import Drawer from '../../drawer';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
import { render, waitFakeTimer, waitFor } from '../../../tests/utils';
Expand Down Expand Up @@ -94,4 +96,34 @@ describe('Watermark', () => {
await waitFor(() => expect(target).toBeTruthy());
expect(container).toMatchSnapshot();
});

describe('nest component', () => {
function test(name: string, children: React.ReactNode, getWatermarkElement: () => Node) {
it(name, async () => {
const { rerender } = render(<Watermark className="test">{children}</Watermark>);
await waitFakeTimer();

const watermark = getWatermarkElement();

expect(watermark).toHaveStyle({
zIndex: '9',
});

// Not crash when children removed
rerender(<Watermark className="test" />);
});
}

test(
'Modal',
<Modal open />,
() => document.body.querySelector('.ant-modal-content')!.lastChild!,
);

test(
'Drawer',
<Drawer open />,
() => document.body.querySelector('.ant-drawer-content')!.lastChild!,
);
});
});
33 changes: 33 additions & 0 deletions components/watermark/context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { useEvent } from 'rc-util';
import * as React from 'react';

export interface WatermarkContextProps {
add: (ele: HTMLElement) => void;
remove: (ele: HTMLElement) => void;
}

function voidFunc() {}

const WatermarkContext = React.createContext<WatermarkContextProps>({
add: voidFunc,
remove: voidFunc,
});

export function usePanelRef(panelSelector?: string) {
const watermark = React.useContext(WatermarkContext);

const panelEleRef = React.useRef<HTMLElement>();
const panelRef = useEvent((ele: HTMLElement | null) => {
if (ele) {
const innerContentEle = panelSelector ? ele.querySelector<HTMLElement>(panelSelector)! : ele;
watermark.add(innerContentEle);
panelEleRef.current = innerContentEle;
} else {
watermark.remove(panelEleRef.current!);
}
});

return panelRef;
}

export default WatermarkContext;
7 changes: 7 additions & 0 deletions components/watermark/demo/portal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## zh-CN

在 Modal 与 Drawer 中使用。

## en-US

Use in Modal and Drawer.
50 changes: 50 additions & 0 deletions components/watermark/demo/portal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react';
import { Watermark, Modal, Drawer, Button, Space } from 'antd';

const placeholder = (
<div
style={{
height: 300,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
background: 'rgba(150, 150, 150, 0.2)',
}}
>
A mock height
</div>
);

const App: React.FC = () => {
const [showModal, setShowModal] = React.useState(false);
const [showDrawer, setShowDrawer] = React.useState(false);

const closeModal = () => setShowModal(false);
const closeDrawer = () => setShowDrawer(false);

return (
<>
<Space>
<Button onClick={() => setShowModal(true)}>Show Modal</Button>
<Button onClick={() => setShowDrawer(true)}>Show Drawer</Button>
</Space>

<Watermark content="Ant Design">
<Modal
destroyOnClose
open={showModal}
title="Modal"
onCancel={closeModal}
onOk={closeModal}
>
{placeholder}
</Modal>
<Drawer destroyOnClose open={showDrawer} title="Drawer" onClose={closeDrawer}>
{placeholder}
</Drawer>
</Watermark>
</>
);
};

export default App;
1 change: 1 addition & 0 deletions components/watermark/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Add specific text or patterns to the page.
<code src="./demo/multi-line.tsx">Multi-line watermark</code>
<code src="./demo/image.tsx">Image watermark</code>
<code src="./demo/custom.tsx">Custom configuration</code>
<code src="./demo/portal.tsx">Modal or Drawer</code>

## API

Expand Down
Loading

0 comments on commit 8a3870f

Please sign in to comment.