mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-24 02:59:58 +08:00
Merge branch 'master' into master
This commit is contained in:
commit
b53205255e
@ -1,16 +1,22 @@
|
|||||||
import { useLocale as useDumiLocale } from 'dumi';
|
import { useLocale as useDumiLocale } from 'dumi';
|
||||||
|
|
||||||
export interface LocaleMap<Key extends string> {
|
export interface LocaleMap<
|
||||||
cn: Record<Key, string>;
|
K extends PropertyKey = PropertyKey,
|
||||||
en: Record<Key, string>;
|
V extends string | ((...params: any[]) => string) = string,
|
||||||
|
> {
|
||||||
|
cn: Record<K, V>;
|
||||||
|
en: Record<K, V>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function useLocale<Key extends string>(
|
const useLocale = <
|
||||||
localeMap?: LocaleMap<Key>,
|
K extends PropertyKey = PropertyKey,
|
||||||
): [Record<Key, string>, 'cn' | 'en'] {
|
V extends string | ((...params: any[]) => string) = string,
|
||||||
|
>(
|
||||||
|
localeMap?: LocaleMap<K, V>,
|
||||||
|
): [Record<K, V>, 'cn' | 'en'] => {
|
||||||
const { id } = useDumiLocale();
|
const { id } = useDumiLocale();
|
||||||
const localeType = id === 'zh-CN' ? 'cn' : 'en';
|
const localeType = id === 'zh-CN' ? 'cn' : 'en';
|
||||||
return [localeMap?.[localeType]!, localeType];
|
return [localeMap?.[localeType]!, localeType] as const;
|
||||||
}
|
};
|
||||||
|
|
||||||
export default useLocale;
|
export default useLocale;
|
||||||
|
@ -1,12 +1,35 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import type { MenuProps } from 'antd';
|
import type { MenuProps } from 'antd';
|
||||||
import { Tag, version } from 'antd';
|
import { Tag, version } from 'antd';
|
||||||
|
import { createStyles } from 'antd-style';
|
||||||
|
import classnames from 'classnames';
|
||||||
import { useFullSidebarData, useSidebarData } from 'dumi';
|
import { useFullSidebarData, useSidebarData } from 'dumi';
|
||||||
|
|
||||||
import Link from '../theme/common/Link';
|
import Link from '../theme/common/Link';
|
||||||
import useLocation from './useLocation';
|
import useLocation from './useLocation';
|
||||||
|
|
||||||
const MenuItemLabelWithTag: React.FC<{
|
function isVersionNumber(value?: string) {
|
||||||
|
return value && /^\d+\.\d+\.\d+$/.test(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
const useStyle = createStyles(({ css, token }) => ({
|
||||||
|
link: css`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
`,
|
||||||
|
tag: css`
|
||||||
|
margin-inline-end: 0;
|
||||||
|
`,
|
||||||
|
subtitle: css`
|
||||||
|
margin-inline-start: ${token.marginXS}px;
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: ${token.fontSizeSM}px;
|
||||||
|
opacity: 0.8;
|
||||||
|
`,
|
||||||
|
}));
|
||||||
|
|
||||||
|
interface MenuItemLabelProps {
|
||||||
before?: React.ReactNode;
|
before?: React.ReactNode;
|
||||||
after?: React.ReactNode;
|
after?: React.ReactNode;
|
||||||
link: string;
|
link: string;
|
||||||
@ -15,27 +38,23 @@ const MenuItemLabelWithTag: React.FC<{
|
|||||||
search?: string;
|
search?: string;
|
||||||
tag?: string;
|
tag?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
}> = ({ before, after, link, title, subtitle, search, tag = '', className }) => {
|
}
|
||||||
|
|
||||||
|
const MenuItemLabelWithTag: React.FC<MenuItemLabelProps> = (props) => {
|
||||||
|
const { styles } = useStyle();
|
||||||
|
const { before, after, link, title, subtitle, search, tag, className } = props;
|
||||||
if (!before && !after) {
|
if (!before && !after) {
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link to={`${link}${search}`} className={classnames(className, { [styles.link]: tag })}>
|
||||||
to={`${link}${search}`}
|
|
||||||
style={
|
|
||||||
tag
|
|
||||||
? { display: 'flex', alignItems: 'center', justifyContent: 'space-between' }
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
className={className}
|
|
||||||
>
|
|
||||||
<span>
|
<span>
|
||||||
{title}
|
{title}
|
||||||
{subtitle && <span className="chinese">{subtitle}</span>}
|
{subtitle && <span className={styles.subtitle}>{subtitle}</span>}
|
||||||
</span>
|
</span>
|
||||||
{tag && (
|
{tag && (
|
||||||
<Tag
|
<Tag
|
||||||
bordered={false}
|
bordered={false}
|
||||||
color={tag === 'New' ? 'success' : 'processing'}
|
className={classnames(styles.tag)}
|
||||||
style={{ marginBlockEnd: 0 }}
|
color={isVersionNumber(tag) || tag === 'New' ? 'success' : 'processing'}
|
||||||
>
|
>
|
||||||
{tag.replace('VERSION', version)}
|
{tag.replace('VERSION', version)}
|
||||||
</Tag>
|
</Tag>
|
||||||
@ -47,7 +66,7 @@ const MenuItemLabelWithTag: React.FC<{
|
|||||||
<Link to={`${link}${search}`} className={className}>
|
<Link to={`${link}${search}`} className={className}>
|
||||||
{before}
|
{before}
|
||||||
{title}
|
{title}
|
||||||
{subtitle && <span className="chinese">{subtitle}</span>}
|
{subtitle && <span className={styles.subtitle}>{subtitle}</span>}
|
||||||
{after}
|
{after}
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
@ -58,7 +77,7 @@ export interface UseMenuOptions {
|
|||||||
after?: React.ReactNode;
|
after?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useMenu = (options: UseMenuOptions = {}): [MenuProps['items'], string] => {
|
const useMenu = (options: UseMenuOptions = {}): readonly [MenuProps['items'], string] => {
|
||||||
const fullData = useFullSidebarData();
|
const fullData = useFullSidebarData();
|
||||||
const { pathname, search } = useLocation();
|
const { pathname, search } = useLocation();
|
||||||
const sidebarData = useSidebarData();
|
const sidebarData = useSidebarData();
|
||||||
@ -192,7 +211,7 @@ const useMenu = (options: UseMenuOptions = {}): [MenuProps['items'], string] =>
|
|||||||
);
|
);
|
||||||
}, [sidebarData, fullData, pathname, search, options]);
|
}, [sidebarData, fullData, pathname, search, options]);
|
||||||
|
|
||||||
return [menuItems, pathname];
|
return [menuItems, pathname] as const;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useMenu;
|
export default useMenu;
|
||||||
|
@ -51,8 +51,7 @@
|
|||||||
top: 120px;
|
top: 120px;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
margin-left: auto;
|
margin: 0 auto;
|
||||||
margin-right: auto;
|
|
||||||
width: 420px;
|
width: 420px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -117,7 +116,7 @@
|
|||||||
.mirror-modal-cancel-btn {
|
.mirror-modal-cancel-btn {
|
||||||
border: 1px solid #eee;
|
border: 1px solid #eee;
|
||||||
color: #000;
|
color: #000;
|
||||||
margin-right: 8px;
|
margin-inline-end: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mirror-modal-cancel-btn:hover {
|
.mirror-modal-cancel-btn:hover {
|
||||||
|
@ -7,7 +7,7 @@ import { Link, useLocation } from 'dumi';
|
|||||||
import useLocale from '../../../hooks/useLocale';
|
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 GroupMaskLayer from './GroupMaskLayer';
|
||||||
|
|
||||||
const locales = {
|
const locales = {
|
||||||
cn: {
|
cn: {
|
||||||
@ -50,6 +50,47 @@ const useStyle = () => {
|
|||||||
btnWrap: css`
|
btnWrap: css`
|
||||||
margin-bottom: ${token.marginXL}px;
|
margin-bottom: ${token.marginXL}px;
|
||||||
`,
|
`,
|
||||||
|
layer: css`
|
||||||
|
text-align: center;
|
||||||
|
padding-top: ${token.marginFar - 16}px;
|
||||||
|
padding-bottom: ${token.marginFarSM}px;
|
||||||
|
`,
|
||||||
|
mobileBg: css`
|
||||||
|
width: 100%;
|
||||||
|
`,
|
||||||
|
videoWrap: css`
|
||||||
|
height: 320px;
|
||||||
|
background-color: #77c6ff;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
justify-content: center;
|
||||||
|
`,
|
||||||
|
video: css`
|
||||||
|
height: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
`,
|
||||||
|
bg: css`
|
||||||
|
flex: auto;
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
background-size: auto 100%;
|
||||||
|
`,
|
||||||
|
bg1: css`
|
||||||
|
background-image: url(https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*6d50SboraPIAAAAAAAAAAAAAARQnAQ);
|
||||||
|
background-position: 100% 0;
|
||||||
|
`,
|
||||||
|
bg2: css`
|
||||||
|
background-image: url(https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*8ILtRrQlVDMAAAAAAAAAAAAAARQnAQ);
|
||||||
|
background-position: 0 0;
|
||||||
|
margin-inline-start: -1px;
|
||||||
|
`,
|
||||||
|
logoWrap: css`
|
||||||
|
position: relative;
|
||||||
|
background-color: #fff;
|
||||||
|
`,
|
||||||
|
bgImg: css`
|
||||||
|
position: absolute;
|
||||||
|
width: 240px;
|
||||||
|
`,
|
||||||
}))();
|
}))();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -65,83 +106,50 @@ const Banner: React.FC<React.PropsWithChildren> = ({ children }) => {
|
|||||||
{/* Banner Placeholder Motion */}
|
{/* Banner Placeholder Motion */}
|
||||||
{isMobile ? (
|
{isMobile ? (
|
||||||
<img
|
<img
|
||||||
|
className={styles.mobileBg}
|
||||||
src="https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*JmlaR5oQn3MAAAAAAAAAAAAADrJ8AQ/original"
|
src="https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*JmlaR5oQn3MAAAAAAAAAAAAADrJ8AQ/original"
|
||||||
style={{ width: '100%' }}
|
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div className={classNames(styles.videoWrap)}>
|
||||||
style={{
|
<div className={classNames(styles.bg, styles.bg1)} />
|
||||||
height: 320,
|
<video className={styles.video} autoPlay muted loop>
|
||||||
background: '#77C6FF',
|
|
||||||
display: 'flex',
|
|
||||||
flexWrap: 'nowrap',
|
|
||||||
justifyContent: 'center',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
backgroundImage: `url(https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*6d50SboraPIAAAAAAAAAAAAAARQnAQ)`,
|
|
||||||
flex: 'auto',
|
|
||||||
backgroundRepeat: 'repeat-x',
|
|
||||||
backgroundPosition: '100% 0',
|
|
||||||
backgroundSize: 'auto 100%',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<video style={{ height: '100%', objectFit: 'contain' }} autoPlay muted loop>
|
|
||||||
<source
|
<source
|
||||||
src="https://mdn.alipayobjects.com/huamei_iwk9zp/afts/file/A*uYT7SZwhJnUAAAAAAAAAAAAADgCCAQ"
|
|
||||||
type="video/webm"
|
type="video/webm"
|
||||||
|
src="https://mdn.alipayobjects.com/huamei_iwk9zp/afts/file/A*uYT7SZwhJnUAAAAAAAAAAAAADgCCAQ"
|
||||||
/>
|
/>
|
||||||
<source
|
<source
|
||||||
src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/file/A*XYYNQJ3NbmMAAAAAAAAAAAAAARQnAQ"
|
|
||||||
type="video/mp4"
|
type="video/mp4"
|
||||||
|
src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/file/A*XYYNQJ3NbmMAAAAAAAAAAAAAARQnAQ"
|
||||||
/>
|
/>
|
||||||
</video>
|
</video>
|
||||||
|
<div className={classNames(styles.bg, styles.bg2)} />
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
backgroundImage: `url(https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*8ILtRrQlVDMAAAAAAAAAAAAAARQnAQ)`,
|
|
||||||
flex: 'auto',
|
|
||||||
backgroundRepeat: 'repeat-x',
|
|
||||||
backgroundPosition: '0 0',
|
|
||||||
backgroundSize: 'auto 100%',
|
|
||||||
marginLeft: -1,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Logo */}
|
{/* Logo */}
|
||||||
<div style={{ position: 'relative', background: '#fff' }}>
|
<div className={styles.logoWrap}>
|
||||||
{/* Image Bottom Right */}
|
{/* Image Bottom Right */}
|
||||||
<img
|
<img
|
||||||
style={{ position: 'absolute', right: 0, top: 240, width: 240 }}
|
className={classNames(styles.bgImg)}
|
||||||
|
style={{ right: 0, top: 240 }}
|
||||||
src="https://gw.alipayobjects.com/zos/bmw-prod/b3b8dc41-dce8-471f-9d81-9a0204f27d03.svg"
|
src="https://gw.alipayobjects.com/zos/bmw-prod/b3b8dc41-dce8-471f-9d81-9a0204f27d03.svg"
|
||||||
alt="Ant Design"
|
alt="Ant Design"
|
||||||
/>
|
/>
|
||||||
|
<GroupMaskLayer className={styles.layer}>
|
||||||
<GroupMask
|
|
||||||
style={{
|
|
||||||
textAlign: 'center',
|
|
||||||
paddingTop: token.marginFar - 16,
|
|
||||||
paddingBottom: token.marginFarSM,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{/* Image Left Top */}
|
{/* Image Left Top */}
|
||||||
<img
|
<img
|
||||||
style={{ position: 'absolute', left: isMobile ? -120 : 0, top: 0, width: 240 }}
|
className={classNames(styles.bgImg)}
|
||||||
|
style={{ left: isMobile ? -120 : 0, top: 0 }}
|
||||||
src="https://gw.alipayobjects.com/zos/bmw-prod/49f963db-b2a8-4f15-857a-270d771a1204.svg"
|
src="https://gw.alipayobjects.com/zos/bmw-prod/49f963db-b2a8-4f15-857a-270d771a1204.svg"
|
||||||
alt="bg"
|
alt="bg"
|
||||||
/>
|
/>
|
||||||
{/* Image Right Top */}
|
{/* Image Right Top */}
|
||||||
<img
|
<img
|
||||||
style={{ position: 'absolute', right: isMobile ? 0 : 120, top: 0, width: 240 }}
|
className={classNames(styles.bgImg)}
|
||||||
|
style={{ right: isMobile ? 0 : 120, top: 0 }}
|
||||||
src="https://gw.alipayobjects.com/zos/bmw-prod/e152223c-bcae-4913-8938-54fda9efe330.svg"
|
src="https://gw.alipayobjects.com/zos/bmw-prod/e152223c-bcae-4913-8938-54fda9efe330.svg"
|
||||||
alt="bg"
|
alt="bg"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Typography.Title level={1} className={classNames(styles.titleBase, styles.title)}>
|
<Typography.Title level={1} className={classNames(styles.titleBase, styles.title)}>
|
||||||
Ant Design 5.0
|
Ant Design 5.0
|
||||||
</Typography.Title>
|
</Typography.Title>
|
||||||
@ -166,7 +174,7 @@ const Banner: React.FC<React.PropsWithChildren> = ({ children }) => {
|
|||||||
</Link>
|
</Link>
|
||||||
</Flex>
|
</Flex>
|
||||||
{children}
|
{children}
|
||||||
</GroupMask>
|
</GroupMaskLayer>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
import * as React from 'react';
|
import React, { useContext } from 'react';
|
||||||
import type { FC } from 'react';
|
|
||||||
import { useContext } from 'react';
|
|
||||||
import { Badge, Carousel, Skeleton, Typography } from 'antd';
|
import { Badge, Carousel, Skeleton, Typography } from 'antd';
|
||||||
import { createStyles, useTheme } from 'antd-style';
|
import { createStyles, useTheme } from 'antd-style';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
@ -46,10 +44,10 @@ const useStyle = createStyles(({ token, css, cx }) => {
|
|||||||
`,
|
`,
|
||||||
container: css`
|
container: css`
|
||||||
display: flex;
|
display: flex;
|
||||||
max-width: 1208px;
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
margin-inline: auto;
|
margin-inline: auto;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding-inline: ${token.marginXXL}px;
|
|
||||||
column-gap: ${token.paddingMD * 2}px;
|
column-gap: ${token.paddingMD * 2}px;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
text-align: start;
|
text-align: start;
|
||||||
@ -107,7 +105,7 @@ const RecommendItem: React.FC<RecommendItemProps> = ({ extra, index, icons, clas
|
|||||||
return card;
|
return card;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const BannerRecommendsFallback: FC = () => {
|
export const BannerRecommendsFallback: React.FC = () => {
|
||||||
const { isMobile } = useContext(SiteContext);
|
const { isMobile } = useContext(SiteContext);
|
||||||
const { styles } = useStyle();
|
const { styles } = useStyle();
|
||||||
|
|
||||||
@ -145,9 +143,8 @@ const BannerRecommends: React.FC = () => {
|
|||||||
return <BannerRecommendsFallback />;
|
return <BannerRecommendsFallback />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isMobile) {
|
||||||
return (
|
return (
|
||||||
<div>
|
|
||||||
{isMobile ? (
|
|
||||||
<Carousel className={styles.carousel}>
|
<Carousel className={styles.carousel}>
|
||||||
{first3.map((extra, index) => (
|
{first3.map((extra, index) => (
|
||||||
<div key={index}>
|
<div key={index}>
|
||||||
@ -160,7 +157,10 @@ const BannerRecommends: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</Carousel>
|
</Carousel>
|
||||||
) : (
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
{first3.map((extra, index) => (
|
{first3.map((extra, index) => (
|
||||||
<RecommendItem
|
<RecommendItem
|
||||||
@ -172,8 +172,6 @@ const BannerRecommends: React.FC = () => {
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -96,6 +96,13 @@ const useStyle = () => {
|
|||||||
mobileCard: css`
|
mobileCard: css`
|
||||||
height: 395px;
|
height: 395px;
|
||||||
`,
|
`,
|
||||||
|
nodeWrap: css`
|
||||||
|
margin-top: ${token.paddingLG}px;
|
||||||
|
flex: auto;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
`,
|
||||||
carousel,
|
carousel,
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
@ -107,8 +114,6 @@ const ComponentItem: React.FC<ComponentItemProps> = ({ title, node, type, index
|
|||||||
const tagText = type === 'new' ? locale.new : locale.update;
|
const tagText = type === 'new' ? locale.new : locale.update;
|
||||||
const { styles } = useStyle();
|
const { styles } = useStyle();
|
||||||
const { isMobile } = useContext(SiteContext);
|
const { isMobile } = useContext(SiteContext);
|
||||||
const token = useTheme();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames(styles.card, isMobile && styles.mobileCard)}>
|
<div className={classNames(styles.card, isMobile && styles.mobileCard)}>
|
||||||
{/* Decorator */}
|
{/* Decorator */}
|
||||||
@ -124,18 +129,7 @@ const ComponentItem: React.FC<ComponentItemProps> = ({ title, node, type, index
|
|||||||
</Typography.Title>
|
</Typography.Title>
|
||||||
<Tag color={tagColor}>{tagText}</Tag>
|
<Tag color={tagColor}>{tagText}</Tag>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
<div className={styles.nodeWrap}>{node}</div>
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
marginTop: token.paddingLG,
|
|
||||||
flex: 'auto',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{node}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -96,7 +96,7 @@ const useStyle = () => {
|
|||||||
}))();
|
}))();
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function DesignFramework() {
|
const DesignFramework: React.FC = () => {
|
||||||
const [locale] = useLocale(locales);
|
const [locale] = useLocale(locales);
|
||||||
const token = useTheme();
|
const token = useTheme();
|
||||||
const { styles } = useStyle();
|
const { styles } = useStyle();
|
||||||
@ -174,4 +174,6 @@ export default function DesignFramework() {
|
|||||||
})}
|
})}
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default DesignFramework;
|
||||||
|
@ -1,68 +1,46 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import { Typography } from 'antd';
|
import { Typography } from 'antd';
|
||||||
import { useTheme } from 'antd-style';
|
import { createStyles, useTheme } from 'antd-style';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import SiteContext from '../../../theme/slots/SiteContext';
|
import SiteContext from '../../../theme/slots/SiteContext';
|
||||||
|
import GroupMaskLayer from './GroupMaskLayer';
|
||||||
|
|
||||||
export interface GroupMaskProps {
|
const useStyle = createStyles(({ css, token }) => ({
|
||||||
style?: React.CSSProperties;
|
box: css`
|
||||||
children?: React.ReactNode;
|
position: relative;
|
||||||
disabled?: boolean;
|
transition: all ${token.motionDurationSlow};
|
||||||
onMouseMove?: React.MouseEventHandler<HTMLDivElement>;
|
`,
|
||||||
onMouseEnter?: React.MouseEventHandler<HTMLDivElement>;
|
marginStyle: css`
|
||||||
onMouseLeave?: React.MouseEventHandler<HTMLDivElement>;
|
max-width: 1208px;
|
||||||
}
|
margin-inline: auto;
|
||||||
|
box-sizing: border-box;
|
||||||
export const GroupMask: React.FC<GroupMaskProps> = (props) => {
|
padding-inline: ${token.marginXXL}px;
|
||||||
const { children, style, disabled, onMouseMove, onMouseEnter, onMouseLeave } = props;
|
`,
|
||||||
const additionalStyle: React.CSSProperties = disabled
|
withoutChildren: css`
|
||||||
? {}
|
min-height: 300px;
|
||||||
: {
|
border-radius: ${token.borderRadiusLG}px;
|
||||||
position: 'relative',
|
background-color: '#e9e9e9';
|
||||||
zIndex: 1,
|
`,
|
||||||
};
|
}));
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className="site-mask"
|
|
||||||
style={{ position: 'relative', ...style, ...additionalStyle }}
|
|
||||||
onMouseMove={onMouseMove}
|
|
||||||
onMouseEnter={onMouseEnter}
|
|
||||||
onMouseLeave={onMouseLeave}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface GroupProps {
|
export interface GroupProps {
|
||||||
id?: string;
|
id?: string;
|
||||||
title?: React.ReactNode;
|
title?: React.ReactNode;
|
||||||
titleColor?: string;
|
titleColor?: string;
|
||||||
description?: React.ReactNode;
|
description?: React.ReactNode;
|
||||||
children?: React.ReactNode;
|
|
||||||
background?: string;
|
background?: string;
|
||||||
|
|
||||||
/** 是否不使用两侧 margin */
|
/** 是否不使用两侧 margin */
|
||||||
collapse?: boolean;
|
collapse?: boolean;
|
||||||
|
|
||||||
decoration?: React.ReactNode;
|
decoration?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Group: React.FC<GroupProps> = (props) => {
|
const Group: React.FC<React.PropsWithChildren<GroupProps>> = (props) => {
|
||||||
const { id, title, titleColor, description, children, decoration, background, collapse } = props;
|
const { id, title, titleColor, description, children, decoration, background, collapse } = props;
|
||||||
const token = useTheme();
|
const token = useTheme();
|
||||||
|
const { styles } = useStyle();
|
||||||
const { isMobile } = useContext(SiteContext);
|
const { isMobile } = useContext(SiteContext);
|
||||||
|
|
||||||
const marginStyle: React.CSSProperties = collapse
|
|
||||||
? {}
|
|
||||||
: {
|
|
||||||
maxWidth: 1208,
|
|
||||||
marginInline: 'auto',
|
|
||||||
boxSizing: 'border-box',
|
|
||||||
paddingInline: isMobile ? token.margin : token.marginXXL,
|
|
||||||
};
|
|
||||||
const childNode = (
|
const childNode = (
|
||||||
<>
|
<>
|
||||||
<div style={{ textAlign: 'center' }}>
|
<div style={{ textAlign: 'center' }}>
|
||||||
@ -82,38 +60,22 @@ const Group: React.FC<GroupProps> = (props) => {
|
|||||||
<Typography.Paragraph
|
<Typography.Paragraph
|
||||||
style={{
|
style={{
|
||||||
color: titleColor,
|
color: titleColor,
|
||||||
marginBottom: isMobile ? token.marginXXL : (token as any).marginFarXS,
|
marginBottom: isMobile ? token.marginXXL : token.marginFarXS,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{description}
|
{description}
|
||||||
</Typography.Paragraph>
|
</Typography.Paragraph>
|
||||||
</div>
|
</div>
|
||||||
|
<div className={classNames({ [styles.marginStyle]: !collapse })}>
|
||||||
<div style={marginStyle}>
|
{children ? <div>{children}</div> : <div className={styles.withoutChildren} />}
|
||||||
{children ? (
|
|
||||||
<div>{children}</div>
|
|
||||||
) : (
|
|
||||||
<div
|
|
||||||
style={{ borderRadius: token.borderRadiusLG, minHeight: 300, background: '#e9e9e9' }}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div style={{ backgroundColor: background }} className={styles.box}>
|
||||||
style={{ position: 'relative', background, transition: `all ${token.motionDurationSlow}` }}
|
|
||||||
>
|
|
||||||
<div style={{ position: 'absolute', inset: 0 }}>{decoration}</div>
|
<div style={{ position: 'absolute', inset: 0 }}>{decoration}</div>
|
||||||
<GroupMask
|
<GroupMaskLayer style={{ paddingBlock: token.marginFarSM }}>{childNode}</GroupMaskLayer>
|
||||||
disabled={!!background}
|
|
||||||
style={{
|
|
||||||
paddingBlock: (token as any).marginFarSM,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{childNode}
|
|
||||||
</GroupMask>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
36
.dumi/pages/index/components/GroupMaskLayer.tsx
Normal file
36
.dumi/pages/index/components/GroupMaskLayer.tsx
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { createStyles } from 'antd-style';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
const useStyle = createStyles(({ css }) => ({
|
||||||
|
siteMask: css`
|
||||||
|
z-index: 1;
|
||||||
|
position: relative;
|
||||||
|
`,
|
||||||
|
}));
|
||||||
|
|
||||||
|
export interface GroupMaskLayerProps {
|
||||||
|
className?: string;
|
||||||
|
style?: React.CSSProperties;
|
||||||
|
onMouseMove?: React.MouseEventHandler<HTMLDivElement>;
|
||||||
|
onMouseEnter?: React.MouseEventHandler<HTMLDivElement>;
|
||||||
|
onMouseLeave?: React.MouseEventHandler<HTMLDivElement>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GroupMaskLayer: React.FC<React.PropsWithChildren<GroupMaskLayerProps>> = (props) => {
|
||||||
|
const { children, className, style, onMouseMove, onMouseEnter, onMouseLeave } = props;
|
||||||
|
const { styles } = useStyle();
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={style}
|
||||||
|
className={classNames(className, styles.siteMask)}
|
||||||
|
onMouseMove={onMouseMove}
|
||||||
|
onMouseEnter={onMouseEnter}
|
||||||
|
onMouseLeave={onMouseLeave}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GroupMaskLayer;
|
@ -6,7 +6,7 @@ import { Link, useLocation } from 'dumi';
|
|||||||
import useLocale from '../../../../hooks/useLocale';
|
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 GroupMaskLayer from '../GroupMaskLayer';
|
||||||
|
|
||||||
const ComponentsBlock = React.lazy(() => import('./ComponentsBlock'));
|
const ComponentsBlock = React.lazy(() => import('./ComponentsBlock'));
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ 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 4px ${token.colorBgContainer}`;
|
||||||
|
|
||||||
const mask = cx(css`
|
const mask = cx(css`
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -91,10 +91,11 @@ const useStyle = () => {
|
|||||||
top: -38px;
|
top: -38px;
|
||||||
transform: ${isRTL ? 'rotate3d(24, 83, -45, 57deg)' : 'rotate3d(24, -83, 45, 57deg)'};
|
transform: ${isRTL ? 'rotate3d(24, 83, -45, 57deg)' : 'rotate3d(24, -83, 45, 57deg)'};
|
||||||
`,
|
`,
|
||||||
|
|
||||||
child: css`
|
child: css`
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
`,
|
`,
|
||||||
btnWrap: css`
|
btnWrap: css`
|
||||||
@ -113,7 +114,7 @@ const PreviewBanner: React.FC<React.PropsWithChildren> = (props) => {
|
|||||||
const isZhCN = utils.isZhCN(pathname);
|
const isZhCN = utils.isZhCN(pathname);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GroupMask>
|
<GroupMaskLayer>
|
||||||
{/* 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 }}
|
||||||
@ -153,7 +154,7 @@ const PreviewBanner: React.FC<React.PropsWithChildren> = (props) => {
|
|||||||
</Flex>
|
</Flex>
|
||||||
<div className={styles.child}>{children}</div>
|
<div className={styles.child}>{children}</div>
|
||||||
</div>
|
</div>
|
||||||
</GroupMask>
|
</GroupMaskLayer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -23,12 +23,9 @@ const useStyle = createStyles(({ token }) => ({
|
|||||||
`,
|
`,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const onShow = () => ({
|
const onShow = () => ({ opacity: 1 });
|
||||||
opacity: 1,
|
|
||||||
});
|
const onHide = () => ({ opacity: 0 });
|
||||||
const onHide = () => ({
|
|
||||||
opacity: 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
const BackgroundImage: React.FC<BackgroundImageProps> = ({ colorPrimary, isLight }) => {
|
const BackgroundImage: React.FC<BackgroundImageProps> = ({ colorPrimary, isLight }) => {
|
||||||
const activeColor = useMemo(() => getClosetColor(colorPrimary), [colorPrimary]);
|
const activeColor = useMemo(() => getClosetColor(colorPrimary), [colorPrimary]);
|
||||||
@ -68,10 +65,7 @@ const BackgroundImage: React.FC<BackgroundImageProps> = ({ colorPrimary, isLight
|
|||||||
<source srcSet={entity.url} type="image/jpeg" />
|
<source srcSet={entity.url} type="image/jpeg" />
|
||||||
<img
|
<img
|
||||||
className={cls}
|
className={cls}
|
||||||
style={{
|
style={{ ...style, opacity: isLight ? opacity : 0 }}
|
||||||
...style,
|
|
||||||
opacity: isLight ? opacity : 0,
|
|
||||||
}}
|
|
||||||
src={entity.url}
|
src={entity.url}
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { Carousel, Typography } from 'antd';
|
||||||
import { createStyles, css, useTheme } from 'antd-style';
|
import { createStyles, css, useTheme } from 'antd-style';
|
||||||
import { Typography, Carousel } from 'antd';
|
|
||||||
import { getCarouselStyle } from '../util';
|
import { getCarouselStyle } from '../util';
|
||||||
|
|
||||||
const useStyle = createStyles(() => {
|
const useStyle = createStyles(() => {
|
||||||
@ -18,6 +19,9 @@ const useStyle = createStyles(() => {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
`,
|
`,
|
||||||
|
img: css`
|
||||||
|
width: 100%;
|
||||||
|
`,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -75,7 +79,7 @@ export interface MobileCarouselProps {
|
|||||||
description?: React.ReactNode;
|
description?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function MobileCarousel(props: MobileCarouselProps) {
|
const MobileCarousel: React.FC<MobileCarouselProps> = (props) => {
|
||||||
const { styles } = useStyle();
|
const { styles } = useStyle();
|
||||||
const { id, title, description } = props;
|
const { id, title, description } = props;
|
||||||
const token = useTheme();
|
const token = useTheme();
|
||||||
@ -109,10 +113,12 @@ export default function MobileCarousel(props: MobileCarouselProps) {
|
|||||||
<Carousel className={styles.carousel} afterChange={setCurrentSlider}>
|
<Carousel className={styles.carousel} afterChange={setCurrentSlider}>
|
||||||
{mobileImageConfigList.map((item, index) => (
|
{mobileImageConfigList.map((item, index) => (
|
||||||
<div key={index}>
|
<div key={index}>
|
||||||
<img src={item.imageSrc} alt="" style={{ width: '100%' }} />
|
<img src={item.imageSrc} className={styles.img} alt="" />
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</Carousel>
|
</Carousel>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default MobileCarousel;
|
||||||
|
@ -85,7 +85,7 @@ const ThemePicker: React.FC<ThemePickerProps> = (props) => {
|
|||||||
const [locale] = useLocale(locales);
|
const [locale] = useLocale(locales);
|
||||||
return (
|
return (
|
||||||
<Flex gap="large" wrap="wrap">
|
<Flex gap="large" wrap="wrap">
|
||||||
{Object.keys(THEMES).map<React.ReactNode>((theme: THEME, index) => (
|
{(Object.keys(THEMES) as (keyof typeof THEMES)[]).map<React.ReactNode>((theme, index) => (
|
||||||
<Flex vertical gap="small" justify="center" align="center" key={theme}>
|
<Flex vertical gap="small" justify="center" align="center" key={theme}>
|
||||||
<label
|
<label
|
||||||
onClick={() => onChange?.(theme)}
|
onClick={() => onChange?.(theme)}
|
||||||
|
@ -7,7 +7,7 @@ import {
|
|||||||
QuestionCircleOutlined,
|
QuestionCircleOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { TinyColor } from '@ctrl/tinycolor';
|
import { TinyColor } from '@ctrl/tinycolor';
|
||||||
import type { MenuProps } from 'antd';
|
import type { MenuProps, ThemeConfig } from 'antd';
|
||||||
import {
|
import {
|
||||||
Breadcrumb,
|
Breadcrumb,
|
||||||
Button,
|
Button,
|
||||||
@ -21,7 +21,7 @@ import {
|
|||||||
theme,
|
theme,
|
||||||
Typography,
|
Typography,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import { createStyles, css, useTheme } from 'antd-style';
|
import { createStyles } from 'antd-style';
|
||||||
import type { Color } from 'antd/es/color-picker';
|
import type { Color } from 'antd/es/color-picker';
|
||||||
import { generateColor } from 'antd/es/color-picker/util';
|
import { generateColor } from 'antd/es/color-picker/util';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
@ -90,9 +90,8 @@ const locales = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// ============================= Style =============================
|
// ============================= Style =============================
|
||||||
const useStyle = createStyles(({ token, cx }) => {
|
const useStyle = createStyles(({ token, css, cx }) => {
|
||||||
const { carousel } = getCarouselStyle();
|
const { carousel } = getCarouselStyle();
|
||||||
|
|
||||||
const demo = css`
|
const demo = css`
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: rgba(240, 242, 245, 0.25);
|
background: rgba(240, 242, 245, 0.25);
|
||||||
@ -134,8 +133,6 @@ const useStyle = createStyles(({ token, cx }) => {
|
|||||||
margin-inline-start: auto;
|
margin-inline-start: auto;
|
||||||
`,
|
`,
|
||||||
|
|
||||||
darkSideMenu: css``,
|
|
||||||
|
|
||||||
header: css`
|
header: css`
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -169,7 +166,7 @@ const useStyle = createStyles(({ token, cx }) => {
|
|||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 16px;
|
font-size: ${token.fontSizeLG}px;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
@ -194,6 +191,40 @@ const useStyle = createStyles(({ token, cx }) => {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
`,
|
`,
|
||||||
|
pos: css`
|
||||||
|
position: absolute;
|
||||||
|
`,
|
||||||
|
leftTopImagePos: css`
|
||||||
|
left: 0;
|
||||||
|
top: -100px;
|
||||||
|
height: 500px;
|
||||||
|
`,
|
||||||
|
rightBottomPos: css`
|
||||||
|
right: 0;
|
||||||
|
bottom: -100px;
|
||||||
|
height: 287px;
|
||||||
|
`,
|
||||||
|
leftTopImage: css`
|
||||||
|
left: 50%;
|
||||||
|
transform: translate3d(-900px, 0, 0);
|
||||||
|
top: -100px;
|
||||||
|
height: 500px;
|
||||||
|
`,
|
||||||
|
rightBottomImage: css`
|
||||||
|
right: 50%;
|
||||||
|
transform: translate3d(750px, 0, 0);
|
||||||
|
bottom: -100px;
|
||||||
|
height: 287px;
|
||||||
|
`,
|
||||||
|
motion: css`
|
||||||
|
transition: all ${token.motionDurationSlow};
|
||||||
|
`,
|
||||||
|
op1: css`
|
||||||
|
opacity: 1;
|
||||||
|
`,
|
||||||
|
op0: css`
|
||||||
|
opacity: 0;
|
||||||
|
`,
|
||||||
carousel,
|
carousel,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -311,9 +342,8 @@ function rgbToColorMatrix(color: string) {
|
|||||||
return `invert(${invertValue}%) sepia(${sepiaValue}%) saturate(${saturateValue}%) hue-rotate(${hueRotateValue}deg)`;
|
return `invert(${invertValue}%) sepia(${sepiaValue}%) saturate(${saturateValue}%) hue-rotate(${hueRotateValue}deg)`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Theme() {
|
const Theme: React.FC = () => {
|
||||||
const { styles } = useStyle();
|
const { styles } = useStyle();
|
||||||
const token = useTheme();
|
|
||||||
const [locale, lang] = useLocale(locales);
|
const [locale, lang] = useLocale(locales);
|
||||||
const isZhCN = lang === 'cn';
|
const isZhCN = lang === 'cn';
|
||||||
const { search } = useLocation();
|
const { search } = useLocation();
|
||||||
@ -393,18 +423,12 @@ export default function Theme() {
|
|||||||
const logoColor = React.useMemo(() => {
|
const logoColor = React.useMemo(() => {
|
||||||
const hsb = generateColor(colorPrimaryValue).toHsb();
|
const hsb = generateColor(colorPrimaryValue).toHsb();
|
||||||
hsb.b = Math.min(hsb.b, 0.7);
|
hsb.b = Math.min(hsb.b, 0.7);
|
||||||
|
|
||||||
return generateColor(hsb).toHexString();
|
return generateColor(hsb).toHexString();
|
||||||
}, [colorPrimaryValue]);
|
}, [colorPrimaryValue]);
|
||||||
|
|
||||||
// ================================ Render ================================
|
const memoTheme = React.useMemo<ThemeConfig>(
|
||||||
const themeNode = (
|
() => ({
|
||||||
<ConfigProvider
|
token: { ...themeToken, colorPrimary: colorPrimaryValue },
|
||||||
theme={{
|
|
||||||
token: {
|
|
||||||
...themeToken,
|
|
||||||
colorPrimary: colorPrimaryValue,
|
|
||||||
},
|
|
||||||
algorithm: algorithmFn,
|
algorithm: algorithmFn,
|
||||||
components: {
|
components: {
|
||||||
Layout: isLight
|
Layout: isLight
|
||||||
@ -412,25 +436,23 @@ export default function Theme() {
|
|||||||
headerBg: 'transparent',
|
headerBg: 'transparent',
|
||||||
bodyBg: 'transparent',
|
bodyBg: 'transparent',
|
||||||
}
|
}
|
||||||
: {
|
: {},
|
||||||
// colorBgBody: 'transparent',
|
|
||||||
},
|
|
||||||
Menu: isLight
|
Menu: isLight
|
||||||
? {
|
? {
|
||||||
itemBg: 'transparent',
|
itemBg: 'transparent',
|
||||||
subMenuItemBg: 'transparent',
|
subMenuItemBg: 'transparent',
|
||||||
activeBarBorderWidth: 0,
|
activeBarBorderWidth: 0,
|
||||||
}
|
}
|
||||||
: {
|
: {},
|
||||||
// colorItemBg: 'transparent',
|
|
||||||
// colorSubItemBg: 'transparent',
|
|
||||||
// colorItemBgActive: 'rgba(255,255,255,0.2)',
|
|
||||||
// colorItemBgSelected: 'rgba(255,255,255,0.2)',
|
|
||||||
},
|
|
||||||
...(themeType === 'v4' ? defaultTheme.components : {}),
|
...(themeType === 'v4' ? defaultTheme.components : {}),
|
||||||
},
|
},
|
||||||
}}
|
}),
|
||||||
>
|
[themeToken, colorPrimaryValue, algorithmFn, themeType],
|
||||||
|
);
|
||||||
|
|
||||||
|
// ================================ Render ================================
|
||||||
|
const themeNode = (
|
||||||
|
<ConfigProvider theme={memoTheme}>
|
||||||
<TokenChecker />
|
<TokenChecker />
|
||||||
<div
|
<div
|
||||||
className={classNames(styles.demo, {
|
className={classNames(styles.demo, {
|
||||||
@ -450,10 +472,7 @@ export default function Theme() {
|
|||||||
src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
|
src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
|
||||||
style={{
|
style={{
|
||||||
filter:
|
filter:
|
||||||
closestColor === DEFAULT_COLOR
|
closestColor === DEFAULT_COLOR ? undefined : rgbToColorMatrix(logoColor),
|
||||||
? undefined
|
|
||||||
: // : `drop-shadow(30px 0 0 ${logoColor})`,
|
|
||||||
rgbToColorMatrix(logoColor),
|
|
||||||
}}
|
}}
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
@ -464,7 +483,7 @@ export default function Theme() {
|
|||||||
<BellOutlined />
|
<BellOutlined />
|
||||||
<QuestionCircleOutlined />
|
<QuestionCircleOutlined />
|
||||||
<div
|
<div
|
||||||
className={classNames(styles.avatar, themeType === 'dark' && styles.avatarDark)}
|
className={classNames(styles.avatar, { [styles.avatarDark]: themeType === 'dark' })}
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: avatarColor,
|
backgroundColor: avatarColor,
|
||||||
backgroundImage: `url(${getAvatarURL(closestColor)})`,
|
backgroundImage: `url(${getAvatarURL(closestColor)})`,
|
||||||
@ -473,10 +492,10 @@ export default function Theme() {
|
|||||||
</Flex>
|
</Flex>
|
||||||
</Header>
|
</Header>
|
||||||
<Layout className={styles.transBg} hasSider>
|
<Layout className={styles.transBg} hasSider>
|
||||||
<Sider className={classNames(styles.transBg, 'site-layout-background')} width={200}>
|
<Sider className={classNames(styles.transBg)} width={200}>
|
||||||
<Menu
|
<Menu
|
||||||
mode="inline"
|
mode="inline"
|
||||||
className={classNames(styles.transBg, !isLight && styles.darkSideMenu)}
|
className={classNames(styles.transBg)}
|
||||||
selectedKeys={['Themes']}
|
selectedKeys={['Themes']}
|
||||||
openKeys={['Design']}
|
openKeys={['Design']}
|
||||||
style={{ height: '100%', borderRight: 0 }}
|
style={{ height: '100%', borderRight: 0 }}
|
||||||
@ -521,7 +540,6 @@ export default function Theme() {
|
|||||||
<Form.Item label={locale.titleTheme} name="themeType">
|
<Form.Item label={locale.titleTheme} name="themeType">
|
||||||
<ThemePicker />
|
<ThemePicker />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item label={locale.titlePrimaryColor} name="colorPrimary">
|
<Form.Item label={locale.titlePrimaryColor} name="colorPrimary">
|
||||||
<ColorPicker />
|
<ColorPicker />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
@ -546,22 +564,6 @@ export default function Theme() {
|
|||||||
</ConfigProvider>
|
</ConfigProvider>
|
||||||
);
|
);
|
||||||
|
|
||||||
const posStyle: React.CSSProperties = {
|
|
||||||
position: 'absolute',
|
|
||||||
};
|
|
||||||
const leftTopImageStyle: React.CSSProperties = {
|
|
||||||
left: '50%',
|
|
||||||
transform: 'translate3d(-900px, 0, 0)',
|
|
||||||
top: -100,
|
|
||||||
height: 500,
|
|
||||||
};
|
|
||||||
const rightBottomImageStyle: React.CSSProperties = {
|
|
||||||
right: '50%',
|
|
||||||
transform: 'translate3d(750px, 0, 0)',
|
|
||||||
bottom: -100,
|
|
||||||
height: 287,
|
|
||||||
};
|
|
||||||
|
|
||||||
return isMobile ? (
|
return isMobile ? (
|
||||||
<MobileCarousel title={locale.themeTitle} description={locale.themeDesc} id="flexible" />
|
<MobileCarousel title={locale.themeTitle} description={locale.themeDesc} id="flexible" />
|
||||||
) : (
|
) : (
|
||||||
@ -576,52 +578,44 @@ export default function Theme() {
|
|||||||
<>
|
<>
|
||||||
{/* >>>>>> Default <<<<<< */}
|
{/* >>>>>> Default <<<<<< */}
|
||||||
<div
|
<div
|
||||||
style={{
|
className={classNames(
|
||||||
transition: `all ${token.motionDurationSlow}`,
|
styles.motion,
|
||||||
opacity: isLight && closestColor === DEFAULT_COLOR ? 1 : 0,
|
isLight && closestColor === DEFAULT_COLOR ? styles.op1 : styles.op0,
|
||||||
}}
|
)}
|
||||||
>
|
>
|
||||||
{/* Image Left Top */}
|
{/* Image Left Top */}
|
||||||
<img
|
<img
|
||||||
style={{
|
className={classNames(styles.pos, styles.leftTopImage)}
|
||||||
...posStyle,
|
|
||||||
...leftTopImageStyle,
|
|
||||||
}}
|
|
||||||
src="https://gw.alipayobjects.com/zos/bmw-prod/bd71b0c6-f93a-4e52-9c8a-f01a9b8fe22b.svg"
|
src="https://gw.alipayobjects.com/zos/bmw-prod/bd71b0c6-f93a-4e52-9c8a-f01a9b8fe22b.svg"
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
{/* Image Right Bottom */}
|
{/* Image Right Bottom */}
|
||||||
<img
|
<img
|
||||||
style={{
|
className={classNames(styles.pos, styles.rightBottomImage)}
|
||||||
...posStyle,
|
|
||||||
...rightBottomImageStyle,
|
|
||||||
}}
|
|
||||||
src="https://gw.alipayobjects.com/zos/bmw-prod/84ad805a-74cb-4916-b7ba-9cdc2bdec23a.svg"
|
src="https://gw.alipayobjects.com/zos/bmw-prod/84ad805a-74cb-4916-b7ba-9cdc2bdec23a.svg"
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* >>>>>> Dark <<<<<< */}
|
{/* >>>>>> Dark <<<<<< */}
|
||||||
<div
|
<div
|
||||||
style={{
|
className={classNames(
|
||||||
transition: `all ${token.motionDurationSlow}`,
|
styles.motion,
|
||||||
opacity: !isLight || !closestColor ? 1 : 0,
|
!isLight || !closestColor ? styles.op1 : styles.op0,
|
||||||
}}
|
)}
|
||||||
>
|
>
|
||||||
{/* Image Left Top */}
|
{/* Image Left Top */}
|
||||||
<img
|
<img
|
||||||
style={{ ...posStyle, left: 0, top: -100, height: 500 }}
|
className={classNames(styles.pos, styles.leftTopImagePos)}
|
||||||
src="https://gw.alipayobjects.com/zos/bmw-prod/a213184a-f212-4afb-beec-1e8b36bb4b8a.svg"
|
src="https://gw.alipayobjects.com/zos/bmw-prod/a213184a-f212-4afb-beec-1e8b36bb4b8a.svg"
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
{/* Image Right Bottom */}
|
{/* Image Right Bottom */}
|
||||||
<img
|
<img
|
||||||
style={{ ...posStyle, right: 0, bottom: -100, height: 287 }}
|
className={classNames(styles.pos, styles.rightBottomPos)}
|
||||||
src="https://gw.alipayobjects.com/zos/bmw-prod/bb74a2fb-bff1-4d0d-8c2d-2ade0cd9bb0d.svg"
|
src="https://gw.alipayobjects.com/zos/bmw-prod/bb74a2fb-bff1-4d0d-8c2d-2ade0cd9bb0d.svg"
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* >>>>>> Background Image <<<<<< */}
|
{/* >>>>>> Background Image <<<<<< */}
|
||||||
<BackgroundImage isLight={isLight} colorPrimary={colorPrimaryValue} />
|
<BackgroundImage isLight={isLight} colorPrimary={colorPrimaryValue} />
|
||||||
</>
|
</>
|
||||||
@ -630,4 +624,6 @@ export default function Theme() {
|
|||||||
{themeNode}
|
{themeNode}
|
||||||
</Group>
|
</Group>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default Theme;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { css } from 'antd-style';
|
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
import { css } from 'antd-style';
|
||||||
import fetch from 'cross-fetch';
|
import fetch from 'cross-fetch';
|
||||||
|
|
||||||
export interface Author {
|
export interface Author {
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { enUS, zhCN } from 'antd-token-previewer';
|
|
||||||
import { Helmet } from 'dumi';
|
|
||||||
import React, { Suspense, useEffect } from 'react';
|
import React, { Suspense, useEffect } from 'react';
|
||||||
import type { ThemeConfig } from 'antd/es/config-provider/context';
|
|
||||||
import { Button, message, Skeleton } from 'antd';
|
import { Button, message, Skeleton } from 'antd';
|
||||||
|
import { enUS, zhCN } from 'antd-token-previewer';
|
||||||
|
import type { ThemeConfig } from 'antd/es/config-provider/context';
|
||||||
|
import { Helmet } from 'dumi';
|
||||||
|
|
||||||
import useLocale from '../../hooks/useLocale';
|
import useLocale from '../../hooks/useLocale';
|
||||||
|
|
||||||
const ThemeEditor = React.lazy(() => import('antd-token-previewer/lib/ThemeEditor'));
|
const ThemeEditor = React.lazy(() => import('antd-token-previewer/lib/ThemeEditor'));
|
||||||
@ -34,7 +35,7 @@ const locales = {
|
|||||||
|
|
||||||
const ANT_DESIGN_V5_THEME_EDITOR_THEME = 'ant-design-v5-theme-editor-theme';
|
const ANT_DESIGN_V5_THEME_EDITOR_THEME = 'ant-design-v5-theme-editor-theme';
|
||||||
|
|
||||||
const CustomTheme = () => {
|
const CustomTheme: React.FC = () => {
|
||||||
const [messageApi, contextHolder] = message.useMessage();
|
const [messageApi, contextHolder] = message.useMessage();
|
||||||
const [locale, lang] = useLocale(locales);
|
const [locale, lang] = useLocale(locales);
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
import { unistUtilVisit, type HastRoot, type UnifiedTransformer } from 'dumi';
|
import type { HastRoot, UnifiedTransformer } from 'dumi';
|
||||||
|
import { unistUtilVisit } from 'dumi';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* plugin for modify hast tree when docs compiling
|
* plugin for modify hast tree when docs compiling
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { TinyColor, type ColorInput } from '@ctrl/tinycolor';
|
|
||||||
import { createStyles } from 'antd-style';
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import type { ColorInput } from '@ctrl/tinycolor';
|
||||||
|
import { TinyColor } from '@ctrl/tinycolor';
|
||||||
|
import { createStyles } from 'antd-style';
|
||||||
|
|
||||||
interface ColorChunkProps {
|
interface ColorChunkProps {
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
@ -20,7 +21,7 @@ const useStyle = createStyles(({ token, css }) => ({
|
|||||||
width: 6px;
|
width: 6px;
|
||||||
height: 6px;
|
height: 6px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
margin-inline-end: 4px;
|
margin-inline-end: ${token.marginXXS}px;
|
||||||
border: 1px solid ${token.colorSplit};
|
border: 1px solid ${token.colorSplit};
|
||||||
`,
|
`,
|
||||||
}));
|
}));
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { EditOutlined, GithubOutlined } from '@ant-design/icons';
|
import { EditOutlined, GithubOutlined } from '@ant-design/icons';
|
||||||
import { Descriptions, theme, Tooltip, Typography, type GetProp } from 'antd';
|
import type { GetProp } from 'antd';
|
||||||
|
import { Descriptions, theme, Tooltip, Typography } from 'antd';
|
||||||
import { createStyles, css } from 'antd-style';
|
import { createStyles, css } from 'antd-style';
|
||||||
import kebabCase from 'lodash/kebabCase';
|
import kebabCase from 'lodash/kebabCase';
|
||||||
import CopyToClipboard from 'react-copy-to-clipboard';
|
import CopyToClipboard from 'react-copy-to-clipboard';
|
||||||
@ -15,6 +16,7 @@ const locales = {
|
|||||||
source: '源码',
|
source: '源码',
|
||||||
docs: '文档',
|
docs: '文档',
|
||||||
edit: '编辑此页',
|
edit: '编辑此页',
|
||||||
|
version: '版本',
|
||||||
},
|
},
|
||||||
en: {
|
en: {
|
||||||
import: 'Import',
|
import: 'Import',
|
||||||
@ -23,28 +25,31 @@ const locales = {
|
|||||||
source: 'Source',
|
source: 'Source',
|
||||||
docs: 'Docs',
|
docs: 'Docs',
|
||||||
edit: 'Edit this page',
|
edit: 'Edit this page',
|
||||||
|
version: 'Version',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const branchUrl = 'https://github.com/ant-design/ant-design/edit/master/';
|
const branchUrl = 'https://github.com/ant-design/ant-design/edit/master/';
|
||||||
|
|
||||||
|
function isVersionNumber(value?: string) {
|
||||||
|
return value && /^\d+\.\d+\.\d+$/.test(value);
|
||||||
|
}
|
||||||
|
|
||||||
const useStyle = createStyles(({ token }) => ({
|
const useStyle = createStyles(({ token }) => ({
|
||||||
code: css`
|
code: css`
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
column-gap: 4px;
|
column-gap: ${token.paddingXXS}px;
|
||||||
border-radius: 4px;
|
border-radius: ${token.borderRadiusSM}px;
|
||||||
padding-inline: ${token.paddingXS}px;
|
padding-inline: ${token.paddingXS}px;
|
||||||
transition: all ${token.motionDurationSlow} !important;
|
transition: all ${token.motionDurationSlow} !important;
|
||||||
font-family: ${token.codeFamily};
|
font-family: ${token.codeFamily};
|
||||||
color: ${token.colorTextSecondary} !important;
|
color: ${token.colorTextSecondary} !important;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: ${token.controlItemBgHover};
|
background: ${token.controlItemBgHover};
|
||||||
}
|
}
|
||||||
|
|
||||||
a&:hover {
|
a&:hover {
|
||||||
text-decoration: underline !important;
|
text-decoration: underline !important;
|
||||||
}
|
}
|
||||||
@ -70,13 +75,14 @@ export interface ComponentMetaProps {
|
|||||||
component: string;
|
component: string;
|
||||||
source: string | true;
|
source: string | true;
|
||||||
filename?: string;
|
filename?: string;
|
||||||
|
version?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ComponentMeta: React.FC<ComponentMetaProps> = (props) => {
|
const ComponentMeta: React.FC<ComponentMetaProps> = (props) => {
|
||||||
const { component, source, filename } = props;
|
const { component, source, filename, version } = props;
|
||||||
const { token } = theme.useToken();
|
const { token } = theme.useToken();
|
||||||
const [locale] = useLocale(locales);
|
const [locale, lang] = useLocale(locales);
|
||||||
|
const isZhCN = lang === 'cn';
|
||||||
const { styles } = useStyle();
|
const { styles } = useStyle();
|
||||||
|
|
||||||
// ========================= Copy =========================
|
// ========================= Copy =========================
|
||||||
@ -175,7 +181,15 @@ const ComponentMeta: React.FC<ComponentMetaProps> = (props) => {
|
|||||||
</Typography.Link>
|
</Typography.Link>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
].filter((v) => v) as GetProp<typeof Descriptions, 'items'>
|
isVersionNumber(version) && {
|
||||||
|
label: locale.version,
|
||||||
|
children: (
|
||||||
|
<Typography.Text className={styles.code}>
|
||||||
|
{isZhCN ? `自 ${version} 后支持` : `supported since ${version}`}
|
||||||
|
</Typography.Text>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
].filter(Boolean) as GetProp<typeof Descriptions, 'items'>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -14,7 +14,7 @@ import proComponentsList from './ProComponentsList';
|
|||||||
|
|
||||||
const useStyle = createStyles(({ token, css }) => ({
|
const useStyle = createStyles(({ token, css }) => ({
|
||||||
componentsOverviewGroupTitle: css`
|
componentsOverviewGroupTitle: css`
|
||||||
margin-bottom: 24px !important;
|
margin-bottom: ${token.marginLG}px !important;
|
||||||
`,
|
`,
|
||||||
componentsOverviewTitle: css`
|
componentsOverviewTitle: css`
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -39,7 +39,7 @@ const useStyle = createStyles(({ token, css }) => ({
|
|||||||
`,
|
`,
|
||||||
componentsOverviewAffix: css`
|
componentsOverviewAffix: css`
|
||||||
display: flex;
|
display: flex;
|
||||||
transition: all 0.3s;
|
transition: all ${token.motionDurationSlow};
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
`,
|
`,
|
||||||
componentsOverviewSearch: css`
|
componentsOverviewSearch: css`
|
||||||
@ -52,7 +52,7 @@ const useStyle = createStyles(({ token, css }) => ({
|
|||||||
componentsOverviewContent: css`
|
componentsOverviewContent: css`
|
||||||
&:empty:after {
|
&:empty:after {
|
||||||
display: block;
|
display: block;
|
||||||
padding: 16px 0 40px;
|
padding: ${token.padding}px 0 ${token.paddingMD * 2}px;
|
||||||
color: ${token.colorTextDisabled};
|
color: ${token.colorTextDisabled};
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-bottom: 1px solid ${token.colorSplit};
|
border-bottom: 1px solid ${token.colorSplit};
|
||||||
|
@ -52,7 +52,7 @@ const locales = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const useStyle = createStyles(() => ({
|
const useStyle = createStyles(({ token }) => ({
|
||||||
tableTitle: css`
|
tableTitle: css`
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -62,15 +62,15 @@ const useStyle = createStyles(() => ({
|
|||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
`,
|
`,
|
||||||
arrowIcon: css`
|
arrowIcon: css`
|
||||||
font-size: 16px;
|
font-size: ${token.fontSizeLG}px;
|
||||||
margin-inline-end: 8px;
|
margin-inline-end: ${token.marginXS}px;
|
||||||
& svg {
|
& svg {
|
||||||
transition: all 0.3s;
|
transition: all ${token.motionDurationSlow};
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
help: css`
|
help: css`
|
||||||
margin-inline-start: 8px;
|
margin-inline-start: ${token.marginXS}px;
|
||||||
font-size: 12px;
|
font-size: ${token.fontSizeSM}px;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
color: #999;
|
color: #999;
|
||||||
a {
|
a {
|
||||||
@ -98,7 +98,7 @@ const SubTokenTable: React.FC<SubTokenTableProps> = (props) => {
|
|||||||
const token = useTheme();
|
const token = useTheme();
|
||||||
const columns = useColumns();
|
const columns = useColumns();
|
||||||
|
|
||||||
const [open, setOpen] = useState<boolean>(defaultOpen || process.env.NODE_ENV !== 'production');
|
const [open, setOpen] = useState<boolean>(defaultOpen ?? process.env.NODE_ENV !== 'production');
|
||||||
|
|
||||||
const { styles } = useStyle();
|
const { styles } = useStyle();
|
||||||
|
|
||||||
|
@ -2,8 +2,9 @@
|
|||||||
* copied: https://github.com/arvinxx/dumi-theme-antd-style/tree/master/src/builtins/Container
|
* copied: https://github.com/arvinxx/dumi-theme-antd-style/tree/master/src/builtins/Container
|
||||||
*/
|
*/
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import type { FC, ReactNode } from 'react';
|
||||||
import { Alert } from 'antd';
|
import { Alert } from 'antd';
|
||||||
import { type FC, type ReactNode } from 'react';
|
|
||||||
import useStyles from './style';
|
import useStyles from './style';
|
||||||
|
|
||||||
const Container: FC<{
|
const Container: FC<{
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { createStyles } from 'antd-style';
|
import { createStyles } from 'antd-style';
|
||||||
|
|
||||||
const useStyles = createStyles(({ prefixCls, css }) => ({
|
const useStyles = createStyles(({ token, prefixCls, css }) => ({
|
||||||
container: css`
|
container: css`
|
||||||
margin: 8px 0;
|
margin: ${token.marginXS}px 0;
|
||||||
`,
|
`,
|
||||||
|
|
||||||
alert: css`
|
alert: css`
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import React, { useContext } from 'react';
|
import React, { useContext } from 'react';
|
||||||
import { DumiDemoGrid, FormattedMessage } from 'dumi';
|
|
||||||
import {
|
import {
|
||||||
BugFilled,
|
BugFilled,
|
||||||
BugOutlined,
|
BugOutlined,
|
||||||
@ -8,11 +7,13 @@ import {
|
|||||||
ExperimentFilled,
|
ExperimentFilled,
|
||||||
ExperimentOutlined,
|
ExperimentOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import classNames from 'classnames';
|
|
||||||
import { ConfigProvider, Tooltip } from 'antd';
|
import { ConfigProvider, Tooltip } from 'antd';
|
||||||
import DemoContext from '../../slots/DemoContext';
|
import classNames from 'classnames';
|
||||||
|
import { DumiDemoGrid, FormattedMessage } from 'dumi';
|
||||||
|
|
||||||
import useLayoutState from '../../../hooks/useLayoutState';
|
import useLayoutState from '../../../hooks/useLayoutState';
|
||||||
import useLocale from '../../../hooks/useLocale';
|
import useLocale from '../../../hooks/useLocale';
|
||||||
|
import DemoContext from '../../slots/DemoContext';
|
||||||
|
|
||||||
const locales = {
|
const locales = {
|
||||||
cn: {
|
cn: {
|
||||||
@ -55,7 +56,9 @@ const DemoWrapper: typeof DumiDemoGrid = ({ items }) => {
|
|||||||
const { previewerProps } = item;
|
const { previewerProps } = item;
|
||||||
const { debug } = previewerProps;
|
const { debug } = previewerProps;
|
||||||
|
|
||||||
if (debug && !showDebug) return acc;
|
if (debug && !showDebug) {
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
|
||||||
return acc.concat({
|
return acc.concat({
|
||||||
...item,
|
...item,
|
||||||
@ -110,7 +113,7 @@ const DemoWrapper: typeof DumiDemoGrid = ({ items }) => {
|
|||||||
)}
|
)}
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</span>
|
</span>
|
||||||
<ConfigProvider theme={{ cssVar: enableCssVar }}>
|
<ConfigProvider theme={{ cssVar: enableCssVar, hashed: !enableCssVar }}>
|
||||||
<DumiDemoGrid items={demos} />
|
<DumiDemoGrid items={demos} />
|
||||||
</ConfigProvider>
|
</ConfigProvider>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import type { CSSProperties } from 'react';
|
import type { CSSProperties } from 'react';
|
||||||
import React, { useCallback, useMemo, useState } from 'react';
|
import React, { useCallback, useMemo, useState } from 'react';
|
||||||
import Icon, * as AntdIcons from '@ant-design/icons';
|
import Icon, * as AntdIcons from '@ant-design/icons';
|
||||||
|
import type { SegmentedProps } from 'antd';
|
||||||
|
import { Affix, Empty, Input, Segmented } from 'antd';
|
||||||
import { createStyles, useTheme } from 'antd-style';
|
import { createStyles, useTheme } from 'antd-style';
|
||||||
import { useIntl } from 'dumi';
|
import { useIntl } from 'dumi';
|
||||||
import debounce from 'lodash/debounce';
|
import debounce from 'lodash/debounce';
|
||||||
import type { SegmentedProps } from 'antd';
|
|
||||||
import { Affix, Empty, Input, Segmented } from 'antd';
|
|
||||||
import Category from './Category';
|
import Category from './Category';
|
||||||
import { FilledIcon, OutlinedIcon, TwoToneIcon } from './themeIcons';
|
|
||||||
import type { CategoriesKeys } from './fields';
|
import type { CategoriesKeys } from './fields';
|
||||||
import { categories } from './fields';
|
import { categories } from './fields';
|
||||||
|
import { FilledIcon, OutlinedIcon, TwoToneIcon } from './themeIcons';
|
||||||
|
|
||||||
export enum ThemeType {
|
export enum ThemeType {
|
||||||
Filled = 'Filled',
|
Filled = 'Filled',
|
||||||
@ -19,10 +20,10 @@ export enum ThemeType {
|
|||||||
|
|
||||||
const allIcons: { [key: string]: any } = AntdIcons;
|
const allIcons: { [key: string]: any } = AntdIcons;
|
||||||
|
|
||||||
const useStyle = createStyles(({ css }) => ({
|
const useStyle = createStyles(({ token, css }) => ({
|
||||||
iconSearchAffix: css`
|
iconSearchAffix: css`
|
||||||
display: flex;
|
display: flex;
|
||||||
transition: all 0.3s;
|
transition: all ${token.motionDurationSlow};
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
`,
|
`,
|
||||||
}));
|
}));
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import React, { Suspense } from 'react';
|
import React, { Suspense } from 'react';
|
||||||
import { createStyles } from 'antd-style';
|
|
||||||
import { Skeleton } from 'antd';
|
import { Skeleton } from 'antd';
|
||||||
|
import { createStyles } from 'antd-style';
|
||||||
|
|
||||||
const IconSearch = React.lazy(() => import('./IconSearch'));
|
const IconSearch = React.lazy(() => import('./IconSearch'));
|
||||||
|
|
||||||
const useStyle = createStyles(({ css }) => ({
|
const useStyle = createStyles(({ token, css }) => ({
|
||||||
searchWrapper: css`
|
searchWrapper: css`
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 16px;
|
gap: ${token.padding}px;
|
||||||
> *:first-child {
|
> *:first-child {
|
||||||
flex: 0 0 328px;
|
flex: 0 0 328px;
|
||||||
}
|
}
|
||||||
@ -21,7 +21,7 @@ const useStyle = createStyles(({ css }) => ({
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
> * {
|
> * {
|
||||||
flex: 0 0 15%;
|
flex: 0 0 15%;
|
||||||
margin: 3px 0;
|
margin: ${token.marginXXS}px 0;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
skeletonWrapper: css`
|
skeletonWrapper: css`
|
||||||
@ -33,7 +33,7 @@ const useStyle = createStyles(({ css }) => ({
|
|||||||
`,
|
`,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const IconSearchFallback = () => {
|
const IconSearchFallback: React.FC = () => {
|
||||||
const { styles } = useStyle();
|
const { styles } = useStyle();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
142
.dumi/theme/builtins/InstallDependencies/bun.tsx
Normal file
142
.dumi/theme/builtins/InstallDependencies/bun.tsx
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { createStyles, css } from 'antd-style';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
interface IconProps {
|
||||||
|
className?: string;
|
||||||
|
style?: React.CSSProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
const useStyle = createStyles(() => ({
|
||||||
|
iconWrap: css`
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
line-height: 0;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: -0.125em;
|
||||||
|
`,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const BunIcon: React.FC<IconProps> = (props) => {
|
||||||
|
const { className, style } = props;
|
||||||
|
const { styles } = useStyle();
|
||||||
|
return (
|
||||||
|
<span className={classNames(styles.iconWrap, className)} style={style}>
|
||||||
|
<svg id="Bun" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 70" width="1em" height="1em">
|
||||||
|
<title>Bun Logo</title>
|
||||||
|
<path
|
||||||
|
id="Shadow"
|
||||||
|
d="M71.09,20.74c-.16-.17-.33-.34-.5-.5s-.33-.34-.5-.5-.33-.34-.5-.5-.33-.34-.5-.5-.33-.34-.5-.5-.33-.34-.5-.5-.33-.34-.5-.5A26.46,26.46,0,0,1,75.5,35.7c0,16.57-16.82,30.05-37.5,30.05-11.58,0-21.94-4.23-28.83-10.86l.5.5.5.5.5.5.5.5.5.5.5.5.5.5C19.55,65.3,30.14,69.75,42,69.75c20.68,0,37.5-13.48,37.5-30C79.5,32.69,76.46,26,71.09,20.74Z"
|
||||||
|
/>
|
||||||
|
<g id="Body">
|
||||||
|
<path
|
||||||
|
id="Background"
|
||||||
|
d="M73,35.7c0,15.21-15.67,27.54-35,27.54S3,50.91,3,35.7C3,26.27,9,17.94,18.22,13S33.18,3,38,3s8.94,4.13,19.78,10C67,17.94,73,26.27,73,35.7Z"
|
||||||
|
style={{
|
||||||
|
fill: '#fbf0df',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
id="Bottom_Shadow"
|
||||||
|
data-name="Bottom Shadow"
|
||||||
|
d="M73,35.7a21.67,21.67,0,0,0-.8-5.78c-2.73,33.3-43.35,34.9-59.32,24.94A40,40,0,0,0,38,63.24C57.3,63.24,73,50.89,73,35.7Z"
|
||||||
|
style={{
|
||||||
|
fill: '#f6dece',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
id="Light_Shine"
|
||||||
|
data-name="Light Shine"
|
||||||
|
d="M24.53,11.17C29,8.49,34.94,3.46,40.78,3.45A9.29,9.29,0,0,0,38,3c-2.42,0-5,1.25-8.25,3.13-1.13.66-2.3,1.39-3.54,2.15-2.33,1.44-5,3.07-8,4.7C8.69,18.13,3,26.62,3,35.7c0,.4,0,.8,0,1.19C9.06,15.48,20.07,13.85,24.53,11.17Z"
|
||||||
|
style={{
|
||||||
|
fill: '#fffefc',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
id="Top"
|
||||||
|
d="M35.12,5.53A16.41,16.41,0,0,1,29.49,18c-.28.25-.06.73.3.59,3.37-1.31,7.92-5.23,6-13.14C35.71,5,35.12,5.12,35.12,5.53Zm2.27,0A16.24,16.24,0,0,1,39,19c-.12.35.31.65.55.36C41.74,16.56,43.65,11,37.93,5,37.64,4.74,37.19,5.14,37.39,5.49Zm2.76-.17A16.42,16.42,0,0,1,47,17.12a.33.33,0,0,0,.65.11c.92-3.49.4-9.44-7.17-12.53C40.08,4.54,39.82,5.08,40.15,5.32ZM21.69,15.76a16.94,16.94,0,0,0,10.47-9c.18-.36.75-.22.66.18-1.73,8-7.52,9.67-11.12,9.45C21.32,16.4,21.33,15.87,21.69,15.76Z"
|
||||||
|
style={{
|
||||||
|
fill: '#ccbea7',
|
||||||
|
fillRule: 'evenodd',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
id="Outline"
|
||||||
|
d="M38,65.75C17.32,65.75.5,52.27.5,35.7c0-10,6.18-19.33,16.53-24.92,3-1.6,5.57-3.21,7.86-4.62,1.26-.78,2.45-1.51,3.6-2.19C32,1.89,35,.5,38,.5s5.62,1.2,8.9,3.14c1,.57,2,1.19,3.07,1.87,2.49,1.54,5.3,3.28,9,5.27C69.32,16.37,75.5,25.69,75.5,35.7,75.5,52.27,58.68,65.75,38,65.75ZM38,3c-2.42,0-5,1.25-8.25,3.13-1.13.66-2.3,1.39-3.54,2.15-2.33,1.44-5,3.07-8,4.7C8.69,18.13,3,26.62,3,35.7,3,50.89,18.7,63.25,38,63.25S73,50.89,73,35.7C73,26.62,67.31,18.13,57.78,13,54,11,51.05,9.12,48.66,7.64c-1.09-.67-2.09-1.29-3-1.84C42.63,4,40.42,3,38,3Z"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
<g id="Mouth">
|
||||||
|
<g id="Background-2" data-name="Background">
|
||||||
|
<path
|
||||||
|
d="M45.05,43a8.93,8.93,0,0,1-2.92,4.71,6.81,6.81,0,0,1-4,1.88A6.84,6.84,0,0,1,34,47.71,8.93,8.93,0,0,1,31.12,43a.72.72,0,0,1,.8-.81H44.26A.72.72,0,0,1,45.05,43Z"
|
||||||
|
style={{
|
||||||
|
fill: '#b71422',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
<g id="Tongue">
|
||||||
|
<path
|
||||||
|
id="Background-3"
|
||||||
|
data-name="Background"
|
||||||
|
d="M34,47.79a6.91,6.91,0,0,0,4.12,1.9,6.91,6.91,0,0,0,4.11-1.9,10.63,10.63,0,0,0,1-1.07,6.83,6.83,0,0,0-4.9-2.31,6.15,6.15,0,0,0-5,2.78C33.56,47.4,33.76,47.6,34,47.79Z"
|
||||||
|
style={{
|
||||||
|
fill: '#ff6164',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
id="Outline-2"
|
||||||
|
data-name="Outline"
|
||||||
|
d="M34.16,47a5.36,5.36,0,0,1,4.19-2.08,6,6,0,0,1,4,1.69c.23-.25.45-.51.66-.77a7,7,0,0,0-4.71-1.93,6.36,6.36,0,0,0-4.89,2.36A9.53,9.53,0,0,0,34.16,47Z"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
id="Outline-3"
|
||||||
|
data-name="Outline"
|
||||||
|
d="M38.09,50.19a7.42,7.42,0,0,1-4.45-2,9.52,9.52,0,0,1-3.11-5.05,1.2,1.2,0,0,1,.26-1,1.41,1.41,0,0,1,1.13-.51H44.26a1.44,1.44,0,0,1,1.13.51,1.19,1.19,0,0,1,.25,1h0a9.52,9.52,0,0,1-3.11,5.05A7.42,7.42,0,0,1,38.09,50.19Zm-6.17-7.4c-.16,0-.2.07-.21.09a8.29,8.29,0,0,0,2.73,4.37A6.23,6.23,0,0,0,38.09,49a6.28,6.28,0,0,0,3.65-1.73,8.3,8.3,0,0,0,2.72-4.37.21.21,0,0,0-.2-.09Z"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
<g id="Face">
|
||||||
|
<ellipse
|
||||||
|
id="Right_Blush"
|
||||||
|
data-name="Right Blush"
|
||||||
|
cx="53.22"
|
||||||
|
cy="40.18"
|
||||||
|
rx="5.85"
|
||||||
|
ry="3.44"
|
||||||
|
style={{
|
||||||
|
fill: '#febbd0',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ellipse
|
||||||
|
id="Left_Bluch"
|
||||||
|
data-name="Left Bluch"
|
||||||
|
cx="22.95"
|
||||||
|
cy="40.18"
|
||||||
|
rx="5.85"
|
||||||
|
ry="3.44"
|
||||||
|
style={{
|
||||||
|
fill: '#febbd0',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
id="Eyes"
|
||||||
|
d="M25.7,38.8a5.51,5.51,0,1,0-5.5-5.51A5.51,5.51,0,0,0,25.7,38.8Zm24.77,0A5.51,5.51,0,1,0,45,33.29,5.5,5.5,0,0,0,50.47,38.8Z"
|
||||||
|
style={{
|
||||||
|
fillRule: 'evenodd',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
id="Iris"
|
||||||
|
d="M24,33.64a2.07,2.07,0,1,0-2.06-2.07A2.07,2.07,0,0,0,24,33.64Zm24.77,0a2.07,2.07,0,1,0-2.06-2.07A2.07,2.07,0,0,0,48.75,33.64Z"
|
||||||
|
style={{
|
||||||
|
fill: '#fff',
|
||||||
|
fillRule: 'evenodd',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BunIcon;
|
@ -6,15 +6,17 @@ 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';
|
||||||
|
import BunLogo from './bun';
|
||||||
|
|
||||||
interface InstallProps {
|
interface InstallProps {
|
||||||
npm?: string;
|
npm?: string;
|
||||||
yarn?: string;
|
yarn?: string;
|
||||||
pnpm?: string;
|
pnpm?: string;
|
||||||
|
bun?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const InstallDependencies: React.FC<InstallProps> = (props) => {
|
const InstallDependencies: React.FC<InstallProps> = (props) => {
|
||||||
const { npm, yarn, pnpm } = props;
|
const { npm, yarn, pnpm, bun } = props;
|
||||||
const items: Tab[] = [
|
const items: Tab[] = [
|
||||||
{
|
{
|
||||||
key: 'npm',
|
key: 'npm',
|
||||||
@ -34,6 +36,12 @@ const InstallDependencies: React.FC<InstallProps> = (props) => {
|
|||||||
children: pnpm ? <SourceCode lang="bash">{pnpm}</SourceCode> : null,
|
children: pnpm ? <SourceCode lang="bash">{pnpm}</SourceCode> : null,
|
||||||
icon: <PnpmLogo />,
|
icon: <PnpmLogo />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'bun',
|
||||||
|
label: 'Bun',
|
||||||
|
children: bun ? <SourceCode lang="bash">{bun}</SourceCode> : null,
|
||||||
|
icon: <BunLogo />,
|
||||||
|
},
|
||||||
].filter((item) => item.children);
|
].filter((item) => item.children);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Link } from 'dumi';
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { Link } from 'dumi';
|
||||||
|
|
||||||
import useLocale from '../../../hooks/useLocale';
|
import useLocale from '../../../hooks/useLocale';
|
||||||
|
|
||||||
type LinkProps = Parameters<typeof Link>[0];
|
type LinkProps = Parameters<typeof Link>[0];
|
||||||
@ -9,7 +10,7 @@ export interface LocaleLinkProps extends LinkProps {
|
|||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function LocaleLink({ sourceType, to, ...props }: LocaleLinkProps) {
|
const LocaleLink: React.FC<LocaleLinkProps> = ({ sourceType, to, ...props }) => {
|
||||||
const Component = sourceType === 'a' ? 'a' : Link;
|
const Component = sourceType === 'a' ? 'a' : Link;
|
||||||
|
|
||||||
const [, localeType] = useLocale();
|
const [, localeType] = useLocale();
|
||||||
@ -46,4 +47,6 @@ export default function LocaleLink({ sourceType, to, ...props }: LocaleLinkProps
|
|||||||
}
|
}
|
||||||
|
|
||||||
return <Component {...linkProps} />;
|
return <Component {...linkProps} />;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default LocaleLink;
|
||||||
|
@ -75,14 +75,14 @@ const useStyle = createStyles(({ token }) => {
|
|||||||
border-radius: 0 0 ${borderRadius}px ${borderRadius}px;
|
border-radius: 0 0 ${borderRadius}px ${borderRadius}px;
|
||||||
border-top: 1px solid ${token.colorSplit};
|
border-top: 1px solid ${token.colorSplit};
|
||||||
color: ${token.colorTextSecondary};
|
color: ${token.colorTextSecondary};
|
||||||
transition: all 0.2s ease-in-out;
|
transition: all ${token.motionDurationMid} ease-in-out;
|
||||||
background-color: ${token.colorBgElevated};
|
background-color: ${token.colorBgElevated};
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
&:hover {
|
&:hover {
|
||||||
color: ${token.colorPrimary};
|
color: ${token.colorPrimary};
|
||||||
}
|
}
|
||||||
span {
|
span {
|
||||||
margin-right: ${token.marginXXS}px;
|
margin-inline-end: ${token.marginXXS}px;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
@ -108,7 +108,7 @@ const CodePreviewer: React.FC<AntdPreviewerProps> = (props) => {
|
|||||||
clientOnly,
|
clientOnly,
|
||||||
pkgDependencyList,
|
pkgDependencyList,
|
||||||
} = props;
|
} = props;
|
||||||
const { showDebug } = useContext(DemoContext);
|
const { showDebug, codeType } = useContext(DemoContext);
|
||||||
|
|
||||||
const { pkg } = useSiteData();
|
const { pkg } = useSiteData();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
@ -134,7 +134,6 @@ const CodePreviewer: React.FC<AntdPreviewerProps> = (props) => {
|
|||||||
const riddleIconRef = useRef<HTMLFormElement>(null);
|
const riddleIconRef = useRef<HTMLFormElement>(null);
|
||||||
const codepenIconRef = useRef<HTMLFormElement>(null);
|
const codepenIconRef = useRef<HTMLFormElement>(null);
|
||||||
const [codeExpand, setCodeExpand] = useState<boolean>(false);
|
const [codeExpand, setCodeExpand] = useState<boolean>(false);
|
||||||
const [codeType, setCodeType] = useState<string>('tsx');
|
|
||||||
const { theme } = useContext<SiteContextProps>(SiteContext);
|
const { theme } = useContext<SiteContextProps>(SiteContext);
|
||||||
|
|
||||||
const { hash, pathname, search } = location;
|
const { hash, pathname, search } = location;
|
||||||
@ -541,7 +540,6 @@ createRoot(document.getElementById('container')).render(<Demo />);
|
|||||||
styleCode={style}
|
styleCode={style}
|
||||||
error={liveDemoError}
|
error={liveDemoError}
|
||||||
entryName={entryName}
|
entryName={entryName}
|
||||||
onCodeTypeChange={setCodeType}
|
|
||||||
onSourceChange={setLiveDemoSource}
|
onSourceChange={setLiveDemoSource}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
|
@ -10,10 +10,10 @@ import type { AntdPreviewerProps } from './Previewer';
|
|||||||
|
|
||||||
const useStyle = createStyles(({ token, css }) => ({
|
const useStyle = createStyles(({ token, css }) => ({
|
||||||
wrapper: css`
|
wrapper: css`
|
||||||
|
position: relative;
|
||||||
border: 1px solid ${token.colorBorderSecondary};
|
border: 1px solid ${token.colorBorderSecondary};
|
||||||
border-radius: ${token.borderRadius}px;
|
border-radius: ${token.borderRadius}px;
|
||||||
padding: 20px 24px 40px;
|
padding: ${token.paddingMD}px ${token.paddingLG}px ${token.paddingMD * 2}px;
|
||||||
position: relative;
|
|
||||||
margin-bottom: ${token.marginLG}px;
|
margin-bottom: ${token.marginLG}px;
|
||||||
`,
|
`,
|
||||||
title: css`
|
title: css`
|
||||||
@ -35,8 +35,8 @@ const useStyle = createStyles(({ token, css }) => ({
|
|||||||
`,
|
`,
|
||||||
copy: css`
|
copy: css`
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset-inline-end: 20px;
|
inset-inline-end: ${token.paddingMD}px;
|
||||||
inset-block-start: 20px;
|
inset-block-start: ${token.paddingMD}px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
`,
|
`,
|
||||||
copyTip: css`
|
copyTip: css`
|
||||||
@ -49,7 +49,7 @@ const useStyle = createStyles(({ token, css }) => ({
|
|||||||
`,
|
`,
|
||||||
tip: css`
|
tip: css`
|
||||||
color: ${token.colorTextTertiary};
|
color: ${token.colorTextTertiary};
|
||||||
margin-top: 40px;
|
margin-top: ${token.marginMD * 2}px;
|
||||||
`,
|
`,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -86,12 +86,12 @@ const DesignPreviewer: FC<AntdPreviewerProps> = ({ children, title, description,
|
|||||||
{copied ? (
|
{copied ? (
|
||||||
<div className={styles.copiedTip}>
|
<div className={styles.copiedTip}>
|
||||||
<CheckOutlined />
|
<CheckOutlined />
|
||||||
<span style={{ marginLeft: 8 }}>已复制,使用 Kitchen 插件即可粘贴</span>
|
<span style={{ marginInlineStart: 8 }}>已复制,使用 Kitchen 插件即可粘贴</span>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div onClick={handleCopy} className={styles.copyTip}>
|
<div onClick={handleCopy} className={styles.copyTip}>
|
||||||
<SketchOutlined />
|
<SketchOutlined />
|
||||||
<span style={{ marginLeft: 8 }}>复制 Sketch JSON</span>
|
<span style={{ marginInlineStart: 8 }}>复制 Sketch JSON</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,12 +7,12 @@ const { ErrorBoundary } = Alert;
|
|||||||
|
|
||||||
const Previewer = React.lazy(() => import('./Previewer'));
|
const Previewer = React.lazy(() => import('./Previewer'));
|
||||||
|
|
||||||
const useStyle = createStyles(({ css }) => ({
|
const useStyle = createStyles(({ token, css }) => ({
|
||||||
skeletonWrapper: css`
|
skeletonWrapper: css`
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
height: 250px;
|
height: 250px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: ${token.margin}px;
|
||||||
border-radius: 8px;
|
border-radius: ${token.borderRadiusLG}px;
|
||||||
`,
|
`,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
/* 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 { Avatar, Divider, Empty, Skeleton, Tabs } from 'antd';
|
||||||
|
import { createStyles } from 'antd-style';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { FormattedMessage } from 'dumi';
|
import { FormattedMessage } from 'dumi';
|
||||||
import { createStyles } from 'antd-style';
|
|
||||||
import { Avatar, Divider, Empty, Skeleton, Tabs } from 'antd';
|
import useLocale from '../../../hooks/useLocale';
|
||||||
import type { Article, Authors, SiteData } 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';
|
|
||||||
|
|
||||||
const useStyle = createStyles(({ token, css }) => {
|
const useStyle = createStyles(({ token, css }) => {
|
||||||
const { antCls } = token;
|
const { antCls } = token;
|
||||||
@ -16,7 +17,7 @@ const useStyle = createStyles(({ token, css }) => {
|
|||||||
h4 {
|
h4 {
|
||||||
margin: 40px 0 24px;
|
margin: 40px 0 24px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 20px;
|
font-size: ${token.fontSizeXL}px;
|
||||||
}
|
}
|
||||||
|
|
||||||
${antCls}-skeleton {
|
${antCls}-skeleton {
|
||||||
@ -26,7 +27,7 @@ const useStyle = createStyles(({ token, css }) => {
|
|||||||
|
|
||||||
ul li {
|
ul li {
|
||||||
display: block;
|
display: block;
|
||||||
margin-left: 0;
|
margin-inline-start: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +45,7 @@ const useStyle = createStyles(({ token, css }) => {
|
|||||||
li {
|
li {
|
||||||
margin: 1em 0;
|
margin: 1em 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
font-size: 14px;
|
font-size: ${token.fontSize}px;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
@ -1,65 +1,41 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { createStyles } from 'antd-style';
|
|
||||||
import { ExclamationCircleOutlined } from '@ant-design/icons';
|
import { ExclamationCircleOutlined } from '@ant-design/icons';
|
||||||
import { Col, Row, Tooltip } from 'antd';
|
import { Col, Row, Tooltip, Card, Typography } from 'antd';
|
||||||
|
import { createStyles } from 'antd-style';
|
||||||
import useLocale from '../../../hooks/useLocale';
|
import useLocale from '../../../hooks/useLocale';
|
||||||
|
|
||||||
const useStyle = createStyles(({ token, css }) => {
|
const { Paragraph } = Typography;
|
||||||
const { boxShadowSecondary } = token;
|
|
||||||
|
|
||||||
return {
|
const useStyle = createStyles(({ token, css }) => ({
|
||||||
card: css`
|
card: css`
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
overflow: hidden;
|
||||||
flex-direction: column;
|
|
||||||
height: 100%;
|
|
||||||
color: inherit;
|
|
||||||
list-style: none;
|
|
||||||
border: 1px solid ${token.colorSplit};
|
|
||||||
border-radius: 2px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: box-shadow 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
.ant-card-cover {
|
||||||
box-shadow: ${boxShadowSecondary};
|
overflow: hidden;
|
||||||
color: inherit;
|
|
||||||
}
|
}
|
||||||
`,
|
img {
|
||||||
image: css`
|
transition: all ${token.motionDurationSlow} ease-out;
|
||||||
width: calc(100% + 2px);
|
}
|
||||||
max-width: none;
|
|
||||||
height: 184px;
|
&:hover img {
|
||||||
margin: -1px -1px 0;
|
transform: scale(1.3);
|
||||||
object-fit: cover;
|
|
||||||
`,
|
`,
|
||||||
badge: css`
|
badge: css`
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 8px;
|
top: 8px;
|
||||||
right: 8px;
|
right: 8px;
|
||||||
padding: 4px 8px;
|
padding: ${token.paddingXXS}px ${token.paddingXS}px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 12px;
|
font-size: ${token.fontSizeSM}px;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
background: rgba(0, 0, 0, 0.65);
|
background: rgba(0, 0, 0, 0.65);
|
||||||
border-radius: 1px;
|
border-radius: ${token.borderRadiusLG}px;
|
||||||
box-shadow: 0 0 2px rgba(255, 255, 255, 0.2);
|
box-shadow: 0 0 2px rgba(255, 255, 255, 0.2);
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
column-gap: 4px;
|
column-gap: ${token.paddingXXS}px;
|
||||||
`,
|
`,
|
||||||
title: css`
|
}));
|
||||||
margin: 16px 20px 8px;
|
|
||||||
opacity: 0.85;
|
|
||||||
font-size: 20px;
|
|
||||||
line-height: 28px;
|
|
||||||
`,
|
|
||||||
description: css`
|
|
||||||
margin: 0 20px 20px;
|
|
||||||
opacity: 0.65;
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 22px;
|
|
||||||
`,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
export type Resource = {
|
export type Resource = {
|
||||||
title: string;
|
title: string;
|
||||||
@ -90,27 +66,9 @@ const ResourceCard: React.FC<ResourceCardProps> = ({ resource }) => {
|
|||||||
const { styles } = useStyle();
|
const { styles } = useStyle();
|
||||||
const [locale] = useLocale(locales);
|
const [locale] = useLocale(locales);
|
||||||
|
|
||||||
const { title: titleStr, description, cover, src, official } = resource;
|
const { title, description, cover, src, official } = resource;
|
||||||
|
|
||||||
let coverColor: string | null = null;
|
const badge = official ? (
|
||||||
let title: string = titleStr;
|
|
||||||
const titleMatch = titleStr.match(/(.*)(#[\dA-Fa-f]{6})/);
|
|
||||||
if (titleMatch) {
|
|
||||||
title = titleMatch[1].trim();
|
|
||||||
// eslint-disable-next-line prefer-destructuring
|
|
||||||
coverColor = titleMatch[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Col xs={24} sm={12} md={8} lg={6} style={{ padding: 12 }}>
|
|
||||||
<a className={styles.card} target="_blank" href={src} rel="noreferrer">
|
|
||||||
<img
|
|
||||||
className={styles.image}
|
|
||||||
src={cover}
|
|
||||||
alt={title}
|
|
||||||
style={coverColor ? { backgroundColor: coverColor } : {}}
|
|
||||||
/>
|
|
||||||
{official ? (
|
|
||||||
<div className={styles.badge}>{locale.official}</div>
|
<div className={styles.badge}>{locale.official}</div>
|
||||||
) : (
|
) : (
|
||||||
<Tooltip title={locale.thirdPartDesc}>
|
<Tooltip title={locale.thirdPartDesc}>
|
||||||
@ -119,9 +77,22 @@ const ResourceCard: React.FC<ResourceCardProps> = ({ resource }) => {
|
|||||||
{locale.thirdPart}
|
{locale.thirdPart}
|
||||||
</div>
|
</div>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
);
|
||||||
<p className={styles?.title}>{title}</p>
|
|
||||||
<p className={styles.description}>{description}</p>
|
return (
|
||||||
|
<Col xs={24} sm={12} md={8} lg={6}>
|
||||||
|
<a className={styles.card} target="_blank" href={src} rel="noreferrer">
|
||||||
|
<Card hoverable className={styles.card} cover={<img src={cover} alt={title} />}>
|
||||||
|
<Card.Meta
|
||||||
|
title={title}
|
||||||
|
description={
|
||||||
|
<Paragraph style={{ marginBottom: 0 }} ellipsis={{ rows: 1 }} title={description}>
|
||||||
|
{description}
|
||||||
|
</Paragraph>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{badge}
|
||||||
|
</Card>
|
||||||
</a>
|
</a>
|
||||||
</Col>
|
</Col>
|
||||||
);
|
);
|
||||||
@ -132,7 +103,7 @@ export type ResourceCardsProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const ResourceCards: React.FC<ResourceCardsProps> = ({ resources }) => (
|
const ResourceCards: React.FC<ResourceCardsProps> = ({ resources }) => (
|
||||||
<Row style={{ margin: '-12px -12px 0 -12px' }}>
|
<Row gutter={[24, 24]}>
|
||||||
{resources.map((item) => (
|
{resources.map((item) => (
|
||||||
<ResourceCard resource={item} key={item?.title} />
|
<ResourceCard resource={item} key={item?.title} />
|
||||||
))}
|
))}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import type { FC, ReactNode } from 'react';
|
import type { FC, ReactNode } from 'react';
|
||||||
import React, { Suspense } from 'react';
|
import React, { Suspense } from 'react';
|
||||||
import { useSearchParams } from 'dumi';
|
|
||||||
import { createStyles } from 'antd-style';
|
|
||||||
import { Skeleton } from 'antd';
|
import { Skeleton } from 'antd';
|
||||||
|
import { createStyles } from 'antd-style';
|
||||||
|
import { useSearchParams } from 'dumi';
|
||||||
|
|
||||||
const OriginSandpack = React.lazy(() => import('./Sandpack'));
|
const OriginSandpack = React.lazy(() => import('./Sandpack'));
|
||||||
|
|
||||||
@ -20,12 +20,12 @@ const useStyle = createStyles(({ token, css }) => ({
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
> * {
|
> * {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
border-radius: 8px;
|
border-radius: ${token.borderRadiusLG}px;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
placeholder: css`
|
placeholder: css`
|
||||||
color: ${token.colorTextDescription};
|
color: ${token.colorTextDescription};
|
||||||
font-size: 16px;
|
font-size: ${token.fontSizeLG}px;
|
||||||
`,
|
`,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -41,12 +41,12 @@ const SandpackFallback = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
type SandpackProps = {
|
interface SandpackProps {
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
dark?: boolean;
|
dark?: boolean;
|
||||||
autorun?: boolean;
|
autorun?: boolean;
|
||||||
dependencies?: string;
|
dependencies?: string;
|
||||||
};
|
}
|
||||||
|
|
||||||
const Sandpack: FC<SandpackProps> = ({
|
const Sandpack: FC<SandpackProps> = ({
|
||||||
children,
|
children,
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import type { TableProps } from 'antd';
|
||||||
|
import { Table } from 'antd';
|
||||||
import { createStyles } from 'antd-style';
|
import { createStyles } from 'antd-style';
|
||||||
import { getDesignToken } from 'antd-token-previewer';
|
import { getDesignToken } from 'antd-token-previewer';
|
||||||
import tokenMeta from 'antd/es/version/token-meta.json';
|
import tokenMeta from 'antd/es/version/token-meta.json';
|
||||||
import type { TableProps } from 'antd';
|
|
||||||
import { Table } from 'antd';
|
|
||||||
import useLocale from '../../../hooks/useLocale';
|
import useLocale from '../../../hooks/useLocale';
|
||||||
import ColorChunk from '../ColorChunk';
|
import ColorChunk from '../ColorChunk';
|
||||||
|
|
||||||
@ -44,7 +45,7 @@ const useStyle = createStyles(({ token, css }) => ({
|
|||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
background: ${token.siteMarkdownCodeBg};
|
background: ${token.siteMarkdownCodeBg};
|
||||||
border: 1px solid ${token.colorSplit};
|
border: 1px solid ${token.colorSplit};
|
||||||
border-radius: 3px;
|
border-radius: ${token.borderRadiusSM}px;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
`,
|
`,
|
||||||
}));
|
}));
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { PauseCircleFilled, PlayCircleFilled } from '@ant-design/icons';
|
||||||
import { createStyles, css } from 'antd-style';
|
import { createStyles, css } from 'antd-style';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { PlayCircleFilled, PauseCircleFilled } from '@ant-design/icons';
|
|
||||||
|
|
||||||
const useStyles = createStyles(({ cx, token }) => {
|
const useStyles = createStyles(({ cx, token }) => {
|
||||||
const play = css`
|
const play = css`
|
||||||
@ -41,10 +41,10 @@ const useStyles = createStyles(({ cx, token }) => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
export default function VideoPlayer({
|
const VideoPlayer: React.FC<React.HtmlHTMLAttributes<HTMLVideoElement>> = ({
|
||||||
className,
|
className,
|
||||||
...restProps
|
...restProps
|
||||||
}: React.HtmlHTMLAttributes<HTMLVideoElement>) {
|
}) => {
|
||||||
const { styles } = useStyles();
|
const { styles } = useStyles();
|
||||||
const videoRef = React.useRef<HTMLVideoElement>(null);
|
const videoRef = React.useRef<HTMLVideoElement>(null);
|
||||||
const [playing, setPlaying] = React.useState(false);
|
const [playing, setPlaying] = React.useState(false);
|
||||||
@ -69,9 +69,10 @@ export default function VideoPlayer({
|
|||||||
>
|
>
|
||||||
<div className={classNames(styles.holder)}>
|
<div className={classNames(styles.holder)}>
|
||||||
<video ref={videoRef} className={styles.video} muted loop {...restProps} />
|
<video ref={videoRef} className={styles.video} muted loop {...restProps} />
|
||||||
|
|
||||||
<div className={styles.play}>{playing ? <PauseCircleFilled /> : <PlayCircleFilled />}</div>
|
<div className={styles.play}>{playing ? <PauseCircleFilled /> : <PlayCircleFilled />}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default VideoPlayer;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
import React, { useEffect, useRef } from 'react';
|
||||||
import G6 from '@antv/g6';
|
import G6 from '@antv/g6';
|
||||||
import { createStyles, css } from 'antd-style';
|
import { createStyles, css } from 'antd-style';
|
||||||
import { useRouteMeta } from 'dumi';
|
import { useRouteMeta } from 'dumi';
|
||||||
import React, { useEffect, useRef } from 'react';
|
|
||||||
|
|
||||||
G6.registerNode('behavior-start-node', {
|
G6.registerNode('behavior-start-node', {
|
||||||
draw: (cfg, group) => {
|
draw: (cfg, group) => {
|
||||||
@ -214,13 +214,13 @@ type BehaviorMapItem = {
|
|||||||
link?: string;
|
link?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const useStyle = createStyles(() => ({
|
const useStyle = createStyles(({ token }) => ({
|
||||||
container: css`
|
container: css`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 600px;
|
height: 600px;
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
border: 1px solid #e8e8e8;
|
border: 1px solid #e8e8e8;
|
||||||
border-radius: 8px;
|
border-radius: ${token.borderRadiusLG}px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
`,
|
`,
|
||||||
@ -228,7 +228,7 @@ const useStyle = createStyles(() => ({
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 20px;
|
top: 20px;
|
||||||
left: 20px;
|
left: 20px;
|
||||||
font-size: 16px;
|
font-size: ${token.fontSizeLG}px;
|
||||||
`,
|
`,
|
||||||
tips: css`
|
tips: css`
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -237,14 +237,14 @@ const useStyle = createStyles(() => ({
|
|||||||
right: 20px;
|
right: 20px;
|
||||||
`,
|
`,
|
||||||
mvp: css`
|
mvp: css`
|
||||||
margin-right: 20px;
|
margin-inline-end: ${token.marginMD}px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
&::before {
|
&::before {
|
||||||
display: block;
|
display: block;
|
||||||
width: 8px;
|
width: 8px;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
margin-right: 8px;
|
margin-inline-end: ${token.marginXS}px;
|
||||||
background-color: #1677ff;
|
background-color: #1677ff;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
content: '';
|
content: '';
|
||||||
@ -257,7 +257,7 @@ const useStyle = createStyles(() => ({
|
|||||||
display: block;
|
display: block;
|
||||||
width: 8px;
|
width: 8px;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
margin-right: 8px;
|
margin-inline-end: ${token.marginXS}px;
|
||||||
background-color: #a0a0a0;
|
background-color: #a0a0a0;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
content: '';
|
content: '';
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import React, { Suspense } from 'react';
|
import React, { Suspense } from 'react';
|
||||||
import { createStyles } from 'antd-style';
|
|
||||||
import { Skeleton } from 'antd';
|
import { Skeleton } from 'antd';
|
||||||
|
import { createStyles } from 'antd-style';
|
||||||
|
|
||||||
import type { BehaviorMapProps } from './BehaviorMap';
|
import type { BehaviorMapProps } from './BehaviorMap';
|
||||||
|
|
||||||
const InternalBehaviorMap = React.lazy(() => import('./BehaviorMap'));
|
const InternalBehaviorMap = React.lazy(() => import('./BehaviorMap'));
|
||||||
@ -11,18 +12,17 @@ const useStyle = createStyles(({ token, css }) => ({
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
> * {
|
> * {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
border-radius: 8px;
|
border-radius: ${token.borderRadiusLG}px;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
placeholder: css`
|
placeholder: css`
|
||||||
color: ${token.colorTextDescription};
|
color: ${token.colorTextDescription};
|
||||||
font-size: 16px;
|
font-size: ${token.fontSizeLG}px;
|
||||||
`,
|
`,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const BehaviorMapFallback = () => {
|
const BehaviorMapFallback: React.FC = () => {
|
||||||
const { styles } = useStyle();
|
const { styles } = useStyle();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.fallback}>
|
<div className={styles.fallback}>
|
||||||
<Skeleton.Node active style={{ height: 600, width: '100%' }}>
|
<Skeleton.Node active style={{ height: 600, width: '100%' }}>
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import React, { useEffect, useMemo, type ComponentProps } from 'react';
|
import type { ComponentProps } from 'react';
|
||||||
|
import React, { useContext, useEffect, useMemo } from 'react';
|
||||||
import { Button, Tabs, Typography } from 'antd';
|
import { Button, Tabs, Typography } from 'antd';
|
||||||
import { createStyles } from 'antd-style';
|
import { createStyles } from 'antd-style';
|
||||||
import toReactElement from 'jsonml-to-react-element';
|
import toReactElement from 'jsonml-to-react-element';
|
||||||
import JsonML from 'jsonml.js/lib/utils';
|
import JsonML from 'jsonml.js/lib/utils';
|
||||||
import Prism from 'prismjs';
|
import Prism from 'prismjs';
|
||||||
|
|
||||||
|
import DemoContext from '../slots/DemoContext';
|
||||||
import LiveCode from './LiveCode';
|
import LiveCode from './LiveCode';
|
||||||
|
|
||||||
const useStyle = createStyles(({ token, css }) => {
|
const useStyle = createStyles(({ token, css }) => {
|
||||||
@ -13,7 +15,7 @@ const useStyle = createStyles(({ token, css }) => {
|
|||||||
return {
|
return {
|
||||||
code: css`
|
code: css`
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-top: -16px;
|
margin-top: -${token.margin}px;
|
||||||
`,
|
`,
|
||||||
|
|
||||||
copyButton: css`
|
copyButton: css`
|
||||||
@ -21,7 +23,7 @@ const useStyle = createStyles(({ token, css }) => {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
top: 16px;
|
top: 16px;
|
||||||
inset-inline-end: 16px;
|
inset-inline-end: ${token.padding}px;
|
||||||
width: 32px;
|
width: 32px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@ -66,7 +68,6 @@ interface CodePreviewProps
|
|||||||
jsxCode?: string;
|
jsxCode?: string;
|
||||||
styleCode?: string;
|
styleCode?: string;
|
||||||
entryName: string;
|
entryName: string;
|
||||||
onCodeTypeChange?: (activeKey: string) => void;
|
|
||||||
onSourceChange?: (source: Record<string, string>) => void;
|
onSourceChange?: (source: Record<string, string>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +92,6 @@ const CodePreview: React.FC<CodePreviewProps> = ({
|
|||||||
jsxCode = '',
|
jsxCode = '',
|
||||||
styleCode = '',
|
styleCode = '',
|
||||||
entryName,
|
entryName,
|
||||||
onCodeTypeChange,
|
|
||||||
onSourceChange,
|
onSourceChange,
|
||||||
error,
|
error,
|
||||||
}) => {
|
}) => {
|
||||||
@ -107,6 +107,7 @@ const CodePreview: React.FC<CodePreviewProps> = ({
|
|||||||
initialCodes.style = '';
|
initialCodes.style = '';
|
||||||
}
|
}
|
||||||
const [highlightedCodes, setHighlightedCodes] = React.useState(initialCodes);
|
const [highlightedCodes, setHighlightedCodes] = React.useState(initialCodes);
|
||||||
|
const { codeType, setCodeType } = useContext(DemoContext);
|
||||||
const sourceCodes = {
|
const sourceCodes = {
|
||||||
// omit trailing line break
|
// omit trailing line break
|
||||||
tsx: sourceCode?.trim(),
|
tsx: sourceCode?.trim(),
|
||||||
@ -120,7 +121,7 @@ const CodePreview: React.FC<CodePreviewProps> = ({
|
|||||||
style: Prism.highlight(styleCode, Prism.languages.css, 'css'),
|
style: Prism.highlight(styleCode, Prism.languages.css, 'css'),
|
||||||
};
|
};
|
||||||
// 去掉空的代码类型
|
// 去掉空的代码类型
|
||||||
Object.keys(codes).forEach((key: keyof typeof codes) => {
|
(Object.keys(codes) as (keyof typeof codes)[]).forEach((key) => {
|
||||||
if (!codes[key]) {
|
if (!codes[key]) {
|
||||||
delete codes[key];
|
delete codes[key];
|
||||||
}
|
}
|
||||||
@ -177,7 +178,15 @@ const CodePreview: React.FC<CodePreviewProps> = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Tabs centered className="highlight" onChange={onCodeTypeChange} items={items} />;
|
return (
|
||||||
|
<Tabs
|
||||||
|
centered
|
||||||
|
className="highlight"
|
||||||
|
activeKey={codeType}
|
||||||
|
onChange={setCodeType}
|
||||||
|
items={items}
|
||||||
|
/>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CodePreview;
|
export default CodePreview;
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { FormattedMessage } from 'dumi';
|
import React from 'react';
|
||||||
import React, { useMemo, useState } from 'react';
|
|
||||||
import { ColorPicker } from 'antd';
|
import { ColorPicker } from 'antd';
|
||||||
import type { Color } from 'antd/es/color-picker';
|
import type { Color } from 'antd/es/color-picker';
|
||||||
import ColorPatterns from './ColorPatterns';
|
import { FormattedMessage } from 'dumi';
|
||||||
|
|
||||||
import useLocale from '../../../hooks/useLocale';
|
import useLocale from '../../../hooks/useLocale';
|
||||||
|
import ColorPatterns from './ColorPatterns';
|
||||||
|
|
||||||
const primaryMinSaturation = 70; // 主色推荐最小饱和度
|
const primaryMinSaturation = 70; // 主色推荐最小饱和度
|
||||||
const primaryMinBrightness = 70; // 主色推荐最小亮度
|
const primaryMinBrightness = 70; // 主色推荐最小亮度
|
||||||
@ -22,8 +23,8 @@ const locales = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const ColorPaletteTool: React.FC = () => {
|
const ColorPaletteTool: React.FC = () => {
|
||||||
const [primaryColor, setPrimaryColor] = useState<string>('#1890ff');
|
const [primaryColor, setPrimaryColor] = React.useState<string>('#1890ff');
|
||||||
const [primaryColorInstance, setPrimaryColorInstance] = useState<Color>(null);
|
const [primaryColorInstance, setPrimaryColorInstance] = React.useState<Color>();
|
||||||
|
|
||||||
const [locale] = useLocale(locales);
|
const [locale] = useLocale(locales);
|
||||||
|
|
||||||
@ -32,7 +33,7 @@ const ColorPaletteTool: React.FC = () => {
|
|||||||
setPrimaryColorInstance(color);
|
setPrimaryColorInstance(color);
|
||||||
};
|
};
|
||||||
|
|
||||||
const colorValidation = useMemo<React.ReactNode>(() => {
|
const colorValidation = React.useMemo<React.ReactNode>(() => {
|
||||||
let text = '';
|
let text = '';
|
||||||
if (primaryColorInstance) {
|
if (primaryColorInstance) {
|
||||||
const { s, b } = primaryColorInstance.toHsb() || {};
|
const { s, b } = primaryColorInstance.toHsb() || {};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Global, css } from '@emotion/react';
|
import { css, Global } from '@emotion/react';
|
||||||
import { useTheme } from 'antd-style';
|
import { useTheme } from 'antd-style';
|
||||||
|
|
||||||
const gray: { [key: number]: string } = {
|
const gray: { [key: number]: string } = {
|
||||||
@ -18,7 +18,7 @@ const gray: { [key: number]: string } = {
|
|||||||
13: '#000',
|
13: '#000',
|
||||||
};
|
};
|
||||||
|
|
||||||
const ColorStyle = () => {
|
const ColorStyle: React.FC = () => {
|
||||||
const token = useTheme();
|
const token = useTheme();
|
||||||
|
|
||||||
const makePalette = (color: string, index: number = 1): string => {
|
const makePalette = (color: string, index: number = 1): string => {
|
||||||
@ -68,14 +68,14 @@ ${makeGrayPalette(index + 1)}
|
|||||||
margin: 45px 3.5% 45px 0;
|
margin: 45px 3.5% 45px 0;
|
||||||
|
|
||||||
&:nth-of-type(3n) {
|
&:nth-of-type(3n) {
|
||||||
margin-right: 0;
|
margin-inline-end: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-color-item {
|
.main-color-item {
|
||||||
margin-right: 0;
|
margin-inline-end: 0;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
margin-right: -8px;
|
margin-inline-end: -${token.paddingXS}px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -88,41 +88,40 @@ ${makeGrayPalette(index + 1)}
|
|||||||
margin: 45px 1%;
|
margin: 45px 1%;
|
||||||
|
|
||||||
&-pick {
|
&-pick {
|
||||||
margin: 0 0 20px;
|
margin: 0 0 ${token.marginMD}px;
|
||||||
font-size: 20px;
|
font-size: ${token.fontSizeXL}px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-picker {
|
&-picker {
|
||||||
margin: 24px 0;
|
margin: ${token.marginLG}px 0;
|
||||||
|
|
||||||
&-value {
|
&-value {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: -3px;
|
top: -3px;
|
||||||
margin-left: 16px;
|
margin-inline-start: ${token.margin}px;
|
||||||
font-size: 14px;
|
font-size: ${token.fontSize}px;
|
||||||
font-family: Consolas, sans-serif;
|
font-family: Consolas, sans-serif;
|
||||||
|
|
||||||
.ant-row-rtl & {
|
.ant-row-rtl & {
|
||||||
margin-right: 16px;
|
margin-inline-end: ${token.margin}px;
|
||||||
margin-left: 0;
|
margin-inline-start: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-validation {
|
&-validation {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: -3px;
|
top: -3px;
|
||||||
margin-left: 16px;
|
margin-inline-start: ${token.margin}px;
|
||||||
color: ${token.colorError};
|
color: ${token.colorError};
|
||||||
font-size: 13px;
|
font-size: ${token.fontSize}px;
|
||||||
|
|
||||||
.ant-row-rtl & {
|
.ant-row-rtl & {
|
||||||
margin-right: 16px;
|
margin-inline-end: ${token.margin}px;
|
||||||
margin-left: 0;
|
margin-inline-start: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-dark {
|
&-dark {
|
||||||
margin-left: 0;
|
margin-inline-start: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -148,31 +147,31 @@ ${makeGrayPalette(index + 1)}
|
|||||||
&-item {
|
&-item {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 44px;
|
height: 44px;
|
||||||
margin-right: 4px;
|
margin-inline-end: ${token.marginXXS}px;
|
||||||
padding: 0 12px;
|
padding: 0 ${token.paddingSM}px;
|
||||||
font-size: 14px;
|
font-size: ${token.fontSize}px;
|
||||||
font-family: Consolas, sans-serif;
|
font-family: Consolas, sans-serif;
|
||||||
line-height: 44px;
|
line-height: 44px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s;
|
transition: all ${token.motionDurationMid};
|
||||||
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
border-radius: 4px 4px 0 0;
|
border-radius: ${token.borderRadiusSM}px ${token.borderRadiusSM}px 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
border-radius: 0 0 4px 4px;
|
border-radius: 0 0 ${token.borderRadiusSM}px ${token.borderRadiusSM}px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
margin-right: -8px;
|
margin-inline-end: -${token.marginXS}px;
|
||||||
border-radius: 0 4px 4px 0;
|
border-radius: 0 ${token.borderRadiusSM}px ${token.borderRadiusSM}px 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-item &-text {
|
&-item &-text {
|
||||||
float: left;
|
float: left;
|
||||||
transition: all 0.3s;
|
transition: all ${token.motionDurationSlow};
|
||||||
}
|
}
|
||||||
|
|
||||||
&-item &-value {
|
&-item &-value {
|
||||||
@ -182,12 +181,12 @@ ${makeGrayPalette(index + 1)}
|
|||||||
transform: scale(0.85);
|
transform: scale(0.85);
|
||||||
transform-origin: 100% 50%;
|
transform-origin: 100% 50%;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: all 0.3s;
|
transition: all ${token.motionDurationSlow};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-title {
|
.color-title {
|
||||||
margin: 0 0 24px;
|
margin: 0 0 ${token.marginLG}px;
|
||||||
color: #5c6b77;
|
color: #5c6b77;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
@ -199,7 +198,7 @@ ${makeGrayPalette(index + 1)}
|
|||||||
display: block;
|
display: block;
|
||||||
color: #777;
|
color: #777;
|
||||||
font-weight: lighter;
|
font-weight: lighter;
|
||||||
font-size: 14px;
|
font-size: ${token.fontSize}px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-color:hover {
|
.main-color:hover {
|
||||||
@ -215,7 +214,7 @@ ${makeGrayPalette(index + 1)}
|
|||||||
|
|
||||||
&-dark {
|
&-dark {
|
||||||
height: 303px;
|
height: 303px;
|
||||||
padding: 32px 28px;
|
padding: ${token.paddingXL}px ${token.paddingXL - 4}px;
|
||||||
background-color: #141414;
|
background-color: #141414;
|
||||||
|
|
||||||
.color-palette-picker {
|
.color-palette-picker {
|
||||||
@ -245,7 +244,7 @@ ${makeGrayPalette(index + 1)}
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
height: 86px;
|
height: 86px;
|
||||||
margin-right: 0;
|
margin-inline-end: 0;
|
||||||
padding: 37px 0 0;
|
padding: 37px 0 0;
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@ -258,7 +257,7 @@ ${makeGrayPalette(index + 1)}
|
|||||||
&:hover {
|
&:hover {
|
||||||
height: 96px;
|
height: 96px;
|
||||||
margin-top: -10px;
|
margin-top: -10px;
|
||||||
border-radius: 4px 4px 0 0;
|
border-radius: ${token.borderRadiusSM}px ${token.borderRadiusSM}px 0 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,7 +272,7 @@ ${makeGrayPalette(index + 1)}
|
|||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
.main-color-item {
|
.main-color-item {
|
||||||
padding-top: 8px;
|
padding-top: ${token.paddingXS}px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-color-value {
|
.main-color-value {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { presetDarkPalettes } from '@ant-design/colors';
|
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import CopyToClipboard from 'react-copy-to-clipboard';
|
import { presetDarkPalettes } from '@ant-design/colors';
|
||||||
import { message } from 'antd';
|
import { message } from 'antd';
|
||||||
|
import CopyToClipboard from 'react-copy-to-clipboard';
|
||||||
|
|
||||||
const rgbToHex = (rgbString: string): string => {
|
const rgbToHex = (rgbString: string): string => {
|
||||||
const rgb = rgbString.match(/\d+/g);
|
const rgb = rgbString.match(/\d+/g);
|
||||||
|
@ -1,13 +1,32 @@
|
|||||||
/* eslint-disable global-require */
|
/* eslint-disable global-require */
|
||||||
import React, { useMemo } from 'react';
|
import React from 'react';
|
||||||
import { HistoryOutlined } from '@ant-design/icons';
|
import { BugOutlined, HistoryOutlined } from '@ant-design/icons';
|
||||||
import { Button, Drawer, Timeline, Typography, Grid } from 'antd';
|
import { Button, Drawer, Grid, Popover, Timeline, Typography } from 'antd';
|
||||||
|
import type { TimelineItemProps } from 'antd';
|
||||||
import { createStyles } from 'antd-style';
|
import { createStyles } from 'antd-style';
|
||||||
|
import semver from 'semver';
|
||||||
|
|
||||||
|
import deprecatedVersions from '../../../../BUG_VERSIONS.json';
|
||||||
import useFetch from '../../../hooks/useFetch';
|
import useFetch from '../../../hooks/useFetch';
|
||||||
import useLocale from '../../../hooks/useLocale';
|
import useLocale from '../../../hooks/useLocale';
|
||||||
import Link from '../Link';
|
import Link from '../Link';
|
||||||
|
|
||||||
|
interface MatchDeprecatedResult {
|
||||||
|
match?: string;
|
||||||
|
reason: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
function matchDeprecated(v: string): MatchDeprecatedResult {
|
||||||
|
const match = Object.keys(deprecatedVersions).find((depreciated) =>
|
||||||
|
semver.satisfies(v, depreciated),
|
||||||
|
);
|
||||||
|
const reason = deprecatedVersions[match as keyof typeof deprecatedVersions] || [];
|
||||||
|
return {
|
||||||
|
match,
|
||||||
|
reason: Array.isArray(reason) ? reason : [reason],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const useStyle = createStyles(({ token, css }) => ({
|
const useStyle = createStyles(({ token, css }) => ({
|
||||||
history: css`
|
history: css`
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -20,7 +39,33 @@ const useStyle = createStyles(({ token, css }) => ({
|
|||||||
`,
|
`,
|
||||||
|
|
||||||
ref: css`
|
ref: css`
|
||||||
margin-left: ${token.marginXS}px;
|
margin-inline-start: ${token.marginXS}px;
|
||||||
|
`,
|
||||||
|
bug: css`
|
||||||
|
font-size: ${token.fontSize}px;
|
||||||
|
color: #aaa;
|
||||||
|
margin-inline-start: ${token.marginXS}px;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: inherit;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
bugReasonTitle: css`
|
||||||
|
padding: ${token.paddingXXS}px ${token.paddingXS}px;
|
||||||
|
`,
|
||||||
|
bugReasonList: css`
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
li {
|
||||||
|
padding: ${token.paddingXXS}px ${token.paddingXS}px;
|
||||||
|
a {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: ${token.marginXXS}px;
|
||||||
|
}
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -34,16 +79,18 @@ const locales = {
|
|||||||
changelog: '更新日志',
|
changelog: '更新日志',
|
||||||
loading: '加载中...',
|
loading: '加载中...',
|
||||||
empty: '暂无更新',
|
empty: '暂无更新',
|
||||||
|
bugList: 'Bug 版本',
|
||||||
},
|
},
|
||||||
en: {
|
en: {
|
||||||
full: 'Full Changelog',
|
full: 'Full Changelog',
|
||||||
changelog: 'Changelog',
|
changelog: 'Changelog',
|
||||||
loading: 'loading...',
|
loading: 'loading...',
|
||||||
empty: 'Nothing update',
|
empty: 'Nothing update',
|
||||||
|
bugList: 'Bug Versions',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function ParseChangelog(props: { changelog: string; refs: string[]; styles: any }) {
|
const ParseChangelog: React.FC<{ changelog: string; refs: string[]; styles: any }> = (props) => {
|
||||||
const { changelog = '', refs = [], styles } = props;
|
const { changelog = '', refs = [], styles } = props;
|
||||||
|
|
||||||
const parsedChangelog = React.useMemo(() => {
|
const parsedChangelog = React.useMemo(() => {
|
||||||
@ -78,7 +125,6 @@ function ParseChangelog(props: { changelog: string; refs: string[]; styles: any
|
|||||||
<>
|
<>
|
||||||
{/* Changelog */}
|
{/* Changelog */}
|
||||||
<span>{parsedChangelog}</span>
|
<span>{parsedChangelog}</span>
|
||||||
|
|
||||||
{/* Refs */}
|
{/* Refs */}
|
||||||
{refs?.map((ref) => (
|
{refs?.map((ref) => (
|
||||||
<a className={styles.ref} key={ref} href={ref} target="_blank" rel="noreferrer">
|
<a className={styles.ref} key={ref} href={ref} target="_blank" rel="noreferrer">
|
||||||
@ -87,39 +133,29 @@ function ParseChangelog(props: { changelog: string; refs: string[]; styles: any
|
|||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
type ChangelogInfo = {
|
interface ChangelogInfo {
|
||||||
version: string;
|
version: string;
|
||||||
changelog: string;
|
changelog: string;
|
||||||
refs: string[];
|
refs: string[];
|
||||||
};
|
|
||||||
|
|
||||||
function useChangelog(componentPath: string, lang: 'cn' | 'en'): ChangelogInfo[] {
|
|
||||||
const data: any = useFetch(
|
|
||||||
lang === 'cn'
|
|
||||||
? {
|
|
||||||
key: 'component-changelog-cn',
|
|
||||||
request: () => import('../../../preset/components-changelog-cn.json'),
|
|
||||||
}
|
}
|
||||||
: {
|
|
||||||
key: 'component-changelog-en',
|
|
||||||
request: () => import('../../../preset/components-changelog-en.json'),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
return useMemo(() => {
|
const useChangelog = (componentPath: string, lang: 'cn' | 'en'): ChangelogInfo[] => {
|
||||||
|
const data = useFetch({
|
||||||
|
key: `component-changelog-${lang}`,
|
||||||
|
request: () => import(`../../../preset/components-changelog-${lang}.json`),
|
||||||
|
});
|
||||||
|
return React.useMemo(() => {
|
||||||
const component = componentPath.replace(/-/g, '');
|
const component = componentPath.replace(/-/g, '');
|
||||||
|
|
||||||
const componentName = Object.keys(data).find(
|
const componentName = Object.keys(data).find(
|
||||||
(name) => name.toLowerCase() === component.toLowerCase(),
|
(name) => name.toLowerCase() === component.toLowerCase(),
|
||||||
);
|
);
|
||||||
|
return data[componentName as keyof typeof data] as ChangelogInfo[];
|
||||||
return data[componentName!];
|
|
||||||
}, [data, componentPath]);
|
}, [data, componentPath]);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default function ComponentChangelog(props: ComponentChangelogProps) {
|
const ComponentChangelog: React.FC<ComponentChangelogProps> = (props) => {
|
||||||
const { pathname = '' } = props;
|
const { pathname = '' } = props;
|
||||||
const [locale, lang] = useLocale(locales);
|
const [locale, lang] = useLocale(locales);
|
||||||
const [show, setShow] = React.useState(false);
|
const [show, setShow] = React.useState(false);
|
||||||
@ -130,7 +166,7 @@ export default function ComponentChangelog(props: ComponentChangelogProps) {
|
|||||||
|
|
||||||
const list = useChangelog(componentPath, lang);
|
const list = useChangelog(componentPath, lang);
|
||||||
|
|
||||||
const timelineItems = React.useMemo(() => {
|
const timelineItems = React.useMemo<TimelineItemProps[]>(() => {
|
||||||
const changelogMap: Record<string, ChangelogInfo[]> = {};
|
const changelogMap: Record<string, ChangelogInfo[]> = {};
|
||||||
|
|
||||||
list?.forEach((info) => {
|
list?.forEach((info) => {
|
||||||
@ -140,13 +176,41 @@ export default function ComponentChangelog(props: ComponentChangelogProps) {
|
|||||||
|
|
||||||
return Object.keys(changelogMap).map((version) => {
|
return Object.keys(changelogMap).map((version) => {
|
||||||
const changelogList = changelogMap[version];
|
const changelogList = changelogMap[version];
|
||||||
|
const bugVersionInfo = matchDeprecated(version);
|
||||||
return {
|
return {
|
||||||
children: (
|
children: (
|
||||||
<Typography>
|
<Typography>
|
||||||
<h4>{version}</h4>
|
<Typography.Title level={4}>
|
||||||
|
{version}
|
||||||
|
{bugVersionInfo.match && (
|
||||||
|
<Popover
|
||||||
|
destroyTooltipOnHide
|
||||||
|
placement="right"
|
||||||
|
title={<span className={styles.bugReasonTitle}>{locale.bugList}</span>}
|
||||||
|
content={
|
||||||
|
<ul className={styles.bugReasonList}>
|
||||||
|
{bugVersionInfo.reason.map<React.ReactNode>((reason, index) => (
|
||||||
|
<li key={`reason-${index}`}>
|
||||||
|
<a type="link" target="_blank" rel="noreferrer" href={reason}>
|
||||||
|
<BugOutlined />
|
||||||
|
{reason
|
||||||
|
?.replace(/#.*$/, '')
|
||||||
|
?.replace(
|
||||||
|
/^https:\/\/github\.com\/ant-design\/ant-design\/(issues|pull)\//,
|
||||||
|
'#',
|
||||||
|
)}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<BugOutlined className={styles.bug} />
|
||||||
|
</Popover>
|
||||||
|
)}
|
||||||
|
</Typography.Title>
|
||||||
<ul>
|
<ul>
|
||||||
{changelogList.map((info, index) => (
|
{changelogList.map<React.ReactNode>((info, index) => (
|
||||||
<li key={index} className={styles.li}>
|
<li key={index} className={styles.li}>
|
||||||
<ParseChangelog {...info} styles={styles} />
|
<ParseChangelog {...info} styles={styles} />
|
||||||
</li>
|
</li>
|
||||||
@ -194,4 +258,6 @@ export default function ComponentChangelog(props: ComponentChangelogProps) {
|
|||||||
</Drawer>
|
</Drawer>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default ComponentChangelog;
|
||||||
|
@ -21,14 +21,12 @@ const useStyle = createStyles(({ token, css }) => {
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
margin-inline-start: 6px;
|
margin-inline-start: ${token.marginXS}px;
|
||||||
|
|
||||||
${iconCls} {
|
${iconCls} {
|
||||||
display: block;
|
display: block;
|
||||||
color: ${colorIcon};
|
color: ${colorIcon};
|
||||||
font-size: 16px;
|
font-size: ${token.fontSizeLG}px;
|
||||||
transition: all 0.3s;
|
transition: all ${token.motionDurationSlow};
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: ${colorText};
|
color: ${colorText};
|
||||||
}
|
}
|
||||||
|
@ -22,12 +22,12 @@ const useStyle = createStyles(({ token, css }) => {
|
|||||||
.dumi-default-source-code > pre,
|
.dumi-default-source-code > pre,
|
||||||
.dumi-default-source-code-scroll-content > pre,
|
.dumi-default-source-code-scroll-content > pre,
|
||||||
.dumi-default-source-code-editor-textarea {
|
.dumi-default-source-code-editor-textarea {
|
||||||
padding: 12px 16px;
|
padding: ${token.paddingSM}px ${token.padding}px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dumi-default-source-code > pre,
|
.dumi-default-source-code > pre,
|
||||||
.dumi-default-source-code-scroll-content > pre {
|
.dumi-default-source-code-scroll-content > pre {
|
||||||
font-size: 13px;
|
font-size: ${token.fontSize}px;
|
||||||
line-height: 2;
|
line-height: 2;
|
||||||
font-family: 'Lucida Console', Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
font-family: 'Lucida Console', Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { LeftOutlined, RightOutlined } from '@ant-design/icons';
|
|
||||||
import { createStyles } from 'antd-style';
|
|
||||||
import type { ReactElement } from 'react';
|
import type { ReactElement } from 'react';
|
||||||
import React, { useMemo, useContext } from 'react';
|
import React, { useContext, useMemo } from 'react';
|
||||||
import classNames from 'classnames';
|
import { LeftOutlined, RightOutlined } from '@ant-design/icons';
|
||||||
import type { MenuItemType } from 'antd/es/menu/hooks/useItems';
|
|
||||||
import type { MenuProps } from 'antd';
|
import type { MenuProps } from 'antd';
|
||||||
|
import { createStyles } from 'antd-style';
|
||||||
|
import type { MenuItemType } from 'antd/es/menu/hooks/useItems';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import useMenu from '../../hooks/useMenu';
|
import useMenu from '../../hooks/useMenu';
|
||||||
import SiteContext from '../slots/SiteContext';
|
import SiteContext from '../slots/SiteContext';
|
||||||
import type { SiteContextProps } from '../slots/SiteContext';
|
import type { SiteContextProps } from '../slots/SiteContext';
|
||||||
@ -18,7 +19,7 @@ const useStyle = createStyles(({ token, css }) => {
|
|||||||
margin-inline-end: 170px;
|
margin-inline-end: 170px;
|
||||||
margin-inline-start: 64px;
|
margin-inline-start: 64px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
font-size: 14px;
|
font-size: ${token.fontSize}px;
|
||||||
border-top: 1px solid ${colorSplit};
|
border-top: 1px solid ${colorSplit};
|
||||||
display: flex;
|
display: flex;
|
||||||
`,
|
`,
|
||||||
@ -31,11 +32,11 @@ const useStyle = createStyles(({ token, css }) => {
|
|||||||
${iconCls} {
|
${iconCls} {
|
||||||
color: #999;
|
color: #999;
|
||||||
font-size: ${fontSizeIcon}px;
|
font-size: ${fontSizeIcon}px;
|
||||||
transition: all 0.3s;
|
transition: all ${token.motionDurationSlow};
|
||||||
}
|
}
|
||||||
|
|
||||||
.chinese {
|
.chinese {
|
||||||
margin-inline-start: 4px;
|
margin-inline-start: ${token.marginXXS}px;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
prevNav: css`
|
prevNav: css`
|
||||||
@ -52,7 +53,7 @@ const useStyle = createStyles(({ token, css }) => {
|
|||||||
position: relative;
|
position: relative;
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
transition: inset-inline-end 0.3s;
|
transition: inset-inline-end ${token.motionDurationSlow};
|
||||||
margin-inline-end: 1em;
|
margin-inline-end: 1em;
|
||||||
inset-inline-end: 0;
|
inset-inline-end: 0;
|
||||||
}
|
}
|
||||||
@ -76,7 +77,7 @@ const useStyle = createStyles(({ token, css }) => {
|
|||||||
margin-bottom: 1px;
|
margin-bottom: 1px;
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
transition: inset-inline-start 0.3s;
|
transition: inset-inline-start ${token.motionDurationSlow};
|
||||||
margin-inline-start: 1em;
|
margin-inline-start: 1em;
|
||||||
inset-inline-start: 0;
|
inset-inline-start: 0;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
import { css, Global } from '@emotion/react';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { css, Global } from '@emotion/react';
|
||||||
|
import { useTheme } from 'antd-style';
|
||||||
|
|
||||||
export default () => (
|
export default () => {
|
||||||
|
const token = useTheme();
|
||||||
|
return (
|
||||||
<Global
|
<Global
|
||||||
styles={css`
|
styles={css`
|
||||||
/* Browser mockup code
|
/* Browser mockup code
|
||||||
@ -12,7 +15,7 @@ export default () => (
|
|||||||
.browser-mockup {
|
.browser-mockup {
|
||||||
position: relative;
|
position: relative;
|
||||||
border-top: 2em solid rgba(230, 230, 230, 0.7);
|
border-top: 2em solid rgba(230, 230, 230, 0.7);
|
||||||
border-radius: 3px 3px 0 0;
|
border-radius: ${token.borderRadiusSM}px ${token.borderRadiusSM}px 0 0;
|
||||||
box-shadow: 0 0.1em 0.5em 0 rgba(0, 0, 0, 0.28);
|
box-shadow: 0 0.1em 0.5em 0 rgba(0, 0, 0, 0.28);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,7 +28,10 @@ export default () => (
|
|||||||
height: 0.5em;
|
height: 0.5em;
|
||||||
background-color: #f44;
|
background-color: #f44;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
box-shadow: 0 0 0 2px #f44, 1.5em 0 0 2px #9b3, 3em 0 0 2px #fb5;
|
box-shadow:
|
||||||
|
0 0 0 2px #f44,
|
||||||
|
1.5em 0 0 2px #9b3,
|
||||||
|
3em 0 0 2px #fb5;
|
||||||
content: '';
|
content: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,14 +55,14 @@ export default () => (
|
|||||||
display: block;
|
display: block;
|
||||||
width: calc(100% - 6em);
|
width: calc(100% - 6em);
|
||||||
height: 1.2em;
|
height: 1.2em;
|
||||||
background-color: white;
|
background-color: #fff;
|
||||||
border-radius: 2px;
|
border-radius: ${token.borderRadiusXS}px;
|
||||||
content: '';
|
content: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
.browser-mockup > * {
|
.browser-mockup > * {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
`}
|
`}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
@ -23,11 +23,11 @@ const GlobalDemoStyles: React.FC = () => {
|
|||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: calc(100% - ${token.lineWidth * 2}px);
|
width: calc(100% - ${token.lineWidth * 2}px);
|
||||||
margin: 0 0 16px;
|
margin: 0 0 ${token.margin}px;
|
||||||
background-color: ${token.colorBgContainer};
|
background-color: ${token.colorBgContainer};
|
||||||
border: 1px solid ${token.colorSplit};
|
border: 1px solid ${token.colorSplit};
|
||||||
border-radius: ${token.borderRadiusLG}px;
|
border-radius: ${token.borderRadiusLG}px;
|
||||||
transition: all 0.2s;
|
transition: all ${token.motionDurationMid};
|
||||||
|
|
||||||
&.code-box-simplify {
|
&.code-box-simplify {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
@ -74,12 +74,10 @@ const GlobalDemoStyles: React.FC = () => {
|
|||||||
&-expand-trigger {
|
&-expand-trigger {
|
||||||
position: relative;
|
position: relative;
|
||||||
color: #3b4357;
|
color: #3b4357;
|
||||||
font-size: 20px;
|
font-size: ${token.fontSizeXL}px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
opacity: 0.75;
|
opacity: 0.75;
|
||||||
transition: all 0.3s;
|
transition: all ${token.motionDurationSlow};
|
||||||
margin-inline-start: 12px;
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
@ -93,7 +91,7 @@ const GlobalDemoStyles: React.FC = () => {
|
|||||||
background: ${token.colorBgContainer};
|
background: ${token.colorBgContainer};
|
||||||
border-radius: ${token.borderRadius}px ${token.borderRadius}px 0 0;
|
border-radius: ${token.borderRadius}px ${token.borderRadius}px 0 0;
|
||||||
transition: background-color 0.4s;
|
transition: background-color 0.4s;
|
||||||
margin-inline-start: 16px;
|
margin-inline-start: ${token.margin}px;
|
||||||
|
|
||||||
a,
|
a,
|
||||||
a:hover {
|
a:hover {
|
||||||
@ -111,15 +109,15 @@ const GlobalDemoStyles: React.FC = () => {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 7px;
|
top: 7px;
|
||||||
right: -16px;
|
right: -16px;
|
||||||
font-size: 12px;
|
font-size: ${token.fontSizeSM}px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
background: inherit;
|
background: inherit;
|
||||||
transform: scale(0.9);
|
transform: scale(0.9);
|
||||||
padding-inline-end: 6px;
|
padding-inline-end: ${token.paddingXXS}px;
|
||||||
|
|
||||||
${iconCls} {
|
${iconCls} {
|
||||||
color: ${token.colorTextSecondary};
|
color: ${token.colorTextSecondary};
|
||||||
transition: all 0.3s;
|
transition: all ${token.motionDurationSlow};
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: ${token.colorText};
|
color: ${token.colorText};
|
||||||
@ -164,7 +162,7 @@ const GlobalDemoStyles: React.FC = () => {
|
|||||||
> p {
|
> p {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0.5em 0;
|
margin: 0.5em 0;
|
||||||
font-size: 12px;
|
font-size: ${token.fontSizeSM}px;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
padding-inline-end: 25px;
|
padding-inline-end: 25px;
|
||||||
}
|
}
|
||||||
@ -244,10 +242,10 @@ const GlobalDemoStyles: React.FC = () => {
|
|||||||
&-actions {
|
&-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 12px 0;
|
padding: ${token.paddingSM}px 0;
|
||||||
border-top: 1px dashed ${token.colorSplit};
|
border-top: 1px dashed ${token.colorSplit};
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
transition: opacity 0.3s;
|
transition: opacity ${token.motionDurationSlow};
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
@ -276,7 +274,7 @@ const GlobalDemoStyles: React.FC = () => {
|
|||||||
&-code-copy {
|
&-code-copy {
|
||||||
width: 14px;
|
width: 14px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
font-size: 14px;
|
font-size: ${token.fontSize}px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background: ${token.colorBgContainer};
|
background: ${token.colorBgContainer};
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@ -331,8 +329,8 @@ const GlobalDemoStyles: React.FC = () => {
|
|||||||
background: ${token.colorBgContainer};
|
background: ${token.colorBgContainer};
|
||||||
border: none;
|
border: none;
|
||||||
box-shadow: unset;
|
box-shadow: unset;
|
||||||
padding: 12px 16px;
|
padding: ${token.paddingSM}px ${token.padding}px;
|
||||||
font-size: 13px;
|
font-size: ${token.fontSize}px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,6 +351,9 @@ const GlobalDemoStyles: React.FC = () => {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: -32px;
|
top: -32px;
|
||||||
inset-inline-end: 0;
|
inset-inline-end: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
column-gap: ${token.marginSM}px;
|
||||||
}
|
}
|
||||||
|
|
||||||
${antCls}-row-rtl {
|
${antCls}-row-rtl {
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { css, Global } from '@emotion/react';
|
import { css, Global } from '@emotion/react';
|
||||||
|
import { useTheme } from 'antd-style';
|
||||||
|
|
||||||
export default () => (
|
export default () => {
|
||||||
|
const token = useTheme();
|
||||||
|
return (
|
||||||
<Global
|
<Global
|
||||||
styles={css`
|
styles={css`
|
||||||
h1,
|
h1,
|
||||||
@ -13,12 +16,12 @@ export default () => (
|
|||||||
> a[aria-hidden]:first-child {
|
> a[aria-hidden]:first-child {
|
||||||
float: left;
|
float: left;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
padding-inline-end: 4px;
|
padding-inline-end: ${token.paddingXXS}px;
|
||||||
font-size: 0;
|
font-size: 0;
|
||||||
line-height: inherit;
|
line-height: inherit;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
padding-inline-end: 4px;
|
padding-inline-end: ${token.paddingXXS}px;
|
||||||
margin-inline-start: -24px;
|
margin-inline-start: -${token.marginLG}px;
|
||||||
|
|
||||||
[data-direction='rtl'] & {
|
[data-direction='rtl'] & {
|
||||||
float: right;
|
float: right;
|
||||||
@ -29,7 +32,7 @@ export default () => (
|
|||||||
}
|
}
|
||||||
|
|
||||||
> .icon-link::before {
|
> .icon-link::before {
|
||||||
font-size: 20px;
|
font-size: ${token.fontSizeXL}px;
|
||||||
content: '#';
|
content: '#';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -41,3 +44,4 @@ export default () => (
|
|||||||
`}
|
`}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
@ -16,7 +16,7 @@ export default () => {
|
|||||||
|
|
||||||
pre code {
|
pre code {
|
||||||
display: block;
|
display: block;
|
||||||
padding: 16px 32px;
|
padding: ${token.padding}px ${token.paddingXL}px;
|
||||||
color: ${token.colorText};
|
color: ${token.colorText};
|
||||||
font-size: ${token.fontSize}px;
|
font-size: ${token.fontSize}px;
|
||||||
font-family: 'Lucida Console', Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
font-family: 'Lucida Console', Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||||
@ -31,7 +31,7 @@ export default () => {
|
|||||||
pre[class*='language-'] {
|
pre[class*='language-'] {
|
||||||
color: ${token.colorText};
|
color: ${token.colorText};
|
||||||
font-family: 'Lucida Console', Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
font-family: 'Lucida Console', Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||||
line-height: 1.5;
|
line-height: ${token.lineHeightLG};
|
||||||
direction: ltr;
|
direction: ltr;
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
@ -62,14 +62,14 @@ export default () => {
|
|||||||
|
|
||||||
/* Code blocks */
|
/* Code blocks */
|
||||||
pre[class*='language-'] {
|
pre[class*='language-'] {
|
||||||
margin: 16px 0;
|
margin: ${token.margin}px 0;
|
||||||
padding: 12px 20px;
|
padding: ${token.paddingSM}px ${token.paddingMD}px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
:not(pre) > code[class*='language-'],
|
:not(pre) > code[class*='language-'],
|
||||||
pre[class*='language-'] {
|
pre[class*='language-'] {
|
||||||
background: #f5f5f5;
|
background: ${token.colorBgLayout};
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Inline code */
|
/* Inline code */
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { css, Global } from '@emotion/react';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { css, Global } from '@emotion/react';
|
||||||
import { useTheme } from 'antd-style';
|
import { useTheme } from 'antd-style';
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
@ -28,9 +28,11 @@ export default () => {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
background-color: inherit;
|
background-color: inherit;
|
||||||
border-radius: 4px;
|
border-radius: ${token.borderRadiusSM}px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: color 0.3s ease-in-out, background-color 0.3s ease-in-out;
|
transition:
|
||||||
|
color ${token.motionDurationSlow} ease-in-out,
|
||||||
|
background-color ${token.motionDurationSlow} ease-in-out;
|
||||||
|
|
||||||
.rtl & {
|
.rtl & {
|
||||||
margin: 3px 0;
|
margin: 3px 0;
|
||||||
@ -38,9 +40,9 @@ export default () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
${iconCls} {
|
${iconCls} {
|
||||||
margin: 12px 0 8px;
|
margin: ${token.marginSM}px 0 ${token.marginXS}px;
|
||||||
font-size: 36px;
|
font-size: 36px;
|
||||||
transition: transform 0.3s ease-in-out;
|
transition: transform ${token.motionDurationSlow} ease-in-out;
|
||||||
will-change: transform;
|
will-change: transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +55,7 @@ export default () => {
|
|||||||
transform: scale(0.83);
|
transform: scale(0.83);
|
||||||
|
|
||||||
${antCls}-badge {
|
${antCls}-badge {
|
||||||
transition: color 0.3s ease-in-out;
|
transition: color ${token.motionDurationSlow} ease-in-out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +91,7 @@ export default () => {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
background: #1677ff;
|
background: #1677ff;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: all 0.3s cubic-bezier(0.18, 0.89, 0.32, 1.28);
|
transition: all ${token.motionDurationSlow} cubic-bezier(0.18, 0.89, 0.32, 1.28);
|
||||||
content: 'Copied!';
|
content: 'Copied!';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,9 +103,9 @@ export default () => {
|
|||||||
|
|
||||||
.copied-code {
|
.copied-code {
|
||||||
padding: 2px 4px;
|
padding: 2px 4px;
|
||||||
font-size: 12px;
|
font-size: ${token.fontSizeSM}px;
|
||||||
background: #f5f5f5;
|
background: ${token.colorBgLayout};
|
||||||
border-radius: 2px;
|
border-radius: ${token.borderRadiusXS}px;
|
||||||
}
|
}
|
||||||
`}
|
`}
|
||||||
/>
|
/>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { css, Global } from '@emotion/react';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { css, Global } from '@emotion/react';
|
||||||
import { useTheme } from 'antd-style';
|
import { useTheme } from 'antd-style';
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
@ -12,12 +12,12 @@ export default () => {
|
|||||||
styles={css`
|
styles={css`
|
||||||
.icon-pic-searcher {
|
.icon-pic-searcher {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin: 0 8px;
|
margin: 0 ${token.marginXS}px;
|
||||||
|
|
||||||
.icon-pic-btn {
|
.icon-pic-btn {
|
||||||
color: ${token.colorIcon};
|
color: ${token.colorIcon};
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s;
|
transition: all ${token.motionDurationSlow};
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: ${token.colorIconHover};
|
color: ${token.colorIconHover};
|
||||||
@ -29,10 +29,10 @@ export default () => {
|
|||||||
width: 66px;
|
width: 66px;
|
||||||
height: 66px;
|
height: 66px;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
padding: 8px;
|
padding: ${token.paddingXS}px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border: 1px solid ${token.colorBorder};
|
border: 1px solid ${token.colorBorder};
|
||||||
border-radius: 4px;
|
border-radius: ${token.borderRadiusSM}px;
|
||||||
|
|
||||||
> img {
|
> img {
|
||||||
max-width: 50px;
|
max-width: 50px;
|
||||||
@ -57,8 +57,7 @@ export default () => {
|
|||||||
padding: 10px 0;
|
padding: 10px 0;
|
||||||
|
|
||||||
> ${iconCls} {
|
> ${iconCls} {
|
||||||
font-size: 30px;
|
font-size: ${token.fontSizeHeading2}px;
|
||||||
|
|
||||||
:hover {
|
:hover {
|
||||||
color: ${token.colorLinkHover};
|
color: ${token.colorLinkHover};
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { css, Global } from '@emotion/react';
|
import { css, Global } from '@emotion/react';
|
||||||
|
import { useTheme } from 'antd-style';
|
||||||
|
|
||||||
export default () => (
|
export default () => {
|
||||||
|
const token = useTheme();
|
||||||
|
return (
|
||||||
<Global
|
<Global
|
||||||
styles={css`
|
styles={css`
|
||||||
.design-inline-cards {
|
.design-inline-cards {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin: 0 -20px;
|
margin: 0 -${token.marginMD}px;
|
||||||
}
|
}
|
||||||
.design-inline-cards > * {
|
.design-inline-cards > * {
|
||||||
flex: 10%;
|
flex: 10%;
|
||||||
margin: 0 20px;
|
margin: 0 ${token.marginMD}px;
|
||||||
}
|
}
|
||||||
.design-inline-cards img {
|
.design-inline-cards img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -22,3 +25,4 @@ export default () => (
|
|||||||
`}
|
`}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
@ -15,7 +15,7 @@ const GlobalStyle: React.FC = () => {
|
|||||||
styles={css`
|
styles={css`
|
||||||
.markdown {
|
.markdown {
|
||||||
color: ${token.colorText};
|
color: ${token.colorText};
|
||||||
font-size: 14px;
|
font-size: ${token.fontSize}px;
|
||||||
line-height: 2;
|
line-height: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,8 +47,8 @@ const GlobalStyle: React.FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.markdown h1 {
|
.markdown h1 {
|
||||||
margin-top: 8px;
|
margin-top: ${token.marginXS}px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: ${token.marginMD}px;
|
||||||
color: ${token.colorTextHeading};
|
color: ${token.colorTextHeading};
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 30px;
|
font-size: 30px;
|
||||||
@ -56,7 +56,7 @@ const GlobalStyle: React.FC = () => {
|
|||||||
line-height: 38px;
|
line-height: 38px;
|
||||||
|
|
||||||
.subtitle {
|
.subtitle {
|
||||||
margin-left: 12px;
|
margin-inline-start: ${token.marginSM}px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,21 +82,21 @@ const GlobalStyle: React.FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.markdown h4 {
|
.markdown h4 {
|
||||||
font-size: 16px;
|
font-size: ${token.fontSizeLG}px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.markdown h5 {
|
.markdown h5 {
|
||||||
font-size: 14px;
|
font-size: ${token.fontSize}px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.markdown h6 {
|
.markdown h6 {
|
||||||
font-size: 12px;
|
font-size: ${token.fontSizeSM}px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.markdown hr {
|
.markdown hr {
|
||||||
clear: both;
|
clear: both;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
margin: 24px 0;
|
margin: ${token.marginLG}px 0;
|
||||||
background: ${token.colorSplit};
|
background: ${token.colorSplit};
|
||||||
border: 0;
|
border: 0;
|
||||||
}
|
}
|
||||||
@ -112,15 +112,15 @@ const GlobalStyle: React.FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.markdown ul > li {
|
.markdown ul > li {
|
||||||
margin-left: 20px;
|
margin-inline-start: ${token.marginMD}px;
|
||||||
padding-left: 4px;
|
padding-inline-start: ${token.paddingXXS}px;
|
||||||
list-style-type: circle;
|
list-style-type: circle;
|
||||||
|
|
||||||
.rtl & {
|
.rtl & {
|
||||||
margin-right: 20px;
|
margin-inline-end: ${token.marginMD}px;
|
||||||
margin-left: 0;
|
margin-inline-start: 0;
|
||||||
padding-right: 4px;
|
padding-inline-end: ${token.paddingXXS}px;
|
||||||
padding-left: 0;
|
padding-inline-start: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:empty {
|
&:empty {
|
||||||
@ -129,15 +129,15 @@ const GlobalStyle: React.FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.markdown ol > li {
|
.markdown ol > li {
|
||||||
margin-left: 20px;
|
margin-inline-start: ${token.marginMD}px;
|
||||||
padding-left: 4px;
|
padding-inline-start: ${token.paddingXXS}px;
|
||||||
list-style-type: decimal;
|
list-style-type: decimal;
|
||||||
|
|
||||||
${antCls}-row-rtl & {
|
${antCls}-row-rtl & {
|
||||||
margin-right: 20px;
|
margin-inline-end: ${token.marginMD}px;
|
||||||
margin-left: 0;
|
margin-inline-start: 0;
|
||||||
padding-right: 4px;
|
padding-inline-end: ${token.paddingXXS}px;
|
||||||
padding-left: 0;
|
padding-inline-start: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,7 +152,7 @@ const GlobalStyle: React.FC = () => {
|
|||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
background: ${token.siteMarkdownCodeBg};
|
background: ${token.siteMarkdownCodeBg};
|
||||||
border: 1px solid ${token.colorSplit};
|
border: 1px solid ${token.colorSplit};
|
||||||
border-radius: 3px;
|
border-radius: ${token.borderRadiusSM}px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.markdown pre {
|
.markdown pre {
|
||||||
@ -169,7 +169,7 @@ const GlobalStyle: React.FC = () => {
|
|||||||
font-size: ${Math.max(token.fontSize - 1, 12)}px;
|
font-size: ${Math.max(token.fontSize - 1, 12)}px;
|
||||||
direction: ltr;
|
direction: ltr;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
background: #f5f5f5;
|
background-color: ${token.colorBgLayout};
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,8 +183,8 @@ const GlobalStyle: React.FC = () => {
|
|||||||
background-color: ${token.siteMarkdownCodeBg};
|
background-color: ${token.siteMarkdownCodeBg};
|
||||||
border-radius: ${token.borderRadius}px;
|
border-radius: ${token.borderRadius}px;
|
||||||
> pre.prism-code {
|
> pre.prism-code {
|
||||||
padding: 12px 20px;
|
padding: ${token.paddingSM}px ${token.paddingMD}px;
|
||||||
font-size: 13px;
|
font-size: ${token.fontSize}px;
|
||||||
line-height: 2;
|
line-height: 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -194,14 +194,14 @@ const GlobalStyle: React.FC = () => {
|
|||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
span {
|
span {
|
||||||
margin: 0 20px;
|
margin: 0 ${token.marginMD}px;
|
||||||
color: #aaa;
|
color: #aaa;
|
||||||
font-size: 30px;
|
font-size: 30px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.markdown table td > a:not(:last-child) {
|
.markdown table td > a:not(:last-child) {
|
||||||
margin-right: 0 !important;
|
margin-inline-end: 0 !important;
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
position: relative !important;
|
position: relative !important;
|
||||||
@ -210,14 +210,14 @@ const GlobalStyle: React.FC = () => {
|
|||||||
|
|
||||||
.markdown blockquote {
|
.markdown blockquote {
|
||||||
margin: 1em 0;
|
margin: 1em 0;
|
||||||
padding-left: 0.8em;
|
padding-inline-start: 0.8em;
|
||||||
color: ${token.colorTextSecondary};
|
color: ${token.colorTextSecondary};
|
||||||
font-size: 90%;
|
font-size: 90%;
|
||||||
border-left: 4px solid ${token.colorSplit};
|
border-left: 4px solid ${token.colorSplit};
|
||||||
|
|
||||||
.rtl & {
|
.rtl & {
|
||||||
padding-right: 0.8em;
|
padding-inline-end: 0.8em;
|
||||||
padding-left: 0;
|
padding-inline-start: 0;
|
||||||
border-right: 4px solid ${token.colorSplit};
|
border-right: 4px solid ${token.colorSplit};
|
||||||
border-left: none;
|
border-left: none;
|
||||||
}
|
}
|
||||||
@ -228,13 +228,13 @@ const GlobalStyle: React.FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.markdown .anchor {
|
.markdown .anchor {
|
||||||
margin-left: 8px;
|
margin-inline-start: ${token.marginXS}px;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity 0.3s;
|
transition: opacity ${token.motionDurationSlow};
|
||||||
|
|
||||||
.rtl & {
|
.rtl & {
|
||||||
margin-right: 8px;
|
margin-inline-end: ${token.marginXS}px;
|
||||||
margin-left: 0;
|
margin-inline-start: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,20 +245,20 @@ const GlobalStyle: React.FC = () => {
|
|||||||
|
|
||||||
.markdown a.edit-button {
|
.markdown a.edit-button {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-left: 8px;
|
margin-inline-start: ${token.marginXS}px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
||||||
.rtl & {
|
.rtl & {
|
||||||
margin-right: 8px;
|
margin-inline-end: ${token.marginXS}px;
|
||||||
margin-left: 0;
|
margin-inline-start: 0;
|
||||||
transform: rotateY(180deg);
|
transform: rotateY(180deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
${antCls}icon {
|
${antCls}icon {
|
||||||
display: block;
|
display: block;
|
||||||
color: ${token.colorTextSecondary};
|
color: ${token.colorTextSecondary};
|
||||||
font-size: 16px;
|
font-size: ${token.fontSizeLG}px;
|
||||||
transition: all 0.3s;
|
transition: all ${token.motionDurationSlow};
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: ${token.colorText};
|
color: ${token.colorText};
|
||||||
@ -294,7 +294,7 @@ const GlobalStyle: React.FC = () => {
|
|||||||
|
|
||||||
th,
|
th,
|
||||||
td {
|
td {
|
||||||
padding: 12px 24px;
|
padding: ${token.paddingSM}px ${token.paddingLG}px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
border: 1px solid ${token.colorSplit};
|
border: 1px solid ${token.colorSplit};
|
||||||
|
|
||||||
@ -320,7 +320,7 @@ const GlobalStyle: React.FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tbody tr {
|
tbody tr {
|
||||||
transition: all 0.3s;
|
transition: all ${token.motionDurationSlow};
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: rgba(60, 90, 100, 0.04);
|
background: rgba(60, 90, 100, 0.04);
|
||||||
@ -348,7 +348,7 @@ const GlobalStyle: React.FC = () => {
|
|||||||
width: 18%;
|
width: 18%;
|
||||||
min-width: 58px;
|
min-width: 58px;
|
||||||
color: ${token.colorText};
|
color: ${token.colorText};
|
||||||
font-weight: 600;
|
font-weight: ${token.fontWeightStrong};
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -388,15 +388,15 @@ const GlobalStyle: React.FC = () => {
|
|||||||
${antCls}-row > div,
|
${antCls}-row > div,
|
||||||
.code-box-demo ${antCls}-row > div {
|
.code-box-demo ${antCls}-row > div {
|
||||||
min-height: 30px;
|
min-height: 30px;
|
||||||
margin-top: 8px;
|
margin-top: ${token.marginXS}px;
|
||||||
margin-bottom: 8px;
|
margin-bottom: ${token.marginXS}px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.code-box-demo ${antCls}-row > div:not(.gutter-row) {
|
.code-box-demo ${antCls}-row > div:not(.gutter-row) {
|
||||||
padding: 16px 0;
|
padding: ${token.padding}px 0;
|
||||||
background: ${demoGridColor};
|
background: ${demoGridColor};
|
||||||
|
|
||||||
&:nth-child(2n + 1) {
|
&:nth-child(2n + 1) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { css, Global } from '@emotion/react';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { css, Global } from '@emotion/react';
|
||||||
import { useTheme } from 'antd-style';
|
import { useTheme } from 'antd-style';
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
@ -39,11 +39,11 @@ export default () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.preview-image-box + .preview-image-box {
|
.preview-image-box + .preview-image-box {
|
||||||
margin-left: 24px;
|
margin-inline-start: ${token.marginLG}px;
|
||||||
|
|
||||||
.ant-row-rtl & {
|
.ant-row-rtl & {
|
||||||
margin-right: 24px;
|
margin-inline-end: ${token.marginLG}px;
|
||||||
margin-left: 0;
|
margin-inline-start: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ export default () => {
|
|||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 16px;
|
padding: ${token.padding}px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background: #f2f4f5;
|
background: #f2f4f5;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@ -97,15 +97,15 @@ export default () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.preview-image-title {
|
.preview-image-title {
|
||||||
margin-top: 20px;
|
margin-top: ${token.marginMD}px;
|
||||||
color: ${token.colorText};
|
color: ${token.colorText};
|
||||||
font-size: 12px;
|
font-size: ${token.fontSizeSM}px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-image-description {
|
.preview-image-description {
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
color: ${token.colorTextSecondary};
|
color: ${token.colorTextSecondary};
|
||||||
font-size: 12px;
|
font-size: ${token.fontSizeSM}px;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,11 +118,11 @@ export default () => {
|
|||||||
.preview-image-box img {
|
.preview-image-box img {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
padding: 12px;
|
padding: ${token.paddingSM}px;
|
||||||
background: ${token.colorBgContainer};
|
background: ${token.colorBgContainer};
|
||||||
border-radius: ${token.borderRadius}px;
|
border-radius: ${token.borderRadius}px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s;
|
transition: all ${token.motionDurationSlow};
|
||||||
|
|
||||||
&.no-padding {
|
&.no-padding {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@ -132,8 +132,12 @@ export default () => {
|
|||||||
|
|
||||||
.preview-image-boxes.preview-image-boxes-with-carousel img {
|
.preview-image-boxes.preview-image-boxes-with-carousel img {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
box-shadow: 0 1px 0 0 #ddd, 0 3px 0 0 ${token.colorBgContainer}, 0 4px 0 0 #ddd,
|
box-shadow:
|
||||||
0 6px 0 0 ${token.colorBgContainer}, 0 7px 0 0 #ddd;
|
0 1px 0 0 #ddd,
|
||||||
|
0 3px 0 0 ${token.colorBgContainer},
|
||||||
|
0 4px 0 0 #ddd,
|
||||||
|
0 6px 0 0 ${token.colorBgContainer},
|
||||||
|
0 7px 0 0 #ddd;
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-image-box img:hover {
|
.preview-image-box img:hover {
|
||||||
@ -162,7 +166,7 @@ export default () => {
|
|||||||
.motion-principle-wrapper {
|
.motion-principle-wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 900px;
|
max-width: 900px;
|
||||||
margin: 48px 0 24px;
|
margin: ${token.marginXXL}px 0 ${token.marginLG}px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.principle-wrapper {
|
.principle-wrapper {
|
||||||
@ -173,24 +177,24 @@ export default () => {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 180px;
|
min-height: 180px;
|
||||||
margin-right: 12.5%;
|
margin-inline-end: 12.5%;
|
||||||
margin-bottom: 24px;
|
margin-bottom: ${token.marginLG}px;
|
||||||
padding: 24px;
|
padding: ${token.paddingLG}px;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border: 1px solid #e8e8e8;
|
border: 1px solid #e8e8e8;
|
||||||
border-radius: 4px;
|
border-radius: ${token.borderRadiusSM}px;
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
margin-right: 0;
|
margin-inline-end: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
h4 {
|
h4 {
|
||||||
margin: 16px 0 8px;
|
margin: ${token.margin}px 0 ${token.marginXS}px;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
font-size: 12px;
|
font-size: ${token.fontSizeSM}px;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { css, Global } from '@emotion/react';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { css, Global } from '@emotion/react';
|
||||||
import { useTheme } from 'antd-style';
|
import { useTheme } from 'antd-style';
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
@ -70,10 +70,10 @@ export default () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ant-row-rtl {
|
.ant-row-rtl {
|
||||||
margin-right: 0;
|
margin-inline-end: 0;
|
||||||
margin-left: 0;
|
margin-inline-start: 0;
|
||||||
padding-right: 16px;
|
padding-inline-end: ${token.padding}px;
|
||||||
padding-left: 16px;
|
padding-inline-start: ${token.padding}px;
|
||||||
|
|
||||||
> .markdown > * {
|
> .markdown > * {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
@ -88,11 +88,10 @@ export default () => {
|
|||||||
|
|
||||||
.prev-next-nav {
|
.prev-next-nav {
|
||||||
width: calc(100% - 32px);
|
width: calc(100% - 32px);
|
||||||
margin-left: 16px;
|
margin-inline-start: ${token.margin}px;
|
||||||
|
|
||||||
.ant-row-rtl & {
|
.ant-row-rtl & {
|
||||||
margin-right: 16px;
|
margin-inline-end: ${token.margin}px;
|
||||||
margin-left: 64px;
|
margin-inline-start: 64px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,7 +136,7 @@ export default () => {
|
|||||||
|
|
||||||
.img-wrapper {
|
.img-wrapper {
|
||||||
position: initial;
|
position: initial;
|
||||||
margin-top: 20px;
|
margin-top: ${token.marginMD}px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
@ -150,7 +149,7 @@ export default () => {
|
|||||||
|
|
||||||
.text-wrapper {
|
.text-wrapper {
|
||||||
min-height: 200px;
|
min-height: 200px;
|
||||||
margin-top: 32px;
|
margin-top: ${token.marginXL}px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
@ -159,7 +158,7 @@ export default () => {
|
|||||||
|
|
||||||
p {
|
p {
|
||||||
color: #314659;
|
color: #314659;
|
||||||
font-size: 14px;
|
font-size: ${token.fontSize}px;
|
||||||
line-height: 28px;
|
line-height: 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,21 +169,21 @@ export default () => {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
.banner-btn {
|
.banner-btn {
|
||||||
padding: 0 20px;
|
padding: 0 ${token.paddingMD}px;
|
||||||
font-size: 14px;
|
font-size: ${token.fontSize}px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.banner-promote {
|
.banner-promote {
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
margin-top: 32px;
|
margin-top: ${token.marginXL}px;
|
||||||
|
|
||||||
.ant-divider {
|
.ant-divider {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
font-size: 14px;
|
font-size: ${token.fontSize}px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
@ -200,7 +199,6 @@ export default () => {
|
|||||||
|
|
||||||
.ant-row {
|
.ant-row {
|
||||||
margin: 24px auto 64px;
|
margin: 24px auto 64px;
|
||||||
|
|
||||||
> div {
|
> div {
|
||||||
margin-bottom: 48px;
|
margin-bottom: 48px;
|
||||||
}
|
}
|
||||||
@ -221,7 +219,7 @@ export default () => {
|
|||||||
|
|
||||||
&-product {
|
&-product {
|
||||||
min-height: auto;
|
min-height: auto;
|
||||||
padding: 0 16px;
|
padding: 0 ${token.padding}px;
|
||||||
|
|
||||||
.product-block {
|
.product-block {
|
||||||
margin-bottom: 34px;
|
margin-bottom: 34px;
|
||||||
@ -229,7 +227,7 @@ export default () => {
|
|||||||
border-bottom: 1px solid ${token.colorSplit};
|
border-bottom: 1px solid ${token.colorSplit};
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
margin-bottom: 32px;
|
margin-bottom: ${token.marginXL}px;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
|
|
||||||
.block-text-wrapper {
|
.block-text-wrapper {
|
||||||
@ -250,14 +248,14 @@ export default () => {
|
|||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
|
|
||||||
h4 {
|
h4 {
|
||||||
margin-bottom: 4px;
|
margin-bottom: ${token.marginXXS}px;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin-bottom: 8px;
|
margin-bottom: ${token.marginXS}px;
|
||||||
font-size: 12px;
|
font-size: ${token.fontSizeSM}px;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,8 +264,8 @@ export default () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.components-button-wrapper {
|
.components-button-wrapper {
|
||||||
margin-top: 16px;
|
margin-top: ${token.margin}px;
|
||||||
font-size: 12px;
|
font-size: ${token.fontSizeSM}px;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
display: block;
|
display: block;
|
||||||
@ -291,19 +289,18 @@ export default () => {
|
|||||||
|
|
||||||
.page3 {
|
.page3 {
|
||||||
min-height: 688px;
|
min-height: 688px;
|
||||||
background: url('https://gw.alipayobjects.com/zos/rmsportal/qICoJIqqQRMeRGhPHBBS.svg')
|
background-image: url('https://gw.alipayobjects.com/zos/rmsportal/qICoJIqqQRMeRGhPHBBS.svg');
|
||||||
no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
|
|
||||||
.ant-row {
|
.ant-row {
|
||||||
margin: 0 8px;
|
margin: 0 ${token.marginXS}px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page3-block {
|
.page3-block {
|
||||||
margin-bottom: 32px;
|
margin-bottom: ${token.marginXL}px;
|
||||||
padding: 24px;
|
padding: ${token.paddingLG}px;
|
||||||
background: ${token.colorBgContainer};
|
background: ${token.colorBgContainer};
|
||||||
border-radius: 4px;
|
border-radius: ${token.borderRadiusSM}px;
|
||||||
box-shadow: 0 8px 16px rgba(174, 185, 193, 0.3);
|
box-shadow: 0 8px 16px rgba(174, 185, 193, 0.3);
|
||||||
|
|
||||||
&:nth-child(2) {
|
&:nth-child(2) {
|
||||||
@ -315,7 +312,7 @@ export default () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
font-size: 12px;
|
font-size: ${token.fontSizeSM}px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page3-img-wrapper {
|
.page3-img-wrapper {
|
||||||
@ -330,7 +327,7 @@ export default () => {
|
|||||||
width: 80%;
|
width: 80%;
|
||||||
max-width: initial;
|
max-width: initial;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding-left: 16px;
|
padding-inline-start: ${token.padding}px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,8 @@ const useStyle = createStyles(({ token, css }) => {
|
|||||||
transform: translate3d(0, -100%, 0);
|
transform: translate3d(0, -100%, 0);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition:
|
transition:
|
||||||
opacity 0.3s,
|
opacity ${token.motionDurationSlow},
|
||||||
transform 0.3s;
|
transform ${token.motionDurationSlow};
|
||||||
|
|
||||||
${antCls}-tabs {
|
${antCls}-tabs {
|
||||||
max-width: 1208px;
|
max-width: 1208px;
|
||||||
|
@ -31,8 +31,8 @@ const useStyle = () => {
|
|||||||
.rc-footer-container {
|
.rc-footer-container {
|
||||||
max-width: ${articleMaxWidth}px;
|
max-width: ${articleMaxWidth}px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding-right: 0;
|
padding-inline-end: 0;
|
||||||
padding-left: 0;
|
padding-inline-start: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
@ -48,10 +48,9 @@ const useStyle = () => {
|
|||||||
article {
|
article {
|
||||||
padding: 0 ${resourcePaddingXS}px;
|
padding: 0 ${resourcePaddingXS}px;
|
||||||
}
|
}
|
||||||
|
|
||||||
${antCls}-col {
|
${antCls}-col {
|
||||||
padding-top: 16px !important;
|
padding-top: ${token.padding}px !important;
|
||||||
padding-bottom: 16px !important;
|
padding-bottom: ${token.padding}px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -76,7 +75,7 @@ const useStyle = () => {
|
|||||||
max-width: ${articleMaxWidth}px;
|
max-width: ${articleMaxWidth}px;
|
||||||
margin: 0 auto 56px;
|
margin: 0 auto 56px;
|
||||||
font-weight: 200;
|
font-weight: 200;
|
||||||
font-size: 16px;
|
font-size: ${token.fontSizeLG}px;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,15 +12,15 @@ const ANTD_IMG_URL =
|
|||||||
const useStyle = createStyles(({ token, css }) => ({
|
const useStyle = createStyles(({ token, css }) => ({
|
||||||
card: css`
|
card: css`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 40px 0;
|
margin: ${token.marginMD * 2}px 0;
|
||||||
transition: all 0.2s;
|
transition: all ${token.motionDurationMid};
|
||||||
background-color: ${token.colorFillQuaternary};
|
background-color: ${token.colorFillQuaternary};
|
||||||
`,
|
`,
|
||||||
bigTitle: css`
|
bigTitle: css`
|
||||||
font-size: 16px;
|
|
||||||
color: #121212;
|
color: #121212;
|
||||||
margin-bottom: 24px;
|
font-size: ${token.fontSizeLG}px;
|
||||||
font-weight: 600;
|
margin-bottom: ${token.marginLG}px;
|
||||||
|
font-weight: ${token.fontWeightStrong};
|
||||||
`,
|
`,
|
||||||
cardBody: css`
|
cardBody: css`
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -33,24 +33,24 @@ const useStyle = createStyles(({ token, css }) => ({
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
img {
|
img {
|
||||||
width: 200px;
|
width: 200px;
|
||||||
margin-right: 24px;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-radius: 8px;
|
margin-inline-end: ${token.marginLG}px;
|
||||||
|
border-radius: ${token.borderRadiusLG}px;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
title: css`
|
title: css`
|
||||||
color: #444;
|
color: #444;
|
||||||
font-size: 16px;
|
font-size: ${token.fontSizeLG}px;
|
||||||
font-weight: 600;
|
font-weight: ${token.fontWeightStrong};
|
||||||
`,
|
`,
|
||||||
subTitle: css`
|
subTitle: css`
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
color: #646464;
|
color: #646464;
|
||||||
font-size: 14px;
|
font-size: ${token.fontSize}px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
margin-top: 8px;
|
margin-top: ${token.marginXS}px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
@ -69,9 +69,9 @@ const useStyle = createStyles(({ token, css }) => ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.arrowIcon {
|
.arrowIcon {
|
||||||
margin: 0 8px;
|
|
||||||
color: #8a8f8d;
|
color: #8a8f8d;
|
||||||
font-size: 12px;
|
margin: 0 ${token.marginXS}px;
|
||||||
|
font-size: ${token.fontSizeSM}px;
|
||||||
}
|
}
|
||||||
.zl-btn {
|
.zl-btn {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -15,9 +15,9 @@ const useStyle = createStyles(({ token, css }) => ({
|
|||||||
margin: 1em 0 !important;
|
margin: 1em 0 !important;
|
||||||
`,
|
`,
|
||||||
title: css`
|
title: css`
|
||||||
font-size: 12px;
|
font-size: ${token.fontSizeSM}px;
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
margin-bottom: 8px;
|
margin-bottom: ${token.marginXS}px;
|
||||||
`,
|
`,
|
||||||
list: css`
|
list: css`
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -26,7 +26,7 @@ const useStyle = createStyles(({ token, css }) => ({
|
|||||||
li {
|
li {
|
||||||
height: 24px;
|
height: 24px;
|
||||||
transition: all ${token.motionDurationSlow};
|
transition: all ${token.motionDurationSlow};
|
||||||
margin-inline-end: -8px;
|
margin-inline-end: -${token.marginXS}px;
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
li {
|
li {
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React from 'react';
|
||||||
import { Anchor } from 'antd';
|
import { Anchor } from 'antd';
|
||||||
import { createStyles, useTheme } from 'antd-style';
|
import { createStyles, useTheme } from 'antd-style';
|
||||||
|
import type { AnchorLinkItemProps } from 'antd/es/anchor/Anchor';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { useRouteMeta, useTabMeta } from 'dumi';
|
import { useRouteMeta, useTabMeta } from 'dumi';
|
||||||
|
|
||||||
const useStyle = createStyles(({ token, css }) => {
|
const useStyle = createStyles(({ token, css }) => {
|
||||||
const { antCls } = token;
|
const { antCls } = token;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
toc: css`
|
toc: css`
|
||||||
${antCls}-anchor {
|
${antCls}-anchor {
|
||||||
${antCls}-anchor-link-title {
|
${antCls}-anchor-link-title {
|
||||||
font-size: 12px;
|
font-size: ${token.fontSizeSM}px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
@ -20,30 +20,25 @@ const useStyle = createStyles(({ token, css }) => {
|
|||||||
top: ${token.headerHeight + token.contentMarginTop - 8}px;
|
top: ${token.headerHeight + token.contentMarginTop - 8}px;
|
||||||
inset-inline-end: 0;
|
inset-inline-end: 0;
|
||||||
width: 160px;
|
width: 160px;
|
||||||
margin: 0 0 12px 0;
|
padding: ${token.paddingXS}px;
|
||||||
padding: 8px 0;
|
|
||||||
padding-inline: 4px 8px;
|
|
||||||
backdrop-filter: blur(8px);
|
|
||||||
border-radius: ${token.borderRadius}px;
|
border-radius: ${token.borderRadius}px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
margin-inline-end: calc(16px - 100vw + 100%);
|
margin-inline-end: calc(16px - 100vw + 100%);
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
|
|
||||||
.toc-debug {
|
.toc-debug {
|
||||||
color: ${token.purple6};
|
color: ${token.purple6};
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: ${token.purple5};
|
color: ${token.purple5};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> div {
|
> div {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-height: calc(100vh - ${token.headerHeight + token.contentMarginTop + 24}px) !important;
|
max-height: calc(100vh - ${token.headerHeight + token.contentMarginTop + 24}px) !important;
|
||||||
margin: 0 auto;
|
margin: auto;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding-inline: 4px;
|
padding: ${token.paddingXXS}px;
|
||||||
|
backdrop-filter: blur(8px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: ${token.screenLG}px) {
|
@media only screen and (max-width: ${token.screenLG}px) {
|
||||||
@ -60,7 +55,7 @@ const useStyle = createStyles(({ token, css }) => {
|
|||||||
@media only screen and (max-width: ${token.screenLG}px) {
|
@media only screen and (max-width: ${token.screenLG}px) {
|
||||||
&,
|
&,
|
||||||
&.rtl {
|
&.rtl {
|
||||||
padding: 0 48px;
|
padding: 0 ${token.paddingLG * 2}px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
@ -72,11 +67,11 @@ interface DocAnchorProps {
|
|||||||
debugDemos?: string[];
|
debugDemos?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
type AnchorItem = {
|
interface AnchorItem {
|
||||||
id: string;
|
id: string;
|
||||||
title: string;
|
title: string;
|
||||||
children?: AnchorItem[];
|
children?: AnchorItem[];
|
||||||
};
|
}
|
||||||
|
|
||||||
const DocAnchor: React.FC<DocAnchorProps> = ({ showDebug, debugDemos = [] }) => {
|
const DocAnchor: React.FC<DocAnchorProps> = ({ showDebug, debugDemos = [] }) => {
|
||||||
const { styles } = useStyle();
|
const { styles } = useStyle();
|
||||||
@ -84,24 +79,24 @@ const DocAnchor: React.FC<DocAnchorProps> = ({ showDebug, debugDemos = [] }) =>
|
|||||||
const meta = useRouteMeta();
|
const meta = useRouteMeta();
|
||||||
const tab = useTabMeta();
|
const tab = useTabMeta();
|
||||||
|
|
||||||
const renderAnchorItem = (item: AnchorItem) => ({
|
const renderAnchorItem = (item: AnchorItem): AnchorLinkItemProps => ({
|
||||||
href: `#${item.id}`,
|
href: `#${item.id}`,
|
||||||
title: item.title,
|
title: item.title,
|
||||||
key: item.id,
|
key: item.id,
|
||||||
children: item.children
|
children: item.children
|
||||||
?.filter((child) => showDebug || !debugDemos.includes(child.id))
|
?.filter((child) => showDebug || !debugDemos.includes(child.id))
|
||||||
.map((child) => ({
|
.map<AnchorLinkItemProps>((child) => ({
|
||||||
key: child.id,
|
key: child.id,
|
||||||
href: `#${child.id}`,
|
href: `#${child.id}`,
|
||||||
title: (
|
title: (
|
||||||
<span className={classNames(debugDemos.includes(child.id) && 'toc-debug')}>
|
<span className={classNames({ 'toc-debug': debugDemos.includes(child.id) })}>
|
||||||
{child?.title}
|
{child?.title}
|
||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
})),
|
})),
|
||||||
});
|
});
|
||||||
|
|
||||||
const anchorItems = useMemo(
|
const anchorItems = React.useMemo<AnchorItem[]>(
|
||||||
() =>
|
() =>
|
||||||
(tab?.toc || meta.toc).reduce<AnchorItem[]>((result, item) => {
|
(tab?.toc || meta.toc).reduce<AnchorItem[]>((result, item) => {
|
||||||
if (item.depth === 2) {
|
if (item.depth === 2) {
|
||||||
@ -129,7 +124,7 @@ const DocAnchor: React.FC<DocAnchorProps> = ({ showDebug, debugDemos = [] }) =>
|
|||||||
affix={false}
|
affix={false}
|
||||||
targetOffset={token.anchorTop}
|
targetOffset={token.anchorTop}
|
||||||
showInkInFixed
|
showInkInFixed
|
||||||
items={anchorItems.map(renderAnchorItem)}
|
items={anchorItems.map<AnchorLinkItemProps>(renderAnchorItem)}
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useContext, useLayoutEffect, useMemo } from 'react';
|
import React, { useContext, useLayoutEffect, useMemo, useState } from 'react';
|
||||||
import { Col, Flex, Typography } from 'antd';
|
import { Col, Flex, Typography } from 'antd';
|
||||||
import { createStyles } from 'antd-style';
|
import { createStyles } from 'antd-style';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
@ -30,7 +30,7 @@ const useStyle = createStyles(({ token, css }) => ({
|
|||||||
@media only screen and (max-width: ${token.screenLG}px) {
|
@media only screen and (max-width: ${token.screenLG}px) {
|
||||||
&,
|
&,
|
||||||
&.rtl {
|
&.rtl {
|
||||||
padding: 0 48px;
|
padding: 0 ${token.paddingLG * 2}px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
@ -43,6 +43,7 @@ const Content: React.FC<React.PropsWithChildren> = ({ children }) => {
|
|||||||
const { styles } = useStyle();
|
const { styles } = useStyle();
|
||||||
|
|
||||||
const [showDebug, setShowDebug] = useLayoutState(false);
|
const [showDebug, setShowDebug] = useLayoutState(false);
|
||||||
|
const [codeType, setCodeType] = useState('tsx');
|
||||||
const debugDemos = useMemo(
|
const debugDemos = useMemo(
|
||||||
() => meta.toc?.filter((item) => item._debug_demo).map((item) => item.id) || [],
|
() => meta.toc?.filter((item) => item._debug_demo).map((item) => item.id) || [],
|
||||||
[meta],
|
[meta],
|
||||||
@ -55,8 +56,8 @@ const Content: React.FC<React.PropsWithChildren> = ({ children }) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const contextValue = useMemo<DemoContextProps>(
|
const contextValue = useMemo<DemoContextProps>(
|
||||||
() => ({ showDebug, setShowDebug }),
|
() => ({ showDebug, setShowDebug, codeType, setCodeType }),
|
||||||
[showDebug, debugDemos],
|
[showDebug, codeType, debugDemos],
|
||||||
);
|
);
|
||||||
|
|
||||||
const isRTL = direction === 'rtl';
|
const isRTL = direction === 'rtl';
|
||||||
@ -98,12 +99,15 @@ const Content: React.FC<React.PropsWithChildren> = ({ children }) => {
|
|||||||
{meta.frontmatter.category === 'Components' &&
|
{meta.frontmatter.category === 'Components' &&
|
||||||
String(meta.frontmatter.showImport) !== 'false' && (
|
String(meta.frontmatter.showImport) !== 'false' && (
|
||||||
<ComponentMeta
|
<ComponentMeta
|
||||||
component={meta.frontmatter.title}
|
|
||||||
source
|
source
|
||||||
|
component={meta.frontmatter.title}
|
||||||
filename={meta.frontmatter.filename}
|
filename={meta.frontmatter.filename}
|
||||||
|
version={meta.frontmatter.tag}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<div style={{ minHeight: 'calc(100vh - 64px)' }}>{children}</div>
|
<div style={{ minHeight: 'calc(100vh - 64px)', width: 'calc(100% - 10px)' }}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
<InViewSuspense>
|
<InViewSuspense>
|
||||||
<ColumnCard
|
<ColumnCard
|
||||||
zhihuLink={meta.frontmatter.zhihu_url}
|
zhihuLink={meta.frontmatter.zhihu_url}
|
||||||
|
@ -2,11 +2,14 @@ import { createContext } from 'react';
|
|||||||
|
|
||||||
export type DemoContextProps = {
|
export type DemoContextProps = {
|
||||||
showDebug?: boolean;
|
showDebug?: boolean;
|
||||||
|
codeType?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const DemoContext = createContext<{
|
const DemoContext = createContext<{
|
||||||
showDebug?: boolean;
|
showDebug?: boolean;
|
||||||
setShowDebug?: (showDebug: boolean) => void;
|
setShowDebug?: (showDebug: boolean) => void;
|
||||||
|
codeType?: string;
|
||||||
|
setCodeType?: (codeType: string) => void;
|
||||||
}>({});
|
}>({});
|
||||||
|
|
||||||
export default DemoContext;
|
export default DemoContext;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { removeCSS, updateCSS } from 'rc-util/lib/Dom/dynamicCSS';
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { removeCSS, updateCSS } from 'rc-util/lib/Dom/dynamicCSS';
|
||||||
|
|
||||||
import useLocale from '../../../hooks/useLocale';
|
import useLocale from '../../../hooks/useLocale';
|
||||||
|
|
||||||
const whereCls = 'ant-where-checker';
|
const whereCls = 'ant-where-checker';
|
||||||
@ -20,7 +21,7 @@ const locales = {
|
|||||||
|
|
||||||
// Check for browser support `:where` or not
|
// Check for browser support `:where` or not
|
||||||
// Warning user if not support to modern browser
|
// Warning user if not support to modern browser
|
||||||
export default function InfoNewVersion() {
|
function InfoNewVersion() {
|
||||||
const [location] = useLocale(locales);
|
const [location] = useLocale(locales);
|
||||||
const [supportWhere, setSupportWhere] = React.useState(true);
|
const [supportWhere, setSupportWhere] = React.useState(true);
|
||||||
|
|
||||||
@ -84,3 +85,5 @@ export default function InfoNewVersion() {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default InfoNewVersion;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import React, { useContext } from 'react';
|
||||||
import {
|
import {
|
||||||
AntDesignOutlined,
|
AntDesignOutlined,
|
||||||
BgColorsOutlined,
|
BgColorsOutlined,
|
||||||
@ -14,11 +15,11 @@ import {
|
|||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { TinyColor } from '@ctrl/tinycolor';
|
import { TinyColor } from '@ctrl/tinycolor';
|
||||||
import { createStyles } from 'antd-style';
|
import { createStyles } from 'antd-style';
|
||||||
|
import getAlphaColor from 'antd/es/theme/util/getAlphaColor';
|
||||||
import { FormattedMessage, Link } from 'dumi';
|
import { FormattedMessage, Link } from 'dumi';
|
||||||
import RcFooter from 'rc-footer';
|
import RcFooter from 'rc-footer';
|
||||||
import type { FooterColumn } from 'rc-footer/lib/column';
|
import type { FooterColumn } from 'rc-footer/lib/column';
|
||||||
import React, { useContext } from 'react';
|
|
||||||
import getAlphaColor from 'antd/es/theme/util/getAlphaColor';
|
|
||||||
import useLocale from '../../../hooks/useLocale';
|
import useLocale from '../../../hooks/useLocale';
|
||||||
import useLocation from '../../../hooks/useLocation';
|
import useLocation from '../../../hooks/useLocation';
|
||||||
import SiteContext from '../SiteContext';
|
import SiteContext from '../SiteContext';
|
||||||
@ -246,7 +247,7 @@ const Footer: React.FC = () => {
|
|||||||
en: 'JoinUs',
|
en: 'JoinUs',
|
||||||
}),
|
}),
|
||||||
LinkComponent: Link,
|
LinkComponent: Link,
|
||||||
} as unknown as typeof col2['items'][number]);
|
} as unknown as (typeof col2)['items'][number]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const col3 = {
|
const col3 = {
|
||||||
|
@ -30,7 +30,7 @@ const useStyle = createStyles(({ token, css }) => {
|
|||||||
img {
|
img {
|
||||||
height: 32px;
|
height: 32px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
margin-inline-end: 12px;
|
margin-inline-end: ${token.marginSM}px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: ${mobileMaxWidth}px) {
|
@media only screen and (max-width: ${mobileMaxWidth}px) {
|
||||||
|
@ -30,13 +30,21 @@ const locales = {
|
|||||||
|
|
||||||
// ============================= Style =============================
|
// ============================= Style =============================
|
||||||
const useStyle = createStyles(({ token }) => {
|
const useStyle = createStyles(({ token }) => {
|
||||||
const { antCls, iconCls, fontFamily, headerHeight, menuItemBorder, colorPrimary, colorText } =
|
const {
|
||||||
token;
|
antCls,
|
||||||
|
iconCls,
|
||||||
|
fontFamily,
|
||||||
|
fontSize,
|
||||||
|
headerHeight,
|
||||||
|
menuItemBorder,
|
||||||
|
colorPrimary,
|
||||||
|
colorText,
|
||||||
|
} = token;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
nav: css`
|
nav: css`
|
||||||
height: 100%;
|
height: 100%;
|
||||||
font-size: 14px;
|
font-size: ${fontSize}px;
|
||||||
font-family: Avenir, ${fontFamily}, sans-serif;
|
font-family: Avenir, ${fontFamily}, sans-serif;
|
||||||
border: 0;
|
border: 0;
|
||||||
|
|
||||||
@ -46,8 +54,8 @@ const useStyle = createStyles(({ token }) => {
|
|||||||
& > ${antCls}-menu-item, & > ${antCls}-menu-submenu {
|
& > ${antCls}-menu-item, & > ${antCls}-menu-submenu {
|
||||||
min-width: ${40 + 12 * 2}px;
|
min-width: ${40 + 12 * 2}px;
|
||||||
height: ${headerHeight}px;
|
height: ${headerHeight}px;
|
||||||
padding-right: 12px;
|
padding-inline-end: ${token.paddingSM}px;
|
||||||
padding-left: 12px;
|
padding-inline-start: ${token.paddingSM}px;
|
||||||
line-height: ${headerHeight}px;
|
line-height: ${headerHeight}px;
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
@ -92,11 +100,11 @@ const useStyle = createStyles(({ token }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
${antCls}-menu-item-group-title {
|
${antCls}-menu-item-group-title {
|
||||||
padding-left: 24px;
|
padding-inline-start: ${token.paddingLG}px;
|
||||||
}
|
}
|
||||||
|
|
||||||
${antCls}-menu-item-group-list {
|
${antCls}-menu-item-group-list {
|
||||||
padding: 0 16px;
|
padding: 0 ${token.paddingLG}px;
|
||||||
}
|
}
|
||||||
|
|
||||||
${antCls}-menu-item,
|
${antCls}-menu-item,
|
||||||
|
@ -83,7 +83,7 @@ const useStyle = createStyles(({ token, css }) => {
|
|||||||
color: ${searchIconColor};
|
color: ${searchIconColor};
|
||||||
background-color: rgba(150, 150, 150, 0.06);
|
background-color: rgba(150, 150, 150, 0.06);
|
||||||
border-color: rgba(100, 100, 100, 0.2);
|
border-color: rgba(100, 100, 100, 0.2);
|
||||||
border-radius: 4px;
|
border-radius: ${token.borderRadiusSM}px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dumi-default-search-popover {
|
.dumi-default-search-popover {
|
||||||
@ -101,7 +101,7 @@ const useStyle = createStyles(({ token, css }) => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
column-gap: 12px;
|
column-gap: ${token.paddingSM}px;
|
||||||
> * {
|
> * {
|
||||||
flex: none;
|
flex: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -21,14 +21,14 @@ const useStyle = createStyles(({ token, css }) => {
|
|||||||
> ${antCls}-menu-item,
|
> ${antCls}-menu-item,
|
||||||
${antCls}-menu-item a {
|
${antCls}-menu-item a {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
font-size: 14px;
|
font-size: ${token.fontSize}px;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
> ${antCls}-menu-item-group > ${antCls}-menu-item-group-title {
|
> ${antCls}-menu-item-group > ${antCls}-menu-item-group-title {
|
||||||
margin-top: 16px;
|
margin-top: ${token.margin}px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: ${token.margin}px;
|
||||||
font-size: 13px;
|
font-size: ${token.fontSize}px;
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -53,32 +53,32 @@ const useStyle = createStyles(({ token, css }) => {
|
|||||||
> ${antCls}-menu-item-group
|
> ${antCls}-menu-item-group
|
||||||
> ${antCls}-menu-item-group-list
|
> ${antCls}-menu-item-group-list
|
||||||
> ${antCls}-menu-item {
|
> ${antCls}-menu-item {
|
||||||
padding-left: 40px !important;
|
padding-inline-start: 40px !important;
|
||||||
|
|
||||||
${antCls}-row-rtl & {
|
${antCls}-row-rtl & {
|
||||||
padding-right: 40px !important;
|
padding-inline-end: 40px !important;
|
||||||
padding-left: 16px !important;
|
padding-inline-start: ${token.padding}px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nest Category > Type > Article
|
// Nest Category > Type > Article
|
||||||
&${antCls}-menu-inline {
|
&${antCls}-menu-inline {
|
||||||
${antCls}-menu-item-group-title {
|
${antCls}-menu-item-group-title {
|
||||||
margin-left: 4px;
|
margin-inline-start: ${token.marginXXS}px;
|
||||||
padding-left: 60px;
|
padding-inline-start: 60px;
|
||||||
|
|
||||||
${antCls}-row-rtl & {
|
${antCls}-row-rtl & {
|
||||||
padding-right: 60px;
|
padding-inline-end: 60px;
|
||||||
padding-left: 16px;
|
padding-inline-start: ${token.padding}px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
${antCls}-menu-item-group-list > ${antCls}-menu-item {
|
${antCls}-menu-item-group-list > ${antCls}-menu-item {
|
||||||
padding-left: 80px !important;
|
padding-inline-start: 80px !important;
|
||||||
|
|
||||||
${antCls}-row-rtl & {
|
${antCls}-row-rtl & {
|
||||||
padding-right: 80px !important;
|
padding-inline-end: 80px !important;
|
||||||
padding-left: 16px !important;
|
padding-inline-start: ${token.padding}px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,13 +93,6 @@ const useStyle = createStyles(({ token, css }) => {
|
|||||||
a[disabled] {
|
a[disabled] {
|
||||||
color: #ccc;
|
color: #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chinese {
|
|
||||||
margin-left: 6px;
|
|
||||||
font-weight: normal;
|
|
||||||
font-size: 12px;
|
|
||||||
opacity: 0.67;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
mainMenu: css`
|
mainMenu: css`
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
@ -3,5 +3,5 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"resolveJsonModule": true
|
"resolveJsonModule": true
|
||||||
},
|
},
|
||||||
"include": ["**/*"]
|
"include": ["**/*", "../typings/index.d.ts"]
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@ module.exports = {
|
|||||||
'no-unused-expressions': 'off',
|
'no-unused-expressions': 'off',
|
||||||
'@typescript-eslint/no-unused-expressions': 2,
|
'@typescript-eslint/no-unused-expressions': 2,
|
||||||
'@typescript-eslint/consistent-type-imports': [2, { disallowTypeAnnotations: false }],
|
'@typescript-eslint/consistent-type-imports': [2, { disallowTypeAnnotations: false }],
|
||||||
|
'import/consistent-type-specifier-style': 2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -173,6 +174,7 @@ module.exports = {
|
|||||||
'site/**',
|
'site/**',
|
||||||
'tests/**',
|
'tests/**',
|
||||||
'scripts/**',
|
'scripts/**',
|
||||||
|
'scripts/*.ts',
|
||||||
'**/*.test.js',
|
'**/*.test.js',
|
||||||
'**/__tests__/*',
|
'**/__tests__/*',
|
||||||
'*.config.js',
|
'*.config.js',
|
||||||
|
2
.github/workflows/preview-build.yml
vendored
2
.github/workflows/preview-build.yml
vendored
@ -122,4 +122,4 @@ jobs:
|
|||||||
path: _site
|
path: _site
|
||||||
|
|
||||||
- name: run e2e test
|
- name: run e2e test
|
||||||
run: npm run site:test
|
run: npm run test:site
|
||||||
|
2
.github/workflows/site-deploy.yml
vendored
2
.github/workflows/site-deploy.yml
vendored
@ -83,7 +83,7 @@ jobs:
|
|||||||
run: echo "VERSION=$(echo ${{ github.ref_name }} | sed 's/\./-/g')" >> $GITHUB_OUTPUT
|
run: echo "VERSION=$(echo ${{ github.ref_name }} | sed 's/\./-/g')" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Deploy to GitHub Pages
|
- name: Deploy to GitHub Pages
|
||||||
uses: peaceiris/actions-gh-pages@v3
|
uses: peaceiris/actions-gh-pages@v4
|
||||||
with:
|
with:
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
publish_dir: ./_site
|
publish_dir: ./_site
|
||||||
|
74
.github/workflows/test.yml
vendored
74
.github/workflows/test.yml
vendored
@ -51,6 +51,7 @@ jobs:
|
|||||||
|
|
||||||
lint:
|
lint:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs: setup
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@ -79,10 +80,10 @@ jobs:
|
|||||||
|
|
||||||
- name: lint:react-17
|
- name: lint:react-17
|
||||||
run: npm run compile && npm run install-react-17 && npm run tsc:old
|
run: npm run compile && npm run install-react-17 && npm run tsc:old
|
||||||
needs: setup
|
|
||||||
|
|
||||||
check_metadata:
|
check_metadata:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs: setup
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@ -102,44 +103,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: node_modules
|
path: node_modules
|
||||||
key: node_modules-${{ hashFiles('**/package-temp-dir/package-lock.json') }}
|
key: node_modules-${{ hashFiles('**/package-temp-dir/package-lock.json') }}
|
||||||
needs: setup
|
|
||||||
|
|
||||||
################################ Dist ################################
|
|
||||||
dist:
|
|
||||||
name: dist
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 18
|
|
||||||
|
|
||||||
- name: restore cache from package-lock.json
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: package-temp-dir
|
|
||||||
key: lock-${{ github.sha }}
|
|
||||||
|
|
||||||
- name: restore cache from node_modules
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: node_modules
|
|
||||||
key: node_modules-${{ hashFiles('**/package-temp-dir/package-lock.json') }}
|
|
||||||
|
|
||||||
- name: cache dist
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: dist
|
|
||||||
key: dist-${{ github.sha }}
|
|
||||||
|
|
||||||
- name: dist
|
|
||||||
run: npm run dist
|
|
||||||
env:
|
|
||||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
|
||||||
CI: 1
|
|
||||||
needs: setup
|
|
||||||
|
|
||||||
################################ Test ################################
|
################################ Test ################################
|
||||||
normal-test:
|
normal-test:
|
||||||
@ -152,6 +115,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
REACT: ${{ matrix.react }}
|
REACT: ${{ matrix.react }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@ -222,7 +186,7 @@ jobs:
|
|||||||
# node test
|
# node test
|
||||||
- name: node test
|
- name: node test
|
||||||
if: ${{ matrix.module == 'node' }}
|
if: ${{ matrix.module == 'node' }}
|
||||||
run: npm run test-node
|
run: npm run test:node
|
||||||
|
|
||||||
# dist test
|
# dist test
|
||||||
- name: dist test
|
- name: dist test
|
||||||
@ -237,13 +201,12 @@ jobs:
|
|||||||
run: npm test
|
run: npm test
|
||||||
env:
|
env:
|
||||||
LIB_DIR: dist-min
|
LIB_DIR: dist-min
|
||||||
needs: [setup, dist]
|
|
||||||
|
|
||||||
############################ Test Coverage ###########################
|
############################ Test Coverage ###########################
|
||||||
upload-test-coverage:
|
upload-test-coverage:
|
||||||
name: test-coverage
|
name: test-coverage
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [normal-test]
|
needs: normal-test
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
@ -268,8 +231,9 @@ jobs:
|
|||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
|
||||||
########################### Compile & Test ###########################
|
########################### Compile & Test ###########################
|
||||||
compile:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs: setup
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@ -311,11 +275,32 @@ jobs:
|
|||||||
- name: check use client
|
- name: check use client
|
||||||
run: node ./tests/dekko/use-client.test.js
|
run: node ./tests/dekko/use-client.test.js
|
||||||
|
|
||||||
needs: setup
|
- name: cache dist
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: dist
|
||||||
|
key: dist-${{ github.sha }}
|
||||||
|
|
||||||
|
- name: dist
|
||||||
|
run: npm run dist
|
||||||
|
env:
|
||||||
|
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||||
|
CI: 1
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||||
|
with:
|
||||||
|
name: build artifacts
|
||||||
|
path: |
|
||||||
|
dist
|
||||||
|
locale
|
||||||
|
es
|
||||||
|
lib
|
||||||
|
|
||||||
compiled-module-test:
|
compiled-module-test:
|
||||||
name: module test
|
name: module test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
react: ['16', '17', '18']
|
react: ['16', '17', '18']
|
||||||
@ -375,4 +360,3 @@ jobs:
|
|||||||
run: npm test -- --maxWorkers=2 --shard=${{matrix.shard}}
|
run: npm test -- --maxWorkers=2 --shard=${{matrix.shard}}
|
||||||
env:
|
env:
|
||||||
LIB_DIR: ${{ matrix.module }}
|
LIB_DIR: ${{ matrix.module }}
|
||||||
needs: compile
|
|
||||||
|
2
.github/workflows/upgrade-deps.yml
vendored
2
.github/workflows/upgrade-deps.yml
vendored
@ -8,7 +8,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
upgrade-deps:
|
upgrade-deps:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.ref == 'refs/heads/master'
|
if: github.repository == 'ant-design/ant-design' && github.ref == 'refs/heads/master'
|
||||||
permissions:
|
permissions:
|
||||||
pull-requests: write # for peter-evans/create-pull-request to create PRs
|
pull-requests: write # for peter-evans/create-pull-request to create PRs
|
||||||
contents: write # for git push
|
contents: write # for git push
|
||||||
|
@ -80,7 +80,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
node node_modules/puppeteer/install.mjs
|
node node_modules/puppeteer/install.mjs
|
||||||
npm run version
|
npm run version
|
||||||
npm run test-image
|
npm run test:image
|
||||||
env:
|
env:
|
||||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ jobs:
|
|||||||
EVENT_NUMBER: ${{ github.event.number }}
|
EVENT_NUMBER: ${{ github.event.number }}
|
||||||
BASE_REF: ${{ github.base_ref }}
|
BASE_REF: ${{ github.base_ref }}
|
||||||
run: |
|
run: |
|
||||||
npm run visual-regression -- --pr-id=$EVENT_NUMBER --base-ref=$BASE_REF
|
npm run test:visual-regression -- --pr-id=$EVENT_NUMBER --base-ref=$BASE_REF
|
||||||
|
|
||||||
# Upload report in `visualRegressionReport`
|
# Upload report in `visualRegressionReport`
|
||||||
- name: upload report artifact
|
- name: upload report artifact
|
||||||
|
@ -72,11 +72,12 @@ jobs:
|
|||||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||||
run_id: ${{ github.event.workflow_run.id }}
|
run_id: ${{ github.event.workflow_run.id }}
|
||||||
name: visual-regression-diff-ref
|
name: visual-regression-diff-ref
|
||||||
|
path: ./tmp
|
||||||
|
|
||||||
# Save PR id to output
|
# Save PR id to output
|
||||||
- name: save PR id
|
- name: save PR id
|
||||||
id: pr
|
id: pr
|
||||||
run: echo "id=$(<visual-regression-pr-id.txt)" >> $GITHUB_OUTPUT
|
run: echo "id=$(<tmp/visual-regression-pr-id.txt)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
# Download report artifact
|
# Download report artifact
|
||||||
- name: download report artifact
|
- name: download report artifact
|
||||||
@ -87,6 +88,7 @@ jobs:
|
|||||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||||
run_id: ${{ github.event.workflow_run.id }}
|
run_id: ${{ github.event.workflow_run.id }}
|
||||||
name: visual-regression-report
|
name: visual-regression-report
|
||||||
|
path: ./tmp
|
||||||
|
|
||||||
# unzip report and then upload them to oss
|
# unzip report and then upload them to oss
|
||||||
- name: upload visual-regression report
|
- name: upload visual-regression report
|
||||||
@ -97,7 +99,7 @@ jobs:
|
|||||||
PR_ID: ${{ steps.pr.outputs.id }}
|
PR_ID: ${{ steps.pr.outputs.id }}
|
||||||
run: |
|
run: |
|
||||||
mkdir ./visualRegressionReport
|
mkdir ./visualRegressionReport
|
||||||
tar -xzvf visualRegressionReport.tar.gz -C ./visualRegressionReport
|
tar -xzvf tmp/visualRegressionReport.tar.gz -C ./visualRegressionReport
|
||||||
echo "✅ Uncompress Finished"
|
echo "✅ Uncompress Finished"
|
||||||
|
|
||||||
rm package.json
|
rm package.json
|
||||||
|
@ -70,11 +70,12 @@ jobs:
|
|||||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||||
run_id: ${{ github.event.workflow_run.id }}
|
run_id: ${{ github.event.workflow_run.id }}
|
||||||
name: visual-regression-ref
|
name: visual-regression-ref
|
||||||
|
path: ./tmp
|
||||||
|
|
||||||
# Save visual-regression ref to output
|
# Save visual-regression ref to output
|
||||||
- name: Extra Visual Regression Ref
|
- name: Extra Visual Regression Ref
|
||||||
id: visual_regression
|
id: visual_regression
|
||||||
run: echo "id=$(<visual-regression-ref.txt)" >> $GITHUB_OUTPUT
|
run: echo "id=$(<tmp/visual-regression-ref.txt)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Download Visual-Regression Artifact
|
- name: Download Visual-Regression Artifact
|
||||||
if: ${{ fromJSON(needs.upstream-workflow-summary.outputs.build-success) }}
|
if: ${{ fromJSON(needs.upstream-workflow-summary.outputs.build-success) }}
|
||||||
@ -83,10 +84,10 @@ jobs:
|
|||||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||||
run_id: ${{ github.event.workflow_run.id }}
|
run_id: ${{ github.event.workflow_run.id }}
|
||||||
name: image-snapshots
|
name: image-snapshots
|
||||||
path: ./
|
path: ./tmp
|
||||||
|
|
||||||
- name: Persist Image Snapshot to OSS
|
- 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')
|
if: github.repository == 'ant-design/ant-design' && github.event.workflow_run.event == 'push' && (github.event.workflow_run.head_branch == 'master' || github.event.workflow_run.head_branch == 'feature')
|
||||||
env:
|
env:
|
||||||
ALI_OSS_AK_ID: ${{ secrets.ALI_OSS_AK_ID }}
|
ALI_OSS_AK_ID: ${{ secrets.ALI_OSS_AK_ID }}
|
||||||
ALI_OSS_AK_SECRET: ${{ secrets.ALI_OSS_AK_SECRET }}
|
ALI_OSS_AK_SECRET: ${{ secrets.ALI_OSS_AK_SECRET }}
|
||||||
@ -97,6 +98,10 @@ jobs:
|
|||||||
npm i ali-oss --no-save
|
npm i ali-oss --no-save
|
||||||
echo "✅ Install `ali-oss` Finished"
|
echo "✅ Install `ali-oss` Finished"
|
||||||
|
|
||||||
|
echo "🔍 Preparing"
|
||||||
|
mv ./tmp/imageSnapshots.tar.gz ./imageSnapshots.tar.gz
|
||||||
|
mv ./tmp/visual-regression-ref.txt ./visual-regression-ref.txt
|
||||||
|
|
||||||
echo "🤖 Uploading"
|
echo "🤖 Uploading"
|
||||||
node scripts/visual-regression/upload.js ./imageSnapshots.tar.gz --ref=$HEAD_SHA
|
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
|
node scripts/visual-regression/upload.js ./visual-regression-ref.txt --ref=$HEAD_BRANCH
|
||||||
|
@ -70,7 +70,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
node node_modules/puppeteer/install.mjs
|
node node_modules/puppeteer/install.mjs
|
||||||
npm run version
|
npm run version
|
||||||
npm run test-image
|
npm run test:image
|
||||||
tar -czvf imageSnapshots.tar.gz imageSnapshots/*
|
tar -czvf imageSnapshots.tar.gz imageSnapshots/*
|
||||||
env:
|
env:
|
||||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -36,6 +36,7 @@ config/base.yaml
|
|||||||
yarn.lock
|
yarn.lock
|
||||||
package-lock.json
|
package-lock.json
|
||||||
pnpm-lock.yaml
|
pnpm-lock.yaml
|
||||||
|
bun.lockb
|
||||||
.pnpm-debug.log
|
.pnpm-debug.log
|
||||||
components/**/*.js
|
components/**/*.js
|
||||||
components/**/*.jsx
|
components/**/*.jsx
|
||||||
@ -43,6 +44,7 @@ components/**/*.jsx
|
|||||||
!components/**/__tests__/**/*.js.snap
|
!components/**/__tests__/**/*.js.snap
|
||||||
/.history
|
/.history
|
||||||
*.tmp
|
*.tmp
|
||||||
|
artifacts.zip
|
||||||
server/
|
server/
|
||||||
|
|
||||||
# Docs templates
|
# Docs templates
|
||||||
|
@ -11,7 +11,12 @@ module.exports = {
|
|||||||
packageManager: 'npm',
|
packageManager: 'npm',
|
||||||
dep: ['prod'], // check only prod dependencies
|
dep: ['prod'], // check only prod dependencies
|
||||||
// https://github.com/raineorshine/npm-check-updates#filter
|
// https://github.com/raineorshine/npm-check-updates#filter
|
||||||
filter: (name) => check.some((prefix) => name.startsWith(prefix)),
|
filter: (name) => {
|
||||||
|
if (name === '@ant-design/cssinjs') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return check.some((prefix) => name.startsWith(prefix));
|
||||||
|
},
|
||||||
// https://github.com/raineorshine/npm-check-updates#target
|
// https://github.com/raineorshine/npm-check-updates#target
|
||||||
target: (name, semver) => {
|
target: (name, semver) => {
|
||||||
const { operator } = semver[0] ?? {};
|
const { operator } = semver[0] ?? {};
|
||||||
|
@ -31,3 +31,4 @@ components/*/*.jsx
|
|||||||
.eslintignore
|
.eslintignore
|
||||||
.history
|
.history
|
||||||
**/*.yml
|
**/*.yml
|
||||||
|
*.html
|
@ -52,5 +52,6 @@
|
|||||||
"5.12.6": ["https://github.com/ant-design/ant-design/issues/46719"],
|
"5.12.6": ["https://github.com/ant-design/ant-design/issues/46719"],
|
||||||
"5.13.0": ["https://github.com/ant-design/ant-design/pull/46962"],
|
"5.13.0": ["https://github.com/ant-design/ant-design/pull/46962"],
|
||||||
"5.14.0": ["https://github.com/ant-design/ant-design/issues/47354"],
|
"5.14.0": ["https://github.com/ant-design/ant-design/issues/47354"],
|
||||||
"5.15.0": ["https://github.com/ant-design/ant-design/pull/47504#issuecomment-1980459433"]
|
"5.15.0": ["https://github.com/ant-design/ant-design/pull/47504#issuecomment-1980459433"],
|
||||||
|
">= 5.16.0 <= 5.16.1": ["https://github.com/ant-design/ant-design/issues/48200"]
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,63 @@ tag: vVERSION
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 5.16.2
|
||||||
|
|
||||||
|
`2024-04-15`
|
||||||
|
|
||||||
|
- 🐞 Fix Input.OTP controlled `value` to `''` not work as expect. [#48399](https://github.com/ant-design/ant-design/pull/48399)
|
||||||
|
- 🐞 Fix DatePicker of `multiple` with week picker not show the selection on the panel. [#48355](https://github.com/ant-design/ant-design/pull/48355)
|
||||||
|
- 🐞 Fix Upload `listType` with `picture-card` or `picture-circle` has additional space on top. [#48370](https://github.com/ant-design/ant-design/pull/48370)
|
||||||
|
- Typography
|
||||||
|
- 🐞 Fix Typography dynamic set `copyable` or `editable` will not show the operation button. [#48350](https://github.com/ant-design/ant-design/pull/48350)
|
||||||
|
- 🐞 Fix Typography dynamic update `copyable.text` not working. [#48347](https://github.com/ant-design/ant-design/pull/48347)
|
||||||
|
- 🐞 Fix Typography using `ellipsis` config with `expandable="collapsible"` and `row={1}` at both time will make ellipsis not working as expect. [#48340](https://github.com/ant-design/ant-design/pull/48340)
|
||||||
|
- 💄 Fix Steps in compact theme not show the correct progress style. [#48251](https://github.com/ant-design/ant-design/pull/48251)
|
||||||
|
- 💄 Refactor Tabs and wave-related components CSS duration values with `motionDurationSlow` Component Token. [#48311](https://github.com/ant-design/ant-design/pull/48311) [#48312](https://github.com/ant-design/ant-design/pull/48312) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||||
|
- 🇯🇵 Add Transfer missing ja_JP translations. [#48411](https://github.com/ant-design/ant-design/pull/48411) [@Inshiku-Han](https://github.com/Inshiku-Han)
|
||||||
|
- 🌐 Fix Picker ja-JP and ko-KR translations. [#48382](https://github.com/ant-design/ant-design/pull/48382) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||||
|
- 🛠 Use constant instead of enumeration to reduce package size. [#48406](https://github.com/ant-design/ant-design/pull/48406) [@kiner-tang](https://github.com/kiner-tang)
|
||||||
|
|
||||||
|
## 5.16.1
|
||||||
|
|
||||||
|
`2024-04-05`
|
||||||
|
|
||||||
|
- 🛠 Adjust Typography `ellipsis` logic to use CSS ellipsis in SSR to enhance user experience. [#48205](https://github.com/ant-design/ant-design/pull/48205)
|
||||||
|
- 🐞 Fix FloatButton config `tooltip` and `badge` at same time will make `badge` customize background not working. [#48198](https://github.com/ant-design/ant-design/pull/48198) [@LonelySnowman](https://github.com/LonelySnowman)
|
||||||
|
|
||||||
|
## 5.16.0
|
||||||
|
|
||||||
|
`2024-03-31`
|
||||||
|
|
||||||
|
- 🔥 New component Input.OTP support. [#48076](https://github.com/ant-design/ant-design/pull/48076)
|
||||||
|
- 🆕 Closable components support `aria-*` in `closable`. [@kiner-tang](https://github.com/kiner-tang)
|
||||||
|
- 🆕 [Tag](https://github.com/ant-design/ant-design/pull/47678)
|
||||||
|
- 🆕 [Notification](https://github.com/ant-design/ant-design/pull/47710)
|
||||||
|
- 🆕 Table add `rowHoverable` to control hover effect. [#48112](https://github.com/ant-design/ant-design/pull/48112) [@madocto](https://github.com/madocto)
|
||||||
|
- 🆕 Typography support async copy. [#48123](https://github.com/ant-design/ant-design/pull/48123) [@crazyair](https://github.com/crazyair)
|
||||||
|
- 🆕 Progress support `steps` with `circle`. [#47940](https://github.com/ant-design/ant-design/pull/47940) [@yykoypj](https://github.com/yykoypj)
|
||||||
|
- 🆕 Table support `onScroll` event for table body scroll. [#47986](https://github.com/ant-design/ant-design/pull/47986)
|
||||||
|
- 🆕 Typography ellipsis supports expand and collapse. [#47264](https://github.com/ant-design/ant-design/pull/47264) [@crazyair](https://github.com/crazyair)
|
||||||
|
- 🆕 ConfigProvider support configuring FloatButton.Group `closeIcon`. [#47953](https://github.com/ant-design/ant-design/pull/47953) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||||
|
- 🆕 Table support `showSorterTooltip.target` prop for sorters. [#47409](https://github.com/ant-design/ant-design/pull/47409) [@Ke1sy](https://github.com/Ke1sy)
|
||||||
|
- 🆕 Cascader support `optionRender`. [#47727](https://github.com/ant-design/ant-design/pull/47727) [@crazyair](https://github.com/crazyair)
|
||||||
|
- ⌨️ Popover can be closed by ESC when trigger is `focus` or `click`. [#47928](https://github.com/ant-design/ant-design/pull/47928) [@CooperHash](https://github.com/CooperHash)
|
||||||
|
- 🐞 Fix Button that vertically center icons when icon-only. [#48178](https://github.com/ant-design/ant-design/pull/48178) [@momesana](https://github.com/momesana)
|
||||||
|
- 🐞 Fix Modal.confirm content is not centered when icon is null. [#48173](https://github.com/ant-design/ant-design/pull/48173)
|
||||||
|
- Form [#48163](https://github.com/ant-design/ant-design/pull/48163) [@madocto](https://github.com/madocto)
|
||||||
|
- 🐞 Fix Form `getValueProps` shouldn't work when FormItem's `name` doesn't exist .
|
||||||
|
- 🐞 Fix Form's `setFieldsValue` should tread same as `setFields`.
|
||||||
|
- 🐞 Fixe Table that internationalization of table columns fails when searching. [#48126](https://github.com/ant-design/ant-design/pull/48126) [@LingJinT](https://github.com/LingJinT)
|
||||||
|
- 🐞 Fix Upload that `onChange` should be triggered when `fileList.length` is larger than `maxCount`. [#47747](https://github.com/ant-design/ant-design/pull/47747) [@Zhou-Bill](https://github.com/Zhou-Bill)
|
||||||
|
- 🐞 Fix Carousel several <a href="https://github.com/ant-design/react-slick/pull/110" data-hovercard-type="pull_request" data-hovercard-url="/ant-design/react-slick/pull/110/hovercard">bugs</a> by upgrading react-slick changes and renewing TS type. [#48093](https://github.com/ant-design/ant-design/pull/48093)
|
||||||
|
- 🐞 Fix ColorPicker that displayed cleared color not change after `value` changed. [#47816](https://github.com/ant-design/ant-design/pull/47816) [@MadCcc](https://github.com/MadCcc)
|
||||||
|
- 🐞 Make Badge consistent with Tag that applay `colorInfo` token in processing. [#47695](https://github.com/ant-design/ant-design/pull/47695) [@pfdgithub](https://github.com/pfdgithub)
|
||||||
|
- 🇮🇸 Add missing form translations in is_IS. [#48104](https://github.com/ant-design/ant-design/pull/48104) [@LonelySnowman](https://github.com/LonelySnowman)
|
||||||
|
- 🇺🇿 Add Uzbek(latn) locale. [#47899](https://github.com/ant-design/ant-design/pull/47899)
|
||||||
|
- TypeScript
|
||||||
|
- 🤖 Improve Transfer's `key` type, change `key: string` to `key: React.Key`. [#47879](https://github.com/ant-design/ant-design/pull/47879) [@madocto](https://github.com/madocto)
|
||||||
|
- 🤖 Table support for generic pairs dataIndex props verification . [@crazyair](https://github.com/crazyair)
|
||||||
|
|
||||||
## 5.15.4
|
## 5.15.4
|
||||||
|
|
||||||
`2024-03-25`
|
`2024-03-25`
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
---
|
---
|
||||||
order: 6
|
order: 6
|
||||||
title: 更新日志
|
title: 更新日志
|
||||||
toc: false
|
|
||||||
timeline: true
|
timeline: true
|
||||||
tag: vVERSION
|
tag: vVERSION
|
||||||
---
|
---
|
||||||
@ -16,6 +15,63 @@ tag: vVERSION
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 5.16.2
|
||||||
|
|
||||||
|
`2024-04-15`
|
||||||
|
|
||||||
|
- 🐞 修复 Input.OTP 组件受控设置 `value` 为 `''` 时不生效的问题。[#48399](https://github.com/ant-design/ant-design/pull/48399)
|
||||||
|
- 🐞 修复 DatePicker 对周选择器配置 `multiple` 多选时,弹出面板不会正确高亮选中项的问题。[#48355](https://github.com/ant-design/ant-design/pull/48355)
|
||||||
|
- 🐞 修复 Upload 配置 `listType` 为 `picture-card` 或 `picture-circle` 时,上方有额外空隙的问题。[#48370](https://github.com/ant-design/ant-design/pull/48370)
|
||||||
|
- Typography
|
||||||
|
- 🐞 修复 Typography 动态配置 `copyable` 或 `editable` 时不会显示操作按钮的问题。[#48350](https://github.com/ant-design/ant-design/pull/48350)
|
||||||
|
- 🐞 修复 Typography 动态调整 `copyable.text` 不生效的问题。[#48347](https://github.com/ant-design/ant-design/pull/48347)
|
||||||
|
- 🐞 修复 Typography 的 `ellipsis` 同时配置 `expandable="collapsible"` 和 `row={1}` 时,不会正确省略的问题。[#48340](https://github.com/ant-design/ant-design/pull/48340)
|
||||||
|
- 💄 修复 Steps 的进度样式在紧凑模式下不正确的问题。[#48251](https://github.com/ant-design/ant-design/pull/48251)
|
||||||
|
- 💄 重构 Tabs 和波纹样式相关组件的 CSS 过渡时间值,替换为 `motionDurationSlow` Component Token。[#48311](https://github.com/ant-design/ant-design/pull/48311) [#48312](https://github.com/ant-design/ant-design/pull/48312) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||||
|
- 🇯🇵 补充 Transfer 的 ja_JP 本地化文案。[#48411](https://github.com/ant-design/ant-design/pull/48411) [@Inshiku-Han](https://github.com/Inshiku-Han)
|
||||||
|
- 🌐 修复 Picker 的 ja_JP 和 ko_KR 本地化文案。[#48382](https://github.com/ant-design/ant-design/pull/48382) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||||
|
- 🛠 使用常量替代枚举减小包体积。[#48406](https://github.com/ant-design/ant-design/pull/48406) [@kiner-tang](https://github.com/kiner-tang)
|
||||||
|
|
||||||
|
## 5.16.1
|
||||||
|
|
||||||
|
`2024-04-05`
|
||||||
|
|
||||||
|
- 🛠 调整 Typography 的 `ellipsis` 使其在 SSR 阶段使用 CSS 省略以优化用户体验。[#48205](https://github.com/ant-design/ant-design/pull/48205)
|
||||||
|
- 🐞 修复 FloatButton 中同时配置 `tooltip` 和 `badge` 时, `badge` 的自定义背景色会失效的问题。[#48198](https://github.com/ant-design/ant-design/pull/48198) [@LonelySnowman](https://github.com/LonelySnowman)
|
||||||
|
|
||||||
|
## 5.16.0
|
||||||
|
|
||||||
|
`2024-03-31`
|
||||||
|
|
||||||
|
- 🔥 新增 Input.OTP 组件。[#48076](https://github.com/ant-design/ant-design/pull/48076)
|
||||||
|
- 🆕 可关闭组件支持在 `closable` 中配置 `aria-*` 属性 [@kiner-tang](https://github.com/kiner-tang)
|
||||||
|
- 🆕 [Tag](https://github.com/ant-design/ant-design/pull/47678)
|
||||||
|
- 🆕 [Notification](https://github.com/ant-design/ant-design/pull/47710)
|
||||||
|
- 🆕 Table 增加 `rowHoverable` 开启或关闭 hover 效果。[#48112](https://github.com/ant-design/ant-design/pull/48112) [@madocto](https://github.com/madocto)
|
||||||
|
- 🆕 Typography 组件支持异步复制。[#48123](https://github.com/ant-design/ant-design/pull/48123) [@crazyair](https://github.com/crazyair)
|
||||||
|
- 🆕 Progress 组件 `circle` 模式下支持 `steps`。[#47940](https://github.com/ant-design/ant-design/pull/47940) [@yykoypj](https://github.com/yykoypj)
|
||||||
|
- 🆕 Table 支持 `onScroll` 事件用于监听表单内容滚动。[#47986](https://github.com/ant-design/ant-design/pull/47986)
|
||||||
|
- 🆕 Typography 省略支持展开和收起。[#47264](https://github.com/ant-design/ant-design/pull/47264) [@crazyair](https://github.com/crazyair)
|
||||||
|
- 🆕 ConfigProvider 支持配置 FloatButton.Group 的 `closeIcon` 属性。[#47953](https://github.com/ant-design/ant-design/pull/47953) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||||
|
- 🆕 Table 支持配置排序的 `showSorterTooltip.target` 属性.[#47409](https://github.com/ant-design/ant-design/pull/47409) [@Ke1sy](https://github.com/Ke1sy)
|
||||||
|
- 🆕 Cascader 支持 `optionRender`。[#47727](https://github.com/ant-design/ant-design/pull/47727) [@crazyair](https://github.com/crazyair)
|
||||||
|
- ⌨️ Popover 当 `trigger` 是 `focus` 或 `click` 时能被 ESC 按键所关闭。[#47928](https://github.com/ant-design/ant-design/pull/47928) [@CooperHash](https://github.com/CooperHash)
|
||||||
|
- 🐞 修复 Button 图标位置居中问题。[#48178](https://github.com/ant-design/ant-design/pull/48178) [@momesana](https://github.com/momesana)
|
||||||
|
- 🐞 修复 Modal.confirm 无图标时内容不居中的问题。[#48173](https://github.com/ant-design/ant-design/pull/48173)
|
||||||
|
- Form [#48163](https://github.com/ant-design/ant-design/pull/48163) [@madocto](https://github.com/madocto)
|
||||||
|
- 🐞 修复 Form 当 FormItem 的 `name` 不存在时,`getValueProps` 不应该执行。
|
||||||
|
- 🐞 修复 Form 的 `setFieldsValue` 和 `setFields` 的行为应该相同。
|
||||||
|
- 🐞 修复 Table 表格列在搜索情况下,国际化失效的问题。[#48126](https://github.com/ant-design/ant-design/pull/48126) [@LingJinT](https://github.com/LingJinT)
|
||||||
|
- 🐞 修复 Upload 当文件数量超出限制时,删除不起作用,无法触发 `onChange` 的问题。[#47747](https://github.com/ant-design/ant-design/pull/47747) [@Zhou-Bill](https://github.com/Zhou-Bill)
|
||||||
|
- 🐞 Carousel 组件同步上游 react-slick 改动,修复一系列<a href="https://github.com/ant-design/react-slick/pull/110" data-hovercard-type="pull_request" data-hovercard-url="/ant-design/react-slick/pull/110/hovercard">问题</a>,并更新到最新 TS 定义。[#48093](https://github.com/ant-design/ant-design/pull/48093)
|
||||||
|
- 🐞 修复 ColorPicker 展示的清除颜色在受控 `value` 变化后不会改变的问题。[#47816](https://github.com/ant-design/ant-design/pull/47816) [@MadCcc](https://github.com/MadCcc)
|
||||||
|
- 🐞 Badge 与 Tag 组件保持一致,processing 状态使用 `colorInfo` token 。[#47695](https://github.com/ant-design/ant-design/pull/47695) [@pfdgithub](https://github.com/pfdgithub)
|
||||||
|
- 🇮🇸 添加冰岛语缺失的 From 翻译。[#48104](https://github.com/ant-design/ant-design/pull/48104) [@LonelySnowman](https://github.com/LonelySnowman)
|
||||||
|
- 🇺🇿 添加乌兹别克语(拉丁字母) 国际化。[#47899](https://github.com/ant-design/ant-design/pull/47899)
|
||||||
|
- TypeScript
|
||||||
|
- 🤖 改进 Transfer 的`key` 类型,将 `key: string` 改为`key: React.Key`。[#47879](https://github.com/ant-design/ant-design/pull/47879) [@madocto](https://github.com/madocto)
|
||||||
|
- 🤖 Table 支持泛型对 dataIndex 属性校验。[#48190](https://github.com/ant-design/ant-design/pull/48190) [@crazyair](https://github.com/crazyair)
|
||||||
|
|
||||||
## 5.15.4
|
## 5.15.4
|
||||||
|
|
||||||
`2024-03-25`
|
`2024-03-25`
|
||||||
|
@ -149,6 +149,10 @@ export default App;
|
|||||||
|
|
||||||
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/ant-design/ant-design)
|
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/ant-design/ant-design)
|
||||||
|
|
||||||
|
或者使用 opensumi.run 进行在线开发:
|
||||||
|
|
||||||
|
[![opensumi.run](https://custom-icon-badges.demolab.com/badge/opensumi-run-blue.svg?logo=opensumi)](https://opensumi.run/ide/ant-design/ant-design)
|
||||||
|
|
||||||
或者克隆到本地开发:
|
或者克隆到本地开发:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@ -141,6 +141,10 @@ Use Gitpod, a free online dev environment for GitHub.
|
|||||||
|
|
||||||
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/ant-design/ant-design)
|
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/ant-design/ant-design)
|
||||||
|
|
||||||
|
Or use opensumi.run, a free online pure front-end dev environemt.
|
||||||
|
|
||||||
|
[![opensumi.run](https://custom-icon-badges.demolab.com/badge/opensumi-run-blue.svg?logo=opensumi)](https://opensumi.run/ide/ant-design/ant-design)
|
||||||
|
|
||||||
Or clone locally:
|
Or clone locally:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { render } from '../../tests/utils';
|
import { render } from '../../tests/utils';
|
||||||
|
|
||||||
describe('SetUp.Test', () => {
|
describe('SetUp.Test', () => {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import useState from 'rc-util/lib/hooks/useState';
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import useState from 'rc-util/lib/hooks/useState';
|
||||||
|
|
||||||
import Button from '../button';
|
import Button from '../button';
|
||||||
import type { ButtonProps, LegacyButtonType } from '../button/button';
|
import type { ButtonProps, LegacyButtonType } from '../button/button';
|
||||||
import { convertLegacyProps } from '../button/buttonHelpers';
|
import { convertLegacyProps } from '../button/buttonHelpers';
|
||||||
|
@ -45,7 +45,7 @@ const genPurePanel = <ComponentProps extends BaseProps = BaseProps>(
|
|||||||
|
|
||||||
if (typeof ResizeObserver !== 'undefined') {
|
if (typeof ResizeObserver !== 'undefined') {
|
||||||
const resizeObserver = new ResizeObserver((entries) => {
|
const resizeObserver = new ResizeObserver((entries) => {
|
||||||
const element: HTMLDivElement = entries[0].target as any;
|
const element = entries[0].target as HTMLDivElement;
|
||||||
setPopupHeight(element.offsetHeight + 8);
|
setPopupHeight(element.offsetHeight + 8);
|
||||||
setPopupWidth(element.offsetWidth);
|
setPopupWidth(element.offsetWidth);
|
||||||
});
|
});
|
||||||
|
@ -6,9 +6,9 @@ import type { UseClosableParams } from '../hooks/useClosable';
|
|||||||
import useClosable from '../hooks/useClosable';
|
import useClosable from '../hooks/useClosable';
|
||||||
|
|
||||||
type ParamsOfUseClosable = [
|
type ParamsOfUseClosable = [
|
||||||
UseClosableParams['closable'],
|
closable: UseClosableParams['closable'],
|
||||||
UseClosableParams['closeIcon'],
|
closeIcon: UseClosableParams['closeIcon'],
|
||||||
UseClosableParams['defaultClosable'],
|
defaultClosable: UseClosableParams['defaultClosable'],
|
||||||
];
|
];
|
||||||
|
|
||||||
describe('hooks test', () => {
|
describe('hooks test', () => {
|
||||||
@ -81,7 +81,7 @@ describe('hooks test', () => {
|
|||||||
res: [false, ''],
|
res: [false, ''],
|
||||||
},
|
},
|
||||||
|
|
||||||
// test case like: <Component closeIcon={null | false | element} />
|
// test case like: <Component closeIcon={null | false | element | true} />
|
||||||
{
|
{
|
||||||
params: [undefined, null, undefined],
|
params: [undefined, null, undefined],
|
||||||
res: [false, ''],
|
res: [false, ''],
|
||||||
@ -90,6 +90,10 @@ describe('hooks test', () => {
|
|||||||
params: [undefined, false, undefined],
|
params: [undefined, false, undefined],
|
||||||
res: [false, ''],
|
res: [false, ''],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
params: [undefined, true, undefined],
|
||||||
|
res: [true, '.anticon-close'],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
params: [
|
params: [
|
||||||
undefined,
|
undefined,
|
||||||
@ -138,11 +142,16 @@ describe('hooks test', () => {
|
|||||||
React.isValidElement(params[1]) ? 'element' : params[1]
|
React.isValidElement(params[1]) ? 'element' : params[1]
|
||||||
},defaultClosable=${params[2]}. the result should be ${res}`, () => {
|
},defaultClosable=${params[2]}. the result should be ${res}`, () => {
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const [closable, closeIcon] = useClosable({
|
const [closable, closeIcon] = useClosable(
|
||||||
|
{
|
||||||
closable: params[0],
|
closable: params[0],
|
||||||
closeIcon: params[1],
|
closeIcon: params[1],
|
||||||
defaultClosable: params[2],
|
},
|
||||||
});
|
null,
|
||||||
|
{
|
||||||
|
closable: params[2],
|
||||||
|
},
|
||||||
|
);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
expect(closable).toBe(res[0]);
|
expect(closable).toBe(res[0]);
|
||||||
}, [closable]);
|
}, [closable]);
|
||||||
@ -159,10 +168,15 @@ describe('hooks test', () => {
|
|||||||
|
|
||||||
it('useClosable with defaultCloseIcon', () => {
|
it('useClosable with defaultCloseIcon', () => {
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const [closable, closeIcon] = useClosable({
|
const [closable, closeIcon] = useClosable(
|
||||||
|
{
|
||||||
closable: true,
|
closable: true,
|
||||||
defaultCloseIcon: <CloseOutlined className="custom-close-icon" />,
|
},
|
||||||
});
|
null,
|
||||||
|
{
|
||||||
|
closeIcon: <CloseOutlined className="custom-close-icon" />,
|
||||||
|
},
|
||||||
|
);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
expect(closable).toBe(true);
|
expect(closable).toBe(true);
|
||||||
}, [closable]);
|
}, [closable]);
|
||||||
@ -171,16 +185,37 @@ describe('hooks test', () => {
|
|||||||
const { container } = render(<App />);
|
const { container } = render(<App />);
|
||||||
expect(container.querySelector('.custom-close-icon')).toBeTruthy();
|
expect(container.querySelector('.custom-close-icon')).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
it('useClosable without defaultCloseIcon', () => {
|
||||||
|
const App = () => {
|
||||||
|
const [closable, closeIcon] = useClosable(
|
||||||
|
{
|
||||||
|
closable: true,
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
useEffect(() => {
|
||||||
|
expect(closable).toBe(true);
|
||||||
|
}, [closable]);
|
||||||
|
return <div>hooks test {closeIcon}</div>;
|
||||||
|
};
|
||||||
|
const { container } = render(<App />);
|
||||||
|
expect(container.querySelector('.anticon-close')).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
it('useClosable with customCloseIconRender', () => {
|
it('useClosable with customCloseIconRender', () => {
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const customCloseIconRender = (icon: React.ReactNode) => (
|
const customCloseIconRender = (icon: React.ReactNode) => (
|
||||||
<span className="custom-close-wrapper">{icon}</span>
|
<span className="custom-close-wrapper">{icon}</span>
|
||||||
);
|
);
|
||||||
const [closable, closeIcon] = useClosable({
|
const [closable, closeIcon] = useClosable(
|
||||||
|
{
|
||||||
closable: true,
|
closable: true,
|
||||||
customCloseIconRender,
|
},
|
||||||
});
|
null,
|
||||||
|
{
|
||||||
|
closeIconRender: customCloseIconRender,
|
||||||
|
},
|
||||||
|
);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
expect(closable).toBe(true);
|
expect(closable).toBe(true);
|
||||||
}, [closable]);
|
}, [closable]);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { render } from '../../../tests/utils';
|
import { render } from '../../../tests/utils';
|
||||||
import useResponsiveObserver from '../responsiveObserver';
|
import useResponsiveObserver from '../responsiveObserver';
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import TransButton from '../transButton';
|
|
||||||
import { render } from '../../../tests/utils';
|
import { render } from '../../../tests/utils';
|
||||||
|
import TransButton from '../transButton';
|
||||||
|
|
||||||
describe('transButton component', () => {
|
describe('transButton component', () => {
|
||||||
it('disabled should update style', () => {
|
it('disabled should update style', () => {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
import { fireEvent, render } from '../../../tests/utils';
|
||||||
import useSyncState from '../hooks/useSyncState';
|
import useSyncState from '../hooks/useSyncState';
|
||||||
import { render, fireEvent } from '../../../tests/utils';
|
|
||||||
|
|
||||||
describe('Table', () => {
|
describe('Table', () => {
|
||||||
it('useSyncState', () => {
|
it('useSyncState', () => {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/* eslint-disable class-methods-use-this */
|
/* eslint-disable class-methods-use-this */
|
||||||
import KeyCode from 'rc-util/lib/KeyCode';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import KeyCode from 'rc-util/lib/KeyCode';
|
||||||
|
|
||||||
import { fireEvent, render, waitFakeTimer } from '../../../tests/utils';
|
import { fireEvent, render, waitFakeTimer } from '../../../tests/utils';
|
||||||
import { isStyleSupport } from '../styleChecker';
|
import { isStyleSupport } from '../styleChecker';
|
||||||
import throttleByAnimationFrame from '../throttleByAnimationFrame';
|
import throttleByAnimationFrame from '../throttleByAnimationFrame';
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { render } from '@testing-library/react';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
import { devUseWarning as useWarning } from '../warning';
|
import { devUseWarning as useWarning } from '../warning';
|
||||||
|
|
||||||
describe('Test warning', () => {
|
describe('Test warning', () => {
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import mountTest from '../../../tests/shared/mountTest';
|
import mountTest from '../../../tests/shared/mountTest';
|
||||||
import { act, fireEvent, getByText, render, waitFakeTimer } from '../../../tests/utils';
|
import { act, fireEvent, getByText, render, waitFakeTimer } from '../../../tests/utils';
|
||||||
|
import Checkbox from '../../checkbox';
|
||||||
import Wave from '../wave';
|
import Wave from '../wave';
|
||||||
import { TARGET_CLS } from '../wave/interface';
|
import { TARGET_CLS } from '../wave/interface';
|
||||||
import Checkbox from '../../checkbox';
|
|
||||||
|
|
||||||
(global as any).isVisible = true;
|
(global as any).isVisible = true;
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ export const PresetStatusColorTypes = [
|
|||||||
|
|
||||||
export type PresetColorType = PresetColorKey | InverseColor;
|
export type PresetColorType = PresetColorKey | InverseColor;
|
||||||
|
|
||||||
export type PresetStatusColorType = typeof PresetStatusColorTypes[number];
|
export type PresetStatusColorType = (typeof PresetStatusColorTypes)[number];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* determine if the color keyword belongs to the `Ant Design` {@link PresetColors}.
|
* determine if the color keyword belongs to the `Ant Design` {@link PresetColors}.
|
||||||
|
@ -3,69 +3,174 @@ import React from 'react';
|
|||||||
import CloseOutlined from '@ant-design/icons/CloseOutlined';
|
import CloseOutlined from '@ant-design/icons/CloseOutlined';
|
||||||
import pickAttrs from 'rc-util/lib/pickAttrs';
|
import pickAttrs from 'rc-util/lib/pickAttrs';
|
||||||
|
|
||||||
|
export type BaseClosableType = { closeIcon?: React.ReactNode } & React.AriaAttributes;
|
||||||
|
export type ClosableType = boolean | BaseClosableType;
|
||||||
|
|
||||||
|
export type ContextClosable<T extends { closable?: ClosableType; closeIcon?: ReactNode } = any> =
|
||||||
|
Partial<Pick<T, 'closable' | 'closeIcon'>>;
|
||||||
|
|
||||||
|
export function pickClosable<T extends { closable?: ClosableType; closeIcon?: ReactNode }>(
|
||||||
|
context?: ContextClosable<T>,
|
||||||
|
): ContextClosable<T> | undefined {
|
||||||
|
if (!context) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
closable: context.closable,
|
||||||
|
closeIcon: context.closeIcon,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export type UseClosableParams = {
|
export type UseClosableParams = {
|
||||||
closable?: boolean | ({ closeIcon?: React.ReactNode } & React.AriaAttributes);
|
closable?: ClosableType;
|
||||||
closeIcon?: ReactNode;
|
closeIcon?: ReactNode;
|
||||||
defaultClosable?: boolean;
|
defaultClosable?: boolean;
|
||||||
defaultCloseIcon?: ReactNode;
|
defaultCloseIcon?: ReactNode;
|
||||||
customCloseIconRender?: (closeIcon: ReactNode) => ReactNode;
|
customCloseIconRender?: (closeIcon: ReactNode) => ReactNode;
|
||||||
|
context?: ContextClosable;
|
||||||
};
|
};
|
||||||
|
|
||||||
function useInnerClosable(
|
/** Convert `closable` and `closeIcon` to config object */
|
||||||
closable?: UseClosableParams['closable'],
|
function useClosableConfig(closableCollection?: ClosableCollection | null) {
|
||||||
closeIcon?: ReactNode,
|
const { closable, closeIcon } = closableCollection || {};
|
||||||
defaultClosable?: boolean,
|
|
||||||
|
return React.useMemo(() => {
|
||||||
|
if (
|
||||||
|
// If `closable`, whatever rest be should be true
|
||||||
|
!closable &&
|
||||||
|
(closable === false || closeIcon === false || closeIcon === null)
|
||||||
) {
|
) {
|
||||||
if (typeof closable === 'boolean') {
|
return false;
|
||||||
return closable;
|
|
||||||
}
|
|
||||||
if (typeof closable === 'object') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (closeIcon === undefined) {
|
|
||||||
return !!defaultClosable;
|
|
||||||
}
|
|
||||||
return closeIcon !== false && closeIcon !== null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function useClosable({
|
if (closable === undefined && closeIcon === undefined) {
|
||||||
closable,
|
return null;
|
||||||
closeIcon,
|
|
||||||
customCloseIconRender,
|
|
||||||
defaultCloseIcon = <CloseOutlined />,
|
|
||||||
defaultClosable = false,
|
|
||||||
}: UseClosableParams): [closable: boolean, closeIcon: React.ReactNode | null] {
|
|
||||||
const mergedClosable = useInnerClosable(closable, closeIcon, defaultClosable);
|
|
||||||
|
|
||||||
if (!mergedClosable) {
|
|
||||||
return [false, null];
|
|
||||||
}
|
}
|
||||||
const { closeIcon: closableIcon, ...restProps } =
|
|
||||||
typeof closable === 'object'
|
let closableConfig: BaseClosableType = {
|
||||||
? closable
|
closeIcon: typeof closeIcon !== 'boolean' && closeIcon !== null ? closeIcon : undefined,
|
||||||
: ({} as { closeIcon: React.ReactNode } & React.AriaAttributes);
|
};
|
||||||
// Priority: closable.closeIcon > closeIcon > defaultCloseIcon
|
if (closable && typeof closable === 'object') {
|
||||||
const mergedCloseIcon: ReactNode = (() => {
|
closableConfig = {
|
||||||
if (typeof closable === 'object' && closableIcon !== undefined) {
|
...closableConfig,
|
||||||
return closableIcon;
|
...closable,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return typeof closeIcon === 'boolean' || closeIcon === undefined || closeIcon === null
|
|
||||||
? defaultCloseIcon
|
|
||||||
: closeIcon;
|
|
||||||
})();
|
|
||||||
const ariaProps = pickAttrs(restProps, true);
|
|
||||||
|
|
||||||
const plainCloseIcon = customCloseIconRender
|
return closableConfig;
|
||||||
? customCloseIconRender(mergedCloseIcon)
|
}, [closable, closeIcon]);
|
||||||
: mergedCloseIcon;
|
}
|
||||||
|
|
||||||
const closeIconWithAria = React.isValidElement(plainCloseIcon) ? (
|
/**
|
||||||
React.cloneElement(plainCloseIcon, ariaProps)
|
* Assign object without `undefined` field. Will skip if is `false`.
|
||||||
) : (
|
* This helps to handle both closableConfig or false
|
||||||
<span {...ariaProps}>{plainCloseIcon}</span>
|
*/
|
||||||
|
function assignWithoutUndefined<T extends object>(
|
||||||
|
...objList: (Partial<T> | false | null | undefined)[]
|
||||||
|
): Partial<T> {
|
||||||
|
const target: Partial<T> = {};
|
||||||
|
|
||||||
|
objList.forEach((obj) => {
|
||||||
|
if (obj) {
|
||||||
|
(Object.keys(obj) as (keyof T)[]).forEach((key) => {
|
||||||
|
if (obj[key] !== undefined) {
|
||||||
|
target[key] = obj[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Collection contains the all the props related with closable. e.g. `closable`, `closeIcon` */
|
||||||
|
interface ClosableCollection {
|
||||||
|
closable?: ClosableType;
|
||||||
|
closeIcon?: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Use same object to support `useMemo` optimization */
|
||||||
|
const EmptyFallbackCloseCollection: ClosableCollection = {};
|
||||||
|
|
||||||
|
export default function useClosable(
|
||||||
|
propCloseCollection?: ClosableCollection,
|
||||||
|
contextCloseCollection?: ClosableCollection | null,
|
||||||
|
fallbackCloseCollection: ClosableCollection & {
|
||||||
|
/**
|
||||||
|
* Some components need to wrap CloseIcon twice,
|
||||||
|
* this method will be executed once after the final CloseIcon is calculated
|
||||||
|
*/
|
||||||
|
closeIconRender?: (closeIcon: ReactNode) => ReactNode;
|
||||||
|
} = EmptyFallbackCloseCollection,
|
||||||
|
): [closable: boolean, closeIcon: React.ReactNode | null] {
|
||||||
|
// Align the `props`, `context` `fallback` to config object first
|
||||||
|
const propCloseConfig = useClosableConfig(propCloseCollection);
|
||||||
|
const contextCloseConfig = useClosableConfig(contextCloseCollection);
|
||||||
|
const mergedFallbackCloseCollection = React.useMemo(
|
||||||
|
() => ({
|
||||||
|
closeIcon: <CloseOutlined />,
|
||||||
|
...fallbackCloseCollection,
|
||||||
|
}),
|
||||||
|
[fallbackCloseCollection],
|
||||||
);
|
);
|
||||||
|
|
||||||
return [true, closeIconWithAria];
|
// Use fallback logic to fill the config
|
||||||
|
const mergedClosableConfig = React.useMemo(() => {
|
||||||
|
// ================ Props First ================
|
||||||
|
// Skip if prop is disabled
|
||||||
|
if (propCloseConfig === false) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useClosable;
|
if (propCloseConfig) {
|
||||||
|
return assignWithoutUndefined(
|
||||||
|
mergedFallbackCloseCollection,
|
||||||
|
contextCloseConfig,
|
||||||
|
propCloseConfig,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============== Context Second ==============
|
||||||
|
// Skip if context is disabled
|
||||||
|
if (contextCloseConfig === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contextCloseConfig) {
|
||||||
|
return assignWithoutUndefined(mergedFallbackCloseCollection, contextCloseConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============= Fallback Default ==============
|
||||||
|
return !mergedFallbackCloseCollection.closable ? false : mergedFallbackCloseCollection;
|
||||||
|
}, [propCloseConfig, contextCloseConfig, mergedFallbackCloseCollection]);
|
||||||
|
|
||||||
|
// Calculate the final closeIcon
|
||||||
|
return React.useMemo(() => {
|
||||||
|
if (mergedClosableConfig === false) {
|
||||||
|
return [false, null];
|
||||||
|
}
|
||||||
|
|
||||||
|
const { closeIconRender } = mergedFallbackCloseCollection;
|
||||||
|
const { closeIcon } = mergedClosableConfig;
|
||||||
|
|
||||||
|
let mergedCloseIcon: ReactNode = closeIcon;
|
||||||
|
if (mergedCloseIcon !== null && mergedCloseIcon !== undefined) {
|
||||||
|
// Wrap the closeIcon if needed
|
||||||
|
if (closeIconRender) {
|
||||||
|
mergedCloseIcon = closeIconRender(closeIcon);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrap the closeIcon with aria props
|
||||||
|
const ariaProps = pickAttrs(mergedClosableConfig, true);
|
||||||
|
if (Object.keys(ariaProps).length) {
|
||||||
|
mergedCloseIcon = React.isValidElement(mergedCloseIcon) ? (
|
||||||
|
React.cloneElement(mergedCloseIcon, ariaProps)
|
||||||
|
) : (
|
||||||
|
<span {...ariaProps}>{mergedCloseIcon}</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [true, mergedCloseIcon];
|
||||||
|
}, [mergedClosableConfig, mergedFallbackCloseCollection]);
|
||||||
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user