mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-27 12:39:49 +08:00
Merge branch 'feature' into fix/remove-duplicate-ant-upload-classname-from-parent-to-child
This commit is contained in:
commit
fd10198641
@ -1,35 +0,0 @@
|
||||
# Use the latest 2.1 version of CircleCI pipeline process engine.
|
||||
# See: https://circleci.com/docs/2.0/configuration-reference
|
||||
version: 2.1
|
||||
|
||||
# Define a job to be invoked later in a workflow.
|
||||
# See: https://circleci.com/docs/2.0/configuration-reference/#jobs
|
||||
jobs:
|
||||
test-argos-ci:
|
||||
docker:
|
||||
- image: cimg/node:21.1-browsers
|
||||
environment:
|
||||
NODE_OPTIONS: --openssl-legacy-provider
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Install node_modules
|
||||
command: yarn
|
||||
- run:
|
||||
name: Build dist file
|
||||
command: npm run dist:esbuild
|
||||
- run:
|
||||
name: Run image screenshot tests
|
||||
command: npm run test-image
|
||||
- run:
|
||||
name: Upload screenshots to Argos CI
|
||||
command: npm run argos
|
||||
# The resource_class feature allows configuring CPU and RAM resources for each job. Different resource classes are available for different executors. https://circleci.com/docs/2.0/configuration-reference/#resourceclass
|
||||
resource_class: large
|
||||
|
||||
# Invoke jobs via workflows
|
||||
# See: https://circleci.com/docs/2.0/configuration-reference/#workflows
|
||||
workflows:
|
||||
test-argos-ci-workflow:
|
||||
jobs:
|
||||
- test-argos-ci
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"installCommand": "npm-install",
|
||||
"sandboxes": ["antd-reproduction-template-forked-jyh2k9"],
|
||||
"node": "18"
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
.demo-logo {
|
||||
width: 120px;
|
||||
min-width: 120px;
|
||||
height: 32px;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 6px;
|
||||
margin-inline-end: 24px;
|
||||
}
|
||||
|
||||
.demo-logo-vertical {
|
||||
|
@ -68,6 +68,7 @@ const useThemeAnimation = () => {
|
||||
if (!(event && typeof document.startViewTransition === 'function')) {
|
||||
return;
|
||||
}
|
||||
const time = Date.now();
|
||||
const x = event.clientX;
|
||||
const y = event.clientY;
|
||||
const endRadius = Math.hypot(Math.max(x, innerWidth - x), Math.max(y, innerHeight - y));
|
||||
@ -98,6 +99,7 @@ const useThemeAnimation = () => {
|
||||
root.classList.add(isDark ? 'light' : 'dark');
|
||||
})
|
||||
.ready.then(() => {
|
||||
console.log(`Theme transition finished in ${Date.now() - time}ms`);
|
||||
const clipPath = [
|
||||
`circle(0px at ${x}px ${y}px)`,
|
||||
`circle(${endRadius}px at ${x}px ${y}px)`,
|
||||
|
@ -1,19 +1,19 @@
|
||||
import * as React from 'react';
|
||||
import { createStyles, css, useTheme } from 'antd-style';
|
||||
import classNames from 'classnames';
|
||||
import type { FC } from 'react';
|
||||
import { useContext } from 'react';
|
||||
import { Typography, Skeleton, Carousel } from 'antd';
|
||||
import type { Extra, Icon } from './util';
|
||||
import SiteContext from '../../../theme/slots/SiteContext';
|
||||
import { getCarouselStyle, useSiteData } from './util';
|
||||
import useLocale from '../../../hooks/useLocale';
|
||||
import { Badge, Carousel, Skeleton, Typography } from 'antd';
|
||||
import { createStyles, useTheme } from 'antd-style';
|
||||
import classNames from 'classnames';
|
||||
|
||||
const useStyle = createStyles(({ token }) => {
|
||||
import useLocale from '../../../hooks/useLocale';
|
||||
import SiteContext from '../../../theme/slots/SiteContext';
|
||||
import type { Extra, Icon } from './util';
|
||||
import { getCarouselStyle, useSiteData } from './util';
|
||||
|
||||
const useStyle = createStyles(({ token, css, cx }) => {
|
||||
const { carousel } = getCarouselStyle();
|
||||
|
||||
return {
|
||||
itemBase: css`
|
||||
const itemBase = css`
|
||||
display: flex;
|
||||
flex: 1 1 0;
|
||||
flex-direction: column;
|
||||
@ -25,9 +25,17 @@ const useStyle = createStyles(({ token }) => {
|
||||
transition: all ${token.motionDurationSlow};
|
||||
padding-block: ${token.paddingMD}px;
|
||||
padding-inline: ${token.paddingLG}px;
|
||||
box-sizing: border-box;
|
||||
`;
|
||||
|
||||
return {
|
||||
itemBase,
|
||||
ribbon: css`
|
||||
& > .${cx(itemBase)} {
|
||||
height: 100%;
|
||||
}
|
||||
`,
|
||||
cardItem: css`
|
||||
width: 33%;
|
||||
&:hover {
|
||||
box-shadow: ${token.boxShadowCard};
|
||||
}
|
||||
@ -45,6 +53,9 @@ const useStyle = createStyles(({ token }) => {
|
||||
column-gap: ${token.paddingMD * 2}px;
|
||||
align-items: stretch;
|
||||
text-align: start;
|
||||
> * {
|
||||
width: calc((100% - ${token.marginXXL * 2}px) / 3);
|
||||
}
|
||||
`,
|
||||
carousel,
|
||||
};
|
||||
@ -56,7 +67,7 @@ interface RecommendItemProps {
|
||||
icons: Icon[];
|
||||
className?: string;
|
||||
}
|
||||
const RecommendItem = ({ extra, index, icons, className }: RecommendItemProps) => {
|
||||
const RecommendItem: React.FC<RecommendItemProps> = ({ extra, index, icons, className }) => {
|
||||
const token = useTheme();
|
||||
const { styles } = useStyle();
|
||||
|
||||
@ -65,7 +76,7 @@ const RecommendItem = ({ extra, index, icons, className }: RecommendItemProps) =
|
||||
}
|
||||
const icon = icons.find((i) => i.name === extra.source);
|
||||
|
||||
return (
|
||||
const card = (
|
||||
<a
|
||||
key={extra?.title}
|
||||
href={extra.href}
|
||||
@ -83,6 +94,16 @@ const RecommendItem = ({ extra, index, icons, className }: RecommendItemProps) =
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
|
||||
if (index === 0) {
|
||||
return (
|
||||
<Badge.Ribbon text="HOT" color="red" rootClassName={styles.ribbon}>
|
||||
{card}
|
||||
</Badge.Ribbon>
|
||||
);
|
||||
}
|
||||
|
||||
return card;
|
||||
};
|
||||
|
||||
export const BannerRecommendsFallback: FC = () => {
|
||||
@ -93,8 +114,8 @@ export const BannerRecommendsFallback: FC = () => {
|
||||
|
||||
return isMobile ? (
|
||||
<Carousel className={styles.carousel}>
|
||||
{list.map((extra, index) => (
|
||||
<div key={index}>
|
||||
{list.map((_, index) => (
|
||||
<div key={index} className={styles.itemBase}>
|
||||
<Skeleton active style={{ padding: '0 24px' }} />
|
||||
</div>
|
||||
))}
|
||||
@ -102,20 +123,26 @@ export const BannerRecommendsFallback: FC = () => {
|
||||
) : (
|
||||
<div className={styles.container}>
|
||||
{list.map((_, index) => (
|
||||
<Skeleton key={index} active />
|
||||
<div key={index} className={styles.itemBase}>
|
||||
<Skeleton active />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default function BannerRecommends() {
|
||||
const BannerRecommends: React.FC = () => {
|
||||
const { styles } = useStyle();
|
||||
const [, lang] = useLocale();
|
||||
const { isMobile } = React.useContext(SiteContext);
|
||||
const data = useSiteData();
|
||||
const extras = data?.extras?.[lang];
|
||||
const icons = data?.icons;
|
||||
const first3 = extras.length === 0 ? Array(3).fill(null) : extras.slice(0, 3);
|
||||
const icons = data?.icons || [];
|
||||
const first3 = !extras || extras.length === 0 ? Array(3).fill(null) : extras.slice(0, 3);
|
||||
|
||||
if (!data) {
|
||||
return <BannerRecommendsFallback />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -147,4 +174,6 @@ export default function BannerRecommends() {
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default BannerRecommends;
|
||||
|
@ -17,9 +17,9 @@ import {
|
||||
Tooltip,
|
||||
} from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import useLocale from '../../../../hooks/useLocale';
|
||||
import Tilt from './Tilt';
|
||||
|
||||
const { _InternalPanelDoNotUseOrYouWillBeFired: ModalPanel } = Modal;
|
||||
const { _InternalPanelDoNotUseOrYouWillBeFired: InternalTooltip } = Tooltip;
|
||||
@ -72,16 +72,14 @@ const locales = {
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => {
|
||||
const gap = token.padding;
|
||||
|
||||
return {
|
||||
holder: css`
|
||||
width: 500px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: ${gap}px;
|
||||
opacity: 0.65;
|
||||
opacity: 0.8;
|
||||
`,
|
||||
|
||||
flex: css`
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
@ -105,25 +103,16 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
};
|
||||
});
|
||||
|
||||
export interface ComponentsBlockProps {
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
const ComponentsBlock: React.FC<ComponentsBlockProps> = (props) => {
|
||||
const { className, style } = props;
|
||||
|
||||
const ComponentsBlock: React.FC = () => {
|
||||
const [locale] = useLocale(locales);
|
||||
const { styles } = useStyle();
|
||||
|
||||
return (
|
||||
<div className={classNames(className, styles.holder)} style={style}>
|
||||
<Tilt options={{ max: 20, glare: true, scale: 1 }} className={styles.holder}>
|
||||
<ModalPanel title="Ant Design 5.0" width="100%">
|
||||
{locale.text}
|
||||
</ModalPanel>
|
||||
|
||||
<Alert message={locale.infoText} type="info" />
|
||||
|
||||
{/* Line */}
|
||||
<div className={styles.flex}>
|
||||
<ColorPicker style={{ flex: 'none' }} />
|
||||
@ -139,57 +128,34 @@ const ComponentsBlock: React.FC<ComponentsBlockProps> = (props) => {
|
||||
{locale.dropdown}
|
||||
</Dropdown.Button>
|
||||
</div>
|
||||
|
||||
<Select
|
||||
style={{ flex: 'auto' }}
|
||||
mode="multiple"
|
||||
maxTagCount="responsive"
|
||||
defaultValue={[{ value: 'apple' }, { value: 'banana' }]}
|
||||
options={[
|
||||
{
|
||||
value: 'apple',
|
||||
label: locale.apple,
|
||||
},
|
||||
{
|
||||
value: 'banana',
|
||||
label: locale.banana,
|
||||
},
|
||||
{
|
||||
value: 'orange',
|
||||
label: locale.orange,
|
||||
},
|
||||
{
|
||||
value: 'watermelon',
|
||||
label: locale.watermelon,
|
||||
},
|
||||
{ value: 'apple', label: locale.apple },
|
||||
{ value: 'banana', label: locale.banana },
|
||||
{ value: 'orange', label: locale.orange },
|
||||
{ value: 'watermelon', label: locale.watermelon },
|
||||
]}
|
||||
/>
|
||||
|
||||
<Input style={{ flex: 'none', width: 120 }} />
|
||||
</div>
|
||||
|
||||
<Progress
|
||||
style={{ margin: 0 }}
|
||||
percent={100}
|
||||
strokeColor={{ '0%': '#108ee9', '100%': '#87d068' }}
|
||||
/>
|
||||
<Progress style={{ margin: 0 }} percent={33} status="exception" />
|
||||
|
||||
<Steps
|
||||
current={1}
|
||||
items={[
|
||||
{
|
||||
title: locale.finished,
|
||||
},
|
||||
{
|
||||
title: locale.inProgress,
|
||||
},
|
||||
{
|
||||
title: locale.waiting,
|
||||
},
|
||||
{ title: locale.finished },
|
||||
{ title: locale.inProgress },
|
||||
{ title: locale.waiting },
|
||||
]}
|
||||
/>
|
||||
|
||||
{/* Line */}
|
||||
<div className={styles.block}>
|
||||
<Slider
|
||||
@ -200,16 +166,13 @@ const ComponentsBlock: React.FC<ComponentsBlockProps> = (props) => {
|
||||
26: '26°C',
|
||||
37: '37°C',
|
||||
100: {
|
||||
style: {
|
||||
color: '#f50',
|
||||
},
|
||||
style: { color: '#f50' },
|
||||
label: <strong>100°C</strong>,
|
||||
},
|
||||
}}
|
||||
defaultValue={[26, 37]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Line */}
|
||||
<div className={styles.flex}>
|
||||
<Button className={styles.ptg_20} type="primary">
|
||||
@ -226,7 +189,6 @@ const ComponentsBlock: React.FC<ComponentsBlockProps> = (props) => {
|
||||
{locale.icon}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Line */}
|
||||
<div className={styles.block}>
|
||||
<div className={styles.flex}>
|
||||
@ -236,7 +198,6 @@ const ComponentsBlock: React.FC<ComponentsBlockProps> = (props) => {
|
||||
checkedChildren={<CheckOutlined />}
|
||||
unCheckedChildren={<CloseOutlined />}
|
||||
/>
|
||||
|
||||
<Checkbox.Group
|
||||
className={styles.ptg_none}
|
||||
options={[locale.apple, locale.banana, locale.orange]}
|
||||
@ -244,15 +205,12 @@ const ComponentsBlock: React.FC<ComponentsBlockProps> = (props) => {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<InternalMessage content={locale.release} type="success" />
|
||||
</div>
|
||||
|
||||
<InternalTooltip title={locale.hello} placement="topLeft" className={styles.noMargin} />
|
||||
|
||||
<Alert message="Ant Design love you!" type="success" />
|
||||
</div>
|
||||
</Tilt>
|
||||
);
|
||||
};
|
||||
|
||||
|
34
.dumi/pages/index/components/PreviewBanner/Tilt.tsx
Normal file
34
.dumi/pages/index/components/PreviewBanner/Tilt.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import VanillaTilt from 'vanilla-tilt';
|
||||
import type { TiltOptions } from 'vanilla-tilt';
|
||||
|
||||
interface TiltProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
options?: TiltOptions;
|
||||
}
|
||||
|
||||
// https://micku7zu.github.io/vanilla-tilt.js/index.html
|
||||
const defaultTiltOptions: TiltOptions = {
|
||||
scale: 1.02,
|
||||
max: 8,
|
||||
speed: 1500,
|
||||
glare: true,
|
||||
'max-glare': 0.8,
|
||||
};
|
||||
|
||||
const Tilt: React.FC<TiltProps> = ({ options, ...props }) => {
|
||||
const node = useRef<HTMLDivElement>(null);
|
||||
useEffect(() => {
|
||||
if (node.current) {
|
||||
VanillaTilt.init(node.current, {
|
||||
...defaultTiltOptions,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
return () => {
|
||||
(node.current as any)?.vanillaTilt.destroy();
|
||||
};
|
||||
}, []);
|
||||
return <div ref={node} {...props} />;
|
||||
};
|
||||
|
||||
export default Tilt;
|
@ -7,7 +7,6 @@ import useLocale from '../../../../hooks/useLocale';
|
||||
import SiteContext from '../../../../theme/slots/SiteContext';
|
||||
import * as utils from '../../../../theme/utils';
|
||||
import { GroupMask } from '../Group';
|
||||
import useMouseTransform from './useMouseTransform';
|
||||
|
||||
const ComponentsBlock = React.lazy(() => import('./ComponentsBlock'));
|
||||
|
||||
@ -28,7 +27,6 @@ const locales = {
|
||||
const useStyle = () => {
|
||||
const { direction } = React.useContext(ConfigProvider.ConfigContext);
|
||||
const isRTL = direction === 'rtl';
|
||||
|
||||
return createStyles(({ token, css, cx }) => {
|
||||
const textShadow = `0 0 3px ${token.colorBgContainer}`;
|
||||
|
||||
@ -37,12 +35,14 @@ const useStyle = () => {
|
||||
inset: 0;
|
||||
backdrop-filter: blur(4px);
|
||||
opacity: 1;
|
||||
transition: opacity 1s ease;
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
transition: all 1s ease;
|
||||
pointer-events: none;
|
||||
`);
|
||||
|
||||
return {
|
||||
holder: css`
|
||||
height: 520px;
|
||||
height: 640px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
@ -94,6 +94,7 @@ const useStyle = () => {
|
||||
|
||||
child: css`
|
||||
position: relative;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
`,
|
||||
};
|
||||
@ -114,10 +115,8 @@ const PreviewBanner: React.FC<PreviewBannerProps> = (props) => {
|
||||
const { pathname, search } = useLocation();
|
||||
const isZhCN = utils.isZhCN(pathname);
|
||||
|
||||
const [componentsBlockStyle, mouseEvents] = useMouseTransform();
|
||||
|
||||
return (
|
||||
<GroupMask {...mouseEvents}>
|
||||
<GroupMask>
|
||||
{/* Image Left Top */}
|
||||
<img
|
||||
style={{ position: 'absolute', left: isMobile ? -120 : 0, top: 0, width: 240 }}
|
||||
@ -134,7 +133,11 @@ const PreviewBanner: React.FC<PreviewBannerProps> = (props) => {
|
||||
<div className={styles.holder}>
|
||||
{/* Mobile not show the component preview */}
|
||||
<Suspense fallback={null}>
|
||||
{!isMobile && <ComponentsBlock className={styles.block} style={componentsBlockStyle} />}
|
||||
{isMobile ? null : (
|
||||
<div className={styles.block}>
|
||||
<ComponentsBlock />
|
||||
</div>
|
||||
)}
|
||||
</Suspense>
|
||||
<div className={styles.mask} />
|
||||
|
||||
|
@ -1,73 +0,0 @@
|
||||
import React, { startTransition } from 'react';
|
||||
import { ConfigProvider } from 'antd';
|
||||
|
||||
const getTransformRotateStyle = (
|
||||
event: React.MouseEvent<HTMLDivElement, MouseEvent>,
|
||||
currentTarget: EventTarget & HTMLDivElement,
|
||||
multiple: number,
|
||||
isRTL: boolean,
|
||||
): string => {
|
||||
const box = currentTarget?.getBoundingClientRect();
|
||||
const calcX = -(event.clientY - box.y - box.height / 2) / multiple;
|
||||
const calcY = (event.clientX - box.x - box.width / 2) / multiple;
|
||||
return isRTL
|
||||
? `rotate3d(${24 + calcX}, ${83 + calcY}, -45, 57deg)`
|
||||
: `rotate3d(${24 + calcX}, ${-83 + calcY}, 45, 57deg)`;
|
||||
};
|
||||
|
||||
const useMouseTransform = ({ transitionDuration = 500, multiple = 36 } = {}) => {
|
||||
const [componentsBlockStyle, setComponentsBlockStyle] = React.useState<React.CSSProperties>({});
|
||||
|
||||
const { direction } = React.useContext(ConfigProvider.ConfigContext);
|
||||
|
||||
const isRTL = direction === 'rtl';
|
||||
|
||||
const onMouseMove: React.MouseEventHandler<HTMLDivElement> = (event) => {
|
||||
const { currentTarget } = event;
|
||||
startTransition(() => {
|
||||
setComponentsBlockStyle((style) => ({
|
||||
...style,
|
||||
transform: getTransformRotateStyle(event, currentTarget, multiple, isRTL),
|
||||
}));
|
||||
});
|
||||
};
|
||||
|
||||
const onMouseEnter: React.MouseEventHandler<HTMLDivElement> = () => {
|
||||
startTransition(() => {
|
||||
setComponentsBlockStyle((style) => ({
|
||||
...style,
|
||||
transition: `transform ${transitionDuration / 1000}s`,
|
||||
}));
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
startTransition(() => {
|
||||
setComponentsBlockStyle((style) => ({
|
||||
...style,
|
||||
transition: '',
|
||||
}));
|
||||
});
|
||||
}, transitionDuration);
|
||||
};
|
||||
|
||||
const onMouseLeave: React.MouseEventHandler<HTMLDivElement> = () => {
|
||||
startTransition(() => {
|
||||
setComponentsBlockStyle((style) => ({
|
||||
...style,
|
||||
transition: `transform ${transitionDuration / 1000}s`,
|
||||
transform: '',
|
||||
}));
|
||||
});
|
||||
};
|
||||
|
||||
return [
|
||||
componentsBlockStyle,
|
||||
{
|
||||
onMouseMove,
|
||||
onMouseEnter,
|
||||
onMouseLeave,
|
||||
},
|
||||
] as const;
|
||||
};
|
||||
|
||||
export default useMouseTransform;
|
@ -1,99 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import { createStyles, css, useTheme } from 'antd-style';
|
||||
import { Row, Col, Typography } from 'antd';
|
||||
import type { Recommendation } from './util';
|
||||
|
||||
const useStyle = createStyles(({ token }) => ({
|
||||
card: css`
|
||||
height: 300px;
|
||||
background-size: 100% 100%;
|
||||
background-position: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
background: linear-gradient(
|
||||
rgba(0, 0, 0, 0) 0%,
|
||||
rgba(0, 0, 0, 0.25) 40%,
|
||||
rgba(0, 0, 0, 0.65) 100%
|
||||
);
|
||||
opacity: 0.3;
|
||||
transition: all 0.5s;
|
||||
content: '';
|
||||
pointer-events: none;
|
||||
inset: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&:before {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.intro {
|
||||
transform: translate3d(0, 0, 0);
|
||||
|
||||
h4${token.antCls}-typography {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.intro {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
transform: translate3d(0, 100%, 0);
|
||||
transition: all ${token.motionDurationSlow};
|
||||
|
||||
${token.antCls}-typography {
|
||||
margin: 0;
|
||||
color: #fff;
|
||||
font-weight: normal;
|
||||
text-shadow: 0 0 1px rgba(0, 0, 0, 0.5);
|
||||
transition: all ${token.motionDurationSlow};
|
||||
}
|
||||
|
||||
h4${token.antCls}-typography {
|
||||
position: absolute;
|
||||
padding: 0 ${token.paddingMD}px ${token.paddingMD}px;
|
||||
transform: translate3d(0, -100%, 0);
|
||||
}
|
||||
|
||||
div${token.antCls}-typography {
|
||||
padding: ${token.paddingXS}px ${token.paddingMD}px ${token.paddingLG}px;
|
||||
}
|
||||
}
|
||||
`,
|
||||
}));
|
||||
|
||||
export interface RecommendsProps {
|
||||
recommendations?: Recommendation[];
|
||||
}
|
||||
|
||||
export default function Recommends({ recommendations = [] }: RecommendsProps) {
|
||||
const token = useTheme();
|
||||
const { styles } = useStyle();
|
||||
|
||||
return (
|
||||
<Row gutter={token.marginLG}>
|
||||
{new Array(3).fill(null).map((_, index) => {
|
||||
const data = recommendations[index];
|
||||
|
||||
return (
|
||||
<Col key={index} span={8}>
|
||||
{data ? (
|
||||
<div className={styles.card} style={{ backgroundImage: `url(${data.img})` }}>
|
||||
<div className="intro">
|
||||
<Typography.Title level={4}>{data?.title}</Typography.Title>
|
||||
<Typography.Paragraph>{data.description}</Typography.Paragraph>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</Col>
|
||||
);
|
||||
})}
|
||||
</Row>
|
||||
);
|
||||
}
|
@ -403,13 +403,12 @@ export default function Theme() {
|
||||
...themeToken,
|
||||
colorPrimary: colorPrimaryValue,
|
||||
},
|
||||
hashed: true,
|
||||
algorithm: algorithmFn,
|
||||
components: {
|
||||
Layout: isLight
|
||||
? {
|
||||
colorBgHeader: 'transparent',
|
||||
colorBgBody: 'transparent',
|
||||
headerBg: 'transparent',
|
||||
bodyBg: 'transparent',
|
||||
}
|
||||
: {
|
||||
// colorBgBody: 'transparent',
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { css } from 'antd-style';
|
||||
import useFetch from '../../../hooks/useFetch';
|
||||
import { useEffect, useState } from 'react';
|
||||
import fetch from 'cross-fetch';
|
||||
|
||||
export interface Author {
|
||||
avatar: string;
|
||||
@ -80,8 +81,18 @@ export function preLoad(list: string[]) {
|
||||
}
|
||||
}
|
||||
|
||||
export function useSiteData(): Partial<SiteData> {
|
||||
return useFetch('https://render.alipay.com/p/h5data/antd4-config_website-h5data.json');
|
||||
export function useSiteData(): Partial<SiteData> | undefined {
|
||||
const [data, setData] = useState<SiteData | undefined>(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
fetch('https://render.alipay.com/p/h5data/antd4-config_website-h5data.json').then(
|
||||
async (res) => {
|
||||
setData(await res.json());
|
||||
},
|
||||
);
|
||||
}, []);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
export const getCarouselStyle = () => ({
|
||||
|
@ -4,7 +4,7 @@ import { createStyles, css } from 'antd-style';
|
||||
|
||||
import useDark from '../../hooks/useDark';
|
||||
import useLocale from '../../hooks/useLocale';
|
||||
// import BannerRecommends, { BannerRecommendsFallback } from './components/BannerRecommends';
|
||||
import BannerRecommends from './components/BannerRecommends';
|
||||
import PreviewBanner from './components/PreviewBanner';
|
||||
import Group from './components/Group';
|
||||
|
||||
@ -46,10 +46,7 @@ const Homepage: React.FC = () => {
|
||||
return (
|
||||
<section>
|
||||
<PreviewBanner>
|
||||
{/* 文档很久没更新了,先藏起来 */}
|
||||
{/* <Suspense fallback={<BannerRecommendsFallback />}>
|
||||
<BannerRecommends />
|
||||
</Suspense> */}
|
||||
</PreviewBanner>
|
||||
|
||||
<div>
|
||||
|
@ -1,13 +1,26 @@
|
||||
import { RightOutlined, LinkOutlined, QuestionCircleOutlined } from '@ant-design/icons';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import { LinkOutlined, QuestionCircleOutlined, RightOutlined } from '@ant-design/icons';
|
||||
import { ConfigProvider, Popover, Table, Typography } from 'antd';
|
||||
import { createStyles, css, useTheme } from 'antd-style';
|
||||
import { getDesignToken } from 'antd-token-previewer';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import tokenMeta from 'antd/es/version/token-meta.json';
|
||||
import tokenData from 'antd/es/version/token.json';
|
||||
import { ConfigProvider, Table, Popover, Typography } from 'antd';
|
||||
|
||||
import useLocale from '../../../hooks/useLocale';
|
||||
import { useColumns } from '../TokenTable';
|
||||
|
||||
const compare = (token1: string, token2: string) => {
|
||||
const hasColor1 = token1.toLowerCase().includes('color');
|
||||
const hasColor2 = token2.toLowerCase().includes('color');
|
||||
if (hasColor1 && !hasColor2) {
|
||||
return -1;
|
||||
}
|
||||
if (!hasColor1 && hasColor2) {
|
||||
return 1;
|
||||
}
|
||||
return token1 < token2 ? -1 : 1;
|
||||
};
|
||||
|
||||
const defaultToken = getDesignToken();
|
||||
|
||||
const locales = {
|
||||
@ -18,6 +31,8 @@ const locales = {
|
||||
value: '默认值',
|
||||
componentToken: '组件 Token',
|
||||
globalToken: '全局 Token',
|
||||
componentComment: '这里是你的组件 token',
|
||||
globalComment: '这里是你的全局 token',
|
||||
help: '如何定制?',
|
||||
customizeTokenLink: '/docs/react/customize-theme-cn#修改主题变量',
|
||||
customizeComponentTokenLink: '/docs/react/customize-theme-cn#修改组件变量',
|
||||
@ -29,6 +44,8 @@ const locales = {
|
||||
value: 'Default Value',
|
||||
componentToken: 'Component Token',
|
||||
globalToken: 'Global Token',
|
||||
componentComment: 'here is your component tokens',
|
||||
globalComment: 'here is your global tokens',
|
||||
help: 'How to use?',
|
||||
customizeTokenLink: '/docs/react/customize-theme#customize-design-token',
|
||||
customizeComponentTokenLink: 'docs/react/customize-theme#customize-component-token',
|
||||
@ -46,13 +63,13 @@ const useStyle = createStyles(() => ({
|
||||
`,
|
||||
arrowIcon: css`
|
||||
font-size: 16px;
|
||||
margin-right: 8px;
|
||||
margin-inline-end: 8px;
|
||||
& svg {
|
||||
transition: all 0.3s;
|
||||
}
|
||||
`,
|
||||
help: css`
|
||||
margin-left: 8px;
|
||||
margin-inline-start: 8px;
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
color: #999;
|
||||
@ -69,16 +86,14 @@ interface SubTokenTableProps {
|
||||
helpLink: string;
|
||||
tokens: string[];
|
||||
component?: string;
|
||||
comment?: {
|
||||
componentComment?: string;
|
||||
globalComment?: string;
|
||||
};
|
||||
}
|
||||
|
||||
const SubTokenTable: React.FC<SubTokenTableProps> = ({
|
||||
defaultOpen,
|
||||
tokens,
|
||||
title,
|
||||
helpText,
|
||||
helpLink,
|
||||
component,
|
||||
}) => {
|
||||
const SubTokenTable: React.FC<SubTokenTableProps> = (props) => {
|
||||
const { defaultOpen, tokens, title, helpText, helpLink, component, comment } = props;
|
||||
const [, lang] = useLocale(locales);
|
||||
const token = useTheme();
|
||||
const columns = useColumns();
|
||||
@ -92,24 +107,7 @@ const SubTokenTable: React.FC<SubTokenTableProps> = ({
|
||||
}
|
||||
|
||||
const data = tokens
|
||||
.sort(
|
||||
component
|
||||
? undefined
|
||||
: (token1, token2) => {
|
||||
const hasColor1 = token1.toLowerCase().includes('color');
|
||||
const hasColor2 = token2.toLowerCase().includes('color');
|
||||
|
||||
if (hasColor1 && !hasColor2) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!hasColor1 && hasColor2) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return token1 < token2 ? -1 : 1;
|
||||
},
|
||||
)
|
||||
.sort(component ? undefined : compare)
|
||||
.map((name) => {
|
||||
const meta = component
|
||||
? tokenMeta.components[component].find((item) => item.token === name)
|
||||
@ -133,7 +131,7 @@ const SubTokenTable: React.FC<SubTokenTableProps> = ({
|
||||
theme={{
|
||||
components: {
|
||||
${component}: {
|
||||
/* here is your component tokens */
|
||||
/* ${comment?.componentComment} */
|
||||
},
|
||||
},
|
||||
}}
|
||||
@ -143,7 +141,7 @@ const SubTokenTable: React.FC<SubTokenTableProps> = ({
|
||||
: `<ConfigProvider
|
||||
theme={{
|
||||
token: {
|
||||
/* here is your global tokens */
|
||||
/* ${comment?.globalComment} */
|
||||
},
|
||||
}}
|
||||
>
|
||||
@ -161,16 +159,17 @@ const SubTokenTable: React.FC<SubTokenTableProps> = ({
|
||||
popupStyle={{ width: 400 }}
|
||||
content={
|
||||
<Typography>
|
||||
{/* <SourceCode lang="jsx">{code}</SourceCode> */}
|
||||
<pre style={{ fontSize: 12 }}>{code}</pre>
|
||||
<a href={helpLink} target="_blank" rel="noreferrer">
|
||||
<LinkOutlined style={{ marginRight: 4 }} />
|
||||
<LinkOutlined style={{ marginInlineEnd: 4 }} />
|
||||
{helpText}
|
||||
</a>
|
||||
</Typography>
|
||||
}
|
||||
>
|
||||
<span className={styles.help}>
|
||||
<QuestionCircleOutlined style={{ marginRight: 3 }} />
|
||||
<QuestionCircleOutlined style={{ marginInlineEnd: 4 }} />
|
||||
{helpText}
|
||||
</span>
|
||||
</Popover>
|
||||
@ -217,12 +216,16 @@ const ComponentTokenTable: React.FC<ComponentTokenTableProps> = ({ component })
|
||||
<>
|
||||
{tokenMeta.components[component] && (
|
||||
<SubTokenTable
|
||||
defaultOpen
|
||||
title={locale.componentToken}
|
||||
helpText={locale.help}
|
||||
helpLink={locale.customizeTokenLink}
|
||||
tokens={tokenMeta.components[component].map((item) => item.token)}
|
||||
component={component}
|
||||
defaultOpen
|
||||
comment={{
|
||||
componentComment: locale.componentComment,
|
||||
globalComment: locale.globalComment,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<SubTokenTable
|
||||
@ -230,6 +233,10 @@ const ComponentTokenTable: React.FC<ComponentTokenTableProps> = ({ component })
|
||||
helpText={locale.help}
|
||||
helpLink={locale.customizeComponentTokenLink}
|
||||
tokens={mergedGlobalTokens}
|
||||
comment={{
|
||||
componentComment: locale.componentComment,
|
||||
globalComment: locale.globalComment,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
39
.dumi/theme/builtins/Container/index.tsx
Normal file
39
.dumi/theme/builtins/Container/index.tsx
Normal file
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* copied: https://github.com/arvinxx/dumi-theme-antd-style/tree/master/src/builtins/Container
|
||||
*/
|
||||
import * as React from 'react';
|
||||
import { Alert } from 'antd';
|
||||
import { type FC, type ReactNode } from 'react';
|
||||
import useStyles from './style';
|
||||
|
||||
const Container: FC<{
|
||||
type: 'info' | 'warning' | 'success' | 'error';
|
||||
title?: string;
|
||||
children: ReactNode;
|
||||
}> = ({ type, title, children }) => {
|
||||
const { styles, cx } = useStyles();
|
||||
|
||||
return (
|
||||
<div data-type={type} className={styles.container}>
|
||||
<Alert
|
||||
showIcon
|
||||
type={type}
|
||||
message={title || type.toUpperCase()}
|
||||
description={
|
||||
<div
|
||||
className={cx(
|
||||
styles.desc,
|
||||
// 为了让 markdown 的样式生效,需要在这里添加一个额外的 class
|
||||
'markdown',
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
}
|
||||
className={styles.alert}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Container;
|
22
.dumi/theme/builtins/Container/style.ts
Normal file
22
.dumi/theme/builtins/Container/style.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { createStyles } from 'antd-style';
|
||||
|
||||
const useStyles = createStyles(({ prefixCls, css }) => ({
|
||||
container: css`
|
||||
margin: 8px 0;
|
||||
`,
|
||||
|
||||
alert: css`
|
||||
.${prefixCls}-alert-message {
|
||||
font-weight: bold;
|
||||
}
|
||||
`,
|
||||
|
||||
/* 使用 `&&` 加一点点权重 */
|
||||
desc: css`
|
||||
&& p {
|
||||
margin: 0;
|
||||
}
|
||||
`,
|
||||
}));
|
||||
|
||||
export default useStyles;
|
@ -1,15 +1,36 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { DumiDemoGrid, FormattedMessage } from 'dumi';
|
||||
import { BugFilled, BugOutlined, CodeFilled, CodeOutlined } from '@ant-design/icons';
|
||||
import {
|
||||
BugFilled,
|
||||
BugOutlined,
|
||||
CodeFilled,
|
||||
CodeOutlined,
|
||||
ExperimentFilled,
|
||||
ExperimentOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import classNames from 'classnames';
|
||||
import { Tooltip } from 'antd';
|
||||
import { ConfigProvider, Tooltip } from 'antd';
|
||||
import DemoContext from '../../slots/DemoContext';
|
||||
import useLayoutState from '../../../hooks/useLayoutState';
|
||||
import useLocale from '../../../hooks/useLocale';
|
||||
|
||||
const locales = {
|
||||
cn: {
|
||||
enableCssVar: '启用 CSS 变量',
|
||||
disableCssVar: '禁用 CSS 变量',
|
||||
},
|
||||
en: {
|
||||
enableCssVar: 'Enable CSS Var',
|
||||
disableCssVar: 'Disable CSS Var',
|
||||
},
|
||||
};
|
||||
|
||||
const DemoWrapper: typeof DumiDemoGrid = ({ items }) => {
|
||||
const { showDebug, setShowDebug } = useContext(DemoContext);
|
||||
const [locale] = useLocale(locales);
|
||||
|
||||
const [expandAll, setExpandAll] = useLayoutState(false);
|
||||
const [enableCssVar, setEnableCssVar] = useLayoutState(true);
|
||||
|
||||
const expandTriggerClass = classNames('code-box-expand-trigger', {
|
||||
'code-box-expand-trigger-active': expandAll,
|
||||
@ -23,9 +44,14 @@ const DemoWrapper: typeof DumiDemoGrid = ({ items }) => {
|
||||
setExpandAll(!expandAll);
|
||||
};
|
||||
|
||||
const handleCssVarToggle = () => {
|
||||
setEnableCssVar((v) => !v);
|
||||
};
|
||||
|
||||
const demos = React.useMemo(
|
||||
() =>
|
||||
items.reduce((acc, item) => {
|
||||
items.reduce(
|
||||
(acc, item) => {
|
||||
const { previewerProps } = item;
|
||||
const { debug } = previewerProps;
|
||||
|
||||
@ -45,7 +71,9 @@ const DemoWrapper: typeof DumiDemoGrid = ({ items }) => {
|
||||
originDebug: debug,
|
||||
},
|
||||
});
|
||||
}, [] as typeof items),
|
||||
},
|
||||
[] as typeof items,
|
||||
),
|
||||
[expandAll, showDebug],
|
||||
);
|
||||
|
||||
@ -74,8 +102,17 @@ const DemoWrapper: typeof DumiDemoGrid = ({ items }) => {
|
||||
<BugOutlined className={expandTriggerClass} onClick={handleVisibleToggle} />
|
||||
)}
|
||||
</Tooltip>
|
||||
<Tooltip title={enableCssVar ? locale.disableCssVar : locale.enableCssVar}>
|
||||
{enableCssVar ? (
|
||||
<ExperimentFilled className={expandTriggerClass} onClick={handleCssVarToggle} />
|
||||
) : (
|
||||
<ExperimentOutlined className={expandTriggerClass} onClick={handleCssVarToggle} />
|
||||
)}
|
||||
</Tooltip>
|
||||
</span>
|
||||
<ConfigProvider theme={{ cssVar: enableCssVar }}>
|
||||
<DumiDemoGrid items={demos} />
|
||||
</ConfigProvider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -1,7 +1,8 @@
|
||||
import SourceCode from 'dumi/theme-default/builtins/SourceCode';
|
||||
import React from 'react';
|
||||
import type { TabsProps } from 'antd';
|
||||
import { Tabs } from 'antd';
|
||||
import { ConfigProvider, Tabs } from 'antd';
|
||||
import SourceCode from 'dumi/theme-default/builtins/SourceCode';
|
||||
import type { Tab } from 'rc-tabs/lib/interface';
|
||||
|
||||
import NpmLogo from './npm';
|
||||
import PnpmLogo from './pnpm';
|
||||
import YarnLogo from './yarn';
|
||||
@ -12,51 +13,34 @@ interface InstallProps {
|
||||
pnpm?: string;
|
||||
}
|
||||
|
||||
const npmLabel = (
|
||||
<span className="snippet-label">
|
||||
<NpmLogo />
|
||||
npm
|
||||
</span>
|
||||
);
|
||||
|
||||
const pnpmLabel = (
|
||||
<span className="snippet-label">
|
||||
<PnpmLogo />
|
||||
pnpm
|
||||
</span>
|
||||
);
|
||||
|
||||
const yarnLabel = (
|
||||
<span className="snippet-label">
|
||||
<YarnLogo />
|
||||
yarn
|
||||
</span>
|
||||
);
|
||||
|
||||
const InstallDependencies: React.FC<InstallProps> = (props) => {
|
||||
const { npm, yarn, pnpm } = props;
|
||||
const items = React.useMemo<TabsProps['items']>(
|
||||
() =>
|
||||
[
|
||||
const items: Tab[] = [
|
||||
{
|
||||
key: 'npm',
|
||||
label: 'npm',
|
||||
children: npm ? <SourceCode lang="bash">{npm}</SourceCode> : null,
|
||||
label: npmLabel,
|
||||
icon: <NpmLogo />,
|
||||
},
|
||||
{
|
||||
key: 'yarn',
|
||||
label: 'yarn',
|
||||
children: yarn ? <SourceCode lang="bash">{yarn}</SourceCode> : null,
|
||||
label: yarnLabel,
|
||||
icon: <YarnLogo />,
|
||||
},
|
||||
{
|
||||
key: 'pnpm',
|
||||
label: 'pnpm',
|
||||
children: pnpm ? <SourceCode lang="bash">{pnpm}</SourceCode> : null,
|
||||
label: pnpmLabel,
|
||||
icon: <PnpmLogo />,
|
||||
},
|
||||
].filter((item) => item.children),
|
||||
[npm, yarn, pnpm],
|
||||
].filter((item) => item.children);
|
||||
|
||||
return (
|
||||
<ConfigProvider theme={{ components: { Tabs: { horizontalMargin: '0' } } }}>
|
||||
<Tabs className="markdown" size="small" defaultActiveKey="npm" items={items} />
|
||||
</ConfigProvider>
|
||||
);
|
||||
return <Tabs className="antd-site-snippet" defaultActiveKey="npm" items={items} />;
|
||||
};
|
||||
|
||||
export default InstallDependencies;
|
||||
|
@ -1,16 +1,28 @@
|
||||
import React from 'react';
|
||||
import { createStyles, css } from 'antd-style';
|
||||
import classNames from 'classnames';
|
||||
|
||||
interface IconProps {
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
const useStyle = createStyles(() => ({
|
||||
iconWrap: css`
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
line-height: 0;
|
||||
text-align: center;
|
||||
vertical-align: -0.125em;
|
||||
`,
|
||||
}));
|
||||
|
||||
const NpmIcon: React.FC<IconProps> = (props) => {
|
||||
const { className, style } = props;
|
||||
const { styles } = useStyle();
|
||||
return (
|
||||
<span className={classNames(styles.iconWrap, className)} style={style}>
|
||||
<svg
|
||||
className={className}
|
||||
style={style}
|
||||
fill="#E53E3E"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
@ -21,6 +33,7 @@ const NpmIcon: React.FC<IconProps> = (props) => {
|
||||
>
|
||||
<path d="M0 0v16h16v-16h-16zM13 13h-2v-8h-3v8h-5v-10h10v10z" />
|
||||
</svg>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,16 +1,28 @@
|
||||
import React from 'react';
|
||||
import { createStyles, css } from 'antd-style';
|
||||
import classNames from 'classnames';
|
||||
|
||||
interface IconProps {
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
const useStyle = createStyles(() => ({
|
||||
iconWrap: css`
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
line-height: 0;
|
||||
text-align: center;
|
||||
vertical-align: -0.125em;
|
||||
`,
|
||||
}));
|
||||
|
||||
const PnpmIcon: React.FC<IconProps> = (props) => {
|
||||
const { className, style } = props;
|
||||
const { styles } = useStyle();
|
||||
return (
|
||||
<span className={classNames(styles.iconWrap, className)} style={style}>
|
||||
<svg
|
||||
className={className}
|
||||
style={style}
|
||||
aria-hidden="true"
|
||||
fill="#F69220"
|
||||
focusable="false"
|
||||
@ -23,6 +35,7 @@ const PnpmIcon: React.FC<IconProps> = (props) => {
|
||||
>
|
||||
<path d="M0 0v7.5h7.5V0zm8.25 0v7.5h7.498V0zm8.25 0v7.5H24V0zM8.25 8.25v7.5h7.498v-7.5zm8.25 0v7.5H24v-7.5zM0 16.5V24h7.5v-7.5zm8.25 0V24h7.498v-7.5zm8.25 0V24H24v-7.5z" />
|
||||
</svg>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,16 +1,28 @@
|
||||
import React from 'react';
|
||||
import { createStyles, css } from 'antd-style';
|
||||
import classNames from 'classnames';
|
||||
|
||||
interface IconProps {
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
const useStyle = createStyles(() => ({
|
||||
iconWrap: css`
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
line-height: 0;
|
||||
text-align: center;
|
||||
vertical-align: -0.125em;
|
||||
`,
|
||||
}));
|
||||
|
||||
const YarnIcon: React.FC<IconProps> = (props) => {
|
||||
const { className, style } = props;
|
||||
const { styles } = useStyle();
|
||||
return (
|
||||
<span className={classNames(styles.iconWrap, className)} style={style}>
|
||||
<svg
|
||||
className={className}
|
||||
style={style}
|
||||
aria-hidden="true"
|
||||
fill="#2C8EBB"
|
||||
focusable="false"
|
||||
@ -22,6 +34,7 @@ const YarnIcon: React.FC<IconProps> = (props) => {
|
||||
>
|
||||
<path d="M393.9 345.2c-39 9.3-48.4 32.1-104 47.4 0 0-2.7 4-10.4 5.8-13.4 3.3-63.9 6-68.5 6.1-12.4.1-19.9-3.2-22-8.2-6.4-15.3 9.2-22 9.2-22-8.1-5-9-9.9-9.8-8.1-2.4 5.8-3.6 20.1-10.1 26.5-8.8 8.9-25.5 5.9-35.3.8-10.8-5.7.8-19.2.8-19.2s-5.8 3.4-10.5-3.6c-6-9.3-17.1-37.3 11.5-62-1.3-10.1-4.6-53.7 40.6-85.6 0 0-20.6-22.8-12.9-43.3 5-13.4 7-13.3 8.6-13.9 5.7-2.2 11.3-4.6 15.4-9.1 20.6-22.2 46.8-18 46.8-18s12.4-37.8 23.9-30.4c3.5 2.3 16.3 30.6 16.3 30.6s13.6-7.9 15.1-5c8.2 16 9.2 46.5 5.6 65.1-6.1 30.6-21.4 47.1-27.6 57.5-1.4 2.4 16.5 10 27.8 41.3 10.4 28.6 1.1 52.7 2.8 55.3.8 1.4 13.7.8 36.4-13.2 12.8-7.9 28.1-16.9 45.4-17 16.7-.5 17.6 19.2 4.9 22.2zM496 256c0 136.9-111.1 248-248 248S0 392.9 0 256 111.1 8 248 8s248 111.1 248 248zm-79.3 75.2c-1.7-13.6-13.2-23-28-22.8-22 .3-40.5 11.7-52.8 19.2-4.8 3-8.9 5.2-12.4 6.8 3.1-44.5-22.5-73.1-28.7-79.4 7.8-11.3 18.4-27.8 23.4-53.2 4.3-21.7 3-55.5-6.9-74.5-1.6-3.1-7.4-11.2-21-7.4-9.7-20-13-22.1-15.6-23.8-1.1-.7-23.6-16.4-41.4 28-12.2.9-31.3 5.3-47.5 22.8-2 2.2-5.9 3.8-10.1 5.4h.1c-8.4 3-12.3 9.9-16.9 22.3-6.5 17.4.2 34.6 6.8 45.7-17.8 15.9-37 39.8-35.7 82.5-34 36-11.8 73-5.6 79.6-1.6 11.1 3.7 19.4 12 23.8 12.6 6.7 30.3 9.6 43.9 2.8 4.9 5.2 13.8 10.1 30 10.1 6.8 0 58-2.9 72.6-6.5 6.8-1.6 11.5-4.5 14.6-7.1 9.8-3.1 36.8-12.3 62.2-28.7 18-11.7 24.2-14.2 37.6-17.4 12.9-3.2 21-15.1 19.4-28.2z" />
|
||||
</svg>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -255,7 +255,7 @@ const CodePreviewer: React.FC<AntdPreviewerProps> = (props) => {
|
||||
'react@18/umd/react.development.js',
|
||||
'react-dom@18/umd/react-dom.development.js',
|
||||
'dayjs@1/dayjs.min.js',
|
||||
`antd@${pkg.version}/dist/antd-with-locales.js`,
|
||||
`antd@${pkg.version}/dist/antd-with-locales.min.js`,
|
||||
`@ant-design/icons/dist/index.umd.js`,
|
||||
'react-router-dom/dist/umd/react-router-dom.production.min.js',
|
||||
'react-router/dist/umd/react-router.production.min.js',
|
||||
|
@ -10,8 +10,9 @@ const Previewer = React.lazy(() => import('./Previewer'));
|
||||
const useStyle = createStyles(({ css }) => ({
|
||||
skeletonWrapper: css`
|
||||
width: 100% !important;
|
||||
height: 500px;
|
||||
height: 250px;
|
||||
margin-bottom: 16px;
|
||||
border-radius: 8px;
|
||||
`,
|
||||
}));
|
||||
|
||||
|
@ -1,11 +1,10 @@
|
||||
/* eslint-disable react/no-array-index-key */
|
||||
import * as React from 'react';
|
||||
import { Suspense } from 'react';
|
||||
import dayjs from 'dayjs';
|
||||
import { FormattedMessage } from 'dumi';
|
||||
import { createStyles } from 'antd-style';
|
||||
import { Avatar, Divider, Empty, Skeleton, Tabs } from 'antd';
|
||||
import type { Article, Authors } from '../../../pages/index/components/util';
|
||||
import type { Article, Authors, SiteData } from '../../../pages/index/components/util';
|
||||
import { useSiteData } from '../../../pages/index/components/util';
|
||||
import useLocale from '../../../hooks/useLocale';
|
||||
|
||||
@ -97,10 +96,11 @@ const ArticleList: React.FC<ArticleListProps> = ({ name, data = [], authors = []
|
||||
);
|
||||
};
|
||||
|
||||
const Articles: React.FC = () => {
|
||||
const Articles: React.FC<{ data: Partial<SiteData> }> = ({ data }) => {
|
||||
const [, lang] = useLocale();
|
||||
const isZhCN = lang === 'cn';
|
||||
const { articles = { cn: [], en: [] }, authors = [] } = useSiteData();
|
||||
|
||||
const { articles = { cn: [], en: [] }, authors = [] } = data;
|
||||
|
||||
// ========================== Data ==========================
|
||||
const mergedData = React.useMemo(() => {
|
||||
@ -149,11 +149,13 @@ const Articles: React.FC = () => {
|
||||
|
||||
export default () => {
|
||||
const { styles } = useStyle();
|
||||
const data = useSiteData();
|
||||
|
||||
const articles = data ? <Articles data={data} /> : <Skeleton active />;
|
||||
|
||||
return (
|
||||
<div id="articles" className={styles.articles}>
|
||||
<Suspense fallback={<Skeleton active />}>
|
||||
<Articles />
|
||||
</Suspense>
|
||||
{articles}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -44,7 +44,7 @@ const ColorPaletteTool: React.FC = () => {
|
||||
text += locale.saturation((s * 100).toFixed(2));
|
||||
}
|
||||
if (b * 100 < primaryMinBrightness) {
|
||||
text += locale.brightness((s * 100).toFixed(2));
|
||||
text += locale.brightness((b * 100).toFixed(2));
|
||||
}
|
||||
}
|
||||
return (
|
||||
|
@ -11,10 +11,16 @@ const Loading: React.FC = () => {
|
||||
pathname.startsWith('/changelog')
|
||||
) {
|
||||
return (
|
||||
<Space direction="vertical" style={{ width: '100%', marginTop: 24 }} size={40}>
|
||||
<Skeleton title={false} active paragraph={{ rows: 3 }} />
|
||||
<div style={{ maxWidth: '70vw', width: '100%', margin: '80px auto 0', textAlign: 'center' }}>
|
||||
<img
|
||||
src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
|
||||
width={40}
|
||||
alt="loading"
|
||||
style={{ marginBottom: 24, filter: 'grayscale(1)', opacity: 0.33 }}
|
||||
/>
|
||||
<Skeleton active paragraph={{ rows: 3 }} />
|
||||
</Space>
|
||||
<Skeleton active paragraph={{ rows: 4 }} style={{ marginTop: 32 }} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ const GlobalDemoStyles: React.FC = () => {
|
||||
margin: 0 0 16px;
|
||||
background-color: ${token.colorBgContainer};
|
||||
border: 1px solid ${token.colorSplit};
|
||||
border-radius: ${token.borderRadius}px;
|
||||
border-radius: ${token.borderRadiusLG}px;
|
||||
transition: all 0.2s;
|
||||
|
||||
.code-box-title {
|
||||
@ -39,7 +39,7 @@ const GlobalDemoStyles: React.FC = () => {
|
||||
|
||||
.code-box-demo {
|
||||
background-color: ${token.colorBgContainer};
|
||||
border-radius: ${token.borderRadius}px ${token.borderRadius}px 0 0;
|
||||
border-radius: ${token.borderRadiusLG}px ${token.borderRadiusLG}px 0 0;
|
||||
> .demo {
|
||||
overflow: auto;
|
||||
}
|
||||
@ -85,10 +85,6 @@ const GlobalDemoStyles: React.FC = () => {
|
||||
transition: background-color 0.4s;
|
||||
margin-inline-start: 16px;
|
||||
|
||||
${antCls}-row-rtl & {
|
||||
border-radius: ${token.borderRadius}px 0 0 ${token.borderRadius}px;
|
||||
}
|
||||
|
||||
a,
|
||||
a:hover {
|
||||
color: ${token.colorText};
|
||||
|
@ -199,28 +199,6 @@ const GlobalStyle: React.FC = () => {
|
||||
font-size: 30px;
|
||||
}
|
||||
}
|
||||
.antd-site-snippet {
|
||||
.ant-tabs-tab {
|
||||
.snippet-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
svg {
|
||||
margin-inline-end: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.dumi-default-source-code {
|
||||
margin: 0 auto;
|
||||
background-color: ${token.siteMarkdownCodeBg};
|
||||
border-radius: ${token.borderRadius}px;
|
||||
> pre.prism-code {
|
||||
padding: 12px 20px;
|
||||
font-size: 13px;
|
||||
line-height: 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.markdown table td > a:not(:last-child) {
|
||||
margin-right: 0 !important;
|
||||
|
@ -4,7 +4,7 @@ import {
|
||||
createCache,
|
||||
extractStyle,
|
||||
legacyNotSelectorLinter,
|
||||
logicalPropertiesLinter,
|
||||
NaNLinter,
|
||||
parentSelectorLinter,
|
||||
StyleProvider,
|
||||
} from '@ant-design/cssinjs';
|
||||
@ -45,7 +45,7 @@ const getAlgorithm = (themes: ThemeName[] = []) =>
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter((item) => item) as typeof antdTheme.darkAlgorithm[];
|
||||
.filter((item) => item) as (typeof antdTheme.darkAlgorithm)[];
|
||||
|
||||
const GlobalLayout: React.FC = () => {
|
||||
const outlet = useOutlet();
|
||||
@ -168,7 +168,7 @@ const GlobalLayout: React.FC = () => {
|
||||
<DarkContext.Provider value={theme.includes('dark')}>
|
||||
<StyleProvider
|
||||
cache={styleCache}
|
||||
linters={[logicalPropertiesLinter, legacyNotSelectorLinter, parentSelectorLinter]}
|
||||
linters={[legacyNotSelectorLinter, parentSelectorLinter, NaNLinter]}
|
||||
>
|
||||
<SiteContext.Provider value={siteContextValue}>
|
||||
<SiteThemeProvider
|
||||
@ -177,6 +177,7 @@ const GlobalLayout: React.FC = () => {
|
||||
token: {
|
||||
motion: !theme.includes('motion-off'),
|
||||
},
|
||||
cssVar: true,
|
||||
}}
|
||||
>
|
||||
<HappyProvider disabled={!theme.includes('happy-work')}>{content}</HappyProvider>
|
||||
|
@ -111,6 +111,8 @@
|
||||
"app.footer.seeconf": "Experience Tech Conference",
|
||||
"app.footer.xtech": "Ant Financial Experience Tech",
|
||||
"app.footer.xtech.slogan": "Experience The Beauty",
|
||||
"app.footer.galacean": "Galacean",
|
||||
"app.footer.galacean.slogan": "Interactive Graphics Solution",
|
||||
"app.docs.color.pick-primary": "Pick your primary color",
|
||||
"app.docs.color.pick-background": "Pick your background color",
|
||||
"app.docs.components.icon.search.placeholder": "Search icons here, click icon to copy code",
|
||||
|
@ -110,6 +110,8 @@
|
||||
"app.footer.seeconf": "蚂蚁体验科技大会",
|
||||
"app.footer.xtech": "蚂蚁体验科技",
|
||||
"app.footer.xtech.slogan": "让用户体验美好",
|
||||
"app.footer.galacean": "Galacean",
|
||||
"app.footer.galacean.slogan": "互动图形解决方案",
|
||||
"app.docs.color.pick-primary": "选择你的主色",
|
||||
"app.docs.color.pick-background": "选择你的背景色",
|
||||
"app.docs.components.icon.search.placeholder": "在此搜索图标,点击图标可复制代码",
|
||||
|
@ -166,7 +166,7 @@ const RoutesPlugin = (api: IApi) => {
|
||||
});
|
||||
|
||||
// Insert antd style to head
|
||||
const matchRegex = /<style data-type="antd-cssinjs">(.*?)<\/style>/;
|
||||
const matchRegex = /<style data-type="antd-cssinjs">([\S\s]+?)<\/style>/;
|
||||
const matchList = file.content.match(matchRegex) || [];
|
||||
|
||||
let antdStyle = '';
|
||||
|
38
.dumi/theme/slots/Content/ContributorAvatar.tsx
Normal file
38
.dumi/theme/slots/Content/ContributorAvatar.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
import React from 'react';
|
||||
import { Avatar, Skeleton, Tooltip } from 'antd';
|
||||
|
||||
const AvatarPlaceholder: React.FC<{ num?: number }> = ({ num = 3 }) => (
|
||||
<li>
|
||||
{Array.from({ length: num }).map((_, i) => (
|
||||
<Skeleton.Avatar size="small" active key={i} style={{ marginLeft: i === 0 ? 0 : -8 }} />
|
||||
))}
|
||||
</li>
|
||||
);
|
||||
|
||||
interface ContributorAvatarProps {
|
||||
username?: string;
|
||||
url?: string;
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
const ContributorAvatar: React.FC<ContributorAvatarProps> = ({ username, url, loading }) => {
|
||||
if (loading) {
|
||||
return <AvatarPlaceholder />;
|
||||
}
|
||||
if (username?.includes('github-actions')) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<Tooltip title={username}>
|
||||
<li>
|
||||
<a href={`https://github.com/${username}`} target="_blank" rel="noopener noreferrer">
|
||||
<Avatar size="small" src={url} alt={username}>
|
||||
{username}
|
||||
</Avatar>
|
||||
</a>
|
||||
</li>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
export default ContributorAvatar;
|
82
.dumi/theme/slots/Content/Contributors.tsx
Normal file
82
.dumi/theme/slots/Content/Contributors.tsx
Normal file
@ -0,0 +1,82 @@
|
||||
import React, { useContext } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { useIntl } from 'dumi';
|
||||
import { createStyles } from 'antd-style';
|
||||
import ContributorsList from '@qixian.cs/github-contributors-list';
|
||||
import ContributorAvatar from './ContributorAvatar';
|
||||
import SiteContext from '../SiteContext';
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => {
|
||||
const { antCls } = token;
|
||||
|
||||
return {
|
||||
contributorsList: css`
|
||||
margin-top: 120px !important;
|
||||
`,
|
||||
listMobile: css`
|
||||
margin: 1em 0 !important;
|
||||
`,
|
||||
title: css`
|
||||
font-size: 12px;
|
||||
opacity: 0.45;
|
||||
`,
|
||||
list: css`
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
clear: both;
|
||||
|
||||
li {
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
li,
|
||||
${antCls}-avatar + ${antCls}-avatar {
|
||||
transition: all ${token.motionDurationSlow};
|
||||
margin-inline-end: -8px;
|
||||
}
|
||||
&:hover {
|
||||
li,
|
||||
${antCls}-avatar {
|
||||
margin-inline-end: 0;
|
||||
}
|
||||
}
|
||||
`,
|
||||
};
|
||||
});
|
||||
|
||||
interface ContributorsProps {
|
||||
filename?: string;
|
||||
}
|
||||
|
||||
const Contributors: React.FC<ContributorsProps> = ({ filename }) => {
|
||||
const { formatMessage } = useIntl();
|
||||
const { styles } = useStyle();
|
||||
const { isMobile } = useContext(SiteContext);
|
||||
|
||||
if (!filename) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classNames(styles.contributorsList, { [styles.listMobile]: isMobile })}>
|
||||
<div className={styles.title}>{formatMessage({ id: 'app.content.contributors' })}</div>
|
||||
<ContributorsList
|
||||
cache
|
||||
repo="ant-design"
|
||||
owner="ant-design"
|
||||
fileName={filename}
|
||||
className={styles.list}
|
||||
renderItem={(item, loading) => (
|
||||
<ContributorAvatar
|
||||
key={item?.username}
|
||||
username={item?.username}
|
||||
url={item?.url}
|
||||
loading={loading}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Contributors;
|
137
.dumi/theme/slots/Content/DocAnchor.tsx
Normal file
137
.dumi/theme/slots/Content/DocAnchor.tsx
Normal file
@ -0,0 +1,137 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { Anchor } from 'antd';
|
||||
import { createStyles, useTheme } from 'antd-style';
|
||||
import { useRouteMeta, useTabMeta } from 'dumi';
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => {
|
||||
const { antCls } = token;
|
||||
|
||||
return {
|
||||
toc: css`
|
||||
${antCls}-anchor {
|
||||
${antCls}-anchor-link-title {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
`,
|
||||
tocWrapper: css`
|
||||
position: fixed;
|
||||
top: ${token.headerHeight + token.contentMarginTop}px;
|
||||
inset-inline-end: 0;
|
||||
width: 160px;
|
||||
margin: 0 0 12px 0;
|
||||
padding: 8px 0;
|
||||
padding-inline: 4px 8px;
|
||||
backdrop-filter: blur(8px);
|
||||
border-radius: ${token.borderRadius}px;
|
||||
box-sizing: border-box;
|
||||
z-index: 1000;
|
||||
|
||||
.toc-debug {
|
||||
color: ${token.purple6};
|
||||
|
||||
&:hover {
|
||||
color: ${token.purple5};
|
||||
}
|
||||
}
|
||||
|
||||
> div {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
max-height: calc(100vh - 40px) !important;
|
||||
margin: 0 auto;
|
||||
overflow: auto;
|
||||
padding-inline: 4px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: ${token.screenLG}px) {
|
||||
display: none;
|
||||
}
|
||||
`,
|
||||
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 48px;
|
||||
}
|
||||
}
|
||||
`,
|
||||
};
|
||||
});
|
||||
|
||||
interface DocAnchorProps {
|
||||
showDebug?: boolean;
|
||||
debugDemos?: string[];
|
||||
}
|
||||
|
||||
type AnchorItem = {
|
||||
id: string;
|
||||
title: string;
|
||||
children?: AnchorItem[];
|
||||
};
|
||||
|
||||
const DocAnchor: React.FC<DocAnchorProps> = ({ showDebug, debugDemos = [] }) => {
|
||||
const { styles } = useStyle();
|
||||
const token = useTheme();
|
||||
const meta = useRouteMeta();
|
||||
const tab = useTabMeta();
|
||||
|
||||
const renderAnchorItem = (item: AnchorItem) => ({
|
||||
href: `#${item.id}`,
|
||||
title: item.title,
|
||||
key: item.id,
|
||||
children: item.children
|
||||
?.filter((child) => showDebug || !debugDemos.includes(child.id))
|
||||
.map((child) => ({
|
||||
key: child.id,
|
||||
href: `#${child.id}`,
|
||||
title: (
|
||||
<span className={classNames(debugDemos.includes(child.id) && 'toc-debug')}>
|
||||
{child?.title}
|
||||
</span>
|
||||
),
|
||||
})),
|
||||
});
|
||||
|
||||
const anchorItems = useMemo(
|
||||
() =>
|
||||
(tab?.toc || meta.toc).reduce<AnchorItem[]>((result, item) => {
|
||||
if (item.depth === 2) {
|
||||
result.push({ ...item });
|
||||
} else if (item.depth === 3) {
|
||||
const parent = result[result.length - 1];
|
||||
if (parent) {
|
||||
parent.children = parent.children || [];
|
||||
parent.children.push({ ...item });
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}, []),
|
||||
[tab?.toc, meta.toc],
|
||||
);
|
||||
|
||||
if (!meta.frontmatter.toc) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<section className={styles.tocWrapper}>
|
||||
<Anchor
|
||||
className={styles.toc}
|
||||
affix={false}
|
||||
targetOffset={token.anchorTop}
|
||||
showInkInFixed
|
||||
items={anchorItems.map(renderAnchorItem)}
|
||||
/>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default DocAnchor;
|
79
.dumi/theme/slots/Content/DocMeta.tsx
Normal file
79
.dumi/theme/slots/Content/DocMeta.tsx
Normal file
@ -0,0 +1,79 @@
|
||||
import React, { useState, useLayoutEffect, useMemo } from 'react';
|
||||
import { Typography, Space, Skeleton, Avatar } from 'antd';
|
||||
import { useRouteMeta } from 'dumi';
|
||||
import DayJS from 'dayjs';
|
||||
import { CalendarOutlined } from '@ant-design/icons';
|
||||
|
||||
const AuthorAvatar: React.FC<{ name: string; avatar: string }> = ({ name, avatar }) => {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(false);
|
||||
useLayoutEffect(() => {
|
||||
const img = new Image();
|
||||
img.src = avatar;
|
||||
img.onload = () => setLoading(false);
|
||||
img.onerror = () => setError(true);
|
||||
}, []);
|
||||
if (error) {
|
||||
return null;
|
||||
}
|
||||
if (loading) {
|
||||
return <Skeleton.Avatar size="small" active />;
|
||||
}
|
||||
return (
|
||||
<Avatar size="small" src={avatar} alt={name}>
|
||||
{name}
|
||||
</Avatar>
|
||||
);
|
||||
};
|
||||
|
||||
const DocMeta: React.FC<{}> = () => {
|
||||
const meta = useRouteMeta();
|
||||
|
||||
const mergedAuthorInfos = useMemo(() => {
|
||||
const { author } = meta.frontmatter;
|
||||
if (!author) {
|
||||
return [];
|
||||
}
|
||||
if (typeof author === 'string') {
|
||||
return author.split(',').map((item) => ({
|
||||
name: item,
|
||||
avatar: `https://github.com/${item}.png`,
|
||||
}));
|
||||
}
|
||||
if (Array.isArray(author)) {
|
||||
return author;
|
||||
}
|
||||
return [];
|
||||
}, [meta.frontmatter.author]);
|
||||
|
||||
if (!meta.frontmatter.date && !meta.frontmatter.author) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Typography.Paragraph>
|
||||
<Space>
|
||||
{meta.frontmatter.date && (
|
||||
<span style={{ opacity: 0.65 }}>
|
||||
<CalendarOutlined /> {DayJS(meta.frontmatter.date).format('YYYY-MM-DD')}
|
||||
</span>
|
||||
)}
|
||||
{mergedAuthorInfos.map((info) => (
|
||||
<a
|
||||
href={`https://github.com/${info.name}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
key={info.name}
|
||||
>
|
||||
<Space size={3}>
|
||||
<AuthorAvatar name={info.name} avatar={info.avatar} />
|
||||
<span style={{ opacity: 0.65 }}>@{info.name}</span>
|
||||
</Space>
|
||||
</a>
|
||||
))}
|
||||
</Space>
|
||||
</Typography.Paragraph>
|
||||
);
|
||||
};
|
||||
|
||||
export default DocMeta;
|
@ -1,93 +1,25 @@
|
||||
import { CalendarOutlined } from '@ant-design/icons';
|
||||
import { createStyles, useTheme } from 'antd-style';
|
||||
import ContributorsList from '@qixian.cs/github-contributors-list';
|
||||
import classNames from 'classnames';
|
||||
import DayJS from 'dayjs';
|
||||
import { FormattedMessage, useIntl, useRouteMeta, useTabMeta } from 'dumi';
|
||||
import { FormattedMessage, useRouteMeta } from 'dumi';
|
||||
import type { ReactNode } from 'react';
|
||||
import React, { useContext, useLayoutEffect, useMemo, useState } from 'react';
|
||||
import { Anchor, Avatar, Col, ConfigProvider, Skeleton, Space, Tooltip, Typography } from 'antd';
|
||||
import React, { Suspense, useContext, useLayoutEffect, useMemo } from 'react';
|
||||
import { Col, Space, Typography, Skeleton } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
import useLayoutState from '../../../hooks/useLayoutState';
|
||||
import useLocation from '../../../hooks/useLocation';
|
||||
import EditButton from '../../common/EditButton';
|
||||
import PrevAndNext from '../../common/PrevAndNext';
|
||||
import ComponentChangelog from '../../common/ComponentChangelog';
|
||||
import type { DemoContextProps } from '../DemoContext';
|
||||
import DemoContext from '../DemoContext';
|
||||
import Footer from '../Footer';
|
||||
import SiteContext from '../SiteContext';
|
||||
import ColumnCard from './ColumnCard';
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => {
|
||||
const { antCls } = token;
|
||||
const Contributors = React.lazy(() => import('./Contributors'));
|
||||
const ColumnCard = React.lazy(() => import('./ColumnCard'));
|
||||
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'));
|
||||
|
||||
return {
|
||||
contributorsList: css`
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 120px !important;
|
||||
clear: both;
|
||||
|
||||
li {
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
li,
|
||||
${antCls}-avatar + ${antCls}-avatar {
|
||||
transition: all ${token.motionDurationSlow};
|
||||
margin-inline-end: -8px;
|
||||
}
|
||||
&:hover {
|
||||
li,
|
||||
${antCls}-avatar {
|
||||
margin-inline-end: 0;
|
||||
}
|
||||
}
|
||||
`,
|
||||
listMobile: css`
|
||||
margin: 1em 0 !important;
|
||||
`,
|
||||
toc: css`
|
||||
${antCls}-anchor {
|
||||
${antCls}-anchor-link-title {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
`,
|
||||
tocWrapper: css`
|
||||
position: fixed;
|
||||
top: ${token.headerHeight + token.contentMarginTop}px;
|
||||
inset-inline-end: 0;
|
||||
width: 160px;
|
||||
margin: 0 0 12px 0;
|
||||
padding: 8px 0;
|
||||
padding-inline: 4px 8px;
|
||||
backdrop-filter: blur(8px);
|
||||
border-radius: ${token.borderRadius}px;
|
||||
box-sizing: border-box;
|
||||
z-index: 1000;
|
||||
|
||||
.toc-debug {
|
||||
color: ${token.purple6};
|
||||
|
||||
&:hover {
|
||||
color: ${token.purple5};
|
||||
}
|
||||
}
|
||||
|
||||
> div {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
max-height: calc(100vh - 40px) !important;
|
||||
margin: 0 auto;
|
||||
overflow: auto;
|
||||
padding-inline: 4px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: ${token.screenLG}px) {
|
||||
display: none;
|
||||
}
|
||||
`,
|
||||
const useStyle = createStyles(({ token, css }) => ({
|
||||
articleWrapper: css`
|
||||
padding: 0 170px 32px 64px;
|
||||
|
||||
@ -102,53 +34,13 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
}
|
||||
}
|
||||
`,
|
||||
};
|
||||
});
|
||||
|
||||
type AnchorItem = {
|
||||
id: string;
|
||||
title: string;
|
||||
children?: AnchorItem[];
|
||||
};
|
||||
|
||||
const AvatarPlaceholder: React.FC<{ num?: number }> = ({ num = 3 }) => (
|
||||
<li>
|
||||
{Array.from({ length: num }).map((_, i) => (
|
||||
<Skeleton.Avatar size="small" active key={i} style={{ marginLeft: i === 0 ? 0 : -8 }} />
|
||||
))}
|
||||
</li>
|
||||
);
|
||||
|
||||
const AuthorAvatar: React.FC<{ name: string; avatar: string }> = ({ name, avatar }) => {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(false);
|
||||
useLayoutEffect(() => {
|
||||
const img = new Image();
|
||||
img.src = avatar;
|
||||
img.onload = () => setLoading(false);
|
||||
img.onerror = () => setError(true);
|
||||
}, []);
|
||||
if (error) {
|
||||
return null;
|
||||
}
|
||||
if (loading) {
|
||||
return <Skeleton.Avatar size="small" active />;
|
||||
}
|
||||
return (
|
||||
<Avatar size="small" src={avatar} alt={name}>
|
||||
{name}
|
||||
</Avatar>
|
||||
);
|
||||
};
|
||||
}));
|
||||
|
||||
const Content: React.FC<{ children: ReactNode }> = ({ children }) => {
|
||||
const meta = useRouteMeta();
|
||||
const tab = useTabMeta();
|
||||
const { pathname, hash } = useLocation();
|
||||
const { formatMessage } = useIntl();
|
||||
const { direction } = useContext(SiteContext);
|
||||
const { styles } = useStyle();
|
||||
const token = useTheme();
|
||||
const { direction, isMobile } = useContext(SiteContext);
|
||||
|
||||
const [showDebug, setShowDebug] = useLayoutState(false);
|
||||
const debugDemos = useMemo(
|
||||
@ -167,71 +59,14 @@ const Content: React.FC<{ children: ReactNode }> = ({ children }) => {
|
||||
[showDebug, debugDemos],
|
||||
);
|
||||
|
||||
const anchorItems = useMemo(
|
||||
() =>
|
||||
(tab?.toc || meta.toc).reduce<AnchorItem[]>((result, item) => {
|
||||
if (item.depth === 2) {
|
||||
result.push({ ...item });
|
||||
} else if (item.depth === 3) {
|
||||
const parent = result[result.length - 1];
|
||||
if (parent) {
|
||||
parent.children = parent.children || [];
|
||||
parent.children.push({ ...item });
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}, []),
|
||||
[tab?.toc, meta.toc],
|
||||
);
|
||||
|
||||
const isRTL = direction === 'rtl';
|
||||
|
||||
const mergedAuthorInfos = useMemo(() => {
|
||||
const { author } = meta.frontmatter;
|
||||
if (!author) {
|
||||
return [];
|
||||
}
|
||||
if (typeof author === 'string') {
|
||||
return author.split(',').map((item) => ({
|
||||
name: item,
|
||||
avatar: `https://github.com/${item}.png`,
|
||||
}));
|
||||
}
|
||||
if (Array.isArray(author)) {
|
||||
return author;
|
||||
}
|
||||
return [];
|
||||
}, [meta.frontmatter.author]);
|
||||
|
||||
return (
|
||||
<DemoContext.Provider value={contextValue}>
|
||||
<Col xxl={20} xl={19} lg={18} md={18} sm={24} xs={24}>
|
||||
{!!meta.frontmatter.toc && (
|
||||
<section className={styles.tocWrapper}>
|
||||
<Anchor
|
||||
className={styles.toc}
|
||||
affix={false}
|
||||
targetOffset={token.anchorTop}
|
||||
showInkInFixed
|
||||
items={anchorItems.map((item) => ({
|
||||
href: `#${item.id}`,
|
||||
title: item.title,
|
||||
key: item.id,
|
||||
children: item.children
|
||||
?.filter((child) => showDebug || !debugDemos.includes(child.id))
|
||||
.map((child) => ({
|
||||
key: child.id,
|
||||
href: `#${child.id}`,
|
||||
title: (
|
||||
<span className={classNames(debugDemos.includes(child.id) && 'toc-debug')}>
|
||||
{child?.title}
|
||||
</span>
|
||||
),
|
||||
})),
|
||||
}))}
|
||||
/>
|
||||
</section>
|
||||
)}
|
||||
<Suspense fallback={<Skeleton.Input active size="small" />}>
|
||||
<DocAnchor showDebug={showDebug} debugDemos={debugDemos} />
|
||||
</Suspense>
|
||||
<article className={classNames(styles.articleWrapper, { rtl: isRTL })}>
|
||||
{meta.frontmatter?.title ? (
|
||||
<Typography.Title style={{ fontSize: 30, position: 'relative' }}>
|
||||
@ -240,92 +75,43 @@ const Content: React.FC<{ children: ReactNode }> = ({ children }) => {
|
||||
{meta.frontmatter?.subtitle}
|
||||
|
||||
{!pathname.startsWith('/components/overview') && (
|
||||
<Suspense fallback={null}>
|
||||
<EditButton
|
||||
title={<FormattedMessage id="app.content.edit-page" />}
|
||||
filename={meta.frontmatter.filename}
|
||||
/>
|
||||
</Suspense>
|
||||
)}
|
||||
</Space>
|
||||
{pathname.startsWith('/components/') && <ComponentChangelog pathname={pathname} />}
|
||||
{pathname.startsWith('/components/') && (
|
||||
<Suspense fallback={null}>
|
||||
<ComponentChangelog pathname={pathname} />
|
||||
</Suspense>
|
||||
)}
|
||||
</Typography.Title>
|
||||
) : null}
|
||||
{/* 添加作者、时间等信息 */}
|
||||
{meta.frontmatter.date || meta.frontmatter.author ? (
|
||||
<Typography.Paragraph>
|
||||
<Space>
|
||||
{meta.frontmatter.date && (
|
||||
<span style={{ opacity: 0.65 }}>
|
||||
<CalendarOutlined /> {DayJS(meta.frontmatter.date).format('YYYY-MM-DD')}
|
||||
</span>
|
||||
)}
|
||||
{mergedAuthorInfos.map((info) => (
|
||||
<a
|
||||
href={`https://github.com/${info.name}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
key={info.name}
|
||||
>
|
||||
<Space size={3}>
|
||||
<AuthorAvatar name={info.name} avatar={info.avatar} />
|
||||
<span style={{ opacity: 0.65 }}>@{info.name}</span>
|
||||
</Space>
|
||||
</a>
|
||||
))}
|
||||
</Space>
|
||||
</Typography.Paragraph>
|
||||
) : null}
|
||||
<Suspense fallback={<Skeleton.Input active size="small" />}>
|
||||
<DocMeta />
|
||||
</Suspense>
|
||||
{!meta.frontmatter.__autoDescription && meta.frontmatter.description}
|
||||
<ConfigProvider theme={{ cssVar: {} }}>
|
||||
<div style={{ minHeight: 'calc(100vh - 64px)' }}>{children}</div>
|
||||
</ConfigProvider>
|
||||
{(meta.frontmatter?.zhihu_url ||
|
||||
meta.frontmatter?.yuque_url ||
|
||||
meta.frontmatter?.juejin_url) && (
|
||||
<Suspense fallback={<Skeleton.Input active size="small" />}>
|
||||
<ColumnCard
|
||||
zhihuLink={meta.frontmatter.zhihu_url}
|
||||
yuqueLink={meta.frontmatter.yuque_url}
|
||||
juejinLink={meta.frontmatter.juejin_url}
|
||||
/>
|
||||
)}
|
||||
{meta.frontmatter.filename && (
|
||||
<ContributorsList
|
||||
cache
|
||||
repo="ant-design"
|
||||
owner="ant-design"
|
||||
className={classNames(styles.contributorsList, { [styles.listMobile]: isMobile })}
|
||||
fileName={meta.frontmatter.filename}
|
||||
renderItem={(item, loading) => {
|
||||
if (!item || loading) {
|
||||
return <AvatarPlaceholder />;
|
||||
}
|
||||
if (item.username?.includes('github-actions')) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<Tooltip
|
||||
mouseEnterDelay={0.3}
|
||||
title={`${formatMessage({ id: 'app.content.contributors' })}: ${item.username}`}
|
||||
key={item.username}
|
||||
>
|
||||
<li>
|
||||
<a
|
||||
href={`https://github.com/${item.username}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Avatar size="small" src={item.url} alt={item.username}>
|
||||
{item.username}
|
||||
</Avatar>
|
||||
</a>
|
||||
</li>
|
||||
</Tooltip>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Suspense>
|
||||
<Suspense fallback={<Skeleton.Input active size="small" />}>
|
||||
<Contributors filename={meta.frontmatter.filename} />
|
||||
</Suspense>
|
||||
</article>
|
||||
<Suspense fallback={<Skeleton.Input active size="small" />}>
|
||||
<PrevAndNext rtl={isRTL} />
|
||||
</Suspense>
|
||||
<Suspense fallback={null}>
|
||||
<Footer />
|
||||
</Suspense>
|
||||
</Col>
|
||||
</DemoContext.Provider>
|
||||
);
|
||||
|
@ -1,12 +1,12 @@
|
||||
import type { FC, ReactNode } from 'react';
|
||||
import React from 'react';
|
||||
import { CodeOutlined, SkinOutlined } from '@ant-design/icons';
|
||||
import { Tabs } from 'antd';
|
||||
import { useRouteMeta } from 'dumi';
|
||||
import type { IContentTabsProps } from 'dumi/theme-default/slots/ContentTabs';
|
||||
import type { TabsProps } from 'rc-tabs';
|
||||
import { Tabs } from 'antd';
|
||||
|
||||
const titleMap: Record<string, string> = {
|
||||
const titleMap: Record<string, ReactNode> = {
|
||||
design: '设计',
|
||||
};
|
||||
|
||||
@ -23,24 +23,17 @@ const ContentTabs: FC<IContentTabsProps> = ({ tabs, tabKey, onChange }) => {
|
||||
|
||||
const items: TabsProps['items'] = [
|
||||
{
|
||||
label: (
|
||||
<span>
|
||||
<CodeOutlined />
|
||||
开发
|
||||
</span>
|
||||
),
|
||||
key: 'development',
|
||||
label: '开发',
|
||||
icon: <CodeOutlined />,
|
||||
},
|
||||
];
|
||||
|
||||
tabs?.forEach((tab) => {
|
||||
items.push({
|
||||
label: (
|
||||
<span>
|
||||
{iconMap[tab.key]}
|
||||
{titleMap[tab.key]}
|
||||
</span>
|
||||
),
|
||||
key: tab.key,
|
||||
label: titleMap[tab.key],
|
||||
icon: iconMap[tab.key],
|
||||
});
|
||||
});
|
||||
|
||||
@ -48,7 +41,7 @@ const ContentTabs: FC<IContentTabsProps> = ({ tabs, tabKey, onChange }) => {
|
||||
<Tabs
|
||||
items={items}
|
||||
activeKey={tabKey || 'development'}
|
||||
onChange={(key) => onChange(tabs.find((tab) => tab.key === key))}
|
||||
onChange={(key) => onChange(tabs?.find((tab) => tab.key === key))}
|
||||
style={{ margin: '32px 0 -16px' }}
|
||||
/>
|
||||
);
|
||||
|
@ -363,6 +363,20 @@ const Footer: React.FC = () => {
|
||||
url: 'https://kitchen.alipay.com',
|
||||
openExternal: true,
|
||||
},
|
||||
{
|
||||
icon: (
|
||||
<img
|
||||
src="https://mdn.alipayobjects.com/huamei_j9rjmc/afts/img/A*3ittT5OEo2gAAAAAAAAAAAAADvGmAQ/original"
|
||||
width={16}
|
||||
height={16}
|
||||
alt="Galacean"
|
||||
/>
|
||||
),
|
||||
title: <FormattedMessage id="app.footer.galacean" />,
|
||||
description: <FormattedMessage id="app.footer.galacean.slogan" />,
|
||||
url: 'https://galacean.antgroup.com/',
|
||||
openExternal: true,
|
||||
},
|
||||
{
|
||||
icon: (
|
||||
<img
|
||||
|
@ -25,15 +25,16 @@ const RESPONSIVE_SM = 1200;
|
||||
|
||||
const locales = {
|
||||
cn: {
|
||||
message:
|
||||
'语雀公益计划:大学生认证教育邮箱,即可免费获得语雀会员。语雀,支付宝匠心打造的在线文档平台。',
|
||||
shortMessage: '支付宝语雀 · 大学生公益计划火热进行中!',
|
||||
more: '了解更多',
|
||||
message: '语雀征文 · 说说你和开源的故事,赢取 Ant Design 精美周边 🎁',
|
||||
shortMessage: '语雀征文 · 说说你和开源的故事,赢取 Ant Design 精美周边 🎁',
|
||||
more: '前往了解',
|
||||
link: 'https://www.yuque.com/opensource2023',
|
||||
},
|
||||
en: {
|
||||
message: '',
|
||||
shortMessage: '',
|
||||
more: '',
|
||||
link: '',
|
||||
},
|
||||
};
|
||||
|
||||
@ -222,9 +223,11 @@ const Header: React.FC = () => {
|
||||
// Mirror url must have `/`, we add this for compatible
|
||||
const urlObj = new URL(currentUrl.replace(window.location.origin, url));
|
||||
if (urlObj.host.includes('antgroup')) {
|
||||
window.location.href = `${urlObj.href.replace(/\/$/, '')}/`;
|
||||
}
|
||||
urlObj.pathname = `${urlObj.pathname.replace(/\/$/, '')}/`;
|
||||
window.location.href = urlObj.toString();
|
||||
} else {
|
||||
window.location.href = urlObj.href.replace(/\/$/, '');
|
||||
}
|
||||
}, []);
|
||||
|
||||
const onLangChange = useCallback(() => {
|
||||
@ -366,26 +369,28 @@ const Header: React.FC = () => {
|
||||
</Popover>
|
||||
)}
|
||||
{isZhCN && bannerVisible && (
|
||||
<ConfigProvider theme={{ token: { colorInfoBg: '#daf5eb', colorTextBase: '#000' } }}>
|
||||
<ConfigProvider
|
||||
theme={{
|
||||
token: {
|
||||
colorInfoBg: 'linear-gradient(90deg, #84fab0, #8fd3f4)',
|
||||
colorTextBase: '#000',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Alert
|
||||
className={styles.banner}
|
||||
message={
|
||||
<>
|
||||
<img
|
||||
className={styles.icon}
|
||||
src="https://gw.alipayobjects.com/zos/rmsportal/XuVpGqBFxXplzvLjJBZB.svg"
|
||||
alt="yuque"
|
||||
/>
|
||||
<span>{isMobile ? locale.shortMessage : locale.message}</span>
|
||||
<a
|
||||
className={styles.link}
|
||||
href="https://www.yuque.com/yuque/blog/welfare-edu?source=antd"
|
||||
href={locale.link}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
onClick={() => {
|
||||
window.gtag?.('event', '点击', {
|
||||
event_category: 'top_banner',
|
||||
event_label: 'https://www.yuque.com/yuque/blog/welfare-edu?source=antd',
|
||||
event_label: locale.link,
|
||||
});
|
||||
}}
|
||||
>
|
||||
|
15
.github/PULL_REQUEST_TEMPLATE.md
vendored
15
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -61,18 +61,3 @@ Describe changes from the user side, and list all potential break changes or oth
|
||||
- [ ] Demo is updated/provided or not needed
|
||||
- [ ] TypeScript definition is updated/provided or not needed
|
||||
- [ ] Changelog is provided or not needed
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
Below are template for copilot to generate CR message.
|
||||
Please DO NOT modify it.
|
||||
-->
|
||||
|
||||
### 🚀 Summary
|
||||
|
||||
copilot:summary
|
||||
|
||||
### 🔍 Walkthrough
|
||||
|
||||
copilot:walkthrough
|
||||
|
14
.github/PULL_REQUEST_TEMPLATE/pr_cn.md
vendored
14
.github/PULL_REQUEST_TEMPLATE/pr_cn.md
vendored
@ -61,17 +61,3 @@
|
||||
- [ ] 代码演示已提供或无须提供
|
||||
- [ ] TypeScript 定义已补充或无须补充
|
||||
- [ ] Changelog 已提供或无须提供
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
以下为 copilot 自动生成的 CR 结果,请勿修改
|
||||
-->
|
||||
|
||||
### 🚀 概述
|
||||
|
||||
copilot:summary
|
||||
|
||||
### 🔍 实现细节
|
||||
|
||||
copilot:walkthrough
|
||||
|
2
.github/workflows/discussion-open-check.yml
vendored
2
.github/workflows/discussion-open-check.yml
vendored
@ -19,7 +19,7 @@ jobs:
|
||||
DING_TALK_TOKEN: |
|
||||
${{ secrets.DINGDING_BOT_TOKEN }}
|
||||
${{ secrets.DINGDING_BOT_COLLABORATOR_TOKEN }}
|
||||
notify_title: '🔥 @${{ github.event.discussion.user.login }} 创建了讨论:${{ github.event.discussion.title }} #${{ github.event.discussion.number }}'
|
||||
notify_title: '🔥 @${{ github.event.discussion.user.login }} 创建了讨论:${{ github.event.discussion.title }} ${{ github.event.discussion.html_url }}'
|
||||
notify_body: '### 🔥 @${{ github.event.discussion.user.login }} 创建了讨论:[${{ github.event.discussion.title }}](${{ github.event.discussion.html_url }}) <hr />'
|
||||
notify_footer: '> 💬 欢迎前往 GitHub 进行讨论,社区可能需要你的帮助。'
|
||||
at_all: false # whether to ding everybody
|
||||
|
4
.github/workflows/issue-labeled.yml
vendored
4
.github/workflows/issue-labeled.yml
vendored
@ -40,7 +40,9 @@ jobs:
|
||||
body: |
|
||||
Hello @${{ github.event.issue.user.login }}. Please provide a online reproduction by forking codesandbox of [antd@5.x](https://u.ant.design/codesandbox-repro) or [antd@4.x](https://u.ant.design/codesandbox-repro-4x), or provide a minimal GitHub repository. Issues labeled by `Need Reproduce` will be closed if no activities in 3 days.
|
||||
|
||||
你好 @${{ github.event.issue.user.login }}, 我们需要你提供一个在线的重现实例以便于我们帮你排查问题。你可以通过点击这里创建一个 [antd@5.x](https://u.ant.design/codesandbox-repro) 或 [antd@4.x](https://u.ant.design/codesandbox-repro-4x) 的 codesandbox,或者提供一个最小化的 GitHub 仓库。3 天内未跟进此 issue 将会被自动关闭。
|
||||
你好 @${{ github.event.issue.user.login }},我们需要你提供一个在线的重现实例以便于我们帮你排查问题。你可以通过点击这里创建一个 [antd@5.x](https://u.ant.design/codesandbox-repro) 或 [antd@4.x](https://u.ant.design/codesandbox-repro-4x) 的 codesandbox,或者提供一个最小化的 GitHub 仓库。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)
|
||||
|
||||
![](https://gw.alipayobjects.com/zos/antfincdn/y9kwg7DVCd/reproduce.gif)
|
||||
|
||||
|
2
.github/workflows/issue-open-check.yml
vendored
2
.github/workflows/issue-open-check.yml
vendored
@ -99,7 +99,7 @@ jobs:
|
||||
DING_TALK_TOKEN: |
|
||||
${{ secrets.DINGDING_BOT_TOKEN }}
|
||||
${{ secrets.DINGDING_BOT_COLLABORATOR_TOKEN }}
|
||||
notify_title: '🔥 @${{ github.event.issue.user.login }} 创建了 issue:${{ github.event.issue.title }} #${{ github.event.issue.number }}'
|
||||
notify_title: '🔥 @${{ github.event.issue.user.login }} 创建了 issue:${{ github.event.issue.title }} ${{ github.event.issue.html_url }}'
|
||||
notify_body: '### 🔥 @${{ github.event.issue.user.login }} 创建了 issue:[${{ github.event.issue.title }}](${{ github.event.issue.html_url }}) <hr />'
|
||||
notify_footer: '> 💬 欢迎前往 GitHub 进行讨论,社区可能需要你的帮助。'
|
||||
at_all: false # whether to ding everybody
|
||||
|
28
.github/workflows/pr-contributor-welcome.yml
vendored
Normal file
28
.github/workflows/pr-contributor-welcome.yml
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
# 当 PR 被合并时,留言欢迎加入共建群
|
||||
name: PullRequest Contributor Welcome
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- closed
|
||||
paths:
|
||||
- 'components/**'
|
||||
|
||||
jobs:
|
||||
comment:
|
||||
if: github.event.pull_request.merged == true && github.repository == 'ant-design/ant-design'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Comment on PR
|
||||
uses: actions-cool/maintain-one-comment@v3
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
body: |
|
||||
🎉 Thank you for your contribution! If you have not yet joined our DingTalk community group, please feel free to join us (when joining, please provide the link to this PR).
|
||||
|
||||
🎉 感谢您的贡献!如果您还没有加入钉钉社区群,请扫描下方二维码加入我们(加群时请提供此 PR 链接)。
|
||||
|
||||
<img src="https://github.com/ant-design/ant-design/assets/5378891/e24c6080-bf38-4523-b1cd-f6c43ad7375f" height="200" />
|
||||
|
||||
<!-- WELCOME_CONTRIBUTION -->
|
||||
body-include: '<!-- WELCOME_CONTRIBUTION -->'
|
9
.github/workflows/pr-open-check.yml
vendored
9
.github/workflows/pr-open-check.yml
vendored
@ -19,10 +19,13 @@ jobs:
|
||||
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. This PR is temporarily not accepted. Thank you again for your contribution! 😊
|
||||
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! 😊
|
||||
|
||||
你好 @${{ github.event.pull_request.user.login }}。这个 PR 提及的 issue 需要和设计师或核心团队进行确认,暂时不接受 PR,再次感谢你的贡献!😊
|
||||
close: true
|
||||
你好 @${{ github.event.pull_request.user.login }}。这个 PR 提及的 issue 需要和设计师或核心团队进行确认!感谢您的贡献!😊
|
||||
close: false
|
||||
reviewers: |
|
||||
MadCcc
|
||||
zombieJ
|
||||
|
||||
check-changelog:
|
||||
permissions:
|
||||
|
2
.github/workflows/preview-build.yml
vendored
2
.github/workflows/preview-build.yml
vendored
@ -74,7 +74,7 @@ jobs:
|
||||
run: npm run site
|
||||
env:
|
||||
SITE_ENV: development
|
||||
NODE_OPTIONS: "--max_old_space_size=4096 --openssl-legacy-provider"
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
|
||||
- name: upload site artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
|
6
.github/workflows/release-tweet.yml
vendored
6
.github/workflows/release-tweet.yml
vendored
@ -1,21 +1,21 @@
|
||||
name: 🐦 Release to Tweet
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
create
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
tweet:
|
||||
if: ${{ github.event.ref_type == 'tag' && !contains(github.event.ref, 'alpha') }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Tweet
|
||||
uses: nearform-actions/github-action-notify-twitter@v1
|
||||
with:
|
||||
message: |
|
||||
Ant Design (antd@${{ github.event.release.tag_name }}) has been released ~ 🎊🎊🎊 Check out the release notes: ${{ github.event.release.html_url }}
|
||||
🤖 Ant Design just released antd@${{ github.event.ref }} ✨🎊✨ Check out the full release note: https://github.com/ant-design/ant-design/releases/tag/${{ github.event.ref }}
|
||||
twitter-app-key: ${{ secrets.TWITTER_API_KEY }}
|
||||
twitter-app-secret: ${{ secrets.TWITTER_API_SECRET_KEY }}
|
||||
twitter-access-token: ${{ secrets.TWITTER_ACCESS_TOKEN }}
|
||||
|
4
.github/workflows/site-deploy.yml
vendored
4
.github/workflows/site-deploy.yml
vendored
@ -70,13 +70,13 @@ jobs:
|
||||
- name: build site
|
||||
run: npm run predeploy
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096 --openssl-legacy-provider"
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
|
||||
- name: build dist and bundle analyzer report
|
||||
run: npm run dist
|
||||
env:
|
||||
ANALYZER: 1
|
||||
NODE_OPTIONS: "--max_old_space_size=4096 --openssl-legacy-provider"
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
|
||||
- name: Get version
|
||||
id: publish-version
|
||||
|
2
.github/workflows/size-limit.yml
vendored
2
.github/workflows/size-limit.yml
vendored
@ -63,5 +63,5 @@ jobs:
|
||||
build_script: dist
|
||||
skip_step: install
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096 --openssl-legacy-provider"
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
PRODUCTION_ONLY: 1
|
||||
|
13
.github/workflows/test.yml
vendored
13
.github/workflows/test.yml
vendored
@ -131,7 +131,7 @@ jobs:
|
||||
- name: dist
|
||||
run: npm run dist
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096 --openssl-legacy-provider"
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
CI: 1
|
||||
needs: setup
|
||||
|
||||
@ -141,7 +141,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
react: ['16', '17', '18']
|
||||
module: ['dom', 'node', 'dist']
|
||||
module: ['dom', 'node', 'dist', 'dist-min']
|
||||
shard: ['1/2', '2/2']
|
||||
env:
|
||||
REACT: ${{ matrix.react }}
|
||||
@ -179,7 +179,7 @@ jobs:
|
||||
run: npm run install-react-18
|
||||
|
||||
- name: restore cache from dist
|
||||
if: ${{ matrix.module == 'dist' }}
|
||||
if: ${{ matrix.module == 'dist' || matrix.module == 'dist-min' }}
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: dist
|
||||
@ -224,6 +224,13 @@ jobs:
|
||||
run: npm test
|
||||
env:
|
||||
LIB_DIR: dist
|
||||
|
||||
# dist min test
|
||||
- name: dist-min test
|
||||
if: ${{ matrix.module == 'dist-min' }}
|
||||
run: npm test
|
||||
env:
|
||||
LIB_DIR: dist-min
|
||||
needs: [setup, dist]
|
||||
|
||||
############################ Test Coverage ###########################
|
||||
|
@ -1,63 +0,0 @@
|
||||
# Due to some special reasons, some accounts are blocked by circleCI
|
||||
# and cannot trigger argos jobs through circleCI.
|
||||
# These accounts can be configured in the whitelist list
|
||||
# and do not need to rely on circleCI to directly trigger argos in the PR workflow
|
||||
|
||||
name: Trigger Argos with white-listed users
|
||||
|
||||
on: [push]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
trigger_argos_with_whitelist_users:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Read white listed users
|
||||
id: read_users
|
||||
run: |
|
||||
whitelist_file="argos-white-listed-users"
|
||||
if [[ -f $whitelist_file ]]; then
|
||||
users=$(cat $whitelist_file)
|
||||
echo "whitelisted_users=$users" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Check if user is whitelisted
|
||||
id: check_user
|
||||
run: |
|
||||
whitelisted_users="${{ steps.read_users.outputs.whitelisted_users }}"
|
||||
current_user="${{ github.actor }}"
|
||||
if grep -Fxq "$current_user" <<< "$whitelisted_users"; then
|
||||
echo "User is whitelisted"
|
||||
echo "whitelisted=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "User is not whitelisted"
|
||||
echo "whitelisted=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: install dependencies
|
||||
if: ${{ steps.check_user.outputs.whitelisted == 'true' }}
|
||||
run: yarn
|
||||
|
||||
- name: Build dist file
|
||||
id: build
|
||||
if: ${{ steps.check_user.outputs.whitelisted == 'true' }}
|
||||
run: npm run dist:esbuild
|
||||
|
||||
- name: Run image screenshot tests
|
||||
id: screenshot
|
||||
if: ${{ steps.check_user.outputs.whitelisted == 'true' }}
|
||||
run: npm run test-image
|
||||
|
||||
- name: Upload screenshots to Argos CI
|
||||
id: upload
|
||||
if: ${{ steps.check_user.outputs.whitelisted == 'true' }}
|
||||
env:
|
||||
ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }}
|
||||
ARGOS_PARALLEL_NONCE: ${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}
|
||||
run: npm run argos
|
115
.github/workflows/visual-regression-diff-build.yml
vendored
Normal file
115
.github/workflows/visual-regression-diff-build.yml
vendored
Normal file
@ -0,0 +1,115 @@
|
||||
# Each PR will visual-regression diff that help to check code is work as expect.
|
||||
|
||||
name: 👀 Visual Regression Diff Build
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [master, feature]
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
# 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:
|
||||
# Prepare node modules. Reuse cache if available
|
||||
setup:
|
||||
name: prepare node_modules
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: cache package-lock.json
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: package-temp-dir
|
||||
key: lock-${{ github.sha }}
|
||||
|
||||
- name: create package-lock.json
|
||||
run: npm i --package-lock-only --ignore-scripts
|
||||
|
||||
- name: hack for single file
|
||||
run: |
|
||||
if [ ! -d "package-temp-dir" ]; then
|
||||
mkdir package-temp-dir
|
||||
fi
|
||||
cp package-lock.json package-temp-dir
|
||||
|
||||
- name: cache node_modules
|
||||
id: node_modules_cache_id
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: node_modules
|
||||
key: node_modules-${{ hashFiles('**/package-temp-dir/package-lock.json') }}
|
||||
|
||||
- name: install
|
||||
if: steps.node_modules_cache_id.outputs.cache-hit != 'true'
|
||||
run: npm ci
|
||||
|
||||
visual-diff-report:
|
||||
name: visual-diff report
|
||||
runs-on: ubuntu-latest
|
||||
needs: setup
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: restore cache from package-lock.json
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: package-temp-dir
|
||||
key: lock-${{ github.sha }}
|
||||
|
||||
- name: restore cache from node_modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: node_modules
|
||||
key: node_modules-${{ hashFiles('**/package-temp-dir/package-lock.json') }}
|
||||
|
||||
- name: generate image snapshots
|
||||
id: test-image
|
||||
run: |
|
||||
node node_modules/puppeteer/install.mjs
|
||||
npm run version
|
||||
npm run test-image
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
|
||||
# Execute visual regression diff task and zip then
|
||||
# output as visualRegressionReport.tar.gz
|
||||
- name: visual regression diff
|
||||
env:
|
||||
EVENT_NUMBER: ${{ github.event.number }}
|
||||
BASE_REF: ${{ github.base_ref }}
|
||||
run: |
|
||||
npm run visual-regression -- --pr-id=$EVENT_NUMBER --base-ref=$BASE_REF
|
||||
|
||||
# Upload report in `visualRegressionReport`
|
||||
- name: upload report artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
if: ${{ always() }}
|
||||
with:
|
||||
name: visual-regression-report
|
||||
path: visualRegressionReport.tar.gz
|
||||
|
||||
# Upload git ref for next workflow `visual-regression-diff-finish` use
|
||||
- name: Save persist key
|
||||
if: ${{ always() }}
|
||||
# should be pr id
|
||||
run: echo ${{ github.event.number }} > ./visual-regression-pr-id.txt
|
||||
|
||||
- name: Upload persist key
|
||||
if: ${{ always() }}
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: visual-regression-diff-ref
|
||||
path: ./visual-regression-pr-id.txt
|
135
.github/workflows/visual-regression-diff-finish.yml
vendored
Normal file
135
.github/workflows/visual-regression-diff-finish.yml
vendored
Normal file
@ -0,0 +1,135 @@
|
||||
# Each PR will visual-regression diff that help to check code is work as expect.
|
||||
|
||||
name: 👀 Visual Regression Diff Finish
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["👀 Visual Regression Diff Build"]
|
||||
types:
|
||||
- completed
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
upstream-workflow-summary:
|
||||
name: upstream workflow summary
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
jobs: ${{ steps.visual_diff_build_job_status.outputs.result }}
|
||||
build-status: ${{ steps.visual_diff_build_job_status.outputs.build-status }}
|
||||
steps:
|
||||
- name: summary jobs status
|
||||
uses: actions/github-script@v6
|
||||
id: visual_diff_build_job_status
|
||||
with:
|
||||
script: |
|
||||
const response = await github.rest.actions.listJobsForWorkflowRun({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
run_id: ${{ github.event.workflow_run.id }},
|
||||
});
|
||||
|
||||
// { [name]: [conclusion] }, e.g. { 'test image': 'success' }
|
||||
const jobs = (response.data?.jobs ?? []).reduce((acc, job) => {
|
||||
if(job?.status === 'completed' && 'name' in job && 'conclusion' in job) {
|
||||
acc[job.name] = job.conclusion;
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const total = Object.keys(jobs).length;
|
||||
if(total === 0) core.setFailed('no jobs found');
|
||||
|
||||
// the name here must be the same as `jobs.xxx.{name}`
|
||||
console.log('visual-diff report job status: %s', jobs['visual-diff report']);
|
||||
|
||||
// set output
|
||||
core.setOutput('build-status', jobs['visual-diff report']);
|
||||
return jobs;
|
||||
|
||||
download-visual-regression-report:
|
||||
name: download visual-regression report
|
||||
permissions:
|
||||
actions: read # for dawidd6/action-download-artifact to query and download artifacts
|
||||
issues: write # for actions-cool/maintain-one-comment to modify or create issue comments
|
||||
pull-requests: write # for actions-cool/maintain-one-comment to modify or create PR comments
|
||||
runs-on: ubuntu-latest
|
||||
needs: [upstream-workflow-summary]
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# We need get persist-index first
|
||||
- name: download image snapshot artifact
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
with:
|
||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
name: visual-regression-diff-ref
|
||||
|
||||
# Save PR id to output
|
||||
- name: save PR id
|
||||
id: pr
|
||||
run: echo "id=$(<visual-regression-pr-id.txt)" >> $GITHUB_OUTPUT
|
||||
|
||||
# Download report artifact
|
||||
- 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@v2
|
||||
with:
|
||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
name: visual-regression-report
|
||||
|
||||
# unzip report and then upload them to oss
|
||||
- name: upload visual-regression report
|
||||
id: report
|
||||
env:
|
||||
ALI_OSS_AK_ID: ${{ secrets.ALI_OSS_AK_ID }}
|
||||
ALI_OSS_AK_SECRET: ${{ secrets.ALI_OSS_AK_SECRET }}
|
||||
PR_ID: ${{ steps.pr.outputs.id }}
|
||||
run: |
|
||||
mkdir ./visualRegressionReport
|
||||
tar -xzvf visualRegressionReport.tar.gz -C ./visualRegressionReport
|
||||
echo "✅ Uncompress Finished"
|
||||
|
||||
rm package.json
|
||||
npm i ali-oss --no-save
|
||||
echo "✅ Install `ali-oss` Finished"
|
||||
|
||||
echo "🤖 Uploading"
|
||||
node scripts/visual-regression/upload.js ./visualRegressionReport --ref=pr-$PR_ID
|
||||
echo "✅ Uploaded"
|
||||
|
||||
delimiter="$(openssl rand -hex 8)"
|
||||
echo "content<<${delimiter}" >> "${GITHUB_OUTPUT}"
|
||||
echo "$(<visualRegressionReport/report.md)" >> "${GITHUB_OUTPUT}"
|
||||
echo "${delimiter}" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
- name: success comment
|
||||
uses: actions-cool/maintain-one-comment@v3
|
||||
if: ${{ steps.report.outcome == 'success' }}
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
body: |
|
||||
${{ steps.report.outputs.content }}
|
||||
<!-- VISUAL_DIFF_REGRESSION_HOOK -->
|
||||
body-include: '<!-- VISUAL_DIFF_REGRESSION_HOOK -->'
|
||||
number: ${{ steps.pr.outputs.id }}
|
||||
|
||||
- name: failed comment
|
||||
if: ${{ steps.download_report.outcome == 'failure' || steps.report.outcome == 'failure' || failure() }}
|
||||
uses: actions-cool/maintain-one-comment@v3
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
body: |
|
||||
## Visual Regression Build for PR #${{ steps.pr.outputs.id }} Failed ❌
|
||||
Potential causes:
|
||||
- `upstream workflow` status: ${{ needs.upstream-workflow-summary.outputs.build-status }}
|
||||
- `download report artifact` status: ${{ steps.download_report.outcome }}
|
||||
- `report upload` status: ${{ steps.report.outcome }}
|
||||
<!-- VISUAL_DIFF_REGRESSION_HOOK -->
|
||||
body-include: '<!-- VISUAL_DIFF_REGRESSION_HOOK -->'
|
||||
number: ${{ steps.pr.outputs.id }}
|
32
.github/workflows/visual-regression-diff-start.yml
vendored
Normal file
32
.github/workflows/visual-regression-diff-start.yml
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
# When `visual-regression-diff-build` start. Leave a message on the PR
|
||||
#
|
||||
# 🚨🚨🚨 Important 🚨🚨🚨
|
||||
# Never do any `checkout` or `npm install` action!
|
||||
# `pull_request_target` will enable PR to access the secrets!
|
||||
|
||||
name: 👀 Visual Regression Diff Start
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
branches: [master, feature]
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
visual-regression-diff-start:
|
||||
permissions:
|
||||
issues: write # for actions-cool/maintain-one-comment to modify or create issue comments
|
||||
pull-requests: write # for actions-cool/maintain-one-comment to modify or create PR comments
|
||||
name: start visual-regression diff
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: update status comment
|
||||
uses: actions-cool/maintain-one-comment@v3
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
body: |
|
||||
## Visual-Regression Diff Building...
|
||||
<!-- VISUAL_DIFF_REGRESSION_HOOK -->
|
||||
body-include: '<!-- VISUAL_DIFF_REGRESSION_HOOK -->'
|
104
.github/workflows/visual-regression-persist-finish.yml
vendored
Normal file
104
.github/workflows/visual-regression-persist-finish.yml
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
# Each `push on master` will persist image-snapshots that used as compare target in visual regression.
|
||||
|
||||
name: 👁️ Visual Regression Persist Finish
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["👁️ Visual Regression Persist Start"]
|
||||
types:
|
||||
- completed
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
upstream-workflow-summary:
|
||||
name: upstream workflow summary
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
jobs: ${{ steps.persist_start_job_status.outputs.result }}
|
||||
build-success: ${{ steps.persist_start_job_status.outputs.build-success }}
|
||||
build-failure: ${{ steps.persist_start_job_status.outputs.build-failure }}
|
||||
steps:
|
||||
- name: summary jobs status
|
||||
uses: actions/github-script@v6
|
||||
id: persist_start_job_status
|
||||
with:
|
||||
script: |
|
||||
const response = await github.rest.actions.listJobsForWorkflowRun({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
run_id: ${{ github.event.workflow_run.id }},
|
||||
});
|
||||
|
||||
// { [name]: [conclusion] }, e.g. { 'test image': 'success' }
|
||||
const jobs = (response.data?.jobs ?? []).reduce((acc, job) => {
|
||||
if(job?.status === 'completed' && 'name' in job && 'conclusion' in job) {
|
||||
acc[job.name] = job.conclusion;
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const total = Object.keys(jobs).length;
|
||||
if(total === 0) core.setFailed('no jobs found');
|
||||
|
||||
// the name here must be the same as `jobs.xxx.{name}`
|
||||
console.log('visual-diff report job status: %s', jobs['test image']);
|
||||
|
||||
// set output
|
||||
core.setOutput('build-success', jobs['test image'] === 'success');
|
||||
core.setOutput('build-failure', jobs['test image'] === 'failure');
|
||||
return jobs;
|
||||
|
||||
persist-image-snapshots:
|
||||
name: persist image-snapshots
|
||||
permissions:
|
||||
actions: read # for dawidd6/action-download-artifact to query and download artifacts
|
||||
runs-on: ubuntu-latest
|
||||
needs: [upstream-workflow-summary]
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# checkout the head sha/branch that triggered this workflow
|
||||
ref: ${{ github.event.workflow_run.head_sha || github.event.workflow_run.head_branch}}
|
||||
|
||||
# We need get persist key first
|
||||
- name: Download Visual Regression Ref
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
with:
|
||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
name: visual-regression-ref
|
||||
|
||||
# Save visual-regression ref to output
|
||||
- name: Extra Visual Regression Ref
|
||||
id: visual_regression
|
||||
run: echo "id=$(<visual-regression-ref.txt)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Download Visual-Regression Artifact
|
||||
if: ${{ fromJSON(needs.upstream-workflow-summary.outputs.build-success) }}
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
with:
|
||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
name: image-snapshots
|
||||
path: ./
|
||||
|
||||
- name: Persist Image Snapshot to OSS
|
||||
if: github.event.workflow_run.event == 'push' && (github.event.workflow_run.head_branch == 'master' || github.event.workflow_run.head_branch == 'feature')
|
||||
env:
|
||||
ALI_OSS_AK_ID: ${{ secrets.ALI_OSS_AK_ID }}
|
||||
ALI_OSS_AK_SECRET: ${{ secrets.ALI_OSS_AK_SECRET }}
|
||||
HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
|
||||
HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }}
|
||||
run: |
|
||||
rm package.json
|
||||
npm i ali-oss --no-save
|
||||
echo "✅ Install `ali-oss` Finished"
|
||||
|
||||
echo "🤖 Uploading"
|
||||
node scripts/visual-regression/upload.js ./imageSnapshots.tar.gz --ref=$HEAD_SHA
|
||||
node scripts/visual-regression/upload.js ./visual-regression-ref.txt --ref=$HEAD_BRANCH
|
||||
|
||||
echo "✅ Uploaded"
|
95
.github/workflows/visual-regression-persist-start.yml
vendored
Normal file
95
.github/workflows/visual-regression-persist-start.yml
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
# Each `push on master` will persist image-snapshots that used as compare target in visual regression.
|
||||
|
||||
name: 👁️ Visual Regression Persist Start
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- feature
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
# Prepare node modules. Reuse cache if available
|
||||
setup:
|
||||
name: prepare node_modules
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: cache package-lock.json
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: package-temp-dir
|
||||
key: lock-${{ github.sha }}
|
||||
|
||||
- name: create package-lock.json
|
||||
run: npm i --package-lock-only --ignore-scripts
|
||||
|
||||
- name: hack for single file
|
||||
run: |
|
||||
if [ ! -d "package-temp-dir" ]; then
|
||||
mkdir package-temp-dir
|
||||
fi
|
||||
cp package-lock.json package-temp-dir
|
||||
- name: cache node_modules
|
||||
id: node_modules_cache_id
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: node_modules
|
||||
key: node_modules-${{ hashFiles('**/package-temp-dir/package-lock.json') }}
|
||||
|
||||
- name: install
|
||||
if: steps.node_modules_cache_id.outputs.cache-hit != 'true'
|
||||
run: npm ci
|
||||
|
||||
test-image:
|
||||
name: test image
|
||||
runs-on: ubuntu-latest
|
||||
needs: setup
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: restore cache from package-lock.json
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: package-temp-dir
|
||||
key: lock-${{ github.sha }}
|
||||
|
||||
- name: restore cache from node_modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: node_modules
|
||||
key: node_modules-${{ hashFiles('**/package-temp-dir/package-lock.json') }}
|
||||
|
||||
- name: generate image snapshots
|
||||
run: |
|
||||
node node_modules/puppeteer/install.mjs
|
||||
npm run version
|
||||
npm run test-image
|
||||
tar -czvf imageSnapshots.tar.gz imageSnapshots/*
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
|
||||
# Upload `imageSnapshots` on master
|
||||
- name: upload report artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: image-snapshots
|
||||
path: imageSnapshots.tar.gz
|
||||
|
||||
# Upload git ref for next workflow `visual-regression-persist-finish` use
|
||||
- name: Save persist key
|
||||
if: ${{ always() }}
|
||||
run: echo ${{ github.sha }} > ./visual-regression-ref.txt
|
||||
|
||||
- name: Upload persist key
|
||||
if: ${{ always() }}
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: visual-regression-ref
|
||||
path: ./visual-regression-ref.txt
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -61,8 +61,9 @@ components/version/token-meta.json
|
||||
__diff_output__/
|
||||
__image_snapshots__/
|
||||
/jest-stare
|
||||
/imageSnapshots
|
||||
/imageSnapshots*
|
||||
/imageDiffSnapshots
|
||||
/visualRegressionReport*
|
||||
|
||||
.devcontainer*
|
||||
.husky/prepare-commit-msg
|
||||
|
@ -2,7 +2,7 @@ const { moduleNameMapper, transformIgnorePatterns } = require('./.jest');
|
||||
|
||||
// jest config for image snapshots
|
||||
module.exports = {
|
||||
setupFiles: ['./tests/setup.js'],
|
||||
setupFiles: ['./tests/setup.ts'],
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'md'],
|
||||
moduleNameMapper,
|
||||
transform: {
|
||||
@ -19,5 +19,5 @@ module.exports = {
|
||||
},
|
||||
},
|
||||
preset: 'jest-puppeteer',
|
||||
testTimeout: 10000,
|
||||
testTimeout: 20000,
|
||||
};
|
||||
|
4
.jest.js
4
.jest.js
@ -23,7 +23,7 @@ const transformIgnorePatterns = [
|
||||
];
|
||||
|
||||
function getTestRegex(libDir) {
|
||||
if (['dist', 'lib', 'es'].includes(libDir)) {
|
||||
if (['dist', 'lib', 'es', 'dist-min'].includes(libDir)) {
|
||||
return 'demo\\.test\\.(j|t)sx?$';
|
||||
}
|
||||
return '.*\\.test\\.(j|t)sx?$';
|
||||
@ -32,7 +32,7 @@ function getTestRegex(libDir) {
|
||||
module.exports = {
|
||||
verbose: true,
|
||||
testEnvironment: 'jsdom',
|
||||
setupFiles: ['./tests/setup.js', 'jest-canvas-mock'],
|
||||
setupFiles: ['./tests/setup.ts', 'jest-canvas-mock'],
|
||||
setupFilesAfterEnv: ['./tests/setupAfterEnv.ts'],
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'md'],
|
||||
modulePathIgnorePatterns: ['/_site/'],
|
||||
|
@ -2,7 +2,7 @@ const { moduleNameMapper, transformIgnorePatterns } = require('./.jest');
|
||||
|
||||
// jest config for server render environment
|
||||
module.exports = {
|
||||
setupFiles: ['./tests/setup.js'],
|
||||
setupFiles: ['./tests/setup.ts'],
|
||||
setupFilesAfterEnv: ['./tests/setupAfterEnv.ts'],
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'md'],
|
||||
moduleNameMapper,
|
||||
|
@ -16,6 +16,137 @@ tag: vVERSION
|
||||
|
||||
---
|
||||
|
||||
## 5.12.5
|
||||
|
||||
`2023-12-22`
|
||||
|
||||
- 💄 Fix Tabs style issue of editable mode when there is only "new" button left. [#46585](https://github.com/ant-design/ant-design/pull/46585) [@hzyhbk](https://github.com/hzyhbk)
|
||||
- 💄 Fix Progress style issue of `line` mode with `strokeLinecap`. [#46551](https://github.com/ant-design/ant-design/pull/46551) [@ZN1996](https://github.com/ZN1996)
|
||||
- 🐞 Fix ColorPicker not support `prefixCls`. [#46561](https://github.com/ant-design/ant-design/pull/46561)
|
||||
|
||||
## 5.12.4
|
||||
|
||||
`2023-12-19`
|
||||
|
||||
- 🐞 Fix DatePicker style in `cssVar` mode. [#46526](https://github.com/ant-design/ant-design/pull/46526)
|
||||
|
||||
## 5.12.3
|
||||
|
||||
`2023-12-18`
|
||||
|
||||
- 💄 Fix Tag that style would be missing in SSR. [#46500](https://github.com/ant-design/ant-design/pull/46500) [@MadCcc](https://github.com/MadCcc)
|
||||
- 🐞 Upload `disabled` prop should not affect download icon. [#46454](https://github.com/ant-design/ant-design/pull/46454)
|
||||
- 💄 Upload.Dragger add vertical padding style. [#46457](https://github.com/ant-design/ant-design/pull/46457)
|
||||
- 🐞 Fix Upload actions color issue. [#46456](https://github.com/ant-design/ant-design/pull/46456)
|
||||
- 🐞 Fix Form with `getValueProps` not working with value update. [#46445](https://github.com/ant-design/ant-design/pull/46445)
|
||||
- 💄 Fix Checkbox style when customize `token.lineWidth`. [#46431](https://github.com/ant-design/ant-design/pull/46431)
|
||||
- 🐞 Fix Select that custom token make `padding` broken. [#46427](https://github.com/ant-design/ant-design/pull/46427) [@MadCcc](https://github.com/MadCcc)
|
||||
- 🐞 Fix Message that token overrides not work in `cssVar` mode. [#46415](https://github.com/ant-design/ant-design/pull/46415) [@MadCcc](https://github.com/MadCcc)
|
||||
- 💄 Fix Flex component don't apply extra style. [#46404](https://github.com/ant-design/ant-design/pull/46404) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
|
||||
## 5.12.2
|
||||
|
||||
`2023-12-11`
|
||||
|
||||
- 🐞 MISC: Fix `useId` error when webpack build with React 17. [#46261](https://github.com/ant-design/ant-design/pull/46261)
|
||||
- Pagination
|
||||
- 🐞 Fix Pagination throws error in legacy browsers. [react-component/pagination#545](https://github.com/react-component/pagination/pull/545)
|
||||
- 🐞 Fix Pagination `current` not working in `simple` mode. [react-component/pagination#546](https://github.com/react-component/pagination/pull/546)
|
||||
- 🐞 Fix Table filter dropdown lost background color in CSS variables mode. [#46314](https://github.com/ant-design/ant-design/pull/46314)
|
||||
- 🐞 Prevent interaction when Spin component enable `fullscreen` prop. [#46303](https://github.com/ant-design/ant-design/pull/46303) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- 🐞 Fix Form `hideRequiredMark` prop's priority compared with ConfigProvider `form` prop. [#46299](https://github.com/ant-design/ant-design/pull/46299) [@linhf123](https://github.com/linhf123)
|
||||
- TypeScript
|
||||
- 🤖 Fix Descriptions `id` type. [#46367](https://github.com/ant-design/ant-design/pull/46367) [@RSS1102](https://github.com/RSS1102)
|
||||
|
||||
## 5.12.1
|
||||
|
||||
`2023-12-04`
|
||||
|
||||
- 🐞 MISC: Fix missing color less variables converted from token. [#46250](https://github.com/ant-design/ant-design/pull/46250)
|
||||
- 🐞 Fix Notification title overlaps with the close icon when it is too long。 [#46211](https://github.com/ant-design/ant-design/pull/46211) [@zh-lx](https://github.com/zh-lx)
|
||||
|
||||
## 5.12.0
|
||||
|
||||
`2023-12-04`
|
||||
|
||||
- 🔥 Component Token support CSS variables mode. For more detail, see [CSS Variables](/docs/react/css-variables). Special thank for contributors of this feature: [@li-jia-nan](https://github.com/li-jia-nan) [@RedJue](https://github.com/RedJue) [@c0dedance](https://github.com/c0dedance) [@kiner-tang](https://github.com/kiner-tang) [@JarvisArt](https://github.com/JarvisArt) [@cc-hearts](https://github.com/cc-hearts)
|
||||
- 🛠 Refactor rc-pagination from class component to FC. [#46204](https://github.com/ant-design/ant-design/pull/46204) [@Wxh16144](https://github.com/Wxh16144)
|
||||
- 🆕 Alert could support linear-gradient background by `colorInfoBg` token. [#46188](https://github.com/ant-design/ant-design/pull/46188)
|
||||
- 🆕 `Form.useWatch` support selector function param. [#46180](https://github.com/ant-design/ant-design/pull/46180) [@crazyair](https://github.com/crazyair)
|
||||
- 🆕 Slider support `onChangeComplete` and deprecate `onAfterChange`. [#46182](https://github.com/ant-design/ant-design/pull/46182) [@MadCcc](https://github.com/MadCcc)
|
||||
- 🆕 Tabs `items` support `icon` prop. [#46096](https://github.com/ant-design/ant-design/pull/46096) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- 🆕 Tour supports `getPopupContainer` property. [#45751](https://github.com/ant-design/ant-design/pull/45751) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- 🆕 Switch support for `value` and `defaultValue` props. [#45747](https://github.com/ant-design/ant-design/pull/45747) [@Wxh16144](https://github.com/Wxh16144)
|
||||
- 🐞 Fix that clicking Form `tooltip` icon should not trigger Switch. [#46155](https://github.com/ant-design/ant-design/pull/46155)
|
||||
- 🐞 Fix Notification that icon should have line-height. [#46148](https://github.com/ant-design/ant-design/pull/46148) [@MadCcc](https://github.com/MadCcc)
|
||||
- 🐞 Fix Progress that gradient in line should follow percent. [#46209](https://github.com/ant-design/ant-design/pull/46209) [@MadCcc](https://github.com/MadCcc)
|
||||
- 💄 Button could be customized to gradient style. [#46192](https://github.com/ant-design/ant-design/pull/46192)
|
||||
- 💄 Fix style of InputNumber with `addon` inside Space.Compact. [#46130](https://github.com/ant-design/ant-design/pull/46130) [@MadCcc](https://github.com/MadCcc)
|
||||
- TypeScript
|
||||
- 🤖 Update `FloatButtonProps` type with `React.DOMAttributes` in FloatButton. [#46175](https://github.com/ant-design/ant-design/pull/46175) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
|
||||
## 5.11.5
|
||||
|
||||
`2023-11-27`
|
||||
|
||||
- 🐞 MISC: Fix error in `dist` artifact. [#46103](https://github.com/ant-design/ant-design/pull/46103) [@MadCcc](https://github.com/MadCcc)
|
||||
- 💄 Fix DatePicker style when disabled and hovered. [#45940](https://github.com/ant-design/ant-design/pull/45940) [@crazyair](https://github.com/crazyair)
|
||||
|
||||
## 5.11.4
|
||||
|
||||
`2023-11-24`
|
||||
|
||||
- 🐞 Fix where Image sets `z-index` abnormally in nested Modal. [#46035](https://github.com/ant-design/ant-design/pull/46035)
|
||||
- 🐞 Fix Button that disabled link button should not have navigate options when right click. [#46021](https://github.com/ant-design/ant-design/pull/46021)
|
||||
- Card
|
||||
- 🛠 Refactor the Card internal method `getAction` into a function component. [#46032](https://github.com/ant-design/ant-design/pull/46032)
|
||||
- 🐞 Fix the problem of Card warning `invalid annotation` in Rollup. [#46024](https://github.com/ant-design/ant-design/pull/46024)
|
||||
- TypeScript
|
||||
- 🤖 Export the type definition for the `required` property of the Radio and Checkbox components. [#46028](https://github.com/ant-design/ant-design/pull/46028) [@nnmax](https://github.com/nnmax)
|
||||
|
||||
## 5.11.3
|
||||
|
||||
`2023-11-22`
|
||||
|
||||
- 🐞 Fix Modal static method create `zIndex` too high will cover other popup content. [#46012](https://github.com/ant-design/ant-design/pull/46012)
|
||||
- Image
|
||||
- 🆕 Image preview support mobile touch interactive. [#45989](https://github.com/ant-design/ant-design/pull/45989) [@JarvisArt](https://github.com/JarvisArt)
|
||||
- 🐞 Fixed Image preview `z-index` conflict when in a nested pop-up. [#45979](https://github.com/ant-design/ant-design/pull/45979) [@kiner-tang](https://github.com/kiner-tang)
|
||||
- 🐞 Fix Collapse header cursor style. [#45994](https://github.com/ant-design/ant-design/pull/45994)
|
||||
- 🐞 Fix ColorPicker not support Form disabled config. [#45978](https://github.com/ant-design/ant-design/pull/45978) [@RedJue](https://github.com/RedJue)
|
||||
- 🐞 Fix Typography.Text `ellipsis.tooltip` cannot open under Layout component. [#45962](https://github.com/ant-design/ant-design/pull/45962)
|
||||
- 🐞 Remove Select native 🔍 icon from search input in Safari. [#46008](https://github.com/ant-design/ant-design/pull/46008)
|
||||
- 💄 Remove Rate useless style.[#45927](https://github.com/ant-design/ant-design/pull/45927) [@JarvisArt](https://github.com/JarvisArt)
|
||||
- 🛠 UMD `antd.js` will try to reuse global `@ant-design/cssinjs` first now. [#46009](https://github.com/ant-design/ant-design/pull/46009)
|
||||
- 🌐 Improve `eu_ES` localization. [#45928](https://github.com/ant-design/ant-design/pull/45928) [@ionlizarazu](https://github.com/ionlizarazu)
|
||||
|
||||
## 5.11.2
|
||||
|
||||
`2023-11-17`
|
||||
|
||||
- 🆕 Table with `virtual` can now customize `components` except the `components.body`. [#45857](https://github.com/ant-design/ant-design/pull/45857)
|
||||
- 🐞 Fix Button with href and disabled that could be focused. [#45910](https://github.com/ant-design/ant-design/pull/45910) [@MadCcc](https://github.com/MadCcc)
|
||||
- 🐞 Fix `zIndex` logic problem that message and notification are covered when multiple Modal are opened. [#45911](https://github.com/ant-design/ant-design/pull/45911) [#45864](https://github.com/ant-design/ant-design/pull/45864) [@kiner-tang](https://github.com/kiner-tang)
|
||||
- 💄 Fix QRCode `style.padding` is not working. [#45815](https://github.com/ant-design/ant-design/pull/45815)
|
||||
- 💄 Optimize Carousel dots border radius style. [#45817](https://github.com/ant-design/ant-design/pull/45817)
|
||||
- TypeScript
|
||||
- 🤖 Optimize List `gutter` property type definition. [#45791](https://github.com/ant-design/ant-design/pull/45791) [@Asanio06](https://github.com/Asanio06)
|
||||
|
||||
## 5.11.1
|
||||
|
||||
`2023-11-09`
|
||||
|
||||
- 🐞 Fix Dropdown use wrong `zIndex` when nest items. [#45761](https://github.com/ant-design/ant-design/pull/45761)
|
||||
- 🐞 Fix Upload should show remove icon when `showRemoveIcon` is specified to true explicitly. [#45752](https://github.com/ant-design/ant-design/pull/45752)
|
||||
- 🐞 Fix Descriptions use `children` structure missing the Descriptions.Item `key` prop. [#45757](https://github.com/ant-design/ant-design/pull/45757)
|
||||
- 🐞 Fix Message that token specified in component scope not work. [#45721](https://github.com/ant-design/ant-design/pull/45721) [@MadCcc](https://github.com/MadCcc)
|
||||
- 🐞 Fix Popconfirm not compatible with `visible` prop. [#45702](https://github.com/ant-design/ant-design/pull/45702) [@linhf123](https://github.com/linhf123)
|
||||
- 🐞 Fix Tag default background color not correct. [#45711](https://github.com/ant-design/ant-design/pull/45711) [@kiner-tang](https://github.com/kiner-tang)
|
||||
- 💄 Fix Notification that `style.width` not work. [#45681](https://github.com/ant-design/ant-design/pull/45681) [@MadCcc](https://github.com/MadCcc)
|
||||
- 🐞 Fix App console unexpected attr warning when set `component=false`. [#45671](https://github.com/ant-design/ant-design/pull/45671) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- TypeScript
|
||||
- 🤖 App support generic type definition. [#45669](https://github.com/ant-design/ant-design/pull/45669) [@JexLau](https://github.com/JexLau)
|
||||
|
||||
## 5.11.0
|
||||
|
||||
`2023-11-03`
|
||||
|
@ -16,6 +16,137 @@ tag: vVERSION
|
||||
|
||||
---
|
||||
|
||||
## 5.12.5
|
||||
|
||||
`2023-12-22`
|
||||
|
||||
- 💄 修复 Tabs 在 可编辑模式下只剩新增按钮时按钮的样式问题[#46585](https://github.com/ant-design/ant-design/pull/46585) [@hzyhbk](https://github.com/hzyhbk)
|
||||
- 💄 修复 Progress `strokeLinecap` 不生效的问题。[#46551](https://github.com/ant-design/ant-design/pull/46551) [@ZN1996](https://github.com/ZN1996)
|
||||
- 🐞 修复 ColorPicker 配置 `prefixCls` 不生效的问题。[#46561](https://github.com/ant-design/ant-design/pull/46561)
|
||||
|
||||
## 5.12.4
|
||||
|
||||
`2023-12-19`
|
||||
|
||||
- 🐞 修复 DatePicker 组件在 CSS 变量模式下的样式错乱问题。[#46526](https://github.com/ant-design/ant-design/pull/46526)
|
||||
|
||||
## 5.12.3
|
||||
|
||||
`2023-12-18`
|
||||
|
||||
- 💄 修复 Tag 组件在 SSR 场景下的样式丢失问题。[#46500](https://github.com/ant-design/ant-design/pull/46500) [@MadCcc](https://github.com/MadCcc)
|
||||
- 🐞 Upload 的 `disabled` 属性不再对下载按钮生效。[#46454](https://github.com/ant-design/ant-design/pull/46454)
|
||||
- 💄 Upload.Dragger 增加一个水平内边距。[#46457](https://github.com/ant-design/ant-design/pull/46457)
|
||||
- 🐞 修复 Upload `actions` 的颜色问题。[#46456](https://github.com/ant-design/ant-design/pull/46456)
|
||||
- 🐞 修复 Form 使用 `getValueProps` 展示值无法更新的问题。[#46445](https://github.com/ant-design/ant-design/pull/46445)
|
||||
- 💄 修复 Checkbox 自定义 `token.lineWidth` 时勾选箭头错位问题。[#46431](https://github.com/ant-design/ant-design/pull/46431)
|
||||
- 🐞 修复 Select 组件定制 token 会让 padding 失效的问题。[#46427](https://github.com/ant-design/ant-design/pull/46427) [@MadCcc](https://github.com/MadCcc)
|
||||
- 🐞 修复 Message 在 `cssVar` 模式下覆盖组件 token 无效的问题。[#46415](https://github.com/ant-design/ant-design/pull/46415) [@MadCcc](https://github.com/MadCcc)
|
||||
- 💄 Flex 组件不应该应用额外的样式。[#46404](https://github.com/ant-design/ant-design/pull/46404) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
|
||||
## 5.12.2
|
||||
|
||||
`2023-12-11`
|
||||
|
||||
- 🐞 MISC: 修复 React 17 以下使用 webpack 构建时报错 `useId` 找不到的问题。[#46261](https://github.com/ant-design/ant-design/pull/46261)
|
||||
- Pagination
|
||||
- 🐞 修复 Pagination 在低版本浏览器上报错的问题。[react-component/pagination#545](https://github.com/react-component/pagination/pull/545)
|
||||
- 🐞 修复 Pagination `simple` 模式下 `current` 受控选中分页不生效的问题。[react-component/pagination#546](https://github.com/react-component/pagination/pull/546)
|
||||
- 🐞 修复 Table 筛选菜单在 CSS 变量模式下丢失背景色的问题。[#46314](https://github.com/ant-design/ant-design/pull/46314)
|
||||
- 🐞 优化 Spin 交互,全屏状态时禁止用户触发鼠标事件。[#46303](https://github.com/ant-design/ant-design/pull/46303) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- 🐞 修复 Form `hideRequiredMark` 属性的优先级低于 ConfigProvider 的 form 配置的问题。[#46299](https://github.com/ant-design/ant-design/pull/46299) [@linhf123](https://github.com/linhf123)
|
||||
- TypeScript
|
||||
- 🤖 修复 Descriptions TS 定义不支持 `id` 属性的问题。[#46367](https://github.com/ant-design/ant-design/pull/46367) [@RSS1102](https://github.com/RSS1102)
|
||||
|
||||
## 5.12.1
|
||||
|
||||
`2023-12-04`
|
||||
|
||||
- 🐞 MISC: 修复 token 转换 less 变量丢失的问题。[#46250](https://github.com/ant-design/ant-design/pull/46250)
|
||||
- 🐞 修复 Notification 标题太长时会与关闭图标重叠的问题。[#46211](https://github.com/ant-design/ant-design/pull/46211) [@zh-lx](https://github.com/zh-lx)
|
||||
|
||||
## 5.12.0
|
||||
|
||||
`2023-12-04`
|
||||
|
||||
- 🔥 Component Token 支持 CSS 变量模式,详情见 [使用 CSS 变量](/docs/react/css-variables-cn)。感谢以下同学对此的贡献:[@li-jia-nan](https://github.com/li-jia-nan) [@RedJue](https://github.com/RedJue) [@c0dedance](https://github.com/c0dedance) [@kiner-tang](https://github.com/kiner-tang) [@JarvisArt](https://github.com/JarvisArt) [@cc-hearts](https://github.com/cc-hearts)
|
||||
- 🛠 rc-pagination 重构为 FC。[#46204](https://github.com/ant-design/ant-design/pull/46204) [@Wxh16144](https://github.com/Wxh16144)
|
||||
- 🆕 `Form.useWatch` 支持 selector 函数参数调用。[#46180](https://github.com/ant-design/ant-design/pull/46180) [@crazyair](https://github.com/crazyair)
|
||||
- 🆕 Slider 组件支持 `onChangeComplete` 事件,并废弃 `onAfterChange`。[#46182](https://github.com/ant-design/ant-design/pull/46182) [@MadCcc](https://github.com/MadCcc)
|
||||
- 🆕 Tabs 配置项 `items` 支持 `icon` 属性。[#46096](https://github.com/ant-design/ant-design/pull/46096) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- 🆕 Tour 支持 `getPopupContainer` 属性。[#45751](https://github.com/ant-design/ant-design/pull/45751) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- 🆕 Switch 支持 `value` and `defaultValue` 属性。[#45747](https://github.com/ant-design/ant-design/pull/45747) [@Wxh16144](https://github.com/Wxh16144)
|
||||
- 🐞 修复 Progress 进度条视觉效果,渐变效果应该随着百分比改变。[#46209](https://github.com/ant-design/ant-design/pull/46209) [@MadCcc](https://github.com/MadCcc)
|
||||
- 🐞 修复点击 Form `tooltip` 图标会触发 Switch 切换的问题。[#46155](https://github.com/ant-design/ant-design/pull/46155)
|
||||
- 🐞 修复 Notification 图标行高为 0 的问题。[#46148](https://github.com/ant-design/ant-design/pull/46148) [@MadCcc](https://github.com/MadCcc)
|
||||
- 💄 Button 按钮支持自定义为渐变色风格。[#46192](https://github.com/ant-design/ant-design/pull/46192)
|
||||
- 💄 Alert 背景色现在可以通过 `colorInfoBg` token 定义为渐变色。[#46188](https://github.com/ant-design/ant-design/pull/46188)
|
||||
- 💄 修复 InputNumber 带有 `addon` 时在 Space.Compact 下使用的样式问题。[#46130](https://github.com/ant-design/ant-design/pull/46130) [@MadCcc](https://github.com/MadCcc)
|
||||
- TypeScript
|
||||
- 🤖 更新 FloatButton 的类型定义,透出原生事件处理函数类型。[#46175](https://github.com/ant-design/ant-design/pull/46175) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
|
||||
## 5.11.5
|
||||
|
||||
`2023-11-27`
|
||||
|
||||
- 🐞 MISC: 修复打包 `dist` 产物错误。[#46103](https://github.com/ant-design/ant-design/pull/46103) [@MadCcc](https://github.com/MadCcc)
|
||||
- 💄 修复 DatePicker 禁用状态下悬浮样式。[#45940](https://github.com/ant-design/ant-design/pull/45940) [@crazyair](https://github.com/crazyair)
|
||||
|
||||
## 5.11.4
|
||||
|
||||
`2023-11-24`
|
||||
|
||||
- 🐞 修复 Image 在嵌套 Modal 中设置 `z-index` 异常的问题。[#46035](https://github.com/ant-design/ant-design/pull/46035)
|
||||
- 🐞 修复 Button 禁用的链接按钮右键点击时会有打开新链接选项的问题。[#46021](https://github.com/ant-design/ant-design/pull/46021)
|
||||
- Card
|
||||
- 🛠 把 Card 内部方法 `getAction` 重构为函数组件。[#46032](https://github.com/ant-design/ant-design/pull/46032)
|
||||
- 🐞 解决 Card 在 Rollup 中会警告 `invalid annotation` 的问题。[#46024](https://github.com/ant-design/ant-design/pull/46024)
|
||||
- TypeScript
|
||||
- 🤖 导出 Radio 和 Checkbox 组件的 `required` 属性的类型定义。[#46028](https://github.com/ant-design/ant-design/pull/46028) [@nnmax](https://github.com/nnmax)
|
||||
|
||||
## 5.11.3
|
||||
|
||||
`2023-11-22`
|
||||
|
||||
- 🐞 修复 Modal 静态方法创建 `zIndex` 过高会覆盖其他弹出内容的问题。[#46012](https://github.com/ant-design/ant-design/pull/46012)
|
||||
- Image
|
||||
- 🆕 Image 预览支持移动触摸事件交互。[#45989](https://github.com/ant-design/ant-design/pull/45989) [@JarvisArt](https://github.com/JarvisArt)
|
||||
- 🐞 修复 Image 预览在嵌套弹框中 `z-index` 设置不正确的问题。[#45979](https://github.com/ant-design/ant-design/pull/45979) [@kiner-tang](https://github.com/kiner-tang)
|
||||
- 🐞 修复 Collapse 可折叠区域鼠标 `hover` 样式问题。[#45994](https://github.com/ant-design/ant-design/pull/45994)
|
||||
- 🐞 修复 ColorPicker 不支持 Form 组件的禁用问题。[#45978](https://github.com/ant-design/ant-design/pull/45978) [@RedJue](https://github.com/RedJue)
|
||||
- 🐞 修复 Typography.Text `code` 在 Layout 下开启 `ellipsis` 时 tooltip 无效的问题。[#45962](https://github.com/ant-design/ant-design/pull/45962)
|
||||
- 🐞 修复 Select 搜索框在 Safari 下显示多余的 🔍 图标。[#46008](https://github.com/ant-design/ant-design/pull/46008)
|
||||
- 💄 删除 Rate 组件无用样式。 [#45927](https://github.com/ant-design/ant-design/pull/45927) [@JarvisArt](https://github.com/JarvisArt)
|
||||
- 🛠 UMD 版本 `antd.js` 现在会优先使用全局的 `@ant-design/cssinjs` 依赖。[#46009](https://github.com/ant-design/ant-design/pull/46009)
|
||||
- 🌐 补充 `eu_ES` 国际化内容。[#45928](https://github.com/ant-design/ant-design/pull/45928) [@ionlizarazu](https://github.com/ionlizarazu)
|
||||
|
||||
## 5.11.2
|
||||
|
||||
`2023-11-17`
|
||||
|
||||
- 🆕 放开 Table `virtual` 下 `components` 的限制,现在除了 `components.body` 都可以自定义。[#45857](https://github.com/ant-design/ant-design/pull/45857)
|
||||
- 🐞 修复 Button 带有链接且禁用时可以被聚焦到的问题。[#45910](https://github.com/ant-design/ant-design/pull/45910) [@MadCcc](https://github.com/MadCcc)
|
||||
- 🐞 修复 `zIndex` 逻辑,解决多层 Modal 打开时,message 与 notification 被遮盖的问题。[#45911](https://github.com/ant-design/ant-design/pull/45911) [#45864](https://github.com/ant-design/ant-design/pull/45864) [@kiner-tang](https://github.com/kiner-tang)
|
||||
- 💄 修复 QRCode 设置 `style.padding` 时无效的问题。[#45815](https://github.com/ant-design/ant-design/pull/45815)
|
||||
- 💄 优化 Carousel 切换条圆角样式。[#45817](https://github.com/ant-design/ant-design/pull/45817)
|
||||
- TypeScript
|
||||
- 🤖 优化 List 属性 `gutter` 的类型定义。[#45791](https://github.com/ant-design/ant-design/pull/45791) [@Asanio06](https://github.com/Asanio06)
|
||||
|
||||
## 5.11.1
|
||||
|
||||
`2023-11-09`
|
||||
|
||||
- 🐞 修复 Dropdown 在嵌套列表时 `zIndex` 错误的问题。[#45761](https://github.com/ant-design/ant-design/pull/45761)
|
||||
- 🐞 修复 Upload 显式指定 `showRemoveIcon: true` 时删除图标未显示的问题。[#45752](https://github.com/ant-design/ant-design/pull/45752)
|
||||
- 🐞 修复 Descriptions 使用 `children` 结构语法糖时,会丢失 Descriptions.Item 的 `key` 的问题。[#45757](https://github.com/ant-design/ant-design/pull/45757)
|
||||
- 🐞 修复 Message 组件在组件范围设置全局 `token` 无效的问题。[#45721](https://github.com/ant-design/ant-design/pull/45721) [@MadCcc](https://github.com/MadCcc)
|
||||
- 🐞 修复 Popconfirm 不兼容 `visible` 的问题。[#45702](https://github.com/ant-design/ant-design/pull/45702) [@linhf123](https://github.com/linhf123)
|
||||
- 🐞 修复默认 Tag 的背景颜色不正确的问题。[#45711](https://github.com/ant-design/ant-design/pull/45711) [@kiner-tang](https://github.com/kiner-tang)
|
||||
- 💄 修复 Notification 组件设置 `style.width` 无效的问题。[#45681](https://github.com/ant-design/ant-design/pull/45681) [@MadCcc](https://github.com/MadCcc)
|
||||
- 🐞 修复 App 设置 `component=false` 时,会报非预期的属性警告的问题。[#45671](https://github.com/ant-design/ant-design/pull/45671) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- TypeScript
|
||||
- 🤖 App 支持泛型定义。[#45669](https://github.com/ant-design/ant-design/pull/45669) [@JexLau](https://github.com/JexLau)
|
||||
|
||||
## 5.11.0
|
||||
|
||||
`2023-11-03`
|
||||
|
@ -1,21 +1,21 @@
|
||||
<p align="center">
|
||||
<a href="https://ant.design">
|
||||
<img width="200" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg">
|
||||
</a>
|
||||
</p>
|
||||
<div align="center"><a name="readme-top"></a>
|
||||
|
||||
<h1 align="center">Ant Design</h1>
|
||||
<img height="180" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg">
|
||||
|
||||
<div align="center">
|
||||
<h1>Ant Design</h1>
|
||||
|
||||
一套企业级 UI 设计语言和 React 组件库。
|
||||
|
||||
[![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] [![NPM version][npm-image]][npm-url] [![NPM downloads][download-image]][download-url]
|
||||
|
||||
[![][bundlephobia-image]][bundlephobia-url] [![][bundlesize-js-image]][unpkg-js-url] [![FOSSA Status][fossa-image]][fossa-url] [![Covered by Argos Visual Testing][argos-ci-image]][argos-ci-url]
|
||||
[![][bundlephobia-image]][bundlephobia-url] [![][bundlesize-js-image]][unpkg-js-url] [![FOSSA Status][fossa-image]][fossa-url]
|
||||
|
||||
[![Follow Twitter][twitter-image]][twitter-url] [![Renovate status][renovate-image]][renovate-dashboard-url] [![][issues-helper-image]][issues-helper-url] [![dumi][dumi-image]][dumi-url] [![Issues need help][help-wanted-image]][help-wanted-url]
|
||||
|
||||
[更新日志](./CHANGELOG-zh-CN.md) · [报告问题][github-issues-url] · [特性需求][github-issues-url] · [English](./README.md) · 中文
|
||||
|
||||
![](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)
|
||||
|
||||
[npm-image]: http://img.shields.io/npm/v/antd.svg?style=flat-square
|
||||
[npm-url]: http://npmjs.org/package/antd
|
||||
[github-action-image]: https://github.com/ant-design/ant-design/workflows/%E2%9C%85%20test/badge.svg
|
||||
@ -34,21 +34,29 @@
|
||||
[unpkg-js-url]: https://unpkg.com/browse/antd/dist/antd.min.js
|
||||
[bundlephobia-image]: https://badgen.net/bundlephobia/minzip/antd?style=flat-square
|
||||
[bundlephobia-url]: https://bundlephobia.com/package/antd
|
||||
[issues-helper-image]: https://img.shields.io/badge/using-issues--helper-orange?style=flat-square
|
||||
[issues-helper-url]: https://github.com/actions-cool/issues-helper
|
||||
[issues-helper-image]: https://img.shields.io/badge/using-actions--cool-blue?style=flat-square
|
||||
[issues-helper-url]: https://github.com/actions-cool
|
||||
[renovate-image]: https://img.shields.io/badge/renovate-enabled-brightgreen.svg?style=flat-square
|
||||
[renovate-dashboard-url]: https://github.com/ant-design/ant-design/issues/32498
|
||||
[dumi-image]: https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square
|
||||
[dumi-url]: https://github.com/umijs/dumi
|
||||
[argos-ci-image]: https://argos-ci.com/badge.svg
|
||||
[argos-ci-url]: https://app.argos-ci.com/ant-design/ant-design/reference
|
||||
[github-issues-url]: https://new-issue.ant.design
|
||||
|
||||
<!-- Copy-paste in your Readme.md file -->
|
||||
|
||||
<a href="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats?repo_id=34526884" target="_blank" style="display: block" align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=dark" width="655" height="auto">
|
||||
<img alt="Performance Stats of ant-design/ant-design - Last 28 days" src="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=light" width="655" height="auto">
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
<!-- Made with [OSS Insight](https://ossinsight.io/) -->
|
||||
|
||||
</div>
|
||||
|
||||
[![](https://user-images.githubusercontent.com/507615/209472919-6f7e8561-be8c-4b0b-9976-eb3c692aa20a.png)](https://ant.design)
|
||||
|
||||
[English](./README.md) | 中文
|
||||
|
||||
## ✨ 特性
|
||||
|
||||
- 🌈 提炼自企业级中后台产品的交互语言和视觉风格。
|
||||
@ -154,6 +162,17 @@ $ npm start
|
||||
|
||||
## 🤝 参与共建 [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
|
||||
|
||||
<!-- Copy-paste in your Readme.md file -->
|
||||
|
||||
<a href="https://next.ossinsight.io/widgets/official/compose-recent-active-contributors?repo_id=34526884&limit=30" target="_blank" style="display: block" align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-recent-active-contributors/thumbnail.png?repo_id=34526884&limit=30&image_size=auto&color_scheme=dark" width="655" height="auto">
|
||||
<img alt="Active Contributors of ant-design/ant-design - Last 28 days" src="https://next.ossinsight.io/widgets/official/compose-recent-active-contributors/thumbnail.png?repo_id=34526884&limit=30&image_size=auto&color_scheme=light" width="655" height="auto">
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
<!-- Made with [OSS Insight](https://ossinsight.io/) -->
|
||||
|
||||
请参考[贡献指南](https://ant.design/docs/react/contributing-cn).
|
||||
|
||||
> 强烈推荐阅读 [《提问的智慧》](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way)、[《如何向开源社区提问题》](https://github.com/seajs/seajs/issues/545) 和 [《如何有效地报告 Bug》](http://www.chiark.greenend.org.uk/%7Esgtatham/bugs-cn.html)、[《如何向开源项目提交无法解答的问题》](https://zhuanlan.zhihu.com/p/25795393),更好的问题更容易获得帮助。
|
||||
|
69
README.md
69
README.md
@ -1,20 +1,29 @@
|
||||
<p align="center">
|
||||
<a href="https://ant.design">
|
||||
<img width="200" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg">
|
||||
</a>
|
||||
</p>
|
||||
<div align="center"><a name="readme-top"></a>
|
||||
|
||||
<h1 align="center">Ant Design</h1>
|
||||
<img height="180" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg">
|
||||
|
||||
<div align="center">
|
||||
<h1>Ant Design</h1>
|
||||
|
||||
An enterprise-class UI design language and React UI library.
|
||||
|
||||
[![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] [![NPM version][npm-image]][npm-url] [![NPM downloads][download-image]][download-url]
|
||||
[![CI status][github-action-image]][github-action-url]
|
||||
[![codecov][codecov-image]][codecov-url]
|
||||
[![NPM version][npm-image]][npm-url]
|
||||
[![NPM downloads][download-image]][download-url]
|
||||
|
||||
[![][bundlephobia-image]][bundlephobia-url] [![][bundlesize-js-image]][unpkg-js-url] [![FOSSA Status][fossa-image]][fossa-url] [![Covered by Argos Visual Testing][argos-ci-image]][argos-ci-url]
|
||||
[![][bundlephobia-image]][bundlephobia-url]
|
||||
[![][bundlesize-js-image]][unpkg-js-url]
|
||||
[![FOSSA Status][fossa-image]][fossa-url]
|
||||
|
||||
[![Follow Twitter][twitter-image]][twitter-url] [![Renovate status][renovate-image]][renovate-dashboard-url] [![][issues-helper-image]][issues-helper-url] [![dumi][dumi-image]][dumi-url] [![Issues need help][help-wanted-image]][help-wanted-url]
|
||||
[![Follow Twitter][twitter-image]][twitter-url]
|
||||
[![Renovate status][renovate-image]][renovate-dashboard-url]
|
||||
[![][issues-helper-image]][issues-helper-url]
|
||||
[![dumi][dumi-image]][dumi-url]
|
||||
[![Issues need help][help-wanted-image]][help-wanted-url]
|
||||
|
||||
[Changelog](./CHANGELOG.en-US.md) · [Report Bug][github-issues-url] · [Request Feature][github-issues-url] · English · [中文](./README-zh_CN.md)
|
||||
|
||||
![](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)
|
||||
|
||||
[npm-image]: http://img.shields.io/npm/v/antd.svg?style=flat-square
|
||||
[npm-url]: http://npmjs.org/package/antd
|
||||
@ -40,15 +49,23 @@ An enterprise-class UI design language and React UI library.
|
||||
[renovate-dashboard-url]: https://github.com/ant-design/ant-design/issues/32498
|
||||
[dumi-image]: https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square
|
||||
[dumi-url]: https://github.com/umijs/dumi
|
||||
[argos-ci-image]: https://argos-ci.com/badge.svg
|
||||
[argos-ci-url]: https://app.argos-ci.com/ant-design/ant-design/reference
|
||||
[github-issues-url]: https://new-issue.ant.design
|
||||
|
||||
<!-- Copy-paste in your Readme.md file -->
|
||||
|
||||
<a href="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats?repo_id=34526884" target="_blank" style="display: block" align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=dark" width="655" height="auto">
|
||||
<img alt="Performance Stats of ant-design/ant-design - Last 28 days" src="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=light" width="655" height="auto">
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
<!-- Made with [OSS Insight](https://ossinsight.io/) -->
|
||||
|
||||
</div>
|
||||
|
||||
[![](https://user-images.githubusercontent.com/507615/209472919-6f7e8561-be8c-4b0b-9976-eb3c692aa20a.png)](https://ant.design)
|
||||
|
||||
English | [中文](./README-zh_CN.md)
|
||||
|
||||
## ✨ Features
|
||||
|
||||
- 🌈 Enterprise-class UI designed for web applications.
|
||||
@ -85,27 +102,16 @@ pnpm add antd
|
||||
## 🔨 Usage
|
||||
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import { Button, DatePicker } from 'antd';
|
||||
|
||||
const App = () => (
|
||||
export default () => (
|
||||
<>
|
||||
<Button type="primary">PRESS ME</Button>
|
||||
<DatePicker placeholder="select date" />
|
||||
</>
|
||||
);
|
||||
|
||||
export default App;
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
|
||||
`antd` is written in TypeScript with complete definitions, check [Usage with create-react-app](https://ant.design/docs/react/use-with-create-react-app) to get started.
|
||||
|
||||
## 🌍 Internationalization
|
||||
|
||||
Dozens of languages are supported in `antd`, see [i18n](https://ant.design/docs/react/i18n).
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
- [Home page](https://ant.design/)
|
||||
@ -148,6 +154,17 @@ Open your browser and visit http://127.0.0.1:8001 , see more at [Development](ht
|
||||
|
||||
## 🤝 Contributing [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
|
||||
|
||||
<!-- Copy-paste in your Readme.md file -->
|
||||
|
||||
<a href="https://next.ossinsight.io/widgets/official/compose-recent-active-contributors?repo_id=34526884&limit=30" target="_blank" style="display: block" align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-recent-active-contributors/thumbnail.png?repo_id=34526884&limit=30&image_size=auto&color_scheme=dark" width="655" height="auto">
|
||||
<img alt="Active Contributors of ant-design/ant-design - Last 28 days" src="https://next.ossinsight.io/widgets/official/compose-recent-active-contributors/thumbnail.png?repo_id=34526884&limit=30&image_size=auto&color_scheme=light" width="655" height="auto">
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
<!-- Made with [OSS Insight](https://ossinsight.io/) -->
|
||||
|
||||
Let's build a better antd together.
|
||||
|
||||
We welcome all contributions. Please read our [Contributing Guide](https://ant.design/docs/react/contributing) first. You can submit any ideas as [Pull Requests](https://github.com/ant-design/ant-design/pulls) or as [GitHub Issues](https://github.com/ant-design/ant-design/issues). If you'd like to improve code, check out the [Development Instructions](https://github.com/ant-design/ant-design/wiki/Development) and have a good time! :)
|
||||
|
19
alias/cssinjs.js
Normal file
19
alias/cssinjs.js
Normal file
@ -0,0 +1,19 @@
|
||||
/* eslint-disable global-require, import/no-unresolved */
|
||||
|
||||
// This is a alias proxy, which will use global `@ant-design/cssinjs` first.
|
||||
// Use local if global not found.
|
||||
let cssinjs;
|
||||
|
||||
if (typeof window !== 'undefined' && window.antdCssinjs) {
|
||||
// Use window UMD version
|
||||
cssinjs = window.antdCssinjs;
|
||||
} else if (typeof global !== 'undefined' && global.antdCssinjs) {
|
||||
// Use global UMD version
|
||||
cssinjs = global.antdCssinjs;
|
||||
} else {
|
||||
// Use local version.
|
||||
// Use relative path since webpack will also replace module here.
|
||||
cssinjs = require('../node_modules/@ant-design/cssinjs');
|
||||
}
|
||||
|
||||
module.exports = cssinjs;
|
@ -1 +0,0 @@
|
||||
kiner-tang
|
@ -1,22 +1,15 @@
|
||||
import useMergedState from 'rc-util/lib/hooks/useMergedState';
|
||||
import * as React from 'react';
|
||||
import ConfigProvider, { ConfigContext } from '../config-provider';
|
||||
import useMergedState from 'rc-util/lib/hooks/useMergedState';
|
||||
|
||||
export function withPureRenderTheme(Component: any) {
|
||||
return function PureRenderThemeComponent(props: any) {
|
||||
return (
|
||||
<ConfigProvider
|
||||
theme={{
|
||||
token: {
|
||||
motion: false,
|
||||
zIndexPopupBase: 0,
|
||||
},
|
||||
}}
|
||||
>
|
||||
import ConfigProvider, { ConfigContext } from '../config-provider';
|
||||
import type { AnyObject } from './type';
|
||||
|
||||
export function withPureRenderTheme<T extends AnyObject = AnyObject>(Component: React.FC<T>) {
|
||||
return (props: T) => (
|
||||
<ConfigProvider theme={{ token: { motion: false, zIndexPopupBase: 0 } }}>
|
||||
<Component {...props} />
|
||||
</ConfigProvider>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export interface BaseProps {
|
||||
@ -25,15 +18,15 @@ export interface BaseProps {
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
export default function genPurePanel<ComponentProps extends BaseProps>(
|
||||
const genPurePanel = <ComponentProps extends BaseProps = BaseProps>(
|
||||
Component: any,
|
||||
defaultPrefixCls?: string,
|
||||
getDropdownCls?: null | ((prefixCls: string) => string),
|
||||
postProps?: (props: ComponentProps) => ComponentProps,
|
||||
) {
|
||||
type WrapProps = Omit<ComponentProps, 'open' | 'visible'> & { open?: boolean };
|
||||
) => {
|
||||
type WrapProps = ComponentProps & AnyObject;
|
||||
|
||||
function PurePanel(props: WrapProps) {
|
||||
const PurePanel: React.FC<WrapProps> = (props) => {
|
||||
const { prefixCls: customizePrefixCls, style } = props;
|
||||
|
||||
const holderRef = React.useRef<HTMLDivElement>(null);
|
||||
@ -88,22 +81,21 @@ export default function genPurePanel<ComponentProps extends BaseProps>(
|
||||
};
|
||||
|
||||
if (postProps) {
|
||||
mergedProps = postProps(mergedProps as ComponentProps);
|
||||
mergedProps = postProps(mergedProps);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={holderRef}
|
||||
style={{
|
||||
const mergedStyle: React.CSSProperties = {
|
||||
paddingBottom: popupHeight,
|
||||
position: 'relative',
|
||||
minWidth: popupWidth,
|
||||
}}
|
||||
>
|
||||
};
|
||||
return (
|
||||
<div ref={holderRef} style={mergedStyle}>
|
||||
<Component {...mergedProps} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
return withPureRenderTheme(PurePanel);
|
||||
}
|
||||
return withPureRenderTheme<AnyObject>(PurePanel);
|
||||
};
|
||||
|
||||
export default genPurePanel;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import type { MenuProps } from 'antd';
|
||||
import type { ImageProps, MenuProps } from 'antd';
|
||||
import {
|
||||
AutoComplete,
|
||||
Cascader,
|
||||
@ -9,6 +9,7 @@ import {
|
||||
DatePicker,
|
||||
Drawer,
|
||||
Dropdown,
|
||||
Image,
|
||||
Menu,
|
||||
Modal,
|
||||
Popconfirm,
|
||||
@ -150,6 +151,7 @@ const consumerComponent: Record<ZIndexConsumer, React.FC<{ rootClassName: string
|
||||
options={options}
|
||||
open
|
||||
/>
|
||||
<ColorPicker {...props} open rootClassName={`${rootClassName} comp-item comp-ColorPicker`} />
|
||||
</>
|
||||
),
|
||||
Dropdown: (props) => (
|
||||
@ -166,7 +168,6 @@ const consumerComponent: Record<ZIndexConsumer, React.FC<{ rootClassName: string
|
||||
<button type="button">test</button>
|
||||
</Dropdown>
|
||||
),
|
||||
ColorPicker: (props) => <ColorPicker {...props} open />,
|
||||
DatePicker: ({ rootClassName, ...props }) => (
|
||||
<>
|
||||
<DatePicker {...props} rootClassName={`${rootClassName} comp-item comp-DatePicker`} open />
|
||||
@ -178,13 +179,36 @@ const consumerComponent: Record<ZIndexConsumer, React.FC<{ rootClassName: string
|
||||
</>
|
||||
),
|
||||
Menu: (props) => <Menu {...props} items={items} defaultOpenKeys={['SubMenu']} />,
|
||||
ImagePreview: ({ rootClassName }: ImageProps) => (
|
||||
<>
|
||||
<Image
|
||||
src="xxx"
|
||||
preview={{
|
||||
visible: true,
|
||||
rootClassName: `${rootClassName} comp-item comp-ImagePreview`,
|
||||
}}
|
||||
/>
|
||||
<Image.PreviewGroup
|
||||
preview={{
|
||||
visible: true,
|
||||
rootClassName: `${rootClassName} comp-item comp-ImagePreviewGroup`,
|
||||
}}
|
||||
>
|
||||
<Image src="xxx" />
|
||||
</Image.PreviewGroup>
|
||||
</>
|
||||
),
|
||||
};
|
||||
|
||||
function getConsumerSelector(baseSelector: string, consumer: ZIndexConsumer): string {
|
||||
let selector = baseSelector;
|
||||
if (consumer === 'SelectLike') {
|
||||
selector = ['Select', 'Cascader', 'TreeSelect', 'AutoComplete']
|
||||
.map((item) => `${baseSelector}.comp-${item}.ant-slide-up`)
|
||||
selector = ['Select', 'Cascader', 'TreeSelect', 'AutoComplete', 'ColorPicker']
|
||||
.map((item) =>
|
||||
item === 'ColorPicker'
|
||||
? `${baseSelector}.ant-popover-placement-bottomLeft`
|
||||
: `${baseSelector}.comp-${item}.ant-slide-up`,
|
||||
)
|
||||
.join(',');
|
||||
} else if (consumer === 'DatePicker') {
|
||||
selector = ['DatePicker', 'TimePicker']
|
||||
@ -192,8 +216,13 @@ function getConsumerSelector(baseSelector: string, consumer: ZIndexConsumer): st
|
||||
.join(',');
|
||||
} else if (['Menu'].includes(consumer)) {
|
||||
selector = `${baseSelector}.ant-menu-submenu-placement-rightTop`;
|
||||
} else if (consumer === 'ColorPicker') {
|
||||
selector = `${baseSelector}.ant-popover-placement-bottomLeft`;
|
||||
} else if (consumer === 'ImagePreview') {
|
||||
selector = ['ImagePreview', 'ImagePreviewGroup']
|
||||
.map(
|
||||
(item) =>
|
||||
`${baseSelector}.comp-${item} .ant-image-preview-wrap, ${baseSelector}.comp-${item}.ant-image-preview-operations-wrapper`,
|
||||
)
|
||||
.join(',');
|
||||
}
|
||||
return selector;
|
||||
}
|
||||
@ -232,7 +261,8 @@ describe('Test useZIndex hooks', () => {
|
||||
);
|
||||
render(<App />);
|
||||
expect(fn).toHaveBeenLastCalledWith(
|
||||
(1000 + containerBaseZIndexOffset[containerKey as ZIndexContainer]) * 3 +
|
||||
1000 +
|
||||
containerBaseZIndexOffset[containerKey as ZIndexContainer] * 3 +
|
||||
consumerBaseZIndexOffset[key as ZIndexConsumer],
|
||||
);
|
||||
});
|
||||
@ -261,28 +291,45 @@ describe('Test useZIndex hooks', () => {
|
||||
const selector2 = getConsumerSelector('.consumer2', key as ZIndexConsumer);
|
||||
const selector3 = getConsumerSelector('.consumer3', key as ZIndexConsumer);
|
||||
|
||||
if (['SelectLike', 'DatePicker'].includes(key)) {
|
||||
if (['SelectLike', 'DatePicker', 'ImagePreview'].includes(key)) {
|
||||
let comps = document.querySelectorAll(selector1);
|
||||
comps.forEach((comp) => {
|
||||
expect((comp as HTMLDivElement).style.zIndex).toBeFalsy();
|
||||
});
|
||||
comps = document.querySelectorAll(selector2);
|
||||
comps.forEach((comp) => {
|
||||
const isColorPicker = (comp as HTMLDivElement).className.includes('comp-ColorPicker');
|
||||
const consumerOffset = isColorPicker
|
||||
? containerBaseZIndexOffset.Popover
|
||||
: consumerBaseZIndexOffset[key as ZIndexConsumer];
|
||||
const operOffset = comp.classList.contains('ant-image-preview-operations-wrapper')
|
||||
? 1
|
||||
: 0;
|
||||
expect((comp as HTMLDivElement).style.zIndex).toBe(
|
||||
String(
|
||||
1000 +
|
||||
containerBaseZIndexOffset[containerKey as ZIndexContainer] +
|
||||
consumerBaseZIndexOffset[key as ZIndexConsumer],
|
||||
consumerOffset +
|
||||
operOffset,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
comps = document.querySelectorAll(selector3);
|
||||
comps.forEach((comp) => {
|
||||
const isColorPicker = (comp as HTMLDivElement).className.includes('comp-ColorPicker');
|
||||
const consumerOffset = isColorPicker
|
||||
? containerBaseZIndexOffset.Popover
|
||||
: consumerBaseZIndexOffset[key as ZIndexConsumer];
|
||||
const operOffset = comp.classList.contains('ant-image-preview-operations-wrapper')
|
||||
? 1
|
||||
: 0;
|
||||
expect((comp as HTMLDivElement).style.zIndex).toBe(
|
||||
String(
|
||||
(1000 + containerBaseZIndexOffset[containerKey as ZIndexContainer]) * 2 +
|
||||
consumerBaseZIndexOffset[key as ZIndexConsumer],
|
||||
1000 +
|
||||
containerBaseZIndexOffset[containerKey as ZIndexContainer] * 2 +
|
||||
consumerOffset +
|
||||
operOffset,
|
||||
),
|
||||
);
|
||||
});
|
||||
@ -296,6 +343,7 @@ describe('Test useZIndex hooks', () => {
|
||||
(document.querySelector(selector1) as HTMLDivElement).style.zIndex,
|
||||
).toBeFalsy();
|
||||
}
|
||||
|
||||
expect((document.querySelector(selector2) as HTMLDivElement).style.zIndex).toBe(
|
||||
String(
|
||||
1000 +
|
||||
@ -306,15 +354,44 @@ describe('Test useZIndex hooks', () => {
|
||||
|
||||
expect((document.querySelector(selector3) as HTMLDivElement).style.zIndex).toBe(
|
||||
String(
|
||||
(1000 + containerBaseZIndexOffset[containerKey as ZIndexContainer]) * 2 +
|
||||
1000 +
|
||||
containerBaseZIndexOffset[containerKey as ZIndexContainer] * 2 +
|
||||
consumerBaseZIndexOffset[key as ZIndexConsumer],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
unmount();
|
||||
}, 15000);
|
||||
}, 20000);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Modal static func should always use max zIndex', async () => {
|
||||
jest.useFakeTimers();
|
||||
|
||||
const instance = Modal.confirm({
|
||||
title: 'bamboo',
|
||||
content: <Select open />,
|
||||
});
|
||||
|
||||
await waitFakeTimer();
|
||||
|
||||
expect(document.querySelector('.ant-modal-wrap')).toHaveStyle({
|
||||
zIndex: '2000',
|
||||
});
|
||||
|
||||
expect(document.querySelector('.ant-select-dropdown')).toHaveStyle({
|
||||
zIndex: '2050',
|
||||
});
|
||||
|
||||
instance.destroy();
|
||||
|
||||
await waitFakeTimer();
|
||||
|
||||
// Clean up for static method
|
||||
document.body.innerHTML = '';
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
type RecordType = Record<string, any>;
|
||||
import type { AnyObject } from './type';
|
||||
|
||||
function extendsObject<T extends RecordType>(...list: T[]) {
|
||||
const result: RecordType = { ...list[0] };
|
||||
const extendsObject = <T extends AnyObject = AnyObject>(...list: T[]) => {
|
||||
const result: AnyObject = { ...list[0] };
|
||||
|
||||
for (let i = 1; i < list.length; i++) {
|
||||
const obj = list[i];
|
||||
@ -16,6 +16,6 @@ function extendsObject<T extends RecordType>(...list: T[]) {
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
export default extendsObject;
|
||||
|
20
components/_util/getAllowClear.tsx
Normal file
20
components/_util/getAllowClear.tsx
Normal file
@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
import CloseCircleFilled from '@ant-design/icons/CloseCircleFilled';
|
||||
import type { BaseInputProps } from 'rc-input/lib/interface';
|
||||
|
||||
export type AllowClear = BaseInputProps['allowClear'];
|
||||
|
||||
const getAllowClear = (allowClear: AllowClear): AllowClear => {
|
||||
let mergedAllowClear: AllowClear;
|
||||
if (typeof allowClear === 'object' && allowClear?.clearIcon) {
|
||||
mergedAllowClear = allowClear;
|
||||
} else if (allowClear) {
|
||||
mergedAllowClear = {
|
||||
clearIcon: <CloseCircleFilled />,
|
||||
};
|
||||
}
|
||||
|
||||
return mergedAllowClear;
|
||||
};
|
||||
|
||||
export default getAllowClear;
|
@ -9,9 +9,5 @@ export const getRenderPropValue = (
|
||||
return null;
|
||||
}
|
||||
|
||||
if (typeof propValue === 'function') {
|
||||
return propValue();
|
||||
}
|
||||
|
||||
return propValue;
|
||||
return typeof propValue === 'function' ? propValue() : propValue;
|
||||
};
|
||||
|
@ -1,25 +1,36 @@
|
||||
import React from 'react';
|
||||
|
||||
import useToken from '../../theme/useToken';
|
||||
import zIndexContext from '../zindexContext';
|
||||
|
||||
export type ZIndexContainer = 'Modal' | 'Drawer' | 'Popover' | 'Popconfirm' | 'Tooltip' | 'Tour';
|
||||
|
||||
export type ZIndexConsumer = 'SelectLike' | 'Dropdown' | 'ColorPicker' | 'DatePicker' | 'Menu';
|
||||
export type ZIndexConsumer = 'SelectLike' | 'Dropdown' | 'DatePicker' | 'Menu' | 'ImagePreview';
|
||||
|
||||
// Z-Index control range
|
||||
// Container: 1000 + offset 100 (max base + 10 * offset = 2000)
|
||||
// Popover: offset 50
|
||||
// Notification: Container Max zIndex + componentOffset
|
||||
|
||||
const CONTAINER_OFFSET = 100;
|
||||
const CONTAINER_OFFSET_MAX_COUNT = 10;
|
||||
|
||||
export const CONTAINER_MAX_OFFSET = CONTAINER_OFFSET * CONTAINER_OFFSET_MAX_COUNT;
|
||||
|
||||
export const containerBaseZIndexOffset: Record<ZIndexContainer, number> = {
|
||||
Modal: 0,
|
||||
Drawer: 0,
|
||||
Popover: 70,
|
||||
Popconfirm: 70,
|
||||
Tooltip: 70,
|
||||
Tour: 70,
|
||||
Modal: CONTAINER_OFFSET,
|
||||
Drawer: CONTAINER_OFFSET,
|
||||
Popover: CONTAINER_OFFSET,
|
||||
Popconfirm: CONTAINER_OFFSET,
|
||||
Tooltip: CONTAINER_OFFSET,
|
||||
Tour: CONTAINER_OFFSET,
|
||||
};
|
||||
export const consumerBaseZIndexOffset: Record<ZIndexConsumer, number> = {
|
||||
SelectLike: 50,
|
||||
Dropdown: 50,
|
||||
ColorPicker: 30,
|
||||
DatePicker: 50,
|
||||
Menu: 50,
|
||||
ImagePreview: 1,
|
||||
};
|
||||
|
||||
function isContainerType(type: ZIndexContainer | ZIndexConsumer): type is ZIndexContainer {
|
||||
@ -33,9 +44,21 @@ export function useZIndex(
|
||||
const [, token] = useToken();
|
||||
const parentZIndex = React.useContext(zIndexContext);
|
||||
const isContainer = isContainerType(componentType);
|
||||
|
||||
if (customZIndex !== undefined) {
|
||||
return [customZIndex, customZIndex];
|
||||
}
|
||||
|
||||
let zIndex = parentZIndex ?? 0;
|
||||
|
||||
if (isContainer) {
|
||||
zIndex += token.zIndexPopupBase + containerBaseZIndexOffset[componentType];
|
||||
zIndex +=
|
||||
// Use preset token zIndex by default but not stack when has parent container
|
||||
(parentZIndex ? 0 : token.zIndexPopupBase) +
|
||||
// Container offset
|
||||
containerBaseZIndexOffset[componentType];
|
||||
|
||||
zIndex = Math.min(zIndex, token.zIndexPopupBase + CONTAINER_MAX_OFFSET);
|
||||
} else {
|
||||
zIndex += consumerBaseZIndexOffset[componentType];
|
||||
}
|
||||
|
@ -2,4 +2,8 @@ import React from 'react';
|
||||
|
||||
const zIndexContext = React.createContext<number | undefined>(undefined);
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
zIndexContext.displayName = 'zIndexContext';
|
||||
}
|
||||
|
||||
export default zIndexContext;
|
||||
|
@ -243,9 +243,9 @@ const Affix = React.forwardRef<AffixRef, AffixProps>((props, ref) => {
|
||||
updatePosition();
|
||||
}, [target, offsetTop, offsetBottom]);
|
||||
|
||||
const [wrapSSR, hashId] = useStyle(affixPrefixCls);
|
||||
const [wrapCSSVar, hashId, cssVarCls] = useStyle(affixPrefixCls);
|
||||
|
||||
const rootCls = classNames(rootClassName, hashId, affixPrefixCls);
|
||||
const rootCls = classNames(rootClassName, hashId, affixPrefixCls, cssVarCls);
|
||||
|
||||
const mergedCls = classNames({ [rootCls]: affixStyle });
|
||||
|
||||
@ -262,7 +262,7 @@ const Affix = React.forwardRef<AffixRef, AffixProps>((props, ref) => {
|
||||
otherProps = omit(otherProps, ['onTestUpdatePosition' as any]);
|
||||
}
|
||||
|
||||
return wrapSSR(
|
||||
return wrapCSSVar(
|
||||
<ResizeObserver onResize={updatePosition}>
|
||||
<div style={style} className={className} ref={placeholderNodeRef} {...otherProps}>
|
||||
{affixStyle && <div style={placeholderStyle} aria-hidden="true" />}
|
||||
|
@ -1,15 +1,19 @@
|
||||
import type { CSSObject } from '@ant-design/cssinjs';
|
||||
import type { FullToken, GenerateStyle } from '../../theme/internal';
|
||||
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
|
||||
|
||||
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
|
||||
import { genStyleHooks } from '../../theme/internal';
|
||||
|
||||
export interface ComponentToken {
|
||||
zIndexPopup: number;
|
||||
}
|
||||
|
||||
interface AffixToken extends FullToken<'Affix'> {
|
||||
zIndexPopup: number;
|
||||
//
|
||||
}
|
||||
|
||||
// ============================== Shared ==============================
|
||||
const genSharedAffixStyle: GenerateStyle<AffixToken> = (token): CSSObject => {
|
||||
const { componentCls } = token;
|
||||
|
||||
return {
|
||||
[componentCls]: {
|
||||
position: 'fixed',
|
||||
@ -18,10 +22,9 @@ const genSharedAffixStyle: GenerateStyle<AffixToken> = (token): CSSObject => {
|
||||
};
|
||||
};
|
||||
|
||||
// ============================== Export ==============================
|
||||
export default genComponentStyleHook('Affix', (token) => {
|
||||
const affixToken = mergeToken<AffixToken>(token, {
|
||||
export const prepareComponentToken: GetDefaultToken<'Affix'> = (token) => ({
|
||||
zIndexPopup: token.zIndexBase + 10,
|
||||
});
|
||||
return [genSharedAffixStyle(affixToken)];
|
||||
});
|
||||
|
||||
// ============================== Export ==============================
|
||||
export default genStyleHooks('Affix', genSharedAffixStyle, prepareComponentToken);
|
||||
|
@ -12,7 +12,6 @@ import pickAttrs from 'rc-util/lib/pickAttrs';
|
||||
import { replaceElement } from '../_util/reactNode';
|
||||
import { devUseWarning } from '../_util/warning';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
// CSSINJS
|
||||
import useStyle from './style';
|
||||
|
||||
export interface AlertProps {
|
||||
@ -127,7 +126,8 @@ const Alert: React.FC<AlertProps> = (props) => {
|
||||
const ref = React.useRef<HTMLDivElement>(null);
|
||||
const { getPrefixCls, direction, alert } = React.useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('alert', customizePrefixCls);
|
||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||
|
||||
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls);
|
||||
|
||||
const handleClose = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
setClosed(true);
|
||||
@ -169,12 +169,13 @@ const Alert: React.FC<AlertProps> = (props) => {
|
||||
alert?.className,
|
||||
className,
|
||||
rootClassName,
|
||||
cssVarCls,
|
||||
hashId,
|
||||
);
|
||||
|
||||
const restProps = pickAttrs(otherProps, { aria: true, data: true });
|
||||
|
||||
return wrapSSR(
|
||||
return wrapCSSVar(
|
||||
<CSSMotion
|
||||
visible={!closed}
|
||||
motionName={`${prefixCls}-motion`}
|
||||
|
@ -1,8 +1,10 @@
|
||||
import type { CSSInterpolation, CSSObject } from '@ant-design/cssinjs';
|
||||
import type { CSSProperties } from 'react';
|
||||
import type { CSSObject } from '@ant-design/cssinjs';
|
||||
import { unit } from '@ant-design/cssinjs';
|
||||
|
||||
import { resetComponent } from '../../style';
|
||||
import type { FullToken, GenerateStyle } from '../../theme/internal';
|
||||
import { genComponentStyleHook } from '../../theme/internal';
|
||||
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
|
||||
import { genStyleHooks } from '../../theme/internal';
|
||||
|
||||
export interface ComponentToken {
|
||||
// Component token here
|
||||
@ -34,8 +36,8 @@ const genAlertTypeStyle = (
|
||||
token: AlertToken,
|
||||
alertCls: string,
|
||||
): CSSObject => ({
|
||||
backgroundColor: bgColor,
|
||||
border: `${token.lineWidth}px ${token.lineType} ${borderColor}`,
|
||||
background: bgColor,
|
||||
border: `${unit(token.lineWidth)} ${token.lineType} ${borderColor}`,
|
||||
[`${alertCls}-icon`]: {
|
||||
color: iconColor,
|
||||
},
|
||||
@ -113,7 +115,6 @@ export const genBaseStyle: GenerateStyle<AlertToken> = (token: AlertToken): CSSO
|
||||
[`${componentCls}-with-description`]: {
|
||||
alignItems: 'flex-start',
|
||||
padding: withDescriptionPadding,
|
||||
|
||||
[`${componentCls}-icon`]: {
|
||||
marginInlineEnd: marginSM,
|
||||
fontSize: withDescriptionIconSize,
|
||||
@ -212,7 +213,7 @@ export const genActionStyle: GenerateStyle<AlertToken> = (token: AlertToken): CS
|
||||
padding: 0,
|
||||
overflow: 'hidden',
|
||||
fontSize: fontSizeIcon,
|
||||
lineHeight: `${fontSizeIcon}px`,
|
||||
lineHeight: unit(fontSizeIcon),
|
||||
backgroundColor: 'transparent',
|
||||
border: 'none',
|
||||
outline: 'none',
|
||||
@ -238,22 +239,17 @@ export const genActionStyle: GenerateStyle<AlertToken> = (token: AlertToken): CS
|
||||
};
|
||||
};
|
||||
|
||||
export const genAlertStyle: GenerateStyle<AlertToken> = (token: AlertToken): CSSInterpolation => [
|
||||
genBaseStyle(token),
|
||||
genTypeStyle(token),
|
||||
genActionStyle(token),
|
||||
];
|
||||
|
||||
export default genComponentStyleHook(
|
||||
'Alert',
|
||||
(token) => [genAlertStyle(token)],
|
||||
(token) => {
|
||||
export const prepareComponentToken: GetDefaultToken<'Alert'> = (token) => {
|
||||
const paddingHorizontal = 12; // Fixed value here.
|
||||
|
||||
return {
|
||||
withDescriptionIconSize: token.fontSizeHeading3,
|
||||
defaultPadding: `${token.paddingContentVerticalSM}px ${paddingHorizontal}px`,
|
||||
withDescriptionPadding: `${token.paddingMD}px ${token.paddingContentHorizontalLG}px`,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
export default genStyleHooks(
|
||||
'Alert',
|
||||
(token) => [genBaseStyle(token), genTypeStyle(token), genActionStyle(token)],
|
||||
prepareComponentToken,
|
||||
);
|
||||
|
@ -9,6 +9,7 @@ import { devUseWarning } from '../_util/warning';
|
||||
import Affix from '../affix';
|
||||
import type { ConfigConsumerProps } from '../config-provider';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
|
||||
import type { AnchorLinkBaseProps } from './AnchorLink';
|
||||
import AnchorLink from './AnchorLink';
|
||||
import AnchorContext from './context';
|
||||
@ -79,11 +80,6 @@ export interface AnchorProps {
|
||||
replace?: boolean;
|
||||
}
|
||||
|
||||
interface InternalAnchorProps extends AnchorProps {
|
||||
anchorPrefixCls: string;
|
||||
rootClassName: string;
|
||||
}
|
||||
|
||||
export interface AnchorState {
|
||||
activeLink: null | string;
|
||||
}
|
||||
@ -109,10 +105,10 @@ export interface AntAnchor {
|
||||
direction: AnchorDirection;
|
||||
}
|
||||
|
||||
const AnchorContent: React.FC<InternalAnchorProps> = (props) => {
|
||||
const Anchor: React.FC<AnchorProps> = (props) => {
|
||||
const {
|
||||
rootClassName,
|
||||
anchorPrefixCls: prefixCls,
|
||||
prefixCls: customPrefixCls,
|
||||
className,
|
||||
style,
|
||||
offsetTop,
|
||||
@ -151,9 +147,14 @@ const AnchorContent: React.FC<InternalAnchorProps> = (props) => {
|
||||
const spanLinkNode = React.useRef<HTMLSpanElement>(null);
|
||||
const animating = React.useRef<boolean>(false);
|
||||
|
||||
const { direction, getTargetContainer, anchor } =
|
||||
const { direction, anchor, getTargetContainer, getPrefixCls } =
|
||||
React.useContext<ConfigConsumerProps>(ConfigContext);
|
||||
|
||||
const prefixCls = getPrefixCls('anchor', customPrefixCls);
|
||||
|
||||
const rootCls = useCSSVarCls(prefixCls);
|
||||
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls, rootCls);
|
||||
|
||||
const getCurrentContainer = getContainer ?? getTargetContainer ?? getDefaultContainer;
|
||||
|
||||
const dependencyListItem: React.DependencyList[number] = JSON.stringify(links);
|
||||
@ -182,10 +183,7 @@ const AnchorContent: React.FC<InternalAnchorProps> = (props) => {
|
||||
inkStyle.left = horizontalAnchor ? `${linkNode.offsetLeft}px` : '';
|
||||
inkStyle.width = horizontalAnchor ? `${linkNode.clientWidth}px` : '';
|
||||
if (horizontalAnchor) {
|
||||
scrollIntoView(linkNode, {
|
||||
scrollMode: 'if-needed',
|
||||
block: 'nearest',
|
||||
});
|
||||
scrollIntoView(linkNode, { scrollMode: 'if-needed', block: 'nearest' });
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -274,6 +272,9 @@ const AnchorContent: React.FC<InternalAnchorProps> = (props) => {
|
||||
);
|
||||
|
||||
const wrapperClass = classNames(
|
||||
hashId,
|
||||
cssVarCls,
|
||||
rootCls,
|
||||
rootClassName,
|
||||
`${prefixCls}-wrapper`,
|
||||
{
|
||||
@ -347,7 +348,7 @@ const AnchorContent: React.FC<InternalAnchorProps> = (props) => {
|
||||
[activeLink, onClick, handleScrollTo, anchorDirection],
|
||||
);
|
||||
|
||||
return (
|
||||
return wrapCSSVar(
|
||||
<AnchorContext.Provider value={memoizedContextValue}>
|
||||
{affix ? (
|
||||
<Affix offsetTop={offsetTop} target={getCurrentContainer}>
|
||||
@ -356,23 +357,7 @@ const AnchorContent: React.FC<InternalAnchorProps> = (props) => {
|
||||
) : (
|
||||
anchorContent
|
||||
)}
|
||||
</AnchorContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
const Anchor: React.FC<AnchorProps> = (props) => {
|
||||
const { prefixCls: customizePrefixCls, rootClassName } = props;
|
||||
const { getPrefixCls } = React.useContext<ConfigConsumerProps>(ConfigContext);
|
||||
const anchorPrefixCls = getPrefixCls('anchor', customizePrefixCls);
|
||||
|
||||
const [wrapSSR, hashId] = useStyle(anchorPrefixCls);
|
||||
|
||||
return wrapSSR(
|
||||
<AnchorContent
|
||||
{...props}
|
||||
rootClassName={classNames(hashId, rootClassName)}
|
||||
anchorPrefixCls={anchorPrefixCls}
|
||||
/>,
|
||||
</AnchorContext.Provider>,
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
import type { CSSObject } from '@ant-design/cssinjs';
|
||||
import { unit } from '@ant-design/cssinjs';
|
||||
|
||||
import { resetComponent, textEllipsis } from '../../style';
|
||||
import type { FullToken, GenerateStyle } from '../../theme/internal';
|
||||
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
|
||||
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
|
||||
import { genStyleHooks, mergeToken } from '../../theme/internal';
|
||||
|
||||
export interface ComponentToken {
|
||||
/**
|
||||
@ -18,13 +19,13 @@ export interface ComponentToken {
|
||||
|
||||
interface AnchorToken extends FullToken<'Anchor'> {
|
||||
holderOffsetBlock: number;
|
||||
anchorPaddingBlockSecondary: number;
|
||||
anchorBallSize: number;
|
||||
anchorTitleBlock: number;
|
||||
anchorPaddingBlockSecondary: number | string;
|
||||
anchorBallSize: number | string;
|
||||
anchorTitleBlock: number | string;
|
||||
}
|
||||
|
||||
// ============================== Shared ==============================
|
||||
const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
|
||||
const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token) => {
|
||||
const {
|
||||
componentCls,
|
||||
holderOffsetBlock,
|
||||
@ -33,11 +34,12 @@ const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
|
||||
colorPrimary,
|
||||
lineType,
|
||||
colorSplit,
|
||||
calc,
|
||||
} = token;
|
||||
|
||||
return {
|
||||
[`${componentCls}-wrapper`]: {
|
||||
marginBlockStart: -holderOffsetBlock,
|
||||
marginBlockStart: calc(holderOffsetBlock).mul(-1).equal(),
|
||||
paddingBlockStart: holderOffsetBlock,
|
||||
|
||||
// delete overflow: auto
|
||||
@ -50,7 +52,7 @@ const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
|
||||
|
||||
[`${componentCls}-link`]: {
|
||||
paddingBlock: token.linkPaddingBlock,
|
||||
paddingInline: `${token.linkPaddingInlineStart}px 0`,
|
||||
paddingInline: `${unit(token.linkPaddingInlineStart)} 0`,
|
||||
|
||||
'&-title': {
|
||||
...textEllipsis,
|
||||
@ -83,7 +85,7 @@ const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
|
||||
insetInlineStart: 0,
|
||||
top: 0,
|
||||
height: '100%',
|
||||
borderInlineStart: `${lineWidthBold}px ${lineType} ${colorSplit}`,
|
||||
borderInlineStart: `${unit(lineWidthBold)} ${lineType} ${colorSplit}`,
|
||||
content: '" "',
|
||||
},
|
||||
|
||||
@ -95,7 +97,6 @@ const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
|
||||
transition: `top ${motionDurationSlow} ease-in-out`,
|
||||
width: lineWidthBold,
|
||||
backgroundColor: colorPrimary,
|
||||
|
||||
[`&${componentCls}-ink-visible`]: {
|
||||
display: 'inline-block',
|
||||
},
|
||||
@ -110,7 +111,7 @@ const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
|
||||
};
|
||||
};
|
||||
|
||||
const genSharedAnchorHorizontalStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
|
||||
const genSharedAnchorHorizontalStyle: GenerateStyle<AnchorToken> = (token) => {
|
||||
const { componentCls, motionDurationSlow, lineWidthBold, colorPrimary } = token;
|
||||
|
||||
return {
|
||||
@ -128,7 +129,7 @@ const genSharedAnchorHorizontalStyle: GenerateStyle<AnchorToken> = (token): CSSO
|
||||
value: 0,
|
||||
},
|
||||
bottom: 0,
|
||||
borderBottom: `1px ${token.lineType} ${token.colorSplit}`,
|
||||
borderBottom: `${unit(token.lineWidth)} ${token.lineType} ${token.colorSplit}`,
|
||||
content: '" "',
|
||||
},
|
||||
|
||||
@ -158,22 +159,23 @@ const genSharedAnchorHorizontalStyle: GenerateStyle<AnchorToken> = (token): CSSO
|
||||
};
|
||||
};
|
||||
|
||||
export const prepareComponentToken: GetDefaultToken<'Anchor'> = (token) => ({
|
||||
linkPaddingBlock: token.paddingXXS,
|
||||
linkPaddingInlineStart: token.padding,
|
||||
});
|
||||
|
||||
// ============================== Export ==============================
|
||||
export default genComponentStyleHook(
|
||||
export default genStyleHooks(
|
||||
'Anchor',
|
||||
(token) => {
|
||||
const { fontSize, fontSizeLG, paddingXXS } = token;
|
||||
|
||||
const { fontSize, fontSizeLG, paddingXXS, calc } = token;
|
||||
const anchorToken = mergeToken<AnchorToken>(token, {
|
||||
holderOffsetBlock: paddingXXS,
|
||||
anchorPaddingBlockSecondary: paddingXXS / 2,
|
||||
anchorTitleBlock: (fontSize / 14) * 3,
|
||||
anchorBallSize: fontSizeLG / 2,
|
||||
anchorPaddingBlockSecondary: calc(paddingXXS).div(2).equal(),
|
||||
anchorTitleBlock: calc(fontSize).div(14).mul(3).equal(),
|
||||
anchorBallSize: calc(fontSizeLG).div(2).equal(),
|
||||
});
|
||||
return [genSharedAnchorStyle(anchorToken), genSharedAnchorHorizontalStyle(anchorToken)];
|
||||
},
|
||||
(token) => ({
|
||||
linkPaddingBlock: token.paddingXXS,
|
||||
linkPaddingInlineStart: token.padding,
|
||||
}),
|
||||
prepareComponentToken,
|
||||
);
|
||||
|
@ -36,8 +36,8 @@ const App: React.FC<AppProps> & { useApp: () => useAppProps } = (props) => {
|
||||
} = props;
|
||||
const { getPrefixCls } = useContext<ConfigConsumerProps>(ConfigContext);
|
||||
const prefixCls = getPrefixCls('app', customizePrefixCls);
|
||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||
const customClassName = classNames(hashId, prefixCls, className, rootClassName);
|
||||
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls);
|
||||
const customClassName = classNames(hashId, prefixCls, className, rootClassName, cssVarCls);
|
||||
|
||||
const appConfig = useContext<AppConfig>(AppConfigContext);
|
||||
|
||||
@ -71,7 +71,7 @@ const App: React.FC<AppProps> & { useApp: () => useAppProps } = (props) => {
|
||||
style,
|
||||
};
|
||||
|
||||
return wrapSSR(
|
||||
return wrapCSSVar(
|
||||
<AppContext.Provider value={memoizedContextValue}>
|
||||
<AppConfigContext.Provider value={mergedAppConfig}>
|
||||
<Component {...(component === false ? undefined : rootProps)}>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import type { FullToken, GenerateStyle } from '../../theme/internal';
|
||||
import { genComponentStyleHook } from '../../theme/internal';
|
||||
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
|
||||
import { genStyleHooks } from '../../theme/internal';
|
||||
|
||||
export type ComponentToken = {};
|
||||
|
||||
@ -18,5 +18,7 @@ const genBaseStyle: GenerateStyle<AppToken> = (token) => {
|
||||
};
|
||||
};
|
||||
|
||||
export const prepareComponentToken: GetDefaultToken<'App'> = () => ({});
|
||||
|
||||
// ============================== Export ==============================
|
||||
export default genComponentStyleHook('App', (token) => [genBaseStyle(token)]);
|
||||
export default genStyleHooks('App', genBaseStyle, prepareComponentToken);
|
||||
|
@ -3,7 +3,7 @@
|
||||
exports[`renders components/auto-complete/demo/allowClear.tsx extend context correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width: 200px;"
|
||||
>
|
||||
<div
|
||||
@ -48,7 +48,7 @@ Array [
|
||||
<br />,
|
||||
<br />,
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-allow-clear ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-allow-clear ant-select-show-search"
|
||||
style="width: 200px;"
|
||||
>
|
||||
<div
|
||||
@ -98,7 +98,7 @@ exports[`renders components/auto-complete/demo/allowClear.tsx extend context cor
|
||||
exports[`renders components/auto-complete/demo/basic.tsx extend context correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width: 200px;"
|
||||
>
|
||||
<div
|
||||
@ -143,7 +143,7 @@ Array [
|
||||
<br />,
|
||||
<br />,
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width: 200px;"
|
||||
>
|
||||
<div
|
||||
@ -190,57 +190,9 @@ Array [
|
||||
|
||||
exports[`renders components/auto-complete/demo/basic.tsx extend context correctly 2`] = `[]`;
|
||||
|
||||
exports[`renders components/auto-complete/demo/borderless.tsx extend context correctly 1`] = `
|
||||
<div
|
||||
class="ant-select ant-select-borderless ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width: 200px;"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
>
|
||||
<span
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<input
|
||||
aria-autocomplete="list"
|
||||
aria-controls="rc_select_TEST_OR_SSR_list"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="rc_select_TEST_OR_SSR_list"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="rc_select_TEST_OR_SSR"
|
||||
role="combobox"
|
||||
type="search"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-select-selection-placeholder"
|
||||
>
|
||||
Borderless
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up ant-select-dropdown-empty ant-select-dropdown-placement-bottomLeft"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-item-empty"
|
||||
id="rc_select_TEST_OR_SSR_list"
|
||||
role="listbox"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders components/auto-complete/demo/borderless.tsx extend context correctly 2`] = `[]`;
|
||||
|
||||
exports[`renders components/auto-complete/demo/certain-category.tsx extend context correctly 1`] = `
|
||||
<div
|
||||
class="ant-select ant-select-lg ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
class="ant-select ant-select-lg ant-select-outlined ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
style="width: 250px;"
|
||||
>
|
||||
<div
|
||||
@ -250,7 +202,7 @@ exports[`renders components/auto-complete/demo/certain-category.tsx extend conte
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<span
|
||||
class="ant-input-group-wrapper ant-input-search ant-input-search-large ant-select-selection-search-input ant-input-group-wrapper-lg"
|
||||
class="ant-input-group-wrapper ant-input-group-wrapper-lg ant-input-group-wrapper-outlined ant-input-search ant-input-search-large ant-select-selection-search-input"
|
||||
>
|
||||
<span
|
||||
class="ant-input-wrapper ant-input-group"
|
||||
@ -262,7 +214,7 @@ exports[`renders components/auto-complete/demo/certain-category.tsx extend conte
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="rc_select_TEST_OR_SSR_list"
|
||||
autocomplete="off"
|
||||
class="ant-input ant-input-lg"
|
||||
class="ant-input ant-input-lg ant-input-outlined"
|
||||
id="rc_select_TEST_OR_SSR"
|
||||
placeholder="input here"
|
||||
role="combobox"
|
||||
@ -609,7 +561,7 @@ exports[`renders components/auto-complete/demo/certain-category.tsx extend conte
|
||||
|
||||
exports[`renders components/auto-complete/demo/custom.tsx extend context correctly 1`] = `
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
style="width: 200px;"
|
||||
>
|
||||
<div
|
||||
@ -625,7 +577,7 @@ exports[`renders components/auto-complete/demo/custom.tsx extend context correct
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="rc_select_TEST_OR_SSR_list"
|
||||
autocomplete="off"
|
||||
class="ant-input ant-select-selection-search-input custom"
|
||||
class="ant-input ant-input-outlined ant-select-selection-search-input custom"
|
||||
id="rc_select_TEST_OR_SSR"
|
||||
placeholder="input here"
|
||||
role="combobox"
|
||||
@ -685,7 +637,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx extend context cor
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-select-in-form-item ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-in-form-item ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
@ -755,7 +707,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx extend context cor
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-tree-select ant-select-in-form-item ant-select-single ant-select-show-arrow"
|
||||
class="ant-select ant-tree-select ant-select-outlined ant-select-in-form-item ant-select-single ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
@ -902,7 +854,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx extend context cor
|
||||
class="ant-input-group ant-input-group-compact"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-tree-select ant-select-single ant-select-show-arrow"
|
||||
class="ant-select ant-tree-select ant-select-outlined ant-select-single ant-select-show-arrow"
|
||||
style="width: 30%;"
|
||||
>
|
||||
<div
|
||||
@ -1017,7 +969,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx extend context cor
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
@ -1088,7 +1040,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx extend context cor
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-select-in-form-item ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-in-form-item ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
@ -1097,7 +1049,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx extend context cor
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<span
|
||||
class="ant-input-affix-wrapper ant-select-selection-search-input"
|
||||
class="ant-input-affix-wrapper ant-input-outlined ant-select-selection-search-input"
|
||||
>
|
||||
<input
|
||||
aria-autocomplete="list"
|
||||
@ -1188,7 +1140,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx extend context cor
|
||||
class="ant-input-group ant-input-group-compact"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-tree-select ant-select-single ant-select-show-arrow"
|
||||
class="ant-select ant-tree-select ant-select-outlined ant-select-single ant-select-show-arrow"
|
||||
style="width: 30%;"
|
||||
>
|
||||
<div
|
||||
@ -1303,7 +1255,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx extend context cor
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
@ -1312,7 +1264,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx extend context cor
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<span
|
||||
class="ant-input-affix-wrapper ant-select-selection-search-input"
|
||||
class="ant-input-affix-wrapper ant-input-outlined ant-select-selection-search-input"
|
||||
>
|
||||
<input
|
||||
aria-autocomplete="list"
|
||||
@ -1404,7 +1356,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx extend context cor
|
||||
class="ant-input-group ant-input-group-compact"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-tree-select ant-select-single ant-select-show-arrow"
|
||||
class="ant-select ant-tree-select ant-select-outlined ant-select-single ant-select-show-arrow"
|
||||
style="width: 30%;"
|
||||
>
|
||||
<div
|
||||
@ -1519,7 +1471,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx extend context cor
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
@ -1528,7 +1480,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx extend context cor
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<span
|
||||
class="ant-input-group-wrapper ant-input-search ant-select-selection-search-input"
|
||||
class="ant-input-group-wrapper ant-input-group-wrapper-outlined ant-input-search ant-select-selection-search-input"
|
||||
>
|
||||
<span
|
||||
class="ant-input-wrapper ant-input-group"
|
||||
@ -1540,7 +1492,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx extend context cor
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="rc_select_TEST_OR_SSR_list"
|
||||
autocomplete="off"
|
||||
class="ant-input"
|
||||
class="ant-input ant-input-outlined"
|
||||
id="rc_select_TEST_OR_SSR"
|
||||
role="combobox"
|
||||
type="search"
|
||||
@ -1633,7 +1585,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx extend context cor
|
||||
class="ant-input-group ant-input-group-compact"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-tree-select ant-select-single ant-select-show-arrow"
|
||||
class="ant-select ant-tree-select ant-select-outlined ant-select-single ant-select-show-arrow"
|
||||
style="width: 20%;"
|
||||
>
|
||||
<div
|
||||
@ -1748,7 +1700,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx extend context cor
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
@ -1757,7 +1709,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx extend context cor
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<span
|
||||
class="ant-input-group-wrapper ant-input-search ant-select-selection-search-input"
|
||||
class="ant-input-group-wrapper ant-input-group-wrapper-outlined ant-input-search ant-select-selection-search-input"
|
||||
>
|
||||
<span
|
||||
class="ant-input-wrapper ant-input-group"
|
||||
@ -1769,7 +1721,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx extend context cor
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="rc_select_TEST_OR_SSR_list"
|
||||
autocomplete="off"
|
||||
class="ant-input"
|
||||
class="ant-input ant-input-outlined"
|
||||
id="rc_select_TEST_OR_SSR"
|
||||
role="combobox"
|
||||
type="search"
|
||||
@ -1875,7 +1827,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx extend context cor
|
||||
|
||||
exports[`renders components/auto-complete/demo/non-case-sensitive.tsx extend context correctly 1`] = `
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width: 200px;"
|
||||
>
|
||||
<div
|
||||
@ -1999,7 +1951,7 @@ exports[`renders components/auto-complete/demo/non-case-sensitive.tsx extend con
|
||||
|
||||
exports[`renders components/auto-complete/demo/options.tsx extend context correctly 1`] = `
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width: 200px;"
|
||||
>
|
||||
<div
|
||||
@ -2081,7 +2033,7 @@ exports[`renders components/auto-complete/demo/render-panel.tsx extend context c
|
||||
style="padding-bottom: 0px; position: relative; min-width: 0;"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width: 120px; margin: 0px;"
|
||||
>
|
||||
<div
|
||||
@ -2236,7 +2188,7 @@ exports[`renders components/auto-complete/demo/status.tsx extend context correct
|
||||
class="ant-space-item"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-select-status-error ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-status-error ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width: 200px;"
|
||||
>
|
||||
<div
|
||||
@ -2281,7 +2233,7 @@ exports[`renders components/auto-complete/demo/status.tsx extend context correct
|
||||
class="ant-space-item"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-select-status-warning ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-status-warning ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width: 200px;"
|
||||
>
|
||||
<div
|
||||
@ -2329,7 +2281,7 @@ exports[`renders components/auto-complete/demo/status.tsx extend context correct
|
||||
|
||||
exports[`renders components/auto-complete/demo/uncertain-category.tsx extend context correctly 1`] = `
|
||||
<div
|
||||
class="ant-select ant-select-lg ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
class="ant-select ant-select-lg ant-select-outlined ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
style="width: 300px;"
|
||||
>
|
||||
<div
|
||||
@ -2339,7 +2291,7 @@ exports[`renders components/auto-complete/demo/uncertain-category.tsx extend con
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<span
|
||||
class="ant-input-group-wrapper ant-input-search ant-input-search-large ant-input-search-with-button ant-select-selection-search-input ant-input-group-wrapper-lg"
|
||||
class="ant-input-group-wrapper ant-input-group-wrapper-lg ant-input-group-wrapper-outlined ant-input-search ant-input-search-large ant-input-search-with-button ant-select-selection-search-input"
|
||||
>
|
||||
<span
|
||||
class="ant-input-wrapper ant-input-group"
|
||||
@ -2351,7 +2303,7 @@ exports[`renders components/auto-complete/demo/uncertain-category.tsx extend con
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="rc_select_TEST_OR_SSR_list"
|
||||
autocomplete="off"
|
||||
class="ant-input ant-input-lg"
|
||||
class="ant-input ant-input-lg ant-input-outlined"
|
||||
id="rc_select_TEST_OR_SSR"
|
||||
placeholder="input here"
|
||||
role="combobox"
|
||||
@ -2417,3 +2369,142 @@ exports[`renders components/auto-complete/demo/uncertain-category.tsx extend con
|
||||
"Warning: [antd: AutoComplete] You need to control style self instead of setting \`size\` when using customize input.",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders components/auto-complete/demo/variant.tsx extend context correctly 1`] = `
|
||||
<div
|
||||
class="ant-flex ant-flex-align-stretch ant-flex-vertical"
|
||||
style="gap: 12px;"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width: 200px;"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
>
|
||||
<span
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<input
|
||||
aria-autocomplete="list"
|
||||
aria-controls="rc_select_TEST_OR_SSR_list"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="rc_select_TEST_OR_SSR_list"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="rc_select_TEST_OR_SSR"
|
||||
role="combobox"
|
||||
type="search"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-select-selection-placeholder"
|
||||
>
|
||||
Outlined
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up ant-select-dropdown-empty ant-select-dropdown-placement-bottomLeft"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-item-empty"
|
||||
id="rc_select_TEST_OR_SSR_list"
|
||||
role="listbox"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-select ant-select-filled ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width: 200px;"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
>
|
||||
<span
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<input
|
||||
aria-autocomplete="list"
|
||||
aria-controls="rc_select_TEST_OR_SSR_list"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="rc_select_TEST_OR_SSR_list"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="rc_select_TEST_OR_SSR"
|
||||
role="combobox"
|
||||
type="search"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-select-selection-placeholder"
|
||||
>
|
||||
Filled
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up ant-select-dropdown-empty ant-select-dropdown-placement-bottomLeft"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-item-empty"
|
||||
id="rc_select_TEST_OR_SSR_list"
|
||||
role="listbox"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-select ant-select-borderless ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width: 200px;"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
>
|
||||
<span
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<input
|
||||
aria-autocomplete="list"
|
||||
aria-controls="rc_select_TEST_OR_SSR_list"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="rc_select_TEST_OR_SSR_list"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
id="rc_select_TEST_OR_SSR"
|
||||
role="combobox"
|
||||
type="search"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-select-selection-placeholder"
|
||||
>
|
||||
Borderless
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up ant-select-dropdown-empty ant-select-dropdown-placement-bottomLeft"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-item-empty"
|
||||
id="rc_select_TEST_OR_SSR_list"
|
||||
role="listbox"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders components/auto-complete/demo/variant.tsx extend context correctly 2`] = `[]`;
|
||||
|
@ -3,7 +3,7 @@
|
||||
exports[`renders components/auto-complete/demo/allowClear.tsx correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width:200px"
|
||||
>
|
||||
<div
|
||||
@ -35,7 +35,7 @@ Array [
|
||||
<br />,
|
||||
<br />,
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-allow-clear ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-allow-clear ant-select-show-search"
|
||||
style="width:200px"
|
||||
>
|
||||
<div
|
||||
@ -70,7 +70,7 @@ Array [
|
||||
exports[`renders components/auto-complete/demo/basic.tsx correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width:200px"
|
||||
>
|
||||
<div
|
||||
@ -102,7 +102,7 @@ Array [
|
||||
<br />,
|
||||
<br />,
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width:200px"
|
||||
>
|
||||
<div
|
||||
@ -134,42 +134,9 @@ Array [
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders components/auto-complete/demo/borderless.tsx correctly 1`] = `
|
||||
<div
|
||||
class="ant-select ant-select-borderless ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width:200px"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
>
|
||||
<span
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<input
|
||||
aria-autocomplete="list"
|
||||
aria-controls="undefined_list"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="undefined_list"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
role="combobox"
|
||||
type="search"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-select-selection-placeholder"
|
||||
>
|
||||
Borderless
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders components/auto-complete/demo/certain-category.tsx correctly 1`] = `
|
||||
<div
|
||||
class="ant-select ant-select-lg ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
class="ant-select ant-select-lg ant-select-outlined ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
style="width:250px"
|
||||
>
|
||||
<div
|
||||
@ -179,7 +146,7 @@ exports[`renders components/auto-complete/demo/certain-category.tsx correctly 1`
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<span
|
||||
class="ant-input-group-wrapper ant-input-search ant-input-search-large ant-select-selection-search-input ant-input-group-wrapper-lg"
|
||||
class="ant-input-group-wrapper ant-input-group-wrapper-lg ant-input-group-wrapper-outlined ant-input-search ant-input-search-large ant-select-selection-search-input"
|
||||
>
|
||||
<span
|
||||
class="ant-input-wrapper ant-input-group"
|
||||
@ -191,7 +158,7 @@ exports[`renders components/auto-complete/demo/certain-category.tsx correctly 1`
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="undefined_list"
|
||||
autocomplete="off"
|
||||
class="ant-input ant-input-lg"
|
||||
class="ant-input ant-input-lg ant-input-outlined"
|
||||
placeholder="input here"
|
||||
role="combobox"
|
||||
type="search"
|
||||
@ -241,7 +208,7 @@ exports[`renders components/auto-complete/demo/certain-category.tsx correctly 1`
|
||||
|
||||
exports[`renders components/auto-complete/demo/custom.tsx correctly 1`] = `
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
style="width:200px"
|
||||
>
|
||||
<div
|
||||
@ -257,7 +224,7 @@ exports[`renders components/auto-complete/demo/custom.tsx correctly 1`] = `
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="undefined_list"
|
||||
autocomplete="off"
|
||||
class="ant-input ant-select-selection-search-input custom"
|
||||
class="ant-input ant-input-outlined ant-select-selection-search-input custom"
|
||||
placeholder="input here"
|
||||
role="combobox"
|
||||
style="height:50px"
|
||||
@ -302,7 +269,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-select-in-form-item ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-in-form-item ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
@ -359,7 +326,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-tree-select ant-select-in-form-item ant-select-single ant-select-show-arrow"
|
||||
class="ant-select ant-tree-select ant-select-outlined ant-select-in-form-item ant-select-single ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
@ -448,7 +415,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
||||
class="ant-input-group ant-input-group-compact"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-tree-select ant-select-single ant-select-show-arrow"
|
||||
class="ant-select ant-tree-select ant-select-outlined ant-select-single ant-select-show-arrow"
|
||||
style="width:30%"
|
||||
>
|
||||
<div
|
||||
@ -505,7 +472,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
@ -563,7 +530,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-select-in-form-item ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-in-form-item ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
@ -572,7 +539,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<span
|
||||
class="ant-input-affix-wrapper ant-select-selection-search-input"
|
||||
class="ant-input-affix-wrapper ant-input-outlined ant-select-selection-search-input"
|
||||
>
|
||||
<input
|
||||
aria-autocomplete="list"
|
||||
@ -650,7 +617,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
||||
class="ant-input-group ant-input-group-compact"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-tree-select ant-select-single ant-select-show-arrow"
|
||||
class="ant-select ant-tree-select ant-select-outlined ant-select-single ant-select-show-arrow"
|
||||
style="width:30%"
|
||||
>
|
||||
<div
|
||||
@ -707,7 +674,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
@ -716,7 +683,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<span
|
||||
class="ant-input-affix-wrapper ant-select-selection-search-input"
|
||||
class="ant-input-affix-wrapper ant-input-outlined ant-select-selection-search-input"
|
||||
>
|
||||
<input
|
||||
aria-autocomplete="list"
|
||||
@ -795,7 +762,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
||||
class="ant-input-group ant-input-group-compact"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-tree-select ant-select-single ant-select-show-arrow"
|
||||
class="ant-select ant-tree-select ant-select-outlined ant-select-single ant-select-show-arrow"
|
||||
style="width:30%"
|
||||
>
|
||||
<div
|
||||
@ -852,7 +819,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
@ -861,7 +828,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<span
|
||||
class="ant-input-group-wrapper ant-input-search ant-select-selection-search-input"
|
||||
class="ant-input-group-wrapper ant-input-group-wrapper-outlined ant-input-search ant-select-selection-search-input"
|
||||
>
|
||||
<span
|
||||
class="ant-input-wrapper ant-input-group"
|
||||
@ -873,7 +840,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="undefined_list"
|
||||
autocomplete="off"
|
||||
class="ant-input"
|
||||
class="ant-input ant-input-outlined"
|
||||
role="combobox"
|
||||
type="search"
|
||||
value=""
|
||||
@ -953,7 +920,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
||||
class="ant-input-group ant-input-group-compact"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-tree-select ant-select-single ant-select-show-arrow"
|
||||
class="ant-select ant-tree-select ant-select-outlined ant-select-single ant-select-show-arrow"
|
||||
style="width:20%"
|
||||
>
|
||||
<div
|
||||
@ -1010,7 +977,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
@ -1019,7 +986,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<span
|
||||
class="ant-input-group-wrapper ant-input-search ant-select-selection-search-input"
|
||||
class="ant-input-group-wrapper ant-input-group-wrapper-outlined ant-input-search ant-select-selection-search-input"
|
||||
>
|
||||
<span
|
||||
class="ant-input-wrapper ant-input-group"
|
||||
@ -1031,7 +998,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="undefined_list"
|
||||
autocomplete="off"
|
||||
class="ant-input"
|
||||
class="ant-input ant-input-outlined"
|
||||
role="combobox"
|
||||
type="search"
|
||||
value=""
|
||||
@ -1118,7 +1085,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
||||
|
||||
exports[`renders components/auto-complete/demo/non-case-sensitive.tsx correctly 1`] = `
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width:200px"
|
||||
>
|
||||
<div
|
||||
@ -1151,7 +1118,7 @@ exports[`renders components/auto-complete/demo/non-case-sensitive.tsx correctly
|
||||
|
||||
exports[`renders components/auto-complete/demo/options.tsx correctly 1`] = `
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width:200px"
|
||||
>
|
||||
<div
|
||||
@ -1218,7 +1185,7 @@ exports[`renders components/auto-complete/demo/render-panel.tsx correctly 1`] =
|
||||
style="padding-bottom:0;position:relative;min-width:0"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width:120px;margin:0"
|
||||
>
|
||||
<div
|
||||
@ -1256,7 +1223,7 @@ exports[`renders components/auto-complete/demo/status.tsx correctly 1`] = `
|
||||
class="ant-space-item"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-select-status-error ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-status-error ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width:200px"
|
||||
>
|
||||
<div
|
||||
@ -1288,7 +1255,7 @@ exports[`renders components/auto-complete/demo/status.tsx correctly 1`] = `
|
||||
class="ant-space-item"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-select-status-warning ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
class="ant-select ant-select-outlined ant-select-status-warning ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width:200px"
|
||||
>
|
||||
<div
|
||||
@ -1321,7 +1288,7 @@ exports[`renders components/auto-complete/demo/status.tsx correctly 1`] = `
|
||||
|
||||
exports[`renders components/auto-complete/demo/uncertain-category.tsx correctly 1`] = `
|
||||
<div
|
||||
class="ant-select ant-select-lg ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
class="ant-select ant-select-lg ant-select-outlined ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
|
||||
style="width:300px"
|
||||
>
|
||||
<div
|
||||
@ -1331,7 +1298,7 @@ exports[`renders components/auto-complete/demo/uncertain-category.tsx correctly
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<span
|
||||
class="ant-input-group-wrapper ant-input-search ant-input-search-large ant-input-search-with-button ant-select-selection-search-input ant-input-group-wrapper-lg"
|
||||
class="ant-input-group-wrapper ant-input-group-wrapper-lg ant-input-group-wrapper-outlined ant-input-search ant-input-search-large ant-input-search-with-button ant-select-selection-search-input"
|
||||
>
|
||||
<span
|
||||
class="ant-input-wrapper ant-input-group"
|
||||
@ -1343,7 +1310,7 @@ exports[`renders components/auto-complete/demo/uncertain-category.tsx correctly
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="undefined_list"
|
||||
autocomplete="off"
|
||||
class="ant-input ant-input-lg"
|
||||
class="ant-input ant-input-lg ant-input-outlined"
|
||||
placeholder="input here"
|
||||
role="combobox"
|
||||
type="search"
|
||||
@ -1390,3 +1357,101 @@ exports[`renders components/auto-complete/demo/uncertain-category.tsx correctly
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders components/auto-complete/demo/variant.tsx correctly 1`] = `
|
||||
<div
|
||||
class="ant-flex ant-flex-align-stretch ant-flex-vertical"
|
||||
style="gap:12px"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-select-outlined ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width:200px"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
>
|
||||
<span
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<input
|
||||
aria-autocomplete="list"
|
||||
aria-controls="undefined_list"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="undefined_list"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
role="combobox"
|
||||
type="search"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-select-selection-placeholder"
|
||||
>
|
||||
Outlined
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-select ant-select-filled ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width:200px"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
>
|
||||
<span
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<input
|
||||
aria-autocomplete="list"
|
||||
aria-controls="undefined_list"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="undefined_list"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
role="combobox"
|
||||
type="search"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-select-selection-placeholder"
|
||||
>
|
||||
Filled
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-select ant-select-borderless ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
style="width:200px"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
>
|
||||
<span
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<input
|
||||
aria-autocomplete="list"
|
||||
aria-controls="undefined_list"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="undefined_list"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
role="combobox"
|
||||
type="search"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-select-selection-placeholder"
|
||||
>
|
||||
Borderless
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
exports[`AutoComplete rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<div
|
||||
class="ant-select ant-select-rtl ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
class="ant-select ant-select-rtl ant-select-outlined ant-select-auto-complete ant-select-single ant-select-show-search"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
|
@ -1,7 +0,0 @@
|
||||
## zh-CN
|
||||
|
||||
没有边框。
|
||||
|
||||
## en-US
|
||||
|
||||
No border.
|
@ -1,26 +0,0 @@
|
||||
import React, { useState } from 'react';
|
||||
import { AutoComplete } from 'antd';
|
||||
|
||||
const mockVal = (str: string, repeat = 1) => ({
|
||||
value: str.repeat(repeat),
|
||||
});
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [options, setOptions] = useState<{ value: string }[]>([]);
|
||||
|
||||
const getPanelValue = (searchText: string) =>
|
||||
!searchText ? [] : [mockVal(searchText), mockVal(searchText, 2), mockVal(searchText, 3)];
|
||||
|
||||
return (
|
||||
<AutoComplete
|
||||
options={options}
|
||||
style={{ width: 200 }}
|
||||
placeholder="Borderless"
|
||||
onSearch={(text) => setOptions(getPanelValue(text))}
|
||||
onSelect={globalThis.console.log}
|
||||
bordered={false}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
7
components/auto-complete/demo/variant.md
Normal file
7
components/auto-complete/demo/variant.md
Normal file
@ -0,0 +1,7 @@
|
||||
## zh-CN
|
||||
|
||||
可选 `outlined` `filled` `borderless` 三种形态。
|
||||
|
||||
## en-US
|
||||
|
||||
There are `outlined` `fille` and `borderless`, totally three variants to choose from.
|
43
components/auto-complete/demo/variant.tsx
Normal file
43
components/auto-complete/demo/variant.tsx
Normal file
@ -0,0 +1,43 @@
|
||||
import React, { useState } from 'react';
|
||||
import { AutoComplete, Flex } from 'antd';
|
||||
|
||||
const mockVal = (str: string, repeat = 1) => ({
|
||||
value: str.repeat(repeat),
|
||||
});
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [options, setOptions] = useState<{ value: string }[]>([]);
|
||||
|
||||
const getPanelValue = (searchText: string) =>
|
||||
!searchText ? [] : [mockVal(searchText), mockVal(searchText, 2), mockVal(searchText, 3)];
|
||||
|
||||
return (
|
||||
<Flex vertical gap={12}>
|
||||
<AutoComplete
|
||||
options={options}
|
||||
style={{ width: 200 }}
|
||||
placeholder="Outlined"
|
||||
onSearch={(text) => setOptions(getPanelValue(text))}
|
||||
onSelect={globalThis.console.log}
|
||||
/>
|
||||
<AutoComplete
|
||||
options={options}
|
||||
style={{ width: 200 }}
|
||||
placeholder="Filled"
|
||||
onSearch={(text) => setOptions(getPanelValue(text))}
|
||||
onSelect={globalThis.console.log}
|
||||
variant="filled"
|
||||
/>
|
||||
<AutoComplete
|
||||
options={options}
|
||||
style={{ width: 200 }}
|
||||
placeholder="Borderless"
|
||||
onSearch={(text) => setOptions(getPanelValue(text))}
|
||||
onSelect={globalThis.console.log}
|
||||
variant="borderless"
|
||||
/>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
@ -32,7 +32,7 @@ The differences with Select are:
|
||||
<code src="./demo/certain-category.tsx">Lookup-Patterns - Certain Category</code>
|
||||
<code src="./demo/uncertain-category.tsx">Lookup-Patterns - Uncertain Category</code>
|
||||
<code src="./demo/status.tsx">Status</code>
|
||||
<code src="./demo/borderless.tsx">Borderless</code>
|
||||
<code src="./demo/variant.tsx" version="5.13.0">Variants</code>
|
||||
<code src="./demo/allowClear.tsx">Customize clear button</code>
|
||||
<code src="./demo/form-debug.tsx" debug>Debug in Form</code>
|
||||
<code src="./demo/render-panel.tsx" debug>_InternalPanelDoNotUseOrYouWillBeFired</code>
|
||||
@ -46,7 +46,6 @@ Common props ref:[Common props](/docs/react/common-props)
|
||||
| allowClear | Show clear button | boolean \| { clearIcon?: ReactNode } | false | 5.8.0: Support Object type |
|
||||
| autoFocus | If get focus when component mounted | boolean | false | |
|
||||
| backfill | If backfill selected item the input when using keyboard | boolean | false | |
|
||||
| bordered | Whether has border style | boolean | true | |
|
||||
| children (for customize input element) | Customize input element | HTMLInputElement \| HTMLTextAreaElement \| React.ReactElement<InputProps> | <Input /> | |
|
||||
| children (for dataSource) | Data source to auto complete | React.ReactElement<OptionProps> \| Array<React.ReactElement<OptionProps>> | - | |
|
||||
| defaultActiveFirstOption | Whether active first option by default | boolean | true | |
|
||||
@ -62,6 +61,7 @@ Common props ref:[Common props](/docs/react/common-props)
|
||||
| placeholder | The placeholder of input | string | - | |
|
||||
| status | Set validation status | 'error' \| 'warning' | - | 4.19.0 |
|
||||
| value | Selected option | string | - | |
|
||||
| variant | Variants of input | `outlined` \| `borderless` \| `filled` | `outlined` | 5.13.0 |
|
||||
| onBlur | Called when leaving the component | function() | - | |
|
||||
| onChange | Called when selecting an option or changing an input value | function(value) | - | |
|
||||
| onDropdownVisibleChange | Call when dropdown open | function(open) | - | |
|
||||
|
@ -33,7 +33,7 @@ demo:
|
||||
<code src="./demo/certain-category.tsx">查询模式 - 确定类目</code>
|
||||
<code src="./demo/uncertain-category.tsx">查询模式 - 不确定类目</code>
|
||||
<code src="./demo/status.tsx">自定义状态</code>
|
||||
<code src="./demo/borderless.tsx">无边框</code>
|
||||
<code src="./demo/variant.tsx" version="5.13.0">多种形态</code>
|
||||
<code src="./demo/allowClear.tsx">自定义清除按钮</code>
|
||||
<code src="./demo/form-debug.tsx" debug>在 Form 中 Debug</code>
|
||||
<code src="./demo/render-panel.tsx" debug>\_InternalPanelDoNotUseOrYouWillBeFired</code>
|
||||
@ -47,13 +47,13 @@ demo:
|
||||
| allowClear | 支持清除 | boolean \| { clearIcon?: ReactNode } | false | 5.8.0: 支持对象形式 |
|
||||
| autoFocus | 自动获取焦点 | boolean | false | |
|
||||
| backfill | 使用键盘选择选项的时候把选中项回填到输入框中 | boolean | false | |
|
||||
| bordered | 是否有边框 | boolean | true | |
|
||||
| children (自动完成的数据源) | 自动完成的数据源 | React.ReactElement<OptionProps> \| Array<React.ReactElement<OptionProps>> | - | |
|
||||
| children (自定义输入框) | 自定义输入框 | HTMLInputElement \| HTMLTextAreaElement \| React.ReactElement<InputProps> | <Input /> | |
|
||||
| defaultActiveFirstOption | 是否默认高亮第一个选项 | boolean | true | |
|
||||
| defaultOpen | 是否默认展开下拉菜单 | boolean | - | |
|
||||
| defaultValue | 指定默认选中的条目 | string | - | |
|
||||
| disabled | 是否禁用 | boolean | false | |
|
||||
| dropdownRender | 自定义下拉框内容 | (menus: ReactNode) => ReactNode | - | 4.24.0 |
|
||||
| popupClassName | 下拉菜单的 className 属性 | string | - | 4.23.0 |
|
||||
| dropdownMatchSelectWidth | 下拉菜单和选择器同宽。默认将设置 `min-width`,当值小于选择框宽度时会被忽略。false 时会关闭虚拟滚动 | boolean \| number | true | |
|
||||
| filterOption | 是否根据输入项进行筛选。当其为一个函数时,会接收 `inputValue` `option` 两个参数,当 `option` 符合筛选条件时,应返回 true,反之则返回 false | boolean \| function(inputValue, option) | true | |
|
||||
@ -64,6 +64,7 @@ demo:
|
||||
| placeholder | 输入框提示 | string | - | |
|
||||
| status | 设置校验状态 | 'error' \| 'warning' | - | 4.19.0 |
|
||||
| value | 指定当前选中的条目 | string | - | |
|
||||
| variant | 形态变体 | `outlined` \| `borderless` \| `filled` | `outlined` | 5.13.0 |
|
||||
| onBlur | 失去焦点时的回调 | function() | - | |
|
||||
| onChange | 选中 option,或 input 的 value 变化时,调用此函数 | function(value) | - | |
|
||||
| onDropdownVisibleChange | 展开下拉菜单的回调 | function(open) | - | |
|
||||
|
@ -439,7 +439,7 @@ Array [
|
||||
</span>
|
||||
<div
|
||||
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-tooltip-placement-top"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box; z-index: 2140;"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box; z-index: 1200;"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-arrow"
|
||||
@ -822,7 +822,7 @@ Array [
|
||||
</span>
|
||||
<div
|
||||
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-tooltip-placement-top"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box; z-index: 2140;"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box; z-index: 1200;"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-arrow"
|
||||
@ -948,7 +948,7 @@ Array [
|
||||
</span>
|
||||
<div
|
||||
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-tooltip-placement-top"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box; z-index: 2140;"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box; z-index: 1200;"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-arrow"
|
||||
@ -1074,7 +1074,7 @@ Array [
|
||||
</span>
|
||||
<div
|
||||
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-tooltip-placement-top"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box; z-index: 2140;"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box; z-index: 1200;"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-arrow"
|
||||
|
@ -12,6 +12,7 @@ import useBreakpoint from '../grid/hooks/useBreakpoint';
|
||||
import type { AvatarContextType, AvatarSize } from './AvatarContext';
|
||||
import AvatarContext from './AvatarContext';
|
||||
import useStyle from './style';
|
||||
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
|
||||
|
||||
export interface AvatarProps {
|
||||
/** Shape of avatar, options: `circle`, `square` */
|
||||
@ -144,7 +145,8 @@ const InternalAvatar: React.ForwardRefRenderFunction<HTMLSpanElement, AvatarProp
|
||||
}
|
||||
|
||||
const prefixCls = getPrefixCls('avatar', customizePrefixCls);
|
||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||
const rootCls = useCSSVarCls(prefixCls);
|
||||
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls, rootCls);
|
||||
|
||||
const sizeCls = classNames({
|
||||
[`${prefixCls}-lg`]: size === 'large',
|
||||
@ -164,6 +166,8 @@ const InternalAvatar: React.ForwardRefRenderFunction<HTMLSpanElement, AvatarProp
|
||||
[`${prefixCls}-image`]: hasImageElement || (src && isImgExist),
|
||||
[`${prefixCls}-icon`]: !!icon,
|
||||
},
|
||||
cssVarCls,
|
||||
rootCls,
|
||||
className,
|
||||
rootClassName,
|
||||
hashId,
|
||||
@ -234,7 +238,7 @@ const InternalAvatar: React.ForwardRefRenderFunction<HTMLSpanElement, AvatarProp
|
||||
delete others.onError;
|
||||
delete others.gap;
|
||||
|
||||
return wrapSSR(
|
||||
return wrapCSSVar(
|
||||
<span
|
||||
{...others}
|
||||
style={{ ...sizeStyle, ...responsiveSizeStyle, ...avatar?.style, ...others.style }}
|
||||
|
@ -8,6 +8,7 @@ import Avatar from './avatar';
|
||||
import AvatarContext from './AvatarContext';
|
||||
import type { AvatarContextType, AvatarSize } from './AvatarContext';
|
||||
import useStyle from './style';
|
||||
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
|
||||
|
||||
interface ContextProps {
|
||||
children?: React.ReactNode;
|
||||
@ -60,13 +61,16 @@ const Group: React.FC<GroupProps> = (props) => {
|
||||
|
||||
const prefixCls = getPrefixCls('avatar', customizePrefixCls);
|
||||
const groupPrefixCls = `${prefixCls}-group`;
|
||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||
const rootCls = useCSSVarCls(prefixCls);
|
||||
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls, rootCls);
|
||||
|
||||
const cls = classNames(
|
||||
groupPrefixCls,
|
||||
{
|
||||
[`${groupPrefixCls}-rtl`]: direction === 'rtl',
|
||||
},
|
||||
cssVarCls,
|
||||
rootCls,
|
||||
className,
|
||||
rootClassName,
|
||||
hashId,
|
||||
@ -91,7 +95,7 @@ const Group: React.FC<GroupProps> = (props) => {
|
||||
<Avatar style={maxStyle}>{`+${numOfChildren - maxCount}`}</Avatar>
|
||||
</Popover>,
|
||||
);
|
||||
return wrapSSR(
|
||||
return wrapCSSVar(
|
||||
<AvatarContextProvider shape={shape} size={size}>
|
||||
<div className={cls} style={style}>
|
||||
{childrenShow}
|
||||
@ -100,7 +104,7 @@ const Group: React.FC<GroupProps> = (props) => {
|
||||
);
|
||||
}
|
||||
|
||||
return wrapSSR(
|
||||
return wrapCSSVar(
|
||||
<AvatarContextProvider shape={shape} size={size}>
|
||||
<div className={cls} style={style}>
|
||||
{childrenWithProps}
|
||||
|
@ -1,7 +1,8 @@
|
||||
import type { CSSObject } from '@ant-design/cssinjs';
|
||||
import { type CSSObject, unit } from '@ant-design/cssinjs';
|
||||
|
||||
import { resetComponent } from '../../style';
|
||||
import type { FullToken, GenerateStyle } from '../../theme/internal';
|
||||
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
|
||||
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
|
||||
import { genStyleHooks, mergeToken } from '../../theme/internal';
|
||||
|
||||
export interface ComponentToken {
|
||||
/**
|
||||
@ -75,13 +76,14 @@ const genBaseStyle: GenerateStyle<AvatarToken> = (token) => {
|
||||
borderRadiusSM,
|
||||
lineWidth,
|
||||
lineType,
|
||||
calc,
|
||||
} = token;
|
||||
|
||||
// Avatar size style
|
||||
const avatarSizeStyle = (size: number, fontSize: number, radius: number): CSSObject => ({
|
||||
width: size,
|
||||
height: size,
|
||||
lineHeight: `${size - lineWidth * 2}px`,
|
||||
lineHeight: unit(calc(size).sub(calc(lineWidth).mul(2)).equal()),
|
||||
borderRadius: '50%',
|
||||
|
||||
[`&${componentCls}-square`]: {
|
||||
@ -116,7 +118,7 @@ const genBaseStyle: GenerateStyle<AvatarToken> = (token) => {
|
||||
textAlign: 'center',
|
||||
verticalAlign: 'middle',
|
||||
background: avatarBg,
|
||||
border: `${lineWidth}px ${lineType} transparent`,
|
||||
border: `${unit(lineWidth)} ${lineType} transparent`,
|
||||
|
||||
[`&-image`]: {
|
||||
background: 'transparent',
|
||||
@ -169,7 +171,33 @@ const genGroupStyle: GenerateStyle<AvatarToken> = (token) => {
|
||||
};
|
||||
};
|
||||
|
||||
export default genComponentStyleHook(
|
||||
export const prepareComponentToken: GetDefaultToken<'Avatar'> = (token) => {
|
||||
const {
|
||||
controlHeight,
|
||||
controlHeightLG,
|
||||
controlHeightSM,
|
||||
fontSize,
|
||||
fontSizeLG,
|
||||
fontSizeXL,
|
||||
fontSizeHeading3,
|
||||
marginXS,
|
||||
marginXXS,
|
||||
colorBorderBg,
|
||||
} = token;
|
||||
return {
|
||||
containerSize: controlHeight,
|
||||
containerSizeLG: controlHeightLG,
|
||||
containerSizeSM: controlHeightSM,
|
||||
textFontSize: Math.round((fontSizeLG + fontSizeXL) / 2),
|
||||
textFontSizeLG: fontSizeHeading3,
|
||||
textFontSizeSM: fontSize,
|
||||
groupSpace: marginXXS,
|
||||
groupOverlapping: -marginXS,
|
||||
groupBorderColor: colorBorderBg,
|
||||
};
|
||||
};
|
||||
|
||||
export default genStyleHooks(
|
||||
'Avatar',
|
||||
(token) => {
|
||||
const { colorTextLightSolid, colorTextPlaceholder } = token;
|
||||
@ -179,33 +207,5 @@ export default genComponentStyleHook(
|
||||
});
|
||||
return [genBaseStyle(avatarToken), genGroupStyle(avatarToken)];
|
||||
},
|
||||
(token) => {
|
||||
const {
|
||||
controlHeight,
|
||||
controlHeightLG,
|
||||
controlHeightSM,
|
||||
|
||||
fontSize,
|
||||
fontSizeLG,
|
||||
fontSizeXL,
|
||||
fontSizeHeading3,
|
||||
|
||||
marginXS,
|
||||
marginXXS,
|
||||
colorBorderBg,
|
||||
} = token;
|
||||
return {
|
||||
containerSize: controlHeight,
|
||||
containerSizeLG: controlHeightLG,
|
||||
containerSizeSM: controlHeightSM,
|
||||
|
||||
textFontSize: Math.round((fontSizeLG + fontSizeXL) / 2),
|
||||
textFontSizeLG: fontSizeHeading3,
|
||||
textFontSizeSM: fontSize,
|
||||
|
||||
groupSpace: marginXXS,
|
||||
groupOverlapping: -marginXS,
|
||||
groupBorderColor: colorBorderBg,
|
||||
};
|
||||
},
|
||||
prepareComponentToken,
|
||||
);
|
||||
|
@ -74,11 +74,14 @@ const BackTop: React.FC<BackTopProps> = (props) => {
|
||||
const { getPrefixCls, direction } = React.useContext<ConfigConsumerProps>(ConfigContext);
|
||||
|
||||
const prefixCls = getPrefixCls('back-top', customizePrefixCls);
|
||||
|
||||
const rootPrefixCls = getPrefixCls();
|
||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||
|
||||
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls);
|
||||
|
||||
const classString = classNames(
|
||||
hashId,
|
||||
cssVarCls,
|
||||
prefixCls,
|
||||
{
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
@ -105,7 +108,7 @@ const BackTop: React.FC<BackTopProps> = (props) => {
|
||||
</div>
|
||||
);
|
||||
|
||||
return wrapSSR(
|
||||
return wrapCSSVar(
|
||||
<div {...divProps} className={classString} onClick={scrollToTop} ref={ref}>
|
||||
<CSSMotion visible={visible} motionName={`${rootPrefixCls}-fade`}>
|
||||
{({ className: motionClassName }) =>
|
||||
|
@ -1,7 +1,8 @@
|
||||
import type { CSSObject } from '@ant-design/cssinjs';
|
||||
import type { FullToken, GenerateStyle } from '../../theme/internal';
|
||||
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
|
||||
import { type CSSObject, unit } from '@ant-design/cssinjs';
|
||||
|
||||
import { resetComponent } from '../../style';
|
||||
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
|
||||
import { genStyleHooks, mergeToken } from '../../theme/internal';
|
||||
|
||||
/** Component only token. Which will handle additional calculation of alias token */
|
||||
export interface ComponentToken {
|
||||
@ -16,10 +17,10 @@ type BackTopToken = FullToken<'BackTop'> & {
|
||||
backTopSize: number;
|
||||
|
||||
// Position
|
||||
backTopBlockEnd: number;
|
||||
backTopInlineEnd: number;
|
||||
backTopInlineEndMD: number;
|
||||
backTopInlineEndXS: number;
|
||||
backTopBlockEnd: number | string;
|
||||
backTopInlineEnd: number | string;
|
||||
backTopInlineEndMD: number | string;
|
||||
backTopInlineEndXS: number | string;
|
||||
};
|
||||
|
||||
// ============================== Shared ==============================
|
||||
@ -61,34 +62,35 @@ const genSharedBackTopStyle: GenerateStyle<BackTopToken, CSSObject> = (token): C
|
||||
// change to .backtop .backtop-icon
|
||||
[`${componentCls}-icon`]: {
|
||||
fontSize: backTopFontSize,
|
||||
lineHeight: `${backTopSize}px`,
|
||||
lineHeight: unit(backTopSize),
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const genMediaBackTopStyle: GenerateStyle<BackTopToken> = (token): CSSObject => {
|
||||
const { componentCls } = token;
|
||||
|
||||
const { componentCls, screenMD, screenXS, backTopInlineEndMD, backTopInlineEndXS } = token;
|
||||
return {
|
||||
[`@media (max-width: ${token.screenMD}px)`]: {
|
||||
[`@media (max-width: ${unit(screenMD)})`]: {
|
||||
[componentCls]: {
|
||||
insetInlineEnd: token.backTopInlineEndMD,
|
||||
insetInlineEnd: backTopInlineEndMD,
|
||||
},
|
||||
},
|
||||
|
||||
[`@media (max-width: ${token.screenXS}px)`]: {
|
||||
[`@media (max-width: ${unit(screenXS)})`]: {
|
||||
[componentCls]: {
|
||||
insetInlineEnd: token.backTopInlineEndXS,
|
||||
insetInlineEnd: backTopInlineEndXS,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// ============================== Export ==============================
|
||||
export default genComponentStyleHook<'BackTop'>(
|
||||
'BackTop',
|
||||
export const prepareComponentToken: GetDefaultToken<'BackTop'> = (token) => ({
|
||||
zIndexPopup: token.zIndexBase + 10,
|
||||
});
|
||||
|
||||
// ============================== Export ==============================
|
||||
export default genStyleHooks(
|
||||
'BackTop',
|
||||
(token) => {
|
||||
const {
|
||||
fontSizeHeading3,
|
||||
@ -96,23 +98,20 @@ export default genComponentStyleHook<'BackTop'>(
|
||||
colorTextLightSolid,
|
||||
colorText,
|
||||
controlHeightLG,
|
||||
calc,
|
||||
} = token;
|
||||
|
||||
const backTopToken = mergeToken<BackTopToken>(token, {
|
||||
backTopBackground: colorTextDescription,
|
||||
backTopColor: colorTextLightSolid,
|
||||
backTopHoverBackground: colorText,
|
||||
backTopFontSize: fontSizeHeading3,
|
||||
backTopSize: controlHeightLG,
|
||||
|
||||
backTopBlockEnd: controlHeightLG * 1.25,
|
||||
backTopInlineEnd: controlHeightLG * 2.5,
|
||||
backTopInlineEndMD: controlHeightLG * 1.5,
|
||||
backTopInlineEndXS: controlHeightLG * 0.5,
|
||||
backTopBlockEnd: calc(controlHeightLG).mul(1.25).equal(),
|
||||
backTopInlineEnd: calc(controlHeightLG).mul(2.5).equal(),
|
||||
backTopInlineEndMD: calc(controlHeightLG).mul(1.5).equal(),
|
||||
backTopInlineEndXS: calc(controlHeightLG).mul(0.5).equal(),
|
||||
});
|
||||
return [genSharedBackTopStyle(backTopToken), genMediaBackTopStyle(backTopToken)];
|
||||
},
|
||||
(token) => ({
|
||||
zIndexPopup: token.zIndexBase + 10,
|
||||
}),
|
||||
prepareComponentToken,
|
||||
);
|
||||
|
@ -33,6 +33,10 @@ const Ribbon: React.FC<RibbonProps> = (props) => {
|
||||
} = props;
|
||||
const { getPrefixCls, direction } = React.useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('ribbon', customizePrefixCls);
|
||||
|
||||
const wrapperCls = `${prefixCls}-wrapper`;
|
||||
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls, wrapperCls);
|
||||
|
||||
const colorInPreset = isPresetColor(color, false);
|
||||
const ribbonCls = classNames(
|
||||
prefixCls,
|
||||
@ -43,15 +47,15 @@ const Ribbon: React.FC<RibbonProps> = (props) => {
|
||||
},
|
||||
className,
|
||||
);
|
||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||
|
||||
const colorStyle: React.CSSProperties = {};
|
||||
const cornerColorStyle: React.CSSProperties = {};
|
||||
if (color && !colorInPreset) {
|
||||
colorStyle.background = color;
|
||||
cornerColorStyle.color = color;
|
||||
}
|
||||
return wrapSSR(
|
||||
<div className={classNames(`${prefixCls}-wrapper`, rootClassName, hashId)}>
|
||||
return wrapCSSVar(
|
||||
<div className={classNames(wrapperCls, rootClassName, hashId, cssVarCls)}>
|
||||
{children}
|
||||
<div className={classNames(ribbonCls, hashId)} style={{ ...colorStyle, ...style }}>
|
||||
<span className={`${prefixCls}-text`}>{text}</span>
|
||||
|
@ -1,7 +1,8 @@
|
||||
import classnames from 'classnames';
|
||||
import CSSMotion from 'rc-motion';
|
||||
import * as React from 'react';
|
||||
import { useMemo, useRef } from 'react';
|
||||
import classnames from 'classnames';
|
||||
import CSSMotion from 'rc-motion';
|
||||
|
||||
import type { PresetStatusColorType } from '../_util/colors';
|
||||
import { isPresetColor } from '../_util/colors';
|
||||
import { cloneElement } from '../_util/reactNode';
|
||||
@ -75,8 +76,7 @@ const InternalBadge: React.ForwardRefRenderFunction<HTMLSpanElement, BadgeProps>
|
||||
const { getPrefixCls, direction, badge } = React.useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('badge', customizePrefixCls);
|
||||
|
||||
// Style
|
||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls);
|
||||
|
||||
// ================================ Misc ================================
|
||||
const numberedDisplayCount = (
|
||||
@ -183,12 +183,13 @@ const InternalBadge: React.ForwardRefRenderFunction<HTMLSpanElement, BadgeProps>
|
||||
badge?.classNames?.root,
|
||||
classNames?.root,
|
||||
hashId,
|
||||
cssVarCls,
|
||||
);
|
||||
|
||||
// <Badge status="success" />
|
||||
if (!children && hasStatus) {
|
||||
const statusTextColor = mergedStyle.color;
|
||||
return wrapSSR(
|
||||
return wrapCSSVar(
|
||||
<span
|
||||
{...restProps}
|
||||
className={badgeClassName}
|
||||
@ -207,7 +208,7 @@ const InternalBadge: React.ForwardRefRenderFunction<HTMLSpanElement, BadgeProps>
|
||||
);
|
||||
}
|
||||
|
||||
return wrapSSR(
|
||||
return wrapCSSVar(
|
||||
<span
|
||||
ref={ref}
|
||||
{...restProps}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user