Merge branch 'master' into feature-merge-master

This commit is contained in:
MadCcc 2023-01-10 17:43:13 +08:00
commit 43541cb6d9
13 changed files with 91 additions and 161 deletions

View File

@ -25,7 +25,12 @@ const DemoWrapper: typeof DumiDemoGrid = ({ items }) => {
const visibleDemos = showDebug ? items : items.filter((item) => !item.previewerProps.debug); const visibleDemos = showDebug ? items : items.filter((item) => !item.previewerProps.debug);
const filteredItems = visibleDemos.map((item) => ({ const filteredItems = visibleDemos.map((item) => ({
...item, ...item,
previewerProps: { ...item.previewerProps, expand: expandAll }, previewerProps: {
...item.previewerProps,
expand: expandAll,
// always override debug property, because dumi will hide debug demo in production
debug: false,
},
})); }));
return ( return (

View File

@ -2,7 +2,7 @@ import React, { useCallback, useContext, useEffect, useMemo, useRef, useState }
import { useLocation } from 'dumi'; import { useLocation } from 'dumi';
import DumiSearchBar from 'dumi/theme-default/slots/SearchBar'; import DumiSearchBar from 'dumi/theme-default/slots/SearchBar';
import classNames from 'classnames'; import classNames from 'classnames';
import { Col, Modal, Popover, Row, Select, Typography } from 'antd'; import { Col, Modal, Popover, Row, Select } from 'antd';
import { GithubOutlined, MenuOutlined } from '@ant-design/icons'; import { GithubOutlined, MenuOutlined } from '@ant-design/icons';
import { ClassNames, css } from '@emotion/react'; import { ClassNames, css } from '@emotion/react';
import * as utils from '../../utils'; import * as utils from '../../utils';
@ -24,17 +24,6 @@ const { Option } = Select;
const antdVersion: string = packageJson.version; const antdVersion: string = packageJson.version;
const locales = {
cn: {
title: '🎉🎉🎉 Ant Design 5.0 发布! 🎉🎉🎉',
ok: '知道了',
},
en: {
title: '🎉🎉🎉 Ant Design 5.0 is released! 🎉🎉🎉',
ok: 'Got it',
},
};
const useStyle = () => { const useStyle = () => {
const { token } = useSiteToken(); const { token } = useSiteToken();
const searchIconColor = '#ced4d9'; const searchIconColor = '#ced4d9';
@ -120,7 +109,6 @@ const useStyle = () => {
}; };
}; };
const V5_NOTIFICATION = 'antd@4.0.0-notification-sent';
const SHOULD_OPEN_ANT_DESIGN_MIRROR_MODAL = 'ANT_DESIGN_DO_NOT_OPEN_MIRROR_MODAL'; const SHOULD_OPEN_ANT_DESIGN_MIRROR_MODAL = 'ANT_DESIGN_DO_NOT_OPEN_MIRROR_MODAL';
function disableAntdMirrorModal() { function disableAntdMirrorModal() {
@ -140,33 +128,7 @@ interface HeaderState {
// ================================= Header ================================= // ================================= Header =================================
const Header: React.FC = () => { const Header: React.FC = () => {
const [isClient, setIsClient] = React.useState(false); const [isClient, setIsClient] = React.useState(false);
const [locale, lang] = useLocale(locales); const [, lang] = useLocale();
const { token } = useSiteToken();
const [notify, setNotify] = React.useState<null | boolean>(null);
// ========================= 发布通知 开始 =========================
React.useEffect(() => {
if (utils.isLocalStorageNameSupported()) {
// 大版本发布后全局弹窗提示
// 1. 点击『知道了』之后不再提示
// 2. 超过截止日期后不再提示
if (
localStorage.getItem(V5_NOTIFICATION) !== 'true' &&
Date.now() < new Date('2022/12/31').getTime()
) {
setNotify(true);
return;
}
}
setNotify(false);
}, []);
function onClose() {
setNotify(false);
localStorage.setItem(V5_NOTIFICATION, 'true');
}
// ========================= 发布通知 结束 =========================
const themeConfig = getThemeConfig(); const themeConfig = getThemeConfig();
const [headerState, setHeaderState] = useState<HeaderState>({ const [headerState, setHeaderState] = useState<HeaderState>({
@ -322,60 +284,20 @@ const Header: React.FC = () => {
/> />
); );
let menu: (React.ReactElement | null)[] = [ let menu: React.ReactNode[] = [
navigationNode, navigationNode,
<Popover <Select
key="version" key="version"
open={!!notify} className="version"
title={locale?.title} size="small"
content={ defaultValue={antdVersion}
<Typography style={{ marginTop: token.marginXS }}> onChange={handleVersionChange}
{lang === 'cn' ? ( dropdownStyle={getDropdownStyle}
<> dropdownMatchSelectWidth={false}
<div> getPopupContainer={(trigger) => trigger.parentNode}
{' '}
<Typography.Link
target="_blank"
href="https://github.com/ant-design/ant-design/issues/38463"
>
GitHub Issue
</Typography.Link>{' '}
</div>
<div> v4 </div>
</>
) : (
<>
<div>
If you find any official site problem. Please feel free to report on{' '}
<Typography.Link
target="_blank"
href="https://github.com/ant-design/ant-design/issues/38463"
>
GitHub Issue
</Typography.Link>
.
</div>
<p>Click above Select to switch to v4 docs.</p>
</>
)}
</Typography>
}
> >
<Select {versionOptions}
key="version" </Select>,
className="version"
size="small"
defaultValue={antdVersion}
onChange={handleVersionChange}
dropdownStyle={getDropdownStyle}
dropdownMatchSelectWidth={false}
getPopupContainer={(trigger) => trigger.parentNode}
onClick={onClose}
>
{versionOptions}
</Select>
</Popover>,
<More key="more" {...sharedProps} />, <More key="more" {...sharedProps} />,
<SwitchBtn <SwitchBtn
key="lang" key="lang"

View File

@ -15,6 +15,14 @@ timeline: true
--- ---
## 5.1.4
`2023-1-9`
- 🐞 Fix missing locale file. [#40116](https://github.com/ant-design/ant-design/pull/40116)
- 🐞 Fix Cascader dropdown `placement` in RTL mode. [#40109](https://github.com/ant-design/ant-design/pull/40109) [@3hson](https://github.com/3hson)
- 🐞 Fix animation flicking in some components. [react-component/motion#39](https://github.com/react-component/motion/pull/39)
## 5.1.3 ## 5.1.3
`2023-1-9` `2023-1-9`

View File

@ -15,6 +15,14 @@ timeline: true
--- ---
## 5.1.4
`2023-1-9`
- 🐞 修复 locale 文件丢失的问题。[#40116](https://github.com/ant-design/ant-design/pull/40116)
- 🐞 修复 Cascader 组件 RTL 模式中下拉菜单位置问题。[#40109](https://github.com/ant-design/ant-design/pull/40109) [@3hson](https://github.com/3hson)
- 🐞 修复部分组件动画闪烁的问题。[react-component/motion#39](https://github.com/react-component/motion/pull/39)
## 5.1.3 ## 5.1.3
`2023-1-9` `2023-1-9`

View File

@ -272,9 +272,7 @@ const Cascader = React.forwardRef((props: CascaderProps<any>, ref: React.Ref<Cas
if (placement !== undefined) { if (placement !== undefined) {
return placement; return placement;
} }
return direction === 'rtl' return isRtl ? 'bottomRight' : 'bottomLeft';
? ('bottomRight' as SelectCommonPlacement)
: ('bottomLeft' as SelectCommonPlacement);
}; };
// ==================== Render ===================== // ==================== Render =====================

View File

@ -104,7 +104,8 @@ We added a `createFromIconfontCN` function to help developer use their own icons
> This method is specified for [iconfont.cn](http://iconfont.cn/). > This method is specified for [iconfont.cn](http://iconfont.cn/).
```js ```jsx
import React from 'react';
import { createFromIconfontCN } from '@ant-design/icons'; import { createFromIconfontCN } from '@ant-design/icons';
const MyIcon = createFromIconfontCN({ const MyIcon = createFromIconfontCN({
@ -133,7 +134,8 @@ You can import SVG icon as a react component by using `webpack` and [`@svgr/webp
```js ```js
// webpack.config.js // webpack.config.js
{ module.exports = {
// ... other config
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
use: [ use: [
{ {
@ -147,7 +149,7 @@ You can import SVG icon as a react component by using `webpack` and [`@svgr/webp
}, },
}, },
], ],
} };
``` ```
```jsx ```jsx

View File

@ -99,7 +99,8 @@ getTwoToneColor(); // #eb2f96
`3.9.0` 之后,我们提供了一个 `createFromIconfontCN` 方法,方便开发者调用在 [iconfont.cn](http://iconfont.cn/) 上自行管理的图标。 `3.9.0` 之后,我们提供了一个 `createFromIconfontCN` 方法,方便开发者调用在 [iconfont.cn](http://iconfont.cn/) 上自行管理的图标。
```js ```jsx
import React from 'react';
import { createFromIconfontCN } from '@ant-design/icons'; import { createFromIconfontCN } from '@ant-design/icons';
const MyIcon = createFromIconfontCN({ const MyIcon = createFromIconfontCN({
@ -128,7 +129,8 @@ options 的配置项如下:
```js ```js
// webpack.config.js // webpack.config.js
{ module.exports = {
// ... other config
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
use: [ use: [
{ {
@ -142,7 +144,7 @@ options 的配置项如下:
}, },
}, },
], ],
} };
``` ```
```jsx ```jsx

View File

@ -2,7 +2,7 @@ import React from 'react';
import Watermark from '..'; import Watermark from '..';
import mountTest from '../../../tests/shared/mountTest'; import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest'; import rtlTest from '../../../tests/shared/rtlTest';
import { render, waitFor } from '../../../tests/utils'; import { render, waitFor, waitFakeTimer } from '../../../tests/utils';
describe('Watermark', () => { describe('Watermark', () => {
mountTest(Watermark); mountTest(Watermark);
@ -67,6 +67,7 @@ describe('Watermark', () => {
it('MutationObserver should work properly', async () => { it('MutationObserver should work properly', async () => {
const { container } = render(<Watermark className="watermark" content="MutationObserver" />); const { container } = render(<Watermark className="watermark" content="MutationObserver" />);
const target = container.querySelector<HTMLDivElement>('.watermark div'); const target = container.querySelector<HTMLDivElement>('.watermark div');
await waitFakeTimer();
target?.remove(); target?.remove();
await waitFor(() => expect(target).toBeTruthy()); await waitFor(() => expect(target).toBeTruthy());
expect(container).toMatchSnapshot(); expect(container).toMatchSnapshot();
@ -77,6 +78,7 @@ describe('Watermark', () => {
<Watermark offset={[-200, -200]} className="watermark" content="MutationObserver" />, <Watermark offset={[-200, -200]} className="watermark" content="MutationObserver" />,
); );
const target = container.querySelector<HTMLDivElement>('.watermark div'); const target = container.querySelector<HTMLDivElement>('.watermark div');
await waitFakeTimer();
target?.setAttribute('style', ''); target?.setAttribute('style', '');
await waitFor(() => expect(target).toBeTruthy()); await waitFor(() => expect(target).toBeTruthy());
expect(container).toMatchSnapshot(); expect(container).toMatchSnapshot();

View File

@ -1,6 +1,6 @@
import React, { useEffect, useRef } from 'react'; import React, { useEffect, useRef } from 'react';
import useMutationObserver from './useMutationObserver'; import MutateObserver from '@rc-component/mutate-observer';
import { getStyleStr, getPixelRatio, rotateWatermark } from './utils'; import { getStyleStr, getPixelRatio, rotateWatermark, reRendering } from './utils';
/** /**
* Base size of the canvas, 1 for parallel layout and 2 for alternate layout * Base size of the canvas, 1 for parallel layout and 2 for alternate layout
@ -96,7 +96,7 @@ const Watermark: React.FC<WatermarkProps> = (props) => {
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
const watermarkRef = useRef<HTMLDivElement>(); const watermarkRef = useRef<HTMLDivElement>();
const { createObserver, destroyObserver, reRendering } = useMutationObserver(); const stopObservation = useRef(false);
const destroyWatermark = () => { const destroyWatermark = () => {
if (watermarkRef.current) { if (watermarkRef.current) {
@ -107,7 +107,7 @@ const Watermark: React.FC<WatermarkProps> = (props) => {
const appendWatermark = (base64Url: string, markWidth: number) => { const appendWatermark = (base64Url: string, markWidth: number) => {
if (containerRef.current && watermarkRef.current) { if (containerRef.current && watermarkRef.current) {
destroyObserver(); stopObservation.current = true;
watermarkRef.current.setAttribute( watermarkRef.current.setAttribute(
'style', 'style',
getStyleStr({ getStyleStr({
@ -117,14 +117,9 @@ const Watermark: React.FC<WatermarkProps> = (props) => {
}), }),
); );
containerRef.current?.append(watermarkRef.current); containerRef.current?.append(watermarkRef.current);
createObserver(containerRef.current, (mutations) => { // Delayed execution
mutations.forEach((mutation) => { setTimeout(() => {
if (reRendering(mutation, watermarkRef.current)) { stopObservation.current = false;
destroyWatermark();
// eslint-disable-next-line @typescript-eslint/no-use-before-define
renderWatermark();
}
});
}); });
} }
}; };
@ -221,6 +216,18 @@ const Watermark: React.FC<WatermarkProps> = (props) => {
} }
}; };
const onMutate = (mutations: MutationRecord[]) => {
if (stopObservation.current) {
return;
}
mutations.forEach((mutation) => {
if (reRendering(mutation, watermarkRef.current)) {
destroyWatermark();
renderWatermark();
}
});
};
useEffect(renderWatermark, [ useEffect(renderWatermark, [
rotate, rotate,
zIndex, zIndex,
@ -240,9 +247,11 @@ const Watermark: React.FC<WatermarkProps> = (props) => {
]); ]);
return ( return (
<div ref={containerRef} className={className} style={{ position: 'relative', ...style }}> <MutateObserver onMutate={onMutate}>
{children} <div ref={containerRef} className={className} style={{ position: 'relative', ...style }}>
</div> {children}
</div>
</MutateObserver>
); );
}; };

View File

@ -1,42 +0,0 @@
import { useEffect, useRef } from 'react';
export default function useMutationObserver() {
const instance = useRef<MutationObserver>();
const destroyObserver = () => {
if (instance.current) {
instance.current.takeRecords();
instance.current.disconnect();
instance.current = undefined;
}
};
const createObserver = (target: Node, callback: MutationCallback) => {
if (MutationObserver) {
destroyObserver();
instance.current = new MutationObserver(callback);
instance.current.observe(target, {
childList: true,
subtree: true,
attributeFilter: ['style', 'class'],
});
}
};
useEffect(() => destroyObserver, []);
const reRendering = (mutation: MutationRecord, watermarkElement?: HTMLElement) => {
let flag = false;
// Whether to delete the watermark node
if (mutation.removedNodes.length) {
flag = Array.from(mutation.removedNodes).some((node) => node === watermarkElement);
}
// Whether the watermark dom property value has been modified
if (mutation.type === 'attributes' && mutation.target === watermarkElement) {
flag = true;
}
return flag;
};
return { createObserver, destroyObserver, reRendering };
}

View File

@ -25,3 +25,17 @@ export function rotateWatermark(
ctx.rotate((Math.PI / 180) * Number(rotate)); ctx.rotate((Math.PI / 180) * Number(rotate));
ctx.translate(-rotateX, -rotateY); ctx.translate(-rotateX, -rotateY);
} }
/** Whether to re-render the watermark */
export const reRendering = (mutation: MutationRecord, watermarkElement?: HTMLElement) => {
let flag = false;
// Whether to delete the watermark node
if (mutation.removedNodes.length) {
flag = Array.from(mutation.removedNodes).some((node) => node === watermarkElement);
}
// Whether the watermark dom property value has been modified
if (mutation.type === 'attributes' && mutation.target === watermarkElement) {
flag = true;
}
return flag;
};

View File

@ -1,6 +1,6 @@
{ {
"name": "antd", "name": "antd",
"version": "5.1.3", "version": "5.1.4",
"description": "An enterprise-class UI design language and React components implementation", "description": "An enterprise-class UI design language and React components implementation",
"title": "Ant Design", "title": "Ant Design",
"keywords": [ "keywords": [
@ -113,6 +113,7 @@
"@ant-design/react-slick": "~1.0.0", "@ant-design/react-slick": "~1.0.0",
"@babel/runtime": "^7.18.3", "@babel/runtime": "^7.18.3",
"@ctrl/tinycolor": "^3.4.0", "@ctrl/tinycolor": "^3.4.0",
"@rc-component/mutate-observer": "^1.0.0",
"@rc-component/tour": "~1.4.0", "@rc-component/tour": "~1.4.0",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"copy-to-clipboard": "^3.2.0", "copy-to-clipboard": "^3.2.0",
@ -155,7 +156,7 @@
"throttle-debounce": "^5.0.0" "throttle-debounce": "^5.0.0"
}, },
"devDependencies": { "devDependencies": {
"@ant-design/tools": "^17.0.0-alpha.5", "@ant-design/tools": "^17.0.0-alpha.7",
"@babel/eslint-plugin": "^7.19.1", "@babel/eslint-plugin": "^7.19.1",
"@emotion/babel-preset-css-prop": "^11.10.0", "@emotion/babel-preset-css-prop": "^11.10.0",
"@emotion/css": "^11.10.5", "@emotion/css": "^11.10.5",

View File

@ -27,6 +27,7 @@ const DEPRECIATED_VERSION = {
'5.0.6': ['https://github.com/ant-design/ant-design/issues/39807'], '5.0.6': ['https://github.com/ant-design/ant-design/issues/39807'],
'5.1.0': ['https://github.com/react-component/drawer/pull/370'], '5.1.0': ['https://github.com/react-component/drawer/pull/370'],
'5.1.2': ['https://github.com/ant-design/ant-design/issues/39949'], '5.1.2': ['https://github.com/ant-design/ant-design/issues/39949'],
'5.1.3': ['https://github.com/ant-design/ant-design/issues/40113'],
}; };
function matchDeprecated(version) { function matchDeprecated(version) {