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"],
|
"sandboxes": ["antd-reproduction-template-forked-jyh2k9"],
|
||||||
"node": "18"
|
"node": "18"
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
.demo-logo {
|
.demo-logo {
|
||||||
width: 120px;
|
width: 120px;
|
||||||
|
min-width: 120px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
background: rgba(255, 255, 255, 0.2);
|
background: rgba(255, 255, 255, 0.2);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
|
margin-inline-end: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.demo-logo-vertical {
|
.demo-logo-vertical {
|
||||||
|
@ -68,6 +68,7 @@ const useThemeAnimation = () => {
|
|||||||
if (!(event && typeof document.startViewTransition === 'function')) {
|
if (!(event && typeof document.startViewTransition === 'function')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const time = Date.now();
|
||||||
const x = event.clientX;
|
const x = event.clientX;
|
||||||
const y = event.clientY;
|
const y = event.clientY;
|
||||||
const endRadius = Math.hypot(Math.max(x, innerWidth - x), Math.max(y, innerHeight - y));
|
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');
|
root.classList.add(isDark ? 'light' : 'dark');
|
||||||
})
|
})
|
||||||
.ready.then(() => {
|
.ready.then(() => {
|
||||||
|
console.log(`Theme transition finished in ${Date.now() - time}ms`);
|
||||||
const clipPath = [
|
const clipPath = [
|
||||||
`circle(0px at ${x}px ${y}px)`,
|
`circle(0px at ${x}px ${y}px)`,
|
||||||
`circle(${endRadius}px at ${x}px ${y}px)`,
|
`circle(${endRadius}px at ${x}px ${y}px)`,
|
||||||
|
@ -1,33 +1,41 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { createStyles, css, useTheme } from 'antd-style';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import { Typography, Skeleton, Carousel } from 'antd';
|
import { Badge, Carousel, Skeleton, Typography } from 'antd';
|
||||||
import type { Extra, Icon } from './util';
|
import { createStyles, useTheme } from 'antd-style';
|
||||||
import SiteContext from '../../../theme/slots/SiteContext';
|
import classNames from 'classnames';
|
||||||
import { getCarouselStyle, useSiteData } from './util';
|
|
||||||
import useLocale from '../../../hooks/useLocale';
|
|
||||||
|
|
||||||
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();
|
const { carousel } = getCarouselStyle();
|
||||||
|
|
||||||
|
const itemBase = css`
|
||||||
|
display: flex;
|
||||||
|
flex: 1 1 0;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
text-decoration: none;
|
||||||
|
background: ${token.colorBgContainer};
|
||||||
|
border: ${token.lineWidth}px solid ${token.colorBorderSecondary};
|
||||||
|
border-radius: ${token.borderRadiusLG}px;
|
||||||
|
transition: all ${token.motionDurationSlow};
|
||||||
|
padding-block: ${token.paddingMD}px;
|
||||||
|
padding-inline: ${token.paddingLG}px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
`;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
itemBase: css`
|
itemBase,
|
||||||
display: flex;
|
ribbon: css`
|
||||||
flex: 1 1 0;
|
& > .${cx(itemBase)} {
|
||||||
flex-direction: column;
|
height: 100%;
|
||||||
align-items: stretch;
|
}
|
||||||
text-decoration: none;
|
|
||||||
background: ${token.colorBgContainer};
|
|
||||||
border: ${token.lineWidth}px solid ${token.colorBorderSecondary};
|
|
||||||
border-radius: ${token.borderRadiusLG}px;
|
|
||||||
transition: all ${token.motionDurationSlow};
|
|
||||||
padding-block: ${token.paddingMD}px;
|
|
||||||
padding-inline: ${token.paddingLG}px;
|
|
||||||
`,
|
`,
|
||||||
cardItem: css`
|
cardItem: css`
|
||||||
width: 33%;
|
|
||||||
&:hover {
|
&:hover {
|
||||||
box-shadow: ${token.boxShadowCard};
|
box-shadow: ${token.boxShadowCard};
|
||||||
}
|
}
|
||||||
@ -45,6 +53,9 @@ const useStyle = createStyles(({ token }) => {
|
|||||||
column-gap: ${token.paddingMD * 2}px;
|
column-gap: ${token.paddingMD * 2}px;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
text-align: start;
|
text-align: start;
|
||||||
|
> * {
|
||||||
|
width: calc((100% - ${token.marginXXL * 2}px) / 3);
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
carousel,
|
carousel,
|
||||||
};
|
};
|
||||||
@ -56,7 +67,7 @@ interface RecommendItemProps {
|
|||||||
icons: Icon[];
|
icons: Icon[];
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
const RecommendItem = ({ extra, index, icons, className }: RecommendItemProps) => {
|
const RecommendItem: React.FC<RecommendItemProps> = ({ extra, index, icons, className }) => {
|
||||||
const token = useTheme();
|
const token = useTheme();
|
||||||
const { styles } = useStyle();
|
const { styles } = useStyle();
|
||||||
|
|
||||||
@ -65,7 +76,7 @@ const RecommendItem = ({ extra, index, icons, className }: RecommendItemProps) =
|
|||||||
}
|
}
|
||||||
const icon = icons.find((i) => i.name === extra.source);
|
const icon = icons.find((i) => i.name === extra.source);
|
||||||
|
|
||||||
return (
|
const card = (
|
||||||
<a
|
<a
|
||||||
key={extra?.title}
|
key={extra?.title}
|
||||||
href={extra.href}
|
href={extra.href}
|
||||||
@ -83,6 +94,16 @@ const RecommendItem = ({ extra, index, icons, className }: RecommendItemProps) =
|
|||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (index === 0) {
|
||||||
|
return (
|
||||||
|
<Badge.Ribbon text="HOT" color="red" rootClassName={styles.ribbon}>
|
||||||
|
{card}
|
||||||
|
</Badge.Ribbon>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return card;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const BannerRecommendsFallback: FC = () => {
|
export const BannerRecommendsFallback: FC = () => {
|
||||||
@ -93,8 +114,8 @@ export const BannerRecommendsFallback: FC = () => {
|
|||||||
|
|
||||||
return isMobile ? (
|
return isMobile ? (
|
||||||
<Carousel className={styles.carousel}>
|
<Carousel className={styles.carousel}>
|
||||||
{list.map((extra, index) => (
|
{list.map((_, index) => (
|
||||||
<div key={index}>
|
<div key={index} className={styles.itemBase}>
|
||||||
<Skeleton active style={{ padding: '0 24px' }} />
|
<Skeleton active style={{ padding: '0 24px' }} />
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@ -102,20 +123,26 @@ export const BannerRecommendsFallback: FC = () => {
|
|||||||
) : (
|
) : (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
{list.map((_, index) => (
|
{list.map((_, index) => (
|
||||||
<Skeleton key={index} active />
|
<div key={index} className={styles.itemBase}>
|
||||||
|
<Skeleton active />
|
||||||
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function BannerRecommends() {
|
const BannerRecommends: React.FC = () => {
|
||||||
const { styles } = useStyle();
|
const { styles } = useStyle();
|
||||||
const [, lang] = useLocale();
|
const [, lang] = useLocale();
|
||||||
const { isMobile } = React.useContext(SiteContext);
|
const { isMobile } = React.useContext(SiteContext);
|
||||||
const data = useSiteData();
|
const data = useSiteData();
|
||||||
const extras = data?.extras?.[lang];
|
const extras = data?.extras?.[lang];
|
||||||
const icons = data?.icons;
|
const icons = data?.icons || [];
|
||||||
const first3 = extras.length === 0 ? Array(3).fill(null) : extras.slice(0, 3);
|
const first3 = !extras || extras.length === 0 ? Array(3).fill(null) : extras.slice(0, 3);
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
return <BannerRecommendsFallback />;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@ -147,4 +174,6 @@ export default function BannerRecommends() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default BannerRecommends;
|
||||||
|
@ -17,9 +17,9 @@ import {
|
|||||||
Tooltip,
|
Tooltip,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import { createStyles } from 'antd-style';
|
import { createStyles } from 'antd-style';
|
||||||
import classNames from 'classnames';
|
|
||||||
|
|
||||||
import useLocale from '../../../../hooks/useLocale';
|
import useLocale from '../../../../hooks/useLocale';
|
||||||
|
import Tilt from './Tilt';
|
||||||
|
|
||||||
const { _InternalPanelDoNotUseOrYouWillBeFired: ModalPanel } = Modal;
|
const { _InternalPanelDoNotUseOrYouWillBeFired: ModalPanel } = Modal;
|
||||||
const { _InternalPanelDoNotUseOrYouWillBeFired: InternalTooltip } = Tooltip;
|
const { _InternalPanelDoNotUseOrYouWillBeFired: InternalTooltip } = Tooltip;
|
||||||
@ -72,16 +72,14 @@ const locales = {
|
|||||||
|
|
||||||
const useStyle = createStyles(({ token, css }) => {
|
const useStyle = createStyles(({ token, css }) => {
|
||||||
const gap = token.padding;
|
const gap = token.padding;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
holder: css`
|
holder: css`
|
||||||
width: 500px;
|
width: 500px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
row-gap: ${gap}px;
|
row-gap: ${gap}px;
|
||||||
opacity: 0.65;
|
opacity: 0.8;
|
||||||
`,
|
`,
|
||||||
|
|
||||||
flex: css`
|
flex: css`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
@ -105,25 +103,16 @@ const useStyle = createStyles(({ token, css }) => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
export interface ComponentsBlockProps {
|
const ComponentsBlock: React.FC = () => {
|
||||||
className?: string;
|
|
||||||
style?: React.CSSProperties;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ComponentsBlock: React.FC<ComponentsBlockProps> = (props) => {
|
|
||||||
const { className, style } = props;
|
|
||||||
|
|
||||||
const [locale] = useLocale(locales);
|
const [locale] = useLocale(locales);
|
||||||
const { styles } = useStyle();
|
const { styles } = useStyle();
|
||||||
|
|
||||||
return (
|
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%">
|
<ModalPanel title="Ant Design 5.0" width="100%">
|
||||||
{locale.text}
|
{locale.text}
|
||||||
</ModalPanel>
|
</ModalPanel>
|
||||||
|
|
||||||
<Alert message={locale.infoText} type="info" />
|
<Alert message={locale.infoText} type="info" />
|
||||||
|
|
||||||
{/* Line */}
|
{/* Line */}
|
||||||
<div className={styles.flex}>
|
<div className={styles.flex}>
|
||||||
<ColorPicker style={{ flex: 'none' }} />
|
<ColorPicker style={{ flex: 'none' }} />
|
||||||
@ -139,57 +128,34 @@ const ComponentsBlock: React.FC<ComponentsBlockProps> = (props) => {
|
|||||||
{locale.dropdown}
|
{locale.dropdown}
|
||||||
</Dropdown.Button>
|
</Dropdown.Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Select
|
<Select
|
||||||
style={{ flex: 'auto' }}
|
style={{ flex: 'auto' }}
|
||||||
mode="multiple"
|
mode="multiple"
|
||||||
maxTagCount="responsive"
|
maxTagCount="responsive"
|
||||||
defaultValue={[{ value: 'apple' }, { value: 'banana' }]}
|
defaultValue={[{ value: 'apple' }, { value: 'banana' }]}
|
||||||
options={[
|
options={[
|
||||||
{
|
{ value: 'apple', label: locale.apple },
|
||||||
value: 'apple',
|
{ value: 'banana', label: locale.banana },
|
||||||
label: locale.apple,
|
{ value: 'orange', label: locale.orange },
|
||||||
},
|
{ value: 'watermelon', label: locale.watermelon },
|
||||||
{
|
|
||||||
value: 'banana',
|
|
||||||
label: locale.banana,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'orange',
|
|
||||||
label: locale.orange,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'watermelon',
|
|
||||||
label: locale.watermelon,
|
|
||||||
},
|
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Input style={{ flex: 'none', width: 120 }} />
|
<Input style={{ flex: 'none', width: 120 }} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Progress
|
<Progress
|
||||||
style={{ margin: 0 }}
|
style={{ margin: 0 }}
|
||||||
percent={100}
|
percent={100}
|
||||||
strokeColor={{ '0%': '#108ee9', '100%': '#87d068' }}
|
strokeColor={{ '0%': '#108ee9', '100%': '#87d068' }}
|
||||||
/>
|
/>
|
||||||
<Progress style={{ margin: 0 }} percent={33} status="exception" />
|
<Progress style={{ margin: 0 }} percent={33} status="exception" />
|
||||||
|
|
||||||
<Steps
|
<Steps
|
||||||
current={1}
|
current={1}
|
||||||
items={[
|
items={[
|
||||||
{
|
{ title: locale.finished },
|
||||||
title: locale.finished,
|
{ title: locale.inProgress },
|
||||||
},
|
{ title: locale.waiting },
|
||||||
{
|
|
||||||
title: locale.inProgress,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: locale.waiting,
|
|
||||||
},
|
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Line */}
|
{/* Line */}
|
||||||
<div className={styles.block}>
|
<div className={styles.block}>
|
||||||
<Slider
|
<Slider
|
||||||
@ -200,16 +166,13 @@ const ComponentsBlock: React.FC<ComponentsBlockProps> = (props) => {
|
|||||||
26: '26°C',
|
26: '26°C',
|
||||||
37: '37°C',
|
37: '37°C',
|
||||||
100: {
|
100: {
|
||||||
style: {
|
style: { color: '#f50' },
|
||||||
color: '#f50',
|
|
||||||
},
|
|
||||||
label: <strong>100°C</strong>,
|
label: <strong>100°C</strong>,
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
defaultValue={[26, 37]}
|
defaultValue={[26, 37]}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Line */}
|
{/* Line */}
|
||||||
<div className={styles.flex}>
|
<div className={styles.flex}>
|
||||||
<Button className={styles.ptg_20} type="primary">
|
<Button className={styles.ptg_20} type="primary">
|
||||||
@ -226,7 +189,6 @@ const ComponentsBlock: React.FC<ComponentsBlockProps> = (props) => {
|
|||||||
{locale.icon}
|
{locale.icon}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Line */}
|
{/* Line */}
|
||||||
<div className={styles.block}>
|
<div className={styles.block}>
|
||||||
<div className={styles.flex}>
|
<div className={styles.flex}>
|
||||||
@ -236,7 +198,6 @@ const ComponentsBlock: React.FC<ComponentsBlockProps> = (props) => {
|
|||||||
checkedChildren={<CheckOutlined />}
|
checkedChildren={<CheckOutlined />}
|
||||||
unCheckedChildren={<CloseOutlined />}
|
unCheckedChildren={<CloseOutlined />}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Checkbox.Group
|
<Checkbox.Group
|
||||||
className={styles.ptg_none}
|
className={styles.ptg_none}
|
||||||
options={[locale.apple, locale.banana, locale.orange]}
|
options={[locale.apple, locale.banana, locale.orange]}
|
||||||
@ -244,15 +205,12 @@ const ComponentsBlock: React.FC<ComponentsBlockProps> = (props) => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<InternalMessage content={locale.release} type="success" />
|
<InternalMessage content={locale.release} type="success" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<InternalTooltip title={locale.hello} placement="topLeft" className={styles.noMargin} />
|
<InternalTooltip title={locale.hello} placement="topLeft" className={styles.noMargin} />
|
||||||
|
|
||||||
<Alert message="Ant Design love you!" type="success" />
|
<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 SiteContext from '../../../../theme/slots/SiteContext';
|
||||||
import * as utils from '../../../../theme/utils';
|
import * as utils from '../../../../theme/utils';
|
||||||
import { GroupMask } from '../Group';
|
import { GroupMask } from '../Group';
|
||||||
import useMouseTransform from './useMouseTransform';
|
|
||||||
|
|
||||||
const ComponentsBlock = React.lazy(() => import('./ComponentsBlock'));
|
const ComponentsBlock = React.lazy(() => import('./ComponentsBlock'));
|
||||||
|
|
||||||
@ -28,7 +27,6 @@ const locales = {
|
|||||||
const useStyle = () => {
|
const useStyle = () => {
|
||||||
const { direction } = React.useContext(ConfigProvider.ConfigContext);
|
const { direction } = React.useContext(ConfigProvider.ConfigContext);
|
||||||
const isRTL = direction === 'rtl';
|
const isRTL = direction === 'rtl';
|
||||||
|
|
||||||
return createStyles(({ token, css, cx }) => {
|
return createStyles(({ token, css, cx }) => {
|
||||||
const textShadow = `0 0 3px ${token.colorBgContainer}`;
|
const textShadow = `0 0 3px ${token.colorBgContainer}`;
|
||||||
|
|
||||||
@ -37,12 +35,14 @@ const useStyle = () => {
|
|||||||
inset: 0;
|
inset: 0;
|
||||||
backdrop-filter: blur(4px);
|
backdrop-filter: blur(4px);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transition: opacity 1s ease;
|
background-color: rgba(255, 255, 255, 0.2);
|
||||||
|
transition: all 1s ease;
|
||||||
|
pointer-events: none;
|
||||||
`);
|
`);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
holder: css`
|
holder: css`
|
||||||
height: 520px;
|
height: 640px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -94,6 +94,7 @@ const useStyle = () => {
|
|||||||
|
|
||||||
child: css`
|
child: css`
|
||||||
position: relative;
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
@ -114,10 +115,8 @@ const PreviewBanner: React.FC<PreviewBannerProps> = (props) => {
|
|||||||
const { pathname, search } = useLocation();
|
const { pathname, search } = useLocation();
|
||||||
const isZhCN = utils.isZhCN(pathname);
|
const isZhCN = utils.isZhCN(pathname);
|
||||||
|
|
||||||
const [componentsBlockStyle, mouseEvents] = useMouseTransform();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GroupMask {...mouseEvents}>
|
<GroupMask>
|
||||||
{/* Image Left Top */}
|
{/* Image Left Top */}
|
||||||
<img
|
<img
|
||||||
style={{ position: 'absolute', left: isMobile ? -120 : 0, top: 0, width: 240 }}
|
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}>
|
<div className={styles.holder}>
|
||||||
{/* Mobile not show the component preview */}
|
{/* Mobile not show the component preview */}
|
||||||
<Suspense fallback={null}>
|
<Suspense fallback={null}>
|
||||||
{!isMobile && <ComponentsBlock className={styles.block} style={componentsBlockStyle} />}
|
{isMobile ? null : (
|
||||||
|
<div className={styles.block}>
|
||||||
|
<ComponentsBlock />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</Suspense>
|
</Suspense>
|
||||||
<div className={styles.mask} />
|
<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,
|
...themeToken,
|
||||||
colorPrimary: colorPrimaryValue,
|
colorPrimary: colorPrimaryValue,
|
||||||
},
|
},
|
||||||
hashed: true,
|
|
||||||
algorithm: algorithmFn,
|
algorithm: algorithmFn,
|
||||||
components: {
|
components: {
|
||||||
Layout: isLight
|
Layout: isLight
|
||||||
? {
|
? {
|
||||||
colorBgHeader: 'transparent',
|
headerBg: 'transparent',
|
||||||
colorBgBody: 'transparent',
|
bodyBg: 'transparent',
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
// colorBgBody: 'transparent',
|
// colorBgBody: 'transparent',
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { css } from 'antd-style';
|
import { css } from 'antd-style';
|
||||||
import useFetch from '../../../hooks/useFetch';
|
import { useEffect, useState } from 'react';
|
||||||
|
import fetch from 'cross-fetch';
|
||||||
|
|
||||||
export interface Author {
|
export interface Author {
|
||||||
avatar: string;
|
avatar: string;
|
||||||
@ -80,8 +81,18 @@ export function preLoad(list: string[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useSiteData(): Partial<SiteData> {
|
export function useSiteData(): Partial<SiteData> | undefined {
|
||||||
return useFetch('https://render.alipay.com/p/h5data/antd4-config_website-h5data.json');
|
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 = () => ({
|
export const getCarouselStyle = () => ({
|
||||||
|
@ -4,7 +4,7 @@ import { createStyles, css } from 'antd-style';
|
|||||||
|
|
||||||
import useDark from '../../hooks/useDark';
|
import useDark from '../../hooks/useDark';
|
||||||
import useLocale from '../../hooks/useLocale';
|
import useLocale from '../../hooks/useLocale';
|
||||||
// import BannerRecommends, { BannerRecommendsFallback } from './components/BannerRecommends';
|
import BannerRecommends from './components/BannerRecommends';
|
||||||
import PreviewBanner from './components/PreviewBanner';
|
import PreviewBanner from './components/PreviewBanner';
|
||||||
import Group from './components/Group';
|
import Group from './components/Group';
|
||||||
|
|
||||||
@ -46,10 +46,7 @@ const Homepage: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
<PreviewBanner>
|
<PreviewBanner>
|
||||||
{/* 文档很久没更新了,先藏起来 */}
|
<BannerRecommends />
|
||||||
{/* <Suspense fallback={<BannerRecommendsFallback />}>
|
|
||||||
<BannerRecommends />
|
|
||||||
</Suspense> */}
|
|
||||||
</PreviewBanner>
|
</PreviewBanner>
|
||||||
|
|
||||||
<div>
|
<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 { createStyles, css, useTheme } from 'antd-style';
|
||||||
import { getDesignToken } from 'antd-token-previewer';
|
import { getDesignToken } from 'antd-token-previewer';
|
||||||
import React, { useMemo, useState } from 'react';
|
|
||||||
import tokenMeta from 'antd/es/version/token-meta.json';
|
import tokenMeta from 'antd/es/version/token-meta.json';
|
||||||
import tokenData from 'antd/es/version/token.json';
|
import tokenData from 'antd/es/version/token.json';
|
||||||
import { ConfigProvider, Table, Popover, Typography } from 'antd';
|
|
||||||
import useLocale from '../../../hooks/useLocale';
|
import useLocale from '../../../hooks/useLocale';
|
||||||
import { useColumns } from '../TokenTable';
|
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 defaultToken = getDesignToken();
|
||||||
|
|
||||||
const locales = {
|
const locales = {
|
||||||
@ -18,6 +31,8 @@ const locales = {
|
|||||||
value: '默认值',
|
value: '默认值',
|
||||||
componentToken: '组件 Token',
|
componentToken: '组件 Token',
|
||||||
globalToken: '全局 Token',
|
globalToken: '全局 Token',
|
||||||
|
componentComment: '这里是你的组件 token',
|
||||||
|
globalComment: '这里是你的全局 token',
|
||||||
help: '如何定制?',
|
help: '如何定制?',
|
||||||
customizeTokenLink: '/docs/react/customize-theme-cn#修改主题变量',
|
customizeTokenLink: '/docs/react/customize-theme-cn#修改主题变量',
|
||||||
customizeComponentTokenLink: '/docs/react/customize-theme-cn#修改组件变量',
|
customizeComponentTokenLink: '/docs/react/customize-theme-cn#修改组件变量',
|
||||||
@ -29,6 +44,8 @@ const locales = {
|
|||||||
value: 'Default Value',
|
value: 'Default Value',
|
||||||
componentToken: 'Component Token',
|
componentToken: 'Component Token',
|
||||||
globalToken: 'Global Token',
|
globalToken: 'Global Token',
|
||||||
|
componentComment: 'here is your component tokens',
|
||||||
|
globalComment: 'here is your global tokens',
|
||||||
help: 'How to use?',
|
help: 'How to use?',
|
||||||
customizeTokenLink: '/docs/react/customize-theme#customize-design-token',
|
customizeTokenLink: '/docs/react/customize-theme#customize-design-token',
|
||||||
customizeComponentTokenLink: 'docs/react/customize-theme#customize-component-token',
|
customizeComponentTokenLink: 'docs/react/customize-theme#customize-component-token',
|
||||||
@ -46,13 +63,13 @@ const useStyle = createStyles(() => ({
|
|||||||
`,
|
`,
|
||||||
arrowIcon: css`
|
arrowIcon: css`
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
margin-right: 8px;
|
margin-inline-end: 8px;
|
||||||
& svg {
|
& svg {
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
help: css`
|
help: css`
|
||||||
margin-left: 8px;
|
margin-inline-start: 8px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
color: #999;
|
color: #999;
|
||||||
@ -69,16 +86,14 @@ interface SubTokenTableProps {
|
|||||||
helpLink: string;
|
helpLink: string;
|
||||||
tokens: string[];
|
tokens: string[];
|
||||||
component?: string;
|
component?: string;
|
||||||
|
comment?: {
|
||||||
|
componentComment?: string;
|
||||||
|
globalComment?: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const SubTokenTable: React.FC<SubTokenTableProps> = ({
|
const SubTokenTable: React.FC<SubTokenTableProps> = (props) => {
|
||||||
defaultOpen,
|
const { defaultOpen, tokens, title, helpText, helpLink, component, comment } = props;
|
||||||
tokens,
|
|
||||||
title,
|
|
||||||
helpText,
|
|
||||||
helpLink,
|
|
||||||
component,
|
|
||||||
}) => {
|
|
||||||
const [, lang] = useLocale(locales);
|
const [, lang] = useLocale(locales);
|
||||||
const token = useTheme();
|
const token = useTheme();
|
||||||
const columns = useColumns();
|
const columns = useColumns();
|
||||||
@ -92,24 +107,7 @@ const SubTokenTable: React.FC<SubTokenTableProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const data = tokens
|
const data = tokens
|
||||||
.sort(
|
.sort(component ? undefined : compare)
|
||||||
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;
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.map((name) => {
|
.map((name) => {
|
||||||
const meta = component
|
const meta = component
|
||||||
? tokenMeta.components[component].find((item) => item.token === name)
|
? tokenMeta.components[component].find((item) => item.token === name)
|
||||||
@ -133,7 +131,7 @@ const SubTokenTable: React.FC<SubTokenTableProps> = ({
|
|||||||
theme={{
|
theme={{
|
||||||
components: {
|
components: {
|
||||||
${component}: {
|
${component}: {
|
||||||
/* here is your component tokens */
|
/* ${comment?.componentComment} */
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
@ -143,7 +141,7 @@ const SubTokenTable: React.FC<SubTokenTableProps> = ({
|
|||||||
: `<ConfigProvider
|
: `<ConfigProvider
|
||||||
theme={{
|
theme={{
|
||||||
token: {
|
token: {
|
||||||
/* here is your global tokens */
|
/* ${comment?.globalComment} */
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -161,16 +159,17 @@ const SubTokenTable: React.FC<SubTokenTableProps> = ({
|
|||||||
popupStyle={{ width: 400 }}
|
popupStyle={{ width: 400 }}
|
||||||
content={
|
content={
|
||||||
<Typography>
|
<Typography>
|
||||||
|
{/* <SourceCode lang="jsx">{code}</SourceCode> */}
|
||||||
<pre style={{ fontSize: 12 }}>{code}</pre>
|
<pre style={{ fontSize: 12 }}>{code}</pre>
|
||||||
<a href={helpLink} target="_blank" rel="noreferrer">
|
<a href={helpLink} target="_blank" rel="noreferrer">
|
||||||
<LinkOutlined style={{ marginRight: 4 }} />
|
<LinkOutlined style={{ marginInlineEnd: 4 }} />
|
||||||
{helpText}
|
{helpText}
|
||||||
</a>
|
</a>
|
||||||
</Typography>
|
</Typography>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<span className={styles.help}>
|
<span className={styles.help}>
|
||||||
<QuestionCircleOutlined style={{ marginRight: 3 }} />
|
<QuestionCircleOutlined style={{ marginInlineEnd: 4 }} />
|
||||||
{helpText}
|
{helpText}
|
||||||
</span>
|
</span>
|
||||||
</Popover>
|
</Popover>
|
||||||
@ -217,12 +216,16 @@ const ComponentTokenTable: React.FC<ComponentTokenTableProps> = ({ component })
|
|||||||
<>
|
<>
|
||||||
{tokenMeta.components[component] && (
|
{tokenMeta.components[component] && (
|
||||||
<SubTokenTable
|
<SubTokenTable
|
||||||
|
defaultOpen
|
||||||
title={locale.componentToken}
|
title={locale.componentToken}
|
||||||
helpText={locale.help}
|
helpText={locale.help}
|
||||||
helpLink={locale.customizeTokenLink}
|
helpLink={locale.customizeTokenLink}
|
||||||
tokens={tokenMeta.components[component].map((item) => item.token)}
|
tokens={tokenMeta.components[component].map((item) => item.token)}
|
||||||
component={component}
|
component={component}
|
||||||
defaultOpen
|
comment={{
|
||||||
|
componentComment: locale.componentComment,
|
||||||
|
globalComment: locale.globalComment,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<SubTokenTable
|
<SubTokenTable
|
||||||
@ -230,6 +233,10 @@ const ComponentTokenTable: React.FC<ComponentTokenTableProps> = ({ component })
|
|||||||
helpText={locale.help}
|
helpText={locale.help}
|
||||||
helpLink={locale.customizeComponentTokenLink}
|
helpLink={locale.customizeComponentTokenLink}
|
||||||
tokens={mergedGlobalTokens}
|
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 React, { useContext } from 'react';
|
||||||
import { DumiDemoGrid, FormattedMessage } from 'dumi';
|
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 classNames from 'classnames';
|
||||||
import { Tooltip } from 'antd';
|
import { ConfigProvider, Tooltip } from 'antd';
|
||||||
import DemoContext from '../../slots/DemoContext';
|
import DemoContext from '../../slots/DemoContext';
|
||||||
import useLayoutState from '../../../hooks/useLayoutState';
|
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 DemoWrapper: typeof DumiDemoGrid = ({ items }) => {
|
||||||
const { showDebug, setShowDebug } = useContext(DemoContext);
|
const { showDebug, setShowDebug } = useContext(DemoContext);
|
||||||
|
const [locale] = useLocale(locales);
|
||||||
|
|
||||||
const [expandAll, setExpandAll] = useLayoutState(false);
|
const [expandAll, setExpandAll] = useLayoutState(false);
|
||||||
|
const [enableCssVar, setEnableCssVar] = useLayoutState(true);
|
||||||
|
|
||||||
const expandTriggerClass = classNames('code-box-expand-trigger', {
|
const expandTriggerClass = classNames('code-box-expand-trigger', {
|
||||||
'code-box-expand-trigger-active': expandAll,
|
'code-box-expand-trigger-active': expandAll,
|
||||||
@ -23,29 +44,36 @@ const DemoWrapper: typeof DumiDemoGrid = ({ items }) => {
|
|||||||
setExpandAll(!expandAll);
|
setExpandAll(!expandAll);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleCssVarToggle = () => {
|
||||||
|
setEnableCssVar((v) => !v);
|
||||||
|
};
|
||||||
|
|
||||||
const demos = React.useMemo(
|
const demos = React.useMemo(
|
||||||
() =>
|
() =>
|
||||||
items.reduce((acc, item) => {
|
items.reduce(
|
||||||
const { previewerProps } = item;
|
(acc, item) => {
|
||||||
const { debug } = previewerProps;
|
const { previewerProps } = item;
|
||||||
|
const { debug } = previewerProps;
|
||||||
|
|
||||||
if (debug && !showDebug) return acc;
|
if (debug && !showDebug) return acc;
|
||||||
|
|
||||||
return acc.concat({
|
return acc.concat({
|
||||||
...item,
|
...item,
|
||||||
previewerProps: {
|
previewerProps: {
|
||||||
...previewerProps,
|
...previewerProps,
|
||||||
expand: expandAll,
|
expand: expandAll,
|
||||||
// always override debug property, because dumi will hide debug demo in production
|
// always override debug property, because dumi will hide debug demo in production
|
||||||
debug: false,
|
debug: false,
|
||||||
/**
|
/**
|
||||||
* antd extra marker for the original debug
|
* antd extra marker for the original debug
|
||||||
* @see https://github.com/ant-design/ant-design/pull/40130#issuecomment-1380208762
|
* @see https://github.com/ant-design/ant-design/pull/40130#issuecomment-1380208762
|
||||||
*/
|
*/
|
||||||
originDebug: debug,
|
originDebug: debug,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}, [] as typeof items),
|
},
|
||||||
|
[] as typeof items,
|
||||||
|
),
|
||||||
[expandAll, showDebug],
|
[expandAll, showDebug],
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -74,8 +102,17 @@ const DemoWrapper: typeof DumiDemoGrid = ({ items }) => {
|
|||||||
<BugOutlined className={expandTriggerClass} onClick={handleVisibleToggle} />
|
<BugOutlined className={expandTriggerClass} onClick={handleVisibleToggle} />
|
||||||
)}
|
)}
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
<Tooltip title={enableCssVar ? locale.disableCssVar : locale.enableCssVar}>
|
||||||
|
{enableCssVar ? (
|
||||||
|
<ExperimentFilled className={expandTriggerClass} onClick={handleCssVarToggle} />
|
||||||
|
) : (
|
||||||
|
<ExperimentOutlined className={expandTriggerClass} onClick={handleCssVarToggle} />
|
||||||
|
)}
|
||||||
|
</Tooltip>
|
||||||
</span>
|
</span>
|
||||||
<DumiDemoGrid items={demos} />
|
<ConfigProvider theme={{ cssVar: enableCssVar }}>
|
||||||
|
<DumiDemoGrid items={demos} />
|
||||||
|
</ConfigProvider>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import SourceCode from 'dumi/theme-default/builtins/SourceCode';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type { TabsProps } from 'antd';
|
import { ConfigProvider, Tabs } from 'antd';
|
||||||
import { Tabs } from 'antd';
|
import SourceCode from 'dumi/theme-default/builtins/SourceCode';
|
||||||
|
import type { Tab } from 'rc-tabs/lib/interface';
|
||||||
|
|
||||||
import NpmLogo from './npm';
|
import NpmLogo from './npm';
|
||||||
import PnpmLogo from './pnpm';
|
import PnpmLogo from './pnpm';
|
||||||
import YarnLogo from './yarn';
|
import YarnLogo from './yarn';
|
||||||
@ -12,51 +13,34 @@ interface InstallProps {
|
|||||||
pnpm?: string;
|
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 InstallDependencies: React.FC<InstallProps> = (props) => {
|
||||||
const { npm, yarn, pnpm } = props;
|
const { npm, yarn, pnpm } = props;
|
||||||
const items = React.useMemo<TabsProps['items']>(
|
const items: Tab[] = [
|
||||||
() =>
|
{
|
||||||
[
|
key: 'npm',
|
||||||
{
|
label: 'npm',
|
||||||
key: 'npm',
|
children: npm ? <SourceCode lang="bash">{npm}</SourceCode> : null,
|
||||||
children: npm ? <SourceCode lang="bash">{npm}</SourceCode> : null,
|
icon: <NpmLogo />,
|
||||||
label: npmLabel,
|
},
|
||||||
},
|
{
|
||||||
{
|
key: 'yarn',
|
||||||
key: 'yarn',
|
label: 'yarn',
|
||||||
children: yarn ? <SourceCode lang="bash">{yarn}</SourceCode> : null,
|
children: yarn ? <SourceCode lang="bash">{yarn}</SourceCode> : null,
|
||||||
label: yarnLabel,
|
icon: <YarnLogo />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'pnpm',
|
key: 'pnpm',
|
||||||
children: pnpm ? <SourceCode lang="bash">{pnpm}</SourceCode> : null,
|
label: 'pnpm',
|
||||||
label: pnpmLabel,
|
children: pnpm ? <SourceCode lang="bash">{pnpm}</SourceCode> : null,
|
||||||
},
|
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;
|
export default InstallDependencies;
|
||||||
|
@ -1,26 +1,39 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { createStyles, css } from 'antd-style';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
interface IconProps {
|
interface IconProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
style?: React.CSSProperties;
|
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 NpmIcon: React.FC<IconProps> = (props) => {
|
||||||
const { className, style } = props;
|
const { className, style } = props;
|
||||||
|
const { styles } = useStyle();
|
||||||
return (
|
return (
|
||||||
<svg
|
<span className={classNames(styles.iconWrap, className)} style={style}>
|
||||||
className={className}
|
<svg
|
||||||
style={style}
|
fill="#E53E3E"
|
||||||
fill="#E53E3E"
|
focusable="false"
|
||||||
focusable="false"
|
height="1em"
|
||||||
height="1em"
|
stroke="#E53E3E"
|
||||||
stroke="#E53E3E"
|
strokeWidth="0"
|
||||||
strokeWidth="0"
|
viewBox="0 0 16 16"
|
||||||
viewBox="0 0 16 16"
|
width="1em"
|
||||||
width="1em"
|
>
|
||||||
>
|
<path d="M0 0v16h16v-16h-16zM13 13h-2v-8h-3v8h-5v-10h10v10z" />
|
||||||
<path d="M0 0v16h16v-16h-16zM13 13h-2v-8h-3v8h-5v-10h10v10z" />
|
</svg>
|
||||||
</svg>
|
</span>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,28 +1,41 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { createStyles, css } from 'antd-style';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
interface IconProps {
|
interface IconProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
style?: React.CSSProperties;
|
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 PnpmIcon: React.FC<IconProps> = (props) => {
|
||||||
const { className, style } = props;
|
const { className, style } = props;
|
||||||
|
const { styles } = useStyle();
|
||||||
return (
|
return (
|
||||||
<svg
|
<span className={classNames(styles.iconWrap, className)} style={style}>
|
||||||
className={className}
|
<svg
|
||||||
style={style}
|
aria-hidden="true"
|
||||||
aria-hidden="true"
|
fill="#F69220"
|
||||||
fill="#F69220"
|
focusable="false"
|
||||||
focusable="false"
|
height="1em"
|
||||||
height="1em"
|
role="img"
|
||||||
role="img"
|
stroke="#F69220"
|
||||||
stroke="#F69220"
|
strokeWidth="0"
|
||||||
strokeWidth="0"
|
viewBox="0 0 24 24"
|
||||||
viewBox="0 0 24 24"
|
width="1em"
|
||||||
width="1em"
|
>
|
||||||
>
|
<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" />
|
||||||
<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>
|
||||||
</svg>
|
</span>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,27 +1,40 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { createStyles, css } from 'antd-style';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
interface IconProps {
|
interface IconProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
style?: React.CSSProperties;
|
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 YarnIcon: React.FC<IconProps> = (props) => {
|
||||||
const { className, style } = props;
|
const { className, style } = props;
|
||||||
|
const { styles } = useStyle();
|
||||||
return (
|
return (
|
||||||
<svg
|
<span className={classNames(styles.iconWrap, className)} style={style}>
|
||||||
className={className}
|
<svg
|
||||||
style={style}
|
aria-hidden="true"
|
||||||
aria-hidden="true"
|
fill="#2C8EBB"
|
||||||
fill="#2C8EBB"
|
focusable="false"
|
||||||
focusable="false"
|
height="1em"
|
||||||
height="1em"
|
stroke="#2C8EBB"
|
||||||
stroke="#2C8EBB"
|
strokeWidth="0"
|
||||||
strokeWidth="0"
|
viewBox="0 0 496 512"
|
||||||
viewBox="0 0 496 512"
|
width="1em"
|
||||||
width="1em"
|
>
|
||||||
>
|
<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" />
|
||||||
<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>
|
||||||
</svg>
|
</span>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -255,7 +255,7 @@ const CodePreviewer: React.FC<AntdPreviewerProps> = (props) => {
|
|||||||
'react@18/umd/react.development.js',
|
'react@18/umd/react.development.js',
|
||||||
'react-dom@18/umd/react-dom.development.js',
|
'react-dom@18/umd/react-dom.development.js',
|
||||||
'dayjs@1/dayjs.min.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`,
|
`@ant-design/icons/dist/index.umd.js`,
|
||||||
'react-router-dom/dist/umd/react-router-dom.production.min.js',
|
'react-router-dom/dist/umd/react-router-dom.production.min.js',
|
||||||
'react-router/dist/umd/react-router.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 }) => ({
|
const useStyle = createStyles(({ css }) => ({
|
||||||
skeletonWrapper: css`
|
skeletonWrapper: css`
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
height: 500px;
|
height: 250px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
|
border-radius: 8px;
|
||||||
`,
|
`,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
/* eslint-disable react/no-array-index-key */
|
/* eslint-disable react/no-array-index-key */
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Suspense } from 'react';
|
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { FormattedMessage } from 'dumi';
|
import { FormattedMessage } from 'dumi';
|
||||||
import { createStyles } from 'antd-style';
|
import { createStyles } from 'antd-style';
|
||||||
import { Avatar, Divider, Empty, Skeleton, Tabs } from 'antd';
|
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 { useSiteData } from '../../../pages/index/components/util';
|
||||||
import useLocale from '../../../hooks/useLocale';
|
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 [, lang] = useLocale();
|
||||||
const isZhCN = lang === 'cn';
|
const isZhCN = lang === 'cn';
|
||||||
const { articles = { cn: [], en: [] }, authors = [] } = useSiteData();
|
|
||||||
|
const { articles = { cn: [], en: [] }, authors = [] } = data;
|
||||||
|
|
||||||
// ========================== Data ==========================
|
// ========================== Data ==========================
|
||||||
const mergedData = React.useMemo(() => {
|
const mergedData = React.useMemo(() => {
|
||||||
@ -149,11 +149,13 @@ const Articles: React.FC = () => {
|
|||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const { styles } = useStyle();
|
const { styles } = useStyle();
|
||||||
|
const data = useSiteData();
|
||||||
|
|
||||||
|
const articles = data ? <Articles data={data} /> : <Skeleton active />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="articles" className={styles.articles}>
|
<div id="articles" className={styles.articles}>
|
||||||
<Suspense fallback={<Skeleton active />}>
|
{articles}
|
||||||
<Articles />
|
|
||||||
</Suspense>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -44,7 +44,7 @@ const ColorPaletteTool: React.FC = () => {
|
|||||||
text += locale.saturation((s * 100).toFixed(2));
|
text += locale.saturation((s * 100).toFixed(2));
|
||||||
}
|
}
|
||||||
if (b * 100 < primaryMinBrightness) {
|
if (b * 100 < primaryMinBrightness) {
|
||||||
text += locale.brightness((s * 100).toFixed(2));
|
text += locale.brightness((b * 100).toFixed(2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
@ -11,10 +11,16 @@ const Loading: React.FC = () => {
|
|||||||
pathname.startsWith('/changelog')
|
pathname.startsWith('/changelog')
|
||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
<Space direction="vertical" style={{ width: '100%', marginTop: 24 }} size={40}>
|
<div style={{ maxWidth: '70vw', width: '100%', margin: '80px auto 0', textAlign: 'center' }}>
|
||||||
<Skeleton title={false} active paragraph={{ rows: 3 }} />
|
<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 }} />
|
<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;
|
margin: 0 0 16px;
|
||||||
background-color: ${token.colorBgContainer};
|
background-color: ${token.colorBgContainer};
|
||||||
border: 1px solid ${token.colorSplit};
|
border: 1px solid ${token.colorSplit};
|
||||||
border-radius: ${token.borderRadius}px;
|
border-radius: ${token.borderRadiusLG}px;
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
|
|
||||||
.code-box-title {
|
.code-box-title {
|
||||||
@ -39,7 +39,7 @@ const GlobalDemoStyles: React.FC = () => {
|
|||||||
|
|
||||||
.code-box-demo {
|
.code-box-demo {
|
||||||
background-color: ${token.colorBgContainer};
|
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 {
|
> .demo {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
@ -85,10 +85,6 @@ const GlobalDemoStyles: React.FC = () => {
|
|||||||
transition: background-color 0.4s;
|
transition: background-color 0.4s;
|
||||||
margin-inline-start: 16px;
|
margin-inline-start: 16px;
|
||||||
|
|
||||||
${antCls}-row-rtl & {
|
|
||||||
border-radius: ${token.borderRadius}px 0 0 ${token.borderRadius}px;
|
|
||||||
}
|
|
||||||
|
|
||||||
a,
|
a,
|
||||||
a:hover {
|
a:hover {
|
||||||
color: ${token.colorText};
|
color: ${token.colorText};
|
||||||
|
@ -199,28 +199,6 @@ const GlobalStyle: React.FC = () => {
|
|||||||
font-size: 30px;
|
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) {
|
.markdown table td > a:not(:last-child) {
|
||||||
margin-right: 0 !important;
|
margin-right: 0 !important;
|
||||||
|
@ -4,7 +4,7 @@ import {
|
|||||||
createCache,
|
createCache,
|
||||||
extractStyle,
|
extractStyle,
|
||||||
legacyNotSelectorLinter,
|
legacyNotSelectorLinter,
|
||||||
logicalPropertiesLinter,
|
NaNLinter,
|
||||||
parentSelectorLinter,
|
parentSelectorLinter,
|
||||||
StyleProvider,
|
StyleProvider,
|
||||||
} from '@ant-design/cssinjs';
|
} from '@ant-design/cssinjs';
|
||||||
@ -45,7 +45,7 @@ const getAlgorithm = (themes: ThemeName[] = []) =>
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
})
|
})
|
||||||
.filter((item) => item) as typeof antdTheme.darkAlgorithm[];
|
.filter((item) => item) as (typeof antdTheme.darkAlgorithm)[];
|
||||||
|
|
||||||
const GlobalLayout: React.FC = () => {
|
const GlobalLayout: React.FC = () => {
|
||||||
const outlet = useOutlet();
|
const outlet = useOutlet();
|
||||||
@ -168,7 +168,7 @@ const GlobalLayout: React.FC = () => {
|
|||||||
<DarkContext.Provider value={theme.includes('dark')}>
|
<DarkContext.Provider value={theme.includes('dark')}>
|
||||||
<StyleProvider
|
<StyleProvider
|
||||||
cache={styleCache}
|
cache={styleCache}
|
||||||
linters={[logicalPropertiesLinter, legacyNotSelectorLinter, parentSelectorLinter]}
|
linters={[legacyNotSelectorLinter, parentSelectorLinter, NaNLinter]}
|
||||||
>
|
>
|
||||||
<SiteContext.Provider value={siteContextValue}>
|
<SiteContext.Provider value={siteContextValue}>
|
||||||
<SiteThemeProvider
|
<SiteThemeProvider
|
||||||
@ -177,6 +177,7 @@ const GlobalLayout: React.FC = () => {
|
|||||||
token: {
|
token: {
|
||||||
motion: !theme.includes('motion-off'),
|
motion: !theme.includes('motion-off'),
|
||||||
},
|
},
|
||||||
|
cssVar: true,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<HappyProvider disabled={!theme.includes('happy-work')}>{content}</HappyProvider>
|
<HappyProvider disabled={!theme.includes('happy-work')}>{content}</HappyProvider>
|
||||||
|
@ -111,6 +111,8 @@
|
|||||||
"app.footer.seeconf": "Experience Tech Conference",
|
"app.footer.seeconf": "Experience Tech Conference",
|
||||||
"app.footer.xtech": "Ant Financial Experience Tech",
|
"app.footer.xtech": "Ant Financial Experience Tech",
|
||||||
"app.footer.xtech.slogan": "Experience The Beauty",
|
"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-primary": "Pick your primary color",
|
||||||
"app.docs.color.pick-background": "Pick your background color",
|
"app.docs.color.pick-background": "Pick your background color",
|
||||||
"app.docs.components.icon.search.placeholder": "Search icons here, click icon to copy code",
|
"app.docs.components.icon.search.placeholder": "Search icons here, click icon to copy code",
|
||||||
|
@ -110,6 +110,8 @@
|
|||||||
"app.footer.seeconf": "蚂蚁体验科技大会",
|
"app.footer.seeconf": "蚂蚁体验科技大会",
|
||||||
"app.footer.xtech": "蚂蚁体验科技",
|
"app.footer.xtech": "蚂蚁体验科技",
|
||||||
"app.footer.xtech.slogan": "让用户体验美好",
|
"app.footer.xtech.slogan": "让用户体验美好",
|
||||||
|
"app.footer.galacean": "Galacean",
|
||||||
|
"app.footer.galacean.slogan": "互动图形解决方案",
|
||||||
"app.docs.color.pick-primary": "选择你的主色",
|
"app.docs.color.pick-primary": "选择你的主色",
|
||||||
"app.docs.color.pick-background": "选择你的背景色",
|
"app.docs.color.pick-background": "选择你的背景色",
|
||||||
"app.docs.components.icon.search.placeholder": "在此搜索图标,点击图标可复制代码",
|
"app.docs.components.icon.search.placeholder": "在此搜索图标,点击图标可复制代码",
|
||||||
|
@ -166,7 +166,7 @@ const RoutesPlugin = (api: IApi) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Insert antd style to head
|
// 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) || [];
|
const matchList = file.content.match(matchRegex) || [];
|
||||||
|
|
||||||
let antdStyle = '';
|
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,94 +1,26 @@
|
|||||||
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 classNames from 'classnames';
|
||||||
import DayJS from 'dayjs';
|
import { FormattedMessage, useRouteMeta } from 'dumi';
|
||||||
import { FormattedMessage, useIntl, useRouteMeta, useTabMeta } from 'dumi';
|
|
||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import React, { useContext, useLayoutEffect, useMemo, useState } from 'react';
|
import React, { Suspense, useContext, useLayoutEffect, useMemo } from 'react';
|
||||||
import { Anchor, Avatar, Col, ConfigProvider, Skeleton, Space, Tooltip, Typography } from 'antd';
|
import { Col, Space, Typography, Skeleton } from 'antd';
|
||||||
|
import { createStyles } from 'antd-style';
|
||||||
import useLayoutState from '../../../hooks/useLayoutState';
|
import useLayoutState from '../../../hooks/useLayoutState';
|
||||||
import useLocation from '../../../hooks/useLocation';
|
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 type { DemoContextProps } from '../DemoContext';
|
||||||
import DemoContext from '../DemoContext';
|
import DemoContext from '../DemoContext';
|
||||||
import Footer from '../Footer';
|
|
||||||
import SiteContext from '../SiteContext';
|
import SiteContext from '../SiteContext';
|
||||||
import ColumnCard from './ColumnCard';
|
|
||||||
|
|
||||||
const useStyle = createStyles(({ token, css }) => {
|
const Contributors = React.lazy(() => import('./Contributors'));
|
||||||
const { antCls } = token;
|
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 {
|
const useStyle = createStyles(({ token, css }) => ({
|
||||||
contributorsList: css`
|
articleWrapper: 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;
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
articleWrapper: css`
|
|
||||||
padding: 0 170px 32px 64px;
|
padding: 0 170px 32px 64px;
|
||||||
|
|
||||||
&.rtl {
|
&.rtl {
|
||||||
@ -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 Content: React.FC<{ children: ReactNode }> = ({ children }) => {
|
||||||
const meta = useRouteMeta();
|
const meta = useRouteMeta();
|
||||||
const tab = useTabMeta();
|
|
||||||
const { pathname, hash } = useLocation();
|
const { pathname, hash } = useLocation();
|
||||||
const { formatMessage } = useIntl();
|
const { direction } = useContext(SiteContext);
|
||||||
const { styles } = useStyle();
|
const { styles } = useStyle();
|
||||||
const token = useTheme();
|
|
||||||
const { direction, isMobile } = useContext(SiteContext);
|
|
||||||
|
|
||||||
const [showDebug, setShowDebug] = useLayoutState(false);
|
const [showDebug, setShowDebug] = useLayoutState(false);
|
||||||
const debugDemos = useMemo(
|
const debugDemos = useMemo(
|
||||||
@ -167,71 +59,14 @@ const Content: React.FC<{ children: ReactNode }> = ({ children }) => {
|
|||||||
[showDebug, debugDemos],
|
[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 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 (
|
return (
|
||||||
<DemoContext.Provider value={contextValue}>
|
<DemoContext.Provider value={contextValue}>
|
||||||
<Col xxl={20} xl={19} lg={18} md={18} sm={24} xs={24}>
|
<Col xxl={20} xl={19} lg={18} md={18} sm={24} xs={24}>
|
||||||
{!!meta.frontmatter.toc && (
|
<Suspense fallback={<Skeleton.Input active size="small" />}>
|
||||||
<section className={styles.tocWrapper}>
|
<DocAnchor showDebug={showDebug} debugDemos={debugDemos} />
|
||||||
<Anchor
|
</Suspense>
|
||||||
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>
|
|
||||||
)}
|
|
||||||
<article className={classNames(styles.articleWrapper, { rtl: isRTL })}>
|
<article className={classNames(styles.articleWrapper, { rtl: isRTL })}>
|
||||||
{meta.frontmatter?.title ? (
|
{meta.frontmatter?.title ? (
|
||||||
<Typography.Title style={{ fontSize: 30, position: 'relative' }}>
|
<Typography.Title style={{ fontSize: 30, position: 'relative' }}>
|
||||||
@ -240,92 +75,43 @@ const Content: React.FC<{ children: ReactNode }> = ({ children }) => {
|
|||||||
{meta.frontmatter?.subtitle}
|
{meta.frontmatter?.subtitle}
|
||||||
|
|
||||||
{!pathname.startsWith('/components/overview') && (
|
{!pathname.startsWith('/components/overview') && (
|
||||||
<EditButton
|
<Suspense fallback={null}>
|
||||||
title={<FormattedMessage id="app.content.edit-page" />}
|
<EditButton
|
||||||
filename={meta.frontmatter.filename}
|
title={<FormattedMessage id="app.content.edit-page" />}
|
||||||
/>
|
filename={meta.frontmatter.filename}
|
||||||
|
/>
|
||||||
|
</Suspense>
|
||||||
)}
|
)}
|
||||||
</Space>
|
</Space>
|
||||||
{pathname.startsWith('/components/') && <ComponentChangelog pathname={pathname} />}
|
{pathname.startsWith('/components/') && (
|
||||||
|
<Suspense fallback={null}>
|
||||||
|
<ComponentChangelog pathname={pathname} />
|
||||||
|
</Suspense>
|
||||||
|
)}
|
||||||
</Typography.Title>
|
</Typography.Title>
|
||||||
) : null}
|
) : null}
|
||||||
{/* 添加作者、时间等信息 */}
|
<Suspense fallback={<Skeleton.Input active size="small" />}>
|
||||||
{meta.frontmatter.date || meta.frontmatter.author ? (
|
<DocMeta />
|
||||||
<Typography.Paragraph>
|
</Suspense>
|
||||||
<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}
|
|
||||||
{!meta.frontmatter.__autoDescription && meta.frontmatter.description}
|
{!meta.frontmatter.__autoDescription && meta.frontmatter.description}
|
||||||
<ConfigProvider theme={{ cssVar: {} }}>
|
<div style={{ minHeight: 'calc(100vh - 64px)' }}>{children}</div>
|
||||||
<div style={{ minHeight: 'calc(100vh - 64px)' }}>{children}</div>
|
<Suspense fallback={<Skeleton.Input active size="small" />}>
|
||||||
</ConfigProvider>
|
|
||||||
{(meta.frontmatter?.zhihu_url ||
|
|
||||||
meta.frontmatter?.yuque_url ||
|
|
||||||
meta.frontmatter?.juejin_url) && (
|
|
||||||
<ColumnCard
|
<ColumnCard
|
||||||
zhihuLink={meta.frontmatter.zhihu_url}
|
zhihuLink={meta.frontmatter.zhihu_url}
|
||||||
yuqueLink={meta.frontmatter.yuque_url}
|
yuqueLink={meta.frontmatter.yuque_url}
|
||||||
juejinLink={meta.frontmatter.juejin_url}
|
juejinLink={meta.frontmatter.juejin_url}
|
||||||
/>
|
/>
|
||||||
)}
|
</Suspense>
|
||||||
{meta.frontmatter.filename && (
|
<Suspense fallback={<Skeleton.Input active size="small" />}>
|
||||||
<ContributorsList
|
<Contributors filename={meta.frontmatter.filename} />
|
||||||
cache
|
</Suspense>
|
||||||
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>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</article>
|
</article>
|
||||||
<PrevAndNext rtl={isRTL} />
|
<Suspense fallback={<Skeleton.Input active size="small" />}>
|
||||||
<Footer />
|
<PrevAndNext rtl={isRTL} />
|
||||||
|
</Suspense>
|
||||||
|
<Suspense fallback={null}>
|
||||||
|
<Footer />
|
||||||
|
</Suspense>
|
||||||
</Col>
|
</Col>
|
||||||
</DemoContext.Provider>
|
</DemoContext.Provider>
|
||||||
);
|
);
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import type { FC, ReactNode } from 'react';
|
import type { FC, ReactNode } from 'react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { CodeOutlined, SkinOutlined } from '@ant-design/icons';
|
import { CodeOutlined, SkinOutlined } from '@ant-design/icons';
|
||||||
|
import { Tabs } from 'antd';
|
||||||
import { useRouteMeta } from 'dumi';
|
import { useRouteMeta } from 'dumi';
|
||||||
import type { IContentTabsProps } from 'dumi/theme-default/slots/ContentTabs';
|
import type { IContentTabsProps } from 'dumi/theme-default/slots/ContentTabs';
|
||||||
import type { TabsProps } from 'rc-tabs';
|
import type { TabsProps } from 'rc-tabs';
|
||||||
import { Tabs } from 'antd';
|
|
||||||
|
|
||||||
const titleMap: Record<string, string> = {
|
const titleMap: Record<string, ReactNode> = {
|
||||||
design: '设计',
|
design: '设计',
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -23,24 +23,17 @@ const ContentTabs: FC<IContentTabsProps> = ({ tabs, tabKey, onChange }) => {
|
|||||||
|
|
||||||
const items: TabsProps['items'] = [
|
const items: TabsProps['items'] = [
|
||||||
{
|
{
|
||||||
label: (
|
|
||||||
<span>
|
|
||||||
<CodeOutlined />
|
|
||||||
开发
|
|
||||||
</span>
|
|
||||||
),
|
|
||||||
key: 'development',
|
key: 'development',
|
||||||
|
label: '开发',
|
||||||
|
icon: <CodeOutlined />,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
tabs?.forEach((tab) => {
|
tabs?.forEach((tab) => {
|
||||||
items.push({
|
items.push({
|
||||||
label: (
|
|
||||||
<span>
|
|
||||||
{iconMap[tab.key]}
|
|
||||||
{titleMap[tab.key]}
|
|
||||||
</span>
|
|
||||||
),
|
|
||||||
key: tab.key,
|
key: tab.key,
|
||||||
|
label: titleMap[tab.key],
|
||||||
|
icon: iconMap[tab.key],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -48,7 +41,7 @@ const ContentTabs: FC<IContentTabsProps> = ({ tabs, tabKey, onChange }) => {
|
|||||||
<Tabs
|
<Tabs
|
||||||
items={items}
|
items={items}
|
||||||
activeKey={tabKey || 'development'}
|
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' }}
|
style={{ margin: '32px 0 -16px' }}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -363,6 +363,20 @@ const Footer: React.FC = () => {
|
|||||||
url: 'https://kitchen.alipay.com',
|
url: 'https://kitchen.alipay.com',
|
||||||
openExternal: true,
|
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: (
|
icon: (
|
||||||
<img
|
<img
|
||||||
|
@ -25,15 +25,16 @@ const RESPONSIVE_SM = 1200;
|
|||||||
|
|
||||||
const locales = {
|
const locales = {
|
||||||
cn: {
|
cn: {
|
||||||
message:
|
message: '语雀征文 · 说说你和开源的故事,赢取 Ant Design 精美周边 🎁',
|
||||||
'语雀公益计划:大学生认证教育邮箱,即可免费获得语雀会员。语雀,支付宝匠心打造的在线文档平台。',
|
shortMessage: '语雀征文 · 说说你和开源的故事,赢取 Ant Design 精美周边 🎁',
|
||||||
shortMessage: '支付宝语雀 · 大学生公益计划火热进行中!',
|
more: '前往了解',
|
||||||
more: '了解更多',
|
link: 'https://www.yuque.com/opensource2023',
|
||||||
},
|
},
|
||||||
en: {
|
en: {
|
||||||
message: '',
|
message: '',
|
||||||
shortMessage: '',
|
shortMessage: '',
|
||||||
more: '',
|
more: '',
|
||||||
|
link: '',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -222,9 +223,11 @@ const Header: React.FC = () => {
|
|||||||
// Mirror url must have `/`, we add this for compatible
|
// Mirror url must have `/`, we add this for compatible
|
||||||
const urlObj = new URL(currentUrl.replace(window.location.origin, url));
|
const urlObj = new URL(currentUrl.replace(window.location.origin, url));
|
||||||
if (urlObj.host.includes('antgroup')) {
|
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(/\/$/, '');
|
||||||
}
|
}
|
||||||
window.location.href = urlObj.href.replace(/\/$/, '');
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const onLangChange = useCallback(() => {
|
const onLangChange = useCallback(() => {
|
||||||
@ -366,26 +369,28 @@ const Header: React.FC = () => {
|
|||||||
</Popover>
|
</Popover>
|
||||||
)}
|
)}
|
||||||
{isZhCN && bannerVisible && (
|
{isZhCN && bannerVisible && (
|
||||||
<ConfigProvider theme={{ token: { colorInfoBg: '#daf5eb', colorTextBase: '#000' } }}>
|
<ConfigProvider
|
||||||
|
theme={{
|
||||||
|
token: {
|
||||||
|
colorInfoBg: 'linear-gradient(90deg, #84fab0, #8fd3f4)',
|
||||||
|
colorTextBase: '#000',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Alert
|
<Alert
|
||||||
className={styles.banner}
|
className={styles.banner}
|
||||||
message={
|
message={
|
||||||
<>
|
<>
|
||||||
<img
|
|
||||||
className={styles.icon}
|
|
||||||
src="https://gw.alipayobjects.com/zos/rmsportal/XuVpGqBFxXplzvLjJBZB.svg"
|
|
||||||
alt="yuque"
|
|
||||||
/>
|
|
||||||
<span>{isMobile ? locale.shortMessage : locale.message}</span>
|
<span>{isMobile ? locale.shortMessage : locale.message}</span>
|
||||||
<a
|
<a
|
||||||
className={styles.link}
|
className={styles.link}
|
||||||
href="https://www.yuque.com/yuque/blog/welfare-edu?source=antd"
|
href={locale.link}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
window.gtag?.('event', '点击', {
|
window.gtag?.('event', '点击', {
|
||||||
event_category: 'top_banner',
|
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
|
- [ ] Demo is updated/provided or not needed
|
||||||
- [ ] TypeScript definition is updated/provided or not needed
|
- [ ] TypeScript definition is updated/provided or not needed
|
||||||
- [ ] Changelog is 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 定义已补充或无须补充
|
- [ ] TypeScript 定义已补充或无须补充
|
||||||
- [ ] Changelog 已提供或无须提供
|
- [ ] 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: |
|
DING_TALK_TOKEN: |
|
||||||
${{ secrets.DINGDING_BOT_TOKEN }}
|
${{ secrets.DINGDING_BOT_TOKEN }}
|
||||||
${{ secrets.DINGDING_BOT_COLLABORATOR_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_body: '### 🔥 @${{ github.event.discussion.user.login }} 创建了讨论:[${{ github.event.discussion.title }}](${{ github.event.discussion.html_url }}) <hr />'
|
||||||
notify_footer: '> 💬 欢迎前往 GitHub 进行讨论,社区可能需要你的帮助。'
|
notify_footer: '> 💬 欢迎前往 GitHub 进行讨论,社区可能需要你的帮助。'
|
||||||
at_all: false # whether to ding everybody
|
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: |
|
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.
|
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)
|
![](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: |
|
DING_TALK_TOKEN: |
|
||||||
${{ secrets.DINGDING_BOT_TOKEN }}
|
${{ secrets.DINGDING_BOT_TOKEN }}
|
||||||
${{ secrets.DINGDING_BOT_COLLABORATOR_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_body: '### 🔥 @${{ github.event.issue.user.login }} 创建了 issue:[${{ github.event.issue.title }}](${{ github.event.issue.html_url }}) <hr />'
|
||||||
notify_footer: '> 💬 欢迎前往 GitHub 进行讨论,社区可能需要你的帮助。'
|
notify_footer: '> 💬 欢迎前往 GitHub 进行讨论,社区可能需要你的帮助。'
|
||||||
at_all: false # whether to ding everybody
|
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'
|
refuse-issue-label: '🎱 Collaborate PR only'
|
||||||
need-creator-authority: 'write'
|
need-creator-authority: 'write'
|
||||||
comment: |
|
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,再次感谢你的贡献!😊
|
你好 @${{ github.event.pull_request.user.login }}。这个 PR 提及的 issue 需要和设计师或核心团队进行确认!感谢您的贡献!😊
|
||||||
close: true
|
close: false
|
||||||
|
reviewers: |
|
||||||
|
MadCcc
|
||||||
|
zombieJ
|
||||||
|
|
||||||
check-changelog:
|
check-changelog:
|
||||||
permissions:
|
permissions:
|
||||||
|
2
.github/workflows/preview-build.yml
vendored
2
.github/workflows/preview-build.yml
vendored
@ -74,7 +74,7 @@ jobs:
|
|||||||
run: npm run site
|
run: npm run site
|
||||||
env:
|
env:
|
||||||
SITE_ENV: development
|
SITE_ENV: development
|
||||||
NODE_OPTIONS: "--max_old_space_size=4096 --openssl-legacy-provider"
|
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||||
|
|
||||||
- name: upload site artifact
|
- name: upload site artifact
|
||||||
uses: actions/upload-artifact@v3
|
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
|
name: 🐦 Release to Tweet
|
||||||
|
|
||||||
on:
|
on:
|
||||||
release:
|
create
|
||||||
types: [published]
|
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
tweet:
|
tweet:
|
||||||
|
if: ${{ github.event.ref_type == 'tag' && !contains(github.event.ref, 'alpha') }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Tweet
|
- name: Tweet
|
||||||
uses: nearform-actions/github-action-notify-twitter@v1
|
uses: nearform-actions/github-action-notify-twitter@v1
|
||||||
with:
|
with:
|
||||||
message: |
|
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-key: ${{ secrets.TWITTER_API_KEY }}
|
||||||
twitter-app-secret: ${{ secrets.TWITTER_API_SECRET_KEY }}
|
twitter-app-secret: ${{ secrets.TWITTER_API_SECRET_KEY }}
|
||||||
twitter-access-token: ${{ secrets.TWITTER_ACCESS_TOKEN }}
|
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
|
- name: build site
|
||||||
run: npm run predeploy
|
run: npm run predeploy
|
||||||
env:
|
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
|
- name: build dist and bundle analyzer report
|
||||||
run: npm run dist
|
run: npm run dist
|
||||||
env:
|
env:
|
||||||
ANALYZER: 1
|
ANALYZER: 1
|
||||||
NODE_OPTIONS: "--max_old_space_size=4096 --openssl-legacy-provider"
|
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||||
|
|
||||||
- name: Get version
|
- name: Get version
|
||||||
id: publish-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
|
build_script: dist
|
||||||
skip_step: install
|
skip_step: install
|
||||||
env:
|
env:
|
||||||
NODE_OPTIONS: "--max_old_space_size=4096 --openssl-legacy-provider"
|
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||||
PRODUCTION_ONLY: 1
|
PRODUCTION_ONLY: 1
|
||||||
|
13
.github/workflows/test.yml
vendored
13
.github/workflows/test.yml
vendored
@ -131,7 +131,7 @@ jobs:
|
|||||||
- name: dist
|
- name: dist
|
||||||
run: npm run dist
|
run: npm run dist
|
||||||
env:
|
env:
|
||||||
NODE_OPTIONS: "--max_old_space_size=4096 --openssl-legacy-provider"
|
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||||
CI: 1
|
CI: 1
|
||||||
needs: setup
|
needs: setup
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
react: ['16', '17', '18']
|
react: ['16', '17', '18']
|
||||||
module: ['dom', 'node', 'dist']
|
module: ['dom', 'node', 'dist', 'dist-min']
|
||||||
shard: ['1/2', '2/2']
|
shard: ['1/2', '2/2']
|
||||||
env:
|
env:
|
||||||
REACT: ${{ matrix.react }}
|
REACT: ${{ matrix.react }}
|
||||||
@ -179,7 +179,7 @@ jobs:
|
|||||||
run: npm run install-react-18
|
run: npm run install-react-18
|
||||||
|
|
||||||
- name: restore cache from dist
|
- name: restore cache from dist
|
||||||
if: ${{ matrix.module == 'dist' }}
|
if: ${{ matrix.module == 'dist' || matrix.module == 'dist-min' }}
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: dist
|
path: dist
|
||||||
@ -224,6 +224,13 @@ jobs:
|
|||||||
run: npm test
|
run: npm test
|
||||||
env:
|
env:
|
||||||
LIB_DIR: dist
|
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]
|
needs: [setup, dist]
|
||||||
|
|
||||||
############################ Test Coverage ###########################
|
############################ 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__/
|
__diff_output__/
|
||||||
__image_snapshots__/
|
__image_snapshots__/
|
||||||
/jest-stare
|
/jest-stare
|
||||||
/imageSnapshots
|
/imageSnapshots*
|
||||||
/imageDiffSnapshots
|
/imageDiffSnapshots
|
||||||
|
/visualRegressionReport*
|
||||||
|
|
||||||
.devcontainer*
|
.devcontainer*
|
||||||
.husky/prepare-commit-msg
|
.husky/prepare-commit-msg
|
||||||
|
@ -2,7 +2,7 @@ const { moduleNameMapper, transformIgnorePatterns } = require('./.jest');
|
|||||||
|
|
||||||
// jest config for image snapshots
|
// jest config for image snapshots
|
||||||
module.exports = {
|
module.exports = {
|
||||||
setupFiles: ['./tests/setup.js'],
|
setupFiles: ['./tests/setup.ts'],
|
||||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'md'],
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'md'],
|
||||||
moduleNameMapper,
|
moduleNameMapper,
|
||||||
transform: {
|
transform: {
|
||||||
@ -19,5 +19,5 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
preset: 'jest-puppeteer',
|
preset: 'jest-puppeteer',
|
||||||
testTimeout: 10000,
|
testTimeout: 20000,
|
||||||
};
|
};
|
||||||
|
4
.jest.js
4
.jest.js
@ -23,7 +23,7 @@ const transformIgnorePatterns = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
function getTestRegex(libDir) {
|
function getTestRegex(libDir) {
|
||||||
if (['dist', 'lib', 'es'].includes(libDir)) {
|
if (['dist', 'lib', 'es', 'dist-min'].includes(libDir)) {
|
||||||
return 'demo\\.test\\.(j|t)sx?$';
|
return 'demo\\.test\\.(j|t)sx?$';
|
||||||
}
|
}
|
||||||
return '.*\\.test\\.(j|t)sx?$';
|
return '.*\\.test\\.(j|t)sx?$';
|
||||||
@ -32,7 +32,7 @@ function getTestRegex(libDir) {
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
verbose: true,
|
verbose: true,
|
||||||
testEnvironment: 'jsdom',
|
testEnvironment: 'jsdom',
|
||||||
setupFiles: ['./tests/setup.js', 'jest-canvas-mock'],
|
setupFiles: ['./tests/setup.ts', 'jest-canvas-mock'],
|
||||||
setupFilesAfterEnv: ['./tests/setupAfterEnv.ts'],
|
setupFilesAfterEnv: ['./tests/setupAfterEnv.ts'],
|
||||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'md'],
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'md'],
|
||||||
modulePathIgnorePatterns: ['/_site/'],
|
modulePathIgnorePatterns: ['/_site/'],
|
||||||
|
@ -2,7 +2,7 @@ const { moduleNameMapper, transformIgnorePatterns } = require('./.jest');
|
|||||||
|
|
||||||
// jest config for server render environment
|
// jest config for server render environment
|
||||||
module.exports = {
|
module.exports = {
|
||||||
setupFiles: ['./tests/setup.js'],
|
setupFiles: ['./tests/setup.ts'],
|
||||||
setupFilesAfterEnv: ['./tests/setupAfterEnv.ts'],
|
setupFilesAfterEnv: ['./tests/setupAfterEnv.ts'],
|
||||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'md'],
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'md'],
|
||||||
moduleNameMapper,
|
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
|
## 5.11.0
|
||||||
|
|
||||||
`2023-11-03`
|
`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
|
## 5.11.0
|
||||||
|
|
||||||
`2023-11-03`
|
`2023-11-03`
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
<p align="center">
|
<div align="center"><a name="readme-top"></a>
|
||||||
<a href="https://ant.design">
|
|
||||||
<img width="200" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg">
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<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 组件库。
|
一套企业级 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]
|
[![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-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-image]: http://img.shields.io/npm/v/antd.svg?style=flat-square
|
||||||
[npm-url]: http://npmjs.org/package/antd
|
[npm-url]: http://npmjs.org/package/antd
|
||||||
[github-action-image]: https://github.com/ant-design/ant-design/workflows/%E2%9C%85%20test/badge.svg
|
[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
|
[unpkg-js-url]: https://unpkg.com/browse/antd/dist/antd.min.js
|
||||||
[bundlephobia-image]: https://badgen.net/bundlephobia/minzip/antd?style=flat-square
|
[bundlephobia-image]: https://badgen.net/bundlephobia/minzip/antd?style=flat-square
|
||||||
[bundlephobia-url]: https://bundlephobia.com/package/antd
|
[bundlephobia-url]: https://bundlephobia.com/package/antd
|
||||||
[issues-helper-image]: https://img.shields.io/badge/using-issues--helper-orange?style=flat-square
|
[issues-helper-image]: https://img.shields.io/badge/using-actions--cool-blue?style=flat-square
|
||||||
[issues-helper-url]: https://github.com/actions-cool/issues-helper
|
[issues-helper-url]: https://github.com/actions-cool
|
||||||
[renovate-image]: https://img.shields.io/badge/renovate-enabled-brightgreen.svg?style=flat-square
|
[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
|
[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-image]: https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square
|
||||||
[dumi-url]: https://github.com/umijs/dumi
|
[dumi-url]: https://github.com/umijs/dumi
|
||||||
[argos-ci-image]: https://argos-ci.com/badge.svg
|
[github-issues-url]: https://new-issue.ant.design
|
||||||
[argos-ci-url]: https://app.argos-ci.com/ant-design/ant-design/reference
|
|
||||||
|
<!-- 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>
|
</div>
|
||||||
|
|
||||||
[![](https://user-images.githubusercontent.com/507615/209472919-6f7e8561-be8c-4b0b-9976-eb3c692aa20a.png)](https://ant.design)
|
[![](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)
|
## 🤝 参与共建 [![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://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),更好的问题更容易获得帮助。
|
> 强烈推荐阅读 [《提问的智慧》](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">
|
<div align="center"><a name="readme-top"></a>
|
||||||
<a href="https://ant.design">
|
|
||||||
<img width="200" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg">
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<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.
|
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-image]: http://img.shields.io/npm/v/antd.svg?style=flat-square
|
||||||
[npm-url]: http://npmjs.org/package/antd
|
[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
|
[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-image]: https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square
|
||||||
[dumi-url]: https://github.com/umijs/dumi
|
[dumi-url]: https://github.com/umijs/dumi
|
||||||
[argos-ci-image]: https://argos-ci.com/badge.svg
|
[github-issues-url]: https://new-issue.ant.design
|
||||||
[argos-ci-url]: https://app.argos-ci.com/ant-design/ant-design/reference
|
|
||||||
|
<!-- 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>
|
</div>
|
||||||
|
|
||||||
[![](https://user-images.githubusercontent.com/507615/209472919-6f7e8561-be8c-4b0b-9976-eb3c692aa20a.png)](https://ant.design)
|
[![](https://user-images.githubusercontent.com/507615/209472919-6f7e8561-be8c-4b0b-9976-eb3c692aa20a.png)](https://ant.design)
|
||||||
|
|
||||||
English | [中文](./README-zh_CN.md)
|
|
||||||
|
|
||||||
## ✨ Features
|
## ✨ Features
|
||||||
|
|
||||||
- 🌈 Enterprise-class UI designed for web applications.
|
- 🌈 Enterprise-class UI designed for web applications.
|
||||||
@ -85,27 +102,16 @@ pnpm add antd
|
|||||||
## 🔨 Usage
|
## 🔨 Usage
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import React from 'react';
|
|
||||||
import { Button, DatePicker } from 'antd';
|
import { Button, DatePicker } from 'antd';
|
||||||
|
|
||||||
const App = () => (
|
export default () => (
|
||||||
<>
|
<>
|
||||||
<Button type="primary">PRESS ME</Button>
|
<Button type="primary">PRESS ME</Button>
|
||||||
<DatePicker placeholder="select date" />
|
<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
|
## 🔗 Links
|
||||||
|
|
||||||
- [Home page](https://ant.design/)
|
- [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)
|
## 🤝 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.
|
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! :)
|
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 * as React from 'react';
|
||||||
import ConfigProvider, { ConfigContext } from '../config-provider';
|
import useMergedState from 'rc-util/lib/hooks/useMergedState';
|
||||||
|
|
||||||
export function withPureRenderTheme(Component: any) {
|
import ConfigProvider, { ConfigContext } from '../config-provider';
|
||||||
return function PureRenderThemeComponent(props: any) {
|
import type { AnyObject } from './type';
|
||||||
return (
|
|
||||||
<ConfigProvider
|
export function withPureRenderTheme<T extends AnyObject = AnyObject>(Component: React.FC<T>) {
|
||||||
theme={{
|
return (props: T) => (
|
||||||
token: {
|
<ConfigProvider theme={{ token: { motion: false, zIndexPopupBase: 0 } }}>
|
||||||
motion: false,
|
<Component {...props} />
|
||||||
zIndexPopupBase: 0,
|
</ConfigProvider>
|
||||||
},
|
);
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Component {...props} />
|
|
||||||
</ConfigProvider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BaseProps {
|
export interface BaseProps {
|
||||||
@ -25,15 +18,15 @@ export interface BaseProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
export default function genPurePanel<ComponentProps extends BaseProps>(
|
const genPurePanel = <ComponentProps extends BaseProps = BaseProps>(
|
||||||
Component: any,
|
Component: any,
|
||||||
defaultPrefixCls?: string,
|
defaultPrefixCls?: string,
|
||||||
getDropdownCls?: null | ((prefixCls: string) => string),
|
getDropdownCls?: null | ((prefixCls: string) => string),
|
||||||
postProps?: (props: ComponentProps) => ComponentProps,
|
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 { prefixCls: customizePrefixCls, style } = props;
|
||||||
|
|
||||||
const holderRef = React.useRef<HTMLDivElement>(null);
|
const holderRef = React.useRef<HTMLDivElement>(null);
|
||||||
@ -88,22 +81,21 @@ export default function genPurePanel<ComponentProps extends BaseProps>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (postProps) {
|
if (postProps) {
|
||||||
mergedProps = postProps(mergedProps as ComponentProps);
|
mergedProps = postProps(mergedProps);
|
||||||
}
|
}
|
||||||
|
const mergedStyle: React.CSSProperties = {
|
||||||
|
paddingBottom: popupHeight,
|
||||||
|
position: 'relative',
|
||||||
|
minWidth: popupWidth,
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div
|
<div ref={holderRef} style={mergedStyle}>
|
||||||
ref={holderRef}
|
|
||||||
style={{
|
|
||||||
paddingBottom: popupHeight,
|
|
||||||
position: 'relative',
|
|
||||||
minWidth: popupWidth,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Component {...mergedProps} />
|
<Component {...mergedProps} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
return withPureRenderTheme(PurePanel);
|
return withPureRenderTheme<AnyObject>(PurePanel);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default genPurePanel;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import type { PropsWithChildren } from 'react';
|
import type { PropsWithChildren } from 'react';
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { render } from '@testing-library/react';
|
import { render } from '@testing-library/react';
|
||||||
import type { MenuProps } from 'antd';
|
import type { ImageProps, MenuProps } from 'antd';
|
||||||
import {
|
import {
|
||||||
AutoComplete,
|
AutoComplete,
|
||||||
Cascader,
|
Cascader,
|
||||||
@ -9,6 +9,7 @@ import {
|
|||||||
DatePicker,
|
DatePicker,
|
||||||
Drawer,
|
Drawer,
|
||||||
Dropdown,
|
Dropdown,
|
||||||
|
Image,
|
||||||
Menu,
|
Menu,
|
||||||
Modal,
|
Modal,
|
||||||
Popconfirm,
|
Popconfirm,
|
||||||
@ -150,6 +151,7 @@ const consumerComponent: Record<ZIndexConsumer, React.FC<{ rootClassName: string
|
|||||||
options={options}
|
options={options}
|
||||||
open
|
open
|
||||||
/>
|
/>
|
||||||
|
<ColorPicker {...props} open rootClassName={`${rootClassName} comp-item comp-ColorPicker`} />
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
Dropdown: (props) => (
|
Dropdown: (props) => (
|
||||||
@ -166,7 +168,6 @@ const consumerComponent: Record<ZIndexConsumer, React.FC<{ rootClassName: string
|
|||||||
<button type="button">test</button>
|
<button type="button">test</button>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
),
|
),
|
||||||
ColorPicker: (props) => <ColorPicker {...props} open />,
|
|
||||||
DatePicker: ({ rootClassName, ...props }) => (
|
DatePicker: ({ rootClassName, ...props }) => (
|
||||||
<>
|
<>
|
||||||
<DatePicker {...props} rootClassName={`${rootClassName} comp-item comp-DatePicker`} open />
|
<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']} />,
|
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 {
|
function getConsumerSelector(baseSelector: string, consumer: ZIndexConsumer): string {
|
||||||
let selector = baseSelector;
|
let selector = baseSelector;
|
||||||
if (consumer === 'SelectLike') {
|
if (consumer === 'SelectLike') {
|
||||||
selector = ['Select', 'Cascader', 'TreeSelect', 'AutoComplete']
|
selector = ['Select', 'Cascader', 'TreeSelect', 'AutoComplete', 'ColorPicker']
|
||||||
.map((item) => `${baseSelector}.comp-${item}.ant-slide-up`)
|
.map((item) =>
|
||||||
|
item === 'ColorPicker'
|
||||||
|
? `${baseSelector}.ant-popover-placement-bottomLeft`
|
||||||
|
: `${baseSelector}.comp-${item}.ant-slide-up`,
|
||||||
|
)
|
||||||
.join(',');
|
.join(',');
|
||||||
} else if (consumer === 'DatePicker') {
|
} else if (consumer === 'DatePicker') {
|
||||||
selector = ['DatePicker', 'TimePicker']
|
selector = ['DatePicker', 'TimePicker']
|
||||||
@ -192,8 +216,13 @@ function getConsumerSelector(baseSelector: string, consumer: ZIndexConsumer): st
|
|||||||
.join(',');
|
.join(',');
|
||||||
} else if (['Menu'].includes(consumer)) {
|
} else if (['Menu'].includes(consumer)) {
|
||||||
selector = `${baseSelector}.ant-menu-submenu-placement-rightTop`;
|
selector = `${baseSelector}.ant-menu-submenu-placement-rightTop`;
|
||||||
} else if (consumer === 'ColorPicker') {
|
} else if (consumer === 'ImagePreview') {
|
||||||
selector = `${baseSelector}.ant-popover-placement-bottomLeft`;
|
selector = ['ImagePreview', 'ImagePreviewGroup']
|
||||||
|
.map(
|
||||||
|
(item) =>
|
||||||
|
`${baseSelector}.comp-${item} .ant-image-preview-wrap, ${baseSelector}.comp-${item}.ant-image-preview-operations-wrapper`,
|
||||||
|
)
|
||||||
|
.join(',');
|
||||||
}
|
}
|
||||||
return selector;
|
return selector;
|
||||||
}
|
}
|
||||||
@ -232,7 +261,8 @@ describe('Test useZIndex hooks', () => {
|
|||||||
);
|
);
|
||||||
render(<App />);
|
render(<App />);
|
||||||
expect(fn).toHaveBeenLastCalledWith(
|
expect(fn).toHaveBeenLastCalledWith(
|
||||||
(1000 + containerBaseZIndexOffset[containerKey as ZIndexContainer]) * 3 +
|
1000 +
|
||||||
|
containerBaseZIndexOffset[containerKey as ZIndexContainer] * 3 +
|
||||||
consumerBaseZIndexOffset[key as ZIndexConsumer],
|
consumerBaseZIndexOffset[key as ZIndexConsumer],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -261,28 +291,45 @@ describe('Test useZIndex hooks', () => {
|
|||||||
const selector2 = getConsumerSelector('.consumer2', key as ZIndexConsumer);
|
const selector2 = getConsumerSelector('.consumer2', key as ZIndexConsumer);
|
||||||
const selector3 = getConsumerSelector('.consumer3', 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);
|
let comps = document.querySelectorAll(selector1);
|
||||||
comps.forEach((comp) => {
|
comps.forEach((comp) => {
|
||||||
expect((comp as HTMLDivElement).style.zIndex).toBeFalsy();
|
expect((comp as HTMLDivElement).style.zIndex).toBeFalsy();
|
||||||
});
|
});
|
||||||
comps = document.querySelectorAll(selector2);
|
comps = document.querySelectorAll(selector2);
|
||||||
comps.forEach((comp) => {
|
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(
|
expect((comp as HTMLDivElement).style.zIndex).toBe(
|
||||||
String(
|
String(
|
||||||
1000 +
|
1000 +
|
||||||
containerBaseZIndexOffset[containerKey as ZIndexContainer] +
|
containerBaseZIndexOffset[containerKey as ZIndexContainer] +
|
||||||
consumerBaseZIndexOffset[key as ZIndexConsumer],
|
consumerOffset +
|
||||||
|
operOffset,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
comps = document.querySelectorAll(selector3);
|
comps = document.querySelectorAll(selector3);
|
||||||
comps.forEach((comp) => {
|
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(
|
expect((comp as HTMLDivElement).style.zIndex).toBe(
|
||||||
String(
|
String(
|
||||||
(1000 + containerBaseZIndexOffset[containerKey as ZIndexContainer]) * 2 +
|
1000 +
|
||||||
consumerBaseZIndexOffset[key as ZIndexConsumer],
|
containerBaseZIndexOffset[containerKey as ZIndexContainer] * 2 +
|
||||||
|
consumerOffset +
|
||||||
|
operOffset,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -296,6 +343,7 @@ describe('Test useZIndex hooks', () => {
|
|||||||
(document.querySelector(selector1) as HTMLDivElement).style.zIndex,
|
(document.querySelector(selector1) as HTMLDivElement).style.zIndex,
|
||||||
).toBeFalsy();
|
).toBeFalsy();
|
||||||
}
|
}
|
||||||
|
|
||||||
expect((document.querySelector(selector2) as HTMLDivElement).style.zIndex).toBe(
|
expect((document.querySelector(selector2) as HTMLDivElement).style.zIndex).toBe(
|
||||||
String(
|
String(
|
||||||
1000 +
|
1000 +
|
||||||
@ -306,15 +354,44 @@ describe('Test useZIndex hooks', () => {
|
|||||||
|
|
||||||
expect((document.querySelector(selector3) as HTMLDivElement).style.zIndex).toBe(
|
expect((document.querySelector(selector3) as HTMLDivElement).style.zIndex).toBe(
|
||||||
String(
|
String(
|
||||||
(1000 + containerBaseZIndexOffset[containerKey as ZIndexContainer]) * 2 +
|
1000 +
|
||||||
|
containerBaseZIndexOffset[containerKey as ZIndexContainer] * 2 +
|
||||||
consumerBaseZIndexOffset[key as ZIndexConsumer],
|
consumerBaseZIndexOffset[key as ZIndexConsumer],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
unmount();
|
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 extendsObject = <T extends AnyObject = AnyObject>(...list: T[]) => {
|
||||||
const result: RecordType = { ...list[0] };
|
const result: AnyObject = { ...list[0] };
|
||||||
|
|
||||||
for (let i = 1; i < list.length; i++) {
|
for (let i = 1; i < list.length; i++) {
|
||||||
const obj = list[i];
|
const obj = list[i];
|
||||||
@ -16,6 +16,6 @@ function extendsObject<T extends RecordType>(...list: T[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
};
|
||||||
|
|
||||||
export default extendsObject;
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof propValue === 'function') {
|
return typeof propValue === 'function' ? propValue() : propValue;
|
||||||
return propValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
return propValue;
|
|
||||||
};
|
};
|
||||||
|
@ -1,25 +1,36 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import useToken from '../../theme/useToken';
|
import useToken from '../../theme/useToken';
|
||||||
import zIndexContext from '../zindexContext';
|
import zIndexContext from '../zindexContext';
|
||||||
|
|
||||||
export type ZIndexContainer = 'Modal' | 'Drawer' | 'Popover' | 'Popconfirm' | 'Tooltip' | 'Tour';
|
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> = {
|
export const containerBaseZIndexOffset: Record<ZIndexContainer, number> = {
|
||||||
Modal: 0,
|
Modal: CONTAINER_OFFSET,
|
||||||
Drawer: 0,
|
Drawer: CONTAINER_OFFSET,
|
||||||
Popover: 70,
|
Popover: CONTAINER_OFFSET,
|
||||||
Popconfirm: 70,
|
Popconfirm: CONTAINER_OFFSET,
|
||||||
Tooltip: 70,
|
Tooltip: CONTAINER_OFFSET,
|
||||||
Tour: 70,
|
Tour: CONTAINER_OFFSET,
|
||||||
};
|
};
|
||||||
export const consumerBaseZIndexOffset: Record<ZIndexConsumer, number> = {
|
export const consumerBaseZIndexOffset: Record<ZIndexConsumer, number> = {
|
||||||
SelectLike: 50,
|
SelectLike: 50,
|
||||||
Dropdown: 50,
|
Dropdown: 50,
|
||||||
ColorPicker: 30,
|
|
||||||
DatePicker: 50,
|
DatePicker: 50,
|
||||||
Menu: 50,
|
Menu: 50,
|
||||||
|
ImagePreview: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
function isContainerType(type: ZIndexContainer | ZIndexConsumer): type is ZIndexContainer {
|
function isContainerType(type: ZIndexContainer | ZIndexConsumer): type is ZIndexContainer {
|
||||||
@ -33,9 +44,21 @@ export function useZIndex(
|
|||||||
const [, token] = useToken();
|
const [, token] = useToken();
|
||||||
const parentZIndex = React.useContext(zIndexContext);
|
const parentZIndex = React.useContext(zIndexContext);
|
||||||
const isContainer = isContainerType(componentType);
|
const isContainer = isContainerType(componentType);
|
||||||
|
|
||||||
|
if (customZIndex !== undefined) {
|
||||||
|
return [customZIndex, customZIndex];
|
||||||
|
}
|
||||||
|
|
||||||
let zIndex = parentZIndex ?? 0;
|
let zIndex = parentZIndex ?? 0;
|
||||||
|
|
||||||
if (isContainer) {
|
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 {
|
} else {
|
||||||
zIndex += consumerBaseZIndexOffset[componentType];
|
zIndex += consumerBaseZIndexOffset[componentType];
|
||||||
}
|
}
|
||||||
|
@ -2,4 +2,8 @@ import React from 'react';
|
|||||||
|
|
||||||
const zIndexContext = React.createContext<number | undefined>(undefined);
|
const zIndexContext = React.createContext<number | undefined>(undefined);
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
zIndexContext.displayName = 'zIndexContext';
|
||||||
|
}
|
||||||
|
|
||||||
export default zIndexContext;
|
export default zIndexContext;
|
||||||
|
@ -243,9 +243,9 @@ const Affix = React.forwardRef<AffixRef, AffixProps>((props, ref) => {
|
|||||||
updatePosition();
|
updatePosition();
|
||||||
}, [target, offsetTop, offsetBottom]);
|
}, [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 });
|
const mergedCls = classNames({ [rootCls]: affixStyle });
|
||||||
|
|
||||||
@ -262,7 +262,7 @@ const Affix = React.forwardRef<AffixRef, AffixProps>((props, ref) => {
|
|||||||
otherProps = omit(otherProps, ['onTestUpdatePosition' as any]);
|
otherProps = omit(otherProps, ['onTestUpdatePosition' as any]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return wrapSSR(
|
return wrapCSSVar(
|
||||||
<ResizeObserver onResize={updatePosition}>
|
<ResizeObserver onResize={updatePosition}>
|
||||||
<div style={style} className={className} ref={placeholderNodeRef} {...otherProps}>
|
<div style={style} className={className} ref={placeholderNodeRef} {...otherProps}>
|
||||||
{affixStyle && <div style={placeholderStyle} aria-hidden="true" />}
|
{affixStyle && <div style={placeholderStyle} aria-hidden="true" />}
|
||||||
|
@ -1,15 +1,19 @@
|
|||||||
import type { CSSObject } from '@ant-design/cssinjs';
|
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'> {
|
interface AffixToken extends FullToken<'Affix'> {
|
||||||
zIndexPopup: number;
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================== Shared ==============================
|
// ============================== Shared ==============================
|
||||||
const genSharedAffixStyle: GenerateStyle<AffixToken> = (token): CSSObject => {
|
const genSharedAffixStyle: GenerateStyle<AffixToken> = (token): CSSObject => {
|
||||||
const { componentCls } = token;
|
const { componentCls } = token;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
[componentCls]: {
|
[componentCls]: {
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
@ -18,10 +22,9 @@ const genSharedAffixStyle: GenerateStyle<AffixToken> = (token): CSSObject => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================== Export ==============================
|
export const prepareComponentToken: GetDefaultToken<'Affix'> = (token) => ({
|
||||||
export default genComponentStyleHook('Affix', (token) => {
|
zIndexPopup: token.zIndexBase + 10,
|
||||||
const affixToken = mergeToken<AffixToken>(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 { replaceElement } from '../_util/reactNode';
|
||||||
import { devUseWarning } from '../_util/warning';
|
import { devUseWarning } from '../_util/warning';
|
||||||
import { ConfigContext } from '../config-provider';
|
import { ConfigContext } from '../config-provider';
|
||||||
// CSSINJS
|
|
||||||
import useStyle from './style';
|
import useStyle from './style';
|
||||||
|
|
||||||
export interface AlertProps {
|
export interface AlertProps {
|
||||||
@ -127,7 +126,8 @@ const Alert: React.FC<AlertProps> = (props) => {
|
|||||||
const ref = React.useRef<HTMLDivElement>(null);
|
const ref = React.useRef<HTMLDivElement>(null);
|
||||||
const { getPrefixCls, direction, alert } = React.useContext(ConfigContext);
|
const { getPrefixCls, direction, alert } = React.useContext(ConfigContext);
|
||||||
const prefixCls = getPrefixCls('alert', customizePrefixCls);
|
const prefixCls = getPrefixCls('alert', customizePrefixCls);
|
||||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
|
||||||
|
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls);
|
||||||
|
|
||||||
const handleClose = (e: React.MouseEvent<HTMLButtonElement>) => {
|
const handleClose = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
setClosed(true);
|
setClosed(true);
|
||||||
@ -169,12 +169,13 @@ const Alert: React.FC<AlertProps> = (props) => {
|
|||||||
alert?.className,
|
alert?.className,
|
||||||
className,
|
className,
|
||||||
rootClassName,
|
rootClassName,
|
||||||
|
cssVarCls,
|
||||||
hashId,
|
hashId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const restProps = pickAttrs(otherProps, { aria: true, data: true });
|
const restProps = pickAttrs(otherProps, { aria: true, data: true });
|
||||||
|
|
||||||
return wrapSSR(
|
return wrapCSSVar(
|
||||||
<CSSMotion
|
<CSSMotion
|
||||||
visible={!closed}
|
visible={!closed}
|
||||||
motionName={`${prefixCls}-motion`}
|
motionName={`${prefixCls}-motion`}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import type { CSSInterpolation, CSSObject } from '@ant-design/cssinjs';
|
|
||||||
import type { CSSProperties } from 'react';
|
import type { CSSProperties } from 'react';
|
||||||
|
import type { CSSObject } from '@ant-design/cssinjs';
|
||||||
|
import { unit } from '@ant-design/cssinjs';
|
||||||
|
|
||||||
import { resetComponent } from '../../style';
|
import { resetComponent } from '../../style';
|
||||||
import type { FullToken, GenerateStyle } from '../../theme/internal';
|
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
|
||||||
import { genComponentStyleHook } from '../../theme/internal';
|
import { genStyleHooks } from '../../theme/internal';
|
||||||
|
|
||||||
export interface ComponentToken {
|
export interface ComponentToken {
|
||||||
// Component token here
|
// Component token here
|
||||||
@ -34,8 +36,8 @@ const genAlertTypeStyle = (
|
|||||||
token: AlertToken,
|
token: AlertToken,
|
||||||
alertCls: string,
|
alertCls: string,
|
||||||
): CSSObject => ({
|
): CSSObject => ({
|
||||||
backgroundColor: bgColor,
|
background: bgColor,
|
||||||
border: `${token.lineWidth}px ${token.lineType} ${borderColor}`,
|
border: `${unit(token.lineWidth)} ${token.lineType} ${borderColor}`,
|
||||||
[`${alertCls}-icon`]: {
|
[`${alertCls}-icon`]: {
|
||||||
color: iconColor,
|
color: iconColor,
|
||||||
},
|
},
|
||||||
@ -113,7 +115,6 @@ export const genBaseStyle: GenerateStyle<AlertToken> = (token: AlertToken): CSSO
|
|||||||
[`${componentCls}-with-description`]: {
|
[`${componentCls}-with-description`]: {
|
||||||
alignItems: 'flex-start',
|
alignItems: 'flex-start',
|
||||||
padding: withDescriptionPadding,
|
padding: withDescriptionPadding,
|
||||||
|
|
||||||
[`${componentCls}-icon`]: {
|
[`${componentCls}-icon`]: {
|
||||||
marginInlineEnd: marginSM,
|
marginInlineEnd: marginSM,
|
||||||
fontSize: withDescriptionIconSize,
|
fontSize: withDescriptionIconSize,
|
||||||
@ -212,7 +213,7 @@ export const genActionStyle: GenerateStyle<AlertToken> = (token: AlertToken): CS
|
|||||||
padding: 0,
|
padding: 0,
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
fontSize: fontSizeIcon,
|
fontSize: fontSizeIcon,
|
||||||
lineHeight: `${fontSizeIcon}px`,
|
lineHeight: unit(fontSizeIcon),
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
border: 'none',
|
border: 'none',
|
||||||
outline: 'none',
|
outline: 'none',
|
||||||
@ -238,22 +239,17 @@ export const genActionStyle: GenerateStyle<AlertToken> = (token: AlertToken): CS
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const genAlertStyle: GenerateStyle<AlertToken> = (token: AlertToken): CSSInterpolation => [
|
export const prepareComponentToken: GetDefaultToken<'Alert'> = (token) => {
|
||||||
genBaseStyle(token),
|
const paddingHorizontal = 12; // Fixed value here.
|
||||||
genTypeStyle(token),
|
return {
|
||||||
genActionStyle(token),
|
withDescriptionIconSize: token.fontSizeHeading3,
|
||||||
];
|
defaultPadding: `${token.paddingContentVerticalSM}px ${paddingHorizontal}px`,
|
||||||
|
withDescriptionPadding: `${token.paddingMD}px ${token.paddingContentHorizontalLG}px`,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export default genComponentStyleHook(
|
export default genStyleHooks(
|
||||||
'Alert',
|
'Alert',
|
||||||
(token) => [genAlertStyle(token)],
|
(token) => [genBaseStyle(token), genTypeStyle(token), genActionStyle(token)],
|
||||||
(token) => {
|
prepareComponentToken,
|
||||||
const paddingHorizontal = 12; // Fixed value here.
|
|
||||||
|
|
||||||
return {
|
|
||||||
withDescriptionIconSize: token.fontSizeHeading3,
|
|
||||||
defaultPadding: `${token.paddingContentVerticalSM}px ${paddingHorizontal}px`,
|
|
||||||
withDescriptionPadding: `${token.paddingMD}px ${token.paddingContentHorizontalLG}px`,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
@ -9,6 +9,7 @@ import { devUseWarning } from '../_util/warning';
|
|||||||
import Affix from '../affix';
|
import Affix from '../affix';
|
||||||
import type { ConfigConsumerProps } from '../config-provider';
|
import type { ConfigConsumerProps } from '../config-provider';
|
||||||
import { ConfigContext } from '../config-provider';
|
import { ConfigContext } from '../config-provider';
|
||||||
|
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
|
||||||
import type { AnchorLinkBaseProps } from './AnchorLink';
|
import type { AnchorLinkBaseProps } from './AnchorLink';
|
||||||
import AnchorLink from './AnchorLink';
|
import AnchorLink from './AnchorLink';
|
||||||
import AnchorContext from './context';
|
import AnchorContext from './context';
|
||||||
@ -79,11 +80,6 @@ export interface AnchorProps {
|
|||||||
replace?: boolean;
|
replace?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface InternalAnchorProps extends AnchorProps {
|
|
||||||
anchorPrefixCls: string;
|
|
||||||
rootClassName: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AnchorState {
|
export interface AnchorState {
|
||||||
activeLink: null | string;
|
activeLink: null | string;
|
||||||
}
|
}
|
||||||
@ -109,10 +105,10 @@ export interface AntAnchor {
|
|||||||
direction: AnchorDirection;
|
direction: AnchorDirection;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AnchorContent: React.FC<InternalAnchorProps> = (props) => {
|
const Anchor: React.FC<AnchorProps> = (props) => {
|
||||||
const {
|
const {
|
||||||
rootClassName,
|
rootClassName,
|
||||||
anchorPrefixCls: prefixCls,
|
prefixCls: customPrefixCls,
|
||||||
className,
|
className,
|
||||||
style,
|
style,
|
||||||
offsetTop,
|
offsetTop,
|
||||||
@ -151,9 +147,14 @@ const AnchorContent: React.FC<InternalAnchorProps> = (props) => {
|
|||||||
const spanLinkNode = React.useRef<HTMLSpanElement>(null);
|
const spanLinkNode = React.useRef<HTMLSpanElement>(null);
|
||||||
const animating = React.useRef<boolean>(false);
|
const animating = React.useRef<boolean>(false);
|
||||||
|
|
||||||
const { direction, getTargetContainer, anchor } =
|
const { direction, anchor, getTargetContainer, getPrefixCls } =
|
||||||
React.useContext<ConfigConsumerProps>(ConfigContext);
|
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 getCurrentContainer = getContainer ?? getTargetContainer ?? getDefaultContainer;
|
||||||
|
|
||||||
const dependencyListItem: React.DependencyList[number] = JSON.stringify(links);
|
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.left = horizontalAnchor ? `${linkNode.offsetLeft}px` : '';
|
||||||
inkStyle.width = horizontalAnchor ? `${linkNode.clientWidth}px` : '';
|
inkStyle.width = horizontalAnchor ? `${linkNode.clientWidth}px` : '';
|
||||||
if (horizontalAnchor) {
|
if (horizontalAnchor) {
|
||||||
scrollIntoView(linkNode, {
|
scrollIntoView(linkNode, { scrollMode: 'if-needed', block: 'nearest' });
|
||||||
scrollMode: 'if-needed',
|
|
||||||
block: 'nearest',
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -274,6 +272,9 @@ const AnchorContent: React.FC<InternalAnchorProps> = (props) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const wrapperClass = classNames(
|
const wrapperClass = classNames(
|
||||||
|
hashId,
|
||||||
|
cssVarCls,
|
||||||
|
rootCls,
|
||||||
rootClassName,
|
rootClassName,
|
||||||
`${prefixCls}-wrapper`,
|
`${prefixCls}-wrapper`,
|
||||||
{
|
{
|
||||||
@ -347,7 +348,7 @@ const AnchorContent: React.FC<InternalAnchorProps> = (props) => {
|
|||||||
[activeLink, onClick, handleScrollTo, anchorDirection],
|
[activeLink, onClick, handleScrollTo, anchorDirection],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return wrapCSSVar(
|
||||||
<AnchorContext.Provider value={memoizedContextValue}>
|
<AnchorContext.Provider value={memoizedContextValue}>
|
||||||
{affix ? (
|
{affix ? (
|
||||||
<Affix offsetTop={offsetTop} target={getCurrentContainer}>
|
<Affix offsetTop={offsetTop} target={getCurrentContainer}>
|
||||||
@ -356,23 +357,7 @@ const AnchorContent: React.FC<InternalAnchorProps> = (props) => {
|
|||||||
) : (
|
) : (
|
||||||
anchorContent
|
anchorContent
|
||||||
)}
|
)}
|
||||||
</AnchorContext.Provider>
|
</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}
|
|
||||||
/>,
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import type { CSSObject } from '@ant-design/cssinjs';
|
import { unit } from '@ant-design/cssinjs';
|
||||||
|
|
||||||
import { resetComponent, textEllipsis } from '../../style';
|
import { resetComponent, textEllipsis } from '../../style';
|
||||||
import type { FullToken, GenerateStyle } from '../../theme/internal';
|
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
|
||||||
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
|
import { genStyleHooks, mergeToken } from '../../theme/internal';
|
||||||
|
|
||||||
export interface ComponentToken {
|
export interface ComponentToken {
|
||||||
/**
|
/**
|
||||||
@ -18,13 +19,13 @@ export interface ComponentToken {
|
|||||||
|
|
||||||
interface AnchorToken extends FullToken<'Anchor'> {
|
interface AnchorToken extends FullToken<'Anchor'> {
|
||||||
holderOffsetBlock: number;
|
holderOffsetBlock: number;
|
||||||
anchorPaddingBlockSecondary: number;
|
anchorPaddingBlockSecondary: number | string;
|
||||||
anchorBallSize: number;
|
anchorBallSize: number | string;
|
||||||
anchorTitleBlock: number;
|
anchorTitleBlock: number | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================== Shared ==============================
|
// ============================== Shared ==============================
|
||||||
const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
|
const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token) => {
|
||||||
const {
|
const {
|
||||||
componentCls,
|
componentCls,
|
||||||
holderOffsetBlock,
|
holderOffsetBlock,
|
||||||
@ -33,11 +34,12 @@ const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
|
|||||||
colorPrimary,
|
colorPrimary,
|
||||||
lineType,
|
lineType,
|
||||||
colorSplit,
|
colorSplit,
|
||||||
|
calc,
|
||||||
} = token;
|
} = token;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
[`${componentCls}-wrapper`]: {
|
[`${componentCls}-wrapper`]: {
|
||||||
marginBlockStart: -holderOffsetBlock,
|
marginBlockStart: calc(holderOffsetBlock).mul(-1).equal(),
|
||||||
paddingBlockStart: holderOffsetBlock,
|
paddingBlockStart: holderOffsetBlock,
|
||||||
|
|
||||||
// delete overflow: auto
|
// delete overflow: auto
|
||||||
@ -50,7 +52,7 @@ const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
|
|||||||
|
|
||||||
[`${componentCls}-link`]: {
|
[`${componentCls}-link`]: {
|
||||||
paddingBlock: token.linkPaddingBlock,
|
paddingBlock: token.linkPaddingBlock,
|
||||||
paddingInline: `${token.linkPaddingInlineStart}px 0`,
|
paddingInline: `${unit(token.linkPaddingInlineStart)} 0`,
|
||||||
|
|
||||||
'&-title': {
|
'&-title': {
|
||||||
...textEllipsis,
|
...textEllipsis,
|
||||||
@ -83,7 +85,7 @@ const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
|
|||||||
insetInlineStart: 0,
|
insetInlineStart: 0,
|
||||||
top: 0,
|
top: 0,
|
||||||
height: '100%',
|
height: '100%',
|
||||||
borderInlineStart: `${lineWidthBold}px ${lineType} ${colorSplit}`,
|
borderInlineStart: `${unit(lineWidthBold)} ${lineType} ${colorSplit}`,
|
||||||
content: '" "',
|
content: '" "',
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -95,7 +97,6 @@ const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
|
|||||||
transition: `top ${motionDurationSlow} ease-in-out`,
|
transition: `top ${motionDurationSlow} ease-in-out`,
|
||||||
width: lineWidthBold,
|
width: lineWidthBold,
|
||||||
backgroundColor: colorPrimary,
|
backgroundColor: colorPrimary,
|
||||||
|
|
||||||
[`&${componentCls}-ink-visible`]: {
|
[`&${componentCls}-ink-visible`]: {
|
||||||
display: 'inline-block',
|
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;
|
const { componentCls, motionDurationSlow, lineWidthBold, colorPrimary } = token;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -128,7 +129,7 @@ const genSharedAnchorHorizontalStyle: GenerateStyle<AnchorToken> = (token): CSSO
|
|||||||
value: 0,
|
value: 0,
|
||||||
},
|
},
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
borderBottom: `1px ${token.lineType} ${token.colorSplit}`,
|
borderBottom: `${unit(token.lineWidth)} ${token.lineType} ${token.colorSplit}`,
|
||||||
content: '" "',
|
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 ==============================
|
||||||
export default genComponentStyleHook(
|
export default genStyleHooks(
|
||||||
'Anchor',
|
'Anchor',
|
||||||
(token) => {
|
(token) => {
|
||||||
const { fontSize, fontSizeLG, paddingXXS } = token;
|
const { fontSize, fontSizeLG, paddingXXS, calc } = token;
|
||||||
|
|
||||||
const anchorToken = mergeToken<AnchorToken>(token, {
|
const anchorToken = mergeToken<AnchorToken>(token, {
|
||||||
holderOffsetBlock: paddingXXS,
|
holderOffsetBlock: paddingXXS,
|
||||||
anchorPaddingBlockSecondary: paddingXXS / 2,
|
anchorPaddingBlockSecondary: calc(paddingXXS).div(2).equal(),
|
||||||
anchorTitleBlock: (fontSize / 14) * 3,
|
anchorTitleBlock: calc(fontSize).div(14).mul(3).equal(),
|
||||||
anchorBallSize: fontSizeLG / 2,
|
anchorBallSize: calc(fontSizeLG).div(2).equal(),
|
||||||
});
|
});
|
||||||
return [genSharedAnchorStyle(anchorToken), genSharedAnchorHorizontalStyle(anchorToken)];
|
return [genSharedAnchorStyle(anchorToken), genSharedAnchorHorizontalStyle(anchorToken)];
|
||||||
},
|
},
|
||||||
(token) => ({
|
prepareComponentToken,
|
||||||
linkPaddingBlock: token.paddingXXS,
|
|
||||||
linkPaddingInlineStart: token.padding,
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
|
@ -36,8 +36,8 @@ const App: React.FC<AppProps> & { useApp: () => useAppProps } = (props) => {
|
|||||||
} = props;
|
} = props;
|
||||||
const { getPrefixCls } = useContext<ConfigConsumerProps>(ConfigContext);
|
const { getPrefixCls } = useContext<ConfigConsumerProps>(ConfigContext);
|
||||||
const prefixCls = getPrefixCls('app', customizePrefixCls);
|
const prefixCls = getPrefixCls('app', customizePrefixCls);
|
||||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls);
|
||||||
const customClassName = classNames(hashId, prefixCls, className, rootClassName);
|
const customClassName = classNames(hashId, prefixCls, className, rootClassName, cssVarCls);
|
||||||
|
|
||||||
const appConfig = useContext<AppConfig>(AppConfigContext);
|
const appConfig = useContext<AppConfig>(AppConfigContext);
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ const App: React.FC<AppProps> & { useApp: () => useAppProps } = (props) => {
|
|||||||
style,
|
style,
|
||||||
};
|
};
|
||||||
|
|
||||||
return wrapSSR(
|
return wrapCSSVar(
|
||||||
<AppContext.Provider value={memoizedContextValue}>
|
<AppContext.Provider value={memoizedContextValue}>
|
||||||
<AppConfigContext.Provider value={mergedAppConfig}>
|
<AppConfigContext.Provider value={mergedAppConfig}>
|
||||||
<Component {...(component === false ? undefined : rootProps)}>
|
<Component {...(component === false ? undefined : rootProps)}>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import type { FullToken, GenerateStyle } from '../../theme/internal';
|
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
|
||||||
import { genComponentStyleHook } from '../../theme/internal';
|
import { genStyleHooks } from '../../theme/internal';
|
||||||
|
|
||||||
export type ComponentToken = {};
|
export type ComponentToken = {};
|
||||||
|
|
||||||
@ -18,5 +18,7 @@ const genBaseStyle: GenerateStyle<AppToken> = (token) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const prepareComponentToken: GetDefaultToken<'App'> = () => ({});
|
||||||
|
|
||||||
// ============================== Export ==============================
|
// ============================== 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`] = `
|
exports[`renders components/auto-complete/demo/allowClear.tsx extend context correctly 1`] = `
|
||||||
Array [
|
Array [
|
||||||
<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"
|
||||||
style="width: 200px;"
|
style="width: 200px;"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -48,7 +48,7 @@ Array [
|
|||||||
<br />,
|
<br />,
|
||||||
<br />,
|
<br />,
|
||||||
<div
|
<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;"
|
style="width: 200px;"
|
||||||
>
|
>
|
||||||
<div
|
<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`] = `
|
exports[`renders components/auto-complete/demo/basic.tsx extend context correctly 1`] = `
|
||||||
Array [
|
Array [
|
||||||
<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"
|
||||||
style="width: 200px;"
|
style="width: 200px;"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -143,7 +143,7 @@ Array [
|
|||||||
<br />,
|
<br />,
|
||||||
<br />,
|
<br />,
|
||||||
<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"
|
||||||
style="width: 200px;"
|
style="width: 200px;"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -190,57 +190,9 @@ Array [
|
|||||||
|
|
||||||
exports[`renders components/auto-complete/demo/basic.tsx extend context correctly 2`] = `[]`;
|
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`] = `
|
exports[`renders components/auto-complete/demo/certain-category.tsx extend context correctly 1`] = `
|
||||||
<div
|
<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;"
|
style="width: 250px;"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -250,7 +202,7 @@ exports[`renders components/auto-complete/demo/certain-category.tsx extend conte
|
|||||||
class="ant-select-selection-search"
|
class="ant-select-selection-search"
|
||||||
>
|
>
|
||||||
<span
|
<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
|
<span
|
||||||
class="ant-input-wrapper ant-input-group"
|
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-haspopup="listbox"
|
||||||
aria-owns="rc_select_TEST_OR_SSR_list"
|
aria-owns="rc_select_TEST_OR_SSR_list"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
class="ant-input ant-input-lg"
|
class="ant-input ant-input-lg ant-input-outlined"
|
||||||
id="rc_select_TEST_OR_SSR"
|
id="rc_select_TEST_OR_SSR"
|
||||||
placeholder="input here"
|
placeholder="input here"
|
||||||
role="combobox"
|
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`] = `
|
exports[`renders components/auto-complete/demo/custom.tsx extend context correctly 1`] = `
|
||||||
<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"
|
||||||
style="width: 200px;"
|
style="width: 200px;"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -625,7 +577,7 @@ exports[`renders components/auto-complete/demo/custom.tsx extend context correct
|
|||||||
aria-haspopup="listbox"
|
aria-haspopup="listbox"
|
||||||
aria-owns="rc_select_TEST_OR_SSR_list"
|
aria-owns="rc_select_TEST_OR_SSR_list"
|
||||||
autocomplete="off"
|
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"
|
id="rc_select_TEST_OR_SSR"
|
||||||
placeholder="input here"
|
placeholder="input here"
|
||||||
role="combobox"
|
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"
|
class="ant-form-item-control-input-content"
|
||||||
>
|
>
|
||||||
<div
|
<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
|
<div
|
||||||
class="ant-select-selector"
|
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"
|
class="ant-form-item-control-input-content"
|
||||||
>
|
>
|
||||||
<div
|
<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
|
<div
|
||||||
class="ant-select-selector"
|
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"
|
class="ant-input-group ant-input-group-compact"
|
||||||
>
|
>
|
||||||
<div
|
<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%;"
|
style="width: 30%;"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -1017,7 +969,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx extend context cor
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<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
|
<div
|
||||||
class="ant-select-selector"
|
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"
|
class="ant-form-item-control-input-content"
|
||||||
>
|
>
|
||||||
<div
|
<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
|
<div
|
||||||
class="ant-select-selector"
|
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"
|
class="ant-select-selection-search"
|
||||||
>
|
>
|
||||||
<span
|
<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
|
<input
|
||||||
aria-autocomplete="list"
|
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"
|
class="ant-input-group ant-input-group-compact"
|
||||||
>
|
>
|
||||||
<div
|
<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%;"
|
style="width: 30%;"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -1303,7 +1255,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx extend context cor
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<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
|
<div
|
||||||
class="ant-select-selector"
|
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"
|
class="ant-select-selection-search"
|
||||||
>
|
>
|
||||||
<span
|
<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
|
<input
|
||||||
aria-autocomplete="list"
|
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"
|
class="ant-input-group ant-input-group-compact"
|
||||||
>
|
>
|
||||||
<div
|
<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%;"
|
style="width: 30%;"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -1519,7 +1471,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx extend context cor
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<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
|
<div
|
||||||
class="ant-select-selector"
|
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"
|
class="ant-select-selection-search"
|
||||||
>
|
>
|
||||||
<span
|
<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
|
<span
|
||||||
class="ant-input-wrapper ant-input-group"
|
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-haspopup="listbox"
|
||||||
aria-owns="rc_select_TEST_OR_SSR_list"
|
aria-owns="rc_select_TEST_OR_SSR_list"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
class="ant-input"
|
class="ant-input ant-input-outlined"
|
||||||
id="rc_select_TEST_OR_SSR"
|
id="rc_select_TEST_OR_SSR"
|
||||||
role="combobox"
|
role="combobox"
|
||||||
type="search"
|
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"
|
class="ant-input-group ant-input-group-compact"
|
||||||
>
|
>
|
||||||
<div
|
<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%;"
|
style="width: 20%;"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -1748,7 +1700,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx extend context cor
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<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
|
<div
|
||||||
class="ant-select-selector"
|
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"
|
class="ant-select-selection-search"
|
||||||
>
|
>
|
||||||
<span
|
<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
|
<span
|
||||||
class="ant-input-wrapper ant-input-group"
|
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-haspopup="listbox"
|
||||||
aria-owns="rc_select_TEST_OR_SSR_list"
|
aria-owns="rc_select_TEST_OR_SSR_list"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
class="ant-input"
|
class="ant-input ant-input-outlined"
|
||||||
id="rc_select_TEST_OR_SSR"
|
id="rc_select_TEST_OR_SSR"
|
||||||
role="combobox"
|
role="combobox"
|
||||||
type="search"
|
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`] = `
|
exports[`renders components/auto-complete/demo/non-case-sensitive.tsx extend context correctly 1`] = `
|
||||||
<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"
|
||||||
style="width: 200px;"
|
style="width: 200px;"
|
||||||
>
|
>
|
||||||
<div
|
<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`] = `
|
exports[`renders components/auto-complete/demo/options.tsx extend context correctly 1`] = `
|
||||||
<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"
|
||||||
style="width: 200px;"
|
style="width: 200px;"
|
||||||
>
|
>
|
||||||
<div
|
<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;"
|
style="padding-bottom: 0px; position: relative; min-width: 0;"
|
||||||
>
|
>
|
||||||
<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"
|
||||||
style="width: 120px; margin: 0px;"
|
style="width: 120px; margin: 0px;"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -2236,7 +2188,7 @@ exports[`renders components/auto-complete/demo/status.tsx extend context correct
|
|||||||
class="ant-space-item"
|
class="ant-space-item"
|
||||||
>
|
>
|
||||||
<div
|
<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;"
|
style="width: 200px;"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -2281,7 +2233,7 @@ exports[`renders components/auto-complete/demo/status.tsx extend context correct
|
|||||||
class="ant-space-item"
|
class="ant-space-item"
|
||||||
>
|
>
|
||||||
<div
|
<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;"
|
style="width: 200px;"
|
||||||
>
|
>
|
||||||
<div
|
<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`] = `
|
exports[`renders components/auto-complete/demo/uncertain-category.tsx extend context correctly 1`] = `
|
||||||
<div
|
<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;"
|
style="width: 300px;"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -2339,7 +2291,7 @@ exports[`renders components/auto-complete/demo/uncertain-category.tsx extend con
|
|||||||
class="ant-select-selection-search"
|
class="ant-select-selection-search"
|
||||||
>
|
>
|
||||||
<span
|
<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
|
<span
|
||||||
class="ant-input-wrapper ant-input-group"
|
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-haspopup="listbox"
|
||||||
aria-owns="rc_select_TEST_OR_SSR_list"
|
aria-owns="rc_select_TEST_OR_SSR_list"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
class="ant-input ant-input-lg"
|
class="ant-input ant-input-lg ant-input-outlined"
|
||||||
id="rc_select_TEST_OR_SSR"
|
id="rc_select_TEST_OR_SSR"
|
||||||
placeholder="input here"
|
placeholder="input here"
|
||||||
role="combobox"
|
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.",
|
"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`] = `
|
exports[`renders components/auto-complete/demo/allowClear.tsx correctly 1`] = `
|
||||||
Array [
|
Array [
|
||||||
<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"
|
||||||
style="width:200px"
|
style="width:200px"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -35,7 +35,7 @@ Array [
|
|||||||
<br />,
|
<br />,
|
||||||
<br />,
|
<br />,
|
||||||
<div
|
<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"
|
style="width:200px"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -70,7 +70,7 @@ Array [
|
|||||||
exports[`renders components/auto-complete/demo/basic.tsx correctly 1`] = `
|
exports[`renders components/auto-complete/demo/basic.tsx correctly 1`] = `
|
||||||
Array [
|
Array [
|
||||||
<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"
|
||||||
style="width:200px"
|
style="width:200px"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -102,7 +102,7 @@ Array [
|
|||||||
<br />,
|
<br />,
|
||||||
<br />,
|
<br />,
|
||||||
<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"
|
||||||
style="width:200px"
|
style="width:200px"
|
||||||
>
|
>
|
||||||
<div
|
<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`] = `
|
exports[`renders components/auto-complete/demo/certain-category.tsx correctly 1`] = `
|
||||||
<div
|
<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"
|
style="width:250px"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -179,7 +146,7 @@ exports[`renders components/auto-complete/demo/certain-category.tsx correctly 1`
|
|||||||
class="ant-select-selection-search"
|
class="ant-select-selection-search"
|
||||||
>
|
>
|
||||||
<span
|
<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
|
<span
|
||||||
class="ant-input-wrapper ant-input-group"
|
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-haspopup="listbox"
|
||||||
aria-owns="undefined_list"
|
aria-owns="undefined_list"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
class="ant-input ant-input-lg"
|
class="ant-input ant-input-lg ant-input-outlined"
|
||||||
placeholder="input here"
|
placeholder="input here"
|
||||||
role="combobox"
|
role="combobox"
|
||||||
type="search"
|
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`] = `
|
exports[`renders components/auto-complete/demo/custom.tsx correctly 1`] = `
|
||||||
<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"
|
||||||
style="width:200px"
|
style="width:200px"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -257,7 +224,7 @@ exports[`renders components/auto-complete/demo/custom.tsx correctly 1`] = `
|
|||||||
aria-haspopup="listbox"
|
aria-haspopup="listbox"
|
||||||
aria-owns="undefined_list"
|
aria-owns="undefined_list"
|
||||||
autocomplete="off"
|
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"
|
placeholder="input here"
|
||||||
role="combobox"
|
role="combobox"
|
||||||
style="height:50px"
|
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"
|
class="ant-form-item-control-input-content"
|
||||||
>
|
>
|
||||||
<div
|
<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
|
<div
|
||||||
class="ant-select-selector"
|
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"
|
class="ant-form-item-control-input-content"
|
||||||
>
|
>
|
||||||
<div
|
<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
|
<div
|
||||||
class="ant-select-selector"
|
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"
|
class="ant-input-group ant-input-group-compact"
|
||||||
>
|
>
|
||||||
<div
|
<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%"
|
style="width:30%"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -505,7 +472,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<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
|
<div
|
||||||
class="ant-select-selector"
|
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"
|
class="ant-form-item-control-input-content"
|
||||||
>
|
>
|
||||||
<div
|
<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
|
<div
|
||||||
class="ant-select-selector"
|
class="ant-select-selector"
|
||||||
@ -572,7 +539,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
|||||||
class="ant-select-selection-search"
|
class="ant-select-selection-search"
|
||||||
>
|
>
|
||||||
<span
|
<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
|
<input
|
||||||
aria-autocomplete="list"
|
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"
|
class="ant-input-group ant-input-group-compact"
|
||||||
>
|
>
|
||||||
<div
|
<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%"
|
style="width:30%"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -707,7 +674,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<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
|
<div
|
||||||
class="ant-select-selector"
|
class="ant-select-selector"
|
||||||
@ -716,7 +683,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
|||||||
class="ant-select-selection-search"
|
class="ant-select-selection-search"
|
||||||
>
|
>
|
||||||
<span
|
<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
|
<input
|
||||||
aria-autocomplete="list"
|
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"
|
class="ant-input-group ant-input-group-compact"
|
||||||
>
|
>
|
||||||
<div
|
<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%"
|
style="width:30%"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -852,7 +819,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<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
|
<div
|
||||||
class="ant-select-selector"
|
class="ant-select-selector"
|
||||||
@ -861,7 +828,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
|||||||
class="ant-select-selection-search"
|
class="ant-select-selection-search"
|
||||||
>
|
>
|
||||||
<span
|
<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
|
<span
|
||||||
class="ant-input-wrapper ant-input-group"
|
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-haspopup="listbox"
|
||||||
aria-owns="undefined_list"
|
aria-owns="undefined_list"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
class="ant-input"
|
class="ant-input ant-input-outlined"
|
||||||
role="combobox"
|
role="combobox"
|
||||||
type="search"
|
type="search"
|
||||||
value=""
|
value=""
|
||||||
@ -953,7 +920,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
|||||||
class="ant-input-group ant-input-group-compact"
|
class="ant-input-group ant-input-group-compact"
|
||||||
>
|
>
|
||||||
<div
|
<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%"
|
style="width:20%"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -1010,7 +977,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<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
|
<div
|
||||||
class="ant-select-selector"
|
class="ant-select-selector"
|
||||||
@ -1019,7 +986,7 @@ exports[`renders components/auto-complete/demo/form-debug.tsx correctly 1`] = `
|
|||||||
class="ant-select-selection-search"
|
class="ant-select-selection-search"
|
||||||
>
|
>
|
||||||
<span
|
<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
|
<span
|
||||||
class="ant-input-wrapper ant-input-group"
|
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-haspopup="listbox"
|
||||||
aria-owns="undefined_list"
|
aria-owns="undefined_list"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
class="ant-input"
|
class="ant-input ant-input-outlined"
|
||||||
role="combobox"
|
role="combobox"
|
||||||
type="search"
|
type="search"
|
||||||
value=""
|
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`] = `
|
exports[`renders components/auto-complete/demo/non-case-sensitive.tsx correctly 1`] = `
|
||||||
<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"
|
||||||
style="width:200px"
|
style="width:200px"
|
||||||
>
|
>
|
||||||
<div
|
<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`] = `
|
exports[`renders components/auto-complete/demo/options.tsx correctly 1`] = `
|
||||||
<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"
|
||||||
style="width:200px"
|
style="width:200px"
|
||||||
>
|
>
|
||||||
<div
|
<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"
|
style="padding-bottom:0;position:relative;min-width:0"
|
||||||
>
|
>
|
||||||
<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"
|
||||||
style="width:120px;margin:0"
|
style="width:120px;margin:0"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -1256,7 +1223,7 @@ exports[`renders components/auto-complete/demo/status.tsx correctly 1`] = `
|
|||||||
class="ant-space-item"
|
class="ant-space-item"
|
||||||
>
|
>
|
||||||
<div
|
<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"
|
style="width:200px"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -1288,7 +1255,7 @@ exports[`renders components/auto-complete/demo/status.tsx correctly 1`] = `
|
|||||||
class="ant-space-item"
|
class="ant-space-item"
|
||||||
>
|
>
|
||||||
<div
|
<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"
|
style="width:200px"
|
||||||
>
|
>
|
||||||
<div
|
<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`] = `
|
exports[`renders components/auto-complete/demo/uncertain-category.tsx correctly 1`] = `
|
||||||
<div
|
<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"
|
style="width:300px"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -1331,7 +1298,7 @@ exports[`renders components/auto-complete/demo/uncertain-category.tsx correctly
|
|||||||
class="ant-select-selection-search"
|
class="ant-select-selection-search"
|
||||||
>
|
>
|
||||||
<span
|
<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
|
<span
|
||||||
class="ant-input-wrapper ant-input-group"
|
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-haspopup="listbox"
|
||||||
aria-owns="undefined_list"
|
aria-owns="undefined_list"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
class="ant-input ant-input-lg"
|
class="ant-input ant-input-lg ant-input-outlined"
|
||||||
placeholder="input here"
|
placeholder="input here"
|
||||||
role="combobox"
|
role="combobox"
|
||||||
type="search"
|
type="search"
|
||||||
@ -1390,3 +1357,101 @@ exports[`renders components/auto-complete/demo/uncertain-category.tsx correctly
|
|||||||
</div>
|
</div>
|
||||||
</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`] = `
|
exports[`AutoComplete rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||||
<div
|
<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
|
<div
|
||||||
class="ant-select-selector"
|
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/certain-category.tsx">Lookup-Patterns - Certain Category</code>
|
||||||
<code src="./demo/uncertain-category.tsx">Lookup-Patterns - Uncertain Category</code>
|
<code src="./demo/uncertain-category.tsx">Lookup-Patterns - Uncertain Category</code>
|
||||||
<code src="./demo/status.tsx">Status</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/allowClear.tsx">Customize clear button</code>
|
||||||
<code src="./demo/form-debug.tsx" debug>Debug in Form</code>
|
<code src="./demo/form-debug.tsx" debug>Debug in Form</code>
|
||||||
<code src="./demo/render-panel.tsx" debug>_InternalPanelDoNotUseOrYouWillBeFired</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 |
|
| allowClear | Show clear button | boolean \| { clearIcon?: ReactNode } | false | 5.8.0: Support Object type |
|
||||||
| autoFocus | If get focus when component mounted | boolean | false | |
|
| autoFocus | If get focus when component mounted | boolean | false | |
|
||||||
| backfill | If backfill selected item the input when using keyboard | 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 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>> | - | |
|
| children (for dataSource) | Data source to auto complete | React.ReactElement<OptionProps> \| Array<React.ReactElement<OptionProps>> | - | |
|
||||||
| defaultActiveFirstOption | Whether active first option by default | boolean | true | |
|
| 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 | - | |
|
| placeholder | The placeholder of input | string | - | |
|
||||||
| status | Set validation status | 'error' \| 'warning' | - | 4.19.0 |
|
| status | Set validation status | 'error' \| 'warning' | - | 4.19.0 |
|
||||||
| value | Selected option | string | - | |
|
| value | Selected option | string | - | |
|
||||||
|
| variant | Variants of input | `outlined` \| `borderless` \| `filled` | `outlined` | 5.13.0 |
|
||||||
| onBlur | Called when leaving the component | function() | - | |
|
| onBlur | Called when leaving the component | function() | - | |
|
||||||
| onChange | Called when selecting an option or changing an input value | function(value) | - | |
|
| onChange | Called when selecting an option or changing an input value | function(value) | - | |
|
||||||
| onDropdownVisibleChange | Call when dropdown open | function(open) | - | |
|
| onDropdownVisibleChange | Call when dropdown open | function(open) | - | |
|
||||||
|
@ -33,7 +33,7 @@ demo:
|
|||||||
<code src="./demo/certain-category.tsx">查询模式 - 确定类目</code>
|
<code src="./demo/certain-category.tsx">查询模式 - 确定类目</code>
|
||||||
<code src="./demo/uncertain-category.tsx">查询模式 - 不确定类目</code>
|
<code src="./demo/uncertain-category.tsx">查询模式 - 不确定类目</code>
|
||||||
<code src="./demo/status.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/allowClear.tsx">自定义清除按钮</code>
|
||||||
<code src="./demo/form-debug.tsx" debug>在 Form 中 Debug</code>
|
<code src="./demo/form-debug.tsx" debug>在 Form 中 Debug</code>
|
||||||
<code src="./demo/render-panel.tsx" debug>\_InternalPanelDoNotUseOrYouWillBeFired</code>
|
<code src="./demo/render-panel.tsx" debug>\_InternalPanelDoNotUseOrYouWillBeFired</code>
|
||||||
@ -47,13 +47,13 @@ demo:
|
|||||||
| allowClear | 支持清除 | boolean \| { clearIcon?: ReactNode } | false | 5.8.0: 支持对象形式 |
|
| allowClear | 支持清除 | boolean \| { clearIcon?: ReactNode } | false | 5.8.0: 支持对象形式 |
|
||||||
| autoFocus | 自动获取焦点 | boolean | false | |
|
| autoFocus | 自动获取焦点 | boolean | false | |
|
||||||
| backfill | 使用键盘选择选项的时候把选中项回填到输入框中 | boolean | false | |
|
| backfill | 使用键盘选择选项的时候把选中项回填到输入框中 | boolean | false | |
|
||||||
| bordered | 是否有边框 | boolean | true | |
|
|
||||||
| children (自动完成的数据源) | 自动完成的数据源 | React.ReactElement<OptionProps> \| Array<React.ReactElement<OptionProps>> | - | |
|
| children (自动完成的数据源) | 自动完成的数据源 | React.ReactElement<OptionProps> \| Array<React.ReactElement<OptionProps>> | - | |
|
||||||
| children (自定义输入框) | 自定义输入框 | HTMLInputElement \| HTMLTextAreaElement \| React.ReactElement<InputProps> | <Input /> | |
|
| children (自定义输入框) | 自定义输入框 | HTMLInputElement \| HTMLTextAreaElement \| React.ReactElement<InputProps> | <Input /> | |
|
||||||
| defaultActiveFirstOption | 是否默认高亮第一个选项 | boolean | true | |
|
| defaultActiveFirstOption | 是否默认高亮第一个选项 | boolean | true | |
|
||||||
| defaultOpen | 是否默认展开下拉菜单 | boolean | - | |
|
| defaultOpen | 是否默认展开下拉菜单 | boolean | - | |
|
||||||
| defaultValue | 指定默认选中的条目 | string | - | |
|
| defaultValue | 指定默认选中的条目 | string | - | |
|
||||||
| disabled | 是否禁用 | boolean | false | |
|
| disabled | 是否禁用 | boolean | false | |
|
||||||
|
| dropdownRender | 自定义下拉框内容 | (menus: ReactNode) => ReactNode | - | 4.24.0 |
|
||||||
| popupClassName | 下拉菜单的 className 属性 | string | - | 4.23.0 |
|
| popupClassName | 下拉菜单的 className 属性 | string | - | 4.23.0 |
|
||||||
| dropdownMatchSelectWidth | 下拉菜单和选择器同宽。默认将设置 `min-width`,当值小于选择框宽度时会被忽略。false 时会关闭虚拟滚动 | boolean \| number | true | |
|
| dropdownMatchSelectWidth | 下拉菜单和选择器同宽。默认将设置 `min-width`,当值小于选择框宽度时会被忽略。false 时会关闭虚拟滚动 | boolean \| number | true | |
|
||||||
| filterOption | 是否根据输入项进行筛选。当其为一个函数时,会接收 `inputValue` `option` 两个参数,当 `option` 符合筛选条件时,应返回 true,反之则返回 false | boolean \| function(inputValue, option) | true | |
|
| filterOption | 是否根据输入项进行筛选。当其为一个函数时,会接收 `inputValue` `option` 两个参数,当 `option` 符合筛选条件时,应返回 true,反之则返回 false | boolean \| function(inputValue, option) | true | |
|
||||||
@ -64,6 +64,7 @@ demo:
|
|||||||
| placeholder | 输入框提示 | string | - | |
|
| placeholder | 输入框提示 | string | - | |
|
||||||
| status | 设置校验状态 | 'error' \| 'warning' | - | 4.19.0 |
|
| status | 设置校验状态 | 'error' \| 'warning' | - | 4.19.0 |
|
||||||
| value | 指定当前选中的条目 | string | - | |
|
| value | 指定当前选中的条目 | string | - | |
|
||||||
|
| variant | 形态变体 | `outlined` \| `borderless` \| `filled` | `outlined` | 5.13.0 |
|
||||||
| onBlur | 失去焦点时的回调 | function() | - | |
|
| onBlur | 失去焦点时的回调 | function() | - | |
|
||||||
| onChange | 选中 option,或 input 的 value 变化时,调用此函数 | function(value) | - | |
|
| onChange | 选中 option,或 input 的 value 变化时,调用此函数 | function(value) | - | |
|
||||||
| onDropdownVisibleChange | 展开下拉菜单的回调 | function(open) | - | |
|
| onDropdownVisibleChange | 展开下拉菜单的回调 | function(open) | - | |
|
||||||
|
@ -439,7 +439,7 @@ Array [
|
|||||||
</span>
|
</span>
|
||||||
<div
|
<div
|
||||||
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-tooltip-placement-top"
|
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
|
<div
|
||||||
class="ant-tooltip-arrow"
|
class="ant-tooltip-arrow"
|
||||||
@ -822,7 +822,7 @@ Array [
|
|||||||
</span>
|
</span>
|
||||||
<div
|
<div
|
||||||
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-tooltip-placement-top"
|
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
|
<div
|
||||||
class="ant-tooltip-arrow"
|
class="ant-tooltip-arrow"
|
||||||
@ -948,7 +948,7 @@ Array [
|
|||||||
</span>
|
</span>
|
||||||
<div
|
<div
|
||||||
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-tooltip-placement-top"
|
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
|
<div
|
||||||
class="ant-tooltip-arrow"
|
class="ant-tooltip-arrow"
|
||||||
@ -1074,7 +1074,7 @@ Array [
|
|||||||
</span>
|
</span>
|
||||||
<div
|
<div
|
||||||
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-tooltip-placement-top"
|
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
|
<div
|
||||||
class="ant-tooltip-arrow"
|
class="ant-tooltip-arrow"
|
||||||
|
@ -12,6 +12,7 @@ import useBreakpoint from '../grid/hooks/useBreakpoint';
|
|||||||
import type { AvatarContextType, AvatarSize } from './AvatarContext';
|
import type { AvatarContextType, AvatarSize } from './AvatarContext';
|
||||||
import AvatarContext from './AvatarContext';
|
import AvatarContext from './AvatarContext';
|
||||||
import useStyle from './style';
|
import useStyle from './style';
|
||||||
|
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
|
||||||
|
|
||||||
export interface AvatarProps {
|
export interface AvatarProps {
|
||||||
/** Shape of avatar, options: `circle`, `square` */
|
/** Shape of avatar, options: `circle`, `square` */
|
||||||
@ -144,7 +145,8 @@ const InternalAvatar: React.ForwardRefRenderFunction<HTMLSpanElement, AvatarProp
|
|||||||
}
|
}
|
||||||
|
|
||||||
const prefixCls = getPrefixCls('avatar', customizePrefixCls);
|
const prefixCls = getPrefixCls('avatar', customizePrefixCls);
|
||||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
const rootCls = useCSSVarCls(prefixCls);
|
||||||
|
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls, rootCls);
|
||||||
|
|
||||||
const sizeCls = classNames({
|
const sizeCls = classNames({
|
||||||
[`${prefixCls}-lg`]: size === 'large',
|
[`${prefixCls}-lg`]: size === 'large',
|
||||||
@ -164,6 +166,8 @@ const InternalAvatar: React.ForwardRefRenderFunction<HTMLSpanElement, AvatarProp
|
|||||||
[`${prefixCls}-image`]: hasImageElement || (src && isImgExist),
|
[`${prefixCls}-image`]: hasImageElement || (src && isImgExist),
|
||||||
[`${prefixCls}-icon`]: !!icon,
|
[`${prefixCls}-icon`]: !!icon,
|
||||||
},
|
},
|
||||||
|
cssVarCls,
|
||||||
|
rootCls,
|
||||||
className,
|
className,
|
||||||
rootClassName,
|
rootClassName,
|
||||||
hashId,
|
hashId,
|
||||||
@ -234,7 +238,7 @@ const InternalAvatar: React.ForwardRefRenderFunction<HTMLSpanElement, AvatarProp
|
|||||||
delete others.onError;
|
delete others.onError;
|
||||||
delete others.gap;
|
delete others.gap;
|
||||||
|
|
||||||
return wrapSSR(
|
return wrapCSSVar(
|
||||||
<span
|
<span
|
||||||
{...others}
|
{...others}
|
||||||
style={{ ...sizeStyle, ...responsiveSizeStyle, ...avatar?.style, ...others.style }}
|
style={{ ...sizeStyle, ...responsiveSizeStyle, ...avatar?.style, ...others.style }}
|
||||||
|
@ -8,6 +8,7 @@ import Avatar from './avatar';
|
|||||||
import AvatarContext from './AvatarContext';
|
import AvatarContext from './AvatarContext';
|
||||||
import type { AvatarContextType, AvatarSize } from './AvatarContext';
|
import type { AvatarContextType, AvatarSize } from './AvatarContext';
|
||||||
import useStyle from './style';
|
import useStyle from './style';
|
||||||
|
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
|
||||||
|
|
||||||
interface ContextProps {
|
interface ContextProps {
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
@ -60,13 +61,16 @@ const Group: React.FC<GroupProps> = (props) => {
|
|||||||
|
|
||||||
const prefixCls = getPrefixCls('avatar', customizePrefixCls);
|
const prefixCls = getPrefixCls('avatar', customizePrefixCls);
|
||||||
const groupPrefixCls = `${prefixCls}-group`;
|
const groupPrefixCls = `${prefixCls}-group`;
|
||||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
const rootCls = useCSSVarCls(prefixCls);
|
||||||
|
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls, rootCls);
|
||||||
|
|
||||||
const cls = classNames(
|
const cls = classNames(
|
||||||
groupPrefixCls,
|
groupPrefixCls,
|
||||||
{
|
{
|
||||||
[`${groupPrefixCls}-rtl`]: direction === 'rtl',
|
[`${groupPrefixCls}-rtl`]: direction === 'rtl',
|
||||||
},
|
},
|
||||||
|
cssVarCls,
|
||||||
|
rootCls,
|
||||||
className,
|
className,
|
||||||
rootClassName,
|
rootClassName,
|
||||||
hashId,
|
hashId,
|
||||||
@ -91,7 +95,7 @@ const Group: React.FC<GroupProps> = (props) => {
|
|||||||
<Avatar style={maxStyle}>{`+${numOfChildren - maxCount}`}</Avatar>
|
<Avatar style={maxStyle}>{`+${numOfChildren - maxCount}`}</Avatar>
|
||||||
</Popover>,
|
</Popover>,
|
||||||
);
|
);
|
||||||
return wrapSSR(
|
return wrapCSSVar(
|
||||||
<AvatarContextProvider shape={shape} size={size}>
|
<AvatarContextProvider shape={shape} size={size}>
|
||||||
<div className={cls} style={style}>
|
<div className={cls} style={style}>
|
||||||
{childrenShow}
|
{childrenShow}
|
||||||
@ -100,7 +104,7 @@ const Group: React.FC<GroupProps> = (props) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return wrapSSR(
|
return wrapCSSVar(
|
||||||
<AvatarContextProvider shape={shape} size={size}>
|
<AvatarContextProvider shape={shape} size={size}>
|
||||||
<div className={cls} style={style}>
|
<div className={cls} style={style}>
|
||||||
{childrenWithProps}
|
{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 { resetComponent } from '../../style';
|
||||||
import type { FullToken, GenerateStyle } from '../../theme/internal';
|
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
|
||||||
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
|
import { genStyleHooks, mergeToken } from '../../theme/internal';
|
||||||
|
|
||||||
export interface ComponentToken {
|
export interface ComponentToken {
|
||||||
/**
|
/**
|
||||||
@ -75,13 +76,14 @@ const genBaseStyle: GenerateStyle<AvatarToken> = (token) => {
|
|||||||
borderRadiusSM,
|
borderRadiusSM,
|
||||||
lineWidth,
|
lineWidth,
|
||||||
lineType,
|
lineType,
|
||||||
|
calc,
|
||||||
} = token;
|
} = token;
|
||||||
|
|
||||||
// Avatar size style
|
// Avatar size style
|
||||||
const avatarSizeStyle = (size: number, fontSize: number, radius: number): CSSObject => ({
|
const avatarSizeStyle = (size: number, fontSize: number, radius: number): CSSObject => ({
|
||||||
width: size,
|
width: size,
|
||||||
height: size,
|
height: size,
|
||||||
lineHeight: `${size - lineWidth * 2}px`,
|
lineHeight: unit(calc(size).sub(calc(lineWidth).mul(2)).equal()),
|
||||||
borderRadius: '50%',
|
borderRadius: '50%',
|
||||||
|
|
||||||
[`&${componentCls}-square`]: {
|
[`&${componentCls}-square`]: {
|
||||||
@ -116,7 +118,7 @@ const genBaseStyle: GenerateStyle<AvatarToken> = (token) => {
|
|||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
verticalAlign: 'middle',
|
verticalAlign: 'middle',
|
||||||
background: avatarBg,
|
background: avatarBg,
|
||||||
border: `${lineWidth}px ${lineType} transparent`,
|
border: `${unit(lineWidth)} ${lineType} transparent`,
|
||||||
|
|
||||||
[`&-image`]: {
|
[`&-image`]: {
|
||||||
background: 'transparent',
|
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',
|
'Avatar',
|
||||||
(token) => {
|
(token) => {
|
||||||
const { colorTextLightSolid, colorTextPlaceholder } = token;
|
const { colorTextLightSolid, colorTextPlaceholder } = token;
|
||||||
@ -179,33 +207,5 @@ export default genComponentStyleHook(
|
|||||||
});
|
});
|
||||||
return [genBaseStyle(avatarToken), genGroupStyle(avatarToken)];
|
return [genBaseStyle(avatarToken), genGroupStyle(avatarToken)];
|
||||||
},
|
},
|
||||||
(token) => {
|
prepareComponentToken,
|
||||||
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,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
@ -74,11 +74,14 @@ const BackTop: React.FC<BackTopProps> = (props) => {
|
|||||||
const { getPrefixCls, direction } = React.useContext<ConfigConsumerProps>(ConfigContext);
|
const { getPrefixCls, direction } = React.useContext<ConfigConsumerProps>(ConfigContext);
|
||||||
|
|
||||||
const prefixCls = getPrefixCls('back-top', customizePrefixCls);
|
const prefixCls = getPrefixCls('back-top', customizePrefixCls);
|
||||||
|
|
||||||
const rootPrefixCls = getPrefixCls();
|
const rootPrefixCls = getPrefixCls();
|
||||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
|
||||||
|
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls);
|
||||||
|
|
||||||
const classString = classNames(
|
const classString = classNames(
|
||||||
hashId,
|
hashId,
|
||||||
|
cssVarCls,
|
||||||
prefixCls,
|
prefixCls,
|
||||||
{
|
{
|
||||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||||
@ -105,7 +108,7 @@ const BackTop: React.FC<BackTopProps> = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
return wrapSSR(
|
return wrapCSSVar(
|
||||||
<div {...divProps} className={classString} onClick={scrollToTop} ref={ref}>
|
<div {...divProps} className={classString} onClick={scrollToTop} ref={ref}>
|
||||||
<CSSMotion visible={visible} motionName={`${rootPrefixCls}-fade`}>
|
<CSSMotion visible={visible} motionName={`${rootPrefixCls}-fade`}>
|
||||||
{({ className: motionClassName }) =>
|
{({ className: motionClassName }) =>
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import type { CSSObject } from '@ant-design/cssinjs';
|
import { type CSSObject, unit } from '@ant-design/cssinjs';
|
||||||
import type { FullToken, GenerateStyle } from '../../theme/internal';
|
|
||||||
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
|
|
||||||
import { resetComponent } from '../../style';
|
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 */
|
/** Component only token. Which will handle additional calculation of alias token */
|
||||||
export interface ComponentToken {
|
export interface ComponentToken {
|
||||||
@ -16,10 +17,10 @@ type BackTopToken = FullToken<'BackTop'> & {
|
|||||||
backTopSize: number;
|
backTopSize: number;
|
||||||
|
|
||||||
// Position
|
// Position
|
||||||
backTopBlockEnd: number;
|
backTopBlockEnd: number | string;
|
||||||
backTopInlineEnd: number;
|
backTopInlineEnd: number | string;
|
||||||
backTopInlineEndMD: number;
|
backTopInlineEndMD: number | string;
|
||||||
backTopInlineEndXS: number;
|
backTopInlineEndXS: number | string;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================== Shared ==============================
|
// ============================== Shared ==============================
|
||||||
@ -61,34 +62,35 @@ const genSharedBackTopStyle: GenerateStyle<BackTopToken, CSSObject> = (token): C
|
|||||||
// change to .backtop .backtop-icon
|
// change to .backtop .backtop-icon
|
||||||
[`${componentCls}-icon`]: {
|
[`${componentCls}-icon`]: {
|
||||||
fontSize: backTopFontSize,
|
fontSize: backTopFontSize,
|
||||||
lineHeight: `${backTopSize}px`,
|
lineHeight: unit(backTopSize),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const genMediaBackTopStyle: GenerateStyle<BackTopToken> = (token): CSSObject => {
|
const genMediaBackTopStyle: GenerateStyle<BackTopToken> = (token): CSSObject => {
|
||||||
const { componentCls } = token;
|
const { componentCls, screenMD, screenXS, backTopInlineEndMD, backTopInlineEndXS } = token;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
[`@media (max-width: ${token.screenMD}px)`]: {
|
[`@media (max-width: ${unit(screenMD)})`]: {
|
||||||
[componentCls]: {
|
[componentCls]: {
|
||||||
insetInlineEnd: token.backTopInlineEndMD,
|
insetInlineEnd: backTopInlineEndMD,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
[`@media (max-width: ${unit(screenXS)})`]: {
|
||||||
[`@media (max-width: ${token.screenXS}px)`]: {
|
|
||||||
[componentCls]: {
|
[componentCls]: {
|
||||||
insetInlineEnd: token.backTopInlineEndXS,
|
insetInlineEnd: backTopInlineEndXS,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================== Export ==============================
|
export const prepareComponentToken: GetDefaultToken<'BackTop'> = (token) => ({
|
||||||
export default genComponentStyleHook<'BackTop'>(
|
zIndexPopup: token.zIndexBase + 10,
|
||||||
'BackTop',
|
});
|
||||||
|
|
||||||
|
// ============================== Export ==============================
|
||||||
|
export default genStyleHooks(
|
||||||
|
'BackTop',
|
||||||
(token) => {
|
(token) => {
|
||||||
const {
|
const {
|
||||||
fontSizeHeading3,
|
fontSizeHeading3,
|
||||||
@ -96,23 +98,20 @@ export default genComponentStyleHook<'BackTop'>(
|
|||||||
colorTextLightSolid,
|
colorTextLightSolid,
|
||||||
colorText,
|
colorText,
|
||||||
controlHeightLG,
|
controlHeightLG,
|
||||||
|
calc,
|
||||||
} = token;
|
} = token;
|
||||||
|
|
||||||
const backTopToken = mergeToken<BackTopToken>(token, {
|
const backTopToken = mergeToken<BackTopToken>(token, {
|
||||||
backTopBackground: colorTextDescription,
|
backTopBackground: colorTextDescription,
|
||||||
backTopColor: colorTextLightSolid,
|
backTopColor: colorTextLightSolid,
|
||||||
backTopHoverBackground: colorText,
|
backTopHoverBackground: colorText,
|
||||||
backTopFontSize: fontSizeHeading3,
|
backTopFontSize: fontSizeHeading3,
|
||||||
backTopSize: controlHeightLG,
|
backTopSize: controlHeightLG,
|
||||||
|
backTopBlockEnd: calc(controlHeightLG).mul(1.25).equal(),
|
||||||
backTopBlockEnd: controlHeightLG * 1.25,
|
backTopInlineEnd: calc(controlHeightLG).mul(2.5).equal(),
|
||||||
backTopInlineEnd: controlHeightLG * 2.5,
|
backTopInlineEndMD: calc(controlHeightLG).mul(1.5).equal(),
|
||||||
backTopInlineEndMD: controlHeightLG * 1.5,
|
backTopInlineEndXS: calc(controlHeightLG).mul(0.5).equal(),
|
||||||
backTopInlineEndXS: controlHeightLG * 0.5,
|
|
||||||
});
|
});
|
||||||
return [genSharedBackTopStyle(backTopToken), genMediaBackTopStyle(backTopToken)];
|
return [genSharedBackTopStyle(backTopToken), genMediaBackTopStyle(backTopToken)];
|
||||||
},
|
},
|
||||||
(token) => ({
|
prepareComponentToken,
|
||||||
zIndexPopup: token.zIndexBase + 10,
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
|
@ -33,6 +33,10 @@ const Ribbon: React.FC<RibbonProps> = (props) => {
|
|||||||
} = props;
|
} = props;
|
||||||
const { getPrefixCls, direction } = React.useContext(ConfigContext);
|
const { getPrefixCls, direction } = React.useContext(ConfigContext);
|
||||||
const prefixCls = getPrefixCls('ribbon', customizePrefixCls);
|
const prefixCls = getPrefixCls('ribbon', customizePrefixCls);
|
||||||
|
|
||||||
|
const wrapperCls = `${prefixCls}-wrapper`;
|
||||||
|
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls, wrapperCls);
|
||||||
|
|
||||||
const colorInPreset = isPresetColor(color, false);
|
const colorInPreset = isPresetColor(color, false);
|
||||||
const ribbonCls = classNames(
|
const ribbonCls = classNames(
|
||||||
prefixCls,
|
prefixCls,
|
||||||
@ -43,15 +47,15 @@ const Ribbon: React.FC<RibbonProps> = (props) => {
|
|||||||
},
|
},
|
||||||
className,
|
className,
|
||||||
);
|
);
|
||||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
|
||||||
const colorStyle: React.CSSProperties = {};
|
const colorStyle: React.CSSProperties = {};
|
||||||
const cornerColorStyle: React.CSSProperties = {};
|
const cornerColorStyle: React.CSSProperties = {};
|
||||||
if (color && !colorInPreset) {
|
if (color && !colorInPreset) {
|
||||||
colorStyle.background = color;
|
colorStyle.background = color;
|
||||||
cornerColorStyle.color = color;
|
cornerColorStyle.color = color;
|
||||||
}
|
}
|
||||||
return wrapSSR(
|
return wrapCSSVar(
|
||||||
<div className={classNames(`${prefixCls}-wrapper`, rootClassName, hashId)}>
|
<div className={classNames(wrapperCls, rootClassName, hashId, cssVarCls)}>
|
||||||
{children}
|
{children}
|
||||||
<div className={classNames(ribbonCls, hashId)} style={{ ...colorStyle, ...style }}>
|
<div className={classNames(ribbonCls, hashId)} style={{ ...colorStyle, ...style }}>
|
||||||
<span className={`${prefixCls}-text`}>{text}</span>
|
<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 * as React from 'react';
|
||||||
import { useMemo, useRef } from 'react';
|
import { useMemo, useRef } from 'react';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
import CSSMotion from 'rc-motion';
|
||||||
|
|
||||||
import type { PresetStatusColorType } from '../_util/colors';
|
import type { PresetStatusColorType } from '../_util/colors';
|
||||||
import { isPresetColor } from '../_util/colors';
|
import { isPresetColor } from '../_util/colors';
|
||||||
import { cloneElement } from '../_util/reactNode';
|
import { cloneElement } from '../_util/reactNode';
|
||||||
@ -75,8 +76,7 @@ const InternalBadge: React.ForwardRefRenderFunction<HTMLSpanElement, BadgeProps>
|
|||||||
const { getPrefixCls, direction, badge } = React.useContext(ConfigContext);
|
const { getPrefixCls, direction, badge } = React.useContext(ConfigContext);
|
||||||
const prefixCls = getPrefixCls('badge', customizePrefixCls);
|
const prefixCls = getPrefixCls('badge', customizePrefixCls);
|
||||||
|
|
||||||
// Style
|
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls);
|
||||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
|
||||||
|
|
||||||
// ================================ Misc ================================
|
// ================================ Misc ================================
|
||||||
const numberedDisplayCount = (
|
const numberedDisplayCount = (
|
||||||
@ -183,12 +183,13 @@ const InternalBadge: React.ForwardRefRenderFunction<HTMLSpanElement, BadgeProps>
|
|||||||
badge?.classNames?.root,
|
badge?.classNames?.root,
|
||||||
classNames?.root,
|
classNames?.root,
|
||||||
hashId,
|
hashId,
|
||||||
|
cssVarCls,
|
||||||
);
|
);
|
||||||
|
|
||||||
// <Badge status="success" />
|
// <Badge status="success" />
|
||||||
if (!children && hasStatus) {
|
if (!children && hasStatus) {
|
||||||
const statusTextColor = mergedStyle.color;
|
const statusTextColor = mergedStyle.color;
|
||||||
return wrapSSR(
|
return wrapCSSVar(
|
||||||
<span
|
<span
|
||||||
{...restProps}
|
{...restProps}
|
||||||
className={badgeClassName}
|
className={badgeClassName}
|
||||||
@ -207,7 +208,7 @@ const InternalBadge: React.ForwardRefRenderFunction<HTMLSpanElement, BadgeProps>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return wrapSSR(
|
return wrapCSSVar(
|
||||||
<span
|
<span
|
||||||
ref={ref}
|
ref={ref}
|
||||||
{...restProps}
|
{...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