diff --git a/.codesandbox/ci.json b/.codesandbox/ci.json deleted file mode 100644 index 16798ee955..0000000000 --- a/.codesandbox/ci.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "installCommand": "npm-install", - "sandboxes": ["antd-reproduction-template-forked-jyh2k9"], - "node": "18" -} diff --git a/.depslintrc.js b/.depslintrc.js index e763e9d5ed..122f41fd75 100644 --- a/.depslintrc.js +++ b/.depslintrc.js @@ -11,15 +11,15 @@ module.exports = { ], modulePattern: [ { - pattern: /ConfigContext.*renderEmpty/ms, + pattern: /ConfigContext.*renderEmpty/s, module: '../empty', }, { - pattern: /ConfigConsumer.*renderEmpty/ms, + pattern: /ConfigConsumer.*renderEmpty/s, module: '../empty', }, { - pattern: /config-provider\/context.*renderEmpty/ms, + pattern: /config-provider\/context.*renderEmpty/s, module: '../empty', }, ], diff --git a/.dumi/components/SemanticPreview.tsx b/.dumi/components/SemanticPreview.tsx index 8641dc25ea..ecdfa5442e 100644 --- a/.dumi/components/SemanticPreview.tsx +++ b/.dumi/components/SemanticPreview.tsx @@ -43,7 +43,7 @@ const useStyle = createStyles(({ token }, markPos: [number, number, number, numb z-index: 999999; box-shadow: 0 0 0 1px #fff; pointer-events: none; - left: ${markPos[0] - MARK_BORDER_SIZE}px; + inset-inline-start: ${markPos[0] - MARK_BORDER_SIZE}px; top: ${markPos[1] - MARK_BORDER_SIZE}px; width: ${markPos[2] + MARK_BORDER_SIZE * 2}px; height: ${markPos[3] + MARK_BORDER_SIZE * 2}px; @@ -66,7 +66,7 @@ const useStyle = createStyles(({ token }, markPos: [number, number, number, numb export interface SemanticPreviewProps { semantics: { name: string; desc: string; version?: string }[]; - children: React.ReactElement; + children: React.ReactElement; height?: number; } @@ -97,7 +97,7 @@ const SemanticPreview: React.FC = (props) => { // ======================== Hover ========================= const containerRef = React.useRef(null); - const timerRef = React.useRef>(); + const timerRef = React.useRef>(null); const [positionMotion, setPositionMotion] = React.useState(false); const [hoverSemantic, setHoverSemantic] = React.useState(null); @@ -111,12 +111,14 @@ const SemanticPreview: React.FC = (props) => { const targetElement = containerRef.current?.querySelector(`.${targetClassName}`); const containerRect = containerRef.current?.getBoundingClientRect(); const targetRect = targetElement?.getBoundingClientRect(); + setMarkPos([ (targetRect?.left || 0) - (containerRect?.left || 0), (targetRect?.top || 0) - (containerRect?.top || 0), targetRect?.width || 0, targetRect?.height || 0, ]); + timerRef.current = setTimeout(() => { setPositionMotion(true); }, 10); diff --git a/.dumi/global.css b/.dumi/global.css index 6c32b20c42..41fc9ed943 100644 --- a/.dumi/global.css +++ b/.dumi/global.css @@ -16,5 +16,5 @@ html { scrollbar-width: thin; - scrollbar-color: unset; + scrollbar-color: #eaeaea transparent; } diff --git a/.dumi/hooks/use.ts b/.dumi/hooks/use.ts index 2502dcd1fa..2e9bc4a0c6 100644 --- a/.dumi/hooks/use.ts +++ b/.dumi/hooks/use.ts @@ -9,22 +9,22 @@ function use(promise: PromiseLike): T { } if (internal.status === 'rejected') { throw internal.reason; - } else if (internal.status === 'pending') { - throw internal; - } else { - internal.status = 'pending'; - internal.then( - (result) => { - internal.status = 'fulfilled'; - internal.value = result; - }, - (reason) => { - internal.status = 'rejected'; - internal.reason = reason; - }, - ); + } + if (internal.status === 'pending') { throw internal; } + internal.status = 'pending'; + internal.then( + (result) => { + internal.status = 'fulfilled'; + internal.value = result; + }, + (reason) => { + internal.status = 'rejected'; + internal.reason = reason; + }, + ); + throw internal; } export default use; diff --git a/.dumi/hooks/useFetch/index.ts b/.dumi/hooks/useFetch/index.ts index 99aa763ab3..d020df56a9 100644 --- a/.dumi/hooks/useFetch/index.ts +++ b/.dumi/hooks/useFetch/index.ts @@ -1,4 +1,5 @@ import fetch from 'cross-fetch'; + import use from '../use'; import FetchCache from './cache'; diff --git a/.dumi/hooks/useLocation.ts b/.dumi/hooks/useLocation.ts index 3499a3bbe2..0c5d2e7344 100644 --- a/.dumi/hooks/useLocation.ts +++ b/.dumi/hooks/useLocation.ts @@ -1,5 +1,6 @@ -import { useLocation as useDumiLocation } from 'dumi'; import * as React from 'react'; +import { useLocation as useDumiLocation } from 'dumi'; + import useLocale from './useLocale'; function clearPath(path: string) { diff --git a/.dumi/hooks/useMenu.tsx b/.dumi/hooks/useMenu.tsx index a3c01e9505..9338510767 100644 --- a/.dumi/hooks/useMenu.tsx +++ b/.dumi/hooks/useMenu.tsx @@ -1,6 +1,6 @@ import React, { useMemo } from 'react'; import type { MenuProps } from 'antd'; -import { Tag, version } from 'antd'; +import { Space, Tag, version } from 'antd'; import { createStyles } from 'antd-style'; import classnames from 'classnames'; import { useFullSidebarData, useSidebarData } from 'dumi'; @@ -22,7 +22,6 @@ const useStyle = createStyles(({ css, token }) => ({ margin-inline-end: 0; `, subtitle: css` - margin-inline-start: ${token.marginXS}px; font-weight: normal; font-size: ${token.fontSizeSM}px; opacity: 0.8; @@ -46,10 +45,10 @@ const MenuItemLabelWithTag: React.FC = (props) => { if (!before && !after) { return ( - - {title} + + {title} {subtitle && {subtitle}} - + {tag && ( { .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); }); @@ -99,6 +98,7 @@ const useThemeAnimation = () => { root.classList.add(isDark ? 'light' : 'dark'); }) .ready.then(() => { + // eslint-disable-next-line no-console console.log(`Theme transition finished in ${Date.now() - time}ms`); const clipPath = [ `circle(0px at ${x}px ${y}px)`, diff --git a/.dumi/loading.js b/.dumi/loading.js index 23b84ea095..811f63354e 100644 --- a/.dumi/loading.js +++ b/.dumi/loading.js @@ -1,3 +1,3 @@ // must be .js file, can't modify to be .ts file! -// eslint-disable-next-line no-restricted-exports + export { default } from './theme/common/Loading'; diff --git a/.dumi/pages/404/index.tsx b/.dumi/pages/404/index.tsx index 502df93dc8..15229c04c8 100644 --- a/.dumi/pages/404/index.tsx +++ b/.dumi/pages/404/index.tsx @@ -1,7 +1,9 @@ -import { HomeOutlined } from '@ant-design/icons'; -import { Link, useLocation } from 'dumi'; import React, { useEffect } from 'react'; +import { HomeOutlined } from '@ant-design/icons'; import { Button, Result } from 'antd'; +import { useLocation } from 'dumi'; + +import Link from '../../theme/common/Link'; import * as utils from '../../theme/utils'; export interface NotFoundProps { diff --git a/.dumi/pages/index/components/BannerRecommends.tsx b/.dumi/pages/index/components/BannerRecommends.tsx index a7cd969d02..8c6dfc16c2 100644 --- a/.dumi/pages/index/components/BannerRecommends.tsx +++ b/.dumi/pages/index/components/BannerRecommends.tsx @@ -1,6 +1,6 @@ import React, { useContext } from 'react'; -import { Badge, Carousel, Skeleton, Typography } from 'antd'; -import { createStyles, useTheme } from 'antd-style'; +import { Badge, Carousel, Flex, Skeleton, Typography } from 'antd'; +import { createStyles } from 'antd-style'; import classNames from 'classnames'; import useLocale from '../../../hooks/useLocale'; @@ -36,6 +36,7 @@ const useStyle = createStyles(({ token, css, cx }) => { cardItem: css` &:hover { box-shadow: ${token.boxShadowCard}; + border-color: transparent; } `, sliderItem: css` @@ -57,6 +58,9 @@ const useStyle = createStyles(({ token, css, cx }) => { } `, carousel, + bannerBg: css` + height: ${token.fontSize}px; + `, }; }); @@ -66,8 +70,8 @@ interface RecommendItemProps { icons: Icon[]; className?: string; } + const RecommendItem: React.FC = ({ extra, index, icons, className }) => { - const token = useTheme(); const { styles } = useStyle(); if (!extra) { @@ -87,10 +91,10 @@ const RecommendItem: React.FC = ({ extra, index, icons, clas {extra.description} -
+ {extra.date} - {icon && banner} -
+ {icon && banner} + ); @@ -109,7 +113,7 @@ export const BannerRecommendsFallback: React.FC = () => { const { isMobile } = useContext(SiteContext); const { styles } = useStyle(); - const list = Array(3).fill(1); + const list = new Array(3).fill(1); return isMobile ? ( @@ -137,7 +141,7 @@ const BannerRecommends: React.FC = () => { const data = useSiteData(); const extras = data?.extras?.[lang]; const icons = data?.icons || []; - const first3 = !extras || extras.length === 0 ? Array(3).fill(null) : extras.slice(0, 3); + const first3 = !extras || extras.length === 0 ? new Array(3).fill(null) : extras.slice(0, 3); if (!data) { return ; diff --git a/.dumi/pages/index/components/ComponentsList.tsx b/.dumi/pages/index/components/ComponentsList.tsx index 8918a037db..739355b890 100644 --- a/.dumi/pages/index/components/ComponentsList.tsx +++ b/.dumi/pages/index/components/ComponentsList.tsx @@ -12,7 +12,7 @@ import { Tour, Typography, } from 'antd'; -import { createStyles, css, useTheme } from 'antd-style'; +import { createStyles, css } from 'antd-style'; import classNames from 'classnames'; import dayjs from 'dayjs'; @@ -104,6 +104,13 @@ const useStyle = () => { justify-content: center; `, carousel, + componentsList: css` + width: 100%; + overflow: hidden; + `, + mobileComponentsList: css` + margin: 0 ${token.margin}px; + `, }; })(); }; @@ -119,7 +126,7 @@ const ComponentItem: React.FC = ({ title, node, type, index {/* Decorator */}
{/* Title */} @@ -142,7 +149,6 @@ interface ComponentItemProps { } const ComponentsList: React.FC = () => { - const token = useTheme(); const { styles } = useStyle(); const [locale] = useLocale(locales); const { isMobile } = useContext(SiteContext); @@ -251,7 +257,7 @@ const ComponentsList: React.FC = () => { style={{ width: 400 }} message="Ant Design 5.0" description={locale.sampleContent} - closable + closable={{ closeIcon: true, disabled: true }} /> ), }, @@ -260,21 +266,33 @@ const ComponentsList: React.FC = () => { ); return isMobile ? ( -
+
{COMPONENTS.map(({ title, node, type }, index) => ( - + ))}
) : ( -
-
+ + {COMPONENTS.map(({ title, node, type }, index) => ( - + ))} -
-
+ + ); }; diff --git a/.dumi/pages/index/components/DesignFramework.tsx b/.dumi/pages/index/components/DesignFramework.tsx index d7fa6c753e..e2816d9118 100644 --- a/.dumi/pages/index/components/DesignFramework.tsx +++ b/.dumi/pages/index/components/DesignFramework.tsx @@ -1,10 +1,11 @@ import React, { useContext } from 'react'; import { Col, Row, Typography } from 'antd'; import { createStyles, useTheme } from 'antd-style'; -import { Link, useLocation } from 'dumi'; +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'; @@ -133,7 +134,7 @@ const DesignFramework: React.FC = () => {
- {title} + {title} { return ( - {title} + {title} { const { direction } = React.useContext(ConfigProvider.ConfigContext); + const { isMobile } = React.useContext(SiteContext); const isRTL = direction === 'rtl'; return createStyles(({ token, css, cx }) => { const textShadow = `0 0 4px ${token.colorBgContainer}`; @@ -101,11 +104,23 @@ const useStyle = () => { btnWrap: css` margin-bottom: ${token.marginXL}px; `, + bgImg: css` + position: absolute; + width: 240px; + `, + bgImgTop: css` + top: 0; + inset-inline-start: ${isMobile ? '-120px' : 0}; + `, + bgImgBottom: css` + bottom: 120px; + inset-inline-end: ${isMobile ? 0 : '40%'}; + `, }; })(); }; -const PreviewBanner: React.FC = (props) => { +const PreviewBanner: React.FC> = (props) => { const { children } = props; const [locale] = useLocale(locales); const { styles } = useStyle(); @@ -117,15 +132,17 @@ const PreviewBanner: React.FC = (props) => { {/* Image Left Top */} bg {/* Image Right Top */} bg
@@ -143,14 +160,19 @@ const PreviewBanner: React.FC = (props) => {

{locale.slogan}

- - - - - - + + {locale.start} + + + {locale.designLanguage} +
{children}
diff --git a/.dumi/pages/index/components/Theme/BackgroundImage.tsx b/.dumi/pages/index/components/Theme/BackgroundImage.tsx index 27c027c543..5875571cac 100644 --- a/.dumi/pages/index/components/Theme/BackgroundImage.tsx +++ b/.dumi/pages/index/components/Theme/BackgroundImage.tsx @@ -14,7 +14,7 @@ const useStyle = createStyles(({ token }) => ({ image: css` transition: all ${token.motionDurationSlow}; position: absolute; - left: 0; + inset-inline-start: 0; top: 0; height: 100%; width: 100%; @@ -64,10 +64,11 @@ const BackgroundImage: React.FC = ({ colorPrimary, isLight ); diff --git a/.dumi/pages/index/components/Theme/ColorPicker.tsx b/.dumi/pages/index/components/Theme/ColorPicker.tsx index ab9b1dc08a..68262526b9 100644 --- a/.dumi/pages/index/components/Theme/ColorPicker.tsx +++ b/.dumi/pages/index/components/Theme/ColorPicker.tsx @@ -1,12 +1,14 @@ import React, { useEffect, useState } from 'react'; import { ColorPicker, Flex, Input } from 'antd'; +import type { ColorPickerProps, GetProp } from 'antd'; 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'; +type Color = Extract, string | { cleared: any }>; + const useStyle = createStyles(({ token, css }) => ({ color: css` width: ${token.controlHeightLG / 2}px; @@ -34,13 +36,13 @@ const useStyle = createStyles(({ token, css }) => ({ `, })); -export interface ColorPickerProps { +export interface ThemeColorPickerProps { id?: string; value?: string | Color; onChange?: (value?: Color | string) => void; } -const DebouncedColorPicker: React.FC> = (props) => { +const DebouncedColorPicker: React.FC> = (props) => { const { value: color, children, onChange } = props; const [value, setValue] = useState(color); @@ -59,14 +61,14 @@ const DebouncedColorPicker: React.FC> {children} ); }; -const ThemeColorPicker: React.FC = ({ value, onChange, id }) => { +const ThemeColorPicker: React.FC = ({ value, onChange, id }) => { const { styles } = useStyle(); const matchColors = React.useMemo(() => { @@ -100,7 +102,6 @@ const ThemeColorPicker: React.FC = ({ value, onChange, id }) = {matchColors.map(({ color, active, picker }) => { const colorNode = ( - // eslint-disable-next-line jsx-a11y/label-has-associated-control

Ant Design 5.0

@@ -518,14 +519,15 @@ const Theme: React.FC = () => { title={locale.myTheme} extra={ - - - - + {locale.toDef} + + - - + {locale.toUse} + } > diff --git a/.dumi/pages/index/index.tsx b/.dumi/pages/index/index.tsx index a528f4347e..9e5a23705e 100644 --- a/.dumi/pages/index/index.tsx +++ b/.dumi/pages/index/index.tsx @@ -5,8 +5,8 @@ import { createStyles, css } from 'antd-style'; import useDark from '../../hooks/useDark'; import useLocale from '../../hooks/useLocale'; import BannerRecommends from './components/BannerRecommends'; -import PreviewBanner from './components/PreviewBanner'; import Group from './components/Group'; +import PreviewBanner from './components/PreviewBanner'; const ComponentsList = React.lazy(() => import('./components/ComponentsList')); const DesignFramework = React.lazy(() => import('./components/DesignFramework')); @@ -15,7 +15,7 @@ const Theme = React.lazy(() => import('./components/Theme')); const useStyle = createStyles(() => ({ image: css` position: absolute; - left: 0; + inset-inline-start: 0; top: -50px; height: 160px; `, @@ -78,12 +78,13 @@ const Homepage: React.FC = () => { } > diff --git a/.dumi/pages/theme-editor/index.tsx b/.dumi/pages/theme-editor/index.tsx index 011d3decb5..1082acd642 100644 --- a/.dumi/pages/theme-editor/index.tsx +++ b/.dumi/pages/theme-editor/index.tsx @@ -1,5 +1,5 @@ import React, { Suspense, useEffect } from 'react'; -import { Button, message, Skeleton } from 'antd'; +import { Button, App, Skeleton } from 'antd'; import { enUS, zhCN } from 'antd-token-previewer'; import type { ThemeConfig } from 'antd/es/config-provider/context'; import { Helmet } from 'dumi'; @@ -36,7 +36,7 @@ const locales = { const ANT_DESIGN_V5_THEME_EDITOR_THEME = 'ant-design-v5-theme-editor-theme'; const CustomTheme: React.FC = () => { - const [messageApi, contextHolder] = message.useMessage(); + const { message } = App.useApp(); const [locale, lang] = useLocale(locales); const [theme, setTheme] = React.useState({}); @@ -51,7 +51,7 @@ const CustomTheme: React.FC = () => { const handleSave = () => { localStorage.setItem(ANT_DESIGN_V5_THEME_EDITOR_THEME, JSON.stringify(theme)); - messageApi.success(locale.saveSuccessfully); + message.success(locale.saveSuccessfully); }; return ( @@ -60,7 +60,6 @@ const CustomTheme: React.FC = () => { {`${locale.title} - Ant Design`} - {contextHolder} }> { if (typeof lang === 'string' && lang.startsWith('sandpack')) { const code = (node.children[0] as any).value as string; - const configRegx = /^const sandpackConfig = ([\S\s]*?});/; + const configRegx = /^const sandpackConfig = ([\s\S]*?});/; const [configString] = code.match(configRegx) || []; - // eslint-disable-next-line no-eval + /* biome-ignore lint/security/noGlobalEval: used in documentation */ /* eslint-disable-next-line no-eval */ const config = configString && eval(`(${configString.replace(configRegx, '$1')})`); Object.keys(config || {}).forEach((key) => { if (typeof config[key] === 'object') { diff --git a/.dumi/scripts/mirror-modal.js b/.dumi/scripts/mirror-modal.js index aa34aa964d..9b024a2e0c 100644 --- a/.dumi/scripts/mirror-modal.js +++ b/.dumi/scripts/mirror-modal.js @@ -50,8 +50,8 @@ .mirror-modal-dialog { position: fixed; top: 120px; - left: 0; - right: 0; + inset-inline-start: 0; + inset-inline-end: 0; margin: 0 auto; width: 420px; display: flex; @@ -141,12 +141,12 @@ const title = document.createElement('div'); title.className = 'mirror-modal-title'; - title.innerText = '提示'; + title.textContent = '提示'; dialog.append(title); const content = document.createElement('div'); content.className = 'mirror-modal-content'; - content.innerText = '🚀 国内用户推荐访问国内镜像以获得极速体验~'; + content.textContent = '🚀 国内用户推荐访问国内镜像以获得极速体验~'; dialog.append(content); const btnWrapper = document.createElement('div'); @@ -155,7 +155,7 @@ const cancelBtn = document.createElement('a'); cancelBtn.className = 'mirror-modal-cancel-btn mirror-modal-btn'; - cancelBtn.innerText = '7 天内不再显示'; + cancelBtn.textContent = '7 天内不再显示'; btnWrapper.append(cancelBtn); cancelBtn.addEventListener('click', () => { window.localStorage.setItem(ANTD_DOT_NOT_SHOW_MIRROR_MODAL, new Date().toISOString()); @@ -167,7 +167,7 @@ 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 = '🚀 立刻前往'; + confirmBtn.textContent = '🚀 立刻前往'; btnWrapper.append(confirmBtn); document.body.append(modal); diff --git a/.dumi/theme/SiteThemeProvider.tsx b/.dumi/theme/SiteThemeProvider.tsx index 306d3558a0..a9cc10fb60 100644 --- a/.dumi/theme/SiteThemeProvider.tsx +++ b/.dumi/theme/SiteThemeProvider.tsx @@ -24,7 +24,6 @@ interface NewToken { // 通过给 antd-style 扩展 CustomToken 对象类型定义,可以为 useTheme 中增加相应的 token 对象 declare module 'antd-style' { - // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface CustomToken extends NewToken {} } diff --git a/.dumi/theme/builtins/Antd.tsx b/.dumi/theme/builtins/Antd.tsx new file mode 100644 index 0000000000..910c74ce1a --- /dev/null +++ b/.dumi/theme/builtins/Antd.tsx @@ -0,0 +1,15 @@ +import * as React from 'react'; +import * as all from 'antd'; + +interface AntdProps { + component: keyof typeof all; +} + +function Antd(props: AntdProps) { + const { component, ...restProps } = props; + const Component = (all[component] ?? React.Fragment) as React.ComponentType; + + return ; +} + +export default Antd; diff --git a/.dumi/theme/builtins/Audio/index.tsx b/.dumi/theme/builtins/Audio/index.tsx new file mode 100644 index 0000000000..288bd14cfd --- /dev/null +++ b/.dumi/theme/builtins/Audio/index.tsx @@ -0,0 +1,48 @@ +import React from 'react'; +import { SoundOutlined } from '@ant-design/icons'; +import { createStyles } from 'antd-style'; + +const useStyle = createStyles(({ css, token }) => { + const { paddingXXS, fontSizeXL, motionDurationSlow, colorLink, colorLinkHover, colorLinkActive } = + token; + return { + playBtn: css` + display: inline-flex; + justify-content: center; + align-items: center; + column-gap: ${paddingXXS}px; + margin: 0; + `, + icon: css` + font-size: ${fontSizeXL}px; + color: ${colorLink}; + transition: all ${motionDurationSlow}; + &:hover { + color: ${colorLinkHover}; + } + &:active { + color: ${colorLinkActive}; + } + `, + }; +}); + +interface AudioProps { + id?: string; +} + +const AudioControl: React.FC> = ({ id, children }) => { + const { styles } = useStyle(); + const onClick: React.MouseEventHandler = () => { + const audio = document.querySelector(`#${id}`); + audio?.play(); + }; + return ( +
+ {children} + + + ); +}; + +export default AudioControl; diff --git a/.dumi/theme/builtins/ColorChunk/index.tsx b/.dumi/theme/builtins/ColorChunk/index.tsx index 26d815145f..42c4634a7d 100644 --- a/.dumi/theme/builtins/ColorChunk/index.tsx +++ b/.dumi/theme/builtins/ColorChunk/index.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; -import type { ColorInput } from '@ctrl/tinycolor'; -import { TinyColor } from '@ctrl/tinycolor'; +// @ts-ignore +import { TinyColor } from 'dumi-plugin-color-chunk/component'; import { createStyles } from 'antd-style'; const useStyle = createStyles(({ token, css }) => ({ @@ -22,7 +22,7 @@ const useStyle = createStyles(({ token, css }) => ({ })); interface ColorChunkProps { - value?: ColorInput; + value: any; } const ColorChunk: React.FC> = (props) => { diff --git a/.dumi/theme/builtins/ComponentMeta/index.tsx b/.dumi/theme/builtins/ComponentMeta/index.tsx index 7b891497b0..0539cf9c0a 100644 --- a/.dumi/theme/builtins/ComponentMeta/index.tsx +++ b/.dumi/theme/builtins/ComponentMeta/index.tsx @@ -1,12 +1,13 @@ import React from 'react'; -import { EditOutlined, GithubOutlined } from '@ant-design/icons'; +import { EditOutlined, GithubOutlined, HistoryOutlined } from '@ant-design/icons'; import type { GetProp } from 'antd'; -import { Descriptions, theme, Tooltip, Typography } from 'antd'; +import { Descriptions, Flex, theme, Tooltip, Typography } from 'antd'; import { createStyles, css } from 'antd-style'; import kebabCase from 'lodash/kebabCase'; import CopyToClipboard from 'react-copy-to-clipboard'; import useLocale from '../../../hooks/useLocale'; +import ComponentChangelog from '../../common/ComponentChangelog'; const locales = { cn: { @@ -16,6 +17,7 @@ const locales = { source: '源码', docs: '文档', edit: '编辑此页', + changelog: '更新日志', version: '版本', }, en: { @@ -25,6 +27,7 @@ const locales = { source: 'Source', docs: 'Docs', edit: 'Edit this page', + changelog: 'Changelog', version: 'Version', }, }; @@ -43,7 +46,7 @@ const useStyle = createStyles(({ token }) => ({ align-items: center; column-gap: ${token.paddingXXS}px; border-radius: ${token.borderRadiusSM}px; - padding-inline: ${token.paddingXXS}px; + padding-inline: ${token.paddingXXS}px !important; transition: all ${token.motionDurationSlow} !important; font-family: ${token.codeFamily}; color: ${token.colorTextSecondary} !important; @@ -70,6 +73,9 @@ const useStyle = createStyles(({ token }) => ({ semicolon: css` color: ${token.colorText}; `, + icon: css` + margin-inline-end: ${token.marginXXS}px; + `, })); export interface ComponentMetaProps { @@ -116,12 +122,21 @@ const ComponentMeta: React.FC = (props) => { return [source, source]; }, [component, source]); + const transformComponentName = (componentName: string) => { + if (componentName === 'Notification' || componentName === 'Message') { + return componentName.toLowerCase(); + } + return componentName; + }; + // ======================== Render ======================== const importList = [ import , - {`{ ${component} }`}, + {`{ ${transformComponentName( + component, + )} }`}, from , @@ -139,7 +154,9 @@ const ComponentMeta: React.FC = (props) => { colon={false} column={1} style={{ marginTop: token.margin }} - labelStyle={{ paddingInlineEnd: token.padding, width: 56 }} + styles={{ + label: { paddingInlineEnd: token.padding, width: 56 }, + }} items={ [ { @@ -162,7 +179,7 @@ const ComponentMeta: React.FC = (props) => { label: locale.source, children: ( - + {abbrSource} ), @@ -170,14 +187,22 @@ const ComponentMeta: React.FC = (props) => { filename && { label: locale.docs, children: ( - - - {locale.edit} - + + + + {locale.edit} + + + + + {locale.changelog} + + + ), }, isVersionNumber(version) && { diff --git a/.dumi/theme/builtins/ComponentOverview/index.tsx b/.dumi/theme/builtins/ComponentOverview/index.tsx index 3d4665d67a..ad02ce28e5 100644 --- a/.dumi/theme/builtins/ComponentOverview/index.tsx +++ b/.dumi/theme/builtins/ComponentOverview/index.tsx @@ -198,46 +198,59 @@ const Overview: React.FC = () => { {components.map((component) => { + let url = component.link; /** 是否是外链 */ - const isExternalLink = component.link.startsWith('http'); - let url = `${component.link}`; + const isExternalLink = url.startsWith('http'); if (!isExternalLink) { url += urlSearch; } - return ( - - - onClickCard(url)} - styles={{ - body: { - backgroundRepeat: 'no-repeat', - backgroundPosition: 'bottom right', - backgroundImage: `url(${component?.tag || ''})`, - }, - }} - size="small" - className={styles.componentsOverviewCard} - title={ -
- {component?.title} {component.subtitle} -
+ const cardContent = ( + onClickCard(url)} + styles={{ + body: { + backgroundRepeat: 'no-repeat', + backgroundPosition: 'bottom right', + backgroundImage: `url(${component.tag || ''})`, + }, + }} + size="small" + className={styles.componentsOverviewCard} + title={ +
+ {component.title} {component.subtitle} +
+ } + > +
+ -
- {component?.title} -
- - + alt={component.title} + /> +
+
+ ); + + const linkContent = isExternalLink ? ( + + {cardContent} + + ) : ( + + {cardContent} + + ); + + return ( + + {linkContent} ); })} diff --git a/.dumi/theme/builtins/ComponentTokenTable/index.tsx b/.dumi/theme/builtins/ComponentTokenTable/index.tsx index ab6b6ac299..402a365ff0 100644 --- a/.dumi/theme/builtins/ComponentTokenTable/index.tsx +++ b/.dumi/theme/builtins/ComponentTokenTable/index.tsx @@ -8,6 +8,7 @@ import tokenData from 'antd/es/version/token.json'; import useLocale from '../../../hooks/useLocale'; import { useColumns } from '../TokenTable'; +import type { TokenData } from '../TokenTable'; const compare = (token1: string, token2: string) => { const hasColor1 = token1.toLowerCase().includes('color'); @@ -108,13 +109,13 @@ const SubTokenTable: React.FC = (props) => { const data = tokens .sort(component ? undefined : compare) - .map((name) => { + .map((name) => { const meta = component ? tokenMeta.components[component].find((item) => item.token === name) : tokenMeta.global[name]; if (!meta) { - return null; + return null as unknown as TokenData; } return { @@ -156,7 +157,7 @@ const SubTokenTable: React.FC = (props) => { {title} {/* {code} */} @@ -177,7 +178,7 @@ const SubTokenTable: React.FC = (props) => {
{open && ( - size="middle" columns={columns} bordered diff --git a/.dumi/theme/builtins/DemoWrapper/index.tsx b/.dumi/theme/builtins/DemoWrapper/index.tsx index f5b75efe95..18ca44f5b5 100644 --- a/.dumi/theme/builtins/DemoWrapper/index.tsx +++ b/.dumi/theme/builtins/DemoWrapper/index.tsx @@ -1,19 +1,13 @@ -import React, { useContext } from 'react'; -import { - BugFilled, - BugOutlined, - CodeFilled, - CodeOutlined, - ExperimentFilled, - ExperimentOutlined, -} from '@ant-design/icons'; -import { ConfigProvider, Tooltip } from 'antd'; -import classNames from 'classnames'; -import { DumiDemoGrid, FormattedMessage } from 'dumi'; +import React, { Suspense, useContext } from 'react'; +import { BugOutlined, CodeOutlined, ExperimentOutlined } from '@ant-design/icons'; +import { ConfigProvider, Tooltip, Button } from 'antd'; +import { DumiDemoGrid, FormattedMessage, DumiDemo } from 'dumi'; +import { css, Global } from '@emotion/react'; import useLayoutState from '../../../hooks/useLayoutState'; import useLocale from '../../../hooks/useLocale'; import DemoContext from '../../slots/DemoContext'; +import DemoFallback from '../Previewer/DemoFallback'; const locales = { cn: { @@ -33,10 +27,6 @@ const DemoWrapper: typeof DumiDemoGrid = ({ items }) => { const [expandAll, setExpandAll] = useLayoutState(false); const [enableCssVar, setEnableCssVar] = useLayoutState(true); - const expandTriggerClass = classNames('code-box-expand-trigger', { - 'code-box-expand-trigger-active': expandAll, - }); - const handleVisibleToggle = () => { setShowDebug?.(!showDebug); }; @@ -51,70 +41,85 @@ const DemoWrapper: typeof DumiDemoGrid = ({ items }) => { const demos = React.useMemo( () => - items.reduce( - (acc, item) => { - const { previewerProps } = item; - const { debug } = previewerProps; - - if (debug && !showDebug) { - return acc; - } - - return acc.concat({ - ...item, - previewerProps: { - ...previewerProps, - expand: expandAll, - // always override debug property, because dumi will hide debug demo in production - debug: false, - /** - * antd extra marker for the original debug - * @see https://github.com/ant-design/ant-design/pull/40130#issuecomment-1380208762 - */ - originDebug: debug, - }, - }); - }, - [] as typeof items, - ), + items.reduce((acc, item) => { + const { previewerProps } = item; + const { debug } = previewerProps; + if (debug && !showDebug) { + return acc; + } + return acc.concat({ + ...item, + previewerProps: { + ...previewerProps, + expand: expandAll, + // always override debug property, because dumi will hide debug demo in production + debug: false, + /** + * antd extra marker for the original debug + * @see https://github.com/ant-design/ant-design/pull/40130#issuecomment-1380208762 + */ + originDebug: debug, + }, + }); + }, []), [expandAll, showDebug], ); return (
+ } > - {expandAll ? ( - - ) : ( - - )} +
); diff --git a/.dumi/theme/builtins/IconSearch/Category.tsx b/.dumi/theme/builtins/IconSearch/Category.tsx index 92113e1a58..0a306b256a 100644 --- a/.dumi/theme/builtins/IconSearch/Category.tsx +++ b/.dumi/theme/builtins/IconSearch/Category.tsx @@ -9,39 +9,17 @@ import type { ThemeType } from './IconSearch'; const useStyle = createStyles(({ token, css }) => ({ anticonsList: css` - margin: ${token.marginSM}px 0; + margin: ${token.margin}px 0; overflow: hidden; direction: ltr; list-style: none; - li { - position: relative; - float: left; - width: 16.66%; - height: 100px; - margin: ${token.marginXXS}px 0; - padding: ${token.paddingSM}px 0 0; - overflow: hidden; - color: #555; - text-align: center; - list-style: none; - background-color: inherit; - border-radius: ${token.borderRadiusSM}px; - cursor: pointer; - transition: all ${token.motionDurationSlow} ease-in-out; - .rtl & { - margin: ${token.marginXXS}px 0; - padding: ${token.paddingSM}px 0 0; - } - ${token.iconCls} { - margin: ${token.marginSM}px 0 ${token.marginXS}px; - font-size: 36px; - transition: transform ${token.motionDurationSlow} ease-in-out; - will-change: transform; - } - } + display: grid; + grid-gap: ${token.margin}px; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + padding: 0; `, copiedCode: css` - padding: 2px 4px; + padding: 0 ${token.paddingXXS}px; font-size: ${token.fontSizeSM}px; background-color: ${token.colorBgLayout}; border-radius: ${token.borderRadiusXS}px; diff --git a/.dumi/theme/builtins/IconSearch/CopyableIcon.tsx b/.dumi/theme/builtins/IconSearch/CopyableIcon.tsx index ba3c972a0a..dcf570f6c4 100644 --- a/.dumi/theme/builtins/IconSearch/CopyableIcon.tsx +++ b/.dumi/theme/builtins/IconSearch/CopyableIcon.tsx @@ -1,6 +1,6 @@ import React from 'react'; import * as AntdIcons from '@ant-design/icons'; -import { Badge, message } from 'antd'; +import { App, Badge } from 'antd'; import { createStyles } from 'antd-style'; import classNames from 'classnames'; import CopyToClipboard from 'react-copy-to-clipboard'; @@ -12,15 +12,40 @@ const allIcons: { [key: PropertyKey]: any } = AntdIcons; const useStyle = createStyles(({ token, css }) => { const { antCls, iconCls } = token; return { - item: css` + iconItem: css` + display: inline-flex; + flex-direction: column; + justify-content: center; + align-items: center; + margin-inline-start: 0 !important; + margin-inline-end: 0 !important; + padding-inline-start: 0 !important; + padding-inline-end: 0 !important; + position: relative; + width: 200px; + height: 100px; + overflow: hidden; + color: #555; + text-align: center; + list-style: none; + background-color: inherit; + border-radius: ${token.borderRadiusSM}px; + cursor: pointer; + transition: all ${token.motionDurationSlow} ease-in-out; + ${token.iconCls} { + margin: ${token.marginXS}px 0; + font-size: 36px; + transition: transform ${token.motionDurationSlow} ease-in-out; + will-change: transform; + } &:hover { - color: #fff; + color: ${token.colorWhite}; background-color: ${token.colorPrimary}; ${iconCls} { transform: scale(1.3); } ${antCls}-badge { - color: #fff; + color: ${token.colorWhite}; } } &.TwoTone:hover { @@ -33,13 +58,13 @@ const useStyle = createStyles(({ token, css }) => { content: 'Copied!'; position: absolute; top: 0; - left: 0; + inset-inline-start: 0; width: 100%; height: 100%; - color: #fff; - line-height: 110px; + line-height: 100px; + color: ${token.colorTextLightSolid}; text-align: center; - background-color: #1677ff; + background-color: ${token.colorPrimary}; opacity: 0; transition: all ${token.motionDurationSlow} cubic-bezier(0.18, 0.89, 0.32, 1.28); } @@ -69,6 +94,7 @@ export interface CopyableIconProps { } const CopyableIcon: React.FC = (props) => { + const { message } = App.useApp(); const { name, isNew, justCopied, theme, onCopied } = props; const { styles } = useStyle(); const onCopy = (text: string, result: boolean) => { @@ -80,7 +106,7 @@ const CopyableIcon: React.FC = (props) => { }; return ( `} onCopy={onCopy}> -
  • +
  • {React.createElement(allIcons[name])} {name} diff --git a/.dumi/theme/builtins/IconSearch/IconSearch.tsx b/.dumi/theme/builtins/IconSearch/IconSearch.tsx index 64e5df813e..288f6d2307 100644 --- a/.dumi/theme/builtins/IconSearch/IconSearch.tsx +++ b/.dumi/theme/builtins/IconSearch/IconSearch.tsx @@ -1,9 +1,9 @@ import type { CSSProperties } from 'react'; import React, { useCallback, useMemo, useState } from 'react'; import Icon, * as AntdIcons from '@ant-design/icons'; -import type { SegmentedProps } from 'antd'; import { Affix, Empty, Input, Segmented } from 'antd'; import { createStyles, useTheme } from 'antd-style'; +import type { SegmentedOptions } from 'antd/es/segmented'; import { useIntl } from 'dumi'; import debounce from 'lodash/debounce'; @@ -28,26 +28,6 @@ const useStyle = createStyles(({ token, css }) => ({ `, })); -const options = ( - formatMessage: (values: Record) => React.ReactNode, -): SegmentedProps['options'] => [ - { - value: ThemeType.Outlined, - icon: , - label: formatMessage({ id: 'app.docs.components.icon.outlined' }), - }, - { - value: ThemeType.Filled, - icon: , - label: formatMessage({ id: 'app.docs.components.icon.filled' }), - }, - { - value: ThemeType.TwoTone, - icon: , - label: formatMessage({ id: 'app.docs.components.icon.two-tone' }), - }, -]; - interface IconSearchState { theme: ThemeType; searchKey: string; @@ -80,8 +60,8 @@ const IconSearch: React.FC = () => { let iconList = categories[key as CategoriesKeys]; if (searchKey) { const matchKey = searchKey - // eslint-disable-next-line prefer-regex-literals - .replace(new RegExp(`^<([a-zA-Z]*)\\s/>$`, 'gi'), (_, name) => name) + + .replace(/^<([a-z]*)\s\/>$/gi, (_, name) => name) .replace(/(Filled|Outlined|TwoTone)$/, '') .toLowerCase(); iconList = iconList.filter((iconName) => iconName.toLowerCase().includes(matchKey)); @@ -124,14 +104,35 @@ const IconSearch: React.FC = () => { backgroundColor: colorBgContainer, }; + const memoizedOptions = React.useMemo>( + () => [ + { + value: ThemeType.Outlined, + icon: , + label: intl.formatMessage({ id: 'app.docs.components.icon.outlined' }), + }, + { + value: ThemeType.Filled, + icon: , + label: intl.formatMessage({ id: 'app.docs.components.icon.filled' }), + }, + { + value: ThemeType.TwoTone, + icon: , + label: intl.formatMessage({ id: 'app.docs.components.icon.two-tone' }), + }, + ], + [intl], + ); + return (
    - size="large" value={displayState.theme} - options={options(intl.formatMessage)} + options={memoizedOptions} onChange={handleChangeTheme} /> {
    - {Array(24) - .fill(1) - .map((_, index) => ( -
    - - {' '} - -
    - ))} + {new Array(24).fill(1).map((_, index) => ( +
    + + {' '} + +
    + ))}
    ); diff --git a/.dumi/theme/builtins/IconSearch/themeIcons.tsx b/.dumi/theme/builtins/IconSearch/themeIcons.tsx index 892a95dd29..bea1ef7509 100644 --- a/.dumi/theme/builtins/IconSearch/themeIcons.tsx +++ b/.dumi/theme/builtins/IconSearch/themeIcons.tsx @@ -12,6 +12,7 @@ export const FilledIcon: CustomIconComponent = (props) => { '0c0-53-43-96-96-96z'; return ( + Filled Icon ); @@ -26,6 +27,7 @@ export const OutlinedIcon: CustomIconComponent = (props) => { ' 12 12v680c0 6.6-5.4 12-12 12z'; return ( + Outlined Icon ); @@ -39,6 +41,7 @@ export const TwoToneIcon: CustomIconComponent = (props) => { '68 368 0 203.41-164.622 368-368 368z'; return ( + TwoTone Icon ); diff --git a/.dumi/theme/builtins/ImagePreview/index.tsx b/.dumi/theme/builtins/ImagePreview/index.tsx index a504bf0164..7fe41f0af4 100644 --- a/.dumi/theme/builtins/ImagePreview/index.tsx +++ b/.dumi/theme/builtins/ImagePreview/index.tsx @@ -117,6 +117,7 @@ const ImagePreview: React.FC> = (prop
    {coverMeta.alt}
    diff --git a/.dumi/theme/builtins/InlinePopover/index.tsx b/.dumi/theme/builtins/InlinePopover/index.tsx index 2621eb0d2d..74852b02e5 100644 --- a/.dumi/theme/builtins/InlinePopover/index.tsx +++ b/.dumi/theme/builtins/InlinePopover/index.tsx @@ -1,6 +1,7 @@ -import { PictureOutlined } from '@ant-design/icons'; import React from 'react'; +import { PictureOutlined } from '@ant-design/icons'; import { Image, Tooltip, Typography } from 'antd'; + import useLocale from '../../../hooks/useLocale'; const locales = { diff --git a/.dumi/theme/builtins/InstallDependencies/index.tsx b/.dumi/theme/builtins/InstallDependencies/index.tsx index d1cd32a845..36bcd4dcc3 100644 --- a/.dumi/theme/builtins/InstallDependencies/index.tsx +++ b/.dumi/theme/builtins/InstallDependencies/index.tsx @@ -3,10 +3,10 @@ import { ConfigProvider, Tabs } from 'antd'; import SourceCode from 'dumi/theme-default/builtins/SourceCode'; import type { Tab } from 'rc-tabs/lib/interface'; +import BunLogo from './bun'; import NpmLogo from './npm'; import PnpmLogo from './pnpm'; import YarnLogo from './yarn'; -import BunLogo from './bun'; interface InstallProps { npm?: string; diff --git a/.dumi/theme/builtins/InstallDependencies/npm.tsx b/.dumi/theme/builtins/InstallDependencies/npm.tsx index 63937b0322..923e18e710 100644 --- a/.dumi/theme/builtins/InstallDependencies/npm.tsx +++ b/.dumi/theme/builtins/InstallDependencies/npm.tsx @@ -31,6 +31,7 @@ const NpmIcon: React.FC = (props) => { viewBox="0 0 16 16" width="1em" > + npm icon diff --git a/.dumi/theme/builtins/InstallDependencies/pnpm.tsx b/.dumi/theme/builtins/InstallDependencies/pnpm.tsx index 67cb132e2e..ea8fd55de8 100644 --- a/.dumi/theme/builtins/InstallDependencies/pnpm.tsx +++ b/.dumi/theme/builtins/InstallDependencies/pnpm.tsx @@ -33,6 +33,7 @@ const PnpmIcon: React.FC = (props) => { viewBox="0 0 24 24" width="1em" > + pnpm icon diff --git a/.dumi/theme/builtins/InstallDependencies/yarn.tsx b/.dumi/theme/builtins/InstallDependencies/yarn.tsx index 7f73b97efd..e4ffa35142 100644 --- a/.dumi/theme/builtins/InstallDependencies/yarn.tsx +++ b/.dumi/theme/builtins/InstallDependencies/yarn.tsx @@ -32,6 +32,7 @@ const YarnIcon: React.FC = (props) => { viewBox="0 0 496 512" width="1em" > + yarn icon diff --git a/.dumi/theme/builtins/Previewer/CodeBlockButton.tsx b/.dumi/theme/builtins/Previewer/CodeBlockButton.tsx new file mode 100644 index 0000000000..b17c2e6543 --- /dev/null +++ b/.dumi/theme/builtins/Previewer/CodeBlockButton.tsx @@ -0,0 +1,80 @@ +import React, { Suspense, useEffect, useState } from 'react'; +import { Tooltip } from 'antd'; +import { FormattedMessage } from 'dumi'; + +import { ping } from '../../utils'; + +let pingDeferrer: PromiseLike; + +const codeBlockJs = + 'https://renderoffice.a' + + 'lipay' + + 'objects.com/p' + + '/yuyan/180020010001206410/parseFileData-v1.0.1.js'; + +function useShowCodeBlockButton() { + const [showCodeBlockButton, setShowCodeBlockButton] = useState(false); + + useEffect(() => { + pingDeferrer ??= new Promise((resolve) => { + ping((status) => { + if (status !== 'timeout' && status !== 'error') { + // Async insert `codeBlockJs` into body end + const script = document.createElement('script'); + script.src = codeBlockJs; + script.async = true; + document.body.appendChild(script); + + return resolve(true); + } + return resolve(false); + }); + }); + pingDeferrer.then(setShowCodeBlockButton); + }, []); + + return showCodeBlockButton; +} + +interface CodeBlockButtonProps { + title?: string; + dependencies: Record; + jsx: string; +} + +const CodeBlockButton: React.FC = ({ title, dependencies = {}, jsx }) => { + const showCodeBlockButton = useShowCodeBlockButton(); + + const codeBlockPrefillConfig = { + title: `${title} - antd@${dependencies.antd}`, + js: `${ + /import React(\D*)from 'react';/.test(jsx) ? '' : `import React from 'react';\n` + }import { createRoot } from 'react-dom/client';\n${jsx.replace( + /export default/, + 'const ComponentDemo =', + )}\n\ncreateRoot(mountNode).render();\n`, + css: '', + json: JSON.stringify({ name: 'antd-demo', dependencies }, null, 2), + }; + + return showCodeBlockButton ? ( + }> +
    + codeblock { + openHituCodeBlock(JSON.stringify(codeBlockPrefillConfig)); + }} + /> +
    +
    + ) : null; +}; + +export default (props: CodeBlockButtonProps) => ( + + + +); diff --git a/.dumi/theme/builtins/Previewer/CodePreviewer.tsx b/.dumi/theme/builtins/Previewer/CodePreviewer.tsx index 22e2ef7774..f453f44b13 100644 --- a/.dumi/theme/builtins/Previewer/CodePreviewer.tsx +++ b/.dumi/theme/builtins/Previewer/CodePreviewer.tsx @@ -11,16 +11,15 @@ import LZString from 'lz-string'; import useLocation from '../../../hooks/useLocation'; import BrowserFrame from '../../common/BrowserFrame'; import ClientOnly from '../../common/ClientOnly'; -import CodePenIcon from '../../common/CodePenIcon'; import CodePreview from '../../common/CodePreview'; -import CodeSandboxIcon from '../../common/CodeSandboxIcon'; import EditButton from '../../common/EditButton'; -import ExternalLinkIcon from '../../common/ExternalLinkIcon'; -import RiddleIcon from '../../common/RiddleIcon'; +import CodePenIcon from '../../icons/CodePenIcon'; +import CodeSandboxIcon from '../../icons/CodeSandboxIcon'; +import ExternalLinkIcon from '../../icons/ExternalLinkIcon'; import DemoContext from '../../slots/DemoContext'; import type { SiteContextProps } from '../../slots/SiteContext'; import SiteContext from '../../slots/SiteContext'; -import { ping } from '../../utils'; +import CodeBlockButton from './CodeBlockButton'; import type { AntdPreviewerProps } from './Previewer'; const { ErrorBoundary } = Alert; @@ -39,27 +38,6 @@ const track = ({ type, demo }: { type: string; demo: string }) => { window.gtag('event', 'demo', { event_category: type, event_label: demo }); }; -let pingDeferrer: PromiseLike; - -function useShowRiddleButton() { - const [showRiddleButton, setShowRiddleButton] = useState(false); - - useEffect(() => { - pingDeferrer ??= new Promise((resolve) => { - ping((status) => { - if (status !== 'timeout' && status !== 'error') { - return resolve(true); - } - - return resolve(false); - }); - }); - pingDeferrer.then(setShowRiddleButton); - }, []); - - return showRiddleButton; -} - const useStyle = createStyles(({ token }) => { const { borderRadius } = token; return { @@ -98,7 +76,7 @@ const CodePreviewer: React.FC = (props) => { title, description, originDebug, - jsx, + jsx = '', style, compact, background, @@ -108,7 +86,7 @@ const CodePreviewer: React.FC = (props) => { clientOnly, pkgDependencyList, } = props; - const { showDebug, codeType } = useContext(DemoContext); + const { codeType } = useContext(DemoContext); const { pkg } = useSiteData(); const location = useLocation(); @@ -117,8 +95,7 @@ const CodePreviewer: React.FC = (props) => { const entryName = 'index.tsx'; const entryCode = asset.dependencies[entryName].value; - const showRiddleButton = useShowRiddleButton(); - + const previewDemo = useRef(null); const demoContainer = useRef(null); const { @@ -127,11 +104,10 @@ const CodePreviewer: React.FC = (props) => { setSource: setLiveDemoSource, } = useLiveDemo(asset.id, { iframe: Boolean(iframe), - containerRef: demoContainer, + containerRef: demoContainer as React.RefObject, }); const anchorRef = useRef(null); const codeSandboxIconRef = useRef(null); - const riddleIconRef = useRef(null); const codepenIconRef = useRef(null); const [codeExpand, setCodeExpand] = useState(false); const { theme } = useContext(SiteContext); @@ -278,18 +254,6 @@ const CodePreviewer: React.FC = (props) => { js_pre_processor: 'typescript', }; - const riddlePrefillConfig = { - title: `${localizedTitle} - antd@${dependencies.antd}`, - js: `${ - /import React(\D*)from 'react';/.test(jsx) ? '' : `import React from 'react';\n` - }import { createRoot } from 'react-dom/client';\n${jsx.replace( - /export default/, - 'const ComponentDemo =', - )}\n\ncreateRoot(mountNode).render();\n`, - css: '', - json: JSON.stringify({ name: 'antd-demo', dependencies }, null, 2), - }; - // Reorder source code let parsedSourceCode = suffix === 'tsx' ? entryCode : jsx; let importReactContent = "import React from 'react';"; @@ -308,7 +272,9 @@ ${parsedSourceCode} .trim() .replace(new RegExp(`#${asset.id}\\s*`, 'g'), '') .replace('', '') - .replace(' diff --git a/components/affix/demo/target.tsx b/components/affix/demo/target.tsx index 290ec81a2d..1a06be105d 100644 --- a/components/affix/demo/target.tsx +++ b/components/affix/demo/target.tsx @@ -5,7 +5,9 @@ const containerStyle: React.CSSProperties = { width: '100%', height: 100, overflow: 'auto', - border: '1px solid #40a9ff', + boxShadow: '0 0 0 1px #1677ff', + scrollbarWidth: 'thin', + scrollbarGutter: 'stable', }; const style: React.CSSProperties = { diff --git a/components/affix/index.tsx b/components/affix/index.tsx index 5cc93d742c..42562a3cf1 100644 --- a/components/affix/index.tsx +++ b/components/affix/index.tsx @@ -9,7 +9,7 @@ import { ConfigContext } from '../config-provider'; import useStyle from './style'; import { getFixedBottom, getFixedTop, getTargetRect } from './utils'; -const TRIGGER_EVENTS = [ +const TRIGGER_EVENTS: (keyof WindowEventMap)[] = [ 'resize', 'scroll', 'touchstart', @@ -17,7 +17,7 @@ const TRIGGER_EVENTS = [ 'touchend', 'pageshow', 'load', -] as const; +]; function getDefaultTarget() { return typeof window !== 'undefined' ? window : null; @@ -80,7 +80,7 @@ const Affix = React.forwardRef((props, ref) => { const status = React.useRef(AFFIX_STATUS_NONE); const prevTarget = React.useRef(null); - const prevListener = React.useRef(); + const prevListener = React.useRef(null); const placeholderNodeRef = React.useRef(null); const fixedNodeRef = React.useRef(null); diff --git a/components/affix/style/index.ts b/components/affix/style/index.ts index aaaedb9bb8..0cd9757b34 100644 --- a/components/affix/style/index.ts +++ b/components/affix/style/index.ts @@ -4,6 +4,10 @@ import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/inte import { genStyleHooks } from '../../theme/internal'; export interface ComponentToken { + /** + * @desc 弹出层的 z-index + * @descEN z-index of popup + */ zIndexPopup: number; } diff --git a/components/alert/Alert.tsx b/components/alert/Alert.tsx index a529226c0b..f53c5cd4dd 100644 --- a/components/alert/Alert.tsx +++ b/components/alert/Alert.tsx @@ -7,8 +7,8 @@ import ExclamationCircleFilled from '@ant-design/icons/ExclamationCircleFilled'; import InfoCircleFilled from '@ant-design/icons/InfoCircleFilled'; import classNames from 'classnames'; import CSSMotion from 'rc-motion'; -import { composeRef } from 'rc-util/lib/ref'; import pickAttrs from 'rc-util/lib/pickAttrs'; +import { composeRef } from 'rc-util/lib/ref'; import type { ClosableType } from '../_util/hooks/useClosable'; import { replaceElement } from '../_util/reactNode'; @@ -76,9 +76,14 @@ const IconNode: React.FC = (props) => { const iconType = iconMapFilled[type!] || null; if (icon) { return replaceElement(icon, {icon}, () => ({ - className: classNames(`${prefixCls}-icon`, { - [(icon as ReactElement).props.className]: (icon as ReactElement).props.className, - }), + className: classNames( + `${prefixCls}-icon`, + ( + icon as ReactElement<{ + className?: string; + }> + ).props.className, + ), })) as ReactElement; } return React.createElement(iconType, { className: `${prefixCls}-icon` }); @@ -219,7 +224,6 @@ const Alert = React.forwardRef((props, ref) => { const mergedAriaProps = React.useMemo(() => { const merged = closable ?? alert?.closable; if (typeof merged === 'object') { - // eslint-disable-next-line @typescript-eslint/no-unused-vars const { closeIcon: _, ...ariaProps } = merged; return ariaProps; } diff --git a/components/alert/ErrorBoundary.tsx b/components/alert/ErrorBoundary.tsx index c12595e11e..995f7de8eb 100644 --- a/components/alert/ErrorBoundary.tsx +++ b/components/alert/ErrorBoundary.tsx @@ -31,7 +31,7 @@ class ErrorBoundary extends React.Component +Array [ , +
    , +
    , +
    , -`; - -exports[`renders components/alert/demo/action.tsx extend context correctly 2`] = ` -[ - "Warning: [antd: Button] \`link\` or \`text\` button can't be a \`ghost\` button.", + + , ] `; +exports[`renders components/alert/demo/action.tsx extend context correctly 2`] = `[]`; + exports[`renders components/alert/demo/banner.tsx extend context correctly 1`] = ` -
    +Array [ , +
    , + -
    -
    - -
    -
    - -
    -
    - , +
    , + -
    + , +
    , + , +] `; exports[`renders components/alert/demo/banner.tsx extend context correctly 2`] = `[]`; @@ -484,623 +448,563 @@ exports[`renders components/alert/demo/basic.tsx extend context correctly 1`] = exports[`renders components/alert/demo/basic.tsx extend context correctly 2`] = `[]`; exports[`renders components/alert/demo/closable.tsx extend context correctly 1`] = ` -
    +Array [ -
    - -
    -
    - , +
    , + -
    + +
    , +
    , + , +] `; exports[`renders components/alert/demo/closable.tsx extend context correctly 2`] = `[]`; exports[`renders components/alert/demo/custom-icon.tsx extend context correctly 1`] = ` -
    +Array [ +
    , +
    , , +
    , , +
    , , +
    , , +
    , , +
    , , +
    , , +
    , + , +] `; exports[`renders components/alert/demo/custom-icon.tsx extend context correctly 2`] = `[]`; exports[`renders components/alert/demo/description.tsx extend context correctly 1`] = ` -
    +Array [ +
    , +
    , + , +
    , + , +
    , - + , +] `; exports[`renders components/alert/demo/description.tsx extend context correctly 2`] = `[]`; exports[`renders components/alert/demo/error-boundary.tsx extend context correctly 1`] = ` - -
    - , +
    , , +
    , + , +
    , + -
    -
    - -
    -
    - -
    -
    - +
    , +] `; exports[`renders components/alert/demo/icon.tsx extend context correctly 2`] = `[]`; exports[`renders components/alert/demo/smooth-closed.tsx extend context correctly 1`] = ` -
    +Array [ -
    -

    - click the close button to see the effect -

    -
    -
    -
    -
    + , +

    + click the close button to see the effect +

    , + , +] `; exports[`renders components/alert/demo/smooth-closed.tsx extend context correctly 2`] = `[]`; exports[`renders components/alert/demo/style.tsx extend context correctly 1`] = ` -
    +Array [ +
    , +
    , + , +
    , + , +
    , - + , +] `; exports[`renders components/alert/demo/style.tsx extend context correctly 2`] = `[]`; diff --git a/components/alert/__tests__/__snapshots__/demo.test.ts.snap b/components/alert/__tests__/__snapshots__/demo.test.ts.snap index 45e372512b..1508ecc8aa 100644 --- a/components/alert/__tests__/__snapshots__/demo.test.ts.snap +++ b/components/alert/__tests__/__snapshots__/demo.test.ts.snap @@ -1,102 +1,65 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`renders components/alert/demo/action.tsx correctly 1`] = ` -
    +Array [ , +
    , +
    , +
    , + + , +] `; exports[`renders components/alert/demo/banner.tsx correctly 1`] = ` -
    +Array [ , +
    , + -
    -
    - -
    -
    - -
    -
    - , +
    , + -
    + , +
    , + , +] `; exports[`renders components/alert/demo/basic.tsx correctly 1`] = ` @@ -474,617 +442,557 @@ exports[`renders components/alert/demo/basic.tsx correctly 1`] = ` `; exports[`renders components/alert/demo/closable.tsx correctly 1`] = ` -
    +Array [ -
    - -
    -
    - , +
    , + -
    + +
    , +
    , + , +] `; exports[`renders components/alert/demo/custom-icon.tsx correctly 1`] = ` -
    +Array [ +
    , +
    , , +
    , , +
    , , +
    , , +
    , , +
    , , +
    , , +
    , + , +] `; exports[`renders components/alert/demo/description.tsx correctly 1`] = ` -
    +Array [ +
    , +
    , + , +
    , + , +
    , - + , +] `; exports[`renders components/alert/demo/error-boundary.tsx correctly 1`] = ` - -
    - , +
    , , +
    , + , +
    , + -
    -
    - -
    -
    - -
    -
    - +
    , +] `; exports[`renders components/alert/demo/smooth-closed.tsx correctly 1`] = ` -
    +Array [ -
    -

    - click the close button to see the effect -

    -
    -
    -
    -
    + , +

    + click the close button to see the effect +

    , + , +] `; exports[`renders components/alert/demo/style.tsx correctly 1`] = ` -
    +Array [ +
    , +
    , + , +
    , + , +
    , - + , +] `; diff --git a/components/alert/__tests__/__snapshots__/index.test.tsx.snap b/components/alert/__tests__/__snapshots__/index.test.tsx.snap index 374770f36d..e26d0fb3ad 100644 --- a/components/alert/__tests__/__snapshots__/index.test.tsx.snap +++ b/components/alert/__tests__/__snapshots__/index.test.tsx.snap @@ -38,7 +38,7 @@ exports[`Alert custom action 1`] = ` class="ant-alert-action" > } /> +
    - } closable /> +
    ( } closable /> - + ); export default App; diff --git a/components/alert/demo/banner.tsx b/components/alert/demo/banner.tsx index 552d6ca9ee..cc8bcb6a67 100644 --- a/components/alert/demo/banner.tsx +++ b/components/alert/demo/banner.tsx @@ -1,17 +1,20 @@ import React from 'react'; -import { Alert, Space } from 'antd'; +import { Alert } from 'antd'; const App: React.FC = () => ( - + <> +
    +
    +
    -
    + ); export default App; diff --git a/components/alert/demo/closable.tsx b/components/alert/demo/closable.tsx index 4369716d8d..46b5557340 100644 --- a/components/alert/demo/closable.tsx +++ b/components/alert/demo/closable.tsx @@ -1,19 +1,20 @@ import React from 'react'; import { CloseSquareFilled } from '@ant-design/icons'; -import { Alert, Space } from 'antd'; +import { Alert } from 'antd'; const onClose = (e: React.MouseEvent) => { console.log(e, 'I was closed.'); }; const App: React.FC = () => ( - + <> +
    ( closable onClose={onClose} /> +
    ( }} onClose={onClose} /> -
    + ); export default App; diff --git a/components/alert/demo/component-token.tsx b/components/alert/demo/component-token.tsx index 00f1d7f1c3..2a655b15e6 100644 --- a/components/alert/demo/component-token.tsx +++ b/components/alert/demo/component-token.tsx @@ -18,7 +18,7 @@ const App: React.FC = () => ( diff --git a/components/alert/demo/custom-icon.tsx b/components/alert/demo/custom-icon.tsx index e1767a937e..415fc064fd 100644 --- a/components/alert/demo/custom-icon.tsx +++ b/components/alert/demo/custom-icon.tsx @@ -1,30 +1,37 @@ import React from 'react'; import { SmileOutlined } from '@ant-design/icons'; -import { Alert, Space } from 'antd'; +import { Alert } from 'antd'; const icon = ; const App: React.FC = () => ( - + <> +
    +
    +
    +
    +
    +
    +
    ( type="warning" showIcon /> +
    ( type="error" showIcon /> -
    + ); export default App; diff --git a/components/alert/demo/description.tsx b/components/alert/demo/description.tsx index 0abd7b08b1..4b15cb9c95 100644 --- a/components/alert/demo/description.tsx +++ b/components/alert/demo/description.tsx @@ -1,29 +1,32 @@ import React from 'react'; -import { Alert, Space } from 'antd'; +import { Alert } from 'antd'; const App: React.FC = () => ( - + <> +
    +
    +
    -
    + ); export default App; diff --git a/components/alert/demo/icon.tsx b/components/alert/demo/icon.tsx index bc9baca870..37e19b3e20 100644 --- a/components/alert/demo/icon.tsx +++ b/components/alert/demo/icon.tsx @@ -1,24 +1,30 @@ import React from 'react'; -import { Alert, Space } from 'antd'; +import { Alert } from 'antd'; const App: React.FC = () => ( - + <> +
    +
    +
    +
    +
    +
    ( showIcon closable /> +
    -
    + ); export default App; diff --git a/components/alert/demo/smooth-closed.tsx b/components/alert/demo/smooth-closed.tsx index d9020eeaa6..82f5ff08f3 100644 --- a/components/alert/demo/smooth-closed.tsx +++ b/components/alert/demo/smooth-closed.tsx @@ -1,5 +1,5 @@ import React, { useState } from 'react'; -import { Alert, Space, Switch } from 'antd'; +import { Alert, Switch } from 'antd'; const App: React.FC = () => { const [visible, setVisible] = useState(true); @@ -9,13 +9,13 @@ const App: React.FC = () => { }; return ( - + <> {visible && ( )}

    click the close button to see the effect

    -
    + ); }; diff --git a/components/alert/demo/style.tsx b/components/alert/demo/style.tsx index f89bc3f879..82fcc683c7 100644 --- a/components/alert/demo/style.tsx +++ b/components/alert/demo/style.tsx @@ -1,13 +1,16 @@ import React from 'react'; -import { Alert, Space } from 'antd'; +import { Alert } from 'antd'; const App: React.FC = () => ( - + <> +
    +
    +
    -
    + ); export default App; diff --git a/components/alert/design/behavior-pattern.tsx b/components/alert/design/behavior-pattern.tsx index 631ea06304..98bc6d80b7 100644 --- a/components/alert/design/behavior-pattern.tsx +++ b/components/alert/design/behavior-pattern.tsx @@ -16,12 +16,12 @@ const BehaviorPattern: React.FC = () => ( { id: '707000085', label: '了解提示内容', - link: 'components-alert-index-tab-design-demo-content', + link: 'alert-index-tab-design-demo-content', }, { id: '707000086', label: '了解提示类型', - link: 'components-alert-index-tab-design-demo-type', + link: 'alert-index-tab-design-demo-type', }, ], }, @@ -29,7 +29,7 @@ const BehaviorPattern: React.FC = () => ( id: '200000005', label: '针对提示进行操作', targetType: 'extension', - link: 'components-alert-index-tab-design-demo-action', + link: 'alert-index-tab-design-demo-action', }, ], }} diff --git a/components/alert/index.ts b/components/alert/index.tsx similarity index 100% rename from components/alert/index.ts rename to components/alert/index.tsx diff --git a/components/alert/style/index.ts b/components/alert/style/index.ts index 02bcce8d5b..681feea84e 100644 --- a/components/alert/style/index.ts +++ b/components/alert/style/index.ts @@ -85,7 +85,7 @@ export const genBaseStyle: GenerateStyle = (token: AlertToken): CSSO lineHeight: 0, }, - [`&-description`]: { + '&-description': { display: 'none', fontSize, lineHeight, @@ -204,7 +204,7 @@ export const genActionStyle: GenerateStyle = (token: AlertToken): CS return { [componentCls]: { - [`&-action`]: { + '&-action': { marginInlineStart: marginXS, }, diff --git a/components/anchor/Anchor.tsx b/components/anchor/Anchor.tsx index 03fb706f2a..452836fa36 100644 --- a/components/anchor/Anchor.tsx +++ b/components/anchor/Anchor.tsx @@ -1,12 +1,13 @@ import * as React from 'react'; import classNames from 'classnames'; -import { useEvent } from 'rc-util'; +import useEvent from 'rc-util/lib/hooks/useEvent'; import scrollIntoView from 'scroll-into-view-if-needed'; import getScroll from '../_util/getScroll'; import scrollTo from '../_util/scrollTo'; import { devUseWarning } from '../_util/warning'; import Affix from '../affix'; +import type { AffixProps } from '../affix'; import type { ConfigConsumerProps } from '../config-provider'; import { ConfigContext } from '../config-provider'; import useCSSVarCls from '../config-provider/hooks/useCSSVarCls'; @@ -35,8 +36,7 @@ function getOffsetTop(element: HTMLElement, container: AnchorContainer): number if (rect.width || rect.height) { if (container === window) { - container = element.ownerDocument!.documentElement!; - return rect.top - container.clientTop; + return rect.top - element.ownerDocument!.documentElement!.clientTop; } return rect.top - (container as HTMLElement).getBoundingClientRect().top; } @@ -62,7 +62,7 @@ export interface AnchorProps { children?: React.ReactNode; offsetTop?: number; bounds?: number; - affix?: boolean; + affix?: boolean | Omit; showInkInFixed?: boolean; getContainer?: () => AnchorContainer; /** Return customize highlight anchor */ @@ -256,7 +256,7 @@ const Anchor: React.FC = (props) => { } const container = getCurrentContainer(); - const scrollTop = getScroll(container, true); + const scrollTop = getScroll(container); const eleOffsetTop = getOffsetTop(targetElement, container); let y = scrollTop + eleOffsetTop; y -= targetOffset !== undefined ? targetOffset : offsetTop || 0; @@ -348,10 +348,12 @@ const Anchor: React.FC = (props) => { [activeLink, onClick, handleScrollTo, anchorDirection], ); + const affixProps = affix && typeof affix === 'object' ? affix : undefined; + return wrapCSSVar( {affix ? ( - + {anchorContent} ) : ( diff --git a/components/anchor/__tests__/Anchor.test.tsx b/components/anchor/__tests__/Anchor.test.tsx index 760bf21b67..02e3b0ed45 100644 --- a/components/anchor/__tests__/Anchor.test.tsx +++ b/components/anchor/__tests__/Anchor.test.tsx @@ -67,12 +67,12 @@ describe('Anchor Render', () => { items={[ { key: '1', - href: '#components-anchor-demo-basic', + href: '#anchor-demo-basic', title: 'Item Basic Demo', }, { key: '2', - href: '#components-anchor-demo-static', + href: '#anchor-demo-static', title: 'Static demo', }, { @@ -101,8 +101,8 @@ describe('Anchor Render', () => { const linkTitles = Array.from(container.querySelector('.ant-anchor')?.childNodes!).map((n) => (n as HTMLElement).querySelector('.ant-anchor-link-title'), ); - expect((linkTitles[1] as HTMLAnchorElement).href).toContain('#components-anchor-demo-basic'); - expect((linkTitles[2] as HTMLAnchorElement).href).toContain('#components-anchor-demo-static'); + expect((linkTitles[1] as HTMLAnchorElement).href).toContain('#anchor-demo-basic'); + expect((linkTitles[2] as HTMLAnchorElement).href).toContain('#anchor-demo-static'); expect((linkTitles[3] as HTMLAnchorElement).href).toContain('#api'); expect( ( @@ -127,12 +127,12 @@ describe('Anchor Render', () => { items={[ { key: '1', - href: '#components-anchor-demo-basic', + href: '#anchor-demo-basic', title: 'Item Basic Demo', }, { key: '2', - href: '#components-anchor-demo-static', + href: '#anchor-demo-static', title: 'Static demo', }, { @@ -147,8 +147,8 @@ describe('Anchor Render', () => { const linkTitles = Array.from(container.querySelector('.ant-anchor')?.childNodes!).map((n) => (n as HTMLElement).querySelector('.ant-anchor-link-title'), ); - expect((linkTitles[1] as HTMLAnchorElement).href).toContain('#components-anchor-demo-basic'); - expect((linkTitles[2] as HTMLAnchorElement).href).toContain('#components-anchor-demo-static'); + expect((linkTitles[1] as HTMLAnchorElement).href).toContain('#anchor-demo-basic'); + expect((linkTitles[2] as HTMLAnchorElement).href).toContain('#anchor-demo-static'); expect((linkTitles[3] as HTMLAnchorElement).href).toContain('#api'); expect(asFragment().firstChild).toMatchSnapshot(); }); @@ -159,7 +159,7 @@ describe('Anchor Render', () => { items={[ { key: '1', - href: '#components-anchor-demo-basic', + href: '#anchor-demo-basic', title: 'Item Basic Demo', }, ]} @@ -170,7 +170,7 @@ describe('Anchor Render', () => { expect(container.querySelectorAll('.ant-anchor .ant-anchor-link').length).toBe(1); expect( (container.querySelector('.ant-anchor .ant-anchor-link-title') as HTMLAnchorElement).href, - ).toContain('#components-anchor-demo-basic'); + ).toContain('#anchor-demo-basic'); expect(asFragment().firstChild).toMatchSnapshot(); }); @@ -381,8 +381,6 @@ describe('Anchor Render', () => { }, ]} />, - // https://github.com/testing-library/react-testing-library/releases/tag/v13.0.0 - { legacyRoot: true }, ); expect(onChange).toHaveBeenCalledTimes(1); @@ -556,16 +554,14 @@ describe('Anchor Render', () => { { key: hash2, href: `#${hash2}`, title: hash2 }, ]} />, - // https://github.com/testing-library/react-testing-library/releases/tag/v13.0.0 - { legacyRoot: true }, ); // Should be 2 times: // 1. '' // 2. hash1 (Since `getCurrentAnchor` still return same hash) - expect(onChange).toHaveBeenCalledTimes(2); + const calledTimes = onChange.mock.calls.length; fireEvent.click(container.querySelector(`a[href="#${hash2}"]`)!); - expect(onChange).toHaveBeenCalledTimes(3); + expect(onChange).toHaveBeenCalledTimes(calledTimes + 1); expect(onChange).toHaveBeenLastCalledWith(`#${hash2}`); }); @@ -694,12 +690,12 @@ describe('Anchor Render', () => { items={[ { key: '1', - href: '#components-anchor-demo-basic', + href: '#anchor-demo-basic', title: 'Item Basic Demo', }, { key: '2', - href: '#components-anchor-demo-static', + href: '#anchor-demo-static', title: 'Static demo', }, { @@ -725,12 +721,12 @@ describe('Anchor Render', () => { items={[ { key: '1', - href: '#components-anchor-demo-basic', + href: '#anchor-demo-basic', title: 'Item Basic Demo', }, { key: '2', - href: '#components-anchor-demo-static', + href: '#anchor-demo-static', title: 'Static demo', }, { @@ -759,8 +755,8 @@ describe('Anchor Render', () => { it('nested children via jsx should be filtered out when direction is horizontal', () => { const { container } = render( - - + + @@ -904,12 +900,12 @@ describe('Anchor Render', () => { items={[ { key: '1', - href: '#components-anchor-demo-basic', + href: '#anchor-demo-basic', title: 'Item Basic Demo', }, { key: '2', - href: '#components-anchor-demo-static', + href: '#anchor-demo-static', title: 'Static demo', }, { @@ -935,8 +931,8 @@ describe('Anchor Render', () => { it('deprecated jsx style', () => { render( - - + + , ); expect(errSpy).toHaveBeenCalledWith( @@ -947,8 +943,8 @@ describe('Anchor Render', () => { it('deprecated jsx style for direction#vertical', () => { render( - - + + , ); expect(errSpy).toHaveBeenCalledWith( diff --git a/components/anchor/__tests__/__snapshots__/Anchor.test.tsx.snap b/components/anchor/__tests__/__snapshots__/Anchor.test.tsx.snap index aa6da33ae7..44b7d8b28f 100644 --- a/components/anchor/__tests__/__snapshots__/Anchor.test.tsx.snap +++ b/components/anchor/__tests__/__snapshots__/Anchor.test.tsx.snap @@ -20,7 +20,7 @@ exports[`Anchor Render render items and ignore jsx children 1`] = ` > Item Basic Demo @@ -52,7 +52,7 @@ exports[`Anchor Render renders items correctly 1`] = ` > Item Basic Demo @@ -63,7 +63,7 @@ exports[`Anchor Render renders items correctly 1`] = ` > Static demo @@ -128,7 +128,7 @@ exports[`Anchor Render renders items correctly#horizontal 1`] = ` > Item Basic Demo @@ -139,7 +139,7 @@ exports[`Anchor Render renders items correctly#horizontal 1`] = ` > Static demo diff --git a/components/anchor/__tests__/__snapshots__/demo-extend.test.ts.snap b/components/anchor/__tests__/__snapshots__/demo-extend.test.ts.snap index f51fde5aca..62d0b81ab0 100644 --- a/components/anchor/__tests__/__snapshots__/demo-extend.test.ts.snap +++ b/components/anchor/__tests__/__snapshots__/demo-extend.test.ts.snap @@ -179,7 +179,7 @@ exports[`renders components/anchor/demo/customizeHighlight.tsx extend context co > Basic demo @@ -190,7 +190,7 @@ exports[`renders components/anchor/demo/customizeHighlight.tsx extend context co > Static demo @@ -328,7 +328,7 @@ exports[`renders components/anchor/demo/legacy-anchor.tsx extend context correct > Basic demo @@ -339,7 +339,7 @@ exports[`renders components/anchor/demo/legacy-anchor.tsx extend context correct > Static demo @@ -404,7 +404,7 @@ exports[`renders components/anchor/demo/onChange.tsx extend context correctly 1` > Basic demo @@ -415,7 +415,7 @@ exports[`renders components/anchor/demo/onChange.tsx extend context correctly 1` > Static demo @@ -476,7 +476,7 @@ exports[`renders components/anchor/demo/onClick.tsx extend context correctly 1`] > Basic demo @@ -487,7 +487,7 @@ exports[`renders components/anchor/demo/onClick.tsx extend context correctly 1`] > Static demo @@ -629,7 +629,7 @@ exports[`renders components/anchor/demo/static.tsx extend context correctly 1`] > Basic demo @@ -640,7 +640,7 @@ exports[`renders components/anchor/demo/static.tsx extend context correctly 1`] > Static demo @@ -770,7 +770,7 @@ exports[`renders components/anchor/demo/targetOffset.tsx extend context correctl
    Fixed Top Block diff --git a/components/anchor/__tests__/__snapshots__/demo.test.tsx.snap b/components/anchor/__tests__/__snapshots__/demo.test.tsx.snap index d388bea819..01a8a8f5e6 100644 --- a/components/anchor/__tests__/__snapshots__/demo.test.tsx.snap +++ b/components/anchor/__tests__/__snapshots__/demo.test.tsx.snap @@ -172,7 +172,7 @@ exports[`renders components/anchor/demo/customizeHighlight.tsx correctly 1`] = ` > Basic demo @@ -183,7 +183,7 @@ exports[`renders components/anchor/demo/customizeHighlight.tsx correctly 1`] = ` > Static demo @@ -316,7 +316,7 @@ exports[`renders components/anchor/demo/legacy-anchor.tsx correctly 1`] = ` > Basic demo @@ -327,7 +327,7 @@ exports[`renders components/anchor/demo/legacy-anchor.tsx correctly 1`] = ` > Static demo @@ -386,7 +386,7 @@ exports[`renders components/anchor/demo/onChange.tsx correctly 1`] = ` > Basic demo @@ -397,7 +397,7 @@ exports[`renders components/anchor/demo/onChange.tsx correctly 1`] = ` > Static demo @@ -456,7 +456,7 @@ exports[`renders components/anchor/demo/onClick.tsx correctly 1`] = ` > Basic demo @@ -467,7 +467,7 @@ exports[`renders components/anchor/demo/onClick.tsx correctly 1`] = ` > Static demo @@ -604,7 +604,7 @@ exports[`renders components/anchor/demo/static.tsx correctly 1`] = ` > Basic demo @@ -615,7 +615,7 @@ exports[`renders components/anchor/demo/static.tsx correctly 1`] = ` > Static demo @@ -742,7 +742,7 @@ exports[`renders components/anchor/demo/targetOffset.tsx correctly 1`] = `
    Fixed Top Block diff --git a/components/anchor/__tests__/a11y.test.ts b/components/anchor/__tests__/a11y.test.ts new file mode 100644 index 0000000000..279baa3edd --- /dev/null +++ b/components/anchor/__tests__/a11y.test.ts @@ -0,0 +1,5 @@ +import accessibilityDemoTest from '../../../tests/shared/accessibilityTest'; + +describe('anchor demo a11y', () => { + accessibilityDemoTest('anchor'); +}); diff --git a/components/anchor/demo/customizeHighlight.tsx b/components/anchor/demo/customizeHighlight.tsx index fed1ebb932..dc0f4dd03b 100644 --- a/components/anchor/demo/customizeHighlight.tsx +++ b/components/anchor/demo/customizeHighlight.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Anchor } from 'antd'; -const getCurrentAnchor = () => '#components-anchor-demo-static'; +const getCurrentAnchor = () => '#anchor-demo-static'; const App: React.FC = () => ( ( items={[ { key: '1', - href: '#components-anchor-demo-basic', + href: '#anchor-demo-basic', title: 'Basic demo', }, { key: '2', - href: '#components-anchor-demo-static', + href: '#anchor-demo-static', title: 'Static demo', }, { diff --git a/components/anchor/demo/legacy-anchor.tsx b/components/anchor/demo/legacy-anchor.tsx index a5dabdc510..fffb844a2e 100644 --- a/components/anchor/demo/legacy-anchor.tsx +++ b/components/anchor/demo/legacy-anchor.tsx @@ -5,8 +5,8 @@ const { Link } = Anchor; const App: React.FC = () => ( - - + + diff --git a/components/anchor/demo/onChange.tsx b/components/anchor/demo/onChange.tsx index da2f7b587e..0fb21dcf3e 100644 --- a/components/anchor/demo/onChange.tsx +++ b/components/anchor/demo/onChange.tsx @@ -12,12 +12,12 @@ const App: React.FC = () => ( items={[ { key: '1', - href: '#components-anchor-demo-basic', + href: '#anchor-demo-basic', title: 'Basic demo', }, { key: '2', - href: '#components-anchor-demo-static', + href: '#anchor-demo-static', title: 'Static demo', }, { diff --git a/components/anchor/demo/onClick.tsx b/components/anchor/demo/onClick.tsx index 4f9866572d..73bbcbf9c8 100644 --- a/components/anchor/demo/onClick.tsx +++ b/components/anchor/demo/onClick.tsx @@ -19,12 +19,12 @@ const App: React.FC = () => ( items={[ { key: '1', - href: '#components-anchor-demo-basic', + href: '#anchor-demo-basic', title: 'Basic demo', }, { key: '2', - href: '#components-anchor-demo-static', + href: '#anchor-demo-static', title: 'Static demo', }, { diff --git a/components/anchor/demo/static.tsx b/components/anchor/demo/static.tsx index be2d34c053..2be1d61028 100644 --- a/components/anchor/demo/static.tsx +++ b/components/anchor/demo/static.tsx @@ -7,12 +7,12 @@ const App: React.FC = () => ( items={[ { key: '1', - href: '#components-anchor-demo-basic', + href: '#anchor-demo-basic', title: 'Basic demo', }, { key: '2', - href: '#components-anchor-demo-static', + href: '#anchor-demo-static', title: 'Static demo', }, { diff --git a/components/anchor/demo/targetOffset.tsx b/components/anchor/demo/targetOffset.tsx index 27927783a2..2a4b91a0a1 100644 --- a/components/anchor/demo/targetOffset.tsx +++ b/components/anchor/demo/targetOffset.tsx @@ -1,6 +1,16 @@ import React, { useEffect, useState } from 'react'; import { Anchor, Col, Row } from 'antd'; +const style: React.CSSProperties = { + height: '30vh', + backgroundColor: 'rgba(0, 0, 0, 0.85)', + position: 'fixed', + top: 0, + insetInlineStart: 0, + width: '75%', + color: '#fff', +}; + const App: React.FC = () => { const topRef = React.useRef(null); const [targetOffset, setTargetOffset] = useState(); @@ -30,38 +40,14 @@ const App: React.FC = () => { - -
    +
    Fixed Top Block
    diff --git a/components/anchor/index.en-US.md b/components/anchor/index.en-US.md index 0ecc8347ab..5aaf25f4fb 100644 --- a/components/anchor/index.en-US.md +++ b/components/anchor/index.en-US.md @@ -40,13 +40,13 @@ Common props ref:[Common props](/docs/react/common-props) | Property | Description | Type | Default | Version | | --- | --- | --- | --- | --- | -| affix | Fixed mode of Anchor | boolean | true | | +| affix | Fixed mode of Anchor | boolean \| Omit | true | object: 5.19.0 | | bounds | Bounding distance of anchor area | number | 5 | | | getContainer | Scrolling container | () => HTMLElement | () => window | | | getCurrentAnchor | Customize the anchor highlight | (activeLink: string) => string | - | | | offsetTop | Pixels to offset from top when calculating position of scroll | number | 0 | | | showInkInFixed | Whether show ink-square when `affix={false}` | boolean | false | | -| targetOffset | Anchor scroll offset, default as `offsetTop`, [example](#components-anchor-demo-targetoffset) | number | - | | +| targetOffset | Anchor scroll offset, default as `offsetTop`, [example](#anchor-demo-targetoffset) | number | - | | | onChange | Listening for anchor link change | (currentActiveLink: string) => void | | | | onClick | Set the handler to handle `click` event | (e: MouseEvent, link: object) => void | - | | | items | Data configuration option content, support nesting through children | { key, href, title, target, children }\[] [see](#anchoritem) | - | 5.1.0 | diff --git a/components/anchor/index.ts b/components/anchor/index.tsx similarity index 100% rename from components/anchor/index.ts rename to components/anchor/index.tsx diff --git a/components/anchor/index.zh-CN.md b/components/anchor/index.zh-CN.md index 7c93cd575c..733f3ade86 100644 --- a/components/anchor/index.zh-CN.md +++ b/components/anchor/index.zh-CN.md @@ -41,13 +41,13 @@ group: | 参数 | 说明 | 类型 | 默认值 | 版本 | | --- | --- | --- | --- | --- | -| affix | 固定模式 | boolean | true | | +| affix | 固定模式 | boolean \| Omit | true | object: 5.19.0 | | bounds | 锚点区域边界 | number | 5 | | | getContainer | 指定滚动的容器 | () => HTMLElement | () => window | | | getCurrentAnchor | 自定义高亮的锚点 | (activeLink: string) => string | - | | | offsetTop | 距离窗口顶部达到指定偏移量后触发 | number | | | | showInkInFixed | `affix={false}` 时是否显示小方块 | boolean | false | | -| targetOffset | 锚点滚动偏移量,默认与 offsetTop 相同,[例子](#components-anchor-demo-targetoffset) | number | - | | +| targetOffset | 锚点滚动偏移量,默认与 offsetTop 相同,[例子](#anchor-demo-targetoffset) | number | - | | | onChange | 监听锚点链接改变 | (currentActiveLink: string) => void | - | | | onClick | `click` 事件的 handler | (e: MouseEvent, link: object) => void | - | | | items | 数据化配置选项内容,支持通过 children 嵌套 | { key, href, title, target, children }\[] [具体见](#anchoritem) | - | 5.1.0 | diff --git a/components/anchor/style/index.ts b/components/anchor/style/index.ts index 4e5a66f30f..646c796925 100644 --- a/components/anchor/style/index.ts +++ b/components/anchor/style/index.ts @@ -17,10 +17,30 @@ export interface ComponentToken { linkPaddingInlineStart: number; } +/** + * @desc Anchor 组件的 Token + * @descEN Token for Anchor component + */ interface AnchorToken extends FullToken<'Anchor'> { + /** + * @desc 容器块偏移量 + * @descEN Holder block offset + */ holderOffsetBlock: number; + /** + * @desc 次级锚点块内间距 + * @descEN Secondary anchor block padding + */ anchorPaddingBlockSecondary: number | string; + /** + * @desc 锚点球大小 + * @descEN Anchor ball size + */ anchorBallSize: number | string; + /** + * @desc 锚点标题块 + * @descEN Anchor title block + */ anchorTitleBlock: number | string; } diff --git a/components/app/__tests__/__snapshots__/demo-extend.test.ts.snap b/components/app/__tests__/__snapshots__/demo-extend.test.ts.snap index cecadc8853..5f45b88f80 100644 --- a/components/app/__tests__/__snapshots__/demo-extend.test.ts.snap +++ b/components/app/__tests__/__snapshots__/demo-extend.test.ts.snap @@ -12,7 +12,7 @@ exports[`renders components/app/demo/basic.tsx extend context correctly 1`] = ` class="ant-space-item" > + + + -
    AntDesign @@ -354,7 +375,7 @@ exports[`renders components/auto-complete/demo/certain-category.tsx extend conte class="ant-select-item-option-content" >
    AntDesign UI @@ -391,17 +412,18 @@ exports[`renders components/auto-complete/demo/certain-category.tsx extend conte
    - +
    Solutions more - +
    AntDesign UI FAQ @@ -453,7 +475,7 @@ exports[`renders components/auto-complete/demo/certain-category.tsx extend conte class="ant-select-item-option-content" >
    AntDesign FAQ @@ -490,17 +512,18 @@ exports[`renders components/auto-complete/demo/certain-category.tsx extend conte
    - +
    Articles more - +
    AntDesign design language @@ -568,26 +591,30 @@ exports[`renders components/auto-complete/demo/custom.tsx extend context correct class="ant-select-selector" > -