diff --git a/.dumi/rehypeAntd.ts b/.dumi/rehypeAntd.ts index 9db6f65717..fa4733585f 100644 --- a/.dumi/rehypeAntd.ts +++ b/.dumi/rehypeAntd.ts @@ -64,6 +64,8 @@ function rehypeAntd(): UnifiedTransformer { const { tagName } = node; node.properties.sourceType = tagName; node.tagName = 'LocaleLink'; + } else if (node.type === 'element' && node.tagName === 'video') { + node.tagName = 'VideoPlayer'; } }); }; diff --git a/.dumi/theme/builtins/IconSearch/fields.ts b/.dumi/theme/builtins/IconSearch/fields.ts index e86cd40639..f171a94065 100644 --- a/.dumi/theme/builtins/IconSearch/fields.ts +++ b/.dumi/theme/builtins/IconSearch/fields.ts @@ -165,9 +165,11 @@ const logo = [ 'Weibo', 'Twitter', 'Wechat', + 'WhatsApp', 'Youtube', 'AlipayCircle', 'Taobao', + 'Dingtalk', 'Skype', 'Qq', 'MediumWorkmark', diff --git a/.dumi/theme/builtins/ImagePreview/index.tsx b/.dumi/theme/builtins/ImagePreview/index.tsx index 7ea701a689..7143082cce 100644 --- a/.dumi/theme/builtins/ImagePreview/index.tsx +++ b/.dumi/theme/builtins/ImagePreview/index.tsx @@ -5,6 +5,9 @@ import toArray from 'rc-util/lib/Children/toArray'; interface ImagePreviewProps { children: React.ReactNode[]; + className?: string; + /** Do not show padding & background */ + pure?: boolean; } function isGood(className: string): boolean { @@ -26,9 +29,8 @@ function isGoodBadImg(imgMeta: any): boolean { function isCompareImg(imgMeta: any): boolean { return isGoodBadImg(imgMeta) || imgMeta.inline; } - const ImagePreview: React.FC = (props) => { - const { children } = props; + const { children, className: rootClassName, pure } = props; const imgs = toArray(children).filter((ele) => ele.type === 'img'); const imgsMeta = imgs.map((img) => { @@ -67,21 +69,33 @@ const ImagePreview: React.FC = (props) => { : {}; const hasCarousel = imgs.length > 1 && !comparable; - const previewClassName = classNames({ + const previewClassName = classNames(rootClassName, { 'preview-image-boxes': true, clearfix: true, 'preview-image-boxes-compare': comparable, 'preview-image-boxes-with-carousel': hasCarousel, }); + // ===================== Render ===================== + const imgWrapperCls = 'preview-image-wrapper'; + return (
+ {!imgs.length && ( +
+ {children} +
+ )} + {imagesList.map((_, index) => { if (!comparable && index !== 0) { return null; } const coverMeta = imgsMeta[index]; - const imageWrapperClassName = classNames('preview-image-wrapper', { + const imageWrapperClassName = classNames(imgWrapperCls, { good: coverMeta.isGood, bad: coverMeta.isBad, }); diff --git a/.dumi/theme/builtins/TokenCompare/index.tsx b/.dumi/theme/builtins/TokenCompare/index.tsx new file mode 100644 index 0000000000..7650855e1c --- /dev/null +++ b/.dumi/theme/builtins/TokenCompare/index.tsx @@ -0,0 +1,119 @@ +// 用于 color.md 中的颜色对比 +import React from 'react'; +import classNames from 'classnames'; +import { theme, Space } from 'antd'; +import { TinyColor } from '@ctrl/tinycolor'; +import tokenMeta from 'antd/es/version/token-meta.json'; +import { createStyles } from 'antd-style'; +import useLocale from '../../../hooks/useLocale'; + +const useStyle = createStyles(({ token, css }) => { + const height = token.controlHeightLG; + const dotSize = height / 5; + + return { + container: css` + background: #fff; + border-radius: ${token.borderRadiusLG}px; + overflow: hidden; + `, + + row: css` + display: flex; + align-items: center; + `, + + col: css` + flex: 1 1 33%; + height: ${height}px; + display: flex; + align-items: center; + justify-content: center; + + border-right: 1px solid rgba(0, 0, 0, 0.1); + `, + + colDark: css` + background: #000; + color: #fff; + `, + + dot: css` + border-radius: 100%; + width: ${dotSize}px; + height: ${dotSize}px; + background: #000; + box-shadow: 0 0 0 1px rgba(150, 150, 150, 0.25); + `, + + dotColor: css` + width: ${token.fontSize * 6}px; + white-space: nowrap; + `, + }; +}); + +function color2Rgba(color: string) { + return `#${new TinyColor(color).toHex8().toUpperCase()}`; +} + +interface ColorCircleProps { + color?: string; +} + +function ColorCircle({ color }: ColorCircleProps) { + const { styles } = useStyle(); + + return ( + +
+
{color}
+ + ); +} + +export interface TokenCompareProps { + tokenNames?: string; +} + +export default function TokenCompare(props: TokenCompareProps) { + const { tokenNames = '' } = props; + const [, lang] = useLocale({}); + const { styles } = useStyle(); + + const tokenList = React.useMemo(() => { + const list = tokenNames.split('|'); + + const lightTokens = theme.getDesignToken(); + const darkTokens = theme.getDesignToken({ + algorithm: theme.darkAlgorithm, + }); + + return list.map((tokenName) => { + const meta = tokenMeta.global[tokenName]; + const name = lang === 'cn' ? meta.name : meta.nameEn; + + return { + name: name.replace('颜色', '').replace('色', '').replace('Color', '').trim(), + light: color2Rgba(lightTokens[tokenName]), + dark: color2Rgba(darkTokens[tokenName]), + }; + }); + }, [tokenNames]); + + return ( +
+ {tokenList.map((data) => ( +
+
{data.name}
+
+ +
+
+ +
+
+ ))} +
+ ); +} diff --git a/.dumi/theme/builtins/VideoPlayer/index.tsx b/.dumi/theme/builtins/VideoPlayer/index.tsx new file mode 100644 index 0000000000..02ef594246 --- /dev/null +++ b/.dumi/theme/builtins/VideoPlayer/index.tsx @@ -0,0 +1,77 @@ +import React from 'react'; +import { createStyles, css } from 'antd-style'; +import classNames from 'classnames'; +import { PlayCircleFilled, PauseCircleFilled } from '@ant-design/icons'; + +const useStyles = createStyles(({ cx, token }) => { + const play = css` + position: absolute; + right: ${token.paddingLG}px; + bottom: ${token.paddingLG}px; + font-size: 64px; + display: flex; + align-items: center; + justify-content: center; + color: rgba(0, 0, 0, 0.65); + opacity: 0; + transition: opacity ${token.motionDurationSlow}; + `; + + return { + container: css` + position: relative; + `, + + holder: css` + position: relative; + cursor: pointer; + + &:hover { + .${cx(play)} { + opacity: 1; + } + } + `, + + video: css` + width: 100%; + `, + + play, + }; +}); + +export default function VideoPlayer({ + className, + ...restProps +}: React.HtmlHTMLAttributes) { + const { styles } = useStyles(); + const videoRef = React.useRef(null); + const [playing, setPlaying] = React.useState(false); + + React.useEffect(() => { + if (playing) { + videoRef.current?.play(); + } else { + videoRef.current?.pause(); + } + }, [playing]); + + return ( +
{ + setPlaying(!playing); + }} + > +
+
+
+ ); +} diff --git a/.dumi/theme/slots/Sidebar/index.tsx b/.dumi/theme/slots/Sidebar/index.tsx index 3a6fb7c367..22c5e78cb8 100644 --- a/.dumi/theme/slots/Sidebar/index.tsx +++ b/.dumi/theme/slots/Sidebar/index.tsx @@ -134,7 +134,9 @@ const Sidebar: React.FC = () => { } = useSiteToken(); const menuChild = ( - + ![](https://gw.alipayobjects.com/zos/antfincdn/5Cl2G7JjF/jieping2022-03-20%252520xiawu11.06.04.png)' + notify_title: '🔥 @${{ github.event.discussion.user.login }} 创建了讨论:${{ github.event.discussion.title }} #${{ github.event.discussion.number }}' + notify_body: '### 🔥 @${{ github.event.discussion.user.login }} 创建了讨论:[${{ github.event.discussion.title }}](${{ github.event.discussion.html_url }})
' notify_footer: '> 💬 欢迎前往 GitHub 进行讨论,社区可能需要你的帮助。' at_all: false # whether to ding everybody diff --git a/.github/workflows/issue-open-check.yml b/.github/workflows/issue-open-check.yml index 98c679cc9d..4925f613f5 100644 --- a/.github/workflows/issue-open-check.yml +++ b/.github/workflows/issue-open-check.yml @@ -99,7 +99,7 @@ jobs: DING_TALK_TOKEN: | ${{ secrets.DINGDING_BOT_TOKEN }} ${{ secrets.DINGDING_BOT_COLLABORATOR_TOKEN }} - notify_title: '🔥 @${{ github.event.issue.user.login }} 创建了 issue:${{ github.event.issue.title }}' - notify_body: '### 🔥 @${{ github.event.issue.user.login }} 创建了 issue:[${{ github.event.issue.title }}](${{ github.event.issue.html_url }})
![](https://gw.alipayobjects.com/zos/antfincdn/5Cl2G7JjF/jieping2022-03-20%252520xiawu11.06.04.png)' + notify_title: '🔥 @${{ github.event.issue.user.login }} 创建了 issue:${{ github.event.issue.title }} #${{ github.event.issue.number }}' + notify_body: '### 🔥 @${{ github.event.issue.user.login }} 创建了 issue:[${{ github.event.issue.title }}](${{ github.event.issue.html_url }})
' notify_footer: '> 💬 欢迎前往 GitHub 进行讨论,社区可能需要你的帮助。' at_all: false # whether to ding everybody diff --git a/CHANGELOG.en-US.md b/CHANGELOG.en-US.md index 8a21f91080..bd26cb9a17 100644 --- a/CHANGELOG.en-US.md +++ b/CHANGELOG.en-US.md @@ -15,6 +15,25 @@ timeline: true --- +## 5.7.1 + +`2023-07-19` + +- 💄 Migrate Component Token of Menu from 4.x less variables. [#43576](https://github.com/ant-design/ant-design/pull/43576) +- 🐞 Fix QRCode throws `Can't resolve 'antd/lib/qr-code'` in Next.js 13. [#43572](https://github.com/ant-design/ant-design/issues/43572) +- 🐞 Fix that antd components usage in Next.js App Router, check the [documentation](/docs/react/use-with-next#using-nextjs-app-router). [#43573](https://github.com/ant-design/ant-design/pull/43573) [@li-jia-nan](https://github.com/li-jia-nan) +- 🐞 Fix InputNumber Phantom dependency issue: `Cannot find module 'rc-component/mini-decimal'`. [#43635](https://github.com/ant-design/ant-design/pull/43635) +- 🐞 Fix Checkbox both set `checked` and `indeterminate` prop will not show as `indeterminate` style. [#43626](https://github.com/ant-design/ant-design/pull/43626) +- 🐞 Fix Form.Item set `label=""` will break the line align. [#43614](https://github.com/ant-design/ant-design/pull/43614) +- 🐞 Fix notification `placement` not being respected when passed via App component. [#43522](https://github.com/ant-design/ant-design/pull/43522) [@Rajil1213](https://github.com/Rajil1213) +- 🐞 Fix Pagination jumpy page size select when search in it. [#43556](https://github.com/ant-design/ant-design/pull/43556) +- 🐞 Fix Button disabled style is missing when use with the deprecated usage of `type="ghost"`. [#43558](https://github.com/ant-design/ant-design/pull/43558) [@kiner-tang](https://github.com/kiner-tang) +- 🐞 Fix Tag extra margin when there is only `icon` inside it. [#43518](https://github.com/ant-design/ant-design/pull/43518) [@Yuiai01](https://github.com/Yuiai01) +- 🐞 Fix ColorPicker that status style is missing inside Form.Item. [#42880](https://github.com/ant-design/ant-design/pull/42880) [@RedJue](https://github.com/RedJue) +- TypeScript + - 🤖 Fix `SpaceContext` don't exported correctly. [#43501](https://github.com/ant-design/ant-design/pull/43501) [@VovkaGoodwin](https://github.com/VovkaGoodwin) + - 🤖 Improve TS definitions for some components. [#43581](https://github.com/ant-design/ant-design/pull/43581) [#43545](https://github.com/ant-design/ant-design/pull/43545) [#43588](https://github.com/ant-design/ant-design/pull/43588) [#43610](https://github.com/ant-design/ant-design/pull/43610) [#43629](https://github.com/ant-design/ant-design/pull/43629). Thanks to [@thinkasany](https://github.com/thinkasany)、[@li-jia-nan](https://github.com/li-jia-nan) for the contributions. + ## 5.7.0 `2023-07-11` @@ -30,30 +49,30 @@ timeline: true - 🆕 Alert, Drawer, Modal, Notifaction, Tag, Tabs now support hiding the close button by setting `closeIcon` to null or false. [#42828](https://github.com/ant-design/ant-design/discussions/42828) [@kiner-tang](https://github.com/kiner-tang) - 🆕 Image supports `imageRender`, `toolbarRender` attributes to support custom rendering of preview images and toolbars, also supports new props such as `onTransform`, `minScale`, `maxScale`. Image.PreviewGroup supports `items` attribute to pass in list data, and fixes that the native attributes of the img tag are not passed to preview images The problem. [#43075](https://github.com/ant-design/ant-design/pull/43075) [@linxianxi](https://github.com/linxianxi) - 🆕 Modify the layout style of the Image preview, the `preview` attribute supports `closeIcon`, Image.PreviewGroup supports the `fallback` attribute, and fixes the problem of loading preview resources in advance. [#43167](https://github.com/ant-design/ant-design/pull/43167) [@linxianxi](https://github.com/linxianxi) -- 🆕 Changed the layout style, Preview now supports `closeIcon`, PreviewGroup now supports `fallback`, and fixed an issue where preview resources would be loaded at the beginning.[#43167](https://github.com/ant-design/ant-design/pull/43167) [@linxianxi](https://github.com/linxianxi) -- 🛠 InputNumber was refactored to use rc-input. (#43000)。[#42762](https://github.com/ant-design/ant-design/pull/43000) [@MuxinFeng](https://github.com/MuxinFeng) +- 🆕 Changed the layout style, Preview now supports `closeIcon`, PreviewGroup now supports `fallback`, and fixed an issue where preview resources would be loaded at the beginning. [#43167](https://github.com/ant-design/ant-design/pull/43167) [@linxianxi](https://github.com/linxianxi) +- 🛠 InputNumber was refactored to use rc-input. [#42762](https://github.com/ant-design/ant-design/pull/43000) [@MuxinFeng](https://github.com/MuxinFeng) - 🛠 Resolved Circular dependency issue in vite, rollup, meteor and microbundle. [#42750](https://github.com/ant-design/ant-design/pull/42750). Thanks to [@jrr997](https://github.com/jrr997), [@kiner-tang](https://github.com/kiner-tang) and [@MuxinFeng](https://github.com/MuxinFeng) for their contributions. - 🐞 Remove default values (empty string) of `className` prop in Anchor, CollapsePanel, and Input.Group. [#43481](https://github.com/ant-design/ant-design/pull/43481) [@thinkasany](https://github.com/thinkasany) - 🐞 Fix Upload progress bar missing fade motion. [#43471](https://github.com/ant-design/ant-design/pull/43471) -- 🐞 Added warning for deprecated Token `colorItemBgSelected` in Menu.[#43461](https://github.com/ant-design/ant-design/pull/43461) [@MadCcc](https://github.com/MadCcc) -- 🐞 Fixed an issue where some browsers had scroll bars that were not redrawn when style feature support was detected.[#43358](https://github.com/ant-design/ant-design/pull/43358) [@LeeeeeeM](https://github.com/LeeeeeeM) -- 🐞 Fixed an issue where the Tab component of Card would not be displayed at all when tabList is empty.[#43416](https://github.com/ant-design/ant-design/pull/43416) [@linxianxi](https://github.com/linxianxi) -- 🐞 Fixed an issue where the `form.validateMessages`` configuration would be lost when using ConfigProvider nestedly.[#43239](https://github.com/ant-design/ant-design/pull/43239) [@Wxh16144](https://github.com/Wxh16144) -- 🐞 Fixed an issue where the ripple effect of Tag click would sometimes be offset from the Tag element.[#43402](https://github.com/ant-design/ant-design/pull/43402) -- 🐞 Fixed an issue where clicking "now" in DatePicker when switching to the year-month panel would not work.[#43367](https://github.com/ant-design/ant-design/pull/43367) [@Yuiai01](https://github.com/Yuiai01) -- 🐞 Fixed an issue where the height set for the TextArea component would become invalid when the screen size changed.[#43169](https://github.com/ant-design/ant-design/pull/43169) [@MadCcc](https://github.com/MadCcc) +- 🐞 Added warning for deprecated Token `colorItemBgSelected` in Menu. [#43461](https://github.com/ant-design/ant-design/pull/43461) [@MadCcc](https://github.com/MadCcc) +- 🐞 Fixed an issue where some browsers had scroll bars that were not redrawn when style feature support was detected. [#43358](https://github.com/ant-design/ant-design/pull/43358) [@LeeeeeeM](https://github.com/LeeeeeeM) +- 🐞 Fixed an issue where the Tab component of Card would not be displayed at all when tabList is empty. [#43416](https://github.com/ant-design/ant-design/pull/43416) [@linxianxi](https://github.com/linxianxi) +- 🐞 Fixed an issue where the `form.validateMessages` configuration would be lost when using ConfigProvider nestedly. [#43239](https://github.com/ant-design/ant-design/pull/43239) [@Wxh16144](https://github.com/Wxh16144) +- 🐞 Fixed an issue where the ripple effect of Tag click would sometimes be offset from the Tag element .[#43402](https://github.com/ant-design/ant-design/pull/43402) +- 🐞 Fixed an issue where clicking "now" in DatePicker when switching to the year-month panel would not work. [#43367](https://github.com/ant-design/ant-design/pull/43367) [@Yuiai01](https://github.com/Yuiai01) +- 🐞 Fixed an issue where the height set for the TextArea component would become invalid when the screen size changed. [#43169](https://github.com/ant-design/ant-design/pull/43169) [@MadCcc](https://github.com/MadCcc) - 💄 In Slider, the `tooltip` should be centered when there is little content. [#43430](https://github.com/ant-design/ant-design/pull/43430) [@Jomorx](https://github.com/Jomorx) -- 💄 Added `colorLink` to the seed token, and `colorLinkHover` and `colorLinkActive` will be calculated from colorLink.[#43183](https://github.com/ant-design/ant-design/pull/43183) [@MadCcc](https://github.com/MadCcc) +- 💄 Added `colorLink` to the seed token, and `colorLinkHover` and `colorLinkActive` will be calculated from colorLink. [#43183](https://github.com/ant-design/ant-design/pull/43183) [@MadCcc](https://github.com/MadCcc) - 💄 Adjusted some tokens in Slider to component tokens. [#42428](https://github.com/ant-design/ant-design/pull/42428) [@heiyu4585](https://github.com/heiyu4585) RTL[#42428](https://github.com/ant-design/ant-design/pull/42428) [@heiyu4585](https://github.com/heiyu4585) - RTL - - 🤖 Progress now supports animations in rtl direction.[#43316](https://github.com/ant-design/ant-design/pull/43316) [@Yuiai01](https://github.com/Yuiai01) + - 🤖 Progress now supports animations in rtl direction. [#43316](https://github.com/ant-design/ant-design/pull/43316) [@Yuiai01](https://github.com/Yuiai01) - TypeScript - - 🤖 Added `RawPurePanelProps` interface description for Popover.[#43453](https://github.com/ant-design/ant-design/pull/43453) [@thinkasany](https://github.com/thinkasany) - - 🤖 Replaced `ref` type with `TooltipRef` instead of `unknown` for `Popconfirm`.[#43452](https://github.com/ant-design/ant-design/pull/43452) [@thinkasany](https://github.com/thinkasany) - - 🤖 Replaced `ref` type with `TooltipRef` instead of `unknown` for Popover.[#43450](https://github.com/ant-design/ant-design/pull/43450) [@Negentropy247](https://github.com/Negentropy247) - - 🤖 Improved type declaration of `GroupSizeContext` in ButtonGroup.[#43439](https://github.com/ant-design/ant-design/pull/43439) [@thinkasany](https://github.com/thinkasany) - - 🤖 Improved type declaration of `mode` property in Select.[#43413](https://github.com/ant-design/ant-design/pull/43413) [@thinkasany](https://github.com/thinkasany) - - 🤖 Replaced `ref` type with `CheckboxRef` instead of `unknown` for Checkbox.[#43424](https://github.com/ant-design/ant-design/pull/43424) [@li-jia-nan](https://github.com/li-jia-nan) + - 🤖 Added `RawPurePanelProps` interface description for Popover. [#43453](https://github.com/ant-design/ant-design/pull/43453) [@thinkasany](https://github.com/thinkasany) + - 🤖 Replaced `ref` type with `TooltipRef` instead of `unknown` for `Popconfirm`. [#43452](https://github.com/ant-design/ant-design/pull/43452) [@thinkasany](https://github.com/thinkasany) + - 🤖 Replaced `ref` type with `TooltipRef` instead of `unknown` for Popover. [#43450](https://github.com/ant-design/ant-design/pull/43450) [@Negentropy247](https://github.com/Negentropy247) + - 🤖 Improved type declaration of `GroupSizeContext` in ButtonGroup. [#43439](https://github.com/ant-design/ant-design/pull/43439) [@thinkasany](https://github.com/thinkasany) + - 🤖 Improved type declaration of `mode` property in Select. [#43413](https://github.com/ant-design/ant-design/pull/43413) [@thinkasany](https://github.com/thinkasany) + - 🤖 Replaced `ref` type with `CheckboxRef` instead of `unknown` for Checkbox. [#43424](https://github.com/ant-design/ant-design/pull/43424) [@li-jia-nan](https://github.com/li-jia-nan) - 🤖 Improved internal type implementation for Table/Tag/Notification. - [#43366](https://github.com/ant-design/ant-design/pull/43366) [@li-jia-nan](https://github.com/li-jia-nan) - [#43357](https://github.com/ant-design/ant-design/pull/43357) [@thinkasany](https://github.com/thinkasany) diff --git a/CHANGELOG.zh-CN.md b/CHANGELOG.zh-CN.md index d06a59188e..047f5b8cbd 100644 --- a/CHANGELOG.zh-CN.md +++ b/CHANGELOG.zh-CN.md @@ -15,6 +15,25 @@ timeline: true --- +## 5.7.1 + +`2023-07-19` + +- 💄 补全 Menu 主题定制 token。[#43576](https://github.com/ant-design/ant-design/pull/43576) +- 🐞 修复 QRCode 在 Next.js 13 中报错 `Can't resolve 'antd/lib/qr-code'` 的问题。[#43572](https://github.com/ant-design/ant-design/issues/43572) +- 🐞 修复 antd 不支持在 Next.js App Router 中使用的问题,查看[使用文档](/docs/react/use-with-next#使用-nextjs-的-app-router)。[#43573](https://github.com/ant-design/ant-design/pull/43573) +- 🐞 修复 InputNumber 幽灵依赖报错 `Cannot find module 'rc-component/mini-decimal'`。[#43635](https://github.com/ant-design/ant-design/pull/43635) +- 🐞 修复 App.useApp 方式调用 notification 组件时 `placement` 属性不生效的问题。[#43522](https://github.com/ant-design/ant-design/pull/43522) [@Rajil1213](https://github.com/Rajil1213) +- 🐞 修复 Checkbox 同时配置 `checked` 和 `indeterminate` 时没有展示为 `indeterminate` 样式的问题。[#43626](https://github.com/ant-design/ant-design/pull/43626) +- 🐞 修复 Form.Item 设置 `label=""` 时垂直方向对齐偏移的问题。[#43614](https://github.com/ant-design/ant-design/pull/43614) +- 🐞 修复 Pagination 分页选择器弹层抖动的问题。[#43556](https://github.com/ant-design/ant-design/pull/43556) +- 🐞 修复 Button 幽灵按钮禁用状态丢失的问题。[#43558](https://github.com/ant-design/ant-design/pull/43558) [@kiner-tang](https://github.com/kiner-tang) +- 🐞 修复 Tag 仅传入 `icon` 时渲染多余间距的问题。[#43518](https://github.com/ant-design/ant-design/pull/43518) [@Yuiai01](https://github.com/Yuiai01) +- 🐞 修复 ColorPicker 不跟随表单校验状态改变 UI 的问题。[#42880](https://github.com/ant-design/ant-design/pull/42880) [@RedJue](https://github.com/RedJue) +- TypeScript + - 🤖 修复 `SpaceContext` 没有正确导出的问题。[#43501](https://github.com/ant-design/ant-design/pull/43501) [@VovkaGoodwin](https://github.com/VovkaGoodwin) + - 🤖 优化部分组件 TS 定义实现。[#43581](https://github.com/ant-design/ant-design/pull/43581) [#43545](https://github.com/ant-design/ant-design/pull/43545) [#43588](https://github.com/ant-design/ant-design/pull/43588) [#43610](https://github.com/ant-design/ant-design/pull/43610) [#43629](https://github.com/ant-design/ant-design/pull/43629),感谢 [@thinkasany](https://github.com/thinkasany)、[@li-jia-nan](https://github.com/li-jia-nan) 的贡献。 + ## 5.7.0 `2023-07-11` diff --git a/components/app/__tests__/__snapshots__/demo-extend.test.ts.snap b/components/app/__tests__/__snapshots__/demo-extend.test.ts.snap index dfcd5a9b10..3aa9b9e8b8 100644 --- a/components/app/__tests__/__snapshots__/demo-extend.test.ts.snap +++ b/components/app/__tests__/__snapshots__/demo-extend.test.ts.snap @@ -48,3 +48,39 @@ exports[`renders components/app/demo/basic.tsx extend context correctly 1`] = `
`; + +exports[`renders components/app/demo/config.tsx extend context correctly 1`] = ` +
+
+
+ +
+
+ +
+
+
+`; diff --git a/components/app/__tests__/__snapshots__/demo.test.ts.snap b/components/app/__tests__/__snapshots__/demo.test.ts.snap index dea888a49b..833887ea86 100644 --- a/components/app/__tests__/__snapshots__/demo.test.ts.snap +++ b/components/app/__tests__/__snapshots__/demo.test.ts.snap @@ -48,3 +48,39 @@ exports[`renders components/app/demo/basic.tsx correctly 1`] = ` `; + +exports[`renders components/app/demo/config.tsx correctly 1`] = ` +
+
+
+ +
+
+ +
+
+
+`; diff --git a/components/app/__tests__/index.test.tsx b/components/app/__tests__/index.test.tsx index c738a60a20..7cfccbdc93 100644 --- a/components/app/__tests__/index.test.tsx +++ b/components/app/__tests__/index.test.tsx @@ -1,4 +1,5 @@ import React, { useEffect } from 'react'; +import type { NotificationConfig } from 'antd/es/notification/interface'; import App from '..'; import mountTest from '../../../tests/shared/mountTest'; import rtlTest from '../../../tests/shared/rtlTest'; @@ -123,6 +124,46 @@ describe('App', () => { expect(config?.notification).toStrictEqual({ maxCount: 30, bottom: 41 }); }); + it('should respect notification placement config from props in priority', async () => { + let consumedConfig: AppConfig | undefined; + + const Consumer = () => { + const { notification } = App.useApp(); + consumedConfig = React.useContext(AppConfigContext); + + useEffect(() => { + notification.success({ message: 'Notification 1' }); + notification.success({ message: 'Notification 2' }); + notification.success({ message: 'Notification 3' }); + }, [notification]); + + return
; + }; + + const config: NotificationConfig = { + placement: 'bottomLeft', + top: 100, + bottom: 50, + }; + + const Wrapper = () => ( + + + + ); + + render(); + await waitFakeTimer(); + + expect(consumedConfig?.notification).toStrictEqual(config); + expect(document.querySelector('.ant-notification-topRight')).not.toBeInTheDocument(); + expect(document.querySelector('.ant-notification-bottomLeft')).toHaveStyle({ + top: '', + left: '0px', + bottom: '50px', + }); + }); + it('support className', () => { const { container } = render( diff --git a/components/app/demo/basic.md b/components/app/demo/basic.md index f8f1d48607..9976b036fd 100644 --- a/components/app/demo/basic.md +++ b/components/app/demo/basic.md @@ -1,7 +1,7 @@ ## zh-CN -获取 `message`、`notification`、`modal` 静态方法。 +获取 `message`、`notification`、`modal` 实例。 ## en-US -Static method for `message`, `notification`, `modal`. +Get instance for `message`, `notification`, `modal`. diff --git a/components/app/demo/config.md b/components/app/demo/config.md new file mode 100644 index 0000000000..200dc53e95 --- /dev/null +++ b/components/app/demo/config.md @@ -0,0 +1,7 @@ +## zh-CN + +对 `message`、`notification` 进行配置。 + +## en-US + +Config for `message`, `notification`. diff --git a/components/app/demo/config.tsx b/components/app/demo/config.tsx new file mode 100644 index 0000000000..fdc25a6e70 --- /dev/null +++ b/components/app/demo/config.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { App, Button, Space } from 'antd'; + +// Sub page +const MyPage = () => { + const { message, notification } = App.useApp(); + + const showMessage = () => { + message.success('Success!'); + }; + + const showNotification = () => { + notification.info({ + message: `Notification`, + description: 'Hello, Ant Design!!', + }); + }; + + return ( + + + + + ); +}; + +// Entry component +export default () => ( + + + +); diff --git a/components/app/index.en-US.md b/components/app/index.en-US.md index eda1014f72..ddc515ed09 100644 --- a/components/app/index.en-US.md +++ b/components/app/index.en-US.md @@ -18,7 +18,8 @@ Application wrapper for some global usages. ## Examples -basic +Basic +Hooks config ## How to use diff --git a/components/app/index.zh-CN.md b/components/app/index.zh-CN.md index 97793b5d1e..1d73396dff 100644 --- a/components/app/index.zh-CN.md +++ b/components/app/index.zh-CN.md @@ -20,6 +20,7 @@ demo: 基本用法 +Hooks 配置 ## 如何使用 diff --git a/components/auto-complete/index.tsx b/components/auto-complete/index.tsx index 5bf552b9c8..872913ed65 100755 --- a/components/auto-complete/index.tsx +++ b/components/auto-complete/index.tsx @@ -16,6 +16,7 @@ import type { DefaultOptionType, InternalSelectProps, RefSelectProps, + SelectProps, } from '../select'; import Select from '../select'; @@ -146,7 +147,7 @@ const AutoComplete: React.ForwardRefRenderFunction( ref?: React.Ref; }, ) => React.ReactElement) & { + displayName?: string; Option: typeof Option; _InternalPanelDoNotUseOrYouWillBeFired: typeof PurePanel; }; @@ -179,7 +181,7 @@ RefAutoComplete.Option = Option; RefAutoComplete._InternalPanelDoNotUseOrYouWillBeFired = PurePanel; if (process.env.NODE_ENV !== 'production') { - AutoComplete.displayName = 'AutoComplete'; + RefAutoComplete.displayName = 'AutoComplete'; } export default RefAutoComplete; diff --git a/components/back-top/index.tsx b/components/back-top/index.tsx index 97b11277e6..7ade5fa225 100644 --- a/components/back-top/index.tsx +++ b/components/back-top/index.tsx @@ -121,4 +121,4 @@ if (process.env.NODE_ENV !== 'production') { BackTop.displayName = 'BackTop'; } -export default React.memo(BackTop); +export default BackTop; diff --git a/components/button/__tests__/index.test.tsx b/components/button/__tests__/index.test.tsx index 4e6216ca5b..496de4d8c8 100644 --- a/components/button/__tests__/index.test.tsx +++ b/components/button/__tests__/index.test.tsx @@ -343,4 +343,15 @@ describe('Button', () => { ); expect(window.getComputedStyle(container.querySelector('#link')!).pointerEvents).toBe('none'); }); + + it('Correct type', () => { + const onBtnClick: React.MouseEventHandler = () => {}; + const onAnchorClick: React.MouseEventHandler = () => {}; + + const button = )} @@ -77,7 +77,7 @@ exports[`renders components/qrcode/demo/base.tsx extend context correctly 1`] =
`; -exports[`renders components/qrcode/demo/customColor.tsx extend context correctly 1`] = ` +exports[`renders components/qr-code/demo/customColor.tsx extend context correctly 1`] = `
@@ -113,7 +113,7 @@ exports[`renders components/qrcode/demo/customColor.tsx extend context correctly
`; -exports[`renders components/qrcode/demo/customSize.tsx extend context correctly 1`] = ` +exports[`renders components/qr-code/demo/customSize.tsx extend context correctly 1`] = ` Array [
@@ -230,7 +230,7 @@ exports[`renders components/qrcode/demo/download.tsx extend context correctly 1`
`; -exports[`renders components/qrcode/demo/errorlevel.tsx extend context correctly 1`] = ` +exports[`renders components/qr-code/demo/errorlevel.tsx extend context correctly 1`] = ` Array [
`; -exports[`renders components/qrcode/demo/status.tsx extend context correctly 1`] = ` +exports[`renders components/qr-code/demo/status.tsx extend context correctly 1`] = `
`; -exports[`renders components/qrcode/demo/type.tsx extend context correctly 1`] = ` +exports[`renders components/qr-code/demo/type.tsx extend context correctly 1`] = `
diff --git a/components/qrcode/__tests__/__snapshots__/demo.test.ts.snap b/components/qr-code/__tests__/__snapshots__/demo.test.ts.snap similarity index 94% rename from components/qrcode/__tests__/__snapshots__/demo.test.ts.snap rename to components/qr-code/__tests__/__snapshots__/demo.test.ts.snap index a1dcc054ed..466f0be83c 100644 --- a/components/qrcode/__tests__/__snapshots__/demo.test.ts.snap +++ b/components/qr-code/__tests__/__snapshots__/demo.test.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`renders components/qrcode/demo/Popover.tsx correctly 1`] = ` +exports[`renders components/qr-code/demo/Popover.tsx correctly 1`] = ` icon `; -exports[`renders components/qrcode/demo/base.tsx correctly 1`] = ` +exports[`renders components/qr-code/demo/base.tsx correctly 1`] = `
@@ -42,7 +42,7 @@ exports[`renders components/qrcode/demo/base.tsx correctly 1`] = `
`; -exports[`renders components/qrcode/demo/customColor.tsx correctly 1`] = ` +exports[`renders components/qr-code/demo/customColor.tsx correctly 1`] = `
@@ -78,7 +78,7 @@ exports[`renders components/qrcode/demo/customColor.tsx correctly 1`] = `
`; -exports[`renders components/qrcode/demo/customSize.tsx correctly 1`] = ` +exports[`renders components/qr-code/demo/customSize.tsx correctly 1`] = ` Array [
@@ -195,7 +195,7 @@ exports[`renders components/qrcode/demo/download.tsx correctly 1`] = `
`; -exports[`renders components/qrcode/demo/errorlevel.tsx correctly 1`] = ` +exports[`renders components/qr-code/demo/errorlevel.tsx correctly 1`] = ` Array [
`; -exports[`renders components/qrcode/demo/status.tsx correctly 1`] = ` +exports[`renders components/qr-code/demo/status.tsx correctly 1`] = `
`; -exports[`renders components/qrcode/demo/type.tsx correctly 1`] = ` +exports[`renders components/qr-code/demo/type.tsx correctly 1`] = `
diff --git a/components/qrcode/__tests__/__snapshots__/index.test.tsx.snap b/components/qr-code/__tests__/__snapshots__/index.test.tsx.snap similarity index 100% rename from components/qrcode/__tests__/__snapshots__/index.test.tsx.snap rename to components/qr-code/__tests__/__snapshots__/index.test.tsx.snap diff --git a/components/qrcode/__tests__/demo-extend.test.ts b/components/qr-code/__tests__/demo-extend.test.ts similarity index 72% rename from components/qrcode/__tests__/demo-extend.test.ts rename to components/qr-code/__tests__/demo-extend.test.ts index 79dea1e4fa..4f084aa2f9 100644 --- a/components/qrcode/__tests__/demo-extend.test.ts +++ b/components/qr-code/__tests__/demo-extend.test.ts @@ -1,3 +1,3 @@ import { extendTest } from '../../../tests/shared/demoTest'; -extendTest('qrcode'); +extendTest('qr-code'); diff --git a/components/qrcode/__tests__/demo.test.ts b/components/qr-code/__tests__/demo.test.ts similarity index 72% rename from components/qrcode/__tests__/demo.test.ts rename to components/qr-code/__tests__/demo.test.ts index 1cb1d77dd4..3333ff7dac 100644 --- a/components/qrcode/__tests__/demo.test.ts +++ b/components/qr-code/__tests__/demo.test.ts @@ -1,3 +1,3 @@ import demoTest from '../../../tests/shared/demoTest'; -demoTest('qrcode'); +demoTest('qr-code'); diff --git a/components/qrcode/__tests__/image.test.ts b/components/qr-code/__tests__/image.test.ts similarity index 78% rename from components/qrcode/__tests__/image.test.ts rename to components/qr-code/__tests__/image.test.ts index df82d405e5..46d23d37f9 100644 --- a/components/qrcode/__tests__/image.test.ts +++ b/components/qr-code/__tests__/image.test.ts @@ -1,5 +1,5 @@ import { imageDemoTest } from '../../../tests/shared/imageTest'; describe('QRCode image', () => { - imageDemoTest('qrcode'); + imageDemoTest('qr-code'); }); diff --git a/components/qrcode/__tests__/index.test.tsx b/components/qr-code/__tests__/index.test.tsx similarity index 100% rename from components/qrcode/__tests__/index.test.tsx rename to components/qr-code/__tests__/index.test.tsx diff --git a/components/qrcode/demo/Popover.md b/components/qr-code/demo/Popover.md similarity index 100% rename from components/qrcode/demo/Popover.md rename to components/qr-code/demo/Popover.md diff --git a/components/qrcode/demo/Popover.tsx b/components/qr-code/demo/Popover.tsx similarity index 100% rename from components/qrcode/demo/Popover.tsx rename to components/qr-code/demo/Popover.tsx diff --git a/components/qrcode/demo/base.md b/components/qr-code/demo/base.md similarity index 100% rename from components/qrcode/demo/base.md rename to components/qr-code/demo/base.md diff --git a/components/qrcode/demo/base.tsx b/components/qr-code/demo/base.tsx similarity index 100% rename from components/qrcode/demo/base.tsx rename to components/qr-code/demo/base.tsx diff --git a/components/qrcode/demo/customColor.md b/components/qr-code/demo/customColor.md similarity index 100% rename from components/qrcode/demo/customColor.md rename to components/qr-code/demo/customColor.md diff --git a/components/qrcode/demo/customColor.tsx b/components/qr-code/demo/customColor.tsx similarity index 100% rename from components/qrcode/demo/customColor.tsx rename to components/qr-code/demo/customColor.tsx diff --git a/components/qrcode/demo/customSize.md b/components/qr-code/demo/customSize.md similarity index 100% rename from components/qrcode/demo/customSize.md rename to components/qr-code/demo/customSize.md diff --git a/components/qrcode/demo/customSize.tsx b/components/qr-code/demo/customSize.tsx similarity index 100% rename from components/qrcode/demo/customSize.tsx rename to components/qr-code/demo/customSize.tsx diff --git a/components/qrcode/demo/download.md b/components/qr-code/demo/download.md similarity index 100% rename from components/qrcode/demo/download.md rename to components/qr-code/demo/download.md diff --git a/components/qrcode/demo/download.tsx b/components/qr-code/demo/download.tsx similarity index 100% rename from components/qrcode/demo/download.tsx rename to components/qr-code/demo/download.tsx diff --git a/components/qrcode/demo/errorlevel.md b/components/qr-code/demo/errorlevel.md similarity index 100% rename from components/qrcode/demo/errorlevel.md rename to components/qr-code/demo/errorlevel.md diff --git a/components/qrcode/demo/errorlevel.tsx b/components/qr-code/demo/errorlevel.tsx similarity index 100% rename from components/qrcode/demo/errorlevel.tsx rename to components/qr-code/demo/errorlevel.tsx diff --git a/components/qrcode/demo/icon.md b/components/qr-code/demo/icon.md similarity index 100% rename from components/qrcode/demo/icon.md rename to components/qr-code/demo/icon.md diff --git a/components/qrcode/demo/icon.tsx b/components/qr-code/demo/icon.tsx similarity index 100% rename from components/qrcode/demo/icon.tsx rename to components/qr-code/demo/icon.tsx diff --git a/components/qrcode/demo/status.md b/components/qr-code/demo/status.md similarity index 100% rename from components/qrcode/demo/status.md rename to components/qr-code/demo/status.md diff --git a/components/qrcode/demo/status.tsx b/components/qr-code/demo/status.tsx similarity index 100% rename from components/qrcode/demo/status.tsx rename to components/qr-code/demo/status.tsx diff --git a/components/qrcode/demo/type.md b/components/qr-code/demo/type.md similarity index 100% rename from components/qrcode/demo/type.md rename to components/qr-code/demo/type.md diff --git a/components/qrcode/demo/type.tsx b/components/qr-code/demo/type.tsx similarity index 100% rename from components/qrcode/demo/type.tsx rename to components/qr-code/demo/type.tsx diff --git a/components/qrcode/index.en-US.md b/components/qr-code/index.en-US.md similarity index 100% rename from components/qrcode/index.en-US.md rename to components/qr-code/index.en-US.md diff --git a/components/qrcode/index.tsx b/components/qr-code/index.tsx similarity index 100% rename from components/qrcode/index.tsx rename to components/qr-code/index.tsx diff --git a/components/qrcode/index.zh-CN.md b/components/qr-code/index.zh-CN.md similarity index 100% rename from components/qrcode/index.zh-CN.md rename to components/qr-code/index.zh-CN.md diff --git a/components/qr-code/interface.ts b/components/qr-code/interface.ts new file mode 100644 index 0000000000..59c4324a21 --- /dev/null +++ b/components/qr-code/interface.ts @@ -0,0 +1,37 @@ +import type { CSSProperties } from 'react'; + +interface ImageSettings { + src: string; + height: number; + width: number; + excavate: boolean; + x?: number; + y?: number; +} + +export interface QRProps { + value: string; + type?: 'canvas' | 'svg'; + size?: number; + color?: string; + style?: CSSProperties; + includeMargin?: boolean; + imageSettings?: ImageSettings; + bgColor?: string; +} + +export type QRPropsCanvas = QRProps & React.CanvasHTMLAttributes; + +export type QRPropsSvg = QRProps & React.SVGAttributes; + +export interface QRCodeProps extends QRProps { + className?: string; + rootClassName?: string; + prefixCls?: string; + icon?: string; + iconSize?: number; + bordered?: boolean; + errorLevel?: 'L' | 'M' | 'Q' | 'H'; + status?: 'active' | 'expired' | 'loading'; + onRefresh?: () => void; +} diff --git a/components/qr-code/style/index.ts b/components/qr-code/style/index.ts new file mode 100644 index 0000000000..f40e1f30a9 --- /dev/null +++ b/components/qr-code/style/index.ts @@ -0,0 +1,65 @@ +import { resetComponent } from '../../style'; +import type { FullToken, GenerateStyle } from '../../theme/internal'; +import { genComponentStyleHook, mergeToken } from '../../theme/internal'; + +export interface ComponentToken {} + +interface QRCodeToken extends FullToken<'QRCode'> { + QRCodeExpiredTextColor: string; + QRCodeMaskBackgroundColor: string; +} + +const genQRCodeStyle: GenerateStyle = (token) => { + const { componentCls } = token; + return { + [componentCls]: { + ...resetComponent(token), + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + padding: token.paddingSM, + backgroundColor: token.colorWhite, + borderRadius: token.borderRadiusLG, + border: `${token.lineWidth}px ${token.lineType} ${token.colorSplit}`, + position: 'relative', + width: '100%', + height: '100%', + overflow: 'hidden', + [`& > ${componentCls}-mask`]: { + position: 'absolute', + insetBlockStart: 0, + insetInlineStart: 0, + zIndex: 10, + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + width: '100%', + height: '100%', + color: token.colorText, + lineHeight: token.lineHeight, + background: token.QRCodeMaskBackgroundColor, + textAlign: 'center', + [`& > ${componentCls}-expired`]: { + color: token.QRCodeExpiredTextColor, + }, + }, + '&-icon': { + marginBlockEnd: token.marginXS, + fontSize: token.controlHeight, + }, + }, + [`${componentCls}-borderless`]: { + borderColor: 'transparent', + }, + }; +}; + +export default genComponentStyleHook<'QRCode'>('QRCode', (token) => + genQRCodeStyle( + mergeToken(token, { + QRCodeExpiredTextColor: 'rgba(0, 0, 0, 0.88)', + QRCodeMaskBackgroundColor: 'rgba(255, 255, 255, 0.96)', + }), + ), +); diff --git a/components/qrcode/index.ts b/components/qrcode/index.ts new file mode 100644 index 0000000000..f5fce35367 --- /dev/null +++ b/components/qrcode/index.ts @@ -0,0 +1,5 @@ +// Legacy path. Please use `qr-code` instead. +// Keep file here in case developer import directly from the old path. +import QRCode from '../qr-code'; + +export default QRCode; diff --git a/components/qrcode/interface.ts b/components/qrcode/interface.ts index 59c4324a21..28ba47cc8e 100644 --- a/components/qrcode/interface.ts +++ b/components/qrcode/interface.ts @@ -1,37 +1,3 @@ -import type { CSSProperties } from 'react'; - -interface ImageSettings { - src: string; - height: number; - width: number; - excavate: boolean; - x?: number; - y?: number; -} - -export interface QRProps { - value: string; - type?: 'canvas' | 'svg'; - size?: number; - color?: string; - style?: CSSProperties; - includeMargin?: boolean; - imageSettings?: ImageSettings; - bgColor?: string; -} - -export type QRPropsCanvas = QRProps & React.CanvasHTMLAttributes; - -export type QRPropsSvg = QRProps & React.SVGAttributes; - -export interface QRCodeProps extends QRProps { - className?: string; - rootClassName?: string; - prefixCls?: string; - icon?: string; - iconSize?: number; - bordered?: boolean; - errorLevel?: 'L' | 'M' | 'Q' | 'H'; - status?: 'active' | 'expired' | 'loading'; - onRefresh?: () => void; -} +// Legacy path. Please use `qr-code` instead. +// Keep file here in case developer import directly from the old path. +export * from '../qr-code/interface'; diff --git a/components/qrcode/style/index.ts b/components/qrcode/style/index.ts index f40e1f30a9..cb88b4260b 100644 --- a/components/qrcode/style/index.ts +++ b/components/qrcode/style/index.ts @@ -1,65 +1,3 @@ -import { resetComponent } from '../../style'; -import type { FullToken, GenerateStyle } from '../../theme/internal'; -import { genComponentStyleHook, mergeToken } from '../../theme/internal'; - -export interface ComponentToken {} - -interface QRCodeToken extends FullToken<'QRCode'> { - QRCodeExpiredTextColor: string; - QRCodeMaskBackgroundColor: string; -} - -const genQRCodeStyle: GenerateStyle = (token) => { - const { componentCls } = token; - return { - [componentCls]: { - ...resetComponent(token), - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - padding: token.paddingSM, - backgroundColor: token.colorWhite, - borderRadius: token.borderRadiusLG, - border: `${token.lineWidth}px ${token.lineType} ${token.colorSplit}`, - position: 'relative', - width: '100%', - height: '100%', - overflow: 'hidden', - [`& > ${componentCls}-mask`]: { - position: 'absolute', - insetBlockStart: 0, - insetInlineStart: 0, - zIndex: 10, - display: 'flex', - flexDirection: 'column', - justifyContent: 'center', - alignItems: 'center', - width: '100%', - height: '100%', - color: token.colorText, - lineHeight: token.lineHeight, - background: token.QRCodeMaskBackgroundColor, - textAlign: 'center', - [`& > ${componentCls}-expired`]: { - color: token.QRCodeExpiredTextColor, - }, - }, - '&-icon': { - marginBlockEnd: token.marginXS, - fontSize: token.controlHeight, - }, - }, - [`${componentCls}-borderless`]: { - borderColor: 'transparent', - }, - }; -}; - -export default genComponentStyleHook<'QRCode'>('QRCode', (token) => - genQRCodeStyle( - mergeToken(token, { - QRCodeExpiredTextColor: 'rgba(0, 0, 0, 0.88)', - QRCodeMaskBackgroundColor: 'rgba(255, 255, 255, 0.96)', - }), - ), -); +// Legacy path. Please use `qr-code` instead. +// Keep file here in case developer import directly from the old path. +export * from '../../qr-code/style'; diff --git a/components/radio/context.tsx b/components/radio/context.ts similarity index 100% rename from components/radio/context.tsx rename to components/radio/context.ts diff --git a/components/radio/index.tsx b/components/radio/index.ts similarity index 100% rename from components/radio/index.tsx rename to components/radio/index.ts diff --git a/components/radio/interface.tsx b/components/radio/interface.ts similarity index 100% rename from components/radio/interface.tsx rename to components/radio/interface.ts diff --git a/components/radio/radioButton.tsx b/components/radio/radioButton.tsx index 1cdf3b6a94..2a42c95840 100644 --- a/components/radio/radioButton.tsx +++ b/components/radio/radioButton.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import type { CheckboxRef } from '../checkbox'; import type { AbstractCheckboxProps } from '../checkbox/Checkbox'; import { ConfigContext } from '../config-provider'; import { RadioOptionTypeContextProvider } from './context'; @@ -7,17 +8,17 @@ import Radio from './radio'; export type RadioButtonProps = AbstractCheckboxProps; -const RadioButton = (props: RadioButtonProps, ref: React.Ref) => { +const RadioButton: React.ForwardRefRenderFunction = (props, ref) => { const { getPrefixCls } = React.useContext(ConfigContext); const { prefixCls: customizePrefixCls, ...radioProps } = props; const prefixCls = getPrefixCls('radio', customizePrefixCls); return ( - - + + ); }; -export default React.forwardRef(RadioButton); +export default React.forwardRef(RadioButton); diff --git a/components/select/index.tsx b/components/select/index.tsx index b79085df0d..aa80da86a2 100755 --- a/components/select/index.tsx +++ b/components/select/index.tsx @@ -285,6 +285,7 @@ const Select = React.forwardRef(InternalSelect) as unknown as (< ref?: React.Ref; }, ) => React.ReactElement) & { + displayName?: string; SECRET_COMBOBOX_MODE_DO_NOT_USE: string; Option: typeof Option; OptGroup: typeof OptGroup; @@ -300,4 +301,8 @@ Select.Option = Option; Select.OptGroup = OptGroup; Select._InternalPanelDoNotUseOrYouWillBeFired = PurePanel; +if (process.env.NODE_ENV !== 'production') { + Select.displayName = 'Select'; +} + export default Select; diff --git a/components/slider/__tests__/index.test.tsx b/components/slider/__tests__/index.test.tsx index 27355bacce..affefebca3 100644 --- a/components/slider/__tests__/index.test.tsx +++ b/components/slider/__tests__/index.test.tsx @@ -6,7 +6,7 @@ import rtlTest from '../../../tests/shared/rtlTest'; import { act, fireEvent, render } from '../../../tests/utils'; import { resetWarned } from '../../_util/warning'; import ConfigProvider from '../../config-provider'; -import type { TooltipProps } from '../../tooltip'; +import type { TooltipProps, TooltipRef } from '../../tooltip'; import SliderTooltip from '../SliderTooltip'; function tooltipProps(): TooltipProps { @@ -14,10 +14,10 @@ function tooltipProps(): TooltipProps { } jest.mock('../../tooltip', () => { - const ReactReal = jest.requireActual('react'); + const ReactReal: typeof React = jest.requireActual('react'); const Tooltip = jest.requireActual('../../tooltip'); const TooltipComponent = Tooltip.default; - return ReactReal.forwardRef((props: TooltipProps, ref: any) => { + return ReactReal.forwardRef((props, ref) => { (global as any).tooltipProps = props; return ; }); diff --git a/components/slider/index.zh-CN.md b/components/slider/index.zh-CN.md index 7d5ec37f90..1036fa393a 100644 --- a/components/slider/index.zh-CN.md +++ b/components/slider/index.zh-CN.md @@ -35,7 +35,6 @@ demo: | 参数 | 说明 | 类型 | 默认值 | 版本 | | --- | --- | --- | --- | --- | | autoFocus | 自动获取焦点 | boolean | false | | -| allowClear | 支持清除, 单选模式有效 | boolean | false | | | defaultValue | 设置初始取值。当 `range` 为 false 时,使用 number,否则用 \[number, number] | number \| \[number, number] | 0 \| \[0, 0] | | | disabled | 值为 true 时,滑块为禁用状态 | boolean | false | | | keyboard | 支持使用键盘操作 handler | boolean | true | 5.2.0+ | diff --git a/components/steps/style/index.tsx b/components/steps/style/index.tsx index ccd1658c71..cd2dafdc1d 100644 --- a/components/steps/style/index.tsx +++ b/components/steps/style/index.tsx @@ -1,6 +1,6 @@ import type { CSSObject } from '@ant-design/cssinjs'; import type { CSSProperties } from 'react'; -import { resetComponent } from '../../style'; +import { genFocusOutline, resetComponent } from '../../style'; import type { FullToken, GenerateStyle } from '../../theme/internal'; import { genComponentStyleHook, mergeToken } from '../../theme/internal'; import genStepsCustomIconStyle from './custom-icon'; @@ -171,6 +171,7 @@ const genStepsItemStatusStyle = (status: StepItemStatusEnum, token: StepsToken): const genStepsItemStyle: GenerateStyle = (token) => { const { componentCls, motionDurationSlow } = token; const stepsItemCls = `${componentCls}-item`; // .ant-steps-item + const stepItemIconCls = `${stepsItemCls}-icon`; return { [stepsItemCls]: { @@ -189,12 +190,18 @@ const genStepsItemStyle: GenerateStyle = (token) => { }, [`${stepsItemCls}-container`]: { outline: 'none', + + [`&:focus-visible`]: { + [stepItemIconCls]: { + ...genFocusOutline(token), + }, + }, }, - [`${stepsItemCls}-icon, ${stepsItemCls}-content`]: { + [`${stepItemIconCls}, ${stepsItemCls}-content`]: { display: 'inline-block', verticalAlign: 'top', }, - [`${stepsItemCls}-icon`]: { + [stepItemIconCls]: { width: token.iconSize, height: token.iconSize, marginTop: 0, diff --git a/components/table/Table.tsx b/components/table/Table.tsx index 4ab399bffd..12a136a955 100644 --- a/components/table/Table.tsx +++ b/components/table/Table.tsx @@ -23,6 +23,7 @@ const Table = ( }; const ForwardTable = React.forwardRef(Table) as unknown as RefTable & { + displayName?: string; SELECTION_COLUMN: typeof SELECTION_COLUMN; EXPAND_COLUMN: typeof EXPAND_COLUMN; SELECTION_ALL: typeof SELECTION_ALL; @@ -42,4 +43,8 @@ ForwardTable.Column = Column; ForwardTable.ColumnGroup = ColumnGroup; ForwardTable.Summary = Summary; +if (process.env.NODE_ENV !== 'production') { + ForwardTable.displayName = 'Table'; +} + export default ForwardTable; diff --git a/components/theme/interface/alias.ts b/components/theme/interface/alias.ts index a27da4c854..a08f61d008 100644 --- a/components/theme/interface/alias.ts +++ b/components/theme/interface/alias.ts @@ -61,7 +61,7 @@ export interface AliasToken extends MapToken { colorBorderBg: string; /** * @nameZH 分割线颜色 - * @nameEN Separator color + * @nameEN Separator Color * @desc 用于作为分割线的颜色,此颜色和 colorBorderSecondary 的颜色一致,但是用的是透明色。 * @descEN Used as the color of separator, this color is the same as colorBorderSecondary but with transparency. */ @@ -70,21 +70,21 @@ export interface AliasToken extends MapToken { // Text /** * @nameZH 占位文本颜色 - * @nameEN Placeholder text color + * @nameEN Placeholder Text Color * @desc 控制占位文本的颜色。 * @descEN Control the color of placeholder text. */ colorTextPlaceholder: string; /** * @nameZH 禁用字体颜色 - * @nameEN Disabled text color + * @nameEN Disabled Text Color * @desc 控制禁用状态下的字体颜色。 * @descEN Control the color of text in disabled state. */ colorTextDisabled: string; /** * @nameZH 标题字体颜色 - * @nameEN Heading font color + * @nameEN Heading Text Color * @desc 控制标题字体颜色。 * @descEN Control the font color of heading. */ diff --git a/components/theme/interface/components.ts b/components/theme/interface/components.ts index d8edbf6000..8ae0623864 100644 --- a/components/theme/interface/components.ts +++ b/components/theme/interface/components.ts @@ -33,7 +33,7 @@ import type { ComponentToken as PaginationComponentToken } from '../../paginatio import type { ComponentToken as PopconfirmComponentToken } from '../../popconfirm/style'; import type { ComponentToken as PopoverComponentToken } from '../../popover/style'; import type { ComponentToken as ProgressComponentToken } from '../../progress/style'; -import type { ComponentToken as QRCodeComponentToken } from '../../qrcode/style'; +import type { ComponentToken as QRCodeComponentToken } from '../../qr-code/style'; import type { ComponentToken as RadioComponentToken } from '../../radio/style'; import type { ComponentToken as RateComponentToken } from '../../rate/style'; import type { ComponentToken as ResultComponentToken } from '../../result/style'; diff --git a/components/theme/interface/maps/colors.ts b/components/theme/interface/maps/colors.ts index ee98286097..2078a32c70 100644 --- a/components/theme/interface/maps/colors.ts +++ b/components/theme/interface/maps/colors.ts @@ -13,6 +13,7 @@ export interface ColorNeutralMapToken { /** * @nameZH 一级文本色 + * @nameEN Text Color * @desc 最深的文本色。为了符合W3C标准,默认的文本颜色使用了该色,同时这个颜色也是最深的中性色。 * @descEN Default text color which comply with W3C standards, and this color is also the darkest neutral color. */ @@ -20,6 +21,7 @@ export interface ColorNeutralMapToken { /** * @nameZH 二级文本色 + * @nameEN Secondary Text Color * @desc 作为第二梯度的文本色,一般用在不那么需要强化文本颜色的场景,例如 Label 文本、Menu 的文本选中态等场景。 * @descEN The second level of text color is generally used in scenarios where text color is not emphasized, such as label text, menu text selection state, etc. */ @@ -91,6 +93,7 @@ export interface ColorNeutralMapToken { /** * @nameZH 布局背景色 + * @nameEN Layout Background Color * @desc 该色用于页面整体布局的背景色,只有需要在页面中处于 B1 的视觉层级时才会使用该 token,其他用法都是错误的 * @descEN This color is used for the background color of the overall layout of the page. This token will only be used when it is necessary to be at the B1 visual level in the page. Other usages are wrong. */ diff --git a/components/tree-select/index.tsx b/components/tree-select/index.tsx index f0072b0c5d..a7438cdbc1 100644 --- a/components/tree-select/index.tsx +++ b/components/tree-select/index.tsx @@ -300,6 +300,7 @@ const TreeSelectRef = React.forwardRef(InternalTreeSelect) as < type InternalTreeSelectType = typeof TreeSelectRef; type CompoundedComponent = InternalTreeSelectType & { + displayName?: string; TreeNode: typeof TreeNode; SHOW_ALL: typeof SHOW_ALL; SHOW_PARENT: typeof SHOW_PARENT; @@ -319,6 +320,10 @@ TreeSelect.SHOW_PARENT = SHOW_PARENT; TreeSelect.SHOW_CHILD = SHOW_CHILD; TreeSelect._InternalPanelDoNotUseOrYouWillBeFired = PurePanel; +if (process.env.NODE_ENV !== 'production') { + TreeSelect.displayName = 'TreeSelect'; +} + export { TreeNode }; export default TreeSelect; diff --git a/components/upload/UploadList/ListItem.tsx b/components/upload/UploadList/ListItem.tsx index 53784e4d8b..5bb9574128 100644 --- a/components/upload/UploadList/ListItem.tsx +++ b/components/upload/UploadList/ListItem.tsx @@ -44,7 +44,7 @@ export interface ListItemProps { progress?: UploadListProgressProps; } -const ListItem = React.forwardRef( +const ListItem = React.forwardRef( ( { prefixCls, @@ -68,8 +68,8 @@ const ListItem = React.forwardRef( onPreview, onDownload, onClose, - }: ListItemProps, - ref: React.Ref, + }, + ref, ) => { // Status: which will ignore `removed` status const { status } = file; @@ -111,8 +111,7 @@ const ListItem = React.forwardRef( ) : ( iconNode ); - const aClassName = classNames({ - [`${prefixCls}-list-item-thumbnail`]: true, + const aClassName = classNames(`${prefixCls}-list-item-thumbnail`, { [`${prefixCls}-list-item-file`]: isImgUrl && !isImgUrl(file), }); icon = ( diff --git a/docs/blog/extract-ssr.en-US.md b/docs/blog/extract-ssr.en-US.md index c3076ee616..a53ff5f6c7 100644 --- a/docs/blog/extract-ssr.en-US.md +++ b/docs/blog/extract-ssr.en-US.md @@ -139,7 +139,7 @@ if (!fs.existsSync(cssFileName)) { Then add the corresponding CSS file on the HTML template side: ```html - + diff --git a/docs/blog/extract-ssr.zh-CN.md b/docs/blog/extract-ssr.zh-CN.md index c9dcaa1725..f4e8cd5b1a 100644 --- a/docs/blog/extract-ssr.zh-CN.md +++ b/docs/blog/extract-ssr.zh-CN.md @@ -139,7 +139,7 @@ if (!fs.existsSync(cssFileName)) { 然后在 HTML 模板侧添加对应的 CSS 文件: ```html - + diff --git a/docs/blog/suspense.en-US.md b/docs/blog/suspense.en-US.md index 26b9d96ce0..9b9b40caf1 100644 --- a/docs/blog/suspense.en-US.md +++ b/docs/blog/suspense.en-US.md @@ -177,6 +177,85 @@ useLayoutEffect(() => { Measure logic in `useLayoutEffect` is executed before injecting style, resulting in incorrect size information. It can also be predicted that this will have an impact on developers. So we have to compromise, and in React 17 version, it will be downgraded to the original `useMemo` insertion. +## New Problem under React 17 + +With the above solution, `useInsertionEffect` perfectly solve the rendering problem. But in React 17 and below versions, we still insert styles in the render phase, but we will increase the reference count in the effect phase. But this brings a new problem, let's look at a piece of code ([CodeSandbox](https://codesandbox.io/s/aged-cdn-qjxmpz?file=/src/App.tsx:23-886)): + +```tsx +import React from 'react'; + +const A = () => { + React.useMemo(() => { + console.log('A render'); + }, []); + + React.useEffect(() => { + console.log('A mounted'); + return () => { + console.log('A unmounted'); + }; + }, []); + + return
A
; +}; + +const B = () => { + React.useMemo(() => { + console.log('B render'); + }, []); + + React.useEffect(() => { + console.log('B mounted'); + return () => { + console.log('B unmounted'); + }; + }, []); + + return
B
; +}; + +export default function App() { + const [show, setShow] = React.useState(true); + + const toggle = () => { + setShow((prev) => !prev); + }; + + return ( +
+ +
{show ? : }
+
+ ); +} +``` + +In this code (strict mode), clicking the button will switch the rendering of A and B. So what will the order of console be when switching from A to B? The answer is: + +``` +B render +B render +A unmounted +B mounted +B unmounted +B mounted +``` + +We can see that the rendering of the new component is before the unmount callback of the old component. Remember the processing logic of `cssinjs` in React 17? Let's mark it: + +``` +B render // Write to cache and insert style tag +B render // Write to cache and insert style tag +A unmounted // **Reference count--** (Reference count changed from 1 to 0, so the style was unloaded) +B mounted // Reference count++ (Reference count changed from 0 to 1, but the style was inserted before unloaded) +B unmounted // Reference count-- +B mounted // Reference count++ +``` + +We finally find out that due to reference count is not updated in time, the style was unloaded, which in not as expected. + +And the solution is simple: when the count changes from 0 to 1, style will be inserted again. + ## Summary Suspense brings rendering performance improvements, but it also makes timing very important. It is not the best way to only 'work on' StrictMode. Different logic is used for different React versions is not good choice since it will have timing problem. `render` will trigger from parent node to child node in turn, while `useInsertionEffect` is the opposite. However, from the perspective of antd, the component styles are independent of each other, so this problem will not affect us. diff --git a/docs/blog/suspense.zh-CN.md b/docs/blog/suspense.zh-CN.md index 27d84129fb..df1c263ca3 100644 --- a/docs/blog/suspense.zh-CN.md +++ b/docs/blog/suspense.zh-CN.md @@ -175,6 +175,85 @@ useLayoutEffect(() => { 测量的 `useLayoutEffect` 先于注入样式执行,导致获取了错误的尺寸信息。也可以预测到这会对开发者产生影响。因而我们退而求其次,在 React 17 版本时会降级为原先的 `useMemo` 插入。 +## 新的兼容问题 + +在上面的方案中,我们启用了 `useInsertionEffect` 从而完美解决了渲染问题。但在 React 17 及以下版本,我们仍然会在 render 阶段插入样式,但是会在 effect 阶段让引用计数加一。但是这带来了新的问题,我们来看一段代码 ([CodeSandbox](https://codesandbox.io/s/aged-cdn-qjxmpz?file=/src/App.tsx:23-886)): + +```tsx +import React from 'react'; + +const A = () => { + React.useMemo(() => { + console.log('A render'); + }, []); + + React.useEffect(() => { + console.log('A mounted'); + return () => { + console.log('A unmounted'); + }; + }, []); + + return
A
; +}; + +const B = () => { + React.useMemo(() => { + console.log('B render'); + }, []); + + React.useEffect(() => { + console.log('B mounted'); + return () => { + console.log('B unmounted'); + }; + }, []); + + return
B
; +}; + +export default function App() { + const [show, setShow] = React.useState(true); + + const toggle = () => { + setShow((prev) => !prev); + }; + + return ( +
+ ); +} +``` + +在这段代码(严格模式)中,点击按钮会切换 A 与 B 的渲染。那么从 A 切换到 B 时,顺序会是什么样的呢?答案是: + +``` +B render +B render +A unmounted +B mounted +B unmounted +B mounted +``` + +可以看到新组件的渲染是在旧组件的卸载回调之前的。还记得 cssinjs 在 React 17 一下的处理逻辑吗?我们来标记一下: + +``` +B render // 写入 cache,插入样式 +B render // 写入 cache,插入样式(虽然是重复的,但是有缓存,不会有冗余) +A unmounted // **引用计数减一** (此时原本的计数是 1,执行后变为 0,触发了样式卸载) +B mounted // 引用计数加一 (此时计数是 1,但是样式已经被 A 连带卸载) +B unmounted // 引用计数减一 +B mounted // 引用计数加一 +``` + +这样就可以发现,当 A 与 B 共用一段样式时,由于计数没有几十更新,导致样式先被卸载了,后续也并没有触发插入逻辑,所以依然会导致丢失。 + +解决方案也很简单,当计数从 0 变为 1 时,重新插入样式即可。 + ## 总结 Suspense 在带来渲染能力提升的同时也让时序变得十分重要,仅仅对 StrictMode 进行处理并不是一个最优的方式。针对不同的 React 版本使用不同的逻辑其实会存在不同版本之间的时序问题,`render` 会从父节点到子节点依次触发,而 `useInsertionEffect` 则相反。不过从 antd 角度来说,组件样式之间相互独立,所以这种时序问题并不会对我们产生影响。 diff --git a/docs/react/compatible-style.en-US.md b/docs/react/compatible-style.en-US.md index d00c4629f6..80878e8a29 100644 --- a/docs/react/compatible-style.en-US.md +++ b/docs/react/compatible-style.en-US.md @@ -71,3 +71,53 @@ When toggled, styles will downgrade CSS logical properties: ++ left: 0; } ``` + +### Rem Adaptation + +In responsive web development, there is a need for a convenient and flexible way to achieve page adaptation and responsive design. The `px2remTransformer` transformer can quickly and accurately convert pixel units in style sheets to rem units relative to the root element (HTML tag), enabling the implementation of adaptive and responsive layouts. + +```tsx +import { StyleProvider, px2remTransformer } from '@ant-design/cssinjs'; + +const px2rem = px2remTransformer({ + rootValue: 32, // 32px = 1rem; @default 16 +}); + +export default () => ( + + + +); +``` + +The resulting transformed styles: + +```diff + .px2rem-box { +- width: 400px; ++ width: 12.5rem; + background-color: green; +- font-size: 32px; ++ font-size: 1rem; + border: 10PX solid #f0f; + } + + @media only screen and (max-width: 600px) { + .px2rem-box { + background-color: red; +- margin: 10px; ++ margin: 0.3125rem; + } + } +``` + +#### Options + + +| Parameter | Description | Type | Default | +| --- | --- | --- | --- | +| rootValue | Font size of the root element | `number` | 16 | +| precision | Decimal places for the converted value | `number` | 5 | +| mediaQuery | Whether to convert px in media queries | `boolean` | false | + +For more details, please refer to: [px2rem.ts#Options](https://github.com/ant-design/cssinjs/blob/master/src/transformers/px2rem.ts) diff --git a/docs/react/compatible-style.zh-CN.md b/docs/react/compatible-style.zh-CN.md index 868fc0830d..1ee317a3c2 100644 --- a/docs/react/compatible-style.zh-CN.md +++ b/docs/react/compatible-style.zh-CN.md @@ -71,3 +71,53 @@ export default () => ( ++ left: 0; } ``` + +### rem 适配 + +在响应式网页开发中,需要一种方便且灵活的方式来实现页面的适配和响应式设计。`px2remTransformer` 转换器可以快速而准确地将样式表中的像素单位转换为相对于根元素(HTML 标签)的 rem 单位,实现页面的自适应和响应式布局。 + +```tsx +import { StyleProvider, px2remTransformer } from '@ant-design/cssinjs'; + +const px2rem = px2remTransformer({ + rootValue: 32, // 32px = 1rem; @default 16 +}); + +export default () => ( + + + +); +``` + +最终转换后的样式: + +```diff + .px2rem-box { +- width: 400px; ++ width: 12.5rem; + background-color: green; +- font-size: 32px; ++ font-size: 1rem; + border: 10PX solid #f0f; + } + + @media only screen and (max-width: 600px) { + .px2rem-box { + background-color: red; +- margin: 10px; ++ margin: 0.3125rem; + } + } +``` + +#### 配置项 + + +| 参数 | 说明 | 类型 | 默认值 | +| --- | --- | --- | --- | +| rootValue | 根元素字体大小 | `number` | 16 | +| precision | 转换后的小数点位数 | `number` | 5 | +| mediaQuery | 是否转换媒体查询中的 px | `boolean` | false | + +详细请参考: [px2rem.ts#Options](https://github.com/ant-design/cssinjs/blob/master/src/transformers/px2rem.ts) diff --git a/docs/react/faq.en-US.md b/docs/react/faq.en-US.md index 865845e137..658c2fe4cd 100644 --- a/docs/react/faq.en-US.md +++ b/docs/react/faq.en-US.md @@ -265,3 +265,30 @@ If you encounter the above error, please check the current project `tsconfig.jso ``` The above problem occurs if `strictNullChecks` is set to `true`, If you can determine the project don't need this configuration (see [strictNullChecks](https://www.typescriptlang.org/zh/tsconfig#strictNullChecks) to judge whether need the configuration). You can try changing to `false` to turn off the control strict check. However, if you do need to enable this feature, you can avoid this situation by using other types instead of `null` when designing types + +## The antd component reported an error when using the App Router of Next.js + +If you are using the App Router of Next.js, when you use the sub-components provided by some antd components, such as `Select.Option `, `Form.Item`, etc., you may get the following error: + +```bash +Error: Cannot access .Option on the server. You cannot dot into a client module from a server component. You can only pass the imported name through. +``` + +At present, this problem is waiting for Next.js to give an official solution, before this, if you use sub-components in your page, you can try to add the following client tag at the top of the page to solve this problem: + +```tsx +'use client'; + +// This is not real world code, just for explain +export default () => { + return ( +
+
+ + + +
+
+ ); +}; +``` diff --git a/docs/react/faq.zh-CN.md b/docs/react/faq.zh-CN.md index 35973d24f7..93c7189808 100644 --- a/docs/react/faq.zh-CN.md +++ b/docs/react/faq.zh-CN.md @@ -287,3 +287,30 @@ export default () => { ``` 如果 `strictNullChecks` 的值被设置为 `true` 就会出现上述问题,如果你确定项目中可以不需要这个检测配置(查看[strictNullChecks](https://www.typescriptlang.org/zh/tsconfig#strictNullChecks)判断是否需要该配置),可以尝试改为 `false` 关闭控制严格检查功能。但如果你确实需要开启这个功能,那么,你可以在设计类型时,使用其他类型替代 `null` 以避免出现这种情况。 + +## 使用 Next.js 的 App Router 时 antd 组件报错 + +如果你在使用 Next.js 的 App Router,当你使用 antd 中某些组件提供的子组件,如:`Select.Option`、`Form.Item` 等,可能会出现如下报错: + +```bash +Error: Cannot access .Option on the server. You cannot dot into a client module from a server component. You can only pass the imported name through. +``` + +目前这个问题等待 Next.js 给出官方的解决方案,在此之前,如果在你的页面中有使用子组件的话,可以尝试在页面顶部增加如下客户端标签解决这个问题: + +```tsx +'use client'; + +// This is not real world code, just for explain +export default () => { + return ( +
+
+ + + +
+
+ ); +}; +``` diff --git a/docs/react/migrate-less-variables.en-US.md b/docs/react/migrate-less-variables.en-US.md index c964b52973..bf6b9f93bd 100644 --- a/docs/react/migrate-less-variables.en-US.md +++ b/docs/react/migrate-less-variables.en-US.md @@ -240,12 +240,50 @@ export default App; ### Mentions -| less 变量 | Component Token | Note | +| Less variables | Component Token | Note | | --- | --- | --- | | `@mentions-dropdown-bg` | `colorBgElevated` | GlobalToken | | `@mentions-dropdown-menu-item-hover-bg` | - | Deprecated | - +### Menu + + +| Less variables | Component Token | Note | +| --- | --- | --- | +| `@menu-inline-toplevel-item-height` | `itemHeight` | Same as `@menu-item-height` | +| `@menu-item-height` | `itemHeight` | - | +| `@menu-item-group-height` | `groupTitleLineHeight` | - | +| `@menu-collapsed-width` | `collapsedWidth` | - | +| `@menu-bg` | `itemBg` | - | +| `@menu-popup-bg` | `popupBg` | - | +| `@menu-item-color` | `itemColor` | - | +| `@menu-inline-submenu-bg` | `subMenuItemBg` | - | +| `@menu-highlight-color` | `itemSelectedColor` | - | +| `@menu-highlight-danger-color` | `dangerItemSelectedColor` | - | +| `@menu-item-active-bg` | `itemActiveBg` | - | +| `@menu-item-active-danger-bg` | `dangerItemActiveBg` | - | +| `@menu-item-active-border-width` | `activeBarBorderWidth` | - | +| `@menu-item-group-title-color` | `groupTitleColor` | - | +| `@menu-item-vertical-margin` | `itemMarginBlock` | - | +| `@menu-item-font-size` | `fontSize` | Global Token | +| `@menu-item-boundary-margin` | - | Deprecated in favor of new style, use `itemMarginBlock` instead | +| `@menu-item-padding-horizontal` | `itemPaddingInline` | - | +| `@menu-item-padding` | - | Depreacated, use `itemPaddingInline` and `itemHeight` instead | +| `@menu-horizontal-line-height` | `horizontalLineHeight` | - | +| `@menu-icon-margin-right` | `iconMarginInlineEnd` | - | +| `@menu-icon-size` | `iconSize` | - | +| `@menu-icon-size-lg` | `horizontalLineHeight` | - | +| `@menu-dark-color` | `darkItemColor` | - | +| `@menu-dark-danger-color` | `darkDangerItemColor` | - | +| `@menu-dark-bg` | `darkItemBg` | - | +| `@menu-dark-arrow-color` | - | Deprecated, and same as text color | +| `@menu-dark-inline-submenu-bg` | `darkSubMenuItemBg` | - | +| `@menu-dark-highlight-color` | `darkItemSelectedColor` | - | +| `@menu-dark-item-active-bg` | `darkItemSelectedBg` | - | +| `@menu-dark-item-active-danger-bg` | `darkDangerItemSelectedBg` | - | +| `@menu-dark-selected-item-icon-color` | - | Deprecated, same as `darkItemSelectedColor` | +| `@menu-dark-selected-item-text-color` | - | Deprecated, same as `darkItemSelectedColor` | +| `@menu-dark-item-hover-bg` | `darkItemHoverBg` | - | ### Message diff --git a/docs/react/migrate-less-variables.zh-CN.md b/docs/react/migrate-less-variables.zh-CN.md index a95f0f65f7..b4573085de 100644 --- a/docs/react/migrate-less-variables.zh-CN.md +++ b/docs/react/migrate-less-variables.zh-CN.md @@ -243,7 +243,45 @@ Mentions 提及 | `@mentions-dropdown-bg` | `colorBgElevated` | - | | `@mentions-dropdown-menu-item-hover-bg` | - | 已废弃 | - +### Menu 导航菜单 + + +| Less 变量 | Component Token | 备注 | +| --- | --- | --- | +| `@menu-inline-toplevel-item-height` | `itemHeight` | 同 `@menu-item-height` | +| `@menu-item-height` | `itemHeight` | - | +| `@menu-item-group-height` | `groupTitleLineHeight` | - | +| `@menu-collapsed-width` | `collapsedWidth` | - | +| `@menu-bg` | `itemBg` | - | +| `@menu-popup-bg` | `popupBg` | - | +| `@menu-item-color` | `itemColor` | - | +| `@menu-inline-submenu-bg` | `subMenuItemBg` | - | +| `@menu-highlight-color` | `itemSelectedColor` | - | +| `@menu-highlight-danger-color` | `dangerItemSelectedColor` | - | +| `@menu-item-active-bg` | `itemActiveBg` | - | +| `@menu-item-active-danger-bg` | `dangerItemActiveBg` | - | +| `@menu-item-active-border-width` | `activeBarBorderWidth` | - | +| `@menu-item-group-title-color` | `groupTitleColor` | - | +| `@menu-item-vertical-margin` | `itemMarginBlock` | - | +| `@menu-item-font-size` | `fontSize` | 全局 Token | +| `@menu-item-boundary-margin` | - | 因样式调整已废弃,可使用 `itemMarginBlock` 替代 | +| `@menu-item-padding-horizontal` | `itemPaddingInline` | - | +| `@menu-item-padding` | - | 已废弃,使用 `itemPaddingInline` 和 `itemHeight` 替代 | +| `@menu-horizontal-line-height` | `horizontalLineHeight` | - | +| `@menu-icon-margin-right` | `iconMarginInlineEnd` | - | +| `@menu-icon-size` | `iconSize` | - | +| `@menu-icon-size-lg` | `horizontalLineHeight` | - | +| `@menu-dark-color` | `darkItemColor` | - | +| `@menu-dark-danger-color` | `darkDangerItemColor` | - | +| `@menu-dark-bg` | `darkItemBg` | - | +| `@menu-dark-arrow-color` | - | 已废弃,和文字颜色相同 | +| `@menu-dark-inline-submenu-bg` | `darkSubMenuItemBg` | - | +| `@menu-dark-highlight-color` | `darkItemSelectedColor` | - | +| `@menu-dark-item-active-bg` | `darkItemSelectedBg` | - | +| `@menu-dark-item-active-danger-bg` | `darkDangerItemSelectedBg` | - | +| `@menu-dark-selected-item-icon-color` | - | 已废弃,同 `darkItemSelectedColor` | +| `@menu-dark-selected-item-text-color` | - | 已废弃,同 `darkItemSelectedColor` | +| `@menu-dark-item-hover-bg` | `darkItemHoverBg` | - | ### Message 全局提示 diff --git a/docs/react/use-with-next.en-US.md b/docs/react/use-with-next.en-US.md index 5a8bfa2b04..150194f7ea 100644 --- a/docs/react/use-with-next.en-US.md +++ b/docs/react/use-with-next.en-US.md @@ -31,8 +31,6 @@ Now we install `antd` from yarn or npm or pnpm. Modify `src/app/page.tsx`, import Button component from `antd`. ```jsx -'use client'; - import React from 'react'; import { Button } from 'antd'; @@ -48,3 +46,200 @@ export default Home; OK, you should now see a blue primary button displayed on the page. Next you can choose any components of `antd` to develop your application. Visit other workflows of `Next.js` at its [User Guide](https://nextjs.org/). We are successfully running antd components now, go build your own application! + +## Use the Pages Router of Next.js + +If you are using the Pages Router in Next.js and using antd as your component library, to make the antd component library work better in your Next.js application and provide a better user experience, you can try using the following method to extract and inject antd's first-screen styles into HTML to avoid page flicker. + +1. Install `@ant-design/cssinjs` + + + +2. Rewrite `pages/_document.tsx` + +```tsx +import Document, { Html, Head, Main, NextScript, DocumentContext } from 'next/document'; +import { StyleProvider, createCache, extractStyle } from '@ant-design/cssinjs'; + +const MyDocument = () => ( + + + +
+ + + +); + +MyDocument.getInitialProps = async (ctx: DocumentContext) => { + const cache = createCache(); + const originalRenderPage = ctx.renderPage; + ctx.renderPage = () => + originalRenderPage({ + enhanceApp: (App) => (props) => ( + + + + ), + }); + + const initialProps = await Document.getInitialProps(ctx); + // 1.1 extract style which had been used + const style = extractStyle(cache, true); + return { + ...initialProps, + styles: ( + <> + {initialProps.styles} + {/* 1.2 inject css */} + + + ), + }; +}; + +export default MyDocument; +``` + +3. Supports custom themes + +```tsx +import React from 'react'; +import { ConfigProvider } from 'antd'; + +const withTheme = (node: JSX.Element) => ( + <> + + {node} + + +); + +export default withTheme; +``` + +4. Rewrite `pages/_app.tsx` + +```tsx +import '../styles/globals.css'; +import type { AppProps } from 'next/app'; +import withTheme from '../theme'; + +export default function App({ Component, pageProps }: AppProps) { + return withTheme(); +} +``` + +5. Use antd in page component + +```tsx +import { Button } from 'antd'; + +export default function Home() { + return ( +
+ +
+ ); +} +``` + +For more detailed information, please refer to [with-nextjs-inline-style](https://github.com/ant-design/ant-design-examples/tree/main/examples/with-nextjs-inline-style). + +## Using Next.js App Router + +If you are using the App Router in Next.js and using antd as your component library, to make the antd component library work better in your Next.js application and provide a better user experience, you can try using the following method to extract and inject antd's first-screen styles into HTML to avoid page flicker. + +1. Install `@ant-design/cssinjs` + + + +2. Create `lib/AntdRegistry.tsx` + +```tsx +'use client'; + +import { StyleProvider, createCache, extractStyle } from '@ant-design/cssinjs'; +import { useServerInsertedHTML } from 'next/navigation'; +import React from 'react'; + +const StyledComponentsRegistry = ({ children }: { children: React.ReactNode }) => { + const cache = createCache(); + useServerInsertedHTML(() => ( + + + ), + }; +}; + +export default MyDocument; +``` + +3. 支持自定义主题 + +```tsx +import React from 'react'; +import { ConfigProvider } from 'antd'; + +const withTheme = (node: JSX.Element) => ( + <> + + {node} + + +); + +export default withTheme; +``` + +4. 改写 `pages/_app.tsx` + +```tsx +import '../styles/globals.css'; +import type { AppProps } from 'next/app'; +import withTheme from '../theme'; + +export default function App({ Component, pageProps }: AppProps) { + return withTheme(); +} +``` + +5. 在页面中使用 antd + +```tsx +import { Button } from 'antd'; + +export default function Home() { + return ( +
+ +
+ ); +} +``` + +更多详细的细节可以参考 [with-nextjs-inline-style](https://github.com/ant-design/ant-design-examples/tree/main/examples/with-nextjs-inline-style)。 + +## 使用 Next.js 的 App Router + +如果你在 Next.js 当中使用了 App Router, 并使用 antd 作为页面组件库,为了让 antd 组件库在你的 Next.js 应用中能够更好的工作,提供更好的用户体验,你可以尝试使用下面的方式将 antd 首屏样式按需抽离并植入到 HTML 中,以避免页面闪动的情况。 + +1. 安装 `@ant-design/cssinjs` + + + +2. 创建 `lib/AntdRegistry.tsx` + +```tsx +import { StyleProvider, createCache, extractStyle } from '@ant-design/cssinjs'; +import { useServerInsertedHTML } from 'next/navigation'; +import React from 'react'; + +const StyledComponentsRegistry = ({ children }: { children: React.ReactNode }) => { + const cache = createCache(); + useServerInsertedHTML(() => ( +