chore: auto merge branches (#39003)

chore: feature merge master
This commit is contained in:
github-actions[bot] 2022-11-25 12:35:04 +00:00 committed by GitHub
commit 5bb2479184
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
236 changed files with 7466 additions and 3701 deletions

View File

@ -10,7 +10,7 @@ export type UseMenuOptions = {
const useMenu = (options: UseMenuOptions = {}): [MenuProps['items'], string] => {
const fullData = useFullSidebarData();
const { pathname } = useLocation();
const { pathname, search } = useLocation();
const sidebarData = useSidebarData();
const { before, after } = options;
@ -60,7 +60,7 @@ const useMenu = (options: UseMenuOptions = {}): [MenuProps['items'], string] =>
childItems.push(
...childrenGroup.default.map((item) => ({
label: (
<Link to={item.link}>
<Link to={`${item.link}${search}`}>
{before}
{item.title}
{after}
@ -77,7 +77,7 @@ const useMenu = (options: UseMenuOptions = {}): [MenuProps['items'], string] =>
key: type,
children: children?.map((item) => ({
label: (
<Link to={item.link}>
<Link to={`${item.link}${search}`}>
{before}
{item.title}
{after}
@ -100,7 +100,7 @@ const useMenu = (options: UseMenuOptions = {}): [MenuProps['items'], string] =>
key: group.title,
children: group.children?.map((item) => ({
label: (
<Link to={item.link}>
<Link to={`${item.link}${search}`}>
{before}
<span key="english">{item.title}</span>
<span className="chinese" key="chinese">
@ -117,7 +117,7 @@ const useMenu = (options: UseMenuOptions = {}): [MenuProps['items'], string] =>
result.push(
...group.children?.map((item) => ({
label: (
<Link to={item.link}>
<Link to={`${item.link}${search}`}>
{before}
{item.title}
{after}
@ -130,7 +130,7 @@ const useMenu = (options: UseMenuOptions = {}): [MenuProps['items'], string] =>
return result;
}, []) ?? []
);
}, [sidebarData, fullData, pathname]);
}, [sidebarData, fullData, pathname, search]);
return [menuItems, pathname];
};

View File

@ -35,7 +35,7 @@ const useStyle = () => {
}
.intro {
transform: translateY(0);
transform: translate3d(0, 0, 0);
h4${token.antCls}-typography {
padding-bottom: 0;
@ -48,7 +48,7 @@ const useStyle = () => {
right: 0;
bottom: 0;
left: 0;
transform: translateY(100%);
transform: translate3d(0, 100%, 0);
transition: all ${token.motionDurationSlow};
${token.antCls}-typography {
@ -62,7 +62,7 @@ const useStyle = () => {
h4${token.antCls}-typography {
position: absolute;
padding: 0 ${token.paddingMD}px ${token.paddingMD}px;
transform: translateY(-100%);
transform: translate3d(0, -100%, 0);
}
div${token.antCls}-typography {

View File

@ -164,7 +164,7 @@ const useStyle = () => {
logoImgPureColor: css`
img {
transform: translateX(-30px);
transform: translate3d(-30px, 0, 0);
}
`,
@ -512,7 +512,7 @@ export default function Theme() {
style={{
...posStyle,
left: '50%',
transform: 'translateX(-900px)',
transform: 'translate3d(-900px, 0, 0)',
top: -100,
height: 500,
}}
@ -523,7 +523,7 @@ export default function Theme() {
style={{
...posStyle,
right: '50%',
transform: 'translateX(750px)',
transform: 'translate3d(750px, 0, 0)',
bottom: -100,
height: 287,
}}

View File

@ -1,4 +1,4 @@
import React, { useEffect, useLayoutEffect, type FC } from 'react';
import React from 'react';
import { useLocale as useDumiLocale } from 'dumi';
import { css } from '@emotion/react';
import useLocale from '../../hooks/useLocale';
@ -11,8 +11,6 @@ import BannerRecommends from './components/BannerRecommends';
import ComponentsList from './components/ComponentsList';
import DesignFramework from './components/DesignFramework';
import { ConfigProvider } from 'antd';
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
const useStyle = () => {
const { token } = useSiteToken();
@ -44,8 +42,8 @@ const locales = {
},
};
const Homepage: FC = () => {
const [locale, lang] = useLocale(locales);
const Homepage: React.FC = () => {
const [locale] = useLocale(locales);
const { id: localeId } = useDumiLocale();
const localeStr = localeId === 'zh-CN' ? 'cn' : 'en';
@ -53,14 +51,6 @@ const Homepage: FC = () => {
const style = useStyle();
useLayoutEffect(() => {
if (lang === 'cn') {
dayjs.locale('zh-cn');
} else {
dayjs.locale('en');
}
}, []);
return (
<ConfigProvider theme={{ algorithm: undefined }}>
<section>

View File

@ -1,8 +1,8 @@
import { ThemeEditor } from 'antd-token-previewer';
import { useContext } from 'react';
import ThemeContext from '../../theme/slots/ThemeContext';
import { useState } from 'react';
import useLocale from '../../hooks/useLocale';
import { ConfigProvider } from 'antd';
import { ThemeConfig } from 'antd/es/config-provider/context';
const locales = {
cn: {
@ -15,13 +15,13 @@ const locales = {
const CustomTheme = () => {
const [locale] = useLocale(locales);
const { setTheme, theme } = useContext(ThemeContext);
const [theme, setTheme] = useState<ThemeConfig>({});
return (
<div>
<ConfigProvider theme={{ algorithm: undefined }}>
<ConfigProvider theme={{ inherit: false }}>
<ThemeEditor
theme={{ name: 'test', key: 'test', config: theme }}
theme={{ name: 'Custom Theme', key: 'test', config: theme }}
simple
style={{ height: 'calc(100vh - 64px)' }}
onThemeChange={(newTheme) => {

View File

@ -1,6 +1,6 @@
import React, { type FC } from 'react';
import React from 'react';
const APITable: FC = () => {
const APITable: React.FC = () => {
// TODO: implement api table, depend on the new markdown data structure passed
return <>API Table</>;
};

View File

@ -1,4 +1,4 @@
import React, { useEffect, useState, type FC } from 'react';
import React, { useEffect, useState } from 'react';
// @ts-ignore
import JsonML from 'jsonml.js/lib/utils';
// @ts-ignore
@ -36,7 +36,7 @@ function useShowRiddleButton() {
*/
export default function fromDumiProps<P extends object>(
WrappedComponent: React.ComponentType<P>,
): FC<IPreviewerProps> {
): React.FC<IPreviewerProps> {
const hoc = function DumiPropsAntdPreviewer(props: IPreviewerProps) {
const showRiddleButton = useShowRiddleButton();
const location = useLocation();

View File

@ -1,7 +1,7 @@
/* eslint jsx-a11y/no-noninteractive-element-interactions: 0 */
import { CheckOutlined, SnippetsOutlined, ThunderboltOutlined } from '@ant-design/icons';
import stackblitzSdk from '@stackblitz/sdk';
import { Alert, Badge, Tooltip } from 'antd';
import { Alert, Badge, Tooltip, Space } from 'antd';
import classNames from 'classnames';
import LZString from 'lz-string';
import React from 'react';
@ -375,7 +375,7 @@ createRoot(document.getElementById('container')).render(<Demo />);
/>
</div>
<div className="code-box-description">{introChildren}</div>
<div className="code-box-actions">
<Space wrap size="middle" className="code-box-actions">
{showRiddleButton ? (
<form
className="code-box-code-action"
@ -466,7 +466,7 @@ createRoot(document.getElementById('container')).render(<Demo />);
<Tooltip
title={<FormattedMessage id={`app.demo.code.${codeExpand ? 'hide' : 'show'}`} />}
>
<span className="code-expand-icon code-box-code-action">
<div className="code-expand-icon code-box-code-action">
<img
alt="expand code"
src={
@ -487,9 +487,9 @@ createRoot(document.getElementById('container')).render(<Demo />);
className={codeExpand ? 'code-expand-icon-show' : 'code-expand-icon-hide'}
onClick={() => this.handleCodeExpand(meta.id)}
/>
</span>
</div>
</Tooltip>
</div>
</Space>
</section>
<section className={highlightClass} key="code">
<CodePreview

View File

@ -1,4 +1,4 @@
import React, { type FC } from 'react';
import React from 'react';
import { Col, Row } from 'antd';
import { css } from '@emotion/react';
import useSiteToken from '../../../hooks/useSiteToken';
@ -70,7 +70,7 @@ export type ResourceCardProps = {
resource: Resource;
};
const ResourceCard: FC<ResourceCardProps> = ({ resource }) => {
const ResourceCard: React.FC<ResourceCardProps> = ({ resource }) => {
const styles = useStyle();
const { title: titleStr, description, cover, src, official } = resource;
@ -105,7 +105,7 @@ export type ResourceCardsProps = {
resources: Resource[];
};
const ResourceCards: FC<ResourceCardsProps> = ({ resources }) => {
const ResourceCards: React.FC<ResourceCardsProps> = ({ resources }) => {
return (
<Row style={{ margin: '-12px -12px 0 -12px' }}>
{resources.map((item) => (

View File

@ -0,0 +1,114 @@
import React, { FC, useMemo } from 'react';
import tokenMeta from 'antd/es/version/token-meta.json';
import { getDesignToken } from 'antd-token-previewer';
import { Table, TableProps, Tag } from 'antd';
import useLocale from '../../../hooks/useLocale';
import useSiteToken from '../../../hooks/useSiteToken';
import { css } from '@emotion/react';
type TokenTableProps = {
type: 'seed' | 'map' | 'alias';
lang: 'zh' | 'en';
};
type TokenData = {
name: string;
desc: string;
type: string;
value: any;
};
const defaultToken = getDesignToken();
const locales = {
cn: {
token: 'Token 名称',
description: '描述',
type: '类型',
value: '默认值',
},
en: {
token: 'Token Name',
description: 'Description',
type: 'Type',
value: 'Default Value',
},
};
const useStyle = () => {
const { token } = useSiteToken();
return {
codeSpan: css`
margin: 0 1px;
padding: 0.2em 0.4em;
font-size: 0.9em;
background: ${token.siteMarkdownCodeBg};
border: 1px solid ${token.colorSplit};
border-radius: 3px;
font-family: monospace;
`,
};
};
const TokenTable: FC<TokenTableProps> = ({ type }) => {
const styles = useStyle();
const [locale, lang] = useLocale(locales);
const columns: Exclude<TableProps<TokenData>['columns'], undefined> = [
{
title: locale.token,
key: 'name',
dataIndex: 'name',
},
{
title: locale.description,
key: 'desc',
dataIndex: 'desc',
width: 300,
},
{
title: locale.type,
key: 'type',
dataIndex: 'type',
render: (_, record) => <span css={styles.codeSpan}>{record.type}</span>,
},
{
title: locale.value,
key: 'value',
render: (_, record) => (
<span style={{ display: 'inline-flex', alignItems: 'center' }}>
{typeof record.value === 'string' &&
(record.value.startsWith('#') || record.value.startsWith('rgb')) && (
<span
style={{
background: record.value,
display: 'inline-block',
width: 6,
height: 6,
borderRadius: '50%',
boxShadow: 'inset 0 0 0 1px rgba(0, 0, 0, 0.06)',
marginRight: 4,
}}
></span>
)}
{typeof record.value !== 'string' ? JSON.stringify(record.value) : record.value}
</span>
),
},
];
const data = useMemo<TokenData[]>(() => {
return tokenMeta[type].map((token) => {
return {
name: token.name,
desc: lang === 'cn' ? token.desc : token.descEn,
type: token.type,
value: (defaultToken as any)[token.name],
};
});
}, [type, lang]);
return <Table dataSource={data} columns={columns} pagination={false} bordered />;
};
export default TokenTable;

View File

@ -286,8 +286,11 @@ const GlobalStyles = () => {
}
.markdown .dumi-default-source-code {
margin: 1em 0;
background-color: ${token.siteMarkdownCodeBg};
border-radius: ${token.borderRadius}px;
> pre.prism-code {
padding: 12px 20px;
font-size: 13px;
line-height: 2;
}
@ -450,7 +453,7 @@ const GlobalStyles = () => {
.markdown .dumi-default-table {
table {
margin: 2em 0;
margin: 0;
overflow-x: auto;
overflow-y: hidden;
font-size: ${Math.max(token.fontSize - 1, 12)}px;
@ -1001,6 +1004,9 @@ const GlobalStyles = () => {
}
.code-expand-icon {
width: 16px;
height: 16px;
position: relative;
cursor: pointer;
}
@ -1083,7 +1089,6 @@ const GlobalStyles = () => {
align-items: center;
width: 16px;
height: 16px;
margin-left: 16px;
color: ${token.colorTextSecondary};
cursor: pointer;
transition: all 0.24s;
@ -1093,14 +1098,6 @@ const GlobalStyles = () => {
margin-left: 0;
}
&:first-child {
margin-left: 0;
${antCls}-row-rtl & {
margin-right: 0;
}
}
&:hover {
color: ${token.colorText};
}

View File

@ -1,8 +1,8 @@
import React, { type FC } from 'react';
import React from 'react';
import { Skeleton, Space, Spin } from 'antd';
import { useLocation } from 'dumi';
const Loading: FC = () => {
const Loading: React.FC = () => {
const { pathname } = useLocation();
if (

View File

@ -0,0 +1,20 @@
import React from 'react';
import Icon from '@ant-design/icons';
const ThemeIcon = (props: any) => {
const SVGIcon = React.useCallback(
() => (
<svg width={21} height={21} viewBox="0 0 21 21" fill="currentColor" {...props}>
<g fillRule="evenodd">
<g fillRule="nonzero">
<path d="M7.02 3.635l12.518 12.518a1.863 1.863 0 010 2.635l-1.317 1.318a1.863 1.863 0 01-2.635 0L3.068 7.588A2.795 2.795 0 117.02 3.635zm2.09 14.428a.932.932 0 110 1.864.932.932 0 010-1.864zm-.043-9.747L7.75 9.635l9.154 9.153 1.318-1.317-9.154-9.155zM3.52 12.473c.514 0 .931.417.931.931v.932h.932a.932.932 0 110 1.864h-.932v.931a.932.932 0 01-1.863 0l-.001-.931h-.93a.932.932 0 010-1.864h.93v-.932c0-.514.418-.931.933-.931zm15.374-3.727a1.398 1.398 0 110 2.795 1.398 1.398 0 010-2.795zM4.385 4.953a.932.932 0 000 1.317l2.046 2.047L7.75 7 5.703 4.953a.932.932 0 00-1.318 0zM14.701.36a.932.932 0 01.931.932v.931h.932a.932.932 0 010 1.864h-.933l.001.932a.932.932 0 11-1.863 0l-.001-.932h-.93a.932.932 0 110-1.864h.93v-.931a.932.932 0 01.933-.932z" />
</g>
</g>
</svg>
),
[props],
);
return <Icon component={SVGIcon} {...props} />;
};
export default ThemeIcon;

View File

@ -0,0 +1,68 @@
import React, { FC } from 'react';
import { FloatButton, theme } from 'antd';
import ThemeIcon from './ThemeIcon';
import { DarkTheme, Light, CompactTheme } from 'antd-token-previewer/es/icons';
const { defaultAlgorithm, darkAlgorithm, compactAlgorithm } = theme;
export type ThemeSwitchProps = {
value: typeof defaultAlgorithm[];
onChange: (value: typeof defaultAlgorithm[]) => void;
};
const ThemeSwitch: FC<ThemeSwitchProps> = ({ value, onChange }) => {
const handleLightSwitch = () => {
let newValue = [...value];
if (value.includes(darkAlgorithm)) {
newValue = newValue.filter((item) => item !== darkAlgorithm);
}
if (!value.includes(defaultAlgorithm)) {
newValue.unshift(defaultAlgorithm);
}
onChange(newValue);
};
const handleDarkSwitch = () => {
let newValue = [...value];
if (value.includes(defaultAlgorithm)) {
newValue = newValue.filter((item) => item !== defaultAlgorithm);
}
if (!value.includes(darkAlgorithm)) {
newValue.push(darkAlgorithm);
}
onChange(newValue);
};
const handleCompactSwitch = () => {
if (value.includes(compactAlgorithm)) {
onChange(value.filter((item) => item !== compactAlgorithm));
} else {
onChange([...value, compactAlgorithm]);
}
};
return (
<FloatButton.Group trigger="click" icon={<ThemeIcon />}>
<FloatButton
icon={<Light />}
type={value.includes(defaultAlgorithm) ? 'primary' : 'default'}
onClick={handleLightSwitch}
tooltip="Light"
/>
<FloatButton
icon={<DarkTheme />}
type={value.includes(darkAlgorithm) ? 'primary' : 'default'}
onClick={handleDarkSwitch}
tooltip="Dark"
/>
<FloatButton
icon={<CompactTheme />}
type={value.includes(compactAlgorithm) ? 'primary' : 'default'}
onClick={handleCompactSwitch}
tooltip="Compact"
/>
</FloatButton.Group>
);
};
export default ThemeSwitch;

View File

@ -1,4 +1,6 @@
import React, { type FC, useEffect, useMemo, useRef } from 'react';
import React, { useEffect, useMemo, useRef, useLayoutEffect } from 'react';
import 'dayjs/locale/zh-cn';
import dayjs from 'dayjs';
import { useOutlet, useSearchParams, Helmet } from 'dumi';
import Header from 'dumi/theme/slots/Header';
import Footer from 'dumi/theme/slots/Footer';
@ -33,7 +35,7 @@ const locales = {
const RESPONSIVE_MOBILE = 768;
const DocLayout: FC = () => {
const DocLayout: React.FC = () => {
const outlet = useOutlet();
const location = useLocation();
const { pathname, search } = location;
@ -52,6 +54,14 @@ const DocLayout: FC = () => {
setIsMobile(window.innerWidth < RESPONSIVE_MOBILE);
};
useLayoutEffect(() => {
if (lang === 'cn') {
dayjs.locale('zh-cn');
} else {
dayjs.locale('en');
}
}, []);
useEffect(() => {
const nprogressHiddenStyle = document.getElementById('nprogress-style');
if (nprogressHiddenStyle) {

View File

@ -1,31 +1,62 @@
import React, { type FC, useLayoutEffect } from 'react';
import React, { useLayoutEffect } from 'react';
import { useOutlet } from 'dumi';
import { ConfigProvider, theme as antdTheme } from 'antd';
import { ThemeConfig } from 'antd/es/config-provider/context';
import ThemeContext, { ThemeContextProps } from '../slots/ThemeContext';
import ThemeSwitch from '../common/ThemeSwitch';
import useLocation from '../../hooks/useLocation';
const ANT_DESIGN_SITE_THEME = 'antd-site-theme';
const GlobalLayout: FC = () => {
const outlet = useOutlet();
const getAlgorithm = (theme: string) => {
if (theme === 'dark') {
return antdTheme.darkAlgorithm;
}
if (theme === 'compact') {
return antdTheme.compactAlgorithm;
}
return antdTheme.defaultAlgorithm;
};
const [theme, setTheme] = React.useState<ThemeConfig>({});
const getThemeString = (algorithm: typeof antdTheme.defaultAlgorithm) => {
if (algorithm === antdTheme.darkAlgorithm) {
return 'dark';
}
if (algorithm === antdTheme.compactAlgorithm) {
return 'compact';
}
return 'light';
};
const GlobalLayout: React.FC = () => {
const outlet = useOutlet();
const { pathname } = useLocation();
const [theme, setTheme] = React.useState<ThemeConfig>({
algorithm: [antdTheme.defaultAlgorithm],
});
const handleThemeChange = (newTheme: ThemeConfig, ignoreAlgorithm: boolean = true) => {
const nextTheme = { ...newTheme };
if (ignoreAlgorithm) {
nextTheme.algorithm = theme.algorithm;
}
setTheme(nextTheme);
localStorage.setItem(
ANT_DESIGN_SITE_THEME,
JSON.stringify(nextTheme, (key, value) => {
if (key === 'algorithm') {
return Array.isArray(value) ? value.map((item) => getThemeString(item)) : ['light'];
}
return value;
}),
);
};
const contextValue = React.useMemo<ThemeContextProps>(
() => ({
theme,
setTheme: (newTheme) => {
setTheme(newTheme);
localStorage.setItem(
ANT_DESIGN_SITE_THEME,
JSON.stringify(newTheme, (key, value) => {
if (key === 'algorithm') {
return value === antdTheme.darkAlgorithm ? 'dark' : value;
}
return value;
}),
);
},
setTheme: handleThemeChange,
}),
[theme],
);
@ -35,8 +66,10 @@ const GlobalLayout: FC = () => {
if (localTheme) {
try {
const themeConfig = JSON.parse(localTheme);
if (themeConfig.algorithm === 'dark') {
themeConfig.algorithm = antdTheme.darkAlgorithm;
if (themeConfig.algorithm) {
themeConfig.algorithm = themeConfig.algorithm.map((item: string) => getAlgorithm(item));
} else {
themeConfig.algorithm = [antdTheme.defaultAlgorithm];
}
setTheme(themeConfig);
} catch (e) {
@ -50,11 +83,15 @@ const GlobalLayout: FC = () => {
<ConfigProvider
theme={{
...theme,
// TODO: Site algorithm
// algorithm: undefined,
}}
>
{outlet}
{!pathname.startsWith('/~demos') && (
<ThemeSwitch
value={theme.algorithm as []}
onChange={(value) => handleThemeChange({ ...theme, algorithm: value }, false)}
/>
)}
</ConfigProvider>
</ThemeContext.Provider>
);

View File

@ -21,7 +21,7 @@ const useStyle = () => {
padding: 0 40px;
background: #fff;
box-shadow: ${boxShadowSecondary};
transform: translateY(-100%);
transform: translate3d(0, -100%, 0);
opacity: 0;
transition: opacity 0.3s, transform 0.3s;
@ -43,7 +43,7 @@ const useStyle = () => {
}
`,
affixTabsFixed: css`
transform: translateY(0);
transform: translate3d(0, 0, 0);
opacity: 1;
`,
};

View File

@ -104,7 +104,9 @@ const RoutesPlugin = (api: IApi) => {
// generate ssr css file
api.onBuildHtmlComplete(() => {
const styleText = extractStyle((global as any).styleCache);
// FIXME: This should not be empty @peachScript
const styleCache = (global as any)?.styleCache;
const styleText = styleCache ? extractStyle(styleCache) : '';
const styleTextWithoutStyleTag = styleText
.replace(/<style\s[^>]*>/g, '')
.replace(/<\/style>/g, '');

View File

@ -1,4 +1,4 @@
import React, { ReactNode, type FC, useMemo, useState, useLayoutEffect, useContext } from 'react';
import React, { ReactNode, useMemo, useState, useLayoutEffect, useContext } from 'react';
import { useIntl, useRouteMeta } from 'dumi';
import Footer from 'dumi/theme/slots/Footer';
import { Col, Typography, Avatar, Tooltip, Affix, Anchor } from 'antd';
@ -82,7 +82,8 @@ const useStyle = () => {
}
@media only screen and (max-width: ${token.screenLG}px) {
&, &.rtl {
&,
&.rtl {
padding-right: 48px;
padding-left: 48px;
}
@ -97,7 +98,7 @@ type AnchorItem = {
children?: AnchorItem[];
};
const Content: FC<{ children: ReactNode }> = ({ children }) => {
const Content: React.FC<{ children: ReactNode }> = ({ children }) => {
const meta = useRouteMeta();
const { pathname } = useLocation();
const { formatMessage } = useIntl();

View File

@ -1,194 +1,88 @@
import * as React from 'react';
import { Modal, Button, Typography, Row, Col, Tour } from 'antd';
import { SmileOutlined } from '@ant-design/icons';
import { isLocalStorageNameSupported, ping } from '../../utils';
import { updateCSS, removeCSS } from 'rc-util/lib/Dom/dynamicCSS';
import useLocale from '../../../hooks/useLocale';
import useSiteToken from '../../../hooks/useSiteToken';
const whereCls = 'ant-where-checker';
const locales = {
cn: {
title: '🎉🎉🎉 Ant Design 5.0 发布! 🎉🎉🎉',
ok: '知道了',
whereNotSupport: `你的浏览器不支持现代 CSS Selector请使用现代浏览器如 Chrome、Firefox 等等)查看官网。如果需要对旧版浏览器进行样式支持,欢迎查阅配置文档:`,
whereDocTitle: '兼容性调整(请使用现代浏览器访问)',
whereDocUrl: '/docs/react/customize-theme-cn#兼容性调整',
},
en: {
title: '🎉🎉🎉 Ant Design 5.0 is released! 🎉🎉🎉',
ok: 'Got it',
whereNotSupport:
'Your browser not support modern CSS Selector. Please use modern browser to view (e.g. Chrome, Firefox, etc). If you want to compatible style with legacy browser, please refer to the configuration document:',
whereDocTitle: 'Compatible adjustment (Please use modern browser to visit)',
whereDocUrl: '/docs/react/customize-theme#compatible-adjustment',
},
};
const V5_NOTIFICATION = 'antd@4.0.0-notification-sent';
const SHOULD_OPEN_ANT_DESIGN_MIRROR_MODAL = 'ANT_DESIGN_DO_NOT_OPEN_MIRROR_MODAL';
function disableAntdMirrorModal() {
window.localStorage.setItem(SHOULD_OPEN_ANT_DESIGN_MIRROR_MODAL, 'true');
}
function shouldOpenAntdMirrorModal() {
return !window.localStorage.getItem(SHOULD_OPEN_ANT_DESIGN_MIRROR_MODAL);
}
// Check for browser support `:where` or not
// Warning user if not support to modern browser
export default function InfoNewVersion() {
return null;
const [locale, lang] = useLocale(locales);
const [notify, setNotify] = React.useState<null | boolean>(null);
const { token } = useSiteToken();
function onClose() {
setNotify(false);
localStorage.setItem(V5_NOTIFICATION, 'true');
}
const [location] = useLocale(locales);
const [supportWhere, setSupportWhere] = React.useState(true);
React.useEffect(() => {
if (isLocalStorageNameSupported()) {
// 大版本发布后全局弹窗提示
// 1. 点击『知道了』之后不再提示
// 2. 超过截止日期后不再提示
if (
localStorage.getItem(V5_NOTIFICATION) !== 'true' &&
Date.now() < new Date('2022/12/31').getTime()
) {
setNotify(true);
return;
}
}
const p = document.createElement('p');
p.className = whereCls;
p.style.position = 'fixed';
p.style.pointerEvents = 'none';
p.style.visibility = 'hidden';
p.style.opacity = '0';
document.body.appendChild(p);
updateCSS(
`
:where(.${whereCls}) {
opacity: 0.3 !important;
}
`,
whereCls,
);
setNotify(false);
// Check style
const { opacity } = getComputedStyle(p);
setSupportWhere(String(opacity) === '0.3');
return () => {
document.body.removeChild(p);
removeCSS(whereCls);
};
}, []);
React.useEffect(() => {
const timeout = ping((status) => {
if (status !== 'timeout' && status !== 'error') {
if (
// process.env.NODE_ENV === 'production' &&
notify === false &&
window.location.host !== 'ant-design.antgroup.com' &&
shouldOpenAntdMirrorModal()
) {
Modal.confirm({
title: '提示',
content: '内网用户推荐访问国内镜像以获得极速体验~',
okText: '🚀 立刻前往',
cancelText: '不再弹出',
closable: true,
onOk() {
window.open('https://ant-design.antgroup.com', '_self');
disableAntdMirrorModal();
},
onCancel() {
disableAntdMirrorModal();
},
});
}
}
});
return clearTimeout(timeout);
}, [notify]);
return (
<>
<Tour
open={!!notify}
mask={false}
steps={[
{
title: locale.title,
target: () => document.querySelector('#versionSelector')!,
description: (
<Typography style={{ marginTop: token.marginXS }}>
{lang === 'cn' ? (
<>
<p>
{' '}
<Typography.Link href="/changelog-cn" onClick={onClose}>
</Typography.Link>{' '}
</p>
<p>
访 v4 {' '}
<Typography.Link href="https://4x.ant.design/" onClick={onClose}>
</Typography.Link>
</p>
</>
) : (
<>
<p>
Click{' '}
<Typography.Link href="/changelog" onClick={onClose}>
here
</Typography.Link>{' '}
to view full changelog.
</p>
<p>
If you want to check v4 documentation, please click{' '}
<Typography.Link href="https://4x.ant.design/" onClick={onClose}>
here
</Typography.Link>
.
</p>
</>
)}
</Typography>
),
},
]}
/>
{/* <Modal
open={!!notify}
title={locale.title}
closable={false}
footer={<Button onClick={onClose}>{locale.ok}</Button>}
return supportWhere ? null : (
<div
style={{
position: 'fixed',
left: 0,
right: 0,
top: 0,
bottom: 0,
zIndex: 99999999,
background: 'rgba(0,0,0,0.65)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}
>
<div
style={{
border: `1px solid #ffe58f`,
background: '#fffbe6',
color: 'rgba(0,0,0,0.88)',
padding: '8px 12px',
borderRadius: '8px',
zIndex: 9999999999,
lineHeight: '22px',
width: 520,
}}
>
<Row gutter={16}>
<Col flex="none">
<SmileOutlined style={{ fontSize: 72, color: token.colorSuccess }} />
</Col>
<Col flex="auto">
<Typography style={{ marginTop: token.marginXS }}>
{lang === 'cn' ? (
<>
<p>
{' '}
<Typography.Link href="/changelog-cn" onClick={onClose}>
</Typography.Link>{' '}
</p>
<p>
访 v4 {' '}
<Typography.Link href="https://4x.ant.design/" onClick={onClose}>
</Typography.Link>
</p>
</>
) : (
<>
<p>
Click{' '}
<Typography.Link href="/changelog" onClick={onClose}>
here
</Typography.Link>{' '}
to view full changelog.
</p>
<p>
If you want to check v4 documentation, please click{' '}
<Typography.Link href="https://4x.ant.design/" onClick={onClose}>
here
</Typography.Link>
.
</p>
</>
)}
</Typography>
</Col>
</Row>
</Modal> */}
</>
{location.whereNotSupport}{' '}
<a style={{ color: '#1677ff', textDecoration: 'none' }} href={location.whereDocUrl}>
{location.whereDocTitle}
</a>
</div>
</div>
);
}

View File

@ -232,9 +232,9 @@ const Header: React.FC<HeaderProps> = (props) => {
const onMenuVisibleChange = useCallback((visible: boolean) => {
setHeaderState((prev) => ({ ...prev, menuVisible: visible }));
}, []);
const onDirectionChange = useCallback(() => {
const onDirectionChange = () => {
changeDirection?.(direction !== 'rtl' ? 'rtl' : 'ltr');
}, [direction]);
};
useEffect(() => {
handleHideMenu();

View File

@ -1,4 +1,4 @@
import React, { type FC, useContext } from 'react';
import React, { useContext } from 'react';
import { useSidebarData } from 'dumi';
import { Affix, Col, Menu } from 'antd';
import MobileMenu from 'rc-drawer';
@ -66,8 +66,8 @@ const useStyle = () => {
// Nest Category > Type > Article
&${antCls}-menu-inline {
${antCls}-menu-item-group-title {
padding-left: 60px;
margin-left: 4px;
padding-left: 60px;
${antCls}-row-rtl & {
padding-right: 60px;
@ -124,7 +124,7 @@ const useStyle = () => {
};
};
const Sidebar: FC = () => {
const Sidebar: React.FC = () => {
const sidebarData = useSidebarData();
const { isMobile } = useContext(SiteContext);
const styles = useStyle();

View File

@ -46,7 +46,7 @@ export default {
'Template Document': 3,
},
docVersions: {
'4.x': chineseMirror ? 'https://4x-ant-design.antgroup.com/' : 'https://4x.ant.design',
'4.x': chineseMirror ? 'https://4x-ant-design.antgroup.com' : 'https://4x.ant.design',
'3.x': 'https://3x.ant.design',
'2.x': 'https://2x.ant.design',
'1.x': 'https://1x.ant.design',

3
.gitignore vendored
View File

@ -48,7 +48,8 @@ server/
# Docs templates
scripts/previewEditor/index.html
components/version/version.tsx
components/version/token.tsx
components/version/token.json
components/version/token-meta.json
.dumi/tmp
.dumi/tmp-test
.dumi/tmp-production

View File

@ -15,6 +15,23 @@ timeline: true
---
## 5.0.1
`2022-11-22`
- 💄 Optimize Empty svg color in dark theme. [#38785](https://github.com/ant-design/ant-design/pull/38785)
- 💄 Fix Form, Input, Select, Tree part style convert to CSS-in-JS missing. [#38742](https://github.com/ant-design/ant-design/pull/38742)
- 💄 Fix animation flick for some components in Firefox. [#38729](https://github.com/ant-design/ant-design/pull/38729)
- Menu
- 🐞 Fix Menu SubMenu margin style. [#38714](https://github.com/ant-design/ant-design/pull/38714) [@JarvisArt](https://github.com/JarvisArt)
- 🐞 Fix Menu height in dark theme. [#38741](https://github.com/ant-design/ant-design/pull/38741) [@LuciNyan](https://github.com/LuciNyan)
- 🐞 Fix Menu SubMenu flicking when expanding. [#38748](https://github.com/ant-design/ant-design/pull/38748) [@JarvisArt](https://github.com/JarvisArt)
- 🐞 Fix that Table expanded icons are not aligned。[#38823](https://github.com/ant-design/ant-design/pull/38823) [@turdiyev](https://github.com/turdiyev)
- 🐞 Fix FloatButton.BackTop missing animation. [#38770](https://github.com/ant-design/ant-design/pull/38770) [@li-jia-nan](https://github.com/li-jia-nan)
- 🛠 Remove `Moment.js` dependency. [#38762](https://github.com/ant-design/ant-design/pull/38762)
- 🛠 Fix `CompoundedComponent` ts error。[#38666](https://github.com/ant-design/ant-design/pull/38666) [@wangcch](https://github.com/wangcch)
- 🛠 Rollback `lib` in package。[#38832](https://github.com/ant-design/ant-design/pull/38832) [@chunsch](https://github.com/chunsch)
## 5.0.0
`2022-11-18`
@ -58,7 +75,7 @@ timeline: true
- 🆕 Default algorithm `theme.defaultAlgorithm`. [#36175](https://github.com/ant-design/ant-design/pull/36175)
- 🆕 Dark algorithm `theme.darkAlgorithm`. [#36546](https://github.com/ant-design/ant-design/pull/36546) [#36656](https://github.com/ant-design/ant-design/pull/36656)
- 🆕 Compact algorithm `theme.compactAlgorithm`. [#38105](https://github.com/ant-design/ant-design/pull/38105)
- 🆕 ConfigProvider support `theme` prop to modify theme configuration. For more: [Customize Theme](https://ant.design/docs/react/customize-theme-v5).
- 🆕 ConfigProvider support `theme` prop to modify theme configuration. For more: [Customize Theme](https://ant.design/docs/react/customize-theme).
- 🆕 Support multiple `algorithm` pipeline. [#37082](https://github.com/ant-design/ant-design/pull/37082)
- 🆕 Support switching wireframe style. [#37507](https://github.com/ant-design/ant-design/pull/37507)
- 🆕 Support override Design Token for single component. [#37568](https://github.com/ant-design/ant-design/pull/37568)

View File

@ -15,6 +15,23 @@ timeline: true
---
## 5.0.1
`2022-11-22`
- 💄 优化 Empty 组件的 svg 图片在暗色主题下的颜色。[#38785](https://github.com/ant-design/ant-design/pull/38785)
- 💄 修复 Form, Input, Select, Tree 转换到 CSS-in-JS 丢失少量样式的问题。[#38742](https://github.com/ant-design/ant-design/pull/38742)
- 💄 修复 Firefox 下拉菜单动画抖动的问题。[#38729](https://github.com/ant-design/ant-design/pull/38729)
- Menu
- 🐞 修复 Menu SubMenu 间距问题。[#38714](https://github.com/ant-design/ant-design/pull/38714) [@JarvisArt](https://github.com/JarvisArt)
- 🐞 修复 Menu 暗色主题下高度多了 1px 的问题。[#38741](https://github.com/ant-design/ant-design/pull/38741) [@LuciNyan](https://github.com/LuciNyan)
- 🐞 修复 Menu 展开 Submenu 时抖动的问题。[#38748](https://github.com/ant-design/ant-design/pull/38748) [@JarvisArt](https://github.com/JarvisArt)
- 🐞 修复 Table 组件展开 icon 不对齐的问题。[#38823](https://github.com/ant-design/ant-design/pull/38823) [@turdiyev](https://github.com/turdiyev)
- 🐞 修复 FloatButton.BackTop 组件动画丢失的问题。[#38770](https://github.com/ant-design/ant-design/pull/38770) [@li-jia-nan](https://github.com/li-jia-nan)
- 🛠 清除残留 `Moment.js` 依赖。[#38762](https://github.com/ant-design/ant-design/pull/38762)
- 🛠 修复外部暴露类 `CompoundedComponent` 的组件的类型报错。[#38666](https://github.com/ant-design/ant-design/pull/38666) [@wangcch](https://github.com/wangcch)
- 🛠 重新添加 `lib` 产物。[#38832](https://github.com/ant-design/ant-design/pull/38832) [@chunsch](https://github.com/chunsch)
## 5.0.0
`2022-11-18`
@ -58,7 +75,7 @@ timeline: true
- 🆕 默认算法 `theme.defaultAlgorithm`。[#36175](https://github.com/ant-design/ant-design/pull/36175)
- 🆕 暗色算法 `theme.darkAlgorithm`。[#36546](https://github.com/ant-design/ant-design/pull/36546) [#36656](https://github.com/ant-design/ant-design/pull/36656)
- 🆕 紧凑算法 `theme.compactAlgorithm`。[#38105](https://github.com/ant-design/ant-design/pull/38105)
- 🆕 ConfigProvider 新增 `theme` 属性,用于更改主题配置,详情:[定制主题](https://ant.design/docs/react/customize-theme-v5-cn)。
- 🆕 ConfigProvider 新增 `theme` 属性,用于更改主题配置,详情:[定制主题](https://ant.design/docs/react/customize-theme-cn)。
- 🆕 支持多个 `algorithm`。[#37082](https://github.com/ant-design/ant-design/pull/37082)
- 🆕 支持线框化切换。[#37507](https://github.com/ant-design/ant-design/pull/37507)
- 🆕 支持覆盖单个组件的主题变量。[#37568](https://github.com/ant-design/ant-design/pull/37568)

View File

@ -1,8 +1,8 @@
import { Keyframes, useStyleRegister } from '@ant-design/cssinjs';
import { useContext } from 'react';
import { ConfigContext } from '../../config-provider';
import type { AliasToken, GenerateStyle, UseComponentStyleResult } from '../../theme';
import { useToken } from '../../theme';
import type { AliasToken, GenerateStyle, UseComponentStyleResult } from '../../theme/internal';
import { useToken } from '../../theme/internal';
interface WaveToken extends AliasToken {
hashId: string;

View File

@ -67,7 +67,7 @@ class Affix extends React.Component<InternalAffixProps, AffixState> {
fixedNode: HTMLDivElement;
private timeout: any;
private timeout: NodeJS.Timeout | null;
context: ConfigConsumerProps;
@ -124,7 +124,10 @@ class Affix extends React.Component<InternalAffixProps, AffixState> {
}
componentWillUnmount() {
clearTimeout(this.timeout);
if (this.timeout) {
clearTimeout(this.timeout);
this.timeout = null;
}
removeObserveTarget(this);
this.updatePosition.cancel();
// https://github.com/ant-design/ant-design/issues/22683

View File

@ -1,6 +1,6 @@
import type { CSSObject } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
interface AffixToken extends FullToken<'Affix'> {
zIndexPopup: number;

View File

@ -1,6 +1,6 @@
import type { CSSInterpolation, CSSObject } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import { resetComponent } from '../../style';
export interface ComponentToken {}

View File

@ -1,6 +1,6 @@
import type { CSSObject } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import { resetComponent, textEllipsis } from '../../style';
export interface ComponentToken {}

View File

@ -1,6 +1,6 @@
import type { CSSObject } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import { resetComponent } from '../../style';
export interface ComponentToken {}

View File

@ -5,47 +5,42 @@ import rtlTest from '../../../tests/shared/rtlTest';
import { fireEvent, render, waitFakeTimer } from '../../../tests/utils';
describe('BackTop', () => {
beforeEach(() => {
jest.useFakeTimers();
});
afterEach(() => {
jest.useRealTimers();
});
mountTest(BackTop);
rtlTest(BackTop);
it('should scroll to top after click it', async () => {
jest.useFakeTimers();
const { container } = render(<BackTop visibilityHeight={-1} />);
const { container } = render(<BackTop />);
const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((_, y) => {
window.scrollY = y;
window.pageYOffset = y;
document.documentElement.scrollTop = y;
});
window.scrollTo(0, 400);
await waitFakeTimer();
expect(document.documentElement.scrollTop).toBe(400);
fireEvent.click(container.querySelector('.ant-back-top')!);
fireEvent.click(container.querySelector<HTMLDivElement>('.ant-back-top')!);
await waitFakeTimer();
expect(document.documentElement.scrollTop).toBe(0);
scrollToSpy.mockRestore();
jest.clearAllTimers();
jest.useRealTimers();
});
it('support onClick', async () => {
it('support onClick', () => {
const onClick = jest.fn();
const { container } = render(<BackTop onClick={onClick} visibilityHeight={-1} />);
const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((_, y) => {
window.scrollY = y;
window.pageYOffset = y;
});
document.dispatchEvent(new Event('scroll'));
window.scrollTo(0, 400);
fireEvent.click(container.querySelector('.ant-back-top')!);
const { container } = render(<BackTop onClick={onClick} visibilityHeight={0} />);
fireEvent.click(container.querySelector<HTMLDivElement>('.ant-back-top')!);
expect(onClick).toHaveBeenCalled();
scrollToSpy.mockRestore();
});
it('invalid target', async () => {
it('invalid target', () => {
const onClick = jest.fn();
const { container } = render(<BackTop onClick={onClick} visible target={undefined} />);
fireEvent.click(container.querySelector('.ant-back-top')!);
const { container } = render(<BackTop onClick={onClick} target={undefined} />);
fireEvent.click(container.querySelector<HTMLDivElement>('.ant-back-top')!);
expect(onClick).toHaveBeenCalled();
});
it('should console Error', () => {

View File

@ -2,9 +2,9 @@ import VerticalAlignTopOutlined from '@ant-design/icons/VerticalAlignTopOutlined
import classNames from 'classnames';
import CSSMotion from 'rc-motion';
import addEventListener from 'rc-util/lib/Dom/addEventListener';
import useMergedState from 'rc-util/lib/hooks/useMergedState';
import omit from 'rc-util/lib/omit';
import * as React from 'react';
import type { ConfigConsumerProps } from '../config-provider';
import { ConfigContext } from '../config-provider';
import getScroll from '../_util/getScroll';
import { cloneElement } from '../_util/reactNode';
@ -22,62 +22,36 @@ export interface BackTopProps {
className?: string;
style?: React.CSSProperties;
duration?: number;
visible?: boolean; // Only for test. Don't use it.
}
interface ChildrenProps {
prefixCls: string;
rootPrefixCls: string;
children?: React.ReactNode;
visible?: boolean; // Only for test. Don't use it.
}
const BackTopContent: React.FC<ChildrenProps> = (props) => {
const { prefixCls, rootPrefixCls, children, visible } = props;
const defaultElement = (
<div className={`${prefixCls}-content`}>
<div className={`${prefixCls}-icon`}>
<VerticalAlignTopOutlined />
</div>
</div>
);
return (
<CSSMotion visible={visible} motionName={`${rootPrefixCls}-fade`}>
{({ className: motionClassName }) =>
cloneElement(children || defaultElement, ({ className }) => ({
className: classNames(motionClassName, className),
}))
}
</CSSMotion>
);
};
const BackTop: React.FC<BackTopProps> = (props) => {
const [visible, setVisible] = useMergedState(false, {
value: props.visible,
});
const {
prefixCls: customizePrefixCls,
className = '',
visibilityHeight = 400,
target,
onClick,
duration = 450,
} = props;
const [visible, setVisible] = React.useState<boolean>(visibilityHeight === 0);
const ref = React.createRef<HTMLDivElement>();
const scrollEvent = React.useRef<ReturnType<typeof addEventListener>>(null);
const ref = React.useRef<HTMLDivElement>(null);
const scrollEvent = React.useRef<ReturnType<typeof addEventListener> | null>(null);
const getDefaultTarget = () =>
const getDefaultTarget = (): HTMLElement | Document | Window =>
ref.current && ref.current.ownerDocument ? ref.current.ownerDocument : window;
const handleScroll = throttleByAnimationFrame(
(e: React.UIEvent<HTMLElement> | { target: any }) => {
const { visibilityHeight = 400 } = props;
(e: React.UIEvent<HTMLElement, UIEvent> | { target: any }) => {
const scrollTop = getScroll(e.target, true);
setVisible(scrollTop > visibilityHeight);
setVisible(scrollTop >= visibilityHeight);
},
);
const bindScrollEvent = () => {
const { target } = props;
const getTarget = target || getDefaultTarget;
const container = getTarget();
scrollEvent.current = addEventListener(container, 'scroll', (e: React.UIEvent<HTMLElement>) => {
handleScroll(e);
});
scrollEvent.current = addEventListener(container, 'scroll', handleScroll);
handleScroll({ target: container });
};
@ -88,26 +62,18 @@ const BackTop: React.FC<BackTopProps> = (props) => {
React.useEffect(() => {
bindScrollEvent();
return () => {
if (scrollEvent.current) {
scrollEvent.current.remove();
}
handleScroll.cancel();
scrollEvent.current?.remove();
};
}, [props.target]);
}, [target]);
const scrollToTop = (e: React.MouseEvent<HTMLDivElement>) => {
const { onClick, target, duration = 450 } = props;
scrollTo(0, {
getContainer: target || getDefaultTarget,
duration,
});
if (typeof onClick === 'function') {
onClick(e);
}
scrollTo(0, { getContainer: target || getDefaultTarget, duration });
onClick?.(e);
};
const { getPrefixCls, direction } = React.useContext(ConfigContext);
const { prefixCls: customizePrefixCls, className = '' } = props;
const { getPrefixCls, direction } = React.useContext<ConfigConsumerProps>(ConfigContext);
const prefixCls = getPrefixCls('back-top', customizePrefixCls);
const rootPrefixCls = getPrefixCls();
const [wrapSSR, hashId] = useStyle(prefixCls);
@ -128,14 +94,25 @@ const BackTop: React.FC<BackTopProps> = (props) => {
'children',
'visibilityHeight',
'target',
'visible',
]);
const defaultElement = (
<div className={`${prefixCls}-content`}>
<div className={`${prefixCls}-icon`}>
<VerticalAlignTopOutlined />
</div>
</div>
);
return wrapSSR(
<div {...divProps} className={classString} onClick={scrollToTop} ref={ref}>
<BackTopContent prefixCls={prefixCls} rootPrefixCls={rootPrefixCls} visible={visible}>
{props.children}
</BackTopContent>
<CSSMotion visible={visible} motionName={`${rootPrefixCls}-fade`}>
{({ className: motionClassName }) =>
cloneElement(props.children || defaultElement, ({ className: cloneCls }) => ({
className: classNames(motionClassName, cloneCls),
}))
}
</CSSMotion>
</div>,
);
};

View File

@ -1,6 +1,6 @@
import type { CSSObject } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import { resetComponent } from '../../style';
/** Component only token. Which will handle additional calculation of alias token */

View File

@ -1238,223 +1238,342 @@ exports[`renders ./components/badge/demo/link.tsx extend context correctly 1`] =
exports[`renders ./components/badge/demo/mix.tsx extend context correctly 1`] = `
<div
class="ant-space ant-space-horizontal ant-space-align-center"
style="flex-wrap:wrap;margin-bottom:-16px"
>
<div
class="ant-space-item"
style="margin-right:16px"
style="margin-right:16px;padding-bottom:16px"
>
<span
class="ant-badge"
<div
class="ant-space ant-space-horizontal ant-space-align-center"
style="flex-wrap:wrap;margin-bottom:-16px"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
<div
class="ant-space-item"
style="margin-right:16px;padding-bottom:16px"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-count ant-badge-status-success"
data-show="true"
title="5"
>
<span
class="ant-scroll-number-only"
style="transition:none"
class="ant-badge"
>
<span
class="ant-scroll-number-only-unit current"
class="ant-avatar ant-avatar-lg ant-avatar-square"
>
5
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-count ant-badge-status-success"
data-show="true"
title="5"
>
<span
class="ant-scroll-number-only"
style="transition:none"
>
<span
class="ant-scroll-number-only-unit current"
>
5
</span>
</span>
</sup>
</span>
</sup>
</span>
</div>
<div
class="ant-space-item"
style="margin-right:16px"
>
<span
class="ant-badge"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
</div>
<div
class="ant-space-item"
style="margin-right:16px;padding-bottom:16px"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-count ant-badge-status-warning"
data-show="true"
title="5"
>
<span
class="ant-scroll-number-only"
style="transition:none"
class="ant-badge"
>
<span
class="ant-scroll-number-only-unit current"
class="ant-avatar ant-avatar-lg ant-avatar-square"
>
5
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-count ant-badge-status-warning"
data-show="true"
title="5"
>
<span
class="ant-scroll-number-only"
style="transition:none"
>
<span
class="ant-scroll-number-only-unit current"
>
5
</span>
</span>
</sup>
</span>
</sup>
</span>
</div>
<div
class="ant-space-item"
style="margin-right:16px"
>
<span
class="ant-badge"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
</div>
<div
class="ant-space-item"
style="margin-right:16px;padding-bottom:16px"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-count ant-badge-status-blue"
data-show="true"
title="5"
>
<span
class="ant-scroll-number-only"
style="transition:none"
class="ant-badge"
>
<span
class="ant-scroll-number-only-unit current"
class="ant-avatar ant-avatar-lg ant-avatar-square"
>
5
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-count ant-badge-status-blue"
data-show="true"
title="5"
>
<span
class="ant-scroll-number-only"
style="transition:none"
>
<span
class="ant-scroll-number-only-unit current"
>
5
</span>
</span>
</sup>
</span>
</sup>
</span>
</div>
<div
class="ant-space-item"
style="margin-right:16px"
>
<span
class="ant-badge"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
</div>
<div
class="ant-space-item"
style="margin-right:16px;padding-bottom:16px"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-count"
data-show="true"
style="background:#fa541c"
title="5"
>
<span
class="ant-scroll-number-only"
style="transition:none"
class="ant-badge"
>
<span
class="ant-scroll-number-only-unit current"
class="ant-avatar ant-avatar-lg ant-avatar-square"
>
5
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-count"
data-show="true"
style="background:#fa541c"
title="5"
>
<span
class="ant-scroll-number-only"
style="transition:none"
>
<span
class="ant-scroll-number-only-unit current"
>
5
</span>
</span>
</sup>
</span>
</sup>
</span>
</div>
<div
class="ant-space-item"
style="margin-right:16px;padding-bottom:16px"
>
<span
class="ant-badge ant-badge-status"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-dot ant-badge-status-success"
data-show="true"
/>
</span>
</div>
<div
class="ant-space-item"
style="margin-right:16px;padding-bottom:16px"
>
<span
class="ant-badge ant-badge-status"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-dot ant-badge-status-warning"
data-show="true"
/>
</span>
</div>
<div
class="ant-space-item"
style="margin-right:16px;padding-bottom:16px"
>
<span
class="ant-badge ant-badge-status"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-dot ant-badge-status-blue"
data-show="true"
/>
</span>
</div>
<div
class="ant-space-item"
style="padding-bottom:16px"
>
<span
class="ant-badge ant-badge-status"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-dot"
data-show="true"
style="background:#fa541c"
/>
</span>
</div>
</div>
</div>
<div
class="ant-space-item"
style="margin-right:16px"
style="padding-bottom:16px"
>
<span
class="ant-badge ant-badge-status"
<div
class="ant-space ant-space-horizontal ant-space-align-center"
style="flex-wrap:wrap;margin-bottom:-16px"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
<div
class="ant-space-item"
style="margin-right:16px;padding-bottom:16px"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-dot ant-badge-status-success"
data-show="true"
/>
</span>
</div>
<div
class="ant-space-item"
style="margin-right:16px"
>
<span
class="ant-badge ant-badge-status"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
class="ant-badge ant-badge-not-a-wrapper"
>
<sup
class="ant-scroll-number ant-badge-count"
data-show="true"
title="0"
>
0
</sup>
</span>
</div>
<div
class="ant-space-item"
style="margin-right:16px;padding-bottom:16px"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-dot ant-badge-status-warning"
data-show="true"
/>
</span>
</div>
<div
class="ant-space-item"
style="margin-right:16px"
>
<span
class="ant-badge ant-badge-status"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
class="ant-badge ant-badge-not-a-wrapper"
>
<sup
class="ant-scroll-number ant-badge-count ant-badge-status-blue"
data-show="true"
title="0"
>
0
</sup>
</span>
</div>
<div
class="ant-space-item"
style="margin-right:16px;padding-bottom:16px"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-dot ant-badge-status-blue"
data-show="true"
/>
</span>
</div>
<div
class="ant-space-item"
>
<span
class="ant-badge ant-badge-status"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
class="ant-badge ant-badge-not-a-wrapper"
>
<sup
class="ant-scroll-number ant-badge-count"
data-show="true"
style="background:#f0f"
title="0"
>
0
</sup>
</span>
</div>
<div
class="ant-space-item"
style="margin-right:16px;padding-bottom:16px"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-dot"
data-show="true"
style="background:#fa541c"
/>
</span>
class="ant-badge"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-count"
data-show="true"
title="0"
>
0
</sup>
</span>
</div>
<div
class="ant-space-item"
style="padding-bottom:16px"
>
<span
class="ant-badge"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-count ant-badge-status-blue"
data-show="true"
title="0"
>
0
</sup>
</span>
</div>
</div>
</div>
</div>
`;
@ -1488,6 +1607,42 @@ exports[`renders ./components/badge/demo/no-wrapper.tsx extend context correctly
</span>
</button>
</div>
<div
class="ant-space-item"
style="margin-right:8px"
>
<span
class="ant-badge ant-badge-not-a-wrapper"
>
<sup
class="ant-scroll-number ant-badge-count ant-badge-multiple-words"
data-show="true"
style="background:#faad14"
title="11"
>
<span
class="ant-scroll-number-only"
style="transition:none"
>
<span
class="ant-scroll-number-only-unit current"
>
1
</span>
</span>
<span
class="ant-scroll-number-only"
style="transition:none"
>
<span
class="ant-scroll-number-only-unit current"
>
1
</span>
</span>
</sup>
</span>
</div>
<div
class="ant-space-item"
style="margin-right:8px"

View File

@ -1238,223 +1238,342 @@ exports[`renders ./components/badge/demo/link.tsx correctly 1`] = `
exports[`renders ./components/badge/demo/mix.tsx correctly 1`] = `
<div
class="ant-space ant-space-horizontal ant-space-align-center"
style="flex-wrap:wrap;margin-bottom:-16px"
>
<div
class="ant-space-item"
style="margin-right:16px"
style="margin-right:16px;padding-bottom:16px"
>
<span
class="ant-badge"
<div
class="ant-space ant-space-horizontal ant-space-align-center"
style="flex-wrap:wrap;margin-bottom:-16px"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
<div
class="ant-space-item"
style="margin-right:16px;padding-bottom:16px"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-count ant-badge-status-success"
data-show="true"
title="5"
>
<span
class="ant-scroll-number-only"
style="transition:none"
class="ant-badge"
>
<span
class="ant-scroll-number-only-unit current"
class="ant-avatar ant-avatar-lg ant-avatar-square"
>
5
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-count ant-badge-status-success"
data-show="true"
title="5"
>
<span
class="ant-scroll-number-only"
style="transition:none"
>
<span
class="ant-scroll-number-only-unit current"
>
5
</span>
</span>
</sup>
</span>
</sup>
</span>
</div>
<div
class="ant-space-item"
style="margin-right:16px"
>
<span
class="ant-badge"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
</div>
<div
class="ant-space-item"
style="margin-right:16px;padding-bottom:16px"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-count ant-badge-status-warning"
data-show="true"
title="5"
>
<span
class="ant-scroll-number-only"
style="transition:none"
class="ant-badge"
>
<span
class="ant-scroll-number-only-unit current"
class="ant-avatar ant-avatar-lg ant-avatar-square"
>
5
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-count ant-badge-status-warning"
data-show="true"
title="5"
>
<span
class="ant-scroll-number-only"
style="transition:none"
>
<span
class="ant-scroll-number-only-unit current"
>
5
</span>
</span>
</sup>
</span>
</sup>
</span>
</div>
<div
class="ant-space-item"
style="margin-right:16px"
>
<span
class="ant-badge"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
</div>
<div
class="ant-space-item"
style="margin-right:16px;padding-bottom:16px"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-count ant-badge-status-blue"
data-show="true"
title="5"
>
<span
class="ant-scroll-number-only"
style="transition:none"
class="ant-badge"
>
<span
class="ant-scroll-number-only-unit current"
class="ant-avatar ant-avatar-lg ant-avatar-square"
>
5
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-count ant-badge-status-blue"
data-show="true"
title="5"
>
<span
class="ant-scroll-number-only"
style="transition:none"
>
<span
class="ant-scroll-number-only-unit current"
>
5
</span>
</span>
</sup>
</span>
</sup>
</span>
</div>
<div
class="ant-space-item"
style="margin-right:16px"
>
<span
class="ant-badge"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
</div>
<div
class="ant-space-item"
style="margin-right:16px;padding-bottom:16px"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-count"
data-show="true"
style="background:#fa541c"
title="5"
>
<span
class="ant-scroll-number-only"
style="transition:none"
class="ant-badge"
>
<span
class="ant-scroll-number-only-unit current"
class="ant-avatar ant-avatar-lg ant-avatar-square"
>
5
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-count"
data-show="true"
style="background:#fa541c"
title="5"
>
<span
class="ant-scroll-number-only"
style="transition:none"
>
<span
class="ant-scroll-number-only-unit current"
>
5
</span>
</span>
</sup>
</span>
</sup>
</span>
</div>
<div
class="ant-space-item"
style="margin-right:16px;padding-bottom:16px"
>
<span
class="ant-badge ant-badge-status"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-dot ant-badge-status-success"
data-show="true"
/>
</span>
</div>
<div
class="ant-space-item"
style="margin-right:16px;padding-bottom:16px"
>
<span
class="ant-badge ant-badge-status"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-dot ant-badge-status-warning"
data-show="true"
/>
</span>
</div>
<div
class="ant-space-item"
style="margin-right:16px;padding-bottom:16px"
>
<span
class="ant-badge ant-badge-status"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-dot ant-badge-status-blue"
data-show="true"
/>
</span>
</div>
<div
class="ant-space-item"
style="padding-bottom:16px"
>
<span
class="ant-badge ant-badge-status"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-dot"
data-show="true"
style="background:#fa541c"
/>
</span>
</div>
</div>
</div>
<div
class="ant-space-item"
style="margin-right:16px"
style="padding-bottom:16px"
>
<span
class="ant-badge ant-badge-status"
<div
class="ant-space ant-space-horizontal ant-space-align-center"
style="flex-wrap:wrap;margin-bottom:-16px"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
<div
class="ant-space-item"
style="margin-right:16px;padding-bottom:16px"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-dot ant-badge-status-success"
data-show="true"
/>
</span>
</div>
<div
class="ant-space-item"
style="margin-right:16px"
>
<span
class="ant-badge ant-badge-status"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
class="ant-badge ant-badge-not-a-wrapper"
>
<sup
class="ant-scroll-number ant-badge-count"
data-show="true"
title="0"
>
0
</sup>
</span>
</div>
<div
class="ant-space-item"
style="margin-right:16px;padding-bottom:16px"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-dot ant-badge-status-warning"
data-show="true"
/>
</span>
</div>
<div
class="ant-space-item"
style="margin-right:16px"
>
<span
class="ant-badge ant-badge-status"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
class="ant-badge ant-badge-not-a-wrapper"
>
<sup
class="ant-scroll-number ant-badge-count ant-badge-status-blue"
data-show="true"
title="0"
>
0
</sup>
</span>
</div>
<div
class="ant-space-item"
style="margin-right:16px;padding-bottom:16px"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-dot ant-badge-status-blue"
data-show="true"
/>
</span>
</div>
<div
class="ant-space-item"
>
<span
class="ant-badge ant-badge-status"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
class="ant-badge ant-badge-not-a-wrapper"
>
<sup
class="ant-scroll-number ant-badge-count"
data-show="true"
style="background:#f0f"
title="0"
>
0
</sup>
</span>
</div>
<div
class="ant-space-item"
style="margin-right:16px;padding-bottom:16px"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-dot"
data-show="true"
style="background:#fa541c"
/>
</span>
class="ant-badge"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-count"
data-show="true"
title="0"
>
0
</sup>
</span>
</div>
<div
class="ant-space-item"
style="padding-bottom:16px"
>
<span
class="ant-badge"
>
<span
class="ant-avatar ant-avatar-lg ant-avatar-square"
>
<span
class="ant-avatar-string"
style="opacity:0"
/>
</span>
<sup
class="ant-scroll-number ant-badge-count ant-badge-status-blue"
data-show="true"
title="0"
>
0
</sup>
</span>
</div>
</div>
</div>
</div>
`;
@ -1488,6 +1607,42 @@ exports[`renders ./components/badge/demo/no-wrapper.tsx correctly 1`] = `
</span>
</button>
</div>
<div
class="ant-space-item"
style="margin-right:8px"
>
<span
class="ant-badge ant-badge-not-a-wrapper"
>
<sup
class="ant-scroll-number ant-badge-count ant-badge-multiple-words"
data-show="true"
style="background:#faad14"
title="11"
>
<span
class="ant-scroll-number-only"
style="transition:none"
>
<span
class="ant-scroll-number-only-unit current"
>
1
</span>
</span>
<span
class="ant-scroll-number-only"
style="transition:none"
>
<span
class="ant-scroll-number-only-unit current"
>
1
</span>
</span>
</sup>
</span>
</div>
<div
class="ant-space-item"
style="margin-right:8px"

View File

@ -214,6 +214,57 @@ exports[`Badge should be compatible with borderColor style 1`] = `
</span>
`;
exports[`Badge should display custom color and number is 0 1`] = `
<div>
<span
class="ant-badge ant-badge-not-a-wrapper"
>
<sup
class="ant-scroll-number ant-badge-count"
data-show="true"
style="background: rgb(255, 255, 0);"
title="0"
>
0
</sup>
</span>
<span
class="ant-badge ant-badge-not-a-wrapper"
>
<sup
class="ant-scroll-number ant-badge-count ant-badge-status-blue"
data-show="true"
title="0"
>
0
</sup>
</span>
<span
class="ant-badge ant-badge-not-a-wrapper"
>
<sup
class="ant-scroll-number ant-badge-count"
data-show="true"
title="0"
>
0
</sup>
</span>
<span
class="ant-badge"
>
<div />
<sup
class="ant-scroll-number ant-badge-count ant-badge-status-green"
data-show="true"
title="0"
>
0
</sup>
</span>
</div>
`;
exports[`Badge should render when count is changed 1`] = `
<span
class="ant-badge ant-badge-not-a-wrapper"

View File

@ -185,4 +185,22 @@ describe('Badge', () => {
expect(container.querySelectorAll('.ant-badge > .ant-badge-status-text')).toHaveLength(0);
});
// https://github.com/ant-design/ant-design/issues/38965
it('should display custom color and number is 0', () => {
const { container } = render(
<>
<Badge count={0} showZero color="#ff0" />
<Badge count={0} showZero color="blue" />
<Badge count={0} showZero />
<Badge count={0} showZero color='green'>
<div />
</Badge>
</>,
);
expect(container).toMatchSnapshot();
expect(container.querySelectorAll('.ant-badge-count')).toHaveLength(4);
expect(container.querySelectorAll('[title="0"]')).toHaveLength(4);
});
});

View File

@ -2,31 +2,45 @@ import React from 'react';
import { Avatar, Badge, Space } from 'antd';
const App: React.FC = () => (
<Space size="middle">
<Badge count={5} status="success">
<Avatar shape="square" size="large" />
</Badge>
<Badge count={5} status="warning">
<Avatar shape="square" size="large" />
</Badge>
<Badge count={5} color="blue">
<Avatar shape="square" size="large" />
</Badge>
<Badge count={5} color="#fa541c">
<Avatar shape="square" size="large" />
</Badge>
<Badge dot status="success">
<Avatar shape="square" size="large" />
</Badge>
<Badge dot status="warning">
<Avatar shape="square" size="large" />
</Badge>
<Badge dot color="blue">
<Avatar shape="square" size="large" />
</Badge>
<Badge dot color="#fa541c">
<Avatar shape="square" size="large" />
</Badge>
<Space size="middle" wrap>
<Space size="middle" wrap>
<Badge count={5} status="success">
<Avatar shape="square" size="large" />
</Badge>
<Badge count={5} status="warning">
<Avatar shape="square" size="large" />
</Badge>
<Badge count={5} color="blue">
<Avatar shape="square" size="large" />
</Badge>
<Badge count={5} color="#fa541c">
<Avatar shape="square" size="large" />
</Badge>
<Badge dot status="success">
<Avatar shape="square" size="large" />
</Badge>
<Badge dot status="warning">
<Avatar shape="square" size="large" />
</Badge>
<Badge dot color="blue">
<Avatar shape="square" size="large" />
</Badge>
<Badge dot color="#fa541c">
<Avatar shape="square" size="large" />
</Badge>
</Space>
<Space size="middle" wrap>
<Badge count={0} showZero />
<Badge count={0} showZero color='blue' />
<Badge count={0} showZero color='#f0f' />
<Badge count={0} showZero>
<Avatar shape="square" size="large" />
</Badge>
<Badge count={0} showZero color='blue'>
<Avatar shape="square" size="large" />
</Badge>
</Space>
</Space>
);

View File

@ -8,6 +8,7 @@ const App: React.FC = () => {
return (
<Space>
<Switch checked={show} onChange={() => setShow(!show)} />
<Badge count={show ? 11 : 0} showZero color='#faad14' />
<Badge count={show ? 25 : 0} />
<Badge count={show ? <ClockCircleOutlined style={{ color: '#f5222d' }} /> : 0} />
<Badge

View File

@ -69,7 +69,7 @@ const Badge: CompoundedComponent = ({
const isZero = numberedDisplayCount === '0' || numberedDisplayCount === 0;
const ignoreCount = count === null || isZero;
const ignoreCount = count === null || (isZero && !showZero);
const hasStatus =
((status !== null && status !== undefined) || (color !== null && color !== undefined)) &&

View File

@ -1,7 +1,7 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { Keyframes } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle, PresetColorType } from '../../theme';
import { genComponentStyleHook, mergeToken, PresetColors } from '../../theme';
import type { FullToken, GenerateStyle, PresetColorType } from '../../theme/internal';
import { genComponentStyleHook, mergeToken, PresetColors } from '../../theme/internal';
import { resetComponent } from '../../style';
interface BadgeToken extends FullToken<'Badge'> {
@ -276,6 +276,15 @@ const genSharedBadgeStyle: GenerateStyle<BadgeToken> = (token: BadgeToken): CSSO
},
[`${numberPrefixCls}-symbol`]: { verticalAlign: 'top' },
},
// ====================== RTL =======================
'&-rtl': {
direction: 'rtl',
[`${componentCls}-count, ${componentCls}-dot, ${numberPrefixCls}-custom-component`]: {
insetInlineEnd: 'auto',
},
},
},
[`${ribbonWrapperPrefixCls}`]: { position: 'relative' },
[`${ribbonPrefixCls}`]: {
@ -307,7 +316,8 @@ const genSharedBadgeStyle: GenerateStyle<BadgeToken> = (token: BadgeToken): CSSO
borderEndEndRadius: 0,
[`${ribbonPrefixCls}-corner`]: {
insetInlineEnd: 0,
borderColor: 'currentcolor transparent transparent currentcolor',
borderInlineEndColor: 'transparent',
borderBlockEndColor: 'transparent',
},
},
[`&${ribbonPrefixCls}-placement-start`]: {
@ -315,9 +325,15 @@ const genSharedBadgeStyle: GenerateStyle<BadgeToken> = (token: BadgeToken): CSSO
borderEndStartRadius: 0,
[`${ribbonPrefixCls}-corner`]: {
insetInlineStart: 0,
borderColor: 'currentcolor currentcolor transparent transparent',
borderBlockEndColor: 'transparent',
borderInlineStartColor: 'transparent',
},
},
// ====================== RTL =======================
'&-rtl': {
direction: 'rtl',
},
},
};
};

View File

@ -1,6 +1,6 @@
import type { CSSObject } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import { genFocusStyle, resetComponent } from '../../style';
interface BreadcrumbToken extends FullToken<'Breadcrumb'> {

View File

@ -2,7 +2,7 @@ import classNames from 'classnames';
import * as React from 'react';
import { ConfigContext } from '../config-provider';
import type { SizeType } from '../config-provider/SizeContext';
import { useToken } from '../theme';
import { useToken } from '../theme/internal';
import warning from '../_util/warning';
export interface ButtonGroupProps {

View File

@ -1,5 +1,5 @@
import type { ButtonToken } from '.';
import type { GenerateStyle } from '../../theme';
import type { GenerateStyle } from '../../theme/internal';
const genButtonBorderStyle = (buttonTypeCls: string, borderColor: string) => ({
// Border

View File

@ -1,6 +1,6 @@
import type { CSSInterpolation, CSSObject } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import genGroupStyle from './group';
import { genFocusStyle } from '../../style';
import { genCompactItemStyle } from '../../style/compact-item';
@ -46,10 +46,6 @@ const genSharedButtonStyle: GenerateStyle<ButtonToken, CSSObject> = (token): CSS
marginInlineStart: token.marginXS,
},
[`&${componentCls}-block`]: {
width: '100%',
},
'&:not(:disabled)': {
...genFocusStyle(token),
},
@ -214,7 +210,7 @@ const genDefaultButtonStyle: GenerateStyle<ButtonToken, CSSObject> = (token) =>
...genHoverActiveButtonStyle(
{
color: token.colorErrorHover,
borderColor: token.colorErrorBorder,
borderColor: token.colorErrorBorderHover,
},
{
color: token.colorErrorActive,
@ -463,6 +459,17 @@ const genSizeLargeButtonStyle: GenerateStyle<ButtonToken> = (token) => {
return genSizeButtonStyle(largeToken, `${token.componentCls}-lg`);
};
const genBlockButtonStyle: GenerateStyle<ButtonToken> = (token) => {
const { componentCls } = token;
return {
[componentCls]: {
[`&${componentCls}-block`]: {
width: '100%',
},
},
};
};
// ============================== Export ==============================
export default genComponentStyleHook('Button', (token) => {
const { controlTmpOutline, paddingContentHorizontal } = token;
@ -481,6 +488,9 @@ export default genComponentStyleHook('Button', (token) => {
genSizeBaseButtonStyle(buttonToken),
genSizeLargeButtonStyle(buttonToken),
// Block
genBlockButtonStyle(buttonToken),
// Group (type, ghost, danger, disabled, loading)
genTypeButtonStyle(buttonToken),

View File

@ -23,7 +23,7 @@ cover: https://gw.alipayobjects.com/zos/antfincdn/dPQmLq08DI/Calendar.svg
## API
**注意**Calendar 部分 locale 是从 value 中读取,所以请先正确设置 dayjs 的 locale。
**注意**Calendar 部分 locale 是从 value 中读取,所以请先正确设置 dayjs 的 locale。
```jsx
// 默认语言为 en-US所以如果需要使用其他语言推荐在入口文件全局设置 locale

View File

@ -4,8 +4,8 @@ import type { PickerPanelToken } from '../../date-picker/style';
import { genPanelStyle, initPickerPanelToken } from '../../date-picker/style';
import type { InputToken } from '../../input/style';
import { initInputToken } from '../../input/style';
import type { FullToken } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import type { FullToken } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
export interface ComponentToken {
yearControlWidth: number;

View File

@ -1,7 +1,7 @@
import type { CSSObject } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import { clearFix, resetComponent, textEllipsis } from '../../style';
export interface ComponentToken {}
@ -267,6 +267,7 @@ const genCardStyle: GenerateStyle<CardToken> = (token): CSSObject => {
[`${componentCls}-body`]: {
padding: cardPaddingBase,
borderRadius: ` 0 0 ${token.borderRadiusLG}px ${token.borderRadiusLG}px`,
...clearFix(),
},

View File

@ -1,5 +1,5 @@
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import { resetComponent } from '../../style';
export interface ComponentToken {

View File

@ -1,6 +1,6 @@
import { getStyle as getCheckboxStyle } from '../../checkbox/style';
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook } from '../../theme/internal';
import { textEllipsis } from '../../style';
import { genCompactItemStyle } from '../../style/compact-item';

View File

@ -1,6 +1,6 @@
import { Keyframes } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import { genFocusOutline, resetComponent } from '../../style';
export interface ComponentToken {}

View File

@ -1,6 +1,6 @@
import { genCollapseMotion } from '../../style/motion';
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import { resetComponent, resetIcon } from '../../style';
export interface ComponentToken {}

View File

@ -12,7 +12,7 @@ export interface DisabledContextProps {
export const DisabledContextProvider: React.FC<DisabledContextProps> = ({ children, disabled }) => {
const originDisabled = React.useContext(DisabledContext);
return (
<DisabledContext.Provider value={disabled || originDisabled}>
<DisabledContext.Provider value={disabled ?? originDisabled}>
{children}
</DisabledContext.Provider>
);

View File

@ -15518,12 +15518,11 @@ exports[`ConfigProvider components Form configProvider 1`] = `
style="display: flex; flex-wrap: nowrap;"
>
<div
class="config-form-item-explain config-show-help-appear config-show-help-appear-start config-show-help config-form-item-explain-connected"
class="config-form-item-explain config-form-show-help-appear config-form-show-help-appear-start config-form-show-help config-form-item-explain-connected"
role="alert"
style="height: 0px; opacity: 0;"
>
<div
class="config-show-help-item-appear config-show-help-item-appear-start config-show-help-item config-form-item-explain-error"
class="config-form-show-help-item-appear config-form-show-help-item-appear-start config-form-show-help-item config-form-item-explain-error"
style="height: 0px; opacity: 0;"
>
Bamboo is Light
@ -15574,12 +15573,11 @@ exports[`ConfigProvider components Form configProvider componentDisabled 1`] = `
style="display: flex; flex-wrap: nowrap;"
>
<div
class="config-form-item-explain config-show-help-appear config-show-help-appear-start config-show-help config-form-item-explain-connected"
class="config-form-item-explain config-form-show-help-appear config-form-show-help-appear-start config-form-show-help config-form-item-explain-connected"
role="alert"
style="height: 0px; opacity: 0;"
>
<div
class="config-show-help-item-appear config-show-help-item-appear-start config-show-help-item config-form-item-explain-error"
class="config-form-show-help-item-appear config-form-show-help-item-appear-start config-form-show-help-item config-form-item-explain-error"
style="height: 0px; opacity: 0;"
>
Bamboo is Light
@ -15629,12 +15627,11 @@ exports[`ConfigProvider components Form configProvider componentSize large 1`] =
style="display: flex; flex-wrap: nowrap;"
>
<div
class="config-form-item-explain config-show-help-appear config-show-help-appear-start config-show-help config-form-item-explain-connected"
class="config-form-item-explain config-form-show-help-appear config-form-show-help-appear-start config-form-show-help config-form-item-explain-connected"
role="alert"
style="height: 0px; opacity: 0;"
>
<div
class="config-show-help-item-appear config-show-help-item-appear-start config-show-help-item config-form-item-explain-error"
class="config-form-show-help-item-appear config-form-show-help-item-appear-start config-form-show-help-item config-form-item-explain-error"
style="height: 0px; opacity: 0;"
>
Bamboo is Light
@ -15684,12 +15681,11 @@ exports[`ConfigProvider components Form configProvider componentSize middle 1`]
style="display: flex; flex-wrap: nowrap;"
>
<div
class="config-form-item-explain config-show-help-appear config-show-help-appear-start config-show-help config-form-item-explain-connected"
class="config-form-item-explain config-form-show-help-appear config-form-show-help-appear-start config-form-show-help config-form-item-explain-connected"
role="alert"
style="height: 0px; opacity: 0;"
>
<div
class="config-show-help-item-appear config-show-help-item-appear-start config-show-help-item config-form-item-explain-error"
class="config-form-show-help-item-appear config-form-show-help-item-appear-start config-form-show-help-item config-form-item-explain-error"
style="height: 0px; opacity: 0;"
>
Bamboo is Light
@ -15739,12 +15735,11 @@ exports[`ConfigProvider components Form configProvider virtual and dropdownMatch
style="display: flex; flex-wrap: nowrap;"
>
<div
class="ant-form-item-explain ant-show-help-appear ant-show-help-appear-start ant-show-help ant-form-item-explain-connected"
class="ant-form-item-explain ant-form-show-help-appear ant-form-show-help-appear-start ant-form-show-help ant-form-item-explain-connected"
role="alert"
style="height: 0px; opacity: 0;"
>
<div
class="ant-show-help-item-appear ant-show-help-item-appear-start ant-show-help-item ant-form-item-explain-error"
class="ant-form-show-help-item-appear ant-form-show-help-item-appear-start ant-form-show-help-item ant-form-item-explain-error"
style="height: 0px; opacity: 0;"
>
Bamboo is Light
@ -15794,12 +15789,11 @@ exports[`ConfigProvider components Form normal 1`] = `
style="display: flex; flex-wrap: nowrap;"
>
<div
class="ant-form-item-explain ant-show-help-appear ant-show-help-appear-start ant-show-help ant-form-item-explain-connected"
class="ant-form-item-explain ant-form-show-help-appear ant-form-show-help-appear-start ant-form-show-help ant-form-item-explain-connected"
role="alert"
style="height: 0px; opacity: 0;"
>
<div
class="ant-show-help-item-appear ant-show-help-item-appear-start ant-show-help-item ant-form-item-explain-error"
class="ant-form-show-help-item-appear ant-form-show-help-item-appear-start ant-form-show-help-item ant-form-item-explain-error"
style="height: 0px; opacity: 0;"
>
Bamboo is Light
@ -15849,12 +15843,11 @@ exports[`ConfigProvider components Form prefixCls 1`] = `
style="display: flex; flex-wrap: nowrap;"
>
<div
class="prefix-Form-item-explain ant-show-help-appear ant-show-help-appear-start ant-show-help prefix-Form-item-explain-connected"
class="prefix-Form-item-explain prefix-Form-show-help-appear prefix-Form-show-help-appear-start prefix-Form-show-help prefix-Form-item-explain-connected"
role="alert"
style="height: 0px; opacity: 0;"
>
<div
class="ant-show-help-item-appear ant-show-help-item-appear-start ant-show-help-item prefix-Form-item-explain-error"
class="prefix-Form-show-help-item-appear prefix-Form-show-help-item-appear-start prefix-Form-show-help-item prefix-Form-item-explain-error"
style="height: 0px; opacity: 0;"
>
Bamboo is Light

View File

@ -144,7 +144,7 @@ describe('ConfigProvider', () => {
testPair('Avatar', (props) => <Avatar {...props} />);
// BackTop
testPair('BackTop', (props) => <BackTop visible {...props} />);
testPair('BackTop', (props) => <BackTop visibilityHeight={0} {...props} />);
// Badge
testPair('Badge', (props) => {

View File

@ -4,6 +4,7 @@ import ConfigProvider from '..';
import { render } from '../../../tests/utils';
import type { FormInstance } from '../../form';
import Form from '../../form';
import Input from '../../input';
import zhCN from '../../locale/zh_CN';
describe('ConfigProvider.Form', () => {
@ -125,4 +126,24 @@ describe('ConfigProvider.Form', () => {
expect(container.querySelector('.ant-form-item-no-colon')).toBeFalsy();
});
});
describe('form disabled', () => {
it('set Input enabled', () => {
const { container } = render(
<Form disabled>
<ConfigProvider componentDisabled={false}>
<Form.Item name="input1" label="启用">
<Input />
</Form.Item>
</ConfigProvider>
<Form.Item name="input" label="禁用">
<Input />
</Form.Item>
</Form>,
);
expect(container.querySelector('#input1[disabled]')).toBeFalsy();
expect(container.querySelector('#input[disabled]')).toBeTruthy();
});
});
});

View File

@ -4,8 +4,8 @@ import React from 'react';
import ConfigProvider from '..';
import { InputNumber } from '../..';
import { render } from '../../../tests/utils';
import { useToken } from '../../theme';
import theme from '../../theme/export';
import { useToken } from '../../theme/internal';
import theme from '../../theme';
import { resetWarned } from '../../_util/warning';
const { defaultAlgorithm, darkAlgorithm, compactAlgorithm } = theme;

View File

@ -2,7 +2,7 @@ import useMemo from 'rc-util/lib/hooks/useMemo';
import shallowEqual from 'shallowequal';
import type { OverrideToken } from '../../theme/interface';
import type { ThemeConfig } from '../context';
import { defaultConfig } from '../../theme';
import { defaultConfig } from '../../theme/internal';
export default function useTheme(
theme?: ThemeConfig,

View File

@ -61,7 +61,7 @@ Some components use dynamic style to support wave effect. You can config `csp` p
| prefixCls | Set prefix className | string | `ant` | |
| renderEmpty | Set empty content of components. Ref [Empty](/components/empty/) | function(componentName: string): ReactNode | - | |
| space | Set Space `size`, ref [Space](/components/space) | { size: `small` \| `middle` \| `large` \| `number` } | - | 4.1.0 |
| theme | Set theme, ref [Customize Theme](/docs/react/customize-theme-v5) | - | - | 5.0.0 |
| theme | Set theme, ref [Customize Theme](/docs/react/customize-theme) | - | - | 5.0.0 |
| virtual | Disable virtual scroll when set to `false` | boolean | - | 4.3.0 |
### ConfigProvider.config() `4.13.0+`

View File

@ -10,7 +10,7 @@ import type { Locale } from '../locale-provider';
import LocaleProvider, { ANT_MARK } from '../locale-provider';
import LocaleReceiver from '../locale-provider/LocaleReceiver';
import defaultLocale from '../locale/en_US';
import { DesignTokenContext } from '../theme';
import { DesignTokenContext } from '../theme/internal';
import defaultSeedToken from '../theme/themes/seed';
import type { ConfigConsumerProps, CSPConfig, DirectionType, Theme, ThemeConfig } from './context';
import { ConfigConsumer, ConfigContext, defaultIconPrefixCls } from './context';

View File

@ -62,7 +62,7 @@ export default () => (
| prefixCls | 设置统一样式前缀 | string | `ant` | |
| renderEmpty | 自定义组件空状态。参考 [空状态](/components/empty/) | function(componentName: string): ReactNode | - | |
| space | 设置 Space 的 `size`,参考 [Space](/components/space) | { size: `small` \| `middle` \| `large` \| `number` } | - | 4.1.0 |
| theme | 设置主题,参考 [定制主题](/docs/react/customize-theme-v5-cn) | - | - | 5.0.0 |
| theme | 设置主题,参考 [定制主题](/docs/react/customize-theme-cn) | - | - | 5.0.0 |
| virtual | 设置 `false` 时关闭虚拟滚动 | boolean | - | 4.3.0 |
### ConfigProvider.config() `4.13.0+`

View File

@ -1,6 +1,6 @@
import { useStyleRegister } from '@ant-design/cssinjs';
import { resetIcon } from '../../style';
import { useToken } from '../../theme';
import { useToken } from '../../theme/internal';
const useStyle = (iconPrefixCls: string) => {
const [theme, token] = useToken();

View File

@ -221,14 +221,15 @@ See FAQ [Date-related-components-locale-is-not-working?](/docs/react/faq#Date-re
Please use correct [language](/docs/react/i18n) ([#5605](https://github.com/ant-design/ant-design/issues/5605)), or update dayjs `locale` config:
- Example: <https://codesandbox.io/s/moment-day-of-week-6dby5>
- Alternate example: <https://stackblitz.com/edit/react-9aegkj>
- Example: <https://codesandbox.io/s/dayjs-day-of-week-x9tuj2?file=/demo.tsx>
```js
dayjs.locale('en', {
week: {
dow: 1,
},
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
import 'dayjs/plugin/updateLocale';
dayjs.updateLocale('zh-cn', {
weekStart: 0,
});
```

View File

@ -216,14 +216,15 @@ import locale from 'antd/locale/zh_CN';
### 如何修改周的起始日?
请使用正确的[语言包](/docs/react/i18n)[#5605](https://github.com/ant-design/ant-design/issues/5605)),或者修改 dayjs 的 `locale` 配置:<https://codesandbox.io/s/moment-day-of-week-6dby5>
请使用正确的[语言包](/docs/react/i18n-cn)[#5605](https://github.com/ant-design/ant-design/issues/5605)),或者修改 dayjs 的 `locale` 配置:<https://codesandbox.io/s/dayjs-day-of-week-x9tuj2?file=/demo.tsx>
```js
dayjs.locale('en', {
// 注意请修改你正在使用的 locale 语言,比如 zh-cn
week: {
dow: 1,
},
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
import 'dayjs/plugin/updateLocale';
dayjs.updateLocale('zh-cn', {
weekStart: 0,
});
```

View File

@ -15,8 +15,8 @@ import {
slideUpIn,
slideUpOut,
} from '../../style/motion';
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import type { GlobalToken } from '../../theme/interface';
import type { TokenWithCommonCls } from '../../theme/util/genComponentStyleHook';
import { resetComponent, roundedArrow, textEllipsis } from '../../style';

View File

@ -1,6 +1,6 @@
import type { CSSObject } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import { resetComponent, textEllipsis } from '../../style';
interface DescriptionsToken extends FullToken<'Descriptions'> {

View File

@ -1,6 +1,6 @@
import type { CSSObject } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import { resetComponent } from '../../style';
/** Component only token. Which will handle additional calculation of alias token */

View File

@ -13,6 +13,7 @@ import type { DrawerPanelProps } from './DrawerPanel';
// CSSINJS
import useStyle from './style';
import { NoCompactStyle } from '../space/Compact';
const SizeTypes = tuple('default', 'large');
type sizeType = typeof SizeTypes[number];
@ -120,25 +121,27 @@ function Drawer(props: DrawerProps) {
// =========================== Render ===========================
return wrapSSR(
<NoFormStyle status override>
<RcDrawer
prefixCls={prefixCls}
onClose={onClose}
maskMotion={maskMotion}
motion={panelMotion}
{...rest}
open={open ?? visible}
mask={mask}
push={push}
width={mergedWidth}
height={mergedHeight}
rootClassName={drawerClassName}
getContainer={getContainer}
afterOpenChange={afterOpenChange ?? afterVisibleChange}
>
<DrawerPanel prefixCls={prefixCls} {...rest} onClose={onClose} />
</RcDrawer>
</NoFormStyle>,
<NoCompactStyle>
<NoFormStyle status override>
<RcDrawer
prefixCls={prefixCls}
onClose={onClose}
maskMotion={maskMotion}
motion={panelMotion}
{...rest}
open={open ?? visible}
mask={mask}
push={push}
width={mergedWidth}
height={mergedHeight}
rootClassName={drawerClassName}
getContainer={getContainer}
afterOpenChange={afterOpenChange ?? afterVisibleChange}
>
<DrawerPanel prefixCls={prefixCls} {...rest} onClose={onClose} />
</RcDrawer>
</NoFormStyle>
</NoCompactStyle>,
);
}

View File

@ -1,5 +1,5 @@
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import genMotionStyle from './motion';
export interface ComponentToken {

View File

@ -1,5 +1,5 @@
import type { DrawerToken } from '.';
import type { GenerateStyle } from '../../theme';
import type { GenerateStyle } from '../../theme/internal';
const genMotionStyle: GenerateStyle<DrawerToken> = (token: DrawerToken) => {
const { componentCls, motionDurationSlow } = token;

View File

@ -145,4 +145,10 @@ describe('DropdownButton', () => {
expect(errSpy).not.toHaveBeenCalled();
errSpy.mockRestore();
});
it('should support dropdownRender', () => {
const dropdownRender = jest.fn((menu) => <div>Custom Menu {menu}</div>);
render(<DropdownButton open dropdownRender={dropdownRender} />);
expect(dropdownRender).toHaveBeenCalled();
});
});

View File

@ -69,6 +69,7 @@ const DropdownButton: DropdownButtonInterface = (props) => {
overlayClassName,
overlayStyle,
destroyPopupOnHide,
dropdownRender,
...restProps
} = props;
@ -90,6 +91,7 @@ const DropdownButton: DropdownButtonInterface = (props) => {
overlayClassName,
overlayStyle,
destroyPopupOnHide,
dropdownRender,
};
const { compactSize, compactItemClassnames } = useCompactItemContext(prefixCls, direction);

View File

@ -13,6 +13,7 @@ import getPlacements from '../_util/placements';
import { cloneElement } from '../_util/reactNode';
import { tuple } from '../_util/type';
import warning from '../_util/warning';
import { NoCompactStyle } from '../space/Compact';
import DropdownButton from './dropdown-button';
import useStyle from './style';
@ -264,7 +265,7 @@ const Dropdown: DropdownInterface = (props) => {
);
}}
>
{overlayNode}
<NoCompactStyle>{overlayNode}</NoCompactStyle>
</OverrideProvider>
);
};

View File

@ -1,5 +1,5 @@
import type { DropdownToken } from '.';
import type { GenerateStyle } from '../../theme';
import type { GenerateStyle } from '../../theme/internal';
const genButtonStyle: GenerateStyle<DropdownToken> = (token) => {
const { componentCls, antCls, paddingXS, opacityLoading } = token;

View File

@ -7,8 +7,8 @@ import {
slideUpIn,
slideUpOut,
} from '../../style/motion';
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import genButtonStyle from './button';
import genStatusStyle from './status';
import { genFocusStyle, resetComponent, roundedArrow } from '../../style';

View File

@ -1,5 +1,5 @@
import type { DropdownToken } from '.';
import type { GenerateStyle } from '../../theme';
import type { GenerateStyle } from '../../theme/internal';
const genStatusStyle: GenerateStyle<DropdownToken> = (token) => {
const { componentCls, menuCls, colorError, colorTextLightSolid } = token;

View File

@ -1,7 +1,7 @@
import * as React from 'react';
import { useMemo } from 'react';
import { TinyColor } from '@ctrl/tinycolor';
import { useToken } from '../theme';
import { useToken } from '../theme/internal';
const Simple = () => {
const [, token] = useToken();

View File

@ -1,6 +1,6 @@
import type { CSSObject } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
/** Component only token. Which will handle additional calculation of alias token */
export interface ComponentToken {}

View File

@ -2,8 +2,7 @@ import VerticalAlignTopOutlined from '@ant-design/icons/VerticalAlignTopOutlined
import classNames from 'classnames';
import CSSMotion from 'rc-motion';
import addEventListener from 'rc-util/lib/Dom/addEventListener';
import useMergedState from 'rc-util/lib/hooks/useMergedState';
import React, { memo, useContext, useEffect, useRef } from 'react';
import React, { memo, useContext, useEffect, useRef, useState } from 'react';
import FloatButton, { floatButtonPrefixCls } from './FloatButton';
import type { ConfigConsumerProps } from '../config-provider';
import { ConfigContext } from '../config-provider';
@ -11,7 +10,7 @@ import getScroll from '../_util/getScroll';
import scrollTo from '../_util/scrollTo';
import throttleByAnimationFrame from '../_util/throttleByAnimationFrame';
import FloatButtonGroupContext from './context';
import type { BackTopProps, FloatButtonShape } from './interface';
import type { BackTopProps, FloatButtonProps, FloatButtonShape } from './interface';
import useStyle from './style';
const BackTop: React.FC<BackTopProps> = (props) => {
@ -28,46 +27,39 @@ const BackTop: React.FC<BackTopProps> = (props) => {
...restProps
} = props;
const [visible, setVisible] = useMergedState(false, { value: props.visible });
const [visible, setVisible] = useState<boolean>(visibilityHeight === 0);
const ref = useRef<HTMLAnchorElement | HTMLButtonElement>(null);
const scrollEvent = useRef<any>(null);
const scrollEvent = useRef<ReturnType<typeof addEventListener> | null>(null);
const getDefaultTarget = (): HTMLElement | Document | Window =>
ref.current && ref.current.ownerDocument ? ref.current.ownerDocument : window;
const handleScroll = throttleByAnimationFrame(
(e: React.UIEvent<HTMLElement> | { target: any }) => {
(e: React.UIEvent<HTMLElement, UIEvent> | { target: any }) => {
const scrollTop = getScroll(e.target, true);
setVisible(scrollTop > visibilityHeight!);
setVisible(scrollTop >= visibilityHeight);
},
);
const bindScrollEvent = () => {
const getTarget = target || getDefaultTarget;
const container = getTarget();
scrollEvent.current = addEventListener(container, 'scroll', (e: React.UIEvent<HTMLElement>) => {
handleScroll(e);
});
scrollEvent.current = addEventListener(container, 'scroll', handleScroll);
handleScroll({ target: container });
};
useEffect(() => {
bindScrollEvent();
return () => {
if (scrollEvent.current) {
scrollEvent.current.remove();
}
handleScroll.cancel();
scrollEvent.current?.remove();
};
}, [target]);
const scrollToTop: React.MouseEventHandler<HTMLDivElement> = (e) => {
scrollTo(0, { getContainer: target || getDefaultTarget, duration });
if (typeof onClick === 'function') {
onClick(e);
}
onClick?.(e);
};
const { getPrefixCls } = useContext<ConfigConsumerProps>(ConfigContext);
@ -80,7 +72,7 @@ const BackTop: React.FC<BackTopProps> = (props) => {
const mergeShape = groupShape || shape;
const contentProps = { prefixCls, icon, type, shape: mergeShape, ...restProps };
const contentProps: FloatButtonProps = { prefixCls, icon, type, shape: mergeShape, ...restProps };
return wrapSSR(
<CSSMotion visible={visible} motionName={`${rootPrefixCls}-fade`}>

View File

@ -7,7 +7,7 @@ import BackTop from './BackTop';
import type { FloatButtonProps, FloatButtonGroupProps } from './interface';
import { ConfigContext } from '../config-provider';
export interface PureFloatButtonProps extends FloatButtonProps {
export interface PureFloatButtonProps extends Omit<FloatButtonProps, 'target'> {
backTop?: boolean;
}
@ -18,11 +18,10 @@ export interface PurePanelProps
items?: PureFloatButtonProps[];
}
function PureFloatButton({ backTop, ...props }: PureFloatButtonProps) {
return backTop ? <BackTop {...props} visible target={undefined} /> : <FloatButton {...props} />;
}
const PureFloatButton: React.FC<PureFloatButtonProps> = ({ backTop, ...props }) =>
backTop ? <BackTop {...props} visibilityHeight={0} /> : <FloatButton {...props} />;
export default function PurePanel({ className, items, ...props }: PurePanelProps) {
function PurePanel({ className, items, ...props }: PurePanelProps) {
const { prefixCls: customizePrefixCls } = props;
const { getPrefixCls } = React.useContext(ConfigContext);
@ -41,3 +40,5 @@ export default function PurePanel({ className, items, ...props }: PurePanelProps
return <PureFloatButton className={classNames(className, pureCls)} {...props} />;
}
export default React.memo(PurePanel);

View File

@ -2,52 +2,53 @@ import React from 'react';
import FloatButton from '..';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
import { fireEvent, render, sleep } from '../../../tests/utils';
import { fireEvent, render, waitFakeTimer } from '../../../tests/utils';
const { BackTop } = FloatButton;
describe('BackTop', () => {
beforeEach(() => {
jest.useFakeTimers();
});
afterEach(() => {
jest.useRealTimers();
});
mountTest(BackTop);
rtlTest(BackTop);
it('should scroll to top after click it', async () => {
const { container } = render(<BackTop visible visibilityHeight={-1} />);
const { container } = render(<BackTop />);
const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((_, y) => {
window.scrollY = y;
window.pageYOffset = y;
document.documentElement.scrollTop = y;
});
window.scrollTo(0, 400);
await waitFakeTimer();
expect(document.documentElement.scrollTop).toBe(400);
fireEvent.click(container.querySelector('.ant-float-btn')!);
await sleep(500);
fireEvent.click(container.querySelector<HTMLButtonElement>('.ant-float-btn')!);
await waitFakeTimer();
expect(document.documentElement.scrollTop).toBe(0);
scrollToSpy.mockRestore();
});
it('support onClick', () => {
const onClick = jest.fn();
const { container } = render(<BackTop visible visibilityHeight={-1} onClick={onClick} />);
const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((_, y) => {
window.scrollY = y;
window.pageYOffset = y;
});
document.dispatchEvent(new Event('scroll'));
window.scrollTo(0, 400);
fireEvent.click(container.querySelector('.ant-float-btn')!);
const { container } = render(<BackTop onClick={onClick} visibilityHeight={0} />);
fireEvent.click(container.querySelector<HTMLButtonElement>('.ant-float-btn')!);
expect(onClick).toHaveBeenCalled();
scrollToSpy.mockRestore();
});
it('invalid target', () => {
it('support invalid target', () => {
const onClick = jest.fn();
const { container } = render(<BackTop onClick={onClick} visible target={undefined} />);
fireEvent.click(container.querySelector('.ant-float-btn')!);
const { container } = render(
<BackTop onClick={onClick} visibilityHeight={0} target={undefined} />,
);
fireEvent.click(container.querySelector<HTMLButtonElement>('.ant-float-btn')!);
expect(onClick).toHaveBeenCalled();
});
it('pass style to float button', () => {
const { container } = render(<BackTop style={{ color: 'red' }} visible target={undefined} />);
const btn = container.querySelector('.ant-float-btn')!;
expect(btn).toHaveAttribute('style', 'color: red;');
const { container } = render(<BackTop style={{ color: 'red' }} visibilityHeight={0} />);
expect(container.querySelector<HTMLButtonElement>('.ant-float-btn')?.style.color).toBe('red');
});
});

View File

@ -3,8 +3,8 @@ import FloatButtonGroup from './FloatButtonGroup';
import BackTop from './BackTop';
import PurePanel from './PurePanel';
FloatButton.Group = FloatButtonGroup;
FloatButton.BackTop = BackTop;
FloatButton.Group = FloatButtonGroup;
FloatButton._InternalPanelDoNotUseOrYouWillBeFired = PurePanel;
export default FloatButton;

View File

@ -53,7 +53,6 @@ export interface BackTopProps extends Omit<FloatButtonProps, 'target'> {
className?: string;
style?: React.CSSProperties;
duration?: number;
visible?: boolean; // Only for test. Don't use it.
}
export type CompoundedComponent = React.ForwardRefExoticComponent<

View File

@ -1,7 +1,7 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { Keyframes } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import { initFadeMotion } from '../../style/motion/fade';
import { resetComponent } from '../../style';
@ -234,10 +234,10 @@ const sharedFloatButtonStyle: GenerateStyle<FloatButtonToken, CSSObject> = (toke
},
},
[`${componentCls}-default`]: {
backgroundColor: token.colorBgContainer,
backgroundColor: token.floatButtonBackgroundColor,
transition: `background-color ${token.motionDurationMid}`,
[`${componentCls}-body`]: {
backgroundColor: token.colorBgContainer,
backgroundColor: token.floatButtonBackgroundColor,
transition: `background-color ${token.motionDurationMid}`,
'&:hover': {
backgroundColor: token.colorFillContent,
@ -285,7 +285,7 @@ const sharedFloatButtonStyle: GenerateStyle<FloatButtonToken, CSSObject> = (toke
export default genComponentStyleHook<'FloatButton'>('FloatButton', (token) => {
const {
colorTextLightSolid,
colorBgContainer,
colorBgElevated,
controlHeightLG,
marginXXL,
marginLG,
@ -294,7 +294,7 @@ export default genComponentStyleHook<'FloatButton'>('FloatButton', (token) => {
controlItemBgHover,
} = token;
const floatButtonToken = mergeToken<FloatButtonToken>(token, {
floatButtonBackgroundColor: colorBgContainer,
floatButtonBackgroundColor: colorBgElevated,
floatButtonColor: colorTextLightSolid,
floatButtonHoverBackgroundColor: controlItemBgHover,
floatButtonFontSize: fontSize,

View File

@ -2,12 +2,13 @@ import classNames from 'classnames';
import CSSMotion, { CSSMotionList } from 'rc-motion';
import * as React from 'react';
import { useMemo } from 'react';
import { ConfigContext } from '../config-provider';
import initCollapseMotion from '../_util/motion';
import { FormItemPrefixContext } from './context';
import type { ValidateStatus } from './FormItem';
import useDebounce from './hooks/useDebounce';
import useStyle from './style';
const EMPTY_LIST: React.ReactNode[] = [];
interface ErrorEntity {
@ -49,12 +50,12 @@ export default function ErrorList({
onVisibleChanged,
}: ErrorListProps) {
const { prefixCls } = React.useContext(FormItemPrefixContext);
const { getPrefixCls } = React.useContext(ConfigContext);
const baseClassName = `${prefixCls}-item-explain`;
const rootPrefixCls = getPrefixCls();
const collapseMotion = useMemo(() => initCollapseMotion(rootPrefixCls), [rootPrefixCls]);
const [, hashId] = useStyle(prefixCls);
const collapseMotion = useMemo(() => initCollapseMotion(prefixCls), [prefixCls]);
// We have to debounce here again since somewhere use ErrorList directly still need no shaking
// ref: https://github.com/ant-design/ant-design/issues/36336
@ -82,9 +83,8 @@ export default function ErrorList({
return (
<CSSMotion
{...collapseMotion}
motionDeadline={collapseMotion.motionDeadline}
motionName={`${rootPrefixCls}-show-help`}
motionName={`${prefixCls}-show-help`}
visible={!!fullKeyList.length}
onVisibleChanged={onVisibleChanged}
>
@ -94,14 +94,14 @@ export default function ErrorList({
return (
<div
{...helpProps}
className={classNames(baseClassName, holderClassName, rootClassName)}
className={classNames(baseClassName, holderClassName, rootClassName, hashId)}
style={holderStyle}
role="alert"
>
<CSSMotionList
keys={fullKeyList}
{...initCollapseMotion(rootPrefixCls)}
motionName={`${rootPrefixCls}-show-help-item`}
{...initCollapseMotion(prefixCls)}
motionName={`${prefixCls}-show-help-item`}
component={false}
>
{(itemProps) => {

View File

@ -0,0 +1,56 @@
import type { FormToken } from '.';
import type { GenerateStyle } from '../../theme/internal';
const genFormValidateMotionStyle: GenerateStyle<FormToken> = (token) => {
const { componentCls } = token;
const helpCls = `${componentCls}-show-help`;
const helpItemCls = `${componentCls}-show-help-item`;
return {
[helpCls]: {
// Explain holder
transition: `opacity ${token.motionDurationSlow} ${token.motionEaseInOut}`,
'&-appear, &-enter': {
opacity: 0,
'&-active': {
opacity: 1,
},
},
'&-leave': {
opacity: 1,
'&-active': {
opacity: 0,
},
},
// Explain
[helpItemCls]: {
overflow: 'hidden',
transition: `height ${token.motionDurationSlow} ${token.motionEaseInOut},
opacity ${token.motionDurationSlow} ${token.motionEaseInOut},
transform ${token.motionDurationSlow} ${token.motionEaseInOut} !important`,
[`&${helpItemCls}-appear, &${helpItemCls}-enter`]: {
transform: `translateY(-5px)`,
opacity: 0,
[`&-active`]: {
transform: 'translateY(0)',
opacity: 1,
},
},
[`&${helpItemCls}-leave-active`]: {
transform: `translateY(-5px)`,
},
},
},
};
};
export default genFormValidateMotionStyle;

View File

@ -1,10 +1,11 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { genCollapseMotion, zoomIn } from '../../style/motion';
import type { AliasToken, FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import type { AliasToken, FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import { resetComponent } from '../../style';
import genFormValidateMotionStyle from './explain';
interface FormToken extends FullToken<'Form'> {
export interface FormToken extends FullToken<'Form'> {
formItemCls: string;
rootPrefixCls: string;
}
@ -261,7 +262,6 @@ const genFormItemStyle: GenerateStyle<FormToken> = (token) => {
color: token.colorTextDescription,
fontSize: token.fontSize,
lineHeight: token.lineHeight,
transition: `color ${token.motionDurationMid} ${token.motionEaseOut}`, // sync input color transition
},
'&-explain-connected': {
@ -270,6 +270,7 @@ const genFormItemStyle: GenerateStyle<FormToken> = (token) => {
'&-extra': {
minHeight: token.controlHeightSM,
transition: `color ${token.motionDurationMid} ${token.motionEaseOut}`, // sync input color transition
},
'&-explain': {
@ -320,58 +321,6 @@ const genFormItemStyle: GenerateStyle<FormToken> = (token) => {
};
};
const genFormMotionStyle: GenerateStyle<FormToken> = (token) => {
const { componentCls, rootPrefixCls } = token;
return {
[componentCls]: {
// Explain holder
[`.${rootPrefixCls}-show-help`]: {
transition: `opacity ${token.motionDurationSlow} ${token.motionEaseInOut}`,
'&-appear, &-enter': {
opacity: 0,
'&-active': {
opacity: 1,
},
},
'&-leave': {
opacity: 1,
'&-active': {
opacity: 0,
},
},
},
// Explain
[`.${rootPrefixCls}-show-help-item`]: {
overflow: 'hidden',
transition: `height ${token.motionDurationSlow} ${token.motionEaseInOut},
opacity ${token.motionDurationSlow} ${token.motionEaseInOut},
transform ${token.motionDurationSlow} ${token.motionEaseInOut} !important`,
[`&-appear,
&-enter`]: {
transform: `translateY(-5px)`,
opacity: 0,
'&-active': {
transform: 'translateY(0)',
opacity: 1,
},
},
'&-leave-active': {
transform: `translateY(-5px)`,
},
},
},
};
};
const genHorizontalStyle: GenerateStyle<FormToken> = (token) => {
const { componentCls, formItemCls, rootPrefixCls } = token;
@ -543,7 +492,7 @@ export default genComponentStyleHook('Form', (token, { rootPrefixCls }) => {
return [
genFormStyle(formToken),
genFormItemStyle(formToken),
genFormMotionStyle(formToken),
genFormValidateMotionStyle(formToken),
genHorizontalStyle(formToken),
genInlineStyle(formToken),
genVerticalStyle(formToken),

View File

@ -1,6 +1,6 @@
import type { CSSObject } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
interface GridRowToken extends FullToken<'Grid'> {}

View File

@ -40,6 +40,146 @@ exports[`Image Default Group preview props 1`] = `
</div>
</div>
</div>
<div
class="ant-image-preview-operations-wrapper ant-fade-appear ant-fade-appear-start ant-fade"
>
<ul
class="ant-image-preview-operations"
>
<li
class="ant-image-preview-operations-progress"
>
1 / 1
</li>
<li
class="ant-image-preview-operations-operation ant-image-preview-operations-operation-close"
>
<span
aria-label="close"
class="anticon anticon-close ant-image-preview-operations-icon"
role="img"
>
<svg
aria-hidden="true"
data-icon="close"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"
/>
</svg>
</span>
</li>
<li
class="ant-image-preview-operations-operation ant-image-preview-operations-operation-zoomIn"
>
<span
aria-label="zoom-in"
class="anticon anticon-zoom-in ant-image-preview-operations-icon"
role="img"
>
<svg
aria-hidden="true"
data-icon="zoom-in"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M637 443H519V309c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v134H325c-4.4 0-8 3.6-8 8v60c0 4.4 3.6 8 8 8h118v134c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V519h118c4.4 0 8-3.6 8-8v-60c0-4.4-3.6-8-8-8zm284 424L775 721c122.1-148.9 113.6-369.5-26-509-148-148.1-388.4-148.1-537 0-148.1 148.6-148.1 389 0 537 139.5 139.6 360.1 148.1 509 26l146 146c3.2 2.8 8.3 2.8 11 0l43-43c2.8-2.7 2.8-7.8 0-11zM696 696c-118.8 118.7-311.2 118.7-430 0-118.7-118.8-118.7-311.2 0-430 118.8-118.7 311.2-118.7 430 0 118.7 118.8 118.7 311.2 0 430z"
/>
</svg>
</span>
</li>
<li
class="ant-image-preview-operations-operation ant-image-preview-operations-operation-zoomOut ant-image-preview-operations-operation-disabled"
>
<span
aria-label="zoom-out"
class="anticon anticon-zoom-out ant-image-preview-operations-icon"
role="img"
>
<svg
aria-hidden="true"
data-icon="zoom-out"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M637 443H325c-4.4 0-8 3.6-8 8v60c0 4.4 3.6 8 8 8h312c4.4 0 8-3.6 8-8v-60c0-4.4-3.6-8-8-8zm284 424L775 721c122.1-148.9 113.6-369.5-26-509-148-148.1-388.4-148.1-537 0-148.1 148.6-148.1 389 0 537 139.5 139.6 360.1 148.1 509 26l146 146c3.2 2.8 8.3 2.8 11 0l43-43c2.8-2.7 2.8-7.8 0-11zM696 696c-118.8 118.7-311.2 118.7-430 0-118.7-118.8-118.7-311.2 0-430 118.8-118.7 311.2-118.7 430 0 118.7 118.8 118.7 311.2 0 430z"
/>
</svg>
</span>
</li>
<li
class="ant-image-preview-operations-operation ant-image-preview-operations-operation-rotateRight"
>
<span
aria-label="rotate-right"
class="anticon anticon-rotate-right ant-image-preview-operations-icon"
role="img"
>
<svg
aria-hidden="true"
data-icon="rotate-right"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<defs>
<style />
</defs>
<path
d="M480.5 251.2c13-1.6 25.9-2.4 38.8-2.5v63.9c0 6.5 7.5 10.1 12.6 6.1L660 217.6c4-3.2 4-9.2 0-12.3l-128-101c-5.1-4-12.6-.4-12.6 6.1l-.2 64c-118.6.5-235.8 53.4-314.6 154.2A399.75 399.75 0 00123.5 631h74.9c-.9-5.3-1.7-10.7-2.4-16.1-5.1-42.1-2.1-84.1 8.9-124.8 11.4-42.2 31-81.1 58.1-115.8 27.2-34.7 60.3-63.2 98.4-84.3 37-20.6 76.9-33.6 119.1-38.8z"
/>
<path
d="M880 418H352c-17.7 0-32 14.3-32 32v414c0 17.7 14.3 32 32 32h528c17.7 0 32-14.3 32-32V450c0-17.7-14.3-32-32-32zm-44 402H396V494h440v326z"
/>
</svg>
</span>
</li>
<li
class="ant-image-preview-operations-operation ant-image-preview-operations-operation-rotateLeft"
>
<span
aria-label="rotate-left"
class="anticon anticon-rotate-left ant-image-preview-operations-icon"
role="img"
>
<svg
aria-hidden="true"
data-icon="rotate-left"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<defs>
<style />
</defs>
<path
d="M672 418H144c-17.7 0-32 14.3-32 32v414c0 17.7 14.3 32 32 32h528c17.7 0 32-14.3 32-32V450c0-17.7-14.3-32-32-32zm-44 402H188V494h440v326z"
/>
<path
d="M819.3 328.5c-78.8-100.7-196-153.6-314.6-154.2l-.2-64c0-6.5-7.6-10.1-12.6-6.1l-128 101c-4 3.1-3.9 9.1 0 12.3L492 318.6c5.1 4 12.7.4 12.6-6.1v-63.9c12.9.1 25.9.9 38.8 2.5 42.1 5.2 82.1 18.2 119 38.7 38.1 21.2 71.2 49.7 98.4 84.3 27.1 34.7 46.7 73.7 58.1 115.8a325.95 325.95 0 016.5 140.9h74.9c14.8-103.6-11.3-213-81-302.3z"
/>
</svg>
</span>
</li>
</ul>
</div>
<div>
<div
class="ant-image-preview-root"
@ -88,148 +228,6 @@ exports[`Image Default Group preview props 1`] = `
</div>
</div>
</div>
<div>
<div
class="ant-image-preview-operations-wrapper ant-fade-appear ant-fade-appear-start ant-fade"
>
<ul
class="ant-image-preview-operations"
>
<li
class="ant-image-preview-operations-progress"
>
1 / 1
</li>
<li
class="ant-image-preview-operations-operation ant-image-preview-operations-operation-close"
>
<span
aria-label="close"
class="anticon anticon-close ant-image-preview-operations-icon"
role="img"
>
<svg
aria-hidden="true"
data-icon="close"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"
/>
</svg>
</span>
</li>
<li
class="ant-image-preview-operations-operation ant-image-preview-operations-operation-zoomIn"
>
<span
aria-label="zoom-in"
class="anticon anticon-zoom-in ant-image-preview-operations-icon"
role="img"
>
<svg
aria-hidden="true"
data-icon="zoom-in"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M637 443H519V309c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v134H325c-4.4 0-8 3.6-8 8v60c0 4.4 3.6 8 8 8h118v134c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V519h118c4.4 0 8-3.6 8-8v-60c0-4.4-3.6-8-8-8zm284 424L775 721c122.1-148.9 113.6-369.5-26-509-148-148.1-388.4-148.1-537 0-148.1 148.6-148.1 389 0 537 139.5 139.6 360.1 148.1 509 26l146 146c3.2 2.8 8.3 2.8 11 0l43-43c2.8-2.7 2.8-7.8 0-11zM696 696c-118.8 118.7-311.2 118.7-430 0-118.7-118.8-118.7-311.2 0-430 118.8-118.7 311.2-118.7 430 0 118.7 118.8 118.7 311.2 0 430z"
/>
</svg>
</span>
</li>
<li
class="ant-image-preview-operations-operation ant-image-preview-operations-operation-zoomOut ant-image-preview-operations-operation-disabled"
>
<span
aria-label="zoom-out"
class="anticon anticon-zoom-out ant-image-preview-operations-icon"
role="img"
>
<svg
aria-hidden="true"
data-icon="zoom-out"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M637 443H325c-4.4 0-8 3.6-8 8v60c0 4.4 3.6 8 8 8h312c4.4 0 8-3.6 8-8v-60c0-4.4-3.6-8-8-8zm284 424L775 721c122.1-148.9 113.6-369.5-26-509-148-148.1-388.4-148.1-537 0-148.1 148.6-148.1 389 0 537 139.5 139.6 360.1 148.1 509 26l146 146c3.2 2.8 8.3 2.8 11 0l43-43c2.8-2.7 2.8-7.8 0-11zM696 696c-118.8 118.7-311.2 118.7-430 0-118.7-118.8-118.7-311.2 0-430 118.8-118.7 311.2-118.7 430 0 118.7 118.8 118.7 311.2 0 430z"
/>
</svg>
</span>
</li>
<li
class="ant-image-preview-operations-operation ant-image-preview-operations-operation-rotateRight"
>
<span
aria-label="rotate-right"
class="anticon anticon-rotate-right ant-image-preview-operations-icon"
role="img"
>
<svg
aria-hidden="true"
data-icon="rotate-right"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<defs>
<style />
</defs>
<path
d="M480.5 251.2c13-1.6 25.9-2.4 38.8-2.5v63.9c0 6.5 7.5 10.1 12.6 6.1L660 217.6c4-3.2 4-9.2 0-12.3l-128-101c-5.1-4-12.6-.4-12.6 6.1l-.2 64c-118.6.5-235.8 53.4-314.6 154.2A399.75 399.75 0 00123.5 631h74.9c-.9-5.3-1.7-10.7-2.4-16.1-5.1-42.1-2.1-84.1 8.9-124.8 11.4-42.2 31-81.1 58.1-115.8 27.2-34.7 60.3-63.2 98.4-84.3 37-20.6 76.9-33.6 119.1-38.8z"
/>
<path
d="M880 418H352c-17.7 0-32 14.3-32 32v414c0 17.7 14.3 32 32 32h528c17.7 0 32-14.3 32-32V450c0-17.7-14.3-32-32-32zm-44 402H396V494h440v326z"
/>
</svg>
</span>
</li>
<li
class="ant-image-preview-operations-operation ant-image-preview-operations-operation-rotateLeft"
>
<span
aria-label="rotate-left"
class="anticon anticon-rotate-left ant-image-preview-operations-icon"
role="img"
>
<svg
aria-hidden="true"
data-icon="rotate-left"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<defs>
<style />
</defs>
<path
d="M672 418H144c-17.7 0-32 14.3-32 32v414c0 17.7 14.3 32 32 32h528c17.7 0 32-14.3 32-32V450c0-17.7-14.3-32-32-32zm-44 402H188V494h440v326z"
/>
<path
d="M819.3 328.5c-78.8-100.7-196-153.6-314.6-154.2l-.2-64c0-6.5-7.6-10.1-12.6-6.1l-128 101c-4 3.1-3.9 9.1 0 12.3L492 318.6c5.1 4 12.7.4 12.6-6.1v-63.9c12.9.1 25.9.9 38.8 2.5 42.1 5.2 82.1 18.2 119 38.7 38.1 21.2 71.2 49.7 98.4 84.3 27.1 34.7 46.7 73.7 58.1 115.8a325.95 325.95 0 016.5 140.9h74.9c14.8-103.6-11.3-213-81-302.3z"
/>
</svg>
</span>
</li>
</ul>
</div>
</div>
</body>
`;

View File

@ -2,8 +2,8 @@ import type { CSSObject } from '@ant-design/cssinjs';
import { TinyColor } from '@ctrl/tinycolor';
import { genModalMaskStyle } from '../../modal/style';
import { initZoomMotion, initFadeMotion } from '../../style/motion';
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import { resetComponent, textEllipsis } from '../../style';
export interface ComponentToken {

View File

@ -126,7 +126,7 @@ export { default as Tabs } from './tabs';
export type { TabPaneProps, TabsProps } from './tabs';
export { default as Tag } from './tag';
export type { TagProps, TagType } from './tag';
export { default as theme } from './theme/export';
export { default as theme } from './theme';
export { default as TimePicker } from './time-picker';
export type { TimePickerProps, TimeRangePickerProps } from './time-picker';
export { default as Timeline } from './timeline';

View File

@ -11,7 +11,7 @@ import DisabledContext from '../config-provider/DisabledContext';
import type { SizeType } from '../config-provider/SizeContext';
import SizeContext from '../config-provider/SizeContext';
import { FormItemInputContext, NoFormStyle } from '../form/context';
import { useCompactItemContext } from '../space/Compact';
import { NoCompactStyle, useCompactItemContext } from '../space/Compact';
import { cloneElement } from '../_util/reactNode';
import type { InputStatus } from '../_util/statusUtils';
import { getMergedStatus, getStatusClassNames } from '../_util/statusUtils';
@ -188,15 +188,19 @@ const InputNumber = React.forwardRef<HTMLInputElement, InputNumberProps>((props,
<div className={mergedGroupClassName} style={props.style}>
<div className={mergedWrapperClassName}>
{addonBeforeNode && (
<NoFormStyle status override>
{addonBeforeNode}
</NoFormStyle>
<NoCompactStyle>
<NoFormStyle status override>
{addonBeforeNode}
</NoFormStyle>
</NoCompactStyle>
)}
{cloneElement(element, { style: null, disabled: mergedDisabled })}
{addonAfterNode && (
<NoFormStyle status override>
{addonAfterNode}
</NoFormStyle>
<NoCompactStyle>
<NoFormStyle status override>
{addonAfterNode}
</NoFormStyle>
</NoCompactStyle>
)}
</div>
</div>

View File

@ -9,8 +9,8 @@ import {
genStatusStyle,
initInputToken,
} from '../../input/style';
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook } from '../../theme/internal';
import { resetComponent, resetIcon } from '../../style';
import { genCompactItemStyle } from '../../style/compact-item';

View File

@ -10005,7 +10005,7 @@ Array [
<div
class="ant-input-textarea ant-input-textarea-show-count"
data-count="0 / 100"
style="height:120px"
style="height:120px;margin-bottom:24px"
>
<textarea
class="ant-input"

View File

@ -3753,7 +3753,7 @@ Array [
<div
class="ant-input-textarea ant-input-textarea-show-count"
data-count="0 / 100"
style="height:120px"
style="height:120px;margin-bottom:24px"
>
<textarea
class="ant-input"

View File

@ -12,7 +12,7 @@ const App: React.FC = () => (
<TextArea
showCount
maxLength={100}
style={{ height: 120 }}
style={{ height: 120, marginBottom: 24 }}
onChange={onChange}
placeholder="can resize"
/>

View File

@ -1,6 +1,6 @@
import type { CSSObject } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import type { GlobalToken } from '../../theme/interface';
import { clearFix, resetComponent } from '../../style';
import { genCompactItemStyle } from '../../style/compact-item';

View File

@ -1,6 +1,6 @@
import type { CSSObject } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import genLayoutLightStyle from './light';
export interface ComponentToken {

Some files were not shown because too many files have changed in this diff Show More