Merge branch 'master' into feature-merge-master

This commit is contained in:
MadCcc 2022-11-22 16:47:28 +08:00
commit 5ec18089e6
577 changed files with 2913 additions and 3509 deletions

View File

@ -1,23 +1,21 @@
const fs = require('fs');
const path = require('path');
const restCssPath = path.join(process.cwd(), 'components', 'style', 'reset.css');
function finalizeCompile() {
if (fs.existsSync(path.join(__dirname, './es'))) {
// Build less entry file: dist/antd.less
fs.copyFileSync(
path.join(process.cwd(), 'components', 'style', 'reset.css'),
path.join(process.cwd(), 'es', 'style', 'reset.css'),
);
fs.copyFileSync(restCssPath, path.join(process.cwd(), 'es', 'style', 'reset.css'));
}
if (fs.existsSync(path.join(__dirname, './lib'))) {
fs.copyFileSync(restCssPath, path.join(process.cwd(), 'lib', 'style', 'reset.css'));
}
}
function finalizeDist() {
if (fs.existsSync(path.join(__dirname, './dist'))) {
// Build less entry file: dist/antd.less
fs.copyFileSync(
path.join(process.cwd(), 'components', 'style', 'reset.css'),
path.join(process.cwd(), 'dist', 'reset.css'),
);
fs.copyFileSync(restCssPath, path.join(process.cwd(), 'dist', 'reset.css'));
}
}

View File

@ -58,7 +58,7 @@ const useMenu = (options: UseMenuOptions = {}): [MenuProps['items'], string] =>
}, {});
const childItems = [];
childItems.push(
...childrenGroup.default.map(item => ({
...childrenGroup.default.map((item) => ({
label: (
<Link to={item.link}>
{before}
@ -75,7 +75,7 @@ const useMenu = (options: UseMenuOptions = {}): [MenuProps['items'], string] =>
type: 'group',
label: type,
key: type,
children: children?.map(item => ({
children: children?.map((item) => ({
label: (
<Link to={item.link}>
{before}
@ -98,7 +98,7 @@ const useMenu = (options: UseMenuOptions = {}): [MenuProps['items'], string] =>
type: 'group',
label: group.title,
key: group.title,
children: group.children?.map(item => ({
children: group.children?.map((item) => ({
label: (
<Link to={item.link}>
{before}
@ -115,7 +115,7 @@ const useMenu = (options: UseMenuOptions = {}): [MenuProps['items'], string] =>
}
} else {
result.push(
...group.children?.map(item => ({
...group.children?.map((item) => ({
label: (
<Link to={item.link}>
{before}

View File

@ -26,7 +26,7 @@ const useSiteToken = () => {
/** 80 */
marginFarSM: (token.marginXXL / 3) * 5,
/** 96 */
marginFar: token.marginXXL * 1.8,
marginFar: token.marginXXL * 2,
codeFamily: `'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace`,
},
};

View File

@ -8,14 +8,14 @@ import * as utils from '../../../theme/utils';
const locales = {
cn: {
slogan: '助力设计开发者「更灵活」搭建出「更美」的产品,让用户「快乐工作」~',
slogan: '助力设计开发者「更灵活」搭建出「更美」的产品,让用户「快乐工作」~',
start: '开始使用',
designLanguage: '设计语言',
},
en: {
slogan:
'Help design developers "more flexible" to build "more beautiful" products, helping users to "work happily"~',
start: 'Get Start',
'Help designers/developers building beautiful products more flexible and working with happiness',
start: 'Getting Started',
designLanguage: 'Design Language',
},
};
@ -36,7 +36,7 @@ export default function Banner({ children }: BannerProps) {
{/* Banner Placeholder Motion */}
<div
style={{
height: 240,
height: 320,
background: '#77C6FF',
display: 'flex',
flexWrap: 'nowrap',
@ -53,12 +53,7 @@ export default function Banner({ children }: BannerProps) {
}}
/>
<video
style={{ height: '100%', objectFit: 'contain' }}
autoPlay
muted
loop
>
<video style={{ height: '100%', objectFit: 'contain' }} autoPlay muted loop>
<source
src="https://mdn.alipayobjects.com/huamei_iwk9zp/afts/file/A*uYT7SZwhJnUAAAAAAAAAAAAADgCCAQ"
type="video/webm"
@ -76,6 +71,7 @@ export default function Banner({ children }: BannerProps) {
backgroundRepeat: 'repeat-x',
backgroundPosition: '0 0',
backgroundSize: 'auto 100%',
marginLeft: -1,
}}
/>
</div>
@ -91,7 +87,7 @@ export default function Banner({ children }: BannerProps) {
<GroupMask
style={{
textAlign: 'center',
paddingTop: token.marginFar,
paddingTop: token.marginFar - 16,
paddingBottom: token.marginFarSM,
}}
>

View File

@ -54,7 +54,7 @@ export default function BannerRecommends({ extras = [], icons = [] }: BannerReco
>
{first3.map((extra, index) => {
if (!extra) {
return <Skeleton />;
return <Skeleton key={index} />;
}
const icon = icons.find((icon) => icon.name === extra.source);
return (

View File

@ -10,7 +10,6 @@ import {
Modal,
FloatButton,
Progress,
ConfigProvider,
} from 'antd';
import dayjs from 'dayjs';
import { CustomerServiceOutlined, QuestionCircleOutlined, SyncOutlined } from '@ant-design/icons';
@ -222,7 +221,7 @@ export default function ComponentsList() {
const tagText = type === 'new' ? locale.new : locale.update;
return (
<div key={index} css={styles.card} style={{ pointerEvents: 'none' }}>
<div key={index} css={styles.card}>
{/* Decorator */}
<div
css={styles.cardCircle}

View File

@ -54,7 +54,7 @@ export default function ColorPicker({ value, onChange }: RadiusPickerProps) {
const valueStr = new TinyColor(value).toRgbString();
let existActive = false;
const colors = PRESET_COLORS.map(color => {
const colors = PRESET_COLORS.map((color) => {
const colorStr = new TinyColor(color).toRgbString();
const active = colorStr === valueStr;
existActive = existActive || active;
@ -80,7 +80,7 @@ export default function ColorPicker({ value, onChange }: RadiusPickerProps) {
<Space size="large">
<Input
value={value}
onChange={event => {
onChange={(event) => {
onChange?.(event.target.value);
}}
style={{ width: 120 }}
@ -109,7 +109,10 @@ export default function ColorPicker({ value, onChange }: RadiusPickerProps) {
key={color}
overlayInnerStyle={{ padding: 0 }}
content={
<DebouncedColorPanel color={value || ''} onChange={color => onChange?.(color)} />
<DebouncedColorPanel
color={value || ''}
onChange={(color) => onChange?.(color)}
/>
}
trigger="click"
showArrow={false}

View File

@ -14,8 +14,8 @@ export default function RadiusPicker({ value, onChange }: RadiusPickerProps) {
onChange={onChange}
style={{ width: 120 }}
min={0}
formatter={val => `${val}px`}
parser={str => (str ? parseFloat(str) : (str as any))}
formatter={(val) => `${val}px`}
parser={(str) => (str ? parseFloat(str) : (str as any))}
/>
<Slider

View File

@ -74,7 +74,7 @@ export default function ThemePicker({ value, onChange }: ThemePickerProps) {
return (
<Space size={token.paddingLG}>
{Object.keys(THEMES).map(theme => {
{Object.keys(THEMES).map((theme) => {
const url = THEMES[theme as THEME];
return (

View File

@ -73,7 +73,7 @@ export function getAvatarURL(color?: string | null) {
}
return (
COLOR_IMAGES.find(obj => obj.color === closestColor)?.url ||
COLOR_IMAGES.find((obj) => obj.color === closestColor)?.url ||
'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*CLp0Qqc11AkAAAAAAAAAAAAAARQnAQ'
);
}

View File

@ -72,7 +72,7 @@ export function preLoad(list: string[]) {
const div = document.createElement('div');
div.style.display = 'none';
document.body.appendChild(div);
list.forEach(src => {
list.forEach((src) => {
const img = new Image();
img.src = src;
div.appendChild(img);
@ -88,8 +88,8 @@ export function useSiteData(): [Partial<SiteData>, boolean] {
if (Object.keys(data ?? {}).length === 0 && typeof fetch !== 'undefined') {
setLoading(true);
fetch(`https://render.alipay.com/p/h5data/antd4-config_website-h5data.json`)
.then(res => res.json())
.then(result => {
.then((res) => res.json())
.then((result) => {
setData(result);
setLoading(false);
});

View File

@ -24,7 +24,7 @@ const CustomTheme = () => {
theme={{ name: 'test', key: 'test', config: theme }}
simple
style={{ height: 'calc(100vh - 64px)' }}
onThemeChange={newTheme => {
onThemeChange={(newTheme) => {
setTheme(newTheme.config);
}}
/>

View File

@ -6,6 +6,8 @@ import { type HastRoot, type UnifiedTransformer, unistUtilVisit } from 'dumi';
*/
function rehypeAntd(): UnifiedTransformer<HastRoot> {
return (tree, vFile) => {
const filename = (vFile.data.frontmatter as any).filename;
unistUtilVisit.visit(tree, 'element', (node) => {
if (node.tagName === 'DumiDemoGrid') {
// replace DumiDemoGrid to DemoWrapper, to implement demo toolbar
@ -16,9 +18,7 @@ function rehypeAntd(): UnifiedTransformer<HastRoot> {
assert(
contentNode.type === 'text',
`ResourceCards content must be plain text!\nat ${
(vFile.data.frontmatter as any).filename
}`,
`ResourceCards content must be plain text!\nat ${filename}`,
);
// clear children
@ -52,6 +52,14 @@ function rehypeAntd(): UnifiedTransformer<HastRoot> {
),
},
];
} else if (
node.type === 'element' &&
node.tagName === 'Table' &&
/^components/.test(filename)
) {
if (!node.properties) return;
node.properties.className ??= [];
(node.properties.className as string[]).push('component-api-table');
}
});
};

View File

@ -29,7 +29,6 @@ const useStyle = () => {
align-items: center;
justify-content: center;
height: 152px;
background-color: ${token.colorBgElevated};
`,
componentsOverviewCard: css`
cursor: pointer;
@ -68,7 +67,7 @@ const onClickCard = (pathname: string) => {
}
};
const reportSearch = debounce<(value: string) => void>(value => {
const reportSearch = debounce<(value: string) => void>((value) => {
if (window.gtag) {
window.gtag('event', '搜索', {
event_category: '组件总览卡片',
@ -91,7 +90,7 @@ const Overview: React.FC = () => {
const sectionRef = React.useRef<HTMLElement>(null);
const onKeyDown: React.KeyboardEventHandler<HTMLInputElement> = event => {
const onKeyDown: React.KeyboardEventHandler<HTMLInputElement> = (event) => {
if (event.keyCode === 13 && search.trim().length) {
sectionRef.current?.querySelector<HTMLElement>('.components-overview-card')?.click();
}
@ -99,11 +98,11 @@ const Overview: React.FC = () => {
const groups = useMemo<{ title: string; children: Component[] }[]>(() => {
return data
.filter(item => item.title)
.map<{ title: string; children: Component[] }>(item => {
.filter((item) => item.title)
.map<{ title: string; children: Component[] }>((item) => {
return {
title: item.title!,
children: item.children.map(child => ({
children: item.children.map((child) => ({
title: child.frontmatter.title,
subtitle: child.frontmatter.subtitle,
cover: child.frontmatter.cover,
@ -114,7 +113,10 @@ const Overview: React.FC = () => {
.concat([
{
title: locale === 'zh-CN' ? '重型组件' : 'Others',
children: proComponentsList,
children:
locale === 'zh-CN'
? proComponentsList
: proComponentsList.map((component) => ({ ...component, subtitle: '' })),
},
]);
}, [data, locale]);
@ -126,7 +128,7 @@ const Overview: React.FC = () => {
value={search}
placeholder={formatMessage({ id: 'app.components.overview.search' })}
css={style.componentsOverviewSearch}
onChange={e => {
onChange={(e) => {
setSearch(e.target.value);
reportSearch(e.target.value);
}}
@ -136,10 +138,10 @@ const Overview: React.FC = () => {
/>
<Divider />
{groups
.filter(i => i.title)
.map(group => {
.filter((i) => i.title)
.map((group) => {
const components = group?.children?.filter(
component =>
(component) =>
!search.trim() ||
component.title.toLowerCase().includes(search.trim().toLowerCase()) ||
(component?.subtitle || '').toLowerCase().includes(search.trim().toLowerCase()),
@ -153,7 +155,7 @@ const Overview: React.FC = () => {
</Space>
</Title>
<Row gutter={[24, 24]}>
{components.map(component => {
{components.map((component) => {
const url = `${component.link}/`;
/** Link 不能跳转到外链 */

View File

@ -12,7 +12,7 @@ interface CategoryProps {
newIcons: string[];
}
const Category: React.FC<CategoryProps> = props => {
const Category: React.FC<CategoryProps> = (props) => {
const { icons, title, newIcons, theme } = props;
const intl = useIntl();
const [justCopied, setJustCopied] = React.useState<string | null>(null);
@ -40,7 +40,7 @@ const Category: React.FC<CategoryProps> = props => {
<div>
<h3>{intl.formatMessage({ id: `app.docs.components.icon.category.${title}` })}</h3>
<ul className="anticons-list">
{icons.map(name => (
{icons.map((name) => (
<CopyableIcon
key={name}
name={name}

View File

@ -1,239 +0,0 @@
import React, { useCallback, useEffect, useState } from 'react';
import { Upload, Tooltip, Popover, Modal, Progress, message, Spin, Result } from 'antd';
import CopyToClipboard from 'react-copy-to-clipboard';
import { useIntl } from 'dumi';
import * as AntdIcons from '@ant-design/icons';
const allIcons: { [key: string]: any } = AntdIcons;
const { Dragger } = Upload;
interface AntdIconClassifier {
load: Function;
predict: Function;
}
declare global {
interface Window {
antdIconClassifier: AntdIconClassifier;
}
}
interface PicSearcherState {
loading: boolean;
modalOpen: boolean;
popoverVisible: boolean;
icons: iconObject[];
fileList: any[];
error: boolean;
modelLoaded: boolean;
}
interface iconObject {
type: string;
score: number;
}
const PicSearcher: React.FC = () => {
const intl = useIntl();
const [state, setState] = useState<PicSearcherState>({
loading: false,
modalOpen: false,
popoverVisible: false,
icons: [],
fileList: [],
error: false,
modelLoaded: false,
});
const predict = (imgEl: HTMLImageElement) => {
try {
let icons: any[] = window.antdIconClassifier.predict(imgEl);
if (gtag && icons.length) {
gtag('event', 'icon', {
event_category: 'search-by-image',
event_label: icons[0].className,
});
}
icons = icons.map(i => ({ score: i.score, type: i.className.replace(/\s/g, '-') }));
setState(prev => ({ ...prev, loading: false, error: false, icons }));
} catch {
setState(prev => ({ ...prev, loading: false, error: true }));
}
};
// eslint-disable-next-line class-methods-use-this
const toImage = (url: string): Promise<HTMLImageElement> =>
new Promise(resolve => {
const img = new Image();
img.setAttribute('crossOrigin', 'anonymous');
img.src = url;
img.onload = () => {
resolve(img);
};
});
const uploadFile = useCallback((file: File) => {
setState(prev => ({ ...prev, loading: true }));
const reader = new FileReader();
reader.onload = () => {
toImage(reader.result as string).then(predict);
setState(prev => ({
...prev,
fileList: [{ uid: 1, name: file.name, status: 'done', url: reader.result }],
}));
};
reader.readAsDataURL(file);
}, []);
const onPaste = useCallback((event: ClipboardEvent) => {
const items = event.clipboardData && event.clipboardData.items;
let file = null;
if (items && items.length) {
for (let i = 0; i < items.length; i++) {
if (items[i].type.includes('image')) {
file = items[i].getAsFile();
break;
}
}
}
if (file) {
uploadFile(file);
}
}, []);
const toggleModal = useCallback(() => {
setState(prev => ({
...prev,
modalOpen: !prev.modalOpen,
popoverVisible: false,
fileList: [],
icons: [],
}));
if (!localStorage.getItem('disableIconTip')) {
localStorage.setItem('disableIconTip', 'true');
}
}, []);
// eslint-disable-next-line class-methods-use-this
const onCopied = useCallback((text: string) => {
message.success(
<span>
<code className="copied-code">{text}</code> copied 🎉
</span>,
);
}, []);
useEffect(() => {
const script = document.createElement('script');
script.onload = async () => {
await window.antdIconClassifier.load();
setState(prev => ({ ...prev, modelLoaded: true }));
document.addEventListener('paste', onPaste);
};
script.src = 'https://cdn.jsdelivr.net/gh/lewis617/antd-icon-classifier@0.0/dist/main.js';
document.head.appendChild(script);
setState(prev => ({ ...prev, popoverVisible: !localStorage.getItem('disableIconTip') }));
return () => {
document.removeEventListener('paste', onPaste);
};
}, []);
return (
<div className="icon-pic-searcher">
<Popover
content={intl.formatMessage({ id: `app.docs.components.icon.pic-searcher.intro` })}
open={state.popoverVisible}
>
<AntdIcons.CameraOutlined className="icon-pic-btn" onClick={toggleModal} />
</Popover>
<Modal
title={intl.formatMessage({ id: `app.docs.components.icon.pic-searcher.title` })}
open={state.modalOpen}
onCancel={toggleModal}
footer={null}
>
{state.modelLoaded || (
<Spin
spinning={!state.modelLoaded}
tip={intl.formatMessage({ id: 'app.docs.components.icon.pic-searcher.modelloading' })}
>
<div style={{ height: 100 }} />
</Spin>
)}
{state.modelLoaded && (
<Dragger
accept="image/jpeg, image/png"
listType="picture"
customRequest={o => uploadFile(o.file as File)}
fileList={state.fileList}
showUploadList={{ showPreviewIcon: false, showRemoveIcon: false }}
>
<p className="ant-upload-drag-icon">
<AntdIcons.InboxOutlined />
</p>
<p className="ant-upload-text">
{intl.formatMessage({ id: 'app.docs.components.icon.pic-searcher.upload-text' })}
</p>
<p className="ant-upload-hint">
{intl.formatMessage({ id: 'app.docs.components.icon.pic-searcher.upload-hint' })}
</p>
</Dragger>
)}
<Spin
spinning={state.loading}
tip={intl.formatMessage({ id: 'app.docs.components.icon.pic-searcher.matching' })}
>
<div className="icon-pic-search-result">
{state.icons.length > 0 && (
<div className="result-tip">
{intl.formatMessage({ id: 'app.docs.components.icon.pic-searcher.result-tip' })}
</div>
)}
<table>
{state.icons.length > 0 && (
<thead>
<tr>
<th className="col-icon">
{intl.formatMessage({ id: 'app.docs.components.icon.pic-searcher.th-icon' })}
</th>
<th>
{intl.formatMessage({ id: 'app.docs.components.icon.pic-searcher.th-score' })}
</th>
</tr>
</thead>
)}
<tbody>
{state.icons.map(icon => {
const { type } = icon;
const iconName = `${type
.split('-')
.map(str => `${str[0].toUpperCase()}${str.slice(1)}`)
.join('')}Outlined`;
return (
<tr key={iconName}>
<td className="col-icon">
<CopyToClipboard text={`<${iconName} />`} onCopy={onCopied}>
<Tooltip title={icon.type} placement="right">
{React.createElement(allIcons[iconName])}
</Tooltip>
</CopyToClipboard>
</td>
<td>
<Progress percent={Math.ceil(icon.score * 100)} />
</td>
</tr>
);
})}
</tbody>
</table>
{state.error && (
<Result
status="500"
title="503"
subTitle={intl.formatMessage({
id: 'app.docs.components.icon.pic-searcher.server-error',
})}
/>
)}
</div>
</Spin>
</Modal>
</div>
);
};
export default PicSearcher;

View File

@ -1,7 +1,7 @@
import * as AntdIcons from '@ant-design/icons/lib/icons';
const all = Object.keys(AntdIcons)
.map(n => n.replace(/(Outlined|Filled|TwoTone)$/, ''))
.map((n) => n.replace(/(Outlined|Filled|TwoTone)$/, ''))
.filter((n, i, arr) => arr.indexOf(n) === i);
const direction = [
@ -204,7 +204,7 @@ const logo = [
const datum = [...direction, ...suggestion, ...editor, ...data, ...logo];
const other = all.filter(n => !datum.includes(n));
const other = all.filter((n) => !datum.includes(n));
export const categories = {
direction,

View File

@ -5,7 +5,6 @@ import type { RadioChangeEvent } from 'antd/es/radio/interface';
import { useIntl } from 'dumi';
import debounce from 'lodash/debounce';
import Category from './Category';
import IconPicSearcher from './IconPicSearcher';
import { FilledIcon, OutlinedIcon, TwoToneIcon } from './themeIcons';
import type { CategoriesKeys } from './fields';
import { categories } from './fields';
@ -34,20 +33,20 @@ const IconSearch: React.FC = () => {
const handleSearchIcon = React.useCallback(
debounce((searchKey: string) => {
setDisplayState(prevState => ({ ...prevState, searchKey }));
setDisplayState((prevState) => ({ ...prevState, searchKey }));
}),
[],
);
const handleChangeTheme = React.useCallback((e: RadioChangeEvent) => {
setDisplayState(prevState => ({ ...prevState, theme: e.target.value as ThemeType }));
setDisplayState((prevState) => ({ ...prevState, theme: e.target.value as ThemeType }));
}, []);
const renderCategories = React.useMemo<React.ReactNode | React.ReactNode[]>(() => {
const { searchKey = '', theme } = displayState;
const categoriesResult = Object.keys(categories)
.map(key => {
.map((key) => {
let iconList = categories[key as CategoriesKeys];
if (searchKey) {
const matchKey = searchKey
@ -55,15 +54,17 @@ const IconSearch: React.FC = () => {
.replace(new RegExp(`^<([a-zA-Z]*)\\s/>$`, 'gi'), (_, name) => name)
.replace(/(Filled|Outlined|TwoTone)$/, '')
.toLowerCase();
iconList = iconList.filter(iconName => iconName.toLowerCase().includes(matchKey));
iconList = iconList.filter((iconName) => iconName.toLowerCase().includes(matchKey));
}
// CopyrightCircle is same as Copyright, don't show it
iconList = iconList.filter(icon => icon !== 'CopyrightCircle');
iconList = iconList.filter((icon) => icon !== 'CopyrightCircle');
return {
category: key,
icons: iconList.map(iconName => iconName + theme).filter(iconName => allIcons[iconName]),
icons: iconList
.map((iconName) => iconName + theme)
.filter((iconName) => allIcons[iconName]),
};
})
.filter(({ icons }) => !!icons.length)
@ -104,10 +105,9 @@ const IconSearch: React.FC = () => {
placeholder={intl.formatMessage({ id: 'app.docs.components.icon.search.placeholder' })}
style={{ margin: '0 10px', flex: 1 }}
allowClear
onChange={e => handleSearchIcon(e.currentTarget.value)}
onChange={(e) => handleSearchIcon(e.currentTarget.value)}
size="large"
autoFocus
suffix={<IconPicSearcher />}
/>
</div>
{renderCategories}

View File

@ -5,7 +5,7 @@ type CustomIconComponent = React.ComponentType<
CustomIconComponentProps | React.SVGProps<SVGSVGElement>
>;
export const FilledIcon: CustomIconComponent = props => {
export const FilledIcon: CustomIconComponent = (props) => {
const path =
'M864 64H160C107 64 64 107 64 160v' +
'704c0 53 43 96 96 96h704c53 0 96-43 96-96V16' +
@ -17,7 +17,7 @@ export const FilledIcon: CustomIconComponent = props => {
);
};
export const OutlinedIcon: CustomIconComponent = props => {
export const OutlinedIcon: CustomIconComponent = (props) => {
const path =
'M864 64H160C107 64 64 107 64 160v7' +
'04c0 53 43 96 96 96h704c53 0 96-43 96-96V160c' +
@ -31,7 +31,7 @@ export const OutlinedIcon: CustomIconComponent = props => {
);
};
export const TwoToneIcon: CustomIconComponent = props => {
export const TwoToneIcon: CustomIconComponent = (props) => {
const path =
'M16 512c0 273.932 222.066 496 496 49' +
'6s496-222.068 496-496S785.932 16 512 16 16 238.' +

View File

@ -15,14 +15,14 @@ function isInline(className) {
}
function PreviewImageBox({
cover,
coverMeta,
imgs,
style,
previewVisible,
comparable,
onClick,
onCancel,
cover,
coverMeta,
imgs,
style,
previewVisible,
comparable,
onClick,
onCancel,
}) {
const onlyOneImg = comparable || imgs.length === 1;
const imageWrapperClassName = classNames('preview-image-wrapper', {
@ -77,7 +77,7 @@ export default class ImagePreview extends React.Component {
};
}
handleClick = index => {
handleClick = (index) => {
this.setState({
previewVisible: {
[index]: true,
@ -93,7 +93,7 @@ export default class ImagePreview extends React.Component {
render() {
const { imgs } = this.props;
const imgsMeta = imgs.map(img => {
const imgsMeta = imgs.map((img) => {
const { alt, description, src } = img;
const imgClassName = img.class;
return {

View File

@ -16,8 +16,8 @@ function useShowRiddleButton() {
const [showRiddleButton, setShowRiddleButton] = useState(false);
useEffect(() => {
pingDeferrer ??= new Promise<boolean>(resolve => {
ping(status => {
pingDeferrer ??= new Promise<boolean>((resolve) => {
ping((status) => {
if (status !== 'timeout' && status !== 'error') {
return resolve(true);
}

View File

@ -75,7 +75,7 @@ class Demo extends React.Component {
return ['', ''];
}
handleCodeExpand = demo => {
handleCodeExpand = (demo) => {
const { codeExpand } = this.state;
this.setState({ codeExpand: !codeExpand });
this.track({
@ -84,11 +84,11 @@ class Demo extends React.Component {
});
};
saveAnchor = anchor => {
saveAnchor = (anchor) => {
this.anchor = anchor;
};
handleCodeCopied = demo => {
handleCodeCopied = (demo) => {
this.setState({ copied: true });
this.track({
type: 'copy',
@ -96,7 +96,7 @@ class Demo extends React.Component {
});
};
onCopyTooltipOpenChange = open => {
onCopyTooltipOpenChange = (open) => {
if (open) {
this.setState({
copyTooltipOpen: open,
@ -254,7 +254,7 @@ class Demo extends React.Component {
'react-router-dom/umd/react-router-dom.min.js',
'react-router@3.x/umd/ReactRouter.min.js',
]
.map(url => `https://unpkg.com/${url}`)
.map((url) => `https://unpkg.com/${url}`)
.join(';'),
js_pre_processor: 'typescript',
};
@ -495,7 +495,7 @@ createRoot(document.getElementById('container')).render(<Demo />);
<CodePreview
toReactComponent={props.utils.toReactComponent}
codes={highlightedCodes}
onCodeTypeChange={type => this.setState({ codeType: type })}
onCodeTypeChange={(type) => this.setState({ codeType: type })}
/>
{highlightedStyle ? (
<div key="style" className="highlight">

View File

@ -76,7 +76,7 @@ const ArticleList: React.FC<ArticleListProps> = ({ name, data = [], authors = []
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
) : (
data.map((article, index) => {
const author = authors.find(auth => auth.name === article.author);
const author = authors.find((auth) => auth.name === article.author);
return (
<li key={index}>
<a href={author?.href} target="_blank" rel="noreferrer">
@ -105,7 +105,7 @@ export default () => {
// ========================== Data ==========================
const mergedData = React.useMemo(() => {
const yearData: Record<number | string, Record<string, Article[]>> = {};
articles[isZhCN ? 'cn' : 'en']?.forEach(article => {
articles[isZhCN ? 'cn' : 'en']?.forEach((article) => {
const year = dayjs(article.date).year();
yearData[year] = yearData[year] || {};
yearData[year][article.type] = [...(yearData[year][article.type] || []), article];
@ -122,7 +122,7 @@ export default () => {
const yearList = Object.keys(mergedData).sort((a, b) => Number(b) - Number(a));
content = yearList.length ? (
<Tabs>
{yearList.map(year => (
{yearList.map((year) => (
<Tabs.TabPane tab={`${year}${isZhCN ? ' 年' : ''}`} key={year}>
<table>
<tbody>

View File

@ -108,7 +108,7 @@ export type ResourceCardsProps = {
const ResourceCards: FC<ResourceCardsProps> = ({ resources }) => {
return (
<Row style={{ margin: '-12px -12px 0 -12px' }}>
{resources.map(item => (
{resources.map((item) => (
<ResourceCard resource={item} key={item.title} />
))}
</Row>

View File

@ -7,6 +7,6 @@ const SVGIcon = () => (
</svg>
);
const CodePenIcon = props => <Icon component={SVGIcon} {...props} />;
const CodePenIcon = (props) => <Icon component={SVGIcon} {...props} />;
export default CodePenIcon;

View File

@ -24,7 +24,7 @@ const CodePreview = ({ toReactComponent, codes, onCodeTypeChange }) => {
} else {
content = (
<Tabs centered onChange={onCodeTypeChange}>
{langList.map(lang => (
{langList.map((lang) => (
<TabPane tab={LANGS[lang]} key={lang}>
{toReactComponent([
'pre',

View File

@ -7,6 +7,6 @@ const SVGIcon = () => (
</svg>
);
const CodeSandboxIcon = props => <Icon component={SVGIcon} {...props} />;
const CodeSandboxIcon = (props) => <Icon component={SVGIcon} {...props} />;
export default CodeSandboxIcon;

View File

@ -22,7 +22,7 @@ export default class ColorPaletteTool extends Component {
});
};
handleChangeBackgroundColor = e => {
handleChangeBackgroundColor = (e) => {
const value = e.target ? e.target.value : e;
this.setState({
backgroundColor: value,

View File

@ -2,7 +2,7 @@ import React from 'react';
import cls from 'classnames';
import Palette from './Palette';
const ColorPalettes = props => {
const ColorPalettes = (props) => {
const { dark } = props;
const colors = [
@ -84,7 +84,7 @@ const ColorPalettes = props => {
});
return (
<div className={colorCls}>
{colors.map(color => (
{colors.map((color) => (
<Palette key={color.name} color={color} dark={dark} showTitle />
))}
</div>

View File

@ -3,7 +3,7 @@ import { message } from 'antd';
import CopyToClipboard from 'react-copy-to-clipboard';
import { presetDarkPalettes } from '@ant-design/colors';
const rgbToHex = rgbString => {
const rgbToHex = (rgbString) => {
const rgb = rgbString.match(/\d+/g);
let r = parseInt(rgb[0], 10).toString(16);
let g = parseInt(rgb[1], 10).toString(16);
@ -17,7 +17,7 @@ const rgbToHex = rgbString => {
export default class Palette extends React.Component {
componentDidMount() {
this.hexColors = {};
Object.keys(this.colorNodes).forEach(key => {
Object.keys(this.colorNodes).forEach((key) => {
const computedColor = getComputedStyle(this.colorNodes[key])['background-color'];
if (computedColor.includes('rgba')) {
this.hexColors[key] = computedColor;
@ -55,7 +55,7 @@ export default class Palette extends React.Component {
>
<div
key={i}
ref={node => {
ref={(node) => {
this.colorNodes[`${name}-${i}`] = node;
}}
className={`main-color-item palette-${name}-${i}`}
@ -90,4 +90,4 @@ export default class Palette extends React.Component {
Palette.defaultProps = {
color: { name: 'gray', count: 13 },
}
};

View File

@ -21,8 +21,10 @@ const useStyle = () => {
a& {
display: inline-block;
text-decoration: none;
margin-inline-start: 4px;
vertical-align: -2px;
margin-inline-start: 6px;
vertical-align: middle;
position: relative;
top: -2px;
${iconCls} {
display: block;

View File

@ -8,6 +8,6 @@ const SVGIcon = ({ color = 'currentColor' }) => (
</svg>
);
const ExternalLinkIcon = props => <Icon component={SVGIcon} {...props} />;
const ExternalLinkIcon = (props) => <Icon component={SVGIcon} {...props} />;
export default ExternalLinkIcon;

View File

@ -406,8 +406,50 @@ const GlobalStyles = () => {
}
.markdown .dumi-default-table {
table {
.component-api-table {
display: block;
td {
&:first-child {
width: 18%;
color: #595959;
font-weight: 600;
white-space: nowrap;
}
&:nth-child(2) {
width: 55%;
}
&:nth-child(3) {
width: 22%;
color: ${token['magenta-7']};
font-size: ${Math.max(token.fontSize - 1, 12)}px;
}
&:nth-child(4) {
width: 15%;
font-size: ${Math.max(token.fontSize - 1, 12)}px;
}
&:nth-child(5) {
width: 8%;
font-size: ${Math.max(token.fontSize - 1, 12)}px;
}
&:nth-last-child(3):first-child {
width: 38%;
}
&:nth-last-child(3):first-child ~ td:nth-last-child(2) {
width: 70%;
}
}
}
}
.markdown .dumi-default-table {
table {
margin: 2em 0;
overflow-x: auto;
overflow-y: hidden;
@ -447,38 +489,7 @@ const GlobalStyles = () => {
td {
&:first-child {
width: 18%;
color: #595959;
font-weight: 600;
white-space: nowrap;
}
&:nth-child(2) {
width: 55%;
}
&:nth-child(3) {
width: 22%;
color: ${token['magenta-7']};
font-size: ${Math.max(token.fontSize - 1, 12)}px;
}
&:nth-child(4) {
width: 15%;
font-size: ${Math.max(token.fontSize - 1, 12)}px;
}
&:nth-child(5) {
width: 8%;
font-size: ${Math.max(token.fontSize - 1, 12)}px;
}
&:nth-last-child(3):first-child {
width: 38%;
}
&:nth-last-child(3):first-child ~ td:nth-last-child(2) {
width: 70%;
min-width: 58px;
}
}
}
@ -1156,6 +1167,7 @@ const GlobalStyles = () => {
code {
background: ${token.colorBgContainer};
border: none;
box-shadow: unset;
}
}
@ -1268,6 +1280,7 @@ const GlobalStyles = () => {
width: 100%;
height: 100%;
color: #fff;
background: #1677ff;
line-height: 110px;
text-align: center;
opacity: 0;
@ -1276,7 +1289,6 @@ const GlobalStyles = () => {
}
&.copied::after {
top: -10px;
opacity: 1;
}
}
@ -1768,236 +1780,237 @@ const GlobalStyles = () => {
{/* Preview Image */}
<Global
styles={css`
.preview-image-boxes {
display: flex;
float: right;
clear: both;
width: 496px;
margin: 0 0 70px 64px;
.preview-image-boxes {
display: flex;
float: right;
clear: both;
width: 496px;
margin: 0 0 70px 64px;
&-with-carousel {
width: 420px;
&-with-carousel {
width: 420px;
.preview-image-box img {
padding: 0;
}
}
.preview-image-box img {
padding: 0;
}
}
.ant-row-rtl & {
float: left;
margin: 0 64px 70px 0;
}
}
.ant-row-rtl & {
float: left;
margin: 0 64px 70px 0;
}
}
.preview-image-boxes + .preview-image-boxes {
margin-top: -35px;
}
.preview-image-boxes + .preview-image-boxes {
margin-top: -35px;
}
.preview-image-box {
float: left;
width: 100%;
}
.preview-image-box {
float: left;
width: 100%;
}
.preview-image-box + .preview-image-box {
margin-left: 24px;
.preview-image-box + .preview-image-box {
margin-left: 24px;
.ant-row-rtl & {
margin-right: 24px;
margin-left: 0;
}
}
.ant-row-rtl & {
margin-right: 24px;
margin-left: 0;
}
}
.preview-image-wrapper {
position: relative;
display: inline-block;
width: 100%;
padding: 16px;
text-align: center;
background: #f2f4f5;
}
.preview-image-wrapper {
position: relative;
display: inline-block;
width: 100%;
padding: 16px;
text-align: center;
background: #f2f4f5;
}
.preview-image-wrapper.video {
display: block;
padding: 0;
background: 0;
}
.preview-image-wrapper.video {
display: block;
padding: 0;
background: 0;
}
.preview-image-wrapper video {
display: block;
width: 100%;
.preview-image-wrapper video {
display: block;
width: 100%;
+ svg {
position: absolute;
top: 0;
left: 0;
}
}
+ svg {
position: absolute;
top: 0;
left: 0;
}
}
.preview-image-wrapper.good::after {
position: absolute;
bottom: 0;
left: 0;
display: block;
width: 100%;
height: 3px;
background: @primary-color;
content: '';
}
.preview-image-wrapper.good::after {
position: absolute;
bottom: 0;
left: 0;
display: block;
width: 100%;
height: 3px;
background: @primary-color;
content: '';
}
.preview-image-wrapper.bad::after {
position: absolute;
bottom: 0;
left: 0;
display: block;
width: 100%;
height: 3px;
background: @error-color;
content: '';
}
.preview-image-wrapper.bad::after {
position: absolute;
bottom: 0;
left: 0;
display: block;
width: 100%;
height: 3px;
background: @error-color;
content: '';
}
.preview-image-title {
margin-top: 20px;
color: @site-text-color;
font-size: 12px;
}
.preview-image-title {
margin-top: 20px;
color: @site-text-color;
font-size: 12px;
}
.preview-image-description {
margin-top: 2px;
color: @site-text-color-secondary;
font-size: 12px;
line-height: 1.5;
}
.preview-image-description {
margin-top: 2px;
color: @site-text-color-secondary;
font-size: 12px;
line-height: 1.5;
}
.preview-image-description hr {
margin: 2px 0;
background: none;
border: 0;
}
.preview-image-description hr {
margin: 2px 0;
background: none;
border: 0;
}
.preview-image-box img {
max-width: 100%;
padding: 12px;
background: @body-background;
border-radius: @border-radius-base;
cursor: pointer;
transition: all 0.3s;
.preview-image-box img {
max-width: 100%;
padding: 12px;
background: @body-background;
border-radius: @border-radius-base;
cursor: pointer;
transition: all 0.3s;
&.no-padding {
padding: 0;
background: none;
}
}
&.no-padding {
padding: 0;
background: none;
}
}
.preview-image-boxes.preview-image-boxes-with-carousel img {
padding: 0;
box-shadow: 0 1px 0 0 #ddd, 0 3px 0 0 @body-background, 0 4px 0 0 #ddd, 0 6px 0 0 @body-background,
0 7px 0 0 #ddd;
}
.preview-image-boxes.preview-image-boxes-with-carousel img {
padding: 0;
box-shadow: 0 1px 0 0 #ddd, 0 3px 0 0 @body-background, 0 4px 0 0 #ddd,
0 6px 0 0 @body-background, 0 7px 0 0 #ddd;
}
.preview-image-box img:hover {
box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.3);
}
.preview-image-box img:hover {
box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.3);
}
.preview-img {
max-width: 496px !important;
clear: both;
float: right;
margin: 0 0 70px 64px;
background-color: #f2f4f5;
padding: 16px;
}
.preview-img {
float: right;
clear: both;
max-width: 496px !important;
margin: 0 0 70px 64px;
padding: 16px;
background-color: #f2f4f5;
}
.image-modal {
text-align: center;
.image-modal {
text-align: center;
&-container {
position: relative;
text-align: center;
}
&-container {
position: relative;
text-align: center;
}
.ant-carousel {
.slick-slider {
padding-bottom: 24px;
.ant-carousel {
.slick-slider {
padding-bottom: 24px;
img {
display: inline;
max-width: 100%;
}
}
img {
display: inline;
max-width: 100%;
}
}
.slick-dots {
bottom: 4px;
.slick-dots {
bottom: 4px;
li button {
background: #888;
}
}
}
li button {
background: #888;
}
}
}
.image-modal-single.slick-slider {
padding-bottom: 0;
}
.image-modal-single.slick-slider {
padding-bottom: 0;
}
.image-modal-single .slick-dots {
display: none !important;
}
}
.image-modal-single .slick-dots {
display: none !important;
}
}
.transition-video-player,
.motion-video-min {
float: right;
width: 600px;
padding: 0 0 70px 20px;
.transition-video-player,
.motion-video-min {
float: right;
width: 600px;
padding: 0 0 70px 20px;
.preview-image-wrapper {
padding: 0;
}
.preview-image-wrapper {
padding: 0;
}
.ant-row-rtl & {
float: left;
}
}
.ant-row-rtl & {
float: left;
}
}
.motion-video-min {
width: 390px;
}
.motion-video-min {
width: 390px;
}
.motion-principle-wrapper {
width: 100%;
max-width: 900px;
margin: 48px 0 24px;
}
.motion-principle-wrapper {
width: 100%;
max-width: 900px;
margin: 48px 0 24px;
}
.principle-wrapper {
width: 100%;
.principle-wrapper {
width: 100%;
.principle {
display: inline-block;
width: 100%;
min-height: 180px;
margin-right: 12.5%;
margin-bottom: 24px;
padding: 24px;
font-size: 24px;
text-align: center;
border: 1px solid #e8e8e8;
border-radius: 4px;
box-sizing: border-box;
.principle {
display: inline-block;
box-sizing: border-box;
width: 100%;
min-height: 180px;
margin-right: 12.5%;
margin-bottom: 24px;
padding: 24px;
font-size: 24px;
text-align: center;
border: 1px solid #e8e8e8;
border-radius: 4px;
&:last-child {
margin-right: 0;
}
&:last-child {
margin-right: 0;
}
h4 {
margin: 16px 0 8px;
}
h4 {
margin: 16px 0 8px;
}
p {
font-size: 12px;
line-height: 24px;
}
}
}`}
p {
font-size: 12px;
line-height: 24px;
}
}
}
`}
/>
<ColorStyle />

View File

@ -7,6 +7,6 @@ const SVGIcon = () => (
</svg>
);
const RiddleIcon = props => <Icon component={SVGIcon} {...props} />;
const RiddleIcon = (props) => <Icon component={SVGIcon} {...props} />;
export default RiddleIcon;

View File

@ -96,8 +96,8 @@ const DocLayout: FC = () => {
const content = useMemo(() => {
if (
['', '/'].some(path => path === pathname) ||
['/index'].some(path => pathname.startsWith(path))
['', '/'].some((path) => path === pathname) ||
['/index'].some((path) => pathname.startsWith(path))
) {
return (
<>

View File

@ -14,7 +14,7 @@ const GlobalLayout: FC = () => {
const contextValue = React.useMemo<ThemeContextProps>(
() => ({
theme,
setTheme: newTheme => {
setTheme: (newTheme) => {
setTheme(newTheme);
localStorage.setItem(
ANT_DESIGN_SITE_THEME,

View File

@ -117,10 +117,10 @@ export default () => {
<div css={[styles.affixTabs, fixedId && styles.affixTabsFixed]} ref={containerRef}>
<Tabs
activeKey={fixedId || undefined}
onChange={key => {
onChange={(key) => {
scrollToId(key);
}}
items={idsRef.current.map(id => ({
items={idsRef.current.map((id) => ({
key: id,
label: <span style={{ textTransform: 'capitalize' }}>{id.replace(/-/g, ' ')}</span>,
}))}

View File

@ -123,16 +123,6 @@
"app.docs.components.icon.category.data": "Data Icons",
"app.docs.components.icon.category.other": "Application Icons",
"app.docs.components.icon.category.logo": "Brand and Logos",
"app.docs.components.icon.pic-searcher.intro": "AI Search by image is online, you are welcome to use it! 🎉",
"app.docs.components.icon.pic-searcher.title": "Search by image",
"app.docs.components.icon.pic-searcher.upload-text": "Click, drag, or paste file to this area to upload",
"app.docs.components.icon.pic-searcher.upload-hint": "We will find the best matching icon based on the image provided",
"app.docs.components.icon.pic-searcher.server-error": "Predict service is temporarily unavailable",
"app.docs.components.icon.pic-searcher.matching": "Matching...",
"app.docs.components.icon.pic-searcher.modelloading": "Model is loading...",
"app.docs.components.icon.pic-searcher.result-tip": "Matched the following icons for you:",
"app.docs.components.icon.pic-searcher.th-icon": "Icon",
"app.docs.components.icon.pic-searcher.th-score": "Probability",
"app.docs.resource.design": "Design",
"app.docs.resource.develop": "Develop",
"app.components.overview.search": "Search in components",

View File

@ -122,16 +122,6 @@
"app.docs.components.icon.category.data": "数据类图标",
"app.docs.components.icon.category.other": "网站通用图标",
"app.docs.components.icon.category.logo": "品牌和标识",
"app.docs.components.icon.pic-searcher.intro": "AI 截图搜索上线了,快来体验吧!🎉",
"app.docs.components.icon.pic-searcher.title": "上传图片搜索图标",
"app.docs.components.icon.pic-searcher.upload-text": "点击/拖拽/粘贴上传图片",
"app.docs.components.icon.pic-searcher.upload-hint": "我们会通过上传的图片进行匹配,得到最相似的图标",
"app.docs.components.icon.pic-searcher.server-error": "识别服务暂不可用",
"app.docs.components.icon.pic-searcher.matching": "匹配中...",
"app.docs.components.icon.pic-searcher.modelloading": "神经网络模型加载中...",
"app.docs.components.icon.pic-searcher.result-tip": "为您匹配到以下图标:",
"app.docs.components.icon.pic-searcher.th-icon": "图标",
"app.docs.components.icon.pic-searcher.th-score": "匹配度",
"app.docs.resource.design": "设计",
"app.docs.resource.develop": "开发",
"app.components.overview.search": "搜索组件",

View File

@ -178,32 +178,36 @@ const Content: FC<{ children: ReactNode }> = ({ children }) => {
)}
</Typography.Title>
{children}
<ContributorsList
css={styles.contributorsList}
fileName={meta.frontmatter.filename ?? ''}
renderItem={(item, loading) =>
loading ? (
<Avatar style={{ opacity: 0.3 }} />
) : (
item && (
<Tooltip
title={`${formatMessage({ id: 'app.content.contributors' })}: ${item.username}`}
key={item.username}
>
<a
href={`https://github.com/${item.username}`}
target="_blank"
rel="noopener noreferrer"
{meta.frontmatter.filename && (
<ContributorsList
css={styles.contributorsList}
fileName={meta.frontmatter.filename}
renderItem={(item, loading) =>
loading ? (
<Avatar style={{ opacity: 0.3 }} />
) : (
item && (
<Tooltip
title={`${formatMessage({ id: 'app.content.contributors' })}: ${
item.username
}`}
key={item.username}
>
<Avatar src={item.url}>{item.username}</Avatar>
</a>
</Tooltip>
<a
href={`https://github.com/${item.username}`}
target="_blank"
rel="noopener noreferrer"
>
<Avatar src={item.url}>{item.username}</Avatar>
</a>
</Tooltip>
)
)
)
}
repo="ant-design"
owner="ant-design"
/>
}
repo="ant-design"
owner="ant-design"
/>
)}
</article>
<PrevAndNext />
<Footer />

View File

@ -15,7 +15,7 @@ import {
TwitterOutlined,
UsergroupAddOutlined,
ZhihuOutlined,
YuqueOutlined,
YuqueFilled,
} from '@ant-design/icons';
import useLocation from '../../../hooks/useLocation';
import { css } from '@emotion/react';
@ -129,7 +129,7 @@ const Footer = () => {
openExternal: true,
},
{
title: 'Dumi',
title: 'dumi',
description: <FormattedMessage id="app.footer.dumi" />,
url: 'https://d.umijs.org',
openExternal: true,
@ -181,7 +181,7 @@ const Footer = () => {
openExternal: true,
},
{
icon: <YuqueOutlined style={{ color: '#00b96b' }} />,
icon: <YuqueFilled style={{ color: '#00b96b' }} />,
title: <FormattedMessage id="app.footer.yuque.repo" />,
url: 'https://yuque.com/ant-design/ant-design',
openExternal: true,
@ -189,7 +189,7 @@ const Footer = () => {
{
icon: <ZhihuOutlined style={{ color: '#0084ff' }} />,
title: <FormattedMessage id="app.footer.zhihu" />,
url: 'http://zhuanlan.zhihu.com/antdesign',
url: 'https://www.zhihu.com/column/c_1564262000561106944',
openExternal: true,
},
{

View File

@ -38,7 +38,8 @@ export function getEcosystemGroup(): Exclude<MenuProps['items'], undefined> {
<a href="http://ng.ant.design" target="_blank" rel="noopener noreferrer">
Ant Design of Angular
<span style={smallStyle}>
(<FormattedMessage id="app.implementation.community" />)
(
<FormattedMessage id="app.implementation.community" />)
</span>
</a>
),
@ -49,7 +50,8 @@ export function getEcosystemGroup(): Exclude<MenuProps['items'], undefined> {
<a href="http://antdv.com" target="_blank" rel="noopener noreferrer">
Ant Design of Vue
<span style={smallStyle}>
(<FormattedMessage id="app.implementation.community" />)
(
<FormattedMessage id="app.implementation.community" />)
</span>
</a>
),

View File

@ -1,3 +1,6 @@
const chineseMirror =
typeof location !== 'undefined' && location.hostname.includes('.antgroup.com');
export default {
categoryOrder: {
'Ant Design': 0,
@ -43,7 +46,7 @@ export default {
'Template Document': 3,
},
docVersions: {
'4.x': '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',

View File

@ -29,11 +29,11 @@ export function getMenuItems(
categoryOrder: Orders,
typeOrder: Orders,
) {
const menuMeta = moduleData.map(item => item.meta).filter(meta => !meta.skip);
const menuMeta = moduleData.map((item) => item.meta).filter((meta) => !meta.skip);
const menuItems: Meta[] = [];
const sortFn = (a: Meta, b: Meta) => (a.order || 0) - (b.order || 0);
menuMeta.sort(sortFn).forEach(meta => {
menuMeta.sort(sortFn).forEach((meta) => {
// Format
if (meta.category) {
meta.category = meta.category[locale] || meta.category;
@ -52,7 +52,7 @@ export function getMenuItems(
// Component
if (meta.category === 'Components' && meta.type) {
let type = menuItems.find(i => i.title === meta.type);
let type = menuItems.find((i) => i.title === meta.type);
if (!type) {
type = {
type: 'type',
@ -67,7 +67,7 @@ export function getMenuItems(
return;
}
let group = menuItems.find(i => i.title === meta.category);
let group = menuItems.find((i) => i.title === meta.category);
if (!group) {
group = {
@ -82,7 +82,7 @@ export function getMenuItems(
group.children = group.children || [];
if (meta.type) {
let type = group.children.filter(i => i.title === meta.type)[0];
let type = group.children.filter((i) => i.title === meta.type)[0];
if (!type) {
type = {
type: 'type',
@ -100,7 +100,7 @@ export function getMenuItems(
});
function nestSort(list: Meta[]): Meta[] {
return list.sort(sortFn).map(item => {
return list.sort(sortFn).map((item) => {
if (item.children) {
return {
...item,
@ -201,7 +201,7 @@ export function getMetaDescription(jml?: any[] | null) {
}
const paragraph = flattenDeep(
jml
.filter(item => {
.filter((item) => {
if (Array.isArray(item)) {
const [tag] = item;
return tag === 'p';
@ -209,14 +209,14 @@ export function getMetaDescription(jml?: any[] | null) {
return false;
})
// ['p', ['code', 'aa'], 'bb'] => ['p', 'aabb']
.map(item => {
.map((item) => {
const [tag, ...others] = flatten(item);
const content = others
.filter(other => typeof other === 'string' && !COMMON_TAGS.includes(other))
.filter((other) => typeof other === 'string' && !COMMON_TAGS.includes(other))
.join('');
return [tag, content];
}),
).find(p => p && typeof p === 'string' && !COMMON_TAGS.includes(p)) as string;
).find((p) => p && typeof p === 'string' && !COMMON_TAGS.includes(p)) as string;
return paragraph;
}

View File

@ -5,7 +5,7 @@ on:
create
permissions:
contents: read
contents: write
jobs:
setup:
@ -66,5 +66,6 @@ jobs:
- name: deploy
uses: peaceiris/actions-gh-pages@v3
with:
deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./_site
force_orphan: true

View File

@ -8,6 +8,7 @@ on:
- feature
- 2.x-stable
- 3.x-stable
- 4.x-stable
create:
permissions:

View File

@ -250,6 +250,12 @@ jobs:
path: node_modules
key: node_modules-${{ hashFiles('**/package-temp-dir/package-lock.json') }}
- name: cache lib
uses: actions/cache@v3
with:
path: lib
key: lib-${{ github.sha }}
- name: cache es
uses: actions/cache@v3
with:
@ -258,6 +264,9 @@ jobs:
- name: compile
run: npm run compile
- name: check
run: node ./tests/dekko/lib.test.js
needs: setup
compiled-module-test:
@ -266,7 +275,7 @@ jobs:
strategy:
matrix:
react: ['16', '17', '18']
module: [es]
module: [lib, es]
shard: ['1/2', '2/2']
env:
REACT: ${{ matrix.react }}

View File

@ -3,7 +3,6 @@
"trailingComma": "all",
"printWidth": 100,
"proseWrap": "never",
"arrowParens": "avoid",
"overrides": [
{
"files": ".prettierrc",

View File

@ -19,13 +19,13 @@ timeline: true
`2022-11-18`
- 🏆 Ant Design 5.0.0 is out!
🏆 Ant Design 5.0.0 is released, see our [release note](https://github.com/ant-design/ant-design/issues/38671) for more details.
**Read it before migration**
#### Read it before migration
- 🌟 If you want to migrate to Ant Design 5.0, please check [V4 to V5](/docs/react/migration-v5).
🌟 If you want to migrate to Ant Design 5.0, please check [V4 to V5](/docs/react/migration-v5).
**Major Changes**
#### Major Changes
- 🔥 New Components
- 🔥 FloatButton component, and refactor BackTop as child component of FloatButton. [#37520](https://github.com/ant-design/ant-design/pull/37520) [@li-jia-nan](https://github.com/li-jia-nan)

View File

@ -19,13 +19,13 @@ timeline: true
`2022-11-18`
- 🏆 Ant Design 5.0.0 已发布!欢迎阅读我们的 [发布文档](https://www.yuque.com/ant-design/ant-design/cy5nfvdo8oidvwmz)。
🏆 Ant Design 5.0.0 已发布!欢迎阅读我们的 [发布文档](https://www.yuque.com/ant-design/ant-design/cy5nfvdo8oidvwmz)。
**升级必读**
#### 升级必读
- 🌟 如果你想升级到 Ant Design 5.0,请仔细查阅我们的[迁移文档](/docs/react/migration-v5-cn)。
🌟 如果你想升级到 Ant Design 5.0,请仔细查阅我们的[迁移文档](/docs/react/migration-v5-cn)。
**主要变化**
#### 主要变化
- 🔥 新增组件
- 🔥 FloatButton 悬浮按钮,原 BackTop 移至 FloatButton 子组件。[#37520](https://github.com/ant-design/ant-design/pull/37520) [@li-jia-nan](https://github.com/li-jia-nan)

View File

@ -62,7 +62,7 @@
- サーバーサイド レンダリング
- [Electron](https://www.electronjs.org/)
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Electron |
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Electron |
| --- | --- | --- | --- | --- |
| Edge | 直近の 2 バージョン | 直近の 2 バージョン | 直近の 2 バージョン | 直近の 2 バージョン |

View File

@ -62,7 +62,7 @@ Uma solução empresarial de design e biblioteca UI para React.
- Renderização no lado do servidor (server-side)
- [Electron](https://www.electronjs.org/)
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png" alt="Opera" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Opera | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Electron |
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png" alt="Opera" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Opera | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Electron |
| --- | --- | --- | --- | --- | --- |
| Edge | últimas 2 versões | últimas 2 versões | últimas 2 versões | últimas 2 versões | últimas 2 versões |

View File

@ -62,7 +62,7 @@ Un lenguaje de diseño de interfaz de usuario de clase empresarial y una bibliot
- Representación del lado del servidor
- [Electron](https://www.electronjs.org/)
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Electron |
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Electron |
| --- | --- | --- | --- | --- |
| Edge | últimas 2 versiones | últimas 2 versiones | últimas 2 versiones | últimas 2 versiones |

View File

@ -62,7 +62,7 @@
- Рендеринг на стороні сервера (SSR)
- [Electron](https://www.electronjs.org/)
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Electron |
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Electron |
| --- | --- | --- | --- | --- |
| Edge | 2 останні версії | 2 останні версії | 2 останні версії | 2 останні версії |

View File

@ -62,7 +62,7 @@
- 支持服务端渲染。
- [Electron](https://www.electronjs.org/)
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Electron |
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Electron |
| --- | --- | --- | --- | --- |
| Edge | last 2 versions | last 2 versions | last 2 versions | last 2 versions |

View File

@ -12,9 +12,9 @@ An enterprise-class UI design language and React UI library.
[![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] [![NPM version][npm-image]][npm-url] [![NPM downloads][download-image]][download-url]
[![Renovate status][renovate-image]][renovate-dashboard-url] [![Total alerts][lgtm-image]][lgtm-url] [![][bundlesize-js-image]][unpkg-js-url]
[![Total alerts][lgtm-image]][lgtm-url] [![][bundlephobia-image]][bundlephobia-url] [![][bundlesize-js-image]][unpkg-js-url] [![FOSSA Status][fossa-image]][fossa-url]
[![Follow Twitter][twitter-image]][twitter-url] [![FOSSA Status][fossa-image]][fossa-url] [![Discussions][discussions-image]][discussions-url] [![][issues-helper-image]][issues-helper-url] [![Issues need help][help-wanted-image]][help-wanted-url]
[![Follow Twitter][twitter-image]][twitter-url] [![Renovate status][renovate-image]][renovate-dashboard-url] [![][issues-helper-image]][issues-helper-url] [![Issues need help][help-wanted-image]][help-wanted-url]
[npm-image]: http://img.shields.io/npm/v/antd.svg?style=flat-square
[npm-url]: http://npmjs.org/package/antd
@ -30,12 +30,12 @@ An enterprise-class UI design language and React UI library.
[fossa-url]: https://app.fossa.io/projects/git%2Bgithub.com%2Fant-design%2Fant-design?ref=badge_shield
[help-wanted-image]: https://flat.badgen.net/github/label-issues/ant-design/ant-design/help%20wanted/open
[help-wanted-url]: https://github.com/ant-design/ant-design/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22
[twitter-image]: https://img.shields.io/twitter/follow/AntDesignUI.svg?label=Ant%20Design&style=social
[twitter-image]: https://badgen.net/twitter/follow/antdesignui?style=flat-square
[twitter-url]: https://twitter.com/AntDesignUI
[discussions-image]: https://img.shields.io/badge/discussions-on%20github-blue?style=flat-square
[discussions-url]: https://github.com/ant-design/ant-design/discussions
[bundlesize-js-image]: https://img.badgesize.io/https:/unpkg.com/antd/dist/antd.min.js?label=antd.min.js&compression=gzip&style=flat-square
[unpkg-js-url]: https://unpkg.com/browse/antd/dist/antd.min.js
[bundlephobia-image]: https://badgen.net/bundlephobia/minzip/antd?style=flat-square
[bundlephobia-url]: https://bundlephobia.com/package/antd
[issues-helper-image]: https://img.shields.io/badge/using-issues--helper-orange?style=flat-square
[issues-helper-url]: https://github.com/actions-cool/issues-helper
[renovate-image]: https://img.shields.io/badge/renovate-enabled-brightgreen.svg?style=flat-square
@ -62,7 +62,7 @@ English | [Português](./README-pt_BR.md) | [简体中文](./README-zh_CN.md) |
- Server-side Rendering
- [Electron](https://www.electronjs.org/)
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Electron |
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/electron/electron_48x48.png" alt="Electron" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Electron |
| --- | --- | --- | --- | --- |
| Edge | last 2 versions | last 2 versions | last 2 versions | last 2 versions |

View File

@ -21,7 +21,7 @@ describe('node', () => {
// Find the component exist demo test file
const files = glob.sync(`./components/*/__tests__/demo.test.@(j|t)s?(x)`);
files.forEach(componentTestFile => {
files.forEach((componentTestFile) => {
const componentName = componentTestFile.match(/components\/([^/]*)\//)![1];
// Test for ssr
@ -32,9 +32,9 @@ describe('node', () => {
require(`../../${componentTestFile}`); // eslint-disable-line global-require, import/no-dynamic-require
const option = (global as any).testConfig?.[componentName];
demoList.forEach(demoFile => {
demoList.forEach((demoFile) => {
const skip: string[] = option?.skip || [];
const test = skip.some(skipMarkdown => demoFile.includes(skipMarkdown)) ? it.skip : it;
const test = skip.some((skipMarkdown) => demoFile.includes(skipMarkdown)) ? it.skip : it;
test(demoFile, () => {
const Demo = require(`../../${demoFile}`).default; // eslint-disable-line global-require, import/no-dynamic-require

View File

@ -20,7 +20,7 @@ function isThenable(thing?: PromiseLike<any>): boolean {
return !!(thing && !!thing.then);
}
const ActionButton: React.FC<ActionButtonProps> = props => {
const ActionButton: React.FC<ActionButtonProps> = (props) => {
const clickedRef = React.useRef<boolean>(false);
const ref = React.useRef<HTMLInputElement>(null);
const [loading, setLoading] = useState<ButtonProps['loading']>(false);

View File

@ -31,7 +31,7 @@ export default function genPurePanel<ComponentProps extends BaseProps>(
setOpen(true);
if (typeof ResizeObserver !== 'undefined') {
const resizeObserver = new ResizeObserver(entries => {
const resizeObserver = new ResizeObserver((entries) => {
const element: HTMLDivElement = entries[0].target as any;
setPopupHeight(element.offsetHeight + 8);
setPopupWidth(element.offsetWidth);

View File

@ -6,10 +6,7 @@ import { waitFakeTimer, render, fireEvent } from '../../../tests/utils';
import getDataOrAriaProps from '../getDataOrAriaProps';
import delayRaf from '../raf';
import { isStyleSupport } from '../styleChecker';
import {
throttleByAnimationFrame,
throttleByAnimationFrameDecorator,
} from '../throttleByAnimationFrame';
import throttleByAnimationFrame from '../throttleByAnimationFrame';
import TransButton from '../transButton';
describe('Test utils function', () => {
@ -49,22 +46,6 @@ describe('Test utils function', () => {
expect(callback).not.toHaveBeenCalled();
});
it('throttleByAnimationFrameDecorator should works', async () => {
const callbackFn = jest.fn();
class Test {
@throttleByAnimationFrameDecorator()
callback() {
callbackFn();
}
}
const test = new Test();
test.callback();
test.callback();
test.callback();
await waitFakeTimer();
expect(callbackFn).toHaveBeenCalledTimes(1);
});
});
describe('getDataOrAriaProps', () => {

View File

@ -1,6 +1,6 @@
import * as React from 'react';
export default function useForceUpdate() {
const [, forceUpdate] = React.useReducer(x => x + 1, 0);
const [, forceUpdate] = React.useReducer((x) => x + 1, 0);
return forceUpdate;
}

View File

@ -8,12 +8,12 @@ export default function usePatchElement(): [
const patchElement = React.useCallback((element: React.ReactElement) => {
// append a new element to elements (and create a new ref)
setElements(originElements => [...originElements, element]);
setElements((originElements) => [...originElements, element]);
// return a function that removes the new element out of elements (and create a new ref)
// it works a little like useEffect
return () => {
setElements(originElements => originElements.filter(ele => ele !== element));
setElements((originElements) => originElements.filter((ele) => ele !== element));
};
}, []);

View File

@ -4,11 +4,11 @@ import { tuple } from './type';
// ================== Collapse Motion ==================
const getCollapsedHeight: MotionEventHandler = () => ({ height: 0, opacity: 0 });
const getRealHeight: MotionEventHandler = node => {
const getRealHeight: MotionEventHandler = (node) => {
const { scrollHeight } = node;
return { height: scrollHeight, opacity: 1 };
};
const getCurrentHeight: MotionEventHandler = node => ({ height: node ? node.offsetHeight : 0 });
const getCurrentHeight: MotionEventHandler = (node) => ({ height: node ? node.offsetHeight : 0 });
const skipOpacityTransition: MotionEndEventHandler = (_, event: MotionEvent) =>
event?.deadline === true || (event as TransitionEvent).propertyName === 'height';

View File

@ -94,7 +94,7 @@ export default function getPlacements(config: PlacementsConfig) {
offset: [-4, verticalArrowShift + arrowWidth],
},
};
Object.keys(placementMap).forEach(key => {
Object.keys(placementMap).forEach((key) => {
placementMap[key] = arrowPointAtCenter
? {
...placementMap[key],

View File

@ -28,7 +28,7 @@ const responsiveObserve = {
},
dispatch(pointMap: ScreenMap) {
screens = pointMap;
subscribers.forEach(func => func(screens));
subscribers.forEach((func) => func(screens));
return subscribers.size >= 1;
},
subscribe(func: SubscribeFunc): number {

View File

@ -1,6 +1,10 @@
import raf from 'rc-util/lib/raf';
export function throttleByAnimationFrame<T extends unknown[]>(fn: (...args: T) => void) {
type throttledFn = (...args: any[]) => void;
type throttledCancelFn = { cancel: () => void };
function throttleByAnimationFrame<T extends any[]>(fn: (...args: T) => void) {
let requestId: number | null;
const later = (args: T) => () => {
@ -8,10 +12,7 @@ export function throttleByAnimationFrame<T extends unknown[]>(fn: (...args: T) =
fn(...args);
};
const throttled: {
(...args: T): void;
cancel: () => void;
} = (...args: T) => {
const throttled: throttledFn & throttledCancelFn = (...args: T) => {
if (requestId == null) {
requestId = raf(later(args));
}
@ -25,32 +26,4 @@ export function throttleByAnimationFrame<T extends unknown[]>(fn: (...args: T) =
return throttled;
}
export function throttleByAnimationFrameDecorator() {
return function throttle(target: any, key: string, descriptor: any) {
const fn = descriptor.value;
let definingProperty = false;
return {
configurable: true,
get() {
// In IE11 calling Object.defineProperty has a side-effect of evaluating the
// getter for the property which is being replaced. This causes infinite
// recursion and an "Out of stack space" error.
// eslint-disable-next-line no-prototype-builtins
if (definingProperty || this === target.prototype || this.hasOwnProperty(key)) {
/* istanbul ignore next */
return fn;
}
const boundFn = throttleByAnimationFrame(fn.bind(this));
definingProperty = true;
Object.defineProperty(this, key, {
value: boundFn,
configurable: true,
writable: true,
});
definingProperty = false;
return boundFn;
},
};
};
}
export default throttleByAnimationFrame;

View File

@ -22,14 +22,14 @@ const inlineStyle: React.CSSProperties = {
};
const TransButton = React.forwardRef<HTMLDivElement, TransButtonProps>((props, ref) => {
const onKeyDown: React.KeyboardEventHandler<HTMLDivElement> = event => {
const onKeyDown: React.KeyboardEventHandler<HTMLDivElement> = (event) => {
const { keyCode } = event;
if (keyCode === KeyCode.ENTER) {
event.preventDefault();
}
};
const onKeyUp: React.KeyboardEventHandler<HTMLDivElement> = event => {
const onKeyUp: React.KeyboardEventHandler<HTMLDivElement> = (event) => {
const { keyCode } = event;
const { onClick } = props;
if (keyCode === KeyCode.ENTER && onClick) {

View File

@ -12,7 +12,7 @@ interface WaveToken extends AliasToken {
clickAnimatingWithoutExtraNodeTrueAfter: string;
}
const genWaveStyle: GenerateStyle<WaveToken> = token => {
const genWaveStyle: GenerateStyle<WaveToken> = (token) => {
const waveEffect = new Keyframes('waveEffect', {
'100%': {
boxShadow: `0 0 0 6px var(--antd-wave-shadow-color)`,

View File

@ -33,7 +33,7 @@ class AffixMounter extends React.Component<{
const { getInstance, ...restProps } = this.props;
return (
<div
ref={node => {
ref={(node) => {
this.container = node!;
}}
className="container"
@ -41,7 +41,7 @@ class AffixMounter extends React.Component<{
<Affix
className="fixed"
target={this.getTarget}
ref={ele => {
ref={(ele) => {
getInstance?.(ele!);
}}
{...restProps}
@ -163,7 +163,7 @@ describe('Affix Render', () => {
let affixInstance: InternalAffixClass;
const { rerender } = render(
<Affix
ref={node => {
ref={(node) => {
affixInstance = node as InternalAffixClass;
}}
target={getTarget}
@ -173,7 +173,7 @@ describe('Affix Render', () => {
);
rerender(
<Affix
ref={node => {
ref={(node) => {
affixInstance = node as InternalAffixClass;
}}
target={() => null}
@ -224,7 +224,7 @@ describe('Affix Render', () => {
const { rerender } = render(
<AffixMounter
getInstance={inst => {
getInstance={(inst) => {
affixInstance = inst;
}}
offsetBottom={0}
@ -235,7 +235,7 @@ describe('Affix Render', () => {
rerender(
<AffixMounter
getInstance={inst => {
getInstance={(inst) => {
affixInstance = inst;
}}
offsetBottom={0}
@ -256,7 +256,7 @@ describe('Affix Render', () => {
let affixInstance: InternalAffixClass | null = null;
render(
<AffixMounter
getInstance={inst => {
getInstance={(inst) => {
affixInstance = inst;
}}
offsetBottom={0}
@ -275,7 +275,7 @@ describe('Affix Render', () => {
[
'.ant-btn', // inner
'.fixed', // outer
].forEach(selector => {
].forEach((selector) => {
it(`trigger listener when size change: ${selector}`, async () => {
const updateCalled = jest.fn();
const { container } = render(

View File

@ -2,7 +2,7 @@ import React from 'react';
import { Affix, Button } from 'antd';
const App: React.FC = () => (
<Affix offsetTop={120} onChange={affixed => console.log(affixed)}>
<Affix offsetTop={120} onChange={(affixed) => console.log(affixed)}>
<Button>120px to affix top</Button>
</Affix>
);

View File

@ -4,7 +4,7 @@ import omit from 'rc-util/lib/omit';
import * as React from 'react';
import type { ConfigConsumerProps } from '../config-provider';
import { ConfigContext } from '../config-provider';
import { throttleByAnimationFrameDecorator } from '../_util/throttleByAnimationFrame';
import throttleByAnimationFrame from '../_util/throttleByAnimationFrame';
import useStyle from './style';
import {
@ -126,9 +126,9 @@ class Affix extends React.Component<InternalAffixProps, AffixState> {
componentWillUnmount() {
clearTimeout(this.timeout);
removeObserveTarget(this);
(this.updatePosition as any).cancel();
this.updatePosition.cancel();
// https://github.com/ant-design/ant-design/issues/22683
(this.lazyUpdatePosition as any).cancel();
this.lazyUpdatePosition.cancel();
}
getOffsetTop = () => {
@ -228,14 +228,11 @@ class Affix extends React.Component<InternalAffixProps, AffixState> {
}
};
// Handle realign logic
@throttleByAnimationFrameDecorator()
updatePosition() {
updatePosition = throttleByAnimationFrame(() => {
this.prepareMeasure();
}
});
@throttleByAnimationFrameDecorator()
lazyUpdatePosition() {
lazyUpdatePosition = throttleByAnimationFrame(() => {
const targetFunc = this.getTargetFunc();
const { affixStyle } = this.state;
@ -262,7 +259,7 @@ class Affix extends React.Component<InternalAffixProps, AffixState> {
// Directly call prepare measure since it's already throttled.
this.prepareMeasure();
}
});
// =================== Render ===================
render() {
@ -288,21 +285,11 @@ class Affix extends React.Component<InternalAffixProps, AffixState> {
}
return (
<ResizeObserver
onResize={() => {
this.updatePosition();
}}
>
<ResizeObserver onResize={this.updatePosition}>
<div {...props} ref={this.savePlaceholderNode}>
{affixStyle && <div style={placeholderStyle} aria-hidden="true" />}
<div className={className} ref={this.saveFixedNode} style={affixStyle}>
<ResizeObserver
onResize={() => {
this.updatePosition();
}}
>
{children}
</ResizeObserver>
<ResizeObserver onResize={this.updatePosition}>{children}</ResizeObserver>
</div>
</div>
</ResizeObserver>
@ -321,7 +308,6 @@ const AffixFC = React.forwardRef<Affix, AffixProps>((props, ref) => {
const AffixProps: InternalAffixProps = {
...props,
affixPrefixCls,
rootClassName: hashId,
};

View File

@ -19,7 +19,7 @@ const genSharedAffixStyle: GenerateStyle<AffixToken> = (token): CSSObject => {
};
// ============================== Export ==============================
export default genComponentStyleHook('Affix', token => {
export default genComponentStyleHook('Affix', (token) => {
const affixToken = mergeToken<AffixToken>(token, {
zIndexPopup: token.zIndexBase + 10,
});

View File

@ -56,7 +56,7 @@ export function addObserveTarget<T>(target: HTMLElement | Window | null, affix?:
return;
}
let entity: ObserverEntity | undefined = observerEntities.find(item => item.target === target);
let entity: ObserverEntity | undefined = observerEntities.find((item) => item.target === target);
if (entity) {
entity.affixList.push(affix);
@ -69,9 +69,9 @@ export function addObserveTarget<T>(target: HTMLElement | Window | null, affix?:
observerEntities.push(entity);
// Add listener
TRIGGER_EVENTS.forEach(eventName => {
TRIGGER_EVENTS.forEach((eventName) => {
entity!.eventHandlers[eventName] = addEventListener(target, eventName, () => {
entity!.affixList.forEach(targetAffix => {
entity!.affixList.forEach((targetAffix) => {
targetAffix.lazyUpdatePosition();
});
});
@ -80,19 +80,19 @@ export function addObserveTarget<T>(target: HTMLElement | Window | null, affix?:
}
export function removeObserveTarget<T>(affix: T): void {
const observerEntity = observerEntities.find(oriObserverEntity => {
const hasAffix = oriObserverEntity.affixList.some(item => item === affix);
const observerEntity = observerEntities.find((oriObserverEntity) => {
const hasAffix = oriObserverEntity.affixList.some((item) => item === affix);
if (hasAffix) {
oriObserverEntity.affixList = oriObserverEntity.affixList.filter(item => item !== affix);
oriObserverEntity.affixList = oriObserverEntity.affixList.filter((item) => item !== affix);
}
return hasAffix;
});
if (observerEntity && observerEntity.affixList.length === 0) {
observerEntities = observerEntities.filter(item => item !== observerEntity);
observerEntities = observerEntities.filter((item) => item !== observerEntity);
// Remove listener
TRIGGER_EVENTS.forEach(eventName => {
TRIGGER_EVENTS.forEach((eventName) => {
const handler = observerEntity.eventHandlers[eventName];
if (handler && handler.remove) {
handler.remove();

View File

@ -61,7 +61,7 @@ interface IconNodeProps {
description: AlertProps['description'];
}
const IconNode: React.FC<IconNodeProps> = props => {
const IconNode: React.FC<IconNodeProps> = (props) => {
const { icon, prefixCls, type } = props;
const iconType = iconMapFilled[type!] || null;
if (icon) {
@ -82,7 +82,7 @@ interface CloseIconProps {
handleClose: AlertProps['onClose'];
}
const CloseIcon: React.FC<CloseIconProps> = props => {
const CloseIcon: React.FC<CloseIconProps> = (props) => {
const { isClosable, closeText, prefixCls, closeIcon, handleClose } = props;
return isClosable ? (
<button type="button" onClick={handleClose} className={`${prefixCls}-close-icon`} tabIndex={0}>
@ -91,11 +91,11 @@ const CloseIcon: React.FC<CloseIconProps> = props => {
) : null;
};
interface AlertInterface extends React.FC<AlertProps> {
type CompoundedComponent = React.FC<AlertProps> & {
ErrorBoundary: typeof ErrorBoundary;
}
};
const Alert: AlertInterface = ({
const Alert: CompoundedComponent = ({
description,
prefixCls: customizePrefixCls,
message,
@ -162,7 +162,7 @@ const Alert: AlertInterface = ({
motionName={`${prefixCls}-motion`}
motionAppear={false}
motionEnter={false}
onLeaveStart={node => ({
onLeaveStart={(node) => ({
maxHeight: node.offsetHeight,
})}
onLeaveEnd={afterClose}

View File

@ -14,7 +14,7 @@ export interface AnchorLinkProps {
className?: string;
}
const AnchorLink: React.FC<AnchorLinkProps> = props => {
const AnchorLink: React.FC<AnchorLinkProps> = (props) => {
const { href = '#', title, prefixCls: customizePrefixCls, children, className, target } = props;
const context = React.useContext<AntAnchor | undefined>(AnchorContext);

View File

@ -6,11 +6,11 @@ export type { AnchorLinkProps } from './AnchorLink';
type InternalAnchorType = typeof InternalAnchor;
interface AnchorInterface extends InternalAnchorType {
type CompoundedComponent = InternalAnchorType & {
Link: typeof AnchorLink;
}
};
const Anchor = InternalAnchor as AnchorInterface;
const Anchor = InternalAnchor as CompoundedComponent;
Anchor.Link = AnchorLink;
export default Anchor;

View File

@ -679,20 +679,20 @@ exports[`renders ./components/auto-complete/demo/form-debug.tsx extend context c
<ellipse
cx="32"
cy="33"
fill="#F5F5F5"
fill="#f5f5f5"
rx="32"
ry="7"
/>
<g
fill-rule="nonzero"
stroke="#D9D9D9"
stroke="#d9d9d9"
>
<path
d="M55 12.76L44.854 1.258C44.367.474 43.656 0 42.907 0H21.093c-.749 0-1.46.474-1.947 1.257L9 12.761V22h46v-9.24z"
/>
<path
d="M41.613 15.931c0-1.605.994-2.93 2.227-2.931H55v18.137C55 33.26 53.68 35 52.05 35h-40.1C10.32 35 9 33.259 9 31.137V13h11.16c1.233 0 2.227 1.323 2.227 2.928v.022c0 1.605 1.005 2.901 2.237 2.901h14.752c1.232 0 2.237-1.308 2.237-2.913v-.007z"
fill="#FAFAFA"
fill="#fafafa"
/>
</g>
</g>
@ -827,20 +827,20 @@ exports[`renders ./components/auto-complete/demo/form-debug.tsx extend context c
<ellipse
cx="32"
cy="33"
fill="#F5F5F5"
fill="#f5f5f5"
rx="32"
ry="7"
/>
<g
fill-rule="nonzero"
stroke="#D9D9D9"
stroke="#d9d9d9"
>
<path
d="M55 12.76L44.854 1.258C44.367.474 43.656 0 42.907 0H21.093c-.749 0-1.46.474-1.947 1.257L9 12.761V22h46v-9.24z"
/>
<path
d="M41.613 15.931c0-1.605.994-2.93 2.227-2.931H55v18.137C55 33.26 53.68 35 52.05 35h-40.1C10.32 35 9 33.259 9 31.137V13h11.16c1.233 0 2.227 1.323 2.227 2.928v.022c0 1.605 1.005 2.901 2.237 2.901h14.752c1.232 0 2.237-1.308 2.237-2.913v-.007z"
fill="#FAFAFA"
fill="#fafafa"
/>
</g>
</g>
@ -1115,20 +1115,20 @@ exports[`renders ./components/auto-complete/demo/form-debug.tsx extend context c
<ellipse
cx="32"
cy="33"
fill="#F5F5F5"
fill="#f5f5f5"
rx="32"
ry="7"
/>
<g
fill-rule="nonzero"
stroke="#D9D9D9"
stroke="#d9d9d9"
>
<path
d="M55 12.76L44.854 1.258C44.367.474 43.656 0 42.907 0H21.093c-.749 0-1.46.474-1.947 1.257L9 12.761V22h46v-9.24z"
/>
<path
d="M41.613 15.931c0-1.605.994-2.93 2.227-2.931H55v18.137C55 33.26 53.68 35 52.05 35h-40.1C10.32 35 9 33.259 9 31.137V13h11.16c1.233 0 2.227 1.323 2.227 2.928v.022c0 1.605 1.005 2.901 2.237 2.901h14.752c1.232 0 2.237-1.308 2.237-2.913v-.007z"
fill="#FAFAFA"
fill="#fafafa"
/>
</g>
</g>
@ -1332,20 +1332,20 @@ exports[`renders ./components/auto-complete/demo/form-debug.tsx extend context c
<ellipse
cx="32"
cy="33"
fill="#F5F5F5"
fill="#f5f5f5"
rx="32"
ry="7"
/>
<g
fill-rule="nonzero"
stroke="#D9D9D9"
stroke="#d9d9d9"
>
<path
d="M55 12.76L44.854 1.258C44.367.474 43.656 0 42.907 0H21.093c-.749 0-1.46.474-1.947 1.257L9 12.761V22h46v-9.24z"
/>
<path
d="M41.613 15.931c0-1.605.994-2.93 2.227-2.931H55v18.137C55 33.26 53.68 35 52.05 35h-40.1C10.32 35 9 33.259 9 31.137V13h11.16c1.233 0 2.227 1.323 2.227 2.928v.022c0 1.605 1.005 2.901 2.237 2.901h14.752c1.232 0 2.237-1.308 2.237-2.913v-.007z"
fill="#FAFAFA"
fill="#fafafa"
/>
</g>
</g>
@ -1558,20 +1558,20 @@ exports[`renders ./components/auto-complete/demo/form-debug.tsx extend context c
<ellipse
cx="32"
cy="33"
fill="#F5F5F5"
fill="#f5f5f5"
rx="32"
ry="7"
/>
<g
fill-rule="nonzero"
stroke="#D9D9D9"
stroke="#d9d9d9"
>
<path
d="M55 12.76L44.854 1.258C44.367.474 43.656 0 42.907 0H21.093c-.749 0-1.46.474-1.947 1.257L9 12.761V22h46v-9.24z"
/>
<path
d="M41.613 15.931c0-1.605.994-2.93 2.227-2.931H55v18.137C55 33.26 53.68 35 52.05 35h-40.1C10.32 35 9 33.259 9 31.137V13h11.16c1.233 0 2.227 1.323 2.227 2.928v.022c0 1.605 1.005 2.901 2.237 2.901h14.752c1.232 0 2.237-1.308 2.237-2.913v-.007z"
fill="#FAFAFA"
fill="#fafafa"
/>
</g>
</g>

View File

@ -9,7 +9,7 @@ const App: React.FC = () => {
if (!value || value.indexOf('@') >= 0) {
res = [];
} else {
res = ['gmail.com', '163.com', 'qq.com'].map(domain => ({
res = ['gmail.com', '163.com', 'qq.com'].map((domain) => ({
value,
label: `${value}@${domain}`,
}));

View File

@ -86,7 +86,7 @@ const AutoComplete: React.ForwardRefRenderFunction<RefSelectProps, AutoCompleteP
optionChildren = children;
} else {
optionChildren = dataSource
? dataSource.map(item => {
? dataSource.map((item) => {
if (isValidElement(item)) {
return item;
}

View File

@ -12,7 +12,7 @@ export interface SizeContextProps {
export const SizeContextProvider: React.FC<SizeContextProps> = ({ children, size }) => (
<SizeContext.Consumer>
{originSize => (
{(originSize) => (
<SizeContext.Provider value={size || originSize}>{children}</SizeContext.Provider>
)}
</SizeContext.Consumer>

View File

@ -108,7 +108,7 @@ const InternalAvatar: React.ForwardRefRenderFunction<HTMLSpanElement, AvatarProp
const size = customSize === 'default' ? groupSize : customSize;
const needResponsive = Object.keys(typeof size === 'object' ? size || {} : {}).some(key =>
const needResponsive = Object.keys(typeof size === 'object' ? size || {} : {}).some((key) =>
['xs', 'sm', 'md', 'lg', 'xl', 'xxl'].includes(key),
);
const screens = useBreakpoint(needResponsive);
@ -117,7 +117,7 @@ const InternalAvatar: React.ForwardRefRenderFunction<HTMLSpanElement, AvatarProp
return {};
}
const currentBreakpoint: Breakpoint = responsiveArray.find(screen => screens[screen])!;
const currentBreakpoint: Breakpoint = responsiveArray.find((screen) => screens[screen])!;
const currentSize = size[currentBreakpoint];
return currentSize

View File

@ -25,7 +25,7 @@ export interface GroupProps {
size?: AvatarSize;
}
const Group: React.FC<GroupProps> = props => {
const Group: React.FC<GroupProps> = (props) => {
const { getPrefixCls, direction } = React.useContext(ConfigContext);
const { prefixCls: customizePrefixCls, className = '', maxCount, maxStyle, size } = props;

View File

@ -20,7 +20,7 @@ type AvatarToken = FullToken<'Avatar'> & {
avatarBgColor: string;
};
const genBaseStyle: GenerateStyle<AvatarToken> = token => {
const genBaseStyle: GenerateStyle<AvatarToken> = (token) => {
const {
antCls,
componentCls,
@ -109,7 +109,7 @@ const genBaseStyle: GenerateStyle<AvatarToken> = token => {
};
};
const genGroupStyle: GenerateStyle<AvatarToken> = token => {
const genGroupStyle: GenerateStyle<AvatarToken> = (token) => {
const { componentCls, avatarGroupBorderColor, avatarGroupOverlapping, avatarGroupSpace } = token;
return {
@ -133,7 +133,7 @@ const genGroupStyle: GenerateStyle<AvatarToken> = token => {
};
};
export default genComponentStyleHook('Avatar', token => {
export default genComponentStyleHook('Avatar', (token) => {
const {
colorTextLightSolid,

View File

@ -9,7 +9,7 @@ import { ConfigContext } from '../config-provider';
import getScroll from '../_util/getScroll';
import { cloneElement } from '../_util/reactNode';
import scrollTo from '../_util/scrollTo';
import { throttleByAnimationFrame } from '../_util/throttleByAnimationFrame';
import throttleByAnimationFrame from '../_util/throttleByAnimationFrame';
import warning from '../_util/warning';
import useStyle from './style';
@ -32,7 +32,7 @@ interface ChildrenProps {
visible?: boolean; // Only for test. Don't use it.
}
const BackTopContent: React.FC<ChildrenProps> = props => {
const BackTopContent: React.FC<ChildrenProps> = (props) => {
const { prefixCls, rootPrefixCls, children, visible } = props;
const defaultElement = (
<div className={`${prefixCls}-content`}>
@ -52,7 +52,7 @@ const BackTopContent: React.FC<ChildrenProps> = props => {
);
};
const BackTop: React.FC<BackTopProps> = props => {
const BackTop: React.FC<BackTopProps> = (props) => {
const [visible, setVisible] = useMergedState(false, {
value: props.visible,
});

View File

@ -95,7 +95,7 @@ export default function SingleNumber(props: SingleNumberProps) {
}
// Fill with number unit nodes
const prevIndex = unitNumberList.findIndex(n => n % 10 === prevValue);
const prevIndex = unitNumberList.findIndex((n) => n % 10 === prevValue);
unitNodes = unitNumberList.map((n, index) => {
const singleUnit = n % 10;
return (

View File

@ -1727,7 +1727,7 @@ exports[`renders ./components/badge/demo/overflow.tsx extend context correctly 1
</div>
`;
exports[`renders ./components/badge/demo/ribbbon.tsx extend context correctly 1`] = `
exports[`renders ./components/badge/demo/ribbon.tsx extend context correctly 1`] = `
<div
class="ant-space ant-space-vertical"
style="width:100%"

View File

@ -1727,7 +1727,7 @@ exports[`renders ./components/badge/demo/overflow.tsx correctly 1`] = `
</div>
`;
exports[`renders ./components/badge/demo/ribbbon.tsx correctly 1`] = `
exports[`renders ./components/badge/demo/ribbon.tsx correctly 1`] = `
<div
class="ant-space ant-space-vertical"
style="width:100%"

View File

@ -21,7 +21,7 @@ const App: React.FC = () => (
<>
<Divider orientation="left">Presets</Divider>
<Space direction="vertical">
{colors.map(color => (
{colors.map((color) => (
<Badge key={color} color={color} text={color} />
))}
</Space>

View File

@ -26,7 +26,7 @@ Badge normally appears in proximity to notifications or user avatars with eye-ca
<code src="./demo/size.tsx">Size</code>
<code src="./demo/status.tsx">Status</code>
<code src="./demo/colorful.tsx">Colorful Badge</code>
<code src="./demo/ribbbon.tsx">Ribbon</code>
<code src="./demo/ribbon.tsx">Ribbon</code>
<code src="./demo/ribbon-debug.tsx" debug>Ribbon Debug</code>
<code src="./demo/mix.tsx" debug>Mixed usage</code>
<code src="./demo/title.tsx" debug>Title</code>

View File

@ -13,9 +13,9 @@ import { isPresetColor } from './utils';
export type { ScrollNumberProps } from './ScrollNumber';
interface CompoundedComponent extends React.FC<BadgeProps> {
type CompoundedComponent = React.FC<BadgeProps> & {
Ribbon: typeof Ribbon;
}
};
export interface BadgeProps {
/** Number to show in badge */
@ -137,7 +137,7 @@ const Badge: CompoundedComponent = ({
const displayNode =
!livingCount || typeof livingCount !== 'object'
? undefined
: cloneElement(livingCount, oriProps => ({
: cloneElement(livingCount, (oriProps) => ({
style: {
...mergedStyle,
...oriProps.style,

View File

@ -27,7 +27,7 @@ group: 数据展示
<code src="./demo/size.tsx">大小</code>
<code src="./demo/status.tsx">状态点</code>
<code src="./demo/colorful.tsx">多彩徽标</code>
<code src="./demo/ribbbon.tsx">缎带</code>
<code src="./demo/ribbon.tsx">缎带</code>
<code src="./demo/ribbon-debug.tsx" debug>Ribbon Debug</code>
<code src="./demo/mix.tsx" debug>各种混用的情况</code>
<code src="./demo/title.tsx" debug>自定义标题</code>

View File

@ -69,12 +69,12 @@ const addChildPath = (paths: string[], childPath: string, params: any) => {
return originalPaths;
};
interface BreadcrumbInterface extends React.FC<BreadcrumbProps> {
type CompoundedComponent = React.FC<BreadcrumbProps> & {
Item: typeof BreadcrumbItem;
Separator: typeof BreadcrumbSeparator;
}
};
const Breadcrumb: BreadcrumbInterface = ({
const Breadcrumb: CompoundedComponent = ({
prefixCls: customizePrefixCls,
separator = '/',
style,

View File

@ -36,7 +36,7 @@ describe('react router', () => {
const Home: React.FC = () => {
const location = useLocation();
const navigate = useNavigate();
const pathSnippets = location.pathname.split('/').filter(i => i);
const pathSnippets = location.pathname.split('/').filter((i) => i);
const extraBreadcrumbItems = pathSnippets.map((_, index) => {
const url = `/${pathSnippets.slice(0, index + 1).join('/')}`;
return (
@ -51,11 +51,11 @@ describe('react router', () => {
</Breadcrumb.Item>,
].concat(extraBreadcrumbItems);
const componentProps = useMemo<RouterProps>(
() => ({ component: Apps } as unknown as RouterProps),
() => ({ component: Apps }) as unknown as RouterProps,
[],
);
const renderProps = useMemo<RouterProps>(
() => ({ render: () => <span>Home Page</span> } as unknown as RouterProps),
() => ({ render: () => <span>Home Page</span> }) as unknown as RouterProps,
[],
);
return (

View File

@ -23,7 +23,7 @@ const breadcrumbNameMap: Record<string, string> = {
const Home = () => {
const location = useLocation();
const pathSnippets = location.pathname.split('/').filter(i => i);
const pathSnippets = location.pathname.split('/').filter((i) => i);
const extraBreadcrumbItems = pathSnippets.map((_, index) => {
const url = `/${pathSnippets.slice(0, index + 1).join('/')}`;

View File

@ -43,11 +43,11 @@ it('Delay loading timer in Button component', () => {
// other component may call setTimeout or clearTimeout
const setTimeoutCount = () => {
const items = setTimeoutMock.mock.calls.filter(item => item[1] === specialDelay);
const items = setTimeoutMock.mock.calls.filter((item) => item[1] === specialDelay);
return items.length;
};
const clearTimeoutCount = () => {
const items = clearTimeoutMock.mock.calls.filter(item => item[0] === btnTimer);
const items = clearTimeoutMock.mock.calls.filter((item) => item[0] === btnTimer);
return items.length;
};

View File

@ -5,7 +5,7 @@ import { act } from 'react-dom/test-utils';
import Button 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';
import ConfigProvider from '../../config-provider';
describe('Button', () => {
@ -242,6 +242,7 @@ describe('Button', () => {
});
it('should support to change loading', async () => {
jest.useFakeTimers();
const { container, rerender, unmount } = render(<Button>Button</Button>);
rerender(<Button loading />);
expect(container.querySelectorAll('.ant-btn-loading').length).toBe(1);
@ -249,12 +250,13 @@ describe('Button', () => {
expect(container.querySelectorAll('.ant-btn-loading').length).toBe(0);
rerender(<Button loading={{ delay: 50 }} />);
expect(container.querySelectorAll('.ant-btn-loading').length).toBe(0);
await sleep(50);
await waitFakeTimer();
expect(container.querySelectorAll('.ant-btn-loading').length).toBe(1);
rerender(<Button loading={false} />);
await sleep(50);
await waitFakeTimer();
expect(container.querySelectorAll('.ant-btn-loading').length).toBe(0);
expect(unmount).not.toThrow();
jest.useRealTimers();
});
it('should warning when pass a string as icon props', () => {
@ -297,7 +299,7 @@ describe('Button', () => {
render(
<ConfigProvider autoInsertSpaceInButton={false}>
<Button
ref={node => {
ref={(node) => {
buttonInstance = node;
}}
>

View File

@ -1,6 +1,7 @@
import userEvent from '@testing-library/user-event';
import React from 'react';
import Button from '..';
import { fireEvent, render, sleep, assertsExist } from '../../../tests/utils';
import { fireEvent, render, assertsExist } from '../../../tests/utils';
// Mock Wave ref
let waveInstanceMock: any;
@ -13,7 +14,7 @@ jest.mock('../../_util/wave', () => {
__esModule: true,
default: (props: import('../../_util/wave').WaveProps) => (
<WaveComponent
ref={node => {
ref={(node) => {
waveInstanceMock = node;
}}
{...props}
@ -23,13 +24,21 @@ jest.mock('../../_util/wave', () => {
});
describe('click wave effect', () => {
beforeEach(() => {
jest.useFakeTimers();
});
afterEach(() => {
jest.clearAllTimers();
jest.useRealTimers();
});
async function clickButton(wrapper: any) {
const element = wrapper.container.firstChild;
fireEvent.click(element);
// https://github.com/testing-library/user-event/issues/833
await userEvent.setup({ advanceTimers: jest.advanceTimersByTime }).click(element);
fireEvent(element, new Event('transitionstart'));
await sleep(20);
fireEvent(element, new Event('animationend'));
await sleep(20);
}
it('should have click wave effect for primary button', async () => {
@ -82,8 +91,9 @@ describe('click wave effect', () => {
const resetEffect = jest.spyOn(waveInstanceMock, 'resetEffect');
await clickButton(wrapper);
expect(resetEffect).toHaveBeenCalledTimes(1);
fireEvent.click(wrapper.container.querySelector('.ant-btn')!);
await sleep(10);
await userEvent
.setup({ advanceTimers: jest.advanceTimersByTime })
.click(wrapper.container.querySelector('.ant-btn')!);
expect(resetEffect).toHaveBeenCalledTimes(2);
waveInstanceMock.animationStart = false;
fireEvent(wrapper.container.querySelector('.ant-btn')!, new Event('transitionstart'));

View File

@ -15,7 +15,7 @@ export interface ButtonGroupProps {
export const GroupSizeContext = React.createContext<SizeType | undefined>(undefined);
const ButtonGroup: React.FC<ButtonGroupProps> = props => {
const ButtonGroup: React.FC<ButtonGroupProps> = (props) => {
const { getPrefixCls, direction } = React.useContext(ConfigContext);
const { prefixCls: customizePrefixCls, size, className, ...others } = props;

View File

@ -58,7 +58,7 @@ function insertSpace(child: React.ReactElement | string | number, needInserted:
function spaceChildren(children: React.ReactNode, needInserted: boolean) {
let isPrevChildPure: boolean = false;
const childList: React.ReactNode[] = [];
React.Children.forEach(children, child => {
React.Children.forEach(children, (child) => {
const type = typeof child;
const isCurrentChildPure = type === 'string' || type === 'number';
if (isPrevChildPure && isCurrentChildPure) {
@ -73,7 +73,7 @@ function spaceChildren(children: React.ReactNode, needInserted: boolean) {
});
// Pass to React.Children.map to auto fill key
return React.Children.map(childList, child =>
return React.Children.map(childList, (child) =>
insertSpace(child as React.ReactElement | string | number, needInserted),
);
}
@ -131,12 +131,13 @@ export type NativeButtonProps = {
export type ButtonProps = Partial<AnchorButtonProps & NativeButtonProps>;
interface CompoundedComponent
extends React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLElement>> {
type CompoundedComponent = React.ForwardRefExoticComponent<
ButtonProps & React.RefAttributes<HTMLElement>
> & {
Group: typeof Group;
/** @internal */
__ANT_BUTTON: boolean;
}
};
type Loading = number | boolean;

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