mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-11-29 18:50:00 +08:00
Merge pull request #48828 from ant-design/master
chore: sync master into feature
This commit is contained in:
commit
00c770537b
@ -36,12 +36,11 @@ const useStyle = createStyles(({ token, css }) => ({
|
||||
|
||||
export interface ColorPickerProps {
|
||||
id?: string;
|
||||
children?: React.ReactNode;
|
||||
value?: string | Color;
|
||||
onChange?: (value?: Color | string) => void;
|
||||
}
|
||||
|
||||
const DebouncedColorPicker: React.FC<ColorPickerProps> = (props) => {
|
||||
const DebouncedColorPicker: React.FC<React.PropsWithChildren<ColorPickerProps>> = (props) => {
|
||||
const { value: color, children, onChange } = props;
|
||||
const [value, setValue] = useState(color);
|
||||
|
||||
|
@ -3,11 +3,6 @@ import type { ColorInput } from '@ctrl/tinycolor';
|
||||
import { TinyColor } from '@ctrl/tinycolor';
|
||||
import { createStyles } from 'antd-style';
|
||||
|
||||
interface ColorChunkProps {
|
||||
children?: React.ReactNode;
|
||||
value?: ColorInput;
|
||||
}
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => ({
|
||||
codeSpan: css`
|
||||
padding: 0.2em 0.4em;
|
||||
@ -26,7 +21,11 @@ const useStyle = createStyles(({ token, css }) => ({
|
||||
`,
|
||||
}));
|
||||
|
||||
const ColorChunk: React.FC<ColorChunkProps> = (props) => {
|
||||
interface ColorChunkProps {
|
||||
value?: ColorInput;
|
||||
}
|
||||
|
||||
const ColorChunk: React.FC<React.PropsWithChildren<ColorChunkProps>> = (props) => {
|
||||
const { styles } = useStyle();
|
||||
const { value, children } = props;
|
||||
|
||||
|
@ -2,16 +2,20 @@
|
||||
* copied: https://github.com/arvinxx/dumi-theme-antd-style/tree/master/src/builtins/Container
|
||||
*/
|
||||
import * as React from 'react';
|
||||
import type { FC, ReactNode } from 'react';
|
||||
import { Alert } from 'antd';
|
||||
|
||||
import useStyles from './style';
|
||||
|
||||
const Container: FC<{
|
||||
interface ContainerProps {
|
||||
type: 'info' | 'warning' | 'success' | 'error';
|
||||
title?: string;
|
||||
children: ReactNode;
|
||||
}> = ({ type, title, children }) => {
|
||||
}
|
||||
|
||||
const Container: React.FC<React.PropsWithChildren<ContainerProps>> = ({
|
||||
type,
|
||||
title,
|
||||
children,
|
||||
}) => {
|
||||
const { styles, cx } = useStyles();
|
||||
|
||||
return (
|
||||
|
@ -1,10 +1,9 @@
|
||||
import React from 'react';
|
||||
import { Image } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import toArray from 'rc-util/lib/Children/toArray';
|
||||
import { Image } from 'antd';
|
||||
|
||||
interface ImagePreviewProps {
|
||||
children: React.ReactNode[];
|
||||
className?: string;
|
||||
/** Do not show padding & background */
|
||||
pure?: boolean;
|
||||
@ -29,11 +28,22 @@ function isGoodBadImg(imgMeta: any): boolean {
|
||||
function isCompareImg(imgMeta: any): boolean {
|
||||
return isGoodBadImg(imgMeta) || imgMeta.inline;
|
||||
}
|
||||
const ImagePreview: React.FC<ImagePreviewProps> = (props) => {
|
||||
|
||||
interface MateType {
|
||||
className: string;
|
||||
alt: string;
|
||||
description: string;
|
||||
src: string;
|
||||
isGood: boolean;
|
||||
isBad: boolean;
|
||||
inline: boolean;
|
||||
}
|
||||
|
||||
const ImagePreview: React.FC<React.PropsWithChildren<ImagePreviewProps>> = (props) => {
|
||||
const { children, className: rootClassName, pure } = props;
|
||||
const imgs = toArray(children).filter((ele) => ele.type === 'img');
|
||||
|
||||
const imgsMeta = imgs.map((img) => {
|
||||
const imgsMeta = imgs.map<Partial<MateType>>((img) => {
|
||||
const { alt, description, src, className } = img.props;
|
||||
return {
|
||||
className,
|
||||
@ -107,7 +117,7 @@ const ImagePreview: React.FC<ImagePreviewProps> = (props) => {
|
||||
<div className="preview-image-title">{coverMeta.alt}</div>
|
||||
<div
|
||||
className="preview-image-description"
|
||||
dangerouslySetInnerHTML={{ __html: coverMeta.description }}
|
||||
dangerouslySetInnerHTML={{ __html: coverMeta.description ?? '' }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -7,10 +7,13 @@ type LinkProps = Parameters<typeof Link>[0];
|
||||
|
||||
export interface LocaleLinkProps extends LinkProps {
|
||||
sourceType: 'a' | 'Link';
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
const LocaleLink: React.FC<LocaleLinkProps> = ({ sourceType, to, ...props }) => {
|
||||
const LocaleLink: React.FC<React.PropsWithChildren<LocaleLinkProps>> = ({
|
||||
sourceType,
|
||||
to,
|
||||
...props
|
||||
}) => {
|
||||
const Component = sourceType === 'a' ? 'a' : Link;
|
||||
|
||||
const [, localeType] = useLocale();
|
||||
|
@ -1,4 +1,3 @@
|
||||
import type { FC, ReactNode } from 'react';
|
||||
import React, { Suspense } from 'react';
|
||||
import { Skeleton } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
@ -42,13 +41,12 @@ const SandpackFallback = () => {
|
||||
};
|
||||
|
||||
interface SandpackProps {
|
||||
children?: ReactNode;
|
||||
dark?: boolean;
|
||||
autorun?: boolean;
|
||||
dependencies?: string;
|
||||
}
|
||||
|
||||
const Sandpack: FC<SandpackProps> = ({
|
||||
const Sandpack: React.FC<React.PropsWithChildren<SandpackProps>> = ({
|
||||
children,
|
||||
dark,
|
||||
dependencies: extraDeps,
|
||||
|
@ -31,7 +31,7 @@ const useStyle = createStyles(({ token, css }) => ({
|
||||
history: css`
|
||||
position: absolute;
|
||||
top: 0;
|
||||
inset-inline-end: 0;
|
||||
inset-inline-end: ${token.marginXS}px;
|
||||
`,
|
||||
|
||||
li: css`
|
||||
|
@ -5,13 +5,14 @@ import nprogress from 'nprogress';
|
||||
|
||||
export interface LinkProps {
|
||||
to: string | { pathname?: string; search?: string; hash?: string };
|
||||
children?: React.ReactNode;
|
||||
style?: React.CSSProperties;
|
||||
className?: string;
|
||||
onClick?: MouseEventHandler;
|
||||
}
|
||||
|
||||
const Link = forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => {
|
||||
nprogress.configure({ showSpinner: false });
|
||||
|
||||
const Link = forwardRef<HTMLAnchorElement, React.PropsWithChildren<LinkProps>>((props, ref) => {
|
||||
const { to, children, ...rest } = props;
|
||||
const [isPending, startTransition] = useTransition();
|
||||
const navigate = useNavigate();
|
||||
|
@ -204,7 +204,6 @@ const GlobalLayout: React.FC = () => {
|
||||
<StyleProvider
|
||||
cache={styleCache}
|
||||
linters={[legacyNotSelectorLinter, parentSelectorLinter, NaNLinter]}
|
||||
layer
|
||||
>
|
||||
<SiteContext.Provider value={siteContextValue}>
|
||||
<SiteThemeProvider theme={themeConfig}>
|
||||
|
@ -8,7 +8,9 @@ import { useRouteMeta, useTabMeta } from 'dumi';
|
||||
const useStyle = createStyles(({ token, css }) => {
|
||||
const { antCls } = token;
|
||||
return {
|
||||
toc: css`
|
||||
anchorToc: css`
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: unset;
|
||||
${antCls}-anchor {
|
||||
${antCls}-anchor-link-title {
|
||||
font-size: ${token.fontSizeSM}px;
|
||||
@ -120,8 +122,8 @@ const DocAnchor: React.FC<DocAnchorProps> = ({ showDebug, debugDemos = [] }) =>
|
||||
return (
|
||||
<section className={styles.tocWrapper}>
|
||||
<Anchor
|
||||
className={styles.toc}
|
||||
affix={false}
|
||||
className={styles.anchorToc}
|
||||
targetOffset={token.anchorTop}
|
||||
showInkInFixed
|
||||
items={anchorItems.map<AnchorLinkItemProps>(renderAnchorItem)}
|
||||
|
@ -5,10 +5,9 @@ import type { IntersectionObserverProps } from 'react-intersection-observer';
|
||||
|
||||
type InViewSuspenseProps = Pick<IntersectionObserverProps, 'delay'> & {
|
||||
fallback?: React.ReactNode;
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
const InViewSuspense: React.FC<InViewSuspenseProps> = ({
|
||||
const InViewSuspense: React.FC<React.PropsWithChildren<InViewSuspenseProps>> = ({
|
||||
children,
|
||||
fallback = <Skeleton.Input active size="small" />,
|
||||
delay = 200,
|
||||
|
@ -124,7 +124,7 @@ const HeaderNavigation: React.FC<NavigationProps> = (props) => {
|
||||
activeMenuItem = 'docs/resources';
|
||||
}
|
||||
|
||||
let additional: MenuProps['items'];
|
||||
let additional: MenuProps['items'] = [];
|
||||
|
||||
const additionalItems: MenuProps['items'] = [
|
||||
{
|
||||
@ -215,50 +215,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
|
||||
|
@ -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,6 +85,9 @@ 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 {
|
||||
@ -103,12 +106,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 +407,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>
|
||||
|
1
.github/workflows/preview-build.yml
vendored
1
.github/workflows/preview-build.yml
vendored
@ -73,7 +73,6 @@ jobs:
|
||||
id: site
|
||||
run: npm run site
|
||||
env:
|
||||
SITE_ENV: development
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
|
||||
- name: upload site artifact
|
||||
|
4
.github/workflows/size-limit.yml
vendored
4
.github/workflows/size-limit.yml
vendored
@ -17,13 +17,15 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: oven-sh/setup-bun@v1
|
||||
- name: size-limit
|
||||
uses: ant-design/size-limit-action@master
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
package_manager: yarn
|
||||
package_manager: bun
|
||||
build_script: dist
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
PRODUCTION_ONLY: 1
|
||||
NO_DUP_CHECK: 1
|
||||
CI_JOB_NUMBER: 1
|
||||
|
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@ -299,7 +299,7 @@ jobs:
|
||||
lib
|
||||
|
||||
- name: zip builds
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
if: github.repository == 'ant-design/ant-design' && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
env:
|
||||
ALI_OSS_AK_ID: ${{ secrets.ALI_OSS_AK_ID }}
|
||||
ALI_OSS_AK_SECRET: ${{ secrets.ALI_OSS_AK_SECRET }}
|
||||
|
@ -42,17 +42,6 @@
|
||||
[dumi-url]: https://github.com/umijs/dumi
|
||||
[github-issues-url]: https://new-issue.ant.design
|
||||
|
||||
<!-- Copy-paste in your Readme.md file -->
|
||||
|
||||
<a href="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats?repo_id=34526884" target="_blank" style="display: block" align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=dark" width="655" height="auto">
|
||||
<img alt="Performance Stats of ant-design/ant-design - Last 28 days" src="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=light" width="655" height="auto">
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
<!-- Made with [OSS Insight](https://ossinsight.io/) -->
|
||||
|
||||
</div>
|
||||
|
||||
[![](https://user-images.githubusercontent.com/507615/209472919-6f7e8561-be8c-4b0b-9976-eb3c692aa20a.png)](https://ant.design)
|
||||
@ -166,16 +155,36 @@ $ npm start
|
||||
|
||||
## 🤝 参与共建 [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
|
||||
|
||||
<!-- Copy-paste in your Readme.md file -->
|
||||
|
||||
<a href="https://next.ossinsight.io/widgets/official/compose-recent-active-contributors?repo_id=34526884&limit=30" target="_blank" style="display: block" align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-recent-active-contributors/thumbnail.png?repo_id=34526884&limit=30&image_size=auto&color_scheme=dark" width="655" height="auto">
|
||||
<img alt="Active Contributors of ant-design/ant-design - Last 28 days" src="https://next.ossinsight.io/widgets/official/compose-recent-active-contributors/thumbnail.png?repo_id=34526884&limit=30&image_size=auto&color_scheme=light" width="655" height="auto">
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
<!-- Made with [OSS Insight](https://ossinsight.io/) -->
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://next.ossinsight.io/widgets/official/compose-recent-top-contributors?repo_id=34526884" target="_blank" style="display: block" align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-recent-top-contributors/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=dark" width="280">
|
||||
<img alt="Top Contributors of ant-design/ant-design - Last 28 days" src="https://next.ossinsight.io/widgets/official/compose-recent-top-contributors/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=light" width="280">
|
||||
</picture>
|
||||
</a>
|
||||
</td>
|
||||
<td rowspan="2">
|
||||
<a href="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats?repo_id=34526884" target="_blank" style="display: block" align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=dark" width="655" height="auto">
|
||||
<img alt="Performance Stats of ant-design/ant-design - Last 28 days" src="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=light" width="655" height="auto">
|
||||
</picture>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://next.ossinsight.io/widgets/official/compose-org-active-contributors?period=past_28_days&activity=new&owner_id=12101536&repo_ids=34526884" target="_blank" style="display: block" align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?period=past_28_days&activity=new&owner_id=12101536&repo_ids=34526884&image_size=2x3&color_scheme=dark" width="273" height="auto">
|
||||
<img alt="New participants of ant-design - past 28 days" src="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?period=past_28_days&activity=new&owner_id=12101536&repo_ids=34526884&image_size=2x3&color_scheme=light" width="273" height="auto">
|
||||
</picture>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
请参考[贡献指南](https://ant.design/docs/react/contributing-cn).
|
||||
|
||||
|
56
README.md
56
README.md
@ -50,18 +50,6 @@ An enterprise-class UI design language and React UI library.
|
||||
[dumi-image]: https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square
|
||||
[dumi-url]: https://github.com/umijs/dumi
|
||||
[github-issues-url]: https://new-issue.ant.design
|
||||
|
||||
<!-- Copy-paste in your Readme.md file -->
|
||||
|
||||
<a href="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats?repo_id=34526884" target="_blank" style="display: block" align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=dark" width="655" height="auto">
|
||||
<img alt="Performance Stats of ant-design/ant-design - Last 28 days" src="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=light" width="655" height="auto">
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
<!-- Made with [OSS Insight](https://ossinsight.io/) -->
|
||||
|
||||
</div>
|
||||
|
||||
[![](https://user-images.githubusercontent.com/507615/209472919-6f7e8561-be8c-4b0b-9976-eb3c692aa20a.png)](https://ant.design)
|
||||
@ -158,22 +146,42 @@ Open your browser and visit http://127.0.0.1:8001 , see more at [Development](ht
|
||||
|
||||
## 🤝 Contributing [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
|
||||
|
||||
<!-- Copy-paste in your Readme.md file -->
|
||||
|
||||
<a href="https://next.ossinsight.io/widgets/official/compose-recent-active-contributors?repo_id=34526884&limit=30" target="_blank" style="display: block" align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-recent-active-contributors/thumbnail.png?repo_id=34526884&limit=30&image_size=auto&color_scheme=dark" width="655" height="auto">
|
||||
<img alt="Active Contributors of ant-design/ant-design - Last 28 days" src="https://next.ossinsight.io/widgets/official/compose-recent-active-contributors/thumbnail.png?repo_id=34526884&limit=30&image_size=auto&color_scheme=light" width="655" height="auto">
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
<!-- Made with [OSS Insight](https://ossinsight.io/) -->
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://next.ossinsight.io/widgets/official/compose-recent-top-contributors?repo_id=34526884" target="_blank" style="display: block" align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-recent-top-contributors/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=dark" width="280">
|
||||
<img alt="Top Contributors of ant-design/ant-design - Last 28 days" src="https://next.ossinsight.io/widgets/official/compose-recent-top-contributors/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=light" width="280">
|
||||
</picture>
|
||||
</a>
|
||||
</td>
|
||||
<td rowspan="2">
|
||||
<a href="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats?repo_id=34526884" target="_blank" style="display: block" align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=dark" width="655" height="auto">
|
||||
<img alt="Performance Stats of ant-design/ant-design - Last 28 days" src="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=light" width="655" height="auto">
|
||||
</picture>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://next.ossinsight.io/widgets/official/compose-org-active-contributors?period=past_28_days&activity=new&owner_id=12101536&repo_ids=34526884" target="_blank" style="display: block" align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?period=past_28_days&activity=new&owner_id=12101536&repo_ids=34526884&image_size=2x3&color_scheme=dark" width="273" height="auto">
|
||||
<img alt="New participants of ant-design - past 28 days" src="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?period=past_28_days&activity=new&owner_id=12101536&repo_ids=34526884&image_size=2x3&color_scheme=light" width="273" height="auto">
|
||||
</picture>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
Let's build a better antd together.
|
||||
|
||||
We welcome all contributions. Please read our [Contributing Guide](https://ant.design/docs/react/contributing) first. You can submit any ideas as [Pull Requests](https://github.com/ant-design/ant-design/pulls) or as [GitHub Issues](https://github.com/ant-design/ant-design/issues). If you'd like to improve code, check out the [Development Instructions](https://github.com/ant-design/ant-design/wiki/Development) and have a good time! :)
|
||||
We warmly invite contributions from everyone. Before you get started, please take a moment to review our [Contributing Guide](https://ant.design/docs/react/contributing). Feel free to share your ideas through [Pull Requests](https://github.com/ant-design/ant-design/pulls) or [GitHub Issues](https://github.com/ant-design/ant-design/issues). If you're interested in enhancing our codebase, explore the [Development Instructions](https://github.com/ant-design/ant-design/wiki/Development) and enjoy your coding journey! :)
|
||||
|
||||
If you are a collaborator, please follow our [Pull Request Principle](https://github.com/ant-design/ant-design/wiki/PR-principle) to create a Pull Request with our [Pull Request Template](https://github.com/ant-design/ant-design/wiki/PR-principle#pull-request-template).
|
||||
For collaborators, adhere to our [Pull Request Principle](https://github.com/ant-design/ant-design/wiki/PR-principle) and utilize our [Pull Request Template](https://github.com/ant-design/ant-design/wiki/PR-principle#pull-request-template) when creating a Pull Request.
|
||||
|
||||
[![Let's fund issues in this repository](https://raw.githubusercontent.com/BoostIO/issuehunt-materials/master/v1/issuehunt-button-v1.svg)](https://issuehunt.io/repos/34526884)
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { SmileOutlined } from '@ant-design/icons';
|
||||
import type { NotificationConfig } from 'antd/es/notification/interface';
|
||||
import ConfigProvider from 'antd/es/config-provider';
|
||||
|
||||
import App from '..';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
@ -211,6 +212,16 @@ describe('App', () => {
|
||||
});
|
||||
|
||||
describe('component', () => {
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
afterEach(() => {
|
||||
errorSpy.mockReset();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
errorSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('replace', () => {
|
||||
const { container } = render(
|
||||
<App component="section">
|
||||
@ -222,15 +233,25 @@ describe('App', () => {
|
||||
});
|
||||
|
||||
it('to false', () => {
|
||||
const warnSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const { container } = render(
|
||||
<App component={false}>
|
||||
<p />
|
||||
</App>,
|
||||
);
|
||||
expect(warnSpy).not.toHaveBeenCalled();
|
||||
expect(errorSpy).not.toHaveBeenCalled();
|
||||
expect(container.querySelector('.ant-app')).toBeFalsy();
|
||||
warnSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('should warn if component is false and cssVarCls is not empty', () => {
|
||||
render(
|
||||
<ConfigProvider theme={{ cssVar: true }}>
|
||||
<App component={false} />
|
||||
</ConfigProvider>,
|
||||
);
|
||||
|
||||
expect(errorSpy).toHaveBeenCalledWith(
|
||||
'Warning: [antd: App] When using cssVar, ensure `component` is assigned a valid React component string.',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -131,10 +131,16 @@ Common props ref:[Common props](/docs/react/common-props)
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| component | Config render element, if `false` will not create DOM node | ComponentType | div | 5.11.0 |
|
||||
| component | Config render element, if `false` will not create DOM node | ComponentType \| false | div | 5.11.0 |
|
||||
| message | Global config for Message | [MessageConfig](/components/message/#messageconfig) | - | 5.3.0 |
|
||||
| notification | Global config for Notification | [NotificationConfig](/components/notification/#notificationconfig) | - | 5.3.0 |
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="App"></ComponentTokenTable>
|
||||
|
||||
## FAQ
|
||||
|
||||
### CSS Var doesn't work inside `<App component={false}>`
|
||||
|
||||
Make sure the App `component` is a legit React component string, so when you're turning on CSS variables, there's a container to hold the CSS class name.
|
||||
|
@ -3,6 +3,7 @@ import React, { useContext } from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import type { AnyObject, CustomComponent } from '../_util/type';
|
||||
import { devUseWarning } from '../_util/warning';
|
||||
import type { ConfigConsumerProps } from '../config-provider';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import useMessage from '../message/useMessage';
|
||||
@ -64,6 +65,13 @@ const App: React.FC<AppProps> & { useApp: () => useAppProps } = (props) => {
|
||||
[messageApi, notificationApi, ModalApi],
|
||||
);
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/48802#issuecomment-2097813526
|
||||
devUseWarning('App')(
|
||||
!(cssVarCls && component === false),
|
||||
'usage',
|
||||
'When using cssVar, ensure `component` is assigned a valid React component string.',
|
||||
);
|
||||
|
||||
// ============================ Render ============================
|
||||
const Component = component === false ? React.Fragment : component;
|
||||
const rootProps: AppProps = {
|
||||
|
@ -132,10 +132,16 @@ export default () => {
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| component | 设置渲染元素,为 `false` 则不创建 DOM 节点 | ComponentType | div | 5.11.0 |
|
||||
| component | 设置渲染元素,为 `false` 则不创建 DOM 节点 | ComponentType \| false | div | 5.11.0 |
|
||||
| message | App 内 Message 的全局配置 | [MessageConfig](/components/message-cn/#messageconfig) | - | 5.3.0 |
|
||||
| notification | App 内 Notification 的全局配置 | [NotificationConfig](/components/notification-cn/#notificationconfig) | - | 5.3.0 |
|
||||
|
||||
## 主题变量(Design Token)
|
||||
|
||||
<ComponentTokenTable component="App"></ComponentTokenTable>
|
||||
|
||||
## FAQ
|
||||
|
||||
### CSS Var 在 `<App component={false}>` 内不起作用
|
||||
|
||||
请确保 App 的 `component` 是一个有效的 React 组件字符串,以便在启用 CSS 变量时,有一个容器来承载 CSS 类名。
|
||||
|
@ -1532,13 +1532,12 @@ Array [
|
||||
class="ant-radio-group ant-radio-group-outline"
|
||||
>
|
||||
<label
|
||||
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"
|
||||
class="ant-radio-button-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-radio-button ant-radio-button-checked"
|
||||
class="ant-radio-button"
|
||||
>
|
||||
<input
|
||||
checked=""
|
||||
class="ant-radio-button-input"
|
||||
type="radio"
|
||||
value="start"
|
||||
@ -1552,12 +1551,13 @@ Array [
|
||||
</span>
|
||||
</label>
|
||||
<label
|
||||
class="ant-radio-button-wrapper"
|
||||
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"
|
||||
>
|
||||
<span
|
||||
class="ant-radio-button"
|
||||
class="ant-radio-button ant-radio-button-checked"
|
||||
>
|
||||
<input
|
||||
checked=""
|
||||
class="ant-radio-button-input"
|
||||
type="radio"
|
||||
value="end"
|
||||
@ -1648,8 +1648,11 @@ Array [
|
||||
class="ant-btn ant-btn-primary"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Search
|
||||
</span>
|
||||
<span
|
||||
class="ant-btn-icon"
|
||||
class="ant-btn-icon ant-btn-icon-end"
|
||||
>
|
||||
<span
|
||||
aria-label="search"
|
||||
@ -1671,9 +1674,6 @@ Array [
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
Search
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-circle ant-btn-default ant-btn-icon-only"
|
||||
@ -1726,8 +1726,11 @@ Array [
|
||||
class="ant-btn ant-btn-default"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Search
|
||||
</span>
|
||||
<span
|
||||
class="ant-btn-icon"
|
||||
class="ant-btn-icon ant-btn-icon-end"
|
||||
>
|
||||
<span
|
||||
aria-label="search"
|
||||
@ -1749,9 +1752,6 @@ Array [
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
Search
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
@ -1808,8 +1808,11 @@ Array [
|
||||
class="ant-btn ant-btn-text"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Search
|
||||
</span>
|
||||
<span
|
||||
class="ant-btn-icon"
|
||||
class="ant-btn-icon ant-btn-icon-end"
|
||||
>
|
||||
<span
|
||||
aria-label="search"
|
||||
@ -1831,9 +1834,6 @@ Array [
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
Search
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-circle ant-btn-dashed ant-btn-icon-only"
|
||||
@ -1886,8 +1886,11 @@ Array [
|
||||
class="ant-btn ant-btn-dashed"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Search
|
||||
</span>
|
||||
<span
|
||||
class="ant-btn-icon"
|
||||
class="ant-btn-icon ant-btn-icon-end"
|
||||
>
|
||||
<span
|
||||
aria-label="search"
|
||||
@ -1909,9 +1912,6 @@ Array [
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
Search
|
||||
</span>
|
||||
</button>
|
||||
<a
|
||||
class="ant-btn ant-btn-default ant-btn-icon-only"
|
||||
@ -1946,8 +1946,11 @@ Array [
|
||||
class="ant-btn ant-btn-primary ant-btn-loading"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Loading
|
||||
</span>
|
||||
<span
|
||||
class="ant-btn-icon ant-btn-loading-icon"
|
||||
class="ant-btn-icon ant-btn-loading-icon-end"
|
||||
style="width: 0px; opacity: 0; transform: scale(0);"
|
||||
>
|
||||
<span
|
||||
@ -1970,9 +1973,6 @@ Array [
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
Loading
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>,
|
||||
|
@ -1357,13 +1357,12 @@ Array [
|
||||
class="ant-radio-group ant-radio-group-outline"
|
||||
>
|
||||
<label
|
||||
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"
|
||||
class="ant-radio-button-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-radio-button ant-radio-button-checked"
|
||||
class="ant-radio-button"
|
||||
>
|
||||
<input
|
||||
checked=""
|
||||
class="ant-radio-button-input"
|
||||
type="radio"
|
||||
value="start"
|
||||
@ -1377,12 +1376,13 @@ Array [
|
||||
</span>
|
||||
</label>
|
||||
<label
|
||||
class="ant-radio-button-wrapper"
|
||||
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"
|
||||
>
|
||||
<span
|
||||
class="ant-radio-button"
|
||||
class="ant-radio-button ant-radio-button-checked"
|
||||
>
|
||||
<input
|
||||
checked=""
|
||||
class="ant-radio-button-input"
|
||||
type="radio"
|
||||
value="end"
|
||||
@ -1454,8 +1454,11 @@ Array [
|
||||
class="ant-btn ant-btn-primary"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Search
|
||||
</span>
|
||||
<span
|
||||
class="ant-btn-icon"
|
||||
class="ant-btn-icon ant-btn-icon-end"
|
||||
>
|
||||
<span
|
||||
aria-label="search"
|
||||
@ -1477,9 +1480,6 @@ Array [
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
Search
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-circle ant-btn-default ant-btn-icon-only"
|
||||
@ -1513,8 +1513,11 @@ Array [
|
||||
class="ant-btn ant-btn-default"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Search
|
||||
</span>
|
||||
<span
|
||||
class="ant-btn-icon"
|
||||
class="ant-btn-icon ant-btn-icon-end"
|
||||
>
|
||||
<span
|
||||
aria-label="search"
|
||||
@ -1536,9 +1539,6 @@ Array [
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
Search
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
@ -1576,8 +1576,11 @@ Array [
|
||||
class="ant-btn ant-btn-text"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Search
|
||||
</span>
|
||||
<span
|
||||
class="ant-btn-icon"
|
||||
class="ant-btn-icon ant-btn-icon-end"
|
||||
>
|
||||
<span
|
||||
aria-label="search"
|
||||
@ -1599,9 +1602,6 @@ Array [
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
Search
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-circle ant-btn-dashed ant-btn-icon-only"
|
||||
@ -1635,8 +1635,11 @@ Array [
|
||||
class="ant-btn ant-btn-dashed"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Search
|
||||
</span>
|
||||
<span
|
||||
class="ant-btn-icon"
|
||||
class="ant-btn-icon ant-btn-icon-end"
|
||||
>
|
||||
<span
|
||||
aria-label="search"
|
||||
@ -1658,9 +1661,6 @@ Array [
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
Search
|
||||
</span>
|
||||
</button>
|
||||
<a
|
||||
class="ant-btn ant-btn-default ant-btn-icon-only"
|
||||
@ -1695,8 +1695,11 @@ Array [
|
||||
class="ant-btn ant-btn-primary ant-btn-loading"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Loading
|
||||
</span>
|
||||
<span
|
||||
class="ant-btn-icon ant-btn-loading-icon"
|
||||
class="ant-btn-icon ant-btn-loading-icon-end"
|
||||
>
|
||||
<span
|
||||
aria-label="loading"
|
||||
@ -1718,9 +1721,6 @@ Array [
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
Loading
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>,
|
||||
|
@ -88,7 +88,7 @@ describe('Button', () => {
|
||||
});
|
||||
|
||||
it('renders Chinese characters correctly in HOC', () => {
|
||||
const Text = ({ children }: { children: React.ReactNode }) => <span>{children}</span>;
|
||||
const Text: React.FC<React.PropsWithChildren> = ({ children }) => <span>{children}</span>;
|
||||
const { container, rerender } = render(
|
||||
<Button>
|
||||
<Text>按钮</Text>
|
||||
|
@ -258,16 +258,18 @@ const InternalCompoundedButton = React.forwardRef<
|
||||
const kids =
|
||||
children || children === 0 ? spaceChildren(children, needInserted && mergedInsertSpace) : null;
|
||||
|
||||
const genButtonContent = (iconComponent: React.ReactNode, kidsComponent: React.ReactNode) => {
|
||||
const isRTL = direction === 'rtl';
|
||||
const iconFirst = (iconPosition === 'start' && !isRTL) || (iconPosition === 'end' && isRTL);
|
||||
return (
|
||||
const genButtonContent = (iconComponent: React.ReactNode, kidsComponent: React.ReactNode) =>
|
||||
iconPosition === 'start' ? (
|
||||
<>
|
||||
{iconFirst ? iconComponent : kidsComponent}
|
||||
{iconFirst ? kidsComponent : iconComponent}
|
||||
{iconComponent}
|
||||
{kidsComponent}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{kidsComponent}
|
||||
{iconComponent}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
if (linkButtonRestProps.href !== undefined) {
|
||||
return wrapCSSVar(
|
||||
|
@ -3,7 +3,7 @@ import { SearchOutlined } from '@ant-design/icons';
|
||||
import { Button, Divider, Flex, Radio, Space, Tooltip } from 'antd';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [position, setPosition] = useState<'start' | 'end'>('start');
|
||||
const [position, setPosition] = useState<'start' | 'end'>('end');
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -364,7 +364,7 @@ const genCardStyle: GenerateStyle<CardToken> = (token): CSSObject => {
|
||||
},
|
||||
|
||||
[`${componentCls}-contain-tabs`]: {
|
||||
[`> ${componentCls}-head`]: {
|
||||
[`> div${componentCls}-head`]: {
|
||||
minHeight: 0,
|
||||
[`${componentCls}-head-title, ${componentCls}-extra`]: {
|
||||
paddingTop: cardHeadPadding,
|
||||
|
@ -93,7 +93,7 @@ const cascaderOptions = [
|
||||
|
||||
type Placement = 'bottomLeft' | 'bottomRight' | 'topLeft' | 'topRight';
|
||||
|
||||
const Page: React.FC<{ popupPlacement: Placement }> = ({ popupPlacement }) => {
|
||||
const Page: React.FC<{ placement: Placement }> = ({ placement }) => {
|
||||
const [currentStep, setCurrentStep] = useState(0);
|
||||
const [modalOpen, setModalOpen] = useState(false);
|
||||
const [badgeCount, setBadgeCount] = useState(5);
|
||||
@ -169,7 +169,7 @@ const Page: React.FC<{ popupPlacement: Placement }> = ({ popupPlacement }) => {
|
||||
options={cascaderOptions}
|
||||
onChange={onCascaderChange}
|
||||
placeholder="یک مورد انتخاب کنید"
|
||||
popupPlacement={popupPlacement}
|
||||
placement={placement}
|
||||
/>
|
||||
With search:
|
||||
<Cascader
|
||||
@ -177,7 +177,7 @@ const Page: React.FC<{ popupPlacement: Placement }> = ({ popupPlacement }) => {
|
||||
options={cascaderOptions}
|
||||
onChange={onCascaderChange}
|
||||
placeholder="Select an item"
|
||||
popupPlacement={popupPlacement}
|
||||
placement={placement}
|
||||
showSearch={{ filter: cascaderFilter }}
|
||||
/>
|
||||
</Col>
|
||||
@ -495,15 +495,15 @@ const Page: React.FC<{ popupPlacement: Placement }> = ({ popupPlacement }) => {
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [direction, setDirection] = useState<DirectionType>('ltr');
|
||||
const [popupPlacement, setPopupPlacement] = useState<Placement>('bottomLeft');
|
||||
const [placement, setPlacement] = useState<Placement>('bottomLeft');
|
||||
|
||||
const changeDirection = (e: RadioChangeEvent) => {
|
||||
const directionValue = e.target.value;
|
||||
setDirection(directionValue);
|
||||
if (directionValue === 'rtl') {
|
||||
setPopupPlacement('bottomRight');
|
||||
setPlacement('bottomRight');
|
||||
} else {
|
||||
setPopupPlacement('bottomLeft');
|
||||
setPlacement('bottomLeft');
|
||||
}
|
||||
};
|
||||
|
||||
@ -521,7 +521,7 @@ const App: React.FC = () => {
|
||||
</Radio.Group>
|
||||
</div>
|
||||
<ConfigProvider direction={direction}>
|
||||
<Page popupPlacement={popupPlacement} />
|
||||
<Page placement={placement} />
|
||||
</ConfigProvider>
|
||||
</>
|
||||
);
|
||||
|
@ -16,8 +16,6 @@ import type { ConfigProviderProps } from 'antd';
|
||||
|
||||
type SizeType = ConfigProviderProps['componentSize'];
|
||||
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [componentSize, setComponentSize] = useState<SizeType>('small');
|
||||
|
||||
@ -37,17 +35,26 @@ const App: React.FC = () => {
|
||||
<ConfigProvider componentSize={componentSize}>
|
||||
<Space size={[0, 16]} style={{ width: '100%' }} direction="vertical">
|
||||
<Input />
|
||||
<Tabs defaultActiveKey="1">
|
||||
<TabPane tab="Tab 1" key="1">
|
||||
Content of Tab Pane 1
|
||||
</TabPane>
|
||||
<TabPane tab="Tab 2" key="2">
|
||||
Content of Tab Pane 2
|
||||
</TabPane>
|
||||
<TabPane tab="Tab 3" key="3">
|
||||
Content of Tab Pane 3
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
<Tabs
|
||||
defaultActiveKey="1"
|
||||
items={[
|
||||
{
|
||||
label: 'Tab 1',
|
||||
key: '1',
|
||||
children: 'Content of Tab Pane 1',
|
||||
},
|
||||
{
|
||||
label: 'Tab 2',
|
||||
key: '2',
|
||||
children: 'Content of Tab Pane 2',
|
||||
},
|
||||
{
|
||||
label: 'Tab 3',
|
||||
key: '3',
|
||||
children: 'Content of Tab Pane 3',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<Input.Search allowClear />
|
||||
<Input.TextArea allowClear />
|
||||
<Select defaultValue="demo" options={[{ value: 'demo' }]} />
|
||||
|
@ -6,14 +6,16 @@ const MyFormItemContext = React.createContext<(string | number)[]>([]);
|
||||
|
||||
interface MyFormItemGroupProps {
|
||||
prefix: string | number | (string | number)[];
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
function toArr(str: string | number | (string | number)[]): (string | number)[] {
|
||||
return Array.isArray(str) ? str : [str];
|
||||
}
|
||||
|
||||
const MyFormItemGroup = ({ prefix, children }: MyFormItemGroupProps) => {
|
||||
const MyFormItemGroup: React.FC<React.PropsWithChildren<MyFormItemGroupProps>> = ({
|
||||
prefix,
|
||||
children,
|
||||
}) => {
|
||||
const prefixPath = React.useContext(MyFormItemContext);
|
||||
const concatPath = React.useMemo(() => [...prefixPath, ...toArr(prefix)], [prefixPath, prefix]);
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Col, Divider, Row } from 'antd';
|
||||
|
||||
const DemoBox: React.FC<{ children: React.ReactNode; value: number }> = (props) => (
|
||||
const DemoBox: React.FC<React.PropsWithChildren<{ value: number }>> = (props) => (
|
||||
<p className={`height-${props.value}`}>{props.children}</p>
|
||||
);
|
||||
|
||||
|
@ -5,6 +5,7 @@ const App: React.FC = () => (
|
||||
<Image
|
||||
width={200}
|
||||
preview={{
|
||||
destroyOnClose: true,
|
||||
imageRender: () => (
|
||||
<video
|
||||
muted
|
||||
|
@ -68,6 +68,7 @@ Other attributes [<img>](https://developer.mozilla.org/en-US/docs/Web/HTML/El
|
||||
| forceRender | Force render preview dialog | boolean | - | - |
|
||||
| toolbarRender | Custom toolbar render | (originalNode: React.ReactElement, info: Omit<[ToolbarRenderInfoType](#toolbarrenderinfotype), 'current' \| 'total'>) => React.ReactNode | - | 5.7.0 |
|
||||
| imageRender | Custom preview content | (originalNode: React.ReactElement, info: { transform: [TransformType](#transformtype) }) => React.ReactNode | - | 5.7.0 |
|
||||
| destroyOnClose | Destroy child elements when closing preview | boolean | false | |
|
||||
| onTransform | Callback when the transform of image changed | { transform: [TransformType](#transformtype), action: [TransformAction](#transformaction) } | - | 5.7.0 |
|
||||
| onVisibleChange | Callback when `visible` changed | (visible: boolean, prevVisible: boolean) => void | - | - |
|
||||
|
||||
|
@ -69,6 +69,7 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*LVQ3R5JjjJEAAA
|
||||
| forceRender | 强制渲染预览图 | boolean | - | - |
|
||||
| toolbarRender | 自定义工具栏 | (originalNode: React.ReactElement, info: Omit<[ToolbarRenderInfoType](#toolbarrenderinfotype), 'current' \| 'total'>) => React.ReactNode | - | 5.7.0 |
|
||||
| imageRender | 自定义预览内容 | (originalNode: React.ReactElement, info: { transform: [TransformType](#transformtype) }) => React.ReactNode | - | 5.7.0 |
|
||||
| destroyOnClose | 关闭预览时销毁子元素 | boolean | false | |
|
||||
| onTransform | 预览图 transform 变化的回调 | { transform: [TransformType](#transformtype), action: [TransformAction](#transformaction) } | - | 5.7.0 |
|
||||
| onVisibleChange | 当 `visible` 发生改变时的回调 | (visible: boolean, prevVisible: boolean) => void | - | - |
|
||||
|
||||
|
@ -39,7 +39,7 @@ export const OverrideProvider = React.forwardRef<
|
||||
);
|
||||
|
||||
const canRef = supportNodeRef(children);
|
||||
const mergedRef = useComposeRef(ref, canRef ? (children as any).ref : null);
|
||||
const mergedRef = useComposeRef(ref, canRef ? children.ref : null);
|
||||
|
||||
return (
|
||||
<OverrideContext.Provider value={context}>
|
||||
|
@ -31,13 +31,12 @@ const EditableRow: React.FC<EditableRowProps> = ({ index, ...props }) => {
|
||||
interface EditableCellProps {
|
||||
title: React.ReactNode;
|
||||
editable: boolean;
|
||||
children: React.ReactNode;
|
||||
dataIndex: keyof Item;
|
||||
record: Item;
|
||||
handleSave: (record: Item) => void;
|
||||
}
|
||||
|
||||
const EditableCell: React.FC<EditableCellProps> = ({
|
||||
const EditableCell: React.FC<React.PropsWithChildren<EditableCellProps>> = ({
|
||||
title,
|
||||
editable,
|
||||
children,
|
||||
|
@ -25,10 +25,9 @@ interface EditableCellProps extends React.HTMLAttributes<HTMLElement> {
|
||||
inputType: 'number' | 'text';
|
||||
record: Item;
|
||||
index: number;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
const EditableCell: React.FC<EditableCellProps> = ({
|
||||
const EditableCell: React.FC<React.PropsWithChildren<EditableCellProps>> = ({
|
||||
editing,
|
||||
dataIndex,
|
||||
title,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Button, Checkbox, Input, InputNumber, Select, Space, Tooltip } from 'antd';
|
||||
|
||||
const WrapperTooltip: React.FC<{ children?: React.ReactNode }> = (props) => (
|
||||
const WrapperTooltip: React.FC<React.PropsWithChildren> = (props) => (
|
||||
<Tooltip title="Thanks for using antd. Have a nice day!" {...props} />
|
||||
);
|
||||
|
||||
|
@ -116,9 +116,7 @@ describe('Watermark', () => {
|
||||
|
||||
const watermark = getWatermarkElement();
|
||||
|
||||
expect(watermark).toHaveStyle({
|
||||
zIndex: '9',
|
||||
});
|
||||
expect(watermark).toHaveStyle({ zIndex: '9' });
|
||||
|
||||
// Not crash when children removed
|
||||
rerender(<Watermark className="test" />);
|
||||
|
@ -80,7 +80,7 @@ const useButtonStyle = () => {
|
||||
}))();
|
||||
};
|
||||
|
||||
function GeekProvider(props: { children?: React.ReactNode }) {
|
||||
function GeekProvider(props: React.PropsWithChildren) {
|
||||
const { styles } = useButtonStyle();
|
||||
|
||||
return <ConfigProvider button={{ className: styles.btn }}>{props.children}</ConfigProvider>;
|
||||
@ -92,7 +92,7 @@ function GeekProvider(props: { children?: React.ReactNode }) {
|
||||
It's also easy to extend for scenarios that need to inherit `className`:
|
||||
|
||||
```tsx
|
||||
function GeekProvider(props: { children?: React.ReactNode }) {
|
||||
function GeekProvider(props: React.PropsWithChildren) {
|
||||
const { button } = React.useContext(ConfigProvider.ConfigContext);
|
||||
const { styles } = useButtonStyle();
|
||||
|
||||
|
@ -138,7 +138,7 @@ useLayoutEffect(() => {
|
||||
|
||||
### Resolution
|
||||
|
||||
Due to the above queue operation, the DOM of the portal will be triggered in the next `useLayoutEffect` under nesting. This causes the `uesLayoutEffect` timing of the animation to start in `rc-dialog` after the node behavior is added, resulting in the element not being in the document and unable to obtain the correct coordinate information.
|
||||
Due to the above queue operation, the DOM of the portal will be triggered in the next `useLayoutEffect` under nesting. This causes the `useLayoutEffect` timing of the animation to start in `rc-dialog` after the node behavior is added, resulting in the element not being in the document and unable to obtain the correct coordinate information.
|
||||
|
||||
Since Modal is already enabled, it does not need to be executed asynchronously through `queue`, so we only need to add a judgment if it is enabled, and execute `append` directly:
|
||||
|
||||
|
@ -138,7 +138,7 @@ useLayoutEffect(() => {
|
||||
|
||||
### 问题分析
|
||||
|
||||
由于上述的队列操作,使得 portal 的 DOM 在嵌套下会在下一个 `useLayoutEffect` 触发。这导致添加节点行为后于 `rc-dialog` 启动动画的 `uesLayoutEffect` 时机,导致元素不在 document 中而无法获取正确的坐标信息。
|
||||
由于上述的队列操作,使得 portal 的 DOM 在嵌套下会在下一个 `useLayoutEffect` 触发。这导致添加节点行为后于 `rc-dialog` 启动动画的 `useLayoutEffect` 时机,导致元素不在 document 中而无法获取正确的坐标信息。
|
||||
|
||||
由于 Modal 已经是开启状态,其实不需要通过 `queue` 异步执行,所以我们只需要加一个判断如果是开启状态,直接执行 `append` 即可:
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
group:
|
||||
title: Basic Usage
|
||||
order: 2
|
||||
order: 3
|
||||
title: Usage with Next.js
|
||||
tag: Updated
|
||||
---
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
group:
|
||||
title: 如何使用
|
||||
order: 2
|
||||
order: 3
|
||||
title: 在 Next.js 中使用
|
||||
tag: Updated
|
||||
---
|
||||
|
70
docs/react/use-with-rsbuild.en-US.md
Normal file
70
docs/react/use-with-rsbuild.en-US.md
Normal file
@ -0,0 +1,70 @@
|
||||
---
|
||||
group:
|
||||
title: Basic Usage
|
||||
order: 5
|
||||
title: Usage with Rsbuild
|
||||
tag: New
|
||||
---
|
||||
|
||||
[Rsbuild](https://rsbuild.dev) is a build tool driven by Rspack. This article will try to use `Rsbuild` to create a project and import antd.
|
||||
|
||||
## Install and Initialization
|
||||
|
||||
Before all start, you may need install [yarn](https://github.com/yarnpkg/yarn) or [pnpm](https://pnpm.io) or [bun](https://bun.sh).
|
||||
|
||||
<InstallDependencies npm='$ npm create rsbuild' yarn='$ yarn create rsbuild' pnpm='$ pnpm create rsbuild' bun='$ bun create rsbuild'></InstallDependencies>
|
||||
|
||||
During the initialization process, `create-rsbuild` provides a series of templates for us to choose, We need choose the `React` template.
|
||||
|
||||
The tool will create and initialize environment and dependencies automatically, please try config your proxy setting or use another npm registry if any network errors happen during it.
|
||||
|
||||
Then we go inside project and start it.
|
||||
|
||||
```bash
|
||||
$ cd demo
|
||||
$ npm run dev
|
||||
```
|
||||
|
||||
Open the browser at http://localhost:3000. It renders a title saying `Rsbuild with React` on the page, which is considered successful.
|
||||
|
||||
## Import antd
|
||||
|
||||
Now we install `antd` from yarn or npm or pnpm or bun.
|
||||
|
||||
<InstallDependencies npm='$ npm install antd --save' yarn='$ yarn add antd' pnpm='$ pnpm install antd --save' bun='$ bun add antd'></InstallDependencies>
|
||||
|
||||
Modify `src/App.tsx`, import Button component from `antd`.
|
||||
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import { Button } from 'antd';
|
||||
|
||||
const App: React.FC = () => (
|
||||
<div className="App">
|
||||
<Button type="primary">Button</Button>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default App;
|
||||
```
|
||||
|
||||
OK, you should now see a blue primary button displayed on the page. Next you can choose any components of `antd` to develop your application. Visit other workflows of `Rsbuild` at its [Official documentation](https://rsbuild.dev).
|
||||
|
||||
### Customize Theme
|
||||
|
||||
Ref to the [Customize Theme documentation](/docs/react/customize-theme). Modify theme with ConfigProvider:
|
||||
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import { ConfigProvider } from 'antd';
|
||||
|
||||
const App: React.FC = () => (
|
||||
<ConfigProvider theme={{ token: { colorPrimary: '#00b96b' } }}>
|
||||
<MyApp />
|
||||
</ConfigProvider>
|
||||
);
|
||||
|
||||
export default App;
|
||||
```
|
||||
|
||||
We are successfully running the antd components using Rsbuild now, let’s start build your own application!
|
70
docs/react/use-with-rsbuild.zh-CN.md
Normal file
70
docs/react/use-with-rsbuild.zh-CN.md
Normal file
@ -0,0 +1,70 @@
|
||||
---
|
||||
group:
|
||||
title: 如何使用
|
||||
order: 5
|
||||
title: 在 Rsbuild 中使用
|
||||
tag: New
|
||||
---
|
||||
|
||||
[Rsbuild](https://rsbuild.dev/zh) 由 Rspack 驱动的构建工具,本文会尝试使用 `Rsbuild` 创建一个项目,并引入 antd。
|
||||
|
||||
## 安装和初始化
|
||||
|
||||
在开始之前,你可能需要安装 [yarn](https://github.com/yarnpkg/yarn) 或者 [pnpm](https://pnpm.io/zh) 或者 [bun](https://bun.sh)。
|
||||
|
||||
<InstallDependencies npm='$ npm create rsbuild' yarn='$ yarn create rsbuild' pnpm='$ pnpm create rsbuild' bun='$ bun create rsbuild'></InstallDependencies>
|
||||
|
||||
在初始化的过程中,`create-rsbuild` 提供了一系列模板供我们选择,这里我们选择 `React` 模板。
|
||||
|
||||
工具会自动初始化一个脚手架并安装 React 项目的各种必要依赖,如果在过程中出现网络问题,请尝试配置代理或使用其他 npm registry。
|
||||
|
||||
然后我们进入项目并启动。
|
||||
|
||||
```bash
|
||||
$ cd demo
|
||||
$ npm run dev
|
||||
```
|
||||
|
||||
此时访问浏览器 http://localhost:3000,看到 `Rsbuild with React` 的界面就算成功了。
|
||||
|
||||
## 引入 antd
|
||||
|
||||
现在从 yarn 或 npm 或 pnpm 或 bun 安装并引入 antd。
|
||||
|
||||
<InstallDependencies npm='$ npm install antd --save' yarn='$ yarn add antd' pnpm='$ pnpm install antd --save' bun='$ bun add antd'></InstallDependencies>
|
||||
|
||||
修改 `src/App.tsx`,引入 antd 的 Button 组件。
|
||||
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import { Button } from 'antd';
|
||||
|
||||
const App: React.FC = () => (
|
||||
<div className="App">
|
||||
<Button type="primary">Button</Button>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default App;
|
||||
```
|
||||
|
||||
好了,现在你应该能看到页面上已经有了 antd 的蓝色按钮组件,接下来就可以继续选用其他组件开发应用了。其它开发流程你可以参考 Rsbuild 的[官方文档](https://rsbuild.dev/zh)。
|
||||
|
||||
### 自定义主题
|
||||
|
||||
参考 [配置主题](/docs/react/customize-theme),通过 ConfigProvider 进行主题配置:
|
||||
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import { ConfigProvider } from 'antd';
|
||||
|
||||
const App: React.FC = () => (
|
||||
<ConfigProvider theme={{ token: { colorPrimary: '#00b96b' } }}>
|
||||
<MyApp />
|
||||
</ConfigProvider>
|
||||
);
|
||||
|
||||
export default App;
|
||||
```
|
||||
|
||||
我们现在已经把 antd 组件成功使用 Rsbuild 运行起来了,开始开发你的应用吧!
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
group:
|
||||
title: Basic Usage
|
||||
order: 2
|
||||
order: 4
|
||||
title: Usage with Umi
|
||||
---
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
group:
|
||||
title: 如何使用
|
||||
order: 2
|
||||
order: 4
|
||||
title: 在 Umi 中使用
|
||||
---
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
group:
|
||||
title: Basic Usage
|
||||
order: 3
|
||||
order: 2
|
||||
title: Usage with Vite
|
||||
---
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
group:
|
||||
title: 如何使用
|
||||
order: 3
|
||||
order: 2
|
||||
title: 在 Vite 中使用
|
||||
---
|
||||
|
||||
|
10
package.json
10
package.json
@ -118,7 +118,7 @@
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "^7.0.2",
|
||||
"@ant-design/cssinjs": "^1.19.1",
|
||||
"@ant-design/icons": "^5.3.6",
|
||||
"@ant-design/icons": "^5.3.7",
|
||||
"@ant-design/react-slick": "~1.1.2",
|
||||
"@babel/runtime": "^7.24.5",
|
||||
"@ctrl/tinycolor": "^3.6.1",
|
||||
@ -150,7 +150,7 @@
|
||||
"rc-rate": "~2.12.0",
|
||||
"rc-resize-observer": "^1.4.0",
|
||||
"rc-segmented": "~2.3.0",
|
||||
"rc-select": "~14.13.1",
|
||||
"rc-select": "~14.13.2",
|
||||
"rc-slider": "~10.6.2",
|
||||
"rc-steps": "~6.0.1",
|
||||
"rc-switch": "~4.1.0",
|
||||
@ -158,10 +158,10 @@
|
||||
"rc-tabs": "~15.0.0 ",
|
||||
"rc-textarea": "~1.6.3",
|
||||
"rc-tooltip": "~6.2.0",
|
||||
"rc-tree": "~5.8.5",
|
||||
"rc-tree": "~5.8.7",
|
||||
"rc-tree-select": "~5.20.0",
|
||||
"rc-upload": "~4.5.2",
|
||||
"rc-util": "^5.39.1",
|
||||
"rc-util": "^5.39.3",
|
||||
"scroll-into-view-if-needed": "^3.1.0",
|
||||
"throttle-debounce": "^5.0.0"
|
||||
},
|
||||
@ -253,7 +253,7 @@
|
||||
"eslint-plugin-jest": "^28.3.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.8.0",
|
||||
"eslint-plugin-lodash": "^7.4.0",
|
||||
"eslint-plugin-markdown": "^4.0.1",
|
||||
"eslint-plugin-markdown": "^5.0.0",
|
||||
"eslint-plugin-react": "^7.34.1",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"eslint-plugin-unicorn": "^52.0.0",
|
||||
|
@ -5,11 +5,7 @@ import { TriggerMockContext } from '../../../shared/demoTestContext';
|
||||
let OriginPortal = jest.requireActual('rc-util/lib/Portal');
|
||||
OriginPortal = OriginPortal.default ?? OriginPortal;
|
||||
|
||||
interface MockPortalProps {
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
class MockPortal extends React.Component<MockPortalProps> {
|
||||
class MockPortal extends React.Component<React.PropsWithChildren> {
|
||||
container: boolean | undefined;
|
||||
|
||||
static contextType = TriggerMockContext;
|
||||
@ -32,7 +28,7 @@ class MockPortal extends React.Component<MockPortalProps> {
|
||||
}
|
||||
}
|
||||
|
||||
const CustomPortal = React.forwardRef<PortalRef, PortalProps | MockPortalProps>((props, ref) => {
|
||||
const CustomPortal = React.forwardRef<PortalRef, PortalProps | React.PropsWithChildren>((props, ref) => {
|
||||
const context = React.useContext(TriggerMockContext);
|
||||
if (context?.mock === false) {
|
||||
return <OriginPortal {...props} ref={ref} />;
|
||||
|
Loading…
Reference in New Issue
Block a user