mirror of
https://github.com/ant-design/ant-design.git
synced 2025-01-22 08:53:29 +08:00
Merge branch 'master' into patch-1
This commit is contained in:
commit
b438d4c00f
@ -11,15 +11,15 @@ module.exports = {
|
||||
],
|
||||
modulePattern: [
|
||||
{
|
||||
pattern: /ConfigContext.*renderEmpty/ms,
|
||||
pattern: /ConfigContext.*renderEmpty/s,
|
||||
module: '../empty',
|
||||
},
|
||||
{
|
||||
pattern: /ConfigConsumer.*renderEmpty/ms,
|
||||
pattern: /ConfigConsumer.*renderEmpty/s,
|
||||
module: '../empty',
|
||||
},
|
||||
{
|
||||
pattern: /config-provider\/context.*renderEmpty/ms,
|
||||
pattern: /config-provider\/context.*renderEmpty/s,
|
||||
module: '../empty',
|
||||
},
|
||||
],
|
||||
|
@ -66,7 +66,7 @@ const useStyle = createStyles(({ token }, markPos: [number, number, number, numb
|
||||
|
||||
export interface SemanticPreviewProps {
|
||||
semantics: { name: string; desc: string; version?: string }[];
|
||||
children: React.ReactElement;
|
||||
children: React.ReactElement<any>;
|
||||
height?: number;
|
||||
}
|
||||
|
||||
@ -97,7 +97,7 @@ const SemanticPreview: React.FC<SemanticPreviewProps> = (props) => {
|
||||
// ======================== Hover =========================
|
||||
const containerRef = React.useRef<HTMLDivElement>(null);
|
||||
|
||||
const timerRef = React.useRef<ReturnType<typeof setTimeout>>();
|
||||
const timerRef = React.useRef<ReturnType<typeof setTimeout>>(null);
|
||||
|
||||
const [positionMotion, setPositionMotion] = React.useState<boolean>(false);
|
||||
const [hoverSemantic, setHoverSemantic] = React.useState<string | null>(null);
|
||||
@ -111,12 +111,14 @@ const SemanticPreview: React.FC<SemanticPreviewProps> = (props) => {
|
||||
const targetElement = containerRef.current?.querySelector<HTMLElement>(`.${targetClassName}`);
|
||||
const containerRect = containerRef.current?.getBoundingClientRect();
|
||||
const targetRect = targetElement?.getBoundingClientRect();
|
||||
|
||||
setMarkPos([
|
||||
(targetRect?.left || 0) - (containerRect?.left || 0),
|
||||
(targetRect?.top || 0) - (containerRect?.top || 0),
|
||||
targetRect?.width || 0,
|
||||
targetRect?.height || 0,
|
||||
]);
|
||||
|
||||
timerRef.current = setTimeout(() => {
|
||||
setPositionMotion(true);
|
||||
}, 10);
|
||||
|
@ -16,5 +16,5 @@
|
||||
|
||||
html {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: unset;
|
||||
scrollbar-color: #eaeaea transparent;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import type { MenuProps } from 'antd';
|
||||
import { Tag, version } from 'antd';
|
||||
import { Space, Tag, version } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
import classnames from 'classnames';
|
||||
import { useFullSidebarData, useSidebarData } from 'dumi';
|
||||
@ -22,7 +22,6 @@ const useStyle = createStyles(({ css, token }) => ({
|
||||
margin-inline-end: 0;
|
||||
`,
|
||||
subtitle: css`
|
||||
margin-inline-start: ${token.marginXS}px;
|
||||
font-weight: normal;
|
||||
font-size: ${token.fontSizeSM}px;
|
||||
opacity: 0.8;
|
||||
@ -46,10 +45,10 @@ const MenuItemLabelWithTag: React.FC<MenuItemLabelProps> = (props) => {
|
||||
if (!before && !after) {
|
||||
return (
|
||||
<Link to={`${link}${search}`} className={classnames(className, { [styles.link]: tag })}>
|
||||
<span>
|
||||
{title}
|
||||
<Space>
|
||||
<span>{title}</span>
|
||||
{subtitle && <span className={styles.subtitle}>{subtitle}</span>}
|
||||
</span>
|
||||
</Space>
|
||||
{tag && (
|
||||
<Tag
|
||||
bordered={false}
|
||||
|
@ -89,7 +89,6 @@ const useThemeAnimation = () => {
|
||||
.startViewTransition(async () => {
|
||||
// wait for theme change end
|
||||
while (colorBgElevated === animateRef.current.colorBgElevated) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await new Promise((resolve) => {
|
||||
setTimeout(resolve, 1000 / 60);
|
||||
});
|
||||
@ -99,6 +98,7 @@ const useThemeAnimation = () => {
|
||||
root.classList.add(isDark ? 'light' : 'dark');
|
||||
})
|
||||
.ready.then(() => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Theme transition finished in ${Date.now() - time}ms`);
|
||||
const clipPath = [
|
||||
`circle(0px at ${x}px ${y}px)`,
|
||||
|
@ -1,3 +1,3 @@
|
||||
// must be .js file, can't modify to be .ts file!
|
||||
// eslint-disable-next-line no-restricted-exports
|
||||
|
||||
export { default } from './theme/common/Loading';
|
||||
|
@ -36,6 +36,7 @@ const useStyle = createStyles(({ token, css, cx }) => {
|
||||
cardItem: css`
|
||||
&:hover {
|
||||
box-shadow: ${token.boxShadowCard};
|
||||
border-color: transparent;
|
||||
}
|
||||
`,
|
||||
sliderItem: css`
|
||||
@ -112,7 +113,7 @@ export const BannerRecommendsFallback: React.FC = () => {
|
||||
const { isMobile } = useContext(SiteContext);
|
||||
const { styles } = useStyle();
|
||||
|
||||
const list = Array(3).fill(1);
|
||||
const list = new Array(3).fill(1);
|
||||
|
||||
return isMobile ? (
|
||||
<Carousel className={styles.carousel}>
|
||||
@ -140,7 +141,7 @@ const BannerRecommends: React.FC = () => {
|
||||
const data = useSiteData();
|
||||
const extras = data?.extras?.[lang];
|
||||
const icons = data?.icons || [];
|
||||
const first3 = !extras || extras.length === 0 ? Array(3).fill(null) : extras.slice(0, 3);
|
||||
const first3 = !extras || extras.length === 0 ? new Array(3).fill(null) : extras.slice(0, 3);
|
||||
|
||||
if (!data) {
|
||||
return <BannerRecommendsFallback />;
|
||||
|
@ -257,7 +257,7 @@ const ComponentsList: React.FC = () => {
|
||||
style={{ width: 400 }}
|
||||
message="Ant Design 5.0"
|
||||
description={locale.sampleContent}
|
||||
closable
|
||||
closable={{ closeIcon: true, disabled: true }}
|
||||
/>
|
||||
),
|
||||
},
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { ColorPicker, Flex, Input } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
import type { ColorPickerProps, GetProp } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
import { generateColor } from 'antd/es/color-picker/util';
|
||||
import classNames from 'classnames';
|
||||
|
||||
@ -61,7 +61,7 @@ const DebouncedColorPicker: React.FC<React.PropsWithChildren<ThemeColorPickerPro
|
||||
<ColorPicker
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
presets={[{ label: 'PresetColors', colors: PRESET_COLORS }]}
|
||||
presets={[{ label: 'PresetColors', key: 'PresetColors', colors: PRESET_COLORS }]}
|
||||
>
|
||||
{children}
|
||||
</ColorPicker>
|
||||
@ -102,7 +102,6 @@ const ThemeColorPicker: React.FC<ThemeColorPickerProps> = ({ value, onChange, id
|
||||
<Flex gap="middle">
|
||||
{matchColors.map<React.ReactNode>(({ color, active, picker }) => {
|
||||
const colorNode = (
|
||||
// eslint-disable-next-line jsx-a11y/label-has-associated-control
|
||||
<label
|
||||
key={color}
|
||||
className={classNames(styles.color, { [styles.colorActive]: active })}
|
||||
|
@ -1,4 +1,3 @@
|
||||
/* eslint-disable jsx-a11y/label-has-associated-control */
|
||||
import * as React from 'react';
|
||||
import { Flex } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
|
@ -6,7 +6,7 @@ import {
|
||||
HomeOutlined,
|
||||
QuestionCircleOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { TinyColor } from '@ctrl/tinycolor';
|
||||
import { FastColor } from '@ant-design/fast-color';
|
||||
import type { ColorPickerProps, GetProp, MenuProps, ThemeConfig } from 'antd';
|
||||
import {
|
||||
Breadcrumb,
|
||||
@ -46,6 +46,7 @@ const { Header, Content, Sider } = Layout;
|
||||
|
||||
const TokenChecker: React.FC = () => {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Demo Token:', theme.useToken());
|
||||
}
|
||||
return null;
|
||||
@ -323,7 +324,7 @@ const ThemesInfo: Record<THEME, Partial<ThemeData>> = {
|
||||
const normalize = (value: number) => value / 255;
|
||||
|
||||
function rgbToColorMatrix(color: string) {
|
||||
const rgb = new TinyColor(color).toRgb();
|
||||
const rgb = new FastColor(color).toRgb();
|
||||
const { r, g, b } = rgb;
|
||||
|
||||
const invertValue = normalize(r) * 100;
|
||||
|
@ -72,7 +72,7 @@ function rehypeAntd(): UnifiedTransformer<HastRoot> {
|
||||
|
||||
if (typeof lang === 'string' && lang.startsWith('sandpack')) {
|
||||
const code = (node.children[0] as any).value as string;
|
||||
const configRegx = /^const sandpackConfig = ([\S\s]*?});/;
|
||||
const configRegx = /^const sandpackConfig = ([\s\S]*?});/;
|
||||
const [configString] = code.match(configRegx) || [];
|
||||
/* biome-ignore lint/security/noGlobalEval: used in documentation */ /* eslint-disable-next-line no-eval */
|
||||
const config = configString && eval(`(${configString.replace(configRegx, '$1')})`);
|
||||
|
@ -141,12 +141,12 @@
|
||||
|
||||
const title = document.createElement('div');
|
||||
title.className = 'mirror-modal-title';
|
||||
title.innerText = '提示';
|
||||
title.textContent = '提示';
|
||||
dialog.append(title);
|
||||
|
||||
const content = document.createElement('div');
|
||||
content.className = 'mirror-modal-content';
|
||||
content.innerText = '🚀 国内用户推荐访问国内镜像以获得极速体验~';
|
||||
content.textContent = '🚀 国内用户推荐访问国内镜像以获得极速体验~';
|
||||
dialog.append(content);
|
||||
|
||||
const btnWrapper = document.createElement('div');
|
||||
@ -155,7 +155,7 @@
|
||||
|
||||
const cancelBtn = document.createElement('a');
|
||||
cancelBtn.className = 'mirror-modal-cancel-btn mirror-modal-btn';
|
||||
cancelBtn.innerText = '7 天内不再显示';
|
||||
cancelBtn.textContent = '7 天内不再显示';
|
||||
btnWrapper.append(cancelBtn);
|
||||
cancelBtn.addEventListener('click', () => {
|
||||
window.localStorage.setItem(ANTD_DOT_NOT_SHOW_MIRROR_MODAL, new Date().toISOString());
|
||||
@ -167,7 +167,7 @@
|
||||
const confirmBtn = document.createElement('a');
|
||||
confirmBtn.className = 'mirror-modal-confirm-btn mirror-modal-btn';
|
||||
confirmBtn.href = window.location.href.replace(window.location.host, 'ant-design.antgroup.com');
|
||||
confirmBtn.innerText = '🚀 立刻前往';
|
||||
confirmBtn.textContent = '🚀 立刻前往';
|
||||
btnWrapper.append(confirmBtn);
|
||||
|
||||
document.body.append(modal);
|
||||
|
@ -24,7 +24,6 @@ interface NewToken {
|
||||
|
||||
// 通过给 antd-style 扩展 CustomToken 对象类型定义,可以为 useTheme 中增加相应的 token 对象
|
||||
declare module 'antd-style' {
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
export interface CustomToken extends NewToken {}
|
||||
}
|
||||
|
||||
|
15
.dumi/theme/builtins/Antd.tsx
Normal file
15
.dumi/theme/builtins/Antd.tsx
Normal file
@ -0,0 +1,15 @@
|
||||
import * as React from 'react';
|
||||
import * as all from 'antd';
|
||||
|
||||
interface AntdProps {
|
||||
component: keyof typeof all;
|
||||
}
|
||||
|
||||
function Antd(props: AntdProps) {
|
||||
const { component, ...restProps } = props;
|
||||
const Component = (all[component] ?? React.Fragment) as React.ComponentType;
|
||||
|
||||
return <Component {...restProps} />;
|
||||
}
|
||||
|
||||
export default Antd;
|
48
.dumi/theme/builtins/Audio/index.tsx
Normal file
48
.dumi/theme/builtins/Audio/index.tsx
Normal file
@ -0,0 +1,48 @@
|
||||
import React from 'react';
|
||||
import { SoundOutlined } from '@ant-design/icons';
|
||||
import { createStyles } from 'antd-style';
|
||||
|
||||
const useStyle = createStyles(({ css, token }) => {
|
||||
const { paddingXXS, fontSizeXL, motionDurationSlow, colorLink, colorLinkHover, colorLinkActive } =
|
||||
token;
|
||||
return {
|
||||
playBtn: css`
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
column-gap: ${paddingXXS}px;
|
||||
margin: 0;
|
||||
`,
|
||||
icon: css`
|
||||
font-size: ${fontSizeXL}px;
|
||||
color: ${colorLink};
|
||||
transition: all ${motionDurationSlow};
|
||||
&:hover {
|
||||
color: ${colorLinkHover};
|
||||
}
|
||||
&:active {
|
||||
color: ${colorLinkActive};
|
||||
}
|
||||
`,
|
||||
};
|
||||
});
|
||||
|
||||
interface AudioProps {
|
||||
id?: string;
|
||||
}
|
||||
|
||||
const AudioControl: React.FC<React.PropsWithChildren<AudioProps>> = ({ id, children }) => {
|
||||
const { styles } = useStyle();
|
||||
const onClick: React.MouseEventHandler<HTMLAnchorElement> = () => {
|
||||
const audio = document.querySelector<HTMLAudioElement>(`#${id}`);
|
||||
audio?.play();
|
||||
};
|
||||
return (
|
||||
<a className={styles.playBtn} onClick={onClick}>
|
||||
{children}
|
||||
<SoundOutlined className={styles.icon} />
|
||||
</a>
|
||||
);
|
||||
};
|
||||
|
||||
export default AudioControl;
|
@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import type { ColorInput } from '@ctrl/tinycolor';
|
||||
import { TinyColor } from '@ctrl/tinycolor';
|
||||
// @ts-ignore
|
||||
import { TinyColor } from 'dumi-plugin-color-chunk/component';
|
||||
import { createStyles } from 'antd-style';
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => ({
|
||||
@ -22,7 +22,7 @@ const useStyle = createStyles(({ token, css }) => ({
|
||||
}));
|
||||
|
||||
interface ColorChunkProps {
|
||||
value?: ColorInput;
|
||||
value: any;
|
||||
}
|
||||
|
||||
const ColorChunk: React.FC<React.PropsWithChildren<ColorChunkProps>> = (props) => {
|
||||
|
@ -1,12 +1,13 @@
|
||||
import React from 'react';
|
||||
import { EditOutlined, GithubOutlined } from '@ant-design/icons';
|
||||
import { EditOutlined, GithubOutlined, HistoryOutlined } from '@ant-design/icons';
|
||||
import type { GetProp } from 'antd';
|
||||
import { Descriptions, theme, Tooltip, Typography } from 'antd';
|
||||
import { Descriptions, Flex, theme, Tooltip, Typography } from 'antd';
|
||||
import { createStyles, css } from 'antd-style';
|
||||
import kebabCase from 'lodash/kebabCase';
|
||||
import CopyToClipboard from 'react-copy-to-clipboard';
|
||||
|
||||
import useLocale from '../../../hooks/useLocale';
|
||||
import ComponentChangelog from '../../common/ComponentChangelog';
|
||||
|
||||
const locales = {
|
||||
cn: {
|
||||
@ -16,6 +17,7 @@ const locales = {
|
||||
source: '源码',
|
||||
docs: '文档',
|
||||
edit: '编辑此页',
|
||||
changelog: '更新日志',
|
||||
version: '版本',
|
||||
},
|
||||
en: {
|
||||
@ -25,6 +27,7 @@ const locales = {
|
||||
source: 'Source',
|
||||
docs: 'Docs',
|
||||
edit: 'Edit this page',
|
||||
changelog: 'Changelog',
|
||||
version: 'Version',
|
||||
},
|
||||
};
|
||||
@ -43,7 +46,7 @@ const useStyle = createStyles(({ token }) => ({
|
||||
align-items: center;
|
||||
column-gap: ${token.paddingXXS}px;
|
||||
border-radius: ${token.borderRadiusSM}px;
|
||||
padding-inline: ${token.paddingXXS}px;
|
||||
padding-inline: ${token.paddingXXS}px !important;
|
||||
transition: all ${token.motionDurationSlow} !important;
|
||||
font-family: ${token.codeFamily};
|
||||
color: ${token.colorTextSecondary} !important;
|
||||
@ -70,6 +73,9 @@ const useStyle = createStyles(({ token }) => ({
|
||||
semicolon: css`
|
||||
color: ${token.colorText};
|
||||
`,
|
||||
icon: css`
|
||||
margin-inline-end: ${token.marginXXS}px;
|
||||
`,
|
||||
}));
|
||||
|
||||
export interface ComponentMetaProps {
|
||||
@ -117,7 +123,7 @@ const ComponentMeta: React.FC<ComponentMetaProps> = (props) => {
|
||||
}, [component, source]);
|
||||
|
||||
const transformComponentName = (componentName: string) => {
|
||||
if (componentName === 'Notifiction' || componentName === 'Message') {
|
||||
if (componentName === 'Notification' || componentName === 'Message') {
|
||||
return componentName.toLowerCase();
|
||||
}
|
||||
return componentName;
|
||||
@ -148,7 +154,9 @@ const ComponentMeta: React.FC<ComponentMetaProps> = (props) => {
|
||||
colon={false}
|
||||
column={1}
|
||||
style={{ marginTop: token.margin }}
|
||||
labelStyle={{ paddingInlineEnd: token.padding, width: 56 }}
|
||||
styles={{
|
||||
label: { paddingInlineEnd: token.padding, width: 56 },
|
||||
}}
|
||||
items={
|
||||
[
|
||||
{
|
||||
@ -171,7 +179,7 @@ const ComponentMeta: React.FC<ComponentMetaProps> = (props) => {
|
||||
label: locale.source,
|
||||
children: (
|
||||
<Typography.Link className={styles.code} href={filledSource} target="_blank">
|
||||
<GithubOutlined style={{ marginInlineEnd: 4 }} />
|
||||
<GithubOutlined className={styles.icon} />
|
||||
<span>{abbrSource}</span>
|
||||
</Typography.Link>
|
||||
),
|
||||
@ -179,14 +187,22 @@ const ComponentMeta: React.FC<ComponentMetaProps> = (props) => {
|
||||
filename && {
|
||||
label: locale.docs,
|
||||
children: (
|
||||
<Typography.Link
|
||||
className={styles.code}
|
||||
href={`${branchUrl}${filename}`}
|
||||
target="_blank"
|
||||
>
|
||||
<EditOutlined style={{ marginInlineEnd: 4 }} />
|
||||
<span>{locale.edit}</span>
|
||||
</Typography.Link>
|
||||
<Flex justify="flex-start" align="center" gap="middle">
|
||||
<Typography.Link
|
||||
className={styles.code}
|
||||
href={`${branchUrl}${filename}`}
|
||||
target="_blank"
|
||||
>
|
||||
<EditOutlined className={styles.icon} />
|
||||
<span>{locale.edit}</span>
|
||||
</Typography.Link>
|
||||
<ComponentChangelog>
|
||||
<Typography.Link className={styles.code}>
|
||||
<HistoryOutlined className={styles.icon} />
|
||||
<span>{locale.changelog}</span>
|
||||
</Typography.Link>
|
||||
</ComponentChangelog>
|
||||
</Flex>
|
||||
),
|
||||
},
|
||||
isVersionNumber(version) && {
|
||||
|
@ -243,7 +243,7 @@ const Overview: React.FC = () => {
|
||||
{cardContent}
|
||||
</a>
|
||||
) : (
|
||||
<Link to={url} prefetch key={component.title}>
|
||||
<Link to={url} key={component.title}>
|
||||
{cardContent}
|
||||
</Link>
|
||||
);
|
||||
|
@ -8,6 +8,7 @@ import tokenData from 'antd/es/version/token.json';
|
||||
|
||||
import useLocale from '../../../hooks/useLocale';
|
||||
import { useColumns } from '../TokenTable';
|
||||
import type { TokenData } from '../TokenTable';
|
||||
|
||||
const compare = (token1: string, token2: string) => {
|
||||
const hasColor1 = token1.toLowerCase().includes('color');
|
||||
@ -108,13 +109,13 @@ const SubTokenTable: React.FC<SubTokenTableProps> = (props) => {
|
||||
|
||||
const data = tokens
|
||||
.sort(component ? undefined : compare)
|
||||
.map((name) => {
|
||||
.map<TokenData>((name) => {
|
||||
const meta = component
|
||||
? tokenMeta.components[component].find((item) => item.token === name)
|
||||
: tokenMeta.global[name];
|
||||
|
||||
if (!meta) {
|
||||
return null;
|
||||
return null as unknown as TokenData;
|
||||
}
|
||||
|
||||
return {
|
||||
@ -156,7 +157,7 @@ const SubTokenTable: React.FC<SubTokenTableProps> = (props) => {
|
||||
{title}
|
||||
<Popover
|
||||
title={null}
|
||||
overlayStyle={{ width: 400 }}
|
||||
styles={{ root: { width: 400 } }}
|
||||
content={
|
||||
<Typography>
|
||||
{/* <SourceCode lang="jsx">{code}</SourceCode> */}
|
||||
@ -177,7 +178,7 @@ const SubTokenTable: React.FC<SubTokenTableProps> = (props) => {
|
||||
</div>
|
||||
{open && (
|
||||
<ConfigProvider theme={{ token: { borderRadius: 0 } }}>
|
||||
<Table
|
||||
<Table<TokenData>
|
||||
size="middle"
|
||||
columns={columns}
|
||||
bordered
|
||||
|
@ -1,19 +1,13 @@
|
||||
import React, { useContext } from 'react';
|
||||
import {
|
||||
BugFilled,
|
||||
BugOutlined,
|
||||
CodeFilled,
|
||||
CodeOutlined,
|
||||
ExperimentFilled,
|
||||
ExperimentOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { ConfigProvider, Tooltip } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import { DumiDemoGrid, FormattedMessage } from 'dumi';
|
||||
import React, { Suspense, useContext } from 'react';
|
||||
import { BugOutlined, CodeOutlined, ExperimentOutlined } from '@ant-design/icons';
|
||||
import { ConfigProvider, Tooltip, Button } from 'antd';
|
||||
import { DumiDemoGrid, FormattedMessage, DumiDemo } from 'dumi';
|
||||
import { css, Global } from '@emotion/react';
|
||||
|
||||
import useLayoutState from '../../../hooks/useLayoutState';
|
||||
import useLocale from '../../../hooks/useLocale';
|
||||
import DemoContext from '../../slots/DemoContext';
|
||||
import DemoFallback from '../Previewer/DemoFallback';
|
||||
|
||||
const locales = {
|
||||
cn: {
|
||||
@ -33,10 +27,6 @@ const DemoWrapper: typeof DumiDemoGrid = ({ items }) => {
|
||||
const [expandAll, setExpandAll] = useLayoutState(false);
|
||||
const [enableCssVar, setEnableCssVar] = useLayoutState(true);
|
||||
|
||||
const expandTriggerClass = classNames('code-box-expand-trigger', {
|
||||
'code-box-expand-trigger-active': expandAll,
|
||||
});
|
||||
|
||||
const handleVisibleToggle = () => {
|
||||
setShowDebug?.(!showDebug);
|
||||
};
|
||||
@ -77,39 +67,59 @@ const DemoWrapper: typeof DumiDemoGrid = ({ items }) => {
|
||||
|
||||
return (
|
||||
<div className="demo-wrapper">
|
||||
<Global
|
||||
styles={css`
|
||||
:root {
|
||||
--antd-site-api-deprecated-display: ${showDebug ? 'table-row' : 'none'};
|
||||
}
|
||||
`}
|
||||
/>
|
||||
<span className="all-code-box-controls">
|
||||
<Tooltip
|
||||
title={
|
||||
<FormattedMessage id={`app.component.examples.${expandAll ? 'collapse' : 'expand'}`} />
|
||||
}
|
||||
>
|
||||
{expandAll ? (
|
||||
<CodeFilled className={expandTriggerClass} onClick={handleExpandToggle} />
|
||||
) : (
|
||||
<CodeOutlined className={expandTriggerClass} onClick={handleExpandToggle} />
|
||||
)}
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
icon={<CodeOutlined />}
|
||||
onClick={handleExpandToggle}
|
||||
className={expandAll ? 'icon-enabled' : ''}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
title={
|
||||
<FormattedMessage id={`app.component.examples.${showDebug ? 'hide' : 'visible'}`} />
|
||||
}
|
||||
>
|
||||
{showDebug ? (
|
||||
<BugFilled className={expandTriggerClass} onClick={handleVisibleToggle} />
|
||||
) : (
|
||||
<BugOutlined className={expandTriggerClass} onClick={handleVisibleToggle} />
|
||||
)}
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
icon={<BugOutlined />}
|
||||
onClick={handleVisibleToggle}
|
||||
className={showDebug ? 'icon-enabled' : ''}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip title={enableCssVar ? locale.disableCssVar : locale.enableCssVar}>
|
||||
{enableCssVar ? (
|
||||
<ExperimentFilled className={expandTriggerClass} onClick={handleCssVarToggle} />
|
||||
) : (
|
||||
<ExperimentOutlined className={expandTriggerClass} onClick={handleCssVarToggle} />
|
||||
)}
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
icon={<ExperimentOutlined />}
|
||||
onClick={handleCssVarToggle}
|
||||
className={enableCssVar ? 'icon-enabled' : ''}
|
||||
/>
|
||||
</Tooltip>
|
||||
</span>
|
||||
<ConfigProvider theme={{ cssVar: enableCssVar, hashed: !enableCssVar }}>
|
||||
<DumiDemoGrid items={demos} />
|
||||
<DumiDemoGrid
|
||||
items={demos}
|
||||
demoRender={(item) => (
|
||||
<Suspense key={item.demo.id} fallback={<DemoFallback />}>
|
||||
<DumiDemo {...item} />
|
||||
</Suspense>
|
||||
)}
|
||||
/>
|
||||
</ConfigProvider>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,9 +1,9 @@
|
||||
import type { CSSProperties } from 'react';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import Icon, * as AntdIcons from '@ant-design/icons';
|
||||
import type { SegmentedProps } from 'antd';
|
||||
import { Affix, Empty, Input, Segmented } from 'antd';
|
||||
import { createStyles, useTheme } from 'antd-style';
|
||||
import type { SegmentedOptions } from 'antd/es/segmented';
|
||||
import { useIntl } from 'dumi';
|
||||
import debounce from 'lodash/debounce';
|
||||
|
||||
@ -28,26 +28,6 @@ const useStyle = createStyles(({ token, css }) => ({
|
||||
`,
|
||||
}));
|
||||
|
||||
const options = (
|
||||
formatMessage: (values: Record<string, string>) => React.ReactNode,
|
||||
): SegmentedProps['options'] => [
|
||||
{
|
||||
value: ThemeType.Outlined,
|
||||
icon: <Icon component={OutlinedIcon} />,
|
||||
label: formatMessage({ id: 'app.docs.components.icon.outlined' }),
|
||||
},
|
||||
{
|
||||
value: ThemeType.Filled,
|
||||
icon: <Icon component={FilledIcon} />,
|
||||
label: formatMessage({ id: 'app.docs.components.icon.filled' }),
|
||||
},
|
||||
{
|
||||
value: ThemeType.TwoTone,
|
||||
icon: <Icon component={TwoToneIcon} />,
|
||||
label: formatMessage({ id: 'app.docs.components.icon.two-tone' }),
|
||||
},
|
||||
];
|
||||
|
||||
interface IconSearchState {
|
||||
theme: ThemeType;
|
||||
searchKey: string;
|
||||
@ -80,7 +60,7 @@ const IconSearch: React.FC = () => {
|
||||
let iconList = categories[key as CategoriesKeys];
|
||||
if (searchKey) {
|
||||
const matchKey = searchKey
|
||||
// eslint-disable-next-line prefer-regex-literals
|
||||
|
||||
.replace(/^<([a-z]*)\s\/>$/gi, (_, name) => name)
|
||||
.replace(/(Filled|Outlined|TwoTone)$/, '')
|
||||
.toLowerCase();
|
||||
@ -124,14 +104,35 @@ const IconSearch: React.FC = () => {
|
||||
backgroundColor: colorBgContainer,
|
||||
};
|
||||
|
||||
const memoizedOptions = React.useMemo<SegmentedOptions<ThemeType>>(
|
||||
() => [
|
||||
{
|
||||
value: ThemeType.Outlined,
|
||||
icon: <Icon component={OutlinedIcon} />,
|
||||
label: intl.formatMessage({ id: 'app.docs.components.icon.outlined' }),
|
||||
},
|
||||
{
|
||||
value: ThemeType.Filled,
|
||||
icon: <Icon component={FilledIcon} />,
|
||||
label: intl.formatMessage({ id: 'app.docs.components.icon.filled' }),
|
||||
},
|
||||
{
|
||||
value: ThemeType.TwoTone,
|
||||
icon: <Icon component={TwoToneIcon} />,
|
||||
label: intl.formatMessage({ id: 'app.docs.components.icon.two-tone' }),
|
||||
},
|
||||
],
|
||||
[intl],
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="markdown">
|
||||
<Affix offsetTop={anchorTop} onChange={setSearchBarAffixed}>
|
||||
<div className={styles.iconSearchAffix} style={searchBarAffixed ? affixedStyle : {}}>
|
||||
<Segmented
|
||||
<Segmented<ThemeType>
|
||||
size="large"
|
||||
value={displayState.theme}
|
||||
options={options(intl.formatMessage)}
|
||||
options={memoizedOptions}
|
||||
onChange={handleChangeTheme}
|
||||
/>
|
||||
<Input.Search
|
||||
|
@ -44,15 +44,13 @@ const IconSearchFallback: React.FC = () => {
|
||||
</div>
|
||||
<Skeleton.Button active style={{ margin: '28px 0 10px', width: 100 }} />
|
||||
<div className={styles.fallbackWrapper}>
|
||||
{Array(24)
|
||||
.fill(1)
|
||||
.map((_, index) => (
|
||||
<div key={index} className={styles.skeletonWrapper}>
|
||||
<Skeleton.Node active style={{ height: 110, width: '100%' }}>
|
||||
{' '}
|
||||
</Skeleton.Node>
|
||||
</div>
|
||||
))}
|
||||
{new Array(24).fill(1).map((_, index) => (
|
||||
<div key={index} className={styles.skeletonWrapper}>
|
||||
<Skeleton.Node active style={{ height: 110, width: '100%' }}>
|
||||
{' '}
|
||||
</Skeleton.Node>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
80
.dumi/theme/builtins/Previewer/CodeBlockButton.tsx
Normal file
80
.dumi/theme/builtins/Previewer/CodeBlockButton.tsx
Normal file
@ -0,0 +1,80 @@
|
||||
import React, { Suspense, useEffect, useState } from 'react';
|
||||
import { Tooltip } from 'antd';
|
||||
import { FormattedMessage } from 'dumi';
|
||||
|
||||
import { ping } from '../../utils';
|
||||
|
||||
let pingDeferrer: PromiseLike<boolean>;
|
||||
|
||||
const codeBlockJs =
|
||||
'https://renderoffice.a' +
|
||||
'lipay' +
|
||||
'objects.com/p' +
|
||||
'/yuyan/180020010001206410/parseFileData-v1.0.1.js';
|
||||
|
||||
function useShowCodeBlockButton() {
|
||||
const [showCodeBlockButton, setShowCodeBlockButton] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
pingDeferrer ??= new Promise<boolean>((resolve) => {
|
||||
ping((status) => {
|
||||
if (status !== 'timeout' && status !== 'error') {
|
||||
// Async insert `codeBlockJs` into body end
|
||||
const script = document.createElement('script');
|
||||
script.src = codeBlockJs;
|
||||
script.async = true;
|
||||
document.body.appendChild(script);
|
||||
|
||||
return resolve(true);
|
||||
}
|
||||
return resolve(false);
|
||||
});
|
||||
});
|
||||
pingDeferrer.then(setShowCodeBlockButton);
|
||||
}, []);
|
||||
|
||||
return showCodeBlockButton;
|
||||
}
|
||||
|
||||
interface CodeBlockButtonProps {
|
||||
title?: string;
|
||||
dependencies: Record<PropertyKey, string>;
|
||||
jsx: string;
|
||||
}
|
||||
|
||||
const CodeBlockButton: React.FC<CodeBlockButtonProps> = ({ title, dependencies = {}, jsx }) => {
|
||||
const showCodeBlockButton = useShowCodeBlockButton();
|
||||
|
||||
const codeBlockPrefillConfig = {
|
||||
title: `${title} - antd@${dependencies.antd}`,
|
||||
js: `${
|
||||
/import React(\D*)from 'react';/.test(jsx) ? '' : `import React from 'react';\n`
|
||||
}import { createRoot } from 'react-dom/client';\n${jsx.replace(
|
||||
/export default/,
|
||||
'const ComponentDemo =',
|
||||
)}\n\ncreateRoot(mountNode).render(<ComponentDemo />);\n`,
|
||||
css: '',
|
||||
json: JSON.stringify({ name: 'antd-demo', dependencies }, null, 2),
|
||||
};
|
||||
|
||||
return showCodeBlockButton ? (
|
||||
<Tooltip title={<FormattedMessage id="app.demo.codeblock" />}>
|
||||
<div className="code-box-code-action">
|
||||
<img
|
||||
alt="codeblock"
|
||||
src="https://mdn.alipayobjects.com/huamei_wtld8u/afts/img/A*K8rjSJpTNQ8AAAAAAAAAAAAADhOIAQ/original"
|
||||
className="code-box-codeblock"
|
||||
onClick={() => {
|
||||
openHituCodeBlock(JSON.stringify(codeBlockPrefillConfig));
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Tooltip>
|
||||
) : null;
|
||||
};
|
||||
|
||||
export default (props: CodeBlockButtonProps) => (
|
||||
<Suspense>
|
||||
<CodeBlockButton {...props} />
|
||||
</Suspense>
|
||||
);
|
@ -16,11 +16,10 @@ import EditButton from '../../common/EditButton';
|
||||
import CodePenIcon from '../../icons/CodePenIcon';
|
||||
import CodeSandboxIcon from '../../icons/CodeSandboxIcon';
|
||||
import ExternalLinkIcon from '../../icons/ExternalLinkIcon';
|
||||
import RiddleIcon from '../../icons/RiddleIcon';
|
||||
import DemoContext from '../../slots/DemoContext';
|
||||
import type { SiteContextProps } from '../../slots/SiteContext';
|
||||
import SiteContext from '../../slots/SiteContext';
|
||||
import { ping } from '../../utils';
|
||||
import CodeBlockButton from './CodeBlockButton';
|
||||
import type { AntdPreviewerProps } from './Previewer';
|
||||
|
||||
const { ErrorBoundary } = Alert;
|
||||
@ -39,27 +38,6 @@ const track = ({ type, demo }: { type: string; demo: string }) => {
|
||||
window.gtag('event', 'demo', { event_category: type, event_label: demo });
|
||||
};
|
||||
|
||||
let pingDeferrer: PromiseLike<boolean>;
|
||||
|
||||
function useShowRiddleButton() {
|
||||
const [showRiddleButton, setShowRiddleButton] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
pingDeferrer ??= new Promise<boolean>((resolve) => {
|
||||
ping((status) => {
|
||||
if (status !== 'timeout' && status !== 'error') {
|
||||
return resolve(true);
|
||||
}
|
||||
|
||||
return resolve(false);
|
||||
});
|
||||
});
|
||||
pingDeferrer.then(setShowRiddleButton);
|
||||
}, []);
|
||||
|
||||
return showRiddleButton;
|
||||
}
|
||||
|
||||
const useStyle = createStyles(({ token }) => {
|
||||
const { borderRadius } = token;
|
||||
return {
|
||||
@ -98,7 +76,7 @@ const CodePreviewer: React.FC<AntdPreviewerProps> = (props) => {
|
||||
title,
|
||||
description,
|
||||
originDebug,
|
||||
jsx,
|
||||
jsx = '',
|
||||
style,
|
||||
compact,
|
||||
background,
|
||||
@ -108,7 +86,7 @@ const CodePreviewer: React.FC<AntdPreviewerProps> = (props) => {
|
||||
clientOnly,
|
||||
pkgDependencyList,
|
||||
} = props;
|
||||
const { showDebug, codeType } = useContext(DemoContext);
|
||||
const { codeType } = useContext(DemoContext);
|
||||
|
||||
const { pkg } = useSiteData();
|
||||
const location = useLocation();
|
||||
@ -117,8 +95,7 @@ const CodePreviewer: React.FC<AntdPreviewerProps> = (props) => {
|
||||
|
||||
const entryName = 'index.tsx';
|
||||
const entryCode = asset.dependencies[entryName].value;
|
||||
const showRiddleButton = useShowRiddleButton();
|
||||
|
||||
|
||||
const previewDemo = useRef<React.ReactNode>(null);
|
||||
const demoContainer = useRef<HTMLElement>(null);
|
||||
const {
|
||||
@ -127,11 +104,10 @@ const CodePreviewer: React.FC<AntdPreviewerProps> = (props) => {
|
||||
setSource: setLiveDemoSource,
|
||||
} = useLiveDemo(asset.id, {
|
||||
iframe: Boolean(iframe),
|
||||
containerRef: demoContainer,
|
||||
containerRef: demoContainer as React.RefObject<HTMLElement>,
|
||||
});
|
||||
const anchorRef = useRef<HTMLAnchorElement>(null);
|
||||
const codeSandboxIconRef = useRef<HTMLFormElement>(null);
|
||||
const riddleIconRef = useRef<HTMLFormElement>(null);
|
||||
const codepenIconRef = useRef<HTMLFormElement>(null);
|
||||
const [codeExpand, setCodeExpand] = useState<boolean>(false);
|
||||
const { theme } = useContext<SiteContextProps>(SiteContext);
|
||||
@ -278,18 +254,6 @@ const CodePreviewer: React.FC<AntdPreviewerProps> = (props) => {
|
||||
js_pre_processor: 'typescript',
|
||||
};
|
||||
|
||||
const riddlePrefillConfig = {
|
||||
title: `${localizedTitle} - antd@${dependencies.antd}`,
|
||||
js: `${
|
||||
/import React(\D*)from 'react';/.test(jsx) ? '' : `import React from 'react';\n`
|
||||
}import { createRoot } from 'react-dom/client';\n${jsx.replace(
|
||||
/export default/,
|
||||
'const ComponentDemo =',
|
||||
)}\n\ncreateRoot(mountNode).render(<ComponentDemo />);\n`,
|
||||
css: '',
|
||||
json: JSON.stringify({ name: 'antd-demo', dependencies }, null, 2),
|
||||
};
|
||||
|
||||
// Reorder source code
|
||||
let parsedSourceCode = suffix === 'tsx' ? entryCode : jsx;
|
||||
let importReactContent = "import React from 'react';";
|
||||
@ -420,24 +384,27 @@ createRoot(document.getElementById('container')).render(<Demo />);
|
||||
</a>
|
||||
</Tooltip>
|
||||
)}
|
||||
{showRiddleButton ? (
|
||||
<form
|
||||
className="code-box-code-action"
|
||||
action="//riddle.alibaba-inc.com/riddles/define"
|
||||
method="POST"
|
||||
target="_blank"
|
||||
ref={riddleIconRef}
|
||||
onClick={() => {
|
||||
track({ type: 'riddle', demo: asset.id });
|
||||
riddleIconRef.current?.submit();
|
||||
}}
|
||||
>
|
||||
<input type="hidden" name="data" value={JSON.stringify(riddlePrefillConfig)} />
|
||||
<Tooltip title={<FormattedMessage id="app.demo.riddle" />}>
|
||||
<RiddleIcon className="code-box-riddle" />
|
||||
</Tooltip>
|
||||
</form>
|
||||
) : null}
|
||||
<form
|
||||
className="code-box-code-action"
|
||||
action="https://codesandbox.io/api/v1/sandboxes/define"
|
||||
method="POST"
|
||||
target="_blank"
|
||||
ref={codeSandboxIconRef}
|
||||
onClick={() => {
|
||||
track({ type: 'codesandbox', demo: asset.id });
|
||||
codeSandboxIconRef.current?.submit();
|
||||
}}
|
||||
>
|
||||
<input
|
||||
type="hidden"
|
||||
name="parameters"
|
||||
value={compress(JSON.stringify(codesanboxPrefillConfig))}
|
||||
/>
|
||||
<Tooltip title={<FormattedMessage id="app.demo.codesandbox" />}>
|
||||
<CodeSandboxIcon className="code-box-codesandbox" />
|
||||
</Tooltip>
|
||||
</form>
|
||||
<CodeBlockButton title={localizedTitle} dependencies={dependencies} jsx={jsx} />
|
||||
<Tooltip title={<FormattedMessage id="app.demo.stackblitz" />}>
|
||||
<span
|
||||
className="code-box-code-action"
|
||||
@ -472,28 +439,6 @@ createRoot(document.getElementById('container')).render(<Demo />);
|
||||
<CodePenIcon className="code-box-codepen" />
|
||||
</Tooltip>
|
||||
</form>
|
||||
{showDebug && (
|
||||
<form
|
||||
className="code-box-code-action"
|
||||
action="https://codesandbox.io/api/v1/sandboxes/define"
|
||||
method="POST"
|
||||
target="_blank"
|
||||
ref={codeSandboxIconRef}
|
||||
onClick={() => {
|
||||
track({ type: 'codesandbox', demo: asset.id });
|
||||
codeSandboxIconRef.current?.submit();
|
||||
}}
|
||||
>
|
||||
<input
|
||||
type="hidden"
|
||||
name="parameters"
|
||||
value={compress(JSON.stringify(codesanboxPrefillConfig))}
|
||||
/>
|
||||
<Tooltip title={<FormattedMessage id="app.demo.codesandbox" />}>
|
||||
<CodeSandboxIcon className="code-box-codesandbox" />
|
||||
</Tooltip>
|
||||
</form>
|
||||
)}
|
||||
<Tooltip title={<FormattedMessage id="app.demo.separate" />}>
|
||||
<a
|
||||
className="code-box-code-action"
|
||||
|
27
.dumi/theme/builtins/Previewer/DemoFallback.tsx
Normal file
27
.dumi/theme/builtins/Previewer/DemoFallback.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
import React from 'react';
|
||||
import { Skeleton } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => ({
|
||||
skeletonWrapper: css`
|
||||
width: 100% !important;
|
||||
height: 250px;
|
||||
margin-bottom: ${token.margin}px;
|
||||
border-radius: ${token.borderRadiusLG}px;
|
||||
`,
|
||||
}));
|
||||
|
||||
const DemoFallback = () => {
|
||||
const { styles } = useStyle();
|
||||
return (
|
||||
<Skeleton.Node
|
||||
active
|
||||
className={styles.skeletonWrapper}
|
||||
style={{ width: '100%', height: '100%' }}
|
||||
>
|
||||
{' '}
|
||||
</Skeleton.Node>
|
||||
);
|
||||
};
|
||||
|
||||
export default DemoFallback;
|
@ -41,6 +41,10 @@ const useStyle = createStyles(({ token, css }) => ({
|
||||
`,
|
||||
copyTip: css`
|
||||
color: ${token.colorTextTertiary};
|
||||
border: none;
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
`,
|
||||
copiedTip: css`
|
||||
.anticon {
|
||||
|
@ -7,6 +7,7 @@ import DesignPreviewer from './DesignPreviewer';
|
||||
|
||||
export interface AntdPreviewerProps extends IPreviewerProps {
|
||||
originDebug?: IPreviewerProps['debug'];
|
||||
jsx?: string;
|
||||
}
|
||||
|
||||
const Previewer: React.FC<AntdPreviewerProps> = (props) => {
|
||||
|
91
.dumi/theme/builtins/Previewer/RiddleButton.tsx
Normal file
91
.dumi/theme/builtins/Previewer/RiddleButton.tsx
Normal file
@ -0,0 +1,91 @@
|
||||
import React, { Suspense, useEffect, useRef, useState } from 'react';
|
||||
import { Tooltip } from 'antd';
|
||||
import { FormattedMessage } from 'dumi';
|
||||
|
||||
import type { IPreviewerProps } from 'dumi';
|
||||
|
||||
import RiddleIcon from '../../icons/RiddleIcon';
|
||||
import { ping } from '../../utils';
|
||||
|
||||
let pingDeferrer: PromiseLike<boolean>;
|
||||
|
||||
function useShowRiddleButton() {
|
||||
const [showRiddleButton, setShowRiddleButton] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
pingDeferrer ??= new Promise<boolean>((resolve) => {
|
||||
ping((status) => {
|
||||
if (status !== 'timeout' && status !== 'error') {
|
||||
return resolve(true);
|
||||
}
|
||||
|
||||
return resolve(false);
|
||||
});
|
||||
});
|
||||
pingDeferrer.then(setShowRiddleButton);
|
||||
}, []);
|
||||
|
||||
return showRiddleButton;
|
||||
}
|
||||
|
||||
interface RiddleButtonProps {
|
||||
title?: string;
|
||||
dependencies: Record<PropertyKey, string>;
|
||||
jsx: string;
|
||||
track: ({
|
||||
type,
|
||||
demo,
|
||||
}: {
|
||||
type: string;
|
||||
demo: string;
|
||||
}) => void;
|
||||
asset: IPreviewerProps['asset'];
|
||||
}
|
||||
|
||||
const RiddleButton: React.FC<RiddleButtonProps> = ({
|
||||
title,
|
||||
dependencies = {},
|
||||
jsx,
|
||||
track,
|
||||
asset,
|
||||
}) => {
|
||||
const riddleIconRef = useRef<HTMLFormElement>(null);
|
||||
const showRiddleButton = useShowRiddleButton();
|
||||
|
||||
const riddlePrefillConfig = {
|
||||
title: `${title} - antd@${dependencies.antd}`,
|
||||
js: `${
|
||||
/import React(\D*)from 'react';/.test(jsx) ? '' : `import React from 'react';\n`
|
||||
}import { createRoot } from 'react-dom/client';\n${jsx.replace(
|
||||
/export default/,
|
||||
'const ComponentDemo =',
|
||||
)}\n\ncreateRoot(mountNode).render(<ComponentDemo />);\n`,
|
||||
css: '',
|
||||
json: JSON.stringify({ name: 'antd-demo', dependencies }, null, 2),
|
||||
};
|
||||
|
||||
return showRiddleButton ? (
|
||||
<form
|
||||
className="code-box-code-action"
|
||||
action="//riddle.alibaba-inc.com/riddles/define"
|
||||
method="POST"
|
||||
target="_blank"
|
||||
ref={riddleIconRef}
|
||||
onClick={() => {
|
||||
track({ type: 'riddle', demo: asset.id });
|
||||
riddleIconRef.current?.submit();
|
||||
}}
|
||||
>
|
||||
<input type="hidden" name="data" value={JSON.stringify(riddlePrefillConfig)} />
|
||||
<Tooltip title={<FormattedMessage id="app.demo.riddle" />}>
|
||||
<RiddleIcon className="code-box-riddle" />
|
||||
</Tooltip>
|
||||
</form>
|
||||
) : null;
|
||||
};
|
||||
|
||||
export default (props: RiddleButtonProps) => (
|
||||
<Suspense>
|
||||
<RiddleButton {...props} />
|
||||
</Suspense>
|
||||
);
|
@ -1,40 +1,17 @@
|
||||
import React, { Suspense } from 'react';
|
||||
import { Alert, Skeleton } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
import { Alert } from 'antd';
|
||||
import Previewer from './Previewer';
|
||||
import DemoFallback from './DemoFallback';
|
||||
import type { IPreviewerProps } from 'dumi';
|
||||
|
||||
const { ErrorBoundary } = Alert;
|
||||
|
||||
const Previewer = React.lazy(() => import('./Previewer'));
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => ({
|
||||
skeletonWrapper: css`
|
||||
width: 100% !important;
|
||||
height: 250px;
|
||||
margin-bottom: ${token.margin}px;
|
||||
border-radius: ${token.borderRadiusLG}px;
|
||||
`,
|
||||
}));
|
||||
|
||||
const PreviewerSuspense: React.FC<IPreviewerProps> = (props) => {
|
||||
const { styles } = useStyle();
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
<Suspense
|
||||
fallback={
|
||||
<Skeleton.Node
|
||||
active
|
||||
className={styles.skeletonWrapper}
|
||||
style={{ width: '100%', height: '100%' }}
|
||||
>
|
||||
{' '}
|
||||
</Skeleton.Node>
|
||||
}
|
||||
>
|
||||
<Previewer {...props} />
|
||||
</Suspense>
|
||||
</ErrorBoundary>
|
||||
);
|
||||
};
|
||||
const PreviewerSuspense: React.FC<IPreviewerProps> = (props) => (
|
||||
<ErrorBoundary>
|
||||
<Suspense fallback={<DemoFallback />}>
|
||||
<Previewer {...props} />
|
||||
</Suspense>
|
||||
</ErrorBoundary>
|
||||
);
|
||||
|
||||
export default PreviewerSuspense;
|
||||
|
@ -1,4 +1,3 @@
|
||||
/* eslint-disable react/no-array-index-key */
|
||||
import * as React from 'react';
|
||||
import { Avatar, Divider, Empty, Skeleton, Tabs } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
|
@ -11,7 +11,7 @@ const useStyle = createStyles(({ token, css }) => ({
|
||||
card: css`
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
.${token.antCls}-card-cover {
|
||||
${token.antCls}-card-cover {
|
||||
overflow: hidden;
|
||||
}
|
||||
img {
|
||||
|
@ -1,6 +1,6 @@
|
||||
// 用于 color.md 中的颜色对比
|
||||
import React from 'react';
|
||||
import { TinyColor } from '@ctrl/tinycolor';
|
||||
import { FastColor } from '@ant-design/fast-color';
|
||||
import { Flex, theme } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
import tokenMeta from 'antd/es/version/token-meta.json';
|
||||
@ -55,7 +55,7 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
});
|
||||
|
||||
function color2Rgba(color: string) {
|
||||
return `#${new TinyColor(color).toHex8().toUpperCase()}`;
|
||||
return `#${new FastColor(color).toHexString().toUpperCase()}`;
|
||||
}
|
||||
|
||||
interface ColorCircleProps {
|
||||
|
@ -14,7 +14,7 @@ type TokenTableProps = {
|
||||
lang: 'zh' | 'en';
|
||||
};
|
||||
|
||||
type TokenData = {
|
||||
export type TokenData = {
|
||||
name: string;
|
||||
desc: string;
|
||||
type: string;
|
||||
@ -99,7 +99,7 @@ const TokenTable: FC<TokenTableProps> = ({ type }) => {
|
||||
name: token,
|
||||
desc: lang === 'cn' ? meta.desc : meta.descEn,
|
||||
type: meta.type,
|
||||
value: defaultToken[token],
|
||||
value: defaultToken[token as keyof typeof defaultToken],
|
||||
})),
|
||||
[type, lang],
|
||||
);
|
||||
|
@ -1,185 +1,7 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import G6 from '@antv/g6';
|
||||
import { createStyles, css } from 'antd-style';
|
||||
import { useRouteMeta } from 'dumi';
|
||||
|
||||
G6.registerNode('behavior-start-node', {
|
||||
draw: (cfg, group) => {
|
||||
const textWidth = G6.Util.getTextSize(cfg!.label, 16)[0];
|
||||
const size = [textWidth + 20 * 2, 48];
|
||||
const keyShape = group!.addShape('rect', {
|
||||
name: 'start-node',
|
||||
attrs: {
|
||||
width: size[0],
|
||||
height: size[1],
|
||||
y: -size[1] / 2,
|
||||
radius: 8,
|
||||
fill: '#fff',
|
||||
},
|
||||
});
|
||||
group!.addShape('text', {
|
||||
attrs: {
|
||||
text: `${cfg!.label}`,
|
||||
fill: 'rgba(0, 0, 0, 0.88)',
|
||||
fontSize: 16,
|
||||
fontWeight: 500,
|
||||
x: 20,
|
||||
textBaseline: 'middle',
|
||||
},
|
||||
name: 'start-node-text',
|
||||
});
|
||||
return keyShape;
|
||||
},
|
||||
getAnchorPoints() {
|
||||
return [
|
||||
[0, 0.5],
|
||||
[1, 0.5],
|
||||
];
|
||||
},
|
||||
});
|
||||
|
||||
G6.registerNode(
|
||||
'behavior-sub-node',
|
||||
{
|
||||
draw: (cfg, group) => {
|
||||
const textWidth = G6.Util.getTextSize(cfg!.label, 14)[0];
|
||||
const padding = 16;
|
||||
const size = [textWidth + 16 * 2 + (cfg!.targetType ? 12 : 0) + (cfg!.link ? 20 : 0), 40];
|
||||
const keyShape = group!.addShape('rect', {
|
||||
name: 'sub-node',
|
||||
attrs: {
|
||||
width: size[0],
|
||||
height: size[1],
|
||||
y: -size[1] / 2,
|
||||
radius: 8,
|
||||
fill: '#fff',
|
||||
cursor: 'pointer',
|
||||
},
|
||||
});
|
||||
group!.addShape('text', {
|
||||
attrs: {
|
||||
text: `${cfg!.label}`,
|
||||
x: cfg!.targetType ? 12 + 16 : padding,
|
||||
fill: 'rgba(0, 0, 0, 0.88)',
|
||||
fontSize: 14,
|
||||
textBaseline: 'middle',
|
||||
cursor: 'pointer',
|
||||
},
|
||||
name: 'sub-node-text',
|
||||
});
|
||||
if (cfg!.targetType) {
|
||||
group!.addShape('rect', {
|
||||
name: 'sub-node-type',
|
||||
attrs: {
|
||||
width: 8,
|
||||
height: 8,
|
||||
radius: 4,
|
||||
y: -4,
|
||||
x: 12,
|
||||
fill: cfg!.targetType === 'mvp' ? '#1677ff' : '#A0A0A0',
|
||||
cursor: 'pointer',
|
||||
},
|
||||
});
|
||||
}
|
||||
if (cfg!.children) {
|
||||
const { length } = cfg!.children as any;
|
||||
group!.addShape('rect', {
|
||||
name: 'sub-node-children-length',
|
||||
attrs: {
|
||||
width: 20,
|
||||
height: 20,
|
||||
radius: 10,
|
||||
y: -10,
|
||||
x: size[0] - 4,
|
||||
fill: '#404040',
|
||||
cursor: 'pointer',
|
||||
},
|
||||
});
|
||||
group!.addShape('text', {
|
||||
name: 'sub-node-children-length-text',
|
||||
attrs: {
|
||||
text: `${length}`,
|
||||
x: size[0] + 6 - G6.Util.getTextSize(`${length}`, 12)[0] / 2,
|
||||
textBaseline: 'middle',
|
||||
fill: '#fff',
|
||||
fontSize: 12,
|
||||
cursor: 'pointer',
|
||||
},
|
||||
});
|
||||
}
|
||||
if (cfg!.link) {
|
||||
group!.addShape('dom', {
|
||||
attrs: {
|
||||
width: 16,
|
||||
height: 16,
|
||||
x: size[0] - 12 - 16,
|
||||
y: -8,
|
||||
cursor: 'pointer',
|
||||
// DOM's html
|
||||
html: `
|
||||
<div style="width: 16px; height: 16px;">
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="DatePicker" transform="translate(-890.000000, -441.000000)" fill-rule="nonzero">
|
||||
<g id="编组-30" transform="translate(288.000000, 354.000000)">
|
||||
<g id="编组-7备份-7" transform="translate(522.000000, 79.000000)">
|
||||
<g id="right-circle-outlinedd" transform="translate(80.000000, 8.000000)">
|
||||
<rect id="矩形" fill="#000000" opacity="0" x="0" y="0" width="16" height="16"></rect>
|
||||
<path d="M10.4171875,7.8984375 L6.5734375,5.1171875 C6.490625,5.0578125 6.375,5.115625 6.375,5.21875 L6.375,5.9515625 C6.375,6.1109375 6.4515625,6.2625 6.58125,6.35625 L8.853125,8 L6.58125,9.64375 C6.4515625,9.7375 6.375,9.8875 6.375,10.0484375 L6.375,10.78125 C6.375,10.8828125 6.490625,10.9421875 6.5734375,10.8828125 L10.4171875,8.1015625 C10.4859375,8.0515625 10.4859375,7.9484375 10.4171875,7.8984375 Z" id="路径" fill="#BFBFBF"></path>
|
||||
<path d="M8,1 C4.134375,1 1,4.134375 1,8 C1,11.865625 4.134375,15 8,15 C11.865625,15 15,11.865625 15,8 C15,4.134375 11.865625,1 8,1 Z M8,13.8125 C4.790625,13.8125 2.1875,11.209375 2.1875,8 C2.1875,4.790625 4.790625,2.1875 8,2.1875 C11.209375,2.1875 13.8125,4.790625 13.8125,8 C13.8125,11.209375 11.209375,13.8125 8,13.8125 Z" id="形状" fill="#BFBFBF"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
`,
|
||||
},
|
||||
// 在 G6 3.3 及之后的版本中,必须指定 name,可以是任意字符串,但需要在同一个自定义元素类型中保持唯一性
|
||||
name: 'sub-node-link',
|
||||
});
|
||||
}
|
||||
return keyShape;
|
||||
},
|
||||
getAnchorPoints() {
|
||||
return [
|
||||
[0, 0.5],
|
||||
[1, 0.5],
|
||||
];
|
||||
},
|
||||
options: {
|
||||
stateStyles: {
|
||||
hover: {
|
||||
stroke: '#1677ff',
|
||||
'sub-node-link': {
|
||||
html: `
|
||||
<div style="width: 16px; height: 16px;">
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="DatePicker" transform="translate(-890.000000, -441.000000)" fill-rule="nonzero">
|
||||
<g id="编组-30" transform="translate(288.000000, 354.000000)">
|
||||
<g id="编组-7备份-7" transform="translate(522.000000, 79.000000)">
|
||||
<g id="right-circle-outlinedd" transform="translate(80.000000, 8.000000)">
|
||||
<rect id="矩形" fill="#000000" opacity="0" x="0" y="0" width="16" height="16"></rect>
|
||||
<path d="M10.4171875,7.8984375 L6.5734375,5.1171875 C6.490625,5.0578125 6.375,5.115625 6.375,5.21875 L6.375,5.9515625 C6.375,6.1109375 6.4515625,6.2625 6.58125,6.35625 L8.853125,8 L6.58125,9.64375 C6.4515625,9.7375 6.375,9.8875 6.375,10.0484375 L6.375,10.78125 C6.375,10.8828125 6.490625,10.9421875 6.5734375,10.8828125 L10.4171875,8.1015625 C10.4859375,8.0515625 10.4859375,7.9484375 10.4171875,7.8984375 Z" id="路径" fill="#1677ff"></path>
|
||||
<path d="M8,1 C4.134375,1 1,4.134375 1,8 C1,11.865625 4.134375,15 8,15 C11.865625,15 15,11.865625 15,8 C15,4.134375 11.865625,1 8,1 Z M8,13.8125 C4.790625,13.8125 2.1875,11.209375 2.1875,8 C2.1875,4.790625 4.790625,2.1875 8,2.1875 C11.209375,2.1875 13.8125,4.790625 13.8125,8 C13.8125,11.209375 11.209375,13.8125 8,13.8125 Z" id="形状" fill="#1677ff"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'rect',
|
||||
);
|
||||
|
||||
const dataTransform = (data: BehaviorMapItem) => {
|
||||
const changeData = (d: any, level = 0) => {
|
||||
const clonedData: any = {
|
||||
@ -275,48 +97,229 @@ const BehaviorMap: React.FC<BehaviorMapProps> = ({ data }) => {
|
||||
const meta = useRouteMeta();
|
||||
|
||||
useEffect(() => {
|
||||
const graph = new G6.TreeGraph({
|
||||
container: ref.current!,
|
||||
width: ref.current!.scrollWidth,
|
||||
height: ref.current!.scrollHeight,
|
||||
renderer: 'svg',
|
||||
modes: {
|
||||
default: ['collapse-expand', 'drag-canvas'],
|
||||
},
|
||||
defaultEdge: {
|
||||
type: 'cubic-horizontal',
|
||||
style: {
|
||||
lineWidth: 1,
|
||||
stroke: '#BFBFBF',
|
||||
import('@antv/g6').then((G6) => {
|
||||
G6.registerNode('behavior-start-node', {
|
||||
draw: (cfg, group) => {
|
||||
const textWidth = G6.Util.getTextSize(cfg!.label, 16)[0];
|
||||
const size = [textWidth + 20 * 2, 48];
|
||||
const keyShape = group!.addShape('rect', {
|
||||
name: 'start-node',
|
||||
attrs: {
|
||||
width: size[0],
|
||||
height: size[1],
|
||||
y: -size[1] / 2,
|
||||
radius: 8,
|
||||
fill: '#fff',
|
||||
},
|
||||
});
|
||||
group!.addShape('text', {
|
||||
attrs: {
|
||||
text: `${cfg!.label}`,
|
||||
fill: 'rgba(0, 0, 0, 0.88)',
|
||||
fontSize: 16,
|
||||
fontWeight: 500,
|
||||
x: 20,
|
||||
textBaseline: 'middle',
|
||||
},
|
||||
name: 'start-node-text',
|
||||
});
|
||||
return keyShape;
|
||||
},
|
||||
},
|
||||
layout: {
|
||||
type: 'mindmap',
|
||||
direction: 'LR',
|
||||
getHeight: () => 48,
|
||||
getWidth: (node: any) => G6.Util.getTextSize(node.label, 16)[0] + 20 * 2,
|
||||
getVGap: () => 10,
|
||||
getHGap: () => 60,
|
||||
getSide: (node: any) => node.data.direction,
|
||||
},
|
||||
});
|
||||
getAnchorPoints() {
|
||||
return [
|
||||
[0, 0.5],
|
||||
[1, 0.5],
|
||||
];
|
||||
},
|
||||
});
|
||||
|
||||
graph.on('node:mouseenter', (e) => {
|
||||
graph.setItemState(e.item!, 'hover', true);
|
||||
});
|
||||
graph.on('node:mouseleave', (e) => {
|
||||
graph.setItemState(e.item!, 'hover', false);
|
||||
});
|
||||
graph.on('node:click', (e) => {
|
||||
const { link } = e.item!.getModel();
|
||||
if (link) {
|
||||
window.location.hash = link as string;
|
||||
}
|
||||
});
|
||||
G6.registerNode(
|
||||
'behavior-sub-node',
|
||||
{
|
||||
draw: (cfg, group) => {
|
||||
const textWidth = G6.Util.getTextSize(cfg!.label, 14)[0];
|
||||
const padding = 16;
|
||||
const size = [
|
||||
textWidth + 16 * 2 + (cfg!.targetType ? 12 : 0) + (cfg!.link ? 20 : 0),
|
||||
40,
|
||||
];
|
||||
const keyShape = group!.addShape('rect', {
|
||||
name: 'sub-node',
|
||||
attrs: {
|
||||
width: size[0],
|
||||
height: size[1],
|
||||
y: -size[1] / 2,
|
||||
radius: 8,
|
||||
fill: '#fff',
|
||||
cursor: 'pointer',
|
||||
},
|
||||
});
|
||||
group!.addShape('text', {
|
||||
attrs: {
|
||||
text: `${cfg!.label}`,
|
||||
x: cfg!.targetType ? 12 + 16 : padding,
|
||||
fill: 'rgba(0, 0, 0, 0.88)',
|
||||
fontSize: 14,
|
||||
textBaseline: 'middle',
|
||||
cursor: 'pointer',
|
||||
},
|
||||
name: 'sub-node-text',
|
||||
});
|
||||
if (cfg!.targetType) {
|
||||
group!.addShape('rect', {
|
||||
name: 'sub-node-type',
|
||||
attrs: {
|
||||
width: 8,
|
||||
height: 8,
|
||||
radius: 4,
|
||||
y: -4,
|
||||
x: 12,
|
||||
fill: cfg!.targetType === 'mvp' ? '#1677ff' : '#A0A0A0',
|
||||
cursor: 'pointer',
|
||||
},
|
||||
});
|
||||
}
|
||||
if (cfg!.children) {
|
||||
const { length } = cfg!.children as any;
|
||||
group!.addShape('rect', {
|
||||
name: 'sub-node-children-length',
|
||||
attrs: {
|
||||
width: 20,
|
||||
height: 20,
|
||||
radius: 10,
|
||||
y: -10,
|
||||
x: size[0] - 4,
|
||||
fill: '#404040',
|
||||
cursor: 'pointer',
|
||||
},
|
||||
});
|
||||
group!.addShape('text', {
|
||||
name: 'sub-node-children-length-text',
|
||||
attrs: {
|
||||
text: `${length}`,
|
||||
x: size[0] + 6 - G6.Util.getTextSize(`${length}`, 12)[0] / 2,
|
||||
textBaseline: 'middle',
|
||||
fill: '#fff',
|
||||
fontSize: 12,
|
||||
cursor: 'pointer',
|
||||
},
|
||||
});
|
||||
}
|
||||
if (cfg!.link) {
|
||||
group!.addShape('dom', {
|
||||
attrs: {
|
||||
width: 16,
|
||||
height: 16,
|
||||
x: size[0] - 12 - 16,
|
||||
y: -8,
|
||||
cursor: 'pointer',
|
||||
// DOM's html
|
||||
html: `
|
||||
<div style="width: 16px; height: 16px;">
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="DatePicker" transform="translate(-890.000000, -441.000000)" fill-rule="nonzero">
|
||||
<g id="编组-30" transform="translate(288.000000, 354.000000)">
|
||||
<g id="编组-7备份-7" transform="translate(522.000000, 79.000000)">
|
||||
<g id="right-circle-outlinedd" transform="translate(80.000000, 8.000000)">
|
||||
<rect id="矩形" fill="#000000" opacity="0" x="0" y="0" width="16" height="16"></rect>
|
||||
<path d="M10.4171875,7.8984375 L6.5734375,5.1171875 C6.490625,5.0578125 6.375,5.115625 6.375,5.21875 L6.375,5.9515625 C6.375,6.1109375 6.4515625,6.2625 6.58125,6.35625 L8.853125,8 L6.58125,9.64375 C6.4515625,9.7375 6.375,9.8875 6.375,10.0484375 L6.375,10.78125 C6.375,10.8828125 6.490625,10.9421875 6.5734375,10.8828125 L10.4171875,8.1015625 C10.4859375,8.0515625 10.4859375,7.9484375 10.4171875,7.8984375 Z" id="路径" fill="#BFBFBF"></path>
|
||||
<path d="M8,1 C4.134375,1 1,4.134375 1,8 C1,11.865625 4.134375,15 8,15 C11.865625,15 15,11.865625 15,8 C15,4.134375 11.865625,1 8,1 Z M8,13.8125 C4.790625,13.8125 2.1875,11.209375 2.1875,8 C2.1875,4.790625 4.790625,2.1875 8,2.1875 C11.209375,2.1875 13.8125,4.790625 13.8125,8 C13.8125,11.209375 11.209375,13.8125 8,13.8125 Z" id="形状" fill="#BFBFBF"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
`,
|
||||
},
|
||||
// 在 G6 3.3 及之后的版本中,必须指定 name,可以是任意字符串,但需要在同一个自定义元素类型中保持唯一性
|
||||
name: 'sub-node-link',
|
||||
});
|
||||
}
|
||||
return keyShape;
|
||||
},
|
||||
getAnchorPoints() {
|
||||
return [
|
||||
[0, 0.5],
|
||||
[1, 0.5],
|
||||
];
|
||||
},
|
||||
options: {
|
||||
stateStyles: {
|
||||
hover: {
|
||||
stroke: '#1677ff',
|
||||
'sub-node-link': {
|
||||
html: `
|
||||
<div style="width: 16px; height: 16px;">
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="DatePicker" transform="translate(-890.000000, -441.000000)" fill-rule="nonzero">
|
||||
<g id="编组-30" transform="translate(288.000000, 354.000000)">
|
||||
<g id="编组-7备份-7" transform="translate(522.000000, 79.000000)">
|
||||
<g id="right-circle-outlinedd" transform="translate(80.000000, 8.000000)">
|
||||
<rect id="矩形" fill="#000000" opacity="0" x="0" y="0" width="16" height="16"></rect>
|
||||
<path d="M10.4171875,7.8984375 L6.5734375,5.1171875 C6.490625,5.0578125 6.375,5.115625 6.375,5.21875 L6.375,5.9515625 C6.375,6.1109375 6.4515625,6.2625 6.58125,6.35625 L8.853125,8 L6.58125,9.64375 C6.4515625,9.7375 6.375,9.8875 6.375,10.0484375 L6.375,10.78125 C6.375,10.8828125 6.490625,10.9421875 6.5734375,10.8828125 L10.4171875,8.1015625 C10.4859375,8.0515625 10.4859375,7.9484375 10.4171875,7.8984375 Z" id="路径" fill="#1677ff"></path>
|
||||
<path d="M8,1 C4.134375,1 1,4.134375 1,8 C1,11.865625 4.134375,15 8,15 C11.865625,15 15,11.865625 15,8 C15,4.134375 11.865625,1 8,1 Z M8,13.8125 C4.790625,13.8125 2.1875,11.209375 2.1875,8 C2.1875,4.790625 4.790625,2.1875 8,2.1875 C11.209375,2.1875 13.8125,4.790625 13.8125,8 C13.8125,11.209375 11.209375,13.8125 8,13.8125 Z" id="形状" fill="#1677ff"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'rect',
|
||||
);
|
||||
const graph = new G6.TreeGraph({
|
||||
container: ref.current!,
|
||||
width: ref.current!.scrollWidth,
|
||||
height: ref.current!.scrollHeight,
|
||||
renderer: 'svg',
|
||||
modes: {
|
||||
default: ['collapse-expand', 'drag-canvas'],
|
||||
},
|
||||
defaultEdge: {
|
||||
type: 'cubic-horizontal',
|
||||
style: {
|
||||
lineWidth: 1,
|
||||
stroke: '#BFBFBF',
|
||||
},
|
||||
},
|
||||
layout: {
|
||||
type: 'mindmap',
|
||||
direction: 'LR',
|
||||
getHeight: () => 48,
|
||||
getWidth: (node: any) => G6.Util.getTextSize(node.label, 16)[0] + 20 * 2,
|
||||
getVGap: () => 10,
|
||||
getHGap: () => 60,
|
||||
getSide: (node: any) => node.data.direction,
|
||||
},
|
||||
});
|
||||
|
||||
graph.data(dataTransform(data));
|
||||
graph.render();
|
||||
graph.fitCenter();
|
||||
graph.on('node:mouseenter', (e) => {
|
||||
graph.setItemState(e.item!, 'hover', true);
|
||||
});
|
||||
graph.on('node:mouseleave', (e) => {
|
||||
graph.setItemState(e.item!, 'hover', false);
|
||||
});
|
||||
graph.on('node:click', (e) => {
|
||||
const { link } = e.item!.getModel();
|
||||
if (link) {
|
||||
window.location.hash = link as string;
|
||||
}
|
||||
});
|
||||
|
||||
graph.data(dataTransform(data));
|
||||
graph.render();
|
||||
graph.fitCenter();
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import { Col, ColorPicker, Row } from 'antd';
|
||||
import { FormattedMessage } from 'dumi';
|
||||
import type { Color } from 'antd/es/color-picker';
|
||||
import { FormattedMessage } from 'dumi';
|
||||
|
||||
import useLocale from '../../../hooks/useLocale';
|
||||
import ColorPatterns from './ColorPatterns';
|
||||
@ -34,7 +34,7 @@ const ColorPaletteTool: React.FC = () => {
|
||||
setPrimaryColorInstance(color);
|
||||
};
|
||||
|
||||
const handleChangeBackgroundColor = (_, hex: string) => {
|
||||
const handleChangeBackgroundColor = (_: Color, hex: string) => {
|
||||
setBackgroundColor(hex);
|
||||
};
|
||||
|
||||
|
@ -5,6 +5,9 @@ import CopyToClipboard from 'react-copy-to-clipboard';
|
||||
|
||||
const rgbToHex = (rgbString: string): string => {
|
||||
const rgb = rgbString.match(/\d+/g);
|
||||
if (!rgb) {
|
||||
return '';
|
||||
}
|
||||
let r = parseInt(rgb[0], 10).toString(16);
|
||||
let g = parseInt(rgb[1], 10).toString(16);
|
||||
let b = parseInt(rgb[2], 10).toString(16);
|
||||
|
@ -1,7 +1,6 @@
|
||||
/* eslint-disable global-require, import/no-unresolved */
|
||||
import React from 'react';
|
||||
import { BugOutlined, HistoryOutlined } from '@ant-design/icons';
|
||||
import { Button, Drawer, Grid, Popover, Timeline, Typography } from 'antd';
|
||||
import React, { cloneElement, isValidElement } from 'react';
|
||||
import { BugOutlined } from '@ant-design/icons';
|
||||
import { Button, Drawer, Flex, Grid, Popover, Tag, Timeline, Typography } from 'antd';
|
||||
import type { TimelineItemProps } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
import semver from 'semver';
|
||||
@ -9,6 +8,7 @@ import semver from 'semver';
|
||||
import deprecatedVersions from '../../../../BUG_VERSIONS.json';
|
||||
import useFetch from '../../../hooks/useFetch';
|
||||
import useLocale from '../../../hooks/useLocale';
|
||||
import useLocation from '../../../hooks/useLocation';
|
||||
import Link from '../Link';
|
||||
|
||||
interface MatchDeprecatedResult {
|
||||
@ -16,6 +16,14 @@ interface MatchDeprecatedResult {
|
||||
reason: string[];
|
||||
}
|
||||
|
||||
interface ChangelogInfo {
|
||||
version: string;
|
||||
changelog: string;
|
||||
refs: string[];
|
||||
contributors: string[];
|
||||
releaseDate: string;
|
||||
}
|
||||
|
||||
function matchDeprecated(v: string): MatchDeprecatedResult {
|
||||
const match = Object.keys(deprecatedVersions).find((depreciated) =>
|
||||
semver.satisfies(v, depreciated),
|
||||
@ -28,6 +36,11 @@ function matchDeprecated(v: string): MatchDeprecatedResult {
|
||||
}
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => ({
|
||||
listWrap: css`
|
||||
> li {
|
||||
line-height: 2;
|
||||
}
|
||||
`,
|
||||
linkRef: css`
|
||||
margin-inline-start: ${token.marginXS}px;
|
||||
`,
|
||||
@ -64,15 +77,30 @@ const useStyle = createStyles(({ token, css }) => ({
|
||||
position: 'relative',
|
||||
[`> ${token.antCls}-drawer-body`]: {
|
||||
scrollbarWidth: 'thin',
|
||||
scrollbarColor: 'unset',
|
||||
scrollbarGutter: 'stable',
|
||||
},
|
||||
},
|
||||
versionWrap: css`
|
||||
margin-bottom: 1em;
|
||||
`,
|
||||
versionTitle: css`
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
font-weight: 600;
|
||||
font-size: 20px;
|
||||
margin: 0 !important;
|
||||
`,
|
||||
versionTag: css`
|
||||
user-select: none;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
&:last-child {
|
||||
margin-inline-end: 0;
|
||||
}
|
||||
`,
|
||||
}));
|
||||
|
||||
export interface ComponentChangelogProps {
|
||||
pathname: string;
|
||||
}
|
||||
|
||||
const locales = {
|
||||
cn: {
|
||||
full: '查看完整日志',
|
||||
@ -90,29 +118,38 @@ const locales = {
|
||||
},
|
||||
};
|
||||
|
||||
const ParseChangelog: React.FC<{ changelog: string; refs: string[]; styles: any }> = (props) => {
|
||||
const { changelog = '', refs = [], styles } = props;
|
||||
const ParseChangelog: React.FC<{ changelog: string }> = (props) => {
|
||||
const { changelog = '' } = props;
|
||||
|
||||
const parsedChangelog = React.useMemo(() => {
|
||||
const nodes: React.ReactNode[] = [];
|
||||
|
||||
let isQuota = false;
|
||||
let isBold = false;
|
||||
let lastStr = '';
|
||||
|
||||
for (let i = 0; i < changelog.length; i += 1) {
|
||||
const char = changelog[i];
|
||||
const isDoubleAsterisk = char === '*' && changelog[i + 1] === '*';
|
||||
|
||||
if (char !== '`') {
|
||||
if (char !== '`' && !isDoubleAsterisk) {
|
||||
lastStr += char;
|
||||
} else {
|
||||
let node: React.ReactNode = lastStr;
|
||||
if (isQuota) {
|
||||
node = <code>{node}</code>;
|
||||
} else if (isBold) {
|
||||
node = <strong>{node}</strong>;
|
||||
}
|
||||
|
||||
nodes.push(node);
|
||||
lastStr = '';
|
||||
isQuota = !isQuota;
|
||||
if (char === '`') {
|
||||
isQuota = !isQuota;
|
||||
} else if (isDoubleAsterisk) {
|
||||
isBold = !isBold;
|
||||
i += 1; // Skip the next '*'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,25 +158,72 @@ const ParseChangelog: React.FC<{ changelog: string; refs: string[]; styles: any
|
||||
return nodes;
|
||||
}, [changelog]);
|
||||
|
||||
return <span>{parsedChangelog}</span>;
|
||||
};
|
||||
|
||||
const RefLinks: React.FC<{ refs: string[]; contributors: string[] }> = ({ refs, contributors }) => {
|
||||
const { styles } = useStyle();
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Changelog */}
|
||||
<span>{parsedChangelog}</span>
|
||||
{/* Refs */}
|
||||
{refs?.map((ref) => (
|
||||
<a className={styles.linkRef} key={ref} href={ref} target="_blank" rel="noreferrer">
|
||||
#{ref.match(/^.*\/(\d+)$/)?.[1]}
|
||||
</a>
|
||||
<React.Fragment key={ref}>
|
||||
<a className={styles.linkRef} key={ref} href={ref} target="_blank" rel="noreferrer">
|
||||
#{ref.match(/[^/]+$/)?.[0]}
|
||||
</a>
|
||||
</React.Fragment>
|
||||
))}
|
||||
{contributors?.map((contributor) => (
|
||||
<React.Fragment key={contributor}>
|
||||
<a
|
||||
className={styles.linkRef}
|
||||
key={contributor}
|
||||
href={`https://github.com/${contributor}`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
@{contributor}
|
||||
</a>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
interface ChangelogInfo {
|
||||
version: string;
|
||||
changelog: string;
|
||||
refs: string[];
|
||||
}
|
||||
const RenderChangelogList: React.FC<{ changelogList: ChangelogInfo[] }> = ({ changelogList }) => {
|
||||
const elements: React.ReactNode[] = [];
|
||||
const { styles } = useStyle();
|
||||
const len = changelogList.length;
|
||||
for (let i = 0; i < len; i += 1) {
|
||||
const { refs, changelog, contributors } = changelogList[i];
|
||||
// Check if the next line is an image link and append it to the current line
|
||||
if (i + 1 < len && changelogList[i + 1].changelog.trim().startsWith('<img')) {
|
||||
const imgDom = new DOMParser().parseFromString(changelogList[i + 1].changelog, 'text/html');
|
||||
const imgElement = imgDom.querySelector<HTMLImageElement>('img');
|
||||
elements.push(
|
||||
<li key={i}>
|
||||
<ParseChangelog changelog={changelog} />
|
||||
<RefLinks refs={refs} contributors={contributors} />
|
||||
<br />
|
||||
<img
|
||||
src={imgElement?.getAttribute('src') || ''}
|
||||
alt={imgElement?.getAttribute('alt') || ''}
|
||||
width={imgElement?.getAttribute('width') || ''}
|
||||
/>
|
||||
</li>,
|
||||
);
|
||||
i += 1; // Skip the next line
|
||||
} else {
|
||||
elements.push(
|
||||
<li key={i}>
|
||||
<ParseChangelog changelog={changelog} />
|
||||
<RefLinks refs={refs} contributors={contributors} />
|
||||
</li>,
|
||||
);
|
||||
}
|
||||
}
|
||||
return <ul className={styles.listWrap}>{elements}</ul>;
|
||||
};
|
||||
|
||||
const useChangelog = (componentPath: string, lang: 'cn' | 'en'): ChangelogInfo[] => {
|
||||
const logFileName = `components-changelog-${lang}.json`;
|
||||
@ -157,10 +241,11 @@ const useChangelog = (componentPath: string, lang: 'cn' | 'en'): ChangelogInfo[]
|
||||
}, [data, componentPath]);
|
||||
};
|
||||
|
||||
const ComponentChangelog: React.FC<ComponentChangelogProps> = (props) => {
|
||||
const { pathname = '' } = props;
|
||||
const ComponentChangelog: React.FC<Readonly<React.PropsWithChildren>> = (props) => {
|
||||
const { children } = props;
|
||||
const [locale, lang] = useLocale(locales);
|
||||
const [show, setShow] = React.useState(false);
|
||||
const { pathname } = useLocation();
|
||||
|
||||
const { styles } = useStyle();
|
||||
|
||||
@ -182,42 +267,46 @@ const ComponentChangelog: React.FC<ComponentChangelogProps> = (props) => {
|
||||
return {
|
||||
children: (
|
||||
<Typography>
|
||||
<Typography.Title level={4}>
|
||||
{version}
|
||||
{bugVersionInfo.match && (
|
||||
<Popover
|
||||
destroyTooltipOnHide
|
||||
placement="right"
|
||||
title={<span className={styles.bugReasonTitle}>{locale.bugList}</span>}
|
||||
content={
|
||||
<ul className={styles.bugReasonList}>
|
||||
{bugVersionInfo.reason.map<React.ReactNode>((reason, index) => (
|
||||
<li key={`reason-${index}`}>
|
||||
<a type="link" target="_blank" rel="noreferrer" href={reason}>
|
||||
<BugOutlined />
|
||||
{reason
|
||||
?.replace(/#.*$/, '')
|
||||
?.replace(
|
||||
/^https:\/\/github\.com\/ant-design\/ant-design\/(issues|pull)\//,
|
||||
'#',
|
||||
)}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
}
|
||||
>
|
||||
<BugOutlined className={styles.bug} />
|
||||
</Popover>
|
||||
)}
|
||||
</Typography.Title>
|
||||
<ul>
|
||||
{changelogList.map<React.ReactNode>((info, index) => (
|
||||
<li key={index}>
|
||||
<ParseChangelog {...info} styles={styles} />
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<Flex className={styles.versionWrap} justify="flex-start" align="center" gap="middle">
|
||||
<Button
|
||||
color="default"
|
||||
className={styles.versionTitle}
|
||||
variant="link"
|
||||
href={`/changelog${lang === 'cn' ? '-cn' : ''}/#${version.replace(/\./g, '').replace(/\s.*/g, '-')}`}
|
||||
>
|
||||
{version}
|
||||
{bugVersionInfo.match && (
|
||||
<Popover
|
||||
destroyTooltipOnHide
|
||||
placement="right"
|
||||
title={<span className={styles.bugReasonTitle}>{locale.bugList}</span>}
|
||||
content={
|
||||
<ul className={styles.bugReasonList}>
|
||||
{bugVersionInfo.reason.map<React.ReactNode>((reason, index) => (
|
||||
<li key={`reason-${index}`}>
|
||||
<a type="link" target="_blank" rel="noreferrer" href={reason}>
|
||||
<BugOutlined />
|
||||
{reason
|
||||
?.replace(/#.*$/, '')
|
||||
?.replace(
|
||||
/^https:\/\/github\.com\/ant-design\/ant-design\/(issues|pull)\//,
|
||||
'#',
|
||||
)}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
}
|
||||
>
|
||||
<BugOutlined className={styles.bug} />
|
||||
</Popover>
|
||||
)}
|
||||
</Button>
|
||||
<Tag className={styles.versionTag} bordered={false} color="blue">
|
||||
{changelogList[0]?.releaseDate}
|
||||
</Tag>
|
||||
</Flex>
|
||||
<RenderChangelogList changelogList={changelogList} />
|
||||
</Typography>
|
||||
),
|
||||
};
|
||||
@ -227,15 +316,16 @@ const ComponentChangelog: React.FC<ComponentChangelogProps> = (props) => {
|
||||
const screens = Grid.useBreakpoint();
|
||||
const width = screens.md ? '48vw' : '90vw';
|
||||
|
||||
if (!list || !list.length) {
|
||||
if (!pathname.startsWith('/components/') || !list || !list.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button icon={<HistoryOutlined />} onClick={() => setShow(true)}>
|
||||
{locale.changelog}
|
||||
</Button>
|
||||
{isValidElement(children) &&
|
||||
cloneElement(children as React.ReactElement<any>, {
|
||||
onClick: () => setShow(true),
|
||||
})}
|
||||
<Drawer
|
||||
destroyOnClose
|
||||
className={styles.drawerContent}
|
||||
|
@ -1,10 +1,11 @@
|
||||
import React from 'react';
|
||||
|
||||
import type { ComponentChangelogProps } from './ComponentChangelog';
|
||||
import ComponentChangelog from './ComponentChangelog';
|
||||
|
||||
export default (props: ComponentChangelogProps) => (
|
||||
const ChangeLog: React.FC<Readonly<React.PropsWithChildren>> = ({ children }) => (
|
||||
<React.Suspense fallback={null}>
|
||||
<ComponentChangelog {...props} />
|
||||
<ComponentChangelog>{children}</ComponentChangelog>
|
||||
</React.Suspense>
|
||||
);
|
||||
|
||||
export default ChangeLog;
|
||||
|
@ -1,16 +1,20 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import type { JSONEditorPropsOptional } from 'vanilla-jsoneditor';
|
||||
import { JSONEditor, Mode } from 'vanilla-jsoneditor';
|
||||
import type { JsonEditor, JSONEditorPropsOptional } from 'vanilla-jsoneditor';
|
||||
import { createJSONEditor, Mode } from 'vanilla-jsoneditor';
|
||||
|
||||
const Editor: React.FC<JSONEditorPropsOptional> = (props) => {
|
||||
const editorRef = useRef<JSONEditor>(null);
|
||||
const editorRef = useRef<JsonEditor>();
|
||||
const container = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
editorRef.current = new JSONEditor({
|
||||
target: container.current,
|
||||
props: { mode: Mode.text },
|
||||
});
|
||||
if (container.current) {
|
||||
editorRef.current = createJSONEditor({
|
||||
target: container.current,
|
||||
props: {
|
||||
mode: Mode.text,
|
||||
},
|
||||
});
|
||||
}
|
||||
return () => {
|
||||
editorRef.current?.destroy();
|
||||
};
|
||||
|
@ -1,7 +1,6 @@
|
||||
import type { MouseEvent, MouseEventHandler } from 'react';
|
||||
import React, { forwardRef, useLayoutEffect, useTransition } from 'react';
|
||||
import { Link as DumiLink, useLocation, useNavigate } from 'dumi';
|
||||
import nprogress from 'nprogress';
|
||||
import React, { useMemo, forwardRef } from 'react';
|
||||
import { Link as DumiLink, useLocation, useAppData, useNavigate } from 'dumi';
|
||||
|
||||
export interface LinkProps {
|
||||
to: string | { pathname?: string; search?: string; hash?: string };
|
||||
@ -9,64 +8,49 @@ export interface LinkProps {
|
||||
className?: string;
|
||||
onClick?: MouseEventHandler;
|
||||
component?: React.ComponentType<any>;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
nprogress.configure({ showSpinner: false });
|
||||
|
||||
const Link = forwardRef<HTMLAnchorElement, React.PropsWithChildren<LinkProps>>((props, ref) => {
|
||||
const { to, children, component, ...rest } = props;
|
||||
const [isPending, startTransition] = useTransition();
|
||||
const navigate = useNavigate();
|
||||
const { pathname } = useLocation();
|
||||
|
||||
const href = React.useMemo<string>(() => {
|
||||
if (typeof to === 'object') {
|
||||
return `${to.pathname || pathname}${to.search || ''}${to.hash || ''}`;
|
||||
}
|
||||
return to;
|
||||
}, [to]);
|
||||
|
||||
const handleClick = (e: MouseEvent<HTMLAnchorElement>) => {
|
||||
props.onClick?.(e);
|
||||
if (!href?.startsWith('http')) {
|
||||
// Should support open in new tab
|
||||
if (!e.metaKey && !e.ctrlKey && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
startTransition(() => {
|
||||
if (href) {
|
||||
navigate(href);
|
||||
}
|
||||
});
|
||||
const Link = forwardRef<HTMLAnchorElement, React.PropsWithChildren<LinkProps>>(
|
||||
({ component, children, to, ...rest }, ref) => {
|
||||
const { pathname } = useLocation();
|
||||
const { preloadRoute } = useAppData();
|
||||
const navigate = useNavigate();
|
||||
const href = useMemo<string>(() => {
|
||||
if (typeof to === 'object') {
|
||||
return `${to.pathname || pathname}${to.search || ''}${to.hash || ''}`;
|
||||
}
|
||||
return to;
|
||||
}, [to]);
|
||||
const onClick = (e: MouseEvent<HTMLAnchorElement>) => {
|
||||
rest.onClick?.(e);
|
||||
if (!href?.startsWith('http')) {
|
||||
// Should support open in new tab
|
||||
if (!e.metaKey && !e.ctrlKey && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
navigate(href);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (component) {
|
||||
return React.createElement(
|
||||
component,
|
||||
{
|
||||
...rest,
|
||||
ref,
|
||||
href,
|
||||
onClick,
|
||||
onMouseEnter: () => preloadRoute?.(href),
|
||||
},
|
||||
children,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (isPending) {
|
||||
nprogress.start();
|
||||
} else {
|
||||
nprogress.done();
|
||||
}
|
||||
}, [isPending]);
|
||||
|
||||
if (component) {
|
||||
return React.createElement(
|
||||
component,
|
||||
{
|
||||
...rest,
|
||||
ref,
|
||||
onClick: handleClick,
|
||||
href,
|
||||
},
|
||||
children,
|
||||
return (
|
||||
<DumiLink ref={ref} {...rest} to={href} prefetch>
|
||||
{children}
|
||||
</DumiLink>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<DumiLink ref={ref} onClick={handleClick} {...rest} to={href} prefetch>
|
||||
{children}
|
||||
</DumiLink>
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
export default Link;
|
||||
|
@ -15,7 +15,7 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
background: ${colorBgContainer};
|
||||
&-scroll-container {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: unset;
|
||||
scrollbar-gutter: stable;
|
||||
}
|
||||
}
|
||||
.dumi-default-source-code > pre,
|
||||
|
@ -141,13 +141,23 @@ const PrevAndNext: React.FC<{ rtl?: boolean }> = ({ rtl }) => {
|
||||
return (
|
||||
<section className={styles.prevNextNav}>
|
||||
{prev &&
|
||||
React.cloneElement(prev.label as ReactElement, {
|
||||
className: classNames(styles.pageNav, styles.prevNav, prev.className),
|
||||
})}
|
||||
React.cloneElement(
|
||||
prev.label as ReactElement<{
|
||||
className: string;
|
||||
}>,
|
||||
{
|
||||
className: classNames(styles.pageNav, styles.prevNav, prev.className),
|
||||
},
|
||||
)}
|
||||
{next &&
|
||||
React.cloneElement(next.label as ReactElement, {
|
||||
className: classNames(styles.pageNav, styles.nextNav, next.className),
|
||||
})}
|
||||
React.cloneElement(
|
||||
next.label as ReactElement<{
|
||||
className: string;
|
||||
}>,
|
||||
{
|
||||
className: classNames(styles.pageNav, styles.nextNav, next.className),
|
||||
},
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
@ -1,21 +1,19 @@
|
||||
import React from 'react';
|
||||
import Icon from '@ant-design/icons';
|
||||
|
||||
const ThemeIcon: React.FC<{ className?: string }> = (props) => {
|
||||
const SVGIcon = React.useCallback(
|
||||
() => (
|
||||
<svg width={20} height={20} viewBox="0 0 24 24" fill="currentColor" {...props}>
|
||||
<title>Theme icon</title>
|
||||
<g fillRule="evenodd">
|
||||
<g fillRule="nonzero">
|
||||
<path d="M7.02 3.635l12.518 12.518a1.863 1.863 0 010 2.635l-1.317 1.318a1.863 1.863 0 01-2.635 0L3.068 7.588A2.795 2.795 0 117.02 3.635zm2.09 14.428a.932.932 0 110 1.864.932.932 0 010-1.864zm-.043-9.747L7.75 9.635l9.154 9.153 1.318-1.317-9.154-9.155zM3.52 12.473c.514 0 .931.417.931.931v.932h.932a.932.932 0 110 1.864h-.932v.931a.932.932 0 01-1.863 0l-.001-.931h-.93a.932.932 0 010-1.864h.93v-.932c0-.514.418-.931.933-.931zm15.374-3.727a1.398 1.398 0 110 2.795 1.398 1.398 0 010-2.795zM4.385 4.953a.932.932 0 000 1.317l2.046 2.047L7.75 7 5.703 4.953a.932.932 0 00-1.318 0zM14.701.36a.932.932 0 01.931.932v.931h.932a.932.932 0 010 1.864h-.933l.001.932a.932.932 0 11-1.863 0l-.001-.932h-.93a.932.932 0 110-1.864h.93v-.931a.932.932 0 01.933-.932z" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
),
|
||||
[props],
|
||||
);
|
||||
return <Icon component={SVGIcon} {...props} />;
|
||||
};
|
||||
const SVGIcon: React.FC = (props) => (
|
||||
<svg width={20} height={20} viewBox="0 0 24 24" fill="currentColor" {...props}>
|
||||
<title>Theme icon</title>
|
||||
<g fillRule="evenodd">
|
||||
<g fillRule="nonzero">
|
||||
<path d="M7.02 3.635l12.518 12.518a1.863 1.863 0 010 2.635l-1.317 1.318a1.863 1.863 0 01-2.635 0L3.068 7.588A2.795 2.795 0 117.02 3.635zm2.09 14.428a.932.932 0 110 1.864.932.932 0 010-1.864zm-.043-9.747L7.75 9.635l9.154 9.153 1.318-1.317-9.154-9.155zM3.52 12.473c.514 0 .931.417.931.931v.932h.932a.932.932 0 110 1.864h-.932v.931a.932.932 0 01-1.863 0l-.001-.931h-.93a.932.932 0 010-1.864h.93v-.932c0-.514.418-.931.933-.931zm15.374-3.727a1.398 1.398 0 110 2.795 1.398 1.398 0 010-2.795zM4.385 4.953a.932.932 0 000 1.317l2.046 2.047L7.75 7 5.703 4.953a.932.932 0 00-1.318 0zM14.701.36a.932.932 0 01.931.932v.931h.932a.932.932 0 010 1.864h-.933l.001.932a.932.932 0 11-1.863 0l-.001-.932h-.93a.932.932 0 110-1.864h.93v-.931a.932.932 0 01.933-.932z" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
||||
const ThemeIcon: React.FC<{ className?: string }> = (props) => (
|
||||
<Icon component={SVGIcon} {...props} />
|
||||
);
|
||||
|
||||
export default ThemeIcon;
|
||||
|
@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
import { BgColorsOutlined, SmileOutlined } from '@ant-design/icons';
|
||||
import { FloatButton } from 'antd';
|
||||
import { useTheme } from 'antd-style';
|
||||
import { CompactTheme, DarkTheme } from 'antd-token-previewer/es/icons';
|
||||
// import { Motion } from 'antd-token-previewer/es/icons';
|
||||
import { FormattedMessage, useLocation } from 'dumi';
|
||||
@ -20,7 +19,6 @@ export interface ThemeSwitchProps {
|
||||
|
||||
const ThemeSwitch: React.FC<ThemeSwitchProps> = (props) => {
|
||||
const { value = ['light'], onChange } = props;
|
||||
const token = useTheme();
|
||||
const { pathname, search } = useLocation();
|
||||
|
||||
// const isMotionOff = value.includes('motion-off');
|
||||
@ -38,7 +36,7 @@ const ThemeSwitch: React.FC<ThemeSwitchProps> = (props) => {
|
||||
>
|
||||
<Link
|
||||
to={getLocalizedPathname('/theme-editor', isZhCN(pathname), search)}
|
||||
style={{ display: 'block', marginBottom: token.margin }}
|
||||
style={{ display: 'block' }}
|
||||
>
|
||||
<FloatButton
|
||||
icon={<BgColorsOutlined />}
|
||||
|
@ -71,18 +71,6 @@ const GlobalDemoStyles: React.FC = () => {
|
||||
border: 1px solid ${token.colorPrimary};
|
||||
}
|
||||
|
||||
&-expand-trigger {
|
||||
position: relative;
|
||||
color: #3b4357;
|
||||
font-size: ${token.fontSizeXL}px;
|
||||
cursor: pointer;
|
||||
opacity: 0.75;
|
||||
transition: all ${token.motionDurationSlow};
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&-title {
|
||||
position: absolute;
|
||||
top: -14px;
|
||||
@ -294,12 +282,13 @@ const GlobalDemoStyles: React.FC = () => {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&-riddle {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
&-codeblock {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
overflow: hidden;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
&-codesandbox {
|
||||
@ -353,7 +342,18 @@ const GlobalDemoStyles: React.FC = () => {
|
||||
inset-inline-end: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
column-gap: ${token.marginSM}px;
|
||||
column-gap: ${token.marginXS}px;
|
||||
}
|
||||
|
||||
${antCls}-btn {
|
||||
&.icon-enabled {
|
||||
background-color: ${token.colorFillSecondary};
|
||||
opacity: 1;
|
||||
${iconCls} {
|
||||
color: ${token.colorTextBase};
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
${antCls}-row-rtl {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { TinyColor } from '@ctrl/tinycolor';
|
||||
import { FastColor } from '@ant-design/fast-color';
|
||||
import { css, Global } from '@emotion/react';
|
||||
import { useTheme } from 'antd-style';
|
||||
|
||||
@ -34,7 +34,8 @@ const GlobalStyle: React.FC = () => {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.markdown p > img {
|
||||
.markdown p > img,
|
||||
.markdown li > img {
|
||||
margin: 34px auto;
|
||||
box-shadow: 0 8px 20px rgba(143, 168, 191, 0.35);
|
||||
display: block;
|
||||
@ -168,7 +169,7 @@ const GlobalStyle: React.FC = () => {
|
||||
border-radius: ${token.borderRadius}px;
|
||||
> pre.prism-code {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: unset;
|
||||
scrollbar-gutter: stable;
|
||||
padding: ${token.paddingSM}px ${token.paddingMD}px;
|
||||
font-size: ${token.fontSize}px;
|
||||
line-height: 2;
|
||||
@ -271,7 +272,7 @@ const GlobalStyle: React.FC = () => {
|
||||
.markdown .dumi-default-table {
|
||||
&-content {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: unset;
|
||||
scrollbar-gutter: stable;
|
||||
}
|
||||
table {
|
||||
margin: 0;
|
||||
@ -372,6 +373,24 @@ const GlobalStyle: React.FC = () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Api 表中某些属性用 del 标记,表示已废弃(但仍期望给开发者一个过渡期)用 css 标记出来。仅此而已。
|
||||
有更多看法?移步讨论区: https://github.com/ant-design/ant-design/discussions/51298
|
||||
*/
|
||||
tr:has(td:first-child > del) {
|
||||
color: ${token.colorWarning} !important;
|
||||
background-color: ${token.colorWarningBg} !important;
|
||||
display: var(--antd-site-api-deprecated-display, none);
|
||||
|
||||
del {
|
||||
color: ${token.colorWarning};
|
||||
}
|
||||
|
||||
&:hover del {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.grid-demo,
|
||||
@ -391,7 +410,7 @@ const GlobalStyle: React.FC = () => {
|
||||
background: ${demoGridColor};
|
||||
|
||||
&:nth-child(2n + 1) {
|
||||
background: ${new TinyColor(demoGridColor).setAlpha(0.75).toHex8String()};
|
||||
background: ${new FastColor(demoGridColor).setA(0.75).toHexString()};
|
||||
}
|
||||
}
|
||||
|
||||
@ -407,12 +426,12 @@ const GlobalStyle: React.FC = () => {
|
||||
}
|
||||
|
||||
${antCls}-row .demo-col-1 {
|
||||
background: ${new TinyColor(demoGridColor).setAlpha(0.75).toHexString()};
|
||||
background: ${new FastColor(demoGridColor).setA(0.75).toHexString()};
|
||||
}
|
||||
|
||||
${antCls}-row .demo-col-2,
|
||||
.code-box-demo ${antCls}-row .demo-col-2 {
|
||||
background: ${new TinyColor(demoGridColor).setAlpha(0.75).toHexString()};
|
||||
background: ${new FastColor(demoGridColor).setA(0.75).toHexString()};
|
||||
}
|
||||
|
||||
${antCls}-row .demo-col-3,
|
||||
@ -423,7 +442,7 @@ const GlobalStyle: React.FC = () => {
|
||||
|
||||
${antCls}-row .demo-col-4,
|
||||
.code-box-demo ${antCls}-row .demo-col-4 {
|
||||
background: ${new TinyColor(demoGridColor).setAlpha(0.6).toHexString()};
|
||||
background: ${new FastColor(demoGridColor).setA(0.6).toHexString()};
|
||||
}
|
||||
|
||||
${antCls}-row .demo-col-5,
|
||||
|
@ -37,7 +37,7 @@ const DocLayout: React.FC = () => {
|
||||
const location = useLocation();
|
||||
const { pathname, search, hash } = location;
|
||||
const [locale, lang] = useLocale(locales);
|
||||
const timerRef = useRef<ReturnType<typeof setTimeout>>();
|
||||
const timerRef = useRef<ReturnType<typeof setTimeout>>(null!);
|
||||
const { direction } = useContext(SiteContext);
|
||||
const { loading } = useSiteData();
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React, { Suspense, useCallback, useEffect } from 'react';
|
||||
import { Monitoring } from 'react-scan/monitoring';
|
||||
import {
|
||||
createCache,
|
||||
extractStyle,
|
||||
@ -12,7 +13,13 @@ import { getSandpackCssText } from '@codesandbox/sandpack-react';
|
||||
import { theme as antdTheme, App } from 'antd';
|
||||
import type { MappingAlgorithm } from 'antd';
|
||||
import type { DirectionType, ThemeConfig } from 'antd/es/config-provider';
|
||||
import { createSearchParams, useOutlet, useSearchParams, useServerInsertedHTML } from 'dumi';
|
||||
import {
|
||||
createSearchParams,
|
||||
useOutlet,
|
||||
useParams,
|
||||
useSearchParams,
|
||||
useServerInsertedHTML,
|
||||
} from 'dumi';
|
||||
|
||||
import { DarkContext } from '../../hooks/useDark';
|
||||
import useLayoutState from '../../hooks/useLayoutState';
|
||||
@ -22,6 +29,8 @@ import SiteThemeProvider from '../SiteThemeProvider';
|
||||
import type { SiteContextProps } from '../slots/SiteContext';
|
||||
import SiteContext from '../slots/SiteContext';
|
||||
|
||||
import '@ant-design/v5-patch-for-react-19';
|
||||
|
||||
const ThemeSwitch = React.lazy(() => import('../common/ThemeSwitch'));
|
||||
|
||||
type Entries<T> = { [K in keyof T]: [K, T[K]] }[keyof T][];
|
||||
@ -61,6 +70,7 @@ const getAlgorithm = (themes: ThemeName[] = []) =>
|
||||
const GlobalLayout: React.FC = () => {
|
||||
const outlet = useOutlet();
|
||||
const { pathname } = useLocation();
|
||||
const params = useParams();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const [{ theme = [], direction, isMobile, bannerVisible = false }, setSiteState] =
|
||||
useLayoutState<SiteState>({
|
||||
@ -70,6 +80,9 @@ const GlobalLayout: React.FC = () => {
|
||||
bannerVisible: false,
|
||||
});
|
||||
|
||||
// TODO: This can be remove in v6
|
||||
const useCssVar = searchParams.get('cssVar') !== 'false';
|
||||
|
||||
const updateSiteConfig = useCallback(
|
||||
(props: SiteState) => {
|
||||
setSiteState((prev) => ({ ...prev, ...props }));
|
||||
@ -150,8 +163,8 @@ const GlobalLayout: React.FC = () => {
|
||||
() => ({
|
||||
algorithm: getAlgorithm(theme),
|
||||
token: { motion: !theme.includes('motion-off') },
|
||||
cssVar: true,
|
||||
hashed: false,
|
||||
cssVar: useCssVar,
|
||||
hashed: !useCssVar,
|
||||
}),
|
||||
[theme],
|
||||
);
|
||||
@ -220,7 +233,17 @@ const GlobalLayout: React.FC = () => {
|
||||
>
|
||||
<SiteContext.Provider value={siteContextValue}>
|
||||
<SiteThemeProvider theme={themeConfig}>
|
||||
<HappyProvider disabled={!theme.includes('happy-work')}>{content}</HappyProvider>
|
||||
<HappyProvider disabled={!theme.includes('happy-work')}>
|
||||
{content}
|
||||
<Monitoring
|
||||
apiKey="GhrCCNrHZHXlf4P6E03ntrFwhRLxJL30" // Safe to expose publically
|
||||
url="https://monitoring.react-scan.com/api/v1/ingest"
|
||||
commit={process.env.COMMIT_HASH}
|
||||
branch={process.env.BRANCH}
|
||||
params={params as Record<string, string>}
|
||||
path={pathname}
|
||||
/>
|
||||
</HappyProvider>
|
||||
</SiteThemeProvider>
|
||||
</SiteContext.Provider>
|
||||
</StyleProvider>
|
||||
|
@ -35,7 +35,7 @@
|
||||
"app.demo.codepen": "Open in CodePen",
|
||||
"app.demo.codesandbox": "Open in CodeSandbox",
|
||||
"app.demo.stackblitz": "Open in Stackblitz",
|
||||
"app.demo.riddle": "Open in Riddle",
|
||||
"app.demo.codeblock": "Open in Hitu",
|
||||
"app.demo.separate": "Open in a new window",
|
||||
"app.demo.online": "Online Address",
|
||||
"app.home.introduce": "A design system for enterprise-level products. Create an efficient and enjoyable work experience.",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"app.demo.codepen": "在 CodePen 中打开",
|
||||
"app.demo.codesandbox": "在 CodeSandbox 中打开",
|
||||
"app.demo.stackblitz": "在 Stackblitz 中打开",
|
||||
"app.demo.riddle": "在 Riddle 中打开",
|
||||
"app.demo.codeblock": "在海兔中打开",
|
||||
"app.demo.separate": "在新窗口打开",
|
||||
"app.demo.online": "线上地址",
|
||||
"app.home.introduce": "企业级产品设计体系,创造高效愉悦的工作体验",
|
||||
|
@ -2,7 +2,6 @@ import { createHash } from 'crypto';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import createEmotionServer from '@emotion/server/create-instance';
|
||||
import chalk from 'chalk';
|
||||
import type { IApi, IRoute } from 'dumi';
|
||||
import ReactTechStack from 'dumi/dist/techStacks/react';
|
||||
import sylvanas from 'sylvanas';
|
||||
@ -37,7 +36,6 @@ export const getHash = (str: string, length = 8) =>
|
||||
* extends dumi internal tech stack, for customize previewer props
|
||||
*/
|
||||
class AntdReactTechStack extends ReactTechStack {
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
generatePreviewerProps(...[props, opts]: any) {
|
||||
props.pkgDependencyList = { ...devDependencies, ...dependencies };
|
||||
props.jsx ??= '';
|
||||
@ -127,7 +125,8 @@ class AntdReactTechStack extends ReactTechStack {
|
||||
|
||||
const resolve = (p: string): string => require.resolve(p);
|
||||
|
||||
const RoutesPlugin = (api: IApi) => {
|
||||
const RoutesPlugin = async (api: IApi) => {
|
||||
const chalk = await import('chalk').then((m) => m.default);
|
||||
// const ssrCssFileName = `ssr-${Date.now()}.css`;
|
||||
|
||||
const writeCSSFile = (key: string, hashKey: string, cssString: string) => {
|
||||
|
@ -1,19 +1,6 @@
|
||||
import React from 'react';
|
||||
import type { AvatarListItem } from '@qixian.cs/github-contributors-list/dist/AvatarList';
|
||||
import { Avatar, Skeleton, Tooltip } from 'antd';
|
||||
|
||||
const AvatarPlaceholder: React.FC<{ num?: number }> = ({ num = 3 }) => (
|
||||
<li>
|
||||
{Array.from({ length: num }).map<React.ReactNode>((_, i) => (
|
||||
<Skeleton.Avatar
|
||||
size="small"
|
||||
active
|
||||
key={i}
|
||||
style={{ marginInlineStart: i === 0 ? 0 : -8 }}
|
||||
/>
|
||||
))}
|
||||
</li>
|
||||
);
|
||||
import { Avatar, Tooltip } from 'antd';
|
||||
|
||||
interface ContributorAvatarProps {
|
||||
loading?: boolean;
|
||||
@ -23,11 +10,7 @@ interface ContributorAvatarProps {
|
||||
const ContributorAvatar: React.FC<ContributorAvatarProps> = (props) => {
|
||||
const {
|
||||
item: { username, url } = {},
|
||||
loading,
|
||||
} = props;
|
||||
if (loading) {
|
||||
return <AvatarPlaceholder />;
|
||||
}
|
||||
if (username?.includes('github-actions')) {
|
||||
return null;
|
||||
}
|
||||
|
@ -8,9 +8,6 @@ import SiteContext from '../SiteContext';
|
||||
import ContributorAvatar from './ContributorAvatar';
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => ({
|
||||
contributorsList: css`
|
||||
margin-top: 120px !important;
|
||||
`,
|
||||
listMobile: css`
|
||||
margin: 1em 0 !important;
|
||||
`,
|
||||
@ -50,7 +47,7 @@ const Contributors: React.FC<ContributorsProps> = ({ filename }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classNames(styles.contributorsList, { [styles.listMobile]: isMobile })}>
|
||||
<div className={classNames({ [styles.listMobile]: isMobile })}>
|
||||
<div className={styles.title}>{formatMessage({ id: 'app.content.contributors' })}</div>
|
||||
<ContributorsList
|
||||
cache
|
||||
|
@ -5,12 +5,12 @@ import type { AnchorLinkItemProps } from 'antd/es/anchor/Anchor';
|
||||
import classNames from 'classnames';
|
||||
import { useRouteMeta, useTabMeta } from 'dumi';
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => {
|
||||
export const useStyle = createStyles(({ token, css }) => {
|
||||
const { antCls } = token;
|
||||
return {
|
||||
anchorToc: css`
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: unset;
|
||||
scrollbar-gutter: stable;
|
||||
${antCls}-anchor {
|
||||
${antCls}-anchor-link-title {
|
||||
font-size: ${token.fontSizeSM}px;
|
||||
@ -19,13 +19,13 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
`,
|
||||
tocWrapper: css`
|
||||
position: fixed;
|
||||
top: ${token.headerHeight + token.contentMarginTop - 8}px;
|
||||
top: ${token.headerHeight + token.contentMarginTop - 4}px;
|
||||
inset-inline-end: 0;
|
||||
width: 160px;
|
||||
padding: ${token.paddingXS}px;
|
||||
width: 148px;
|
||||
padding: 0;
|
||||
border-radius: ${token.borderRadius}px;
|
||||
box-sizing: border-box;
|
||||
margin-inline-end: calc(16px - 100vw + 100%);
|
||||
margin-inline-end: calc(8px - 100vw + 100%);
|
||||
z-index: 10;
|
||||
.toc-debug {
|
||||
color: ${token.purple6};
|
||||
@ -48,15 +48,11 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
}
|
||||
`,
|
||||
articleWrapper: css`
|
||||
padding: 0 170px 32px 64px;
|
||||
|
||||
&.rtl {
|
||||
padding: 0 64px 144px 170px;
|
||||
}
|
||||
padding-inline: 48px 164px;
|
||||
padding-block: 0 32px;
|
||||
|
||||
@media only screen and (max-width: ${token.screenLG}px) {
|
||||
&,
|
||||
&.rtl {
|
||||
& {
|
||||
padding: 0 ${token.paddingLG * 2}px;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
import React, { useContext, useLayoutEffect, useMemo, useState } from 'react';
|
||||
import { Col, Flex, Space, Typography } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
import { Col, Flex, Space, Typography, Skeleton } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import { FormattedMessage, useRouteMeta } from 'dumi';
|
||||
|
||||
@ -11,6 +10,7 @@ import type { DemoContextProps } from '../DemoContext';
|
||||
import DemoContext from '../DemoContext';
|
||||
import SiteContext from '../SiteContext';
|
||||
import InViewSuspense from './InViewSuspense';
|
||||
import { useStyle } from './DocAnchor';
|
||||
|
||||
const Contributors = React.lazy(() => import('./Contributors'));
|
||||
const ColumnCard = React.lazy(() => import('./ColumnCard'));
|
||||
@ -18,23 +18,12 @@ const DocAnchor = React.lazy(() => import('./DocAnchor'));
|
||||
const DocMeta = React.lazy(() => import('./DocMeta'));
|
||||
const Footer = React.lazy(() => import('../Footer'));
|
||||
const PrevAndNext = React.lazy(() => import('../../common/PrevAndNext'));
|
||||
const ComponentChangelog = React.lazy(() => import('../../common/ComponentChangelog'));
|
||||
const EditButton = React.lazy(() => import('../../common/EditButton'));
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => ({
|
||||
articleWrapper: css`
|
||||
padding: 0 170px 32px 64px;
|
||||
&.rtl {
|
||||
padding: 0 64px 144px 170px;
|
||||
}
|
||||
@media only screen and (max-width: ${token.screenLG}px) {
|
||||
&,
|
||||
&.rtl {
|
||||
padding: 0 ${token.paddingLG * 2}px;
|
||||
}
|
||||
}
|
||||
`,
|
||||
}));
|
||||
const AvatarPlaceholder: React.FC<{ num?: number }> = ({ num = 6 }) =>
|
||||
Array.from({ length: num }).map<React.ReactNode>((_, i) => (
|
||||
<Skeleton.Avatar size="small" active key={i} style={{ marginInlineStart: i === 0 ? 0 : -8 }} />
|
||||
));
|
||||
|
||||
const Content: React.FC<React.PropsWithChildren> = ({ children }) => {
|
||||
const meta = useRouteMeta();
|
||||
@ -85,11 +74,6 @@ const Content: React.FC<React.PropsWithChildren> = ({ children }) => {
|
||||
)}
|
||||
</Space>
|
||||
</Typography.Title>
|
||||
{pathname.startsWith('/components/') && (
|
||||
<InViewSuspense fallback={null}>
|
||||
<ComponentChangelog pathname={pathname} />
|
||||
</InViewSuspense>
|
||||
)}
|
||||
</Flex>
|
||||
) : null}
|
||||
<InViewSuspense fallback={null}>
|
||||
@ -107,19 +91,19 @@ const Content: React.FC<React.PropsWithChildren> = ({ children }) => {
|
||||
version={meta.frontmatter.tag}
|
||||
/>
|
||||
)}
|
||||
<div style={{ minHeight: 'calc(100vh - 64px)', width: 'calc(100% - 10px)' }}>
|
||||
{children}
|
||||
</div>
|
||||
<InViewSuspense>
|
||||
<div style={{ minHeight: 'calc(100vh - 64px)' }}>{children}</div>
|
||||
<InViewSuspense fallback={null}>
|
||||
<ColumnCard
|
||||
zhihuLink={meta.frontmatter.zhihu_url}
|
||||
yuqueLink={meta.frontmatter.yuque_url}
|
||||
juejinLink={meta.frontmatter.juejin_url}
|
||||
/>
|
||||
</InViewSuspense>
|
||||
<InViewSuspense fallback={<div style={{ height: 50, marginTop: 120 }} />}>
|
||||
<Contributors filename={meta.frontmatter.filename} />
|
||||
</InViewSuspense>
|
||||
<div style={{ marginTop: 120 }}>
|
||||
<InViewSuspense fallback={<AvatarPlaceholder />}>
|
||||
<Contributors filename={meta.frontmatter.filename} />
|
||||
</InViewSuspense>
|
||||
</div>
|
||||
</article>
|
||||
<InViewSuspense fallback={null}>
|
||||
<PrevAndNext rtl={isRTL} />
|
||||
|
@ -13,7 +13,7 @@ import {
|
||||
UsergroupAddOutlined,
|
||||
ZhihuOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { TinyColor } from '@ctrl/tinycolor';
|
||||
import { FastColor } from '@ant-design/fast-color';
|
||||
import { createStyles } from 'antd-style';
|
||||
import getAlphaColor from 'antd/es/theme/util/getAlphaColor';
|
||||
import { FormattedMessage, Link } from 'dumi';
|
||||
@ -37,7 +37,7 @@ const locales = {
|
||||
const useStyle = () => {
|
||||
const { isMobile } = useContext(SiteContext);
|
||||
return createStyles(({ token, css }) => {
|
||||
const background = new TinyColor(getAlphaColor('#f0f3fa', '#fff'))
|
||||
const background = new FastColor(getAlphaColor('#f0f3fa', '#fff'))
|
||||
.onBackground(token.colorBgContainer)
|
||||
.toHexString();
|
||||
|
||||
@ -101,6 +101,11 @@ const Footer: React.FC = () => {
|
||||
const col1 = {
|
||||
title: <FormattedMessage id="app.footer.resources" />,
|
||||
items: [
|
||||
{
|
||||
title: 'Ant Design X',
|
||||
url: isZhCN ? 'https://ant-design-x.antgroup.com' : 'https://x.ant.design',
|
||||
openExternal: true,
|
||||
},
|
||||
{
|
||||
title: 'Ant Design Charts',
|
||||
url: isZhCN ? 'https://ant-design-charts.antgroup.com' : 'https://charts.ant.design',
|
||||
@ -112,7 +117,7 @@ const Footer: React.FC = () => {
|
||||
openExternal: true,
|
||||
},
|
||||
{
|
||||
title: 'Ant Design Pro Components',
|
||||
title: 'Pro Components',
|
||||
url: 'https://procomponents.ant.design',
|
||||
openExternal: true,
|
||||
},
|
||||
@ -126,6 +131,11 @@ const Footer: React.FC = () => {
|
||||
url: isZhCN ? 'https://ant-design-mini.antgroup.com/' : 'https://mini.ant.design',
|
||||
openExternal: true,
|
||||
},
|
||||
{
|
||||
title: 'Ant Design Web3',
|
||||
url: isZhCN ? 'https://web3.antdigital.dev' : 'https://web3.ant.design',
|
||||
openExternal: true,
|
||||
},
|
||||
{
|
||||
title: 'Ant Design Landing',
|
||||
description: <FormattedMessage id="app.footer.landing" />,
|
||||
@ -156,12 +166,6 @@ const Footer: React.FC = () => {
|
||||
url: 'https://qiankun.umijs.org',
|
||||
openExternal: true,
|
||||
},
|
||||
{
|
||||
title: 'ahooks',
|
||||
description: <FormattedMessage id="app.footer.hooks" />,
|
||||
url: 'https://github.com/alibaba/hooks',
|
||||
openExternal: true,
|
||||
},
|
||||
{
|
||||
title: 'Ant Motion',
|
||||
description: <FormattedMessage id="app.footer.motion" />,
|
||||
|
@ -93,13 +93,14 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
.dumi-default-search-popover {
|
||||
inset-inline-start: ${token.paddingSM}px;
|
||||
inset-inline-end: unset;
|
||||
z-index: 1;
|
||||
&::before {
|
||||
inset-inline-start: 100px;
|
||||
inset-inline-end: unset;
|
||||
}
|
||||
& > section {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: unset;
|
||||
scrollbar-gutter: stable;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -142,7 +143,7 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
.rc-virtual-list {
|
||||
.rc-virtual-list-holder {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: unset;
|
||||
scrollbar-gutter: stable;
|
||||
}
|
||||
}
|
||||
`,
|
||||
@ -210,7 +211,6 @@ const Header: React.FC = () => {
|
||||
};
|
||||
}, []);
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
const handleVersionChange = useCallback((url: string) => {
|
||||
const currentUrl = window.location.href;
|
||||
const currentPathname = window.location.pathname;
|
||||
@ -357,7 +357,7 @@ const Header: React.FC = () => {
|
||||
<header className={headerClassName}>
|
||||
{isMobile && (
|
||||
<Popover
|
||||
overlayClassName={styles.popoverMenu}
|
||||
classNames={{ root: styles.popoverMenu }}
|
||||
placement="bottomRight"
|
||||
content={menu}
|
||||
trigger="click"
|
||||
|
@ -8,13 +8,14 @@ import useMenu from '../../../hooks/useMenu';
|
||||
import SiteContext from '../SiteContext';
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => {
|
||||
const { antCls, fontFamily, colorSplit } = token;
|
||||
const { antCls, fontFamily, colorSplit, marginXXL, paddingXXS } = token;
|
||||
|
||||
return {
|
||||
asideContainer: css`
|
||||
min-height: 100%;
|
||||
padding-bottom: 48px;
|
||||
padding-bottom: ${marginXXL}px !important;
|
||||
font-family: Avenir, ${fontFamily}, sans-serif;
|
||||
padding: 0 ${paddingXXS}px;
|
||||
|
||||
&${antCls}-menu-inline {
|
||||
${antCls}-menu-submenu-title h4,
|
||||
@ -53,12 +54,7 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
> ${antCls}-menu-item-group
|
||||
> ${antCls}-menu-item-group-list
|
||||
> ${antCls}-menu-item {
|
||||
padding-inline-start: 40px !important;
|
||||
|
||||
${antCls}-row-rtl & {
|
||||
padding-inline-end: 40px !important;
|
||||
padding-inline-start: ${token.padding}px !important;
|
||||
}
|
||||
padding-inline: 36px 12px !important;
|
||||
}
|
||||
|
||||
// Nest Category > Type > Article
|
||||
@ -96,19 +92,15 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
`,
|
||||
mainMenu: css`
|
||||
z-index: 1;
|
||||
position: sticky;
|
||||
top: ${token.headerHeight + token.contentMarginTop}px;
|
||||
width: 100%;
|
||||
max-height: calc(100vh - ${token.headerHeight + token.contentMarginTop}px);
|
||||
overflow: hidden;
|
||||
scrollbar-width: thin;
|
||||
scrollbar-gutter: stable;
|
||||
|
||||
.main-menu-inner {
|
||||
position: sticky;
|
||||
top: ${token.headerHeight + token.contentMarginTop}px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-height: calc(100vh - ${token.headerHeight + token.contentMarginTop}px);
|
||||
overflow: hidden;
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: unset;
|
||||
}
|
||||
|
||||
&:hover .main-menu-inner {
|
||||
&:hover {
|
||||
overflow-y: auto;
|
||||
}
|
||||
`,
|
||||
@ -144,7 +136,7 @@ const Sidebar: React.FC = () => {
|
||||
<MobileMenu key="Mobile-menu">{menuChild}</MobileMenu>
|
||||
) : (
|
||||
<Col xxl={4} xl={5} lg={6} md={6} sm={24} xs={24} className={styles.mainMenu}>
|
||||
<section className="main-menu-inner">{menuChild}</section>
|
||||
{menuChild}
|
||||
</Col>
|
||||
);
|
||||
};
|
||||
|
16
.dumirc.ts
16
.dumirc.ts
@ -1,6 +1,7 @@
|
||||
import path from 'path';
|
||||
import { defineConfig } from 'dumi';
|
||||
import * as fs from 'fs-extra';
|
||||
import os from 'node:os';
|
||||
|
||||
import rehypeAntd from './.dumi/rehypeAntd';
|
||||
import remarkAntd from './.dumi/remarkAntd';
|
||||
@ -8,7 +9,11 @@ import { version } from './package.json';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: ['dumi-plugin-color-chunk'],
|
||||
|
||||
// For <Link prefetch />
|
||||
routePrefetch: {},
|
||||
manifest: {},
|
||||
|
||||
conventionRoutes: {
|
||||
// to avoid generate routes for .dumi/pages/index/components/xx
|
||||
exclude: [/index\/components\//],
|
||||
@ -21,7 +26,7 @@ export default defineConfig({
|
||||
: false,
|
||||
hash: true,
|
||||
mfsu: false,
|
||||
mako: {},
|
||||
mako: ['Darwin', 'Linux'].includes(os.type()) ? {} : false,
|
||||
crossorigin: {},
|
||||
runtimePublicPath: {},
|
||||
outputPath: '_site',
|
||||
@ -57,9 +62,12 @@ export default defineConfig({
|
||||
analytics: {
|
||||
ga_v2: 'UA-72788897-1',
|
||||
},
|
||||
analyze: process.env.NODE_ENV === 'production' ? false : {
|
||||
analyzerPort: 'auto',
|
||||
},
|
||||
analyze:
|
||||
process.env.NODE_ENV === 'production'
|
||||
? false
|
||||
: {
|
||||
analyzerPort: 'auto',
|
||||
},
|
||||
links: [
|
||||
{
|
||||
rel: 'prefetch',
|
||||
|
@ -1,24 +0,0 @@
|
||||
components/**/*.js
|
||||
components/**/*.jsx
|
||||
components/version/token.tsx
|
||||
!components/*/__tests__/**/*.js
|
||||
!components/*/demo/*.md
|
||||
!.*.js
|
||||
~*
|
||||
typings
|
||||
es/**/*
|
||||
lib/**/*
|
||||
locale
|
||||
server
|
||||
.dumi/tmp
|
||||
.dumi/tmp-production
|
||||
!.dumi/
|
||||
node_modules
|
||||
.eslintcache
|
||||
_site
|
||||
dist
|
||||
coverage
|
||||
**/*.d.ts
|
||||
# Scripts
|
||||
scripts/previewEditor/**/*
|
||||
jest-stare
|
231
.eslintrc.js
231
.eslintrc.js
@ -1,231 +0,0 @@
|
||||
module.exports = {
|
||||
extends: [
|
||||
'airbnb',
|
||||
'prettier',
|
||||
'plugin:compat/recommended',
|
||||
'plugin:jest/recommended',
|
||||
'plugin:react/recommended',
|
||||
'plugin:import/typescript',
|
||||
'plugin:markdown/recommended-legacy',
|
||||
],
|
||||
env: {
|
||||
browser: true,
|
||||
node: true,
|
||||
jasmine: true,
|
||||
jest: true,
|
||||
es6: true,
|
||||
},
|
||||
settings: {
|
||||
react: {
|
||||
version: 'detect',
|
||||
},
|
||||
polyfills: ['Promise', 'URL'],
|
||||
'import/resolver': {
|
||||
typescript: {},
|
||||
},
|
||||
},
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: [
|
||||
'react',
|
||||
'@babel',
|
||||
'jest',
|
||||
'@typescript-eslint',
|
||||
'react-hooks',
|
||||
'unicorn',
|
||||
'markdown',
|
||||
'lodash',
|
||||
],
|
||||
// https://github.com/typescript-eslint/typescript-eslint/issues/46#issuecomment-470486034
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.ts', '*.tsx'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-unused-vars': [2, { args: 'none' }],
|
||||
'no-unused-expressions': 'off',
|
||||
'@typescript-eslint/no-unused-expressions': 2,
|
||||
'@typescript-eslint/consistent-type-imports': [2, { disallowTypeAnnotations: false }],
|
||||
'import/consistent-type-specifier-style': 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
// In v2, explicitly apply eslint-plugin-markdown's `markdown`
|
||||
// processor on any Markdown files you want to lint.
|
||||
files: ['components/*/demo/*.md'],
|
||||
processor: 'markdown/markdown',
|
||||
},
|
||||
{
|
||||
// In v2, configuration for fenced code blocks is separate from the
|
||||
// containing Markdown file. Each code block has a virtual filename
|
||||
// appended to the Markdown file's path.
|
||||
files: [
|
||||
'components/*/demo/*.md/*.ts',
|
||||
'components/*/demo/*.md/*.tsx',
|
||||
'components/*/demo/*.md/*.js',
|
||||
'components/*/demo/*.md/*.jsx',
|
||||
],
|
||||
// Configuration for fenced code blocks goes with the override for
|
||||
// the code block's virtual filename, for example:
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
impliedStrict: true,
|
||||
},
|
||||
},
|
||||
globals: {
|
||||
React: true,
|
||||
ReactDOM: true,
|
||||
mountNode: true,
|
||||
},
|
||||
rules: {
|
||||
indent: 0,
|
||||
'@babel/new-cap': 0,
|
||||
'@babel/no-invalid-this': 0,
|
||||
'@babel/no-unused-expressions': 2,
|
||||
'@babel/object-curly-spacing': 0,
|
||||
'@babel/semi': 2,
|
||||
'default-case': 0,
|
||||
'eol-last': 0,
|
||||
'no-console': 0,
|
||||
'no-plusplus': 0,
|
||||
'no-script-url': 0,
|
||||
'prefer-rest-params': 0,
|
||||
'compat/compat': 0,
|
||||
'class-methods-use-this': 0,
|
||||
'react/no-access-state-in-setstate': 0,
|
||||
'react/destructuring-assignment': 0,
|
||||
'react/no-multi-comp': 0,
|
||||
'react/no-array-index-key': 0,
|
||||
'jsx-a11y/href-no-hash': 0,
|
||||
'jsx-a11y/control-has-associated-label': 0,
|
||||
'import/no-extraneous-dependencies': 0,
|
||||
'react/jsx-no-constructed-context-values': 0,
|
||||
'react/no-unstable-nested-components': 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['components/**/demo/*.tsx'],
|
||||
rules: {
|
||||
'import/no-extraneous-dependencies': 0,
|
||||
'no-console': 0,
|
||||
'compat/compat': 0,
|
||||
'react/no-unstable-nested-components': 0,
|
||||
'jsx-a11y/control-has-associated-label': 0,
|
||||
'class-methods-use-this': 0,
|
||||
'react/no-access-state-in-setstate': 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['.dumi/**/*.ts', '.dumi/**/*.tsx', '.dumi/**/*.js', '.dumi/**/*.jsx'],
|
||||
rules: {
|
||||
'import/no-extraneous-dependencies': 0,
|
||||
'no-console': 0,
|
||||
'compat/compat': 0,
|
||||
'react/no-unstable-nested-components': 0,
|
||||
'jsx-a11y/control-has-associated-label': 0,
|
||||
'class-methods-use-this': 0,
|
||||
'react/no-access-state-in-setstate': 0,
|
||||
'react/no-unknown-property': ['error', { ignore: ['css'] }],
|
||||
'react/no-array-index-key': 0,
|
||||
'react/button-has-type': 0,
|
||||
'react/no-danger': 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.json'],
|
||||
rules: {
|
||||
'no-unused-expressions': 0,
|
||||
'comma-dangle': 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.test.ts', '**/*.test.tsx', '**/*.spec.ts', '**/*.spec.tsx'],
|
||||
rules: {
|
||||
'compat/compat': 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
rules: {
|
||||
'react/jsx-one-expression-per-line': 0,
|
||||
'react/prop-types': 0,
|
||||
'react/forbid-prop-types': 0,
|
||||
'react/jsx-indent': 0,
|
||||
'react/jsx-wrap-multilines': ['error', { declaration: false, assignment: false }],
|
||||
'react/jsx-filename-extension': 0,
|
||||
'react/state-in-constructor': 0,
|
||||
'react/jsx-props-no-spreading': 0,
|
||||
'react/destructuring-assignment': 0, // TODO: remove later
|
||||
'react/require-default-props': 0,
|
||||
'react/sort-comp': 0,
|
||||
'react/display-name': 0,
|
||||
'react/static-property-placement': 0,
|
||||
'react/jsx-no-bind': 0, // Should not check test file
|
||||
'react/no-find-dom-node': 0,
|
||||
'react/no-unused-prop-types': 0,
|
||||
'react/default-props-match-prop-types': 0,
|
||||
'react-hooks/rules-of-hooks': 2, // Checks rules of Hooks
|
||||
'react/function-component-definition': 0,
|
||||
'react/no-unused-class-component-methods': 0,
|
||||
'import/extensions': 0,
|
||||
'import/no-cycle': 2,
|
||||
'lodash/import-scope': 2,
|
||||
'import/no-extraneous-dependencies': [
|
||||
'error',
|
||||
{
|
||||
devDependencies: [
|
||||
'site/**',
|
||||
'tests/**',
|
||||
'scripts/**',
|
||||
'scripts/*.ts',
|
||||
'**/*.test.js',
|
||||
'**/__tests__/*',
|
||||
'*.config.js',
|
||||
'**/*.md',
|
||||
],
|
||||
},
|
||||
],
|
||||
'jsx-a11y/no-static-element-interactions': 0,
|
||||
'jsx-a11y/anchor-has-content': 0,
|
||||
'jsx-a11y/click-events-have-key-events': 0,
|
||||
'jsx-a11y/anchor-is-valid': 0,
|
||||
'jsx-a11y/no-noninteractive-element-interactions': 0,
|
||||
// label-has-for has been deprecated
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/label-has-for.md
|
||||
'jsx-a11y/label-has-for': 0,
|
||||
|
||||
'comma-dangle': ['error', 'always-multiline'],
|
||||
'consistent-return': 0, // TODO: remove later
|
||||
'no-param-reassign': 0, // TODO: remove later
|
||||
'no-underscore-dangle': 0,
|
||||
// for (let i = 0; i < len; i++)
|
||||
'no-plusplus': 0,
|
||||
// https://eslint.org/docs/rules/no-continue
|
||||
// labeledLoop is conflicted with `eslint . --fix`
|
||||
'no-continue': 0,
|
||||
// ban this for Number.isNaN needs polyfill
|
||||
'no-restricted-globals': 0,
|
||||
'max-classes-per-file': 0,
|
||||
|
||||
'jest/no-test-callback': 0,
|
||||
'jest/expect-expect': 0,
|
||||
'jest/no-done-callback': 0,
|
||||
'jest/valid-title': 0,
|
||||
'jest/no-conditional-expect': 0,
|
||||
'jest/no-standalone-expect': 0,
|
||||
|
||||
'unicorn/better-regex': 2,
|
||||
'unicorn/prefer-string-trim-start-end': 2,
|
||||
'unicorn/expiring-todo-comments': 2,
|
||||
'unicorn/no-abusive-eslint-disable': 0,
|
||||
|
||||
// https://github.com/typescript-eslint/typescript-eslint/issues/2540#issuecomment-692866111
|
||||
'no-use-before-define': 0,
|
||||
'@typescript-eslint/no-use-before-define': 2,
|
||||
'no-shadow': 0,
|
||||
'@typescript-eslint/no-shadow': [2, { ignoreTypeValueShadow: true }],
|
||||
// https://github.com/typescript-eslint/typescript-eslint/issues/2528#issuecomment-689369395
|
||||
'no-undef': 0,
|
||||
'import/order': 0,
|
||||
},
|
||||
globals: {
|
||||
gtag: true,
|
||||
},
|
||||
};
|
34
.github/dependabot.yml
vendored
34
.github/dependabot.yml
vendored
@ -5,35 +5,35 @@
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
- package-ecosystem: npm
|
||||
directory: /
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: daily
|
||||
groups:
|
||||
rc-component-patch:
|
||||
dependency-type: "production"
|
||||
dependency-type: production
|
||||
patterns:
|
||||
- "rc-*"
|
||||
- "@rc-component*"
|
||||
update-types: ["patch"]
|
||||
update-types: [patch]
|
||||
dependencies:
|
||||
dependency-type: "production"
|
||||
dependency-type: production
|
||||
exclude-patterns:
|
||||
- "rc-*"
|
||||
- "@rc-component*"
|
||||
update-types: ["major", "minor"]
|
||||
update-types: [major, minor]
|
||||
dev-dependencies:
|
||||
dependency-type: "development"
|
||||
update-types: ["major"]
|
||||
dependency-type: development
|
||||
update-types: [major]
|
||||
ignore:
|
||||
- dependency-name: "@ant-design/cssinjs"
|
||||
- dependency-name: "dayjs"
|
||||
versions: ["1.x"]
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
- dependency-name: dayjs
|
||||
versions: [1.x]
|
||||
- package-ecosystem: github-actions
|
||||
directory: /
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: daily
|
||||
labels:
|
||||
- "github-actions"
|
||||
- "dependencies"
|
||||
- "skip-verify-files"
|
||||
- github-actions
|
||||
- dependencies
|
||||
- skip-verify-files
|
||||
|
4
.github/workflows/issue-check-inactive.yml
vendored
4
.github/workflows/issue-check-inactive.yml
vendored
@ -17,6 +17,6 @@ jobs:
|
||||
- name: check-inactive
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'check-inactive'
|
||||
inactive-label: 'Inactive'
|
||||
actions: check-inactive
|
||||
inactive-label: Inactive
|
||||
inactive-day: 30
|
||||
|
8
.github/workflows/issue-close-require.yml
vendored
8
.github/workflows/issue-close-require.yml
vendored
@ -17,15 +17,15 @@ jobs:
|
||||
- name: need reproduce
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'close-issues'
|
||||
labels: '🤔 Need Reproduce'
|
||||
actions: close-issues
|
||||
labels: 🤔 Need Reproduce
|
||||
inactive-day: 3
|
||||
|
||||
- name: needs more info
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'close-issues'
|
||||
labels: 'needs-more-info'
|
||||
actions: close-issues
|
||||
labels: needs-more-info
|
||||
inactive-day: 3
|
||||
body: |
|
||||
Since the issue was labeled with `needs-more-info`, but no response in 3 days. This issue will be closed. If you have any questions, you can comment and reply.
|
||||
|
86
.github/workflows/issue-inactivity-reminder.yml
vendored
Normal file
86
.github/workflows/issue-inactivity-reminder.yml
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
name: Issue Inactivity Reminder
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *" # Run at 00:00 every day
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
reminder_job:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Send reminders for inactive issues
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const daysBeforeReminder = 14;
|
||||
let page = 1;
|
||||
const perPage = 100;
|
||||
|
||||
const reminderSignature = "This issue has been inactive for more than 14 days";
|
||||
|
||||
while (true) {
|
||||
const { data: issues } = await github.rest.issues.listForRepo({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
state: 'open',
|
||||
assignee: '*',
|
||||
per_page: perPage,
|
||||
page: page,
|
||||
});
|
||||
|
||||
if (issues.length === 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
const now = new Date();
|
||||
|
||||
for (const issue of issues) {
|
||||
if (issue.pull_request) continue;
|
||||
|
||||
const updatedAt = new Date(issue.updated_at);
|
||||
const daysInactive = (now - updatedAt) / (1000 * 60 * 60 * 24);
|
||||
|
||||
const { data: timeline } = await github.rest.issues.listEventsForTimeline({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
});
|
||||
|
||||
const hasLinkedPR = timeline.some(event =>
|
||||
event.event === 'connected' || // PR connected via keywords
|
||||
event.event === 'referenced' && event.commit_id // Connected via commit
|
||||
);
|
||||
|
||||
if (daysInactive >= daysBeforeReminder && !hasLinkedPR) {
|
||||
// get issue comments
|
||||
const { data: comments } = await github.rest.issues.listComments({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
});
|
||||
|
||||
// check if reminder has been sent
|
||||
const hasReminder = comments.some(comment =>
|
||||
comment.body.includes(reminderSignature)
|
||||
);
|
||||
|
||||
if (!hasReminder) {
|
||||
const assigneesMentions = issue.assignees
|
||||
.map(user => `@${user.login}`)
|
||||
.join(' ');
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: `${assigneesMentions} 这个 issue 已经超过 14 天没有更新或关联 PR。如果您仍在处理这个 issue,请更新进度;如果您无法继续处理,请联系维护者重新分配。\n\nThis issue has been inactive for more than 14 days without any updates or linked PR. If you are still working on this issue, please provide a progress update. If you are unable to continue, please contact the maintainers for reassignment.`,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
page += 1;
|
||||
}
|
16
.github/workflows/issue-labeled.yml
vendored
16
.github/workflows/issue-labeled.yml
vendored
@ -20,7 +20,7 @@ jobs:
|
||||
if: github.event.label.name == 'help wanted'
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'create-comment'
|
||||
actions: create-comment
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
body: |
|
||||
@ -34,13 +34,13 @@ jobs:
|
||||
if: github.event.label.name == '🤔 Need Reproduce'
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'create-comment'
|
||||
actions: create-comment
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
body: |
|
||||
Hello @${{ github.event.issue.user.login }}. Please provide a online reproduction by forking [this one](https://u.ant.design/repro) or provide a minimal GitHub repository like [create-react-app-antd](https://github.com/ant-design/create-react-app-antd). Issues labeled by `Need Reproduce` will be closed if no activities in 3 days.
|
||||
Hello @${{ github.event.issue.user.login }}. Please provide a online reproduction by forking [this one](https://u.ant.design/reproduce) or provide a minimal GitHub repository like [create-react-app-antd](https://github.com/ant-design/create-react-app-antd). Issues labeled by `Need Reproduce` will be closed if no activities in 3 days.
|
||||
|
||||
你好 @${{ github.event.issue.user.login }},我们需要你提供一个在线的重现实例以便于我们帮你排查问题。你可以通过 fork 这个[在线重现案例](https://u.ant.design/repro) ,或者提供一个最小化的 GitHub 仓库(类似 [create-react-app-antd](https://github.com/ant-design/create-react-app-antd))。3 天内未跟进此 issue 将会被自动关闭。
|
||||
你好 @${{ github.event.issue.user.login }},我们需要你提供一个在线的重现实例以便于我们帮你排查问题。你可以通过 fork 这个[在线重现案例](https://u.ant.design/reproduce) ,或者提供一个最小化的 GitHub 仓库(类似 [create-react-app-antd](https://github.com/ant-design/create-react-app-antd))。3 天内未跟进此 issue 将会被自动关闭。
|
||||
|
||||
> [什么是最小化重现,为什么这是必需的?](https://github.com/ant-design/ant-design/wiki/%E4%BB%80%E4%B9%88%E6%98%AF%E6%9C%80%E5%B0%8F%E5%8C%96%E9%87%8D%E7%8E%B0%EF%BC%8C%E4%B8%BA%E4%BB%80%E4%B9%88%E8%BF%99%E6%98%AF%E5%BF%85%E9%9C%80%E7%9A%84%EF%BC%9F)
|
||||
|
||||
@ -81,3 +81,11 @@ jobs:
|
||||
Hello @${{ github.event.issue.user.login }}, your issue has been closed because it does not conform to our issue requirements. Please use the [Issue Helper](http://new-issue.ant.design) to create an issue, thank you!
|
||||
|
||||
你好 @${{ github.event.issue.user.login }},为了能够进行高效沟通,我们对 issue 有一定的格式要求,你的 issue 因为不符合要求而被自动关闭。你可以通过 [issue 助手](http://new-issue.ant.design) 来创建 issue 以方便我们定位错误。谢谢配合!
|
||||
|
||||
- name: remove unconfirmed label
|
||||
if: github.event.label.name != 'unconfirmed'
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: remove-labels
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
labels: unconfirmed
|
||||
|
12
.github/workflows/issue-open-check.yml
vendored
12
.github/workflows/issue-open-check.yml
vendored
@ -18,15 +18,15 @@ jobs:
|
||||
- uses: actions-cool/check-user-permission@v2
|
||||
id: checkUser
|
||||
with:
|
||||
require: 'write'
|
||||
require: write
|
||||
check-bot: true
|
||||
|
||||
- name: add unconfirmed label
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'add-labels'
|
||||
actions: add-labels
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
labels: 'unconfirmed'
|
||||
labels: unconfirmed
|
||||
|
||||
- name: check invalid
|
||||
if: (contains(github.event.issue.body, 'ant-design-issue-helper') == false) && (steps.checkUser.outputs.require-result == 'false')
|
||||
@ -34,7 +34,7 @@ jobs:
|
||||
with:
|
||||
actions: 'create-comment,add-labels,close-issue'
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
labels: 'Invalid'
|
||||
labels: Invalid
|
||||
body: |
|
||||
Hello @${{ github.event.issue.user.login }}, your issue has been closed because it does not conform to our issue requirements. Please use the [Issue Helper](http://new-issue.ant.design) to create an issue, thank you!
|
||||
|
||||
@ -44,7 +44,7 @@ jobs:
|
||||
uses: actions-cool/issues-helper@v3
|
||||
id: checkid
|
||||
with:
|
||||
actions: 'check-issue'
|
||||
actions: check-issue
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
# 格式如:'x1,x2' or 'x1,x2/y1,y2' 最多支持 2 个数组
|
||||
title-includes: '官网,网站,国内,镜像,mobile ant design,mobile.ant.design,ant design,ant design pro,pro.ant.design/挂了,挂掉了,无法访问,不能访问,访问速度,访问慢,访问不了,加载太慢,加载慢,加载很慢,出问题,打不开,登不上,can not open,cannot open,can not be reached'
|
||||
@ -80,7 +80,7 @@ jobs:
|
||||
if: contains(github.event.issue.body, 'ant-design-issue-helper') == true && contains(github.event.issue.title, 'IE9') == true || contains(github.event.issue.title, 'IE 9') == true || contains(github.event.issue.title, 'IE10') == true || contains(github.event.issue.title, 'IE 10') == true || contains(github.event.issue.title, 'IE11') == true || contains(github.event.issue.title, 'IE 11') == true || contains(github.event.issue.title, 'Internet Explorer') == true || contains(github.event.issue.body, 'IE9') == true || contains(github.event.issue.body, 'IE 9') == true || contains(github.event.issue.body, 'IE10') == true || contains(github.event.issue.body, 'IE 10') == true || contains(github.event.issue.body, 'IE11') == true || contains(github.event.issue.body, 'IE 11') == true || contains(github.event.issue.body, 'Internet Explorer') == true
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'add-labels'
|
||||
actions: add-labels
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
labels: 'IE | Firefox | Safari,Internet Explorer'
|
||||
|
||||
|
2
.github/workflows/issue-remove-inactive.yml
vendored
2
.github/workflows/issue-remove-inactive.yml
vendored
@ -20,6 +20,6 @@ jobs:
|
||||
if: github.event.issue.state == 'open' && github.actor == github.event.issue.user.login
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'remove-labels'
|
||||
actions: remove-labels
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
labels: 'Inactive, needs-more-info'
|
||||
|
97
.github/workflows/issue-schedule.yml
vendored
Normal file
97
.github/workflows/issue-schedule.yml
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
name: Issue Schedule
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '30 1 * * *'
|
||||
|
||||
jobs:
|
||||
send-message:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Send Unconfirmed Issues to DingTalk
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
DINGDING_BOT_TOKEN: ${{ secrets.DINGDING_BOT_COLLABORATOR_TOKEN }}
|
||||
actionTitle: 近 7 天未确认的 issue
|
||||
with:
|
||||
script: |
|
||||
const dingdingTokenKey = process.env.DINGDING_BOT_TOKEN;
|
||||
|
||||
const fromNow = (data) => {
|
||||
const relativeTimeFormat = new Intl.RelativeTimeFormat('zh-CN');
|
||||
const date = new Date(data);
|
||||
const now = new Date();
|
||||
|
||||
const diffInSeconds = Math.floor((now - date) / 1000);
|
||||
const diffInMinutes = Math.floor(diffInSeconds / 60);
|
||||
const diffInHours = Math.floor(diffInMinutes / 60);
|
||||
const diffInDays = Math.floor(diffInHours / 24);
|
||||
|
||||
if (diffInDays > 0) {
|
||||
return relativeTimeFormat.format(-diffInDays, 'day');
|
||||
} else if (diffInHours > 0) {
|
||||
return relativeTimeFormat.format(-diffInHours, 'hour');
|
||||
} else if (diffInMinutes > 0) {
|
||||
return relativeTimeFormat.format(-diffInMinutes, 'minute');
|
||||
} else {
|
||||
return relativeTimeFormat.format(-diffInSeconds, 'second');
|
||||
}
|
||||
};
|
||||
|
||||
const response = await fetch('https://api.github.com/search/issues?q=repo:ant-design/ant-design&is:open+is:issue+label:unconfirmed&per_page=100');
|
||||
const data = await response.json();
|
||||
const issueList = [];
|
||||
for (const item of data.items) {
|
||||
const { created_at, html_url, pull_request, state, title, labels } = item;
|
||||
const createdAt = new Date(created_at);
|
||||
const now = new Date();
|
||||
const diffTime = Math.abs(now - createdAt);
|
||||
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
||||
|
||||
const isUnconfirmed = labels.some(label => label.name === 'unconfirmed');
|
||||
|
||||
if (!isUnconfirmed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (diffDays > 7) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!pull_request && !html_url.includes('pull') && state === 'open') {
|
||||
issueList.push({
|
||||
html_url,
|
||||
created_at,
|
||||
title
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const actionTitle = process.env.actionTitle + `(${issueList.length})`;
|
||||
|
||||
const markdownList = `## ${actionTitle}\n\n`
|
||||
+ issueList.map(issue => `- [${issue.title}](${issue.html_url}) ${fromNow(issue.created_at)}`).join('\n')
|
||||
+ `\n\n > 🫵🏻 快去帮忙处理吧,社区需要你的帮助!`;
|
||||
|
||||
console.log(markdownList);
|
||||
|
||||
try {
|
||||
await fetch(
|
||||
`https://oapi.dingtalk.com/robot/send?access_token=${dingdingTokenKey}`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
msgtype: 'markdown',
|
||||
markdown: {
|
||||
title: actionTitle,
|
||||
text: markdownList,
|
||||
},
|
||||
}),
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.log('发送失败, error:', error);
|
||||
}
|
4
.github/workflows/mock-project-build.yml
vendored
4
.github/workflows/mock-project-build.yml
vendored
@ -57,10 +57,10 @@ jobs:
|
||||
- uses: actions-cool/ci-notice@v1
|
||||
if: ${{ failure() }}
|
||||
with:
|
||||
notice-types: 'dingding'
|
||||
notice-types: dingding
|
||||
# Exit directly with non-zero to trigger the failure logic of ci-notice.
|
||||
ci: |
|
||||
echo "❌ CI Mock Project Build Failed"
|
||||
exit 1
|
||||
dingding-token: ${{ secrets.DINGDING_BOT_COLLABORATOR_TOKEN }}
|
||||
notice-title: 'CI Mock Project Build Failed'
|
||||
notice-title: CI Mock Project Build Failed
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Used to merge master/feature branches with each other
|
||||
name: PR Check CI
|
||||
name: PR Auto Merge Bot
|
||||
|
||||
on:
|
||||
schedule:
|
||||
@ -20,13 +20,13 @@ jobs:
|
||||
steps:
|
||||
- uses: actions-cool/check-pr-ci@v1
|
||||
with:
|
||||
filter-label: 'BranchAutoMerge'
|
||||
filter-creator-authority: 'write'
|
||||
filter-label: BranchAutoMerge
|
||||
filter-creator-authority: write
|
||||
filter-head-ref: 'master, feature, next, master-merge-feature, feature-merge-master, next-merge-master, next-merge-feature'
|
||||
filter-support-fork: false
|
||||
skip-run-names: 'deploy preview, pr-check-ci, upstream workflow summary, suggest-related-links, download visual-regression report'
|
||||
conflict-review-body: '😅 This branch has conflicts that must be resolved!'
|
||||
conflict-review-body: 😅 This branch has conflicts that must be resolved!
|
||||
success-review: true
|
||||
success-merge: true
|
||||
merge-method: 'merge'
|
||||
merge-method: merge
|
||||
merge-title: 'chore: auto merge branches (#${number})'
|
4
.github/workflows/pr-check-merge.yml
vendored
4
.github/workflows/pr-check-merge.yml
vendored
@ -13,11 +13,11 @@ jobs:
|
||||
issues: write # for actions-cool/issues-helper to update issues
|
||||
pull-requests: write # for actions-cool/issues-helper to update PRs
|
||||
runs-on: ubuntu-latest
|
||||
if: (github.event.pull_request.head.ref == 'feature' || github.event.pull_request.head.ref == 'master') && github.event.pull_request.head.user.login == 'ant-design'
|
||||
if: (github.event.pull_request.head.ref == 'next' || github.event.pull_request.head.ref == 'feature' || github.event.pull_request.head.ref == 'master') && github.event.pull_request.head.user.login == 'ant-design'
|
||||
steps:
|
||||
- uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'create-comment'
|
||||
actions: create-comment
|
||||
issue-number: ${{ github.event.number }}
|
||||
body: |
|
||||
Hi @${{ github.event.pull_request.user.login }}。
|
||||
|
4
.github/workflows/pr-contributor-welcome.yml
vendored
4
.github/workflows/pr-contributor-welcome.yml
vendored
@ -36,7 +36,7 @@ jobs:
|
||||
|
||||
🎉 感谢您的贡献!如果您还没有加入钉钉社区群,请扫描下方二维码加入我们(加群时请提供此 PR 链接)。
|
||||
|
||||
<img src="https://github.com/ant-design/ant-design/assets/5378891/e24c6080-bf38-4523-b1cd-f6c43ad7375f" height="200" />
|
||||
<img src="https://github.com/user-attachments/assets/cfee105e-8731-481f-a336-92b79a84d35a" height="200" />
|
||||
|
||||
<!-- WELCOME_CONTRIBUTION -->
|
||||
body-include: '<!-- WELCOME_CONTRIBUTION -->'
|
||||
body-include: <!-- WELCOME_CONTRIBUTION -->
|
||||
|
4
.github/workflows/pr-open-check.yml
vendored
4
.github/workflows/pr-open-check.yml
vendored
@ -16,8 +16,8 @@ jobs:
|
||||
steps:
|
||||
- uses: actions-cool/pr-welcome@v1
|
||||
with:
|
||||
refuse-issue-label: '🎱 Collaborate PR only'
|
||||
need-creator-authority: 'write'
|
||||
refuse-issue-label: 🎱 Collaborate PR only
|
||||
need-creator-authority: write
|
||||
comment: |
|
||||
Hi @${{ github.event.pull_request.user.login }}. The issue mentioned in this PR needs to be confirmed with the designer or core team. Thank you for your contribution! 😊
|
||||
|
||||
|
2
.github/workflows/pr-open-notify.yml
vendored
2
.github/workflows/pr-open-notify.yml
vendored
@ -1,4 +1,4 @@
|
||||
name: PR Open Check
|
||||
name: PR Open Notify
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
|
2
.github/workflows/preview-build.yml
vendored
2
.github/workflows/preview-build.yml
vendored
@ -26,7 +26,7 @@ jobs:
|
||||
id: site
|
||||
run: bun run site
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
NODE_OPTIONS: --max_old_space_size=4096
|
||||
- name: run e2e test
|
||||
run: bun run test:site
|
||||
- name: upload site artifact
|
||||
|
10
.github/workflows/preview-deploy.yml
vendored
10
.github/workflows/preview-deploy.yml
vendored
@ -4,7 +4,7 @@ name: Preview Deploy
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Preview Build"]
|
||||
workflows: [Preview Build]
|
||||
types:
|
||||
- completed
|
||||
|
||||
@ -61,7 +61,7 @@ jobs:
|
||||
steps:
|
||||
# We need get PR id first
|
||||
- name: download pr artifact
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
uses: dawidd6/action-download-artifact@v7
|
||||
with:
|
||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
@ -81,7 +81,7 @@ jobs:
|
||||
# Download site artifact
|
||||
- name: download site artifact
|
||||
if: ${{ fromJSON(needs.upstream-workflow-summary.outputs.build-success) }}
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
uses: dawidd6/action-download-artifact@v7
|
||||
with:
|
||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
@ -104,7 +104,7 @@ jobs:
|
||||
body: |
|
||||
[<img width="300" alt="Preview is ready" src="https://user-images.githubusercontent.com/5378891/72400743-23dbb200-3785-11ea-9d13-1a2d92743846.png">](https://preview-${{ steps.pr.outputs.id }}-ant-design.surge.sh)
|
||||
<!-- AUTO_PREVIEW_HOOK -->
|
||||
body-include: '<!-- AUTO_PREVIEW_HOOK -->'
|
||||
body-include: <!-- AUTO_PREVIEW_HOOK -->
|
||||
number: ${{ steps.pr.outputs.id }}
|
||||
|
||||
- name: failed comment
|
||||
@ -115,7 +115,7 @@ jobs:
|
||||
body: |
|
||||
[<img width="300" alt="Preview failed" src="https://user-images.githubusercontent.com/5378891/75333447-1e63a280-58c1-11ea-975d-235367fd1522.png">](https://preview-${{ steps.pr.outputs.id }}-ant-design.surge.sh)
|
||||
<!-- AUTO_PREVIEW_HOOK -->
|
||||
body-include: '<!-- AUTO_PREVIEW_HOOK -->'
|
||||
body-include: <!-- AUTO_PREVIEW_HOOK -->
|
||||
number: ${{ steps.pr.outputs.id }}
|
||||
|
||||
- name: Check surge deploy result and exit if failed
|
||||
|
2
.github/workflows/preview-start.yml
vendored
2
.github/workflows/preview-start.yml
vendored
@ -28,4 +28,4 @@ jobs:
|
||||
body: |
|
||||
[<img width="500" alt="Prepare preview" src="https://user-images.githubusercontent.com/5378891/72351368-2c979e00-371b-11ea-9652-eb4e825d745e.gif">](https://preview-${{ github.event.number }}-ant-design.surge.sh)
|
||||
<!-- AUTO_PREVIEW_HOOK -->
|
||||
body-include: '<!-- AUTO_PREVIEW_HOOK -->'
|
||||
body-include: <!-- AUTO_PREVIEW_HOOK -->
|
||||
|
10
.github/workflows/release-dingtalk.yml
vendored
10
.github/workflows/release-dingtalk.yml
vendored
@ -23,13 +23,13 @@ jobs:
|
||||
- name: Send to Ant Design DingGroup
|
||||
uses: actions-cool/release-helper@v2
|
||||
with:
|
||||
trigger: 'tag'
|
||||
trigger: tag
|
||||
changelogs: 'CHANGELOG.en-US.md, CHANGELOG.zh-CN.md'
|
||||
branch: 'master, 4.x-stable'
|
||||
tag: '5*, 4*'
|
||||
latest: '5*'
|
||||
dingding-token: ${{ secrets.DINGDING_BOT_TOKEN }} ${{ secrets.DINGDING_BOT_COLLABORATOR_TOKEN }} ${{ secrets.DINGDING_BOT_MAINTAINER_TOKEN }}
|
||||
dingding-msg: 'CHANGELOG.zh-CN.md'
|
||||
dingding-msg: CHANGELOG.zh-CN.md
|
||||
msg-title: '# Ant Design {{v}} 发布日志'
|
||||
msg-poster: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*zx7LTI_ECSAAAAAAAAAAAABkARQnAQ'
|
||||
msg-footer: '💬 前往 [**Ant Design Releases**]({{url}}) 查看更新日志'
|
||||
@ -39,17 +39,17 @@ jobs:
|
||||
- name: Send to Bigfish DingGroup
|
||||
uses: actions-cool/release-helper@v2
|
||||
with:
|
||||
trigger: 'tag'
|
||||
trigger: tag
|
||||
changelogs: 'CHANGELOG.en-US.md, CHANGELOG.zh-CN.md'
|
||||
branch: 'master, 4.x-stable'
|
||||
tag: '5*, 4*'
|
||||
latest: '5*'
|
||||
dingding-token: ${{ secrets.DINGDING_BOT_BIGFISH_TOKEN }} ${{ secrets.DINGDING_BOT_BIGFISH_2_TOKEN }} ${{ secrets.DINGDING_BOT_YUNFENGDIE_TOKEN }}
|
||||
dingding-msg: 'CHANGELOG.zh-CN.md'
|
||||
dingding-msg: CHANGELOG.zh-CN.md
|
||||
dingding-delay-minute: 10
|
||||
release: false
|
||||
conch-tag: 'conch-v5, conch'
|
||||
antd-conch-msg: '🐟 当前 Bigfish 内嵌 antd 版本:'
|
||||
antd-conch-msg: 🐟 当前 Bigfish 内嵌 antd 版本:
|
||||
msg-title: '# Ant Design {{v}} 发布日志'
|
||||
msg-poster: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*zx7LTI_ECSAAAAAAAAAAAABkARQnAQ'
|
||||
msg-footer: '💬 前往 [**Ant Design Releases**]({{url}}) 查看更新日志'
|
||||
|
75
.github/workflows/site-deploy.yml
vendored
75
.github/workflows/site-deploy.yml
vendored
@ -11,9 +11,14 @@ permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
build-site:
|
||||
runs-on: ubuntu-latest
|
||||
if: (startsWith(github.ref, 'refs/tags/') && (contains(github.ref_name, '-') == false)) || github.event_name == 'workflow_dispatch'
|
||||
|
||||
# https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#example-defining-outputs-for-a-job
|
||||
outputs:
|
||||
formatted_version: ${{ steps.shared-formatted_version.outputs.VERSION }}
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
@ -25,23 +30,50 @@ jobs:
|
||||
- name: build site
|
||||
run: bun run predeploy
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
NODE_OPTIONS: --max_old_space_size=4096
|
||||
|
||||
- name: build dist and bundle analyzer report
|
||||
run: bun run dist
|
||||
env:
|
||||
ANALYZER: 1
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
NODE_OPTIONS: --max_old_space_size=4096
|
||||
|
||||
- name: Get version
|
||||
id: publish-version
|
||||
- name: move report.html to _site
|
||||
run: |
|
||||
if [ -f report.html ]; then
|
||||
mv report.html _site && echo "report.html moved to _site"
|
||||
fi
|
||||
|
||||
- name: upload site artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: real-site
|
||||
path: _site/
|
||||
retention-days: 1 # Not need to keep for too long
|
||||
|
||||
- name: Format version
|
||||
if: ${{ always() }}
|
||||
id: shared-formatted_version
|
||||
run: echo "VERSION=$(echo ${{ github.ref_name }} | sed 's/\./-/g')" >> $GITHUB_OUTPUT
|
||||
|
||||
deploy-to-pages:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-site
|
||||
steps:
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
|
||||
- name: download site artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: real-site
|
||||
path: _site
|
||||
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: peaceiris/actions-gh-pages@v4
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./_site
|
||||
exclude_files: ./_site/report.html # 👈 这个功能是 beta, 但即便不排除,也不 care
|
||||
force_orphan: true
|
||||
|
||||
# Since force_orphan will not trigger Sync to Gitee, we need to force run it here
|
||||
@ -55,14 +87,37 @@ jobs:
|
||||
|
||||
- name: Deploy to Surge (with TAG)
|
||||
run: |
|
||||
export DEPLOY_DOMAIN=ant-design-${{ steps.publish-version.outputs.VERSION }}.surge.sh
|
||||
cp report.html ./_site
|
||||
npx surge --project ./_site --domain $DEPLOY_DOMAIN --token ${{ secrets.SURGE_TOKEN }}
|
||||
export DEPLOY_DOMAIN=ant-design-${{ needs.build-site.outputs.formatted_version }}.surge.sh
|
||||
bunx surge --project ./_site --domain $DEPLOY_DOMAIN --token ${{ secrets.SURGE_TOKEN }}
|
||||
|
||||
- name: Create Commit Comment
|
||||
uses: peter-evans/commit-comment@v3
|
||||
with:
|
||||
body: |
|
||||
- Documentation site for this release: https://ant-design-${{ steps.publish-version.outputs.VERSION }}.surge.sh
|
||||
- Webpack bundle analyzer report page: https://ant-design-${{ steps.publish-version.outputs.VERSION }}.surge.sh/report.html
|
||||
- Documentation site for this release: https://ant-design-${{ needs.build-site.outputs.formatted_version }}.surge.sh
|
||||
- Webpack bundle analyzer report page: https://ant-design-${{ needs.build-site.outputs.formatted_version }}.surge.sh/report.html
|
||||
|
||||
# https://github.com/ant-design/ant-design/pull/49213/files#r1625446496
|
||||
upload-to-release:
|
||||
runs-on: ubuntu-latest
|
||||
# 仅在 tag 的时候工作,因为我们要将内容发布到以 tag 为版本号的 release 里
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
needs: build-site
|
||||
steps:
|
||||
- name: download site artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: real-site
|
||||
path: _site
|
||||
|
||||
- name: Tarball site
|
||||
run: |
|
||||
cd ./_site
|
||||
tar -czf ../website.tar.gz --transform 's|^|antd-${{ needs.build-site.outputs.formatted_version }}-website/|' .
|
||||
cd ..
|
||||
|
||||
- name: Upload to Release
|
||||
uses: softprops/action-gh-release@01570a1f39cb168c169c802c3bceb9e93fb10974 # v2.1.0
|
||||
with:
|
||||
fail_on_unmatched_files: true
|
||||
files: website.tar.gz
|
||||
|
2
.github/workflows/size-limit.yml
vendored
2
.github/workflows/size-limit.yml
vendored
@ -25,6 +25,6 @@ jobs:
|
||||
package_manager: bun
|
||||
build_script: dist
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
NODE_OPTIONS: --max_old_space_size=4096
|
||||
PRODUCTION_ONLY: 1
|
||||
CI_JOB_NUMBER: 1
|
||||
|
233
.github/workflows/test-v6.yml
vendored
Normal file
233
.github/workflows/test-v6.yml
vendored
Normal file
@ -0,0 +1,233 @@
|
||||
# Origin Source
|
||||
# https://github.com/ant-design/ant-design/blob/79f566b7f8abb1012ef55b0d2793bfdf5595b85d/.github/workflows/test.yml
|
||||
name: ✅ test v6
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [next]
|
||||
pull_request:
|
||||
branches: [next]
|
||||
|
||||
# Cancel prev CI if new commit come
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
- run: bun install
|
||||
- run: bun run lint
|
||||
|
||||
################################ Test ################################
|
||||
test-react-legacy:
|
||||
name: test-react-legacy
|
||||
strategy:
|
||||
matrix:
|
||||
react: ['18']
|
||||
shard: [1/2, 2/2]
|
||||
env:
|
||||
REACT: ${{ matrix.react }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
- run: bun install
|
||||
- name: install react 18
|
||||
if: ${{ matrix.react == '18' }}
|
||||
run: bun run bun-install-react-18
|
||||
# dom test
|
||||
- name: dom test
|
||||
run: bun run test -- --maxWorkers=2 --shard=${{matrix.shard}}
|
||||
|
||||
test-node:
|
||||
name: test-node
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
- run: bun install
|
||||
- run: bun run test:node
|
||||
|
||||
test-react-latest:
|
||||
name: test-react-latest
|
||||
strategy:
|
||||
matrix:
|
||||
module: [dom]
|
||||
shard: [1/2, 2/2]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
- run: bun install
|
||||
|
||||
# dom test
|
||||
- name: dom test
|
||||
run: bun run test -- --maxWorkers=2 --shard=${{matrix.shard}} --coverage
|
||||
|
||||
- name: persist coverages
|
||||
run: |
|
||||
mkdir persist-coverage
|
||||
mv coverage/coverage-final.json persist-coverage/react-test-${{matrix.module}}-${{strategy.job-index}}.json
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
name: upload coverages
|
||||
with:
|
||||
name: coverage-artifacts-${{ matrix.module }}-${{ strategy.job-index }}
|
||||
path: persist-coverage/
|
||||
|
||||
test-react-latest-dist:
|
||||
name: test-react-latest-dist
|
||||
strategy:
|
||||
matrix:
|
||||
module: [dist, dist-min]
|
||||
shard: [1/2, 2/2]
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
- run: bun install
|
||||
|
||||
- name: restore cache from dist
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: dist
|
||||
key: dist-${{ github.sha }}
|
||||
|
||||
- name: dist-min test
|
||||
if: ${{ matrix.module == 'dist-min' }}
|
||||
run: bun run test
|
||||
env:
|
||||
LIB_DIR: dist-min
|
||||
|
||||
- name: dist test
|
||||
if: ${{ matrix.module == 'dist' }}
|
||||
run: bun run test
|
||||
env:
|
||||
LIB_DIR: dist
|
||||
|
||||
############################ Test Coverage ###########################
|
||||
upload-test-coverage:
|
||||
name: test-coverage
|
||||
runs-on: ubuntu-latest
|
||||
needs: test-react-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
- run: bun install
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: coverage-artifacts-*
|
||||
merge-multiple: true
|
||||
path: persist-coverage
|
||||
- name: Merge Code Coverage
|
||||
run: |
|
||||
bunx nyc merge persist-coverage/ coverage/coverage-final.json
|
||||
bunx nyc report --reporter text -t coverage --report-dir coverage
|
||||
rm -rf persist-coverage
|
||||
- name: Upload coverage to codecov
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
# use own token to upload coverage reports
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
########################### Compile & Test ###########################
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
- run: bun install
|
||||
|
||||
- name: cache lib
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: lib
|
||||
key: lib-${{ github.sha }}
|
||||
|
||||
- name: cache es
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: es
|
||||
key: es-${{ github.sha }}
|
||||
|
||||
- name: compile
|
||||
run: bun run compile
|
||||
|
||||
- name: cache dist
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: dist
|
||||
key: dist-${{ github.sha }}
|
||||
|
||||
- name: dist
|
||||
run: bun run dist
|
||||
env:
|
||||
NODE_OPTIONS: --max_old_space_size=4096
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
CI: 1
|
||||
|
||||
- name: check build files
|
||||
run: bun run test:dekko
|
||||
|
||||
# Artifact build files
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
with:
|
||||
name: build artifacts
|
||||
path: |
|
||||
dist
|
||||
locale
|
||||
es
|
||||
lib
|
||||
|
||||
- name: zip builds
|
||||
if: github.repository == 'ant-design/ant-design' && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
env:
|
||||
ALI_OSS_AK_ID: ${{ secrets.ALI_OSS_AK_ID }}
|
||||
ALI_OSS_AK_SECRET: ${{ secrets.ALI_OSS_AK_SECRET }}
|
||||
HEAD_SHA: ${{ github.sha }}
|
||||
run: |
|
||||
zip -r oss-artifacts.zip dist locale es lib
|
||||
echo "🤖 Uploading"
|
||||
node scripts/visual-regression/upload.js ./oss-artifacts.zip --ref=$HEAD_SHA
|
||||
|
||||
test-lib-es:
|
||||
name: test lib/es module
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
module: [lib, es]
|
||||
shard: [1/2, 2/2]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
- run: bun install
|
||||
|
||||
- name: restore cache from ${{ matrix.module }}
|
||||
# lib only run in master branch not in pull request
|
||||
if: ${{ github.event_name != 'pull_request' || matrix.module != 'lib' }}
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ matrix.module }}
|
||||
key: ${{ matrix.module }}-${{ github.sha }}
|
||||
|
||||
- name: compile
|
||||
# lib only run in master branch not in pull request
|
||||
if: ${{ github.event_name != 'pull_request' || matrix.module != 'lib' }}
|
||||
run: bun run compile
|
||||
|
||||
- name: test
|
||||
# lib only run in master branch not in pull request
|
||||
if: ${{ github.event_name != 'pull_request' || matrix.module != 'lib' }}
|
||||
run: bun run test -- --maxWorkers=2 --shard=${{matrix.shard}}
|
||||
env:
|
||||
LIB_DIR: ${{ matrix.module }}
|
24
.github/workflows/test.yml
vendored
24
.github/workflows/test.yml
vendored
@ -2,7 +2,11 @@
|
||||
# https://github.com/ant-design/ant-design/blob/79f566b7f8abb1012ef55b0d2793bfdf5595b85d/.github/workflows/test.yml
|
||||
name: ✅ test
|
||||
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
push:
|
||||
branches: [master, feature]
|
||||
pull_request:
|
||||
branches: [master, feature]
|
||||
|
||||
# Cancel prev CI if new commit come
|
||||
concurrency:
|
||||
@ -27,7 +31,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
react: ['16', '17']
|
||||
shard: ['1/2', '2/2']
|
||||
shard: [1/2, 2/2]
|
||||
env:
|
||||
REACT: ${{ matrix.react }}
|
||||
runs-on: ubuntu-latest
|
||||
@ -58,8 +62,8 @@ jobs:
|
||||
name: test-react-latest
|
||||
strategy:
|
||||
matrix:
|
||||
module: ['dom']
|
||||
shard: ['1/2', '2/2']
|
||||
module: [dom]
|
||||
shard: [1/2, 2/2]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@ -85,8 +89,8 @@ jobs:
|
||||
name: test-react-latest-dist
|
||||
strategy:
|
||||
matrix:
|
||||
module: ['dist', 'dist-min']
|
||||
shard: ['1/2', '2/2']
|
||||
module: [dist, dist-min]
|
||||
shard: [1/2, 2/2]
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
steps:
|
||||
@ -133,7 +137,7 @@ jobs:
|
||||
bunx nyc report --reporter text -t coverage --report-dir coverage
|
||||
rm -rf persist-coverage
|
||||
- name: Upload coverage to codecov
|
||||
uses: codecov/codecov-action@v4
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
# use own token to upload coverage reports
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
@ -170,12 +174,12 @@ jobs:
|
||||
- name: dist
|
||||
run: bun run dist
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
NODE_OPTIONS: --max_old_space_size=4096
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
CI: 1
|
||||
|
||||
- name: check build files
|
||||
run: node ./tests/dekko/index.test.js
|
||||
run: bun run test:dekko
|
||||
|
||||
# Artifact build files
|
||||
- uses: actions/upload-artifact@v4
|
||||
@ -205,7 +209,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
module: [lib, es]
|
||||
shard: ['1/2', '2/2']
|
||||
shard: [1/2, 2/2]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
|
2
.github/workflows/upgrade-deps.yml
vendored
2
.github/workflows/upgrade-deps.yml
vendored
@ -40,7 +40,7 @@ jobs:
|
||||
|
||||
- name: create pull request
|
||||
id: cpr
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }} # Cannot be default!!!
|
||||
assignees: 'afc163, zombieJ, xrkffgg, MadCcc'
|
||||
|
14
.github/workflows/verify-files-modify.yml
vendored
14
.github/workflows/verify-files-modify.yml
vendored
@ -18,10 +18,10 @@ jobs:
|
||||
with:
|
||||
forbid-paths: '.github/, scripts/'
|
||||
forbid-files: 'CHANGELOG.zh-CN.md, CHANGELOG.en-US.md, LICENSE'
|
||||
skip-verify-authority: 'write'
|
||||
skip-label: 'skip-verify-files'
|
||||
skip-verify-authority: write
|
||||
skip-label: skip-verify-files
|
||||
assignees: 'afc163, zombieJ, xrkffgg, MadCcc'
|
||||
comment-mark: 'version'
|
||||
comment-mark: version
|
||||
comment: |
|
||||
Hi @${{ github.event.pull_request.user.login }}. Thanks for your contribution. The path `.github/` or `scripts/` and `CHANGELOG` is only maintained by team members. This current PR will be closed and team members will help on this.
|
||||
close: true
|
||||
@ -35,11 +35,11 @@ jobs:
|
||||
- name: verify-version
|
||||
uses: actions-cool/verify-files-modify@v1
|
||||
with:
|
||||
forbid-files: 'README.md'
|
||||
skip-verify-authority: 'write'
|
||||
skip-label: 'skip-verify-files'
|
||||
forbid-files: README.md
|
||||
skip-verify-authority: write
|
||||
skip-label: skip-verify-files
|
||||
assignees: 'afc163, zombieJ, xrkffgg, MadCcc'
|
||||
comment-mark: 'readmeCheck'
|
||||
comment-mark: readmeCheck
|
||||
comment: |
|
||||
Hi @${{ github.event.pull_request.user.login }}. Thanks for your contribution. But, we don't have plan to add README of more languages. This current PR will be closed and team members will help on this.
|
||||
close: true
|
||||
|
2
.github/workflows/verify-package-version.yml
vendored
2
.github/workflows/verify-package-version.yml
vendored
@ -19,6 +19,6 @@ jobs:
|
||||
- name: verify-version
|
||||
uses: actions-cool/verify-package-version@v1
|
||||
with:
|
||||
title-include-content: 'docs'
|
||||
title-include-content: docs
|
||||
title-include-version: true
|
||||
open-comment: true
|
||||
|
@ -58,7 +58,13 @@ jobs:
|
||||
if (comment.body.includes('VISUAL_DIFF_FAILED')) {
|
||||
hasDiffFailed = true;
|
||||
}
|
||||
if (comment.body.includes('- [x] Visual diff is acceptable')) {
|
||||
|
||||
// https://regex101.com/r/kLjudz/1
|
||||
const RE = /(?<=\>\s\[!IMPORTANT\].*?- \[ \])/s;
|
||||
if (
|
||||
comment.body.includes('- [x] Visual diff is acceptable') &&
|
||||
comment.body.match(RE) == null /** 检查 IMPORTANT 是否存在未勾选的 */
|
||||
) {
|
||||
hasMemberApprove = true;
|
||||
}
|
||||
}
|
||||
@ -71,15 +77,26 @@ jobs:
|
||||
const mergedStatus = diffPassed ? 'success' : hasDiffFailed ? 'failure' : 'pending';
|
||||
console.log('Status:', mergedStatus);
|
||||
|
||||
await github.rest.repos.createCommitStatus({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
sha: prHeadSha,
|
||||
state: mergedStatus,
|
||||
context: 'Visual Regression Diff Wait Approve',
|
||||
description: diffPassed ? 'Visual diff is acceptable' : 'Visual diff is not pass',
|
||||
const { data: currentStatuses } = await github.rest.repos.listCommitStatusesForRef({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
ref: prHeadSha,
|
||||
});
|
||||
|
||||
const currentStatus = currentStatuses.find(status => status.context === 'Visual Regression Diff Wait Approve');
|
||||
if (currentStatus && currentStatus.state === mergedStatus) {
|
||||
console.log('Status has not changed, no need to update:', currentStatus.state);
|
||||
} else {
|
||||
await github.rest.repos.createCommitStatus({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
sha: prHeadSha,
|
||||
state: mergedStatus,
|
||||
context: 'Visual Regression Diff Wait Approve',
|
||||
description: diffPassed ? 'Visual diff is acceptable' : 'Visual diff is not pass',
|
||||
});
|
||||
}
|
||||
|
||||
if (hasDiffSuccess || (hasDiffFailed && hasMemberApprove)) {
|
||||
return 'success';
|
||||
} else if (hasDiffFailed) {
|
||||
|
@ -4,7 +4,7 @@ name: 👀 Visual Regression Diff Build
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [master, feature]
|
||||
branches: [master, feature, next]
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
# Cancel prev CI if new commit come
|
||||
@ -21,7 +21,7 @@ jobs:
|
||||
name: visual-diff snapshot
|
||||
strategy:
|
||||
matrix:
|
||||
shard: ['1/2', '2/2']
|
||||
shard: [1/2, 2/2]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@ -35,7 +35,7 @@ jobs:
|
||||
bun run version
|
||||
bun run test:image -- --shard=${{matrix.shard}}
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
NODE_OPTIONS: --max_old_space_size=4096
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
name: artifact snapshot
|
||||
|
@ -4,7 +4,7 @@ name: 👀 Visual Regression Diff Finish
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["👀 Visual Regression Diff Build"]
|
||||
workflows: [👀 Visual Regression Diff Build]
|
||||
types:
|
||||
- completed
|
||||
|
||||
@ -68,7 +68,7 @@ jobs:
|
||||
|
||||
# We need get persist-index first
|
||||
- name: download image snapshot artifact
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
uses: dawidd6/action-download-artifact@v7
|
||||
with:
|
||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
@ -90,7 +90,7 @@ jobs:
|
||||
- name: download report artifact
|
||||
id: download_report
|
||||
if: ${{ needs.upstream-workflow-summary.outputs.build-status == 'success' || needs.upstream-workflow-summary.outputs.build-status == 'failure' }}
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
uses: dawidd6/action-download-artifact@v7
|
||||
with:
|
||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
@ -130,7 +130,7 @@ jobs:
|
||||
body: |
|
||||
${{ steps.report.outputs.content }}
|
||||
<!-- VISUAL_DIFF_REGRESSION_HOOK -->
|
||||
body-include: '<!-- VISUAL_DIFF_REGRESSION_HOOK -->'
|
||||
body-include: <!-- VISUAL_DIFF_REGRESSION_HOOK -->
|
||||
number: ${{ steps.pr.outputs.id }}
|
||||
|
||||
- name: failed comment
|
||||
@ -147,7 +147,7 @@ jobs:
|
||||
- `report upload` status: ${{ steps.report.outcome }}
|
||||
- workflow url: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
<!-- VISUAL_DIFF_REGRESSION_HOOK -->
|
||||
body-include: '<!-- VISUAL_DIFF_REGRESSION_HOOK -->'
|
||||
body-include: <!-- VISUAL_DIFF_REGRESSION_HOOK -->
|
||||
number: ${{ steps.pr.outputs.id }}
|
||||
|
||||
# Resync commit status. This will be also reset by `visual-regression-diff-approver`
|
||||
|
@ -8,7 +8,7 @@ name: 👀 Visual Regression Diff Start
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
branches: [master, feature]
|
||||
branches: [master, feature, next]
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
permissions:
|
||||
@ -34,4 +34,4 @@ jobs:
|
||||
<img src="https://github.com/ant-design/ant-design/assets/507615/5d52d8a2-f74e-4159-9792-c705b7bc1744" width="300" />
|
||||
|
||||
<!-- VISUAL_DIFF_REGRESSION_HOOK -->
|
||||
body-include: '<!-- VISUAL_DIFF_REGRESSION_HOOK -->'
|
||||
body-include: <!-- VISUAL_DIFF_REGRESSION_HOOK -->
|
||||
|
@ -4,7 +4,7 @@ name: 👁️ Visual Regression Persist Finish
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["👁️ Visual Regression Persist Start"]
|
||||
workflows: [👁️ Visual Regression Persist Start]
|
||||
types:
|
||||
- completed
|
||||
|
||||
@ -65,7 +65,7 @@ jobs:
|
||||
|
||||
# We need get persist key first
|
||||
- name: Download Visual Regression Ref
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
uses: dawidd6/action-download-artifact@v7
|
||||
with:
|
||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
@ -79,7 +79,7 @@ jobs:
|
||||
|
||||
- name: Download Visual-Regression Artifact
|
||||
if: ${{ fromJSON(needs.upstream-workflow-summary.outputs.build-success) }}
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
uses: dawidd6/action-download-artifact@v7
|
||||
with:
|
||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
@ -87,7 +87,7 @@ jobs:
|
||||
path: ./tmp
|
||||
|
||||
- name: Persist Image Snapshot to OSS
|
||||
if: github.repository == 'ant-design/ant-design' && github.event.workflow_run.event == 'push' && (github.event.workflow_run.head_branch == 'master' || github.event.workflow_run.head_branch == 'feature')
|
||||
if: github.repository == 'ant-design/ant-design' && github.event.workflow_run.event == 'push' && (github.event.workflow_run.head_branch == 'master' || github.event.workflow_run.head_branch == 'feature' || github.event.workflow_run.head_branch == 'next')
|
||||
env:
|
||||
ALI_OSS_AK_ID: ${{ secrets.ALI_OSS_AK_ID }}
|
||||
ALI_OSS_AK_SECRET: ${{ secrets.ALI_OSS_AK_SECRET }}
|
||||
|
@ -7,6 +7,7 @@ on:
|
||||
branches:
|
||||
- master
|
||||
- feature
|
||||
- next
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@ -26,7 +27,7 @@ jobs:
|
||||
bun run test:image
|
||||
tar -czvf imageSnapshots.tar.gz imageSnapshots/*
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
NODE_OPTIONS: --max_old_space_size=4096
|
||||
|
||||
# Upload `imageSnapshots` on master
|
||||
- name: upload report artifact
|
||||
|
2
.husky/pre-commit
Executable file → Normal file
2
.husky/pre-commit
Executable file → Normal file
@ -1 +1 @@
|
||||
lint-staged
|
||||
lint-staged
|
1
.jest.js
1
.jest.js
@ -5,6 +5,7 @@ const compileModules = [
|
||||
'@ant-design',
|
||||
'countup.js',
|
||||
'.pnpm',
|
||||
'@asamuzakjp/css-color',
|
||||
];
|
||||
|
||||
const ignoreList = [];
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"*.{ts,tsx,js,jsx,json,css}": ["biome check --write"],
|
||||
"*.{ts,tsx,js,jsx,css,mjs,json}": ["biome check --write --no-errors-on-unmatched", "eslint"],
|
||||
"*.{md,yml}": ["prettier --ignore-unknown --write"]
|
||||
}
|
||||
|
3
.npmrc
3
.npmrc
@ -1,5 +1,4 @@
|
||||
package-lock=false
|
||||
|
||||
legacy-peer-deps=true
|
||||
PUPPETEER_DOWNLOAD_BASE_URL="https://cdn.npmmirror.com/binaries/chrome-for-testing"
|
||||
|
||||
npm_config_sharp_libvips_binary_host="https://cdn.npmmirror.com/binaries/sharp-libvips"
|
||||
|
@ -31,3 +31,4 @@ components/*/*.jsx
|
||||
.history
|
||||
**/*.yml
|
||||
*.html
|
||||
CHANGELOG.*.md
|
||||
|
@ -56,5 +56,24 @@
|
||||
">= 5.16.0 <= 5.16.1": ["https://github.com/ant-design/ant-design/issues/48200"],
|
||||
"5.16.3": ["https://github.com/ant-design/ant-design/issues/48568"],
|
||||
"5.17.1": ["https://github.com/ant-design/ant-design/issues/48913"],
|
||||
"5.18.2": ["https://github.com/ant-design/ant-design/pull/49487"]
|
||||
"5.18.2": ["https://github.com/ant-design/ant-design/pull/49487"],
|
||||
"5.20.4": ["https://github.com/ant-design/ant-design/issues/50687"],
|
||||
"5.21.0": [
|
||||
"https://github.com/ant-design/ant-design/issues/50960",
|
||||
"https://github.com/ant-design/ant-design/issues/50969"
|
||||
],
|
||||
"5.21.6": [
|
||||
"https://github.com/ant-design/ant-design/issues/51420",
|
||||
"https://github.com/ant-design/ant-design/issues/51430"
|
||||
],
|
||||
"5.22.0": [
|
||||
"https://github.com/ant-design/ant-design/issues/51601",
|
||||
"https://github.com/ant-design/ant-design/issues/51420",
|
||||
"https://github.com/ant-design/ant-design/issues/51430"
|
||||
],
|
||||
"5.22.1": [
|
||||
"https://github.com/ant-design/ant-design/issues/51420",
|
||||
"https://github.com/ant-design/ant-design/issues/51430"
|
||||
],
|
||||
"5.22.6": ["https://github.com/ant-design/ant-design/issues/52124"]
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
---
|
||||
order: 6
|
||||
title: Changelog
|
||||
toc: false
|
||||
timeline: true
|
||||
tag: vVERSION
|
||||
---
|
||||
@ -16,6 +15,402 @@ tag: vVERSION
|
||||
|
||||
---
|
||||
|
||||
## 5.23.2
|
||||
|
||||
`2025-01-20`
|
||||
|
||||
- 🐞 Fix Space.Compact throwing `Should not use more than one & in a selector` warning. [#52489](https://github.com/ant-design/ant-design/pull/52489)
|
||||
- 💄 Fix the Layout switching sidebar button style was lost. [#52477](https://github.com/ant-design/ant-design/pull/52477)
|
||||
- 💄 Fix the scroll bar height is not 0 when the first row of the virtual scroll Table is collapsed. [#52447](https://github.com/ant-design/ant-design/pull/52447) [@LeeSSHH](https://github.com/LeeSSHH)
|
||||
- 💄 Fix the last item in Descriptions did not correctly fill the remaining space. [#52410](https://github.com/ant-design/ant-design/pull/52410) [@anyuxuan](https://github.com/anyuxuan)
|
||||
- 💄 Fix extra margin for the last item in Radio. [#52433](https://github.com/ant-design/ant-design/pull/52433)
|
||||
- 💄 Fix the Input/Mentions clear button padding was incorrect. [#52407](https://github.com/ant-design/ant-design/pull/52407) [@ustcfury](https://github.com/ustcfury)
|
||||
- 💄 Fix rounded corners of `addonAfter` in Input compact mode. [#52490](https://github.com/ant-design/ant-design/pull/52490) [@DDDDD12138](https://github.com/DDDDD12138)
|
||||
- 💄 Fix Menu.Item links were still clickable and lacked disabled styles when in disabled state. [#52402](https://github.com/ant-design/ant-design/pull/52402) [@aojunhao123](https://github.com/aojunhao123)
|
||||
- TypeScript
|
||||
- 🤖 MISC: Optimize PurePanel to use React.ComponentType type. [#52480](https://github.com/ant-design/ant-design/pull/52480)
|
||||
- 🤖 Fix missing token type for Skeleton and Rate. [#52406](https://github.com/ant-design/ant-design/pull/52406) [@coding-ice](https://github.com/coding-ice)
|
||||
|
||||
## 5.23.1
|
||||
|
||||
`2025-01-13`
|
||||
|
||||
- 🆕 Add Tree leaf node className for differentiate node type. [#52274](https://github.com/ant-design/ant-design/pull/52274) [@EmilyyyLiu](https://github.com/EmilyyyLiu)
|
||||
- 🐞 Fix DatePicker switch buttons is not hidden when `superPrevIcon/superNextIcon/prevIcon/nextIcon` is null. [#52327](https://github.com/ant-design/ant-design/pull/52327) [@afc163](https://github.com/afc163)
|
||||
- 🐞 Fix Select throws `error not a valid selector` in Jest tests. [#51844](https://github.com/ant-design/ant-design/pull/51844) [@renovate](https://github.com/renovate)
|
||||
- 🐞 Fix Layout.Sider under ConfigProvider directly, the `theme` not working. [#52302](https://github.com/ant-design/ant-design/pull/52302) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 Fix Splitter lost previous state when re-expanding. [#52222](https://github.com/ant-design/ant-design/pull/52222) [@jjlstruggle](https://github.com/jjlstruggle)
|
||||
- 🐞 Fix Table unexpected row selections when set `checkStrictly` to false in tree mode. [#52338](https://github.com/ant-design/ant-design/pull/52338) [@LeeSSHH](https://github.com/LeeSSHH)
|
||||
- Button
|
||||
- 🐞 Fix Button alignment and icon centering by adjusting the icon size for icon-only Buttons. [#52353](https://github.com/ant-design/ant-design/pull/52353) [@afc163](https://github.com/afc163)
|
||||
- 💄 Fix Button missing `box-shadow` style. [#52304](https://github.com/ant-design/ant-design/pull/52304) [@zombieJ](https://github.com/zombieJ)
|
||||
- RTL
|
||||
- 💄 Fix Collapse arrow direction in RTL mode. [#52374](https://github.com/ant-design/ant-design/pull/52374) [@aojunhao123](https://github.com/aojunhao123)
|
||||
- 💄 Fix Layout.Sider arrow direction in RTL mode. [#52374](https://github.com/ant-design/ant-design/pull/52374) [@aojunhao123](https://github.com/aojunhao123)
|
||||
|
||||
## 5.23.0
|
||||
|
||||
`2025-01-06`
|
||||
|
||||
- 🔥 TreeSelect support `maxCount` to limit the maximum number of selections. [#51759](https://github.com/ant-design/ant-design/pull/51759) [@aojunhao123](https://github.com/aojunhao123)
|
||||
- 🔥 Modal `width` support responsive size. [#51653](https://github.com/ant-design/ant-design/pull/51653) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🔥 Splitter support `lazy` mode. [#51557](https://github.com/ant-design/ant-design/pull/51557) [@OysterD3](https://github.com/OysterD3)
|
||||
- Button
|
||||
- 🔥 Button `color` support full color palette. [#51550](https://github.com/ant-design/ant-design/pull/51550) [@OysterD3](https://github.com/OysterD3)
|
||||
<img width="520" alt="Button Colors" src="https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*ApyYQpXQQfgAAAAAAAAAAAAADgCCAQ/original">
|
||||
- 🆕 Button support `loading={{ icon: ReactNode }}` to customize loading icon. [#51758](https://github.com/ant-design/ant-design/pull/51758) [@zhangchao-wooc](https://github.com/zhangchao-wooc)
|
||||
- Menu
|
||||
- 🐞 Fix Menu `extra` font size and vertical align issue. [#52217](https://github.com/ant-design/ant-design/pull/52217) [@guoyunhe](https://github.com/guoyunhe)
|
||||
- 🆕 Menu add token `subMenuItemSelectedColor` to resolve submenu title color being overrided by `itemSelectedColor`. [#52182](https://github.com/ant-design/ant-design/pull/52182) [@afc163](https://github.com/afc163)
|
||||
- 🆕 Semantic Props
|
||||
- 🆕 ConfigProvider support Empty semantic props `classNames` and `styles`. [#52208](https://github.com/ant-design/ant-design/pull/52208) [@thinkasany](https://github.com/thinkasany)
|
||||
- 🆕 ConfigProvider support Popconfirm semantic props `classNames` and `styles`. [#52126](https://github.com/ant-design/ant-design/pull/52126) [@thinkasany](https://github.com/thinkasany)
|
||||
- 🆕 ConfigProvider support Popover semantic props `classNames` and `styles`. [#52110](https://github.com/ant-design/ant-design/pull/52110) [@thinkasany](https://github.com/thinkasany)
|
||||
- 🆕 ConfigProvider support Tooltip semantic props `classNames` and `styles`. [#51872](https://github.com/ant-design/ant-design/pull/51872) [@thinkasany](https://github.com/thinkasany)
|
||||
- 🆕 ConfigProvider support Descriptions semantic props `classNames` and `styles`. [#52120](https://github.com/ant-design/ant-design/pull/52120) [@thinkasany](https://github.com/thinkasany)
|
||||
- 🆕 ConfigProvider support Slider semantic props `classNames` and `styles`. [#52185](https://github.com/ant-design/ant-design/pull/52185) [@thinkasany](https://github.com/thinkasany)
|
||||
- 🆕 Transfer support `showSearch` config `defaultValue` & `placeholder`. [#52125](https://github.com/ant-design/ant-design/pull/52125) [@EmilyyyLiu](https://github.com/EmilyyyLiu)
|
||||
- 🆕 Calendar now supports `showWeek` prop. [#52072](https://github.com/ant-design/ant-design/pull/52072) [@afc163](https://github.com/afc163)
|
||||
- 🆕 Mentions support `onPopupScroll` props. [#51858](https://github.com/ant-design/ant-design/pull/51858) [@OysterD3](https://github.com/OysterD3)
|
||||
- 🆕 Card support `bodyPaddingSM`, `headerPaddingSM`, `bodyPadding`, `headerPadding` component token. [#51762](https://github.com/ant-design/ant-design/pull/51762) [@thinkasany](https://github.com/thinkasany)
|
||||
- 🆕 ColorPicker `presets` support `key` prop. [#51794](https://github.com/ant-design/ant-design/pull/51794) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- 🆕 Cascader support `optionSelectedColor` token. [#51769](https://github.com/ant-design/ant-design/pull/51769) [@thinkasany](https://github.com/thinkasany)
|
||||
- Tree
|
||||
- 🛠 Refactor Tree part code to Function Component for React 19 perf preparing. [#52209](https://github.com/ant-design/ant-design/pull/52209) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- 💄 Optimize Tree `disabled` & `selected` node display style. [#52173](https://github.com/ant-design/ant-design/pull/52173) [@EmilyyyLiu](https://github.com/EmilyyyLiu)
|
||||
- 🐞 Fix Slider crash when `tipFormatter` is undefined. [#52184](https://github.com/ant-design/ant-design/pull/52184) [@thinkasany](https://github.com/thinkasany)
|
||||
- 🐞 Fix Layout.Sider `trigger` style not correct. [#46a8eff](https://github.com/ant-design/ant-design/commit/46a8eff) [@Wxh16144](https://github.com/Wxh16144)
|
||||
- Table
|
||||
- 🐞 Fix Table `fixed:right` is not working in `expandable`. [#52176](https://github.com/ant-design/ant-design/pull/52176) [@afc163](https://github.com/afc163)
|
||||
- 🐞 Fix Table sticky scrollbar not working in rtl direction. [#52176](https://github.com/ant-design/ant-design/pull/52176) [@afc163](https://github.com/afc163)
|
||||
- 💄 Optimize Flex to always reset `margin` & `padding` for customize component. [#52170](https://github.com/ant-design/ant-design/pull/52170) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- 🐞 Fix DatePicker.RangePicker `needConfirm` sometime can switch panel without confirm. [#52102](https://github.com/ant-design/ant-design/pull/52102) [@Zyf665](https://github.com/Zyf665)
|
||||
- 💄 Optimize Collapse focus styles and items border radius. [#52086](https://github.com/ant-design/ant-design/pull/52086) [@aojunhao123](https://github.com/aojunhao123)
|
||||
- ⌨️ Add Radio.Group default `name` prop to improve a11y. [#52076](https://github.com/ant-design/ant-design/pull/52076) [@aojunhao123](https://github.com/aojunhao123)
|
||||
- ⌨️ Input.Search add `type=search` by default. [#52083](https://github.com/ant-design/ant-design/pull/52083) [@Kaikiat1126](https://github.com/Kaikiat1126)
|
||||
- ⌨️ Improve Tabs focus style for keyboard operation. [#52002](https://github.com/ant-design/ant-design/pull/52002) [@aojunhao123](https://github.com/aojunhao123)
|
||||
- Segmented
|
||||
- ⌨️ Optimize Segmented focus style to improve a11y. [#51934](https://github.com/ant-design/ant-design/pull/51934) [@aojunhao123](https://github.com/aojunhao123)
|
||||
- ⌨️ Segmented support `name` prop to improve a11y. [#51725](https://github.com/ant-design/ant-design/pull/51725) [@thinkasany](https://github.com/thinkasany)
|
||||
- 📦 MISC: Reduce bundle size by replacing `@ctrl/tinycolor` with `@ant-design/fast-color`. [#52190](https://github.com/ant-design/ant-design/pull/52190) [#52157](https://github.com/ant-design/ant-design/pull/52157) [@aojunhao123](https://github.com/aojunhao123)
|
||||
- ⌨️ Adjust Input, InputNumber, Mentions, Textarea clear icon from `span` to `button` to improve a11y. [#52180](https://github.com/ant-design/ant-design/pull/52180) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- 🐞 MISC: Fix build error when using React 19. [#52168](https://github.com/ant-design/ant-design/pull/52168) [@zombieJ](https://github.com/zombieJ)
|
||||
- TypeScript
|
||||
- 🤖 Adjust Table `ref` type to React.Ref. [#52205](https://github.com/ant-design/ant-design/pull/52205) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- 🤖 Calendar export CalendarMode type. [#52160](https://github.com/ant-design/ant-design/pull/52160) [@Kaikiat1126](https://github.com/Kaikiat1126)
|
||||
|
||||
## 5.22.7
|
||||
|
||||
`2024-12-27`
|
||||
|
||||
- 🐞 Fix Button text and icon not align. [#52132](https://github.com/ant-design/ant-design/pull/52132) [@afc163](https://github.com/afc163)
|
||||
- 🐞 Fix Button throws `reactRender is not a function` under React 19. [#52105](https://github.com/ant-design/ant-design/pull/52105) [@afc163](https://github.com/afc163)
|
||||
- TypeScript
|
||||
- 🤖 Fix Menu interface type error from external module. [#51715](https://github.com/ant-design/ant-design/pull/51715) [@msyavuz](https://github.com/msyavuz)
|
||||
|
||||
## 5.22.6
|
||||
|
||||
`2024-12-23`
|
||||
|
||||
- 🐞 Align Button with and without icons consistently. [#52070](https://github.com/ant-design/ant-design/pull/52070)
|
||||
- 🐞 Fix Splitter collapsible icon `z-index` too low. [#52065](https://github.com/ant-design/ant-design/pull/52065) [@wanpan11](https://github.com/wanpan11)
|
||||
- 🐞 Fix Button motion not smooth when set `loading`. [#52059](https://github.com/ant-design/ant-design/pull/52059) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 Fix Button issue where solid default button text disappears on hover in dark mode. [#52024](https://github.com/ant-design/ant-design/pull/52024) [@DDDDD12138](https://github.com/DDDDD12138)
|
||||
|
||||
## 5.22.5
|
||||
|
||||
`2024-12-15`
|
||||
|
||||
- 🛠 Refactor Wave/Menu/Form `ref` check logic to resolve React 19 `ref` conflict (Note, this is not finally support React 19 but we will resolve step by step in future version). [#51952](https://github.com/ant-design/ant-design/pull/51952) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 Fix Dropdown cannot accept ReactNode as `children`. [#50174](https://github.com/ant-design/ant-design/pull/50174) [@coding-ice](https://github.com/coding-ice)
|
||||
- 🐞 Fix Carousel cannot display correctly in Modal without icon. [#51988](https://github.com/ant-design/ant-design/pull/51988) [@quan060798](https://github.com/quan060798)
|
||||
- 🐞 Fix Select label overflow issue. [#52011](https://github.com/ant-design/ant-design/pull/52011) [@OysterD3](https://github.com/OysterD3)
|
||||
- 🐞 Fix Form `setFieldValue` not reset field validation. [#51993](https://github.com/ant-design/ant-design/pull/51993) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 Fix Pagination with setting `showSizeChanger.showSearch` not working. [#51962](https://github.com/ant-design/ant-design/pull/51962) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🇰🇷 Improve Korean locales for DatePicker. [#51983](https://github.com/ant-design/ant-design/pull/51983) [@DevLeti](https://github.com/DevLeti)
|
||||
- 🤖 Export `CheckboxChangeEvent` from antd. [#52008](https://github.com/ant-design/ant-design/pull/52008) [@SpecLad](https://github.com/SpecLad)
|
||||
|
||||
## 5.22.4
|
||||
|
||||
`2024-12-09`
|
||||
|
||||
- Transfer
|
||||
- 🐞 Fix the background overflow when Transfer selects the last item on the current page. [#51884](https://github.com/ant-design/ant-design/pull/51884) [@ayangweb](https://github.com/ayangweb)
|
||||
- 🐞 Fix Transfer toggle button being enabled when all items are disabled. [#51784](https://github.com/ant-design/ant-design/pull/51784) [@WwwHhhYran](https://github.com/WwwHhhYran)
|
||||
- 🐞 Fix the arrow would be outside the container when the Tooltip content was too small. [#51904](https://github.com/ant-design/ant-design/pull/51904)
|
||||
- 🐞 Fix where clicking the Radio or Checkbox under Upload would trigger the popup window twice. [#51874](https://github.com/ant-design/ant-design/pull/51874)
|
||||
- 💄 Fix Menu icon alignment when using `collapsedIconSize`. [#51863](https://github.com/ant-design/ant-design/pull/51863) [@Gnomeek](https://github.com/Gnomeek)
|
||||
- 💄 Fix incorrect styling of Tabs component when `type="editable-card"`. [#51935](https://github.com/ant-design/ant-design/pull/51935) [@aojunhao123](https://github.com/aojunhao123)
|
||||
- 💄 Fix insufficient trigger style priority in Layout.Sider component in `zero-width` mode. [#51936](https://github.com/ant-design/ant-design/pull/51936) [@aojunhao123](https://github.com/aojunhao123)
|
||||
- 💄 MISC: Fix the icon styles were created repeatedly. [#51897](https://github.com/ant-design/ant-design/pull/51897) [@YumoImer](https://github.com/YumoImer)
|
||||
- 💄 MISC: Inline styles refactored to cssinjs. [#51843](https://github.com/ant-design/ant-design/pull/51843)
|
||||
|
||||
## 5.22.3
|
||||
|
||||
`2024-12-02`
|
||||
|
||||
- 🐞 Fix Select clear button may has incorrect position within Form.item. [#51649](https://github.com/ant-design/ant-design/pull/51649) [@dislido](https://github.com/dislido)
|
||||
- 🐞 Fix InputNumber `handleVisible` token not work as expected. [#51728](https://github.com/ant-design/ant-design/pull/51728) [@dengfuping](https://github.com/dengfuping)
|
||||
- 🐞 Fix ColorPicker error when pass `ReactNode` to `label` field of `presets` property. [#51808](https://github.com/ant-design/ant-design/pull/51808) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- 🐞 Fix Menu `inlineCollapsed` property not works bug within Layout. [#51775](https://github.com/ant-design/ant-design/pull/51775) [@coderz-w](https://github.com/coderz-w)
|
||||
- 🐞 Fix Table `onHeaderCell` provided part `style` can not override. [#51793](https://github.com/ant-design/ant-design/pull/51793) [@Wxh16144](https://github.com/Wxh16144)
|
||||
- ⌨️ Improve Collapse accessibility. [#51836](https://github.com/ant-design/ant-design/pull/51836) [@aojunhao123](https://github.com/aojunhao123)
|
||||
- TypeScript
|
||||
- 🤖 Add Table argument type for `clearFilters` function property. [#51754](https://github.com/ant-design/ant-design/pull/51754) [@fubd](https://github.com/fubd)
|
||||
- 🤖 Fix Form.List with nest field will miss value with remove when set Form `preserve` to `false`. [#51796](https://github.com/ant-design/ant-design/pull/51796) [@zombieJ](https://github.com/zombieJ)
|
||||
|
||||
## 5.22.2
|
||||
|
||||
`2024-11-21`
|
||||
|
||||
- 🐞 Fix Input.OTP focus from advancing when previous input is empty. [#51664](https://github.com/ant-design/ant-design/pull/51664) [@thecodesalim](https://github.com/thecodesalim)
|
||||
- 🐞 Adjust Modal function call not to scroll the confirm button when it get auto focused. [#51647](https://github.com/ant-design/ant-design/pull/51647) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 Fix Form `rules` with same error content will cause React render warning. [#51636](https://github.com/ant-design/ant-design/pull/51636) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 Refactor Button `focus` logic trigger with `useEffect` to resolve some async load case not get `autoFocus`. [#51624](https://github.com/ant-design/ant-design/pull/51624) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 Fix Button custom icon not center-aligned. [#51652](https://github.com/ant-design/ant-design/pull/51652) [@afc163](https://github.com/afc163)
|
||||
- 🐞 Fix Table `getCheckboxProps` event handlers being overridden by internal selection logic. [#51661](https://github.com/ant-design/ant-design/pull/51661) [@Zyf665](https://github.com/Zyf665)
|
||||
- 🐞 Fix Tree that `onCheck` and `onSelect` were not properly triggered. [#51448](https://github.com/ant-design/ant-design/pull/51448) [@Wxh16144](https://github.com/Wxh16144)
|
||||
- 🐞 Fix vertical alignment of clear icon in Input component. [#51700](https://github.com/ant-design/ant-design/pull/51700) [@jynxio](https://github.com/jynxio)
|
||||
- 🐞 Fix Select with `prefix` style issue with color, line break, status error. [#51694](https://github.com/ant-design/ant-design/pull/51694) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🌐 Localization
|
||||
- 🇷🇺 Add support for Russian translation. [#51619](https://github.com/ant-design/ant-design/pull/51619) [@avvakumovid](https://github.com/avvakumovid)
|
||||
- 🇮🇹 Add support for Italian translation in TimePicker. [#51685](https://github.com/ant-design/ant-design/pull/51685) [@LorenzoCardinali](https://github.com/LorenzoCardinali)
|
||||
|
||||
## 5.22.1
|
||||
|
||||
`2024-11-13`
|
||||
|
||||
- 🛠 Adjust DatePicker.RangePicker to not allow switching to the next field by clicking the input when `needConfirm` and the user has not submitted the date. [#51591](https://github.com/ant-design/ant-design/pull/51591) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🛠 Lock Input.OTP `ctrl + z` operation to avoid data not correct. [#51609](https://github.com/ant-design/ant-design/pull/51609) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 Fix Select `tags` or `multiple` mode display issue. [#51605](https://github.com/ant-design/ant-design/pull/51605) [@guoyunhe](https://github.com/guoyunhe)
|
||||
- 🐞 Fix Badge `count` motion missing in Safari. [#51598](https://github.com/ant-design/ant-design/pull/51598) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 Fix Tabs with `centered` the tabs can not fully display. [#51571](https://github.com/ant-design/ant-design/pull/51571) [@DDDDD12138](https://github.com/DDDDD12138)
|
||||
- 🐞 Fix Transfer with controlled `dataSource` & `selectedKeys` sometime miss sync checked state. [#51523](https://github.com/ant-design/ant-design/pull/51523) [@IsKaros](https://github.com/IsKaros)
|
||||
- 🐞 Revert Button `display` `inline-flex` back to `inline-block` to resolve Icon align issue. [#51588](https://github.com/ant-design/ant-design/pull/51588) [@Wxh16144](https://github.com/Wxh16144)
|
||||
|
||||
## 5.22.0
|
||||
|
||||
`2024-11-12`
|
||||
|
||||
- Form
|
||||
- 🆕 Form.Item supports hiding labels. [#51524](https://github.com/ant-design/ant-design/pull/51524) [@crazyair](https://github.com/crazyair)
|
||||
- 🐞 Form removes the div used to expand the error height, wraps errorDom and extraDom with a div, and sets a minimum height for the div. [#51254](https://github.com/ant-design/ant-design/pull/51254) [@hongzzz](https://github.com/hongzzz)
|
||||
- 🐞 Fix the problem that `onValuesChange` is still triggered when the Form field triggers change but the value does not change. [#51437](https://github.com/ant-design/ant-design/pull/51437) [@crazyair](https://github.com/crazyair)
|
||||
- 🆕 Form supports the focus property in scrollToFirstError when form validation fails. [#51231](https://github.com/ant-design/ant-design/pull/51231) [@nathanlao](https://github.com/nathanlao)
|
||||
- Table
|
||||
- 🆕 Table column filter drop-down box supports `filterDropdownProps`. [#51297](https://github.com/ant-design/ant-design/pull/51297) [@Wxh16144](https://github.com/Wxh16144)
|
||||
- 🆕 Table `expandedRowClassName` supports string . [#51067](https://github.com/ant-design/ant-design/pull/51067) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- Tree
|
||||
- 💄 Fix the problem of missing padding style for selected nodes in Tree. [#51492](https://github.com/ant-design/ant-design/pull/51492) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🆕 Tree component Token adds `nodeHoverColor` and `nodeSelectedColor` support. [#51367](https://github.com/ant-design/ant-design/pull/51367) [@zmbxy](https://github.com/zmbxy)
|
||||
- 🆕 Tree adds `indentSize` token for custom indent width. [#51010](https://github.com/ant-design/ant-design/pull/51010) [@afc163](https://github.com/afc163)
|
||||
- DatePicker
|
||||
- 🆕 DatePicker supports prefix attribute. [#51335](https://github.com/ant-design/ant-design/pull/51335) [@guoyunhe](https://github.com/guoyunhe)
|
||||
- 💄 Fixed the issue of DatePicker.RangePicker flashing when the mouse moves between cells. [#51533](https://github.com/ant-design/ant-design/pull/51533) [@afc163](https://github.com/afc163)
|
||||
- Input.OTP
|
||||
- 🆕 In the `Input.OTP` component, add `onInput` event to get the value of each user input. At the same time, the relevant documentation has been updated. [#51289](https://github.com/ant-design/ant-design/pull/51289) [@aojunhao123](https://github.com/aojunhao123)
|
||||
- 🐞 Fixed the problem that Input.OTP cannot specify `inputMode`. [#51271](https://github.com/ant-design/ant-design/pull/51271) [@alan-rudzinski](https://github.com/alan-rudzinski)
|
||||
- 🆕 ColorPicker supports `disabledFormat`. [#51539](https://github.com/ant-design/ant-design/pull/51539) [@su-muzhi](https://github.com/su-muzhi)
|
||||
- 🆕 Add `cursor` configuration item to the `focus` method of InputNumber component to control the cursor position. [#51444](https://github.com/ant-design/ant-design/pull/51444) [@aojunhao123](https://github.com/aojunhao123)
|
||||
- 🆕 Cascader adds `disabled` attribute to disable all first-level directory items of the component. [#51272](https://github.com/ant-design/ant-design/pull/51272) [@aojunhao123](https://github.com/aojunhao123)
|
||||
- 🆕 Descriptions supports single-line spreading. [#51365](https://github.com/ant-design/ant-design/pull/51365) [@crazyair](https://github.com/crazyair)
|
||||
- 🆕 Select/TreeSelect/Cascader components add `prefix` property to support custom prefix. [#51186](https://github.com/ant-design/ant-design/pull/51186) [@guoyunhe](https://github.com/guoyunhe)
|
||||
- 🐞 Fix the problem that the preview image class name is lost when setting `ImageProps.preview.rootClassName` in Image. [#51538](https://github.com/ant-design/ant-design/pull/51538) [@dislido](https://github.com/dislido)
|
||||
- 🐞 Fixed the issue that the last item in the TimePicker panel column cannot be scrolled to the top. [#51481](https://github.com/ant-design/ant-design/pull/51481) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 Fix TreeSelect dropdown height not enough. [#51567](https://github.com/ant-design/ant-design/pull/51567) [@afc163](https://github.com/afc163)
|
||||
- 🐞 Fixed the issue that Typography is not updated immediately when the ConfigProvider language is switched. [#51453](https://github.com/ant-design/ant-design/pull/51453) [@thinkasany](https://github.com/thinkasany)
|
||||
- 🐞 Fixed the issue that Upload `itemRender` calling `action.preview` will cause a crash. [#51419](https://github.com/ant-design/ant-design/pull/51419) [@yoyo837](https://github.com/yoyo837)
|
||||
- 🐞 Fixed Splitter pseudo-element symbol issue. [#51536](https://github.com/ant-design/ant-design/pull/51536) [@dislido](https://github.com/dislido)
|
||||
- 💄 Optimize Collapse accessibility attribute and mouse hover style. [#51400](https://github.com/ant-design/ant-design/pull/51400) [@afc163](https://github.com/afc163)
|
||||
- 💄 Fix styling issue of Menu title content. [#51425](https://github.com/ant-design/ant-design/pull/51425) [@coding-ice](https://github.com/coding-ice)
|
||||
- 🇵🇹 Fix translation in Portuguese (pt_PT) localization file for better accuracy and consistency. [#51501](https://github.com/ant-design/ant-design/pull/51501) [@alexandre-p-marques-alb](https://github.com/alexandre-p-marques-alb)
|
||||
- 🇺🇿 Optimize uz_UZ internationalization. [#51407](https://github.com/ant-design/ant-design/pull/51407) [@Zukhrik](https://github.com/Zukhrik)
|
||||
- TypeScript
|
||||
- 🤖 Upload exports type DraggerProps. [#51546](https://github.com/ant-design/ant-design/pull/51546) [@DBvc](https://github.com/DBvc)
|
||||
- 🤖 Add defaultValue property to TimePicker.RangePicker example. [#51413](https://github.com/ant-design/ant-design/pull/51413) [@nathanlao](https://github.com/nathanlao)
|
||||
- 🤖 Message Optimize the top type in message.config. [#51468](https://github.com/ant-design/ant-design/pull/51468) [@Fog3211](https://github.com/Fog3211)
|
||||
- 🤖 Optimize the TS definition of Tree and TreeSelect. [#51251](https://github.com/ant-design/ant-design/pull/51251) [@afc163](https://github.com/afc163)
|
||||
|
||||
## 5.21.6
|
||||
|
||||
`2024-10-28`
|
||||
|
||||
- 🐞 Fix Tree.DirectoryTree interactive area not being a whole row. [#51210](https://github.com/ant-design/ant-design/pull/51210)
|
||||
- 🐞 Fix the Button icon was not vertically centered. [#51381](https://github.com/ant-design/ant-design/pull/51381)
|
||||
- 🐞 Fix the pointer style not set to `not-allowed` in the `disabled` state when `variant` of the Input was set to `borderless`. [#51387](https://github.com/ant-design/ant-design/pull/51387) [@ustcfury](https://github.com/ustcfury)
|
||||
- Splitter
|
||||
- 💄 Improve the pre-rendered style of Splitter under SSR. [#51378](https://github.com/ant-design/ant-design/pull/51378)
|
||||
- 💄 Increased the click area of the Splitter collapse button to improve usability. [#51383](https://github.com/ant-design/ant-design/pull/51383) [@aojunhao123](https://github.com/aojunhao123)
|
||||
- 💄 Improve Checkbox `indeterminate` to enhance accessibility experience. [#51350](https://github.com/ant-design/ant-design/pull/51350) [@SpaNb4](https://github.com/SpaNb4)
|
||||
- 💄 Improve the `title` of the Empty preset svg image to improve accessibility experience. [#51368](https://github.com/ant-design/ant-design/pull/51368)
|
||||
|
||||
## 5.21.5
|
||||
|
||||
`2024-10-21`
|
||||
|
||||
- 🐞 Fix Cascader filter limitation not working when `limit` set to `false`. [#51263](https://github.com/ant-design/ant-design/pull/51263) [@dongbanban](https://github.com/dongbanban)
|
||||
- 🐞 Fix DatePicker disabled items cannot response mouse events bug. [#51294](https://github.com/ant-design/ant-design/pull/51294) [@ajenkins-mparticle](https://github.com/ajenkins-mparticle)
|
||||
- 🐞 Fix FloatButton menu problem what is difficult to click. [#51208](https://github.com/ant-design/ant-design/pull/51208) [@aojunhao123](https://github.com/aojunhao123)
|
||||
- 🐞 Fix QRCode `onRefresh` property not working properly. [#51315](https://github.com/ant-design/ant-design/pull/51315) [@kiner-tang](https://github.com/kiner-tang)
|
||||
- 🐞 Fix Typography links cannot be selected by user. [#51243](https://github.com/ant-design/ant-design/pull/51243) [@thinkasany](https://github.com/thinkasany)
|
||||
- 💄 Fix Badge incorrect token of texts. [#51252](https://github.com/ant-design/ant-design/pull/51252) [@Wxh16144](https://github.com/Wxh16144)
|
||||
- 💄 Fix Layout lost styles of collapse button. [#51313](https://github.com/ant-design/ant-design/pull/51313) [@aojunhao123](https://github.com/aojunhao123)
|
||||
- 🛠 Improve Button event handler declaration. [#42037](https://github.com/ant-design/ant-design/pull/42037) [@SohaibRaza](https://github.com/SohaibRaza)
|
||||
- 🛠 Improve Splitter style token semantic name. [#51223](https://github.com/ant-design/ant-design/pull/51223) [@wanpan11](https://github.com/wanpan11)
|
||||
|
||||
## 5.21.4
|
||||
|
||||
`2024-10-14`
|
||||
|
||||
- 🐞 Fixed Input.Search not applying the `hoverBorderColor/activeBorderColor` token for hover/active states. [#51226](https://github.com/ant-design/ant-design/pull/51226) [@iqingting](https://github.com/iqingting)
|
||||
- 🐞 Fix Tree icon align issue. [#51181](https://github.com/ant-design/ant-design/pull/51181) [@Meowu](https://github.com/Meowu)
|
||||
- 🐞 Fix Splitter occasionally shows unnecessary scrollbars in nested combinations. [#51169](https://github.com/ant-design/ant-design/pull/51169) [@zombieJ](https://github.com/zombieJ)
|
||||
- 💄 Modify Button `textHoverBg` hover background to `colorFillTertiary`. [#51187](https://github.com/ant-design/ant-design/pull/51187) [@coding-ice](https://github.com/coding-ice)
|
||||
- TypeScript
|
||||
- 🤖 Improve type of Switch `eventHandler`. [#51165](https://github.com/ant-design/ant-design/pull/51165) [@thinkasany](https://github.com/thinkasany)
|
||||
## 5.21.3
|
||||
|
||||
`2024-10-09`
|
||||
|
||||
- 💄 Added a scroll bar to Dropdown when having many items. [#51112](https://github.com/ant-design/ant-design/pull/51112) [@Cameron-Asdf](https://github.com/Cameron-Asdf)
|
||||
- Slider [#51150](https://github.com/ant-design/ant-design/pull/51150) [@yoyo837](https://github.com/yoyo837)
|
||||
- 🐞 Fix Slider issue where the `id` prop is not supported.
|
||||
- 🐞 Fix Slider to address the issue causing `useLayoutEffect does nothing on the server` warning when `extractStyle` is invoked.
|
||||
- 🐞 Fix ColorPicker with gradient mode, sometimes handle color will be force sync back to first handle color issue. [#51161](https://github.com/ant-design/ant-design/pull/51161) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 Fix Table `onChange` function receiving incorrect sorter value. [#51114](https://github.com/ant-design/ant-design/pull/51114) [@nathanlao](https://github.com/nathanlao)
|
||||
- Splitter
|
||||
- 🐞 Fix the issue about throw a warning when Splitter nested in a hidden tab panel. [#51109](https://github.com/ant-design/ant-design/pull/51109) [@kiner-tang](https://github.com/kiner-tang)
|
||||
- 🐞 Fix the issue about Splitter had unexpected gaps in Flex. [#51096](https://github.com/ant-design/ant-design/pull/51096) [@kiner-tang](https://github.com/kiner-tang)
|
||||
- 🐞 MISC: Restore `react` and `react-dom` peerDependencies. [#51079](https://github.com/ant-design/ant-design/pull/51079) [@chentsulin](https://github.com/chentsulin)
|
||||
- TypeScript
|
||||
- 🤖 Improve type of Slider `eventName`. [#51156](https://github.com/ant-design/ant-design/pull/51156) [@thinkasany](https://github.com/thinkasany)
|
||||
|
||||
## 5.21.2
|
||||
|
||||
`2024-10-01`
|
||||
|
||||
- 🐞 Revert [#49221](https://github.com/ant-design/ant-design/pull/49221) to fix Typography `copyable` icon align issue. [#51066](https://github.com/ant-design/ant-design/pull/51066) [@afc163](https://github.com/afc163)
|
||||
- 🐞 Fix Tabs flicker when browser zoom is enabled. [#51072](https://github.com/ant-design/ant-design/pull/51072) [@afc163](https://github.com/afc163)
|
||||
- 🐞 Fix Select incorrect `activeBorderColor` token when variant is filled. [#51054](https://github.com/ant-design/ant-design/pull/51054) [@coding-ice](https://github.com/coding-ice)
|
||||
- 🐞 Fixed Input.Search alignment issue between the input field and search button at different zoom levels. [#50926](https://github.com/ant-design/ant-design/pull/50926) [@nathanlao](https://github.com/nathanlao)
|
||||
- 💄 MISC: Tweak outline width of focus style from `4px` to `3px`. [#51069](https://github.com/ant-design/ant-design/pull/51069) [@afc163](https://github.com/afc163)
|
||||
- Splitter
|
||||
- 🐞 Fixed the issue with Splitter dragging abnormally on touch screen devices. [#51060](https://github.com/ant-design/ant-design/pull/51060) [@sakuraee](https://github.com/sakuraee)
|
||||
- 💄 Fixed Splitter.Panel style is invalid error. [#51032](https://github.com/ant-design/ant-design/pull/51032) [@wanpan11](https://github.com/wanpan11)
|
||||
- ⚡️ Remove TransButton in Table/Transfer/Typography. [#51068](https://github.com/ant-design/ant-design/pull/51068) [@afc163](https://github.com/afc163)
|
||||
|
||||
## 5.21.1
|
||||
|
||||
`2024-09-25`
|
||||
|
||||
- 🐞 Fix Button issue where `type="link"` incorrectly used `colorPrimary`. [#50962](https://github.com/ant-design/ant-design/pull/50962) [@coding-ice](https://github.com/coding-ice)
|
||||
- 🐞 Fix Button style class name weight issue that caused custom gradient styles to be overridden. [#50962](https://github.com/ant-design/ant-design/pull/50962) [@coding-ice](https://github.com/coding-ice)
|
||||
- 🐞 Fix Transfer width issue when customized as TableTransfer. [#50974](https://github.com/ant-design/ant-design/pull/50974) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🇹🇷 Add Turkish text for `filterCheckall` in Table component. [#51000](https://github.com/ant-design/ant-design/pull/51000) [@ytahirkose](https://github.com/ytahirkose)
|
||||
|
||||
## 5.21.0 🔥
|
||||
|
||||
`2024-09-22`
|
||||
|
||||
- 🔥 **Introduce the new Splitter component**, draggale split panel. [#50038](https://github.com/ant-design/ant-design/pull/50038) [@wanpan11](https://github.com/wanpan11)
|
||||
<img width="520" alt="Splitter" src="https://github.com/user-attachments/assets/25fc4e3c-1aa5-41bb-8f39-f34f7149e0f6">
|
||||
- Button
|
||||
- 🔥 Button supports `variant` and `color` properties for more combination styles. [#50051](https://github.com/ant-design/ant-design/pull/50051) [@coding-ice](https://github.com/coding-ice)
|
||||
<img width="420" alt="Button" src="https://github.com/user-attachments/assets/cd5cb7fb-25e8-445f-b217-7fdd4ae0f9b4">
|
||||
- 💄 Button adds `textColor`, `textHoverColor` and ` textActiveColor` tokens. [#47870](https://github.com/ant-design/ant-design/pull/47870) [@madocto](https://github.com/madocto)
|
||||
- FloatButton
|
||||
- 🆕 FloatButton supports `placement` property, allowing menus to pop up from multiple directions. [#50407](https://github.com/ant-design/ant-design/pull/50407) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
<img width="300" alt="float button" src="https://github.com/user-attachments/assets/4b53c0f6-7bdd-4e2a-91cc-2fb804f6e6d3" />
|
||||
- 🆕 FloatButton supports `htmlType` prop. [#50892](https://github.com/ant-design/ant-design/pull/50892) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- 💄 Unify FloatButton and FloatButton.Group button round style. [#50513](https://github.com/ant-design/ant-design/pull/50513) [@Layouwen](https://github.com/Layouwen)
|
||||
- 💄 Manage FloatButton's `z-index` with `useZIndex` to improve compatibility with other popup components. [#50311](https://github.com/ant-design/ant-design/pull/50311) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- Menu
|
||||
- 🆕 Menu.Item and Dropdown's `menu` supports `extra` prop now. [#50431](https://github.com/ant-design/ant-design/pull/50431) [@coding-ice](https://github.com/coding-ice)
|
||||
<img width="259" alt="menu extra" src="https://github.com/user-attachments/assets/fee57c43-b948-4f98-8a6b-0d94094a8a65">
|
||||
- 🐞 Fix Menu `popupStyle` not working on SubMenu. [#50922](https://github.com/ant-design/ant-design/pull/50922) [@Wxh16144](https://github.com/Wxh16144)
|
||||
- Table
|
||||
- 🆕 Table supports `minWidth` for columns. [#50416](https://github.com/ant-design/ant-design/pull/50416) [@linxianxi](https://github.com/linxianxi)
|
||||
- 🐞 Fix Table empty and shadow issues in virtual mode. [#50416](https://github.com/ant-design/ant-design/pull/50416) [@linxianxi](https://github.com/linxianxi)
|
||||
- 🐞 Fix Table column selection issue where deselection was not possible under certain circumstances. [#50746](https://github.com/ant-design/ant-design/pull/50746) [@Jarryxin](https://github.com/Jarryxin)
|
||||
- Input
|
||||
- 🆕 Input.OTP support `type` to help handle some case need number only. [#50811](https://github.com/ant-design/ant-design/pull/50811) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 Fix Select inside Input addon text color when Select is focused. [#50486](https://github.com/ant-design/ant-design/pull/50486) [@DDDDD12138](https://github.com/DDDDD12138)
|
||||
- Modal
|
||||
- ⌨️ Fix Modal throws warning `avoid using aria-hidden on a focused element or its ancestor`. [#50823](https://github.com/ant-design/ant-design/pull/50823) [@afc163](https://github.com/afc163)
|
||||
- 🆕 Modal supports `closable.disabled` prop now. [#50522](https://github.com/ant-design/ant-design/pull/50522) [@Ke1sy](https://github.com/Ke1sy)
|
||||
- Descriptions
|
||||
- 🐞 Fix Descriptions column is missing in some cases. [#50895](https://github.com/ant-design/ant-design/pull/50895) [@yezhonghu0503](https://github.com/yezhonghu0503)
|
||||
- 🐞 Revert [#49946](https://github.com/ant-design/ant-design/pull/49946) to fix the issue where the popup layer component inside Descriptions is being cut off. [#50891](https://github.com/ant-design/ant-design/pull/50891) [@afc163](https://github.com/afc163)
|
||||
- Upload
|
||||
- 🆕 Upload will pass `name` prop to `<input type="file" />`. [#50652](https://github.com/ant-design/ant-design/pull/50652) [@Wxh16144](https://github.com/Wxh16144)
|
||||
- 🆕 Upload `showUploadList.showXxxIcon` accept a function value now. [#50245](https://github.com/ant-design/ant-design/pull/50245) [@guoyunhe](https://github.com/guoyunhe)
|
||||
- ColorPicker
|
||||
- 🐞 Fix ColorPicker when type hex input may not get correct color with precision issue. [#50843](https://github.com/ant-design/ant-design/pull/50843) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 Adjust ColorPicker popup panel not lock by `value` to allow control mode with `onChangeComplete` scenarios. [#50785](https://github.com/ant-design/ant-design/pull/50785) [@zombieJ](https://github.com/zombieJ)
|
||||
- App
|
||||
- 🐞 Fixed App warn about `zIndex` too large when using the `modal` with having popup component method via `useApp`. [#50829](https://github.com/ant-design/ant-design/pull/50829) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 Fix App rtl style does not respect ConfigProvider direction prop. [#50246](https://github.com/ant-design/ant-design/pull/50246) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- Pagination
|
||||
- 🆕 Pagination `showSizeChanger` accepts Select props now. [#50952](https://github.com/ant-design/ant-design/pull/50952) [@afc163](https://github.com/afc163)
|
||||
- 💄 Remove Pagination default font family. [#50808](https://github.com/ant-design/ant-design/pull/50808) [@afc163](https://github.com/afc163)
|
||||
- Select
|
||||
- 💄 Add more tokens for Select to customize hover/focus style. [#50951](https://github.com/ant-design/ant-design/pull/50951) [@kiner-tang](https://github.com/kiner-tang)
|
||||
- 🐞 Fix Select search text overlap with arrow icon. [#50917](https://github.com/ant-design/ant-design/pull/50917) [@yezhonghu0503](https://github.com/yezhonghu0503)
|
||||
- 🐞 Fix Select extra background of clear icon when enable `allowClear` and `variant="filled"`. [#50916](https://github.com/ant-design/ant-design/pull/50916) [@thinkasany](https://github.com/thinkasany)
|
||||
- 🆕 Segmented adds `vertical` property and improves accessibility. [#50708](https://github.com/ant-design/ant-design/pull/50708) [@liangchaofei](https://github.com/liangchaofei)
|
||||
<img width="72" alt="Segmented vertical demo" src="https://github.com/user-attachments/assets/c1b0f971-9966-48d4-b641-4fd476c59513">
|
||||
- 🆕 Radio.Group supports `block` prop now. [#50828](https://github.com/ant-design/ant-design/pull/50828) [@yuanliu147](https://github.com/yuanliu147)
|
||||
- 🆕 ConfigProvider supports configuring the `className` and `style` properties of the Splitter component. [#50855](https://github.com/ant-design/ant-design/pull/50855) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- 🆕 Image add `onActive` to `toolbarRender` for toggling images . [#50812](https://github.com/ant-design/ant-design/pull/50812) [@madocto](https://github.com/madocto)
|
||||
- 🆕 Add ref on List component. [#50772](https://github.com/ant-design/ant-design/pull/50772) [@Asanio06](https://github.com/Asanio06)
|
||||
- 🆕 Collapse support `classNames` and `styles` for semantic style customization. [#50557](https://github.com/ant-design/ant-design/pull/50557) [@wanpan11](https://github.com/wanpan11)
|
||||
- 💄 Make Skeleton.Node custom node by remove it's default icon children. [#50278](https://github.com/ant-design/ant-design/pull/50278) [@afc163](https://github.com/afc163)
|
||||
- 🐞 Fix Layout.Sider can not modify theme when used alone. [#50780](https://github.com/ant-design/ant-design/pull/50780) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 Fix Typography `copyable` with array `children` has additional `,` string issue. [#50813](https://github.com/ant-design/ant-design/pull/50813) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 Fix Tour where long title will overlap with close button. [#50942](https://github.com/ant-design/ant-design/pull/50942) [@kiner-tang](https://github.com/kiner-tang)
|
||||
- 🌐 Localization
|
||||
- 🇯🇵 Added `ja_JP` locale for DatePicker's `shortWeekDays` and `shortMonths` text. [#50893](https://github.com/ant-design/ant-design/pull/50893) [@harapeko](https://github.com/harapeko)
|
||||
- 🇪🇬 Added Arabic `ar_EG` text for Image preview feature. [#50851](https://github.com/ant-design/ant-design/pull/50851) [@nathanlao](https://github.com/nathanlao)
|
||||
- 🇬🇷 Added Greek text for the Form component. [#50825](https://github.com/ant-design/ant-design/pull/50825) [@nathanlao](https://github.com/nathanlao)
|
||||
- 🇪🇸 Added Spanish `es_ES` text for the Tour component. [#50805](https://github.com/ant-design/ant-design/pull/50805) [@thinkasany](https://github.com/thinkasany)
|
||||
- TypeScript
|
||||
- 🤖 Checkbox adds onFocus` and `onBlur` in type definition. [#50842](https://github.com/ant-design/ant-design/pull/50842) [@huiliangShen](https://github.com/huiliangShen)
|
||||
- 🤖 Fix Badge property type definition to support passing mouse events. [#50774](https://github.com/ant-design/ant-design/pull/50774) [@yuanliu147](https://github.com/yuanliu147)
|
||||
|
||||
## 5.20.6
|
||||
|
||||
`2024-09-09`
|
||||
|
||||
- 🐞 Improve Menu collapse animation smoothness. [#50751](https://github.com/ant-design/ant-design/pull/50751) [@afc163](https://github.com/afc163)
|
||||
- 🐞 Fix Table cell overflow bug if edit with virtual scroll. [#50737](https://github.com/ant-design/ant-design/pull/50737) [@huiliangShen](https://github.com/huiliangShen)
|
||||
- 🐞 Fix Input.Search button radius not changing with `size`. [#50734](https://github.com/ant-design/ant-design/pull/50734) [@afc163](https://github.com/afc163)
|
||||
- 🐞 Fix Form password still can be toggle show/hide even if disabled. [#50616](https://github.com/ant-design/ant-design/pull/50616) [@Jarryxin](https://github.com/Jarryxin)
|
||||
- 🐞 Revert [#49899](https://github.com/ant-design/ant-design/pull/49899) to fix wrap behavior for Dropdown, and re-fix wrap when out of screen edge. [#50718](https://github.com/ant-design/ant-design/pull/50718) [@afc163](https://github.com/afc163)
|
||||
- 💄 Fix Badge background transition when mouse out. [#50743](https://github.com/ant-design/ant-design/pull/50743) [@coding-ice](https://github.com/coding-ice)
|
||||
- TypeScript
|
||||
- 🤖 Fix Collapse types for `onChange` arguments. [#50754](https://github.com/ant-design/ant-design/pull/50754) [@yuanliu147](https://github.com/yuanliu147)
|
||||
|
||||
## 5.20.5
|
||||
|
||||
`2024-09-03`
|
||||
|
||||
- 🛠 Adjust Tree & TreeSelect `defaultExpandAll` logic to only add internal `expandedKeys` which `treeNode` has children instead to avoid perf issue when with large data or `loadData` case. [#50689](https://github.com/ant-design/ant-design/pull/50689) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 Fix Cascader not show parent option in search when using `multiple`. [#50689](https://github.com/ant-design/ant-design/pull/50689)
|
||||
- 🐞 Fix Typography `ellipsis.tooltip.title` with ReactNode will cause dead loop. [#50688](https://github.com/ant-design/ant-design/pull/50688) [@zombieJ](https://github.com/zombieJ)
|
||||
|
||||
## 5.20.4
|
||||
|
||||
`2024-09-02`
|
||||
|
||||
- Menu
|
||||
- 🐞 Fix Menu token `itemPaddingInline inoperative` not working. [#50663](https://github.com/ant-design/ant-design/pull/50663) [@coding-ice](https://github.com/coding-ice)
|
||||
- 🐞 Fix Menu missing `hover` transition style. [#50624](https://github.com/ant-design/ant-design/pull/50624) [@afc163](https://github.com/afc163)
|
||||
- 💄 Badge add transition effect to count node. [#50607](https://github.com/ant-design/ant-design/pull/50607) [@afc163](https://github.com/afc163)
|
||||
- 💄 Fix Table column header move with unexpected transition. [#50605](https://github.com/ant-design/ant-design/pull/50605) [@afc163](https://github.com/afc163)
|
||||
- 🛠 Refactor Typography code to optimize internal logic. [#50561](https://github.com/ant-design/ant-design/pull/50561) [@afc163](https://github.com/afc163)
|
||||
- 🐞 Disable the Rate component within Form.Item when the form is disabled. [#50594](https://github.com/ant-design/ant-design/pull/50594) [@nikzanda](https://github.com/nikzanda)
|
||||
- 🌐 Patch tr_TR `Transfer.deselectAll` locale. [#50672](https://github.com/ant-design/ant-design/pull/50672) [@coding-ice](https://github.com/coding-ice)
|
||||
|
||||
## 5.20.3
|
||||
|
||||
`2024-08-26`
|
||||
@ -1723,7 +2118,7 @@ tag: vVERSION
|
||||
- 💄 Adjust Select, TreeSelect, Cascader always show the `arrow` by default when multiple. [#41028](https://github.com/ant-design/ant-design/pull/41028)
|
||||
- 🐞 Fix Form `Form.Item.useStatus` problem with sever-side-rendering. [#40977](https://github.com/ant-design/ant-design/pull/40977) [@AndyBoat](https://github.com/AndyBoat)
|
||||
- 🐞 MISC: Fix arrow shape in some components. [#40971](https://github.com/ant-design/ant-design/pull/40971)
|
||||
- 🐞 Fix Layout throw `React does not recognize the `suffixCls` prop on a DOM element` warning. [#40969](https://github.com/ant-design/ant-design/pull/40969)
|
||||
- 🐞 Fix Layout throw "React does not recognize the `suffixCls` prop on a DOM element" warning. [#40969](https://github.com/ant-design/ant-design/pull/40969)
|
||||
- 🐞 Fix Watermark that text will be displayed when the picture loads abnormally. [#40770](https://github.com/ant-design/ant-design/pull/40770) [@OriginRing](https://github.com/OriginRing)
|
||||
- 🐞 Image support flip function in preview mode. Fix Image `fallback` when used in ssr. [#40660](https://github.com/ant-design/ant-design/pull/40660)
|
||||
- 🐞 Fix Typography component is not centered in the Select component. [#40422](https://github.com/ant-design/ant-design/pull/40422) [@Yuiai01](https://github.com/Yuiai01)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user