refactor: Watermark add overflow hidden style to avoid visible show (#49130)

* refactor: add overflow style

* test: add test case
This commit is contained in:
二货爱吃白萝卜 2024-05-30 19:53:02 +08:00 committed by GitHub
parent d4c5cb66de
commit b4a98273fb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 83 additions and 44 deletions

View File

@ -3,7 +3,7 @@
exports[`renders components/watermark/demo/basic.tsx extend context correctly 1`] = `
<div
class=""
style="position: relative;"
style="position: relative; overflow: hidden;"
>
<div
style="height: 500px;"
@ -22,7 +22,7 @@ exports[`renders components/watermark/demo/custom.tsx extend context correctly 1
>
<div
class=""
style="position: relative;"
style="position: relative; overflow: hidden;"
>
<article
class="ant-typography"
@ -1196,7 +1196,7 @@ exports[`renders components/watermark/demo/custom.tsx extend context correctly 2
exports[`renders components/watermark/demo/image.tsx extend context correctly 1`] = `
<div
class=""
style="position: relative;"
style="position: relative; overflow: hidden;"
>
<div
style="height: 500px;"
@ -1209,7 +1209,7 @@ exports[`renders components/watermark/demo/image.tsx extend context correctly 2`
exports[`renders components/watermark/demo/multi-line.tsx extend context correctly 1`] = `
<div
class=""
style="position: relative;"
style="position: relative; overflow: hidden;"
>
<div
style="height: 500px;"
@ -1254,7 +1254,7 @@ Array [
</div>,
<div
class=""
style="position: relative;"
style="position: relative; overflow: hidden;"
>
<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: 218px; visibility: visible !important;"
@ -1262,7 +1262,7 @@ Array [
</div>,
<div
class=""
style="position: relative;"
style="position: relative; overflow: hidden;"
>
<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: 218px; visibility: visible !important;"

View File

@ -3,7 +3,7 @@
exports[`renders components/watermark/demo/basic.tsx correctly 1`] = `
<div
class=""
style="position:relative"
style="position:relative;overflow:hidden"
>
<div
style="height:500px"
@ -17,7 +17,7 @@ exports[`renders components/watermark/demo/custom.tsx correctly 1`] = `
>
<div
class=""
style="position:relative"
style="position:relative;overflow:hidden"
>
<article
class="ant-typography"
@ -761,7 +761,7 @@ exports[`renders components/watermark/demo/custom.tsx correctly 1`] = `
exports[`renders components/watermark/demo/image.tsx correctly 1`] = `
<div
class=""
style="position:relative"
style="position:relative;overflow:hidden"
>
<div
style="height:500px"
@ -772,7 +772,7 @@ exports[`renders components/watermark/demo/image.tsx correctly 1`] = `
exports[`renders components/watermark/demo/multi-line.tsx correctly 1`] = `
<div
class=""
style="position:relative"
style="position:relative;overflow:hidden"
>
<div
style="height:500px"
@ -812,11 +812,11 @@ Array [
</div>,
<div
class=""
style="position:relative"
style="position:relative;overflow:hidden"
/>,
<div
class=""
style="position:relative"
style="position:relative;overflow:hidden"
/>,
]
`;

View File

@ -4,7 +4,7 @@ exports[`Watermark Image watermark snapshot 1`] = `
<div>
<div
class=""
style="position: relative;"
style="position: relative; overflow: hidden;"
>
<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: 470px; visibility: visible !important;"
@ -17,7 +17,7 @@ exports[`Watermark Interleaved watermark backgroundSize is correct 1`] = `
<div>
<div
class="watermark"
style="position: relative;"
style="position: relative; overflow: hidden;"
>
<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: 720px; visibility: visible !important;"
@ -30,7 +30,7 @@ exports[`Watermark Invalid image watermark 1`] = `
<div>
<div
class="watermark"
style="position: relative;"
style="position: relative; overflow: hidden;"
>
<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: 470px; visibility: visible !important;"
@ -43,7 +43,7 @@ exports[`Watermark MutationObserver should work properly 1`] = `
<div>
<div
class="watermark"
style="position: relative;"
style="position: relative; overflow: hidden;"
>
<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: 229px; visibility: visible !important;"
@ -52,11 +52,11 @@ exports[`Watermark MutationObserver should work properly 1`] = `
</div>
`;
exports[`Watermark Observe the modification of style 1`] = `
exports[`Watermark Observe the modification of style watermark 1`] = `
<div>
<div
class="watermark"
style="position: relative;"
style="position: relative; overflow: hidden;"
>
<div
style="z-index: 9; position: absolute; left: 0; top: 0; width: 100%; height: 100%; pointer-events: none; background-repeat: repeat; background-position: -250px -250px; background-image: url('data:image/png;base64,00'); background-size: 229px; visibility: visible !important;"
@ -69,7 +69,7 @@ exports[`Watermark The offset should be correct 1`] = `
<div>
<div
class="watermark"
style="position: relative;"
style="position: relative; overflow: hidden;"
>
<div
style="z-index: 9; position: absolute; left: 150px; top: 150px; width: calc(100% - 150px); height: calc(100% - 150px); pointer-events: none; background-repeat: repeat; background-position: 0px 0px; background-image: url('data:image/png;base64,00'); background-size: 228px; visibility: visible !important;"
@ -82,7 +82,7 @@ exports[`Watermark The watermark should render successfully 1`] = `
<div>
<div
class="watermark"
style="position: relative;"
style="position: relative; overflow: hidden;"
>
<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: 218px; visibility: visible !important;"
@ -94,7 +94,7 @@ exports[`Watermark The watermark should render successfully 1`] = `
exports[`Watermark rtl render component should be rendered correctly in RTL direction 1`] = `
<div
class=""
style="position: relative;"
style="position: relative; overflow: hidden;"
>
<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: 200px; visibility: visible !important;"

View File

@ -97,15 +97,32 @@ describe('Watermark', () => {
expect(container).toMatchSnapshot();
});
it('Observe the modification of style', async () => {
const { container } = render(
<Watermark offset={[-200, -200]} className="watermark" content="MutationObserver" />,
);
const target = container.querySelector<HTMLDivElement>('.watermark div');
await waitFakeTimer();
target?.setAttribute('style', '');
await waitFakeTimer();
expect(container).toMatchSnapshot();
describe('Observe the modification of style', () => {
it('watermark', async () => {
const { container } = render(
<Watermark offset={[-200, -200]} className="watermark" content="MutationObserver" />,
);
const target = container.querySelector<HTMLDivElement>('.watermark div');
await waitFakeTimer();
target?.setAttribute('style', '');
await waitFakeTimer();
expect(container).toMatchSnapshot();
});
it('container', async () => {
const { container } = render(
<Watermark offset={[-200, -200]} className="watermark" content="MutationObserver" />,
);
const target = container.querySelector<HTMLDivElement>('.watermark');
await waitFakeTimer();
target?.setAttribute('style', '');
await waitFakeTimer();
expect(target).toHaveStyle({
overflow: 'hidden',
});
});
});
describe('nest component', () => {

View File

@ -1,6 +1,7 @@
import React, { useEffect } from 'react';
import { useMutateObserver } from '@rc-component/mutate-observer';
import classNames from 'classnames';
import { useEvent } from 'rc-util';
import { useToken } from '../theme/internal';
import WatermarkContext from './context';
@ -45,6 +46,11 @@ function getSizeDiff<T>(prev: Set<T>, next: Set<T>) {
const DEFAULT_GAP_X = 100;
const DEFAULT_GAP_Y = 100;
const fixedStyle: React.CSSProperties = {
position: 'relative',
overflow: 'hidden',
};
const Watermark: React.FC<WatermarkProps> = (props) => {
const {
/**
@ -66,6 +72,12 @@ const Watermark: React.FC<WatermarkProps> = (props) => {
children,
inherit = true,
} = props;
const mergedStyle = {
...fixedStyle,
...style,
};
const [, token] = useToken();
const {
color = token.colorFill,
@ -83,7 +95,7 @@ const Watermark: React.FC<WatermarkProps> = (props) => {
const offsetTop = offset?.[1] ?? gapYCenter;
const markStyle = React.useMemo(() => {
const mergedStyle: React.CSSProperties = {
const mergedMarkStyle: React.CSSProperties = {
zIndex,
position: 'absolute',
left: 0,
@ -98,18 +110,18 @@ const Watermark: React.FC<WatermarkProps> = (props) => {
let positionLeft = offsetLeft - gapXCenter;
let positionTop = offsetTop - gapYCenter;
if (positionLeft > 0) {
mergedStyle.left = `${positionLeft}px`;
mergedStyle.width = `calc(100% - ${positionLeft}px)`;
mergedMarkStyle.left = `${positionLeft}px`;
mergedMarkStyle.width = `calc(100% - ${positionLeft}px)`;
positionLeft = 0;
}
if (positionTop > 0) {
mergedStyle.top = `${positionTop}px`;
mergedStyle.height = `calc(100% - ${positionTop}px)`;
mergedMarkStyle.top = `${positionTop}px`;
mergedMarkStyle.height = `calc(100% - ${positionTop}px)`;
positionTop = 0;
}
mergedStyle.backgroundPosition = `${positionLeft}px ${positionTop}px`;
mergedMarkStyle.backgroundPosition = `${positionLeft}px ${positionTop}px`;
return mergedStyle;
return mergedMarkStyle;
}, [zIndex, offsetLeft, gapXCenter, offsetTop, gapYCenter]);
const [container, setContainer] = React.useState<HTMLDivElement | null>();
@ -218,13 +230,27 @@ const Watermark: React.FC<WatermarkProps> = (props) => {
}, [watermarkInfo, targetElements]);
// ============================ Observe =============================
const onMutate = (mutations: MutationRecord[]) => {
const onMutate = useEvent((mutations: MutationRecord[]) => {
mutations.forEach((mutation) => {
if (reRendering(mutation, isWatermarkEle)) {
syncWatermark();
} else if (mutation.target === container && mutation.attributeName === 'style') {
// We've only force container not modify.
// Not consider nest case.
const keyStyles = Object.keys(fixedStyle);
for (let i = 0; i < keyStyles.length; i += 1) {
const key = keyStyles[i];
const oriValue = (mergedStyle as any)[key];
const currentValue = (container.style as any)[key];
if (oriValue && oriValue !== currentValue) {
(container.style as any)[key] = oriValue;
}
}
}
});
};
});
useMutateObserver(targetElements, onMutate);
@ -279,11 +305,7 @@ const Watermark: React.FC<WatermarkProps> = (props) => {
);
return (
<div
ref={setContainer}
className={classNames(className, rootClassName)}
style={{ position: 'relative', ...style }}
>
<div ref={setContainer} className={classNames(className, rootClassName)} style={mergedStyle}>
{childNode}
</div>
);