mirror of
https://github.com/ant-design/ant-design.git
synced 2024-12-11 23:00:20 +08:00
commit
9f2b9656d0
@ -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'));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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}
|
||||
|
@ -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`,
|
||||
},
|
||||
};
|
||||
|
@ -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,
|
||||
}}
|
||||
>
|
||||
|
@ -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 (
|
||||
|
@ -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}
|
||||
|
@ -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}
|
||||
|
@ -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
|
||||
|
@ -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 (
|
||||
|
@ -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'
|
||||
);
|
||||
}
|
||||
|
@ -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);
|
||||
});
|
||||
|
@ -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);
|
||||
}}
|
||||
/>
|
||||
|
@ -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');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -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 不能跳转到外链 */
|
||||
|
@ -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}
|
||||
|
@ -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;
|
@ -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,
|
||||
|
@ -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}
|
||||
|
@ -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.' +
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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">
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -7,6 +7,6 @@ const SVGIcon = () => (
|
||||
</svg>
|
||||
);
|
||||
|
||||
const CodePenIcon = props => <Icon component={SVGIcon} {...props} />;
|
||||
const CodePenIcon = (props) => <Icon component={SVGIcon} {...props} />;
|
||||
|
||||
export default CodePenIcon;
|
||||
|
@ -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',
|
||||
|
@ -7,6 +7,6 @@ const SVGIcon = () => (
|
||||
</svg>
|
||||
);
|
||||
|
||||
const CodeSandboxIcon = props => <Icon component={SVGIcon} {...props} />;
|
||||
const CodeSandboxIcon = (props) => <Icon component={SVGIcon} {...props} />;
|
||||
|
||||
export default CodeSandboxIcon;
|
||||
|
@ -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,
|
||||
|
@ -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>
|
||||
|
@ -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 },
|
||||
}
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
@ -1890,8 +1902,8 @@ const GlobalStyles = () => {
|
||||
|
||||
.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;
|
||||
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 {
|
||||
@ -1899,12 +1911,12 @@ const GlobalStyles = () => {
|
||||
}
|
||||
|
||||
.preview-img {
|
||||
max-width: 496px !important;
|
||||
clear: both;
|
||||
float: right;
|
||||
clear: both;
|
||||
max-width: 496px !important;
|
||||
margin: 0 0 70px 64px;
|
||||
background-color: #f2f4f5;
|
||||
padding: 16px;
|
||||
background-color: #f2f4f5;
|
||||
}
|
||||
|
||||
.image-modal {
|
||||
@ -1973,6 +1985,7 @@ const GlobalStyles = () => {
|
||||
|
||||
.principle {
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
min-height: 180px;
|
||||
margin-right: 12.5%;
|
||||
@ -1982,7 +1995,6 @@ const GlobalStyles = () => {
|
||||
text-align: center;
|
||||
border: 1px solid #e8e8e8;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
@ -1997,7 +2009,8 @@ const GlobalStyles = () => {
|
||||
line-height: 24px;
|
||||
}
|
||||
}
|
||||
}`}
|
||||
}
|
||||
`}
|
||||
/>
|
||||
|
||||
<ColorStyle />
|
||||
|
@ -7,6 +7,6 @@ const SVGIcon = () => (
|
||||
</svg>
|
||||
);
|
||||
|
||||
const RiddleIcon = props => <Icon component={SVGIcon} {...props} />;
|
||||
const RiddleIcon = (props) => <Icon component={SVGIcon} {...props} />;
|
||||
|
||||
export default RiddleIcon;
|
||||
|
@ -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 (
|
||||
<>
|
||||
|
@ -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,
|
||||
|
@ -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>,
|
||||
}))}
|
||||
|
@ -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",
|
||||
|
@ -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": "搜索组件",
|
||||
|
@ -178,16 +178,19 @@ const Content: FC<{ children: ReactNode }> = ({ children }) => {
|
||||
)}
|
||||
</Typography.Title>
|
||||
{children}
|
||||
{meta.frontmatter.filename && (
|
||||
<ContributorsList
|
||||
css={styles.contributorsList}
|
||||
fileName={meta.frontmatter.filename ?? ''}
|
||||
fileName={meta.frontmatter.filename}
|
||||
renderItem={(item, loading) =>
|
||||
loading ? (
|
||||
<Avatar style={{ opacity: 0.3 }} />
|
||||
) : (
|
||||
item && (
|
||||
<Tooltip
|
||||
title={`${formatMessage({ id: 'app.content.contributors' })}: ${item.username}`}
|
||||
title={`${formatMessage({ id: 'app.content.contributors' })}: ${
|
||||
item.username
|
||||
}`}
|
||||
key={item.username}
|
||||
>
|
||||
<a
|
||||
@ -204,6 +207,7 @@ const Content: FC<{ children: ReactNode }> = ({ children }) => {
|
||||
repo="ant-design"
|
||||
owner="ant-design"
|
||||
/>
|
||||
)}
|
||||
</article>
|
||||
<PrevAndNext />
|
||||
<Footer />
|
||||
|
@ -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,
|
||||
},
|
||||
{
|
||||
|
@ -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>
|
||||
),
|
||||
|
@ -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',
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
5
.github/workflows/site-deploy.yml
vendored
5
.github/workflows/site-deploy.yml
vendored
@ -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
|
||||
|
1
.github/workflows/sync-gitee.yml
vendored
1
.github/workflows/sync-gitee.yml
vendored
@ -8,6 +8,7 @@ on:
|
||||
- feature
|
||||
- 2.x-stable
|
||||
- 3.x-stable
|
||||
- 4.x-stable
|
||||
create:
|
||||
|
||||
permissions:
|
||||
|
11
.github/workflows/test.yml
vendored
11
.github/workflows/test.yml
vendored
@ -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 }}
|
||||
|
@ -3,7 +3,6 @@
|
||||
"trailingComma": "all",
|
||||
"printWidth": 100,
|
||||
"proseWrap": "never",
|
||||
"arrowParens": "avoid",
|
||||
"overrides": [
|
||||
{
|
||||
"files": ".prettierrc",
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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 バージョン |
|
||||
|
||||
|
@ -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 |
|
||||
|
||||
|
@ -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 |
|
||||
|
||||
|
@ -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 останні версії |
|
||||
|
||||
|
@ -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 |
|
||||
|
||||
|
12
README.md
12
README.md
@ -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 |
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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', () => {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
};
|
||||
}, []);
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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],
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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)`,
|
||||
|
@ -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(
|
||||
|
@ -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>
|
||||
);
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
});
|
||||
|
@ -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();
|
||||
|
@ -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}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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}`,
|
||||
}));
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
|
||||
|
@ -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,
|
||||
});
|
||||
|
@ -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 (
|
||||
|
@ -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%"
|
||||
|
@ -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%"
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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,
|
||||
|
@ -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>
|
||||
|
@ -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,
|
||||
|
@ -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 (
|
||||
|
@ -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('/')}`;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}}
|
||||
>
|
||||
|
@ -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'));
|
||||
|
@ -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;
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user