diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 2e2f2fd3c8..0000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,35 +0,0 @@ -# Use the latest 2.1 version of CircleCI pipeline process engine. -# See: https://circleci.com/docs/2.0/configuration-reference -version: 2.1 - -# Define a job to be invoked later in a workflow. -# See: https://circleci.com/docs/2.0/configuration-reference/#jobs -jobs: - test-argos-ci: - docker: - - image: cimg/node:21.1-browsers - environment: - NODE_OPTIONS: --openssl-legacy-provider - steps: - - checkout - - run: - name: Install node_modules - command: yarn - - run: - name: Build dist file - command: npm run dist:esbuild - - run: - name: Run image screenshot tests - command: npm run test-image - - run: - name: Upload screenshots to Argos CI - command: npm run argos - # The resource_class feature allows configuring CPU and RAM resources for each job. Different resource classes are available for different executors. https://circleci.com/docs/2.0/configuration-reference/#resourceclass - resource_class: large - -# Invoke jobs via workflows -# See: https://circleci.com/docs/2.0/configuration-reference/#workflows -workflows: - test-argos-ci-workflow: - jobs: - - test-argos-ci diff --git a/.codesandbox/ci.json b/.codesandbox/ci.json index 96c2526e4c..16798ee955 100644 --- a/.codesandbox/ci.json +++ b/.codesandbox/ci.json @@ -1,4 +1,5 @@ { + "installCommand": "npm-install", "sandboxes": ["antd-reproduction-template-forked-jyh2k9"], "node": "18" } diff --git a/.dumi/global.css b/.dumi/global.css index 8a14f9a69a..e56892774b 100644 --- a/.dumi/global.css +++ b/.dumi/global.css @@ -1,8 +1,10 @@ .demo-logo { width: 120px; + min-width: 120px; height: 32px; background: rgba(255, 255, 255, 0.2); border-radius: 6px; + margin-inline-end: 24px; } .demo-logo-vertical { diff --git a/.dumi/hooks/useThemeAnimation.ts b/.dumi/hooks/useThemeAnimation.ts index 34b72e7809..9e0f421633 100644 --- a/.dumi/hooks/useThemeAnimation.ts +++ b/.dumi/hooks/useThemeAnimation.ts @@ -68,6 +68,7 @@ const useThemeAnimation = () => { if (!(event && typeof document.startViewTransition === 'function')) { return; } + const time = Date.now(); const x = event.clientX; const y = event.clientY; const endRadius = Math.hypot(Math.max(x, innerWidth - x), Math.max(y, innerHeight - y)); @@ -98,6 +99,7 @@ const useThemeAnimation = () => { root.classList.add(isDark ? 'light' : 'dark'); }) .ready.then(() => { + console.log(`Theme transition finished in ${Date.now() - time}ms`); const clipPath = [ `circle(0px at ${x}px ${y}px)`, `circle(${endRadius}px at ${x}px ${y}px)`, diff --git a/.dumi/pages/index/components/BannerRecommends.tsx b/.dumi/pages/index/components/BannerRecommends.tsx index 7a4dfb5612..961f7576e7 100644 --- a/.dumi/pages/index/components/BannerRecommends.tsx +++ b/.dumi/pages/index/components/BannerRecommends.tsx @@ -1,33 +1,41 @@ import * as React from 'react'; -import { createStyles, css, useTheme } from 'antd-style'; -import classNames from 'classnames'; import type { FC } from 'react'; import { useContext } from 'react'; -import { Typography, Skeleton, Carousel } from 'antd'; -import type { Extra, Icon } from './util'; -import SiteContext from '../../../theme/slots/SiteContext'; -import { getCarouselStyle, useSiteData } from './util'; -import useLocale from '../../../hooks/useLocale'; +import { Badge, Carousel, Skeleton, Typography } from 'antd'; +import { createStyles, useTheme } from 'antd-style'; +import classNames from 'classnames'; -const useStyle = createStyles(({ token }) => { +import useLocale from '../../../hooks/useLocale'; +import SiteContext from '../../../theme/slots/SiteContext'; +import type { Extra, Icon } from './util'; +import { getCarouselStyle, useSiteData } from './util'; + +const useStyle = createStyles(({ token, css, cx }) => { const { carousel } = getCarouselStyle(); + const itemBase = css` + display: flex; + flex: 1 1 0; + flex-direction: column; + align-items: stretch; + text-decoration: none; + background: ${token.colorBgContainer}; + border: ${token.lineWidth}px solid ${token.colorBorderSecondary}; + border-radius: ${token.borderRadiusLG}px; + transition: all ${token.motionDurationSlow}; + padding-block: ${token.paddingMD}px; + padding-inline: ${token.paddingLG}px; + box-sizing: border-box; + `; + return { - itemBase: css` - display: flex; - flex: 1 1 0; - flex-direction: column; - align-items: stretch; - text-decoration: none; - background: ${token.colorBgContainer}; - border: ${token.lineWidth}px solid ${token.colorBorderSecondary}; - border-radius: ${token.borderRadiusLG}px; - transition: all ${token.motionDurationSlow}; - padding-block: ${token.paddingMD}px; - padding-inline: ${token.paddingLG}px; + itemBase, + ribbon: css` + & > .${cx(itemBase)} { + height: 100%; + } `, cardItem: css` - width: 33%; &:hover { box-shadow: ${token.boxShadowCard}; } @@ -45,6 +53,9 @@ const useStyle = createStyles(({ token }) => { column-gap: ${token.paddingMD * 2}px; align-items: stretch; text-align: start; + > * { + width: calc((100% - ${token.marginXXL * 2}px) / 3); + } `, carousel, }; @@ -56,7 +67,7 @@ interface RecommendItemProps { icons: Icon[]; className?: string; } -const RecommendItem = ({ extra, index, icons, className }: RecommendItemProps) => { +const RecommendItem: React.FC = ({ extra, index, icons, className }) => { const token = useTheme(); const { styles } = useStyle(); @@ -65,7 +76,7 @@ const RecommendItem = ({ extra, index, icons, className }: RecommendItemProps) = } const icon = icons.find((i) => i.name === extra.source); - return ( + const card = ( ); + + if (index === 0) { + return ( + + {card} + + ); + } + + return card; }; export const BannerRecommendsFallback: FC = () => { @@ -93,8 +114,8 @@ export const BannerRecommendsFallback: FC = () => { return isMobile ? ( - {list.map((extra, index) => ( -
+ {list.map((_, index) => ( +
))} @@ -102,20 +123,26 @@ export const BannerRecommendsFallback: FC = () => { ) : (
{list.map((_, index) => ( - +
+ +
))}
); }; -export default function BannerRecommends() { +const BannerRecommends: React.FC = () => { const { styles } = useStyle(); const [, lang] = useLocale(); const { isMobile } = React.useContext(SiteContext); const data = useSiteData(); const extras = data?.extras?.[lang]; - const icons = data?.icons; - const first3 = extras.length === 0 ? Array(3).fill(null) : extras.slice(0, 3); + const icons = data?.icons || []; + const first3 = !extras || extras.length === 0 ? Array(3).fill(null) : extras.slice(0, 3); + + if (!data) { + return ; + } return (
@@ -147,4 +174,6 @@ export default function BannerRecommends() { )}
); -} +}; + +export default BannerRecommends; diff --git a/.dumi/pages/index/components/PreviewBanner/ComponentsBlock.tsx b/.dumi/pages/index/components/PreviewBanner/ComponentsBlock.tsx index 42dc50702d..e28b46c549 100644 --- a/.dumi/pages/index/components/PreviewBanner/ComponentsBlock.tsx +++ b/.dumi/pages/index/components/PreviewBanner/ComponentsBlock.tsx @@ -17,9 +17,9 @@ import { Tooltip, } from 'antd'; import { createStyles } from 'antd-style'; -import classNames from 'classnames'; import useLocale from '../../../../hooks/useLocale'; +import Tilt from './Tilt'; const { _InternalPanelDoNotUseOrYouWillBeFired: ModalPanel } = Modal; const { _InternalPanelDoNotUseOrYouWillBeFired: InternalTooltip } = Tooltip; @@ -72,16 +72,14 @@ const locales = { 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; + opacity: 0.8; `, - flex: css` display: flex; flex-wrap: nowrap; @@ -105,25 +103,16 @@ const useStyle = createStyles(({ token, css }) => { }; }); -export interface ComponentsBlockProps { - className?: string; - style?: React.CSSProperties; -} - -const ComponentsBlock: React.FC = (props) => { - const { className, style } = props; - +const ComponentsBlock: React.FC = () => { const [locale] = useLocale(locales); const { styles } = useStyle(); return ( -
+ {locale.text} - - {/* Line */}
@@ -139,57 +128,34 @@ const ComponentsBlock: React.FC = (props) => { {locale.dropdown}
-
- - - {/* Line */}
= (props) => { 26: '26°C', 37: '37°C', 100: { - style: { - color: '#f50', - }, + style: { color: '#f50' }, label: 100°C, }, }} defaultValue={[26, 37]} />
- {/* Line */}
- {/* Line */}
@@ -236,7 +198,6 @@ const ComponentsBlock: React.FC = (props) => { checkedChildren={} unCheckedChildren={} /> - = (props) => { />
-
- - -
+ ); }; diff --git a/.dumi/pages/index/components/PreviewBanner/Tilt.tsx b/.dumi/pages/index/components/PreviewBanner/Tilt.tsx new file mode 100644 index 0000000000..ec1213e03f --- /dev/null +++ b/.dumi/pages/index/components/PreviewBanner/Tilt.tsx @@ -0,0 +1,34 @@ +import React, { useEffect, useRef } from 'react'; +import VanillaTilt from 'vanilla-tilt'; +import type { TiltOptions } from 'vanilla-tilt'; + +interface TiltProps extends React.HTMLAttributes { + options?: TiltOptions; +} + +// https://micku7zu.github.io/vanilla-tilt.js/index.html +const defaultTiltOptions: TiltOptions = { + scale: 1.02, + max: 8, + speed: 1500, + glare: true, + 'max-glare': 0.8, +}; + +const Tilt: React.FC = ({ options, ...props }) => { + const node = useRef(null); + useEffect(() => { + if (node.current) { + VanillaTilt.init(node.current, { + ...defaultTiltOptions, + ...options, + }); + } + return () => { + (node.current as any)?.vanillaTilt.destroy(); + }; + }, []); + return
; +}; + +export default Tilt; diff --git a/.dumi/pages/index/components/PreviewBanner/index.tsx b/.dumi/pages/index/components/PreviewBanner/index.tsx index 45991dfaba..cb26d82c1c 100644 --- a/.dumi/pages/index/components/PreviewBanner/index.tsx +++ b/.dumi/pages/index/components/PreviewBanner/index.tsx @@ -7,7 +7,6 @@ import useLocale from '../../../../hooks/useLocale'; import SiteContext from '../../../../theme/slots/SiteContext'; import * as utils from '../../../../theme/utils'; import { GroupMask } from '../Group'; -import useMouseTransform from './useMouseTransform'; const ComponentsBlock = React.lazy(() => import('./ComponentsBlock')); @@ -28,7 +27,6 @@ const locales = { const useStyle = () => { const { direction } = React.useContext(ConfigProvider.ConfigContext); const isRTL = direction === 'rtl'; - return createStyles(({ token, css, cx }) => { const textShadow = `0 0 3px ${token.colorBgContainer}`; @@ -37,12 +35,14 @@ const useStyle = () => { inset: 0; backdrop-filter: blur(4px); opacity: 1; - transition: opacity 1s ease; + background-color: rgba(255, 255, 255, 0.2); + transition: all 1s ease; + pointer-events: none; `); return { holder: css` - height: 520px; + height: 640px; display: flex; flex-direction: column; align-items: center; @@ -94,6 +94,7 @@ const useStyle = () => { child: css` position: relative; + width: 100%; z-index: 1; `, }; @@ -114,10 +115,8 @@ const PreviewBanner: React.FC = (props) => { const { pathname, search } = useLocation(); const isZhCN = utils.isZhCN(pathname); - const [componentsBlockStyle, mouseEvents] = useMouseTransform(); - return ( - + {/* Image Left Top */} = (props) => {
{/* Mobile not show the component preview */} - {!isMobile && } + {isMobile ? null : ( +
+ +
+ )}
diff --git a/.dumi/pages/index/components/PreviewBanner/useMouseTransform.tsx b/.dumi/pages/index/components/PreviewBanner/useMouseTransform.tsx deleted file mode 100644 index a6985067bb..0000000000 --- a/.dumi/pages/index/components/PreviewBanner/useMouseTransform.tsx +++ /dev/null @@ -1,73 +0,0 @@ -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/RecommendsOld.tsx b/.dumi/pages/index/components/RecommendsOld.tsx deleted file mode 100644 index 5e6c00fa47..0000000000 --- a/.dumi/pages/index/components/RecommendsOld.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import * as React from 'react'; -import { createStyles, css, useTheme } from 'antd-style'; -import { Row, Col, Typography } from 'antd'; -import type { Recommendation } from './util'; - -const useStyle = createStyles(({ token }) => ({ - card: css` - height: 300px; - background-size: 100% 100%; - background-position: center; - position: relative; - overflow: hidden; - - &:before { - position: absolute; - background: linear-gradient( - rgba(0, 0, 0, 0) 0%, - rgba(0, 0, 0, 0.25) 40%, - rgba(0, 0, 0, 0.65) 100% - ); - opacity: 0.3; - transition: all 0.5s; - content: ''; - pointer-events: none; - inset: 0; - } - - &:hover { - &:before { - opacity: 1; - } - - .intro { - transform: translate3d(0, 0, 0); - - h4${token.antCls}-typography { - padding-bottom: 0; - } - } - } - - .intro { - position: absolute; - right: 0; - bottom: 0; - left: 0; - transform: translate3d(0, 100%, 0); - transition: all ${token.motionDurationSlow}; - - ${token.antCls}-typography { - margin: 0; - color: #fff; - font-weight: normal; - text-shadow: 0 0 1px rgba(0, 0, 0, 0.5); - transition: all ${token.motionDurationSlow}; - } - - h4${token.antCls}-typography { - position: absolute; - padding: 0 ${token.paddingMD}px ${token.paddingMD}px; - transform: translate3d(0, -100%, 0); - } - - div${token.antCls}-typography { - padding: ${token.paddingXS}px ${token.paddingMD}px ${token.paddingLG}px; - } - } - `, -})); - -export interface RecommendsProps { - recommendations?: Recommendation[]; -} - -export default function Recommends({ recommendations = [] }: RecommendsProps) { - const token = useTheme(); - const { styles } = useStyle(); - - return ( - - {new Array(3).fill(null).map((_, index) => { - const data = recommendations[index]; - - return ( - - {data ? ( -
-
- {data?.title} - {data.description} -
-
- ) : null} - - ); - })} -
- ); -} diff --git a/.dumi/pages/index/components/Theme/index.tsx b/.dumi/pages/index/components/Theme/index.tsx index e528a1ad39..399b377b34 100644 --- a/.dumi/pages/index/components/Theme/index.tsx +++ b/.dumi/pages/index/components/Theme/index.tsx @@ -403,13 +403,12 @@ export default function Theme() { ...themeToken, colorPrimary: colorPrimaryValue, }, - hashed: true, algorithm: algorithmFn, components: { Layout: isLight ? { - colorBgHeader: 'transparent', - colorBgBody: 'transparent', + headerBg: 'transparent', + bodyBg: 'transparent', } : { // colorBgBody: 'transparent', diff --git a/.dumi/pages/index/components/util.ts b/.dumi/pages/index/components/util.ts index 295ff4bee7..a4cacaf55d 100644 --- a/.dumi/pages/index/components/util.ts +++ b/.dumi/pages/index/components/util.ts @@ -1,5 +1,6 @@ import { css } from 'antd-style'; -import useFetch from '../../../hooks/useFetch'; +import { useEffect, useState } from 'react'; +import fetch from 'cross-fetch'; export interface Author { avatar: string; @@ -80,8 +81,18 @@ export function preLoad(list: string[]) { } } -export function useSiteData(): Partial { - return useFetch('https://render.alipay.com/p/h5data/antd4-config_website-h5data.json'); +export function useSiteData(): Partial | undefined { + const [data, setData] = useState(undefined); + + useEffect(() => { + fetch('https://render.alipay.com/p/h5data/antd4-config_website-h5data.json').then( + async (res) => { + setData(await res.json()); + }, + ); + }, []); + + return data; } export const getCarouselStyle = () => ({ diff --git a/.dumi/pages/index/index.tsx b/.dumi/pages/index/index.tsx index 775df42f83..a528f4347e 100644 --- a/.dumi/pages/index/index.tsx +++ b/.dumi/pages/index/index.tsx @@ -4,7 +4,7 @@ import { createStyles, css } from 'antd-style'; import useDark from '../../hooks/useDark'; import useLocale from '../../hooks/useLocale'; -// import BannerRecommends, { BannerRecommendsFallback } from './components/BannerRecommends'; +import BannerRecommends from './components/BannerRecommends'; import PreviewBanner from './components/PreviewBanner'; import Group from './components/Group'; @@ -46,10 +46,7 @@ const Homepage: React.FC = () => { return (
- {/* 文档很久没更新了,先藏起来 */} - {/* }> - - */} +
diff --git a/.dumi/theme/builtins/ComponentTokenTable/index.tsx b/.dumi/theme/builtins/ComponentTokenTable/index.tsx index 7d64eb2d5a..45134cdca3 100644 --- a/.dumi/theme/builtins/ComponentTokenTable/index.tsx +++ b/.dumi/theme/builtins/ComponentTokenTable/index.tsx @@ -1,13 +1,26 @@ -import { RightOutlined, LinkOutlined, QuestionCircleOutlined } from '@ant-design/icons'; +import React, { useMemo, useState } from 'react'; +import { LinkOutlined, QuestionCircleOutlined, RightOutlined } from '@ant-design/icons'; +import { ConfigProvider, Popover, Table, Typography } from 'antd'; 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, Popover, Typography } from 'antd'; + import useLocale from '../../../hooks/useLocale'; import { useColumns } from '../TokenTable'; +const compare = (token1: string, token2: string) => { + const hasColor1 = token1.toLowerCase().includes('color'); + const hasColor2 = token2.toLowerCase().includes('color'); + if (hasColor1 && !hasColor2) { + return -1; + } + if (!hasColor1 && hasColor2) { + return 1; + } + return token1 < token2 ? -1 : 1; +}; + const defaultToken = getDesignToken(); const locales = { @@ -18,6 +31,8 @@ const locales = { value: '默认值', componentToken: '组件 Token', globalToken: '全局 Token', + componentComment: '这里是你的组件 token', + globalComment: '这里是你的全局 token', help: '如何定制?', customizeTokenLink: '/docs/react/customize-theme-cn#修改主题变量', customizeComponentTokenLink: '/docs/react/customize-theme-cn#修改组件变量', @@ -29,6 +44,8 @@ const locales = { value: 'Default Value', componentToken: 'Component Token', globalToken: 'Global Token', + componentComment: 'here is your component tokens', + globalComment: 'here is your global tokens', help: 'How to use?', customizeTokenLink: '/docs/react/customize-theme#customize-design-token', customizeComponentTokenLink: 'docs/react/customize-theme#customize-component-token', @@ -46,13 +63,13 @@ const useStyle = createStyles(() => ({ `, arrowIcon: css` font-size: 16px; - margin-right: 8px; + margin-inline-end: 8px; & svg { transition: all 0.3s; } `, help: css` - margin-left: 8px; + margin-inline-start: 8px; font-size: 12px; font-weight: normal; color: #999; @@ -69,16 +86,14 @@ interface SubTokenTableProps { helpLink: string; tokens: string[]; component?: string; + comment?: { + componentComment?: string; + globalComment?: string; + }; } -const SubTokenTable: React.FC = ({ - defaultOpen, - tokens, - title, - helpText, - helpLink, - component, -}) => { +const SubTokenTable: React.FC = (props) => { + const { defaultOpen, tokens, title, helpText, helpLink, component, comment } = props; const [, lang] = useLocale(locales); const token = useTheme(); const columns = useColumns(); @@ -92,24 +107,7 @@ const SubTokenTable: React.FC = ({ } const data = tokens - .sort( - component - ? undefined - : (token1, token2) => { - const hasColor1 = token1.toLowerCase().includes('color'); - const hasColor2 = token2.toLowerCase().includes('color'); - - if (hasColor1 && !hasColor2) { - return -1; - } - - if (!hasColor1 && hasColor2) { - return 1; - } - - return token1 < token2 ? -1 : 1; - }, - ) + .sort(component ? undefined : compare) .map((name) => { const meta = component ? tokenMeta.components[component].find((item) => item.token === name) @@ -133,7 +131,7 @@ const SubTokenTable: React.FC = ({ theme={{ components: { ${component}: { - /* here is your component tokens */ + /* ${comment?.componentComment} */ }, }, }} @@ -143,7 +141,7 @@ const SubTokenTable: React.FC = ({ : ` @@ -161,16 +159,17 @@ const SubTokenTable: React.FC = ({ popupStyle={{ width: 400 }} content={ + {/* {code} */}
{code}
- + {helpText}
} > - + {helpText} @@ -217,12 +216,16 @@ const ComponentTokenTable: React.FC = ({ component }) <> {tokenMeta.components[component] && ( item.token)} component={component} - defaultOpen + comment={{ + componentComment: locale.componentComment, + globalComment: locale.globalComment, + }} /> )} = ({ component }) helpText={locale.help} helpLink={locale.customizeComponentTokenLink} tokens={mergedGlobalTokens} + comment={{ + componentComment: locale.componentComment, + globalComment: locale.globalComment, + }} /> ); diff --git a/.dumi/theme/builtins/Container/index.tsx b/.dumi/theme/builtins/Container/index.tsx new file mode 100644 index 0000000000..0d299bf903 --- /dev/null +++ b/.dumi/theme/builtins/Container/index.tsx @@ -0,0 +1,39 @@ +/** + * copied: https://github.com/arvinxx/dumi-theme-antd-style/tree/master/src/builtins/Container + */ +import * as React from 'react'; +import { Alert } from 'antd'; +import { type FC, type ReactNode } from 'react'; +import useStyles from './style'; + +const Container: FC<{ + type: 'info' | 'warning' | 'success' | 'error'; + title?: string; + children: ReactNode; +}> = ({ type, title, children }) => { + const { styles, cx } = useStyles(); + + return ( +
+ + {children} +
+ } + className={styles.alert} + /> +
+ ); +}; + +export default Container; diff --git a/.dumi/theme/builtins/Container/style.ts b/.dumi/theme/builtins/Container/style.ts new file mode 100644 index 0000000000..eea3d77bd0 --- /dev/null +++ b/.dumi/theme/builtins/Container/style.ts @@ -0,0 +1,22 @@ +import { createStyles } from 'antd-style'; + +const useStyles = createStyles(({ prefixCls, css }) => ({ + container: css` + margin: 8px 0; + `, + + alert: css` + .${prefixCls}-alert-message { + font-weight: bold; + } + `, + + /* 使用 `&&` 加一点点权重 */ + desc: css` + && p { + margin: 0; + } + `, +})); + +export default useStyles; diff --git a/.dumi/theme/builtins/DemoWrapper/index.tsx b/.dumi/theme/builtins/DemoWrapper/index.tsx index 6cceeb3c51..5ce92c4570 100644 --- a/.dumi/theme/builtins/DemoWrapper/index.tsx +++ b/.dumi/theme/builtins/DemoWrapper/index.tsx @@ -1,15 +1,36 @@ import React, { useContext } from 'react'; import { DumiDemoGrid, FormattedMessage } from 'dumi'; -import { BugFilled, BugOutlined, CodeFilled, CodeOutlined } from '@ant-design/icons'; +import { + BugFilled, + BugOutlined, + CodeFilled, + CodeOutlined, + ExperimentFilled, + ExperimentOutlined, +} from '@ant-design/icons'; import classNames from 'classnames'; -import { Tooltip } from 'antd'; +import { ConfigProvider, Tooltip } from 'antd'; import DemoContext from '../../slots/DemoContext'; import useLayoutState from '../../../hooks/useLayoutState'; +import useLocale from '../../../hooks/useLocale'; + +const locales = { + cn: { + enableCssVar: '启用 CSS 变量', + disableCssVar: '禁用 CSS 变量', + }, + en: { + enableCssVar: 'Enable CSS Var', + disableCssVar: 'Disable CSS Var', + }, +}; const DemoWrapper: typeof DumiDemoGrid = ({ items }) => { const { showDebug, setShowDebug } = useContext(DemoContext); + const [locale] = useLocale(locales); const [expandAll, setExpandAll] = useLayoutState(false); + const [enableCssVar, setEnableCssVar] = useLayoutState(true); const expandTriggerClass = classNames('code-box-expand-trigger', { 'code-box-expand-trigger-active': expandAll, @@ -23,29 +44,36 @@ const DemoWrapper: typeof DumiDemoGrid = ({ items }) => { setExpandAll(!expandAll); }; + const handleCssVarToggle = () => { + setEnableCssVar((v) => !v); + }; + const demos = React.useMemo( () => - items.reduce((acc, item) => { - const { previewerProps } = item; - const { debug } = previewerProps; + items.reduce( + (acc, item) => { + const { previewerProps } = item; + const { debug } = previewerProps; - if (debug && !showDebug) return acc; + 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), + 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, + ), [expandAll, showDebug], ); @@ -74,8 +102,17 @@ const DemoWrapper: typeof DumiDemoGrid = ({ items }) => { )} + + {enableCssVar ? ( + + ) : ( + + )} + - + + +
); }; diff --git a/.dumi/theme/builtins/InstallDependencies/index.tsx b/.dumi/theme/builtins/InstallDependencies/index.tsx index fd61fa091b..777241401f 100644 --- a/.dumi/theme/builtins/InstallDependencies/index.tsx +++ b/.dumi/theme/builtins/InstallDependencies/index.tsx @@ -1,7 +1,8 @@ -import SourceCode from 'dumi/theme-default/builtins/SourceCode'; import React from 'react'; -import type { TabsProps } from 'antd'; -import { Tabs } from 'antd'; +import { ConfigProvider, Tabs } from 'antd'; +import SourceCode from 'dumi/theme-default/builtins/SourceCode'; +import type { Tab } from 'rc-tabs/lib/interface'; + import NpmLogo from './npm'; import PnpmLogo from './pnpm'; import YarnLogo from './yarn'; @@ -12,51 +13,34 @@ interface InstallProps { pnpm?: string; } -const npmLabel = ( - - - npm - -); - -const pnpmLabel = ( - - - pnpm - -); - -const yarnLabel = ( - - - yarn - -); - const InstallDependencies: React.FC = (props) => { const { npm, yarn, pnpm } = props; - const items = React.useMemo( - () => - [ - { - key: 'npm', - children: npm ? {npm} : null, - label: npmLabel, - }, - { - key: 'yarn', - children: yarn ? {yarn} : null, - label: yarnLabel, - }, - { - key: 'pnpm', - children: pnpm ? {pnpm} : null, - label: pnpmLabel, - }, - ].filter((item) => item.children), - [npm, yarn, pnpm], + const items: Tab[] = [ + { + key: 'npm', + label: 'npm', + children: npm ? {npm} : null, + icon: , + }, + { + key: 'yarn', + label: 'yarn', + children: yarn ? {yarn} : null, + icon: , + }, + { + key: 'pnpm', + label: 'pnpm', + children: pnpm ? {pnpm} : null, + icon: , + }, + ].filter((item) => item.children); + + return ( + + + ); - return ; }; export default InstallDependencies; diff --git a/.dumi/theme/builtins/InstallDependencies/npm.tsx b/.dumi/theme/builtins/InstallDependencies/npm.tsx index ffd6755688..63937b0322 100644 --- a/.dumi/theme/builtins/InstallDependencies/npm.tsx +++ b/.dumi/theme/builtins/InstallDependencies/npm.tsx @@ -1,26 +1,39 @@ import React from 'react'; +import { createStyles, css } from 'antd-style'; +import classNames from 'classnames'; interface IconProps { className?: string; style?: React.CSSProperties; } +const useStyle = createStyles(() => ({ + iconWrap: css` + display: inline-flex; + align-items: center; + line-height: 0; + text-align: center; + vertical-align: -0.125em; + `, +})); + const NpmIcon: React.FC = (props) => { const { className, style } = props; + const { styles } = useStyle(); return ( - - - + + + + + ); }; diff --git a/.dumi/theme/builtins/InstallDependencies/pnpm.tsx b/.dumi/theme/builtins/InstallDependencies/pnpm.tsx index 1be5a1ce3a..67cb132e2e 100644 --- a/.dumi/theme/builtins/InstallDependencies/pnpm.tsx +++ b/.dumi/theme/builtins/InstallDependencies/pnpm.tsx @@ -1,28 +1,41 @@ import React from 'react'; +import { createStyles, css } from 'antd-style'; +import classNames from 'classnames'; interface IconProps { className?: string; style?: React.CSSProperties; } +const useStyle = createStyles(() => ({ + iconWrap: css` + display: inline-flex; + align-items: center; + line-height: 0; + text-align: center; + vertical-align: -0.125em; + `, +})); + const PnpmIcon: React.FC = (props) => { const { className, style } = props; + const { styles } = useStyle(); return ( - + + + ); }; diff --git a/.dumi/theme/builtins/InstallDependencies/yarn.tsx b/.dumi/theme/builtins/InstallDependencies/yarn.tsx index c79ac4eee7..7f73b97efd 100644 --- a/.dumi/theme/builtins/InstallDependencies/yarn.tsx +++ b/.dumi/theme/builtins/InstallDependencies/yarn.tsx @@ -1,27 +1,40 @@ import React from 'react'; +import { createStyles, css } from 'antd-style'; +import classNames from 'classnames'; interface IconProps { className?: string; style?: React.CSSProperties; } +const useStyle = createStyles(() => ({ + iconWrap: css` + display: inline-flex; + align-items: center; + line-height: 0; + text-align: center; + vertical-align: -0.125em; + `, +})); + const YarnIcon: React.FC = (props) => { const { className, style } = props; + const { styles } = useStyle(); return ( - + + + ); }; diff --git a/.dumi/theme/builtins/Previewer/CodePreviewer.tsx b/.dumi/theme/builtins/Previewer/CodePreviewer.tsx index e5516170cf..b9c0ec0896 100644 --- a/.dumi/theme/builtins/Previewer/CodePreviewer.tsx +++ b/.dumi/theme/builtins/Previewer/CodePreviewer.tsx @@ -255,7 +255,7 @@ const CodePreviewer: React.FC = (props) => { 'react@18/umd/react.development.js', 'react-dom@18/umd/react-dom.development.js', 'dayjs@1/dayjs.min.js', - `antd@${pkg.version}/dist/antd-with-locales.js`, + `antd@${pkg.version}/dist/antd-with-locales.min.js`, `@ant-design/icons/dist/index.umd.js`, 'react-router-dom/dist/umd/react-router-dom.production.min.js', 'react-router/dist/umd/react-router.production.min.js', diff --git a/.dumi/theme/builtins/Previewer/index.tsx b/.dumi/theme/builtins/Previewer/index.tsx index e36c556112..83a5b56a07 100644 --- a/.dumi/theme/builtins/Previewer/index.tsx +++ b/.dumi/theme/builtins/Previewer/index.tsx @@ -10,8 +10,9 @@ const Previewer = React.lazy(() => import('./Previewer')); const useStyle = createStyles(({ css }) => ({ skeletonWrapper: css` width: 100% !important; - height: 500px; + height: 250px; margin-bottom: 16px; + border-radius: 8px; `, })); diff --git a/.dumi/theme/builtins/ResourceArticles/index.tsx b/.dumi/theme/builtins/ResourceArticles/index.tsx index b6fbf635e9..d6bf4927f4 100644 --- a/.dumi/theme/builtins/ResourceArticles/index.tsx +++ b/.dumi/theme/builtins/ResourceArticles/index.tsx @@ -1,11 +1,10 @@ /* eslint-disable react/no-array-index-key */ import * as React from 'react'; -import { Suspense } from 'react'; import dayjs from 'dayjs'; import { FormattedMessage } from 'dumi'; import { createStyles } from 'antd-style'; import { Avatar, Divider, Empty, Skeleton, Tabs } from 'antd'; -import type { Article, Authors } from '../../../pages/index/components/util'; +import type { Article, Authors, SiteData } from '../../../pages/index/components/util'; import { useSiteData } from '../../../pages/index/components/util'; import useLocale from '../../../hooks/useLocale'; @@ -97,10 +96,11 @@ const ArticleList: React.FC = ({ name, data = [], authors = [] ); }; -const Articles: React.FC = () => { +const Articles: React.FC<{ data: Partial }> = ({ data }) => { const [, lang] = useLocale(); const isZhCN = lang === 'cn'; - const { articles = { cn: [], en: [] }, authors = [] } = useSiteData(); + + const { articles = { cn: [], en: [] }, authors = [] } = data; // ========================== Data ========================== const mergedData = React.useMemo(() => { @@ -149,11 +149,13 @@ const Articles: React.FC = () => { export default () => { const { styles } = useStyle(); + const data = useSiteData(); + + const articles = data ? : ; + return (
- }> - - + {articles}
); }; diff --git a/.dumi/theme/common/Color/ColorPaletteToolDark.tsx b/.dumi/theme/common/Color/ColorPaletteToolDark.tsx index 59400cfae1..c7f3da669f 100644 --- a/.dumi/theme/common/Color/ColorPaletteToolDark.tsx +++ b/.dumi/theme/common/Color/ColorPaletteToolDark.tsx @@ -44,7 +44,7 @@ const ColorPaletteTool: React.FC = () => { text += locale.saturation((s * 100).toFixed(2)); } if (b * 100 < primaryMinBrightness) { - text += locale.brightness((s * 100).toFixed(2)); + text += locale.brightness((b * 100).toFixed(2)); } } return ( diff --git a/.dumi/theme/common/Loading.tsx b/.dumi/theme/common/Loading.tsx index 912bd7cb37..cf1ff79613 100644 --- a/.dumi/theme/common/Loading.tsx +++ b/.dumi/theme/common/Loading.tsx @@ -11,10 +11,16 @@ const Loading: React.FC = () => { pathname.startsWith('/changelog') ) { return ( - - +
+ loading - + +
); } diff --git a/.dumi/theme/common/styles/Demo.tsx b/.dumi/theme/common/styles/Demo.tsx index c988dc2999..9476e49a05 100644 --- a/.dumi/theme/common/styles/Demo.tsx +++ b/.dumi/theme/common/styles/Demo.tsx @@ -26,7 +26,7 @@ const GlobalDemoStyles: React.FC = () => { margin: 0 0 16px; background-color: ${token.colorBgContainer}; border: 1px solid ${token.colorSplit}; - border-radius: ${token.borderRadius}px; + border-radius: ${token.borderRadiusLG}px; transition: all 0.2s; .code-box-title { @@ -39,7 +39,7 @@ const GlobalDemoStyles: React.FC = () => { .code-box-demo { background-color: ${token.colorBgContainer}; - border-radius: ${token.borderRadius}px ${token.borderRadius}px 0 0; + border-radius: ${token.borderRadiusLG}px ${token.borderRadiusLG}px 0 0; > .demo { overflow: auto; } @@ -85,10 +85,6 @@ const GlobalDemoStyles: React.FC = () => { transition: background-color 0.4s; margin-inline-start: 16px; - ${antCls}-row-rtl & { - border-radius: ${token.borderRadius}px 0 0 ${token.borderRadius}px; - } - a, a:hover { color: ${token.colorText}; diff --git a/.dumi/theme/common/styles/Markdown.tsx b/.dumi/theme/common/styles/Markdown.tsx index 0eef2359a9..56246e6160 100644 --- a/.dumi/theme/common/styles/Markdown.tsx +++ b/.dumi/theme/common/styles/Markdown.tsx @@ -199,28 +199,6 @@ const GlobalStyle: React.FC = () => { font-size: 30px; } } - .antd-site-snippet { - .ant-tabs-tab { - .snippet-label { - display: flex; - align-items: center; - justify-content: center; - svg { - margin-inline-end: 8px; - } - } - } - .dumi-default-source-code { - margin: 0 auto; - background-color: ${token.siteMarkdownCodeBg}; - border-radius: ${token.borderRadius}px; - > pre.prism-code { - padding: 12px 20px; - font-size: 13px; - line-height: 2; - } - } - } .markdown table td > a:not(:last-child) { margin-right: 0 !important; diff --git a/.dumi/theme/layouts/GlobalLayout.tsx b/.dumi/theme/layouts/GlobalLayout.tsx index 9a93813a2c..34f42003a5 100644 --- a/.dumi/theme/layouts/GlobalLayout.tsx +++ b/.dumi/theme/layouts/GlobalLayout.tsx @@ -4,7 +4,7 @@ import { createCache, extractStyle, legacyNotSelectorLinter, - logicalPropertiesLinter, + NaNLinter, parentSelectorLinter, StyleProvider, } from '@ant-design/cssinjs'; @@ -45,7 +45,7 @@ const getAlgorithm = (themes: ThemeName[] = []) => } return null; }) - .filter((item) => item) as typeof antdTheme.darkAlgorithm[]; + .filter((item) => item) as (typeof antdTheme.darkAlgorithm)[]; const GlobalLayout: React.FC = () => { const outlet = useOutlet(); @@ -168,7 +168,7 @@ const GlobalLayout: React.FC = () => { { token: { motion: !theme.includes('motion-off'), }, + cssVar: true, }} > {content} diff --git a/.dumi/theme/locales/en-US.json b/.dumi/theme/locales/en-US.json index 6ca8a49d35..41dd070306 100644 --- a/.dumi/theme/locales/en-US.json +++ b/.dumi/theme/locales/en-US.json @@ -111,6 +111,8 @@ "app.footer.seeconf": "Experience Tech Conference", "app.footer.xtech": "Ant Financial Experience Tech", "app.footer.xtech.slogan": "Experience The Beauty", + "app.footer.galacean": "Galacean", + "app.footer.galacean.slogan": "Interactive Graphics Solution", "app.docs.color.pick-primary": "Pick your primary color", "app.docs.color.pick-background": "Pick your background color", "app.docs.components.icon.search.placeholder": "Search icons here, click icon to copy code", diff --git a/.dumi/theme/locales/zh-CN.json b/.dumi/theme/locales/zh-CN.json index 2a37d63e3e..1cefada772 100644 --- a/.dumi/theme/locales/zh-CN.json +++ b/.dumi/theme/locales/zh-CN.json @@ -110,6 +110,8 @@ "app.footer.seeconf": "蚂蚁体验科技大会", "app.footer.xtech": "蚂蚁体验科技", "app.footer.xtech.slogan": "让用户体验美好", + "app.footer.galacean": "Galacean", + "app.footer.galacean.slogan": "互动图形解决方案", "app.docs.color.pick-primary": "选择你的主色", "app.docs.color.pick-background": "选择你的背景色", "app.docs.components.icon.search.placeholder": "在此搜索图标,点击图标可复制代码", diff --git a/.dumi/theme/plugin.ts b/.dumi/theme/plugin.ts index 90a1490d0a..b6744cc65d 100644 --- a/.dumi/theme/plugin.ts +++ b/.dumi/theme/plugin.ts @@ -166,7 +166,7 @@ const RoutesPlugin = (api: IApi) => { }); // Insert antd style to head - const matchRegex = / + + + + {{reportContent}} + + + \ No newline at end of file diff --git a/scripts/visual-regression/upload.js b/scripts/visual-regression/upload.js new file mode 100644 index 0000000000..4b035efec6 --- /dev/null +++ b/scripts/visual-regression/upload.js @@ -0,0 +1,124 @@ +/* eslint-disable no-restricted-syntax, no-console */ +// Attention: use all node builtin modules except `ali-oss` +// Must keep our ak/sk safe + +// eslint-disable-next-line import/no-extraneous-dependencies +const OSS = require('ali-oss'); +const path = require('path'); +const fs = require('fs'); +const assert = require('assert'); + +// node scripts/visual-regression/upload.js ./visualRegressionReport.tar.gz --ref=pr-id +// node scripts/visual-regression/upload.js ./imageSnapshots.tar.gz --ref=master-commitId + +const args = process.argv.slice(2); +if (args.length < 2) { + console.error('Usage: node scripts/visual-regression/upload.js --ref='); + process.exit(1); +} + +const ALI_OSS_BUCKET = 'antd-visual-diff'; + +/** + * Extract the tar file path and ref value from the cli arguments + * @param {string[]} cliArgs + */ +function parseArgs(cliArgs) { + const filepath = cliArgs[0]; + let refValue = ''; + + for (let i = 1; i < cliArgs.length; i++) { + if (cliArgs[i].startsWith('--ref=')) { + refValue = cliArgs[i].substring(6); + break; + } + } + + assert(filepath, 'filepath is required'); + assert(refValue, 'refValue is required'); + + return [filepath, refValue]; +} + +async function walkDir(dirPath) { + const fileList = []; + + const files = await fs.promises.readdir(dirPath); + + for (const file of files) { + const filePath = path.join(dirPath, file); + const fileStat = fs.statSync(filePath); + + if (fileStat.isDirectory()) { + // Recursively call this func for subdirs + // eslint-disable-next-line no-await-in-loop + fileList.push(...(await walkDir(filePath))); + } else { + fileList.push(filePath); + } + } + + return fileList; +} + +/** + * + * @param {import('ali-oss')} client + * @param {*} filePath + * @param {*} refValue + */ +async function uploadFile(client, filePath, refValue) { + const headers = { + // https://help.aliyun.com/zh/oss/user-guide/object-acl + 'x-oss-object-acl': 'public-read', + // https://help.aliyun.com/zh/oss/developer-reference/prevent-objects-from-being-overwritten-by-objects-that-have-the-same-names-3 + 'x-oss-forbid-overwrite': 'false', + }; + + console.log('Uploading file: %s', filePath); + try { + const targetFilePath = path.relative(process.cwd(), filePath); + const r1 = await client.put(`${refValue}/${targetFilePath}`, filePath, { headers }); + console.log('Uploading file successfully: %s', r1.name); + } catch (err) { + console.error('Uploading file failed: %s', err); + process.exit(1); + } +} + +async function boot() { + const [filepath, refValue] = parseArgs(args); + + const fileOrFolderName = filepath; + // check if exists + const filePath = path.resolve(process.cwd(), fileOrFolderName); + + if (!fs.existsSync(filePath)) { + console.error('File not exists: %s', filePath); + process.exit(1); + } + + const client = new OSS({ + endpoint: 'oss-cn-shanghai.aliyuncs.com', + accessKeyId: process.env.ALI_OSS_AK_ID, + accessKeySecret: process.env.ALI_OSS_AK_SECRET, + bucket: ALI_OSS_BUCKET, + }); + + // if is a file then upload it directly + const stat = fs.statSync(filePath); + if (stat.isFile()) { + await uploadFile(client, filePath, refValue); + return; + } + + if (stat.isDirectory()) { + const fileList = await walkDir(filePath); + for (const file of fileList) { + // eslint-disable-next-line no-await-in-loop + await uploadFile(client, file, refValue); + } + } +} + +boot(); diff --git a/tests/index.test.ts b/tests/index.test.ts index 5261565775..bbc286a7e8 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -1,13 +1,23 @@ +/* eslint-disable global-require */ import pkg from '../package.json'; const testDist = process.env.LIB_DIR === 'dist'; +const testDistMin = process.env.LIB_DIR === 'dist-min'; describe('antd dist files', () => { // https://github.com/ant-design/ant-design/issues/1638 // https://github.com/ant-design/ant-design/issues/1968 it('exports modules correctly', () => { - // eslint-disable-next-line global-require,import/no-unresolved - const antd = testDist ? require('../dist/antd') : require('../components'); + let antd; + if (testDist) { + // eslint-disable-next-line import/no-unresolved + antd = require('../dist/antd'); + } else if (testDistMin) { + // eslint-disable-next-line import/no-unresolved + antd = require('../dist/antd.min'); + } else { + antd = require('../components'); + } expect(Object.keys(antd)).toMatchSnapshot(); }); diff --git a/tests/setup.js b/tests/setup.ts similarity index 51% rename from tests/setup.js rename to tests/setup.ts index e5da82ca53..1977c6b1a8 100644 --- a/tests/setup.js +++ b/tests/setup.ts @@ -1,5 +1,9 @@ -/* eslint-disable no-console */ -const util = require('util'); +/* eslint-disable no-console, import/prefer-default-export */ +import util from 'util'; +import type { DOMWindow } from 'jsdom'; + +// import { fillWindowEnv } from './utils'; + const React = require('react'); // eslint-disable-next-line no-console @@ -20,17 +24,21 @@ console.error = (...args) => { } }; -/* eslint-disable global-require */ -if (typeof window !== 'undefined') { - global.window.resizeTo = (width, height) => { - global.window.innerWidth = width || global.window.innerWidth; - global.window.innerHeight = height || global.window.innerHeight; - global.window.dispatchEvent(new Event('resize')); +type Writeable = { -readonly [P in keyof T]: T[P] }; + +// This function can not move to external file since jest setup not support +export function fillWindowEnv(window: Window | DOMWindow) { + const win = window as Writeable & typeof globalThis; + + win.resizeTo = (width, height) => { + win.innerWidth = width || win.innerWidth; + win.innerHeight = height || win.innerHeight; + win.dispatchEvent(new Event('resize')); }; - global.window.scrollTo = () => {}; + win.scrollTo = () => {}; // ref: https://github.com/ant-design/ant-design/issues/18774 - if (!window.matchMedia) { - Object.defineProperty(global.window, 'matchMedia', { + if (!win.matchMedia) { + Object.defineProperty(win, 'matchMedia', { writable: true, configurable: true, value: jest.fn((query) => ({ @@ -44,11 +52,19 @@ if (typeof window !== 'undefined') { // Fix css-animation or rc-motion deps on these // https://github.com/react-component/motion/blob/9c04ef1a210a4f3246c9becba6e33ea945e00669/src/util/motion.ts#L27-L35 // https://github.com/yiminghe/css-animation/blob/a5986d73fd7dfce75665337f39b91483d63a4c8c/src/Event.js#L44 - window.AnimationEvent = window.AnimationEvent || window.Event; - window.TransitionEvent = window.TransitionEvent || window.Event; + win.AnimationEvent = win.AnimationEvent || win.Event; + win.TransitionEvent = win.TransitionEvent || win.Event; // ref: https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom // ref: https://github.com/jsdom/jsdom/issues/2524 - Object.defineProperty(window, 'TextEncoder', { writable: true, value: util.TextEncoder }); - Object.defineProperty(window, 'TextDecoder', { writable: true, value: util.TextDecoder }); + Object.defineProperty(win, 'TextEncoder', { writable: true, value: util.TextEncoder }); + Object.defineProperty(win, 'TextDecoder', { writable: true, value: util.TextDecoder }); } + +/* eslint-disable global-require */ +if (typeof window !== 'undefined') { + fillWindowEnv(window); +} + +global.requestAnimationFrame = global.requestAnimationFrame || global.setTimeout; +global.cancelAnimationFrame = global.cancelAnimationFrame || global.clearTimeout; diff --git a/tests/setupAfterEnv.ts b/tests/setupAfterEnv.ts index 974bb9b650..0d71e44999 100644 --- a/tests/setupAfterEnv.ts +++ b/tests/setupAfterEnv.ts @@ -8,13 +8,11 @@ import { defaultConfig } from '../components/theme/internal'; defaultConfig.hashed = false; if (process.env.LIB_DIR === 'dist') { - jest.mock('../dist/antd', () => { - const antd = jest.requireActual('../dist/antd'); - antd.theme.defaultConfig.hashed = false; - - return antd; - }); + jest.mock('antd', () => jest.requireActual('../dist/antd')); +} else if (process.env.LIB_DIR === 'dist-min') { + jest.mock('antd', () => jest.requireActual('../dist/antd.min')); } else if (process.env.LIB_DIR === 'es') { + jest.mock('antd', () => jest.requireActual('../es')); jest.mock('../es/theme/internal', () => { const esTheme = jest.requireActual('../es/theme/internal'); if (esTheme.defaultConfig) { diff --git a/tests/shared/demoTest.tsx b/tests/shared/demoTest.tsx index 538a4a3c7e..63bac11c88 100644 --- a/tests/shared/demoTest.tsx +++ b/tests/shared/demoTest.tsx @@ -11,6 +11,7 @@ import { render } from '../utils'; import { TriggerMockContext } from './demoTestContext'; import { excludeWarning, isSafeWarning } from './excludeWarning'; import rootPropsTest from './rootPropsTest'; +import { ConfigProvider } from 'antd'; export { rootPropsTest }; @@ -60,7 +61,11 @@ function baseText(doInject: boolean, component: string, options: Options = {}) { } // Inject cssinjs cache to avoid create