diff --git a/.circleci/config.yml b/.circleci/config.yml index ed1f4c5e93cd..269504b01ce6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,7 +7,9 @@ version: 2.1 jobs: test-argos-ci: docker: - - image: cimg/node:16.20-browsers + - image: cimg/node:18.18-browsers + environment: + NODE_OPTIONS: --openssl-legacy-provider steps: - checkout - run: diff --git a/.dumi/hooks/use.ts b/.dumi/hooks/use.ts index d4d572981ba6..2502dcd1fa4e 100644 --- a/.dumi/hooks/use.ts +++ b/.dumi/hooks/use.ts @@ -1,11 +1,11 @@ -export default function use(promise: PromiseLike): T { +function use(promise: PromiseLike): T { const internal: PromiseLike & { status?: 'pending' | 'fulfilled' | 'rejected'; value?: T; reason?: any; } = promise; if (internal.status === 'fulfilled') { - return internal.value; + return internal.value as T; } if (internal.status === 'rejected') { throw internal.reason; @@ -26,3 +26,5 @@ export default function use(promise: PromiseLike): T { throw internal; } } + +export default use; diff --git a/.dumi/hooks/useDark.tsx b/.dumi/hooks/useDark.tsx new file mode 100644 index 000000000000..6b31dee12c40 --- /dev/null +++ b/.dumi/hooks/useDark.tsx @@ -0,0 +1,7 @@ +import React from 'react'; + +export const DarkContext = React.createContext(false); + +export default function useDark() { + return React.useContext(DarkContext); +} diff --git a/.dumi/hooks/useLocale.ts b/.dumi/hooks/useLocale.ts index 9bc0dc4d4840..8ad296953196 100644 --- a/.dumi/hooks/useLocale.ts +++ b/.dumi/hooks/useLocale.ts @@ -5,10 +5,12 @@ export interface LocaleMap { en: Record; } -export default function useLocale( +function useLocale( localeMap?: LocaleMap, ): [Record, 'cn' | 'en'] { const { id } = useDumiLocale(); - const localeType = id === 'zh-CN' ? 'cn' : 'en'; - return [localeMap?.[localeType], localeType]; + const localeType = id === 'zh-CN' ? ('cn' as const) : ('en' as const); + return [localeMap?.[localeType]!, localeType]; } + +export default useLocale; diff --git a/.dumi/hooks/useMenu.tsx b/.dumi/hooks/useMenu.tsx index 37483b149a72..89bc9e16402e 100644 --- a/.dumi/hooks/useMenu.tsx +++ b/.dumi/hooks/useMenu.tsx @@ -1,7 +1,8 @@ -import { useFullSidebarData, useSidebarData } from 'dumi'; import React, { useMemo } from 'react'; import type { MenuProps } from 'antd'; import { Tag, version } from 'antd'; +import { useFullSidebarData, useSidebarData } from 'dumi'; + import Link from '../theme/common/Link'; import useLocation from './useLocation'; @@ -136,7 +137,7 @@ const useMenu = (options: UseMenuOptions = {}): [MenuProps['items'], string] => const list = group.children || []; // 如果有 date 字段,我们就对其进行排序 if (list.every((info) => info?.frontmatter?.date)) { - list.sort((a, b) => (a.frontmatter.date > b.frontmatter.date ? -1 : 1)); + list.sort((a, b) => (a.frontmatter?.date > b.frontmatter?.date ? -1 : 1)); } result.push( diff --git a/.dumi/hooks/useThemeAnimation.ts b/.dumi/hooks/useThemeAnimation.ts new file mode 100644 index 000000000000..34b72e780960 --- /dev/null +++ b/.dumi/hooks/useThemeAnimation.ts @@ -0,0 +1,127 @@ +import { useEffect, useRef } from 'react'; +import { removeCSS, updateCSS } from 'rc-util/lib/Dom/dynamicCSS'; + +import theme from '../../components/theme'; + +const viewTransitionStyle = ` +::view-transition-old(root), +::view-transition-new(root) { + animation: none; + mix-blend-mode: normal; +} + +.dark::view-transition-old(root) { + z-index: 1; +} + +.dark::view-transition-new(root) { + z-index: 999; +} + +::view-transition-old(root) { + z-index: 999; +} + +::view-transition-new(root) { + z-index: 1; +} +`; + +const useThemeAnimation = () => { + const { + token: { colorBgElevated }, + } = theme.useToken(); + + const animateRef = useRef<{ colorBgElevated: string }>({ colorBgElevated }); + + const startAnimationTheme = (clipPath: string[], isDark: boolean) => { + updateCSS( + ` + * { + transition: none !important; + } + `, + 'disable-transition', + ); + + document.documentElement + .animate( + { + clipPath: isDark ? [...clipPath].reverse() : clipPath, + }, + { + duration: 500, + easing: 'ease-in', + pseudoElement: isDark ? '::view-transition-old(root)' : '::view-transition-new(root)', + }, + ) + .addEventListener('finish', () => { + removeCSS('disable-transition'); + }); + }; + + const toggleAnimationTheme = ( + event: React.MouseEvent, + isDark: boolean, + ) => { + // @ts-ignore + if (!(event && typeof document.startViewTransition === 'function')) { + return; + } + const x = event.clientX; + const y = event.clientY; + const endRadius = Math.hypot(Math.max(x, innerWidth - x), Math.max(y, innerHeight - y)); + updateCSS( + ` + [data-prefers-color='dark'] { + color-scheme: light !important; + } + + [data-prefers-color='light'] { + color-scheme: dark !important; + } + `, + 'color-scheme', + ); + document + // @ts-ignore + .startViewTransition(async () => { + // wait for theme change end + while (colorBgElevated === animateRef.current.colorBgElevated) { + // eslint-disable-next-line no-await-in-loop + await new Promise((resolve) => { + setTimeout(resolve, 1000 / 60); + }); + } + const root = document.documentElement; + root.classList.remove(isDark ? 'dark' : 'light'); + root.classList.add(isDark ? 'light' : 'dark'); + }) + .ready.then(() => { + const clipPath = [ + `circle(0px at ${x}px ${y}px)`, + `circle(${endRadius}px at ${x}px ${y}px)`, + ]; + removeCSS('color-scheme'); + startAnimationTheme(clipPath, isDark); + }); + }; + + // inject transition style + useEffect(() => { + // @ts-ignore + if (typeof document.startViewTransition === 'function') { + updateCSS(viewTransitionStyle, 'view-transition-style'); + } + }, []); + + useEffect(() => { + if (colorBgElevated !== animateRef.current.colorBgElevated) { + animateRef.current.colorBgElevated = colorBgElevated; + } + }, [colorBgElevated]); + + return toggleAnimationTheme; +}; + +export default useThemeAnimation; diff --git a/.dumi/mirror-modal.js b/.dumi/mirror-modal.js new file mode 100644 index 000000000000..3128af996d90 --- /dev/null +++ b/.dumi/mirror-modal.js @@ -0,0 +1,173 @@ +(function createMirrorModal() { + if ( + (navigator.languages.includes('zh') || navigator.languages.includes('zh-CN')) && + /-cn\/?$/.test(window.location.pathname) && + !['ant-design.gitee.io', 'ant-design.antgroup.com'].includes(window.location.hostname) && + !window.location.host.includes('surge') + ) { + const ANTD_DOT_NOT_SHOW_MIRROR_MODAL = 'ANT_DESIGN_DO_NOT_OPEN_MIRROR_MODAL'; + + const lastShowTime = window.localStorage.getItem(ANTD_DOT_NOT_SHOW_MIRROR_MODAL); + if ( + lastShowTime && + lastShowTime !== 'true' && + Date.now() - new Date(lastShowTime).getTime() < 7 * 24 * 60 * 60 * 1000 + ) { + return; + } + + const style = document.createElement('style'); + style.innerHTML = ` + @keyframes mirror-fade-in { + from { + opacity: 0; + } + to { + opacity: 1; + } + } + + @keyframes mirror-zoom-in { + from { + transform: scale(0.8); + } + to { + transform: scale(1); + } + } + + .mirror-modal-mask { + position: fixed; + inset: 0; + height: '100vh'; + width: '100vw'; + background: rgba(0, 0, 0, 0.3); + z-index: 9999; + animation: mirror-fade-in 0.3s forwards; + } + + .mirror-modal-dialog { + position: fixed; + inset: 0; + top: 120px; + margin-left: auto; + margin-right: auto; + width: 400px; + height: 120px; + display: flex; + align-items: center; + flex-direction: column; + border-radius: 8px; + border: 1px solid #eee; + background: #fff; + padding: 20px 24px; + box-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05); + animation: mirror-zoom-in 0.3s forwards; + } + + .mirror-modal-title { + font-size: 16px; + font-weight: 500; + align-self: flex-start; + margin-bottom: 8px; + } + + .mirror-modal-content { + font-size: 14px; + align-self: flex-start; + margin-bottom: 16px; + } + + .mirror-modal-btns { + align-self: flex-end; + margin-top: auto; + display: flex; + align-items: center; + } + + .mirror-modal-btn { + border-radius: 6px; + cursor: pointer; + height: 32px; + box-sizing: border-box; + font-size: 14px; + padding: 4px 16px; + display: inline-flex; + align-items: center; + text-decoration: none; + transition: all 0.2s; + } + + .mirror-modal-confirm-btn { + background: #1677ff; + color: #fff; + } + + .mirror-modal-confirm-btn:hover { + background: #4096ff; + } + + .mirror-modal-confirm-btn:active { + background: #0958d9; + } + + .mirror-modal-cancel-btn { + border: 1px solid #eee; + color: #000; + margin-right: 8px; + } + + .mirror-modal-cancel-btn:hover { + border-color: #4096ff; + color: #4096ff + } + + .mirror-modal-cancel-btn:active { + border-color: #0958d9; + color: #0958d9; + } + `; + document.head.append(style); + + const modal = document.createElement('div'); + modal.className = 'mirror-modal-mask'; + + const dialog = document.createElement('div'); + dialog.className = 'mirror-modal-dialog'; + modal.append(dialog); + + const title = document.createElement('div'); + title.className = 'mirror-modal-title'; + title.innerText = '提示'; + dialog.append(title); + + const content = document.createElement('div'); + content.className = 'mirror-modal-content'; + content.innerText = '国内用户推荐访问国内镜像以获得极速体验~'; + dialog.append(content); + + const btnWrapper = document.createElement('div'); + btnWrapper.className = 'mirror-modal-btns'; + dialog.append(btnWrapper); + + const cancelBtn = document.createElement('a'); + cancelBtn.className = 'mirror-modal-cancel-btn mirror-modal-btn'; + cancelBtn.innerText = '7 天内不再显示'; + btnWrapper.append(cancelBtn); + cancelBtn.addEventListener('click', () => { + window.localStorage.setItem(ANTD_DOT_NOT_SHOW_MIRROR_MODAL, new Date().toISOString()); + document.body.removeChild(modal); + document.head.removeChild(style); + document.body.style.overflow = ''; + }); + + const confirmBtn = document.createElement('a'); + confirmBtn.className = 'mirror-modal-confirm-btn mirror-modal-btn'; + confirmBtn.href = window.location.href.replace(window.location.host, 'ant-design.antgroup.com'); + confirmBtn.innerText = '🚀 立刻前往'; + btnWrapper.append(confirmBtn); + + document.body.append(modal); + document.body.style.overflow = 'hidden'; + } +})(); diff --git a/.dumi/pages/index/components/ComponentsList.tsx b/.dumi/pages/index/components/ComponentsList.tsx index 4885c7a0ba92..a528d1c4ce4a 100644 --- a/.dumi/pages/index/components/ComponentsList.tsx +++ b/.dumi/pages/index/components/ComponentsList.tsx @@ -1,21 +1,23 @@ /* eslint-disable react/jsx-pascal-case */ import React, { useContext } from 'react'; -import dayjs from 'dayjs'; import { CustomerServiceOutlined, QuestionCircleOutlined, SyncOutlined } from '@ant-design/icons'; -import { createStyles, css, useTheme } from 'antd-style'; -import classNames from 'classnames'; import { - Space, - Typography, - Tour, - Tag, - DatePicker, Alert, - Modal, + Carousel, + DatePicker, FloatButton, + Modal, Progress, - Carousel, + Space, + Tag, + Tour, + Typography, } from 'antd'; +import { createStyles, css, useTheme } from 'antd-style'; +import classNames from 'classnames'; +import dayjs from 'dayjs'; + +import useDark from '../../../hooks/useDark'; import useLocale from '../../../hooks/useLocale'; import SiteContext from '../../../theme/slots/SiteContext'; import { getCarouselStyle } from './util'; @@ -55,40 +57,45 @@ const locales = { }, }; -const useStyle = createStyles(({ token }) => { - const { carousel } = getCarouselStyle(); +const useStyle = () => { + const isRootDark = useDark(); - return { - card: css` - border-radius: ${token.borderRadius}px; - background: #f5f8ff; - padding: ${token.paddingXL}px; - flex: none; - overflow: hidden; - position: relative; - display: flex; - flex-direction: column; - align-items: stretch; + return createStyles(({ token }) => { + const { carousel } = getCarouselStyle(); - > * { + return { + card: css` + border-radius: ${token.borderRadius}px; + border: 1px solid ${isRootDark ? token.colorBorder : 'transparent'}; + background: ${isRootDark ? token.colorBgContainer : '#f5f8ff'}; + padding: ${token.paddingXL}px; flex: none; - } - `, - cardCircle: css` - position: absolute; - width: 120px; - height: 120px; - background: #1677ff; - border-radius: 50%; - filter: blur(40px); - opacity: 0.1; - `, - mobileCard: css` - height: 395px; - `, - carousel, - }; -}); + overflow: hidden; + position: relative; + display: flex; + flex-direction: column; + align-items: stretch; + + > * { + flex: none; + } + `, + cardCircle: css` + position: absolute; + width: 120px; + height: 120px; + background: #1677ff; + border-radius: 50%; + filter: blur(40px); + opacity: 0.1; + `, + mobileCard: css` + height: 395px; + `, + carousel, + }; + })(); +}; const ComponentItem: React.FC = ({ title, node, type, index }) => { const tagColor = type === 'new' ? 'processing' : 'warning'; diff --git a/.dumi/pages/index/components/DesignFramework.tsx b/.dumi/pages/index/components/DesignFramework.tsx index 4060493b23c4..1f744b343329 100644 --- a/.dumi/pages/index/components/DesignFramework.tsx +++ b/.dumi/pages/index/components/DesignFramework.tsx @@ -1,10 +1,12 @@ import React, { useContext } from 'react'; +import { Col, Row, Typography } from 'antd'; import { createStyles, useTheme } from 'antd-style'; import { Link, useLocation } from 'dumi'; -import { Col, Row, Typography } from 'antd'; + +import useDark from '../../../hooks/useDark'; import useLocale from '../../../hooks/useLocale'; -import * as utils from '../../../theme/utils'; import SiteContext from '../../../theme/slots/SiteContext'; +import * as utils from '../../../theme/utils'; const SECONDARY_LIST = [ { @@ -60,12 +62,17 @@ const locales = { }, }; -const useStyle = createStyles(({ token, css }) => ({ - card: css` +const useStyle = () => { + const isRootDark = useDark(); + + return createStyles(({ token, css }) => ({ + card: css` padding: ${token.paddingSM}px; border-radius: ${token.borderRadius * 2}px; - background: #fff; - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03), 0 1px 6px -1px rgba(0, 0, 0, 0.02), + background: ${isRootDark ? 'rgba(0,0,0,0.45)' : token.colorBgElevated}; + box-shadow: + 0 1px 2px rgba(0, 0, 0, 0.03), + 0 1px 6px -1px rgba(0, 0, 0, 0.02), 0 2px 4px rgba(0, 0, 0, 0.02); img { @@ -75,18 +82,19 @@ const useStyle = createStyles(({ token, css }) => ({ } `, - cardMini: css` + cardMini: css` display: block; border-radius: ${token.borderRadius * 2}px; padding: ${token.paddingMD}px ${token.paddingLG}px; - background: rgba(0, 0, 0, 0.02); - border: 1px solid rgba(0, 0, 0, 0.06); + background: ${isRootDark ? 'rgba(0,0,0,0.25)' : 'rgba(0, 0, 0, 0.02)'}; + border: 1px solid ${isRootDark ? 'rgba(255,255,255, 0.45)' : 'rgba(0, 0, 0, 0.06)'}; img { height: 48px; } `, -})); + }))(); +}; export default function DesignFramework() { const [locale] = useLocale(locales); diff --git a/.dumi/pages/index/components/Group.tsx b/.dumi/pages/index/components/Group.tsx index 1ea9a7e0b5a3..788809502f32 100644 --- a/.dumi/pages/index/components/Group.tsx +++ b/.dumi/pages/index/components/Group.tsx @@ -1,21 +1,26 @@ import * as React from 'react'; import { useContext } from 'react'; -import { useTheme } from 'antd-style'; import { Typography } from 'antd'; +import { useTheme } from 'antd-style'; + import SiteContext from '../../../theme/slots/SiteContext'; export interface GroupMaskProps { style?: React.CSSProperties; children?: React.ReactNode; disabled?: boolean; + onMouseMove?: React.MouseEventHandler; + onMouseEnter?: React.MouseEventHandler; + onMouseLeave?: React.MouseEventHandler; } -export function GroupMask({ children, style, disabled }: GroupMaskProps) { +export const GroupMask: React.FC = (props) => { + const { children, style, disabled, onMouseMove, onMouseEnter, onMouseLeave } = props; const additionalStyle: React.CSSProperties = disabled ? {} : { position: 'relative', - background: `rgba(255,255,255,0.1)`, + background: `rgba(255, 255, 255, 0.1)`, backdropFilter: `blur(25px)`, zIndex: 1, }; @@ -23,16 +28,15 @@ export function GroupMask({ children, style, disabled }: GroupMaskProps) { return (
{children}
); -} +}; export interface GroupProps { id?: string; @@ -48,7 +52,7 @@ export interface GroupProps { decoration?: React.ReactNode; } -export default function Group(props: GroupProps) { +const Group: React.FC = (props) => { const { id, title, titleColor, description, children, decoration, background, collapse } = props; const token = useTheme(); const { isMobile } = useContext(SiteContext); @@ -79,8 +83,8 @@ export default function Group(props: GroupProps) { {description} @@ -107,11 +111,13 @@ export default function Group(props: GroupProps) { {childNode} ); -} +}; + +export default Group; diff --git a/.dumi/pages/index/components/PreviewBanner/ComponentsBlock.tsx b/.dumi/pages/index/components/PreviewBanner/ComponentsBlock.tsx new file mode 100644 index 000000000000..42dc50702d02 --- /dev/null +++ b/.dumi/pages/index/components/PreviewBanner/ComponentsBlock.tsx @@ -0,0 +1,259 @@ +import React from 'react'; +import { AntDesignOutlined, CheckOutlined, CloseOutlined } from '@ant-design/icons'; +import { + Alert, + Button, + Checkbox, + ColorPicker, + Dropdown, + Input, + message, + Modal, + Progress, + Select, + Slider, + Steps, + Switch, + Tooltip, +} from 'antd'; +import { createStyles } from 'antd-style'; +import classNames from 'classnames'; + +import useLocale from '../../../../hooks/useLocale'; + +const { _InternalPanelDoNotUseOrYouWillBeFired: ModalPanel } = Modal; +const { _InternalPanelDoNotUseOrYouWillBeFired: InternalTooltip } = Tooltip; +const { _InternalPanelDoNotUseOrYouWillBeFired: InternalMessage } = message; + +const locales = { + cn: { + range: '设置范围', + text: 'Ant Design 5.0 使用 CSS-in-JS 技术以提供动态与混合主题的能力。与此同时,我们使用组件级别的 CSS-in-JS 解决方案,让你的应用获得更好的性能。', + infoText: '信息内容展示', + dropdown: '下拉菜单', + finished: '已完成', + inProgress: '进行中', + waiting: '等待中', + option: '选项', + apple: '苹果', + banana: '香蕉', + orange: '橘子', + watermelon: '西瓜', + primary: '主要按钮', + danger: '危险按钮', + default: '默认按钮', + dashed: '虚线按钮', + icon: '图标按钮', + hello: '你好,Ant Design!', + release: 'Ant Design 5.0 正式发布!', + }, + en: { + range: 'Set Range', + text: 'Ant Design 5.0 use CSS-in-JS technology to provide dynamic & mix theme ability. And which use component level CSS-in-JS solution get your application a better performance.', + infoText: 'Info Text', + dropdown: 'Dropdown', + finished: 'Finished', + inProgress: 'In Progress', + waiting: 'Waiting', + option: 'Option', + apple: 'Apple', + banana: 'Banana', + orange: 'Orange', + watermelon: 'Watermelon', + primary: 'Primary', + danger: 'Danger', + default: 'Default', + dashed: 'Dashed', + icon: 'Icon', + hello: 'Hello, Ant Design!', + release: 'Ant Design 5.0 is released!', + }, +}; + +const useStyle = createStyles(({ token, css }) => { + const gap = token.padding; + + return { + holder: css` + width: 500px; + display: flex; + flex-direction: column; + row-gap: ${gap}px; + opacity: 0.65; + `, + + flex: css` + display: flex; + flex-wrap: nowrap; + column-gap: ${gap}px; + `, + ptg_20: css` + flex: 0 1 20%; + `, + ptg_none: css` + flex: none; + `, + block: css` + background-color: ${token.colorBgContainer}; + padding: ${token.paddingXS}px ${token.paddingSM}px; + border-radius: ${token.borderRadius}px; + border: 1px solid ${token.colorBorder}; + `, + noMargin: css` + margin: 0; + `, + }; +}); + +export interface ComponentsBlockProps { + className?: string; + style?: React.CSSProperties; +} + +const ComponentsBlock: React.FC = (props) => { + const { className, style } = props; + + const [locale] = useLocale(locales); + const { styles } = useStyle(); + + return ( +
+ + {locale.text} + + + + + {/* Line */} +
+ +
+ ({ + key: `opt${index}`, + label: `${locale.option} ${index}`, + })), + }} + > + {locale.dropdown} + +
+ + +
+ + + + + + + {/* Line */} +
+ 100°C, + }, + }} + defaultValue={[26, 37]} + /> +
+ + {/* Line */} +
+ + + + + +
+ + {/* Line */} +
+
+ } + unCheckedChildren={} + /> + + +
+
+ +
+ +
+ + + + +
+ ); +}; + +export default ComponentsBlock; diff --git a/.dumi/pages/index/components/PreviewBanner/index.tsx b/.dumi/pages/index/components/PreviewBanner/index.tsx new file mode 100644 index 000000000000..cf257a0d6d77 --- /dev/null +++ b/.dumi/pages/index/components/PreviewBanner/index.tsx @@ -0,0 +1,142 @@ +import React from 'react'; +import { Button, ConfigProvider, Space, Typography } from 'antd'; +import { createStyles, useTheme } from 'antd-style'; +import { Link, useLocation } from 'dumi'; + +import useLocale from '../../../../hooks/useLocale'; +import SiteContext from '../../../../theme/slots/SiteContext'; +import * as utils from '../../../../theme/utils'; +import { GroupMask } from '../Group'; +import ComponentsBlock from './ComponentsBlock'; +import useMouseTransform from './useMouseTransform'; + +const locales = { + cn: { + slogan: '助力设计开发者「更灵活」地搭建出「更美」的产品,让用户「快乐工作」~', + start: '开始使用', + designLanguage: '设计语言', + }, + en: { + slogan: + 'Help designers/developers building beautiful products more flexible and working with happiness', + start: 'Getting Started', + designLanguage: 'Design Language', + }, +}; + +const useStyle = () => { + const { direction } = React.useContext(ConfigProvider.ConfigContext); + const isRTL = direction === 'rtl'; + + return createStyles(({ token, css }) => { + const textShadow = `0 0 3px ${token.colorBgContainer}`; + + return { + holder: css` + height: 520px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + position: relative; + overflow: hidden; + perspective: 800px; + row-gap: ${token.marginXL}px; + `, + + typography: css` + text-align: center; + position: relative; + z-index: 1; + padding-inline: ${token.paddingXL}px; + text-shadow: ${new Array(5) + .fill(null) + .map(() => textShadow) + .join(', ')}; + + h1 { + font-family: AliPuHui, ${token.fontFamily} !important; + font-weight: 900 !important; + font-size: ${token.fontSizeHeading2 * 2}px !important; + line-height: ${token.lineHeightHeading2} !important; + } + + p { + font-size: ${token.fontSizeLG}px !important; + font-weight: normal !important; + margin-bottom: 0; + } + `, + + block: css` + position: absolute; + inset-inline-end: 0; + top: -38px; + transform: ${isRTL ? 'rotate3d(24, 83, -45, 57deg)' : 'rotate3d(24, -83, 45, 57deg)'}; + `, + + child: css` + position: relative; + z-index: 1; + `, + }; + })(); +}; + +export interface PreviewBannerProps { + children?: React.ReactNode; +} + +const PreviewBanner: React.FC = (props) => { + const { children } = props; + + const [locale] = useLocale(locales); + const { styles } = useStyle(); + const { isMobile } = React.useContext(SiteContext); + const token = useTheme(); + const { pathname, search } = useLocation(); + const isZhCN = utils.isZhCN(pathname); + + const [componentsBlockStyle, mouseEvents] = useMouseTransform(); + + return ( + + {/* Image Left Top */} + bg + {/* Image Right Top */} + bg + +
+ {/* Mobile not show the component preview */} + {!isMobile && } + + +

Ant Design 5.0

+

{locale.slogan}

+
+ + + + + + + + + +
{children}
+
+
+ ); +}; + +export default PreviewBanner; diff --git a/.dumi/pages/index/components/PreviewBanner/useMouseTransform.tsx b/.dumi/pages/index/components/PreviewBanner/useMouseTransform.tsx new file mode 100644 index 000000000000..a6985067bb6a --- /dev/null +++ b/.dumi/pages/index/components/PreviewBanner/useMouseTransform.tsx @@ -0,0 +1,73 @@ +import React, { startTransition } from 'react'; +import { ConfigProvider } from 'antd'; + +const getTransformRotateStyle = ( + event: React.MouseEvent, + currentTarget: EventTarget & HTMLDivElement, + multiple: number, + isRTL: boolean, +): string => { + const box = currentTarget?.getBoundingClientRect(); + const calcX = -(event.clientY - box.y - box.height / 2) / multiple; + const calcY = (event.clientX - box.x - box.width / 2) / multiple; + return isRTL + ? `rotate3d(${24 + calcX}, ${83 + calcY}, -45, 57deg)` + : `rotate3d(${24 + calcX}, ${-83 + calcY}, 45, 57deg)`; +}; + +const useMouseTransform = ({ transitionDuration = 500, multiple = 36 } = {}) => { + const [componentsBlockStyle, setComponentsBlockStyle] = React.useState({}); + + const { direction } = React.useContext(ConfigProvider.ConfigContext); + + const isRTL = direction === 'rtl'; + + const onMouseMove: React.MouseEventHandler = (event) => { + const { currentTarget } = event; + startTransition(() => { + setComponentsBlockStyle((style) => ({ + ...style, + transform: getTransformRotateStyle(event, currentTarget, multiple, isRTL), + })); + }); + }; + + const onMouseEnter: React.MouseEventHandler = () => { + startTransition(() => { + setComponentsBlockStyle((style) => ({ + ...style, + transition: `transform ${transitionDuration / 1000}s`, + })); + }); + + setTimeout(() => { + startTransition(() => { + setComponentsBlockStyle((style) => ({ + ...style, + transition: '', + })); + }); + }, transitionDuration); + }; + + const onMouseLeave: React.MouseEventHandler = () => { + startTransition(() => { + setComponentsBlockStyle((style) => ({ + ...style, + transition: `transform ${transitionDuration / 1000}s`, + transform: '', + })); + }); + }; + + return [ + componentsBlockStyle, + { + onMouseMove, + onMouseEnter, + onMouseLeave, + }, + ] as const; +}; + +export default useMouseTransform; diff --git a/.dumi/pages/index/components/Theme/BackgroundImage.tsx b/.dumi/pages/index/components/Theme/BackgroundImage.tsx index 32bc19c0b3a2..077f34dc2899 100644 --- a/.dumi/pages/index/components/Theme/BackgroundImage.tsx +++ b/.dumi/pages/index/components/Theme/BackgroundImage.tsx @@ -1,7 +1,8 @@ -import { createStyles, css } from 'antd-style'; import React, { useMemo, useState } from 'react'; -import { CSSMotionList } from 'rc-motion'; +import { createStyles, css } from 'antd-style'; import classNames from 'classnames'; +import { CSSMotionList } from 'rc-motion'; + import { COLOR_IMAGES, getClosetColor } from './colorUtil'; export interface BackgroundImageProps { @@ -36,7 +37,7 @@ const BackgroundImage: React.FC = ({ colorPrimary, isLight const [keyList, setKeyList] = useState([]); React.useLayoutEffect(() => { - setKeyList([activeColor]); + setKeyList([activeColor as string]); }, [activeColor]); return ( @@ -56,7 +57,7 @@ const BackgroundImage: React.FC = ({ colorPrimary, isLight const entity = COLOR_IMAGES.find((ent) => ent.color === color); if (!entity || !entity.url) { - return null; + return null as unknown as React.ReactElement; } const { opacity } = style || {}; diff --git a/.dumi/pages/index/components/Theme/ColorPicker.tsx b/.dumi/pages/index/components/Theme/ColorPicker.tsx index 3642d1357325..464566be4759 100644 --- a/.dumi/pages/index/components/Theme/ColorPicker.tsx +++ b/.dumi/pages/index/components/Theme/ColorPicker.tsx @@ -1,39 +1,48 @@ -import { createStyles } from 'antd-style'; -import type { FC } from 'react'; import React, { useEffect, useState } from 'react'; -import classNames from 'classnames'; import { ColorPicker, Input, Space } from 'antd'; -import type { Color, ColorPickerProps } from 'antd/es/color-picker'; +import { createStyles } from 'antd-style'; +import type { Color } from 'antd/es/color-picker'; import { generateColor } from 'antd/es/color-picker/util'; +import classNames from 'classnames'; + import { PRESET_COLORS } from './colorUtil'; const useStyle = createStyles(({ token, css }) => ({ color: css` - width: ${token.controlHeightLG / 2}px; - height: ${token.controlHeightLG / 2}px; - border-radius: 100%; - cursor: pointer; - transition: all ${token.motionDurationFast}; - display: inline-block; - - & > input[type='radio'] { - width: 0; - height: 0; - opacity: 0; - } - - &:focus-within { - // need ? - } - `, + width: ${token.controlHeightLG / 2}px; + height: ${token.controlHeightLG / 2}px; + border-radius: 100%; + cursor: pointer; + transition: all ${token.motionDurationFast}; + display: inline-block; + + & > input[type='radio'] { + width: 0; + height: 0; + opacity: 0; + } + + &:focus-within { + // need ? + } + `, colorActive: css` - box-shadow: 0 0 0 1px ${token.colorBgContainer}, - 0 0 0 ${token.controlOutlineWidth * 2 + 1}px ${token.colorPrimary}; - `, + box-shadow: + 0 0 0 1px ${token.colorBgContainer}, + 0 0 0 ${token.controlOutlineWidth * 2 + 1}px ${token.colorPrimary}; + `, })); -const DebouncedColorPicker: FC = ({ value: color, onChange, children }) => { +export interface ColorPickerProps { + id?: string; + children?: React.ReactNode; + value?: string | Color; + onChange?: (value?: Color | string) => void; +} + +const DebouncedColorPicker: React.FC = (props) => { + const { value: color, children, onChange } = props; const [value, setValue] = useState(color); useEffect(() => { @@ -51,40 +60,24 @@ const DebouncedColorPicker: FC = ({ value: color, onChange, ch {children} ); }; -export interface RadiusPickerProps { - value?: string | Color; - onChange?: (value: string) => void; -} - -export default function ThemeColorPicker({ value, onChange }: RadiusPickerProps) { +const ThemeColorPicker: React.FC = ({ value, onChange, id }) => { const { styles } = useStyle(); const matchColors = React.useMemo(() => { - const valueStr = generateColor(value).toRgbString(); + const valueStr = generateColor(value || '').toRgbString(); let existActive = false; - const colors = PRESET_COLORS.map((color) => { const colorStr = generateColor(color).toRgbString(); const active = colorStr === valueStr; existActive = existActive || active; - - return { - color, - active, - picker: false, - }; + return { color, active, picker: false }; }); return [ @@ -100,11 +93,10 @@ export default function ThemeColorPicker({ value, onChange }: RadiusPickerProps) return ( { - onChange?.(event.target.value); - }} + value={typeof value === 'string' ? value : value?.toHexString()} + onChange={(event) => onChange?.(event.target.value)} style={{ width: 120 }} + id={id} /> @@ -114,9 +106,7 @@ export default function ThemeColorPicker({ value, onChange }: RadiusPickerProps) ); -} +}; + +export default ThemeColorPicker; diff --git a/.dumi/pages/index/components/Theme/RadiusPicker.tsx b/.dumi/pages/index/components/Theme/RadiusPicker.tsx index d0718b58e68c..ee7f03e574c7 100644 --- a/.dumi/pages/index/components/Theme/RadiusPicker.tsx +++ b/.dumi/pages/index/components/Theme/RadiusPicker.tsx @@ -1,12 +1,13 @@ import React from 'react'; -import { InputNumber, Space, Slider } from 'antd'; +import { InputNumber, Slider, Space } from 'antd'; export interface RadiusPickerProps { + id?: string; value?: number; onChange?: (value: number | null) => void; } -export default function RadiusPicker({ value, onChange }: RadiusPickerProps) { +export default function RadiusPicker({ value, onChange, id }: RadiusPickerProps) { return ( `${val}px`} parser={(str) => (str ? parseFloat(str) : (str as any))} + id={id} /> ({ themeCard: css` - border-radius: ${token.borderRadius}px; - cursor: pointer; - transition: all ${token.motionDurationSlow}; - overflow: hidden; - display: inline-block; - - & > input[type="radio"] { - width: 0; - height: 0; - opacity: 0; - } - - img { - vertical-align: top; - box-shadow: 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 6px 16px 0 rgba(0, 0, 0, 0.08), - 0 9px 28px 8px rgba(0, 0, 0, 0.05); - } - - &:focus-within, - &:hover { - transform: scale(1.04); - } - `, + border-radius: ${token.borderRadius}px; + cursor: pointer; + transition: all ${token.motionDurationSlow}; + overflow: hidden; + display: inline-block; + + & > input[type='radio'] { + width: 0; + height: 0; + opacity: 0; + position: absolute; + } + + img { + vertical-align: top; + box-shadow: + 0 3px 6px -4px rgba(0, 0, 0, 0.12), + 0 6px 16px 0 rgba(0, 0, 0, 0.08), + 0 9px 28px 8px rgba(0, 0, 0, 0.05); + } + + &:focus-within, + &:hover { + transform: scale(1.04); + } + `, themeCardActive: css` - box-shadow: 0 0 0 1px ${token.colorBgContainer}, - 0 0 0 ${token.controlOutlineWidth * 2 + 1}px ${token.colorPrimary}; - - &, - &:hover:not(:focus-within) { - transform: scale(1); - } - `, + box-shadow: + 0 0 0 1px ${token.colorBgContainer}, + 0 0 0 ${token.controlOutlineWidth * 2 + 1}px ${token.colorPrimary}; + + &, + &:hover:not(:focus-within) { + transform: scale(1); + } + `, })); export interface ThemePickerProps { + id?: string; value?: string; onChange?: (value: string) => void; } -export default function ThemePicker({ value, onChange }: ThemePickerProps) { +export default function ThemePicker(props: ThemePickerProps) { + const { value, onChange, id } = props; + const token = useTheme(); const { styles } = useStyle(); @@ -81,7 +89,7 @@ export default function ThemePicker({ value, onChange }: ThemePickerProps) { return ( - {Object.keys(THEMES).map((theme) => { + {Object.keys(THEMES).map((theme, index) => { const url = THEMES[theme as THEME]; return ( @@ -93,7 +101,7 @@ export default function ThemePicker({ value, onChange }: ThemePickerProps) { onChange?.(theme); }} > - + {theme} {locale[theme as keyof typeof locale]} diff --git a/.dumi/pages/index/components/Theme/colorUtil.ts b/.dumi/pages/index/components/Theme/colorUtil.ts index 14c8254c3a17..de913e83f0ac 100644 --- a/.dumi/pages/index/components/Theme/colorUtil.ts +++ b/.dumi/pages/index/components/Theme/colorUtil.ts @@ -1,3 +1,4 @@ +import type { Color } from 'antd/es/color-picker'; import { generateColor } from 'antd/es/color-picker/util'; export const DEFAULT_COLOR = '#1677FF'; @@ -50,7 +51,8 @@ export const COLOR_IMAGES = [ export const PRESET_COLORS = COLOR_IMAGES.map(({ color }) => color); const DISTANCE = 33; -export function getClosetColor(colorPrimary?: string | null) { + +export function getClosetColor(colorPrimary?: Color | string | null) { if (!colorPrimary) { return null; } diff --git a/.dumi/pages/index/components/Theme/index.tsx b/.dumi/pages/index/components/Theme/index.tsx index 436c90cf61c1..e528a1ad398e 100644 --- a/.dumi/pages/index/components/Theme/index.tsx +++ b/.dumi/pages/index/components/Theme/index.tsx @@ -1,15 +1,12 @@ -import { TinyColor } from '@ctrl/tinycolor'; +import * as React from 'react'; +import { defaultAlgorithm, defaultTheme } from '@ant-design/compatible'; import { BellOutlined, FolderOutlined, HomeOutlined, QuestionCircleOutlined, } from '@ant-design/icons'; -import { createStyles, css, useTheme } from 'antd-style'; -import * as React from 'react'; -import classNames from 'classnames'; -import { defaultTheme, defaultAlgorithm } from '@ant-design/compatible'; -import { useLocation } from 'dumi'; +import { TinyColor } from '@ctrl/tinycolor'; import type { MenuProps } from 'antd'; import { Breadcrumb, @@ -21,28 +18,33 @@ import { Menu, Radio, Space, - Typography, theme, + Typography, } from 'antd'; +import { createStyles, css, useTheme } from 'antd-style'; import type { Color } from 'antd/es/color-picker'; import { generateColor } from 'antd/es/color-picker/util'; -import * as utils from '../../../../theme/utils'; +import classNames from 'classnames'; +import { useLocation } from 'dumi'; + +import useDark from '../../../../hooks/useDark'; import useLocale from '../../../../hooks/useLocale'; +import Link from '../../../../theme/common/Link'; import SiteContext from '../../../../theme/slots/SiteContext'; +import * as utils from '../../../../theme/utils'; import Group from '../Group'; import { getCarouselStyle } from '../util'; import BackgroundImage from './BackgroundImage'; import ColorPicker from './ColorPicker'; +import { DEFAULT_COLOR, getAvatarURL, getClosetColor, PINK_COLOR } from './colorUtil'; import MobileCarousel from './MobileCarousel'; import RadiusPicker from './RadiusPicker'; import type { THEME } from './ThemePicker'; import ThemePicker from './ThemePicker'; -import { DEFAULT_COLOR, PINK_COLOR, getAvatarURL, getClosetColor } from './colorUtil'; -import Link from '../../../../theme/common/Link'; const { Header, Content, Sider } = Layout; -const TokenChecker = () => { +const TokenChecker: React.FC = () => { if (process.env.NODE_ENV !== 'production') { console.log('Demo Token:', theme.useToken()); } @@ -195,7 +197,7 @@ const useStyle = createStyles(({ token, cx }) => { }); // ========================== Menu Config ========================== -const subMenuItems: MenuProps['items'] = [ +const subMenuItems = [ { key: `Design Values`, label: `Design Values`, @@ -285,11 +287,12 @@ const ThemesInfo: Record> = { }, }; +const normalize = (value: number) => value / 255; + function rgbToColorMatrix(color: string) { const rgb = new TinyColor(color).toRgb(); const { r, g, b } = rgb; - const normalize = (value) => value / 255; const invertValue = normalize(r) * 100; const sepiaValue = 100; const saturateValue = Math.max(normalize(r), normalize(g), normalize(b)) * 10000; @@ -316,7 +319,9 @@ export default function Theme() { const [themeData, setThemeData] = React.useState(ThemeDefault); const onThemeChange = (_: Partial, nextThemeData: ThemeData) => { - setThemeData({ ...ThemesInfo[nextThemeData.themeType], ...nextThemeData }); + React.startTransition(() => { + setThemeData({ ...ThemesInfo[nextThemeData.themeType], ...nextThemeData }); + }); }; const { compact, themeType, colorPrimary, ...themeToken } = themeData; @@ -355,6 +360,12 @@ export default function Theme() { form.setFieldsValue(mergedData); }, [themeType]); + const isRootDark = useDark(); + + React.useEffect(() => { + onThemeChange({}, { ...themeData, themeType: isRootDark ? 'dark' : 'default' }); + }, [isRootDark]); + // ================================ Tokens ================================ const closestColor = getClosetColor(colorPrimaryValue); @@ -472,6 +483,7 @@ export default function Theme() { openKeys={['Design']} style={{ height: '100%', borderRight: 0 }} items={sideMenuItems} + expandIcon={false} /> @@ -522,11 +534,20 @@ export default function Theme() { - - - {locale.default} - {locale.compact} - + + diff --git a/.dumi/pages/index/index.tsx b/.dumi/pages/index/index.tsx index 71e85f2f51d3..8494a508d605 100644 --- a/.dumi/pages/index/index.tsx +++ b/.dumi/pages/index/index.tsx @@ -1,12 +1,14 @@ +import React from 'react'; +import { ConfigProvider, theme } from 'antd'; import { createStyles, css } from 'antd-style'; -import React, { Suspense } from 'react'; -import { ConfigProvider } from 'antd'; + +import useDark from '../../hooks/useDark'; import useLocale from '../../hooks/useLocale'; -import Banner from './components/Banner'; -import BannerRecommends, { BannerRecommendsFallback } from './components/BannerRecommends'; +// import BannerRecommends, { BannerRecommendsFallback } from './components/BannerRecommends'; import ComponentsList from './components/ComponentsList'; import DesignFramework from './components/DesignFramework'; import Group from './components/Group'; +import PreviewBanner from './components/PreviewBanner'; import Theme from './components/Theme'; const useStyle = createStyles(() => ({ @@ -36,43 +38,57 @@ const locales = { const Homepage: React.FC = () => { const [locale] = useLocale(locales); const { styles } = useStyle(); + const { token } = theme.useToken(); + + const isRootDark = useDark(); return ( - -
- - }> - - - -
+
+ + {/* 文档很久没更新了,先藏起来 */} + {/* }> + + */} + + +
+ {/* 定制主题 */} + - - - - - } - > - - -
-
- + + + {/* 组件列表 */} + + + + + {/* 设计语言 */} + + } + > + + +
+
); }; diff --git a/.dumi/pages/theme-editor/index.tsx b/.dumi/pages/theme-editor/index.tsx index d67fa4ca52d6..9b62a90e8014 100644 --- a/.dumi/pages/theme-editor/index.tsx +++ b/.dumi/pages/theme-editor/index.tsx @@ -44,11 +44,6 @@ const CustomTheme = () => { const storedConfig = localStorage.getItem(ANT_DESIGN_V5_THEME_EDITOR_THEME); if (storedConfig) { const themeConfig = JSON.parse(storedConfig); - const originThemeConfig = { - json: themeConfig, - text: undefined, - }; - setThemeConfigContent(originThemeConfig); setTheme(themeConfig); } }, []); diff --git a/.dumi/rehypeAntd.ts b/.dumi/rehypeAntd.ts index 56c5b1acf311..8f10bf4d8485 100644 --- a/.dumi/rehypeAntd.ts +++ b/.dumi/rehypeAntd.ts @@ -62,12 +62,12 @@ function rehypeAntd(): UnifiedTransformer { (node.properties.className as string[]).push('component-api-table'); } else if (node.type === 'element' && (node.tagName === 'Link' || node.tagName === 'a')) { const { tagName } = node; - node.properties.sourceType = tagName; + node.properties!.sourceType = tagName; node.tagName = 'LocaleLink'; } else if (node.type === 'element' && node.tagName === 'video') { node.tagName = 'VideoPlayer'; } else if (node.tagName === 'SourceCode') { - const { lang } = node.properties; + const { lang } = node.properties!; if (typeof lang === 'string' && lang.startsWith('sandpack')) { const code = (node.children[0] as any).value as string; diff --git a/.dumi/remarkAntd.ts b/.dumi/remarkAntd.ts index 85970e2c01ec..84dc32df3e60 100644 --- a/.dumi/remarkAntd.ts +++ b/.dumi/remarkAntd.ts @@ -1,12 +1,15 @@ import { unistUtilVisit } from 'dumi'; +import type { UnifiedTransformer } from 'dumi'; -export default function remarkMeta() { +function remarkMeta(): UnifiedTransformer { return (tree, vFile) => { // read frontmatter unistUtilVisit.visit(tree, 'yaml', (node) => { if (!/(^|[\n\r])description:/.test(node.value)) { - vFile.data.frontmatter.__autoDescription = true; + (vFile.data.frontmatter as any).__autoDescription = true; } }); }; } + +export default remarkMeta; diff --git a/.dumi/theme/SiteThemeProvider.tsx b/.dumi/theme/SiteThemeProvider.tsx index 609f44f4a1ef..99847195058d 100644 --- a/.dumi/theme/SiteThemeProvider.tsx +++ b/.dumi/theme/SiteThemeProvider.tsx @@ -1,10 +1,12 @@ +import React, { useContext } from 'react'; +import { theme as antdTheme, ConfigProvider } from 'antd'; +import type { ThemeConfig } from 'antd'; import type { ThemeProviderProps } from 'antd-style'; import { ThemeProvider } from 'antd-style'; -import type { FC } from 'react'; -import React, { useContext } from 'react'; -import { ConfigProvider, theme as antdTheme } from 'antd'; +import SiteContext from './slots/SiteContext'; interface NewToken { + bannerHeight: number; headerHeight: number; menuItemBorder: number; mobileMaxWidth: number; @@ -16,6 +18,7 @@ interface NewToken { marginFar: number; codeFamily: string; contentMarginTop: number; + anchorTop: number; } // 通过给 antd-style 扩展 CustomToken 对象类型定义,可以为 useTheme 中增加相应的 token 对象 @@ -24,15 +27,16 @@ declare module 'antd-style' { export interface CustomToken extends NewToken {} } -const SiteThemeProvider: FC = ({ children, theme, ...rest }) => { +const headerHeight = 64; +const bannerHeight = 38; + +const SiteThemeProvider: React.FC> = ({ children, theme, ...rest }) => { const { getPrefixCls, iconPrefixCls } = useContext(ConfigProvider.ConfigContext); const rootPrefixCls = getPrefixCls(); const { token } = antdTheme.useToken(); - + const { bannerVisible } = useContext(SiteContext); React.useEffect(() => { - ConfigProvider.config({ - theme, - }); + ConfigProvider.config({ theme: theme as ThemeConfig }); }, [theme]); return ( @@ -40,7 +44,8 @@ const SiteThemeProvider: FC = ({ children, theme, ...rest }) {...rest} theme={theme} customToken={{ - headerHeight: 64, + headerHeight, + bannerHeight, menuItemBorder: 2, mobileMaxWidth: 767.99, siteMarkdownCodeBg: token.colorFillTertiary, @@ -54,6 +59,7 @@ const SiteThemeProvider: FC = ({ children, theme, ...rest }) marginFar: token.marginXXL * 2, codeFamily: `'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace`, contentMarginTop: 40, + anchorTop: headerHeight + token.margin + (bannerVisible ? bannerHeight : 0), }} > {children} diff --git a/.dumi/theme/builtins/ColorChunk/index.tsx b/.dumi/theme/builtins/ColorChunk/index.tsx index 04e5ade72d36..598abb34b2b1 100644 --- a/.dumi/theme/builtins/ColorChunk/index.tsx +++ b/.dumi/theme/builtins/ColorChunk/index.tsx @@ -4,7 +4,7 @@ import * as React from 'react'; interface ColorChunkProps { children?: React.ReactNode; - color?: ColorInput; + value?: ColorInput; } const useStyle = createStyles(({ token, css }) => ({ @@ -27,12 +27,12 @@ const useStyle = createStyles(({ token, css }) => ({ const ColorChunk: React.FC = (props) => { const { styles } = useStyle(); - const { color, children } = props; + const { value, children } = props; const dotColor = React.useMemo(() => { - const _color = new TinyColor(color).toHex8String(); + const _color = new TinyColor(value).toHex8String(); return _color.endsWith('ff') ? _color.slice(0, -2) : _color; - }, [color]); + }, [value]); return ( diff --git a/.dumi/theme/builtins/ComponentOverview/index.tsx b/.dumi/theme/builtins/ComponentOverview/index.tsx index 2347962cb17b..045f9d436f37 100644 --- a/.dumi/theme/builtins/ComponentOverview/index.tsx +++ b/.dumi/theme/builtins/ComponentOverview/index.tsx @@ -1,57 +1,63 @@ import React, { memo, useContext, useMemo, useRef, useState } from 'react'; import type { CSSProperties } from 'react'; -import { Link, useIntl, useSidebarData, useLocation } from 'dumi'; +import { SearchOutlined } from '@ant-design/icons'; +import { Affix, Card, Col, Divider, Input, Row, Space, Tag, Typography } from 'antd'; import { createStyles, useTheme } from 'antd-style'; +import { useIntl, useLocation, useSidebarData } from 'dumi'; import debounce from 'lodash/debounce'; -import { SearchOutlined } from '@ant-design/icons'; -import { Card, Col, Divider, Input, Row, Space, Tag, Typography, Affix } from 'antd'; +import scrollIntoView from 'scroll-into-view-if-needed'; + +import Link from '../../common/Link'; +import SiteContext from '../../slots/SiteContext'; import type { Component } from './ProComponentsList'; import proComponentsList from './ProComponentsList'; -import SiteContext from '../../slots/SiteContext'; const useStyle = createStyles(({ token, css }) => ({ componentsOverviewGroupTitle: css` - margin-bottom: 24px !important; - `, + margin-bottom: 24px !important; + `, componentsOverviewTitle: css` - overflow: hidden; - color: ${token.colorTextHeading}; - text-overflow: ellipsis; - `, + overflow: hidden; + color: ${token.colorTextHeading}; + text-overflow: ellipsis; + `, componentsOverviewImg: css` - display: flex; - align-items: center; - justify-content: center; - height: 152px; - `, + display: flex; + align-items: center; + justify-content: center; + height: 152px; + `, componentsOverviewCard: css` - cursor: pointer; - transition: all 0.5s; - &:hover { - box-shadow: 0 6px 16px -8px #00000014, 0 9px 28px #0000000d, 0 12px 48px 16px #00000008; - } - `, + cursor: pointer; + transition: all 0.5s; + &:hover { + box-shadow: + 0 6px 16px -8px #00000014, + 0 9px 28px #0000000d, + 0 12px 48px 16px #00000008; + } + `, componentsOverviewAffix: css` - display: flex; - transition: all 0.3s; - justify-content: space-between; - `, + display: flex; + transition: all 0.3s; + justify-content: space-between; + `, componentsOverviewSearch: css` - padding: 0; - .anticon-search { - color: ${token.colorTextDisabled}; - } - `, + padding: 0; + .anticon-search { + color: ${token.colorTextDisabled}; + } + `, componentsOverviewContent: css` - &:empty:after { - display: block; - padding: 16px 0 40px; - color: ${token.colorTextDisabled}; - text-align: center; - border-bottom: 1px solid ${token.colorSplit}; - content: 'Not Found'; - } - `, + &:empty:after { + display: block; + padding: 16px 0 40px; + color: ${token.colorTextDisabled}; + text-align: center; + border-bottom: 1px solid ${token.colorSplit}; + content: 'Not Found'; + } + `, })); const onClickCard = (pathname: string) => { @@ -82,7 +88,7 @@ const Overview: React.FC = () => { const [searchBarAffixed, setSearchBarAffixed] = useState(false); const token = useTheme(); - const { borderRadius, colorBgContainer, fontSizeXL } = token; + const { borderRadius, colorBgContainer, fontSizeXL, anchorTop } = token; const affixedStyle: CSSProperties = { boxShadow: 'rgba(50, 50, 93, 0.25) 0 6px 12px -2px, rgba(0, 0, 0, 0.3) 0 3px 7px -3px', @@ -98,7 +104,7 @@ const Overview: React.FC = () => { const [search, setSearch] = useState(() => { const params = new URLSearchParams(urlSearch); if (params.has('s')) { - return params.get('s'); + return params.get('s') || ''; } return ''; }); @@ -107,7 +113,7 @@ const Overview: React.FC = () => { const onKeyDown: React.KeyboardEventHandler = (event) => { if (event.keyCode === 13 && search.trim().length) { - sectionRef.current?.querySelector('.components-overview-card')?.click(); + sectionRef.current?.querySelector(`.${styles.componentsOverviewCard}`)?.click(); } }; @@ -116,12 +122,12 @@ const Overview: React.FC = () => { data .filter((item) => item?.title) .map<{ title: string; children: Component[] }>((item) => ({ - title: item?.title, + title: item?.title || '', children: item.children.map((child) => ({ - title: child.frontmatter?.title, - subtitle: child.frontmatter.subtitle, - cover: child.frontmatter.cover, - coverDark: child.frontmatter.coverDark, + title: child.frontmatter?.title || '', + subtitle: child.frontmatter?.subtitle, + cover: child.frontmatter?.cover, + coverDark: child.frontmatter?.coverDark, link: child.link, })), })) @@ -139,7 +145,7 @@ const Overview: React.FC = () => { return (
- + setSearchBarAffixed(!!affixed)}>
{ onChange={(e) => { setSearch(e.target.value); reportSearch(e.target.value); + if (sectionRef.current && searchBarAffixed) { + scrollIntoView(sectionRef.current, { + scrollMode: 'if-needed', + block: 'start', + behavior: (actions) => + actions.forEach(({ el, top }) => { + el.scrollTop = top - 64; + }), + }); + } }} onKeyDown={onKeyDown} bordered={false} @@ -189,13 +205,11 @@ const Overview: React.FC = () => { url += urlSearch; } - /** Link 不能跳转到外链 */ - const ComponentLink = isExternalLink ? 'a' : Link; - return ( - onClickCard(url)}> + onClickCard(url)} bodyStyle={{ backgroundRepeat: 'no-repeat', backgroundPosition: 'bottom right', @@ -220,7 +234,7 @@ const Overview: React.FC = () => { />
- + ); })} diff --git a/.dumi/theme/builtins/ComponentTokenTable/index.tsx b/.dumi/theme/builtins/ComponentTokenTable/index.tsx index c67edab7b904..7d64eb2d5aed 100644 --- a/.dumi/theme/builtins/ComponentTokenTable/index.tsx +++ b/.dumi/theme/builtins/ComponentTokenTable/index.tsx @@ -1,10 +1,10 @@ -import { RightOutlined } from '@ant-design/icons'; +import { RightOutlined, LinkOutlined, QuestionCircleOutlined } from '@ant-design/icons'; import { createStyles, css, useTheme } from 'antd-style'; import { getDesignToken } from 'antd-token-previewer'; import React, { useMemo, useState } from 'react'; import tokenMeta from 'antd/es/version/token-meta.json'; import tokenData from 'antd/es/version/token.json'; -import { ConfigProvider, Table } from 'antd'; +import { ConfigProvider, Table, Popover, Typography } from 'antd'; import useLocale from '../../../hooks/useLocale'; import { useColumns } from '../TokenTable'; @@ -18,6 +18,9 @@ const locales = { value: '默认值', componentToken: '组件 Token', globalToken: '全局 Token', + help: '如何定制?', + customizeTokenLink: '/docs/react/customize-theme-cn#修改主题变量', + customizeComponentTokenLink: '/docs/react/customize-theme-cn#修改组件变量', }, en: { token: 'Token Name', @@ -26,6 +29,9 @@ const locales = { value: 'Default Value', componentToken: 'Component Token', globalToken: 'Global Token', + help: 'How to use?', + customizeTokenLink: '/docs/react/customize-theme#customize-design-token', + customizeComponentTokenLink: 'docs/react/customize-theme#customize-component-token', }, }; @@ -45,16 +51,34 @@ const useStyle = createStyles(() => ({ transition: all 0.3s; } `, + help: css` + margin-left: 8px; + font-size: 12px; + font-weight: normal; + color: #999; + a { + color: #999; + } + `, })); interface SubTokenTableProps { defaultOpen?: boolean; title: string; + helpText: React.ReactNode; + helpLink: string; tokens: string[]; component?: string; } -const SubTokenTable: React.FC = ({ defaultOpen, tokens, title, component }) => { +const SubTokenTable: React.FC = ({ + defaultOpen, + tokens, + title, + helpText, + helpLink, + component, +}) => { const [, lang] = useLocale(locales); const token = useTheme(); const columns = useColumns(); @@ -104,11 +128,53 @@ const SubTokenTable: React.FC = ({ defaultOpen, tokens, titl }) .filter(Boolean); + const code = component + ? ` + ... +` + : ` + ... +`; + return ( -
+ <>
setOpen(!open)}> -

{title}

+

+ {title} + +
{code}
+ + + {helpText} + + + } + > + + + {helpText} + +
+

{open && ( @@ -123,7 +189,7 @@ const SubTokenTable: React.FC = ({ defaultOpen, tokens, titl /> )} -
+ ); }; @@ -152,11 +218,19 @@ const ComponentTokenTable: React.FC = ({ component }) {tokenMeta.components[component] && ( item.token)} component={component} + defaultOpen /> )} - + ); }; diff --git a/.dumi/theme/builtins/IconSearch/Category.tsx b/.dumi/theme/builtins/IconSearch/Category.tsx index 83b70a309eea..1cbbdf4c57c6 100644 --- a/.dumi/theme/builtins/IconSearch/Category.tsx +++ b/.dumi/theme/builtins/IconSearch/Category.tsx @@ -16,7 +16,7 @@ const Category: React.FC = (props) => { const { icons, title, newIcons, theme } = props; const intl = useIntl(); const [justCopied, setJustCopied] = React.useState(null); - const copyId = React.useRef(null); + const copyId = React.useRef | null>(null); const onCopied = React.useCallback((type: string, text: string) => { message.success( diff --git a/.dumi/theme/builtins/IconSearch/IconSearch.tsx b/.dumi/theme/builtins/IconSearch/IconSearch.tsx index 2529aa3da60f..2994df36ea38 100644 --- a/.dumi/theme/builtins/IconSearch/IconSearch.tsx +++ b/.dumi/theme/builtins/IconSearch/IconSearch.tsx @@ -1,12 +1,12 @@ -import React, { useCallback, useMemo, useState } from 'react'; import type { CSSProperties } from 'react'; +import React, { useCallback, useMemo, useState } from 'react'; import Icon, * as AntdIcons from '@ant-design/icons'; import type { IntlShape } from 'react-intl'; import { createStyles, useTheme } from 'antd-style'; import { useIntl } from 'dumi'; import debounce from 'lodash/debounce'; -import { Segmented, Input, Empty, Affix } from 'antd'; import type { SegmentedProps } from 'antd'; +import { Affix, Empty, Input, Segmented } from 'antd'; import Category from './Category'; import { FilledIcon, OutlinedIcon, TwoToneIcon } from './themeIcons'; import type { CategoriesKeys } from './fields'; @@ -112,7 +112,7 @@ const IconSearch: React.FC = () => { }, [displayState.searchKey, displayState.theme]); const [searchBarAffixed, setSearchBarAffixed] = useState(false); - const { borderRadius, colorBgContainer } = token; + const { borderRadius, colorBgContainer, anchorTop } = token; const affixedStyle: CSSProperties = { boxShadow: 'rgba(50, 50, 93, 0.25) 0 6px 12px -2px, rgba(0, 0, 0, 0.3) 0 3px 7px -3px', @@ -124,7 +124,7 @@ const IconSearch: React.FC = () => { return (
- +
JsonML.isElement(node) && JsonML.getTagName(node) === 'pre', - (node: any, index: any) => { - // ref: https://github.com/benjycui/bisheng/blob/master/packages/bisheng/src/bisheng-plugin-highlight/lib/browser.js#L7 - const attr = JsonML.getAttributes(node); - return React.createElement( - 'pre', - { - key: index, - className: `language-${attr.lang}`, - }, - React.createElement('code', { - dangerouslySetInnerHTML: { __html: attr.highlighted }, - }), - ); - }, - ], - ]); -} - function compress(string: string): string { return LZString.compressToBase64(string) .replace(/\+/g, '-') // Convert '+' to '-' @@ -88,6 +59,31 @@ function useShowRiddleButton() { return showRiddleButton; } +const useStyle = createStyles(({ token }) => { + const { borderRadius } = token; + return { + codeHideBtn: css` + width: 100%; + height: 40px; + display: flex; + justify-content: center; + align-items: center; + border-radius: 0 0 ${borderRadius}px ${borderRadius}px; + border-top: 1px solid ${token.colorSplit}; + color: ${token.colorTextSecondary}; + transition: all 0.2s ease-in-out; + background-color: ${token.colorBgElevated}; + cursor: pointer; + &:hover { + color: ${token.colorPrimary}; + } + span { + margin-right: ${token.marginXXS}px; + } + `, + }; +}); + const CodePreviewer: React.FC = (props) => { const { asset, @@ -111,6 +107,8 @@ const CodePreviewer: React.FC = (props) => { const { pkg } = useSiteData(); const location = useLocation(); + const { styles } = useStyle(); + const entryCode = asset.dependencies['index.tsx'].value; const showRiddleButton = useShowRiddleButton(); @@ -120,8 +118,6 @@ const CodePreviewer: React.FC = (props) => { const riddleIconRef = useRef(null); const codepenIconRef = useRef(null); const [codeExpand, setCodeExpand] = useState(false); - const [copyTooltipOpen, setCopyTooltipOpen] = useState(false); - const [copied, setCopied] = useState(false); const [codeType, setCodeType] = useState('tsx'); const { theme } = useContext(SiteContext); @@ -130,13 +126,6 @@ const CodePreviewer: React.FC = (props) => { const [showOnlineUrl, setShowOnlineUrl] = useState(false); - const highlightedCodes = { - jsx: Prism.highlight(jsx, Prism.languages.javascript, 'jsx'), - tsx: Prism.highlight(entryCode, Prism.languages.javascript, 'jsx'), - }; - - const highlightedStyle = style ? Prism.highlight(style, Prism.languages.css, 'css') : ''; - useEffect(() => { const regexp = /preview-(\d+)-ant-design/; // matching PR preview addresses setShowOnlineUrl( @@ -149,18 +138,6 @@ const CodePreviewer: React.FC = (props) => { track({ type: 'expand', demo }); }; - const handleCodeCopied = (demo: string) => { - setCopied(true); - track({ type: 'copy', demo }); - }; - - const onCopyTooltipOpenChange = (open: boolean) => { - setCopyTooltipOpen(open); - if (open) { - setCopied(false); - } - }; - useEffect(() => { if (asset.id === hash.slice(1)) { anchorRef.current?.click(); @@ -194,7 +171,6 @@ const CodePreviewer: React.FC = (props) => { }); const localizedTitle = title; - const introChildren =
; const highlightClass = classNames('highlight-wrapper', { 'highlight-wrapper-expand': codeExpand, }); @@ -228,15 +204,13 @@ const CodePreviewer: React.FC = (props) => { const suffix = codeType === 'tsx' ? 'tsx' : 'js'; - const dependencies: Record = jsx.split('\n').reduce( + const dependencies = (jsx as string).split('\n').reduce>( (acc, line) => { const matches = line.match(/import .+? from '(.+)';$/); - if (matches && matches[1] && !line.includes('antd')) { + if (matches?.[1]) { const paths = matches[1].split('/'); - if (paths.length) { - const dep = paths[0].startsWith('@') ? `${paths[0]}/${paths[1]}` : paths[0]; - acc[dep] = 'latest'; - } + const dep = paths[0].startsWith('@') ? `${paths[0]}/${paths[1]}` : paths[0]; + acc[dep] ??= pkgDependencyList[dep] ?? 'latest'; } return acc; }, @@ -402,7 +376,9 @@ createRoot(document.getElementById('container')).render(); } filename={filename} />
-
{introChildren}
+ {description && ( +
+ )} {showOnlineUrl && ( }> @@ -485,17 +461,6 @@ createRoot(document.getElementById('container')).render(); - handleCodeCopied(asset.id)}> - } - > - {React.createElement(copied && copyTooltipOpen ? CheckOutlined : SnippetsOutlined, { - className: 'code-box-code-copy code-box-code-action', - })} - - }> ); {codeExpand && (
setCodeType(type)} + sourceCode={entryCode} + jsxCode={jsx} + styleCode={style} + onCodeTypeChange={setCodeType} /> - {highlightedStyle ? ( -
-
-                
-              
-
- ) : null} +
setCodeExpand(false)} + > + + +
)}
@@ -560,11 +528,13 @@ createRoot(document.getElementById('container')).render(); // resulting in some response delays like following issue: // https://github.com/ant-design/ant-design/issues/39995 // So we insert style tag into head tag. - if (!style) return; - const styleTag = document.createElement('style'); + if (!style) { + return; + } + const styleTag = document.createElement('style') as HTMLStyleElement; styleTag.type = 'text/css'; styleTag.innerHTML = style; - styleTag['data-demo-url'] = demoUrl; + (styleTag as any)['data-demo-url'] = demoUrl; document.head.appendChild(styleTag); return () => { document.head.removeChild(styleTag); @@ -573,7 +543,7 @@ createRoot(document.getElementById('container')).render(); if (version) { return ( - + {codeBox} ); diff --git a/.dumi/theme/builtins/Previewer/DesignPreviewer.tsx b/.dumi/theme/builtins/Previewer/DesignPreviewer.tsx index c64ad7966bbd..d3b591aebaee 100644 --- a/.dumi/theme/builtins/Previewer/DesignPreviewer.tsx +++ b/.dumi/theme/builtins/Previewer/DesignPreviewer.tsx @@ -5,7 +5,7 @@ import { CheckOutlined, SketchOutlined } from '@ant-design/icons'; import { nodeToGroup } from 'html2sketch'; import copy from 'copy-to-clipboard'; import { App } from 'antd'; -import type { AntdPreviewerProps } from '.'; +import type { AntdPreviewerProps } from './Previewer'; const useStyle = createStyles(({ token, css }) => ({ wrapper: css` diff --git a/.dumi/theme/builtins/Previewer/Previewer.tsx b/.dumi/theme/builtins/Previewer/Previewer.tsx new file mode 100644 index 000000000000..fb23c55e0f71 --- /dev/null +++ b/.dumi/theme/builtins/Previewer/Previewer.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import type { IPreviewerProps } from 'dumi'; +import { useTabMeta } from 'dumi'; + +import CodePreviewer from './CodePreviewer'; +import DesignPreviewer from './DesignPreviewer'; + +export interface AntdPreviewerProps extends IPreviewerProps { + originDebug?: IPreviewerProps['debug']; +} + +const Previewer: React.FC = (props) => { + const tab = useTabMeta(); + + if (tab?.frontmatter.title === 'Design') { + return ; + } + + return ; +}; + +export default Previewer; diff --git a/.dumi/theme/builtins/Previewer/index.tsx b/.dumi/theme/builtins/Previewer/index.tsx index a37144956fd6..e36c556112f8 100644 --- a/.dumi/theme/builtins/Previewer/index.tsx +++ b/.dumi/theme/builtins/Previewer/index.tsx @@ -1,21 +1,40 @@ +import React, { Suspense } from 'react'; import type { IPreviewerProps } from 'dumi'; -import { useTabMeta } from 'dumi'; -import React from 'react'; -import CodePreviewer from './CodePreviewer'; -import DesignPreviewer from './DesignPreviewer'; +import { Skeleton, Alert } from 'antd'; +import { createStyles } from 'antd-style'; -export interface AntdPreviewerProps extends IPreviewerProps { - originDebug?: IPreviewerProps['debug']; -} +const { ErrorBoundary } = Alert; -const Previewer: React.FC = (props) => { - const tab = useTabMeta(); +const Previewer = React.lazy(() => import('./Previewer')); - if (tab?.frontmatter.title === 'Design') { - return ; - } +const useStyle = createStyles(({ css }) => ({ + skeletonWrapper: css` + width: 100% !important; + height: 500px; + margin-bottom: 16px; + `, +})); - return ; +export default (props: IPreviewerProps) => { + const { styles } = useStyle(); + return ( + + + {' '} + + } + > + + + + ); }; - -export default Previewer; diff --git a/.dumi/theme/builtins/TokenCompare/index.tsx b/.dumi/theme/builtins/TokenCompare/index.tsx index a44ffcda8da2..9ae37389f0b0 100644 --- a/.dumi/theme/builtins/TokenCompare/index.tsx +++ b/.dumi/theme/builtins/TokenCompare/index.tsx @@ -4,7 +4,7 @@ import classNames from 'classnames'; import { TinyColor } from '@ctrl/tinycolor'; import { createStyles } from 'antd-style'; import tokenMeta from 'antd/es/version/token-meta.json'; -import { theme, Space } from 'antd'; +import { Space, theme } from 'antd'; import useLocale from '../../../hooks/useLocale'; const useStyle = createStyles(({ token, css }) => { @@ -29,7 +29,7 @@ const useStyle = createStyles(({ token, css }) => { display: flex; align-items: center; justify-content: center; - + color: rgba(0,0,0,0.88); border-right: 1px solid rgba(0, 0, 0, 0.1); `, diff --git a/.dumi/theme/builtins/TokenTable/index.tsx b/.dumi/theme/builtins/TokenTable/index.tsx index 00e885c4af9b..6cb8fdfdf1c7 100644 --- a/.dumi/theme/builtins/TokenTable/index.tsx +++ b/.dumi/theme/builtins/TokenTable/index.tsx @@ -78,7 +78,7 @@ export function useColumns(): Exclude['columns'], undefine typeof record.value === 'string' && (record.value.startsWith('#') || record.value.startsWith('rgb')); if (isColor) { - return {record.value}; + return {record.value}; } return typeof record.value !== 'string' ? JSON.stringify(record.value) : record.value; }, diff --git a/.dumi/theme/common/CodePreview.tsx b/.dumi/theme/common/CodePreview.tsx index 93c9c4580710..b58b4661d082 100644 --- a/.dumi/theme/common/CodePreview.tsx +++ b/.dumi/theme/common/CodePreview.tsx @@ -1,37 +1,148 @@ -import React from 'react'; -import { Tabs } from 'antd'; +import React, { useEffect, useMemo } from 'react'; +import { Tabs, Typography, Button } from 'antd'; +import toReactElement from 'jsonml-to-react-element'; +import JsonML from 'jsonml.js/lib/utils'; +import Prism from 'prismjs'; +import { createStyles } from 'antd-style'; + +const useStyle = createStyles(({ token, css }) => { + const { colorIcon, colorBgTextHover, antCls } = token; + + return { + code: css` + position: relative; + `, + + copyButton: css` + color: ${colorIcon}; + position: absolute; + top: 0; + inset-inline-end: 16px; + width: 32px; + text-align: center; + background: ${colorBgTextHover}; + padding: 0; + `, + + copyIcon: css` + ${antCls}-typography-copy { + margin-inline-start: 0; + } + ${antCls}-typography-copy:not(${antCls}-typography-copy-success) { + color: ${colorIcon}; + + &:hover { + color: ${colorIcon}; + } + } + `, + }; +}); const LANGS = { tsx: 'TypeScript', jsx: 'JavaScript', + style: 'CSS', }; interface CodePreviewProps { - codes?: Record; - toReactComponent?: (node: any) => React.ReactNode; + sourceCode?: string; + jsxCode?: string; + styleCode?: string; onCodeTypeChange?: (activeKey: string) => void; } -const CodePreview: React.FC = ({ toReactComponent, codes, onCodeTypeChange }) => { - const langList = Object.keys(codes).sort().reverse(); +function toReactComponent(jsonML: any[]) { + return toReactElement(jsonML, [ + [ + (node: any) => JsonML.isElement(node) && JsonML.getTagName(node) === 'pre', + (node: any, index: number) => { + const attr = JsonML.getAttributes(node); + return ( +
+            
+          
+ ); + }, + ], + ]); +} + +const CodePreview: React.FC = ({ + sourceCode = '', + jsxCode = '', + styleCode = '', + onCodeTypeChange, +}) => { + // 避免 Tabs 数量不稳定的闪动问题 + const initialCodes = {} as Record<'tsx' | 'jsx' | 'style', string>; + if (sourceCode) { + initialCodes.tsx = ''; + } + if (jsxCode) { + initialCodes.jsx = ''; + } + if (styleCode) { + initialCodes.style = ''; + } + const [highlightedCodes, setHighlightedCodes] = React.useState(initialCodes); + const sourceCodes = { + tsx: sourceCode, + jsx: jsxCode, + style: styleCode, + } as Record<'tsx' | 'jsx' | 'style', string>; + useEffect(() => { + const codes = { + tsx: Prism.highlight(sourceCode, Prism.languages.javascript, 'jsx'), + jsx: Prism.highlight(jsxCode, Prism.languages.javascript, 'jsx'), + style: Prism.highlight(styleCode, Prism.languages.css, 'css'), + }; + // 去掉空的代码类型 + Object.keys(codes).forEach((key: keyof typeof codes) => { + if (!codes[key]) { + delete codes[key]; + } + }); + setHighlightedCodes(codes); + }, [jsxCode, sourceCode, styleCode]); + + const langList = Object.keys(highlightedCodes); + + const { styles } = useStyle(); + + const items = useMemo( + () => + langList.map((lang: keyof typeof LANGS) => ({ + label: LANGS[lang], + key: lang, + children: ( +
+ {toReactComponent(['pre', { lang, highlighted: highlightedCodes[lang] }])} + +
+ ), + })), + [JSON.stringify(highlightedCodes)], + ); + + if (!langList.length) { + return null; + } + if (langList.length === 1) { return toReactComponent([ 'pre', - { lang: langList[0], highlighted: codes[langList[0]], className: 'highlight' }, + { + lang: langList[0], + highlighted: highlightedCodes[langList[0] as keyof typeof LANGS], + className: 'highlight', + }, ]); } - return ( - ({ - label: LANGS[lang], - key: lang, - children: toReactComponent(['pre', { lang, highlighted: codes[lang] }]), - }))} - /> - ); + + return ; }; export default CodePreview; diff --git a/.dumi/theme/common/Color/ColorPaletteTool.tsx b/.dumi/theme/common/Color/ColorPaletteTool.tsx index 5f9b4319eb68..2c2de6d3f9ef 100644 --- a/.dumi/theme/common/Color/ColorPaletteTool.tsx +++ b/.dumi/theme/common/Color/ColorPaletteTool.tsx @@ -3,26 +3,44 @@ import React, { useMemo, useState } from 'react'; import { ColorPicker } from 'antd'; import type { Color } from 'antd/es/color-picker'; import ColorPatterns from './ColorPatterns'; +import useLocale from '../../../hooks/useLocale'; const primaryMinSaturation = 70; // 主色推荐最小饱和度 const primaryMinBrightness = 70; // 主色推荐最小亮度 +const locales = { + cn: { + saturation: (s: string) => `饱和度建议不低于${primaryMinSaturation}(现在${s})`, + brightness: (b: string) => `亮度建议不低于${primaryMinBrightness}(现在${b})`, + }, + en: { + saturation: (s: string) => + `Saturation is recommended not to be lower than ${primaryMinSaturation}(currently${s})`, + brightness: (b: string) => + `Brightness is recommended not to be lower than ${primaryMinBrightness}(currently${b})`, + }, +}; + const ColorPaletteTool: React.FC = () => { const [primaryColor, setPrimaryColor] = useState('#1890ff'); const [primaryColorInstance, setPrimaryColorInstance] = useState(null); + + const [locale] = useLocale(locales); + const handleChangeColor = (color: Color, hex: string) => { setPrimaryColor(hex); setPrimaryColorInstance(color); }; + const colorValidation = useMemo(() => { let text = ''; if (primaryColorInstance) { - const { s, b } = primaryColorInstance.toHsb(); + const { s, b } = primaryColorInstance.toHsb() || {}; if (s * 100 < primaryMinSaturation) { - text += ` 饱和度建议不低于${primaryMinSaturation}(现在 ${(s * 100).toFixed(2)})`; + text += locale.saturation((s * 100).toFixed(2)); } if (b * 100 < primaryMinBrightness) { - text += ` 亮度建议不低于${primaryMinBrightness}(现在 ${(b * 100).toFixed(2)})`; + text += locale.brightness((s * 100).toFixed(2)); } } return {text.trim()}; @@ -32,7 +50,9 @@ const ColorPaletteTool: React.FC = () => {
-
{ColorPatterns({ color: primaryColor })}
+
+ +
diff --git a/.dumi/theme/common/Color/ColorPaletteToolDark.tsx b/.dumi/theme/common/Color/ColorPaletteToolDark.tsx index 2c81fa008a5c..59400cfae121 100644 --- a/.dumi/theme/common/Color/ColorPaletteToolDark.tsx +++ b/.dumi/theme/common/Color/ColorPaletteToolDark.tsx @@ -2,14 +2,30 @@ import { FormattedMessage } from 'dumi'; import React, { useMemo, useState } from 'react'; import { Col, ColorPicker, Row } from 'antd'; import ColorPatterns from './ColorPatterns'; +import useLocale from '../../../hooks/useLocale'; const primaryMinSaturation = 70; // 主色推荐最小饱和度 const primaryMinBrightness = 70; // 主色推荐最小亮度 +const locales = { + cn: { + saturation: (s: string) => `饱和度建议不低于${primaryMinSaturation}(现在${s})`, + brightness: (b: string) => `亮度建议不低于${primaryMinBrightness}(现在${b})`, + }, + en: { + saturation: (s: string) => + `Saturation is recommended not to be lower than ${primaryMinSaturation}(currently${s})`, + brightness: (b: string) => + `Brightness is recommended not to be lower than ${primaryMinBrightness}(currently${b})`, + }, +}; + const ColorPaletteTool: React.FC = () => { const [primaryColor, setPrimaryColor] = useState('#1890ff'); const [backgroundColor, setBackgroundColor] = useState('#141414'); - const [primaryColorInstance, setPrimaryColorInstance] = useState(null); + const [primaryColorInstance, setPrimaryColorInstance] = useState(null); + + const [locale] = useLocale(locales); const handleChangeColor = (color: Color, hex: string) => { setPrimaryColor(hex); @@ -23,12 +39,12 @@ const ColorPaletteTool: React.FC = () => { const colorValidation = useMemo(() => { let text = ''; if (primaryColorInstance) { - const { s, b } = primaryColorInstance.toHsb(); + const { s, b } = primaryColorInstance.toHsb() || {}; if (s * 100 < primaryMinSaturation) { - text += ` 饱和度建议不低于${primaryMinSaturation}(现在 ${(s * 100).toFixed(2)})`; + text += locale.saturation((s * 100).toFixed(2)); } if (b * 100 < primaryMinBrightness) { - text += ` 亮度建议不低于${primaryMinBrightness}(现在 ${(b * 100).toFixed(2)})`; + text += locale.brightness((s * 100).toFixed(2)); } } return ( @@ -41,7 +57,7 @@ const ColorPaletteTool: React.FC = () => { return (
- {ColorPatterns({ color: primaryColor, dark: true, backgroundColor })} +
diff --git a/.dumi/theme/common/Color/ColorPatterns.tsx b/.dumi/theme/common/Color/ColorPatterns.tsx index d40d88a0c997..080b5651cea9 100644 --- a/.dumi/theme/common/Color/ColorPatterns.tsx +++ b/.dumi/theme/common/Color/ColorPatterns.tsx @@ -9,11 +9,15 @@ interface ColorPatternsProps { backgroundColor?: string; } -const ColorPatterns = ({ color, dark, backgroundColor }: ColorPatternsProps) => { +const ColorPatterns: React.FC = ({ color, dark, backgroundColor }) => { const colors = generate(color, dark ? { theme: 'dark', backgroundColor } : {}); - return uniq(colors).map((colorString, i) => ( - - )); + return ( + <> + {uniq(colors).map((colorString, i) => ( + + ))} + + ); }; export default ColorPatterns; diff --git a/.dumi/theme/common/ComponentChangelog/ComponentChangelog.tsx b/.dumi/theme/common/ComponentChangelog/ComponentChangelog.tsx index 9c3d8c75d462..57dc1602e50d 100644 --- a/.dumi/theme/common/ComponentChangelog/ComponentChangelog.tsx +++ b/.dumi/theme/common/ComponentChangelog/ComponentChangelog.tsx @@ -1,11 +1,12 @@ /* eslint-disable global-require */ import React, { useMemo } from 'react'; -import { createStyles } from 'antd-style'; import { HistoryOutlined } from '@ant-design/icons'; import { Button, Drawer, Timeline, Typography } from 'antd'; -import Link from '../Link'; -import useLocale from '../../../hooks/useLocale'; +import { createStyles } from 'antd-style'; + import useFetch from '../../../hooks/useFetch'; +import useLocale from '../../../hooks/useLocale'; +import Link from '../Link'; const useStyle = createStyles(({ token, css }) => ({ history: css` @@ -46,7 +47,7 @@ function ParseChangelog(props: { changelog: string; refs: string[]; styles: any const { changelog = '', refs = [], styles } = props; const parsedChangelog = React.useMemo(() => { - const nodes: React.ReactElement[] = []; + const nodes: React.ReactNode[] = []; let isQuota = false; let lastStr = ''; @@ -57,7 +58,7 @@ function ParseChangelog(props: { changelog: string; refs: string[]; styles: any if (char !== '`') { lastStr += char; } else { - let node = lastStr; + let node: React.ReactNode = lastStr; if (isQuota) { node = {node}; } @@ -88,8 +89,14 @@ function ParseChangelog(props: { changelog: string; refs: string[]; styles: any ); } -function useChangelog(componentPath, lang) { - const data = useFetch( +type ChangelogInfo = { + version: string; + changelog: string; + refs: string[]; +}; + +function useChangelog(componentPath: string, lang: 'cn' | 'en'): ChangelogInfo[] { + const data: any = useFetch( lang === 'cn' ? { key: 'component-changelog-cn', @@ -108,7 +115,7 @@ function useChangelog(componentPath, lang) { (name) => name.toLowerCase() === component.toLowerCase(), ); - return data[componentName]; + return data[componentName!]; }, [data, componentPath]); } @@ -124,7 +131,7 @@ export default function ComponentChangelog(props: ComponentChangelogProps) { const list = useChangelog(componentPath, lang); const timelineItems = React.useMemo(() => { - const changelogMap = {}; + const changelogMap: Record = {}; list?.forEach((info) => { changelogMap[info.version] = changelogMap[info.version] || []; diff --git a/.dumi/theme/common/Link.tsx b/.dumi/theme/common/Link.tsx index 1cbe0e393368..a7dac2436f02 100644 --- a/.dumi/theme/common/Link.tsx +++ b/.dumi/theme/common/Link.tsx @@ -1,14 +1,15 @@ -import type { MouseEvent } from 'react'; +import type { MouseEvent, MouseEventHandler } from 'react'; import React, { forwardRef, useLayoutEffect, useMemo, useTransition } from 'react'; import { useLocation, useNavigate } from 'dumi'; import nprogress from 'nprogress'; -export type LinkProps = { +export interface LinkProps { to?: string | { pathname?: string; search?: string; hash?: string }; children?: React.ReactNode; style?: React.CSSProperties; className?: string; -}; + onClick?: MouseEventHandler; +} const Link = forwardRef((props, ref) => { const { to, children, ...rest } = props; @@ -24,12 +25,15 @@ const Link = forwardRef((props, ref) => { }, [to]); const handleClick = (e: MouseEvent) => { - if (!href.startsWith('http')) { + props.onClick?.(e); + if (!href?.startsWith('http')) { // Should support open in new tab if (!e.metaKey && !e.ctrlKey && !e.shiftKey) { e.preventDefault(); startTransition(() => { - navigate(href); + if (href) { + navigate(href); + } }); } } @@ -44,7 +48,7 @@ const Link = forwardRef((props, ref) => { }, [isPending]); return ( - + {children} ); diff --git a/.dumi/theme/common/ThemeSwitch/index.tsx b/.dumi/theme/common/ThemeSwitch/index.tsx index afa8b71da3c7..05caa5d536bd 100644 --- a/.dumi/theme/common/ThemeSwitch/index.tsx +++ b/.dumi/theme/common/ThemeSwitch/index.tsx @@ -1,19 +1,21 @@ +import React from 'react'; import { BgColorsOutlined, SmileOutlined } from '@ant-design/icons'; +import { FloatButton } from 'antd'; +import { useTheme } from 'antd-style'; import { CompactTheme, DarkTheme } from 'antd-token-previewer/es/icons'; // import { Motion } from 'antd-token-previewer/es/icons'; import { FormattedMessage, Link, useLocation } from 'dumi'; -import React from 'react'; -import { useTheme } from 'antd-style'; -import { FloatButton } from 'antd'; + +import useThemeAnimation from '../../../hooks/useThemeAnimation'; import { getLocalizedPathname, isZhCN } from '../../utils'; import ThemeIcon from './ThemeIcon'; export type ThemeName = 'light' | 'dark' | 'compact' | 'motion-off' | 'happy-work'; -export type ThemeSwitchProps = { +export interface ThemeSwitchProps { value?: ThemeName[]; onChange: (value: ThemeName[]) => void; -}; +} const ThemeSwitch: React.FC = (props) => { const { value = ['light'], onChange } = props; @@ -22,6 +24,9 @@ const ThemeSwitch: React.FC = (props) => { // const isMotionOff = value.includes('motion-off'); const isHappyWork = value.includes('happy-work'); + const isDark = value.includes('dark'); + + const toggleAnimationTheme = useThemeAnimation(); return ( = (props) => { } - type={value.includes('dark') ? 'primary' : 'default'} - onClick={() => { - if (value.includes('dark')) { + type={isDark ? 'primary' : 'default'} + onClick={(e) => { + // Toggle animation when switch theme + toggleAnimationTheme(e, isDark); + + if (isDark) { onChange(value.filter((theme) => theme !== 'dark')); } else { onChange([...value, 'dark']); @@ -64,23 +72,6 @@ const ThemeSwitch: React.FC = (props) => { }} tooltip={} /> - {/* Too many float button. Hide motion one */} - {/* } - type={!isMotionOff ? 'primary' : 'default'} - onClick={() => { - if (isMotionOff) { - onChange(value.filter((theme) => theme !== 'motion-off')); - } else { - onChange([...value, 'motion-off']); - } - }} - tooltip={ - - } - /> */} } diff --git a/.dumi/theme/common/styles/Common.tsx b/.dumi/theme/common/styles/Common.tsx index a805422a238c..c2f9cf7f2b67 100644 --- a/.dumi/theme/common/styles/Common.tsx +++ b/.dumi/theme/common/styles/Common.tsx @@ -1,9 +1,13 @@ import { css, Global } from '@emotion/react'; import React from 'react'; +import { useTheme } from 'antd-style'; -export default () => ( - { + const { anchorTop } = useTheme(); + + return ( + ( vertical-align: middle; border-style: none; } + + [id] { + scroll-margin-top: ${anchorTop}px; + } + + [data-prefers-color='dark'] { + color-scheme: dark; + } + + [data-prefers-color='light'] { + color-scheme: light; + } `} - /> -); + /> + ); +}; diff --git a/.dumi/theme/common/styles/Demo.tsx b/.dumi/theme/common/styles/Demo.tsx index c7b9b6fc5c75..9b0d8c1faa96 100644 --- a/.dumi/theme/common/styles/Demo.tsx +++ b/.dumi/theme/common/styles/Demo.tsx @@ -1,5 +1,5 @@ -import { css, Global } from '@emotion/react'; import React from 'react'; +import { css, Global } from '@emotion/react'; import { useTheme } from 'antd-style'; const GlobalDemoStyles: React.FC = () => { diff --git a/.dumi/theme/common/styles/Markdown.tsx b/.dumi/theme/common/styles/Markdown.tsx index a85624b56543..0eef2359a976 100644 --- a/.dumi/theme/common/styles/Markdown.tsx +++ b/.dumi/theme/common/styles/Markdown.tsx @@ -1,6 +1,6 @@ +import React from 'react'; import { TinyColor } from '@ctrl/tinycolor'; import { css, Global } from '@emotion/react'; -import React from 'react'; import { useTheme } from 'antd-style'; const GlobalStyle: React.FC = () => { @@ -28,11 +28,16 @@ const GlobalStyle: React.FC = () => { max-height: 100%; } + .markdown > a > img, + .markdown > img { + display: block; + margin: 0 auto; + } + .markdown p > img { margin: 34px auto; box-shadow: 0 8px 20px rgba(143, 168, 191, 0.35); max-width: 1024px; - width: 100%; display: block; } @@ -364,13 +369,12 @@ const GlobalStyle: React.FC = () => { &:first-child { width: 18%; min-width: 58px; - color: #595959; + color: ${token.colorText}; font-weight: 600; white-space: nowrap; } &:nth-child(2) { - width: 55%; min-width: 160px; } diff --git a/.dumi/theme/common/styles/Responsive.tsx b/.dumi/theme/common/styles/Responsive.tsx index 2228b6550c41..cf31359be328 100644 --- a/.dumi/theme/common/styles/Responsive.tsx +++ b/.dumi/theme/common/styles/Responsive.tsx @@ -10,7 +10,7 @@ export default () => { styles={css` .nav-phone-icon { position: absolute; - top: 25px; + bottom: 17px; right: 30px; z-index: 1; display: none; diff --git a/.dumi/theme/layouts/DocLayout/index.tsx b/.dumi/theme/layouts/DocLayout/index.tsx index f5af2a0a7876..8ddbf828c777 100644 --- a/.dumi/theme/layouts/DocLayout/index.tsx +++ b/.dumi/theme/layouts/DocLayout/index.tsx @@ -8,10 +8,10 @@ import ConfigProvider from 'antd/es/config-provider'; import useLocale from '../../../hooks/useLocale'; import useLocation from '../../../hooks/useLocation'; import GlobalStyles from '../../common/GlobalStyles'; -import Footer from '../../slots/Footer'; import Header from '../../slots/Header'; import SiteContext from '../../slots/SiteContext'; import '../../static/style'; +import IndexLayout from '../IndexLayout'; import ResourceLayout from '../ResourceLayout'; import SidebarLayout from '../SidebarLayout'; @@ -32,7 +32,7 @@ const DocLayout: React.FC = () => { const location = useLocation(); const { pathname, search, hash } = location; const [locale, lang] = useLocale(locales); - const timerRef = useRef(null); + const timerRef = useRef | null>(null); const { direction } = useContext(SiteContext); const { loading } = useSiteData(); @@ -60,13 +60,10 @@ const DocLayout: React.FC = () => { if (id) document.getElementById(decodeURIComponent(id))?.scrollIntoView(); }, [loading, hash]); - React.useEffect(() => { + useEffect(() => { if (typeof (window as any).ga !== 'undefined') { (window as any).ga('send', 'pageview', pathname + search); } - if (typeof (window as any)._hmt !== 'undefined') { - (window as any)._hmt.push(['_trackPageview', pathname + search]); - } }, [location]); const content = useMemo(() => { @@ -75,10 +72,9 @@ const DocLayout: React.FC = () => { ['/index'].some((path) => pathname.startsWith(path)) ) { return ( - <> -
{outlet}
-
- + + {outlet} + ); } if (pathname.startsWith('/docs/resource')) { @@ -98,13 +94,10 @@ const DocLayout: React.FC = () => { data-direction={direction} className={classNames({ rtl: direction === 'rtl' })} /> - {locale?.title} - - = { [K in keyof T]: [K, T[K]] }[keyof T][]; type SiteState = Partial>; const RESPONSIVE_MOBILE = 768; +export const ANT_DESIGN_NOT_SHOW_BANNER = 'ANT_DESIGN_NOT_SHOW_BANNER'; // const styleCache = createCache(); // if (typeof global !== 'undefined') { @@ -31,25 +35,29 @@ const RESPONSIVE_MOBILE = 768; // } const getAlgorithm = (themes: ThemeName[] = []) => - themes.map((theme) => { - if (theme === 'dark') { - return antdTheme.darkAlgorithm; - } - if (theme === 'compact') { - return antdTheme.compactAlgorithm; - } - return antdTheme.defaultAlgorithm; - }); + themes + .map((theme) => { + if (theme === 'dark') { + return antdTheme.darkAlgorithm; + } + if (theme === 'compact') { + return antdTheme.compactAlgorithm; + } + return null; + }) + .filter((item) => item); const GlobalLayout: React.FC = () => { const outlet = useOutlet(); const { pathname } = useLocation(); const [searchParams, setSearchParams] = useSearchParams(); - const [{ theme = [], direction, isMobile }, setSiteState] = useLayoutState({ - isMobile: false, - direction: 'ltr', - theme: [], - }); + const [{ theme = [], direction, isMobile, bannerVisible = false }, setSiteState] = + useLayoutState({ + isMobile: false, + direction: 'ltr', + theme: [], + bannerVisible: false, + }); const updateSiteConfig = useCallback( (props: SiteState) => { @@ -72,6 +80,10 @@ const GlobalLayout: React.FC = () => { ...nextSearchParams, theme: value.filter((t) => t !== 'light'), }); + + document + .querySelector('html') + ?.setAttribute('data-prefers-color', value.includes('dark') ? 'dark' : 'light'); } }); @@ -89,8 +101,16 @@ const GlobalLayout: React.FC = () => { useEffect(() => { const _theme = searchParams.getAll('theme') as ThemeName[]; const _direction = searchParams.get('direction') as DirectionType; - - setSiteState({ theme: _theme, direction: _direction === 'rtl' ? 'rtl' : 'ltr' }); + const storedBannerVisibleLastTime = + localStorage && localStorage.getItem(ANT_DESIGN_NOT_SHOW_BANNER); + const storedBannerVisible = + storedBannerVisibleLastTime && dayjs().diff(dayjs(storedBannerVisibleLastTime), 'day') >= 1; + + setSiteState({ + theme: _theme, + direction: _direction === 'rtl' ? 'rtl' : 'ltr', + bannerVisible: storedBannerVisibleLastTime ? storedBannerVisible : true, + }); // Handle isMobile updateMobileMode(); @@ -106,8 +126,9 @@ const GlobalLayout: React.FC = () => { updateSiteConfig, theme: theme!, isMobile: isMobile!, + bannerVisible, }), - [isMobile, direction, updateSiteConfig, theme], + [isMobile, direction, updateSiteConfig, theme, bannerVisible], ); const [styleCache] = React.useState(() => createCache()); @@ -144,23 +165,25 @@ const GlobalLayout: React.FC = () => { } return ( - - - - {content} - - - + + + + + {content} + + + + ); }; diff --git a/.dumi/theme/layouts/IndexLayout/index.tsx b/.dumi/theme/layouts/IndexLayout/index.tsx new file mode 100644 index 000000000000..dbd85a1fb309 --- /dev/null +++ b/.dumi/theme/layouts/IndexLayout/index.tsx @@ -0,0 +1,21 @@ +import { Helmet } from 'dumi'; +import type { PropsWithChildren } from 'react'; +import React from 'react'; +import Footer from '../../slots/Footer'; + +const IndexLayout: React.FC> = ({ + children, + ...restProps +}) => ( + <> + + {restProps.title} + + {restProps.desc && } + +
{children}
+
+ +); + +export default IndexLayout; diff --git a/.dumi/theme/locales/en-US.json b/.dumi/theme/locales/en-US.json index 7a9f792abbd9..6ca8a49d35ef 100644 --- a/.dumi/theme/locales/en-US.json +++ b/.dumi/theme/locales/en-US.json @@ -31,6 +31,7 @@ "app.demo.copied": "Copied!", "app.demo.code.show": "Show code", "app.demo.code.hide": "Hide code", + "app.demo.code.hide.simplify": "Hide", "app.demo.codepen": "Open in CodePen", "app.demo.codesandbox": "Open in CodeSandbox", "app.demo.stackblitz": "Open in Stackblitz", diff --git a/.dumi/theme/locales/zh-CN.json b/.dumi/theme/locales/zh-CN.json index 3618d9dabbd6..2a37d63e3ea7 100644 --- a/.dumi/theme/locales/zh-CN.json +++ b/.dumi/theme/locales/zh-CN.json @@ -31,6 +31,7 @@ "app.demo.copied": "复制成功", "app.demo.code.show": "显示代码", "app.demo.code.hide": "收起代码", + "app.demo.code.hide.simplify": "收起", "app.demo.codepen": "在 CodePen 中打开", "app.demo.codesandbox": "在 CodeSandbox 中打开", "app.demo.stackblitz": "在 Stackblitz 中打开", diff --git a/.dumi/theme/plugin.ts b/.dumi/theme/plugin.ts index 2f312dc468d6..90a1490d0add 100644 --- a/.dumi/theme/plugin.ts +++ b/.dumi/theme/plugin.ts @@ -44,9 +44,11 @@ class AntdReactTechStack extends ReactTechStack { const codePath = opts.fileAbsPath!.replace(/\.\w+$/, '.tsx'); const code = fs.existsSync(codePath) ? fs.readFileSync(codePath, 'utf-8') : ''; - const pkgDependencyList = localPackage.dependencies; - props.pkgDependencyList = pkgDependencyList; + props.pkgDependencyList = { + ...localPackage.devDependencies, + ...localPackage.dependencies, + }; props.jsx = sylvanas.parseText(code); if (md) { @@ -153,12 +155,12 @@ const RoutesPlugin = (api: IApi) => { // 2. 提取每个样式到独立 css 文件 styles.forEach((result) => { api.logger.event( - `${chalk.yellow(file.path)} include ${chalk.blue`[${result.key}]`} ${chalk.yellow( - result.ids.length, + `${chalk.yellow(file.path)} include ${chalk.blue`[${result!.key}]`} ${chalk.yellow( + result!.ids.length, )} styles`, ); - const cssFile = writeCSSFile(result.key, result.ids.join(''), result.css); + const cssFile = writeCSSFile(result!.key, result!.ids.join(''), result!.css); file.content = addLinkStyle(file.content, cssFile); }); diff --git a/.dumi/theme/slots/Content/index.tsx b/.dumi/theme/slots/Content/index.tsx index f7b40d048d0c..59365bdd034e 100644 --- a/.dumi/theme/slots/Content/index.tsx +++ b/.dumi/theme/slots/Content/index.tsx @@ -211,7 +211,7 @@ const Content: React.FC<{ children: ReactNode }> = ({ children }) => { ({ href: `#${item.id}`, diff --git a/.dumi/theme/slots/Footer/index.tsx b/.dumi/theme/slots/Footer/index.tsx index f65a6a3e23b2..6b34e18ed5aa 100644 --- a/.dumi/theme/slots/Footer/index.tsx +++ b/.dumi/theme/slots/Footer/index.tsx @@ -102,7 +102,7 @@ const Footer: React.FC = () => { items: [ { title: 'Ant Design Charts', - url: 'https://charts.ant.design', + url: isZhCN ? 'https://ant-design-charts.antgroup.com' : 'https://charts.ant.design', openExternal: true, }, { @@ -117,12 +117,12 @@ const Footer: React.FC = () => { }, { title: 'Ant Design Mobile', - url: 'https://mobile.ant.design', + url: isZhCN ? 'https://ant-design-mobile.antgroup.com/zh' : 'https://mobile.ant.design', openExternal: true, }, { title: 'Ant Design Mini', - url: 'https://mini.ant.design', + url: isZhCN ? 'https://ant-design-mini.antgroup.com/' : 'https://mini.ant.design', openExternal: true, }, { @@ -338,7 +338,7 @@ const Footer: React.FC = () => { /> ), title: 'AntV', - url: 'https://antv.vision', + url: 'https://antv.antgroup.com', description: , openExternal: true, }, diff --git a/.dumi/theme/slots/Header/Navigation.tsx b/.dumi/theme/slots/Header/Navigation.tsx index 6bdb4b5012dc..597dc1fd3101 100644 --- a/.dumi/theme/slots/Header/Navigation.tsx +++ b/.dumi/theme/slots/Header/Navigation.tsx @@ -30,7 +30,8 @@ const locales = { // ============================= Style ============================= const useStyle = createStyles(({ token }) => { - const { antCls, iconCls, fontFamily, headerHeight, menuItemBorder, colorPrimary } = token; + const { antCls, iconCls, fontFamily, headerHeight, menuItemBorder, colorPrimary, colorText } = + token; return { nav: css` @@ -56,6 +57,17 @@ const useStyle = createStyles(({ token }) => { left: 12px; border-width: ${menuItemBorder}px; } + + a { + color: ${colorText}; + } + + a:before { + position: absolute; + inset: 0; + background-color: transparent; + content: ""; + } } & ${antCls}-menu-submenu-title ${iconCls} { @@ -97,7 +109,6 @@ const useStyle = createStyles(({ token }) => { export interface NavigationProps extends SharedProps { isMobile: boolean; - isClient: boolean; responsive: null | 'narrow' | 'crowded'; directionText: string; onLangChange: () => void; @@ -106,7 +117,6 @@ export interface NavigationProps extends SharedProps { export default ({ isZhCN, - isClient, isMobile, responsive, directionText, @@ -224,16 +234,21 @@ export default ({ ), key: 'docs/resources', }, - isZhCN && - isClient && - window.location.host !== 'ant-design.antgroup.com' && - window.location.host !== 'ant-design.gitee.io' + isZhCN ? { - label: '国内镜像', + label: ( + + 国内镜像 + + ), key: 'mirror', children: [ { - label: 官方镜像, + label: ( + + 官方镜像 + + ), icon: ( logoGitee 镜像, + label: ( + + Gitee 镜像 + + ), icon: ( gitee { const searchIconColor = '#ced4d9'; @@ -106,19 +118,27 @@ const useStyle = createStyles(({ token, css }) => { padding: 0, }, }, + banner: css` + width: 100%; + text-align: center; + word-break: keep-all; + user-select: none; + `, + link: css` + margin-left: 10px; + + @media only screen and (max-width: ${token.mobileMaxWidth}px) { + margin-left: 0; + } + `, + icon: css` + margin-right: 10px; + width: 22px; + height: 22px; + `, }; }); -const SHOULD_OPEN_ANT_DESIGN_MIRROR_MODAL = 'ANT_DESIGN_DO_NOT_OPEN_MIRROR_MODAL'; - -function disableAntdMirrorModal() { - window.localStorage.setItem(SHOULD_OPEN_ANT_DESIGN_MIRROR_MODAL, 'true'); -} - -function shouldOpenAntdMirrorModal() { - return !window.localStorage.getItem(SHOULD_OPEN_ANT_DESIGN_MIRROR_MODAL); -} - interface HeaderState { menuVisible: boolean; windowWidth: number; @@ -127,8 +147,7 @@ interface HeaderState { // ================================= Header ================================= const Header: React.FC = () => { - const [isClient, setIsClient] = React.useState(false); - const [, lang] = useLocale(); + const [locale, lang] = useLocale(locales); const { pkg } = useSiteData(); @@ -138,8 +157,9 @@ const Header: React.FC = () => { windowWidth: 1400, searching: false, }); - const { direction, isMobile, updateSiteConfig } = useContext(SiteContext); - const pingTimer = useRef(null); + const { direction, isMobile, bannerVisible, updateSiteConfig } = + useContext(SiteContext); + const pingTimer = useRef | null>(null); const location = useLocation(); const { pathname, search } = location; @@ -160,40 +180,21 @@ const Header: React.FC = () => { const onDirectionChange = () => { updateSiteConfig({ direction: direction !== 'rtl' ? 'rtl' : 'ltr' }); }; + const onBannerClose = () => { + updateSiteConfig({ bannerVisible: false }); + + if (utils.isLocalStorageNameSupported()) { + localStorage.setItem(ANT_DESIGN_NOT_SHOW_BANNER, dayjs().toISOString()); + } + }; useEffect(() => { handleHideMenu(); }, [location]); useEffect(() => { - setIsClient(typeof window !== 'undefined'); onWindowResize(); window.addEventListener('resize', onWindowResize); - pingTimer.current = ping((status) => { - if (status !== 'timeout' && status !== 'error') { - if ( - // process.env.NODE_ENV === 'production' && - window.location.host !== 'ant-design.antgroup.com' && - shouldOpenAntdMirrorModal() - ) { - Modal.confirm({ - title: '提示', - content: '内网用户推荐访问国内镜像以获得极速体验~', - okText: '🚀 立刻前往', - cancelText: '不再弹出', - closable: true, - zIndex: 99999, - onOk() { - window.open('https://ant-design.antgroup.com', '_self'); - disableAntdMirrorModal(); - }, - onCancel() { - disableAntdMirrorModal(); - }, - }); - } - } - }); return () => { window.removeEventListener('resize', onWindowResize); if (pingTimer.current) { @@ -273,7 +274,6 @@ const Header: React.FC = () => { const sharedProps: SharedProps = { isZhCN, isRTL, - isClient, }; const navigationNode = ( @@ -360,6 +360,42 @@ const Header: React.FC = () => { )} + {isZhCN && bannerVisible && ( + + + yuque + {isMobile ? locale.shortMessage : locale.message} + { + window.gtag?.('event', '点击', { + event_category: 'top_banner', + event_label: 'https://www.yuque.com/yuque/blog/welfare-edu?source=antd', + }); + }} + > + {locale.more} + + + } + type="info" + banner + closable + showIcon={false} + onClose={onBannerClose} + /> + + )} diff --git a/.dumi/theme/slots/Header/interface.ts b/.dumi/theme/slots/Header/interface.ts index 4c8824787310..8a0755c1bf0e 100644 --- a/.dumi/theme/slots/Header/interface.ts +++ b/.dumi/theme/slots/Header/interface.ts @@ -1,5 +1,4 @@ export interface SharedProps { isZhCN: boolean; isRTL: boolean; - isClient: boolean; } diff --git a/.dumi/theme/slots/SiteContext.ts b/.dumi/theme/slots/SiteContext.ts index 179aa6dc3329..3878940d846f 100644 --- a/.dumi/theme/slots/SiteContext.ts +++ b/.dumi/theme/slots/SiteContext.ts @@ -4,6 +4,7 @@ import type { ThemeName } from '../common/ThemeSwitch'; export interface SiteContextProps { isMobile: boolean; + bannerVisible: boolean; direction: DirectionType; theme: ThemeName[]; updateSiteConfig: (props: Partial) => void; @@ -11,6 +12,7 @@ export interface SiteContextProps { const SiteContext = React.createContext({ isMobile: false, + bannerVisible: true, direction: 'ltr', theme: ['light'], updateSiteConfig: () => {}, diff --git a/.dumi/theme/utils.ts b/.dumi/theme/utils.ts index 2dc8e4b0e0b2..3d6d24c00c44 100644 --- a/.dumi/theme/utils.ts +++ b/.dumi/theme/utils.ts @@ -1,5 +1,6 @@ import flatten from 'lodash/flatten'; import flattenDeep from 'lodash/flattenDeep'; + import themeConfig from './themeConfig'; interface Meta { diff --git a/.dumi/tsconfig.json b/.dumi/tsconfig.json index f0b63fb243b8..74eb1d443906 100644 --- a/.dumi/tsconfig.json +++ b/.dumi/tsconfig.json @@ -1,15 +1,7 @@ { + "extends": "../tsconfig.json", "compilerOptions": { - "jsx": "react-jsx", - "esModuleInterop": true, - "resolveJsonModule": true, - "baseUrl": "../", - "paths": { - "@@/*": [".dumi/tmp/*"], - "antd": ["components/index.tsx"], - "antd/es/*": ["components/*"], - "dumi/theme/*": [".dumi/theme/*"] - } + "resolveJsonModule": true }, - "include": ["./**/*", "../site/theme/template/Content"] + "include": ["**/*"] } diff --git a/.dumirc.ts b/.dumirc.ts index f9aed1f0e5ec..16fd2d16c517 100644 --- a/.dumirc.ts +++ b/.dumirc.ts @@ -3,8 +3,10 @@ import path from 'path'; import rehypeAntd from './.dumi/rehypeAntd'; import remarkAntd from './.dumi/remarkAntd'; import { version } from './package.json'; +import * as fs from 'fs-extra'; export default defineConfig({ + plugins: ['dumi-plugin-color-chunk'], conventionRoutes: { // to avoid generate routes for .dumi/pages/index/components/xx exclude: [new RegExp('index/components/')], @@ -44,42 +46,42 @@ export default defineConfig({ }, links: [ { - rel: 'preload', + rel: 'prefetch', as: 'font', href: '//at.alicdn.com/t/webfont_6e11e43nfj.woff2', type: 'font/woff2', crossorigin: true, }, { - rel: 'preload', + rel: 'prefetch', as: 'font', href: '//at.alicdn.com/t/webfont_6e11e43nfj.woff', type: 'font/woff', crossorigin: true, }, { - rel: 'preload', + rel: 'prefetch', as: 'font', href: '//at.alicdn.com/t/webfont_6e11e43nfj.ttf', type: 'font/ttf', crossorigin: true, }, { - rel: 'preload', + rel: 'prefetch', as: 'font', href: '//at.alicdn.com/t/webfont_exesdog9toj.woff2', type: 'font/woff2', crossorigin: true, }, { - rel: 'preload', + rel: 'prefetch', as: 'font', href: '//at.alicdn.com/t/webfont_exesdog9toj.woff', type: 'font/woff', crossorigin: true, }, { - rel: 'preload', + rel: 'prefetch', as: 'font', href: '//at.alicdn.com/t/webfont_exesdog9toj.ttf', type: 'font/ttf', @@ -158,4 +160,10 @@ export default defineConfig({ })(); `, ], + scripts: [ + { + async: true, + content: fs.readFileSync(path.join(__dirname, '.dumi', 'mirror-modal.js')).toString(), + }, + ], }); diff --git a/.eslintrc.js b/.eslintrc.js index a341d58bb440..12e49328d21e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -126,6 +126,12 @@ module.exports = { 'comma-dangle': 0, }, }, + { + files: ['**/*.test.ts', '**/*.test.tsx', '**/*.spec.ts', '**/*.spec.tsx'], + rules: { + 'compat/compat': 0, + }, + }, ], rules: { 'react/jsx-one-expression-per-line': 0, @@ -205,6 +211,7 @@ module.exports = { '@typescript-eslint/no-shadow': [2, { ignoreTypeValueShadow: true }], // https://github.com/typescript-eslint/typescript-eslint/issues/2528#issuecomment-689369395 'no-undef': 0, + 'import/order': 0, }, globals: { gtag: true, diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 0d4d1732277a..325c2f5d03fe 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,7 +1,7 @@ # To get started with Dependabot version updates, you'll need to specify which # package ecosystems to update and where the package manifests are located. # Please see the documentation for all configuration options: -# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates +# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/about-dependabot-version-updates version: 2 updates: @@ -18,15 +18,19 @@ updates: - dependency-name: "rc-dropdown" - dependency-name: "rc-field-form" - dependency-name: "rc-image" + - dependency-name: "rc-input" + - dependency-name: "rc-input-number" - dependency-name: "rc-mentions" - dependency-name: "rc-menu" - dependency-name: "rc-motion" - dependency-name: "rc-notification" + - dependency-name: "rc-pagination" - dependency-name: "rc-picker" - dependency-name: "rc-progress" - dependency-name: "rc-rate" - dependency-name: "rc-resize-observer" - dependency-name: "rc-select" + - dependency-name: "rc-segmented" - dependency-name: "rc-slider" - dependency-name: "rc-steps" - dependency-name: "rc-switch" @@ -36,6 +40,9 @@ updates: - dependency-name: "rc-tooltip" - dependency-name: "rc-tree" - dependency-name: "rc-tree-select" - - dependency-name: "rc-trigger" + - dependency-name: "@rc-component/trigger" + - dependency-name: "@rc-component/tour" + - dependency-name: "@rc-component/mutate-observer" + - dependency-name: "@rc-component/color-picker" - dependency-name: "rc-upload" - dependency-name: "rc-util" diff --git a/.github/workflows/chatgpt-cr.yml b/.github/workflows/chatgpt-cr.yml deleted file mode 100644 index c849485054ad..000000000000 --- a/.github/workflows/chatgpt-cr.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: 🤖 ChatGPT Code Review - -permissions: - contents: read - pull-requests: write - -on: - pull_request: - types: [opened, reopened, synchronize] - -jobs: - test: - runs-on: ubuntu-latest - if: github.event.pull_request.head.ref != 'feature' && github.event.pull_request.head.ref != 'master' && github.event.pull_request.head.ref != 'next' && github.event.pull_request.head.ref != 'master-merge-feature' && github.event.pull_request.head.ref != 'feature-merge-master' && github.event.pull_request.head.ref != 'next-merge-master' && github.event.pull_request.head.ref != 'next-merge-feature' - steps: - - uses: anc95/ChatGPT-CodeReview@main - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - # Optional - LANGUAGE: Chinese - MODEL: - top_p: 1 - temperature: 1 diff --git a/.github/workflows/mock-project-build.yml b/.github/workflows/mock-project-build.yml index 1c7f3342801d..c45e675af812 100644 --- a/.github/workflows/mock-project-build.yml +++ b/.github/workflows/mock-project-build.yml @@ -18,11 +18,11 @@ jobs: name: Build Project steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 - uses: actions/cache@v3 with: diff --git a/.github/workflows/preview-build.yml b/.github/workflows/preview-build.yml deleted file mode 100644 index 21b7ba9f0794..000000000000 --- a/.github/workflows/preview-build.yml +++ /dev/null @@ -1,96 +0,0 @@ -# Each PR will build preview site that help to check code is work as expect. - -name: Preview Build - -on: - pull_request: - types: [opened, synchronize, reopened] - -# Cancel prev CI if new commit come -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -permissions: - contents: read - -jobs: - # Prepare node modules. Reuse cache if available - setup: - name: prepare preview - runs-on: ubuntu-latest - steps: - - name: checkout - uses: actions/checkout@v3 - - - name: cache package-lock.json - uses: actions/cache@v3 - with: - path: package-temp-dir - key: lock-${{ github.sha }} - - - name: create package-lock.json - run: npm i --package-lock-only --ignore-scripts - - - name: hack for single file - run: | - if [ ! -d "package-temp-dir" ]; then - mkdir package-temp-dir - fi - cp package-lock.json package-temp-dir - - name: cache node_modules - id: node_modules_cache_id - uses: actions/cache@v3 - with: - path: node_modules - key: node_modules-${{ hashFiles('**/package-temp-dir/package-lock.json') }} - - - name: install - if: steps.node_modules_cache_id.outputs.cache-hit != 'true' - run: npm ci - - build-site: - name: build preview - runs-on: ubuntu-latest - needs: setup - steps: - - name: checkout - uses: actions/checkout@v3 - - - name: restore cache from package-lock.json - uses: actions/cache@v3 - with: - path: package-temp-dir - key: lock-${{ github.sha }} - - - name: restore cache from node_modules - uses: actions/cache@v3 - with: - path: node_modules - key: node_modules-${{ hashFiles('**/package-temp-dir/package-lock.json') }} - - - name: npm run site - id: site - run: npm run site - env: - SITE_ENV: development - NODE_OPTIONS: --max_old_space_size=4096 - - - name: upload site artifact - uses: actions/upload-artifact@v3 - with: - name: site - path: _site/ - retention-days: 5 - - # Upload PR id for next workflow use - - name: Save PR number - if: ${{ always() }} - run: echo ${{ github.event.number }} > ./pr-id.txt - - - name: Upload PR number - if: ${{ always() }} - uses: actions/upload-artifact@v3 - with: - name: pr - path: ./pr-id.txt diff --git a/.github/workflows/preview-deploy.yml b/.github/workflows/preview-deploy.yml deleted file mode 100644 index 864729967ac5..000000000000 --- a/.github/workflows/preview-deploy.yml +++ /dev/null @@ -1,106 +0,0 @@ -# Each PR will build preview site that help to check code is work as expect. - -name: Preview Deploy - -on: - workflow_run: - workflows: ["Preview Build"] - types: - - completed - -permissions: - contents: read - -jobs: - deploy-site: - permissions: - actions: read # for dawidd6/action-download-artifact to query and download artifacts - issues: write # for actions-cool/maintain-one-comment to modify or create issue comments - pull-requests: write # for actions-cool/maintain-one-comment to modify or create PR comments - name: deploy preview - runs-on: ubuntu-latest - if: > - github.event.workflow_run.event == 'pull_request' && - github.event.workflow_run.conclusion == 'success' - steps: - # We need get PR id first - - name: download pr artifact - uses: dawidd6/action-download-artifact@v2 - with: - workflow: ${{ github.event.workflow_run.workflow_id }} - run_id: ${{ github.event.workflow_run.id }} - name: pr - - # Save PR id to output - - name: save PR id - id: pr - run: echo "::set-output name=id::$(](https://preview-${{ steps.pr.outputs.id }}-ant-design.surge.sh) - - body-include: '' - number: ${{ steps.pr.outputs.id }} - - - name: The job has failed - if: ${{ failure() }} - uses: actions-cool/maintain-one-comment@v3 - with: - token: ${{ secrets.GITHUB_TOKEN }} - body: | - - - body-include: '' - number: ${{ steps.pr.outputs.id }} - - build-site-failed: - permissions: - actions: read # for dawidd6/action-download-artifact to query and download artifacts - issues: write # for actions-cool/maintain-one-comment to modify or create issue comments - pull-requests: write # for actions-cool/maintain-one-comment to modify or create PR comments - name: build preview failed - runs-on: ubuntu-latest - if: > - github.event.workflow_run.event == 'pull_request' && - github.event.workflow_run.conclusion == 'failure' - steps: - # We need get PR id first - - name: download pr artifact - uses: dawidd6/action-download-artifact@v2 - with: - workflow: ${{ github.event.workflow_run.workflow_id }} - run_id: ${{ github.event.workflow_run.id }} - name: pr - - # Save PR id to output - - name: save PR id - id: pr - run: echo "::set-output name=id::$( - - body-include: '' - number: ${{ steps.pr.outputs.id }} diff --git a/.github/workflows/preview-start.yml b/.github/workflows/preview-start.yml deleted file mode 100644 index 7cc3b9b27a4e..000000000000 --- a/.github/workflows/preview-start.yml +++ /dev/null @@ -1,31 +0,0 @@ -# When `preview-build` start. Leave a message on the PR -# -# 🚨🚨🚨 Important 🚨🚨🚨 -# Never do any `checkout` or `npm install` action! -# `pull_request_target` will enable PR to access the secrets! - -name: Preview Start - -on: - pull_request_target: - types: [opened, synchronize, reopened] - -permissions: - contents: read - -jobs: - preview-start: - permissions: - issues: write # for actions-cool/maintain-one-comment to modify or create issue comments - pull-requests: write # for actions-cool/maintain-one-comment to modify or create PR comments - name: start preview info - runs-on: ubuntu-latest - steps: - - name: update status comment - uses: actions-cool/maintain-one-comment@v3 - with: - token: ${{ secrets.GITHUB_TOKEN }} - body: | - ![Prepare preview](https://user-images.githubusercontent.com/5378891/72351368-2c979e00-371b-11ea-9652-eb4e825d745e.gif) - - body-include: '' diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml new file mode 100644 index 000000000000..c8aa66092459 --- /dev/null +++ b/.github/workflows/preview.yml @@ -0,0 +1,208 @@ +name: PR Preview + +on: + pull_request_target: + types: [opened, synchronize, reopened] + +# Cancel prev CI if new commit come +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + preview-start: + permissions: + issues: write # for actions-cool/maintain-one-comment to modify or create issue comments + pull-requests: write # for actions-cool/maintain-one-comment to modify or create PR comments + name: Prepare preview + runs-on: ubuntu-latest + steps: + - name: update status comment + uses: actions-cool/maintain-one-comment@v3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + body: | + ![Prepare preview](https://user-images.githubusercontent.com/5378891/72351368-2c979e00-371b-11ea-9652-eb4e825d745e.gif) + + body-include: "" + + setup: + name: Setup + runs-on: ubuntu-latest + steps: + - name: checkout + uses: actions/checkout@v4 + + - name: cache package-lock.json + uses: actions/cache@v3 + with: + path: package-temp-dir + key: lock-${{ github.sha }} + + - name: create package-lock.json + run: npm i --package-lock-only --ignore-scripts + + - name: hack for single file + run: | + if [ ! -d "package-temp-dir" ]; then + mkdir package-temp-dir + fi + cp package-lock.json package-temp-dir + - name: cache node_modules + id: node_modules_cache_id + uses: actions/cache@v3 + with: + path: node_modules + key: node_modules-${{ hashFiles('**/package-temp-dir/package-lock.json') }} + + - name: install + if: steps.node_modules_cache_id.outputs.cache-hit != 'true' + run: npm ci + + build-site: + name: Build Preview Site + runs-on: ubuntu-latest + needs: setup + steps: + - name: checkout + uses: actions/checkout@v4 + + - name: restore cache from package-lock.json + uses: actions/cache@v3 + with: + path: package-temp-dir + key: lock-${{ github.sha }} + + - name: restore cache from node_modules + uses: actions/cache@v3 + with: + path: node_modules + key: node_modules-${{ hashFiles('**/package-temp-dir/package-lock.json') }} + + - name: npm run site + id: site + run: npm run site + env: + SITE_ENV: development + NODE_OPTIONS: "--max_old_space_size=4096 --openssl-legacy-provider" + + - name: upload site artifact + uses: actions/upload-artifact@v3 + with: + name: site + path: _site/ + retention-days: 5 + + # Upload PR id for next workflow use + - name: Save PR number + if: ${{ always() }} + run: echo ${{ github.event.number }} > ./pr-id.txt + + - name: Upload PR number + if: ${{ always() }} + uses: actions/upload-artifact@v3 + with: + name: pr + path: ./pr-id.txt + + site-test: + name: Site E2E Test + runs-on: ubuntu-latest + needs: build-site + steps: + - name: checkout + uses: actions/checkout@v4 + + - name: restore cache from package-lock.json + uses: actions/cache@v3 + with: + path: package-temp-dir + key: lock-${{ github.sha }} + + - name: restore cache from node_modules + uses: actions/cache@v3 + with: + path: node_modules + key: node_modules-${{ hashFiles('**/package-temp-dir/package-lock.json') }} + + - name: download site artifact + uses: actions/download-artifact@v3 + with: + name: site + path: _site + + - name: run e2e test + run: npm run site:test + + preview-deploy: + name: Deploy Preview + runs-on: ubuntu-latest + needs: build-site + steps: + # We need get PR id first + - name: download pr artifact + uses: actions/download-artifact@v3 + with: + name: pr + + # Save PR id to output + - name: save PR id + id: pr + run: echo "id=$(> $GITHUB_OUTPUT + + # Download site artifact + - name: download site artifact + uses: actions/download-artifact@v3 + with: + name: site + + - name: upload surge service + id: deploy + run: | + export DEPLOY_DOMAIN=https://preview-${{ steps.pr.outputs.id }}-ant-design.surge.sh + npx surge --project ./ --domain $DEPLOY_DOMAIN --token ${{ secrets.SURGE_TOKEN }} + + preview-end: + name: Preview End + runs-on: ubuntu-latest + needs: + - build-site + - preview-deploy + if: always() + permissions: + issues: write # for actions-cool/maintain-one-comment to modify or create issue comments + pull-requests: write # for actions-cool/maintain-one-comment to modify or create PR comments + steps: + - name: download pr artifact + uses: actions/download-artifact@v3 + with: + name: pr + + - name: save PR id + id: pr + run: echo "id=$(> $GITHUB_OUTPUT + + - name: success comment + if: needs.build-site.result == 'success' && needs.preview-deploy.result == 'success' + uses: actions-cool/maintain-one-comment@v3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + body: | + [Preview Is ready](https://preview-${{ steps.pr.outputs.id }}-ant-design.surge.sh) + + body-include: "" + number: ${{ steps.pr.outputs.id }} + + - name: failed comment + if: needs.build-site.result == 'failure' || needs.preview-deploy.result == 'failure' + uses: actions-cool/maintain-one-comment@v3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + body: | + Preview Failed + + body-include: "" + number: ${{ steps.pr.outputs.id }} diff --git a/.github/workflows/rebase.yml b/.github/workflows/rebase.yml index 9da6d38ca269..c0fba0dec737 100644 --- a/.github/workflows/rebase.yml +++ b/.github/workflows/rebase.yml @@ -16,7 +16,7 @@ jobs: if: github.event.issue.pull_request != '' && (contains(github.event.comment.body, '/rebase') || contains(github.event.comment.body, '\rebase')) runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Automatic Rebase diff --git a/.github/workflows/site-deploy.yml b/.github/workflows/site-deploy.yml index 79cfe9c07df0..5b7e12a470bf 100644 --- a/.github/workflows/site-deploy.yml +++ b/.github/workflows/site-deploy.yml @@ -16,7 +16,7 @@ jobs: if: (startsWith(github.ref, 'refs/tags/') && (contains(github.ref_name, '-') == false)) || github.event_name == 'workflow_dispatch' steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: cache package-lock.json uses: actions/cache@v3 @@ -49,11 +49,11 @@ jobs: needs: setup steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 - name: restore cache from package-lock.json uses: actions/cache@v3 @@ -70,13 +70,13 @@ jobs: - name: build site run: npm run predeploy env: - NODE_OPTIONS: "--max_old_space_size=4096" + NODE_OPTIONS: "--max_old_space_size=4096 --openssl-legacy-provider" - name: build dist and bundle analyzer report run: npm run dist env: ANALYZER: 1 - NODE_OPTIONS: "--max_old_space_size=4096" + NODE_OPTIONS: "--max_old_space_size=4096 --openssl-legacy-provider" - name: Get version id: publish-version @@ -105,7 +105,7 @@ jobs: npx surge --project ./_site --domain $DEPLOY_DOMAIN --token ${{ secrets.SURGE_TOKEN }} - name: Create Commit Comment - uses: peter-evans/commit-comment@v2 + uses: peter-evans/commit-comment@v3 with: body: | - Documentation site for this release: https://ant-design-${{ steps.publish-version.outputs.VERSION }}.surge.sh diff --git a/.github/workflows/size-limit.yml b/.github/workflows/size-limit.yml index 7f86bf3eeca1..89b0b50e008c 100644 --- a/.github/workflows/size-limit.yml +++ b/.github/workflows/size-limit.yml @@ -23,11 +23,11 @@ jobs: steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 - name: cache package-lock.json uses: actions/cache@v3 @@ -63,5 +63,5 @@ jobs: build_script: dist skip_step: install env: - NODE_OPTIONS: --max_old_space_size=4096 + NODE_OPTIONS: "--max_old_space_size=4096 --openssl-legacy-provider" PRODUCTION_ONLY: 1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3eb5482b89f2..1c15128b37db 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,11 +17,11 @@ jobs: runs-on: ubuntu-latest steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 - name: cache package-lock.json uses: actions/cache@v3 @@ -53,11 +53,11 @@ jobs: runs-on: ubuntu-latest steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 - name: restore cache from package-lock.json uses: actions/cache@v3 @@ -79,11 +79,11 @@ jobs: runs-on: ubuntu-latest steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 - name: restore cache from package-lock.json uses: actions/cache@v3 @@ -104,11 +104,11 @@ jobs: runs-on: ubuntu-latest steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 - name: restore cache from package-lock.json uses: actions/cache@v3 @@ -129,9 +129,10 @@ jobs: key: dist-${{ github.sha }} - name: dist - run: CI=1 npm run dist + run: npm run dist env: - NODE_OPTIONS: --max_old_space_size=4096 + NODE_OPTIONS: "--max_old_space_size=4096 --openssl-legacy-provider" + CI: 1 needs: setup ################################ Test ################################ @@ -147,11 +148,11 @@ jobs: runs-on: ubuntu-latest steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 - name: restore cache from package-lock.json uses: actions/cache@v3 @@ -188,6 +189,12 @@ jobs: if: ${{ matrix.module == 'dist' }} run: node ./tests/dekko/dist.test.js + - name: check use client + if: ${{ matrix.module == 'dist' }} + run: node ./tests/dekko/use-client.test.js + env: + LIB_DIR: dist + # dom test - name: dom test if: ${{ matrix.module == 'dom' }} @@ -225,11 +232,11 @@ jobs: runs-on: ubuntu-latest needs: [normal-test] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 - uses: actions/download-artifact@v3 with: @@ -251,11 +258,11 @@ jobs: runs-on: ubuntu-latest steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 - name: restore cache from package-lock.json uses: actions/cache@v3 @@ -286,6 +293,10 @@ jobs: - name: check run: node ./tests/dekko/lib.test.js + + - name: check use client + run: node ./tests/dekko/use-client.test.js + needs: setup compiled-module-test: @@ -302,11 +313,11 @@ jobs: - name: checkout # lib only run in master branch not in pull request if: ${{ github.event_name != 'pull_request' || matrix.module != 'lib' }} - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 - name: restore cache from package-lock.json # lib only run in master branch not in pull request diff --git a/.github/workflows/trigger-argos-with-whitelist-users.yml b/.github/workflows/trigger-argos-with-whitelist-users.yml new file mode 100644 index 000000000000..3c310afaf4a8 --- /dev/null +++ b/.github/workflows/trigger-argos-with-whitelist-users.yml @@ -0,0 +1,63 @@ +# Due to some special reasons, some accounts are blocked by circleCI +# and cannot trigger argos jobs through circleCI. +# These accounts can be configured in the whitelist list +# and do not need to rely on circleCI to directly trigger argos in the PR workflow + +name: Trigger Argos with white-listed users + +on: [push] + +permissions: + contents: read + +jobs: + trigger_argos_with_whitelist_users: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Read white listed users + id: read_users + run: | + whitelist_file="argos-white-listed-users" + if [[ -f $whitelist_file ]]; then + users=$(cat $whitelist_file) + echo "whitelisted_users=$users" >> $GITHUB_OUTPUT + fi + + - name: Check if user is whitelisted + id: check_user + run: | + whitelisted_users="${{ steps.read_users.outputs.whitelisted_users }}" + current_user="${{ github.actor }}" + if grep -Fxq "$current_user" <<< "$whitelisted_users"; then + echo "User is whitelisted" + echo "whitelisted=true" >> $GITHUB_OUTPUT + else + echo "User is not whitelisted" + echo "whitelisted=false" >> $GITHUB_OUTPUT + fi + + - name: install dependencies + if: ${{ steps.check_user.outputs.whitelisted == 'true' }} + run: yarn + + - name: Build dist file + id: build + if: ${{ steps.check_user.outputs.whitelisted == 'true' }} + run: npm run dist:esbuild + + - name: Run image screenshot tests + id: screenshot + if: ${{ steps.check_user.outputs.whitelisted == 'true' }} + run: npm run test-image + + - name: Upload screenshots to Argos CI + id: upload + if: ${{ steps.check_user.outputs.whitelisted == 'true' }} + env: + ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }} + ARGOS_PARALLEL_NONCE: ${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }} + run: npm run argos \ No newline at end of file diff --git a/.github/workflows/verify-files-modify.yml b/.github/workflows/verify-files-modify.yml index 8ca9e727621b..869b47a9eab8 100644 --- a/.github/workflows/verify-files-modify.yml +++ b/.github/workflows/verify-files-modify.yml @@ -26,3 +26,21 @@ jobs: Hi @${{ github.event.pull_request.user.login }}. Thanks for your contribution. The path `.github/` or `scripts/` and `CHANGELOG` is only maintained by team members. This current PR will be closed and team members will help on this. close: true set-failed: false + + readme: + permissions: + pull-requests: write # for actions-cool/verify-files-modify to update status of PRs + runs-on: ubuntu-latest + steps: + - name: verify-version + uses: actions-cool/verify-files-modify@v1 + with: + forbid-files: 'README.md' + skip-verify-authority: 'write' + skip-label: 'skip-verify-files' + assignees: 'afc163, zombieJ, xrkffgg, MadCcc' + comment-mark: 'readmeCheck' + comment: | + Hi @${{ github.event.pull_request.user.login }}. Thanks for your contribution. But, we don't have plan to add README of more languages. This current PR will be closed and team members will help on this. + close: true + set-failed: false diff --git a/.github/workflows/verify-package-version.yml b/.github/workflows/verify-package-version.yml index 6ff6065a3581..506294874259 100644 --- a/.github/workflows/verify-package-version.yml +++ b/.github/workflows/verify-package-version.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest if: contains(github.event.pull_request.title, 'changelog') || contains(github.event.pull_request.title, 'release') steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: verify-version uses: actions-cool/verify-package-version@v1 with: diff --git a/.gitignore b/.gitignore index 8bc92f8bdd6b..fc7b9febbb8f 100644 --- a/.gitignore +++ b/.gitignore @@ -68,3 +68,4 @@ __image_snapshots__/ .husky/prepare-commit-msg .eslintcache +.node-version diff --git a/.npmrc b/.npmrc index 9cf9495031ec..020e8ceaa7d4 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1,5 @@ -package-lock=false \ No newline at end of file +package-lock=false + +PUPPETEER_DOWNLOAD_BASE_URL="https://cdn.npmmirror.com/binaries/chrome-for-testing" + +npm_config_sharp_libvips_binary_host="https://cdn.npmmirror.com/binaries/sharp-libvips" diff --git a/.prettierrc b/.prettierrc index 9d5b9bf640c1..73e7db810cd9 100644 --- a/.prettierrc +++ b/.prettierrc @@ -4,6 +4,8 @@ "trailingComma": "all", "printWidth": 100, "proseWrap": "never", + "importOrder": ["^(react|react-dom)$", "^([a-z]|@[a-z])", "", ".*"], + "plugins": ["@ianvs/prettier-plugin-sort-imports"], "overrides": [ { "files": ".prettierrc", diff --git a/.remarkrc.js b/.remarkrc.js index c10e9c3421c9..c7d96ef04922 100644 --- a/.remarkrc.js +++ b/.remarkrc.js @@ -3,6 +3,7 @@ const config = { 'remark-preset-lint-recommended', ['remark-lint-list-item-indent', 'space'], ['remark-lint-no-literal-urls', false], + ['remark-lint-no-undefined-references', false], ], }; diff --git a/AUTHORS.txt b/AUTHORS.txt deleted file mode 100644 index bc018e296dc5..000000000000 --- a/AUTHORS.txt +++ /dev/null @@ -1,1590 +0,0 @@ -+v -07akioni -17073025 -2724635499 -282159468 -778758944 -AKing -Aaron Cawte -Aaron Planell López -Aaron674092290 -Adam Stankiewicz -Aditya Padhi -Adrian Dimitrov -Adriano Ruberto -Aex -Ahmad Abdelaziz -Ahmed AlSammany -Ahmet Simsek -Aidin -Aiello -Akara -AkiJoey -Akshat Mittal -Alan Braithwaite -Alan Deng -Albert Mañosa -Albert Zhang -Albert Zheng -Albert 理斯特 -Alberto Marchetti -Aleck Landgraf -Alek Ye -Aleksandr Chernokondratenko -Alex -Alex Simons -Alexander -Alexander Anpleenko -Alexander Ionov -Alexander Kachkaev -Alexander Suevalov -Alexander.Kosov -Alexandre Kirszenberg -Alexey Vinogradov -Alexey Yakovlev -Alfred Qiu -Ali Zhdanov -AliRezaBeigy -Aliaksandr -Alina Andrieieva -Alireza -Alvin Abia -Aminul Islam -Amir Arafat -Amir M. Mohamadi -Amorites -Amour1688 -Amumu -Anas Tawfeek -Andre Perunicic -Andre Zyczkowski -Andrea Blanco -Andrew Blakey -Andrew Horn -Andrew Murray -Andrew Shearer -Andrey G -Andrzej Dybionka -André -Andrés -AndyJin -Ankit Babbar -Antee -Aobo Yang -Ardo Kusuma -Ariunbat Ulambayar -Arlindo Torres -Arnab Sen -Arthur Denner Oliveira Santos -Artin -Arvin Xu -Ash Kumar -Ashot Mnatsakanyan -Austaras -Ayden -Aymen Bouchekoua -Aymen Chebbi -BK Heleth -Babajide Fowotade -Baic -Barry -Bartek -Belikov Ivan -Ben Callaway -Benedikt Franke -Benjamin Amelot -Benjamin Kniffler -Benjamin Schuch -Benjamin Vertonghen -Benjy Cui -Benoît Latinier -BensonChen -Bernie -Bestie -Bhavesh Chowdhury -Bilal Sirazitdinov -Bill Searle -Bill Sheikh -Blaz Pocrnja -Bo Chen -Bojack -Bolun Zhang -Bora Ikizoglu -Bosseskompis -Bozhao -Bradley Xu -Brett Lamy -Brook Shi -Bruce Mitchener -Bruno Maia -Bryan Berger -BugHiding -C -C. T. Lin -C.J. Winslow -CORP\lianyufeng -Calin Vlad -Cam Song -Camol -Cang Ta -Canwen Xu -Carlos Coves Prieto -Carter Feldman -Caspian Chen -Cat-XHS -Catalin Miron -Cedong.Lee -Cee Cirno -Cemre Mengu -Chalk -Chandler Moisen -Chang Wang -Chang Wei -Charles Covey-Brandt -Charlie Jonas -Chelsea Huang -ChenXiao -Cheng Liu -Chenjia -Chiciuc Nicușor -Chikara Chan -Chinnawat Chimdee -Chris Frisina -Chris Kelly -Chris Young -ChrisFan -Christian Fleschhut -Christian Vadalà -Christophe Hurpeau -Christopher Deutsch -ChuTao Zhang -Chuang Yu -Chuck -Chuns Chen -Claudio Restifo -Cody Chan -Cole -Colton Pierson -Confiks -Cong Yoo -Cong Zhang -Connor White -Conway Anderson -Cooper Veysey -Cordaro -CornerSkyless -Curly.Water -D & R -Daewoong Moon -Dalton Craven -Damian Green -Dan Minshew -Dana Janoskova -Dane David -Daniel -Daniel Chang -Daniel Gomez -Daniel Harrison -Daniel Pfeffer -Danny Hoower Antonio Viasus Avila -Daphne Won -Daqi Song -Darren Poon -Daryl Roberts -Darío Hereñú -Dave -David Broder-Rodgers -David Hatten -David Schneider -Davide Bianchi -Dawnlck -Dean van Niekerk -Debiancc -DengYun -Denis -Dennis Chen -Denys Halenok -Derrick -Di Wu -DiamondYuan -Diego Barreiro -Diego Villacís -Dimitri Mitropoulos -Dmitriy -Dmitriy Mironov -Dmitry Bolotin -Dmitry Cherendieiev -Dmitry Gladkikh -Dmitry Guryev -Dmitry Manannikov -Dmitry Snegirev -Dmitry Tikhomirov -Dongcheng Wang -Dony Sukardi -Dorian -DosLin -Douglas Mason -Dreamcreative -Dunqing -Duy Pham -Dzmitry Yarmoshkin -EMpersonal -Eager -Eber Rodrigues -EcmaProSrc.P/ka -Ed Moore -Edd Hannay -Eddie Xie -Eden Wang -Eduardo Ludi -Edward -Egor Yurtaev -Elaina Cherudim -Eldar Mirzabekov -Eldar Mustafaiev -Eli White -Eliot Sanford -Ell Bradshaw -Emerson Laurentino -Emily Xiong -Ender Lee -Eric -Eric Bonow -Eric Celeste -Eric Chen -Eric Lee -Eric Turriff -Eric Wang -Ernest Folch -Erwann Mest -Eslam Yahya -Eugene Matvejev -Eugene Molokov -Eusen -Evan Charlton -EvanOne(文一) -Evgeny Kuznetsov -Eward Song -FJHou -Fachreza Muslim -Federico Marcos -Ferdi Koomen -Fergus Leung -Fernando Giarritiello -Filip Kukovec -Filip Seman -Florian Orpelière -Flynn -Fog3211 -For177 -Frank -Frank Fang -Frezc -Fullstop000 -GJ Wang -GSBL -Gabe Medrash -Gabriel Haruki -Gabriel Henrique -Gabriel Le Breton -Gabriel Mendez Reyes -Gabriel Nunes -GalenWong -GannonSun -Gao Jiangmiao -Garrick Crouch -Gautier -Geoff Holden -Geoffrey Bell -George Ciobanu -George Gray -Germini -Gerson Garrido -Gherciu Gheorghe -Gianmarco Rengucci -Gin-X -Go7hic -Goh Zhao Yang -Goku -Golevka -Googleplex -Gourav Saini -Graeme Yeates -Grant Klinsing -Gray Choi -Guan Hao -Guan Yu Pan (Jacky) -Guichi Zhao -Guojun Wang -Guru Mahendran -HJin.me -Hai Phan Nguyen -Haibin Yu -Hale Deng -Han Han -Hanai -Haniel Cui -Hanjun Kim -Hanz Luo -HarlanLuo -Haroen Viaene -Harrison -Harry.Hou -Harshit Mehrotra -Harutaka Kawamura -He Linming -Heaven -Hector Ayala -Hell Cat -Henri Normak -HeskeyBaozi -HiddenMan -Hieu Ho -Hieu Pham -Higor Araújo dos Anjos -Hollow Man -Homyee King -Hossein Alimadad -Hossein Mohammadi -HouXiancheng -Hsuan Lee -Hubert Argasinski -Hughen -Hugo LEHMANN -Humble -Hyunseok.Kim -ILdar Nogmanov -Igor -Igor Andriushchenko -Igor G -Ikko Ashimine -Ilan -Ilya Bondarenko -ImJoeHs -Infinity -Inian -Israel kusayev -Italo -Ivan -Ivan Kravets -Ivan Rudoy -Ivan Trofimov -Ivan Tsybulin -Ivan Yakovlev -Ivo Stratev -JRoger -Jabir K.H -Jack -Jack Hsieh -Jack Lo -Jack Works -Jackie.Ls -Jacques Kvam -JaePil Jung -Jaewook Ahn -Jaimy de Graaf -Jake Richards -Jaly -James -James Tsang -James Yeung -JamesYin -Jamki -Jan Václavík -Janry -Jaroslav Bereza -Jarret Moses -Jarvis1010 -Jase Owens -Jase Pellerin -Jason -Jason Chung -Jason Yin -Jay Fong -Jean-Luc Sorak -Jean-Philippe Roy -Jeff Wen -Jefferson Rafael Kozerski -Jeffrey Carl Faden -Jehu -Jelle de Jong -Jenna Van Conett -Jennie -JeromeLin -Jerry Bendy -Jesper We -Jesus The Hun -Jiabin Peng -Jiahao -Jiajun Chen -Jialei -Jiawei Huang -Jichao Zhong -Jiehui -Jieraaa -Jimmy -Jin ZHANG -JinXin -Jing Ma -Jingsong Gao -Jinke Li -Jinxuan Zhu -Jirka-Lhotka -Joao Rabelo -Jocker -Joe -Joe Hsu -Johannes Andersen -Johannes Loewe -John -John Carlo -John Johnson III -John Nguyen -Johnny Lim -Johnny-young -Johnsen -Jonatas Walker -Jonathan Gabaut -Jonathan Lee -Jonny Buchanan -Joo Wu -Jordan Hornblow -Joshua Chen -Josue Peralta -Josué -JounQin -JribiBelhassen -Jtree03 -Ju/Smwhr -JuFeng Zhang -Juan Carlos Lloret H -Juan Rodrigo Venegas Boesch -Julia Passynkova -Julien Confetti -Jun Wooram -JuniorTour -Junwoo Ji -Junyu Zhan -Juraj Carnogursky -Justin Reich -Justin Schuldt -Justin Sun -Jógvan Olsen -KAM -Kaan KÜÇÜK -Kaien Liao -Kamal Mahmudi -Karott -Kasra Bigdeli -Katsiaryna Pustakhod -Kayson Wu -Kelvin Chu -Kenaniah Cerny -Kenneth Luján Rosas -Kenneth Truong -KentonYu -Kermit -Keven Leone -Kevin Ivan -Kevin Wang -Kevinaskin -KgTong -Khaled -Khalifa Lame -Kian -Kieren -Kiho · Cham -Kim, Harim -Kimmo Saari -KingxBeta -Kirill Alexander Khalitov -Kirill Stiopin -Kiyan -Knacktus -Knut Olav Bøhmer -Kodai Nakamura -Kol Chen -Konrad Machlowski -Krishna Dubagunta -Krishna Singh -KuangPengfei -Kuitos -Kurt Furbush -Kyle Kelley -Kyle Rosenberg -Kyrielin -LLinFan- -LT246-VINHNPH\vinhnph -Laith -Larry Laski -LaySent -LeeHarlan -LeezQ -Len -Lennox Omondi -LeoYang -Leon Koole -Leon Shi -Lewis -Li C. Pan -Li Chao -Li Ming -LiPinghai -LilyWakana -Liming Jin -Lioness100 -Liron Lavy -Liu Bowen -Liu Ya -Liu Yang -LongYinan -Loogeek -Loïc Huvé -Lu Yu -Lucien Lee -Ludwig Bäcklund -Luke Vella -Luobo Zhang -Lyndon001 -M Mitchell -M. Burak Kalkan -MD. Ariful Alam -MESSAOUDI Oussama -MG12 -Ma Tianxiao -MaHui -Maciej Czekaj -MadCcc -Madis Väin -Maksim Nesterenko -Maksim Slotvinskij -Maksym Mosyura -Malven -Manjit Kumar -Manoj Kumar -Manweill -MaoYiWei -Map1en_ -Marcel Jackwerth -Marcela Bomfim -Marcia Sun -Marcio Pamplona -Marco Afonso -Marco Heinrich -Marcus Bransbury -Marcus Stenbeck -Marius Ileana -Mars Wong -Marshall Chen -Martijn -Martin Cermak -Martin Litvaj -Martin Novák -Mateusz Burzyński -Mathew -Mathieu Anderson -Matias Orellana -Matt Lein -Matt Wilkinson -Max -Maximilian Meyer -Md_ZubairAhmed -Mehdi Salem Naraghi -MeiLin -MengZhaoFly -Meow-z -Meowu -Miaow -Micah Guttman -Michael Adams -Michael Crenshaw -Michael Krog -Michael Salaverry -Michael Shing -Michael Waddell -Michael Wang -Michal Pekar -Michalis Macheras -Michał Jasikowski -Michelle Zhang -Miclle Zheng -Mikasa33 -Min -MinJeong Kim -MinYuan -Ming Hann -Minh Quy -Minqi Pan -Minsung Ryu -Minwei Xu -Mirko Alic -Misha Kav -Mitchell Demler -Moein Alizadeh -Mohamed Seada -Mohammad Anas -Mohammad Arsalan -Mohammad Faisal -Mohan Ban -Mohelm97 -Mongkii -Moni -Monty -Mounish Sai -Mr.Biscuit -Mr.Tone -Mr.jiangzhiguo -Ms. Wang -MuYu -Muhammad Sameer -Muhammad Sohaib Raza -MuxinFeng -Mykyta Velykanov -Mário Gonçalves -Nariman Movaffaghi -Nathan Broadbent -Nathan Griffin -Nathan Schneider -Nathan Tavares Nascimento -Nathan Wells -Naveen -Neekey -Neil -Nekron -Neo Tan -Neto Braghetto -Neverland -Nghiệp -Nico -Nicola Bosco -Nidhi Agarwal -Nihal Saxena -Nikesh -Nikita Bystrov -Nikita Marinosyan -Nikitenkova -Niko Autio -Nikolay -Nikolay Solovyov -Nima Dehnashi -Nimo -NinJa -Nishant Arora -Niyaz Akhmetov -Noel Kim (김민혁) -Nokecy -OAwan -Olaniyi Philip Ojeyinka -Oleg Kuzava -Oleksandr Kovalchuk -Olivier Louvignes -Omri Grossman -Ooi Yee Wei -Open Next -Oren Kosto -Orkhan Huseynli -OuYancey -PCCCCCCC -Pablo Recalde -Panjie Setiawan Wicaksono -Patrick Gidich -Patryk -Paul Damnhorns -Paul Julien -Peach -Pengsha Ying -Peritot Chan -Peter -Peter Berg -Peter Gassner -Phanupong Janthapoon -Philip Oliver -PhosphorusP -Phyllis -Picsong -Pierre -Pierre Neter -Piotr Monwid-Olechnowicz -Piper Chester -PisecesPeng -Pixy Yuan -PlayerWho -Pob Ch -Pooya Parsa -Primlx -Pubudu Kodikara -Pyiner -Pyroboomka -QC-L -Qhan W -Qiaosen Huang -QingLance -Qingrong Ke -QoVoQ -Radomir Skrzepij -Rafael Carvalho -Rafael Cosman -Rafael Martins -Rahul Gurung -Rain120 -Rainey -Rainy -Rajil Bajracharya -Rallets -Ramsés Moreno -Ran Byron -Randy -Raphael Chauveau -Ray Booysen -Rayron Victor -Reed Sun -Regan Langford -Renny Ren -Renovate Bot -Rex -Rex Zeng -Ricardo Morais -Ricardo Raphael Joson -Richard D. Worth -Rick Zhou -Ritesh Makan -Riyad Elberkawy -Robert Wilkinson -Robin Pokorny -Rodrigo Ehlers -Rohan Bagchi -Rohan Malhotra -Roman Soroka -Ron Šmeral -Rongjian Zhang -Rrrandom -RunningCoderLee -Ryan Lee -RyanHui -Régis Foucault -SHEN Lin -Saeed Rahimi -Sagar Jain -Sagie501 -Sakari Pesonen -Sakol Assawasagool -Salavat Gizatov -Sam Chen -Sam Kah Chiin -Sam Lanning -Sam Marks -Sam Maxwell -Samed Düzçay -Sami Mäkinen -Samuel Gaus -Sanghyeon Lee -Sangle -Sanjay Kumar -Sanonz -Scott Goci -Scott Sturgeon -Sean Lin -Sean Willis -Seba Kerckhof -Sebastian Blade -Sebastian Busch -Semro -Sepush -Sergey Kachanovskiy -Sergey Levkovich -Sergey Volynkin -Sergio Crisostomo -Sevak -Shanjie Chen -Shawn Sit -Shengnan -Sheralijon -ShiTengFei -ShuYu Wang -Shubham Kanodia -Shun -Shuvalov Anton -SimaQ -Simo Aleksandrov -Simon -Simon Altschuler -Simon Knott -Simón Posada Fishman -Siou -Sivaraj -SkyAo -Skylar艺璇 -Snyk bot -Songhn -Sonjeet Paul -Sonu Sharma -SoraYama -South -Spencer -Stanley Thijssen -Star -Starpuccino -Stef Schenkelaars -Stephen Esser -Stevche Radevski -Steven.zhong -Subroto -Suki小火车 -Sukka -Sumit Vekariya -Sunny Luo -Sven Efftinge -Svyatoslav -SyMind -Sylvain Boulade -SylvanasGone -TTC -TangLL -Tanmoy Bhowmik -Tannmay S Gupta -Tao -Tao Zhang -Taucher Christoph -Taylor Sabell -Ted Shin -Teng YANG -Tengjiao Cai -Terence -The 1975 -The Rock -Themi Tsiotas von Pfaler -Theo Satloff -Thibault Derousseaux -Thiebaud Thomas -Thomas -Thomas Ladd -Thomas Zipner -Tino D -Tmk -Tom Gao -Tom Xu -TomIsion -Tomás Francisco -Tomáš Hylský -Tomáš Szabo -Trotyl Yu -Troy Li -Troy Thompson -TsesamLi -Ty Mick -Tyler -Ubaldo Quintana -Uladzimir Atroshchanka -Umberto Gariggio -Vadim Macagon -Valentin Vichnal -Van Nguyen -Varun Dey -Varun Sharma -Vemund Santi -Vic -Victor -Victor Repkow -Vijay Thirugnanam -Vincent Zhang -Vineet Srivastav -Viorel Cojocaru -Vishal Jagtap -Vitaliy Mazurenko -Vitaly Budovski -ViviaRui -Vlad Vovk -Vu Hoang Minh -Vyacheslav Kamenev -Walter Barbagallo -Wang Jun -Wang Riwu -Wang Zhengchen -Wang yb -Warren Seymour -Webber Takken -Wei Zhu -Wenchao Hu -Wendell -Wenqi Chen -Wensheng Xu -Wesley -Will -Will Chen -Will Soares -William Bergeron-Drouin -William Cai -William Stein -WingGao -Winme -Wu Haotian -WuJiali -Wuxh -X-Jagger -XBTop1! -XIN HU -XTY -XiaoPi -Xiaoming -Xie Guanglei -Xinxing Li -Xinzhe Wang -Xiping.wang -Xu Zhiwei -XuMM_12 -Xudong Cai -Xudong Huang -Xuhao -Yaindrop -YanYuan -Yang Bin -Yanghc -Yangzhedi -Yanlin Jiang -Yanming Deng -Yann Normand -Yann Pringault -Yash Joshi -Yasin Uslu -Yevhen Hryhorevskyi -Yiming -Yogesh -Yu -Yu Mao -YuChao Liang -YuTao -Yuan -Yuhang Liu -Yuiai01 -Yuji Ueki -Yuki Zhang -Yulia Maximova -Yunfly -Yunhwan Logan Na -Yunus EŞ -Yunwoo Ji -Yuri Pirola -Yurii Brusentsov -Yury Kozyrev -Yusuke Ito -Yuwei Ba -Yuxuan Huo -Yuyao Nie -YuyingWu -Yvan Zhu -ZH-seven -ZHANGYU -ZN1996 -ZYSzys -Zach Bird -Zack Amiton -Zack Craig -Zap -ZeroToOne -Zester Quinn Albano -Zhang Zhi -Zhanghao -Zheeeng -ZhiHao Li -Zhiqiang Gong -Zhongjan -Zhou Fang -ZhouZhen -Zhuo Chen -ZhuoYang Wu(阿离) -Ziluo -ZivHe -Zohaib Ijaz -Zzzen -_XiaoTian -aLIEzsss4 -aaarichter -aashutoshrathi -acfasj -adam -afc163 -agarciaguillo -agent-z -aghArdeshir -ahalimkara -ajuner -alekslario -alex89lj -alexchen -amedora -aoxiang78 -appleshell -arange -arifemrecelik -arturpfb -ascodelife -ascoders -ashishg-qburst -atomoo -atzcl -bLue -babycannotsay -baidumap -bang -baozefeng -bcd337 -benben -bigbigbo -binyellow -blankzust -bluelovers -bobo -bqy_fe -btea -bukas -byuanama -byzyk -bzone -caoyi -capdiem -carrie-tanminyi -cathayandy -cc189 -chaofeis -chchen -cheapCoder -chen wen jun -chen-jingjie -chencheng (云谦) -chenlei -chenlong -chensw -chenxiang -chenxiaochun -chequerNoel -chisus -chunlea -cieldon32 -cjahv -cjmafei -cl1107 -clean99 -clinyong -cnjs -codesign -cooljser -corneyl -csr632 -daczczcz1 -dainli -damon.chen -david.lv -davidhatten -ddcat1115 -decade -delesseps -denzw -dependabot[bot] -desperado -detailyang -devqin -dian.li -digz6666 -dingkang -djorkaeff -dolfje -dongfang -douxc -dpyzo0o -dujun -duzliang -edc-hui -edgji -eidonjoe -elios -elrrrrrrr -eruca -ezpub -fairyland -feeng -feng zhi hao -fengmk2 -fish yu -fkysly -flashback313 -flyerH -frezc -gaokaifeis -gaoryrt -gaozhenqian -genie -gepd -godfather -gregahren -gxvv -gyh9457 -gzq -haianweifeng -haimrait -haipeng -handy -hank -hanpei -hansnow -haoxin -hardfist -hatanon -hauwa123 -hebingchang -hehe -hello-chinese -helloqian12138 -henryv0 -hi-caicai -hicrystal -hms181231 -hongxuWei -howard -huangyan.py -hugorezende -huishiyi -hustcc -huzzbuzz -hydraZty -i3web -iamcastelli -iamkun -ibrahim velinov -imosapatryk -int2d -iojichervo -iola1999 -ioldfish -iorikingdom -isaced -isakol -itibbers -iugo -j3l11234 -jasonslyvia -jasonxia23 -jeessy2 -jiajiangxu -jiang -jiang.an -jiang.he -jieniu$ -jinouwuque -jinrui -jinyaqiao1102 -jojoLockLock -joson -jueinin -junjing.zhang -kacjay -kaifei -kailunyao -kalykun -kang -kanweiwei -kaoding -karasu -kasinooya -kavin -kayw -kdenz -kdepp -keng -kenve -kermolaev -kily zhou -kiner-tang(文辉) -klouskingsley -ko -konakona -kossel -kristof0425 -kuang -kun sam -lalalazero -lamvananh -leadream -lehug -leijingdao -lewis liu -lexlexa -lgmcolin -lhx -lhyt -liangfei -lich-yoo -liekkas -lihao -lihqi -lijianan -lilun -limingxin -linqiqi077 -linxianxi -lisenenkov -littleLane -littledian -liuchuzhang -liuycy -lixiaochou077 -lixiaoyang1992 -liyuanqiu -liyunhe -lizhen -llwslc -loganpowell -losgif -lushevol -luyiming -lvren -lxnxbnq -lyhper -lyn -lyon.han -mArker -maks -maomao -maximest-pierre -melchior voidwolf -memoryza -mgrdevport -mingyan.yu -miracles1919 -mjfwebb -mkermani144 -mmmveggies -mofelee -moonrailgun -morning-star -mraiguo -mumiao -mushan0x0 -muxin -muzuiget -natergj -netcon -ngolin -nick-ChenZe -niko -nitinknolder -nnecec -nuintun -oldchicken -paleface001 -parabolazz -paranoidjk -parlop -paul -pbrink231 -peiming -pengtikui -pfsu -picodoth -pinggod -pizn -plainnany -popomore -prettyboyweiwei -puxiao -qi gao -qianbin -qiaojie -qiqiboy -qliu -qqabcv520 -qramilq -qubaoming -ravirambles -realEago -rendaoer -renzhao1113 -richardison -roottool -ryangun -ryanhoho -ryannz -sadmark -sallen450 -samir elsharkawy -sdli -seognil LC -serializedowen -sfturing -shangyuan.ning -shawtung -shelwin -shlice -shmilyKang -shouyong -simplejason -siyu77 -slientcloud -sliwey -snadn -snail -snowingfox -soeyi -sojournerc -soso -sosohime -spideeee -sribich -stefango -stevenyuysy -stickmy -susiwen8 -swindme -syssam -tae -tangjinzhou -tangzixuan -taoweicn -tdida -thegatheringstorm -thilo-behnke -tianli.zhao -tom -toshi1127 -twobin -ty888 -u3u -ubuntugod -uchanlee -undefined -unknown -ustccjw -vaakian X -vagusx -valleykid -vaytsel -veveue -vgeyi -vldh -vouis -wa-ri -wadezhan -wan wan -wangao -wangshantao -wangshuai -wangtao0101 -wangxiaolei -wangxing -wangxingkang -wangxueliang -wanli -warmhug -weited -wendellhu -wenhong -whinc -whtang906 -whwangms -willc001 -wizawu -wleven -wonyun -woodsand -wwwxy -wx1322 -xiaofan2406 -xiaofine1122 -xiaohuoni -xiaosong -xiaoxintang -xiejiahe -xilihuasi -xinhui.zxh -xliez -xrkffgg -xuqiang -xyb -xz -y-take -yanguoyu -yangwukang -yangxiaolin -yanm1ng -yaoweiprc -ycjcl868 -ye4241 -yehq -yeliex -yeshan333 -yibu.wang -yifanwww -yiminanci -yiminghe -yingxirz -yiwwhl -youmoo -youngz -yuche -yuezk -yui -yykoypj -z -zack -zahgboat -zefeng -zelongc -zerob4wl -zhangchen -zhangguanyu02 -zhangj -zhangpc -zhangyangxue -zhangyanling77 -zhangzh -zhao-huo-long -zhaocai -zhaopeidong -zhenfan.yu -zhengjitf -zhuguibiao -zhujun24 -zhyupe -zilong -zinkey -zj9495 -zkwolf -zlljqn -zollero -zongzi531 -zoomdong -zqran -ztplz -zty -zuiidea -zx6658 -zxyao -zytjs -zz -°))))彡 -Ömer Faruk APLAK -Ștefan Filip -रोहन मल्होत्रा -一喵呜 -丁文涛 -不吃猫的鱼 -丶尘殇 -乔奕轩 -九思⚡⚡⚡ -二哲 -二手掉包工程师 -二货爱吃白萝卜 -云剪者 -付引 -何乐 -何志勇 -何锦余 -佛门耶稣 -信鑫-King -元凛 -兼续 -冷方冰 -刘红 -初心Yearth -南北 -南小北 -只捱宅 -可乐 -吕立青 -吴泽康 -啸生 -大猫 -子瞻 Luci -宝码 -小哈husky -小菜 -小镇靓仔 -小鹅鹅鹅 -尾宿君 -山客 -崔宏森 -左耳咚 -广彬-梁 -庄天翼 -廖应龙 -廖星 -张仕传 -张大大 -张威 -张秀玲 -徐坤龙 -徐新航 -愚道 -曾凯 -期贤 -未觉雨声 -朮厃 -李瀚 -李环冀 -杨兴洲 -杨哲迪 -杨小事er -松子 -林煌东 -柚子男 -沐霖 -炒米粉 -烽宁 -爱but的苍蝇 -王小王 -王林涛 -王浩 -王集鹄 -琚致远 -白羊座小葛 -白飞飞 -砖家 -社长长 -章鱼怪 -竹尔 -米老朱 -精武陈真 -红果汁 -约修亚 -翁润雨 -臧甲彬 fadeaway -舜岳 -苏秦 -英布 -菠萝吹雪 -萧琚 -董天成 -蒋璇 -蔡伦 -薛定谔的猫 -藤原托漆 -蘑菇 -行冥 -诸岳 -诸葛龙 -谭真 -超能刚哥 -迷渡 -那里好脏不可以 -郑国庆 -郑旭 -野迂迂 -闲耘™ -陆离 -陈帅 -陈广亮 -陈立林 -隋鑫磊 -雷玮杰 -马斯特 -马金花儿 -骆也 -骗你是小猫咪 -高力 -鬼厉 -麦谷 -黄俊亮 -黄文鉴 -黄斌 -黑雨 -龙风 -龚方闻 \ No newline at end of file diff --git a/CHANGELOG.en-US.md b/CHANGELOG.en-US.md index dc13f5c553a7..a351bbdba82f 100644 --- a/CHANGELOG.en-US.md +++ b/CHANGELOG.en-US.md @@ -16,6 +16,196 @@ tag: vVERSION --- +## 5.10.0 + +`2023-10-10` + +- 🔥 New component Flex, used to set flexible layout. [#44362](https://github.com/ant-design/ant-design/pull/44362) +- 🔥 Notification component supports `stack` configuration. By default, more than three notifications will be stacked. [#44618](https://github.com/ant-design/ant-design/pull/44618) +- 🔥 Update the active styles of Input, InputNumber, Select, Cascader, TreeSelect, DatePicker, and ColorPicker. [#45009](https://github.com/ant-design/ant-design/pull/45009) +- 🆕 Watermark supports setting the text alignment direction through `textAlign`. [#44888](https://github.com/ant-design/ant-design/pull/44888) [@Yuiai01](https://github.com/Yuiai01) +- 🆕 Slider supports any number of nodes and migrates xxxStyles to semantic `styles` and `classNames` properties. [#45000](https://github.com/ant-design/ant-design/pull/45000) +- 🆕 Cascader supports the Cascader.Panel component for inline use. [#45089](https://github.com/ant-design/ant-design/pull/45089) +- 🆕 Tooltip adds `fresh` attribute to support scenarios where content still needs to be updated when closed. [#45020](https://github.com/ant-design/ant-design/pull/45020) +- 🆕 Drawer supports customizing the `className` of built-in modules through `classNames`. [#44935](https://github.com/ant-design/ant-design/pull/44935) +- 🆕 ConfigProvider supports the `warning` attribute to configure warning levels (e.g. filter out deprecated API warnings). [#44809](https://github.com/ant-design/ant-design/pull/44809) +- Modal + - 🆕 Modal supports customizing the `className` of built-in modules through `classNames`. [#44934](https://github.com/ant-design/ant-design/pull/44934) + - 🐞 Fixed the content overflow problem when Modal.confirm `description` is a long text. [#45212](https://github.com/ant-design/ant-design/pull/45212) +- 🐞 Fix the problem that the nested Typography of Menu.Item cannot be vertically centered when `ellipsis` is true. [#41146](https://github.com/ant-design/ant-design/pull/41146) [@Yuiai01](https://github.com/Yuiai01) +- 🐞 Fix Select internal input not being able to apply fontFamily. [#45197](https://github.com/ant-design/ant-design/pull/45197) [@Yuiai01](https://github.com/Yuiai01) +- 🐞 Fix InputNumber border issue when using `addonBefore` in Space.Compact. [#45004](https://github.com/ant-design/ant-design/pull/45004) [@Yuiai01](https://github.com/Yuiai01) +- 🐞 Fix the problem that Tag.CheckableTag does not support ref. [#45164](https://github.com/ant-design/ant-design/pull/45164) [@mingming-ma](https://github.com/mingming-ma) +- 🐞 Fixed the issue where the font in the Avatar.Group component does not support responsiveness. [#34722](https://github.com/ant-design/ant-design/pull/34722) [@laishiwen](https://github.com/laishiwen) +- 🛠 Refactor Affix into a functional component. [#42674](https://github.com/ant-design/ant-design/pull/42674) +- 🛠 The Popover component deprecates the `minWidth` component token and adds `titleMinWidth` as a replacement. [#44750](https://github.com/ant-design/ant-design/pull/44750) +- 🌈 Token + - 🆕 Input adds `hoverBg` `activeBg` token to set the input box hover and activation background color. [#44752](https://github.com/ant-design/ant-design/pull/44752) [@Pan-yongyong](https://github.com/Pan-yongyong) + - 🆕 Descriptions Added `titleColor` and `contentColor` to set the title color and content area text color. [#44729](https://github.com/ant-design/ant-design/pull/44729) [@Child-qjj](https://github.com/Child-qjj) + - 🐞 Fixed the issue where the Input component Token `addonBg` is invalid. [#45222](https://github.com/ant-design/ant-design/pull/45222) +- TypeScript + - 🤖 The ArgsProps type for exported Notification is NotificationArgsProps. [#45147](https://github.com/ant-design/ant-design/pull/45147) +- 🌐 Locales + - 🇵🇱 Added Tour locales for pl_PL. [#45166](https://github.com/ant-design/ant-design/pull/45166) [@antonisierakowski](https://github.com/antonisierakowski) + - 🇰🇷 Optimize ko_KR locales. [#45150](https://github.com/ant-design/ant-design/pull/45150) [@owjs3901](https://github.com/owjs3901) + +## 5.9.4 + +`2023-09-28` + +- Button + - 🐞 Fix Button that two Chinese characters in nested span should have space between. [#45126](https://github.com/ant-design/ant-design/pull/45126) [@MadCcc](https://github.com/MadCcc) + - 🐞 Fix Button unexpected loading icon when conditional rendering. [#45030](https://github.com/ant-design/ant-design/pull/45030) [@lzl0304](https://github.com/lzl0304) +- 🐞 Fix Tour that `step.type` didn't work when shown at first time. [#45086](https://github.com/ant-design/ant-design/pull/45086) [@MadCcc](https://github.com/MadCcc) +- 🐞 Fix Select and DatePicker that input should use `fontFamily` token. [#45088](https://github.com/ant-design/ant-design/pull/45088) [@MadCcc](https://github.com/MadCcc) + +## 5.9.3 + +`2023-09-25` + +- 🔥 Tooltip delete the logic of wrap `span` on `disabled` element. It can always work as expect on disabled element now. [#44895](https://github.com/ant-design/ant-design/pull/44895) [@Yuiai01](https://github.com/Yuiai01) +- 🐞 Fix Popover that should shift automaticly when overflowed. [#45015](https://github.com/ant-design/ant-design/pull/45015) [@MadCcc](https://github.com/MadCcc) +- 🐞 Fix Tooltip / Popover position jump when content height changed. [#44976](https://github.com/ant-design/ant-design/pull/44976) +- 🛠 ComponentToken remove `radiusBase` must less than `16` limitation. [#44980](https://github.com/ant-design/ant-design/pull/44980) +- 🐞 Fix Dropdown can not give `ref` for the root children rendered by `dropdownRender`. [#44971](https://github.com/ant-design/ant-design/pull/44971) +- 🐞 Fix Table `cellPaddingBlock` not working. [#45040](https://github.com/ant-design/ant-design/pull/45040) +- 🐞 Fix Input wrong height with small `controlHeight`. [#45048](https://github.com/ant-design/ant-design/pull/45048) +- 🐞 Fix Typography style issue when `fontSize` is odd. [#45031](https://github.com/ant-design/ant-design/pull/45031) +- TypeScript + - 🤖 MISC: Fix `@types/react@18.2.22` React.Key type errors. [#44938](https://github.com/ant-design/ant-design/pull/44938) + +## 5.9.2 + +`2023-09-19` + +- 🐞 Fix Table selection column not align in center when `size` is `small`. [#44922](https://github.com/ant-design/ant-design/pull/44922) +- 🐞 Fix Select style problem when `label` contains `div` element. [#44927](https://github.com/ant-design/ant-design/pull/44927) +- 🐞 Fix Modal broken style of buttons when custom `footer`. [#44929](https://github.com/ant-design/ant-design/pull/44929) [@Wxh16144](https://github.com/Wxh16144) +- 🐞 Fix notification wrong pop-up animation when `placement` is `bottom`. [#44918](https://github.com/ant-design/ant-design/pull/44918) [@linxianxi](https://github.com/linxianxi) +- 🐞 Fix missing inherited feedbackIcon in Form.Item with `noStyle`. [#44937](https://github.com/ant-design/ant-design/pull/44937) + +## 5.9.1 + +`2023-09-15` + +- 🐞 Fix Select that `controlHeightSM` not work in small size. [#44859](https://github.com/ant-design/ant-design/pull/44859) [@MadCcc](https://github.com/MadCcc) +- 🐞 Fix Rate that star transaform not at center. [#44855](https://github.com/ant-design/ant-design/pull/44855) [@MadCcc](https://github.com/MadCcc) +- 🐞 Fix DatePicker that in `dateTime` mode switching input didn't trigger `onCalendarChange`. [#44845](https://github.com/ant-design/ant-design/pull/44845) [@Yuiai01](https://github.com/Yuiai01) +- 🐞 Fix Table `virtual` selection checkbox or radio not align in center. [#44786](https://github.com/ant-design/ant-design/pull/44786) +- 🐞 Fix Select carbin align top bug when enable `maxTagCount`. [#44757](https://github.com/ant-design/ant-design/pull/44757) +- 🐞 Fix Select alignment issue when label is Typography. [#44756](https://github.com/ant-design/ant-design/pull/44756) +- 💄 Fix Table with `virtual` display issue about columns less than table size and some border & hover style missing. [#44818](https://github.com/ant-design/ant-design/pull/44818) +- 💄 Fix wrong style of Select in Input `addon`. [#44825](https://github.com/ant-design/ant-design/pull/44825) [@MadCcc](https://github.com/MadCcc) +- 💄 Fix Tree that Checkbox should be aligned with first line. [#44827](https://github.com/ant-design/ant-design/pull/44827) [@MadCcc](https://github.com/MadCcc) +- 💄 Fix Card that Card.Grid has wrong style with left bottom corner. [#44801](https://github.com/ant-design/ant-design/pull/44801) [@Jason-huang66](https://github.com/Jason-huang66) +- 💄 Fix Select/Cascader/TreeSelect style issue when customize their height. [#44753](https://github.com/ant-design/ant-design/pull/44753) +- TypeScript + - 🤖 Optimize `ref` type of Radio.Button. [#44747](https://github.com/ant-design/ant-design/pull/44747) [@LexiosAlex](https://github.com/LexiosAlex) + - 🤖 Optimize `ref` type of Checkbox. [#44746](https://github.com/ant-design/ant-design/pull/44746) [@LexiosAlex](https://github.com/LexiosAlex) + +## 5.9.0 + +`2023-09-08` + +- 🔥 Table component now supports the `virtual` attribute to enable virtual scrolling. [#44349](https://github.com/ant-design/ant-design/pull/44349) +- 🔥 Form's `validateFields` now supports `recursive` to validate all fields with nested paths. [#44130](https://github.com/ant-design/ant-design/pull/44130) +- 🔥 Form.Item now supports `validateDebounce` to configure validation debounce. [#44633](https://github.com/ant-design/ant-design/pull/44633) +- 🆕 Button component has added three component tokens: `contentFontSize`, `contentFontSizeSM`, and `contentFontSizeLG`, allowing customization of font sizes for different sizes. [#44257](https://github.com/ant-design/ant-design/pull/44257) +- 🆕 Form's `requiredMark` now supports custom rendering. [#44073](https://github.com/ant-design/ant-design/pull/44073) +- 🆕 Tabs component has added a new component token `itemColor` to control the text color of normal tabs. [#44201](https://github.com/ant-design/ant-design/pull/44201) +- 🆕 ColorPicker now supports `defaultFormat`. [#44487](https://github.com/ant-design/ant-design/pull/44487) [@CYBYOB](https://github.com/CYBYOB) +- 🆕 Form supports `feedbackIcons` and Form.Item supports `hasFeedback={{ icons: ... }}`, now feedback icons could be customized in both ways. [#43894](https://github.com/ant-design/ant-design/pull/43894) [@gldio](https://github.com/gldio) +- 🆕 Added the `itemSelectedColor` component token to the Segmented component. [#44570](https://github.com/ant-design/ant-design/pull/44570) [@xiaozisong](https://github.com/xiaozisong) +- 🆕 Added support for custom function rendering in the Modal footer. [#44318](https://github.com/ant-design/ant-design/pull/44318) [@RedJue](https://github.com/RedJue) +- 🆕 Added responsive setting support for `items.span` in Descriptions. [#44534](https://github.com/ant-design/ant-design/pull/44534) +- 🆕 Added support for global configuration of `indicatorSize` in Tabs component through ConfigProvider. [#44517](https://github.com/ant-design/ant-design/pull/44517) +- 🆕 Added the `direction` parameter to the `filterOption` function in the Transfer component. [#44417](https://github.com/ant-design/ant-design/pull/44417) [@Zian502](https://github.com/Zian502) +- 🆕 Added support for the `source` parameter in the `onSearch` method of the Input.Search component. [#44457](https://github.com/ant-design/ant-design/pull/44457) [@kiner-tang](https://github.com/kiner-tang) +- 🆕 Added a component token to the Input component for customizing the shadow when activated. [#44410](https://github.com/ant-design/ant-design/pull/44410) +- 🆕 Added a component token to the Radio component for customizing the color when the fill button is selected. [#44389](https://github.com/ant-design/ant-design/pull/44389) +- 🆕 Tour component now supports horizontal offset for spacing. [#44377](https://github.com/ant-design/ant-design/pull/44377) [@RedJue](https://github.com/RedJue) +- 🆕 Tour component now supports customizing the close button using the `closeIcon` prop. [#44312](https://github.com/ant-design/ant-design/pull/44312) [@kiner-tang](https://github.com/kiner-tang) +- 🆕 Avatar component now supports configuring size using ConfigProvider. [#44288](https://github.com/ant-design/ant-design/pull/44288) [@li-jia-nan](https://github.com/li-jia-nan) +- 🆕 List component now supports configuring size using ConfigProvider's `componentSize` option. [#44267](https://github.com/ant-design/ant-design/pull/44267) [@Yuiai01](https://github.com/Yuiai01) +- 🆕 Cascader component now supports `autoClearSearchValue` option. [#44033](https://github.com/ant-design/ant-design/pull/44033) [@linxianxi](https://github.com/linxianxi) +- 🆕 Added support for `rootClassName` in [Upload](https://github.com/ant-design/ant-design/pull/44060),[AutoComplete](https://github.com/ant-design/ant-design/pull/44055),[Badge.Ribbon](https://github.com/ant-design/ant-design/pull/44056),[Input.TextArea](https://github.com/ant-design/ant-design/pull/44058),[RangePicker](https://github.com/ant-design/ant-design/pull/44057),[TimePicker](https://github.com/ant-design/ant-design/pull/44059) [@kiner-tang](https://github.com/kiner-tang). +- 💄 Refactored the structure of Modal.confirm to fix the width abnormality caused by `width: fit-content` and the style line break issue with a large amount of text. Extracted confirm styles for lazy loading to optimize style size in SSR. [#44557](https://github.com/ant-design/ant-design/pull/44557) +- 💄 Adjusted the linear gradient colors for `circle` and `dashboard` in Progress to conical gradients. [#44404](https://github.com/ant-design/ant-design/pull/44404) +- 💄 Fixed DatePicker missing custom footer style. [#44642](https://github.com/ant-design/ant-design/pull/44642) [@li-jia-nan](https://github.com/li-jia-nan) +- 💄 Fixed Tag where `tag.className` and `tag.style` did not work on Tag.CheckableTag in ConfigProvider. [#44602](https://github.com/ant-design/ant-design/pull/44602) +- 💄 Fixed the inconsistency in width between the dropdown and the input box when the container of Select component has `transform: scale` style configured in `getPopupContainer` option. [#44378](https://github.com/ant-design/ant-design/pull/44378) +- 🐞 Fixed an issue where Form.Item with `noStyle` configuration prevented the bound element from consuming `useStatus`. [#44576](https://github.com/ant-design/ant-design/pull/44576) +- 🐞 Fixed an issue where using Tag within Popover/Popconfirm caused incorrect `font-size` on hover. [#44663](https://github.com/ant-design/ant-design/pull/44663) +- 🐞 Fixed an issue where Input's default button had extra shadow. [#44660](https://github.com/ant-design/ant-design/pull/44660) [@daledelv](https://github.com/daledelv) +- 🐞 Fixed an issue where using Modal's hooks to close it with the `esc` key didn't correctly trigger the `await`. [#44646](https://github.com/ant-design/ant-design/pull/44646) +- 🐞 Fixed the issue where the preset `size` of Space did not follow the Design Token, now compact mode correctly handles the corresponding spacing values. [#44598](https://github.com/ant-design/ant-design/pull/44598) [@li-jia-nan](https://github.com/li-jia-nan) +- 🐞 Fixed the issue in Upload where the download button would still be displayed after clicking on it and moving the mouse out of the file. [#44594](https://github.com/ant-design/ant-design/pull/44594) [@zbw-zbw](https://github.com/zbw-zbw) +- 🐞 Fix FloatButton that margin not work with `href` in FloatButton.Group. [#44707](https://github.com/ant-design/ant-design/pull/44707) [@Yuiai01](https://github.com/Yuiai01) +- 🐞 Fixed the issue where `fontSizeSM` token was not being applied to Button component. [#44217](https://github.com/ant-design/ant-design/pull/44217) [@CHENGTIANG](https://github.com/CHENGTIANG) +- 🐞 The Watermark now works in nested Modal and Drawer components. [#44104](https://github.com/ant-design/ant-design/pull/44104) +- 🛠 Alert, Tree, Cascader, Layout, Table, Modal, Drawer, Button, Switch, Select, Badge, Form, TimePicker, Spin, Input, Progress, Divider Added Component Token. [#42142](https://github.com/ant-design/ant-design/pull/42142) [#42607](https://github.com/ant-design/ant-design/pull/42607) [#42627](https://github.com/ant-design/ant-design/pull/42627) [#42757](https://github.com/ant-design/ant-design/pull/42757) [#42774](https://github.com/ant-design/ant-design/pull/42774) [#42778](https://github.com/ant-design/ant-design/pull/42778) [#44090](https://github.com/ant-design/ant-design/pull/44090) [#44118](https://github.com/ant-design/ant-design/pull/44118) [#44174](https://github.com/ant-design/ant-design/pull/44174) [#44228](https://github.com/ant-design/ant-design/pull/44228) [#44261](https://github.com/ant-design/ant-design/pull/44261) [#44282](https://github.com/ant-design/ant-design/pull/44282) [#44334](https://github.com/ant-design/ant-design/pull/44334) [#42192](https://github.com/ant-design/ant-design/pull/42192) [@hms181231](https://github.com/hms181231) [@linhf123](https://github.com/linhf123) [@poyiding](https://github.com/poyiding) [@Wxh16144](https://github.com/Wxh16144) [@Yuiai01](https://github.com/Yuiai01) +- 🛠 Remove compatibility logic for old versions of IE browser for Space and Grid components to reduce bundle size. [#44620](https://github.com/ant-design/ant-design/pull/44620) [@li-jia-nan](https://github.com/li-jia-nan) +- TypeScript + - 🤖 Export BasicDataNode type from the Tree. [#44624](https://github.com/ant-design/ant-design/pull/44624) [@kiner-tang](https://github.com/kiner-tang) + +## 5.8.6 + +`2023-09-02` + +- 🛠 Optimize some styles size in document.head by extracting unused styles. + - 🛠 Notification and Message only generate styles when displayed. [#44488](https://github.com/ant-design/ant-design/pull/44488) + - 🛠 Extract Tag status & preset color style which will only generate by needed. [#44512](https://github.com/ant-design/ant-design/pull/44512) + - 🛠 Extract Button compact style, now only the corresponding style will be generated when Space.Compact is used. [#44475](https://github.com/ant-design/ant-design/pull/44475) +- 📦 Remove `lodash/camelCase` from `@ant-design/icons` dependencies to reduce bundle size. [ant-design-icons#595](https://github.com/ant-design/ant-design-icons/pull/595) +- Form + - 🐞 Fix Form.Item children not hidden when `wrapperCol.span` is `0`. [#44485](https://github.com/ant-design/ant-design/pull/44485) [#44472](https://github.com/ant-design/ant-design/pull/44472) [@crazyair](https://github.com/crazyair) + - 🐞 Fix Form `wrapperCol` to be 24 not working when `labelCol` is set to 24. [#44541](https://github.com/ant-design/ant-design/pull/44541) +- 🐞 Fix Watermark that would crash if `content` is empty string. [#44501](https://github.com/ant-design/ant-design/pull/44501) +- 🐞 Fix ColorPicker popup still working when `disabled` is `true`. [#44466](https://github.com/ant-design/ant-design/pull/44466) [@RedJue](https://github.com/RedJue) +- 🐞 Fix Transfer trigger `onSelectChange` twice sometimes when click checkbox. [#44471](https://github.com/ant-design/ant-design/pull/44471) [@kovsu](https://github.com/kovsu) +- 🐞 Fix Typography scrollbar flush problem when enable `ellipsis`. [#43058](https://github.com/ant-design/ant-design/pull/43058) [@bbb169](https://github.com/bbb169) +- Slider + - 🐞 Fix Slider draggable track unpredictable behavior. [#44503](https://github.com/ant-design/ant-design/pull/44503) [@BoyYangzai](https://github.com/BoyYangzai) [@yoyo837](https://github.com/yoyo837) + - ⌨️ Improve Slider a11y behavior by adding `aria-orientation`. [react-component/slider#859](https://github.com/react-component/slider/pull/859) [@5im0n](https://github.com/5im0n) +- 🐞 Fix Steps `type="nav"` last item did not hide arrow properly. [#44582](https://github.com/ant-design/ant-design/pull/44582) [@ohhoney1](https://github.com/ohhoney1) +- TypeScript + - 🤖 Fix Upload file `status` definition to remove unused success status. [#44468](https://github.com/ant-design/ant-design/pull/44468) + +## 5.8.5 + +`2023-08-28` + +- 🛠 Refactor Badge style logic and take Ribbon style out to reduce SSR inline style size. [#44451](https://github.com/ant-design/ant-design/pull/44451) +- 🐞 Fix the issue of abnormal icon styling when using `@ant-design/icons` within App. [#41208](https://github.com/ant-design/ant-design/pull/41208) [@Wxh16144](https://github.com/Wxh16144) +- 🐞 Fix the issue of vertical dragging malfunction in Carousel. [#44460](https://github.com/ant-design/ant-design/pull/44460) [@RedJue](https://github.com/RedJue) +- 🐞 Fix Tour panel use wrong design token. [#44428](https://github.com/ant-design/ant-design/pull/44428) +- 🐞 Fix Form `wrapperCol` with responsive `xs` config not working. [#44388](https://github.com/ant-design/ant-design/pull/44388) +- 🐞 Fix ColorPicker duplicate `key` issue. [#44370](https://github.com/ant-design/ant-design/pull/44370) [@xr0master](https://github.com/xr0master) +- 🐞 Fix Radio that not work in Tree title. [#44380](https://github.com/ant-design/ant-design/pull/44380) +- 🐞 Fix Table that would crash when `filterDropdown` does not support `ref`. [#44357](https://github.com/ant-design/ant-design/pull/44357) +- 🐞 Fix Form `inline` layout show extra bottom margin when validation failed. [#44360](https://github.com/ant-design/ant-design/pull/44360) +- 🐞 Fix DatePicker `showTime` working error when `format` is Array. [#44306](https://github.com/ant-design/ant-design/pull/44306) [@Zian502](https://github.com/Zian502) +- 🐞 Fix Watermark can not be fully shown when `content` is too long. [#44321](https://github.com/ant-design/ant-design/pull/44321) +- TypeScript + - 🤖 Fix the type error with align property in Dropdown component. [#44423](https://github.com/ant-design/ant-design/pull/44423) [@LeTuongKhanh](https://github.com/LeTuongKhanh) + +## 5.8.4 + +`2023-08-18` + +- ColorPicker + - 🐞 Fix the cursor jumps when entering lowercase English letters in the ColorPicker color value input box. [#44137](https://github.com/ant-design/ant-design/pull/44137) [@gouge666](https://github.com/gouge666) + - 🐞 Fix the ColorPicker style is deformed under different sizes. [#44273](https://github.com/ant-design/ant-design/pull/44273) [@kouchao](https://github.com/kouchao) +- 🐞 Fix Descriptions throwing `key is not a prop` error message. [#44278](https://github.com/ant-design/ant-design/pull/44278) [@RedJue](https://github.com/RedJue) +- 🐞 Fix the node is still rendered when Pagination `itemRender` is customized to `null`. [#44226](https://github.com/ant-design/ant-design/pull/44226) +- 🐞 Fix Modal in Dropdown `menu.items`, rapid mouse movement when expanding Modal will make Dropdown reopen. [#44204](https://github.com/ant-design/ant-design/pull/44204) +- DatePicker + - 💄 Fix DatePicker content is not centered. [#44245](https://github.com/ant-design/ant-design/pull/44245) [@Zian502](https://github.com/Zian502) + - 💄 Optimize DatePicker selection range style. [#44206](https://github.com/ant-design/ant-design/pull/44206) [@kiner-tang](https://github.com/kiner-tang) +- 💄 Fix clicking on the Tabs area on the mobile terminal triggers a color change. [#44200](https://github.com/ant-design/ant-design/pull/44200) [@yilaikesi](https://github.com/yilaikesi) +- RTL + - 💄 Fix the numbers in the Badge are also RTL when the text direction of the page is RTL. [#43998](https://github.com/ant-design/ant-design/pull/43998) [@NotEvenANeko](https://github.com/NotEvenANeko) + ## 5.8.3 `2023-08-11` @@ -28,14 +218,14 @@ tag: vVERSION - 💄 Fix Carousel `dots` extra margin style. [#44076](https://github.com/ant-design/ant-design/pull/44076) - 🐞 Fix Modal footer disabled state that affect by Form. [#43055](https://github.com/ant-design/ant-design/pull/43055) [@Wxh16144](https://github.com/Wxh16144) - 🐞 Fix Upload thumbnail that gif will not play. [#44083](https://github.com/ant-design/ant-design/pull/44083) [@linxianxi](https://github.com/linxianxi) -- 🐞 Fix FloatButton that menu mode didn't support `badge` prop. [#44109](https://github.com/ant-design/ant-design/pull/44109) [@MadCcc](https://github.com/MadCcc) +- 🐞 Fix FloatButton that menu mode didn't support `badge` prop. [#44109](https://github.com/ant-design/ant-design/pull/44109) - 🐞 Fix Grid & List responsive config take effect after first render which cause screen flick. [#44075](https://github.com/ant-design/ant-design/pull/44075) -- 🐞 Fix that Design Token partially missing when `@ant-design/cssinjs` version `1.15.0`. [#44091](https://github.com/ant-design/ant-design/pull/44091) [@MadCcc](https://github.com/MadCcc) +- 🐞 Fix that Design Token partially missing when `@ant-design/cssinjs` version `1.15.0`. [#44091](https://github.com/ant-design/ant-design/pull/44091) - 💄 Fix Badge `status="processing"` with `dot` wave style issue. [#44153](https://github.com/ant-design/ant-design/pull/44153) - 💄 Fix Descriptions border styles when it nests itself. [#43454](https://github.com/ant-design/ant-design/pull/43454) [@Yuiai01](https://github.com/Yuiai01) - 💄 Fix Pagination transition style in prev/next buttons. [#44030](https://github.com/ant-design/ant-design/pull/44030) - 💄 Fix Popconfirm button group wraps unexpectedly. [#44022](https://github.com/ant-design/ant-design/pull/44022) [@MuxinFeng](https://github.com/MuxinFeng) -- 💄 Optimize style of Image preview operation icons. [#44141](https://github.com/ant-design/ant-design/pull/44141) [@MadCcc](https://github.com/MadCcc) +- 💄 Optimize style of Image preview operation icons. [#44141](https://github.com/ant-design/ant-design/pull/44141) - 💄 Optimize Input and InputNumber font size in large mode. [#44000](https://github.com/ant-design/ant-design/pull/44000) [@MuxinFeng](https://github.com/MuxinFeng) - 💄 Remove Space part useless style. [#44098](https://github.com/ant-design/ant-design/pull/44098) @@ -46,7 +236,7 @@ tag: vVERSION - 🐞 Fix Checkbox & Radio not support customize wave and add className `ant-wave-target` for this case. [#44014](https://github.com/ant-design/ant-design/pull/44014) - 🐞 Adjust Form.Item renderProps definition to return correct `FormInstance`. [#43996](https://github.com/ant-design/ant-design/pull/43996) - 🐞 Fixed Table incorrect expand icon direction and row indentation in RTL. [#43977](https://github.com/ant-design/ant-design/pull/43977) [@Yuiai01](https://github.com/Yuiai01) -- 💄 Fix Pagination that should not have hover and focus style when disabled. [#43970](https://github.com/ant-design/ant-design/pull/43970) [@MadCcc](https://github.com/MadCcc) +- 💄 Fix Pagination that should not have hover and focus style when disabled. [#43970](https://github.com/ant-design/ant-design/pull/43970) - TypeScript - 🤖 Fix Drawer & Anchor part Design Token TS description not correct issue. [#43994](https://github.com/ant-design/ant-design/pull/43994) [@wving5](https://github.com/wving5) @@ -62,14 +252,14 @@ tag: vVERSION `2023-08-01` -- 🔥 Component Token support `algorithm` to calculate derivative tokens same as global. [#43810](https://github.com/ant-design/ant-design/pull/43810) [@MadCcc](https://github.com/MadCcc) +- 🔥 Component Token support `algorithm` to calculate derivative tokens same as global. [#43810](https://github.com/ant-design/ant-design/pull/43810) - 🔥 Modal hooks function support `await` call. [#43470](https://github.com/ant-design/ant-design/pull/43470) - 🔥 ConfigProvider support `wave` to customize wave effect. [#43784](https://github.com/ant-design/ant-design/pull/43784) - 🆕 Form support `getFieldsValue({ strict: true })` to support only Item bind values. [#43828](https://github.com/ant-design/ant-design/pull/43828) - 🆕 Descriptions support `items` prop. [#43483](https://github.com/ant-design/ant-design/pull/43483) [@RedJue](https://github.com/RedJue) - 🆕 ColorPicker support `disabledAlpha` prop. [#43355](https://github.com/ant-design/ant-design/pull/43355) [@RedJue](https://github.com/RedJue) - 🆕 Avatar.Group support `shape` prop. [#43817](https://github.com/ant-design/ant-design/pull/43817) [@li-jia-nan](https://github.com/li-jia-nan) -- 🆕 AutoComplete/Cascader/DatePicker/Input.Textarea/TimePicker/TreeSelect support `allowClear` prop to customize clear button。[#43582](https://github.com/ant-design/ant-design/discussions/43582) [@kiner-tang](https://github.com/kiner-tang) +- 🆕 AutoComplete/Cascader/DatePicker/Input.Textarea/TimePicker/TreeSelect support `allowClear` prop to customize clear button. [#43582](https://github.com/ant-design/ant-design/discussions/43582) [@kiner-tang](https://github.com/kiner-tang) - 🆕 DatePicker.RangePicker `presets` support callback functions. [#43476](https://github.com/ant-design/ant-design/pull/43476) [@Wxh16144](https://github.com/Wxh16144) - 🆕 Added the `preview={{ movable: Boolean }}` prop to the Image component to support dragging and dropping into folders. [#43823](https://github.com/ant-design/ant-design/pull/43823) [@linxianxi](https://github.com/linxianxi) - 🆕 Slider `tooltip` support `autoAdjustOverflow` prop. [#43788](https://github.com/ant-design/ant-design/pull/43788) @@ -106,11 +296,11 @@ tag: vVERSION `2023-07-20` -- 💄 Fix Menu miss hover style issue. [#43656](https://github.com/ant-design/ant-design/pull/43656) [@MadCcc](https://github.com/MadCcc) +- 💄 Fix Menu miss hover style issue. [#43656](https://github.com/ant-design/ant-design/pull/43656) - 🐞 Fix Notification throwPurePanel definition missing error. [#43687](https://github.com/ant-design/ant-design/pull/43687) [@li-jia-nan](https://github.com/li-jia-nan) - 🐞 Fix Button `onClick` missing `event` definition. [#43666](https://github.com/ant-design/ant-design/pull/43666) - 🐞 Fix Input and InputNumber align issue. [#43548](https://github.com/ant-design/ant-design/pull/43548) [@bbb169](https://github.com/bbb169) -- 🐞 Fix DatePicker suffix use wrong token. [#43646](https://github.com/ant-design/ant-design/pull/43646) [@MadCcc](https://github.com/MadCcc) +- 🐞 Fix DatePicker suffix use wrong token. [#43646](https://github.com/ant-design/ant-design/pull/43646) - 🐞 Fix Steps with clickable can not trigger by keyboard. [#43644](https://github.com/ant-design/ant-design/pull/43644) - TypeScript - 🤖 Remove Button type `ghost` from TS definition. [#43675](https://github.com/ant-design/ant-design/pull/43675) @@ -157,15 +347,15 @@ tag: vVERSION - 🛠 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) +- 🐞 Added warning for deprecated Token `colorItemBgSelected` in Menu. [#43461](https://github.com/ant-design/ant-design/pull/43461) - 🐞 MISC: 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 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 Input.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) +- 🐞 Fixed an issue where the height set for the Input.TextArea component would become invalid when the screen size changed. [#43169](https://github.com/ant-design/ant-design/pull/43169) - 💄 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) -- 💄 Design Token add `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) +- 💄 Design Token add `colorLink` to the seed token, and `colorLinkHover` and `colorLinkActive` will be calculated from colorLink. [#43183](https://github.com/ant-design/ant-design/pull/43183) - 💄 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) @@ -190,7 +380,7 @@ tag: vVERSION - 🐞 Fix the Badge `color` attribute does not take effect. [#43304](https://github.com/ant-design/ant-design/pull/43304) - 🐞 Fix the position of Select clear icon when FormItem sets `hasFeedback`. [#43302](https://github.com/ant-design/ant-design/pull/43302) [@tinyfind](https://github.com/tinyfind) - 🐞 Fix Transfer paging drop-down button is hidden and `showSizeChanger` method is invalid. [#41906](https://github.com/ant-design/ant-design/pull/41906) [@Yuiai01](https://github.com/Yuiai01) -- 🐞 Fix the invalid modification of `colorText` and `fontSize` of Popconfirm component. [#43212](https://github.com/ant-design/ant-design/pull/43212) [@MadCcc](https://github.com/MadCcc) +- 🐞 Fix the invalid modification of `colorText` and `fontSize` of Popconfirm component. [#43212](https://github.com/ant-design/ant-design/pull/43212) - 🐞 Fix the problem that deleting files after Upload configures `maxCount` will not trigger `onChange`. [#43193](https://github.com/ant-design/ant-design/pull/43193) - 💄 Fix Button disabled style error when it has `link` or `href` attribute. [#43091](https://github.com/ant-design/ant-design/pull/43091) [@BoyYangzai](https://github.com/BoyYangzai) - TypeScript @@ -252,7 +442,7 @@ tag: vVERSION - 🆕 ColorPicker add `onClear` and dont't close panel when clearing. [#42634](https://github.com/ant-design/ant-design/pull/42634) [@linxianxi](https://github.com/linxianxi) - 🆕 Collapse `items` to support configure panel content. [#42545](https://github.com/ant-design/ant-design/pull/42545) [@kiner-tang](https://github.com/kiner-tang) -- 🆕 Add static function `getDesignToken` to access full Design Token. [#42723](https://github.com/ant-design/ant-design/pull/42723) [@MadCcc](https://github.com/MadCcc) +- 🆕 Add static function `getDesignToken` to access full Design Token. [#42723](https://github.com/ant-design/ant-design/pull/42723) - 🆕 ConfigProvider support configure Space `classNames` and `styles` properties. [#42748](https://github.com/ant-design/ant-design/pull/42748) [@RedJue](https://github.com/RedJue) - 🆕 Space support `classNames` and `styles` properties. [#42743](https://github.com/ant-design/ant-design/pull/42743) [@RedJue](https://github.com/RedJue) - 🆕 Drawer panel support event listener. Wrapper support passing `data-*` props. [#42718](https://github.com/ant-design/ant-design/pull/42718) [@kiner-tang](https://github.com/kiner-tang) @@ -266,12 +456,12 @@ tag: vVERSION - 🆕 ConfigProvider.config support `theme` for static method config. [#42473](https://github.com/ant-design/ant-design/pull/42473) - 🆕 Calendar `onSelect` support `info.source` param to help get select source. [#42432](https://github.com/ant-design/ant-design/pull/42432) - 💄 Optimize ColorPicker style in dark theme. [#42827](https://github.com/ant-design/ant-design/pull/42827) [@RedJue](https://github.com/RedJue) -- 💄 Fix Popconfirm, Alert and Notification that `colorTextHeading` and `colorText` usage. [#42839](https://github.com/ant-design/ant-design/pull/42839) [@MadCcc](https://github.com/MadCcc) +- 💄 Fix Popconfirm, Alert and Notification that `colorTextHeading` and `colorText` usage. [#42839](https://github.com/ant-design/ant-design/pull/42839) - 💄 Fix Divider style problem. [#42797](https://github.com/ant-design/ant-design/pull/42797) [@kongmingLatern](https://github.com/kongmingLatern) - 🐞 Fix Image.PreviewGroup not reset image state when switch it. [#42793](https://github.com/ant-design/ant-design/pull/42793) [@linxianxi](https://github.com/linxianxi) - 🐞 Reduce bundle size by refactor via `rc-util/lib/pickAttrs`. Fix Rate `findDOMNode is deprecated` warning in StrictMode. [#42688](https://github.com/ant-design/ant-design/pull/42688) - 🐞 Rate could accept `id` `data-*` `aria-*` `role` `onMouseEnter` `onMouseLeave` attributes now, so that it can be wrapped by Tooltip component. [#42676](https://github.com/ant-design/ant-design/pull/42676) -- 🐞 Fix Menu.Submenu not aligned in horizontal mode. [#42648](https://github.com/ant-design/ant-design/pull/42648) [@MadCcc](https://github.com/MadCcc) +- 🐞 Fix Menu.Submenu not aligned in horizontal mode. [#42648](https://github.com/ant-design/ant-design/pull/42648) - 🐞 Align Card `tabList` API with Tab `items`. [#42413](https://github.com/ant-design/ant-design/pull/42413) - 🐞 Fix circular dependencies. - 🐞 Fix Modal circular dependency issue. [#42841](https://github.com/ant-design/ant-design/pull/42841) [@kiner-tang](https://github.com/kiner-tang) @@ -282,10 +472,10 @@ tag: vVERSION - ⌨️ Improve Progress accessibility by adding more `aria` props. [#42704](https://github.com/ant-design/ant-design/pull/42704) [@MehmetYararVX](https://github.com/MehmetYararVX) - ⌨️ Notification add role `props`. [#42484](https://github.com/ant-design/ant-design/pull/42484) [@guan404ming](https://github.com/guan404ming) - 🛠 Collapse use `onKeyDown` instead of `onKeyPress` to change collapse panel active state. [#42592](https://github.com/ant-design/ant-design/pull/42592) [@kiner-tang](https://github.com/kiner-tang) -- 🛠 Refactor Menu with `@rc-component/trigger`. Remove `rc-trigger` and reduce bundle size. [#42554](https://github.com/ant-design/ant-design/pull/42554) [@MadCcc](https://github.com/MadCcc) +- 🛠 Refactor Menu with `@rc-component/trigger`. Remove `rc-trigger` and reduce bundle size. [#42554](https://github.com/ant-design/ant-design/pull/42554) - 🛠 Table rename `sorterOrder` to `sortOrder` for arguement of `sortIcon`. [#42519](https://github.com/ant-design/ant-design/pull/42519) [@sawadyecma](https://github.com/sawadyecma) - Component Token Migration. For more info: [Migrate less variables](/docs/react/migrate-less-variables) - - 🛠 Rename Menu component token with new naming standard. [#42848](https://github.com/ant-design/ant-design/pull/42848) [@MadCcc](https://github.com/MadCcc) + - 🛠 Rename Menu component token with new naming standard. [#42848](https://github.com/ant-design/ant-design/pull/42848) - 🛠 Migrate Radio less variables. [#42050](https://github.com/ant-design/ant-design/pull/42050) [@Yuiai01](https://github.com/Yuiai01) - 🛠 Migrate Image less variables. [#42048](https://github.com/ant-design/ant-design/pull/42048) [@guan404ming](https://github.com/guan404ming) - 🛠 Migrate Tooltip less variables. [#42046](https://github.com/ant-design/ant-design/pull/42046) [@guan404ming](https://github.com/guan404ming) @@ -317,19 +507,19 @@ tag: vVERSION `2023-05-30` - 🐞 Fix ColorPicker hover boundary issue. [#42669](https://github.com/ant-design/ant-design/pull/42669) [@RedJue](https://github.com/RedJue) -- 🐞 Fix Menu that `overflowedIndicatorClassName` should not override origin classes. [#42692](https://github.com/ant-design/ant-design/pull/42692) [@MadCcc](https://github.com/MadCcc) +- 🐞 Fix Menu that `overflowedIndicatorClassName` should not override origin classes. [#42692](https://github.com/ant-design/ant-design/pull/42692) - 🐞 Fix Select that in some cases will display the letter `A`. [#42651](https://github.com/ant-design/ant-design/pull/42651) [@895433995](https://github.com/895433995) - 🐞 Fix Card when `cover` is set to Image, hover mask does not have rounded corner attribute, resulting in UI exception. [#42642](https://github.com/ant-design/ant-design/pull/42642) [@iNeedToCopy](https://github.com/iNeedToCopy) -- 🐞 Fix Checkbox align with label. [#42590](https://github.com/ant-design/ant-design/pull/42590) [@MadCcc](https://github.com/MadCcc) +- 🐞 Fix Checkbox align with label. [#42590](https://github.com/ant-design/ant-design/pull/42590) - 🐞 Fix ConfigProvider makes Form component in the bundle even not use it. [#42604](https://github.com/ant-design/ant-design/pull/42604) - 🐞 Fix InputNumber cannot align well by baseline. [#42580](https://github.com/ant-design/ant-design/pull/42580) -- 🐞 Fix spinning icon animation in Badge. [#42575](https://github.com/ant-design/ant-design/pull/42575) [@MadCcc](https://github.com/MadCcc) +- 🐞 Fix spinning icon animation in Badge. [#42575](https://github.com/ant-design/ant-design/pull/42575) - 📦 Optimize Form `setFieldsValue` logic to reduce bundle size. [#42635](https://github.com/ant-design/ant-design/pull/42635) - 💄 Optimize Image.ImagePreviewGroup style. [#42675](https://github.com/ant-design/ant-design/pull/42675) [@kiner-tang](https://github.com/kiner-tang) - 💄 Fix Tag borderless style with `error` and other status. [#42619](https://github.com/ant-design/ant-design/pull/42619) [@li-jia-nan](https://github.com/li-jia-nan) - 💄 Fix Table `rowSpan` hover highlight style missing. [#42572](https://github.com/ant-design/ant-design/pull/42572) - 💄 Fix Pagination's link icon and ellipsis hover style when disabled. [#42541](https://github.com/ant-design/ant-design/pull/42541) [@qmhc](https://github.com/qmhc) -- 💄 Fix Design Token that global token should be able to override component style. [#42535](https://github.com/ant-design/ant-design/pull/42535) [@MadCcc](https://github.com/MadCcc) +- 💄 Fix Design Token that global token should be able to override component style. [#42535](https://github.com/ant-design/ant-design/pull/42535) - 🇱🇹 Add missing i18n for `lt_LT` locale. [#42664](https://github.com/ant-design/ant-design/pull/42664) [@Digital-512](https://github.com/Digital-512) - RTL - 💄 Fix ColorPicker style in RTL mode. [#42716](https://github.com/ant-design/ant-design/pull/42716) [@RedJue](https://github.com/RedJue) @@ -339,7 +529,7 @@ tag: vVERSION `2023-05-22` -- 🐞 Fix wrong Button icon size and margin. [#42516](https://github.com/ant-design/ant-design/pull/42516) [@MadCcc](https://github.com/MadCcc) +- 🐞 Fix wrong Button icon size and margin. [#42516](https://github.com/ant-design/ant-design/pull/42516) - 🐞 Fix Select remove & selected icon not align in center. [#42513](https://github.com/ant-design/ant-design/pull/42513) - 🐞 Refactor Popconfirm DOM structure to fix extra margin before `title` and `description` when `icon={null}`. [#42433](https://github.com/ant-design/ant-design/pull/42433) - 🐞 Fix Menu item icon not centered when `itemMarginInline` is 0. [#42426](https://github.com/ant-design/ant-design/pull/42426) [@zzwgh](https://github.com/zzwgh) @@ -621,7 +811,7 @@ tag: vVERSION `2023-02-27` - 🐞 Fix for setting `percent` and `success.percent` at the same time for `Progress`, the progress text does not change as `percent` changes. [#40922](https://github.com/ant-design/ant-design/pull/40922) -- 🐞 Fixed Image preview icon was misaligned.[#40911](https://github.com/ant-design/ant-design/pull/40911) +- 🐞 Fixed Image preview icon was misaligned. [#40911](https://github.com/ant-design/ant-design/pull/40911) - 🐞 Fix ConfigProvider validation message template override Form configure template sometime. [#40533](https://github.com/ant-design/ant-design/pull/40533) [@Wxh16144](https://github.com/Wxh16144) - 🐞 Fixed Confirm Modal `onOk` event could be triggered twice when close. [#40719](https://github.com/ant-design/ant-design/pull/40719) [@Rafael-Martins](https://github.com/Rafael-Martins) - 🛠 Rewrote the `useLocale` method and exposed `localeCode` to the public. [#40884](https://github.com/ant-design/ant-design/pull/40884) [@li-jia-nan](https://github.com/li-jia-nan) @@ -631,10 +821,10 @@ tag: vVERSION - 🐞 Fixed where Descriptions did not accept `data-_` and `aria-_` attributes. [#40859](https://github.com/ant-design/ant-design/pull/40859) [@goveo](https://github.com/goveo) - 🛠 Changed the Breadcrumb Separator's DOM element from `span` to `li`. [#40867](https://github.com/ant-design/ant-design/pull/40867) [@heiyu4585](https://github.com/heiyu4585) - 🐞 Fix token of `Layout.colorBgHeader` not work when single use Layout.Header directly. [#40933](https://github.com/ant-design/ant-design/pull/40933) -- 💄 Changed Design Token the component's focus `outline` to the default `4px`.[#40839](https://github.com/ant-design/ant-design/pull/40839) +- 💄 Changed Design Token the component's focus `outline` to the default `4px`. [#40839](https://github.com/ant-design/ant-design/pull/40839) - 🐞 Fixed the Badge color was displayed abnormally. [#40848](https://github.com/ant-design/ant-design/pull/40848) [@kiner-tang](https://github.com/kiner-tang) - 🐞 Fixed an issue with the Timeline item's `className`. [#40835](https://github.com/ant-design/ant-design/pull/40835) [@Yuiai01](https://github.com/Yuiai01) -- 💄 Fixed the interaction style of the Rate component in the disabled state.[#40836](https://github.com/ant-design/ant-design/pull/40836) [@Yuiai01](https://github.com/Yuiai01) +- 💄 Fixed the interaction style of the Rate component in the disabled state. [#40836](https://github.com/ant-design/ant-design/pull/40836) [@Yuiai01](https://github.com/Yuiai01) - 🇮🇷 Added Iranian localization. [#40895](https://github.com/ant-design/ant-design/pull/40895) [@majidsadr](https://github.com/majidsadr) ## 5.2.2 @@ -843,8 +1033,8 @@ tag: vVERSION `2022-12-26` -- 📦 Remove IE and other legacy browsers from browserslist to reduce bundle size.[#38779](https://github.com/ant-design/ant-design/pull/38779) -- ⚡️ Improve Transfer performance when selecting and moving nodes with large data.[#39465](https://github.com/ant-design/ant-design/pull/39465) [@wqs576222103](https://github.com/wqs576222103) +- 📦 Remove IE and other legacy browsers from browserslist to reduce bundle size. [#38779](https://github.com/ant-design/ant-design/pull/38779) +- ⚡️ Improve Transfer performance when selecting and moving nodes with large data. [#39465](https://github.com/ant-design/ant-design/pull/39465) [@wqs576222103](https://github.com/wqs576222103) - 🐞 Fix Design Token wrong `font-family` of components. [#39806](https://github.com/ant-design/ant-design/pull/39806) - 🐞 Fix Drawer default props not working when `placement` `open` `width` are `undefined`. [#39782](https://github.com/ant-design/ant-design/pull/39782) - 🐞 Fix Menu icon animation when collapse it. [#39800](https://github.com/ant-design/ant-design/pull/39800) [@JarvisArt](https://github.com/JarvisArt) diff --git a/CHANGELOG.zh-CN.md b/CHANGELOG.zh-CN.md index 6ba8ef008e4d..a7459075ae58 100644 --- a/CHANGELOG.zh-CN.md +++ b/CHANGELOG.zh-CN.md @@ -16,6 +16,196 @@ tag: vVERSION --- +## 5.10.0 + +`2023-10-10` + +- 🔥 新增 Flex 组件,用于设置弹性布局。[#44362](https://github.com/ant-design/ant-design/pull/44362) +- 🔥 Notification 组件支持 `stack` 配置,默认超过三个以上的提示会堆叠起来。[#44618](https://github.com/ant-design/ant-design/pull/44618) +- 🔥 更新 Input、InputNumber、Select、Cascader、TreeSelect、DatePicker、ColorPicker 的激活态样式。[#45009](https://github.com/ant-design/ant-design/pull/45009) +- 🆕 Watermark 支持通过 `textAlign` 设置文本对齐方向。[#44888](https://github.com/ant-design/ant-design/pull/44888) [@Yuiai01](https://github.com/Yuiai01) +- 🆕 Slider 支持任意节点数并且将 xxxStyle 迁移至语义化 `styles` 和 `classNames` 属性中。[#45000](https://github.com/ant-design/ant-design/pull/45000) +- 🆕 Cascader 支持 Cascader.Panel 组件供内联使用。[#45089](https://github.com/ant-design/ant-design/pull/45089) +- 🆕 Tooltip 添加 `fresh` 属性以支持在关闭时仍然需要更新内容的场景。[#45020](https://github.com/ant-design/ant-design/pull/45020) +- 🆕 Drawer 支持通过 `classNames` 自定义内置模块的 `className`。[#44935](https://github.com/ant-design/ant-design/pull/44935) +- 🆕 ConfigProvider 支持 `warning` 属性以配置警告等级(如过滤掉废弃 API 警告)。[#44809](https://github.com/ant-design/ant-design/pull/44809) +- Modal + - 🆕 Modal 支持通过 `classNames` 自定义内置模块的 `className`。[#44934](https://github.com/ant-design/ant-design/pull/44934) + - 🐞 修复 Modal.confirm `description` 是长文本时的内容溢出问题。[#45212](https://github.com/ant-design/ant-design/pull/45212) +- 🐞 修复 Menu.Item 嵌套的 Typography 其 `ellipsis` 为 true 时无法垂直居中的问题。[#41146](https://github.com/ant-design/ant-design/pull/41146) [@Yuiai01](https://github.com/Yuiai01) +- 🐞 修复 Select 内部 input 无法应用 fontFamily 的问题。[#45197](https://github.com/ant-design/ant-design/pull/45197) [@Yuiai01](https://github.com/Yuiai01) +- 🐞 修复 InputNumber 在 Space.Compact 中使用 `addonBefore` 时的边框问题。[#45004](https://github.com/ant-design/ant-design/pull/45004) [@Yuiai01](https://github.com/Yuiai01) +- 🐞 修复 Tag.CheckableTag 不支持 ref 的问题。[#45164](https://github.com/ant-design/ant-design/pull/45164) [@mingming-ma](https://github.com/mingming-ma) +- 🐞 修复 Avatar.Group 组件内的字体不支持响应式的问题。[#34722](https://github.com/ant-design/ant-design/pull/34722) [@laishiwen](https://github.com/laishiwen) +- 🛠 重构 Affix 为函数组件。[#42674](https://github.com/ant-design/ant-design/pull/42674) +- 🛠 Popover 组件废弃 `minWidth` 组件 token,并添加 `titleMinWidth` 作为替代。[#44750](https://github.com/ant-design/ant-design/pull/44750) +- 🌈 Token + - 🆕 Input 新增 `hoverBg` `activeBg` token 用以设置输入框 hover 和 激活时背景颜色。[#44752](https://github.com/ant-design/ant-design/pull/44752) [@Pan-yongyong](https://github.com/Pan-yongyong) + - 🆕 Descriptions 新增 `titleColor` `contentColor` 用以设置标题颜色和内容区域文字颜色。[#44729](https://github.com/ant-design/ant-design/pull/44729) [@Child-qjj](https://github.com/Child-qjj) + - 🐞 修复 Input 组件 Token `addonBg` 失效的问题。[#45222](https://github.com/ant-design/ant-design/pull/45222) +- TypeScript + - 🤖 导出 Notification 的 ArgsProps 类型为 NotificationArgsProps。[#45147](https://github.com/ant-design/ant-design/pull/45147) +- 🌐 国际化 + - 🇵🇱 为 pl_PL 补充 Tour 国际化。[#45166](https://github.com/ant-design/ant-design/pull/45166) [@antonisierakowski](https://github.com/antonisierakowski) + - 🇰🇷 优化 ko_KR 国际化。[#45150](https://github.com/ant-design/ant-design/pull/45150) [@owjs3901](https://github.com/owjs3901) + +## 5.9.4 + +`2023-09-28` + +- Button + - 🐞 修复 Button 组件只有两个汉字且嵌套在多层 span 中时间距丢失的问题。[#45126](https://github.com/ant-design/ant-design/pull/45126) [@MadCcc](https://github.com/MadCcc) + - 🐞 修复 Button 条件渲染时意外出现加载图标的问题。[#45030](https://github.com/ant-design/ant-design/pull/45030) [@lzl0304](https://github.com/lzl0304) +- 🐞 修复 Tour 组件第一次展示时 `step.type` 无效的问题。[#45086](https://github.com/ant-design/ant-design/pull/45086) [@MadCcc](https://github.com/MadCcc) +- 🐞 修复 Select 和 DatePicker 组件没有使用 `fontFamily` token 的问题。[#45088](https://github.com/ant-design/ant-design/pull/45088) [@MadCcc](https://github.com/MadCcc) + +## 5.9.3 + +`2023-09-25` + +- 🔥 Tooltip 删除对 `disabled` 子元素额外包括 `span` 的逻辑,现在始终能够正确触发。[#44895](https://github.com/ant-design/ant-design/pull/44895) [@Yuiai01](https://github.com/Yuiai01) +- 🐞 修复 Popover 超出屏幕时不会自动调整偏移的问题。[#45015](https://github.com/ant-design/ant-design/pull/45015) [@MadCcc](https://github.com/MadCcc) +- 🐞 修复 Tooltip / Popover 在内容高度变化时,位置会闪动的问题。[#44976](https://github.com/ant-design/ant-design/pull/44976) +- 🛠 ComponentToken 移除 `radiusBase` 必须小于 `16` 的限制。[#44980](https://github.com/ant-design/ant-design/pull/44980) +- 🐞 修复 Dropdown 通过 `dropdownRender` 渲染的子节点配置 `ref` 不生效的问题。[#44971](https://github.com/ant-design/ant-design/pull/44971) +- 🐞 修复 Table `cellPaddingBlock` 不生效的问题。[#45040](https://github.com/ant-design/ant-design/pull/45040) +- 🐞 修复 Input 组件在小尺寸 `controlHeight` 下高度不正确的问题。[#45048](https://github.com/ant-design/ant-design/pull/45048) +- 🐞 修复 Typography 在设置 `fontSize` 为奇数时的样式问题。[#45031](https://github.com/ant-design/ant-design/pull/45031) +- TypeScript + - 🤖 MISC: 修复 `@types/react@18.2.22` React.Key 定义更新引发的问题。[#44938](https://github.com/ant-design/ant-design/pull/44938) + +## 5.9.2 + +`2023-09-19` + +- 🐞 修复 Table `small` 尺寸时选择列没有居中对齐的问题。[#44922](https://github.com/ant-design/ant-design/pull/44922) +- 🐞 修复 Select 当 `label` 内使用了 `div` 块级元素时的样式问题。[#44927](https://github.com/ant-design/ant-design/pull/44927) +- 🐞 修复 Modal 自定义 `footer` 时按钮内容丢失的问题。[#44929](https://github.com/ant-design/ant-design/pull/44929) [@Wxh16144](https://github.com/Wxh16144) +- 🐞 修复 notification 底部弹出动画的问题。[#44918](https://github.com/ant-design/ant-design/pull/44918) [@linxianxi](https://github.com/linxianxi) +- 🐞 修复 Form.Item 有 `noStyle` 属性时没有继承上下文的反馈图标的问题。[#44937](https://github.com/ant-design/ant-design/pull/44937) + +## 5.9.1 + +`2023-09-15` + +- 🐞 修复小尺寸 Select 组件 `controlHeightSM` token 配置无效的问题。[#44859](https://github.com/ant-design/ant-design/pull/44859) [@MadCcc](https://github.com/MadCcc) +- 🐞 修复 Rate 组件星星变换中心不在正中心的问题。[#44855](https://github.com/ant-design/ant-design/pull/44855) [@MadCcc](https://github.com/MadCcc) +- 🐞 修复 DatePicker 组件 `dateTime` 模式切换输入框不会触发 `onCalendarChange` 的问题。[#44845](https://github.com/ant-design/ant-design/pull/44845) [@Yuiai01](https://github.com/Yuiai01) +- 🐞 修复 Table `virtual` 配置下,选择框没有居中对齐的问题。[#44786](https://github.com/ant-design/ant-design/pull/44786) +- 🐞 修复 Select 开启 `maxTagCount` 时搜索光标偏上的问题。[#44757](https://github.com/ant-design/ant-design/pull/44757) +- 🐞 修复 Select 的 label 为 Typography 组件时的选中文本对齐问题。[#44756](https://github.com/ant-design/ant-design/pull/44756) +- 💄 修复 Table `virtual` 开启虚拟滚动时,当 `columns` 小于表格宽度会显示异常的问题以及部分边框、悬浮样式丢失的问题。[#44818](https://github.com/ant-design/ant-design/pull/44818) +- 💄 修复 Select 组件在 Input `addon` 中使用时的样式错误。[#44825](https://github.com/ant-design/ant-design/pull/44825) [@MadCcc](https://github.com/MadCcc) +- 💄 修复 Tree 组件样式,使 Checkbox 与文字第一行对齐。[#44827](https://github.com/ant-design/ant-design/pull/44827) [@MadCcc](https://github.com/MadCcc) +- 💄 修复 Card 组件 Card.Grid 边缘样式问题。[#44801](https://github.com/ant-design/ant-design/pull/44801) [@Jason-huang66](https://github.com/Jason-huang66) +- 💄 修复 Select/Cascader/TreeSelect 自定义高度时的样式问题。[#44753](https://github.com/ant-design/ant-design/pull/44753) +- TypeScript + - 🤖 优化 Radio.Button 的 `ref` 类型。[#44747](https://github.com/ant-design/ant-design/pull/44747) [@LexiosAlex](https://github.com/LexiosAlex) + - 🤖 优化 Checkbox 的 `ref` 类型。[#44746](https://github.com/ant-design/ant-design/pull/44746) [@LexiosAlex](https://github.com/LexiosAlex) + +## 5.9.0 + +`2023-09-08` + +- 🔥 Table 支持 `virtual` 属性开启虚拟滚动。[#44349](https://github.com/ant-design/ant-design/pull/44349) +- 🔥 Form `validateFields` 支持 `recursive` 以校验所有包含路径的字段。[#44130](https://github.com/ant-design/ant-design/pull/44130) +- 🔥 Form.Item 支持 `validateDebounce` 以配置校验防抖。[#44633](https://github.com/ant-design/ant-design/pull/44633) +- 🆕 Button 组件新增 `contentFontSize` `contentFontSizeSM` `contentFontSizeLG` 三个组件 token ,用于定制各个尺寸下的字体大小。[#44257](https://github.com/ant-design/ant-design/pull/44257) +- 🆕 Form `requiredMark` 支持自定义渲染。[#44073](https://github.com/ant-design/ant-design/pull/44073) +- 🆕 Tabs 组件添加新组件 Token `itemColor`,用于控制常态 tab 的文本颜色。[#44201](https://github.com/ant-design/ant-design/pull/44201) +- 🆕 ColorPicker 组件支持 `defaultFormat` 属性。[#44487](https://github.com/ant-design/ant-design/pull/44487) [@CYBYOB](https://github.com/CYBYOB) +- 🆕 Form 新增 `feedbackIcons` 属性且 Form.Item 支持 `hasFeedback={{ icons: ... }}`,用于自定义校验图标。[#43894](https://github.com/ant-design/ant-design/pull/43894) [@gldio](https://github.com/gldio) +- 🆕 Segmented 组件新增 `itemSelectedColor` 的组件 Token。[#44570](https://github.com/ant-design/ant-design/pull/44570) [@xiaozisong](https://github.com/xiaozisong) +- 🆕 Modal 页脚 `footer` 支持自定义函数渲染。[#44318](https://github.com/ant-design/ant-design/pull/44318) [@RedJue](https://github.com/RedJue) +- 🆕 Descriptions 的 `items.span` 支持响应式设置。[#44534](https://github.com/ant-design/ant-design/pull/44534) +- 🆕 Tabs 组件 `indicatorSize` 支持通过 ConfigProvider 全局配置。[#44406](https://github.com/ant-design/ant-design/pull/44406) +- 🆕 Transfer 组件 `filterOption` 函数新增 `direction` 入参。[#44417](https://github.com/ant-design/ant-design/pull/44417) [@Zian502](https://github.com/Zian502) +- 🆕 Input.Search 组件支持在 `onSearch` 方法中接受 `source` 参数。[#44457](https://github.com/ant-design/ant-design/pull/44457) [@kiner-tang](https://github.com/kiner-tang) +- 🆕 Input 组件新增组件 Token 用于定制激活态阴影。[#44410](https://github.com/ant-design/ant-design/pull/44410) +- 🆕 Radio 组件新增组件 Token,用于定制填充按钮选中时的颜色。[#44389](https://github.com/ant-design/ant-design/pull/44389) +- 🆕 Tour 组件间距支持横向偏移量。[#44377](https://github.com/ant-design/ant-design/pull/44377) [@RedJue](https://github.com/RedJue) +- 🆕 Tour 组件支持通过 `closeIcon` 来自定义关闭按钮。[#44312](https://github.com/ant-design/ant-design/pull/44312) [@kiner-tang](https://github.com/kiner-tang) +- 🆕 Avatar 支持使用 ConfigProvider 的 `componentSize` 配置 `size`。[#44288](https://github.com/ant-design/ant-design/pull/44288) [@li-jia-nan](https://github.com/li-jia-nan) +- 🆕 List 支持使用 ConfigProvider 的 `componentSize` 配置 `size`。[#44267](https://github.com/ant-design/ant-design/pull/44267) [@Yuiai01](https://github.com/Yuiai01) +- 🆕 Cascader 支持 `autoClearSearchValue` 属性。[#44033](https://github.com/ant-design/ant-design/pull/44033) [@linxianxi](https://github.com/linxianxi) +- 🆕 在 [Upload](https://github.com/ant-design/ant-design/pull/44060)、[AutoComplete](https://github.com/ant-design/ant-design/pull/44055)、[Badge.Ribbon](https://github.com/ant-design/ant-design/pull/44056)、[Input.TextArea](https://github.com/ant-design/ant-design/pull/44058)、[RangePicker](https://github.com/ant-design/ant-design/pull/44057)、[TimePicker](https://github.com/ant-design/ant-design/pull/44059) 中添加了对 `rootClassName` 的支持。[@kiner-tang](https://github.com/kiner-tang)。 +- 💄 重构 Modal.confirm 结构以修复 `width: fit-content` 导致宽度异常问题以及大量文本下的样式断行问题。抽离 confirm 样式至懒加载以优化 SSR 下的样式尺寸。[#44557](https://github.com/ant-design/ant-design/pull/44557) +- 💄 Progress 调整 `circle` 和 `dashboard` 的线性渐变色为锥形渐变色。[#44404](https://github.com/ant-design/ant-design/pull/44404) +- 💄 修复 DatePicker 组件自定义页脚样式问题。[#44642](https://github.com/ant-design/ant-design/pull/44642) [@li-jia-nan](https://github.com/li-jia-nan) +- 💄 修复 ConfigProvider `tag.className` 与 `tag.style` 无法作用于 Tag.CheckableTag 的问题。[#44602](https://github.com/ant-design/ant-design/pull/44602) +- 💄 修复 Select 配置的 `getPopupContainer` 容器有 `transform: scale` 样式时,弹出框宽度与输入框不一致的情况。[#44378](https://github.com/ant-design/ant-design/pull/44378) +- 🐞 修复 Form.Item 配置 `noStyle` 时,被绑定的元素无法消费 `useStatus` 的问题。[#44576](https://github.com/ant-design/ant-design/pull/44576) +- 🐞 修复 Tag 被 Popover/Popconfirm 包裹时,Hover 会导致 `font-size` 错误的问题。[#44663](https://github.com/ant-design/ant-design/pull/44663) +- 🐞 修复 Input.Search 组合中,搜索按钮存在额外阴影的问题。[#44660](https://github.com/ant-design/ant-design/pull/44660) [@daledelv](https://github.com/daledelv) +- 🐞 修复 Modal 的 hooks 调用通过按键 `esc` 关闭时无法正确触发 await 的问题。[#44646](https://github.com/ant-design/ant-design/pull/44646) +- 🐞 修复 Space 的预设 `size` 不会跟随 Design Token 的问题,现在紧凑模式也会正确处理对应的间距数值。[#44598](https://github.com/ant-design/ant-design/pull/44598) [@li-jia-nan](https://github.com/li-jia-nan) +- 🐞 修复 Upload 组件点击某文件的下载按钮后,鼠标移出该文件时仍展示下载按钮的问题。[#44594](https://github.com/ant-design/ant-design/pull/44594) [@zbw-zbw](https://github.com/zbw-zbw) +- 🐞 修复 FloatButton 组件添加 `href` 后在 FloatButton.Group 中间距失效的问题。[#44707](https://github.com/ant-design/ant-design/pull/44707) [@Yuiai01](https://github.com/Yuiai01) +- 🐞 修复 Button `fontSizeSM` token 不生效的问题。[#44217](https://github.com/ant-design/ant-design/pull/44217) [@CHENGTIANG](https://github.com/CHENGTIANG) +- 🐞 Watermark 现在可以在嵌套的 Modal 和 Drawer 组件中生效。[#44104](https://github.com/ant-design/ant-design/pull/44104) +- 🛠 迁移 Alert、Tree、Cascader、Layout、Table、Modal、Drawer、Button、Switch、Select、Badge、Form、TimePicker、Spin、Input、Progress、Divider 的 less 变量到 Token。 [#42142](https://github.com/ant-design/ant-design/pull/42142) [#42607](https://github.com/ant-design/ant-design/pull/42607) [#42627](https://github.com/ant-design/ant-design/pull/42627) [#42757](https://github.com/ant-design/ant-design/pull/42757) [#42774](https://github.com/ant-design/ant-design/pull/42774) [#42778](https://github.com/ant-design/ant-design/pull/42778) [#44090](https://github.com/ant-design/ant-design/pull/44090)[#44118](https://github.com/ant-design/ant-design/pull/44118) [#44174](https://github.com/ant-design/ant-design/pull/44174) [#44228](https://github.com/ant-design/ant-design/pull/44228) [#44261](https://github.com/ant-design/ant-design/pull/44261) [#44282](https://github.com/ant-design/ant-design/pull/44282) [#44334](https://github.com/ant-design/ant-design/pull/44334) [#42192](https://github.com/ant-design/ant-design/pull/42192) [@hms181231](https://github.com/hms181231) [@linhf123](https://github.com/linhf123) [@poyiding](https://github.com/poyiding) [@Wxh16144](https://github.com/Wxh16144) [@Yuiai01](https://github.com/Yuiai01) +- 📦 移除 Space 和 Grid 对于旧版 IE 浏览器兼容逻辑,减少打包产物体积。[#44620](https://github.com/ant-design/ant-design/pull/44620) [@li-jia-nan](https://github.com/li-jia-nan) +- TypeScript + - 🤖 从 Tree 中导出 `BasicDataNode` 类型。[#44624](https://github.com/ant-design/ant-design/pull/44624) [@kiner-tang](https://github.com/kiner-tang) + +## 5.8.6 + +`2023-09-02` + +- 🛠 针对 CSSInJS 加载 styles 大小进行了优化。 + - 🛠 Notification 和 Message 组件只有在展示时才会插入对应样式。[#44488](https://github.com/ant-design/ant-design/pull/44488) + - 🛠 剥离 Tag 状态与预设颜色样式,现在只有当使用的时候才会生成它们。[#44512](https://github.com/ant-design/ant-design/pull/44512) + - 🛠 剥离 Button 紧凑模式样式,现在只有当使用了 Space.Compact 的时候才会生成它们。[#44475](https://github.com/ant-design/ant-design/pull/44475) +- 📦 移除 `@ant-design/icons` 依赖 `lodash/camelCase` 以优化 bundle size。[ant-design-icons#595](https://github.com/ant-design/ant-design-icons/pull/595) +- Form + - 🐞 修复 Form.Item 设置 `wrapperCol.span` 为 `0` 时,子元素不隐藏的问题。[#44485](https://github.com/ant-design/ant-design/pull/44485) [#44472](https://github.com/ant-design/ant-design/pull/44472) [@crazyair](https://github.com/crazyair) + - 🐞 修复 Form `labelCol` 设置为 24 时,会使 `wrapperCol` 设置 24 失效的问题。[#44541](https://github.com/ant-design/ant-design/pull/44541) +- 🐞 修复 Watermark 组件在 `content` 是空字符串时报错的问题。[#44501](https://github.com/ant-design/ant-design/pull/44501) +- 🐞 修复 ColorPicker 禁用时依然能弹出选择窗口的问题。[#44466](https://github.com/ant-design/ant-design/pull/44466) [@RedJue](https://github.com/RedJue) +- 🐞 修复 Transfer 点击 Checkbox 时有时会触发两次选择行为的问题。[#44471](https://github.com/ant-design/ant-design/pull/44471) [@kovsu](https://github.com/kovsu) +- 🐞 修复 Typography 使用 `ellipsis` 时滚动条闪动的问题。[#43058](https://github.com/ant-design/ant-design/pull/43058) [@bbb169](https://github.com/bbb169) +- Slider + - 🐞 修复 Slider 滑块可拖拽区域范围异常的问题。[#44503](https://github.com/ant-design/ant-design/pull/44503) [@BoyYangzai](https://github.com/BoyYangzai) [@yoyo837](https://github.com/yoyo837) + - ⌨️ 优化 Slider `aria-orientation` 可访问性属性。[react-component/slider#859](https://github.com/react-component/slider/pull/859) [@5im0n](https://github.com/5im0n) +- 🐞 修复 Steps `type="nav"` 垂直导航步骤条的最后一项箭头没隐藏的问题。[#44582](https://github.com/ant-design/ant-design/pull/44582) [@ohhoney1](https://github.com/ohhoney1) +- TypeScript + - 🤖 修复 Upload 文件状态定义,移除未使用过的 `success` 状态。[#44468](https://github.com/ant-design/ant-design/pull/44468) + +## 5.8.5 + +`2023-08-28` + +- 🛠 重构 Badge 样式逻辑将 Ribbon 样式抽离以降低 SSR 内联样式尺寸。[#44451](https://github.com/ant-design/ant-design/pull/44451) +- 🐞 修复 App 组件下使用 `@ant-design/icons` 的图标样式异常的问题。[#41208](https://github.com/ant-design/ant-design/pull/41208) [@Wxh16144](https://github.com/Wxh16144) +- 🐞 修复 Carousel 组件垂直方向拖动失效的问题。[#44460](https://github.com/ant-design/ant-design/pull/44460) [@RedJue](https://github.com/RedJue) +- 🐞 修复 Tour 面板使用的 design token 错误的问题。[#44428](https://github.com/ant-design/ant-design/pull/44428) +- 🐞 修复 Form `wrapperCol` 配置响应式 `xs` 属性无效的问题。[#44388](https://github.com/ant-design/ant-design/pull/44388) +- 🐞 修复 ColorPicker 中重复 `key` 的问题。[#44370](https://github.com/ant-design/ant-design/pull/44370) [@xr0master](https://github.com/xr0master) +- 🐞 修复 Radio 组件组合 Tree 组件后失效的问题。[#44380](https://github.com/ant-design/ant-design/pull/44380) +- 🐞 修复 Table 组件 `filterDropdown` 不支持 `ref` 时报错的问题。[#44357](https://github.com/ant-design/ant-design/pull/44357) +- 🐞 修复 Form `inline` 布局在校验失败时出现额外空行的问题。[#44360](https://github.com/ant-design/ant-design/pull/44360) +- 🐞 修复 DatePicker 中 `showTime` 为 true 且 `format` 为数组时,组件报错。[#44306](https://github.com/ant-design/ant-design/pull/44306) [@Zian502](https://github.com/Zian502) +- 🐞 修复 Watermark 中 `content` 内容过长时无法完整显示的问题。[#44321](https://github.com/ant-design/ant-design/pull/44321) +- TypeScript + - 🤖 修复 Dropdown 组件中 `align` 属性的类型错误。[#44423](https://github.com/ant-design/ant-design/pull/44423) [@LeTuongKhanh](https://github.com/LeTuongKhanh) + +## 5.8.4 + +`2023-08-18` + +- ColorPicker + - 🐞 修复 ColorPicker 色值输入框输入小写英文字母时光标跳动的问题。[#44137](https://github.com/ant-design/ant-design/pull/44137) [@gouge666](https://github.com/gouge666) + - 🐞 修复 ColorPicker 在不同尺寸下样式变形的问题。[#44273](https://github.com/ant-design/ant-design/pull/44273) [@kouchao](https://github.com/kouchao) +- 🐞 修复 Descriptions 抛出 `key is not a prop` 的错误提示。[#44278](https://github.com/ant-design/ant-design/pull/44278) [@RedJue](https://github.com/RedJue) +- 🐞 修复 Pagination `itemRender` 自定义为 `null` 时,仍然渲染节点的问题。[#44226](https://github.com/ant-design/ant-design/pull/44226) +- 🐞 修复 Modal 在 Dropdown `menu.items` 中,展开 Modal 时快速移动鼠标会使 Dropdown 重新打开的问题。[#44204](https://github.com/ant-design/ant-design/pull/44204) +- DatePicker + - 💄 修复 DatePicker 内容不居中问题。[#44245](https://github.com/ant-design/ant-design/pull/44245) [@Zian502](https://github.com/Zian502) + - 💄 优化 DatePicker 中范围选择区域样式。[#44206](https://github.com/ant-design/ant-design/pull/44206) [@kiner-tang](https://github.com/kiner-tang) +- 💄 修复移动端点击 Tabs 区域触发颜色改变的问题。[#44200](https://github.com/ant-design/ant-design/pull/44200) [@yilaikesi](https://github.com/yilaikesi) +- RTL + - 💄 修复了当页面的文字方向为 RTL 时 Badge 里面的数字也是 RTL 的问题。[#43998](https://github.com/ant-design/ant-design/pull/43998) [@NotEvenANeko](https://github.com/NotEvenANeko) + ## 5.8.3 `2023-08-11` @@ -28,14 +218,14 @@ tag: vVERSION - 💄 修复 Carousel `dots` 切换点有多余 margin 的问题。[#44076](https://github.com/ant-design/ant-design/pull/44076) - 🐞 修复 Modal 页脚禁用态受 Form 影响的问题。[#43055](https://github.com/ant-design/ant-design/pull/43055) [@Wxh16144](https://github.com/Wxh16144) - 🐞 修复 Upload gif 缩略图不会动的问题。[#44083](https://github.com/ant-design/ant-design/pull/44083) [@linxianxi](https://github.com/linxianxi) -- 🐞 修复 FloatButton 组件菜单模式不支持 `badge` 配置的问题。[#44109](https://github.com/ant-design/ant-design/pull/44109) [@MadCcc](https://github.com/MadCcc) +- 🐞 修复 FloatButton 组件菜单模式不支持 `badge` 配置的问题。[#44109](https://github.com/ant-design/ant-design/pull/44109) - 🐞 修复 Grid 与 List 响应式布局生效稍晚于首次渲染导致屏幕闪动的问题。[#44075](https://github.com/ant-design/ant-design/pull/44075) -- 🐞 修复 `@ant-design/cssinjs` 版本小于 `1.15.0` 时 Design Token 部分丢失的问题。[#44091](https://github.com/ant-design/ant-design/pull/44091) [@MadCcc](https://github.com/MadCcc) +- 🐞 修复 `@ant-design/cssinjs` 版本小于 `1.15.0` 时 Design Token 部分丢失的问题。[#44091](https://github.com/ant-design/ant-design/pull/44091) - 💄 修复 Badge `status="processing"` 和 `dot` 配合使用时,波纹样式异常的问题。[#44153](https://github.com/ant-design/ant-design/pull/44153) - 💄 修复 Descriptions 组件自行嵌套时的边框样式问题。[#43454](https://github.com/ant-design/ant-design/pull/43454) [@Yuiai01](https://github.com/Yuiai01) -- 💄 修复 Pagination 上下页切换按钮 `transition`` 丢失的问题。[#44030](https://github.com/ant-design/ant-design/pull/44030) +- 💄 修复 Pagination 上下页切换按钮 `transition` 丢失的问题。[#44030](https://github.com/ant-design/ant-design/pull/44030) - 💄 修复 Popconfirm 按钮组意外换行的问题。[#44022](https://github.com/ant-design/ant-design/pull/44022) [@MuxinFeng](https://github.com/MuxinFeng) -- 💄 优化 Image 组件预览操作图标的样式。[#44141](https://github.com/ant-design/ant-design/pull/44141) [@MadCcc](https://github.com/MadCcc) +- 💄 优化 Image 组件预览操作图标的样式。[#44141](https://github.com/ant-design/ant-design/pull/44141) - 💄 优化 Input 和 InputNumber 在大尺寸下的字体大小。[#44000](https://github.com/ant-design/ant-design/pull/44000) [@MuxinFeng](https://github.com/MuxinFeng) - 💄 移除 Space 部分未使用的样式。[#44098](https://github.com/ant-design/ant-design/pull/44098) @@ -46,7 +236,7 @@ tag: vVERSION - 🐞 修复 Checkbox 与 Radio 不支持自定义水波纹效果的问题,并添加 `ant-wave-target` className 到对应元素上。[#44014](https://github.com/ant-design/ant-design/pull/44014) - 🐞 调整 Form.Item renderProps 定义,现在会返回正确的 `FormInstance`。[#43996](https://github.com/ant-design/ant-design/pull/43996) - 🐞 修复 Table 在 `direction` 为 `rlt` 时展开图标的方向和展开行的缩进有误的问题。[#43977](https://github.com/ant-design/ant-design/pull/43977) [@Yuiai01](https://github.com/Yuiai01) -- 💄 修复 Pagination 组件禁用状态仍然有悬浮和聚焦样式的问题。[#43970](https://github.com/ant-design/ant-design/pull/43970) [@MadCcc](https://github.com/MadCcc) +- 💄 修复 Pagination 组件禁用状态仍然有悬浮和聚焦样式的问题。[#43970](https://github.com/ant-design/ant-design/pull/43970) - TypeScript - 🤖 修正 Drawer 和 Anchor 部分 Design Token 的 TS 描述信息错误的问题。[#43994](https://github.com/ant-design/ant-design/pull/43994) [@wving5](https://github.com/wving5) @@ -62,7 +252,7 @@ tag: vVERSION `2023-08-01` -- 🔥 组件 ComponentToken 支持配置 `algorithm` 参数,添加配置即可像全局 Token 一样由部分修改的 token 计算派生 token 的值并用于组件样式中。[#43810](https://github.com/ant-design/ant-design/pull/43810) [@MadCcc](https://github.com/MadCcc) +- 🔥 组件 ComponentToken 支持配置 `algorithm` 参数,添加配置即可像全局 Token 一样由部分修改的 token 计算派生 token 的值并用于组件样式中。[#43810](https://github.com/ant-design/ant-design/pull/43810) - 🔥 Modal hooks 方法支持 `await` 调用。[#43470](https://github.com/ant-design/ant-design/pull/43470) - 🔥 ConfigProvider 支持 `wave` 配置以自定义水波纹效果。[#43784](https://github.com/ant-design/ant-design/pull/43784) - 🆕 Form 新增 `getFieldsValue({ strict: true })` 以支持获取仅通过 Item 绑定的字段。[#43828](https://github.com/ant-design/ant-design/pull/43828) @@ -105,11 +295,11 @@ tag: vVERSION `2023-07-20` -- 💄 修复 Menu 组件悬浮态样式丢失的问题。[#43656](https://github.com/ant-design/ant-design/pull/43656) [@MadCcc](https://github.com/MadCcc) +- 💄 修复 Menu 组件悬浮态样式丢失的问题。[#43656](https://github.com/ant-design/ant-design/pull/43656) - 🐞 修复 Notification 报错 PurePanel 定义未找到的问题。[#43687](https://github.com/ant-design/ant-design/pull/43687) [@li-jia-nan](https://github.com/li-jia-nan) - 🐞 修复 Button `onClick` 事件丢失 `event` 定义的问题。[#43666](https://github.com/ant-design/ant-design/pull/43666) - 🐞 修复 Input 和 InputNumber 行内对齐问题。[#43548](https://github.com/ant-design/ant-design/pull/43548) [@bbb169](https://github.com/bbb169) -- 🐞 修复 DatePicker 后缀颜色使用 `token` 不当的问题。[#43646](https://github.com/ant-design/ant-design/pull/43646) [@MadCcc](https://github.com/MadCcc) +- 🐞 修复 DatePicker 后缀颜色使用 `token` 不当的问题。[#43646](https://github.com/ant-design/ant-design/pull/43646) - 🐞 修复 Steps 配置可点击时不能通过键盘操作的问题。[#43644](https://github.com/ant-design/ant-design/pull/43644) - TypeScript - 🤖 移除 Button 无用的 `type="ghost"` 属性定义。[#43675](https://github.com/ant-design/ant-design/pull/43675) @@ -148,23 +338,23 @@ tag: vVERSION - 🆕 ColorPicker 支持 `onChangeComplete`。[#43370](https://github.com/ant-design/ant-design/pull/43370) [@RedJue](https://github.com/RedJue) - 🆕 ColorPicker 支持 `panelRender`。[#43134](https://github.com/ant-design/ant-design/pull/43134) [@RedJue](https://github.com/RedJue) - 🆕 ColorPicker 支持 `size`。[#43116](https://github.com/ant-design/ant-design/pull/43116) [@RedJue](https://github.com/RedJue) -- 🆕 Alert、Drawer、Modal、Notifaction、Tag、Tabs 均已支持通过设置 `closeIcon` 为 null 或 false 隐藏关闭按钮。 [#42828](https://github.com/ant-design/ant-design/discussions/42828) [@kiner-tang](https://github.com/kiner-tang) +- 🆕 Alert、Drawer、Modal、Notifaction、Tag、Tabs 均已支持通过设置 `closeIcon` 为 null 或 false 隐藏关闭按钮。[#42828](https://github.com/ant-design/ant-design/discussions/42828) [@kiner-tang](https://github.com/kiner-tang) - 🆕 Anchor 添加 `replace` 属性。[#43006](https://github.com/ant-design/ant-design/pull/43006) [@ds1371dani](https://github.com/ds1371dani) - 🆕 Image 支持 `imageRender`、`toolbarRender` 属性以支持预览图和工具栏的自定义渲染,还支持了 `onTransform`、`minScale`、`maxScale` 等新属性,Image.PreviewGroup 支持 `items` 属性传入列表数据,并修复了 img 标签的原生属性没有传递给预览图的问题。[#43075](https://github.com/ant-design/ant-design/pull/43075) [@linxianxi](https://github.com/linxianxi) - 🆕 修改 Image 预览图的布局风格,`preview` 属性支持 `closeIcon`,Image.PreviewGroup 支持 `fallback` 属性,修复加载预览资源提前加载的问题。[#43167](https://github.com/ant-design/ant-design/pull/43167) [@linxianxi](https://github.com/linxianxi) - 🛠 InputNumber 使用 rc-input 进行重构。[#43000](https://github.com/ant-design/ant-design/pull/43000) [@MuxinFeng](https://github.com/MuxinFeng) - 🛠 解决 vite、rollup、meteor、microbundle 等构建工具中遇到的循环依赖问题,并增加相关的检测。[#42750](https://github.com/ant-design/ant-design/pull/42750),感谢 [@jrr997](https://github.com/jrr997)、[@kiner-tang](https://github.com/kiner-tang) 和 [@MuxinFeng](https://github.com/MuxinFeng) 的贡献。 -- 🐞 移除 Anchor/CollapsePanel/Input.Group 组件中 `className` 属性的默认值(空字符串)。 [#43481](https://github.com/ant-design/ant-design/pull/43481) [@thinkasany](https://github.com/thinkasany) +- 🐞 移除 Anchor/CollapsePanel/Input.Group 组件中 `className` 属性的默认值(空字符串)。[#43481](https://github.com/ant-design/ant-design/pull/43481) [@thinkasany](https://github.com/thinkasany) - 🐞 修复 Upload 上传进度条延迟消失且丢失动画效果的问题。[#43471](https://github.com/ant-design/ant-design/pull/43471) -- 🐞 为 Menu 中组件 Token `colorItemBgSelected` 添加废弃警告。[#43461](https://github.com/ant-design/ant-design/pull/43461) [@MadCcc](https://github.com/MadCcc) +- 🐞 为 Menu 中组件 Token `colorItemBgSelected` 添加废弃警告。[#43461](https://github.com/ant-design/ant-design/pull/43461) - 🐞 杂项:修复样式特性支持检测时部分浏览器因为未重绘导致出现滚动条的问题。[#43358](https://github.com/ant-design/ant-design/pull/43358) [@LeeeeeeM](https://github.com/LeeeeeeM) - 🐞 修复 Card `tabList` 为空时 Tab 完全不展示的问题。[#43416](https://github.com/ant-design/ant-design/pull/43416) [@linxianxi](https://github.com/linxianxi) - 🐞 修复 ConfigProvider 嵌套使用时,`form.validateMessages` 配置会丢失的问题。[#43239](https://github.com/ant-design/ant-design/pull/43239) [@Wxh16144](https://github.com/Wxh16144) - 🐞 修复 Tag 点击的水波纹效果有时候会和 Tag 元素产生偏移的问题。[#43402](https://github.com/ant-design/ant-design/pull/43402) - 🐞 修复 DatePicker 切换到年月面板时,`此刻` 点击无效的问题。[#43367](https://github.com/ant-design/ant-design/pull/43367) [@Yuiai01](https://github.com/Yuiai01) -- 🐞 修复 Input.TextArea 组件在屏幕大小变化时设置的高度失效的问题。[#43169](https://github.com/ant-design/ant-design/pull/43169) [@MadCcc](https://github.com/MadCcc) +- 🐞 修复 Input.TextArea 组件在屏幕大小变化时设置的高度失效的问题。[#43169](https://github.com/ant-design/ant-design/pull/43169) - 💄 Slider 中 `tooltip` 在内容很少时应该居中。[#43430](https://github.com/ant-design/ant-design/pull/43430) [@Jomorx](https://github.com/Jomorx) -- 💄 Design Token 将 `colorLink` 添加至 seed token 中, `colorLinkHover` 和 `colorLinkActive` 将会由 `colorLink` 计算得出。[#43183](https://github.com/ant-design/ant-design/pull/43183) [@MadCcc](https://github.com/MadCcc) +- 💄 Design Token 将 `colorLink` 添加至 seed token 中, `colorLinkHover` 和 `colorLinkActive` 将会由 `colorLink` 计算得出。[#43183](https://github.com/ant-design/ant-design/pull/43183) - 💄 调整 Slider 中部分 token 为 component token。[#42428](https://github.com/ant-design/ant-design/pull/42428) [@heiyu4585](https://github.com/heiyu4585) - RTL - 🤖 Progress 支持 rtl 方向的动画。[#43316](https://github.com/ant-design/ant-design/pull/43316) [@Yuiai01](https://github.com/Yuiai01) @@ -189,7 +379,7 @@ tag: vVERSION - 🐞 修复 Badge `color` 属性不生效的问题。[#43304](https://github.com/ant-design/ant-design/pull/43304) - 🐞 修复 Select 组件的消除图标在 FormItem 设置 `hasFeedback` 时的位置问题。[#43302](https://github.com/ant-design/ant-design/pull/43302) [@tinyfind](https://github.com/tinyfind) - 🐞 修复 Transfer 分页下拉按钮被隐藏以及 `showSizeChanger` 方法无效。[#41906](https://github.com/ant-design/ant-design/pull/41906) [@Yuiai01](https://github.com/Yuiai01) -- 🐞 修复 Popconfirm 组件 `colorText` 和 `fontSize` 修改无效的问题。[#43212](https://github.com/ant-design/ant-design/pull/43212) [@MadCcc](https://github.com/MadCcc) +- 🐞 修复 Popconfirm 组件 `colorText` 和 `fontSize` 修改无效的问题。[#43212](https://github.com/ant-design/ant-design/pull/43212) - 🐞 修复 Upload 配置 `maxCount` 后删除文件不会触发 `onChange` 的问题。[#43193](https://github.com/ant-design/ant-design/pull/43193) - 💄 修复 Button 在有 `link` 或 `href` 属性时禁用样式错误。[#43091](https://github.com/ant-design/ant-design/pull/43091) [@BoyYangzai](https://github.com/BoyYangzai) - TypeScript @@ -251,7 +441,7 @@ tag: vVERSION - 🆕 ColorPicker 添加 `onClear` 属性,清除选中颜色时不自动关闭弹窗。[#42634](https://github.com/ant-design/ant-design/pull/42634) [@linxianxi](https://github.com/linxianxi) - 🆕 Collapse 支持通过 `items` 属性来配置面板内容。[#42545](https://github.com/ant-design/ant-design/pull/42545) [@kiner-tang](https://github.com/kiner-tang) -- 🆕 Design Token 新增静态方法 `getDesignToken` 用于获取完整的主题 token。[#42723](https://github.com/ant-design/ant-design/pull/42723) [@MadCcc](https://github.com/MadCcc) +- 🆕 Design Token 新增静态方法 `getDesignToken` 用于获取完整的主题 token。[#42723](https://github.com/ant-design/ant-design/pull/42723) - 🆕 ConfigProvider 支持配置 Space 组件的 `classNames` 和 `styles` 属性。[#42748](https://github.com/ant-design/ant-design/pull/42748) [@RedJue](https://github.com/RedJue) - 🆕 Space 组件支持 `classNames` 和 `styles` 属性。[#42743](https://github.com/ant-design/ant-design/pull/42743) [@RedJue](https://github.com/RedJue) - 🆕 Drawer 抽屉面板支持事件监听,包裹元素支持传入 `data-*` 属性。[#42718](https://github.com/ant-design/ant-design/pull/42718) [@kiner-tang](https://github.com/kiner-tang) @@ -265,12 +455,12 @@ tag: vVERSION - 🆕 ConfigProvider.config 新增 `theme` 支持配置静态方法主题。[#42473](https://github.com/ant-design/ant-design/pull/42473) - 🆕 Calendar `onSelect` 支持 `info.source` 参数以获取选择来源。[#42432](https://github.com/ant-design/ant-design/pull/42432) - 💄 优化 ColorPicker 组件在暗黑模式下的样式。[#42827](https://github.com/ant-design/ant-design/pull/42827) [@RedJue](https://github.com/RedJue) -- 💄 修复 Popconfirm、Alert 和 Notification 组件 `colorTextHeading` 和 `colorText` 误用问题。[#42839](https://github.com/ant-design/ant-design/pull/42839) [@MadCcc](https://github.com/MadCcc) +- 💄 修复 Popconfirm、Alert 和 Notification 组件 `colorTextHeading` 和 `colorText` 误用问题。[#42839](https://github.com/ant-design/ant-design/pull/42839) - 💄 修复 Divider 组件的样式问题。[#42797](https://github.com/ant-design/ant-design/pull/42797) [@kongmingLatern](https://github.com/kongmingLatern) - 🐞 修复 Image.PreviewGroup 预览时图片切换后状态没有重置的问题。[#42793](https://github.com/ant-design/ant-design/pull/42793) [@linxianxi](https://github.com/linxianxi) - 🐞 统一使用 `rc-util/lib/pickAttrs` 以节省包体积。修复 Rate 组件在 StrictMode 下 `findDOMNode is deprecated` 警告信息。[#42688](https://github.com/ant-design/ant-design/pull/42688) - 🐞 Rate 组件支持传入 `id` `data-*` `aria-*` `role` `onMouseEnter` `onMouseLeave` 等属性,修复不支持 Tooltip 包裹的问题。[#42676](https://github.com/ant-design/ant-design/pull/42676) -- 🐞 修复 Menu 组件横向模式下子菜单没有对齐的问题。[#42648](https://github.com/ant-design/ant-design/pull/42648) [@MadCcc](https://github.com/MadCcc) +- 🐞 修复 Menu 组件横向模式下子菜单没有对齐的问题。[#42648](https://github.com/ant-design/ant-design/pull/42648) - 🐞 将 Card `tabList` 的 API 与 Tab `items` 对齐。[#42413](https://github.com/ant-design/ant-design/pull/42413) - 🐞 修复循环依赖问题。 - 🐞 修复 Modal 组件循环依赖问题。[#42841](https://github.com/ant-design/ant-design/pull/42841) [@kiner-tang](https://github.com/kiner-tang) @@ -281,10 +471,10 @@ tag: vVERSION - ⌨️ 增强 Progress 可访问性表现,添加 `aria` 属性。[#42704](https://github.com/ant-design/ant-design/pull/42704) [@MehmetYararVX](https://github.com/MehmetYararVX) - ⌨️ Notification 添加 `role` 属性。[#42484](https://github.com/ant-design/ant-design/pull/42484) [@guan404ming](https://github.com/guan404ming) - 🛠 Collapse 使用 `onKeyDown` 替代 `onKeyPress` 来改变折叠面板的激活状态。[#42592](https://github.com/ant-design/ant-design/pull/42592) [@kiner-tang](https://github.com/kiner-tang) -- 🛠 使用 `@rc-component/trigger` 重构 Menu 组件。移除 `rc-trigger` 依赖,缩小打包体积。[#42554](https://github.com/ant-design/ant-design/pull/42554) [@MadCcc](https://github.com/MadCcc) +- 🛠 使用 `@rc-component/trigger` 重构 Menu 组件。移除 `rc-trigger` 依赖,缩小打包体积。[#42554](https://github.com/ant-design/ant-design/pull/42554) - 🛠 Table 组件将 `sorterOrder` 重命名为 `sortOrder` 用于 `sortIcon` 的参数。[#42519](https://github.com/ant-design/ant-design/pull/42519) [@sawadyecma](https://github.com/sawadyecma) - 组件 Token 迁移,更多详情请查看文档:[迁移 less 变量](/docs/react/migrate-less-variables-cn) - - 🛠 使用新的命名标准重命名 Menu 组件 token。[#42848](https://github.com/ant-design/ant-design/pull/42848) [@MadCcc](https://github.com/MadCcc) + - 🛠 使用新的命名标准重命名 Menu 组件 token。[#42848](https://github.com/ant-design/ant-design/pull/42848) - 🛠 迁移 Radio 组件 less 变量。[#42050](https://github.com/ant-design/ant-design/pull/42050) [@Yuiai01](https://github.com/Yuiai01) - 🛠 迁移 Image 组件 less 变量。[#42048](https://github.com/ant-design/ant-design/pull/42048) [@guan404ming](https://github.com/guan404ming) - 🛠 迁移 Tooltip 组件 less 变量。[#42046](https://github.com/ant-design/ant-design/pull/42046) [@guan404ming](https://github.com/guan404ming) @@ -316,19 +506,19 @@ tag: vVERSION `2023-05-30` - 🐞 修复 ColorPicker 组件悬停边界问题。[#42669](https://github.com/ant-design/ant-design/pull/42669) [@RedJue](https://github.com/RedJue) -- 🐞 修复 Menu 组件 `overflowedIndicatorClassName` 覆盖了原本的 class 的问题。[#42692](https://github.com/ant-design/ant-design/pull/42692) [@MadCcc](https://github.com/MadCcc) +- 🐞 修复 Menu 组件 `overflowedIndicatorClassName` 覆盖了原本的 class 的问题。[#42692](https://github.com/ant-design/ant-design/pull/42692) - 🐞 修复 Select 组件在某些情况下显示乱码问题。[#42651](https://github.com/ant-design/ant-design/pull/42651) [@895433995](https://github.com/895433995) - 🐞 修复 Card 组件,当 Image 设置 `cover` 属性时,悬停蒙版没有圆角属性,导致 UI 异常。[#42642](https://github.com/ant-design/ant-design/pull/42642) [@iNeedToCopy](https://github.com/iNeedToCopy) -- 🐞 修复 Checkbox 和 label 不对齐的问题。[#42590](https://github.com/ant-design/ant-design/pull/42590) [@MadCcc](https://github.com/MadCcc) +- 🐞 修复 Checkbox 和 label 不对齐的问题。[#42590](https://github.com/ant-design/ant-design/pull/42590) - 🐞 修复使用 ConfigProvider 会导致未使用的 Form 组件也被打包的问题。[#42604](https://github.com/ant-design/ant-design/pull/42604) - 🐞 修复 InputNumber 和其他组件无法基线对齐的问题。[#42580](https://github.com/ant-design/ant-design/pull/42580) -- 🐞 修复 Badge 组件中旋转的 `icon` 动画。[#42575](https://github.com/ant-design/ant-design/pull/42575) [@MadCcc](https://github.com/MadCcc) +- 🐞 修复 Badge 组件中旋转的 `icon` 动画。[#42575](https://github.com/ant-design/ant-design/pull/42575) - 📦 优化 Form `setFieldsValue` 相关代码以降低打包尺寸。[#42635](https://github.com/ant-design/ant-design/pull/42635) - 💄 优化 Image 组件预览组样式。[#42675](https://github.com/ant-design/ant-design/pull/42675) [@kiner-tang](https://github.com/kiner-tang) - 💄 修复 Tag 无边框样式在 `error` 等状态下不生效的问题。[#42619](https://github.com/ant-design/ant-design/pull/42619) [@li-jia-nan](https://github.com/li-jia-nan) - 💄 修复 Table `rowSpan` 悬浮高亮背景颜色丢失的问题。[#42572](https://github.com/ant-design/ant-design/pull/42572) - 💄 修复 Pagination 在禁用状态下 link 图标和 ellipsis hover 时的样式。[#42541](https://github.com/ant-design/ant-design/pull/42541) [@qmhc](https://github.com/qmhc) -- 💄 修复部分全局 Design Token 无法覆盖组件样式的问题。[#42535](https://github.com/ant-design/ant-design/pull/42535) [@MadCcc](https://github.com/MadCcc) +- 💄 修复部分全局 Design Token 无法覆盖组件样式的问题。[#42535](https://github.com/ant-design/ant-design/pull/42535) - 🇱🇹 为 `lt_LT` 添加缺失的部分文案。[#42664](https://github.com/ant-design/ant-design/pull/42664) [@Digital-512](https://github.com/Digital-512) - RTL - 💄 修复 ColorPicker 组件 RTL 模式样式。[#42716](https://github.com/ant-design/ant-design/pull/42716) [@RedJue](https://github.com/RedJue) @@ -338,7 +528,7 @@ tag: vVERSION `2023-05-22` -- 🐞 修复 Button 组件 icon 尺寸和间距问题。[#42516](https://github.com/ant-design/ant-design/pull/42516) [@MadCcc](https://github.com/MadCcc) +- 🐞 修复 Button 组件 icon 尺寸和间距问题。[#42516](https://github.com/ant-design/ant-design/pull/42516) - 🐞 修复 Select 移除和选中按钮不居中的问题。[#42513](https://github.com/ant-design/ant-design/pull/42513) - 🐞 重构 Popconfirm DOM 结构以解决 `icon={null}` 时 `title` 和 `description` 的多余 margin 问题。[#42433](https://github.com/ant-design/ant-design/pull/42433) - 🐞 修复 Menu 图标在 `itemMarginInline` 为 0 时不居中的问题。[#42426](https://github.com/ant-design/ant-design/pull/42426) [@zzwgh](https://github.com/zzwgh) @@ -447,7 +637,7 @@ tag: vVERSION `2023-04-19` - 🐞 修复 FloatButton 警告: findDOMNode is deprecated in StrictMode.。[#41833](https://github.com/ant-design/ant-design/pull/41833) [@fourcels](https://github.com/fourcels) -- 🐞 杂项:箭头元素兼容旧版本不支持 `clip-path: path()` 的浏览器。 [#41872](https://github.com/ant-design/ant-design/pull/41872) +- 🐞 杂项:箭头元素兼容旧版本不支持 `clip-path: path()` 的浏览器。[#41872](https://github.com/ant-design/ant-design/pull/41872) - 🐞 修复 Layout.Sider 切换主题时存在背景切换延迟的问题。[#41828](https://github.com/ant-design/ant-design/pull/41828) - 🐞 修复 Tour 的 `type="primary"` 时箭头的颜色仍为白色的问题。[#41761](https://github.com/ant-design/ant-design/pull/41761) - 🐞 优化 Form 字段绑定,现在会忽略在 Form.Item 内的注释不再作为子组件进行绑定。[#41771](https://github.com/ant-design/ant-design/pull/41771) @@ -775,7 +965,7 @@ tag: vVERSION `2023-01-15` -- 🐞 修复 Checkbox 组件 label 不对齐的问题。 [#40208](https://github.com/ant-design/ant-design/pull/40208) +- 🐞 修复 Checkbox 组件 label 不对齐的问题。[#40208](https://github.com/ant-design/ant-design/pull/40208) - 🐞 修复 Button 水波纹效果有时会使得布局抖动的问题。[#40192](https://github.com/ant-design/ant-design/pull/40192) - 🐞 修复 Select 组件会卡住的问题。[#40158](https://github.com/ant-design/ant-design/pull/40158) [@helloqian12138](https://github.com/helloqian12138) - 🐞 修复 Timeline 组件自定义颜色显示错误类名和对齐溢出的问题。[#39394](https://github.com/ant-design/ant-design/pull/39394) [@Wxh16144](https://github.com/Wxh16144) @@ -862,7 +1052,7 @@ tag: vVERSION - 🐞 修复 Card 只有 `extra` 时标题栏高度不足的问题。[#39646](https://github.com/ant-design/ant-design/pull/39646) [@JarvisArt](https://github.com/JarvisArt) - 🐞 修复 Row 组件 `justify` 和 `align` 属性,动态改变不生效的问题。[#39704](https://github.com/ant-design/ant-design/pull/39704) [@candy4290](https://github.com/candy4290) - 🐞 修复 App 中 `children` 使用相同 key 的警告。[#39695](https://github.com/ant-design/ant-design/pull/39695) [@Kamahl19](https://github.com/Kamahl19),[#39701](https://github.com/ant-design/ant-design/pull/39701) [@li-jia-nan](https://github.com/li-jia-nan) -- 💄 Image 组件预览交互优化. [#39812](https://github.com/ant-design/ant-design/pull/39812) [@JarvisArt](https://github.com/JarvisArt) +- 💄 Image 组件预览交互优化。[#39812](https://github.com/ant-design/ant-design/pull/39812) [@JarvisArt](https://github.com/JarvisArt) - 💄 修复 Table 筛选菜单选中背景色和菜单阴影样式。[#39805](https://github.com/ant-design/ant-design/pull/39805) - TypeScript - 🤖 修复部分 Design Token 缺少类型提示的问题。[#39754](https://github.com/ant-design/ant-design/pull/39754) diff --git a/README-ar_EG.md b/README-ar_EG.md deleted file mode 100644 index e36cf43d15c8..000000000000 --- a/README-ar_EG.md +++ /dev/null @@ -1,155 +0,0 @@ -

- - - -

- -

Ant Design

- -
- -لغة تصميم واجهة المستخدم على مستوى المؤسسات ومكتبة React UI. - -[![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] [![NPM version][npm-image]][npm-url] [![NPM downloads][download-image]][download-url] - -[![][bundlephobia-image]][bundlephobia-url] [![][bundlesize-js-image]][unpkg-js-url] [![FOSSA Status][fossa-image]][fossa-url] - -[![Follow Twitter][twitter-image]][twitter-url] [![Renovate status][renovate-image]][renovate-dashboard-url] [![][issues-helper-image]][issues-helper-url] [![dumi][dumi-image]][dumi-url] [![Issues need help][help-wanted-image]][help-wanted-url] - -[npm-image]: http://img.shields.io/npm/v/antd.svg?style=flat-square -[npm-url]: http://npmjs.org/package/antd -[github-action-image]: https://github.com/ant-design/ant-design/workflows/%E2%9C%85%20test/badge.svg -[github-action-url]: https://github.com/ant-design/ant-design/actions?query=workflow%3A%22%E2%9C%85+test%22 -[codecov-image]: https://img.shields.io/codecov/c/github/ant-design/ant-design/master.svg?style=flat-square -[codecov-url]: https://codecov.io/gh/ant-design/ant-design/branch/master -[download-image]: https://img.shields.io/npm/dm/antd.svg?style=flat-square -[download-url]: https://npmjs.org/package/antd -[fossa-image]: https://app.fossa.io/api/projects/git%2Bgithub.com%2Fant-design%2Fant-design.svg?type=shield -[fossa-url]: https://app.fossa.io/projects/git%2Bgithub.com%2Fant-design%2Fant-design?ref=badge_shield -[help-wanted-image]: https://flat.badgen.net/github/label-issues/ant-design/ant-design/help%20wanted/open -[help-wanted-url]: https://github.com/ant-design/ant-design/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22 -[twitter-image]: https://img.shields.io/twitter/follow/AntDesignUI.svg?label=Ant%20Design -[twitter-url]: https://twitter.com/AntDesignUI -[bundlesize-js-image]: https://img.badgesize.io/https:/unpkg.com/antd/dist/antd.min.js?label=antd.min.js&compression=gzip&style=flat-square -[unpkg-js-url]: https://unpkg.com/browse/antd/dist/antd.min.js -[bundlephobia-image]: https://badgen.net/bundlephobia/minzip/antd?style=flat-square -[bundlephobia-url]: https://bundlephobia.com/package/antd -[issues-helper-image]: https://img.shields.io/badge/using-issues--helper-orange?style=flat-square -[issues-helper-url]: https://github.com/actions-cool/issues-helper -[renovate-image]: https://img.shields.io/badge/renovate-enabled-brightgreen.svg?style=flat-square -[renovate-dashboard-url]: https://github.com/ant-design/ant-design/issues/32498 -[dumi-image]: https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square -[dumi-url]: https://github.com/umijs/dumi - -
- -[![](https://user-images.githubusercontent.com/507615/209472919-6f7e8561-be8c-4b0b-9976-eb3c692aa20a.png)](https://ant.design) - -[English](./README.md) | [Português](./README-pt_BR.md) | [简体中文](./README-zh_CN.md) | [Українською](./README-uk_UA.md) | [Spanish](./README-sp_MX.md) | [日本語](./README-ja_JP.md) | العربية - -## ✨ الميزات - -- 🌈 واجهة مستخدم من فئة المؤسسات مصممة لتطبيقات الويب. -- 📦 مجموعة من مكونات React عالية الجودة خارج الصندوق. -- 🛡 مكتوب في TypeScript بأنواع ثابتة يمكن التنبؤ بها. -- ⚙️ مجموعة كاملة من موارد التصميم وأدوات التطوير. -- 🌍 دعم التدويل لعشرات اللغات. -- 🎨 تخصيص موضوع قوي على أساس CSS-in-JS. - -## 🖥 دعم البيئة البرمجية - -- المتصفحات الحديثة -- التقديم من جانب الخادم -- [إلكترون](https://www.electronjs.org/) - -| [Edge](http://godban.github.io/browsers-support-badges/)
Edge | [Firefox](http://godban.github.io/browsers-support-badges/)
Firefox | [Chrome](http://godban.github.io/browsers-support-badges/)
Chrome | [Safari](http://godban.github.io/browsers-support-badges/)
Safari | [Electron](http://godban.github.io/browsers-support-badges/)
Electron | -| --- | --- | --- | --- | --- | -| Edge | last 2 versions | last 2 versions | last 2 versions | last 2 versions | - -## 📦 التثبيت - -```bash -npm install antd -``` - -```bash -yarn add antd -``` - -## 🔨 الاستخدام - -```jsx -import React from 'react'; -import { Button, DatePicker } from 'antd'; - -const App = () => ( - <> - - - -); -``` - -### كتابة السكربيت - -الخاصية `antd` مكتوبة في TypeScript مع تعريفات كاملة ، تحقق [Use in TypeScript](https://ant.design/docs/react/use-in-typescript) للبدء. - -## 🌍 التدويل - -يتم دعم عشرات اللغات في`antd`, انظر [i18n](https://ant.design/docs/react/i18n). - -## 🔗 الروابط - -- [الصفحة الرئيسية](https://ant.design/) -- [نظرة عامة على المكونات](https://ant.design/components/overview) -- [برنامج Ant Design Pro](https://pro.ant.design/) -- [تغير الدخول](CHANGELOG.en-US.md) -- [مكونات](https://react-component.github.io/) -- [موبايل UI](https://mobile.ant.design) -- [برنامج صغير UI](https://mini.ant.design) -- [مكونات Ant Design Pro](https://procomponents.ant.design) -- [رسوم بيانية Ant Design](https://charts.ant.design) -- [أيقونات Ant Design](https://github.com/ant-design/ant-design-icons) -- [ألوان Ant Design](https://github.com/ant-design/ant-design-colors) -- [صفحة لاند](https://landing.ant.design) -- [حركة](https://motion.ant.design) -- [سوق Scaffold](https://scaffold.ant.design) -- [تعليمات المطورين](https://github.com/ant-design/ant-design/wiki/Development) -- [إعداد نسخ الاصدارات](https://github.com/ant-design/ant-design/wiki/%E8%BD%AE%E5%80%BC%E8%A7%84%E5%88%99%E5%92%8C%E7%89%88%E6%9C%AC%E5%8F%91%E5%B8%83%E6%B5%81%E7%A8%8B) -- [أسئلة مكرة](https://ant.design/docs/react/faq) -- [قالب CodeSandbox](https://u.ant.design/codesandbox-repro) -- [تخصيص ثيم](https://ant.design/docs/react/customize-theme) -- [كيفية التقدم بطلب المشاركة كمتعاون](https://github.com/ant-design/ant-design/wiki/Collaborators#how-to-apply-for-being-a-collaborator) - -## ⌨️ التطوير - -استخدم Gitpod, بيئة تطوير مجانية عبر الإنترنت لـ GitHub. - -[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/ant-design/ant-design) - -أو انسخه محلياً: - -```bash -$ git clone git@github.com:ant-design/ant-design.git -$ cd ant-design -$ npm install -$ npm start -``` - -افتح متصفحك وقم بزيارة http://127.0.0.1:8001 , شاهد المزيد [Development](https://github.com/ant-design/ant-design/wiki/Development). - -## 🤝 المساهمة [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) - -أقرأ [دليل المساهمة](https://ant.design/docs/react/contributing) ودعونا نبني معاً الأفضل. - -نرحب بجميع المساهمات. يرجى قراءة [CONTRIBUTING.md](https://github.com/ant-design/ant-design/blob/master/.github/CONTRIBUTING.md) أولاً. يمكنك تقديم أي أفكار [pull requests](https://github.com/ant-design/ant-design/pulls) أو [GitHub issues](https://github.com/ant-design/ant-design/issues). إذا كنت ترغب في تحسين التعليمات البرمجية ، تحقق من [Development Instructions](https://github.com/ant-design/ant-design/wiki/Development) وأتمنى لك وقتاً ممتعاً! :) - -إذا كنت مساهماً ، فيرجى اتباع [Pull Request principle](https://github.com/ant-design/ant-design/wiki/PR-principle) لإنشاء طلب مساهمة مع [collaborator template](https://github.com/ant-design/ant-design/compare?expand=1&template=collaborator.md). - -[![Let's fund issues in this repository](https://issuehunt.io/static/embed/issuehunt-button-v1.svg)](https://issuehunt.io/repos/34526884) - -## ❤️ الرعاة والداعمون [![](https://opencollective.com/ant-design/tiers/sponsors/badge.svg?label=Sponsors&color=brightgreen)](https://opencollective.com/ant-design#support) [![](https://opencollective.com/ant-design/tiers/backers/badge.svg?label=Backers&color=brightgreen)](https://opencollective.com/ant-design#support) - -[![](https://opencollective.com/ant-design/tiers/sponsors.svg?avatarHeight=36)](https://opencollective.com/ant-design#support) - -[![](https://opencollective.com/ant-design/tiers/backers.svg?avatarHeight=36)](https://opencollective.com/ant-design#support) diff --git a/README-ja_JP.md b/README-ja_JP.md deleted file mode 100644 index 94424a959318..000000000000 --- a/README-ja_JP.md +++ /dev/null @@ -1,155 +0,0 @@ -

- - - -

- -

Ant Design

- -
- -エンタープライズクラスの UI 設計言語と React UI ライブラリです。 - -[![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] [![NPM version][npm-image]][npm-url] [![NPM downloads][download-image]][download-url] - -[![][bundlephobia-image]][bundlephobia-url] [![][bundlesize-js-image]][unpkg-js-url] [![FOSSA Status][fossa-image]][fossa-url] - -[![Follow Twitter][twitter-image]][twitter-url] [![Renovate status][renovate-image]][renovate-dashboard-url] [![][issues-helper-image]][issues-helper-url] [![dumi][dumi-image]][dumi-url] [![Issues need help][help-wanted-image]][help-wanted-url] - -[npm-image]: http://img.shields.io/npm/v/antd.svg?style=flat-square -[npm-url]: http://npmjs.org/package/antd -[github-action-image]: https://github.com/ant-design/ant-design/workflows/%E2%9C%85%20test/badge.svg -[github-action-url]: https://github.com/ant-design/ant-design/actions?query=workflow%3A%22%E2%9C%85+test%22 -[codecov-image]: https://img.shields.io/codecov/c/github/ant-design/ant-design/master.svg?style=flat-square -[codecov-url]: https://codecov.io/gh/ant-design/ant-design/branch/master -[download-image]: https://img.shields.io/npm/dm/antd.svg?style=flat-square -[download-url]: https://npmjs.org/package/antd -[fossa-image]: https://app.fossa.io/api/projects/git%2Bgithub.com%2Fant-design%2Fant-design.svg?type=shield -[fossa-url]: https://app.fossa.io/projects/git%2Bgithub.com%2Fant-design%2Fant-design?ref=badge_shield -[help-wanted-image]: https://flat.badgen.net/github/label-issues/ant-design/ant-design/help%20wanted/open -[help-wanted-url]: https://github.com/ant-design/ant-design/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22 -[twitter-image]: https://img.shields.io/twitter/follow/AntDesignUI.svg?label=Ant%20Design -[twitter-url]: https://twitter.com/AntDesignUI -[bundlesize-js-image]: https://img.badgesize.io/https:/unpkg.com/antd/dist/antd.min.js?label=antd.min.js&compression=gzip&style=flat-square -[unpkg-js-url]: https://unpkg.com/browse/antd/dist/antd.min.js -[bundlephobia-image]: https://badgen.net/bundlephobia/minzip/antd?style=flat-square -[bundlephobia-url]: https://bundlephobia.com/package/antd -[issues-helper-image]: https://img.shields.io/badge/using-issues--helper-orange?style=flat-square -[issues-helper-url]: https://github.com/actions-cool/issues-helper -[renovate-image]: https://img.shields.io/badge/renovate-enabled-brightgreen.svg?style=flat-square -[renovate-dashboard-url]: https://github.com/ant-design/ant-design/issues/32498 -[dumi-image]: https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square -[dumi-url]: https://github.com/umijs/dumi - -
- -[![](https://user-images.githubusercontent.com/507615/209472919-6f7e8561-be8c-4b0b-9976-eb3c692aa20a.png)](https://ant.design) - -[English](./README.md) | [Português](./README-pt_BR.md) | [简体中文](./README-zh_CN.md) | [Українською](./README-uk_UA.md) | [Spanish](./README-sp_MX.md) | 日本語 | [العربية](./README-ar_EG.md) - -## ✨ 機能 - -- 🌈 ウェブアプリケーション用に設計されたエンタープライズクラスの UI。 -- 📦 高品質な React コンポーネントのセットが箱から出されます。 -- 🛡 TypeScript で書かれており、予測可能な静的型がある。 -- ⚙️ デザインリソースと開発ツールの全体的なパッケージ。 -- 🌍 数十の言語に対応した国際化サポート。 -- 🎨 強力なテーマのカスタマイズを細部にわたって実現。 - -## 🖥 環境対応 - -- モダンブラウザ -- サーバーサイド レンダリング -- [Electron](https://www.electronjs.org/) - -| [Edge](http://godban.github.io/browsers-support-badges/)
Edge | [Firefox](http://godban.github.io/browsers-support-badges/)
Firefox | [Chrome](http://godban.github.io/browsers-support-badges/)
Chrome | [Safari](http://godban.github.io/browsers-support-badges/)
Safari | [Electron](http://godban.github.io/browsers-support-badges/)
Electron | -| --- | --- | --- | --- | --- | -| Edge | 直近の 2 バージョン | 直近の 2 バージョン | 直近の 2 バージョン | 直近の 2 バージョン | - -## 📦 インストール - -```bash -npm install antd -``` - -```bash -yarn add antd -``` - -## 🔨 使い方 - -```jsx -import React from 'react'; -import { Button, DatePicker } from 'antd'; - -const App = () => ( - <> - - - -); -``` - -### TypeScript - -`antd` は TypeScript で書かれており、完全な定義がなされています。まずは [TypeScript で使う](https://ant.design/docs/react/use-in-typescript)をチェックしてください。 - -## 🌍 国際化対応 - -数十の言語が `antd` でサポートされています。[i18n](https://ant.design/docs/react/i18n) を参照してください。 - -## 🔗 リンク - -- [ホームページ](https://ant.design/) -- [コンポーネントの概要](https://ant.design/components/overview) -- [Ant Design Pro](http://pro.ant.design/) -- [変更ログ](CHANGELOG.en-US.md) -- [rc-components](http://react-component.github.io/) -- [Mobile UI](http://mobile.ant.design) -- [Mini Program UI](http://mini.ant.design) -- [Ant Design Pro コンポーネント](https://procomponents.ant.design) -- [Ant Design チャート](https://charts.ant.design) -- [Ant Design アイコン](https://github.com/ant-design/ant-design-icons) -- [Ant Design カラー](https://github.com/ant-design/ant-design-colors) -- [ランディングページ](https://landing.ant.design) -- [動作](https://motion.ant.design) -- [足場マーケット](http://scaffold.ant.design) -- [開発者向けインストラクション](https://github.com/ant-design/ant-design/wiki/Development) -- [バージョン管理リリースノート](https://github.com/ant-design/ant-design/wiki/%E8%BD%AE%E5%80%BC%E8%A7%84%E5%88%99%E5%92%8C%E7%89%88%E6%9C%AC%E5%8F%91%E5%B8%83%E6%B5%81%E7%A8%8B) -- [FAQ](https://ant.design/docs/react/faq) -- バグレポート用の [CodeSandbox テンプレート](https://u.ant.design/codesandbox-repro) -- [テーマのカスタマイズ](https://ant.design/docs/react/customize-theme) -- [コラボレーターへの応募方法](https://github.com/ant-design/ant-design/wiki/Collaborators#how-to-apply-for-being-a-collaborator) - -## ⌨️ 開発 - -GitHub の無料オンライン開発環境である Gitpod を利用する。 - -[![Gitpod で開く](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/ant-design/ant-design) - -またはローカルにクローンする: - -```bash -$ git clone git@github.com:ant-design/ant-design.git -$ cd ant-design -$ npm install -$ npm start -``` - -ブラウザを起動し、http://127.0.0.1:8001 にアクセスして[開発セクション](https://github.com/ant-design/ant-design/wiki/Development)の続きをもっと見る. - -## 🤝 貢献 [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) - -[貢献ガイド](https://ant.design/docs/react/contributing)を読んで、よりよい antd を一緒の作り上げましょう。 - -すべての貢献に感謝します。まずは [CONTRIBUTING.md](https://github.com/ant-design/ant-design/blob/master/.github/CONTRIBUTING.md) をお読みください. どんなアイデアも [Pull Request](https://github.com/ant-design/ant-design/pulls) や [GitHub issues](https://github.com/ant-design/ant-design/issues) で応募することができます. コードの改良をしたい方は、[開発手順](https://github.com/ant-design/ant-design/wiki/Development) を確認してください。あとは楽しみましょう! :) - -コラボレーターの方は、[コラボレーター テンプレート](https://github.com/ant-design/ant-design/compare?expand=1&template=collaborator.md)を使い、Pull Request を作成するための[プルリクエストの原則](https://github.com/ant-design/ant-design/wiki/PR-principle)に従ってください。 - -[![このレポジトリの課題に資金を提供しよう](https://issuehunt.io/static/embed/issuehunt-button-v1.svg)](https://issuehunt.io/repos/34526884) - -## ❤️ スポンサーと後援者 [![](https://opencollective.com/ant-design/tiers/sponsors/badge.svg?label=Sponsors&color=brightgreen)](https://opencollective.com/ant-design#support) [![](https://opencollective.com/ant-design/tiers/backers/badge.svg?label=Backers&color=brightgreen)](https://opencollective.com/ant-design#support) - -[![](https://opencollective.com/ant-design/tiers/sponsors.svg?avatarHeight=36)](https://opencollective.com/ant-design#support) - -[![](https://opencollective.com/ant-design/tiers/backers.svg?avatarHeight=36)](https://opencollective.com/ant-design#support) diff --git a/README-pt_BR.md b/README-pt_BR.md deleted file mode 100644 index a267d27d70d8..000000000000 --- a/README-pt_BR.md +++ /dev/null @@ -1,158 +0,0 @@ -

- - - -

- -

Ant Design

- -
- -Uma solução empresarial de design e biblioteca UI para React. - -[![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] [![NPM version][npm-image]][npm-url] [![NPM downloads][download-image]][download-url] - -[![][bundlephobia-image]][bundlephobia-url] [![][bundlesize-js-image]][unpkg-js-url] [![FOSSA Status][fossa-image]][fossa-url] - -[![Follow Twitter][twitter-image]][twitter-url] [![Renovate status][renovate-image]][renovate-dashboard-url] [![][issues-helper-image]][issues-helper-url] [![dumi][dumi-image]][dumi-url] [![Issues need help][help-wanted-image]][help-wanted-url] - -[npm-image]: http://img.shields.io/npm/v/antd.svg?style=flat-square -[npm-url]: http://npmjs.org/package/antd -[github-action-image]: https://github.com/ant-design/ant-design/workflows/%E2%9C%85%20test/badge.svg -[github-action-url]: https://github.com/ant-design/ant-design/actions?query=workflow%3A%22%E2%9C%85+test%22 -[codecov-image]: https://img.shields.io/codecov/c/github/ant-design/ant-design/master.svg?style=flat-square -[codecov-url]: https://codecov.io/gh/ant-design/ant-design/branch/master -[download-image]: https://img.shields.io/npm/dm/antd.svg?style=flat-square -[download-url]: https://npmjs.org/package/antd -[fossa-image]: https://app.fossa.io/api/projects/git%2Bgithub.com%2Fant-design%2Fant-design.svg?type=shield -[fossa-url]: https://app.fossa.io/projects/git%2Bgithub.com%2Fant-design%2Fant-design?ref=badge_shield -[help-wanted-image]: https://flat.badgen.net/github/label-issues/ant-design/ant-design/help%20wanted/open -[help-wanted-url]: https://github.com/ant-design/ant-design/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22 -[twitter-image]: https://img.shields.io/twitter/follow/AntDesignUI.svg?label=Ant%20Design -[twitter-url]: https://twitter.com/AntDesignUI -[bundlesize-js-image]: https://img.badgesize.io/https:/unpkg.com/antd/dist/antd.min.js?label=antd.min.js&compression=gzip&style=flat-square -[unpkg-js-url]: https://unpkg.com/browse/antd/dist/antd.min.js -[bundlephobia-image]: https://badgen.net/bundlephobia/minzip/antd?style=flat-square -[bundlephobia-url]: https://bundlephobia.com/package/antd -[issues-helper-image]: https://img.shields.io/badge/using-issues--helper-orange?style=flat-square -[issues-helper-url]: https://github.com/actions-cool/issues-helper -[renovate-image]: https://img.shields.io/badge/renovate-enabled-brightgreen.svg?style=flat-square -[renovate-dashboard-url]: https://github.com/ant-design/ant-design/issues/32498 -[dumi-image]: https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square -[dumi-url]: https://github.com/umijs/dumi - -
- -[![](https://user-images.githubusercontent.com/507615/209472919-6f7e8561-be8c-4b0b-9976-eb3c692aa20a.png)](https://ant.design) - -[English](./README.md) | Português | [简体中文](./README-zh_CN.md) | [Українською](./README-uk_UA.md) | [Spanish](./README-sp_MX.md) | [日本語](./README-ja_JP.md) | [العربية](./README-ar_EG.md) - -## ✨ Funcionalidades - -- 🌈 Design empresarial de interface para aplicações web. -- 📦 Um conjunto de alta qualidade, componentes React prontos para uso. -- 🛡 Escrito em TypeScript com tipos previsíveis. -- ⚙️ Pacote completo de recursos de design e ferramentas de desenvolvimento. -- 🌍 Suporte de internacionalização para dezenas de idiomas. -- 🎨 Personalização poderosa do tema em todos os detalhes. - -## 🖥 Suporte aos ambientes - -- Navegadores modernos -- Renderização no lado do servidor (server-side) -- [Electron](https://www.electronjs.org/) - -| [Edge](http://godban.github.io/browsers-support-badges/)
Edge | [Firefox](http://godban.github.io/browsers-support-badges/)
Firefox | [Chrome](http://godban.github.io/browsers-support-badges/)
Chrome | [Safari](http://godban.github.io/browsers-support-badges/)
Safari | [Opera](http://godban.github.io/browsers-support-badges/)
Opera | [Electron](http://godban.github.io/browsers-support-badges/)
Electron | -| --- | --- | --- | --- | --- | --- | -| Edge | últimas 2 versões | últimas 2 versões | últimas 2 versões | últimas 2 versões | últimas 2 versões | - -## 📦 Instalação - -```bash -npm install antd -``` - -```bash -yarn add antd -``` - -## 🔨 Uso - -```jsx -import React from 'react'; -import { Button, DatePicker } from 'antd'; - -const App = () => ( - <> - - - -); -``` - -### TypeScript - -Veja [Uso no Typescript](https://ant.design/docs/react/use-in-typescript). - -## 🌍 Internacionalização - -Veja [i18n](https://ant.design/docs/react/i18n). - -## 🔗 Links - -- [Página inicial](https://ant.design/) -- [Componentes](https://ant.design/components/overview) -- [Ant Design Pro](http://pro.ant.design/) -- [Ant Design Charts](https://charts.ant.design) -- [Change Log](CHANGELOG.en-US.md) -- [rc-components](http://react-component.github.io/) -- [Mobile UI](http://mobile.ant.design) -- [Mini Program UI](http://mini.ant.design) -- [Ant Design Icones](https://github.com/ant-design/ant-design-icons) -- [Ant Design Cores](https://github.com/ant-design/ant-design-colors) -- [Ant Design Pro Layout](https://github.com/ant-design/ant-design-pro-layout) -- [Ant Design Pro Blocks](https://github.com/ant-design/pro-blocks) -- [Tema escuro](https://github.com/ant-design/ant-design-dark-theme) -- [Página de aterrissagem](https://landing.ant.design) -- [Motion](https://motion.ant.design) -- [Mercado de páginas](http://scaffold.ant.design) -- [Instruções ao desenvolvedor](https://github.com/ant-design/ant-design/wiki/Development) -- [Versionando as notas de atualização](https://github.com/ant-design/ant-design/wiki/%E8%BD%AE%E5%80%BC%E8%A7%84%E5%88%99%E5%92%8C%E7%89%88%E6%9C%AC%E5%8F%91%E5%B8%83%E6%B5%81%E7%A8%8B) -- [FAQ](https://ant.design/docs/react/faq) -- [CodeSandbox Template](https://u.ant.design/codesandbox-repro) para relatório de erros -- [Awesome Ant Design](https://github.com/websemantics/awesome-ant-design) -- [Customize Theme](https://ant.design/docs/react/customize-theme) -- [How to Apply for Being A Collaborator](https://github.com/ant-design/ant-design/wiki/Collaborators#how-to-apply-for-being-a-collaborator) - -## ⌨️ Desenvolvimento - -Use Gitpod, um ambiente de desenvolvimento online para GitHub. - -[![Abrir no Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/ant-design/ant-design) - -Ou clone localmente: - -```bash -$ git clone git@github.com:ant-design/ant-design.git -$ cd ant-design -$ npm install -$ npm start -``` - -Abra seu navegador e visite http://127.0.0.1:8001, veja mais em [Desenvolvimento](https://github.com/ant-design/ant-design/wiki/Development). - -## 🤝 Contribuição [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) - -Leia nosso [guia de contribução](https://ant.design/docs/react/contributing) e vamos contruir um melhor antd juntos. - -Nós saudamos todas as contribuições. Por favor, leia nosso [CONTRIBUTING.md](https://github.com/ant-design/ant-design/blob/master/.github/CONTRIBUTING.md) primeiro. Você pode submeter todas as ideias como [Pull Requests](https://github.com/ant-design/ant-design/pulls) ou como [GitHub issues](https://github.com/ant-design/ant-design/issues). Se você quiser melhorar o código, verifique [instruções ao desenvolvedor](https://github.com/ant-design/ant-design/wiki/Development) e divirta-se! :) - -Se você é um colaborador, por favor siga nossa [Pull Request princípio](https://github.com/ant-design/ant-design/wiki/PR-principle) para criar um Pull Request através do [template do colaborador](https://github.com/ant-design/ant-design/compare?expand=1&template=collaborator.md). - -[![Let's fund issues in this repository](https://issuehunt.io/static/embed/issuehunt-button-v1.svg)](https://issuehunt.io/repos/34526884) - -## ❤️ Patrocionadores e Apoiadores [![](https://opencollective.com/ant-design/tiers/sponsors/badge.svg?label=Sponsors&color=brightgreen)](https://opencollective.com/ant-design#support) [![](https://opencollective.com/ant-design/tiers/backers/badge.svg?label=Backers&color=brightgreen)](https://opencollective.com/ant-design#support) - -[![](https://opencollective.com/ant-design/tiers/sponsors.svg?avatarHeight=36)](https://opencollective.com/ant-design#support) - -[![](https://opencollective.com/ant-design/tiers/backers.svg?avatarHeight=36)](https://opencollective.com/ant-design#support) diff --git a/README-sp_MX.md b/README-sp_MX.md deleted file mode 100644 index 0e2298117733..000000000000 --- a/README-sp_MX.md +++ /dev/null @@ -1,154 +0,0 @@ -

- - - -

- -

Ant Design

- -
- -Un lenguaje de diseño de interfaz de usuario de clase empresarial y una biblioteca de interfaz de usuario React. - -[![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] [![NPM version][npm-image]][npm-url] [![NPM downloads][download-image]][download-url] - -[![][bundlephobia-image]][bundlephobia-url] [![][bundlesize-js-image]][unpkg-js-url] [![FOSSA Status][fossa-image]][fossa-url] - -[![Follow Twitter][twitter-image]][twitter-url] [![Renovate status][renovate-image]][renovate-dashboard-url] [![][issues-helper-image]][issues-helper-url] [![dumi][dumi-image]][dumi-url] [![Issues need help][help-wanted-image]][help-wanted-url] - -[npm-image]: http://img.shields.io/npm/v/antd.svg?style=flat-square -[npm-url]: http://npmjs.org/package/antd -[github-action-image]: https://github.com/ant-design/ant-design/workflows/%E2%9C%85%20test/badge.svg -[github-action-url]: https://github.com/ant-design/ant-design/actions?query=workflow%3A%22%E2%9C%85+test%22 -[codecov-image]: https://img.shields.io/codecov/c/github/ant-design/ant-design/master.svg?style=flat-square -[codecov-url]: https://codecov.io/gh/ant-design/ant-design/branch/master -[download-image]: https://img.shields.io/npm/dm/antd.svg?style=flat-square -[download-url]: https://npmjs.org/package/antd -[fossa-image]: https://app.fossa.io/api/projects/git%2Bgithub.com%2Fant-design%2Fant-design.svg?type=shield -[fossa-url]: https://app.fossa.io/projects/git%2Bgithub.com%2Fant-design%2Fant-design?ref=badge_shield -[help-wanted-image]: https://flat.badgen.net/github/label-issues/ant-design/ant-design/help%20wanted/open -[help-wanted-url]: https://github.com/ant-design/ant-design/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22 -[twitter-image]: https://img.shields.io/twitter/follow/AntDesignUI.svg?label=Ant%20Design -[twitter-url]: https://twitter.com/AntDesignUI -[bundlesize-js-image]: https://img.badgesize.io/https:/unpkg.com/antd/dist/antd.min.js?label=antd.min.js&compression=gzip&style=flat-square -[unpkg-js-url]: https://unpkg.com/browse/antd/dist/antd.min.js -[bundlephobia-image]: https://badgen.net/bundlephobia/minzip/antd?style=flat-square -[bundlephobia-url]: https://bundlephobia.com/package/antd -[issues-helper-image]: https://img.shields.io/badge/using-issues--helper-orange?style=flat-square -[issues-helper-url]: https://github.com/actions-cool/issues-helper -[renovate-image]: https://img.shields.io/badge/renovate-enabled-brightgreen.svg?style=flat-square -[renovate-dashboard-url]: https://github.com/ant-design/ant-design/issues/32498 -[dumi-image]: https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square -[dumi-url]: https://github.com/umijs/dumi - -
- -[![](https://user-images.githubusercontent.com/507615/209472919-6f7e8561-be8c-4b0b-9976-eb3c692aa20a.png)](https://ant.design) - -[English](./README.md) | [Português](./README-pt_BR.md) | [简体中文](./README-zh_CN.md) | [Українською](./README-uk_UA.md) | Spanish | [日本語](./README-ja_JP.md) | [العربية](./README-ar_EG.md) - -## ✨ Características - -- 🌈 Interfaz de usuario de clase empresarial diseñada para aplicaciones de web -- 📦 Un conjunto de componentes React de alta calidad listos para usar. -- 🛡 Escrito en TypeScript con tipos estáticos predecibles. -- ⚙️ Paquete completo de recursos de diseño y herramientas de desarrollo. -- 🌍 Soporte de internacionalización para decenas de idiomas. -- 🎨 Potente personalización del tema en cada detalle. - -## 🖥 Entornos soportados - -- Navegadores modernos -- Representación del lado del servidor -- [Electron](https://www.electronjs.org/) - -| [Edge](http://godban.github.io/browsers-support-badges/)
Edge | [Firefox](http://godban.github.io/browsers-support-badges/)
Firefox | [Chrome](http://godban.github.io/browsers-support-badges/)
Chrome | [Safari](http://godban.github.io/browsers-support-badges/)
Safari | [Electron](http://godban.github.io/browsers-support-badges/)
Electron | -| --- | --- | --- | --- | --- | -| Edge | últimas 2 versiones | últimas 2 versiones | últimas 2 versiones | últimas 2 versiones | - -## 📦 Instalar - -```bash -npm install antd -``` - -```bash -yarn add antd -``` - -## 🔨 Uso - -```jsx -import React from 'react'; -import { Button, DatePicker } from 'antd'; - -const App = () => ( - <> - - - -); -``` - -### TypeScript - -`antd` está escrito en TypeScript con definiciones completas, ver Usar en TypeScript [Usar en TypeScript](https://ant.design/docs/react/use-in-typescript) para comenzar. - -## 🌍 Internacionalización - -Docenas de idiomas compatibles en `antd`, ver [i18n](https://ant.design/docs/react/i18n). - -## 🔗 Enlaces - -- [Página de Inicio](https://ant.design/) -- [Descripción General de los Componentes](https://ant.design/components/overview) -- [Ant Design Pro](http://pro.ant.design/) -- [Cambio de Registro](CHANGELOG.en-US.md) -- [componentes-rc](http://react-component.github.io/) -- [Interfaz de Usuario Móvil](http://mobile.ant.design) -- [Componentes Ant Design Pro](https://procomponents.ant.design) -- [Gráficos de Diseño de Ant Design](https://charts.ant.design) -- [Iconos de Diseño de Ant Design](https://github.com/ant-design/ant-design-icons) -- [Colores de Diseño de Ant Design](https://github.com/ant-design/ant-design-colors) -- [Páginas de Destino](https://landing.ant.design) -- [Movimiento](https://motion.ant.design) -- [Mercado Scaffold](http://scaffold.ant.design) -- [Instrucción para Desarrolladores](https://github.com/ant-design/ant-design/wiki/Development) -- [Nota de la Versión de Control de Versiones](https://github.com/ant-design/ant-design/wiki/%E8%BD%AE%E5%80%BC%E8%A7%84%E5%88%99%E5%92%8C%E7%89%88%E6%9C%AC%E5%8F%91%E5%B8%83%E6%B5%81%E7%A8%8B) -- [FAQ](https://ant.design/docs/react/faq) -- [Plantilla de CodeSandbox](https://u.ant.design/codesandbox-repro) para reportes de errores -- [Tema personalizado](https://ant.design/docs/react/customize-theme) -- [Cómo Postularse para ser Colaborador](https://github.com/ant-design/ant-design/wiki/Collaborators#how-to-apply-for-being-a-collaborator) - -## ⌨️ Desarrollo - -Utilice Gitpod, un entorno de desarrollo en línea gratuito para GitHub. - -[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/ant-design/ant-design) - -O clonar localmente: - -```bash -$ git clone git@github.com:ant-design/ant-design.git -$ cd ant-design -$ npm install -$ npm start -``` - -Abra su navegador y visite http://127.0.0.1:8001 , vea más en [Desarollo](https://github.com/ant-design/ant-design/wiki/Development). - -## 🤝 Contribuyendo [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) - -Lea nuestro [guía de contribución](https://ant.design/docs/react/contributing) y construyamos un mejor antd juntos. - -Damos la bienvenida a todas las contribuciones. Por favor lea nuestro[CONTRIBUTING.md](https://github.com/ant-design/ant-design/blob/master/.github/CONTRIBUTING.md) primero. Puede enviar ideas como [solicitudes de extracción](https://github.com/ant-design/ant-design/pulls) o como [problemas de GitHub](https://github.com/ant-design/ant-design/issues). Si desea mejorar el código, consulte las [Instrucciones de Desarrollo](https://github.com/ant-design/ant-design/wiki/Development) y ¡diviértase! :) - -Si usted es un colaborador, siga nuestro [principio de solicitud de extracción](https://github.com/ant-design/ant-design/wiki/PR-principle) para crear una solicitud de extracción con una [plantilla de colaborador](https://github.com/ant-design/ant-design/compare?expand=1&template=collaborator.md). - -[![Let's fund issues in this repository](https://issuehunt.io/static/embed/issuehunt-button-v1.svg)](https://issuehunt.io/repos/34526884) - -## ❤️ Patrocinadores [![](https://opencollective.com/ant-design/tiers/sponsors/badge.svg?label=Sponsors&color=brightgreen)](https://opencollective.com/ant-design#support) [![](https://opencollective.com/ant-design/tiers/backers/badge.svg?label=Backers&color=brightgreen)](https://opencollective.com/ant-design#support) - -[![](https://opencollective.com/ant-design/tiers/sponsors.svg?avatarHeight=36)](https://opencollective.com/ant-design#support) - -[![](https://opencollective.com/ant-design/tiers/backers.svg?avatarHeight=36)](https://opencollective.com/ant-design#support) diff --git a/README-uk_UA.md b/README-uk_UA.md deleted file mode 100644 index fccd2a1f1a48..000000000000 --- a/README-uk_UA.md +++ /dev/null @@ -1,155 +0,0 @@ -

- - - -

- -

Ant Design

- -
- -Мова інтерфейсу корпоративного класу та React UI бібліотека. - -[![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] [![NPM version][npm-image]][npm-url] [![NPM downloads][download-image]][download-url] - -[![][bundlephobia-image]][bundlephobia-url] [![][bundlesize-js-image]][unpkg-js-url] [![FOSSA Status][fossa-image]][fossa-url] - -[![Follow Twitter][twitter-image]][twitter-url] [![Renovate status][renovate-image]][renovate-dashboard-url] [![][issues-helper-image]][issues-helper-url] [![dumi][dumi-image]][dumi-url] [![Issues need help][help-wanted-image]][help-wanted-url] - -[npm-image]: http://img.shields.io/npm/v/antd.svg?style=flat-square -[npm-url]: http://npmjs.org/package/antd -[github-action-image]: https://github.com/ant-design/ant-design/workflows/%E2%9C%85%20test/badge.svg -[github-action-url]: https://github.com/ant-design/ant-design/actions?query=workflow%3A%22%E2%9C%85+test%22 -[codecov-image]: https://img.shields.io/codecov/c/github/ant-design/ant-design/master.svg?style=flat-square -[codecov-url]: https://codecov.io/gh/ant-design/ant-design/branch/master -[download-image]: https://img.shields.io/npm/dm/antd.svg?style=flat-square -[download-url]: https://npmjs.org/package/antd -[fossa-image]: https://app.fossa.io/api/projects/git%2Bgithub.com%2Fant-design%2Fant-design.svg?type=shield -[fossa-url]: https://app.fossa.io/projects/git%2Bgithub.com%2Fant-design%2Fant-design?ref=badge_shield -[help-wanted-image]: https://flat.badgen.net/github/label-issues/ant-design/ant-design/help%20wanted/open -[help-wanted-url]: https://github.com/ant-design/ant-design/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22 -[twitter-image]: https://img.shields.io/twitter/follow/AntDesignUI.svg?label=Ant%20Design -[twitter-url]: https://twitter.com/AntDesignUI -[bundlesize-js-image]: https://img.badgesize.io/https:/unpkg.com/antd/dist/antd.min.js?label=antd.min.js&compression=gzip&style=flat-square -[unpkg-js-url]: https://unpkg.com/browse/antd/dist/antd.min.js -[bundlephobia-image]: https://badgen.net/bundlephobia/minzip/antd?style=flat-square -[bundlephobia-url]: https://bundlephobia.com/package/antd -[issues-helper-image]: https://img.shields.io/badge/using-issues--helper-orange?style=flat-square -[issues-helper-url]: https://github.com/actions-cool/issues-helper -[renovate-image]: https://img.shields.io/badge/renovate-enabled-brightgreen.svg?style=flat-square -[renovate-dashboard-url]: https://github.com/ant-design/ant-design/issues/32498 -[dumi-image]: https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square -[dumi-url]: https://github.com/umijs/dumi - -
- -[![](https://user-images.githubusercontent.com/507615/209472919-6f7e8561-be8c-4b0b-9976-eb3c692aa20a.png)](https://ant.design) - -[English](./README.md) | [Português](./README-pt_BR.md) | [简体中文](./README-zh_CN.md) | Українською | [Spanish](./README-sp_MX.md) | [日本語](./README-ja_JP.md) | [العربية](./README-ar_EG.md) - -## ✨ Особливості - -- 🌈 UI корпоративного класу, призначений для веб-додатків. -- 📦 Набір високоякісних компонентів React з коробки. -- 🛡 Написано на TypeScript із вбудованими статичними типами. -- ⚙️ Весь пакет дизайнерських ресурсів та засобів розробки. -- 🌍 Підтримка інтернаціоналізації для десятків мов. -- 🎨 Потужне налаштування теми в кожній деталі. - -## 🖥 Підтримка навколишнього середовища - -- Сучасні браузери -- Рендеринг на стороні сервера (SSR) -- [Electron](https://www.electronjs.org/) - -| [Edge](http://godban.github.io/browsers-support-badges/)
Edge | [Firefox](http://godban.github.io/browsers-support-badges/)
Firefox | [Chrome](http://godban.github.io/browsers-support-badges/)
Chrome | [Safari](http://godban.github.io/browsers-support-badges/)
Safari | [Electron](http://godban.github.io/browsers-support-badges/)
Electron | -| --- | --- | --- | --- | --- | -| Edge | 2 останні версії | 2 останні версії | 2 останні версії | 2 останні версії | - -## 📦 Встановлення - -```bash -npm install antd -``` - -```bash -yarn add antd -``` - -## 🔨 Використання - -```jsx -import React from 'react'; -import { Button, DatePicker } from 'antd'; - -const App = () => ( - <> - - - -); -``` - -### TypeScript - -`antd` написано на TypeScript із повною типізацією, вибери [Використання у TypeScript](https://ant.design/docs/react/use-in-typescript) щоб розпочати. - -## 🌍 Інтернаціоналізація - -Десятки мов підтримуються в `antd`, дивись [i18n](https://ant.design/docs/react/i18n). - -## 🔗 Посилання - -- [Домашня сторінка](https://ant.design/) -- [Компоненти](https://ant.design/components/overview) -- [Ant Design Pro](http://pro.ant.design/) -- [Change Log](CHANGELOG.en-US.md) -- [rc-components](http://react-component.github.io/) -- [Mobile UI](http://mobile.ant.design) -- [Mini Program UI](http://mini.ant.design) -- [Ant Design Pro Components](https://procomponents.ant.design) -- [Ant Design Charts](https://charts.ant.design) -- [Ant Design Icons](https://github.com/ant-design/ant-design-icons) -- [Ant Design Colors](https://github.com/ant-design/ant-design-colors) -- [Лендінги](https://landing.ant.design) -- [Motion](https://motion.ant.design) -- [Scaffold Market](http://scaffold.ant.design) -- [Інструкція розробника](https://github.com/ant-design/ant-design/wiki/Development) -- [Примітка до випуску версій](https://github.com/ant-design/ant-design/wiki/%E8%BD%AE%E5%80%BC%E8%A7%84%E5%88%99%E5%92%8C%E7%89%88%E6%9C%AC%E5%8F%91%E5%B8%83%E6%B5%81%E7%A8%8B) -- [FAQ](https://ant.design/docs/react/faq) -- [CodeSandbox темплейт](https://u.ant.design/codesandbox-repro) для звітів про помилки -- [Кастомізація теми](https://ant.design/docs/react/customize-theme) -- [Як подати заявку на участь у програмі Співавторства](https://github.com/ant-design/ant-design/wiki/Collaborators#how-to-apply-for-being-a-collaborator) - -## ⌨️ Розробка - -Використовуй Gitpod, безкоштовне середовище розробки для GitHub. - -[![Відкрити у Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/ant-design/ant-design) - -Або клонуй локально: - -```bash -$ git clone git@github.com:ant-design/ant-design.git -$ cd ant-design -$ npm install -$ npm start -``` - -Відкрий у браузері http://127.0.0.1:8001, докладніше дивись [Розробка](https://github.com/ant-design/ant-design/wiki/Development). - -## 🤝 Контрибьютинг [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) - -Прочитай наш [посібник контриб'ютора](https://ant.design/docs/react/contributing) і давай будувати кращий antd разом. - -Ми вітаємо всі внески. Будь ласка, прочитай наш [CONTRIBUTING.md](https://github.com/ant-design/ant-design/blob/master/.github/CONTRIBUTING.md) спочатку. Ти можеш пропонувати будь-які ідеї як [Pull Request](https://github.com/ant-design/ant-design/pulls) або як [GitHub issues](https://github.com/ant-design/ant-design/issues). Якщо ти хочеш вдосконалити код, переглянь [Інструкції з розробки](https://github.com/ant-design/ant-design/wiki/Development) та добре проведи час! :) - -Якщо ти співавтор, дотримуйся нашого [Pull Request принципу](https://github.com/ant-design/ant-design/wiki/PR-principle) щоб створити Pull Request за [темплейтом співавтора](https://github.com/ant-design/ant-design/compare?expand=1&template=collaborator.md). - -[![Let's fund issues in this repository](https://issuehunt.io/static/embed/issuehunt-button-v1.svg)](https://issuehunt.io/repos/34526884) - -## ❤️ Спонсори та Меценати [![](https://opencollective.com/ant-design/tiers/sponsors/badge.svg?label=Sponsors&color=brightgreen)](https://opencollective.com/ant-design#support) [![](https://opencollective.com/ant-design/tiers/backers/badge.svg?label=Backers&color=brightgreen)](https://opencollective.com/ant-design#support) - -[![](https://opencollective.com/ant-design/tiers/sponsors.svg?avatarHeight=36)](https://opencollective.com/ant-design#support) - -[![](https://opencollective.com/ant-design/tiers/backers.svg?avatarHeight=36)](https://opencollective.com/ant-design#support) diff --git a/README-zh_CN.md b/README-zh_CN.md index 1f822316defe..1d9e5c6e417c 100644 --- a/README-zh_CN.md +++ b/README-zh_CN.md @@ -12,7 +12,7 @@ [![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] [![NPM version][npm-image]][npm-url] [![NPM downloads][download-image]][download-url] -[![][bundlephobia-image]][bundlephobia-url] [![][bundlesize-js-image]][unpkg-js-url] [![FOSSA Status][fossa-image]][fossa-url] +[![][bundlephobia-image]][bundlephobia-url] [![][bundlesize-js-image]][unpkg-js-url] [![FOSSA Status][fossa-image]][fossa-url] [![Covered by Argos Visual Testing][argos-ci-image]][argos-ci-url] [![Follow Twitter][twitter-image]][twitter-url] [![Renovate status][renovate-image]][renovate-dashboard-url] [![][issues-helper-image]][issues-helper-url] [![dumi][dumi-image]][dumi-url] [![Issues need help][help-wanted-image]][help-wanted-url] @@ -40,12 +40,14 @@ [renovate-dashboard-url]: https://github.com/ant-design/ant-design/issues/32498 [dumi-image]: https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square [dumi-url]: https://github.com/umijs/dumi +[argos-ci-image]: https://argos-ci.com/badge.svg +[argos-ci-url]: https://app.argos-ci.com/ant-design/ant-design/reference
[![](https://user-images.githubusercontent.com/507615/209472919-6f7e8561-be8c-4b0b-9976-eb3c692aa20a.png)](https://ant.design) -[English](./README.md) | [Português](./README-pt_BR.md) | 简体中文 | [Українською](./README-uk_UA.md) | [Spanish](./README-sp_MX.md) | [日本語](./README-ja_JP.md) | [العربية](./README-ar_EG.md) +[English](./README.md) | 中文 ## ✨ 特性 @@ -76,6 +78,10 @@ npm install antd --save yarn add antd ``` +```bash +pnpm add antd +``` + ## 🔨 示例 ```jsx @@ -150,7 +156,7 @@ $ npm start > 强烈推荐阅读 [《提问的智慧》](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way)、[《如何向开源社区提问题》](https://github.com/seajs/seajs/issues/545) 和 [《如何有效地报告 Bug》](http://www.chiark.greenend.org.uk/%7Esgtatham/bugs-cn.html)、[《如何向开源项目提交无法解答的问题》](https://zhuanlan.zhihu.com/p/25795393),更好的问题更容易获得帮助。 -[![Let's fund issues in this repository](https://issuehunt.io/static/embed/issuehunt-button-v1.svg)](https://issuehunt.io/repos/34526884) +[![赞助链接](https://raw.githubusercontent.com/BoostIO/issuehunt-materials/master/v1/issuehunt-button-v1.svg)](https://issuehunt.io/repos/34526884) ## 👥 社区互助 diff --git a/README.md b/README.md index a7fc1da34977..82971f3c6632 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ An enterprise-class UI design language and React UI library. [![](https://user-images.githubusercontent.com/507615/209472919-6f7e8561-be8c-4b0b-9976-eb3c692aa20a.png)](https://ant.design) -English | [Português](./README-pt_BR.md) | [简体中文](./README-zh_CN.md) | [Українською](./README-uk_UA.md) | [Spanish](./README-sp_MX.md) | [日本語](./README-ja_JP.md) | [العربية](./README-ar_EG.md) +English | [中文](./README-zh_CN.md) ## ✨ Features @@ -78,6 +78,10 @@ npm install antd yarn add antd ``` +```bash +pnpm add antd +``` + ## 🔨 Usage ```jsx @@ -148,7 +152,7 @@ We welcome all contributions. Please read our [CONTRIBUTING.md](https://github.c If you are a collaborator, please follow our [Pull Request principle](https://github.com/ant-design/ant-design/wiki/PR-principle) to create a Pull Request with [collaborator template](https://github.com/ant-design/ant-design/compare?expand=1&template=collaborator.md). -[![Let's fund issues in this repository](https://issuehunt.io/static/embed/issuehunt-button-v1.svg)](https://issuehunt.io/repos/34526884) +[![Let's fund issues in this repository](https://raw.githubusercontent.com/BoostIO/issuehunt-materials/master/v1/issuehunt-button-v1.svg)](https://issuehunt.io/repos/34526884) ## ❤️ Sponsors and Backers [![](https://opencollective.com/ant-design/tiers/sponsors/badge.svg?label=Sponsors&color=brightgreen)](https://opencollective.com/ant-design#support) [![](https://opencollective.com/ant-design/tiers/backers/badge.svg?label=Backers&color=brightgreen)](https://opencollective.com/ant-design#support) diff --git a/argos-white-listed-users b/argos-white-listed-users new file mode 100644 index 000000000000..6553d0c5f290 --- /dev/null +++ b/argos-white-listed-users @@ -0,0 +1 @@ +kiner-tang \ No newline at end of file diff --git a/rome.json b/biome.json similarity index 80% rename from rome.json rename to biome.json index 618edc3e25f1..9bf6ce31fdd1 100644 --- a/rome.json +++ b/biome.json @@ -1,4 +1,5 @@ { + "$schema": "https://biomejs.dev/schemas/1.0.0/schema.json", "formatter": { "enabled": true, "ignore": ["./dist/*", "./es/**/*", "./lib/**/*", "_site/**/*"], diff --git a/components/__tests__/__snapshots__/index.test.ts.snap b/components/__tests__/__snapshots__/index.test.ts.snap index 8572ab796ffb..50f2581df9e6 100644 --- a/components/__tests__/__snapshots__/index.test.ts.snap +++ b/components/__tests__/__snapshots__/index.test.ts.snap @@ -27,6 +27,7 @@ exports[`antd exports modules correctly 1`] = ` "Drawer", "Dropdown", "Empty", + "Flex", "FloatButton", "Form", "Grid", diff --git a/components/_util/ActionButton.tsx b/components/_util/ActionButton.tsx index aed3cd743997..1da49483d305 100644 --- a/components/_util/ActionButton.tsx +++ b/components/_util/ActionButton.tsx @@ -2,7 +2,7 @@ import useState from 'rc-util/lib/hooks/useState'; import * as React from 'react'; import Button from '../button'; import type { ButtonProps, LegacyButtonType } from '../button/button'; -import { convertLegacyProps } from '../button/button'; +import { convertLegacyProps } from '../button/buttonHelpers'; export interface ActionButtonProps { type?: LegacyButtonType; @@ -48,7 +48,7 @@ const ActionButton: React.FC = (props) => { }; React.useEffect(() => { - let timeoutId: NodeJS.Timer | null = null; + let timeoutId: ReturnType | null = null; if (autoFocus) { timeoutId = setTimeout(() => { buttonRef.current?.focus(); diff --git a/components/_util/__tests__/warning.test.ts b/components/_util/__tests__/warning.test.tsx similarity index 50% rename from components/_util/__tests__/warning.test.ts rename to components/_util/__tests__/warning.test.tsx index 00a952bd49d8..9c85ae405bf1 100644 --- a/components/_util/__tests__/warning.test.ts +++ b/components/_util/__tests__/warning.test.tsx @@ -1,3 +1,7 @@ +import { render } from '@testing-library/react'; +import React from 'react'; +import { devUseWarning as useWarning } from '../warning'; + describe('Test warning', () => { let spy: jest.SpyInstance; @@ -40,13 +44,40 @@ describe('Test warning', () => { expect(spy).not.toHaveBeenCalled(); }); + it('should show warning when using devUseWarning', async () => { + const App = () => { + // Don't use dynamic import to fixed issue: TypeError: Cannot read properties of null (reading 'useContext') + const warning = useWarning('Test'); + warning(false, 'usage', 'test message'); + warning.deprecated(false, 'old prop', 'new prop'); + return null; + }; + render(); + + expect(spy).toHaveBeenCalledWith('Warning: [antd: Test] test message'); + expect(spy).toHaveBeenCalledWith( + 'Warning: [antd: Test] `old prop` is deprecated. Please use `new prop` instead.', + ); + expect(spy).toHaveBeenCalledTimes(2); + }); }); describe('process.env.NODE_ENV === "production"', () => { - it('Whether `true` or `false`, do not exec `console.error`', async () => { - const prevEnv = process.env.NODE_ENV; + let prevEnv: string | undefined; + const mockNodeEnv = () => { + prevEnv = process.env.NODE_ENV; process.env.NODE_ENV = 'production'; - + }; + const restoreNodeEnv = () => { + process.env.NODE_ENV = prevEnv; + }; + beforeEach(() => { + mockNodeEnv(); + }); + afterEach(() => { + restoreNodeEnv(); + }); + it('Whether `true` or `false`, do not exec `console.error`', async () => { const { default: warning, noop } = await import('../warning'); expect(warning).toEqual(noop); @@ -56,8 +87,19 @@ describe('Test warning', () => { warning(true, 'error message'); expect(spy).not.toHaveBeenCalled(); + }); - process.env.NODE_ENV = prevEnv; + it('should not show warning when using devUseWarning', async () => { + const { devUseWarning } = await import('../warning'); + const App = () => { + const warning = devUseWarning('Test'); + warning(false, 'usage', 'test message'); + warning.deprecated(false, 'old prop', 'new prop'); + return null; + }; + render(); + + expect(spy).toHaveBeenCalledTimes(0); }); }); }); diff --git a/components/_util/gapSize.ts b/components/_util/gapSize.ts new file mode 100644 index 000000000000..f4f35ec38085 --- /dev/null +++ b/components/_util/gapSize.ts @@ -0,0 +1,13 @@ +import type { SizeType } from '../config-provider/SizeContext'; + +export function isPresetSize(size?: SizeType | string | number): size is SizeType { + return ['small', 'middle', 'large'].includes(size as string); +} + +export function isValidGapNumber(size?: SizeType | string | number): size is number { + if (!size) { + // The case of size = 0 is deliberately excluded here, because the default value of the gap attribute in CSS is 0, so if the user passes 0 in, we can directly ignore it. + return false; + } + return typeof size === 'number' && !Number.isNaN(size); +} diff --git a/components/_util/hooks/useFlexGapSupport.ts b/components/_util/hooks/useFlexGapSupport.ts deleted file mode 100644 index b0640f0f07c4..000000000000 --- a/components/_util/hooks/useFlexGapSupport.ts +++ /dev/null @@ -1,11 +0,0 @@ -import * as React from 'react'; -import { detectFlexGapSupported } from '../styleChecker'; - -export default () => { - const [flexible, setFlexible] = React.useState(false); - React.useEffect(() => { - setFlexible(detectFlexGapSupported()); - }, []); - - return flexible; -}; diff --git a/components/_util/hooks/useSyncState.ts b/components/_util/hooks/useSyncState.ts index 03fcb47097c9..fe61fac42d9a 100644 --- a/components/_util/hooks/useSyncState.ts +++ b/components/_util/hooks/useSyncState.ts @@ -1,4 +1,5 @@ import * as React from 'react'; + import useForceUpdate from './useForceUpdate'; type UseSyncStateProps = readonly [() => T, (newValue: T) => void]; diff --git a/components/_util/placements.ts b/components/_util/placements.ts index 4a8792d68b77..f2f39fb67910 100644 --- a/components/_util/placements.ts +++ b/components/_util/placements.ts @@ -1,5 +1,6 @@ /* eslint-disable default-case */ import type { AlignType, BuildInPlacements } from '@rc-component/trigger'; + import { getArrowOffset } from '../style/placementArrow'; export interface AdjustOverflow { @@ -38,11 +39,15 @@ export function getOverflowOptions( case 'top': case 'bottom': baseOverflow.shiftX = arrowOffset.dropdownArrowOffset * 2 + arrowWidth; + baseOverflow.shiftY = true; + baseOverflow.adjustY = true; break; case 'left': case 'right': baseOverflow.shiftY = arrowOffset.dropdownArrowOffsetVertical * 2 + arrowWidth; + baseOverflow.shiftX = true; + baseOverflow.adjustX = true; break; } @@ -155,6 +160,7 @@ export default function getPlacements(config: PlacementsConfig) { const placementInfo = { ...template, offset: [0, 0], + dynamicInset: true, }; placementMap[key] = placementInfo; diff --git a/components/_util/responsiveObserver.ts b/components/_util/responsiveObserver.ts index a8fd54df78eb..ca4b3f7844ea 100644 --- a/components/_util/responsiveObserver.ts +++ b/components/_util/responsiveObserver.ts @@ -1,4 +1,5 @@ import React from 'react'; + import type { GlobalToken } from '../theme/interface'; import { useToken } from '../theme/internal'; @@ -124,3 +125,14 @@ export default function useResponsiveObserver() { }; }, [token]); } + +export const matchScreen = (screens: ScreenMap, screenSizes?: ScreenSizeMap) => { + if (screenSizes && typeof screenSizes === 'object') { + for (let i = 0; i < responsiveArray.length; i++) { + const breakpoint: Breakpoint = responsiveArray[i]; + if (screens[breakpoint] && screenSizes[breakpoint] !== undefined) { + return screenSizes[breakpoint]; + } + } + } +}; diff --git a/components/_util/styleChecker.ts b/components/_util/styleChecker.ts index c39ca2510f1a..dfc960fa8fb8 100644 --- a/components/_util/styleChecker.ts +++ b/components/_util/styleChecker.ts @@ -4,38 +4,3 @@ import { isStyleSupport } from 'rc-util/lib/Dom/styleChecker'; export const canUseDocElement = () => canUseDom() && window.document.documentElement; export { isStyleSupport }; - -let flexGapSupported: boolean; -export const detectFlexGapSupported = () => { - if (!canUseDocElement()) { - return false; - } - - if (flexGapSupported !== undefined) { - return flexGapSupported; - } - - // create flex container with row-gap set - const flex = document.createElement('div'); - flex.style.display = 'flex'; - flex.style.flexDirection = 'column'; - flex.style.rowGap = '1px'; - - // create two, elements inside it - flex.appendChild(document.createElement('div')); - flex.appendChild(document.createElement('div')); - - // some browser may not repaint when remove nodes, so we need create a new layer to detect. - const container = document.createElement('div'); - container.style.position = 'absolute'; - container.style.zIndex = '-9999'; - container.appendChild(flex); - - - // append to the DOM (needed to obtain scrollHeight) - document.body.appendChild(container); - flexGapSupported = flex.scrollHeight === 1; // flex container should be 1px high from the row-gap - document.body.removeChild(container); - - return flexGapSupported; -}; diff --git a/components/_util/throttleByAnimationFrame.ts b/components/_util/throttleByAnimationFrame.ts index 4b3c80826ab4..8b0f1c7a479c 100644 --- a/components/_util/throttleByAnimationFrame.ts +++ b/components/_util/throttleByAnimationFrame.ts @@ -1,9 +1,5 @@ import raf from 'rc-util/lib/raf'; -type throttledFn = (...args: any[]) => void; - -type throttledCancelFn = { cancel: () => void }; - function throttleByAnimationFrame(fn: (...args: T) => void) { let requestId: number | null; @@ -12,7 +8,7 @@ function throttleByAnimationFrame(fn: (...args: T) => void) { fn(...args); }; - const throttled: throttledFn & throttledCancelFn = (...args: T) => { + const throttled = (...args: T) => { if (requestId == null) { requestId = raf(later(args)); } diff --git a/components/_util/warning.ts b/components/_util/warning.ts index 994ed46d864b..0c3688fd1f0b 100644 --- a/components/_util/warning.ts +++ b/components/_util/warning.ts @@ -1,8 +1,15 @@ -import rcWarning, { resetWarned } from 'rc-util/lib/warning'; +import * as React from 'react'; +import rcWarning, { resetWarned as rcResetWarned } from 'rc-util/lib/warning'; -export { resetWarned }; export function noop() {} +let deprecatedWarnList: Record | null = null; + +export function resetWarned() { + deprecatedWarnList = null; + rcResetWarned(); +} + type Warning = (valid: boolean, component: string, message?: string) => void; // eslint-disable-next-line import/no-mutable-exports @@ -18,4 +25,83 @@ if (process.env.NODE_ENV !== 'production') { }; } +type BaseTypeWarning = ( + valid: boolean, + /** + * - deprecated: Some API will be removed in future but still support now. + * - usage: Some API usage is not correct. + * - breaking: Breaking change like API is removed. + */ + type: 'deprecated' | 'usage' | 'breaking', + message?: string, +) => void; + +type TypeWarning = BaseTypeWarning & { + deprecated: (valid: boolean, oldProp: string, newProp: string, message?: string) => void; +}; + +export interface WarningContextProps { + strict?: boolean; +} + +export const WarningContext = React.createContext({}); + +/** + * This is a hook but we not named as `useWarning` + * since this is only used in development. + * We should always wrap this in `if (process.env.NODE_ENV !== 'production')` condition + */ +export const devUseWarning: (component: string) => TypeWarning = + process.env.NODE_ENV !== 'production' + ? (component) => { + const { strict } = React.useContext(WarningContext); + + const typeWarning: TypeWarning = (valid, type, message) => { + if (!valid) { + if (strict === false && type === 'deprecated') { + const existWarning = deprecatedWarnList; + + if (!deprecatedWarnList) { + deprecatedWarnList = {}; + } + + deprecatedWarnList[component] = deprecatedWarnList[component] || []; + if (!deprecatedWarnList[component].includes(message || '')) { + deprecatedWarnList[component].push(message || ''); + } + + // Warning for the first time + if (!existWarning) { + // eslint-disable-next-line no-console + console.warn( + '[antd] There exists deprecated usage in your code:', + deprecatedWarnList, + ); + } + } else { + warning(valid, component, message); + } + } + }; + + typeWarning.deprecated = (valid, oldProp, newProp, message) => { + typeWarning( + valid, + 'deprecated', + `\`${oldProp}\` is deprecated. Please use \`${newProp}\` instead.${ + message ? ` ${message}` : '' + }`, + ); + }; + + return typeWarning; + } + : () => { + const noopWarning: TypeWarning = () => {}; + + noopWarning.deprecated = noop; + + return noopWarning; + }; + export default warning; diff --git a/components/_util/wave/useWave.ts b/components/_util/wave/useWave.ts index 788141ebb7ad..24bee62e2243 100644 --- a/components/_util/wave/useWave.ts +++ b/components/_util/wave/useWave.ts @@ -1,5 +1,5 @@ import * as React from 'react'; -import useEvent from 'rc-util/lib/hooks/useEvent'; +import { useEvent } from 'rc-util'; import raf from 'rc-util/lib/raf'; import showWaveEffect from './WaveEffect'; import { ConfigContext } from '../../config-provider'; diff --git a/components/affix/__tests__/Affix.test.tsx b/components/affix/__tests__/Affix.test.tsx index cbe9b44815e0..5f2f594bc5a1 100644 --- a/components/affix/__tests__/Affix.test.tsx +++ b/components/affix/__tests__/Affix.test.tsx @@ -1,6 +1,5 @@ -import type { CSSProperties } from 'react'; import React, { useEffect, useRef } from 'react'; -import type { InternalAffixClass } from '..'; + import Affix from '..'; import accessibilityTest from '../../../tests/shared/accessibilityTest'; import rtlTest from '../../../tests/shared/rtlTest'; @@ -12,13 +11,12 @@ const events: Partial) => interface AffixProps { offsetTop?: number; offsetBottom?: number; - style?: CSSProperties; + style?: React.CSSProperties; onChange?: () => void; onTestUpdatePosition?: () => void; - getInstance?: (inst: InternalAffixClass) => void; } -const AffixMounter: React.FC = ({ getInstance, ...restProps }) => { +const AffixMounter: React.FC = (props) => { const container = useRef(null); useEffect(() => { if (container.current) { @@ -31,7 +29,7 @@ const AffixMounter: React.FC = ({ getInstance, ...restProps }) => { }, []); return (
- container.current} {...restProps}> + container.current} {...props}>
@@ -124,34 +122,14 @@ describe('Affix Render', () => { }); describe('updatePosition when target changed', () => { - it('function change', async () => { - document.body.innerHTML = '
'; - const container = document.getElementById('mounter'); - const getTarget = () => container; - let affixInstance: InternalAffixClass; - const { rerender } = render( - { - affixInstance = node as InternalAffixClass; - }} - target={getTarget} - > - {null} - , - ); - rerender( - { - affixInstance = node as InternalAffixClass; - }} - target={() => null} - > - {null} - , - ); - expect(affixInstance!.state.status).toBe(0); - expect(affixInstance!.state.affixStyle).toBe(undefined); - expect(affixInstance!.state.placeholderStyle).toBe(undefined); + it('function change', () => { + document.body.innerHTML = `
`; + const target = document.getElementById('mounter'); + const getTarget = () => target; + const { container, rerender } = render({null}); + rerender( null}>{null}); + expect(container.querySelector(`div[aria-hidden="true"]`)).toBeNull(); + expect(container.querySelector('.ant-affix')?.getAttribute('style')).toBeUndefined(); }); it('check position change before measure', async () => { @@ -167,34 +145,18 @@ describe('Affix Render', () => { ); await waitFakeTimer(); await movePlaceholder(1000); - expect(container.querySelector('.ant-affix')).toBeTruthy(); + expect(container.querySelector('.ant-affix')).toBeTruthy(); }); it('do not measure when hidden', async () => { - let affixInstance: InternalAffixClass | null = null; - - const { rerender } = render( - { - affixInstance = inst; - }} - offsetBottom={0} - />, - ); + const { container, rerender } = render(); await waitFakeTimer(); - const firstAffixStyle = affixInstance!.state.affixStyle; - - rerender( - { - affixInstance = inst; - }} - offsetBottom={0} - style={{ display: 'none' }} - />, - ); + const affixStyleEle = container.querySelector('.ant-affix'); + const firstAffixStyle = affixStyleEle ? affixStyleEle.getAttribute('style') : null; + + rerender(); await waitFakeTimer(); - const secondAffixStyle = affixInstance!.state.affixStyle; + const secondAffixStyle = affixStyleEle ? affixStyleEle.getAttribute('style') : null; expect(firstAffixStyle).toEqual(secondAffixStyle); }); @@ -204,36 +166,23 @@ describe('Affix Render', () => { it('add class automatically', async () => { document.body.innerHTML = '
'; - let affixInstance: InternalAffixClass | null = null; - render( - { - affixInstance = inst; - }} - offsetBottom={0} - />, - { - container: document.getElementById('mounter')!, - }, - ); + const { container } = render(, { + container: document.getElementById('mounter')!, + }); await waitFakeTimer(); await movePlaceholder(300); - expect(affixInstance!.state.affixStyle).toBeTruthy(); + expect(container.querySelector(`div[aria-hidden="true"]`)).toBeTruthy(); + expect(container.querySelector('.ant-affix')?.getAttribute('style')).toBeTruthy(); }); // Trigger inner and outer element for the two s. - [ - '.ant-btn', // inner - '.fixed', // outer - ].forEach((selector) => { + ['.ant-btn', '.fixed'].forEach((selector) => { it(`trigger listener when size change: ${selector}`, async () => { const updateCalled = jest.fn(); const { container } = render( , - { - container: document.getElementById('mounter')!, - }, + { container: document.getElementById('mounter')! }, ); updateCalled.mockReset(); diff --git a/components/affix/__tests__/__snapshots__/demo-extend.test.ts.snap b/components/affix/__tests__/__snapshots__/demo-extend.test.ts.snap index d9bb5f346ea5..65485c157a5a 100644 --- a/components/affix/__tests__/__snapshots__/demo-extend.test.ts.snap +++ b/components/affix/__tests__/__snapshots__/demo-extend.test.ts.snap @@ -90,10 +90,10 @@ exports[`renders components/affix/demo/on-change.tsx extend context correctly 2` exports[`renders components/affix/demo/target.tsx extend context correctly 1`] = `
{ - const [top, setTop] = useState(10); - const [bottom, setBottom] = useState(10); - + const [top, setTop] = React.useState(100); + const [bottom, setBottom] = React.useState(100); return ( <> diff --git a/components/affix/demo/target.tsx b/components/affix/demo/target.tsx index 9a00d26495bb..bf8a39b1d9b3 100644 --- a/components/affix/demo/target.tsx +++ b/components/affix/demo/target.tsx @@ -1,12 +1,22 @@ -import React, { useState } from 'react'; +import React from 'react'; import { Affix, Button } from 'antd'; -const App: React.FC = () => { - const [container, setContainer] = useState(null); +const containerStyle: React.CSSProperties = { + width: '100%', + height: 100, + overflow: 'auto', +}; +const style: React.CSSProperties = { + width: '100%', + height: 1000, +}; + +const App: React.FC = () => { + const [container, setContainer] = React.useState(null); return ( -
-
+
+
container}> diff --git a/components/affix/index.en-US.md b/components/affix/index.en-US.md index 0e63c68a5ef3..2b208c8bdfa1 100644 --- a/components/affix/index.en-US.md +++ b/components/affix/index.en-US.md @@ -18,6 +18,10 @@ On longer web pages, it's helpful to stick component into the viewport. This is Please note that Affix should not cover other content on the page, especially when the size of the viewport is small. +> Notes for developers +> +> After version `5.10.0`, we rewrite Affix use FC, Some methods of obtaining `ref` and calling internal instance methods will invalid. + ## Examples diff --git a/components/affix/index.tsx b/components/affix/index.tsx index 9f60cdf6661b..1f8d61865dfa 100644 --- a/components/affix/index.tsx +++ b/components/affix/index.tsx @@ -1,9 +1,8 @@ -'use client'; - +import React from 'react'; import classNames from 'classnames'; import ResizeObserver from 'rc-resize-observer'; import omit from 'rc-util/lib/omit'; -import React, { createRef, forwardRef, useContext } from 'react'; + import throttleByAnimationFrame from '../_util/throttleByAnimationFrame'; import type { ConfigConsumerProps } from '../config-provider'; import { ConfigContext } from '../config-provider'; @@ -41,16 +40,16 @@ export interface AffixProps { children: React.ReactNode; } -interface InternalAffixProps extends AffixProps { - affixPrefixCls: string; -} - enum AffixStatus { None, Prepare, } -export interface AffixState { +interface InternalAffixProps extends AffixProps { + affixPrefixCls: string; +} + +interface AffixState { affixStyle?: React.CSSProperties; placeholderStyle?: React.CSSProperties; status: AffixStatus; @@ -58,117 +57,58 @@ export interface AffixState { prevTarget: Window | HTMLElement | null; } -class InternalAffix extends React.Component { - static contextType = ConfigContext; +interface AffixRef { + updatePosition: ReturnType; +} - state: AffixState = { - status: AffixStatus.None, - lastAffix: false, - prevTarget: null, - }; +const InternalAffix = React.forwardRef((props, ref) => { + const { + style, + offsetTop, + offsetBottom, + affixPrefixCls, + rootClassName, + children, + target, + onChange, + } = props; - private placeholderNodeRef = createRef(); + const [lastAffix, setLastAffix] = React.useState(false); + const [affixStyle, setAffixStyle] = React.useState(); + const [placeholderStyle, setPlaceholderStyle] = React.useState(); - private fixedNodeRef = createRef(); + const status = React.useRef(AffixStatus.None); - private timer: NodeJS.Timeout | null; + const prevTarget = React.useRef(null); + const prevListener = React.useRef(); - context: ConfigConsumerProps; + const placeholderNodeRef = React.useRef(null); + const fixedNodeRef = React.useRef(null); + const timer = React.useRef | null>(null); - private getTargetFunc() { - const { getTargetContainer } = this.context; - const { target } = this.props; + const { getTargetContainer } = React.useContext(ConfigContext); - if (target !== undefined) { - return target; - } + const targetFunc = target ?? getTargetContainer ?? getDefaultTarget; - return getTargetContainer ?? getDefaultTarget; - } - - addListeners = () => { - const targetFunc = this.getTargetFunc(); - const target = targetFunc?.(); - const { prevTarget } = this.state; - if (prevTarget !== target) { - TRIGGER_EVENTS.forEach((eventName) => { - prevTarget?.removeEventListener(eventName, this.lazyUpdatePosition); - target?.addEventListener(eventName, this.lazyUpdatePosition); - }); - this.updatePosition(); - this.setState({ prevTarget: target }); - } - }; - - removeListeners = () => { - if (this.timer) { - clearTimeout(this.timer); - this.timer = null; - } - const { prevTarget } = this.state; - const targetFunc = this.getTargetFunc(); - const newTarget = targetFunc?.(); - TRIGGER_EVENTS.forEach((eventName) => { - newTarget?.removeEventListener(eventName, this.lazyUpdatePosition); - prevTarget?.removeEventListener(eventName, this.lazyUpdatePosition); - }); - this.updatePosition.cancel(); - // https://github.com/ant-design/ant-design/issues/22683 - this.lazyUpdatePosition.cancel(); - }; - - // Event handler - componentDidMount() { - // [Legacy] Wait for parent component ref has its value. - // We should use target as directly element instead of function which makes element check hard. - this.timer = setTimeout(this.addListeners); - } - - componentDidUpdate(prevProps: AffixProps) { - this.addListeners(); - if ( - prevProps.offsetTop !== this.props.offsetTop || - prevProps.offsetBottom !== this.props.offsetBottom - ) { - this.updatePosition(); - } - this.measure(); - } - - componentWillUnmount() { - this.removeListeners(); - } - - getOffsetTop = () => { - const { offsetBottom, offsetTop } = this.props; - return offsetBottom === undefined && offsetTop === undefined ? 0 : offsetTop; - }; - - getOffsetBottom = () => this.props.offsetBottom; + const internalOffsetTop = offsetBottom === undefined && offsetTop === undefined ? 0 : offsetTop; // =================== Measure =================== - measure = () => { - const { status, lastAffix } = this.state; - const { onChange } = this.props; - const targetFunc = this.getTargetFunc(); + const measure = () => { if ( - status !== AffixStatus.Prepare || - !this.fixedNodeRef.current || - !this.placeholderNodeRef.current || + status.current !== AffixStatus.Prepare || + !fixedNodeRef.current || + !placeholderNodeRef.current || !targetFunc ) { return; } - const offsetTop = this.getOffsetTop(); - const offsetBottom = this.getOffsetBottom(); - const targetNode = targetFunc(); if (targetNode) { const newState: Partial = { status: AffixStatus.None, }; - const placeholderRect = getTargetRect(this.placeholderNodeRef.current); + const placeholderRect = getTargetRect(placeholderNodeRef.current); if ( placeholderRect.top === 0 && @@ -180,7 +120,7 @@ class InternalAffix extends React.Component { } const targetRect = getTargetRect(targetNode); - const fixedTop = getFixedTop(placeholderRect, targetRect, offsetTop); + const fixedTop = getFixedTop(placeholderRect, targetRect, internalOffsetTop); const fixedBottom = getFixedBottom(placeholderRect, targetRect, offsetBottom); if (fixedTop !== undefined) { @@ -208,46 +148,38 @@ class InternalAffix extends React.Component { } newState.lastAffix = !!newState.affixStyle; - if (onChange && lastAffix !== newState.lastAffix) { - onChange(newState.lastAffix); + + if (lastAffix !== newState.lastAffix) { + onChange?.(newState.lastAffix); } - this.setState(newState as AffixState); + + status.current = newState.status!; + setAffixStyle(newState.affixStyle); + setPlaceholderStyle(newState.placeholderStyle); + setLastAffix(newState.lastAffix); } }; - prepareMeasure = () => { - // event param is used before. Keep compatible ts define here. - this.setState({ - status: AffixStatus.Prepare, - affixStyle: undefined, - placeholderStyle: undefined, - }); - - // Test if `updatePosition` called + const prepareMeasure = () => { + status.current = AffixStatus.Prepare; + measure(); if (process.env.NODE_ENV === 'test') { - const { onTestUpdatePosition } = this.props as any; - onTestUpdatePosition?.(); + (props as any)?.onTestUpdatePosition?.(); } }; - updatePosition = throttleByAnimationFrame(() => { - this.prepareMeasure(); + const updatePosition = throttleByAnimationFrame(() => { + prepareMeasure(); }); - lazyUpdatePosition = throttleByAnimationFrame(() => { - const targetFunc = this.getTargetFunc(); - const { affixStyle } = this.state; - + const lazyUpdatePosition = throttleByAnimationFrame(() => { // Check position change before measure to make Safari smooth if (targetFunc && affixStyle) { - const offsetTop = this.getOffsetTop(); - const offsetBottom = this.getOffsetBottom(); - const targetNode = targetFunc(); - if (targetNode && this.placeholderNodeRef.current) { + if (targetNode && placeholderNodeRef.current) { const targetRect = getTargetRect(targetNode); - const placeholderRect = getTargetRect(this.placeholderNodeRef.current); - const fixedTop = getFixedTop(placeholderRect, targetRect, offsetTop); + const placeholderRect = getTargetRect(placeholderNodeRef.current); + const fixedTop = getFixedTop(placeholderRect, targetRect, internalOffsetTop); const fixedBottom = getFixedBottom(placeholderRect, targetRect, offsetBottom); if ( @@ -260,49 +192,91 @@ class InternalAffix extends React.Component { } // Directly call prepare measure since it's already throttled. - this.prepareMeasure(); + prepareMeasure(); }); - // =================== Render =================== - render() { - const { affixStyle, placeholderStyle } = this.state; - const { affixPrefixCls, rootClassName, children } = this.props; - const className = classNames(affixStyle && rootClassName, { - [affixPrefixCls]: !!affixStyle, + const addListeners = () => { + const listenerTarget = targetFunc?.(); + TRIGGER_EVENTS.forEach((eventName) => { + if (prevListener.current) { + prevTarget.current?.removeEventListener(eventName, prevListener.current); + } + listenerTarget?.addEventListener(eventName, lazyUpdatePosition); }); + prevTarget.current = listenerTarget; + prevListener.current = lazyUpdatePosition; + }; - let props = omit(this.props, [ - 'prefixCls', - 'offsetTop', - 'offsetBottom', - 'target', - 'onChange', - 'affixPrefixCls', - 'rootClassName', - ]); - // Omit this since `onTestUpdatePosition` only works on test. - if (process.env.NODE_ENV === 'test') { - props = omit(props as typeof props & { onTestUpdatePosition: any }, ['onTestUpdatePosition']); + const removeListeners = () => { + if (timer.current) { + clearTimeout(timer.current); + timer.current = null; } + const newTarget = targetFunc?.(); + TRIGGER_EVENTS.forEach((eventName) => { + newTarget?.removeEventListener(eventName, lazyUpdatePosition); + if (prevListener.current) { + prevTarget.current?.removeEventListener(eventName, prevListener.current); + } + }); + updatePosition.cancel(); + lazyUpdatePosition.cancel(); + }; - return ( - -
- {affixStyle && - - ); + React.useImperativeHandle(ref, () => ({ updatePosition })); + + // mount & unmount + React.useEffect(() => { + // [Legacy] Wait for parent component ref has its value. + // We should use target as directly element instead of function which makes element check hard. + timer.current = setTimeout(addListeners); + return () => removeListeners(); + }, []); + + React.useEffect(() => { + addListeners(); + }, [target, affixStyle]); + + React.useEffect(() => { + updatePosition(); + }, [target, offsetTop, offsetBottom]); + + const className = classNames({ + [affixPrefixCls]: affixStyle, + [rootClassName!]: affixStyle && rootClassName, + }); + + let otherProps = omit(props, [ + 'prefixCls', + 'offsetTop', + 'offsetBottom', + 'target', + 'onChange', + 'affixPrefixCls', + 'rootClassName', + ]); + + if (process.env.NODE_ENV === 'test') { + otherProps = omit(otherProps as typeof otherProps & { onTestUpdatePosition: any }, [ + 'onTestUpdatePosition', + ]); } -} -// just use in test -export type InternalAffixClass = InternalAffix; -const Affix = forwardRef((props, ref) => { + return ( + +
+ {affixStyle && + + ); +}); + +const Affix = React.forwardRef((props, ref) => { const { prefixCls: customizePrefixCls, rootClassName } = props; - const { getPrefixCls } = useContext(ConfigContext); + const { getPrefixCls } = React.useContext(ConfigContext); const affixPrefixCls = getPrefixCls('affix', customizePrefixCls); const [wrapSSR, hashId] = useStyle(affixPrefixCls); diff --git a/components/affix/index.zh-CN.md b/components/affix/index.zh-CN.md index e19580dc1c4b..29bdea6b9d4d 100644 --- a/components/affix/index.zh-CN.md +++ b/components/affix/index.zh-CN.md @@ -19,6 +19,10 @@ group: 页面可视范围过小时,慎用此功能以免遮挡页面内容。 +> 开发者注意事项: +> +> 自 `5.10.0` 起,由于 Affix 组件由 class 重构为 FC,之前获取 `ref` 并调用内部实例方法的写法都会失效。 + ## 代码演示 diff --git a/components/alert/Alert.tsx b/components/alert/Alert.tsx index 20a416c8e863..2a9bd543b506 100644 --- a/components/alert/Alert.tsx +++ b/components/alert/Alert.tsx @@ -1,3 +1,5 @@ +import type { ReactElement } from 'react'; +import * as React from 'react'; import CheckCircleFilled from '@ant-design/icons/CheckCircleFilled'; import CloseCircleFilled from '@ant-design/icons/CloseCircleFilled'; import CloseOutlined from '@ant-design/icons/CloseOutlined'; @@ -6,12 +8,10 @@ import InfoCircleFilled from '@ant-design/icons/InfoCircleFilled'; import classNames from 'classnames'; import CSSMotion from 'rc-motion'; import pickAttrs from 'rc-util/lib/pickAttrs'; -import type { ReactElement } from 'react'; -import * as React from 'react'; + import { replaceElement } from '../_util/reactNode'; -import warning from '../_util/warning'; +import { devUseWarning } from '../_util/warning'; import { ConfigContext } from '../config-provider'; - // CSSINJS import useStyle from './style'; @@ -118,9 +118,12 @@ const Alert: React.FC = (props) => { } = props; const [closed, setClosed] = React.useState(false); + if (process.env.NODE_ENV !== 'production') { - warning(!closeText, 'Alert', '`closeText` is deprecated. Please use `closeIcon` instead.'); + const warning = devUseWarning('Alert'); + warning.deprecated(!closeText, 'closeText', 'closeIcon'); } + const ref = React.useRef(null); const { getPrefixCls, direction, alert } = React.useContext(ConfigContext); const prefixCls = getPrefixCls('alert', customizePrefixCls); diff --git a/components/alert/__tests__/__snapshots__/demo-extend.test.ts.snap b/components/alert/__tests__/__snapshots__/demo-extend.test.ts.snap index 5f74b2edae1d..b399d10d4e17 100644 --- a/components/alert/__tests__/__snapshots__/demo-extend.test.ts.snap +++ b/components/alert/__tests__/__snapshots__/demo-extend.test.ts.snap @@ -2,12 +2,11 @@ exports[`renders components/alert/demo/action.tsx extend context correctly 1`] = `
+ + + +
+
+`; + +exports[`renders components/flex/demo/align.tsx extend context correctly 2`] = `[]`; + +exports[`renders components/flex/demo/basic.tsx extend context correctly 1`] = ` +
+
+ + +
+
+
+
+
+
+
+
+`; + +exports[`renders components/flex/demo/basic.tsx extend context correctly 2`] = `[]`; + +exports[`renders components/flex/demo/combination.tsx extend context correctly 1`] = ` +
+
+
+ avatar +
+

+ “antd is an enterprise-class UI design language and React UI library.” +

+ + + Get Start + + +
+
+
+
+`; + +exports[`renders components/flex/demo/combination.tsx extend context correctly 2`] = `[]`; + +exports[`renders components/flex/demo/debug.tsx extend context correctly 1`] = ` +Array [ +
+
+
+
+
+
, +
+
+
+
+
+
, +] +`; + +exports[`renders components/flex/demo/debug.tsx extend context correctly 2`] = `[]`; + +exports[`renders components/flex/demo/gap.tsx extend context correctly 1`] = ` +
+
+ + + + +
+
+ + + + +
+
+`; + +exports[`renders components/flex/demo/gap.tsx extend context correctly 2`] = `[]`; + +exports[`renders components/flex/demo/wrap.tsx extend context correctly 1`] = ` +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+`; + +exports[`renders components/flex/demo/wrap.tsx extend context correctly 2`] = `[]`; diff --git a/components/flex/__tests__/__snapshots__/demo.test.ts.snap b/components/flex/__tests__/__snapshots__/demo.test.ts.snap new file mode 100644 index 000000000000..3bd7aec00563 --- /dev/null +++ b/components/flex/__tests__/__snapshots__/demo.test.ts.snap @@ -0,0 +1,663 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders components/flex/demo/align.tsx correctly 1`] = ` +
+

+ Select justify : +

+
+
+ + + + + + +
+
+

+ Select align : +

+
+
+ + + +
+
+
+ + + + +
+
+`; + +exports[`renders components/flex/demo/basic.tsx correctly 1`] = ` +
+
+ + +
+
+
+
+
+
+
+
+`; + +exports[`renders components/flex/demo/combination.tsx correctly 1`] = ` +
+
+
+ avatar +
+

+ “antd is an enterprise-class UI design language and React UI library.” +

+ + + Get Start + + +
+
+
+
+`; + +exports[`renders components/flex/demo/debug.tsx correctly 1`] = ` +Array [ +
+
+
+
+
+
, +
+
+
+
+
+
, +] +`; + +exports[`renders components/flex/demo/gap.tsx correctly 1`] = ` +
+
+ + + + +
+
+ + + + +
+
+`; + +exports[`renders components/flex/demo/wrap.tsx correctly 1`] = ` +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+`; diff --git a/components/flex/__tests__/__snapshots__/index.test.tsx.snap b/components/flex/__tests__/__snapshots__/index.test.tsx.snap new file mode 100644 index 000000000000..6809df8adf8e --- /dev/null +++ b/components/flex/__tests__/__snapshots__/index.test.tsx.snap @@ -0,0 +1,14 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Flex rtl render component should be rendered correctly in RTL direction 1`] = ` +
+
+ test1 +
+
+ test2 +
+
+`; diff --git a/components/flex/__tests__/demo-extend.test.ts b/components/flex/__tests__/demo-extend.test.ts new file mode 100644 index 000000000000..59f0f997b6d0 --- /dev/null +++ b/components/flex/__tests__/demo-extend.test.ts @@ -0,0 +1,3 @@ +import { extendTest } from '../../../tests/shared/demoTest'; + +extendTest('flex'); diff --git a/components/badge/__tests__/demo.test.ts b/components/flex/__tests__/demo.test.ts similarity index 74% rename from components/badge/__tests__/demo.test.ts rename to components/flex/__tests__/demo.test.ts index e1bdd02d5eee..9f18ce06a392 100644 --- a/components/badge/__tests__/demo.test.ts +++ b/components/flex/__tests__/demo.test.ts @@ -1,3 +1,3 @@ import demoTest from '../../../tests/shared/demoTest'; -demoTest('badge'); +demoTest('flex'); diff --git a/components/back-top/__tests__/image.test.ts b/components/flex/__tests__/image.test.ts similarity index 52% rename from components/back-top/__tests__/image.test.ts rename to components/flex/__tests__/image.test.ts index 2651ed880e1d..3f8a7a1d0b19 100644 --- a/components/back-top/__tests__/image.test.ts +++ b/components/flex/__tests__/image.test.ts @@ -1,5 +1,5 @@ import { imageDemoTest } from '../../../tests/shared/imageTest'; -describe('BackTop image', () => { - imageDemoTest('back-top'); +describe('flex image', () => { + imageDemoTest('flex'); }); diff --git a/components/flex/__tests__/index.test.tsx b/components/flex/__tests__/index.test.tsx new file mode 100644 index 000000000000..7ec72caa718a --- /dev/null +++ b/components/flex/__tests__/index.test.tsx @@ -0,0 +1,70 @@ +import React from 'react'; + +import Flex from '..'; +import mountTest from '../../../tests/shared/mountTest'; +import rtlTest from '../../../tests/shared/rtlTest'; +import { render } from '../../../tests/utils'; + +const FunCom = React.forwardRef((props, ref) => ( +
+ test FC +
+)); + +class ClassCom extends React.PureComponent<{ className?: string }> { + render() { + return
test Class
; + } +} + +describe('Flex', () => { + mountTest(() => ( + +
test1
+
test2
+
+ )); + rtlTest(() => ( + +
test1
+
test2
+
+ )); + it('Flex', () => { + const { container, rerender } = render(test); + expect(container.querySelector('.ant-flex')).toHaveStyle({ justifyContent: 'center' }); + rerender(test); + expect(container.querySelector('.ant-flex')).toHaveStyle({ flex: '0 1 auto' }); + rerender(test); + expect(container.querySelector('.ant-flex')).toHaveStyle({ gap: '100px' }); + }); + it('Component work', () => { + const testFcRef = React.createRef(); + const testClsRef = React.createRef(); + const { container, rerender } = render(test); + expect(container.querySelector('.ant-flex')?.tagName).toBe('DIV'); + rerender(test); + expect(container.querySelector('.ant-flex')?.tagName).toBe('SPAN'); + rerender( }>test); + expect(container.querySelector('.ant-flex')?.textContent).toBe('test FC'); + expect(testFcRef.current).toBeTruthy(); + rerender( }>test); + expect(container.querySelector('.ant-flex')?.textContent).toBe('test Class'); + expect(testClsRef.current).toBeTruthy(); + }); + + it('when vertical=true should stretch work', () => { + const { container, rerender } = render(test); + expect(container.querySelector('.ant-flex')).toHaveClass( + 'ant-flex-align-stretch', + ); + rerender( + + test + , + ); + expect(container.querySelector('.ant-flex')).toHaveClass( + 'ant-flex-align-center', + ); + }); +}); diff --git a/components/flex/demo/align.md b/components/flex/demo/align.md new file mode 100644 index 000000000000..b98b06ce0218 --- /dev/null +++ b/components/flex/demo/align.md @@ -0,0 +1,7 @@ +## zh-CN + +设置对齐方式。 + +## en-US + +Set align. diff --git a/components/flex/demo/align.tsx b/components/flex/demo/align.tsx new file mode 100644 index 000000000000..ef6923f4689c --- /dev/null +++ b/components/flex/demo/align.tsx @@ -0,0 +1,43 @@ +import React from 'react'; +import { Button, Flex, Segmented } from 'antd'; +import type { FlexProps } from 'antd'; +import type { SegmentedProps } from 'antd/es/segmented'; + +const boxStyle: React.CSSProperties = { + width: '100%', + height: 120, + borderRadius: 6, + border: '1px solid #40a9ff', +}; + +const justifyOptions = [ + 'flex-start', + 'center', + 'flex-end', + 'space-between', + 'space-around', + 'space-evenly', +]; + +const alignOptions = ['flex-start', 'center', 'flex-end']; + +const App: React.FC = () => { + const [justify, setJustify] = React.useState(justifyOptions[0]); + const [alignItems, setAlignItems] = React.useState(alignOptions[0]); + return ( + +

Select justify :

+ +

Select align :

+ + + + + + + +
+ ); +}; + +export default App; diff --git a/components/flex/demo/basic.md b/components/flex/demo/basic.md new file mode 100644 index 000000000000..d8863c5bd73f --- /dev/null +++ b/components/flex/demo/basic.md @@ -0,0 +1,7 @@ +## zh-CN + +最简单的用法。 + +## en-US + +The basic usage. diff --git a/components/flex/demo/basic.tsx b/components/flex/demo/basic.tsx new file mode 100644 index 000000000000..fa6b183e6a6c --- /dev/null +++ b/components/flex/demo/basic.tsx @@ -0,0 +1,27 @@ +/* eslint-disable react/no-array-index-key */ +import React from 'react'; +import { Flex, Radio } from 'antd'; + +const baseStyle: React.CSSProperties = { + width: '25%', + height: 54, +}; + +const App: React.FC = () => { + const [value, setValue] = React.useState('horizontal'); + return ( + + setValue(e.target.value)}> + horizontal + vertical + + + {Array.from({ length: 4 }).map((_, i) => ( +
+ ))} + + + ); +}; + +export default App; diff --git a/components/flex/demo/combination.md b/components/flex/demo/combination.md new file mode 100644 index 000000000000..cb5a86034632 --- /dev/null +++ b/components/flex/demo/combination.md @@ -0,0 +1,7 @@ +## zh-CN + +嵌套使用,可以实现更复杂的布局。 + +## en-US + +Nesting can achieve more complex layouts. diff --git a/components/flex/demo/combination.tsx b/components/flex/demo/combination.tsx new file mode 100644 index 000000000000..05cc57f09831 --- /dev/null +++ b/components/flex/demo/combination.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import { Button, Card, Flex, Typography } from 'antd'; + +const cardStyle: React.CSSProperties = { + width: 620, +}; + +const imgStyle: React.CSSProperties = { + display: 'block', + width: 273, +}; + +const App: React.FC = () => ( + + + avatar + + + “antd is an enterprise-class UI design language and React UI library.” + + + + + +); + +export default App; diff --git a/components/flex/demo/debug.md b/components/flex/demo/debug.md new file mode 100644 index 000000000000..22f1c2128928 --- /dev/null +++ b/components/flex/demo/debug.md @@ -0,0 +1,7 @@ +## zh-CN + +调试专用。 + +## en-US + +Use for debug. diff --git a/components/flex/demo/debug.tsx b/components/flex/demo/debug.tsx new file mode 100644 index 000000000000..50f504005ded --- /dev/null +++ b/components/flex/demo/debug.tsx @@ -0,0 +1,33 @@ +/* eslint-disable react/no-array-index-key */ +import React from 'react'; +import { Flex } from 'antd'; + +const App: React.FC = () => ( + <> + + {Array.from({ length: 4 }).map((_, i) => ( +
+ ))} + + + {Array.from({ length: 4 }).map((_, i) => ( +
+ ))} + + +); + +export default App; diff --git a/components/flex/demo/gap.md b/components/flex/demo/gap.md new file mode 100644 index 000000000000..3a8352de1637 --- /dev/null +++ b/components/flex/demo/gap.md @@ -0,0 +1,7 @@ +## zh-CN + +使用 `gap` 设置元素之间的间距,预设了 `small`、`middle`、`large` 三种尺寸,也可以自定义间距。 + +## en-US + +Set the `gap` between elements, which has three preset sizes: `small`, `middle`, `large`, You can also customize the gap size. diff --git a/components/flex/demo/gap.tsx b/components/flex/demo/gap.tsx new file mode 100644 index 000000000000..1d80f1f76ad8 --- /dev/null +++ b/components/flex/demo/gap.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { Button, Flex, Radio, Slider } from 'antd'; +import type { SizeType } from 'antd/es/config-provider/SizeContext'; + +const App: React.FC = () => { + const [gapSize, setGapSize] = React.useState('small'); + const [customGapSize, setCustomGapSize] = React.useState(0); + return ( + + setGapSize(e.target.value)}> + {['small', 'middle', 'large', 'customize'].map((size) => ( + + {size} + + ))} + + {gapSize === 'customize' && } + + + + + + + + ); +}; + +export default App; diff --git a/components/flex/demo/wrap.md b/components/flex/demo/wrap.md new file mode 100644 index 000000000000..0a306a11c186 --- /dev/null +++ b/components/flex/demo/wrap.md @@ -0,0 +1,7 @@ +## zh-CN + +自动换行。 + +## en-US + +Auto wrap line. diff --git a/components/flex/demo/wrap.tsx b/components/flex/demo/wrap.tsx new file mode 100644 index 000000000000..13e9629c4962 --- /dev/null +++ b/components/flex/demo/wrap.tsx @@ -0,0 +1,14 @@ +import React from 'react'; +import { Button, Flex } from 'antd'; + +const Demo: React.FC = () => ( + + {Array.from({ length: 24 }, (_, i) => ( + + ))} + +); + +export default Demo; diff --git a/components/flex/index.en-US.md b/components/flex/index.en-US.md new file mode 100644 index 000000000000..933d48920258 --- /dev/null +++ b/components/flex/index.en-US.md @@ -0,0 +1,50 @@ +--- +category: Components +group: Layout +title: Flex +cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*SMzgSJZE_AwAAAAAAAAAAAAADrJ8AQ/original +coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*8yArQ43EGccAAAAAAAAAAAAADrJ8AQ/original +tag: New +--- + +Flex. Available since `5.10.0`. + +## When To Use + +- Good for setting spacing between elements. +- Suitable for setting various horizontal and vertical alignments. + +### Difference with Space component + +- Space is used to set the spacing between inline elements. It will add a wrapper element for each child element for inline alignment. Suitable for equidistant arrangement of multiple child elements in rows and columns. +- Flex is used to set the layout of block-level elements. It does not add a wrapper element. Suitable for layout of child elements in vertical or horizontal direction, and provides more flexibility and control. + +## Examples + + +Basic +align +gap +Wrap +combination +debug + +## API + +> This component is available since `antd@5.10.0`. The default behavior of Flex in horizontal mode is to align upward, In vertical mode, aligns the stretch, You can adjust this via properties. + +Common props ref:[Common props](/docs/react/common-props) + +| Property | Description | type | Default | Version | +| --- | --- | --- | --- | --- | +| vertical | Is direction of the flex vertical, use `flex-direction: column` | boolean | `false` | | +| wrap | Set whether the element is displayed in a single line or in multiple lines | reference [flex-wrap](https://developer.mozilla.org/en-US/docs/Web/CSS/flex-wrap) | nowrap | | +| justify | Sets the alignment of elements in the direction of the main axis | reference [justify-content](https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content) | normal | | +| align | Sets the alignment of elements in the direction of the cross axis | reference [align-items](https://developer.mozilla.org/en-US/docs/Web/CSS/align-items) | normal | | +| flex | flex CSS shorthand properties | reference [flex](https://developer.mozilla.org/en-US/docs/Web/CSS/flex) | normal | | +| gap | Sets the gap between grids | `small` \| `middle` \| `large` \| string \| number | - | | +| component | custom element type | React.ComponentType | `div` | | + +## Design Token + + diff --git a/components/flex/index.tsx b/components/flex/index.tsx new file mode 100644 index 000000000000..cebaca23e0a6 --- /dev/null +++ b/components/flex/index.tsx @@ -0,0 +1,78 @@ +import React from 'react'; +import classNames from 'classnames'; +import omit from 'rc-util/lib/omit'; + +import { isPresetSize } from '../_util/gapSize'; +import { ConfigContext } from '../config-provider'; +import type { ConfigConsumerProps } from '../config-provider'; +import type { FlexProps } from './interface'; +import useStyle from './style'; +import createFlexClassNames from './utils'; + +const Flex = React.forwardRef((props, ref) => { + const { + prefixCls: customizePrefixCls, + rootClassName, + className, + style, + flex, + gap, + children, + vertical = false, + component: Component = 'div', + ...othersProps + } = props; + + const { + flex: ctxFlex, + direction: ctxDirection, + getPrefixCls, + } = React.useContext(ConfigContext); + + const prefixCls = getPrefixCls('flex', customizePrefixCls); + + const [wrapSSR, hashId] = useStyle(prefixCls); + + const mergedVertical = vertical ?? ctxFlex?.vertical; + + const mergedCls = classNames( + className, + rootClassName, + ctxFlex?.className, + prefixCls, + hashId, + createFlexClassNames(prefixCls, props), + { + [`${prefixCls}-rtl`]: ctxDirection === 'rtl', + [`${prefixCls}-gap-${gap}`]: isPresetSize(gap), + [`${prefixCls}-vertical`]: mergedVertical, + }, + ); + + const mergedStyle: React.CSSProperties = { ...ctxFlex?.style, ...style }; + + if (flex) { + mergedStyle.flex = flex; + } + + if (gap && !isPresetSize(gap)) { + mergedStyle.gap = gap; + } + + return wrapSSR( + + {children} + , + ); +}); + +if (process.env.NODE_ENV !== 'production') { + Flex.displayName = 'Flex'; +} + +export default Flex; diff --git a/components/flex/index.zh-CN.md b/components/flex/index.zh-CN.md new file mode 100644 index 000000000000..965d8d63ba19 --- /dev/null +++ b/components/flex/index.zh-CN.md @@ -0,0 +1,51 @@ +--- +category: Components +subtitle: 弹性布局 +group: 布局 +title: Flex +cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*SMzgSJZE_AwAAAAAAAAAAAAADrJ8AQ/original +coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*8yArQ43EGccAAAAAAAAAAAAADrJ8AQ/original +tag: New +--- + +弹性布局。自 `5.10.0` 版本开始提供该组件。 + +## 何时使用 + +- 适合设置元素之间的间距。 +- 适合设置各种水平、垂直对齐方式。 + +### 与 Space 组件的区别 + +- Space 为内联元素提供间距,其本身会为每一个子元素添加包裹元素用于内联对齐。适用于行、列中多个子元素的等距排列。 +- Flex 为块级元素提供间距,其本身不会添加包裹元素。适用于垂直或水平方向上的子元素布局,并提供了更多的灵活性和控制能力。 + +## 代码演示 + + +基本布局 +对齐方式 +设置间隙 +自动换行 +组合使用 +调试专用 + +## API + +> 自 `antd@5.10.0` 版本开始提供该组件。Flex 组件默认行为在水平模式下,为向上对齐,在垂直模式下,为拉伸对齐,你可以通过属性进行调整。 + +通用属性参考:[通用属性](/docs/react/common-props) + +| 属性 | 说明 | 类型 | 默认值 | 版本 | +| --- | --- | --- | --- | --- | +| vertical | flex 主轴的方向是否垂直,使用 `flex-direction: column` | boolean | `false` | +| wrap | 设置元素单行显示还是多行显示 | 参考 [flex-wrap](https://developer.mozilla.org/zh-CN/docs/Web/CSS/flex-wrap) | nowrap | | +| justify | 设置元素在主轴方向上的对齐方式 | 参考 [justify-content](https://developer.mozilla.org/zh-CN/docs/Web/CSS/justify-content) | normal | | +| align | 设置元素在交叉轴方向上的对齐方式 | 参考 [align-items](https://developer.mozilla.org/zh-CN/docs/Web/CSS/align-items) | normal | | +| flex | flex CSS 简写属性 | 参考 [flex](https://developer.mozilla.org/zh-CN/docs/Web/CSS/flex) | normal | | +| gap | 设置网格之间的间隙 | `small` \| `middle` \| `large` \| string \| number | - | | +| component | 自定义元素类型 | React.ComponentType | `div` | | + +## Design Token + + diff --git a/components/flex/interface.ts b/components/flex/interface.ts new file mode 100644 index 000000000000..d5240cfcae05 --- /dev/null +++ b/components/flex/interface.ts @@ -0,0 +1,17 @@ +import type React from 'react'; + +import type { AnyObject } from '../_util/type'; +import type { SizeType } from '../config-provider/SizeContext'; + +export interface FlexProps

extends React.HTMLAttributes { + prefixCls?: string; + rootClassName?: string; + vertical?: boolean; + wrap?: React.CSSProperties['flexWrap']; + justify?: React.CSSProperties['justifyContent']; + align?: React.CSSProperties['alignItems']; + flex?: React.CSSProperties['flex']; + gap?: React.CSSProperties['gap'] | SizeType; + children: React.ReactNode; + component?: React.ComponentType

| string; +} diff --git a/components/flex/style/index.ts b/components/flex/style/index.ts new file mode 100644 index 000000000000..d90e646578eb --- /dev/null +++ b/components/flex/style/index.ts @@ -0,0 +1,111 @@ +import type { CSSInterpolation } from '@ant-design/cssinjs'; + +import type { FullToken, GenerateStyle } from '../../theme/internal'; +import { genComponentStyleHook, mergeToken } from '../../theme/internal'; +import { alignItemsValues, flexWrapValues, justifyContentValues } from '../utils'; + +/** Component only token. Which will handle additional calculation of alias token */ +export interface ComponentToken { + // Component token here +} + +export interface FlexToken extends FullToken<'Flex'> { + /** + * @nameZH 小间隙 + * @nameEN Small Gap + * @desc 控制元素的小间隙。 + * @descEN Control the small gap of the element. + */ + flexGapSM: number; + /** + * @nameZH 间隙 + * @nameEN Gap + * @desc 控制元素的间隙。 + * @descEN Control the gap of the element. + */ + flexGap: number; + /** + * @nameZH 大间隙 + * @nameEN Large Gap + * @desc 控制元素的大间隙。 + * @descEN Control the large gap of the element. + */ + flexGapLG: number; +} + +const genFlexStyle: GenerateStyle = (token) => { + const { componentCls } = token; + return { + [componentCls]: { + display: 'flex', + '&-vertical': { + flexDirection: 'column', + }, + '&-rtl': { + direction: 'rtl', + }, + '&:empty': { + display: 'none', + }, + }, + }; +}; + +const genFlexGapStyle: GenerateStyle = (token) => { + const { componentCls } = token; + return { + [componentCls]: { + '&-gap-small': { + gap: token.flexGapSM, + }, + '&-gap-middle': { + gap: token.flexGap, + }, + '&-gap-large': { + gap: token.flexGapLG, + }, + }, + }; +}; + +const genFlexWrapStyle: GenerateStyle = (token) => { + const { componentCls } = token; + const wrapStyle: CSSInterpolation = {}; + flexWrapValues.forEach((value) => { + wrapStyle[`${componentCls}-wrap-${value}`] = { flexWrap: value }; + }); + return wrapStyle; +}; + +const genAlignItemsStyle: GenerateStyle = (token) => { + const { componentCls } = token; + const alignStyle: CSSInterpolation = {}; + alignItemsValues.forEach((value) => { + alignStyle[`${componentCls}-align-${value}`] = { alignItems: value }; + }); + return alignStyle; +}; + +const genJustifyContentStyle: GenerateStyle = (token) => { + const { componentCls } = token; + const justifyStyle: CSSInterpolation = {}; + justifyContentValues.forEach((value) => { + justifyStyle[`${componentCls}-justify-${value}`] = { justifyContent: value }; + }); + return justifyStyle; +}; + +export default genComponentStyleHook<'Flex'>('Flex', (token) => { + const flexToken = mergeToken(token, { + flexGapSM: token.paddingXS, + flexGap: token.padding, + flexGapLG: token.paddingLG, + }); + return [ + genFlexStyle(flexToken), + genFlexGapStyle(flexToken), + genFlexWrapStyle(flexToken), + genAlignItemsStyle(flexToken), + genJustifyContentStyle(flexToken), + ]; +}); diff --git a/components/flex/utils.ts b/components/flex/utils.ts new file mode 100644 index 000000000000..1cd814e6979a --- /dev/null +++ b/components/flex/utils.ts @@ -0,0 +1,68 @@ +import classNames from 'classnames'; + +import type { FlexProps } from './interface'; + +export const flexWrapValues = ['wrap', 'nowrap', 'wrap-reverse'] as const; + +export const justifyContentValues = [ + 'flex-start', + 'flex-end', + 'start', + 'end', + 'center', + 'space-between', + 'space-around', + 'space-evenly', + 'stretch', + 'normal', + 'left', + 'right', +] as const; + +export const alignItemsValues = [ + 'center', + 'start', + 'end', + 'flex-start', + 'flex-end', + 'self-start', + 'self-end', + 'baseline', + 'normal', + 'stretch', +] as const; + +const genClsWrap = (prefixCls: string, props: FlexProps) => { + const wrapCls: Record = {}; + flexWrapValues.forEach((cssKey) => { + wrapCls[`${prefixCls}-wrap-${cssKey}`] = props.wrap === cssKey; + }); + return wrapCls; +}; + +const genClsAlign = (prefixCls: string, props: FlexProps) => { + const alignCls: Record = {}; + alignItemsValues.forEach((cssKey) => { + alignCls[`${prefixCls}-align-${cssKey}`] = props.align === cssKey; + }); + alignCls[`${prefixCls}-align-stretch`] = !props.align && !!props.vertical; + return alignCls; +}; + +const genClsJustify = (prefixCls: string, props: FlexProps) => { + const justifyCls: Record = {}; + justifyContentValues.forEach((cssKey) => { + justifyCls[`${prefixCls}-justify-${cssKey}`] = props.justify === cssKey; + }); + return justifyCls; +}; + +function createFlexClassNames(prefixCls: string, props: FlexProps) { + return classNames({ + ...genClsWrap(prefixCls, props), + ...genClsAlign(prefixCls, props), + ...genClsJustify(prefixCls, props), + }); +} + +export default createFlexClassNames; diff --git a/components/float-button/FloatButton.tsx b/components/float-button/FloatButton.tsx index 61ab00677d72..bb67bc678cb2 100644 --- a/components/float-button/FloatButton.tsx +++ b/components/float-button/FloatButton.tsx @@ -1,13 +1,14 @@ +import React, { useContext, useMemo } from 'react'; import classNames from 'classnames'; import omit from 'rc-util/lib/omit'; -import React, { useContext, useMemo } from 'react'; -import warning from '../_util/warning'; + +import { devUseWarning } from '../_util/warning'; import Badge from '../badge'; import type { ConfigConsumerProps } from '../config-provider'; import { ConfigContext } from '../config-provider'; import Tooltip from '../tooltip'; -import Content from './FloatButtonContent'; import FloatButtonGroupContext from './context'; +import Content from './FloatButtonContent'; import type { CompoundedComponent, FloatButtonBadgeProps, @@ -84,9 +85,11 @@ const FloatButton: React.ForwardRefRenderFunction< } if (process.env.NODE_ENV !== 'production') { + const warning = devUseWarning('FloatButton'); + warning( !(shape === 'circle' && description), - 'FloatButton', + 'usage', 'supported only when `shape` is `square`. Due to narrow space for text, short sentence is recommended.', ); } diff --git a/components/float-button/FloatButtonGroup.tsx b/components/float-button/FloatButtonGroup.tsx index e14a2ccb74e9..efa7ea7af9c2 100644 --- a/components/float-button/FloatButtonGroup.tsx +++ b/components/float-button/FloatButtonGroup.tsx @@ -1,14 +1,15 @@ +import React, { memo, useCallback, useContext, useEffect, useMemo, useRef } from 'react'; import CloseOutlined from '@ant-design/icons/CloseOutlined'; import FileTextOutlined from '@ant-design/icons/FileTextOutlined'; import classNames from 'classnames'; import CSSMotion from 'rc-motion'; import useMergedState from 'rc-util/lib/hooks/useMergedState'; -import React, { memo, useCallback, useContext, useEffect, useMemo, useRef } from 'react'; -import warning from '../_util/warning'; + +import { devUseWarning } from '../_util/warning'; import type { ConfigConsumerProps } from '../config-provider'; import { ConfigContext } from '../config-provider'; -import FloatButton, { floatButtonPrefixCls } from './FloatButton'; import { FloatButtonGroupProvider } from './context'; +import FloatButton, { floatButtonPrefixCls } from './FloatButton'; import type { FloatButtonGroupProps } from './interface'; import useStyle from './style'; @@ -93,9 +94,11 @@ const FloatButtonGroup: React.FC = (props) => { // =================== Warning ===================== if (process.env.NODE_ENV !== 'production') { + const warning = devUseWarning('FloatButton.Group'); + warning( !('open' in props) || !!trigger, - 'FloatButton.Group', + 'usage', '`open` need to be used together with `trigger`', ); } diff --git a/components/float-button/__tests__/__snapshots__/demo-extend.test.ts.snap b/components/float-button/__tests__/__snapshots__/demo-extend.test.ts.snap index b2861ebf4250..68dcb4f51fcc 100644 --- a/components/float-button/__tests__/__snapshots__/demo-extend.test.ts.snap +++ b/components/float-button/__tests__/__snapshots__/demo-extend.test.ts.snap @@ -2,7 +2,7 @@ exports[`renders components/float-button/demo/back-top.tsx extend context correctly 1`] = `

Scroll to bottom @@ -81,9 +81,9 @@ Array [ class="ant-float-btn-group ant-float-btn-group-circle ant-float-btn-group-circle-shadow" style="right: 94px;" > -
- + @@ -264,26 +268,28 @@ Array [ data-show="true" title="12" > - + - 1 + + 1 + - - - 2 + + 2 + - + @@ -330,36 +336,38 @@ Array [ data-show="true" title="123" > - + - 1 + + 1 + - - - 2 + + 2 + - - - 3 + + 3 + - + @@ -423,6 +431,7 @@ Array [ />
Scroll to bottom @@ -79,9 +79,9 @@ Array [ class="ant-float-btn-group ant-float-btn-group-circle ant-float-btn-group-circle-shadow" style="right:94px" > - + @@ -241,26 +245,28 @@ Array [ data-show="true" title="12" > - + - 1 + + 1 + - - - 2 + + 2 + - + @@ -307,36 +313,38 @@ Array [ data-show="true" title="123" > - + - 1 + + 1 + - - - 2 + + 2 + - - - 3 + + 3 + - + @@ -398,6 +406,7 @@ Array [ />
{ - imageDemoTest('float-button'); + imageDemoTest('float-button', { splitTheme: true, onlyViewport: ['back-top.tsx'] }); }); diff --git a/components/float-button/demo/back-top.tsx b/components/float-button/demo/back-top.tsx index f359f93359c0..29b5958920ab 100644 --- a/components/float-button/demo/back-top.tsx +++ b/components/float-button/demo/back-top.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { FloatButton } from 'antd'; const App: React.FC = () => ( -
+
Scroll to bottom
Scroll to bottom
Scroll to bottom
diff --git a/components/float-button/demo/badge.tsx b/components/float-button/demo/badge.tsx index 5c6b4d60ef50..00ae514332b9 100644 --- a/components/float-button/demo/badge.tsx +++ b/components/float-button/demo/badge.tsx @@ -6,7 +6,11 @@ const App: React.FC = () => ( <> - custom badge color
} badge={{ count: 5, color: 'blue' }} /> + custom badge color
} + badge={{ count: 5, color: 'blue' }} + /> diff --git a/components/float-button/index.ts b/components/float-button/index.ts index 2e443547314f..663dda19f0c8 100644 --- a/components/float-button/index.ts +++ b/components/float-button/index.ts @@ -1,5 +1,3 @@ -'use client'; - import BackTop from './BackTop'; import FloatButton from './FloatButton'; import FloatButtonGroup from './FloatButtonGroup'; diff --git a/components/float-button/index.zh-CN.md b/components/float-button/index.zh-CN.md index 165cb9872668..3b9efdc5e8d5 100644 --- a/components/float-button/index.zh-CN.md +++ b/components/float-button/index.zh-CN.md @@ -71,6 +71,6 @@ tag: New | visibilityHeight | 滚动高度达到此参数值才出现 BackTop | number | 400 | | | onClick | 点击按钮的回调函数 | () => void | - | | -## Design Token +## 主题变量(Design Token) diff --git a/components/float-button/style/index.ts b/components/float-button/style/index.ts index a0c031f5998c..16b8d468d290 100644 --- a/components/float-button/style/index.ts +++ b/components/float-button/style/index.ts @@ -220,9 +220,10 @@ const sharedFloatButtonStyle: GenerateStyle = (toke position: 'fixed', cursor: 'pointer', zIndex: 99, + // Do not remove the 'display: block' here. + // Deleting it will cause marginBottom to become ineffective. + // Ref: https://github.com/ant-design/ant-design/issues/44700 display: 'block', - justifyContent: 'center', - alignItems: 'center', width: floatButtonSize, height: floatButtonSize, insetInlineEnd: token.floatButtonInsetInlineEnd, diff --git a/components/form/Form.tsx b/components/form/Form.tsx index c853d9c30c55..f0e3743e103b 100644 --- a/components/form/Form.tsx +++ b/components/form/Form.tsx @@ -18,8 +18,12 @@ import useFormWarning from './hooks/useFormWarning'; import type { FormLabelAlign } from './interface'; import useStyle from './style'; import ValidateMessagesContext from './validateMessagesContext'; +import type { FeedbackIcons } from './FormItem'; -export type RequiredMark = boolean | 'optional'; +export type RequiredMark = + | boolean + | 'optional' + | ((labelNode: React.ReactNode, info: { required: boolean }) => React.ReactNode); export type FormLayout = 'horizontal' | 'inline' | 'vertical'; export interface FormProps extends Omit, 'form'> { @@ -32,6 +36,7 @@ export interface FormProps extends Omit, 'form labelCol?: ColProps; wrapperCol?: ColProps; form?: FormInstance; + feedbackIcons?: FeedbackIcons; size?: SizeType; disabled?: boolean; scrollToFirstError?: Options | boolean; @@ -64,6 +69,7 @@ const InternalForm: React.ForwardRefRenderFunction = (p onFinishFailed, name, style, + feedbackIcons, ...restFormProps } = props; @@ -129,8 +135,19 @@ const InternalForm: React.ForwardRefRenderFunction = (p requiredMark: mergedRequiredMark, itemRef: __INTERNAL__.itemRef, form: wrapForm, + feedbackIcons, }), - [name, labelAlign, labelCol, wrapperCol, layout, mergedColon, mergedRequiredMark, wrapForm], + [ + name, + labelAlign, + labelCol, + wrapperCol, + layout, + mergedColon, + mergedRequiredMark, + wrapForm, + feedbackIcons, + ], ); React.useImperativeHandle(ref, () => wrapForm); diff --git a/components/form/FormItem/ItemHolder.tsx b/components/form/FormItem/ItemHolder.tsx index d338594325cb..928a0b490703 100644 --- a/components/form/FormItem/ItemHolder.tsx +++ b/components/form/FormItem/ItemHolder.tsx @@ -1,27 +1,19 @@ -import CheckCircleFilled from '@ant-design/icons/CheckCircleFilled'; -import CloseCircleFilled from '@ant-design/icons/CloseCircleFilled'; -import ExclamationCircleFilled from '@ant-design/icons/ExclamationCircleFilled'; -import LoadingOutlined from '@ant-design/icons/LoadingOutlined'; +import * as React from 'react'; import classNames from 'classnames'; import type { Meta } from 'rc-field-form/lib/interface'; -import useLayoutEffect from 'rc-util/lib/hooks/useLayoutEffect'; import isVisible from 'rc-util/lib/Dom/isVisible'; +import useLayoutEffect from 'rc-util/lib/hooks/useLayoutEffect'; import omit from 'rc-util/lib/omit'; -import * as React from 'react'; -import type { FormItemProps, ValidateStatus } from '.'; + +import type { FormItemProps } from '.'; import { Row } from '../../grid'; +import type { ReportMetaChange } from '../context'; +import { FormContext, NoStyleItemContext } from '../context'; import FormItemInput from '../FormItemInput'; import FormItemLabel from '../FormItemLabel'; -import type { FormItemStatusContextProps, ReportMetaChange } from '../context'; -import { FormContext, FormItemInputContext, NoStyleItemContext } from '../context'; import useDebounce from '../hooks/useDebounce'; - -const iconMap = { - success: CheckCircleFilled, - warning: ExclamationCircleFilled, - error: CloseCircleFilled, - validating: LoadingOutlined, -}; +import { getStatus } from '../util'; +import StatusProvider from './StatusProvider'; export interface ItemHolderProps extends FormItemProps { prefixCls: string; @@ -88,52 +80,14 @@ export default function ItemHolder(props: ItemHolderProps) { // ======================== Status ======================== const getValidateState = (isDebounce = false) => { - let status: ValidateStatus = ''; const _errors = isDebounce ? debounceErrors : meta.errors; const _warnings = isDebounce ? debounceWarnings : meta.warnings; - if (validateStatus !== undefined) { - status = validateStatus; - } else if (meta.validating) { - status = 'validating'; - } else if (_errors.length) { - status = 'error'; - } else if (_warnings.length) { - status = 'warning'; - } else if (meta.touched || (hasFeedback && meta.validated)) { - // success feedback should display when pass hasFeedback prop and current value is valid value - status = 'success'; - } - return status; + + return getStatus(_errors, _warnings, meta, '', !!hasFeedback, validateStatus); }; const mergedValidateStatus = getValidateState(); - const formItemStatusContext = React.useMemo(() => { - let feedbackIcon: React.ReactNode; - if (hasFeedback) { - const IconNode = mergedValidateStatus && iconMap[mergedValidateStatus]; - feedbackIcon = IconNode ? ( - - - - ) : null; - } - - return { - status: mergedValidateStatus, - errors, - warnings, - hasFeedback, - feedbackIcon, - isFormItemInput: true, - }; - }, [mergedValidateStatus, hasFeedback]); - // ======================== Render ======================== const itemClassName = classNames(itemPrefixCls, className, rootClassName, { [`${itemPrefixCls}-with-help`]: hasHelp || debounceErrors.length || debounceWarnings.length, @@ -181,6 +135,7 @@ export default function ItemHolder(props: ItemHolderProps) { 'validateTrigger', 'valuePropName', 'wrapperCol', + 'validateDebounce', ])} > {/* Label */} @@ -204,9 +159,17 @@ export default function ItemHolder(props: ItemHolderProps) { onErrorVisibleChanged={onErrorVisibleChanged} > - + {children} - + diff --git a/components/form/FormItem/StatusProvider.tsx b/components/form/FormItem/StatusProvider.tsx new file mode 100644 index 000000000000..ca9c79b413eb --- /dev/null +++ b/components/form/FormItem/StatusProvider.tsx @@ -0,0 +1,108 @@ +import * as React from 'react'; +import CheckCircleFilled from '@ant-design/icons/CheckCircleFilled'; +import CloseCircleFilled from '@ant-design/icons/CloseCircleFilled'; +import ExclamationCircleFilled from '@ant-design/icons/ExclamationCircleFilled'; +import LoadingOutlined from '@ant-design/icons/LoadingOutlined'; +import classNames from 'classnames'; +import type { Meta } from 'rc-field-form/lib/interface'; + +import type { FeedbackIcons, ValidateStatus } from '.'; +import { FormContext, FormItemInputContext, type FormItemStatusContextProps } from '../context'; +import { getStatus } from '../util'; + +const iconMap = { + success: CheckCircleFilled, + warning: ExclamationCircleFilled, + error: CloseCircleFilled, + validating: LoadingOutlined, +}; + +export interface StatusProviderProps { + children?: React.ReactNode; + validateStatus?: ValidateStatus; + prefixCls: string; + meta: Meta; + errors: React.ReactNode[]; + warnings: React.ReactNode[]; + hasFeedback?: boolean | { icons?: FeedbackIcons }; + noStyle?: boolean; +} + +export default function StatusProvider({ + children, + errors, + warnings, + hasFeedback, + validateStatus, + prefixCls, + meta, + noStyle, +}: StatusProviderProps) { + const itemPrefixCls = `${prefixCls}-item`; + const { feedbackIcons } = React.useContext(FormContext); + + const mergedValidateStatus = getStatus( + errors, + warnings, + meta, + null, + !!hasFeedback, + validateStatus, + ); + + const { + isFormItemInput: parentIsFormItemInput, + status: parentStatus, + hasFeedback: parentHasFeedback, + feedbackIcon: parentFeedbackIcon, + } = React.useContext(FormItemInputContext); + + // ====================== Context ======================= + const formItemStatusContext = React.useMemo(() => { + let feedbackIcon: React.ReactNode; + if (hasFeedback) { + const customIcons = (hasFeedback !== true && hasFeedback.icons) || feedbackIcons; + const customIconNode = + mergedValidateStatus && + customIcons?.({ status: mergedValidateStatus, errors, warnings })?.[mergedValidateStatus]; + const IconNode = mergedValidateStatus && iconMap[mergedValidateStatus]; + feedbackIcon = + customIconNode !== false && IconNode ? ( + + {customIconNode || } + + ) : null; + } + + const context: FormItemStatusContextProps = { + status: mergedValidateStatus || '', + errors, + warnings, + hasFeedback: !!hasFeedback, + feedbackIcon, + isFormItemInput: true, + }; + + // No style will follow parent context + if (noStyle) { + context.status = (mergedValidateStatus ?? parentStatus) || ''; + context.isFormItemInput = parentIsFormItemInput; + context.hasFeedback = !!(hasFeedback ?? parentHasFeedback); + context.feedbackIcon = hasFeedback !== undefined ? context.feedbackIcon : parentFeedbackIcon; + } + + return context; + }, [mergedValidateStatus, hasFeedback, noStyle, parentIsFormItemInput, parentStatus]); + + // ======================= Render ======================= + return ( + + {children} + + ); +} diff --git a/components/form/FormItem/index.tsx b/components/form/FormItem/index.tsx index c4f21056c6a6..3009518dfedd 100644 --- a/components/form/FormItem/index.tsx +++ b/components/form/FormItem/index.tsx @@ -1,24 +1,26 @@ +import * as React from 'react'; import classNames from 'classnames'; import { Field, FieldContext, ListContext } from 'rc-field-form'; import type { FieldProps } from 'rc-field-form/lib/Field'; -import type { Meta, NamePath } from 'rc-field-form/lib/interface'; +import type { InternalNamePath, Meta } from 'rc-field-form/lib/interface'; import useState from 'rc-util/lib/hooks/useState'; import { supportRef } from 'rc-util/lib/ref'; -import * as React from 'react'; + import { cloneElement, isValidElement } from '../../_util/reactNode'; -import warning from '../../_util/warning'; +import { devUseWarning } from '../../_util/warning'; import { ConfigContext } from '../../config-provider'; +import { FormContext, NoStyleItemContext } from '../context'; +import type { FormInstance } from '../Form'; import type { FormItemInputProps } from '../FormItemInput'; import type { FormItemLabelProps, LabelTooltipType } from '../FormItemLabel'; -import { FormContext, NoStyleItemContext } from '../context'; +import useChildren from '../hooks/useChildren'; import useFormItemStatus from '../hooks/useFormItemStatus'; import useFrameState from '../hooks/useFrameState'; import useItemRef from '../hooks/useItemRef'; +import useStyle from '../style'; import { getFieldId, toArray } from '../util'; import ItemHolder from './ItemHolder'; -import useChildren from '../hooks/useChildren'; -import useStyle from '../style'; -import type { FormInstance } from '../Form'; +import StatusProvider from './StatusProvider'; const NAME_SPLIT = '__SPLIT__'; @@ -34,6 +36,12 @@ type RenderChildren = (form: FormInstance) => React.ReactN type RcFieldProps = Omit, 'children'>; type ChildrenType = RenderChildren | React.ReactNode; +export type FeedbackIcons = (itemStatus: { + status: ValidateStatus; + errors?: React.ReactNode[]; + warnings?: React.ReactNode[]; +}) => { [key in ValidateStatus]?: React.ReactNode }; + interface MemoInputProps { value: any; update: any; @@ -61,7 +69,7 @@ export interface FormItemProps rootClassName?: string; children?: ChildrenType; id?: string; - hasFeedback?: boolean; + hasFeedback?: boolean | { icons: FeedbackIcons }; validateStatus?: ValidateStatus; required?: boolean; hidden?: boolean; @@ -72,13 +80,6 @@ export interface FormItemProps fieldKey?: React.Key | React.Key[]; } -function hasValidName(name?: NamePath): Boolean { - if (name === null) { - warning(false, 'Form.Item', '`null` is passed as `name` property'); - } - return !(name === undefined || name === null); -} - function genEmptyMeta(): Meta { return { errors: [], @@ -120,17 +121,24 @@ function InternalFormItem(props: FormItemProps): React.Rea const mergedValidateTrigger = validateTrigger !== undefined ? validateTrigger : contextValidateTrigger; - const hasName = hasValidName(name); + const hasName = !(name === undefined || name === null); const prefixCls = getPrefixCls('form', customizePrefixCls); // Style const [wrapSSR, hashId] = useStyle(prefixCls); + // ========================= Warn ========================= + const warning = devUseWarning('Form.Item'); + + if (process.env.NODE_ENV !== 'production') { + warning(name !== null, 'usage', '`null` is passed as `name` property'); + } + // ========================= MISC ========================= // Get `noStyle` required info const listContext = React.useContext(ListContext); - const fieldKeyPathRef = React.useRef(); + const fieldKeyPathRef = React.useRef(); // ======================== Errors ======================== // >>>>> Collect sub field errors @@ -213,7 +221,19 @@ function InternalFormItem(props: FormItemProps): React.Rea isRequired?: boolean, ): React.ReactNode { if (noStyle && !hidden) { - return baseChildren; + return ( + + {baseChildren} + + ); } return ( @@ -287,37 +307,37 @@ function InternalFormItem(props: FormItemProps): React.Rea warning( !(shouldUpdate && dependencies), - 'Form.Item', + 'usage', "`shouldUpdate` and `dependencies` shouldn't be used together. See https://u.ant.design/form-deps.", ); if (Array.isArray(mergedChildren) && hasName) { warning( false, - 'Form.Item', + 'usage', 'A `Form.Item` with a `name` prop must have a single child element. For information on how to render more complex form items, see https://u.ant.design/complex-form-item.', ); childNode = mergedChildren; } else if (isRenderProps && (!(shouldUpdate || dependencies) || hasName)) { warning( !!(shouldUpdate || dependencies), - 'Form.Item', + 'usage', 'A `Form.Item` with a render function must have either `shouldUpdate` or `dependencies`.', ); warning( !hasName, - 'Form.Item', + 'usage', 'A `Form.Item` with a render function cannot be a field, and thus cannot have a `name` prop.', ); } else if (dependencies && !isRenderProps && !hasName) { warning( false, - 'Form.Item', + 'usage', 'Must set `name` or use a render function when `dependencies` is set.', ); } else if (isValidElement(mergedChildren)) { warning( mergedChildren.props.defaultValue === undefined, - 'Form.Item', + 'usage', '`defaultValue` will not work on controlled Field. You should use `initialValues` of Form instead.', ); @@ -383,7 +403,7 @@ function InternalFormItem(props: FormItemProps): React.Rea } else { warning( !mergedName.length, - 'Form.Item', + 'usage', '`name` is only used for validate React element. If you are using Form.Item as layout display, please remove `name` instead.', ); childNode = mergedChildren as React.ReactNode; diff --git a/components/form/FormItemInput.tsx b/components/form/FormItemInput.tsx index a806be17940c..741a86d92061 100644 --- a/components/form/FormItemInput.tsx +++ b/components/form/FormItemInput.tsx @@ -1,10 +1,12 @@ -import classNames from 'classnames'; import * as React from 'react'; +import classNames from 'classnames'; + import type { ColProps } from '../grid/col'; import Col from '../grid/col'; import { FormContext, FormItemPrefixContext } from './context'; import ErrorList from './ErrorList'; import type { ValidateStatus } from './FormItem'; +import FallbackCmp from './style/fallbackCmp'; interface FormItemInputMiscProps { prefixCls: string; @@ -116,6 +118,7 @@ const FormItemInput: React.FC = (pr {dom} + ); }; diff --git a/components/form/FormItemLabel.tsx b/components/form/FormItemLabel.tsx index 69fed60960d8..8d53fff2f317 100644 --- a/components/form/FormItemLabel.tsx +++ b/components/form/FormItemLabel.tsx @@ -114,7 +114,13 @@ const FormItemLabel: React.FC {labelChildren} @@ -127,7 +133,7 @@ const FormItemLabel: React.FC = ({ children, ...props }) => { - warning( - typeof props.name === 'number' || - (Array.isArray(props.name) ? !!props.name.length : !!props.name), - 'Form.List', - 'Miss `name` prop.', - ); + if (process.env.NODE_ENV !== 'production') { + const warning = devUseWarning('Form.List'); + + warning( + typeof props.name === 'number' || + (Array.isArray(props.name) ? !!props.name.length : !!props.name), + 'usage', + 'Miss `name` prop.', + ); + } const { getPrefixCls } = React.useContext(ConfigContext); const prefixCls = getPrefixCls('form', customizePrefixCls); diff --git a/components/form/__tests__/__snapshots__/demo-extend.test.ts.snap b/components/form/__tests__/__snapshots__/demo-extend.test.ts.snap index 23adac0b8e45..bc8b4a3581ef 100644 --- a/components/form/__tests__/__snapshots__/demo-extend.test.ts.snap +++ b/components/form/__tests__/__snapshots__/demo-extend.test.ts.snap @@ -100,7 +100,6 @@ Array [ aria-controls="advanced_search_field-1_list" aria-expanded="false" aria-haspopup="listbox" - aria-label="Search" aria-owns="advanced_search_field-1_list" aria-required="true" autocomplete="off" @@ -367,7 +366,6 @@ Array [ aria-controls="advanced_search_field-4_list" aria-expanded="false" aria-haspopup="listbox" - aria-label="Search" aria-owns="advanced_search_field-4_list" aria-required="true" autocomplete="off" @@ -550,11 +548,10 @@ Array [ style="text-align: right;" >
+
+
+
+
+
+ +`; + +exports[`renders components/form/demo/custom-feedback-icons.tsx extend context correctly 2`] = `[]`; + exports[`renders components/form/demo/customized-form-controls.tsx extend context correctly 1`] = ` +`; + +exports[`renders components/form/demo/dependencies.tsx extend context correctly 2`] = `[]`; + exports[`renders components/form/demo/disabled.tsx extend context correctly 1`] = ` Array [