mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-27 12:39:49 +08:00
Merge branch 'master' into master
This commit is contained in:
commit
bfd62c9390
@ -1,5 +0,0 @@
|
||||
{
|
||||
"installCommand": "npm-install",
|
||||
"sandboxes": ["antd-reproduction-template-forked-jyh2k9"],
|
||||
"node": "18"
|
||||
}
|
@ -43,7 +43,7 @@ const useStyle = createStyles(({ token }, markPos: [number, number, number, numb
|
||||
z-index: 999999;
|
||||
box-shadow: 0 0 0 1px #fff;
|
||||
pointer-events: none;
|
||||
left: ${markPos[0] - MARK_BORDER_SIZE}px;
|
||||
inset-inline-start: ${markPos[0] - MARK_BORDER_SIZE}px;
|
||||
top: ${markPos[1] - MARK_BORDER_SIZE}px;
|
||||
width: ${markPos[2] + MARK_BORDER_SIZE * 2}px;
|
||||
height: ${markPos[3] + MARK_BORDER_SIZE * 2}px;
|
||||
|
@ -9,22 +9,22 @@ function use<T>(promise: PromiseLike<T>): T {
|
||||
}
|
||||
if (internal.status === 'rejected') {
|
||||
throw internal.reason;
|
||||
} else if (internal.status === 'pending') {
|
||||
throw internal;
|
||||
} else {
|
||||
internal.status = 'pending';
|
||||
internal.then(
|
||||
(result) => {
|
||||
internal.status = 'fulfilled';
|
||||
internal.value = result;
|
||||
},
|
||||
(reason) => {
|
||||
internal.status = 'rejected';
|
||||
internal.reason = reason;
|
||||
},
|
||||
);
|
||||
}
|
||||
if (internal.status === 'pending') {
|
||||
throw internal;
|
||||
}
|
||||
internal.status = 'pending';
|
||||
internal.then(
|
||||
(result) => {
|
||||
internal.status = 'fulfilled';
|
||||
internal.value = result;
|
||||
},
|
||||
(reason) => {
|
||||
internal.status = 'rejected';
|
||||
internal.reason = reason;
|
||||
},
|
||||
);
|
||||
throw internal;
|
||||
}
|
||||
|
||||
export default use;
|
||||
|
@ -1,4 +1,5 @@
|
||||
import fetch from 'cross-fetch';
|
||||
|
||||
import use from '../use';
|
||||
import FetchCache from './cache';
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { useLocation as useDumiLocation } from 'dumi';
|
||||
import * as React from 'react';
|
||||
import { useLocation as useDumiLocation } from 'dumi';
|
||||
|
||||
import useLocale from './useLocale';
|
||||
|
||||
function clearPath(path: string) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import type { MenuProps } from 'antd';
|
||||
import { Tag, version } from 'antd';
|
||||
import { Space, Tag, version } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
import classnames from 'classnames';
|
||||
import { useFullSidebarData, useSidebarData } from 'dumi';
|
||||
@ -22,7 +22,6 @@ const useStyle = createStyles(({ css, token }) => ({
|
||||
margin-inline-end: 0;
|
||||
`,
|
||||
subtitle: css`
|
||||
margin-inline-start: ${token.marginXS}px;
|
||||
font-weight: normal;
|
||||
font-size: ${token.fontSizeSM}px;
|
||||
opacity: 0.8;
|
||||
@ -46,10 +45,10 @@ const MenuItemLabelWithTag: React.FC<MenuItemLabelProps> = (props) => {
|
||||
if (!before && !after) {
|
||||
return (
|
||||
<Link to={`${link}${search}`} className={classnames(className, { [styles.link]: tag })}>
|
||||
<span>
|
||||
{title}
|
||||
<Space>
|
||||
<span>{title}</span>
|
||||
{subtitle && <span className={styles.subtitle}>{subtitle}</span>}
|
||||
</span>
|
||||
</Space>
|
||||
{tag && (
|
||||
<Tag
|
||||
bordered={false}
|
||||
|
@ -1,7 +1,9 @@
|
||||
import { HomeOutlined } from '@ant-design/icons';
|
||||
import { Link, useLocation } from 'dumi';
|
||||
import React, { useEffect } from 'react';
|
||||
import { HomeOutlined } from '@ant-design/icons';
|
||||
import { Button, Result } from 'antd';
|
||||
import { useLocation } from 'dumi';
|
||||
|
||||
import Link from '../../theme/common/Link';
|
||||
import * as utils from '../../theme/utils';
|
||||
|
||||
export interface NotFoundProps {
|
||||
|
@ -1,183 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import { Button, Flex, Typography } from 'antd';
|
||||
import { createStyles, css, useTheme } from 'antd-style';
|
||||
import classNames from 'classnames';
|
||||
import { Link, useLocation } from 'dumi';
|
||||
|
||||
import useLocale from '../../../hooks/useLocale';
|
||||
import SiteContext from '../../../theme/slots/SiteContext';
|
||||
import * as utils from '../../../theme/utils';
|
||||
import GroupMaskLayer from './GroupMaskLayer';
|
||||
|
||||
const locales = {
|
||||
cn: {
|
||||
slogan: '助力设计开发者「更灵活」地搭建出「更美」的产品,让用户「快乐工作」~',
|
||||
start: '开始使用',
|
||||
designLanguage: '设计语言',
|
||||
},
|
||||
en: {
|
||||
slogan:
|
||||
'Help designers/developers building beautiful products more flexible and working with happiness',
|
||||
start: 'Getting Started',
|
||||
designLanguage: 'Design Language',
|
||||
},
|
||||
};
|
||||
|
||||
const useStyle = () => {
|
||||
const { isMobile } = React.useContext(SiteContext);
|
||||
return createStyles(({ token }) => ({
|
||||
titleBase: css`
|
||||
h1& {
|
||||
font-family: AliPuHui, ${token.fontFamily};
|
||||
}
|
||||
`,
|
||||
title: isMobile
|
||||
? css`
|
||||
h1& {
|
||||
margin-bottom: ${token.margin}px;
|
||||
font-weight: normal;
|
||||
font-size: ${token.fontSizeHeading1 + 2}px;
|
||||
line-height: ${token.lineHeightHeading2};
|
||||
}
|
||||
`
|
||||
: css`
|
||||
h1& {
|
||||
margin-bottom: ${token.marginMD}px;
|
||||
font-weight: 900;
|
||||
font-size: 68px;
|
||||
}
|
||||
`,
|
||||
btnWrap: css`
|
||||
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;
|
||||
`,
|
||||
}))();
|
||||
};
|
||||
|
||||
const Banner: React.FC<React.PropsWithChildren> = ({ children }) => {
|
||||
const [locale] = useLocale(locales);
|
||||
const { pathname, search } = useLocation();
|
||||
const token = useTheme();
|
||||
const { styles } = useStyle();
|
||||
const { isMobile } = React.useContext(SiteContext);
|
||||
const isZhCN = utils.isZhCN(pathname);
|
||||
return (
|
||||
<>
|
||||
{/* Banner Placeholder Motion */}
|
||||
{isMobile ? (
|
||||
<img
|
||||
className={styles.mobileBg}
|
||||
src="https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*JmlaR5oQn3MAAAAAAAAAAAAADrJ8AQ/original"
|
||||
alt=""
|
||||
/>
|
||||
) : (
|
||||
<div className={classNames(styles.videoWrap)}>
|
||||
<div className={classNames(styles.bg, styles.bg1)} />
|
||||
<video className={styles.video} autoPlay muted loop>
|
||||
<source
|
||||
type="video/webm"
|
||||
src="https://mdn.alipayobjects.com/huamei_iwk9zp/afts/file/A*uYT7SZwhJnUAAAAAAAAAAAAADgCCAQ"
|
||||
/>
|
||||
<source
|
||||
type="video/mp4"
|
||||
src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/file/A*XYYNQJ3NbmMAAAAAAAAAAAAAARQnAQ"
|
||||
/>
|
||||
</video>
|
||||
<div className={classNames(styles.bg, styles.bg2)} />
|
||||
</div>
|
||||
)}
|
||||
{/* Logo */}
|
||||
<div className={styles.logoWrap}>
|
||||
{/* Image Bottom Right */}
|
||||
<img
|
||||
className={classNames(styles.bgImg)}
|
||||
style={{ right: 0, top: 240 }}
|
||||
src="https://gw.alipayobjects.com/zos/bmw-prod/b3b8dc41-dce8-471f-9d81-9a0204f27d03.svg"
|
||||
alt="Ant Design"
|
||||
/>
|
||||
<GroupMaskLayer className={styles.layer}>
|
||||
{/* Image Left Top */}
|
||||
<img
|
||||
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"
|
||||
alt="bg"
|
||||
/>
|
||||
{/* Image Right Top */}
|
||||
<img
|
||||
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"
|
||||
alt="bg"
|
||||
/>
|
||||
<Typography.Title level={1} className={classNames(styles.titleBase, styles.title)}>
|
||||
Ant Design 5.0
|
||||
</Typography.Title>
|
||||
<Typography.Paragraph
|
||||
style={{
|
||||
fontSize: isMobile ? token.fontSizeHeading5 - 2 : token.fontSizeHeading5,
|
||||
lineHeight: isMobile ? token.lineHeightSM : token.lineHeightHeading5,
|
||||
marginBottom: token.marginMD * 2,
|
||||
padding: isMobile ? `0 ${token.paddingLG + 2}px` : 0,
|
||||
}}
|
||||
>
|
||||
<div>{locale.slogan}</div>
|
||||
</Typography.Paragraph>
|
||||
<Flex gap="middle" className={styles.btnWrap}>
|
||||
<Link to={utils.getLocalizedPathname('/components/overview/', isZhCN, search)}>
|
||||
<Button size="large" type="primary">
|
||||
{locale.start}
|
||||
</Button>
|
||||
</Link>
|
||||
<Link to={utils.getLocalizedPathname('/docs/spec/introduce/', isZhCN, search)}>
|
||||
<Button size="large">{locale.designLanguage}</Button>
|
||||
</Link>
|
||||
</Flex>
|
||||
{children}
|
||||
</GroupMaskLayer>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Banner;
|
@ -1,6 +1,6 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { Badge, Carousel, Skeleton, Typography } from 'antd';
|
||||
import { createStyles, useTheme } from 'antd-style';
|
||||
import { Badge, Carousel, Flex, Skeleton, Typography } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import useLocale from '../../../hooks/useLocale';
|
||||
@ -57,6 +57,9 @@ const useStyle = createStyles(({ token, css, cx }) => {
|
||||
}
|
||||
`,
|
||||
carousel,
|
||||
bannerBg: css`
|
||||
height: ${token.fontSize}px;
|
||||
`,
|
||||
};
|
||||
});
|
||||
|
||||
@ -66,8 +69,8 @@ interface RecommendItemProps {
|
||||
icons: Icon[];
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const RecommendItem: React.FC<RecommendItemProps> = ({ extra, index, icons, className }) => {
|
||||
const token = useTheme();
|
||||
const { styles } = useStyle();
|
||||
|
||||
if (!extra) {
|
||||
@ -87,10 +90,10 @@ const RecommendItem: React.FC<RecommendItemProps> = ({ extra, index, icons, clas
|
||||
<Typography.Paragraph type="secondary" style={{ flex: 'auto' }}>
|
||||
{extra.description}
|
||||
</Typography.Paragraph>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Flex justify="space-between" align="center">
|
||||
<Typography.Text>{extra.date}</Typography.Text>
|
||||
{icon && <img src={icon.href} style={{ height: token.fontSize }} alt="banner" />}
|
||||
</div>
|
||||
{icon && <img src={icon.href} draggable={false} className={styles.bannerBg} alt="banner" />}
|
||||
</Flex>
|
||||
</a>
|
||||
);
|
||||
|
||||
|
@ -12,7 +12,7 @@ import {
|
||||
Tour,
|
||||
Typography,
|
||||
} from 'antd';
|
||||
import { createStyles, css, useTheme } from 'antd-style';
|
||||
import { createStyles, css } from 'antd-style';
|
||||
import classNames from 'classnames';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
@ -104,6 +104,13 @@ const useStyle = () => {
|
||||
justify-content: center;
|
||||
`,
|
||||
carousel,
|
||||
componentsList: css`
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
`,
|
||||
mobileComponentsList: css`
|
||||
margin: 0 ${token.margin}px;
|
||||
`,
|
||||
};
|
||||
})();
|
||||
};
|
||||
@ -119,7 +126,7 @@ const ComponentItem: React.FC<ComponentItemProps> = ({ title, node, type, index
|
||||
{/* Decorator */}
|
||||
<div
|
||||
className={styles.cardCircle}
|
||||
style={{ right: (index % 2) * -20 - 20, bottom: (index % 3) * -40 - 20 }}
|
||||
style={{ insetInlineEnd: (index % 2) * -20 - 20, bottom: (index % 3) * -40 - 20 }}
|
||||
/>
|
||||
|
||||
{/* Title */}
|
||||
@ -142,7 +149,6 @@ interface ComponentItemProps {
|
||||
}
|
||||
|
||||
const ComponentsList: React.FC = () => {
|
||||
const token = useTheme();
|
||||
const { styles } = useStyle();
|
||||
const [locale] = useLocale(locales);
|
||||
const { isMobile } = useContext(SiteContext);
|
||||
@ -260,21 +266,33 @@ const ComponentsList: React.FC = () => {
|
||||
);
|
||||
|
||||
return isMobile ? (
|
||||
<div style={{ margin: '0 16px' }}>
|
||||
<div className={styles.mobileComponentsList}>
|
||||
<Carousel className={styles.carousel}>
|
||||
{COMPONENTS.map<React.ReactNode>(({ title, node, type }, index) => (
|
||||
<ComponentItem title={title} node={node} type={type} index={index} key={index} />
|
||||
<ComponentItem
|
||||
title={title}
|
||||
node={node}
|
||||
type={type}
|
||||
index={index}
|
||||
key={`mobile-item-${index}`}
|
||||
/>
|
||||
))}
|
||||
</Carousel>
|
||||
</div>
|
||||
) : (
|
||||
<div style={{ width: '100%', overflow: 'hidden', display: 'flex', justifyContent: 'center' }}>
|
||||
<div style={{ display: 'flex', alignItems: 'stretch', columnGap: token.paddingLG }}>
|
||||
<Flex justify="center" className={styles.componentsList}>
|
||||
<Flex align="stretch" gap="large">
|
||||
{COMPONENTS.map<React.ReactNode>(({ title, node, type }, index) => (
|
||||
<ComponentItem title={title} node={node} type={type} index={index} key={index} />
|
||||
<ComponentItem
|
||||
title={title}
|
||||
node={node}
|
||||
type={type}
|
||||
index={index}
|
||||
key={`desktop-item-${index}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,10 +1,11 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { Col, Row, Typography } from 'antd';
|
||||
import { createStyles, useTheme } from 'antd-style';
|
||||
import { Link, useLocation } from 'dumi';
|
||||
import { useLocation } from 'dumi';
|
||||
|
||||
import useDark from '../../../hooks/useDark';
|
||||
import useLocale from '../../../hooks/useLocale';
|
||||
import Link from '../../../theme/common/Link';
|
||||
import SiteContext from '../../../theme/slots/SiteContext';
|
||||
import * as utils from '../../../theme/utils';
|
||||
|
||||
@ -133,7 +134,7 @@ const DesignFramework: React.FC = () => {
|
||||
<Col key={index} span={colSpan}>
|
||||
<Link to={path}>
|
||||
<div className={styles.card}>
|
||||
<img alt={title} src={img} />
|
||||
<img draggable={false} alt={title} src={img} />
|
||||
|
||||
<Typography.Title
|
||||
level={4}
|
||||
@ -157,7 +158,12 @@ const DesignFramework: React.FC = () => {
|
||||
return (
|
||||
<Col key={index} span={colSpan}>
|
||||
<a className={styles.cardMini} target="_blank" href={url} rel="noreferrer">
|
||||
<img alt={title} src={img} style={{ transform: `scale(${imgScale})` }} />
|
||||
<img
|
||||
draggable={false}
|
||||
alt={title}
|
||||
src={img}
|
||||
style={{ transform: `scale(${imgScale})` }}
|
||||
/>
|
||||
|
||||
<Typography.Title
|
||||
level={4}
|
||||
|
@ -1,9 +1,11 @@
|
||||
import React, { Suspense } from 'react';
|
||||
import { Button, ConfigProvider, Flex, Typography } from 'antd';
|
||||
import { ConfigProvider, Flex, Typography } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
import { Link, useLocation } from 'dumi';
|
||||
import classNames from 'classnames';
|
||||
import { useLocation } from 'dumi';
|
||||
|
||||
import useLocale from '../../../../hooks/useLocale';
|
||||
import LinkButton from '../../../../theme/common/LinkButton';
|
||||
import SiteContext from '../../../../theme/slots/SiteContext';
|
||||
import * as utils from '../../../../theme/utils';
|
||||
import GroupMaskLayer from '../GroupMaskLayer';
|
||||
@ -26,6 +28,7 @@ const locales = {
|
||||
|
||||
const useStyle = () => {
|
||||
const { direction } = React.useContext(ConfigProvider.ConfigContext);
|
||||
const { isMobile } = React.useContext(SiteContext);
|
||||
const isRTL = direction === 'rtl';
|
||||
return createStyles(({ token, css, cx }) => {
|
||||
const textShadow = `0 0 4px ${token.colorBgContainer}`;
|
||||
@ -101,11 +104,23 @@ const useStyle = () => {
|
||||
btnWrap: css`
|
||||
margin-bottom: ${token.marginXL}px;
|
||||
`,
|
||||
bgImg: css`
|
||||
position: absolute;
|
||||
width: 240px;
|
||||
`,
|
||||
bgImgTop: css`
|
||||
top: 0;
|
||||
inset-inline-start: ${isMobile ? '-120px' : 0};
|
||||
`,
|
||||
bgImgBottom: css`
|
||||
bottom: 120px;
|
||||
inset-inline-end: ${isMobile ? 0 : '40%'};
|
||||
`,
|
||||
};
|
||||
})();
|
||||
};
|
||||
|
||||
const PreviewBanner: React.FC<React.PropsWithChildren> = (props) => {
|
||||
const PreviewBanner: React.FC<Readonly<React.PropsWithChildren>> = (props) => {
|
||||
const { children } = props;
|
||||
const [locale] = useLocale(locales);
|
||||
const { styles } = useStyle();
|
||||
@ -117,15 +132,17 @@ const PreviewBanner: React.FC<React.PropsWithChildren> = (props) => {
|
||||
<GroupMaskLayer>
|
||||
{/* Image Left Top */}
|
||||
<img
|
||||
style={{ position: 'absolute', left: isMobile ? -120 : 0, top: 0, width: 240 }}
|
||||
src="https://gw.alipayobjects.com/zos/bmw-prod/49f963db-b2a8-4f15-857a-270d771a1204.svg"
|
||||
alt="bg"
|
||||
src="https://gw.alipayobjects.com/zos/bmw-prod/49f963db-b2a8-4f15-857a-270d771a1204.svg"
|
||||
draggable={false}
|
||||
className={classNames(styles.bgImg, styles.bgImgTop)}
|
||||
/>
|
||||
{/* Image Right Top */}
|
||||
<img
|
||||
style={{ position: 'absolute', right: isMobile ? 0 : '40%', bottom: 120, width: 240 }}
|
||||
src="https://gw.alipayobjects.com/zos/bmw-prod/e152223c-bcae-4913-8938-54fda9efe330.svg"
|
||||
alt="bg"
|
||||
src="https://gw.alipayobjects.com/zos/bmw-prod/e152223c-bcae-4913-8938-54fda9efe330.svg"
|
||||
draggable={false}
|
||||
className={classNames(styles.bgImg, styles.bgImgBottom)}
|
||||
/>
|
||||
|
||||
<div className={styles.holder}>
|
||||
@ -143,14 +160,19 @@ const PreviewBanner: React.FC<React.PropsWithChildren> = (props) => {
|
||||
<p>{locale.slogan}</p>
|
||||
</Typography>
|
||||
<Flex gap="middle" className={styles.btnWrap}>
|
||||
<Link to={utils.getLocalizedPathname('/components/overview/', isZhCN, search)}>
|
||||
<Button size="large" type="primary">
|
||||
{locale.start}
|
||||
</Button>
|
||||
</Link>
|
||||
<Link to={utils.getLocalizedPathname('/docs/spec/introduce/', isZhCN, search)}>
|
||||
<Button size="large">{locale.designLanguage}</Button>
|
||||
</Link>
|
||||
<LinkButton
|
||||
size="large"
|
||||
type="primary"
|
||||
to={utils.getLocalizedPathname('/components/overview/', isZhCN, search)}
|
||||
>
|
||||
{locale.start}
|
||||
</LinkButton>
|
||||
<LinkButton
|
||||
size="large"
|
||||
to={utils.getLocalizedPathname('/docs/spec/introduce/', isZhCN, search)}
|
||||
>
|
||||
{locale.designLanguage}
|
||||
</LinkButton>
|
||||
</Flex>
|
||||
<div className={styles.child}>{children}</div>
|
||||
</div>
|
||||
|
@ -14,7 +14,7 @@ const useStyle = createStyles(({ token }) => ({
|
||||
image: css`
|
||||
transition: all ${token.motionDurationSlow};
|
||||
position: absolute;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
@ -64,10 +64,11 @@ const BackgroundImage: React.FC<BackgroundImageProps> = ({ colorPrimary, isLight
|
||||
<source srcSet={entity.webp} type="image/webp" />
|
||||
<source srcSet={entity.url} type="image/jpeg" />
|
||||
<img
|
||||
draggable={false}
|
||||
className={cls}
|
||||
style={{ ...style, opacity: isLight ? opacity : 0 }}
|
||||
src={entity.url}
|
||||
alt=""
|
||||
alt="bg"
|
||||
/>
|
||||
</picture>
|
||||
);
|
||||
|
@ -1,12 +1,14 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { ColorPicker, Flex, Input } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
import type { Color } from 'antd/es/color-picker';
|
||||
import type { ColorPickerProps, GetProp } from 'antd';
|
||||
import { generateColor } from 'antd/es/color-picker/util';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { PRESET_COLORS } from './colorUtil';
|
||||
|
||||
type Color = Extract<GetProp<ColorPickerProps, 'value'>, string | { cleared: any }>;
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => ({
|
||||
color: css`
|
||||
width: ${token.controlHeightLG / 2}px;
|
||||
@ -34,13 +36,13 @@ const useStyle = createStyles(({ token, css }) => ({
|
||||
`,
|
||||
}));
|
||||
|
||||
export interface ColorPickerProps {
|
||||
export interface ThemeColorPickerProps {
|
||||
id?: string;
|
||||
value?: string | Color;
|
||||
onChange?: (value?: Color | string) => void;
|
||||
}
|
||||
|
||||
const DebouncedColorPicker: React.FC<React.PropsWithChildren<ColorPickerProps>> = (props) => {
|
||||
const DebouncedColorPicker: React.FC<React.PropsWithChildren<ThemeColorPickerProps>> = (props) => {
|
||||
const { value: color, children, onChange } = props;
|
||||
const [value, setValue] = useState(color);
|
||||
|
||||
@ -66,7 +68,7 @@ const DebouncedColorPicker: React.FC<React.PropsWithChildren<ColorPickerProps>>
|
||||
);
|
||||
};
|
||||
|
||||
const ThemeColorPicker: React.FC<ColorPickerProps> = ({ value, onChange, id }) => {
|
||||
const ThemeColorPicker: React.FC<ThemeColorPickerProps> = ({ value, onChange, id }) => {
|
||||
const { styles } = useStyle();
|
||||
|
||||
const matchColors = React.useMemo(() => {
|
||||
@ -114,6 +116,7 @@ const ThemeColorPicker: React.FC<ColorPickerProps> = ({ value, onChange, id }) =
|
||||
<input
|
||||
type="radio"
|
||||
name={picker ? 'picker' : 'color'}
|
||||
aria-label={color}
|
||||
tabIndex={picker ? -1 : 0}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
/>
|
||||
|
@ -113,7 +113,7 @@ const MobileCarousel: React.FC<MobileCarouselProps> = (props) => {
|
||||
<Carousel className={styles.carousel} afterChange={setCurrentSlider}>
|
||||
{mobileImageConfigList.map((item, index) => (
|
||||
<div key={index}>
|
||||
<img src={item.imageSrc} className={styles.img} alt="" />
|
||||
<img draggable={false} src={item.imageSrc} className={styles.img} alt="carousel" />
|
||||
</div>
|
||||
))}
|
||||
</Carousel>
|
||||
|
@ -15,7 +15,7 @@ const RadiusPicker: React.FC<RadiusPickerProps> = ({ id, value, onChange }) => (
|
||||
style={{ width: 120 }}
|
||||
min={0}
|
||||
formatter={(val) => `${val}px`}
|
||||
parser={(str) => (str ? parseFloat(str) : (str as any))}
|
||||
parser={(str) => str?.replace('px', '') as unknown as number}
|
||||
id={id}
|
||||
/>
|
||||
<Slider
|
||||
|
@ -1,6 +1,8 @@
|
||||
import type { Color } from 'antd/es/color-picker';
|
||||
import type { ColorPickerProps, GetProp } from 'antd';
|
||||
import { generateColor } from 'antd/es/color-picker/util';
|
||||
|
||||
type Color = GetProp<ColorPickerProps, 'value'>;
|
||||
|
||||
export const DEFAULT_COLOR = '#1677FF';
|
||||
export const PINK_COLOR = '#ED4192';
|
||||
|
||||
|
@ -7,10 +7,9 @@ import {
|
||||
QuestionCircleOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { TinyColor } from '@ctrl/tinycolor';
|
||||
import type { MenuProps, ThemeConfig } from 'antd';
|
||||
import type { ColorPickerProps, GetProp, MenuProps, ThemeConfig } from 'antd';
|
||||
import {
|
||||
Breadcrumb,
|
||||
Button,
|
||||
Card,
|
||||
ConfigProvider,
|
||||
Flex,
|
||||
@ -22,14 +21,13 @@ import {
|
||||
Typography,
|
||||
} from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
import type { Color } from 'antd/es/color-picker';
|
||||
import { generateColor } from 'antd/es/color-picker/util';
|
||||
import classNames from 'classnames';
|
||||
import { useLocation } from 'dumi';
|
||||
|
||||
import useDark from '../../../../hooks/useDark';
|
||||
import useLocale from '../../../../hooks/useLocale';
|
||||
import Link from '../../../../theme/common/Link';
|
||||
import LinkButton from '../../../../theme/common/LinkButton';
|
||||
import SiteContext from '../../../../theme/slots/SiteContext';
|
||||
import { getLocalizedPathname } from '../../../../theme/utils';
|
||||
import Group from '../Group';
|
||||
@ -42,6 +40,8 @@ import RadiusPicker from './RadiusPicker';
|
||||
import type { THEME } from './ThemePicker';
|
||||
import ThemePicker from './ThemePicker';
|
||||
|
||||
type Color = Extract<GetProp<ColorPickerProps, 'value'>, string | { cleared: any }>;
|
||||
|
||||
const { Header, Content, Sider } = Layout;
|
||||
|
||||
const TokenChecker: React.FC = () => {
|
||||
@ -195,23 +195,23 @@ const useStyle = createStyles(({ token, css, cx }) => {
|
||||
position: absolute;
|
||||
`,
|
||||
leftTopImagePos: css`
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
top: -100px;
|
||||
height: 500px;
|
||||
`,
|
||||
rightBottomPos: css`
|
||||
right: 0;
|
||||
inset-inline-end: 0;
|
||||
bottom: -100px;
|
||||
height: 287px;
|
||||
`,
|
||||
leftTopImage: css`
|
||||
left: 50%;
|
||||
inset-inline-start: 50%;
|
||||
transform: translate3d(-900px, 0, 0);
|
||||
top: -100px;
|
||||
height: 500px;
|
||||
`,
|
||||
rightBottomImage: css`
|
||||
right: 50%;
|
||||
inset-inline-end: 50%;
|
||||
transform: translate3d(750px, 0, 0);
|
||||
bottom: -100px;
|
||||
height: 287px;
|
||||
@ -265,7 +265,7 @@ const sideMenuItems: MenuProps['items'] = [
|
||||
|
||||
// ============================= Theme =============================
|
||||
|
||||
function getTitleColor(colorPrimary: string | Color, isLight?: boolean) {
|
||||
function getTitleColor(colorPrimary: Color, isLight?: boolean) {
|
||||
if (!isLight) {
|
||||
return '#FFF';
|
||||
}
|
||||
@ -290,7 +290,7 @@ function getTitleColor(colorPrimary: string | Color, isLight?: boolean) {
|
||||
|
||||
interface ThemeData {
|
||||
themeType: THEME;
|
||||
colorPrimary: string | Color;
|
||||
colorPrimary: Color;
|
||||
borderRadius: number;
|
||||
compact: 'default' | 'compact';
|
||||
}
|
||||
@ -474,7 +474,7 @@ const Theme: React.FC = () => {
|
||||
filter:
|
||||
closestColor === DEFAULT_COLOR ? undefined : rgbToColorMatrix(logoColor),
|
||||
}}
|
||||
alt=""
|
||||
alt="antd logo"
|
||||
/>
|
||||
</div>
|
||||
<h1>Ant Design 5.0</h1>
|
||||
@ -518,14 +518,15 @@ const Theme: React.FC = () => {
|
||||
title={locale.myTheme}
|
||||
extra={
|
||||
<Flex gap="small">
|
||||
<Link to={getLocalizedPathname('/theme-editor', isZhCN, search)}>
|
||||
<Button type="default">{locale.toDef}</Button>
|
||||
</Link>
|
||||
<Link
|
||||
<LinkButton to={getLocalizedPathname('/theme-editor', isZhCN, search)}>
|
||||
{locale.toDef}
|
||||
</LinkButton>
|
||||
<LinkButton
|
||||
type="primary"
|
||||
to={getLocalizedPathname('/docs/react/customize-theme', isZhCN, search)}
|
||||
>
|
||||
<Button type="primary">{locale.toUse}</Button>
|
||||
</Link>
|
||||
{locale.toUse}
|
||||
</LinkButton>
|
||||
</Flex>
|
||||
}
|
||||
>
|
||||
|
@ -5,8 +5,8 @@ import { createStyles, css } from 'antd-style';
|
||||
import useDark from '../../hooks/useDark';
|
||||
import useLocale from '../../hooks/useLocale';
|
||||
import BannerRecommends from './components/BannerRecommends';
|
||||
import PreviewBanner from './components/PreviewBanner';
|
||||
import Group from './components/Group';
|
||||
import PreviewBanner from './components/PreviewBanner';
|
||||
|
||||
const ComponentsList = React.lazy(() => import('./components/ComponentsList'));
|
||||
const DesignFramework = React.lazy(() => import('./components/DesignFramework'));
|
||||
@ -15,7 +15,7 @@ const Theme = React.lazy(() => import('./components/Theme'));
|
||||
const useStyle = createStyles(() => ({
|
||||
image: css`
|
||||
position: absolute;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
top: -50px;
|
||||
height: 160px;
|
||||
`,
|
||||
@ -78,12 +78,13 @@ const Homepage: React.FC = () => {
|
||||
<Group
|
||||
title={locale.designTitle}
|
||||
description={locale.designDesc}
|
||||
background={isRootDark ? 'rgb(57, 63, 74)' : '#F5F8FF'}
|
||||
background={isRootDark ? '#393F4A' : '#F5F8FF'}
|
||||
decoration={
|
||||
<img
|
||||
draggable={false}
|
||||
className={styles.image}
|
||||
src="https://gw.alipayobjects.com/zos/bmw-prod/ba37a413-28e6-4be4-b1c5-01be1a0ebb1c.svg"
|
||||
alt=""
|
||||
alt="bg"
|
||||
/>
|
||||
}
|
||||
>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { Suspense, useEffect } from 'react';
|
||||
import { Button, message, Skeleton } from 'antd';
|
||||
import { Button, App, Skeleton } from 'antd';
|
||||
import { enUS, zhCN } from 'antd-token-previewer';
|
||||
import type { ThemeConfig } from 'antd/es/config-provider/context';
|
||||
import { Helmet } from 'dumi';
|
||||
@ -36,7 +36,7 @@ const locales = {
|
||||
const ANT_DESIGN_V5_THEME_EDITOR_THEME = 'ant-design-v5-theme-editor-theme';
|
||||
|
||||
const CustomTheme: React.FC = () => {
|
||||
const [messageApi, contextHolder] = message.useMessage();
|
||||
const { message } = App.useApp();
|
||||
const [locale, lang] = useLocale(locales);
|
||||
|
||||
const [theme, setTheme] = React.useState<ThemeConfig>({});
|
||||
@ -51,7 +51,7 @@ const CustomTheme: React.FC = () => {
|
||||
|
||||
const handleSave = () => {
|
||||
localStorage.setItem(ANT_DESIGN_V5_THEME_EDITOR_THEME, JSON.stringify(theme));
|
||||
messageApi.success(locale.saveSuccessfully);
|
||||
message.success(locale.saveSuccessfully);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -60,7 +60,6 @@ const CustomTheme: React.FC = () => {
|
||||
<title>{`${locale.title} - Ant Design`}</title>
|
||||
<meta property="og:title" content={`${locale.title} - Ant Design`} />
|
||||
</Helmet>
|
||||
{contextHolder}
|
||||
<Suspense fallback={<Skeleton style={{ margin: 24 }} />}>
|
||||
<ThemeEditor
|
||||
advanced
|
||||
|
@ -74,7 +74,7 @@ function rehypeAntd(): UnifiedTransformer<HastRoot> {
|
||||
const code = (node.children[0] as any).value as string;
|
||||
const configRegx = /^const sandpackConfig = ([\S\s]*?});/;
|
||||
const [configString] = code.match(configRegx) || [];
|
||||
// eslint-disable-next-line no-eval
|
||||
/* biome-ignore lint/security/noGlobalEval: used in documentation */ /* eslint-disable-next-line no-eval */
|
||||
const config = configString && eval(`(${configString.replace(configRegx, '$1')})`);
|
||||
Object.keys(config || {}).forEach((key) => {
|
||||
if (typeof config[key] === 'object') {
|
||||
|
14
.dumi/scripts/clarity.js
Normal file
14
.dumi/scripts/clarity.js
Normal file
@ -0,0 +1,14 @@
|
||||
/* eslint-disable */
|
||||
// https://clarity.microsoft.com
|
||||
(function (c, l, a, r, i, t, y) {
|
||||
c[a] =
|
||||
c[a] ||
|
||||
function () {
|
||||
(c[a].q = c[a].q || []).push(arguments);
|
||||
};
|
||||
t = l.createElement(r);
|
||||
t.async = 1;
|
||||
t.src = 'https://www.clarity.ms/tag/' + i;
|
||||
y = l.getElementsByTagName(r)[0];
|
||||
y.parentNode.insertBefore(t, y);
|
||||
})(window, document, 'clarity', 'script', 'lyia7jfwui');
|
@ -3,7 +3,8 @@
|
||||
(navigator.languages.includes('zh') || navigator.languages.includes('zh-CN')) &&
|
||||
/-cn\/?$/.test(window.location.pathname) &&
|
||||
!['ant-design.gitee.io', 'ant-design.antgroup.com'].includes(window.location.hostname) &&
|
||||
!window.location.host.includes('surge')
|
||||
!window.location.host.includes('surge') &&
|
||||
window.location.hostname !== 'localhost'
|
||||
) {
|
||||
const ANTD_DOT_NOT_SHOW_MIRROR_MODAL = 'ANT_DESIGN_DO_NOT_OPEN_MIRROR_MODAL';
|
||||
|
||||
@ -49,8 +50,8 @@
|
||||
.mirror-modal-dialog {
|
||||
position: fixed;
|
||||
top: 120px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-end: 0;
|
||||
margin: 0 auto;
|
||||
width: 420px;
|
||||
display: flex;
|
@ -116,12 +116,21 @@ const ComponentMeta: React.FC<ComponentMetaProps> = (props) => {
|
||||
return [source, source];
|
||||
}, [component, source]);
|
||||
|
||||
const transformComponentName = (componentName: string) => {
|
||||
if (componentName === 'Notifiction' || componentName === 'Message') {
|
||||
return componentName.toLowerCase();
|
||||
}
|
||||
return componentName;
|
||||
};
|
||||
|
||||
// ======================== Render ========================
|
||||
const importList = [
|
||||
<span key="import" className={styles.import}>
|
||||
import
|
||||
</span>,
|
||||
<span key="component" className={styles.component}>{`{ ${component} }`}</span>,
|
||||
<span key="component" className={styles.component}>{`{ ${transformComponentName(
|
||||
component,
|
||||
)} }`}</span>,
|
||||
<span key="from" className={styles.from}>
|
||||
from
|
||||
</span>,
|
||||
@ -139,7 +148,7 @@ const ComponentMeta: React.FC<ComponentMetaProps> = (props) => {
|
||||
colon={false}
|
||||
column={1}
|
||||
style={{ marginTop: token.margin }}
|
||||
labelStyle={{ paddingInlineEnd: token.padding, width: 54 }}
|
||||
labelStyle={{ paddingInlineEnd: token.padding, width: 56 }}
|
||||
items={
|
||||
[
|
||||
{
|
||||
|
@ -198,46 +198,59 @@ const Overview: React.FC = () => {
|
||||
</Title>
|
||||
<Row gutter={[24, 24]}>
|
||||
{components.map((component) => {
|
||||
let url = component.link;
|
||||
/** 是否是外链 */
|
||||
const isExternalLink = component.link.startsWith('http');
|
||||
let url = `${component.link}`;
|
||||
const isExternalLink = url.startsWith('http');
|
||||
|
||||
if (!isExternalLink) {
|
||||
url += urlSearch;
|
||||
}
|
||||
|
||||
return (
|
||||
<Col xs={24} sm={12} lg={8} xl={6} key={component?.title}>
|
||||
<Link to={url}>
|
||||
<Card
|
||||
onClick={() => onClickCard(url)}
|
||||
styles={{
|
||||
body: {
|
||||
backgroundRepeat: 'no-repeat',
|
||||
backgroundPosition: 'bottom right',
|
||||
backgroundImage: `url(${component?.tag || ''})`,
|
||||
},
|
||||
}}
|
||||
size="small"
|
||||
className={styles.componentsOverviewCard}
|
||||
title={
|
||||
<div className={styles.componentsOverviewTitle}>
|
||||
{component?.title} {component.subtitle}
|
||||
</div>
|
||||
const cardContent = (
|
||||
<Card
|
||||
key={component.title}
|
||||
onClick={() => onClickCard(url)}
|
||||
styles={{
|
||||
body: {
|
||||
backgroundRepeat: 'no-repeat',
|
||||
backgroundPosition: 'bottom right',
|
||||
backgroundImage: `url(${component.tag || ''})`,
|
||||
},
|
||||
}}
|
||||
size="small"
|
||||
className={styles.componentsOverviewCard}
|
||||
title={
|
||||
<div className={styles.componentsOverviewTitle}>
|
||||
{component.title} {component.subtitle}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className={styles.componentsOverviewImg}>
|
||||
<img
|
||||
src={
|
||||
theme.includes('dark') && component.coverDark
|
||||
? component.coverDark
|
||||
: component.cover
|
||||
}
|
||||
>
|
||||
<div className={styles.componentsOverviewImg}>
|
||||
<img
|
||||
src={
|
||||
theme.includes('dark') && component.coverDark
|
||||
? component.coverDark
|
||||
: component.cover
|
||||
}
|
||||
alt={component?.title}
|
||||
/>
|
||||
</div>
|
||||
</Card>
|
||||
</Link>
|
||||
alt={component.title}
|
||||
/>
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
|
||||
const linkContent = isExternalLink ? (
|
||||
<a href={url} key={component.title}>
|
||||
{cardContent}
|
||||
</a>
|
||||
) : (
|
||||
<Link to={url} prefetch key={component.title}>
|
||||
{cardContent}
|
||||
</Link>
|
||||
);
|
||||
|
||||
return (
|
||||
<Col xs={24} sm={12} lg={8} xl={6} key={component.title}>
|
||||
{linkContent}
|
||||
</Col>
|
||||
);
|
||||
})}
|
||||
|
@ -156,7 +156,7 @@ const SubTokenTable: React.FC<SubTokenTableProps> = (props) => {
|
||||
{title}
|
||||
<Popover
|
||||
title={null}
|
||||
popupStyle={{ width: 400 }}
|
||||
overlayStyle={{ width: 400 }}
|
||||
content={
|
||||
<Typography>
|
||||
{/* <SourceCode lang="jsx">{code}</SourceCode> */}
|
||||
|
@ -51,32 +51,27 @@ const DemoWrapper: typeof DumiDemoGrid = ({ items }) => {
|
||||
|
||||
const demos = React.useMemo(
|
||||
() =>
|
||||
items.reduce(
|
||||
(acc, item) => {
|
||||
const { previewerProps } = item;
|
||||
const { debug } = previewerProps;
|
||||
|
||||
if (debug && !showDebug) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
return acc.concat({
|
||||
...item,
|
||||
previewerProps: {
|
||||
...previewerProps,
|
||||
expand: expandAll,
|
||||
// always override debug property, because dumi will hide debug demo in production
|
||||
debug: false,
|
||||
/**
|
||||
* antd extra marker for the original debug
|
||||
* @see https://github.com/ant-design/ant-design/pull/40130#issuecomment-1380208762
|
||||
*/
|
||||
originDebug: debug,
|
||||
},
|
||||
});
|
||||
},
|
||||
[] as typeof items,
|
||||
),
|
||||
items.reduce<typeof items>((acc, item) => {
|
||||
const { previewerProps } = item;
|
||||
const { debug } = previewerProps;
|
||||
if (debug && !showDebug) {
|
||||
return acc;
|
||||
}
|
||||
return acc.concat({
|
||||
...item,
|
||||
previewerProps: {
|
||||
...previewerProps,
|
||||
expand: expandAll,
|
||||
// always override debug property, because dumi will hide debug demo in production
|
||||
debug: false,
|
||||
/**
|
||||
* antd extra marker for the original debug
|
||||
* @see https://github.com/ant-design/ant-design/pull/40130#issuecomment-1380208762
|
||||
*/
|
||||
originDebug: debug,
|
||||
},
|
||||
});
|
||||
}, []),
|
||||
[expandAll, showDebug],
|
||||
);
|
||||
|
||||
|
@ -1,9 +1,30 @@
|
||||
import * as React from 'react';
|
||||
import { App } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
import { useIntl } from 'dumi';
|
||||
import { message } from 'antd';
|
||||
|
||||
import CopyableIcon from './CopyableIcon';
|
||||
import type { ThemeType } from './index';
|
||||
import type { CategoriesKeys } from './fields';
|
||||
import type { ThemeType } from './IconSearch';
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => ({
|
||||
anticonsList: css`
|
||||
margin: ${token.margin}px 0;
|
||||
overflow: hidden;
|
||||
direction: ltr;
|
||||
list-style: none;
|
||||
display: grid;
|
||||
grid-gap: ${token.margin}px;
|
||||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
||||
padding: 0;
|
||||
`,
|
||||
copiedCode: css`
|
||||
padding: 0 ${token.paddingXXS}px;
|
||||
font-size: ${token.fontSizeSM}px;
|
||||
background-color: ${token.colorBgLayout};
|
||||
border-radius: ${token.borderRadiusXS}px;
|
||||
`,
|
||||
}));
|
||||
|
||||
interface CategoryProps {
|
||||
title: CategoriesKeys;
|
||||
@ -13,14 +34,16 @@ interface CategoryProps {
|
||||
}
|
||||
|
||||
const Category: React.FC<CategoryProps> = (props) => {
|
||||
const { message } = App.useApp();
|
||||
const { icons, title, newIcons, theme } = props;
|
||||
const { styles } = useStyle();
|
||||
const intl = useIntl();
|
||||
const [justCopied, setJustCopied] = React.useState<string | null>(null);
|
||||
const copyId = React.useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
const onCopied = React.useCallback((type: string, text: string) => {
|
||||
message.success(
|
||||
<span>
|
||||
<code className="copied-code">{text}</code> copied 🎉
|
||||
<code className={styles.copiedCode}>{text}</code> copied 🎉
|
||||
</span>,
|
||||
);
|
||||
setJustCopied(type);
|
||||
@ -39,7 +62,7 @@ const Category: React.FC<CategoryProps> = (props) => {
|
||||
return (
|
||||
<div>
|
||||
<h3>{intl.formatMessage({ id: `app.docs.components.icon.category.${title}` })}</h3>
|
||||
<ul className="anticons-list">
|
||||
<ul className={styles.anticonsList}>
|
||||
{icons.map((name) => (
|
||||
<CopyableIcon
|
||||
key={name}
|
||||
|
@ -1,33 +1,102 @@
|
||||
import * as React from 'react';
|
||||
import CopyToClipboard from 'react-copy-to-clipboard';
|
||||
import classNames from 'classnames';
|
||||
import React from 'react';
|
||||
import * as AntdIcons from '@ant-design/icons';
|
||||
import { Badge, message } from 'antd';
|
||||
import type { ThemeType } from './index';
|
||||
import { App, Badge } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
import classNames from 'classnames';
|
||||
import CopyToClipboard from 'react-copy-to-clipboard';
|
||||
|
||||
const allIcons: {
|
||||
[key: string]: any;
|
||||
} = AntdIcons;
|
||||
import type { ThemeType } from './IconSearch';
|
||||
|
||||
const allIcons: { [key: PropertyKey]: any } = AntdIcons;
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => {
|
||||
const { antCls, iconCls } = token;
|
||||
return {
|
||||
iconItem: css`
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-inline-start: 0 !important;
|
||||
margin-inline-end: 0 !important;
|
||||
padding-inline-start: 0 !important;
|
||||
padding-inline-end: 0 !important;
|
||||
position: relative;
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
overflow: hidden;
|
||||
color: #555;
|
||||
text-align: center;
|
||||
list-style: none;
|
||||
background-color: inherit;
|
||||
border-radius: ${token.borderRadiusSM}px;
|
||||
cursor: pointer;
|
||||
transition: all ${token.motionDurationSlow} ease-in-out;
|
||||
${token.iconCls} {
|
||||
margin: ${token.marginXS}px 0;
|
||||
font-size: 36px;
|
||||
transition: transform ${token.motionDurationSlow} ease-in-out;
|
||||
will-change: transform;
|
||||
}
|
||||
&:hover {
|
||||
color: ${token.colorWhite};
|
||||
background-color: ${token.colorPrimary};
|
||||
${iconCls} {
|
||||
transform: scale(1.3);
|
||||
}
|
||||
${antCls}-badge {
|
||||
color: ${token.colorWhite};
|
||||
}
|
||||
}
|
||||
&.TwoTone:hover {
|
||||
background-color: #8ecafe;
|
||||
}
|
||||
&.copied:hover {
|
||||
color: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
&::after {
|
||||
content: 'Copied!';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
inset-inline-start: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
line-height: 100px;
|
||||
color: ${token.colorTextLightSolid};
|
||||
text-align: center;
|
||||
background-color: ${token.colorPrimary};
|
||||
opacity: 0;
|
||||
transition: all ${token.motionDurationSlow} cubic-bezier(0.18, 0.89, 0.32, 1.28);
|
||||
}
|
||||
&.copied::after {
|
||||
opacity: 1;
|
||||
}
|
||||
`,
|
||||
anticonCls: css`
|
||||
display: block;
|
||||
font-family: 'Lucida Console', Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
transform: scale(0.8);
|
||||
${antCls}-badge {
|
||||
transition: color ${token.motionDurationSlow} ease-in-out;
|
||||
}
|
||||
`,
|
||||
};
|
||||
});
|
||||
|
||||
export interface CopyableIconProps {
|
||||
name: string;
|
||||
isNew: boolean;
|
||||
theme: ThemeType;
|
||||
justCopied: string | null;
|
||||
onCopied: (type: string, text: string) => any;
|
||||
onCopied: (type: string, text: string) => void;
|
||||
}
|
||||
|
||||
const CopyableIcon: React.FC<CopyableIconProps> = ({
|
||||
name,
|
||||
isNew,
|
||||
justCopied,
|
||||
onCopied,
|
||||
theme,
|
||||
}) => {
|
||||
const className = classNames({
|
||||
copied: justCopied === name,
|
||||
[theme]: !!theme,
|
||||
});
|
||||
const CopyableIcon: React.FC<CopyableIconProps> = (props) => {
|
||||
const { message } = App.useApp();
|
||||
const { name, isNew, justCopied, theme, onCopied } = props;
|
||||
const { styles } = useStyle();
|
||||
const onCopy = (text: string, result: boolean) => {
|
||||
if (result) {
|
||||
onCopied(name, text);
|
||||
@ -37,9 +106,9 @@ const CopyableIcon: React.FC<CopyableIconProps> = ({
|
||||
};
|
||||
return (
|
||||
<CopyToClipboard text={`<${name} />`} onCopy={onCopy}>
|
||||
<li className={className}>
|
||||
<li className={classNames(theme, styles.iconItem, { copied: justCopied === name })}>
|
||||
{React.createElement(allIcons[name])}
|
||||
<span className="anticon-class">
|
||||
<span className={styles.anticonCls}>
|
||||
<Badge dot={isNew}>{name}</Badge>
|
||||
</span>
|
||||
</li>
|
||||
|
@ -81,7 +81,7 @@ const IconSearch: React.FC = () => {
|
||||
if (searchKey) {
|
||||
const matchKey = searchKey
|
||||
// eslint-disable-next-line prefer-regex-literals
|
||||
.replace(new RegExp(`^<([a-zA-Z]*)\\s/>$`, 'gi'), (_, name) => name)
|
||||
.replace(/^<([a-z]*)\s\/>$/gi, (_, name) => name)
|
||||
.replace(/(Filled|Outlined|TwoTone)$/, '')
|
||||
.toLowerCase();
|
||||
iconList = iconList.filter((iconName) => iconName.toLowerCase().includes(matchKey));
|
||||
|
@ -12,6 +12,7 @@ export const FilledIcon: CustomIconComponent = (props) => {
|
||||
'0c0-53-43-96-96-96z';
|
||||
return (
|
||||
<svg {...props} viewBox="0 0 1024 1024">
|
||||
<title>Filled Icon</title>
|
||||
<path d={path} />
|
||||
</svg>
|
||||
);
|
||||
@ -26,6 +27,7 @@ export const OutlinedIcon: CustomIconComponent = (props) => {
|
||||
' 12 12v680c0 6.6-5.4 12-12 12z';
|
||||
return (
|
||||
<svg {...props} viewBox="0 0 1024 1024">
|
||||
<title>Outlined Icon</title>
|
||||
<path d={path} />
|
||||
</svg>
|
||||
);
|
||||
@ -39,6 +41,7 @@ export const TwoToneIcon: CustomIconComponent = (props) => {
|
||||
'68 368 0 203.41-164.622 368-368 368z';
|
||||
return (
|
||||
<svg {...props} viewBox="0 0 1024 1024">
|
||||
<title>TwoTone Icon</title>
|
||||
<path d={path} />
|
||||
</svg>
|
||||
);
|
||||
|
@ -117,6 +117,7 @@ const ImagePreview: React.FC<React.PropsWithChildren<ImagePreviewProps>> = (prop
|
||||
<div className="preview-image-title">{coverMeta.alt}</div>
|
||||
<div
|
||||
className="preview-image-description"
|
||||
// biome-ignore lint/security/noDangerouslySetInnerHtml: it's for markdown
|
||||
dangerouslySetInnerHTML={{ __html: coverMeta.description ?? '' }}
|
||||
/>
|
||||
</div>
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { PictureOutlined } from '@ant-design/icons';
|
||||
import React from 'react';
|
||||
import { PictureOutlined } from '@ant-design/icons';
|
||||
import { Image, Tooltip, Typography } from 'antd';
|
||||
|
||||
import useLocale from '../../../hooks/useLocale';
|
||||
|
||||
const locales = {
|
||||
|
@ -3,10 +3,10 @@ import { ConfigProvider, Tabs } from 'antd';
|
||||
import SourceCode from 'dumi/theme-default/builtins/SourceCode';
|
||||
import type { Tab } from 'rc-tabs/lib/interface';
|
||||
|
||||
import BunLogo from './bun';
|
||||
import NpmLogo from './npm';
|
||||
import PnpmLogo from './pnpm';
|
||||
import YarnLogo from './yarn';
|
||||
import BunLogo from './bun';
|
||||
|
||||
interface InstallProps {
|
||||
npm?: string;
|
||||
|
@ -31,6 +31,7 @@ const NpmIcon: React.FC<IconProps> = (props) => {
|
||||
viewBox="0 0 16 16"
|
||||
width="1em"
|
||||
>
|
||||
<title>npm icon</title>
|
||||
<path d="M0 0v16h16v-16h-16zM13 13h-2v-8h-3v8h-5v-10h10v10z" />
|
||||
</svg>
|
||||
</span>
|
||||
|
@ -33,6 +33,7 @@ const PnpmIcon: React.FC<IconProps> = (props) => {
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
>
|
||||
<title>pnpm icon</title>
|
||||
<path d="M0 0v7.5h7.5V0zm8.25 0v7.5h7.498V0zm8.25 0v7.5H24V0zM8.25 8.25v7.5h7.498v-7.5zm8.25 0v7.5H24v-7.5zM0 16.5V24h7.5v-7.5zm8.25 0V24h7.498v-7.5zm8.25 0V24H24v-7.5z" />
|
||||
</svg>
|
||||
</span>
|
||||
|
@ -32,6 +32,7 @@ const YarnIcon: React.FC<IconProps> = (props) => {
|
||||
viewBox="0 0 496 512"
|
||||
width="1em"
|
||||
>
|
||||
<title>yarn icon</title>
|
||||
<path d="M393.9 345.2c-39 9.3-48.4 32.1-104 47.4 0 0-2.7 4-10.4 5.8-13.4 3.3-63.9 6-68.5 6.1-12.4.1-19.9-3.2-22-8.2-6.4-15.3 9.2-22 9.2-22-8.1-5-9-9.9-9.8-8.1-2.4 5.8-3.6 20.1-10.1 26.5-8.8 8.9-25.5 5.9-35.3.8-10.8-5.7.8-19.2.8-19.2s-5.8 3.4-10.5-3.6c-6-9.3-17.1-37.3 11.5-62-1.3-10.1-4.6-53.7 40.6-85.6 0 0-20.6-22.8-12.9-43.3 5-13.4 7-13.3 8.6-13.9 5.7-2.2 11.3-4.6 15.4-9.1 20.6-22.2 46.8-18 46.8-18s12.4-37.8 23.9-30.4c3.5 2.3 16.3 30.6 16.3 30.6s13.6-7.9 15.1-5c8.2 16 9.2 46.5 5.6 65.1-6.1 30.6-21.4 47.1-27.6 57.5-1.4 2.4 16.5 10 27.8 41.3 10.4 28.6 1.1 52.7 2.8 55.3.8 1.4 13.7.8 36.4-13.2 12.8-7.9 28.1-16.9 45.4-17 16.7-.5 17.6 19.2 4.9 22.2zM496 256c0 136.9-111.1 248-248 248S0 392.9 0 256 111.1 8 248 8s248 111.1 248 248zm-79.3 75.2c-1.7-13.6-13.2-23-28-22.8-22 .3-40.5 11.7-52.8 19.2-4.8 3-8.9 5.2-12.4 6.8 3.1-44.5-22.5-73.1-28.7-79.4 7.8-11.3 18.4-27.8 23.4-53.2 4.3-21.7 3-55.5-6.9-74.5-1.6-3.1-7.4-11.2-21-7.4-9.7-20-13-22.1-15.6-23.8-1.1-.7-23.6-16.4-41.4 28-12.2.9-31.3 5.3-47.5 22.8-2 2.2-5.9 3.8-10.1 5.4h.1c-8.4 3-12.3 9.9-16.9 22.3-6.5 17.4.2 34.6 6.8 45.7-17.8 15.9-37 39.8-35.7 82.5-34 36-11.8 73-5.6 79.6-1.6 11.1 3.7 19.4 12 23.8 12.6 6.7 30.3 9.6 43.9 2.8 4.9 5.2 13.8 10.1 30 10.1 6.8 0 58-2.9 72.6-6.5 6.8-1.6 11.5-4.5 14.6-7.1 9.8-3.1 36.8-12.3 62.2-28.7 18-11.7 24.2-14.2 37.6-17.4 12.9-3.2 21-15.1 19.4-28.2z" />
|
||||
</svg>
|
||||
</span>
|
||||
|
@ -11,12 +11,12 @@ import LZString from 'lz-string';
|
||||
import useLocation from '../../../hooks/useLocation';
|
||||
import BrowserFrame from '../../common/BrowserFrame';
|
||||
import ClientOnly from '../../common/ClientOnly';
|
||||
import CodePenIcon from '../../common/CodePenIcon';
|
||||
import CodePreview from '../../common/CodePreview';
|
||||
import CodeSandboxIcon from '../../common/CodeSandboxIcon';
|
||||
import EditButton from '../../common/EditButton';
|
||||
import ExternalLinkIcon from '../../common/ExternalLinkIcon';
|
||||
import RiddleIcon from '../../common/RiddleIcon';
|
||||
import CodePenIcon from '../../icons/CodePenIcon';
|
||||
import CodeSandboxIcon from '../../icons/CodeSandboxIcon';
|
||||
import ExternalLinkIcon from '../../icons/ExternalLinkIcon';
|
||||
import RiddleIcon from '../../icons/RiddleIcon';
|
||||
import DemoContext from '../../slots/DemoContext';
|
||||
import type { SiteContextProps } from '../../slots/SiteContext';
|
||||
import SiteContext from '../../slots/SiteContext';
|
||||
@ -308,7 +308,9 @@ ${parsedSourceCode}
|
||||
.trim()
|
||||
.replace(new RegExp(`#${asset.id}\\s*`, 'g'), '')
|
||||
.replace('</style>', '')
|
||||
.replace('<style>', '');
|
||||
.replace('<style>', '')
|
||||
.replace('```css', '')
|
||||
.replace('```', '');
|
||||
|
||||
const indexJsContent = `import React from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
@ -401,6 +403,7 @@ createRoot(document.getElementById('container')).render(<Demo />);
|
||||
{description && (
|
||||
<div
|
||||
className="code-box-description"
|
||||
// biome-ignore lint/security/noDangerouslySetInnerHtml: it's for markdown
|
||||
dangerouslySetInnerHTML={{ __html: description }}
|
||||
/>
|
||||
)}
|
||||
|
@ -80,6 +80,7 @@ const DesignPreviewer: FC<AntdPreviewerProps> = ({ children, title, description,
|
||||
{title}
|
||||
</a>
|
||||
{description && (
|
||||
// biome-ignore lint/security/noDangerouslySetInnerHtml: description is from markdown
|
||||
<div className={styles.description} dangerouslySetInnerHTML={{ __html: description }} />
|
||||
)}
|
||||
<div className={styles.copy}>
|
||||
@ -89,10 +90,10 @@ const DesignPreviewer: FC<AntdPreviewerProps> = ({ children, title, description,
|
||||
<span style={{ marginInlineStart: 8 }}>已复制,使用 Kitchen 插件即可粘贴</span>
|
||||
</div>
|
||||
) : (
|
||||
<div onClick={handleCopy} className={styles.copyTip}>
|
||||
<button type="button" onClick={handleCopy} className={styles.copyTip}>
|
||||
<SketchOutlined />
|
||||
<span style={{ marginInlineStart: 8 }}>复制 Sketch JSON</span>
|
||||
</div>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.demo} ref={demoRef}>
|
||||
|
@ -1,40 +1,41 @@
|
||||
import React from 'react';
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons';
|
||||
import { Col, Row, Tooltip, Card, Typography } from 'antd';
|
||||
import { Card, Col, Row, Tooltip, Typography } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
|
||||
import useLocale from '../../../hooks/useLocale';
|
||||
|
||||
const { Paragraph } = Typography;
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => ({
|
||||
card: css`
|
||||
position: relative;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
.${token.antCls}-card-cover {
|
||||
overflow: hidden;
|
||||
|
||||
.ant-card-cover {
|
||||
overflow: hidden;
|
||||
}
|
||||
img {
|
||||
transition: all ${token.motionDurationSlow} ease-out;
|
||||
}
|
||||
|
||||
&:hover img {
|
||||
transform: scale(1.3);
|
||||
`,
|
||||
}
|
||||
img {
|
||||
display: block;
|
||||
transition: all ${token.motionDurationSlow} ease-out;
|
||||
}
|
||||
&:hover img {
|
||||
transform: scale(1.3);
|
||||
}
|
||||
`,
|
||||
badge: css`
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
padding: ${token.paddingXXS}px ${token.paddingXS}px;
|
||||
color: #fff;
|
||||
font-size: ${token.fontSizeSM}px;
|
||||
line-height: 1;
|
||||
background: rgba(0, 0, 0, 0.65);
|
||||
border-radius: ${token.borderRadiusLG}px;
|
||||
box-shadow: 0 0 2px rgba(255, 255, 255, 0.2);
|
||||
display: inline-flex;
|
||||
column-gap: ${token.paddingXXS}px;
|
||||
`,
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
inset-inline-end: 8px;
|
||||
padding: ${token.paddingXXS}px ${token.paddingXS}px;
|
||||
color: #fff;
|
||||
font-size: ${token.fontSizeSM}px;
|
||||
line-height: 1;
|
||||
background: rgba(0, 0, 0, 0.65);
|
||||
border-radius: ${token.borderRadiusLG}px;
|
||||
box-shadow: 0 0 2px rgba(255, 255, 255, 0.2);
|
||||
display: inline-flex;
|
||||
column-gap: ${token.paddingXXS}px;
|
||||
`,
|
||||
}));
|
||||
|
||||
export type Resource = {
|
||||
|
@ -6,7 +6,7 @@ import classNames from 'classnames';
|
||||
const useStyles = createStyles(({ cx, token }) => {
|
||||
const play = css`
|
||||
position: absolute;
|
||||
right: ${token.paddingLG}px;
|
||||
inset-inline-end: ${token.paddingLG}px;
|
||||
bottom: ${token.paddingLG}px;
|
||||
font-size: 64px;
|
||||
display: flex;
|
||||
|
@ -227,14 +227,14 @@ const useStyle = createStyles(({ token }) => ({
|
||||
title: css`
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 20px;
|
||||
inset-inline-start: 20px;
|
||||
font-size: ${token.fontSizeLG}px;
|
||||
`,
|
||||
tips: css`
|
||||
display: flex;
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
inset-inline-end: 20px;
|
||||
`,
|
||||
mvp: css`
|
||||
margin-inline-end: ${token.marginMD}px;
|
||||
|
@ -1,7 +1,47 @@
|
||||
import React from 'react';
|
||||
import { createStyles } from 'antd-style';
|
||||
|
||||
const BrowserFrame: React.FC<React.PropsWithChildren> = ({ children }) => (
|
||||
<div className="browser-mockup with-url">{children}</div>
|
||||
);
|
||||
const useStyle = createStyles(({ token, css }) => ({
|
||||
browserMockup: css`
|
||||
position: relative;
|
||||
border-top: 2em solid rgba(230, 230, 230, 0.7);
|
||||
border-radius: ${token.borderRadiusSM}px ${token.borderRadiusSM}px 0 0;
|
||||
box-shadow: 0 0.1em 0.5em 0 rgba(0, 0, 0, 0.28);
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: -1.25em;
|
||||
inset-inline-start: 1em;
|
||||
display: block;
|
||||
width: 0.5em;
|
||||
height: 0.5em;
|
||||
background-color: #f44;
|
||||
border-radius: 50%;
|
||||
box-shadow:
|
||||
0 0 0 2px #f44,
|
||||
1.5em 0 0 2px #9b3,
|
||||
3em 0 0 2px #fb5;
|
||||
content: '';
|
||||
}
|
||||
&::after {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: -1.6em;
|
||||
inset-inline-start: 5.5em;
|
||||
width: calc(100% - 6em);
|
||||
height: 1.2em;
|
||||
background-color: #fff;
|
||||
border-radius: ${token.borderRadiusSM}px;
|
||||
}
|
||||
& > * {
|
||||
display: block;
|
||||
}
|
||||
`,
|
||||
}));
|
||||
|
||||
const BrowserFrame: React.FC<React.PropsWithChildren> = ({ children }) => {
|
||||
const { styles } = useStyle();
|
||||
return <div className={styles.browserMockup}>{children}</div>;
|
||||
};
|
||||
|
||||
export default BrowserFrame;
|
||||
|
@ -40,9 +40,9 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
left: -9px;
|
||||
inset-inline-start: -9px;
|
||||
bottom: -5px;
|
||||
right: -9px;
|
||||
inset-inline-end: -9px;
|
||||
}
|
||||
}
|
||||
${antCls}-typography-copy:not(${antCls}-typography-copy-success) {
|
||||
@ -79,6 +79,7 @@ function toReactComponent(jsonML: any[]) {
|
||||
const attr = JsonML.getAttributes(node);
|
||||
return (
|
||||
<pre key={index} className={`language-${attr.lang}`}>
|
||||
{/* biome-ignore lint/security/noDangerouslySetInnerHtml: it's for markdown */}
|
||||
<code dangerouslySetInnerHTML={{ __html: attr.highlighted }} />
|
||||
</pre>
|
||||
);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { App } from 'antd';
|
||||
import CopyToClipboard from 'react-copy-to-clipboard';
|
||||
import { message } from 'antd';
|
||||
|
||||
interface ColorBlockProps {
|
||||
color: string;
|
||||
@ -9,6 +9,7 @@ interface ColorBlockProps {
|
||||
}
|
||||
|
||||
const ColorBlock: React.FC<ColorBlockProps> = (props) => {
|
||||
const { message } = App.useApp();
|
||||
const { color, index, dark } = props;
|
||||
const textStyle = useMemo<React.CSSProperties>(() => {
|
||||
const colorMap = { default: ['#fff', 'unset'], dark: ['#314659', '#fff'] };
|
||||
|
@ -11,14 +11,14 @@ const primaryMinBrightness = 70; // 主色推荐最小亮度
|
||||
|
||||
const locales = {
|
||||
cn: {
|
||||
saturation: (s: string) => `饱和度建议不低于${primaryMinSaturation}(现在${s})`,
|
||||
brightness: (b: string) => `亮度建议不低于${primaryMinBrightness}(现在${b})`,
|
||||
saturation: (s: string) => `饱和度建议不低于${primaryMinSaturation}(当前值 ${s})`,
|
||||
brightness: (b: string) => `亮度建议不低于${primaryMinBrightness}(当前值 ${b})`,
|
||||
},
|
||||
en: {
|
||||
saturation: (s: string) =>
|
||||
`Saturation is recommended not to be lower than ${primaryMinSaturation}(currently${s})`,
|
||||
`Saturation is recommended not to be lower than ${primaryMinSaturation} (currently ${s})`,
|
||||
brightness: (b: string) =>
|
||||
`Brightness is recommended not to be lower than ${primaryMinBrightness}(currently${b})`,
|
||||
`Brightness is recommended not to be lower than ${primaryMinBrightness} (currently ${b})`,
|
||||
},
|
||||
};
|
||||
|
||||
@ -41,7 +41,7 @@ const ColorPaletteTool: React.FC = () => {
|
||||
text += locale.saturation((s * 100).toFixed(2));
|
||||
}
|
||||
if (b * 100 < primaryMinBrightness) {
|
||||
text += locale.brightness((s * 100).toFixed(2));
|
||||
text += locale.brightness((b * 100).toFixed(2));
|
||||
}
|
||||
}
|
||||
return <span className="color-palette-picker-validation">{text.trim()}</span>;
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { FormattedMessage } from 'dumi';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import { Col, ColorPicker, Row } from 'antd';
|
||||
import ColorPatterns from './ColorPatterns';
|
||||
import { FormattedMessage } from 'dumi';
|
||||
import type { Color } from 'antd/es/color-picker';
|
||||
|
||||
import useLocale from '../../../hooks/useLocale';
|
||||
import ColorPatterns from './ColorPatterns';
|
||||
|
||||
const primaryMinSaturation = 70; // 主色推荐最小饱和度
|
||||
const primaryMinBrightness = 70; // 主色推荐最小亮度
|
||||
@ -23,7 +25,7 @@ const locales = {
|
||||
const ColorPaletteTool: React.FC = () => {
|
||||
const [primaryColor, setPrimaryColor] = useState<string>('#1890ff');
|
||||
const [backgroundColor, setBackgroundColor] = useState<string>('#141414');
|
||||
const [primaryColorInstance, setPrimaryColorInstance] = useState<Color>(null);
|
||||
const [primaryColorInstance, setPrimaryColorInstance] = useState<Color | null>(null);
|
||||
|
||||
const [locale] = useLocale(locales);
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import classNames from 'classnames';
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import Palette from './Palette';
|
||||
|
||||
const colors = [
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { generate } from '@ant-design/colors';
|
||||
import uniq from 'lodash/uniq';
|
||||
|
||||
import ColorBlock from './ColorBlock';
|
||||
|
||||
interface ColorPatternsProps {
|
||||
|
@ -21,7 +21,7 @@ const gray: { [key: number]: string } = {
|
||||
const ColorStyle: React.FC = () => {
|
||||
const token = useTheme();
|
||||
|
||||
const makePalette = (color: string, index: number = 1): string => {
|
||||
const makePalette = (color: string, index = 1): string => {
|
||||
if (index <= 10) {
|
||||
return `
|
||||
.palette-${color}-${index} {
|
||||
@ -33,7 +33,7 @@ ${makePalette(color, index + 1)}
|
||||
return '';
|
||||
};
|
||||
|
||||
const makeGrayPalette = (index: number = 1): string => {
|
||||
const makeGrayPalette = (index = 1): string => {
|
||||
if (index <= 13) {
|
||||
return `
|
||||
.palette-gray-${index} {
|
||||
@ -130,17 +130,17 @@ ${makeGrayPalette(index + 1)}
|
||||
.main-color {
|
||||
${makePalette('blue')}
|
||||
${makePalette('purple')}
|
||||
${makePalette('cyan')}
|
||||
${makePalette('green')}
|
||||
${makePalette('magenta')}
|
||||
${makePalette('red')}
|
||||
${makePalette('volcano')}
|
||||
${makePalette('orange')}
|
||||
${makePalette('gold')}
|
||||
${makePalette('yellow')}
|
||||
${makePalette('lime')}
|
||||
${makePalette('geekblue')}
|
||||
${makeGrayPalette()}
|
||||
${makePalette('cyan')}
|
||||
${makePalette('green')}
|
||||
${makePalette('magenta')}
|
||||
${makePalette('red')}
|
||||
${makePalette('volcano')}
|
||||
${makePalette('orange')}
|
||||
${makePalette('gold')}
|
||||
${makePalette('yellow')}
|
||||
${makePalette('lime')}
|
||||
${makePalette('geekblue')}
|
||||
${makeGrayPalette()}
|
||||
|
||||
text-align: left;
|
||||
|
||||
@ -176,7 +176,7 @@ ${makeGrayPalette(index + 1)}
|
||||
|
||||
&-item &-value {
|
||||
position: relative;
|
||||
left: 3px;
|
||||
inset-inline-start: ${token.marginXXS}px;
|
||||
float: right;
|
||||
transform: scale(0.85);
|
||||
transform-origin: 100% 50%;
|
||||
@ -203,7 +203,7 @@ ${makeGrayPalette(index + 1)}
|
||||
|
||||
.main-color:hover {
|
||||
.main-color-value {
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
@ -264,7 +264,7 @@ ${makeGrayPalette(index + 1)}
|
||||
&-value {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
transform-origin: unset;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { presetDarkPalettes } from '@ant-design/colors';
|
||||
import { message } from 'antd';
|
||||
import { App } from 'antd';
|
||||
import CopyToClipboard from 'react-copy-to-clipboard';
|
||||
|
||||
const rgbToHex = (rgbString: string): string => {
|
||||
@ -36,9 +36,10 @@ const Palette: React.FC<PaletteProps> = (props) => {
|
||||
} = props;
|
||||
const [hexColors, setHexColors] = React.useState<Record<PropertyKey, string>>({});
|
||||
const colorNodesRef = React.useRef<Record<PropertyKey, HTMLDivElement>>({});
|
||||
const { message } = App.useApp();
|
||||
|
||||
useEffect(() => {
|
||||
const colors = {};
|
||||
const colors: Record<string, string> = {};
|
||||
Object.keys(colorNodesRef.current || {}).forEach((key) => {
|
||||
const computedColor = getComputedStyle(colorNodesRef.current[key])['background-color'];
|
||||
if (computedColor.includes('rgba')) {
|
||||
@ -70,7 +71,9 @@ const Palette: React.FC<PaletteProps> = (props) => {
|
||||
<div
|
||||
key={i}
|
||||
ref={(node) => {
|
||||
colorNodesRef.current[`${name}-${i}`] = node;
|
||||
if (node) {
|
||||
colorNodesRef.current[`${name}-${i}`] = node;
|
||||
}
|
||||
}}
|
||||
className={`main-color-item palette-${name}-${i}`}
|
||||
style={{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* eslint-disable global-require */
|
||||
/* eslint-disable global-require, import/no-unresolved */
|
||||
import React from 'react';
|
||||
import { BugOutlined, HistoryOutlined } from '@ant-design/icons';
|
||||
import { Button, Drawer, Grid, Popover, Timeline, Typography } from 'antd';
|
||||
@ -28,17 +28,7 @@ function matchDeprecated(v: string): MatchDeprecatedResult {
|
||||
}
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => ({
|
||||
history: css`
|
||||
position: absolute;
|
||||
top: 0;
|
||||
inset-inline-end: 0;
|
||||
`,
|
||||
|
||||
li: css`
|
||||
// white-space: pre;
|
||||
`,
|
||||
|
||||
ref: css`
|
||||
linkRef: css`
|
||||
margin-inline-start: ${token.marginXS}px;
|
||||
`,
|
||||
bug: css`
|
||||
@ -67,6 +57,16 @@ const useStyle = createStyles(({ token, css }) => ({
|
||||
}
|
||||
}
|
||||
`,
|
||||
extraLink: css`
|
||||
font-size: ${token.fontSize}px;
|
||||
`,
|
||||
drawerContent: {
|
||||
position: 'relative',
|
||||
[`> ${token.antCls}-drawer-body`]: {
|
||||
scrollbarWidth: 'thin',
|
||||
scrollbarColor: 'unset',
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
export interface ComponentChangelogProps {
|
||||
@ -75,7 +75,7 @@ export interface ComponentChangelogProps {
|
||||
|
||||
const locales = {
|
||||
cn: {
|
||||
full: '完整更新日志',
|
||||
full: '查看完整日志',
|
||||
changelog: '更新日志',
|
||||
loading: '加载中...',
|
||||
empty: '暂无更新',
|
||||
@ -127,7 +127,7 @@ const ParseChangelog: React.FC<{ changelog: string; refs: string[]; styles: any
|
||||
<span>{parsedChangelog}</span>
|
||||
{/* Refs */}
|
||||
{refs?.map((ref) => (
|
||||
<a className={styles.ref} key={ref} href={ref} target="_blank" rel="noreferrer">
|
||||
<a className={styles.linkRef} key={ref} href={ref} target="_blank" rel="noreferrer">
|
||||
#{ref.match(/^.*\/(\d+)$/)?.[1]}
|
||||
</a>
|
||||
))}
|
||||
@ -142,9 +142,11 @@ interface ChangelogInfo {
|
||||
}
|
||||
|
||||
const useChangelog = (componentPath: string, lang: 'cn' | 'en'): ChangelogInfo[] => {
|
||||
const logFileName = `components-changelog-${lang}.json`;
|
||||
|
||||
const data = useFetch({
|
||||
key: `component-changelog-${lang}`,
|
||||
request: () => import(`../../../preset/components-changelog-${lang}.json`),
|
||||
request: () => import(`../../../preset/${logFileName}`),
|
||||
});
|
||||
return React.useMemo(() => {
|
||||
const component = componentPath.replace(/-/g, '');
|
||||
@ -211,7 +213,7 @@ const ComponentChangelog: React.FC<ComponentChangelogProps> = (props) => {
|
||||
</Typography.Title>
|
||||
<ul>
|
||||
{changelogList.map<React.ReactNode>((info, index) => (
|
||||
<li key={index} className={styles.li}>
|
||||
<li key={index}>
|
||||
<ParseChangelog {...info} styles={styles} />
|
||||
</li>
|
||||
))}
|
||||
@ -231,28 +233,21 @@ const ComponentChangelog: React.FC<ComponentChangelogProps> = (props) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
className={styles.history}
|
||||
icon={<HistoryOutlined />}
|
||||
onClick={() => {
|
||||
setShow(true);
|
||||
}}
|
||||
>
|
||||
<Button icon={<HistoryOutlined />} onClick={() => setShow(true)}>
|
||||
{locale.changelog}
|
||||
</Button>
|
||||
<Drawer
|
||||
destroyOnClose
|
||||
className={styles.drawerContent}
|
||||
title={locale.changelog}
|
||||
extra={
|
||||
<Link style={{ fontSize: 14 }} to={`/changelog${lang === 'cn' ? '-cn' : ''}`}>
|
||||
<Link className={styles.extraLink} to={`/changelog${lang === 'cn' ? '-cn' : ''}`}>
|
||||
{locale.full}
|
||||
</Link>
|
||||
}
|
||||
open={show}
|
||||
width={width}
|
||||
onClose={() => {
|
||||
setShow(false);
|
||||
}}
|
||||
destroyOnClose
|
||||
onClose={() => setShow(false)}
|
||||
>
|
||||
<Timeline items={timelineItems} />
|
||||
</Drawer>
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
|
||||
import type { ComponentChangelogProps } from './ComponentChangelog';
|
||||
import ComponentChangelog from './ComponentChangelog';
|
||||
|
||||
|
@ -2,13 +2,10 @@ import React from 'react';
|
||||
|
||||
import ColorStyle from './Color/ColorStyle';
|
||||
import {
|
||||
BrowserMockup,
|
||||
Common,
|
||||
Demo,
|
||||
HeadingAnchor,
|
||||
Highlight,
|
||||
Icon,
|
||||
IconPickSearcher,
|
||||
Markdown,
|
||||
NProgress,
|
||||
PreviewImage,
|
||||
@ -25,9 +22,6 @@ const GlobalStyles: React.FC = () => (
|
||||
<Markdown />
|
||||
<Highlight />
|
||||
<Demo />
|
||||
<Icon />
|
||||
<IconPickSearcher />
|
||||
<BrowserMockup />
|
||||
<Responsive />
|
||||
<NProgress />
|
||||
<PreviewImage />
|
||||
|
@ -1,6 +1,6 @@
|
||||
import type { MouseEvent, MouseEventHandler } from 'react';
|
||||
import React, { forwardRef, useLayoutEffect, useTransition } from 'react';
|
||||
import { useLocation, useNavigate } from 'dumi';
|
||||
import { Link as DumiLink, useLocation, useNavigate } from 'dumi';
|
||||
import nprogress from 'nprogress';
|
||||
|
||||
export interface LinkProps {
|
||||
@ -8,10 +8,13 @@ export interface LinkProps {
|
||||
style?: React.CSSProperties;
|
||||
className?: string;
|
||||
onClick?: MouseEventHandler;
|
||||
component?: React.ComponentType<any>;
|
||||
}
|
||||
|
||||
nprogress.configure({ showSpinner: false });
|
||||
|
||||
const Link = forwardRef<HTMLAnchorElement, React.PropsWithChildren<LinkProps>>((props, ref) => {
|
||||
const { to, children, ...rest } = props;
|
||||
const { to, children, component, ...rest } = props;
|
||||
const [isPending, startTransition] = useTransition();
|
||||
const navigate = useNavigate();
|
||||
const { pathname } = useLocation();
|
||||
@ -46,10 +49,23 @@ const Link = forwardRef<HTMLAnchorElement, React.PropsWithChildren<LinkProps>>((
|
||||
}
|
||||
}, [isPending]);
|
||||
|
||||
if (component) {
|
||||
return React.createElement(
|
||||
component,
|
||||
{
|
||||
...rest,
|
||||
ref,
|
||||
onClick: handleClick,
|
||||
href,
|
||||
},
|
||||
children,
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<a ref={ref} onClick={handleClick} {...rest} href={href}>
|
||||
<DumiLink ref={ref} onClick={handleClick} {...rest} to={href} prefetch>
|
||||
{children}
|
||||
</a>
|
||||
</DumiLink>
|
||||
);
|
||||
});
|
||||
|
||||
|
12
.dumi/theme/common/LinkButton.tsx
Normal file
12
.dumi/theme/common/LinkButton.tsx
Normal file
@ -0,0 +1,12 @@
|
||||
import React from 'react';
|
||||
import { Button } from 'antd';
|
||||
import type { ButtonProps } from 'antd';
|
||||
import Link from './Link';
|
||||
import type { LinkProps } from './Link';
|
||||
|
||||
type LinkButtonProps = LinkProps &
|
||||
Readonly<React.PropsWithChildren<Pick<ButtonProps, 'type' | 'size'>>>;
|
||||
|
||||
const LinkButton: React.FC<LinkButtonProps> = (props) => <Link component={Button} {...props} />;
|
||||
|
||||
export default LinkButton;
|
@ -1,24 +1,23 @@
|
||||
import type { ComponentProps, FC } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { EditFilled } from '@ant-design/icons';
|
||||
import { Tooltip } from 'antd';
|
||||
import React from 'react';
|
||||
import { createStyles } from 'antd-style';
|
||||
import SourceCodeEditor from 'dumi/theme-default/slots/SourceCodeEditor';
|
||||
|
||||
import useLocale from '../../hooks/useLocale';
|
||||
import LiveError from '../slots/LiveError';
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => {
|
||||
const { colorBgContainer, colorIcon } = token;
|
||||
|
||||
const { colorBgContainer } = token;
|
||||
return {
|
||||
editor: css`
|
||||
// override dumi editor styles
|
||||
.dumi-default-source-code-editor {
|
||||
.dumi-default-source-code {
|
||||
background: ${colorBgContainer};
|
||||
&-scroll-container {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: unset;
|
||||
}
|
||||
}
|
||||
|
||||
.dumi-default-source-code > pre,
|
||||
.dumi-default-source-code-scroll-content > pre,
|
||||
.dumi-default-source-code-editor-textarea {
|
||||
@ -48,70 +47,24 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
}
|
||||
}
|
||||
`,
|
||||
|
||||
editableIcon: css`
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
top: 16px;
|
||||
inset-inline-end: 56px;
|
||||
color: ${colorIcon};
|
||||
`,
|
||||
};
|
||||
});
|
||||
|
||||
const locales = {
|
||||
cn: {
|
||||
demoEditable: '编辑 Demo 可实时预览',
|
||||
},
|
||||
en: {
|
||||
demoEditable: 'Edit demo with real-time preview',
|
||||
},
|
||||
};
|
||||
|
||||
const HIDE_LIVE_DEMO_TIP = 'hide-live-demo-tip';
|
||||
|
||||
const LiveCode: FC<
|
||||
{
|
||||
error: Error | null;
|
||||
} & Pick<ComponentProps<typeof SourceCodeEditor>, 'lang' | 'initialValue' | 'onChange'>
|
||||
> = (props) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const { styles } = useStyle();
|
||||
const [locale] = useLocale(locales);
|
||||
|
||||
useEffect(() => {
|
||||
const shouldOpen = !localStorage.getItem(HIDE_LIVE_DEMO_TIP);
|
||||
if (shouldOpen) {
|
||||
setOpen(true);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleOpenChange = (newOpen: boolean) => {
|
||||
setOpen(newOpen);
|
||||
if (!newOpen) {
|
||||
localStorage.setItem(HIDE_LIVE_DEMO_TIP, 'true');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.editor}>
|
||||
<SourceCodeEditor
|
||||
lang={props.lang}
|
||||
initialValue={props.initialValue}
|
||||
onChange={props.onChange}
|
||||
/>
|
||||
<LiveError error={props.error} />
|
||||
</div>
|
||||
<Tooltip title={locale.demoEditable} open={open} onOpenChange={handleOpenChange}>
|
||||
<EditFilled className={styles.editableIcon} />
|
||||
</Tooltip>
|
||||
</>
|
||||
<div className={styles.editor}>
|
||||
<SourceCodeEditor
|
||||
lang={props.lang}
|
||||
initialValue={props.initialValue}
|
||||
onChange={props.onChange}
|
||||
/>
|
||||
<LiveError error={props.error} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,15 +1,16 @@
|
||||
import type { ReactElement } from 'react';
|
||||
import React, { useContext, useMemo } from 'react';
|
||||
import { LeftOutlined, RightOutlined } from '@ant-design/icons';
|
||||
import type { MenuProps } from 'antd';
|
||||
import type { GetProp, 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 SiteContext from '../slots/SiteContext';
|
||||
import type { SiteContextProps } from '../slots/SiteContext';
|
||||
|
||||
type MenuItemType = Extract<GetProp<MenuProps, 'items'>[number], { type?: 'item' }>;
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => {
|
||||
const { colorSplit, iconCls, fontSizeIcon } = token;
|
||||
|
||||
|
@ -5,6 +5,7 @@ const ThemeIcon: React.FC<{ className?: string }> = (props) => {
|
||||
const SVGIcon = React.useCallback(
|
||||
() => (
|
||||
<svg width={20} height={20} viewBox="0 0 24 24" fill="currentColor" {...props}>
|
||||
<title>Theme icon</title>
|
||||
<g fillRule="evenodd">
|
||||
<g fillRule="nonzero">
|
||||
<path d="M7.02 3.635l12.518 12.518a1.863 1.863 0 010 2.635l-1.317 1.318a1.863 1.863 0 01-2.635 0L3.068 7.588A2.795 2.795 0 117.02 3.635zm2.09 14.428a.932.932 0 110 1.864.932.932 0 010-1.864zm-.043-9.747L7.75 9.635l9.154 9.153 1.318-1.317-9.154-9.155zM3.52 12.473c.514 0 .931.417.931.931v.932h.932a.932.932 0 110 1.864h-.932v.931a.932.932 0 01-1.863 0l-.001-.931h-.93a.932.932 0 010-1.864h.93v-.932c0-.514.418-.931.933-.931zm15.374-3.727a1.398 1.398 0 110 2.795 1.398 1.398 0 010-2.795zM4.385 4.953a.932.932 0 000 1.317l2.046 2.047L7.75 7 5.703 4.953a.932.932 0 00-1.318 0zM14.701.36a.932.932 0 01.931.932v.931h.932a.932.932 0 010 1.864h-.933l.001.932a.932.932 0 11-1.863 0l-.001-.932h-.93a.932.932 0 110-1.864h.93v-.931a.932.932 0 01.933-.932z" />
|
||||
|
@ -4,10 +4,11 @@ import { FloatButton } from 'antd';
|
||||
import { useTheme } from 'antd-style';
|
||||
import { CompactTheme, DarkTheme } from 'antd-token-previewer/es/icons';
|
||||
// import { Motion } from 'antd-token-previewer/es/icons';
|
||||
import { FormattedMessage, Link, useLocation } from 'dumi';
|
||||
import { FormattedMessage, useLocation } from 'dumi';
|
||||
|
||||
import useThemeAnimation from '../../../hooks/useThemeAnimation';
|
||||
import { getLocalizedPathname, isZhCN } from '../../utils';
|
||||
import Link from '../Link';
|
||||
import ThemeIcon from './ThemeIcon';
|
||||
|
||||
export type ThemeName = 'light' | 'dark' | 'compact' | 'motion-off' | 'happy-work';
|
||||
@ -34,7 +35,6 @@ const ThemeSwitch: React.FC<ThemeSwitchProps> = (props) => {
|
||||
icon={<ThemeIcon />}
|
||||
aria-label="Theme Switcher"
|
||||
badge={{ dot: true }}
|
||||
style={{ zIndex: 1010 }}
|
||||
>
|
||||
<Link
|
||||
to={getLocalizedPathname('/theme-editor', isZhCN(pathname), search)}
|
||||
|
@ -1,68 +0,0 @@
|
||||
import React from 'react';
|
||||
import { css, Global } from '@emotion/react';
|
||||
import { useTheme } from 'antd-style';
|
||||
|
||||
export default () => {
|
||||
const token = useTheme();
|
||||
return (
|
||||
<Global
|
||||
styles={css`
|
||||
/* Browser mockup code
|
||||
* Contribute: https://gist.github.com/jarthod/8719db9fef8deb937f4f
|
||||
* Live example: https://updown.io
|
||||
*/
|
||||
|
||||
.browser-mockup {
|
||||
position: relative;
|
||||
border-top: 2em solid rgba(230, 230, 230, 0.7);
|
||||
border-radius: ${token.borderRadiusSM}px ${token.borderRadiusSM}px 0 0;
|
||||
box-shadow: 0 0.1em 0.5em 0 rgba(0, 0, 0, 0.28);
|
||||
}
|
||||
|
||||
.browser-mockup::before {
|
||||
position: absolute;
|
||||
top: -1.25em;
|
||||
left: 1em;
|
||||
display: block;
|
||||
width: 0.5em;
|
||||
height: 0.5em;
|
||||
background-color: #f44;
|
||||
border-radius: 50%;
|
||||
box-shadow:
|
||||
0 0 0 2px #f44,
|
||||
1.5em 0 0 2px #9b3,
|
||||
3em 0 0 2px #fb5;
|
||||
content: '';
|
||||
}
|
||||
|
||||
.browser-mockup.with-tab::after {
|
||||
position: absolute;
|
||||
top: -2em;
|
||||
left: 5.5em;
|
||||
display: block;
|
||||
width: 20%;
|
||||
height: 0;
|
||||
border-right: 0.8em solid transparent;
|
||||
border-bottom: 2em solid white;
|
||||
border-left: 0.8em solid transparent;
|
||||
content: '';
|
||||
}
|
||||
|
||||
.browser-mockup.with-url::after {
|
||||
position: absolute;
|
||||
top: -1.6em;
|
||||
left: 5.5em;
|
||||
display: block;
|
||||
width: calc(100% - 6em);
|
||||
height: 1.2em;
|
||||
background-color: #fff;
|
||||
border-radius: ${token.borderRadiusXS}px;
|
||||
content: '';
|
||||
}
|
||||
.browser-mockup > * {
|
||||
display: block;
|
||||
}
|
||||
`}
|
||||
/>
|
||||
);
|
||||
};
|
@ -108,7 +108,7 @@ const GlobalDemoStyles: React.FC = () => {
|
||||
a.edit-button {
|
||||
position: absolute;
|
||||
top: 7px;
|
||||
right: -16px;
|
||||
inset-inline-end: -16px;
|
||||
font-size: ${token.fontSizeSM}px;
|
||||
text-decoration: none;
|
||||
background: inherit;
|
||||
@ -125,8 +125,8 @@ const GlobalDemoStyles: React.FC = () => {
|
||||
}
|
||||
|
||||
${antCls}-row${antCls}-row-rtl & {
|
||||
right: auto;
|
||||
left: -22px;
|
||||
inset-inline-end: auto;
|
||||
inset-inline-start: -22px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -184,7 +184,7 @@ const GlobalDemoStyles: React.FC = () => {
|
||||
.code-expand-icon-hide {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
margin: 0;
|
||||
@ -193,8 +193,8 @@ const GlobalDemoStyles: React.FC = () => {
|
||||
user-select: none;
|
||||
|
||||
${antCls}-row-rtl & {
|
||||
right: 0;
|
||||
left: auto;
|
||||
inset-inline-end: 0;
|
||||
inset-inline-start: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@ -357,9 +357,9 @@ const GlobalDemoStyles: React.FC = () => {
|
||||
}
|
||||
|
||||
${antCls}-row-rtl {
|
||||
#components-tooltip-demo-placement,
|
||||
#components-popover-demo-placement,
|
||||
#components-popconfirm-demo-placement {
|
||||
#tooltip-demo-placement,
|
||||
#popover-demo-placement,
|
||||
#popconfirm-demo-placement {
|
||||
.code-box-demo {
|
||||
direction: ltr;
|
||||
}
|
||||
|
@ -1,113 +0,0 @@
|
||||
import React from 'react';
|
||||
import { css, Global } from '@emotion/react';
|
||||
import { useTheme } from 'antd-style';
|
||||
|
||||
export default () => {
|
||||
const token = useTheme();
|
||||
|
||||
const { antCls, iconCls } = token;
|
||||
|
||||
return (
|
||||
<Global
|
||||
styles={css`
|
||||
ul.anticons-list {
|
||||
margin: 10px 0;
|
||||
overflow: hidden;
|
||||
direction: ltr;
|
||||
list-style: none;
|
||||
|
||||
li {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 16.66%;
|
||||
height: 100px;
|
||||
margin: 3px 0;
|
||||
padding: 10px 0 0;
|
||||
overflow: hidden;
|
||||
color: #555;
|
||||
text-align: center;
|
||||
list-style: none;
|
||||
background-color: inherit;
|
||||
border-radius: ${token.borderRadiusSM}px;
|
||||
cursor: pointer;
|
||||
transition:
|
||||
color ${token.motionDurationSlow} ease-in-out,
|
||||
background-color ${token.motionDurationSlow} ease-in-out;
|
||||
|
||||
.rtl & {
|
||||
margin: 3px 0;
|
||||
padding: 10px 0 0;
|
||||
}
|
||||
|
||||
${iconCls} {
|
||||
margin: ${token.marginSM}px 0 ${token.marginXS}px;
|
||||
font-size: 36px;
|
||||
transition: transform ${token.motionDurationSlow} ease-in-out;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.anticon-class {
|
||||
display: block;
|
||||
font-family: 'Lucida Console', Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono',
|
||||
monospace;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
transform: scale(0.83);
|
||||
|
||||
${antCls}-badge {
|
||||
transition: color ${token.motionDurationSlow} ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background-color: ${token.colorPrimary};
|
||||
|
||||
${iconCls} {
|
||||
transform: scale(1.4);
|
||||
}
|
||||
|
||||
${antCls}-badge {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&.TwoTone:hover {
|
||||
background-color: #8ecafe;
|
||||
}
|
||||
|
||||
&.copied:hover {
|
||||
color: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: #fff;
|
||||
line-height: 110px;
|
||||
text-align: center;
|
||||
background: #1677ff;
|
||||
opacity: 0;
|
||||
transition: all ${token.motionDurationSlow} cubic-bezier(0.18, 0.89, 0.32, 1.28);
|
||||
content: 'Copied!';
|
||||
}
|
||||
|
||||
&.copied::after {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.copied-code {
|
||||
padding: 2px 4px;
|
||||
font-size: ${token.fontSizeSM}px;
|
||||
background: ${token.colorBgLayout};
|
||||
border-radius: ${token.borderRadiusXS}px;
|
||||
}
|
||||
`}
|
||||
/>
|
||||
);
|
||||
};
|
@ -1,71 +0,0 @@
|
||||
import React from 'react';
|
||||
import { css, Global } from '@emotion/react';
|
||||
import { useTheme } from 'antd-style';
|
||||
|
||||
export default () => {
|
||||
const token = useTheme();
|
||||
|
||||
const { iconCls } = token;
|
||||
|
||||
return (
|
||||
<Global
|
||||
styles={css`
|
||||
.icon-pic-searcher {
|
||||
display: inline-block;
|
||||
margin: 0 ${token.marginXS}px;
|
||||
|
||||
.icon-pic-btn {
|
||||
color: ${token.colorIcon};
|
||||
cursor: pointer;
|
||||
transition: all ${token.motionDurationSlow};
|
||||
|
||||
&:hover {
|
||||
color: ${token.colorIconHover};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icon-pic-preview {
|
||||
width: 66px;
|
||||
height: 66px;
|
||||
margin-top: 10px;
|
||||
padding: ${token.paddingXS}px;
|
||||
text-align: center;
|
||||
border: 1px solid ${token.colorBorder};
|
||||
border-radius: ${token.borderRadiusSM}px;
|
||||
|
||||
> img {
|
||||
max-width: 50px;
|
||||
max-height: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-pic-search-result {
|
||||
min-height: 50px;
|
||||
padding: 0 10px;
|
||||
|
||||
> .result-tip {
|
||||
padding: 10px 0;
|
||||
color: ${token.colorTextSecondary};
|
||||
}
|
||||
|
||||
> table {
|
||||
width: 100%;
|
||||
|
||||
.col-icon {
|
||||
width: 80px;
|
||||
padding: 10px 0;
|
||||
|
||||
> ${iconCls} {
|
||||
font-size: ${token.fontSizeHeading2}px;
|
||||
:hover {
|
||||
color: ${token.colorLinkHover};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`}
|
||||
/>
|
||||
);
|
||||
};
|
@ -37,7 +37,6 @@ const GlobalStyle: React.FC = () => {
|
||||
.markdown p > img {
|
||||
margin: 34px auto;
|
||||
box-shadow: 0 8px 20px rgba(143, 168, 191, 0.35);
|
||||
max-width: 1024px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
@ -111,39 +110,24 @@ const GlobalStyle: React.FC = () => {
|
||||
}
|
||||
}
|
||||
|
||||
.markdown ul > li {
|
||||
margin-inline-start: ${token.marginMD}px;
|
||||
.markdown ul > li,
|
||||
.markdown ol > li {
|
||||
padding-inline-start: ${token.paddingXXS}px;
|
||||
list-style-type: circle;
|
||||
|
||||
.rtl & {
|
||||
margin-inline-end: ${token.marginMD}px;
|
||||
margin-inline-start: 0;
|
||||
padding-inline-end: ${token.paddingXXS}px;
|
||||
padding-inline-start: 0;
|
||||
margin-inline-start: ${token.marginMD}px;
|
||||
> p {
|
||||
margin: 0.2em 0;
|
||||
}
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.markdown ol > li {
|
||||
margin-inline-start: ${token.marginMD}px;
|
||||
padding-inline-start: ${token.paddingXXS}px;
|
||||
list-style-type: decimal;
|
||||
|
||||
${antCls}-row-rtl & {
|
||||
margin-inline-end: ${token.marginMD}px;
|
||||
margin-inline-start: 0;
|
||||
padding-inline-end: ${token.paddingXXS}px;
|
||||
padding-inline-start: 0;
|
||||
}
|
||||
.markdown ul > li {
|
||||
list-style-type: circle;
|
||||
}
|
||||
|
||||
.markdown ul > li > p,
|
||||
.markdown ol > li > p {
|
||||
margin: 0.2em 0;
|
||||
.markdown ol > li {
|
||||
list-style-type: decimal;
|
||||
}
|
||||
|
||||
.markdown code {
|
||||
@ -183,6 +167,8 @@ const GlobalStyle: React.FC = () => {
|
||||
background-color: ${token.siteMarkdownCodeBg};
|
||||
border-radius: ${token.borderRadius}px;
|
||||
> pre.prism-code {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: unset;
|
||||
padding: ${token.paddingSM}px ${token.paddingMD}px;
|
||||
font-size: ${token.fontSize}px;
|
||||
line-height: 2;
|
||||
@ -197,6 +183,7 @@ const GlobalStyle: React.FC = () => {
|
||||
margin: 0 ${token.marginMD}px;
|
||||
color: #aaa;
|
||||
font-size: 30px;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
|
||||
@ -282,6 +269,10 @@ const GlobalStyle: React.FC = () => {
|
||||
}
|
||||
|
||||
.markdown .dumi-default-table {
|
||||
&-content {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: unset;
|
||||
}
|
||||
table {
|
||||
margin: 0;
|
||||
overflow-x: auto;
|
||||
@ -384,7 +375,7 @@ const GlobalStyle: React.FC = () => {
|
||||
}
|
||||
|
||||
.grid-demo,
|
||||
[id^='components-grid-demo-'] {
|
||||
[id^='grid-demo-'] {
|
||||
${antCls}-row > div,
|
||||
.code-box-demo ${antCls}-row > div {
|
||||
min-height: 30px;
|
||||
@ -462,8 +453,8 @@ const GlobalStyle: React.FC = () => {
|
||||
}
|
||||
}
|
||||
|
||||
[id='components-grid-demo-playground'],
|
||||
[id='components-grid-demo-gutter'] {
|
||||
[id='grid-demo-playground'],
|
||||
[id='grid-demo-gutter'] {
|
||||
> .code-box-demo ${antCls}-row > div {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { css, Global } from '@emotion/react';
|
||||
import React from 'react';
|
||||
import { css, Global } from '@emotion/react';
|
||||
import { useTheme } from 'antd-style';
|
||||
|
||||
export default () => {
|
||||
@ -13,7 +13,9 @@ export default () => {
|
||||
}
|
||||
|
||||
.peg {
|
||||
box-shadow: 0 0 10px ${token.colorPrimary}, 0 0 5px ${token.colorPrimary};
|
||||
box-shadow:
|
||||
0 0 10px ${token.colorPrimary},
|
||||
0 0 5px ${token.colorPrimary};
|
||||
}
|
||||
|
||||
.spinner-icon {
|
||||
|
@ -70,14 +70,14 @@ export default () => {
|
||||
+ svg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.preview-image-wrapper.good::after {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 3px;
|
||||
@ -88,7 +88,7 @@ export default () => {
|
||||
.preview-image-wrapper.bad::after {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 3px;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { css, Global } from '@emotion/react';
|
||||
import React from 'react';
|
||||
import { css, Global } from '@emotion/react';
|
||||
import { useTheme } from 'antd-style';
|
||||
|
||||
export default () => {
|
||||
@ -11,7 +11,8 @@ export default () => {
|
||||
@font-face {
|
||||
font-weight: normal;
|
||||
font-family: AlibabaPuHuiTi;
|
||||
src: url('//at.alicdn.com/t/webfont_6e11e43nfj.woff2') format('woff2'),
|
||||
src:
|
||||
url('//at.alicdn.com/t/webfont_6e11e43nfj.woff2') format('woff2'),
|
||||
url('//at.alicdn.com/t/webfont_6e11e43nfj.woff') format('woff'),
|
||||
/* chrome、firefox */ url('//at.alicdn.com/t/webfont_6e11e43nfj.ttf') format('truetype'); /* chrome、firefox、opera、Safari, Android, iOS 4.2+ */
|
||||
font-display: swap;
|
||||
@ -20,7 +21,8 @@ export default () => {
|
||||
@font-face {
|
||||
font-weight: bold;
|
||||
font-family: AlibabaPuHuiTi;
|
||||
src: url('//at.alicdn.com/t/webfont_exesdog9toj.woff2') format('woff2'),
|
||||
src:
|
||||
url('//at.alicdn.com/t/webfont_exesdog9toj.woff2') format('woff2'),
|
||||
url('//at.alicdn.com/t/webfont_exesdog9toj.woff') format('woff'),
|
||||
/* chrome、firefox */ url('//at.alicdn.com/t/webfont_exesdog9toj.ttf')
|
||||
format('truetype'); /* chrome、firefox、opera、Safari, Android, iOS 4.2+ */
|
||||
@ -32,7 +34,8 @@ export default () => {
|
||||
@font-face {
|
||||
font-weight: 900;
|
||||
font-family: 'AliPuHui';
|
||||
src: url('//at.alicdn.com/wf/webfont/exMpJIukiCms/Gsw2PSKrftc1yNWMNlXgw.woff2')
|
||||
src:
|
||||
url('//at.alicdn.com/wf/webfont/exMpJIukiCms/Gsw2PSKrftc1yNWMNlXgw.woff2')
|
||||
format('woff2'),
|
||||
url('//at.alicdn.com/wf/webfont/exMpJIukiCms/vtu73by4O2gEBcvBuLgeu.woff') format('woff');
|
||||
font-display: swap;
|
||||
|
@ -11,7 +11,7 @@ export default () => {
|
||||
.nav-phone-icon {
|
||||
position: absolute;
|
||||
bottom: 17px;
|
||||
right: 30px;
|
||||
inset-inline-end: 30px;
|
||||
z-index: 1;
|
||||
display: none;
|
||||
width: 16px;
|
||||
@ -98,8 +98,8 @@ export default () => {
|
||||
.drawer {
|
||||
.ant-menu-inline .ant-menu-item::after,
|
||||
.ant-menu-vertical .ant-menu-item::after {
|
||||
right: auto;
|
||||
left: 0;
|
||||
inset-inline-end: auto;
|
||||
inset-inline-start: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,9 +4,6 @@ export { default as Common } from './Common';
|
||||
export { default as Markdown } from './Markdown';
|
||||
export { default as Highlight } from './Highlight';
|
||||
export { default as Demo } from './Demo';
|
||||
export { default as Icon } from './Icon';
|
||||
export { default as IconPickSearcher } from './IconPickSearcher';
|
||||
export { default as BrowserMockup } from './BrowserMockup';
|
||||
export { default as Responsive } from './Responsive';
|
||||
export { default as NProgress } from './NProgress';
|
||||
export { default as PreviewImage } from './PreviewImage';
|
||||
|
@ -3,12 +3,13 @@ import Icon from '@ant-design/icons';
|
||||
|
||||
const SVGIcon: React.FC = () => (
|
||||
<svg viewBox="0 0 15 15" fill="currentColor">
|
||||
<title>codepen icon</title>
|
||||
<path d="M14.777304,4.75062256 L7.77734505,0.0839936563 C7.60939924,-0.0279665065 7.39060662,-0.0279665065 7.22266081,0.0839936563 L0.222701813,4.75062256 C0.0836082937,4.84334851 5.66973453e-05,4.99945222 4.6875e-05,5.16662013 L4.6875e-05,9.83324903 C4.6875e-05,10.0004355 0.0836088906,10.1565596 0.222701812,10.2492466 L7.22266081,14.9158755 C7.30662908,14.9718752 7.403316,14.999875 7.50000292,14.999875 C7.59668984,14.999875 7.69337678,14.9718752 7.77734505,14.9158755 L14.777304,10.2492466 C14.9163976,10.1565206 14.9999492,10.0004169 14.999959,9.83324903 L14.999959,5.16662013 C14.9999492,4.99945222 14.9163976,4.84334851 14.777304,4.75062256 Z M7.50000292,9.23237755 L4.90139316,7.4999502 L7.50000292,5.76755409 L10.0986127,7.4999502 L7.50000292,9.23237755 Z M8,4.89905919 L8,1.43423573 L13.598561,5.16665138 L10.9999824,6.89904747 L8,4.89905919 Z M7.00000586,4.89905919 L4.00002344,6.89904747 L1.40141366,5.16665138 L7.00000586,1.43423573 L7.00000586,4.89905919 Z M3.09865372,7.4999502 L1.00004102,8.89903575 L1.00004102,6.10089589 L3.09865372,7.4999502 Z M4.00002344,8.10085292 L7.00000586,10.1008412 L7.00000586,13.5656334 L1.40141366,9.83328028 L4.00002344,8.10085292 Z M8,10.1008412 L10.9999824,8.10085292 L13.5985922,9.83328028 L8,13.5656647 L8,10.1008412 L8,10.1008412 Z M11.9013521,7.4999502 L13.9999648,6.10089589 L13.9999648,8.899067 L11.9013521,7.4999502 Z" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
const CodePenIcon: React.FC<{ className?: string }> = (props) => (
|
||||
<Icon component={SVGIcon} {...props} />
|
||||
);
|
||||
const CodePenIcon = React.forwardRef<HTMLSpanElement, { className?: string }>((props, ref) => (
|
||||
<Icon component={SVGIcon} ref={ref} {...props} />
|
||||
));
|
||||
|
||||
export default CodePenIcon;
|
@ -3,12 +3,13 @@ import Icon from '@ant-design/icons';
|
||||
|
||||
const SVGIcon: React.FC = () => (
|
||||
<svg viewBox="0 0 1024 1024" fill="currentColor">
|
||||
<title>CodeSandbox Icon</title>
|
||||
<path d="M755 140.3l0.5-0.3h0.3L512 0 268.3 140h-0.3l0.8 0.4L68.6 256v512L512 1024l443.4-256V256L755 140.3z m-30 506.4v171.2L548 920.1V534.7L883.4 341v215.7l-158.4 90z m-584.4-90.6V340.8L476 534.4v385.7L300 818.5V646.7l-159.4-90.6zM511.7 280l171.1-98.3 166.3 96-336.9 194.5-337-194.6 165.7-95.7L511.7 280z" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
const CodeSandboxIcon: React.FC<{ className?: string }> = (props) => (
|
||||
<Icon component={SVGIcon} {...props} />
|
||||
);
|
||||
const CodeSandboxIcon = React.forwardRef<HTMLSpanElement, { className?: string }>((props, ref) => (
|
||||
<Icon component={SVGIcon} ref={ref} {...props} />
|
||||
));
|
||||
|
||||
export default CodeSandboxIcon;
|
@ -15,12 +15,13 @@ const DirectionSvg: React.FC<DirectionIconProps> = ({ direction }) => (
|
||||
fill="currentColor"
|
||||
style={{ transform: `scaleX(${direction === 'ltr' ? '1' : '-1'})` }}
|
||||
>
|
||||
<title>Direction Icon</title>
|
||||
<path d="m14.6961816 11.6470802.0841184.0726198 2 2c.2662727.2662727.2904793.682876.0726198.9764816l-.0726198.0841184-2 2c-.2929.2929-.7677.2929-1.0606 0-.2662727-.2662727-.2904793-.682876-.0726198-.9764816l.0726198-.0841184.7196-.7197h-10.6893c-.41421 0-.75-.3358-.75-.75 0-.3796833.28215688-.6934889.64823019-.7431531l.10176981-.0068469h10.6893l-.7196-.7197c-.2929-.2929-.2929-.7677 0-1.0606.2662727-.2662727.682876-.2904793.9764816-.0726198zm-8.1961616-8.6470802c.30667 0 .58246.18671.69635.47146l3.00003 7.50004c.1538.3845-.0333.821-.41784.9749-.38459.1538-.82107-.0333-.9749-.4179l-.81142-2.0285h-2.98445l-.81142 2.0285c-.15383.3846-.59031.5717-.9749.4179-.38458-.1539-.57165-.5904-.41781-.9749l3-7.50004c.1139-.28475.38968-.47146.69636-.47146zm8.1961616 1.14705264.0841184.07261736 2 2c.2662727.26626364.2904793.68293223.0726198.97654222l-.0726198.08411778-2 2c-.2929.29289-.7677.29289-1.0606 0-.2662727-.26626364-.2904793-.68293223-.0726198-.97654222l.0726198-.08411778.7196-.7196675h-3.6893c-.4142 0-.75-.3357925-.75-.7500025 0-.3796925.2821653-.69348832.6482323-.74315087l.1017677-.00684663h3.6893l-.7196-.7196725c-.2929-.29289-.2929-.76777 0-1.06066.2662727-.26626364.682876-.29046942.9764816-.07261736zm-8.1961616 1.62238736-.89223 2.23056h1.78445z" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
const DirectionIcon: React.FC<DirectionIconProps> = (props) => (
|
||||
<Icon {...props} component={() => <DirectionSvg direction={props.direction} />} />
|
||||
);
|
||||
const DirectionIcon = React.forwardRef<HTMLSpanElement, DirectionIconProps>((props, ref) => (
|
||||
<Icon ref={ref} component={() => <DirectionSvg direction={props.direction} />} {...props} />
|
||||
));
|
||||
|
||||
export default DirectionIcon;
|
@ -1,15 +1,21 @@
|
||||
import React from 'react';
|
||||
import Icon from '@ant-design/icons';
|
||||
|
||||
interface ExternalIconProps {
|
||||
className?: string;
|
||||
color?: string;
|
||||
}
|
||||
|
||||
const SVGIcon: React.FC<{ color?: string }> = ({ color = 'currentColor' }) => (
|
||||
<svg viewBox="0 0 1024 1024" width="1em" height="1em" fill={color}>
|
||||
<title>External Link Icon</title>
|
||||
<path d="M853.333 469.333A42.667 42.667 0 0 0 810.667 512v256A42.667 42.667 0 0 1 768 810.667H256A42.667 42.667 0 0 1 213.333 768V256A42.667 42.667 0 0 1 256 213.333h256A42.667 42.667 0 0 0 512 128H256a128 128 0 0 0-128 128v512a128 128 0 0 0 128 128h512a128 128 0 0 0 128-128V512a42.667 42.667 0 0 0-42.667-42.667z" />
|
||||
<path d="M682.667 213.333h67.413L481.707 481.28a42.667 42.667 0 0 0 0 60.587 42.667 42.667 0 0 0 60.586 0L810.667 273.92v67.413A42.667 42.667 0 0 0 853.333 384 42.667 42.667 0 0 0 896 341.333V170.667A42.667 42.667 0 0 0 853.333 128H682.667a42.667 42.667 0 0 0 0 85.333z" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
const ExternalLinkIcon: React.FC<{ className?: string }> = (props) => (
|
||||
<Icon component={SVGIcon} {...props} />
|
||||
);
|
||||
const ExternalLinkIcon = React.forwardRef<HTMLSpanElement, ExternalIconProps>((props, ref) => (
|
||||
<Icon component={() => <SVGIcon color={props.color} />} ref={ref} {...props} />
|
||||
));
|
||||
|
||||
export default ExternalLinkIcon;
|
@ -3,12 +3,13 @@ import Icon from '@ant-design/icons';
|
||||
|
||||
const SVGIcon: React.FC = () => (
|
||||
<svg viewBox="0 0 14 14" fill="currentColor">
|
||||
<title>Riddle logo</title>
|
||||
<path d="M13.8875145,13.1234844 C13.8687399,13.0691875 13.8499977,13.0329687 13.8312555,12.9786562 L11.3687445,8.83296875 C12.9187468,8.05754687 13.9640694,6.49009375 13.9640694,4.68728125 C13.9624994,2.09095312 11.7968694,0 9.10938728,0 L3.86404855,0 C3.04217572,0 2.37028902,0.648703125 2.37028902,1.44223437 L2.37028902,1.82090625 L0.746871676,1.82090625 C0.33593526,1.82090625 0,2.14526562 0,2.54203125 L0,13.4478437 C0,13.7540937 0.242191908,13.9879375 0.559368786,13.9879375 C0.615627746,13.9879375 0.67187052,13.9698281 0.72812948,13.9517187 L13.440615,13.9517187 C13.7578081,13.9517187 14,13.7178906 14,13.4116406 C14,13.321125 13.9624994,13.2125 13.8875145,13.1234844 Z M3.49061272,8.0394375 L3.49061272,2.9206875 L8.71719306,2.9206875 C9.74375723,2.9206875 10.5843723,3.73232812 10.5843723,4.7235 C10.5843723,5.71465625 9.76249942,6.5081875 8.71719306,6.5081875 L6.53280462,6.5081875 L6.53280462,6.52629688 C6.45781965,6.52629688 6.3828185,6.5625 6.3093711,6.59870313 C6.04843699,6.74354688 5.95469364,7.08598438 6.10467977,7.33792188 L8.3078104,11.0325469 L3.4906289,11.0325469 L3.4906289,8.0394375 L3.49061272,8.0394375 Z M1.1203237,12.8881406 L1.1203237,2.9206875 L2.3703052,2.9206875 L2.3703052,11.5545313 C2.3703052,11.8607813 2.61249711,12.0946094 2.92969017,12.0946094 L2.94843237,12.0946094 C2.98593295,12.1127188 3.04219191,12.1127188 3.09843468,12.1127188 L9.16563006,12.1127188 C9.48280694,12.1127188 9.72499884,11.878875 9.72499884,11.572625 L9.72499884,11.5364219 C9.76249942,11.3915938 9.74375723,11.2482813 9.66875607,11.1215469 L7.5593526,7.58835938 L8.6984185,7.58835938 C10.3406104,7.58835938 11.6843514,6.29095313 11.6843514,4.703875 C11.6843514,3.1168125 10.3406104,1.81939063 8.6984185,1.81939063 L3.4906289,1.81939063 L3.4906289,1.44073437 C3.4906289,1.24310937 3.65937341,1.08017187 3.86406474,1.08017187 L9.09061272,1.08017187 C11.143741,1.08017187 12.8234173,2.7019375 12.8234173,4.68578125 C12.8234173,6.21853125 11.8343538,7.5340625 10.4343538,8.05603125 C10.378111,8.07414063 10.3406104,8.09223438 10.2843514,8.11034375 C10.0234173,8.25517188 9.92967399,8.597625 10.0796763,8.8495625 L12.5062405,12.8881563 L1.12030751,12.8881563 L1.1203237,12.8881406 Z" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
const RiddleIcon: React.FC<{ className?: string }> = (props) => (
|
||||
<Icon component={SVGIcon} {...props} />
|
||||
);
|
||||
const RiddleIcon = React.forwardRef<HTMLSpanElement, { className?: string }>((props, ref) => (
|
||||
<Icon component={SVGIcon} ref={ref} {...props} />
|
||||
));
|
||||
|
||||
export default RiddleIcon;
|
@ -37,7 +37,7 @@ const DocLayout: React.FC = () => {
|
||||
const location = useLocation();
|
||||
const { pathname, search, hash } = location;
|
||||
const [locale, lang] = useLocale(locales);
|
||||
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
const timerRef = useRef<ReturnType<typeof setTimeout>>();
|
||||
const { direction } = useContext(SiteContext);
|
||||
const { loading } = useSiteData();
|
||||
|
||||
@ -51,11 +51,10 @@ const DocLayout: React.FC = () => {
|
||||
|
||||
useEffect(() => {
|
||||
const nprogressHiddenStyle = document.getElementById('nprogress-style');
|
||||
if (nprogressHiddenStyle) {
|
||||
timerRef.current = setTimeout(() => {
|
||||
nprogressHiddenStyle.parentNode?.removeChild(nprogressHiddenStyle);
|
||||
}, 0);
|
||||
}
|
||||
timerRef.current = setTimeout(() => {
|
||||
nprogressHiddenStyle?.remove();
|
||||
}, 0);
|
||||
return () => clearTimeout(timerRef.current);
|
||||
}, []);
|
||||
|
||||
// handle hash change or visit page hash from Link component, and jump after async chunk loaded
|
||||
|
@ -35,6 +35,16 @@ export const ANT_DESIGN_NOT_SHOW_BANNER = 'ANT_DESIGN_NOT_SHOW_BANNER';
|
||||
// (global as any).styleCache = styleCache;
|
||||
// }
|
||||
|
||||
// Compatible with old anchors
|
||||
if (typeof window !== 'undefined') {
|
||||
const hashId = location.hash.slice(1);
|
||||
if (hashId.startsWith('components-')) {
|
||||
if (!document.querySelector(`#${hashId}`)) {
|
||||
location.hash = `#${hashId.replace(/^components-/, '')}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const getAlgorithm = (themes: ThemeName[] = []) =>
|
||||
themes
|
||||
.map((theme) => {
|
||||
@ -153,6 +163,7 @@ const GlobalLayout: React.FC = () => {
|
||||
plain: true,
|
||||
types: 'style',
|
||||
});
|
||||
// biome-ignore lint/security/noDangerouslySetInnerHtml: only used in .dumi
|
||||
return <style data-type="antd-cssinjs" dangerouslySetInnerHTML={{ __html: styleText }} />;
|
||||
});
|
||||
|
||||
@ -166,6 +177,7 @@ const GlobalLayout: React.FC = () => {
|
||||
data-type="antd-css-var"
|
||||
data-rc-order="prepend"
|
||||
data-rc-priority="-9999"
|
||||
// biome-ignore lint/security/noDangerouslySetInnerHtml: only used in .dumi
|
||||
dangerouslySetInnerHTML={{ __html: styleText }}
|
||||
/>
|
||||
);
|
||||
@ -175,6 +187,7 @@ const GlobalLayout: React.FC = () => {
|
||||
<style
|
||||
data-sandpack="true"
|
||||
id="sandpack"
|
||||
// biome-ignore lint/security/noDangerouslySetInnerHtml: only used in .dumi
|
||||
dangerouslySetInnerHTML={{ __html: getSandpackCssText() }}
|
||||
/>
|
||||
));
|
||||
|
@ -6,7 +6,7 @@ import throttle from 'lodash/throttle';
|
||||
|
||||
import scrollTo from '../../../../components/_util/scrollTo';
|
||||
|
||||
const listenerEvents = ['scroll', 'resize'] as const;
|
||||
const listenerEvents: (keyof WindowEventMap)[] = ['scroll', 'resize'];
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => {
|
||||
const { boxShadowSecondary, antCls } = token;
|
||||
@ -15,8 +15,8 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
affixTabs: css`
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
inset-inline-end: 0;
|
||||
inset-inline-start: 0;
|
||||
z-index: 1001;
|
||||
padding: 0 40px;
|
||||
background: #fff;
|
||||
|
@ -10,7 +10,7 @@ import EditButton from '../../common/EditButton';
|
||||
import Footer from '../../slots/Footer';
|
||||
import AffixTabs from './AffixTabs';
|
||||
|
||||
export type ResourceLayoutProps = PropsWithChildren<{}>;
|
||||
export type ResourceLayoutProps = PropsWithChildren<NonNullable<any>>;
|
||||
|
||||
const resourcePadding = 40;
|
||||
const articleMaxWidth = 1208;
|
||||
|
@ -39,6 +39,13 @@ export const getHash = (str: string, length = 8) =>
|
||||
class AntdReactTechStack extends ReactTechStack {
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
generatePreviewerProps(...[props, opts]: any) {
|
||||
props.pkgDependencyList = { ...devDependencies, ...dependencies };
|
||||
props.jsx ??= '';
|
||||
|
||||
if (opts.type === 'code-block') {
|
||||
props.jsx = opts?.entryPointCode ? sylvanas.parseText(opts.entryPointCode) : '';
|
||||
}
|
||||
|
||||
if (opts.type === 'external') {
|
||||
// try to find md file with the same name as the demo tsx file
|
||||
const locale = opts.mdAbsPath.match(/index\.([a-z-]+)\.md$/i)?.[1];
|
||||
@ -48,7 +55,6 @@ class AntdReactTechStack extends ReactTechStack {
|
||||
const codePath = opts.fileAbsPath!.replace(/\.\w+$/, '.tsx');
|
||||
const code = fs.existsSync(codePath) ? fs.readFileSync(codePath, 'utf-8') : '';
|
||||
|
||||
props.pkgDependencyList = { ...devDependencies, ...dependencies };
|
||||
props.jsx = sylvanas.parseText(code);
|
||||
|
||||
if (md) {
|
||||
@ -181,26 +187,6 @@ const RoutesPlugin = (api: IApi) => {
|
||||
// exclude dynamic route path, to avoid deploy failed by `:id` directory
|
||||
.filter((f) => !f.path.includes(':'))
|
||||
.map((file) => {
|
||||
let globalStyles = '';
|
||||
|
||||
// Debug for file content: uncomment this if need check raw out
|
||||
// const tmpFileName = `_${file.path.replace(/\//g, '-')}`;
|
||||
// const tmpFilePath = path.join(api.paths.absOutputPath, tmpFileName);
|
||||
// fs.writeFileSync(tmpFilePath, file.content, 'utf8');
|
||||
|
||||
// extract all emotion style tags from body
|
||||
file.content = file.content.replace(
|
||||
/<style (data-emotion|data-sandpack)[\S\s]+?<\/style>/g,
|
||||
(s) => {
|
||||
globalStyles += s;
|
||||
|
||||
return '';
|
||||
},
|
||||
);
|
||||
|
||||
// insert emotion style tags to head
|
||||
file.content = file.content.replace('</head>', `${globalStyles}</head>`);
|
||||
|
||||
// 1. 提取 antd-style 样式
|
||||
const styles = extractEmotionStyle(file.content);
|
||||
|
||||
@ -217,30 +203,6 @@ const RoutesPlugin = (api: IApi) => {
|
||||
file.content = addLinkStyle(file.content, cssFile);
|
||||
});
|
||||
|
||||
// Insert antd style to head
|
||||
const matchRegex = /<style data-type="antd-cssinjs">([\S\s]+?)<\/style>/;
|
||||
const matchList = file.content.match(matchRegex) || [];
|
||||
|
||||
// Init to order the `@layer`
|
||||
let antdStyle = '@layer global, antd;';
|
||||
|
||||
matchList.forEach((text) => {
|
||||
file.content = file.content.replace(text, '');
|
||||
antdStyle += text.replace(matchRegex, '$1');
|
||||
});
|
||||
|
||||
const cssFile = writeCSSFile('antd', antdStyle, antdStyle);
|
||||
file.content = addLinkStyle(file.content, cssFile, true);
|
||||
|
||||
// Insert antd cssVar to head
|
||||
const cssVarMatchRegex = /<style data-type="antd-css-var"[\S\s]+?<\/style>/;
|
||||
const cssVarMatchList = file.content.match(cssVarMatchRegex) || [];
|
||||
|
||||
cssVarMatchList.forEach((text) => {
|
||||
file.content = file.content.replace(text, '');
|
||||
file.content = file.content.replace('<head>', `<head>${text}`);
|
||||
});
|
||||
|
||||
return file;
|
||||
}),
|
||||
);
|
||||
|
@ -2,6 +2,7 @@ import React from 'react';
|
||||
import { RightOutlined, YuqueOutlined, ZhihuOutlined } from '@ant-design/icons';
|
||||
import { Button, Card, Divider } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import useLocale from '../../../hooks/useLocale';
|
||||
import JuejinLogo from './JuejinLogo';
|
||||
@ -27,7 +28,7 @@ const useStyle = createStyles(({ token, css }) => ({
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
`,
|
||||
left: css`
|
||||
leftCard: css`
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
@ -42,6 +43,7 @@ const useStyle = createStyles(({ token, css }) => ({
|
||||
color: #444;
|
||||
font-size: ${token.fontSizeLG}px;
|
||||
font-weight: ${token.fontWeightStrong};
|
||||
user-select: none;
|
||||
`,
|
||||
subTitle: css`
|
||||
display: flex;
|
||||
@ -54,37 +56,34 @@ const useStyle = createStyles(({ token, css }) => ({
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
.logo {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
font-size: 24px;
|
||||
&.zhihu-logo {
|
||||
color: #056de8;
|
||||
}
|
||||
&.yuque-logo {
|
||||
color: #00b96b;
|
||||
}
|
||||
&.juejin-logo {
|
||||
color: #1e80ff;
|
||||
}
|
||||
`,
|
||||
logo: css`
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
font-size: 24px;
|
||||
&.zhihu-logo {
|
||||
color: #056de8;
|
||||
}
|
||||
.arrowIcon {
|
||||
color: #8a8f8d;
|
||||
margin: 0 ${token.marginXS}px;
|
||||
font-size: ${token.fontSizeSM}px;
|
||||
&.yuque-logo {
|
||||
color: #00b96b;
|
||||
}
|
||||
.zl-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
color: #646464;
|
||||
&.juejin-logo {
|
||||
color: #1e80ff;
|
||||
}
|
||||
`,
|
||||
btn: css`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
arrowIcon: css`
|
||||
color: #8a8f8d;
|
||||
margin: 0 ${token.marginXS}px;
|
||||
font-size: ${token.fontSizeSM}px;
|
||||
`,
|
||||
zlBtn: css`
|
||||
padding: 0;
|
||||
color: #646464;
|
||||
`,
|
||||
discussLogo: css`
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
font-size: 16px;
|
||||
`,
|
||||
}));
|
||||
|
||||
@ -114,7 +113,18 @@ interface Props {
|
||||
const ColumnCard: React.FC<Props> = ({ zhihuLink, yuqueLink, juejinLink }) => {
|
||||
const [locale] = useLocale(locales);
|
||||
const {
|
||||
styles: { card, bigTitle, cardBody, left, title, subTitle, btn },
|
||||
styles: {
|
||||
card,
|
||||
bigTitle,
|
||||
cardBody,
|
||||
leftCard,
|
||||
title,
|
||||
subTitle,
|
||||
logo,
|
||||
arrowIcon,
|
||||
zlBtn,
|
||||
discussLogo,
|
||||
},
|
||||
} = useStyle();
|
||||
if (!zhihuLink && !yuqueLink && !juejinLink) {
|
||||
return null;
|
||||
@ -123,52 +133,54 @@ const ColumnCard: React.FC<Props> = ({ zhihuLink, yuqueLink, juejinLink }) => {
|
||||
<Card className={card} bordered={false}>
|
||||
<h3 className={bigTitle}>{locale.bigTitle}</h3>
|
||||
{zhihuLink && (
|
||||
<div className={cardBody}>
|
||||
<div className={left}>
|
||||
<img src={ANTD_IMG_URL} alt="antd" />
|
||||
<div>
|
||||
<p className={title}>Ant Design</p>
|
||||
<div className={subTitle}>
|
||||
<ZhihuOutlined className="logo zhihu-logo" />
|
||||
<RightOutlined className="arrowIcon" />
|
||||
<Button
|
||||
target="_blank"
|
||||
href="https://www.zhihu.com/column/c_1564262000561106944"
|
||||
className="zl-btn"
|
||||
type="link"
|
||||
>
|
||||
{locale.zhiHu}
|
||||
</Button>
|
||||
<>
|
||||
<Divider />
|
||||
<div className={cardBody}>
|
||||
<div className={leftCard}>
|
||||
<img draggable={false} src={ANTD_IMG_URL} alt="antd" />
|
||||
<div>
|
||||
<p className={title}>Ant Design</p>
|
||||
<div className={subTitle}>
|
||||
<ZhihuOutlined className={classNames(logo, 'zhihu-logo')} />
|
||||
<RightOutlined className={arrowIcon} />
|
||||
<Button
|
||||
target="_blank"
|
||||
href="https://www.zhihu.com/column/c_1564262000561106944"
|
||||
className={zlBtn}
|
||||
type="link"
|
||||
>
|
||||
{locale.zhiHu}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
ghost
|
||||
type="primary"
|
||||
icon={<ZhihuOutlined className={discussLogo} />}
|
||||
target="_blank"
|
||||
href={zhihuLink}
|
||||
>
|
||||
{locale.buttonText}
|
||||
</Button>
|
||||
</div>
|
||||
<Button
|
||||
type="primary"
|
||||
className={btn}
|
||||
icon={<ZhihuOutlined style={{ fontSize: 16 }} />}
|
||||
ghost
|
||||
target="_blank"
|
||||
href={zhihuLink}
|
||||
>
|
||||
{locale.buttonText}
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{yuqueLink && (
|
||||
<>
|
||||
<Divider />
|
||||
<div className={cardBody}>
|
||||
<div className={left}>
|
||||
<img src={ANTD_IMG_URL} alt="antd" />
|
||||
<div className={leftCard}>
|
||||
<img draggable={false} src={ANTD_IMG_URL} alt="antd" />
|
||||
<div>
|
||||
<p className={title}>Ant Design</p>
|
||||
<div className={subTitle}>
|
||||
<YuqueOutlined className="logo yuque-logo" />
|
||||
<RightOutlined className="arrowIcon" />
|
||||
<YuqueOutlined className={classNames(logo, 'yuque-logo')} />
|
||||
<RightOutlined className={arrowIcon} />
|
||||
<Button
|
||||
target="_blank"
|
||||
href="https://www.yuque.com/ant-design/ant-design"
|
||||
className="zl-btn"
|
||||
className={zlBtn}
|
||||
type="link"
|
||||
>
|
||||
{locale.yuQue}
|
||||
@ -177,10 +189,9 @@ const ColumnCard: React.FC<Props> = ({ zhihuLink, yuqueLink, juejinLink }) => {
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
type="primary"
|
||||
className={btn}
|
||||
icon={<YuqueOutlined style={{ fontSize: 16 }} />}
|
||||
ghost
|
||||
type="primary"
|
||||
icon={<YuqueOutlined className={discussLogo} />}
|
||||
target="_blank"
|
||||
href={yuqueLink}
|
||||
>
|
||||
@ -193,17 +204,17 @@ const ColumnCard: React.FC<Props> = ({ zhihuLink, yuqueLink, juejinLink }) => {
|
||||
<>
|
||||
<Divider />
|
||||
<div className={cardBody}>
|
||||
<div className={left}>
|
||||
<img src={ANTD_IMG_URL} alt="antd" />
|
||||
<div className={leftCard}>
|
||||
<img draggable={false} src={ANTD_IMG_URL} alt="antd" />
|
||||
<div>
|
||||
<p className={title}>Ant Design</p>
|
||||
<div className={subTitle}>
|
||||
<JuejinLogo className="logo juejin-logo" />
|
||||
<RightOutlined className="arrowIcon" />
|
||||
<JuejinLogo className={classNames(logo, 'juejin-logo')} />
|
||||
<RightOutlined className={arrowIcon} />
|
||||
<Button
|
||||
target="_blank"
|
||||
href="https://juejin.cn/column/7247354308258054200"
|
||||
className="zl-btn"
|
||||
className={zlBtn}
|
||||
type="link"
|
||||
>
|
||||
{locale.junjin}
|
||||
@ -212,10 +223,9 @@ const ColumnCard: React.FC<Props> = ({ zhihuLink, yuqueLink, juejinLink }) => {
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
type="primary"
|
||||
className={btn}
|
||||
icon={<JuejinLogo style={{ fontSize: 16, width: 16, height: 16 }} />}
|
||||
ghost
|
||||
type="primary"
|
||||
icon={<JuejinLogo className={discussLogo} />}
|
||||
target="_blank"
|
||||
href={juejinLink}
|
||||
>
|
||||
|
@ -5,7 +5,7 @@ import type { AnchorLinkItemProps } from 'antd/es/anchor/Anchor';
|
||||
import classNames from 'classnames';
|
||||
import { useRouteMeta, useTabMeta } from 'dumi';
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => {
|
||||
export const useStyle = createStyles(({ token, css }) => {
|
||||
const { antCls } = token;
|
||||
return {
|
||||
anchorToc: css`
|
||||
@ -19,13 +19,13 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
`,
|
||||
tocWrapper: css`
|
||||
position: fixed;
|
||||
top: ${token.headerHeight + token.contentMarginTop - 8}px;
|
||||
top: ${token.headerHeight + token.contentMarginTop - 4}px;
|
||||
inset-inline-end: 0;
|
||||
width: 160px;
|
||||
padding: ${token.paddingXS}px;
|
||||
width: 148px;
|
||||
padding: 0;
|
||||
border-radius: ${token.borderRadius}px;
|
||||
box-sizing: border-box;
|
||||
margin-inline-end: calc(16px - 100vw + 100%);
|
||||
margin-inline-end: calc(8px - 100vw + 100%);
|
||||
z-index: 10;
|
||||
.toc-debug {
|
||||
color: ${token.purple6};
|
||||
@ -48,15 +48,11 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
}
|
||||
`,
|
||||
articleWrapper: css`
|
||||
padding: 0 170px 32px 64px;
|
||||
|
||||
&.rtl {
|
||||
padding: 0 64px 144px 170px;
|
||||
}
|
||||
padding-inline: 48px 164px;
|
||||
padding-block: 0 32px;
|
||||
|
||||
@media only screen and (max-width: ${token.screenLG}px) {
|
||||
&,
|
||||
&.rtl {
|
||||
& {
|
||||
padding: 0 ${token.paddingLG * 2}px;
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ const JuejinLogo: React.FC<Props> = (props) => {
|
||||
viewBox="0 0 36 28"
|
||||
fill="none"
|
||||
>
|
||||
<title>Juejin logo</title>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
|
@ -1,6 +1,5 @@
|
||||
import React, { useContext, useLayoutEffect, useMemo, useState } from 'react';
|
||||
import { Col, Flex, Typography } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
import { Col, Flex, Space, Typography } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import { FormattedMessage, useRouteMeta } from 'dumi';
|
||||
|
||||
@ -11,6 +10,7 @@ import type { DemoContextProps } from '../DemoContext';
|
||||
import DemoContext from '../DemoContext';
|
||||
import SiteContext from '../SiteContext';
|
||||
import InViewSuspense from './InViewSuspense';
|
||||
import { useStyle } from './DocAnchor';
|
||||
|
||||
const Contributors = React.lazy(() => import('./Contributors'));
|
||||
const ColumnCard = React.lazy(() => import('./ColumnCard'));
|
||||
@ -21,21 +21,6 @@ const PrevAndNext = React.lazy(() => import('../../common/PrevAndNext'));
|
||||
const ComponentChangelog = React.lazy(() => import('../../common/ComponentChangelog'));
|
||||
const EditButton = React.lazy(() => import('../../common/EditButton'));
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => ({
|
||||
articleWrapper: css`
|
||||
padding: 0 170px 32px 64px;
|
||||
&.rtl {
|
||||
padding: 0 64px 144px 170px;
|
||||
}
|
||||
@media only screen and (max-width: ${token.screenLG}px) {
|
||||
&,
|
||||
&.rtl {
|
||||
padding: 0 ${token.paddingLG * 2}px;
|
||||
}
|
||||
}
|
||||
`,
|
||||
}));
|
||||
|
||||
const Content: React.FC<React.PropsWithChildren> = ({ children }) => {
|
||||
const meta = useRouteMeta();
|
||||
const { pathname, hash } = useLocation();
|
||||
@ -70,25 +55,27 @@ const Content: React.FC<React.PropsWithChildren> = ({ children }) => {
|
||||
</InViewSuspense>
|
||||
<article className={classNames(styles.articleWrapper, { rtl: isRTL })}>
|
||||
{meta.frontmatter?.title ? (
|
||||
<Typography.Title style={{ fontSize: 30, position: 'relative' }}>
|
||||
<Flex gap="small">
|
||||
<div>{meta.frontmatter?.title}</div>
|
||||
<div>{meta.frontmatter?.subtitle}</div>
|
||||
{!pathname.startsWith('/components/overview') && (
|
||||
<InViewSuspense fallback={null}>
|
||||
<EditButton
|
||||
title={<FormattedMessage id="app.content.edit-page" />}
|
||||
filename={meta.frontmatter.filename}
|
||||
/>
|
||||
</InViewSuspense>
|
||||
)}
|
||||
</Flex>
|
||||
<Flex justify="space-between">
|
||||
<Typography.Title style={{ fontSize: 32, position: 'relative' }}>
|
||||
<Space>
|
||||
<span>{meta.frontmatter?.title}</span>
|
||||
<span>{meta.frontmatter?.subtitle}</span>
|
||||
{!pathname.startsWith('/components/overview') && (
|
||||
<InViewSuspense fallback={null}>
|
||||
<EditButton
|
||||
title={<FormattedMessage id="app.content.edit-page" />}
|
||||
filename={meta.frontmatter.filename}
|
||||
/>
|
||||
</InViewSuspense>
|
||||
)}
|
||||
</Space>
|
||||
</Typography.Title>
|
||||
{pathname.startsWith('/components/') && (
|
||||
<InViewSuspense fallback={null}>
|
||||
<ComponentChangelog pathname={pathname} />
|
||||
</InViewSuspense>
|
||||
)}
|
||||
</Typography.Title>
|
||||
</Flex>
|
||||
) : null}
|
||||
<InViewSuspense fallback={null}>
|
||||
<DocMeta />
|
||||
@ -105,9 +92,7 @@ const Content: React.FC<React.PropsWithChildren> = ({ children }) => {
|
||||
version={meta.frontmatter.tag}
|
||||
/>
|
||||
)}
|
||||
<div style={{ minHeight: 'calc(100vh - 64px)', width: 'calc(100% - 10px)' }}>
|
||||
{children}
|
||||
</div>
|
||||
<div style={{ minHeight: 'calc(100vh - 64px)' }}>{children}</div>
|
||||
<InViewSuspense>
|
||||
<ColumnCard
|
||||
zhihuLink={meta.frontmatter.zhihu_url}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { createStyles } from 'antd-style';
|
||||
import { removeCSS, updateCSS } from 'rc-util/lib/Dom/dynamicCSS';
|
||||
|
||||
import useLocale from '../../../hooks/useLocale';
|
||||
@ -19,9 +20,38 @@ const locales = {
|
||||
},
|
||||
};
|
||||
|
||||
const useStyle = createStyles(({ css, token }) => ({
|
||||
container: css`
|
||||
position: fixed;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-end: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: 99999999;
|
||||
background-color: ${token.colorTextSecondary};
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
`,
|
||||
alertBox: css`
|
||||
border: 1px solid ${token.colorWarningBorder};
|
||||
background-color: ${token.colorWarningBg};
|
||||
color: ${token.colorTextHeading};
|
||||
padding: ${token.paddingXS}px ${token.paddingSM}px;
|
||||
border-radius: ${token.borderRadiusLG}px;
|
||||
z-index: 9999999999;
|
||||
line-height: 22px;
|
||||
width: 520px;
|
||||
a {
|
||||
color: ${token.colorPrimary};
|
||||
text-decoration-line: none;
|
||||
}
|
||||
`,
|
||||
}));
|
||||
|
||||
// Check for browser support `:where` or not
|
||||
// Warning user if not support to modern browser
|
||||
function InfoNewVersion() {
|
||||
const InfoNewVersion: React.FC = () => {
|
||||
const [location] = useLocale(locales);
|
||||
const [supportWhere, setSupportWhere] = React.useState(true);
|
||||
|
||||
@ -50,40 +80,19 @@ function InfoNewVersion() {
|
||||
removeCSS(whereCls);
|
||||
}, []);
|
||||
|
||||
return supportWhere ? null : (
|
||||
<div
|
||||
style={{
|
||||
position: 'fixed',
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
zIndex: 99999999,
|
||||
background: 'rgba(0,0,0,0.65)',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
border: `1px solid #ffe58f`,
|
||||
background: '#fffbe6',
|
||||
color: 'rgba(0,0,0,0.88)',
|
||||
padding: '8px 12px',
|
||||
borderRadius: '8px',
|
||||
zIndex: 9999999999,
|
||||
lineHeight: '22px',
|
||||
width: 520,
|
||||
}}
|
||||
>
|
||||
{location.whereNotSupport}{' '}
|
||||
<a style={{ color: '#1677ff', textDecoration: 'none' }} href={location.whereDocUrl}>
|
||||
{location.whereDocTitle}
|
||||
</a>
|
||||
const { styles } = useStyle();
|
||||
|
||||
if (supportWhere) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.alertBox}>
|
||||
{location.whereNotSupport} <a href={location.whereDocUrl}>{location.whereDocTitle}</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default InfoNewVersion;
|
||||
|
@ -202,7 +202,7 @@ const Footer: React.FC = () => {
|
||||
src="https://gw.alipayobjects.com/zos/rmsportal/XuVpGqBFxXplzvLjJBZB.svg"
|
||||
width={16}
|
||||
height={16}
|
||||
alt="yuque"
|
||||
alt="yuque logo"
|
||||
/>
|
||||
),
|
||||
title: <FormattedMessage id="app.footer.yuque.repo" />,
|
||||
@ -227,7 +227,7 @@ const Footer: React.FC = () => {
|
||||
src="https://gw.alipayobjects.com/zos/rmsportal/mZBWtboYbnMkTBaRIuWQ.png"
|
||||
width={16}
|
||||
height={16}
|
||||
alt="seeconf"
|
||||
alt="seeconf logo"
|
||||
/>
|
||||
),
|
||||
title: 'SEE Conf',
|
||||
@ -310,7 +310,7 @@ const Footer: React.FC = () => {
|
||||
src="https://gw.alipayobjects.com/zos/rmsportal/nBVXkrFdWHxbZlmMbsaH.svg"
|
||||
width={22}
|
||||
height={22}
|
||||
alt="Ant XTech"
|
||||
alt="Ant XTech logo"
|
||||
/>
|
||||
),
|
||||
title: <FormattedMessage id="app.footer.more-product" />,
|
||||
@ -321,7 +321,7 @@ const Footer: React.FC = () => {
|
||||
src="https://gw.alipayobjects.com/zos/rmsportal/XuVpGqBFxXplzvLjJBZB.svg"
|
||||
width={16}
|
||||
height={16}
|
||||
alt="yuque"
|
||||
alt="yuque logo"
|
||||
/>
|
||||
),
|
||||
title: <FormattedMessage id="app.footer.yuque" />,
|
||||
@ -335,7 +335,7 @@ const Footer: React.FC = () => {
|
||||
src="https://gw.alipayobjects.com/zos/antfincdn/nc7Fc0XBg5/8a6844f5-a6ed-4630-9177-4fa5d0b7dd47.png"
|
||||
width={16}
|
||||
height={16}
|
||||
alt="AntV"
|
||||
alt="AntV logo"
|
||||
/>
|
||||
),
|
||||
title: 'AntV',
|
||||
@ -344,7 +344,7 @@ const Footer: React.FC = () => {
|
||||
openExternal: true,
|
||||
},
|
||||
{
|
||||
icon: <img src="https://www.eggjs.org/logo.svg" alt="Egg" width={16} height={16} />,
|
||||
icon: <img src="https://www.eggjs.org/logo.svg" alt="Egg logo" width={16} height={16} />,
|
||||
title: 'Egg',
|
||||
url: 'https://eggjs.org',
|
||||
description: <FormattedMessage id="app.footer.egg.slogan" />,
|
||||
@ -356,7 +356,7 @@ const Footer: React.FC = () => {
|
||||
src="https://gw.alipayobjects.com/zos/rmsportal/DMDOlAUhmktLyEODCMBR.ico"
|
||||
width={16}
|
||||
height={16}
|
||||
alt="kitchen"
|
||||
alt="Kitchen logo"
|
||||
/>
|
||||
),
|
||||
title: 'Kitchen',
|
||||
@ -370,7 +370,7 @@ const Footer: React.FC = () => {
|
||||
src="https://mdn.alipayobjects.com/huamei_j9rjmc/afts/img/A*3ittT5OEo2gAAAAAAAAAAAAADvGmAQ/original"
|
||||
width={16}
|
||||
height={16}
|
||||
alt="Galacean"
|
||||
alt="Galacean logo"
|
||||
/>
|
||||
),
|
||||
title: <FormattedMessage id="app.footer.galacean" />,
|
||||
@ -384,7 +384,7 @@ const Footer: React.FC = () => {
|
||||
src="https://gw.alipayobjects.com/zos/rmsportal/nBVXkrFdWHxbZlmMbsaH.svg"
|
||||
width={16}
|
||||
height={16}
|
||||
alt="xtech"
|
||||
alt="xtech logo"
|
||||
/>
|
||||
),
|
||||
title: <FormattedMessage id="app.footer.xtech" />,
|
||||
|
@ -1,7 +1,8 @@
|
||||
import * as React from 'react';
|
||||
import { createStyles } from 'antd-style';
|
||||
import { Link, useLocation } from 'dumi';
|
||||
import { useLocation } from 'dumi';
|
||||
|
||||
import Link from '../../common/Link';
|
||||
import * as utils from '../../utils';
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => {
|
||||
@ -22,15 +23,17 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
text-decoration: none;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
column-gap: ${token.marginSM}px;
|
||||
|
||||
&:hover {
|
||||
color: ${colorTextHeading};
|
||||
}
|
||||
|
||||
img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-inline-end: ${token.marginSM}px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: ${mobileMaxWidth}px) {
|
||||
@ -49,18 +52,15 @@ export interface LogoProps {
|
||||
location: any;
|
||||
}
|
||||
|
||||
const logoSrc = 'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg';
|
||||
|
||||
const Logo: React.FC<LogoProps> = ({ isZhCN }) => {
|
||||
const { search } = useLocation();
|
||||
const { styles } = useStyle();
|
||||
return (
|
||||
<h1>
|
||||
<Link to={utils.getLocalizedPathname('/', isZhCN, search)} className={styles.logo}>
|
||||
<img
|
||||
src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
|
||||
height={32}
|
||||
width={32}
|
||||
alt="logo"
|
||||
/>
|
||||
<img src={logoSrc} draggable={false} alt="logo" />
|
||||
<span className={styles.title}>Ant Design</span>
|
||||
</Link>
|
||||
</h1>
|
||||
|
@ -30,16 +30,7 @@ const locales = {
|
||||
|
||||
// ============================= Style =============================
|
||||
const useStyle = createStyles(({ token }) => {
|
||||
const {
|
||||
antCls,
|
||||
iconCls,
|
||||
fontFamily,
|
||||
fontSize,
|
||||
headerHeight,
|
||||
menuItemBorder,
|
||||
colorPrimary,
|
||||
colorText,
|
||||
} = token;
|
||||
const { antCls, iconCls, fontFamily, fontSize, headerHeight, colorPrimary } = token;
|
||||
|
||||
return {
|
||||
nav: css`
|
||||
@ -57,25 +48,6 @@ const useStyle = createStyles(({ token }) => {
|
||||
padding-inline-end: ${token.paddingSM}px;
|
||||
padding-inline-start: ${token.paddingSM}px;
|
||||
line-height: ${headerHeight}px;
|
||||
|
||||
&::after {
|
||||
top: 0;
|
||||
right: 12px;
|
||||
bottom: auto;
|
||||
left: 12px;
|
||||
border-width: ${menuItemBorder}px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: ${colorText};
|
||||
}
|
||||
|
||||
a:before {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background-color: transparent;
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
|
||||
& ${antCls}-menu-submenu-title ${iconCls} {
|
||||
@ -124,7 +96,7 @@ const HeaderNavigation: React.FC<NavigationProps> = (props) => {
|
||||
activeMenuItem = 'docs/resources';
|
||||
}
|
||||
|
||||
let additional: MenuProps['items'];
|
||||
let additional: MenuProps['items'] = [];
|
||||
|
||||
const additionalItems: MenuProps['items'] = [
|
||||
{
|
||||
@ -215,50 +187,16 @@ const HeaderNavigation: React.FC<NavigationProps> = (props) => {
|
||||
},
|
||||
isZhCN
|
||||
? {
|
||||
key: 'mirror',
|
||||
label: (
|
||||
<a href="https://ant-design.antgroup.com" target="_blank" rel="noreferrer">
|
||||
国内镜像
|
||||
</a>
|
||||
),
|
||||
key: 'mirror',
|
||||
children: [
|
||||
{
|
||||
label: (
|
||||
<a href="https://ant-design.antgroup.com" target="_blank" rel="noreferrer">
|
||||
官方镜像
|
||||
</a>
|
||||
),
|
||||
icon: (
|
||||
<img
|
||||
alt="logo"
|
||||
src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
|
||||
width={16}
|
||||
style={{ verticalAlign: 'text-bottom' }}
|
||||
/>
|
||||
),
|
||||
key: 'antgroup',
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<a href="https://ant-design.gitee.io" target="_blank" rel="noreferrer">
|
||||
Gitee 镜像
|
||||
</a>
|
||||
),
|
||||
icon: (
|
||||
<img
|
||||
alt="gitee"
|
||||
src="https://gw.alipayobjects.com/zos/bmw-prod/9e91e124-9bab-4113-b500-301412f6b370.svg"
|
||||
width={16}
|
||||
style={{ verticalAlign: 'text-bottom' }}
|
||||
/>
|
||||
),
|
||||
key: 'gitee',
|
||||
},
|
||||
],
|
||||
}
|
||||
: null,
|
||||
...(additional ?? []),
|
||||
];
|
||||
].filter(Boolean);
|
||||
|
||||
return (
|
||||
<Menu
|
||||
|
@ -11,7 +11,7 @@ export interface LangBtnProps {
|
||||
value: 1 | 2;
|
||||
pure?: boolean;
|
||||
onClick?: React.MouseEventHandler;
|
||||
['aria-label']?: string;
|
||||
'aria-label'?: string;
|
||||
}
|
||||
|
||||
const BASE_SIZE = '1.2em';
|
||||
@ -69,7 +69,7 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
color: ${colorText};
|
||||
`,
|
||||
label1Style: css`
|
||||
left: -5%;
|
||||
inset-inline-start: -5%;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
background-color: ${colorText};
|
||||
@ -78,7 +78,7 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
transform-origin: 0 0;
|
||||
`,
|
||||
label2Style: css`
|
||||
right: -5%;
|
||||
inset-inline-end: -5%;
|
||||
bottom: 0;
|
||||
z-index: 0;
|
||||
transform: scale(0.5);
|
||||
@ -95,7 +95,13 @@ const LangBtn: React.FC<LangBtnProps> = (props) => {
|
||||
} = useStyle();
|
||||
|
||||
const node = (
|
||||
<button onClick={onClick} className={btn} key="lang-button" aria-label={props['aria-label']}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClick}
|
||||
className={btn}
|
||||
key="lang-button"
|
||||
aria-label={props['aria-label']}
|
||||
>
|
||||
<div className="btn-inner">
|
||||
{pure && (value === 1 ? label1 : label2)}
|
||||
{!pure && (
|
||||
|
@ -8,7 +8,7 @@ import { useLocation, useSiteData } from 'dumi';
|
||||
import DumiSearchBar from 'dumi/theme-default/slots/SearchBar';
|
||||
|
||||
import useLocale from '../../../hooks/useLocale';
|
||||
import DirectionIcon from '../../common/DirectionIcon';
|
||||
import DirectionIcon from '../../icons/DirectionIcon';
|
||||
import { ANT_DESIGN_NOT_SHOW_BANNER } from '../../layouts/GlobalLayout';
|
||||
import * as utils from '../../utils';
|
||||
import { getThemeConfig } from '../../utils';
|
||||
@ -54,12 +54,11 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.nav-search-wrapper {
|
||||
display: flex;
|
||||
flex: auto;
|
||||
}
|
||||
|
||||
.dumi-default-search-bar {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
flex: auto;
|
||||
margin: 0;
|
||||
border-inline-start: 1px solid rgba(0, 0, 0, 0.06);
|
||||
|
||||
> svg {
|
||||
@ -70,6 +69,7 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
> input {
|
||||
height: 22px;
|
||||
border: 0;
|
||||
max-width: calc(100vw - 768px);
|
||||
|
||||
&:focus {
|
||||
box-shadow: none;
|
||||
@ -85,16 +85,22 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
background-color: rgba(150, 150, 150, 0.06);
|
||||
border-color: rgba(100, 100, 100, 0.2);
|
||||
border-radius: ${token.borderRadiusSM}px;
|
||||
position: static;
|
||||
top: unset;
|
||||
transform: unset;
|
||||
}
|
||||
|
||||
.dumi-default-search-popover {
|
||||
inset-inline-start: 11px;
|
||||
inset-inline-start: ${token.paddingSM}px;
|
||||
inset-inline-end: unset;
|
||||
|
||||
&::before {
|
||||
inset-inline-start: 100px;
|
||||
inset-inline-end: unset;
|
||||
}
|
||||
& > section {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
@ -103,12 +109,11 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
column-gap: ${token.paddingSM}px;
|
||||
padding-inline-end: ${token.padding}px;
|
||||
|
||||
> * {
|
||||
flex: none;
|
||||
margin: 0;
|
||||
&:last-child {
|
||||
margin-inline-end: 40px;
|
||||
}
|
||||
}
|
||||
`,
|
||||
dataDirectionIcon: css`
|
||||
@ -405,11 +410,11 @@ const Header: React.FC = () => {
|
||||
<Col {...colProps[0]}>
|
||||
<Logo {...sharedProps} location={location} />
|
||||
</Col>
|
||||
<Col {...colProps[1]} className={styles.menuRow}>
|
||||
<div className="nav-search-wrapper">
|
||||
<Col {...colProps[1]}>
|
||||
<div className={styles.menuRow}>
|
||||
<DumiSearchBar />
|
||||
{!isMobile && menu}
|
||||
</div>
|
||||
{!isMobile && menu}
|
||||
</Col>
|
||||
</Row>
|
||||
</header>
|
||||
|
@ -53,12 +53,7 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
> ${antCls}-menu-item-group
|
||||
> ${antCls}-menu-item-group-list
|
||||
> ${antCls}-menu-item {
|
||||
padding-inline-start: 40px !important;
|
||||
|
||||
${antCls}-row-rtl & {
|
||||
padding-inline-end: 40px !important;
|
||||
padding-inline-start: ${token.padding}px !important;
|
||||
}
|
||||
padding-inline: 36px 12px !important;
|
||||
}
|
||||
|
||||
// Nest Category > Type > Article
|
||||
@ -96,8 +91,6 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
`,
|
||||
mainMenu: css`
|
||||
z-index: 1;
|
||||
|
||||
.main-menu-inner {
|
||||
position: sticky;
|
||||
top: ${token.headerHeight + token.contentMarginTop}px;
|
||||
width: 100%;
|
||||
@ -106,9 +99,12 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
overflow: hidden;
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: unset;
|
||||
}
|
||||
|
||||
&:hover .main-menu-inner {
|
||||
.ant-menu {
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
overflow-y: auto;
|
||||
}
|
||||
`,
|
||||
@ -144,7 +140,7 @@ const Sidebar: React.FC = () => {
|
||||
<MobileMenu key="Mobile-menu">{menuChild}</MobileMenu>
|
||||
) : (
|
||||
<Col xxl={4} xl={5} lg={6} md={6} sm={24} xs={24} className={styles.mainMenu}>
|
||||
<section className="main-menu-inner">{menuChild}</section>
|
||||
{menuChild}
|
||||
</Col>
|
||||
);
|
||||
};
|
||||
|
@ -1,5 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import type { DirectionType } from 'antd/es/config-provider';
|
||||
|
||||
import type { ThemeName } from '../common/ThemeSwitch';
|
||||
|
||||
export interface SiteContextProps {
|
||||
|
@ -181,6 +181,7 @@ export function isLocalStorageNameSupported() {
|
||||
storage.removeItem(testKey);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Your web browser does not support storing settings locally.', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
45
.dumirc.ts
45
.dumirc.ts
@ -8,14 +8,22 @@ import { version } from './package.json';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: ['dumi-plugin-color-chunk'],
|
||||
manifest: {},
|
||||
conventionRoutes: {
|
||||
// to avoid generate routes for .dumi/pages/index/components/xx
|
||||
exclude: [new RegExp('index/components/')],
|
||||
exclude: [/index\/components\//],
|
||||
},
|
||||
ssr: process.env.NODE_ENV === 'production' ? {} : false,
|
||||
ssr:
|
||||
process.env.NODE_ENV === 'production'
|
||||
? {
|
||||
builder: 'mako',
|
||||
}
|
||||
: false,
|
||||
hash: true,
|
||||
mfsu: false,
|
||||
mako: {},
|
||||
crossorigin: {},
|
||||
runtimePublicPath: {},
|
||||
outputPath: '_site',
|
||||
favicons: ['https://gw.alipayobjects.com/zos/rmsportal/rlpTLlbMzTNYuZGGCVYM.png'],
|
||||
resolve: {
|
||||
@ -40,11 +48,16 @@ export default defineConfig({
|
||||
},
|
||||
extraRehypePlugins: [rehypeAntd],
|
||||
extraRemarkPlugins: [remarkAntd],
|
||||
metas: [{ name: 'theme-color', content: '#1677ff' }],
|
||||
metas: [
|
||||
{ name: 'theme-color', content: '#1677ff' },
|
||||
{ name: 'build-time', content: Date.now().toString() },
|
||||
// https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables
|
||||
{ name: 'build-hash', content: process.env.GITHUB_SHA ?? 'unknown' },
|
||||
],
|
||||
analytics: {
|
||||
ga_v2: 'UA-72788897-1',
|
||||
},
|
||||
analyze: {
|
||||
analyze: process.env.NODE_ENV === 'production' ? false : {
|
||||
analyzerPort: 'auto',
|
||||
},
|
||||
links: [
|
||||
@ -53,56 +66,56 @@ export default defineConfig({
|
||||
as: 'font',
|
||||
href: '//at.alicdn.com/t/webfont_6e11e43nfj.woff2',
|
||||
type: 'font/woff2',
|
||||
crossorigin: true,
|
||||
crossorigin: 'anonymous',
|
||||
},
|
||||
{
|
||||
rel: 'prefetch',
|
||||
as: 'font',
|
||||
href: '//at.alicdn.com/t/webfont_6e11e43nfj.woff',
|
||||
type: 'font/woff',
|
||||
crossorigin: true,
|
||||
crossorigin: 'anonymous',
|
||||
},
|
||||
{
|
||||
rel: 'prefetch',
|
||||
as: 'font',
|
||||
href: '//at.alicdn.com/t/webfont_6e11e43nfj.ttf',
|
||||
type: 'font/ttf',
|
||||
crossorigin: true,
|
||||
crossorigin: 'anonymous',
|
||||
},
|
||||
{
|
||||
rel: 'prefetch',
|
||||
as: 'font',
|
||||
href: '//at.alicdn.com/t/webfont_exesdog9toj.woff2',
|
||||
type: 'font/woff2',
|
||||
crossorigin: true,
|
||||
crossorigin: 'anonymous',
|
||||
},
|
||||
{
|
||||
rel: 'prefetch',
|
||||
as: 'font',
|
||||
href: '//at.alicdn.com/t/webfont_exesdog9toj.woff',
|
||||
type: 'font/woff',
|
||||
crossorigin: true,
|
||||
crossorigin: 'anonymous',
|
||||
},
|
||||
{
|
||||
rel: 'prefetch',
|
||||
as: 'font',
|
||||
href: '//at.alicdn.com/t/webfont_exesdog9toj.ttf',
|
||||
type: 'font/ttf',
|
||||
crossorigin: true,
|
||||
crossorigin: 'anonymous',
|
||||
},
|
||||
{
|
||||
rel: 'preload',
|
||||
as: 'font',
|
||||
href: '//at.alicdn.com/wf/webfont/exMpJIukiCms/Gsw2PSKrftc1yNWMNlXgw.woff2',
|
||||
type: 'font/woff2',
|
||||
crossorigin: true,
|
||||
crossorigin: 'anonymous',
|
||||
},
|
||||
{
|
||||
rel: 'preload',
|
||||
as: 'font',
|
||||
href: '//at.alicdn.com/wf/webfont/exMpJIukiCms/vtu73by4O2gEBcvBuLgeu.woff',
|
||||
type: 'font/woff2',
|
||||
crossorigin: true,
|
||||
crossorigin: 'anonymous',
|
||||
},
|
||||
],
|
||||
headScripts: [
|
||||
@ -166,7 +179,13 @@ export default defineConfig({
|
||||
scripts: [
|
||||
{
|
||||
async: true,
|
||||
content: fs.readFileSync(path.join(__dirname, '.dumi', 'mirror-modal.js')).toString(),
|
||||
content: fs
|
||||
.readFileSync(path.join(__dirname, '.dumi', 'scripts', 'mirror-modal.js'))
|
||||
.toString(),
|
||||
},
|
||||
{
|
||||
async: true,
|
||||
content: fs.readFileSync(path.join(__dirname, '.dumi', 'scripts', 'clarity.js')).toString(),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
1
.github/FUNDING.yml
vendored
1
.github/FUNDING.yml
vendored
@ -2,5 +2,6 @@
|
||||
|
||||
github: ant-design
|
||||
open_collective: ant-design
|
||||
ko_fi: ant_design
|
||||
issuehunt: ant-design/ant-design
|
||||
buy_me_a_coffee: antdesign
|
||||
|
69
.github/PULL_REQUEST_TEMPLATE.md
vendored
69
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -6,58 +6,45 @@ Your pull requests will be merged after one of the collaborators approve.
|
||||
Thank you!
|
||||
-->
|
||||
|
||||
[中文版模板 / Chinese template](https://github.com/ant-design/ant-design/blob/master/.github/PULL_REQUEST_TEMPLATE/pr_cn.md?plain=1)
|
||||
[中文版模板 / Chinese template](https://github.com/ant-design/ant-design/blob/master/.github/PULL_REQUEST_TEMPLATE_CN.md?plain=1)
|
||||
|
||||
### 🤔 This is a ...
|
||||
|
||||
- [ ] New feature
|
||||
- [ ] Bug fix
|
||||
- [ ] Site / documentation update
|
||||
- [ ] Demo update
|
||||
- [ ] Component style update
|
||||
- [ ] TypeScript definition update
|
||||
- [ ] Bundle size optimization
|
||||
- [ ] Performance optimization
|
||||
- [ ] Enhancement feature
|
||||
- [ ] Internationalization
|
||||
- [ ] Refactoring
|
||||
- [ ] Code style optimization
|
||||
- [ ] Test Case
|
||||
- [ ] Branch merge
|
||||
- [ ] Workflow
|
||||
- [ ] Other (about what?)
|
||||
- [ ] 🆕 New feature
|
||||
- [ ] 🐞 Bug fix
|
||||
- [ ] 📝 Site / documentation improvement
|
||||
- [ ] 📽️ Demo improvement
|
||||
- [ ] 💄 Component style improvement
|
||||
- [ ] 🤖 TypeScript definition improvement
|
||||
- [ ] 📦 Bundle size optimization
|
||||
- [ ] ⚡️ Performance optimization
|
||||
- [ ] ⭐️ Feature enhancement
|
||||
- [ ] 🌐 Internationalization
|
||||
- [ ] 🛠 Refactoring
|
||||
- [ ] 🎨 Code style optimization
|
||||
- [ ] ✅ Test Case
|
||||
- [ ] 🔀 Branch merge
|
||||
- [ ] ⏩ Workflow
|
||||
- [ ] ❓ Other (about what?)
|
||||
|
||||
### 🔗 Related issue link
|
||||
### 🔗 Related Issues
|
||||
|
||||
<!--
|
||||
1. Put the related issue or discussion links here.
|
||||
2. close #xxxx or fix #xxxx for instance.
|
||||
-->
|
||||
> - Describe the source of related requirements, such as links to relevant issue discussions.
|
||||
> - For example: close #xxxx, fix #xxxx
|
||||
|
||||
### 💡 Background and solution
|
||||
### 💡 Background and Solution
|
||||
|
||||
<!--
|
||||
1. Describe the problem and the scenario.
|
||||
2. GIF or snapshot should be provided if includes UI/interactive modification.
|
||||
3. How to fix the problem, and list the final API implementation and usage sample if that is a new feature.
|
||||
-->
|
||||
> - The specific problem to be addressed.
|
||||
> - List the final API implementation and usage if needed.
|
||||
> - If there are UI/interaction changes, consider providing screenshots or GIFs.
|
||||
|
||||
### 📝 Changelog
|
||||
### 📝 Change Log
|
||||
|
||||
<!--
|
||||
Describe changes from the user side, and list all potential break changes or other risks.
|
||||
--->
|
||||
> - Read [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) like a cat tracks a laser pointer.
|
||||
> - Describe the impact of the changes on developers, not the solution approach.
|
||||
> - Reference: https://ant.design/changelog
|
||||
|
||||
| Language | Changelog |
|
||||
| ---------- | --------- |
|
||||
| 🇺🇸 English | |
|
||||
| 🇨🇳 Chinese | |
|
||||
|
||||
### ☑️ Self-Check before Merge
|
||||
|
||||
⚠️ Please check all items below before requesting a reviewing. ⚠️
|
||||
|
||||
- [ ] Doc is updated/provided or not needed
|
||||
- [ ] Demo is updated/provided or not needed
|
||||
- [ ] TypeScript definition is updated/provided or not needed
|
||||
- [ ] Changelog is provided or not needed
|
||||
|
63
.github/PULL_REQUEST_TEMPLATE/pr_cn.md
vendored
63
.github/PULL_REQUEST_TEMPLATE/pr_cn.md
vendored
@ -1,63 +0,0 @@
|
||||
<!--
|
||||
首先,感谢你的贡献!😄
|
||||
|
||||
新特性请提交至 feature 分支,其余可提交至 master 分支。
|
||||
在维护者审核通过后会合并。
|
||||
请确保填写以下 pull request 的信息,谢谢!~
|
||||
-->
|
||||
|
||||
[English Template / 英文模板](https://github.com/ant-design/ant-design/blob/master/.github/PULL_REQUEST_TEMPLATE.md?plain=1)
|
||||
|
||||
### 🤔 这个变动的性质是?
|
||||
|
||||
- [ ] 新特性提交
|
||||
- [ ] 日常 bug 修复
|
||||
- [ ] 站点、文档改进
|
||||
- [ ] 演示代码改进
|
||||
- [ ] 组件样式/交互改进
|
||||
- [ ] TypeScript 定义更新
|
||||
- [ ] 包体积优化
|
||||
- [ ] 性能优化
|
||||
- [ ] 功能增强
|
||||
- [ ] 国际化改进
|
||||
- [ ] 重构
|
||||
- [ ] 代码风格优化
|
||||
- [ ] 测试用例
|
||||
- [ ] 分支合并
|
||||
- [ ] 工作流程
|
||||
- [ ] 其他改动(是关于什么的改动?)
|
||||
|
||||
### 🔗 相关 Issue
|
||||
|
||||
<!--
|
||||
1. 描述相关需求的来源,如相关的 issue 讨论链接。
|
||||
2. 例如 close #xxxx、 fix #xxxx
|
||||
-->
|
||||
|
||||
### 💡 需求背景和解决方案
|
||||
|
||||
<!--
|
||||
1. 要解决的具体问题。
|
||||
2. 列出最终的 API 实现和用法。
|
||||
3. 涉及UI/交互变动需要有截图或 GIF。
|
||||
-->
|
||||
|
||||
### 📝 更新日志
|
||||
|
||||
<!--
|
||||
从用户角度描述具体变化,以及可能的 breaking change 和其他风险。
|
||||
-->
|
||||
|
||||
| 语言 | 更新描述 |
|
||||
| ------- | -------- |
|
||||
| 🇺🇸 英文 | |
|
||||
| 🇨🇳 中文 | |
|
||||
|
||||
### ☑️ 请求合并前的自查清单
|
||||
|
||||
⚠️ 请自检并全部**勾选全部选项**。⚠️
|
||||
|
||||
- [ ] 文档已补充或无须补充
|
||||
- [ ] 代码演示已提供或无须提供
|
||||
- [ ] TypeScript 定义已补充或无须补充
|
||||
- [ ] Changelog 已提供或无须提供
|
50
.github/PULL_REQUEST_TEMPLATE_CN.md
vendored
Normal file
50
.github/PULL_REQUEST_TEMPLATE_CN.md
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
<!--
|
||||
首先,感谢你的贡献!😄
|
||||
|
||||
新特性请提交至 feature 分支,其余可提交至 master 分支。
|
||||
在维护者审核通过后会合并。
|
||||
请确保填写以下 pull request 的信息,谢谢!~
|
||||
-->
|
||||
|
||||
[English Template / 英文模板](https://github.com/ant-design/ant-design/blob/master/.github/PULL_REQUEST_TEMPLATE.md?plain=1)
|
||||
|
||||
### 🤔 这个变动的性质是?
|
||||
|
||||
- [ ] 🆕 新特性提交
|
||||
- [ ] 🐞 Bug 修复
|
||||
- [ ] 📝 站点、文档改进
|
||||
- [ ] 📽️ 演示代码改进
|
||||
- [ ] 💄 组件样式/交互改进
|
||||
- [ ] 🤖 TypeScript 定义更新
|
||||
- [ ] 📦 包体积优化
|
||||
- [ ] ⚡️ 性能优化
|
||||
- [ ] ⭐️ 功能增强
|
||||
- [ ] 🌐 国际化改进
|
||||
- [ ] 🛠 重构
|
||||
- [ ] 🎨 代码风格优化
|
||||
- [ ] ✅ 测试用例
|
||||
- [ ] 🔀 分支合并
|
||||
- [ ] ⏩ 工作流程
|
||||
- [ ] ❓ 其他改动(是关于什么的改动?)
|
||||
|
||||
### 🔗 相关 Issue
|
||||
|
||||
> 1. 描述相关需求的来源,如相关的 issue 讨论链接。
|
||||
> 2. 例如 close #xxxx、 fix #xxxx
|
||||
|
||||
### 💡 需求背景和解决方案
|
||||
|
||||
> 1. 要解决的具体问题。
|
||||
> 2. 列出最终的 API 实现和用法。
|
||||
> 3. 涉及UI/交互变动建议提供截图或 GIF。
|
||||
|
||||
### 📝 更新日志
|
||||
|
||||
> - 郑重地阅读 [如何维护更新日志](https://keepachangelog.com/zh-CN/1.1.0/)
|
||||
> - 描述改动对开发者有哪些影响,而非解决方式
|
||||
> - 可参考:https://ant.design/changelog-cn
|
||||
|
||||
| 语言 | 更新描述 |
|
||||
| ------- | -------- |
|
||||
| 🇺🇸 英文 | |
|
||||
| 🇨🇳 中文 | |
|
12
.github/workflows/issue-labeled.yml
vendored
12
.github/workflows/issue-labeled.yml
vendored
@ -38,9 +38,9 @@ jobs:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
body: |
|
||||
Hello @${{ github.event.issue.user.login }}. Please provide a online reproduction by forking codesandbox of [antd@5.x](https://u.ant.design/codesandbox-repro) or [antd@4.x](https://u.ant.design/codesandbox-repro-4x), or provide a minimal GitHub repository. Issues labeled by `Need Reproduce` will be closed if no activities in 3 days.
|
||||
Hello @${{ github.event.issue.user.login }}. Please provide a online reproduction by forking [this one](https://u.ant.design/repro) or provide a minimal GitHub repository like [create-react-app-antd](https://github.com/ant-design/create-react-app-antd). Issues labeled by `Need Reproduce` will be closed if no activities in 3 days.
|
||||
|
||||
你好 @${{ github.event.issue.user.login }},我们需要你提供一个在线的重现实例以便于我们帮你排查问题。你可以通过点击这里创建一个 [antd@5.x](https://u.ant.design/codesandbox-repro) 或 [antd@4.x](https://u.ant.design/codesandbox-repro-4x) 的 codesandbox,或者提供一个最小化的 GitHub 仓库。3 天内未跟进此 issue 将会被自动关闭。
|
||||
你好 @${{ github.event.issue.user.login }},我们需要你提供一个在线的重现实例以便于我们帮你排查问题。你可以通过 fork 这个[在线重现案例](https://u.ant.design/repro) ,或者提供一个最小化的 GitHub 仓库(类似 [create-react-app-antd](https://github.com/ant-design/create-react-app-antd))。3 天内未跟进此 issue 将会被自动关闭。
|
||||
|
||||
> [什么是最小化重现,为什么这是必需的?](https://github.com/ant-design/ant-design/wiki/%E4%BB%80%E4%B9%88%E6%98%AF%E6%9C%80%E5%B0%8F%E5%8C%96%E9%87%8D%E7%8E%B0%EF%BC%8C%E4%B8%BA%E4%BB%80%E4%B9%88%E8%BF%99%E6%98%AF%E5%BF%85%E9%9C%80%E7%9A%84%EF%BC%9F)
|
||||
|
||||
@ -58,17 +58,17 @@ jobs:
|
||||
|
||||
你好 @${{ github.event.issue.user.login }},Ant Design Issue 板块是用于 bug 反馈与需求讨论的地方。请[勿询问如何使用的问题](https://github.com/ant-design/ant-design/issues/2320),你可以试着在 [antd discussions](https://github.com/ant-design/ant-design/discussions) 新开一个 discussion,选择 `Q&A` 类别进行提问,也可以在 [Stack Overflow](http://stackoverflow.com/questions/tagged/antd) 或者 [Segment Fault](https://segmentfault.com/t/antd) 中提问(记得添加 `antd` 和 `react` 标签哦~)。
|
||||
|
||||
- name: 3.x
|
||||
if: github.event.label.name == '3.x'
|
||||
- name: 3.x or 4.x
|
||||
if: github.event.label.name == '3.x' || github.event.label.name == '4.x'
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'create-comment,close-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
body: |
|
||||
Hi @${{ github.event.issue.user.login }}. Current version (3.x) is off the maintenance period. We may not accept pull request or fix bug with it anymore. This topic will be auto closed.
|
||||
Hi @${{ github.event.issue.user.login }}. Current version (${{ github.event.label.name }}) is off the maintenance period. We may not accept pull request or fix bug with it anymore. This topic will be auto closed.
|
||||
|
||||
你好 @${{ github.event.issue.user.login }},当前版本(3.x)已经过了维护期。我们不会再接受对其的相关 PR 与 issue。当前 topic 会被自动关闭。
|
||||
你好 @${{ github.event.issue.user.login }},当前版本(${{ github.event.label.name }})已经过了维护期。我们不会再接受对其的相关 PR 与 issue。当前 topic 会被自动关闭。
|
||||
|
||||
- name: invalid
|
||||
if: github.event.label.name == 'Invalid'
|
||||
|
10
.github/workflows/mock-project-build.yml
vendored
10
.github/workflows/mock-project-build.yml
vendored
@ -20,9 +20,7 @@ jobs:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
@ -54,11 +52,15 @@ jobs:
|
||||
|
||||
- name: 🎨 Diff Report
|
||||
if: ${{ failure() }}
|
||||
run: npx diff-yarn-lock --source=~tmpProj/yarn.lock --target=~tmpProj/yarn.lock.failed
|
||||
run: bunx diff-yarn-lock --source=~tmpProj/yarn.lock --target=~tmpProj/yarn.lock.failed
|
||||
|
||||
- uses: actions-cool/ci-notice@v1
|
||||
if: ${{ failure() }}
|
||||
with:
|
||||
notice-types: 'dingding'
|
||||
# Exit directly with non-zero to trigger the failure logic of ci-notice.
|
||||
ci: |
|
||||
echo "❌ CI Mock Project Build Failed"
|
||||
exit 1
|
||||
dingding-token: ${{ secrets.DINGDING_BOT_COLLABORATOR_TOKEN }}
|
||||
notice-title: 'CI Mock Project Build Failed'
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user