mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-27 12:39:49 +08:00
Merge branch master into master-merge-feature
This commit is contained in:
commit
de2dde6613
@ -9,6 +9,6 @@ export default function useLocale<Key extends string>(
|
||||
localeMap?: LocaleMap<Key>,
|
||||
): [Record<Key, string>, 'cn' | 'en'] {
|
||||
const { id } = useDumiLocale();
|
||||
const localeType = id === 'zh-CN' ? 'cn' : ('en' as const);
|
||||
return [localeMap?.[localeType]!, localeType];
|
||||
const localeType = id === 'zh-CN' ? 'cn' : 'en';
|
||||
return [localeMap?.[localeType], localeType];
|
||||
}
|
||||
|
@ -40,20 +40,40 @@ function SubTokenTable({ defaultOpen, tokens, title }: SubTokenTableProps) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const data = tokens.map((name) => {
|
||||
const meta = tokenMeta[name];
|
||||
const data = tokens
|
||||
.sort((token1, token2) => {
|
||||
const hasColor1 = token1.toLowerCase().includes('color');
|
||||
const hasColor2 = token2.toLowerCase().includes('color');
|
||||
|
||||
return {
|
||||
name,
|
||||
desc: lang === 'cn' ? meta.desc : meta.descEn,
|
||||
type: meta.type,
|
||||
value: (defaultToken as any)[name],
|
||||
};
|
||||
});
|
||||
if (hasColor1 && !hasColor2) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!hasColor1 && hasColor2) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return token1 < token2 ? -1 : 1;
|
||||
})
|
||||
.map((name) => {
|
||||
const meta = tokenMeta[name];
|
||||
|
||||
if (!meta) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
name,
|
||||
desc: lang === 'cn' ? meta.desc : meta.descEn,
|
||||
type: meta.type,
|
||||
value: (defaultToken as any)[name],
|
||||
};
|
||||
})
|
||||
.filter((info) => info);
|
||||
|
||||
return (
|
||||
// Reuse `.markdown` style
|
||||
<details className="markdown" open={defaultOpen}>
|
||||
<details className="markdown" open={defaultOpen || process.env.NODE_ENV !== 'production'}>
|
||||
<summary>
|
||||
<h3 style={{ display: 'inline' }}>{title}</h3>
|
||||
</summary>
|
||||
@ -82,12 +102,32 @@ export interface ComponentTokenTableProps {
|
||||
}
|
||||
|
||||
function ComponentTokenTable({ component }: ComponentTokenTableProps) {
|
||||
const { global: globalTokens = [], component: componentTokens = [] } = tokenData[component] || {};
|
||||
const [mergedGlobalTokens] = React.useMemo(() => {
|
||||
const globalTokenSet = new Set<string>();
|
||||
let componentTokens: Record<string, string> = {};
|
||||
|
||||
component.split(',').forEach((comp) => {
|
||||
const { global: globalTokens = [], component: singleComponentTokens = [] } =
|
||||
tokenData[comp] || {};
|
||||
|
||||
globalTokens.forEach((token: string) => {
|
||||
globalTokenSet.add(token);
|
||||
});
|
||||
|
||||
componentTokens = {
|
||||
...componentTokens,
|
||||
...singleComponentTokens,
|
||||
};
|
||||
});
|
||||
|
||||
return [Array.from(globalTokenSet), componentTokens];
|
||||
}, [component]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SubTokenTable title="Component Token" tokens={componentTokens} defaultOpen />
|
||||
<SubTokenTable title="Global Token" tokens={globalTokens} />
|
||||
{/* Component Token 先不展示 */}
|
||||
{/* <SubTokenTable title="Component Token" tokens={mergedComponentTokens} defaultOpen /> */}
|
||||
<SubTokenTable title="Global Token" tokens={mergedGlobalTokens} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ const CodePreviewer: React.FC<IPreviewerProps> = (props) => {
|
||||
style,
|
||||
compact,
|
||||
background,
|
||||
filePath,
|
||||
filename,
|
||||
version,
|
||||
clientOnly,
|
||||
} = props;
|
||||
@ -333,10 +333,10 @@ createRoot(document.getElementById('container')).render(<Demo />);
|
||||
...dependencies,
|
||||
react: '^18.0.0',
|
||||
'react-dom': '^18.0.0',
|
||||
'react-scripts': '^4.0.0',
|
||||
'react-scripts': '^5.0.0',
|
||||
},
|
||||
devDependencies: {
|
||||
typescript: '^4.0.5',
|
||||
typescript: '^5.0.2',
|
||||
},
|
||||
scripts: {
|
||||
start: 'react-scripts start',
|
||||
@ -399,7 +399,7 @@ createRoot(document.getElementById('container')).render(<Demo />);
|
||||
{localizedTitle}
|
||||
</a>
|
||||
</Tooltip>
|
||||
<EditButton title={<FormattedMessage id="app.content.edit-demo" />} filename={filePath} />
|
||||
<EditButton title={<FormattedMessage id="app.content.edit-demo" />} filename={filename} />
|
||||
</div>
|
||||
<div className="code-box-description">{introChildren}</div>
|
||||
<Space wrap size="middle" className="code-box-actions">
|
||||
|
@ -38,7 +38,6 @@ const GlobalDemoStyles: React.FC = () => {
|
||||
}
|
||||
|
||||
.code-box-demo {
|
||||
overflow: auto;
|
||||
background-color: ${token.colorBgContainer};
|
||||
border-radius: ${token.borderRadius}px ${token.borderRadius}px 0 0;
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ const useStyle = () => {
|
||||
border-bottom: none;
|
||||
|
||||
& > ${antCls}-menu-item, & > ${antCls}-menu-submenu {
|
||||
min-width: (40px + 12px * 2);
|
||||
min-width: ${40 + 12 * 2}px;
|
||||
height: ${headerHeight}px;
|
||||
padding-right: 12px;
|
||||
padding-left: 12px;
|
||||
|
@ -209,7 +209,11 @@ const Header: React.FC = () => {
|
||||
.replace(/\/$/, '');
|
||||
return;
|
||||
}
|
||||
window.location.href = currentUrl.replace(window.location.origin, url);
|
||||
|
||||
// Mirror url must have `/`, we add this for compatible
|
||||
const urlObj = new URL(currentUrl.replace(window.location.origin, url));
|
||||
urlObj.pathname = `${urlObj.pathname.replace(/\/$/, '')}/`;
|
||||
window.location.href = urlObj.href;
|
||||
}, []);
|
||||
|
||||
const onLangChange = useCallback(() => {
|
||||
|
1
.github/workflows/chatgpt-cr.yml
vendored
1
.github/workflows/chatgpt-cr.yml
vendored
@ -11,6 +11,7 @@ on:
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.pull_request.head.ref != 'feature' && github.event.pull_request.head.ref != 'master' && github.event.pull_request.head.ref != 'next' && github.event.pull_request.head.ref != 'master-merge-feature' && github.event.pull_request.head.ref != 'feature-merge-master' && github.event.pull_request.head.ref != 'next-merge-master' && github.event.pull_request.head.ref != 'next-merge-feature'
|
||||
steps:
|
||||
- uses: anc95/ChatGPT-CodeReview@main
|
||||
env:
|
||||
|
22
.github/workflows/issues-similarity-analysis.yml
vendored
22
.github/workflows/issues-similarity-analysis.yml
vendored
@ -1,22 +0,0 @@
|
||||
name: Issues Similarity Analysis
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, edited]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
similarity-analysis:
|
||||
permissions:
|
||||
issues: write # for actions-cool/issues-similarity-analysis to create issue comments
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: analysis
|
||||
uses: actions-cool/issues-similarity-analysis@v1
|
||||
with:
|
||||
filter-threshold: 0.5
|
||||
title-excludes: ''
|
||||
comment-title: '### You may look for issues:'
|
||||
comment-body: '${index}. ${similarity} #${number}'
|
@ -15,6 +15,31 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
## 5.3.3
|
||||
|
||||
`2023-3-28`
|
||||
|
||||
- Menu
|
||||
- 🐞 Fix Menu `items` not accept `key` issue. [#41434](https://github.com/ant-design/ant-design/pull/41434) [@Yuiai01](https://github.com/Yuiai01)
|
||||
- 🐞 Fix submenu themes being overwritten when using `getPopupContainer` to select the main Menu. [#41465](https://github.com/ant-design/ant-design/pull/41465) [@Yuiai01](https://github.com/Yuiai01)
|
||||
- 🐞 Fix Table filter do not persist filter status when filter dropdown is visible. [#41445](https://github.com/ant-design/ant-design/pull/41445) [@ablakey](https://github.com/ablakey)
|
||||
- 🐞 Fix Modal using `useModal` is not transparent and prefers user settings. [#41422](https://github.com/ant-design/ant-design/pull/41422) [@luo3house](https://github.com/luo3house)
|
||||
- Form
|
||||
- 🐞 Fix the problem that the Form validation state does not change in sequence. [#41412](https://github.com/ant-design/ant-design/pull/41412) [@kiner-tang](https://github.com/kiner-tang)
|
||||
- 💄 Fix Form component layout exceptions when set props `layout="inline"`. [#41140](https://github.com/ant-design/ant-design/pull/41140) [@itkui](https://github.com/itkui)
|
||||
- 💄 Fix ConfigProvider `nonce` not working on CSS-in-JS style. [#41482](https://github.com/ant-design/ant-design/pull/41482)
|
||||
- 💄 Fix Pagination when `size=small`, pagination button active, previous page next page button hover and active styles are lost. [#41462](https://github.com/ant-design/ant-design/pull/41462) [#41458](https://github.com/ant-design/ant-design/pull/41458)
|
||||
- 💄 Fix the style problem that the bottom border of the Tabs component overlaps with other borders. [#41381](https://github.com/ant-design/ant-design/pull/41381)
|
||||
- 💄 Fix Dropdown.Button down icon size issue. [#41501](https://github.com/ant-design/ant-design/pull/41501)
|
||||
- TypeScript
|
||||
- 🐞 Fix the incorrect type definition of Breadcrumb.Item `menu`. [#41373](https://github.com/ant-design/ant-design/pull/41373)
|
||||
- 🤖 Optimize Grid Col type. [#41453](https://github.com/ant-design/ant-design/pull/41453) [@vaakian](https://github.com/vaakian)
|
||||
- 🤖 Optimize Table `resetPagination` type. [#41415](https://github.com/ant-design/ant-design/pull/41415)
|
||||
- 🤖 Optimize TreeSelect `InternalTreeSelect` type. [#41386](https://github.com/ant-design/ant-design/pull/41386) [@Andarist](https://github.com/Andarist)
|
||||
- Locales
|
||||
- 🇮🇷 Improve DatePicker `fa_IR` translation. [#41455](https://github.com/ant-design/ant-design/pull/41455) [@ds1371dani](https://github.com/ds1371dani)
|
||||
- 🇸🇪 Add the missing content of `sv_SE` language. [#41424](https://github.com/ant-design/ant-design/pull/41424) [@dhalenok](https://github.com/dhalenok)
|
||||
|
||||
## 5.3.2
|
||||
|
||||
`2023-03-20`
|
||||
|
@ -15,6 +15,31 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
## 5.3.3
|
||||
|
||||
`2023-3-28`
|
||||
|
||||
- Menu
|
||||
- 🐞 修复 Menu `items` 没有使用传入的 `key` 的问题。[#41434](https://github.com/ant-design/ant-design/pull/41434) [@Yuiai01](https://github.com/Yuiai01)
|
||||
- 🐞 修复 Menu 使用 `getPopupContainer` 选择主菜单时子菜单主题被覆盖。[#41465](https://github.com/ant-design/ant-design/pull/41465) [@Yuiai01](https://github.com/Yuiai01)
|
||||
- 🐞 修复 Table 过滤器未保持状态当筛选下拉框展示时。[#41445](https://github.com/ant-design/ant-design/pull/41445) [@ablakey](https://github.com/ablakey)
|
||||
- 🐞 修复 Modal 使用 `useModal` 未透传并优先选择用户设定。[#41422](https://github.com/ant-design/ant-design/pull/41422) [@luo3house](https://github.com/luo3house)
|
||||
- Form
|
||||
- 🐞 修复 Form 验证状态不按照顺序改变的问题。[#41412](https://github.com/ant-design/ant-design/pull/41412) [@kiner-tang](https://github.com/kiner-tang)
|
||||
- 💄 修复 Form 组件 `layout="inline"` 时组件标题与表单项布局异常换行问题。[#41140](https://github.com/ant-design/ant-design/pull/41140) [@itkui](https://github.com/itkui)
|
||||
- 💄 修复 ConfigProvider `nonce` 对 CSS-in-JS 样式不生效的问题。[#41482](https://github.com/ant-design/ant-design/pull/41482)
|
||||
- 💄 修复 Pagination `size=small` 时,分页按钮 active、上一页下一页按钮 hover 和 active 样式丢失。[#41462](https://github.com/ant-design/ant-design/pull/41462) [#41458](https://github.com/ant-design/ant-design/pull/41458)
|
||||
- 💄 修复 Tabs 组件下边框与其他边框叠加的样式问题。[#41381](https://github.com/ant-design/ant-design/pull/41381)
|
||||
- 💄 修复 Dropdown.Button down 图标尺寸问题。[#41501](https://github.com/ant-design/ant-design/pull/41501)
|
||||
- TypeScript
|
||||
- 🐞 修复 Breadcrumb.Item `menu` 类型定义不正确的问题。[#41373](https://github.com/ant-design/ant-design/pull/41373)
|
||||
- 🤖 优化 Grid Col 类型提示。[#41453](https://github.com/ant-design/ant-design/pull/41453) [@vaakian](https://github.com/vaakian)
|
||||
- 🤖 优化 Table `resetPagination` 类型提示。[#41415](https://github.com/ant-design/ant-design/pull/41415)
|
||||
- 🤖 优化 TreeSelect `InternalTreeSelect` 类型提示。[#41386](https://github.com/ant-design/ant-design/pull/41386) [@Andarist](https://github.com/Andarist)
|
||||
- 国际化
|
||||
- 🇮🇷 完善 DatePicker `fa_IR` 翻译。[#41455](https://github.com/ant-design/ant-design/pull/41455) [@ds1371dani](https://github.com/ds1371dani)
|
||||
- 🇸🇪 完善 `sv_SE` 语言缺失内容。[#41424](https://github.com/ant-design/ant-design/pull/41424) [@dhalenok](https://github.com/dhalenok)
|
||||
|
||||
## 5.3.2
|
||||
|
||||
`2023-03-20`
|
||||
|
@ -68,3 +68,7 @@ We recommend using the items form instead.
|
||||
| href | The target of hyperlink | string | | |
|
||||
| target | Specifies where to display the linked URL | string | | |
|
||||
| title | The content of hyperlink | ReactNode | | |
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Anchor"></ComponentTokenTable>
|
||||
|
@ -69,3 +69,7 @@ group:
|
||||
| href | 锚点链接 | string | - | |
|
||||
| target | 该属性指定在何处显示链接的资源 | string | - | |
|
||||
| title | 文字内容 | ReactNode | - | |
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Anchor"></ComponentTokenTable>
|
||||
|
@ -1,8 +1,8 @@
|
||||
import type { CSSObject } from '@ant-design/cssinjs';
|
||||
import { Keyframes } from '@ant-design/cssinjs';
|
||||
import type { FullToken, GenerateStyle } from '../../theme/internal';
|
||||
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
|
||||
import { genPresetColor, resetComponent } from '../../style';
|
||||
import { genComponentStyleHook, mergeToken, genPresetColor } from '../../theme/internal';
|
||||
import { resetComponent } from '../../style';
|
||||
|
||||
interface BadgeToken extends FullToken<'Badge'> {
|
||||
badgeFontHeight: number;
|
||||
|
@ -1,9 +1,9 @@
|
||||
import DownOutlined from '@ant-design/icons/DownOutlined';
|
||||
import * as React from 'react';
|
||||
import warning from '../_util/warning';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import type { DropdownProps } from '../dropdown/dropdown';
|
||||
import Dropdown from '../dropdown/dropdown';
|
||||
import warning from '../_util/warning';
|
||||
import BreadcrumbSeparator from './BreadcrumbSeparator';
|
||||
|
||||
export interface SeparatorType {
|
||||
@ -11,8 +11,9 @@ export interface SeparatorType {
|
||||
key?: React.Key;
|
||||
}
|
||||
|
||||
type MenuType = DropdownProps['menu'];
|
||||
type MenuType = NonNullable<DropdownProps['menu']>;
|
||||
interface MenuItem {
|
||||
key?: React.Key;
|
||||
title?: React.ReactNode;
|
||||
label?: React.ReactNode;
|
||||
path?: string;
|
||||
@ -68,10 +69,10 @@ const BreadcrumbItem: CompoundedComponent = (props: BreadcrumbItemProps) => {
|
||||
};
|
||||
|
||||
if (menu) {
|
||||
const { items, ...menuProps } = menu! || {};
|
||||
const { items, ...menuProps } = menu || {};
|
||||
mergeDropDownProps.menu = {
|
||||
...menuProps,
|
||||
items: items?.map(({ title, label, path, ...itemProps }, index) => {
|
||||
items: items?.map(({ key, title, label, path, ...itemProps }, index) => {
|
||||
let mergedLabel: React.ReactNode = label ?? title;
|
||||
|
||||
if (path) {
|
||||
@ -80,7 +81,7 @@ const BreadcrumbItem: CompoundedComponent = (props: BreadcrumbItemProps) => {
|
||||
|
||||
return {
|
||||
...itemProps,
|
||||
key: index,
|
||||
key: key ?? index,
|
||||
label: mergedLabel as string,
|
||||
};
|
||||
}),
|
||||
|
@ -291,6 +291,21 @@ describe('Breadcrumb', () => {
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should support Breadcrumb.Item customized menu items key', () => {
|
||||
const key = 'test-key';
|
||||
const { container } = render(
|
||||
<Breadcrumb>
|
||||
<Breadcrumb.Item dropdownProps={{ open: true }} menu={{ items: [{ key }] }}>
|
||||
test-item
|
||||
</Breadcrumb.Item>
|
||||
</Breadcrumb>,
|
||||
);
|
||||
|
||||
const item = container.querySelector<HTMLElement>('.ant-dropdown-menu-item');
|
||||
|
||||
expect(item?.getAttribute('data-menu-id')?.endsWith(key)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should support string `0` and number `0`', () => {
|
||||
const { container } = render(
|
||||
<Breadcrumb
|
||||
@ -343,4 +358,8 @@ describe('Breadcrumb', () => {
|
||||
const item = await wrapper.findByText('test');
|
||||
expect(item).toHaveClass(testClassName);
|
||||
});
|
||||
|
||||
it('Breadcrumb.Item menu type', () => {
|
||||
expect(<Breadcrumb.Item menu={{ selectable: true }} />).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
@ -317,7 +317,7 @@ exports[`renders components/breadcrumb/demo/overlay.tsx extend context correctly
|
||||
>
|
||||
<li
|
||||
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
|
||||
data-menu-id="rc-menu-uuid-test-0"
|
||||
data-menu-id="rc-menu-uuid-test-1"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
@ -352,7 +352,7 @@ exports[`renders components/breadcrumb/demo/overlay.tsx extend context correctly
|
||||
</div>
|
||||
<li
|
||||
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
|
||||
data-menu-id="rc-menu-uuid-test-1"
|
||||
data-menu-id="rc-menu-uuid-test-2"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
@ -387,7 +387,7 @@ exports[`renders components/breadcrumb/demo/overlay.tsx extend context correctly
|
||||
</div>
|
||||
<li
|
||||
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
|
||||
data-menu-id="rc-menu-uuid-test-2"
|
||||
data-menu-id="rc-menu-uuid-test-3"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
|
@ -125,3 +125,7 @@ function itemRender(route, params, items, paths) {
|
||||
|
||||
return <Breadcrumb itemRender={itemRender} items={items} />;
|
||||
```
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Breadcrumb"></ComponentTokenTable>
|
||||
|
@ -126,3 +126,7 @@ function itemRender(item, params, items, paths) {
|
||||
|
||||
return <Breadcrumb itemRender={itemRender} items={items} />;
|
||||
```
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Breadcrumb"></ComponentTokenTable>
|
||||
|
@ -33,8 +33,8 @@ A carousel component. Scales with its container.
|
||||
| dots | Whether to show the dots at the bottom of the gallery, `object` for `dotsClass` and any others | boolean \| { className?: string } | true | |
|
||||
| easing | Transition interpolation function name | string | `linear` | |
|
||||
| effect | Transition effect | `scrollx` \| `fade` | `scrollx` | |
|
||||
| afterChange | Callback function called after the current index changes | function(current) | - | |
|
||||
| beforeChange | Callback function called before the current index changes | function(from, to) | - | |
|
||||
| afterChange | Callback function called after the current index changes | (current: number) => void | - | |
|
||||
| beforeChange | Callback function called before the current index changes | (current: number, next: number) => void | - | |
|
||||
|
||||
## Methods
|
||||
|
||||
|
@ -34,8 +34,8 @@ demo:
|
||||
| dots | 是否显示面板指示点,如果为 `object` 则同时可以指定 `dotsClass` 或者 | boolean \| { className?: string } | true | |
|
||||
| easing | 动画效果 | string | `linear` | |
|
||||
| effect | 动画效果函数 | `scrollx` \| `fade` | `scrollx` | |
|
||||
| afterChange | 切换面板的回调 | function(current) | - | |
|
||||
| beforeChange | 切换面板的回调 | function(from, to) | - | |
|
||||
| afterChange | 切换面板的回调 | (current: number) => void | - | |
|
||||
| beforeChange | 切换面板的回调 | (current: number, next: number) => void | - | |
|
||||
|
||||
## 方法
|
||||
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { createCache, StyleProvider } from '@ant-design/cssinjs';
|
||||
import { SmileOutlined } from '@ant-design/icons';
|
||||
import IconContext from '@ant-design/icons/lib/components/Context';
|
||||
import React from 'react';
|
||||
import { render } from '../../../tests/utils';
|
||||
import ConfigProvider from '..';
|
||||
import { render } from '../../../tests/utils';
|
||||
import Button from '../../button';
|
||||
|
||||
describe('ConfigProvider.Icon', () => {
|
||||
beforeEach(() => {
|
||||
@ -62,4 +64,21 @@ describe('ConfigProvider.Icon', () => {
|
||||
expect(styleNode?.nonce).toEqual('light');
|
||||
expect(container.querySelector('#csp')?.innerHTML).toEqual('light');
|
||||
});
|
||||
|
||||
it('cssinjs should support nonce', () => {
|
||||
render(
|
||||
<StyleProvider cache={createCache()}>
|
||||
<ConfigProvider csp={{ nonce: 'bamboo' }}>
|
||||
<Button />
|
||||
</ConfigProvider>
|
||||
</StyleProvider>,
|
||||
);
|
||||
|
||||
const styleList = Array.from(document.querySelectorAll('style'));
|
||||
|
||||
expect(styleList.length).toBeTruthy();
|
||||
styleList.forEach((style) => {
|
||||
expect(style.nonce).toEqual('bamboo');
|
||||
});
|
||||
});
|
||||
});
|
@ -206,7 +206,7 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = (props) => {
|
||||
const shouldWrapSSR = iconPrefixCls !== parentContext.iconPrefixCls;
|
||||
const csp = customCsp || parentContext.csp;
|
||||
|
||||
const wrapSSR = useStyle(iconPrefixCls);
|
||||
const wrapSSR = useStyle(iconPrefixCls, csp);
|
||||
|
||||
const mergedTheme = useTheme(theme, parentContext.theme);
|
||||
|
||||
|
@ -1,12 +1,20 @@
|
||||
import { useStyleRegister } from '@ant-design/cssinjs';
|
||||
import type { CSPConfig } from '..';
|
||||
import { resetIcon } from '../../style';
|
||||
import { useToken } from '../../theme/internal';
|
||||
|
||||
const useStyle = (iconPrefixCls: string) => {
|
||||
const useStyle = (iconPrefixCls: string, csp?: CSPConfig) => {
|
||||
const [theme, token] = useToken();
|
||||
|
||||
// Generate style for icons
|
||||
return useStyleRegister(
|
||||
{ theme, token, hashId: '', path: ['ant-design-icons', iconPrefixCls] },
|
||||
{
|
||||
theme,
|
||||
token,
|
||||
hashId: '',
|
||||
path: ['ant-design-icons', iconPrefixCls],
|
||||
nonce: () => csp?.nonce!,
|
||||
},
|
||||
() => [
|
||||
{
|
||||
[`.${iconPrefixCls}`]: {
|
||||
|
@ -12,6 +12,7 @@ const locale: PickerLocale = {
|
||||
weekPlaceholder: 'انتخاب هفته',
|
||||
rangePlaceholder: ['تاریخ شروع', 'تاریخ پایان'],
|
||||
rangeYearPlaceholder: ['سال شروع', 'سال پایان'],
|
||||
rangeQuarterPlaceholder: ['فصل شروع', 'فصل پایان'],
|
||||
rangeMonthPlaceholder: ['ماه شروع', 'ماه پایان'],
|
||||
rangeWeekPlaceholder: ['هفته شروع', 'هفته پایان'],
|
||||
...CalendarLocale,
|
||||
|
@ -38,3 +38,7 @@ A divider line separates different content.
|
||||
| plain | Divider text show as plain style | boolean | true | 4.2.0 |
|
||||
| style | The style object of container | CSSProperties | - | |
|
||||
| type | The direction type of divider | `horizontal` \| `vertical` | `horizontal` | |
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Divider"></ComponentTokenTable>
|
||||
|
@ -39,3 +39,7 @@ group:
|
||||
| plain | 文字是否显示为普通正文样式 | boolean | false | 4.2.0 |
|
||||
| style | 分割线样式对象 | CSSProperties | - | |
|
||||
| type | 水平还是垂直类型 | `horizontal` \| `vertical` | `horizontal` | |
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Divider"></ComponentTokenTable>
|
||||
|
@ -72,3 +72,7 @@ Same props from Dropdown. And includes additional props:
|
||||
## Note
|
||||
|
||||
Please ensure that the child node of `Dropdown` accepts `onMouseEnter`, `onMouseLeave`, `onFocus`, `onClick` events.
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Dropdown"></ComponentTokenTable>
|
||||
|
@ -76,3 +76,7 @@ demo:
|
||||
## 注意
|
||||
|
||||
请确保 `Dropdown` 的子元素能接受 `onMouseEnter`、`onMouseLeave`、`onFocus`、`onClick` 事件。
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Dropdown"></ComponentTokenTable>
|
||||
|
@ -1,26 +0,0 @@
|
||||
import type { DropdownToken } from '.';
|
||||
import type { GenerateStyle } from '../../theme/internal';
|
||||
|
||||
const genButtonStyle: GenerateStyle<DropdownToken> = (token) => {
|
||||
const { componentCls, antCls, paddingXS, opacityLoading } = token;
|
||||
|
||||
return {
|
||||
[`${componentCls}-button`]: {
|
||||
whiteSpace: 'nowrap',
|
||||
|
||||
[`&${antCls}-btn-group > ${antCls}-btn`]: {
|
||||
[`&-loading, &-loading + ${antCls}-btn`]: {
|
||||
cursor: 'default',
|
||||
pointerEvents: 'none',
|
||||
opacity: opacityLoading,
|
||||
},
|
||||
|
||||
[`&:last-child:not(:first-child):not(${antCls}-btn-icon-only)`]: {
|
||||
paddingInline: paddingXS,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default genButtonStyle;
|
@ -11,7 +11,6 @@ import {
|
||||
import getArrowStyle, { getArrowOffset } from '../../style/placementArrow';
|
||||
import type { FullToken, GenerateStyle } from '../../theme/internal';
|
||||
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
|
||||
import genButtonStyle from './button';
|
||||
import genStatusStyle from './status';
|
||||
|
||||
export interface ComponentToken {
|
||||
@ -71,6 +70,11 @@ const genBaseStyle: GenerateStyle<DropdownToken> = (token) => {
|
||||
content: '""',
|
||||
},
|
||||
|
||||
[`&-trigger${antCls}-btn > ${iconCls}-down`]: {
|
||||
fontSize: fontSizeIcon,
|
||||
transform: 'none',
|
||||
},
|
||||
|
||||
[`${componentCls}-wrap`]: {
|
||||
position: 'relative',
|
||||
|
||||
@ -350,11 +354,7 @@ export default genComponentStyleHook(
|
||||
dropdownPaddingVertical,
|
||||
dropdownEdgeChildPadding: paddingXXS,
|
||||
});
|
||||
return [
|
||||
genBaseStyle(dropdownToken),
|
||||
genButtonStyle(dropdownToken),
|
||||
genStatusStyle(dropdownToken),
|
||||
];
|
||||
return [genBaseStyle(dropdownToken), genStatusStyle(dropdownToken)];
|
||||
},
|
||||
(token) => ({
|
||||
zIndexPopup: token.zIndexPopupBase + 50,
|
||||
|
@ -9,10 +9,10 @@ import omit from 'rc-util/lib/omit';
|
||||
import * as React from 'react';
|
||||
import type { FormItemProps, ValidateStatus } from '.';
|
||||
import { Row } from '../../grid';
|
||||
import type { FormItemStatusContextProps, ReportMetaChange } from '../context';
|
||||
import { FormContext, FormItemInputContext, NoStyleItemContext } from '../context';
|
||||
import FormItemInput from '../FormItemInput';
|
||||
import FormItemLabel from '../FormItemLabel';
|
||||
import type { FormItemStatusContextProps, ReportMetaChange } from '../context';
|
||||
import { FormContext, FormItemInputContext, NoStyleItemContext } from '../context';
|
||||
import useDebounce from '../hooks/useDebounce';
|
||||
|
||||
const iconMap = {
|
||||
@ -81,29 +81,38 @@ export default function ItemHolder(props: ItemHolderProps) {
|
||||
};
|
||||
|
||||
// ======================== Status ========================
|
||||
let mergedValidateStatus: ValidateStatus = '';
|
||||
if (validateStatus !== undefined) {
|
||||
mergedValidateStatus = validateStatus;
|
||||
} else if (meta.validating) {
|
||||
mergedValidateStatus = 'validating';
|
||||
} else if (debounceErrors.length) {
|
||||
mergedValidateStatus = 'error';
|
||||
} else if (debounceWarnings.length) {
|
||||
mergedValidateStatus = 'warning';
|
||||
} else if (meta.touched || (hasFeedback && meta.validated)) {
|
||||
// success feedback should display when pass hasFeedback prop and current value is valid value
|
||||
mergedValidateStatus = 'success';
|
||||
}
|
||||
|
||||
const getValidateState = (isDebounce = false) => {
|
||||
let status: ValidateStatus = '';
|
||||
const _errors = isDebounce ? debounceErrors : meta.errors;
|
||||
const _warnings = isDebounce ? debounceWarnings : meta.warnings;
|
||||
if (validateStatus !== undefined) {
|
||||
status = validateStatus;
|
||||
} else if (meta.validating) {
|
||||
status = 'validating';
|
||||
} else if (_errors.length) {
|
||||
status = 'error';
|
||||
} else if (_warnings.length) {
|
||||
status = 'warning';
|
||||
} else if (meta.touched || (hasFeedback && meta.validated)) {
|
||||
// success feedback should display when pass hasFeedback prop and current value is valid value
|
||||
status = 'success';
|
||||
}
|
||||
return status;
|
||||
};
|
||||
|
||||
const mergedValidateStatus = getValidateState();
|
||||
|
||||
const formItemStatusContext = React.useMemo<FormItemStatusContextProps>(() => {
|
||||
let feedbackIcon: React.ReactNode;
|
||||
const desplayValidateStatus = getValidateState(true);
|
||||
if (hasFeedback) {
|
||||
const IconNode = mergedValidateStatus && iconMap[mergedValidateStatus];
|
||||
const IconNode = desplayValidateStatus && iconMap[desplayValidateStatus];
|
||||
feedbackIcon = IconNode ? (
|
||||
<span
|
||||
className={classNames(
|
||||
`${itemPrefixCls}-feedback-icon`,
|
||||
`${itemPrefixCls}-feedback-icon-${mergedValidateStatus}`,
|
||||
`${itemPrefixCls}-feedback-icon-${desplayValidateStatus}`,
|
||||
)}
|
||||
>
|
||||
<IconNode />
|
||||
|
@ -1,30 +1,30 @@
|
||||
import type { ChangeEventHandler } from 'react';
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import scrollIntoView from 'scroll-into-view-if-needed';
|
||||
import classNames from 'classnames';
|
||||
import type { ColProps } from 'antd/es/grid';
|
||||
import classNames from 'classnames';
|
||||
import type { ChangeEventHandler } from 'react';
|
||||
import React, { version as ReactVersion, useEffect, useRef, useState } from 'react';
|
||||
import scrollIntoView from 'scroll-into-view-if-needed';
|
||||
import type { FormInstance } from '..';
|
||||
import Form from '..';
|
||||
import * as Util from '../util';
|
||||
import Button from '../../button';
|
||||
import Input from '../../input';
|
||||
import Select from '../../select';
|
||||
import Upload from '../../upload';
|
||||
import Cascader from '../../cascader';
|
||||
import Checkbox from '../../checkbox';
|
||||
import DatePicker from '../../date-picker';
|
||||
import InputNumber from '../../input-number';
|
||||
import Radio from '../../radio';
|
||||
import Switch from '../../switch';
|
||||
import TreeSelect from '../../tree-select';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import { fireEvent, pureRender, render, screen, waitFakeTimer } from '../../../tests/utils';
|
||||
import Button from '../../button';
|
||||
import Cascader from '../../cascader';
|
||||
import Checkbox from '../../checkbox';
|
||||
import ConfigProvider from '../../config-provider';
|
||||
import DatePicker from '../../date-picker';
|
||||
import Drawer from '../../drawer';
|
||||
import Input from '../../input';
|
||||
import InputNumber from '../../input-number';
|
||||
import zhCN from '../../locale/zh_CN';
|
||||
import Modal from '../../modal';
|
||||
import Radio from '../../radio';
|
||||
import Select from '../../select';
|
||||
import Switch from '../../switch';
|
||||
import TreeSelect from '../../tree-select';
|
||||
import Upload from '../../upload';
|
||||
import type { NamePath } from '../interface';
|
||||
import * as Util from '../util';
|
||||
|
||||
const { RangePicker } = DatePicker;
|
||||
const { TextArea } = Input;
|
||||
@ -1626,4 +1626,51 @@ describe('Form', () => {
|
||||
expect(container.querySelectorAll('.ant-form-item-has-feedback').length).toBe(1);
|
||||
expect(container.querySelectorAll('.ant-form-item-has-success').length).toBe(1);
|
||||
});
|
||||
it('validate status should be change in order', async () => {
|
||||
const onChange = jest.fn();
|
||||
|
||||
const CustomInput = (props: any) => {
|
||||
const { status } = Form.Item.useStatus();
|
||||
useEffect(() => {
|
||||
onChange(status);
|
||||
}, [status]);
|
||||
return <Input {...props} />;
|
||||
};
|
||||
|
||||
const App = () => (
|
||||
<Form>
|
||||
<Form.Item>
|
||||
<Form.Item name="test" label="test" rules={[{ len: 3, message: 'error.' }]}>
|
||||
<CustomInput />
|
||||
</Form.Item>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
|
||||
render(<App />);
|
||||
await waitFakeTimer();
|
||||
|
||||
// initial validate
|
||||
const initTriggerTime = ReactVersion.startsWith('18') ? 2 : 1;
|
||||
expect(onChange).toHaveBeenCalledTimes(initTriggerTime);
|
||||
let idx = 1;
|
||||
expect(onChange).toHaveBeenNthCalledWith(idx++, '');
|
||||
if (initTriggerTime === 2) {
|
||||
expect(onChange).toHaveBeenNthCalledWith(idx++, '');
|
||||
}
|
||||
|
||||
// change trigger
|
||||
await changeValue(0, '1');
|
||||
expect(onChange).toHaveBeenCalledTimes(initTriggerTime + 2);
|
||||
expect(onChange).toHaveBeenNthCalledWith(idx++, 'validating');
|
||||
expect(onChange).toHaveBeenNthCalledWith(idx++, 'error');
|
||||
await changeValue(0, '11');
|
||||
expect(onChange).toHaveBeenCalledTimes(initTriggerTime + 4);
|
||||
expect(onChange).toHaveBeenNthCalledWith(idx++, 'validating');
|
||||
expect(onChange).toHaveBeenNthCalledWith(idx++, 'error');
|
||||
await changeValue(0, '111');
|
||||
expect(onChange).toHaveBeenCalledTimes(initTriggerTime + 6);
|
||||
expect(onChange).toHaveBeenNthCalledWith(idx++, 'validating');
|
||||
expect(onChange).toHaveBeenNthCalledWith(idx++, 'success');
|
||||
});
|
||||
});
|
||||
|
@ -355,10 +355,13 @@ const genInlineStyle: GenerateStyle<FormToken> = (token) => {
|
||||
|
||||
[formItemCls]: {
|
||||
flex: 'none',
|
||||
flexWrap: 'nowrap',
|
||||
marginInlineEnd: token.margin,
|
||||
marginBottom: 0,
|
||||
|
||||
'&-row': {
|
||||
flexWrap: 'nowrap',
|
||||
},
|
||||
|
||||
'&-with-help': {
|
||||
marginBottom: token.marginLG,
|
||||
},
|
||||
|
@ -3,11 +3,12 @@ import * as React from 'react';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import RowContext from './RowContext';
|
||||
import { useColStyle } from './style';
|
||||
import type { LiteralUnion } from '../_util/type';
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/14324
|
||||
type ColSpanType = number | string;
|
||||
|
||||
type FlexType = number | 'none' | 'auto' | string;
|
||||
type FlexType = number | LiteralUnion<'none' | 'auto'>;
|
||||
|
||||
export interface ColSize {
|
||||
flex?: FlexType;
|
||||
|
@ -120,6 +120,10 @@ Supports all props of `Input`.
|
||||
| blur | Remove focus | - | |
|
||||
| focus | Get focus | (option?: { preventScroll?: boolean, cursor?: 'start' \| 'end' \| 'all' }) | option - 4.10.0 |
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Input"></ComponentTokenTable>
|
||||
|
||||
## FAQ
|
||||
|
||||
### Why Input lose focus when change `prefix/suffix/showCount`
|
||||
|
@ -139,6 +139,10 @@ Input 的其他属性和 React 自带的 [input](https://reactjs.org/docs/dom-el
|
||||
| textarea | `textarea` 元素 | 5.4.0 |
|
||||
| count | 文字计数元素 | 5.4.0 |
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Input"></ComponentTokenTable>
|
||||
|
||||
## FAQ
|
||||
|
||||
### 为什么我动态改变 `prefix/suffix/showCount` 时,Input 会失去焦点?
|
||||
|
@ -127,3 +127,7 @@ The sidebar.
|
||||
xxl: '1600px',
|
||||
}
|
||||
```
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Layout"></ComponentTokenTable>
|
||||
|
@ -128,3 +128,7 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*HdS6Q5vUCDcAAA
|
||||
xxl: '1600px',
|
||||
}
|
||||
```
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Layout"></ComponentTokenTable>
|
||||
|
@ -21,6 +21,8 @@ const localeValues: Locale = {
|
||||
filterConfirm: 'OK',
|
||||
filterReset: 'Återställ',
|
||||
filterEmptyText: 'Inga filter',
|
||||
filterCheckall: 'Markera alla objekt',
|
||||
filterSearchPlaceholder: 'Sök i filter',
|
||||
emptyText: 'Ingen data',
|
||||
selectAll: 'Markera nuvarande sida',
|
||||
selectInvert: 'Invertera nuvarande sida',
|
||||
@ -33,6 +35,11 @@ const localeValues: Locale = {
|
||||
triggerAsc: 'Klicka för att sortera i stigande ordning',
|
||||
cancelSort: 'Klicka för att avbryta sortering',
|
||||
},
|
||||
Tour: {
|
||||
Next: 'Nästa',
|
||||
Previous: 'Föregående',
|
||||
Finish: 'Avsluta',
|
||||
},
|
||||
Modal: {
|
||||
okText: 'OK',
|
||||
cancelText: 'Avbryt',
|
||||
@ -129,6 +136,10 @@ const localeValues: Locale = {
|
||||
Image: {
|
||||
preview: 'Förhandsgranska',
|
||||
},
|
||||
QRCode: {
|
||||
expired: 'QR-koden har upphört att gälla',
|
||||
refresh: 'Uppdatera',
|
||||
},
|
||||
};
|
||||
|
||||
export default localeValues;
|
||||
|
@ -5079,6 +5079,9 @@ Array [
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style="position: absolute; top: 0px; left: 0px; width: 100%;"
|
||||
/>
|
||||
</li>
|
||||
<li
|
||||
class="ant-menu-item ant-menu-item-only-child"
|
||||
|
@ -63,6 +63,7 @@ const App: React.FC = () => {
|
||||
mode="vertical"
|
||||
theme="dark"
|
||||
items={items}
|
||||
getPopupContainer={(node) => node.parentNode as HTMLElement}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
@ -142,3 +142,7 @@ Menu will render fully item in flex layout and then collapse it. You need tell f
|
||||
<Menu style={{ minWidth: 0, flex: "auto" }} />
|
||||
</div>
|
||||
```
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Menu"></ComponentTokenTable>
|
||||
|
@ -142,3 +142,7 @@ Menu 初始化时会先全部渲染,然后根据宽度裁剪内容。当处于
|
||||
<Menu style={{ minWidth: 0, flex: "auto" }} />
|
||||
</div>
|
||||
```
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Menu"></ComponentTokenTable>
|
||||
|
@ -442,10 +442,15 @@ export default (prefixCls: string, injectStyle: boolean): UseComponentStyleResul
|
||||
return [];
|
||||
}
|
||||
|
||||
const { colorBgElevated, colorPrimary, colorError, colorErrorHover, colorTextLightSolid } =
|
||||
token;
|
||||
|
||||
const { controlHeightLG, fontSize } = token;
|
||||
const {
|
||||
colorBgElevated,
|
||||
colorPrimary,
|
||||
colorError,
|
||||
colorErrorHover,
|
||||
colorTextLightSolid,
|
||||
controlHeightLG,
|
||||
fontSize,
|
||||
} = token;
|
||||
|
||||
const menuArrowSize = (fontSize / 7) * 5;
|
||||
|
||||
|
@ -46,7 +46,7 @@ const getThemeStyle = (token: MenuToken, themeSuffix: string): CSSInterpolation
|
||||
} = token;
|
||||
|
||||
return {
|
||||
[`${componentCls}-${themeSuffix}`]: {
|
||||
[`${componentCls}-${themeSuffix}, ${componentCls}-${themeSuffix} > ${componentCls}`]: {
|
||||
color: colorItemText,
|
||||
background: colorItemBg,
|
||||
|
||||
|
@ -350,4 +350,21 @@ describe('Modal.hook', () => {
|
||||
|
||||
expect(document.body.querySelector('.bamboo')?.textContent).toEqual('好的');
|
||||
});
|
||||
|
||||
it('it should call forwarded afterClose', () => {
|
||||
const afterClose = jest.fn();
|
||||
const Demo = () => {
|
||||
const [modal, contextHolder] = Modal.useModal();
|
||||
React.useEffect(() => {
|
||||
modal.confirm({ title: 'Confirm', afterClose });
|
||||
}, []);
|
||||
return contextHolder;
|
||||
};
|
||||
|
||||
render(<Demo />);
|
||||
const btns = document.body.querySelectorAll('.ant-btn');
|
||||
fireEvent.click(btns[btns.length - 1]);
|
||||
|
||||
expect(afterClose).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
@ -16,7 +16,7 @@ export interface HookModalRef {
|
||||
}
|
||||
|
||||
const HookModal: React.ForwardRefRenderFunction<HookModalRef, HookModalProps> = (
|
||||
{ afterClose, config },
|
||||
{ afterClose: hookAfterClose, config },
|
||||
ref,
|
||||
) => {
|
||||
const [open, setOpen] = React.useState(true);
|
||||
@ -26,6 +26,11 @@ const HookModal: React.ForwardRefRenderFunction<HookModalRef, HookModalProps> =
|
||||
const prefixCls = getPrefixCls('modal');
|
||||
const rootPrefixCls = getPrefixCls();
|
||||
|
||||
const afterClose = () => {
|
||||
hookAfterClose();
|
||||
innerConfig.afterClose?.();
|
||||
};
|
||||
|
||||
const close = (...args: any[]) => {
|
||||
setOpen(false);
|
||||
const triggerCancel = args.some((param) => param && param.triggerCancel);
|
||||
@ -59,7 +64,7 @@ const HookModal: React.ForwardRefRenderFunction<HookModalRef, HookModalProps> =
|
||||
okText={
|
||||
innerConfig.okText || (mergedOkCancel ? contextLocale?.okText : contextLocale?.justOkText)
|
||||
}
|
||||
direction={direction}
|
||||
direction={innerConfig.direction || direction}
|
||||
cancelText={innerConfig.cancelText || contextLocale?.cancelText}
|
||||
/>
|
||||
);
|
||||
|
@ -55,49 +55,51 @@ const Pagination: React.FC<PaginationProps> = ({
|
||||
|
||||
const mergedShowSizeChanger = showSizeChanger ?? pagination.showSizeChanger;
|
||||
|
||||
const getIconsProps = () => {
|
||||
const iconsProps = React.useMemo<Record<PropertyKey, React.ReactNode>>(() => {
|
||||
const ellipsis = <span className={`${prefixCls}-item-ellipsis`}>•••</span>;
|
||||
let prevIcon = (
|
||||
const prevIcon = (
|
||||
<button className={`${prefixCls}-item-link`} type="button" tabIndex={-1}>
|
||||
<LeftOutlined />
|
||||
{direction === 'rtl' ? <RightOutlined /> : <LeftOutlined />}
|
||||
</button>
|
||||
);
|
||||
let nextIcon = (
|
||||
const nextIcon = (
|
||||
<button className={`${prefixCls}-item-link`} type="button" tabIndex={-1}>
|
||||
<RightOutlined />
|
||||
{direction === 'rtl' ? <LeftOutlined /> : <RightOutlined />}
|
||||
</button>
|
||||
);
|
||||
let jumpPrevIcon = (
|
||||
const jumpPrevIcon = (
|
||||
<a className={`${prefixCls}-item-link`}>
|
||||
{/* You can use transition effects in the container :) */}
|
||||
<div className={`${prefixCls}-item-container`}>
|
||||
<DoubleLeftOutlined className={`${prefixCls}-item-link-icon`} />
|
||||
{direction === 'rtl' ? (
|
||||
<DoubleRightOutlined className={`${prefixCls}-item-link-icon`} />
|
||||
) : (
|
||||
<DoubleLeftOutlined className={`${prefixCls}-item-link-icon`} />
|
||||
)}
|
||||
{ellipsis}
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
let jumpNextIcon = (
|
||||
const jumpNextIcon = (
|
||||
<a className={`${prefixCls}-item-link`}>
|
||||
{/* You can use transition effects in the container :) */}
|
||||
<div className={`${prefixCls}-item-container`}>
|
||||
<DoubleRightOutlined className={`${prefixCls}-item-link-icon`} />
|
||||
{direction === 'rtl' ? (
|
||||
<DoubleLeftOutlined className={`${prefixCls}-item-link-icon`} />
|
||||
) : (
|
||||
<DoubleRightOutlined className={`${prefixCls}-item-link-icon`} />
|
||||
)}
|
||||
{ellipsis}
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
// change arrows direction in right-to-left direction
|
||||
if (direction === 'rtl') {
|
||||
[prevIcon, nextIcon] = [nextIcon, prevIcon];
|
||||
[jumpPrevIcon, jumpNextIcon] = [jumpNextIcon, jumpPrevIcon];
|
||||
}
|
||||
return { prevIcon, nextIcon, jumpPrevIcon, jumpNextIcon };
|
||||
};
|
||||
}, [direction, prefixCls]);
|
||||
|
||||
const [contextLocale] = useLocale('Pagination', enUS);
|
||||
|
||||
const locale = { ...contextLocale, ...customLocale };
|
||||
|
||||
const isSmall = size === 'small' || !!(xs && !size && responsive);
|
||||
|
||||
const selectPrefixCls = getPrefixCls('select', customizeSelectPrefixCls);
|
||||
const extendedClassName = classNames(
|
||||
{
|
||||
@ -111,7 +113,7 @@ const Pagination: React.FC<PaginationProps> = ({
|
||||
|
||||
return wrapSSR(
|
||||
<RcPagination
|
||||
{...getIconsProps()}
|
||||
{...iconsProps}
|
||||
{...restProps}
|
||||
prefixCls={prefixCls}
|
||||
selectPrefixCls={selectPrefixCls}
|
||||
|
@ -55,3 +55,7 @@ A long list can be divided into several pages using `Pagination`, and only one p
|
||||
| total | Total number of data items | number | 0 | |
|
||||
| onChange | Called when the page number or `pageSize` is changed, and it takes the resulting page number and pageSize as its arguments | function(page, pageSize) | - | |
|
||||
| onShowSizeChange | Called when `pageSize` is changed | function(current, size) | - | |
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Pagination"></ComponentTokenTable>
|
||||
|
@ -56,3 +56,7 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*WM86SrBC8TsAAA
|
||||
| total | 数据总数 | number | 0 | |
|
||||
| onChange | 页码或 `pageSize` 改变的回调,参数是改变后的页码及每页条数 | function(page, pageSize) | - | |
|
||||
| onShowSizeChange | pageSize 变化的回调 | function(current, size) | - | |
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Pagination"></ComponentTokenTable>
|
||||
|
@ -5,9 +5,9 @@ import {
|
||||
initInputToken,
|
||||
type InputToken,
|
||||
} from '../../input/style';
|
||||
import { genFocusOutline, genFocusStyle, resetComponent } from '../../style';
|
||||
import type { FullToken, GenerateStyle } from '../../theme/internal';
|
||||
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
|
||||
import { genFocusOutline, genFocusStyle, resetComponent } from '../../style';
|
||||
|
||||
interface PaginationToken extends InputToken<FullToken<'Pagination'>> {
|
||||
paginationItemSize: number;
|
||||
@ -57,7 +57,16 @@ const genPaginationDisabledStyle: GenerateStyle<PaginationToken, CSSObject> = (t
|
||||
|
||||
[`&${componentCls}-disabled`]: {
|
||||
cursor: 'not-allowed',
|
||||
|
||||
[`&${componentCls}-mini`]: {
|
||||
[`
|
||||
&:hover ${componentCls}-item:not(${componentCls}-item-active),
|
||||
&:active ${componentCls}-item:not(${componentCls}-item-active),
|
||||
&:hover ${componentCls}-item-link,
|
||||
&:active ${componentCls}-item-link
|
||||
`]: {
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
},
|
||||
[`${componentCls}-item`]: {
|
||||
cursor: 'not-allowed',
|
||||
|
||||
@ -134,6 +143,12 @@ const genPaginationMiniStyle: GenerateStyle<PaginationToken, CSSObject> = (token
|
||||
[`&${componentCls}-mini ${componentCls}-item:not(${componentCls}-item-active)`]: {
|
||||
backgroundColor: 'transparent',
|
||||
borderColor: 'transparent',
|
||||
'&:hover': {
|
||||
backgroundColor: token.colorBgTextHover,
|
||||
},
|
||||
'&:active': {
|
||||
backgroundColor: token.colorBgTextActive,
|
||||
},
|
||||
},
|
||||
|
||||
[`&${componentCls}-mini ${componentCls}-prev, &${componentCls}-mini ${componentCls}-next`]: {
|
||||
@ -141,6 +156,15 @@ const genPaginationMiniStyle: GenerateStyle<PaginationToken, CSSObject> = (token
|
||||
height: token.paginationItemSizeSM,
|
||||
margin: 0,
|
||||
lineHeight: `${token.paginationItemSizeSM}px`,
|
||||
[`&:hover ${componentCls}-item-link`]: {
|
||||
backgroundColor: token.colorBgTextHover,
|
||||
},
|
||||
[`&:active ${componentCls}-item-link`]: {
|
||||
backgroundColor: token.colorBgTextActive,
|
||||
},
|
||||
[`&${componentCls}-disabled:hover ${componentCls}-item-link`]: {
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
},
|
||||
|
||||
[`
|
||||
|
@ -137,6 +137,10 @@ Select component to select value from options.
|
||||
| key | Group key | string | - | |
|
||||
| label | Group label | string \| React.Element | - | |
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Select"></ComponentTokenTable>
|
||||
|
||||
## FAQ
|
||||
|
||||
### Why sometime search will show 2 same option when in `tags` mode?
|
||||
|
@ -138,6 +138,10 @@ demo:
|
||||
| key | Key | string | - | |
|
||||
| label | 组名 | string \| React.Element | - | |
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Select"></ComponentTokenTable>
|
||||
|
||||
## FAQ
|
||||
|
||||
### `mode="tags"` 模式下为何搜索有时会出现两个相同选项?
|
||||
|
@ -79,3 +79,7 @@ A single step in the step bar.
|
||||
| status | To specify the status. It will be automatically set by `current` of `Steps` if not configured. Optional values are: `wait` `process` `finish` `error` | string | `wait` | |
|
||||
| subTitle | Subtitle of the step | ReactNode | - | |
|
||||
| title | Title of the step | ReactNode | - | |
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Steps"></ComponentTokenTable>
|
||||
|
@ -80,3 +80,7 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*cFsBQLA0b7UAAA
|
||||
| status | 指定状态。当不配置该属性时,会使用 Steps 的 `current` 来自动指定状态。可选:`wait` `process` `finish` `error` | string | `wait` | |
|
||||
| subTitle | 子标题 | ReactNode | - | |
|
||||
| title | 标题 | ReactNode | - | |
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Steps"></ComponentTokenTable>
|
||||
|
@ -3,7 +3,6 @@ import type { CSSObject } from '@ant-design/cssinjs';
|
||||
import type { AliasToken, DerivativeToken } from '../theme/internal';
|
||||
|
||||
export { operationUnit } from './operationUnit';
|
||||
export { genPresetColor } from './presetColor';
|
||||
export { roundedArrow } from './roundedArrow';
|
||||
|
||||
export const textEllipsis: CSSObject = {
|
||||
|
@ -65,7 +65,7 @@ interface ChangeEventInfo<RecordType> {
|
||||
filterStates: FilterState<RecordType>[];
|
||||
sorterStates: SortState<RecordType>[];
|
||||
|
||||
resetPagination: Function;
|
||||
resetPagination: (current?: number, pageSize?: number) => void;
|
||||
}
|
||||
|
||||
/** Same as `TableProps` but we need record parent render times */
|
||||
@ -238,16 +238,16 @@ function InternalTable<RecordType extends object = any>(
|
||||
};
|
||||
|
||||
if (reset) {
|
||||
changeEventInfo.resetPagination!();
|
||||
changeEventInfo.resetPagination?.();
|
||||
|
||||
// Reset event param
|
||||
if (changeInfo.pagination!.current) {
|
||||
changeInfo.pagination!.current = 1;
|
||||
if (changeInfo.pagination?.current) {
|
||||
changeInfo.pagination.current = 1;
|
||||
}
|
||||
|
||||
// Trigger pagination events
|
||||
if (pagination && pagination.onChange) {
|
||||
pagination.onChange(1, changeInfo.pagination!.pageSize!);
|
||||
pagination.onChange(1, changeInfo.pagination?.pageSize!);
|
||||
}
|
||||
}
|
||||
|
||||
@ -491,10 +491,10 @@ function InternalTable<RecordType extends object = any>(
|
||||
bottomPaginationNode = renderPagination(defaultPosition);
|
||||
}
|
||||
if (topPos) {
|
||||
topPaginationNode = renderPagination(topPos!.toLowerCase().replace('top', ''));
|
||||
topPaginationNode = renderPagination(topPos.toLowerCase().replace('top', ''));
|
||||
}
|
||||
if (bottomPos) {
|
||||
bottomPaginationNode = renderPagination(bottomPos!.toLowerCase().replace('bottom', ''));
|
||||
bottomPaginationNode = renderPagination(bottomPos.toLowerCase().replace('bottom', ''));
|
||||
}
|
||||
} else {
|
||||
bottomPaginationNode = renderPagination(defaultPosition);
|
||||
|
@ -25,9 +25,9 @@ function Table<RecordType extends object = any>(
|
||||
const ForwardTable = React.forwardRef(Table) as any as RefTable & {
|
||||
SELECTION_COLUMN: typeof SELECTION_COLUMN;
|
||||
EXPAND_COLUMN: typeof EXPAND_COLUMN;
|
||||
SELECTION_ALL: 'SELECT_ALL';
|
||||
SELECTION_INVERT: 'SELECT_INVERT';
|
||||
SELECTION_NONE: 'SELECT_NONE';
|
||||
SELECTION_ALL: typeof SELECTION_ALL;
|
||||
SELECTION_INVERT: typeof SELECTION_INVERT;
|
||||
SELECTION_NONE: typeof SELECTION_NONE;
|
||||
Column: typeof Column;
|
||||
ColumnGroup: typeof ColumnGroup;
|
||||
Summary: typeof Summary;
|
||||
|
@ -2777,4 +2777,47 @@ describe('Table.filter', () => {
|
||||
|
||||
expect(renderedNames(container)).toEqual(['Jack']);
|
||||
});
|
||||
|
||||
it('changes to table data should not reset the filter dropdown state being changed by a user', () => {
|
||||
const tableProps = {
|
||||
key: 'stabletable',
|
||||
rowKey: 'name',
|
||||
dataSource: [],
|
||||
columns: [
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
filteredValue: [], // User is controlling filteredValue. It begins with no items checked.
|
||||
filters: [{ text: 'J', value: 'J' }],
|
||||
onFilter: (value: any, record: any) => record.name.includes(value),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const { container, rerender } = render(createTable(tableProps));
|
||||
|
||||
// User opens filter Dropdown.
|
||||
fireEvent.click(container.querySelector('.ant-dropdown-trigger.ant-table-filter-trigger')!);
|
||||
|
||||
// There is one checkbox and it begins unchecked.
|
||||
expect(container.querySelector<HTMLInputElement>('input[type="checkbox"]')!.checked).toEqual(
|
||||
false,
|
||||
);
|
||||
|
||||
// User checks it.
|
||||
fireEvent.click(container.querySelector('input[type="checkbox"]')!);
|
||||
|
||||
// The checkbox is now checked.
|
||||
expect(container.querySelector<HTMLInputElement>('input[type="checkbox"]')!.checked).toEqual(
|
||||
true,
|
||||
);
|
||||
|
||||
// Table data changes while the dropdown is open and a user is setting filters.
|
||||
rerender(createTable({ ...tableProps, dataSource: [{ name: 'Foo' }] }));
|
||||
|
||||
// The checkbox is still checked.
|
||||
expect(container.querySelector<HTMLInputElement>('input[type="checkbox"]')!.checked).toEqual(
|
||||
true,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -215,7 +215,10 @@ function useFilter<RecordType>({
|
||||
FilterState<RecordType>[],
|
||||
Record<string, FilterValue | null>,
|
||||
] {
|
||||
const mergedColumns = getMergedColumns(rawMergedColumns || []);
|
||||
const mergedColumns = React.useMemo(
|
||||
() => getMergedColumns(rawMergedColumns || []),
|
||||
[rawMergedColumns],
|
||||
);
|
||||
|
||||
const [filterStates, setFilterStates] = React.useState<FilterState<RecordType>[]>(() =>
|
||||
collectFilterStates(mergedColumns, true),
|
||||
|
@ -31,7 +31,7 @@ function usePagination(
|
||||
total: number,
|
||||
onChange: (current: number, pageSize: number) => void,
|
||||
pagination?: TablePaginationConfig | false,
|
||||
): readonly [TablePaginationConfig, () => void] {
|
||||
): readonly [TablePaginationConfig, (current?: number, pageSize?: number) => void] {
|
||||
const { total: paginationTotal = 0, ...paginationObj } =
|
||||
pagination && typeof pagination === 'object' ? pagination : {};
|
||||
|
||||
|
@ -29,7 +29,7 @@ const genCardStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject =>
|
||||
tabsCardHorizontalPadding,
|
||||
tabsCardHeadBackground,
|
||||
tabsCardGutter,
|
||||
colorSplit,
|
||||
colorBorderSecondary,
|
||||
} = token;
|
||||
return {
|
||||
[`${componentCls}-card`]: {
|
||||
@ -38,7 +38,7 @@ const genCardStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject =>
|
||||
margin: 0,
|
||||
padding: tabsCardHorizontalPadding,
|
||||
background: tabsCardHeadBackground,
|
||||
border: `${token.lineWidth}px ${token.lineType} ${colorSplit}`,
|
||||
border: `${token.lineWidth}px ${token.lineType} ${colorBorderSecondary}`,
|
||||
transition: `all ${token.motionDurationSlow} ${token.motionEaseInOut}`,
|
||||
},
|
||||
|
||||
@ -226,7 +226,7 @@ const genDropdownStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject
|
||||
};
|
||||
|
||||
const genPositionStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject => {
|
||||
const { componentCls, margin, colorSplit } = token;
|
||||
const { componentCls, margin, colorBorderSecondary } = token;
|
||||
return {
|
||||
// ========================== Top & Bottom ==========================
|
||||
[`${componentCls}-top, ${componentCls}-bottom`]: {
|
||||
@ -245,7 +245,7 @@ const genPositionStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject
|
||||
_skip_check_: true,
|
||||
value: 0,
|
||||
},
|
||||
borderBottom: `${token.lineWidth}px ${token.lineType} ${colorSplit}`,
|
||||
borderBottom: `${token.lineWidth}px ${token.lineType} ${colorBorderSecondary}`,
|
||||
content: "''",
|
||||
},
|
||||
|
||||
@ -714,7 +714,7 @@ const genTabsStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject =>
|
||||
tabsCardGutter,
|
||||
tabsHoverColor,
|
||||
tabsActiveColor,
|
||||
colorSplit,
|
||||
colorBorderSecondary,
|
||||
} = token;
|
||||
|
||||
return {
|
||||
@ -799,7 +799,7 @@ const genTabsStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject =>
|
||||
},
|
||||
padding: `0 ${token.paddingXS}px`,
|
||||
background: 'transparent',
|
||||
border: `${token.lineWidth}px ${token.lineType} ${colorSplit}`,
|
||||
border: `${token.lineWidth}px ${token.lineType} ${colorBorderSecondary}`,
|
||||
borderRadius: `${token.borderRadiusLG}px ${token.borderRadiusLG}px 0 0`,
|
||||
outline: 'none',
|
||||
cursor: 'pointer',
|
||||
|
@ -1,9 +1,9 @@
|
||||
import type { CSSInterpolation } from '@ant-design/cssinjs';
|
||||
import type React from 'react';
|
||||
import capitalize from '../../_util/capitalize';
|
||||
import { genPresetColor, resetComponent } from '../../style';
|
||||
import { resetComponent } from '../../style';
|
||||
import type { FullToken } from '../../theme/internal';
|
||||
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
|
||||
import { genComponentStyleHook, genPresetColor, mergeToken } from '../../theme/internal';
|
||||
|
||||
export interface ComponentToken {}
|
||||
|
||||
|
@ -21,18 +21,21 @@ export interface ColorNeutralMapToken {
|
||||
/**
|
||||
* @nameZH 二级文本色
|
||||
* @desc 作为第二梯度的文本色,一般用在不那么需要强化文本颜色的场景,例如 Label 文本、Menu 的文本选中态等场景。
|
||||
* @descEN The second level of text color is generally used in scenarios where text color is not emphasized, such as label text, menu text selection state, etc.
|
||||
*/
|
||||
colorTextSecondary: string;
|
||||
|
||||
/**
|
||||
* @nameZH 三级文本色
|
||||
* @desc 第三级文本色一般用于描述性文本,例如表单的中的补充说明文本、列表的描述性文本等场景。
|
||||
* @descEN The third level of text color is generally used for descriptive text, such as form supplementary explanation text, list descriptive text, etc.
|
||||
*/
|
||||
colorTextTertiary: string;
|
||||
|
||||
/**
|
||||
* @nameZH 四级文本色
|
||||
* @desc 第四级文本色是最浅的文本色,例如表单的输入提示文本、禁用色文本等。
|
||||
* @descEN The fourth level of text color is the lightest text color, such as form input prompt text, disabled color text, etc.
|
||||
*/
|
||||
colorTextQuaternary: string;
|
||||
|
||||
@ -59,24 +62,28 @@ export interface ColorNeutralMapToken {
|
||||
/**
|
||||
* @nameZH 一级填充色
|
||||
* @desc 最深的填充色,用于拉开与二、三级填充色的区分度,目前只用在 Slider 的 hover 效果。
|
||||
* @descEN The darkest fill color is used to distinguish between the second and third level of fill color, and is currently only used in the hover effect of Slider.
|
||||
*/
|
||||
colorFill: string;
|
||||
|
||||
/**
|
||||
* @nameZH 二级填充色
|
||||
* @desc 二级填充色可以较为明显地勾勒出元素形体,如 Rate、Skeleton 等。也可以作为三级填充色的 Hover 状态,如 Table 等。
|
||||
* @descEN The second level of fill color can outline the shape of the element more clearly, such as Rate, Skeleton, etc. It can also be used as the Hover state of the third level of fill color, such as Table, etc.
|
||||
*/
|
||||
colorFillSecondary: string;
|
||||
|
||||
/**
|
||||
* @nameZH 三级填充色
|
||||
* @desc 三级填充色用于勾勒出元素形体的场景,如 Slider、Segmented 等。如无强调需求的情况下,建议使用三级填色作为默认填色。
|
||||
* @descEN The third level of fill color is used to outline the shape of the element, such as Slider, Segmented, etc. If there is no emphasis requirement, it is recommended to use the third level of fill color as the default fill color.
|
||||
*/
|
||||
colorFillTertiary: string;
|
||||
|
||||
/**
|
||||
* @nameZH 四级填充色
|
||||
* @desc 最弱一级的填充色,适用于不易引起注意的色块,例如斑马纹、区分边界的色块等。
|
||||
* @descEN The weakest level of fill color is suitable for color blocks that are not easy to attract attention, such as zebra stripes, color blocks that distinguish boundaries, etc.
|
||||
*/
|
||||
colorFillQuaternary: string;
|
||||
|
||||
@ -85,6 +92,7 @@ export interface ColorNeutralMapToken {
|
||||
/**
|
||||
* @nameZH 布局背景色
|
||||
* @desc 该色用于页面整体布局的背景色,只有需要在页面中处于 B1 的视觉层级时才会使用该 token,其他用法都是错误的
|
||||
* @descEN This color is used for the background color of the overall layout of the page. This token will only be used when it is necessary to be at the B1 visual level in the page. Other usages are wrong.
|
||||
*/
|
||||
colorBgLayout: string;
|
||||
|
||||
@ -98,12 +106,14 @@ export interface ColorNeutralMapToken {
|
||||
/**
|
||||
* @nameZH 浮层容器背景色
|
||||
* @desc 浮层容器背景色,在暗色模式下该 token 的色值会比 `colorBgContainer` 要亮一些。例如:模态框、弹出框、菜单等。
|
||||
* @descEN Container background color of the popup layer, in dark mode the color value of this token will be a little brighter than `colorBgContainer`. E.g: modal, pop-up, menu, etc.
|
||||
*/
|
||||
colorBgElevated: string;
|
||||
|
||||
/**
|
||||
* @nameZH 引起注意的背景色
|
||||
* @desc 该色用于引起用户强烈关注注意的背景色,目前只用在 Tooltip 的背景色上。
|
||||
* @descEN This color is used to draw the user's strong attention to the background color, and is currently only used in the background color of Tooltip.
|
||||
*/
|
||||
colorBgSpotlight: string;
|
||||
}
|
||||
|
@ -36,6 +36,8 @@ export interface StyleMapToken {
|
||||
* @nameZH 外部圆角
|
||||
* @nameEN Outer Border Radius
|
||||
* @default 4
|
||||
* @desc 外部圆角
|
||||
* @descEN Outer border radius
|
||||
*/
|
||||
borderRadiusOuter: number;
|
||||
}
|
||||
|
@ -69,6 +69,7 @@ export interface SeedToken extends PresetColorType {
|
||||
* @nameZH 字体
|
||||
* @nameEN Font family for default text
|
||||
* @desc Ant Design 的字体家族中优先使用系统默认的界面字体,同时提供了一套利于屏显的备用字体库,来维护在不同平台以及浏览器的显示下,字体始终保持良好的易读性和可读性,体现了友好、稳定和专业的特性。
|
||||
* @descEN The font family of Ant Design prioritizes the default interface font of the system, and provides a set of alternative font libraries that are suitable for screen display to maintain the readability and readability of the font under different platforms and browsers, reflecting the friendly, stable and professional characteristics.
|
||||
*/
|
||||
fontFamily: string;
|
||||
|
||||
@ -76,6 +77,7 @@ export interface SeedToken extends PresetColorType {
|
||||
* @nameZH 代码字体
|
||||
* @nameEN Font family for code text
|
||||
* @desc 代码字体,用于 Typography 内的 code、pre 和 kbd 类型的元素
|
||||
* @descEN Code font, used for code, pre and kbd elements in Typography
|
||||
*/
|
||||
fontFamilyCode: string;
|
||||
|
||||
@ -138,6 +140,8 @@ export interface SeedToken extends PresetColorType {
|
||||
|
||||
/**
|
||||
* @nameZH 组件箭头尺寸
|
||||
* @desc 组件箭头的尺寸
|
||||
* @descEN The size of the component arrow
|
||||
*/
|
||||
sizePopupArrow: number;
|
||||
|
||||
@ -251,6 +255,7 @@ export interface SeedToken extends PresetColorType {
|
||||
* @nameZH 线框风格
|
||||
* @nameEN Wireframe Style
|
||||
* @desc 用于将组件的视觉效果变为线框化,如果需要使用 V4 的效果,需要开启配置项
|
||||
* @descEN Used to change the visual effect of the component to wireframe, if you need to use the V4 effect, you need to enable the configuration item
|
||||
* @default false
|
||||
*/
|
||||
wireframe: boolean;
|
||||
|
@ -18,6 +18,7 @@ import formatToken from './util/alias';
|
||||
import type { FullToken } from './util/genComponentStyleHook';
|
||||
import genComponentStyleHook from './util/genComponentStyleHook';
|
||||
import statisticToken, { merge as mergeToken, statistic } from './util/statistic';
|
||||
import genPresetColor from './util/genPresetColor';
|
||||
|
||||
const defaultTheme = createTheme(defaultDerivative);
|
||||
|
||||
@ -31,6 +32,7 @@ export {
|
||||
// hooks
|
||||
useStyleRegister,
|
||||
genComponentStyleHook,
|
||||
genPresetColor,
|
||||
};
|
||||
export type {
|
||||
SeedToken,
|
||||
|
@ -2,11 +2,11 @@
|
||||
import type { CSSInterpolation } from '@ant-design/cssinjs';
|
||||
import { useStyleRegister } from '@ant-design/cssinjs';
|
||||
import { useContext } from 'react';
|
||||
import { genCommonStyle, genLinkStyle } from '../../style';
|
||||
import { ConfigContext } from '../../config-provider/context';
|
||||
import { genCommonStyle, genLinkStyle } from '../../style';
|
||||
import type { ComponentTokenMap, GlobalToken } from '../interface';
|
||||
import type { UseComponentStyleResult } from '../internal';
|
||||
import { mergeToken, statisticToken, useToken } from '../internal';
|
||||
import type { ComponentTokenMap, GlobalToken } from '../interface';
|
||||
|
||||
export type OverrideTokenWithoutDerivative = ComponentTokenMap;
|
||||
export type OverrideComponent = keyof OverrideTokenWithoutDerivative;
|
||||
@ -44,11 +44,19 @@ export default function genComponentStyleHook<ComponentName extends OverrideComp
|
||||
) {
|
||||
return (prefixCls: string): UseComponentStyleResult => {
|
||||
const [theme, token, hashId] = useToken();
|
||||
const { getPrefixCls, iconPrefixCls } = useContext(ConfigContext);
|
||||
const { getPrefixCls, iconPrefixCls, csp } = useContext(ConfigContext);
|
||||
const rootPrefixCls = getPrefixCls();
|
||||
|
||||
// Shared config
|
||||
const sharedConfig: Omit<Parameters<typeof useStyleRegister>[0], 'path'> = {
|
||||
theme,
|
||||
token,
|
||||
hashId,
|
||||
nonce: () => csp?.nonce!,
|
||||
};
|
||||
|
||||
// Generate style for all a tags in antd component.
|
||||
useStyleRegister({ theme, token, hashId, path: ['Shared', rootPrefixCls] }, () => [
|
||||
useStyleRegister({ ...sharedConfig, path: ['Shared', rootPrefixCls] }, () => [
|
||||
{
|
||||
// Link
|
||||
'&': genLinkStyle(token),
|
||||
@ -56,40 +64,37 @@ export default function genComponentStyleHook<ComponentName extends OverrideComp
|
||||
]);
|
||||
|
||||
return [
|
||||
useStyleRegister(
|
||||
{ theme, token, hashId, path: [component, prefixCls, iconPrefixCls] },
|
||||
() => {
|
||||
const { token: proxyToken, flush } = statisticToken(token);
|
||||
useStyleRegister({ ...sharedConfig, path: [component, prefixCls, iconPrefixCls] }, () => {
|
||||
const { token: proxyToken, flush } = statisticToken(token);
|
||||
|
||||
const defaultComponentToken =
|
||||
typeof getDefaultToken === 'function' ? getDefaultToken(proxyToken) : getDefaultToken;
|
||||
const mergedComponentToken = { ...defaultComponentToken, ...token[component] };
|
||||
const defaultComponentToken =
|
||||
typeof getDefaultToken === 'function' ? getDefaultToken(proxyToken) : getDefaultToken;
|
||||
const mergedComponentToken = { ...defaultComponentToken, ...token[component] };
|
||||
|
||||
const componentCls = `.${prefixCls}`;
|
||||
const mergedToken = mergeToken<
|
||||
TokenWithCommonCls<GlobalTokenWithComponent<OverrideComponent>>
|
||||
>(
|
||||
proxyToken,
|
||||
{
|
||||
componentCls,
|
||||
prefixCls,
|
||||
iconCls: `.${iconPrefixCls}`,
|
||||
antCls: `.${rootPrefixCls}`,
|
||||
},
|
||||
mergedComponentToken,
|
||||
);
|
||||
|
||||
const styleInterpolation = styleFn(mergedToken as unknown as FullToken<ComponentName>, {
|
||||
hashId,
|
||||
const componentCls = `.${prefixCls}`;
|
||||
const mergedToken = mergeToken<
|
||||
TokenWithCommonCls<GlobalTokenWithComponent<OverrideComponent>>
|
||||
>(
|
||||
proxyToken,
|
||||
{
|
||||
componentCls,
|
||||
prefixCls,
|
||||
rootPrefixCls,
|
||||
iconPrefixCls,
|
||||
overrideComponentToken: token[component],
|
||||
});
|
||||
flush(component, mergedComponentToken);
|
||||
return [genCommonStyle(token, prefixCls), styleInterpolation];
|
||||
},
|
||||
),
|
||||
iconCls: `.${iconPrefixCls}`,
|
||||
antCls: `.${rootPrefixCls}`,
|
||||
},
|
||||
mergedComponentToken,
|
||||
);
|
||||
|
||||
const styleInterpolation = styleFn(mergedToken as unknown as FullToken<ComponentName>, {
|
||||
hashId,
|
||||
prefixCls,
|
||||
rootPrefixCls,
|
||||
iconPrefixCls,
|
||||
overrideComponentToken: token[component],
|
||||
});
|
||||
flush(component, mergedComponentToken);
|
||||
return [genCommonStyle(token, prefixCls), styleInterpolation];
|
||||
}),
|
||||
hashId,
|
||||
];
|
||||
};
|
||||
|
@ -1,8 +1,8 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import type { CSSObject } from '@ant-design/cssinjs';
|
||||
import type { AliasToken, PresetColorKey } from '../theme/internal';
|
||||
import { PresetColors } from '../theme/internal';
|
||||
import type { TokenWithCommonCls } from '../theme/util/genComponentStyleHook';
|
||||
import type { AliasToken, PresetColorKey } from '../internal';
|
||||
import { PresetColors } from '../interface';
|
||||
import type { TokenWithCommonCls } from './genComponentStyleHook';
|
||||
|
||||
interface CalcColor {
|
||||
/** token[`${colorKey}-1`] */
|
||||
@ -17,7 +17,7 @@ interface CalcColor {
|
||||
|
||||
type GenCSS = (colorKey: PresetColorKey, calcColor: CalcColor) => CSSObject;
|
||||
|
||||
export function genPresetColor<Token extends TokenWithCommonCls<AliasToken>>(
|
||||
export default function genPresetColor<Token extends TokenWithCommonCls<AliasToken>>(
|
||||
token: Token,
|
||||
genCss: GenCSS,
|
||||
): CSSObject {
|
@ -1,8 +1,8 @@
|
||||
import { genPresetColor, resetComponent } from '../../style';
|
||||
import { resetComponent } from '../../style';
|
||||
import { initZoomMotion } from '../../style/motion';
|
||||
import getArrowStyle, { MAX_VERTICAL_CONTENT_RADIUS } from '../../style/placementArrow';
|
||||
import type { FullToken, GenerateStyle, UseComponentStyleResult } from '../../theme/internal';
|
||||
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
|
||||
import { genComponentStyleHook, mergeToken, genPresetColor } from '../../theme/internal';
|
||||
|
||||
export interface ComponentToken {
|
||||
zIndexPopup: number;
|
||||
|
@ -66,7 +66,10 @@ export interface TreeSelectProps<
|
||||
rootClassName?: string;
|
||||
}
|
||||
|
||||
const InternalTreeSelect = <OptionType extends BaseOptionType | DefaultOptionType = BaseOptionType>(
|
||||
const InternalTreeSelect = <
|
||||
ValueType = any,
|
||||
OptionType extends BaseOptionType | DefaultOptionType = BaseOptionType,
|
||||
>(
|
||||
{
|
||||
prefixCls: customizePrefixCls,
|
||||
size: customizeSize,
|
||||
@ -92,7 +95,7 @@ const InternalTreeSelect = <OptionType extends BaseOptionType | DefaultOptionTyp
|
||||
showArrow,
|
||||
treeExpandAction,
|
||||
...props
|
||||
}: TreeSelectProps<OptionType>,
|
||||
}: TreeSelectProps<ValueType, OptionType>,
|
||||
ref: React.Ref<BaseSelectRef>,
|
||||
) => {
|
||||
const {
|
||||
|
@ -152,6 +152,10 @@ Basic text writing, including headings, body text, lists, and more.
|
||||
| onEllipsis | Called when enter or leave ellipsis state | function(ellipsis) | - | 4.2.0 |
|
||||
| onExpand | Called when expand content | function(event) | - | |
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Typography"></ComponentTokenTable>
|
||||
|
||||
## FAQ
|
||||
|
||||
### How to use Typography.Link in react-router?
|
||||
|
@ -153,6 +153,10 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*LT2jR41Uj2EAAA
|
||||
| onEllipsis | 触发省略时的回调 | function(ellipsis) | - | 4.2.0 |
|
||||
| onExpand | 点击展开时的回调 | function(event) | - | |
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Typography"></ComponentTokenTable>
|
||||
|
||||
## FAQ
|
||||
|
||||
### Typography.Link 如何与 react-router 库集成?
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "antd",
|
||||
"version": "5.3.2",
|
||||
"version": "5.3.3",
|
||||
"description": "An enterprise-class UI design language and React components implementation",
|
||||
"title": "Ant Design",
|
||||
"keywords": [
|
||||
@ -108,7 +108,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "^7.0.0",
|
||||
"@ant-design/cssinjs": "^1.5.6",
|
||||
"@ant-design/cssinjs": "^1.7.1",
|
||||
"@ant-design/icons": "^5.0.0",
|
||||
"@ant-design/react-slick": "~1.0.0",
|
||||
"@babel/runtime": "^7.18.3",
|
||||
@ -131,7 +131,7 @@
|
||||
"rc-input": "~1.0.4",
|
||||
"rc-input-number": "~7.4.0",
|
||||
"rc-mentions": "~2.2.0",
|
||||
"rc-menu": "~9.8.2",
|
||||
"rc-menu": "~9.8.3",
|
||||
"rc-motion": "^2.6.1",
|
||||
"rc-notification": "~5.0.0",
|
||||
"rc-pagination": "~3.3.1",
|
||||
|
2
typings/custom-typings.d.ts
vendored
2
typings/custom-typings.d.ts
vendored
@ -8,8 +8,6 @@ declare module '*.svg' {
|
||||
export default src;
|
||||
}
|
||||
|
||||
declare module 'rc-pagination/*';
|
||||
|
||||
declare module 'rc-util*';
|
||||
|
||||
declare module 'jsonml.js/*';
|
||||
|
Loading…
Reference in New Issue
Block a user