mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-11-29 18:50:00 +08:00
merge master
This commit is contained in:
commit
7a12b2b1ae
22
.jest.site.js
Normal file
22
.jest.site.js
Normal file
@ -0,0 +1,22 @@
|
||||
const { moduleNameMapper, transformIgnorePatterns } = require('./.jest');
|
||||
|
||||
// jest config for server render environment
|
||||
module.exports = {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'md'],
|
||||
moduleNameMapper,
|
||||
transform: {
|
||||
'\\.tsx?$': './node_modules/@ant-design/tools/lib/jest/codePreprocessor',
|
||||
'\\.js$': './node_modules/@ant-design/tools/lib/jest/codePreprocessor',
|
||||
'\\.md$': './node_modules/@ant-design/tools/lib/jest/demoPreprocessor',
|
||||
'\\.(jpg|png|gif|svg)$': './node_modules/@ant-design/tools/lib/jest/imagePreprocessor',
|
||||
},
|
||||
testRegex: 'check-site\\.js$',
|
||||
testEnvironment: 'node',
|
||||
transformIgnorePatterns,
|
||||
snapshotSerializers: ['enzyme-to-json/serializer'],
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
tsConfigFile: './tsconfig.test.json',
|
||||
},
|
||||
},
|
||||
};
|
@ -15,6 +15,41 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
## 3.24.3
|
||||
|
||||
`2019-10-26`
|
||||
|
||||
- 🐞 Fix Table sort not working when `columns` inside render. [#19404](https://github.com/ant-design/ant-design/pull/19404)
|
||||
- 🐞 Fix Grid responsive `gutter` not working. [#19308](https://github.com/ant-design/ant-design/pull/19308)
|
||||
- 🐞 Fix small Table border style. [#19312](https://github.com/ant-design/ant-design/pull/19312) [#19342](https://github.com/ant-design/ant-design/pull/19342)
|
||||
- 🐞 Fix the problem that Menu in Dropdown is not highlighted when SubMenu is selected. [#19313](https://github.com/ant-design/ant-design/pull/19313)
|
||||
- 🐞 Fix the problem that moment.js in Typography & Drawer & Statistic can't be tree-shaking. [#19317](https://github.com/ant-design/ant-design/pull/19317)
|
||||
- 🐞 Fix Input.Search react warnings of `non-boolean attribute` and `unique key`. [#19357](https://github.com/ant-design/ant-design/pull/19357)
|
||||
- 🐞 Fix Modal icon position when not use title. [#19419](https://github.com/ant-design/ant-design/pull/19419)
|
||||
- 💄 Fix a problem with the mouse pointer error when Checkbox is disabled. [#19403](https://github.com/ant-design/ant-design/pull/19403)
|
||||
- 💄 Add `@modal-header-color` variable. [#19385](https://github.com/ant-design/ant-design/pull/19385)
|
||||
- 🛠 Improved some TypeScript definitions. [#19377](https://github.com/ant-design/ant-design/pull/19377) [#19343](https://github.com/ant-design/ant-design/pull/19343) [#19333](https://github.com/ant-design/ant-design/pull/19333)
|
||||
|
||||
## 3.24.2
|
||||
|
||||
`2019-10-19`
|
||||
|
||||
- 🐞 Fix Table `scroll={{ x: 'max-content' }}` rendered without scrollbar problem in Chrome. [#19284](https://github.com/ant-design/ant-design/pull/19284)
|
||||
- 🐞 Fix Table crash when passing `column.filterDropdown` as new prop. [#19302](https://github.com/ant-design/ant-design/pull/19302)
|
||||
- 🐞 Fix Upload `download` button trigger preview unexpectedly. [#19268](https://github.com/ant-design/ant-design/pull/19268) [@qq645381995](https://github.com/qq645381995)
|
||||
- 🐞 Fix Comment long author name breaks on small screen. [#19272](https://github.com/ant-design/ant-design/pull/19272) [@rayronvictor](https://github.com/rayronvictor)
|
||||
- Typescript
|
||||
- 🐞 Improve RangePicker `value` types. [#19300](https://github.com/ant-design/ant-design/pull/19300) [@neung123](https://github.com/neung123)
|
||||
- 🐞 Improve Select `mode` types. [#19286](https://github.com/ant-design/ant-design/pull/19286) [@wleven](https://github.com/wleven)
|
||||
- 🐞 Improve Upload `customRequest` types. [#19278](https://github.com/ant-design/ant-design/pull/19278) [@broder](https://github.com/broder)
|
||||
|
||||
## 3.24.1
|
||||
|
||||
`2019-10-17`
|
||||
|
||||
- 🐞 Fix Table throw `React.createRef is not a function error` in old version of React . [#19262](https://github.com/ant-design/ant-design/pull/19262)
|
||||
- 🐞 Fix Table TypeScript definition missing Column and ColumnGroup. [#19251](https://github.com/ant-design/ant-design/pull/19251)
|
||||
|
||||
## 3.24.0
|
||||
|
||||
`2019-10-16`
|
||||
|
@ -15,6 +15,41 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
## 3.24.3
|
||||
|
||||
`2019-10-26`
|
||||
|
||||
- 🐞 修复 Table `columns` 在 render 中会导致排序失效的问题。[#19404](https://github.com/ant-design/ant-design/pull/19404)
|
||||
- 🐞 修复 Grid 响应式 `gutter` 失效的问题。[#19308](https://github.com/ant-design/ant-design/pull/19308)
|
||||
- 🐞 修复小号 Table 边框样式问题。[#19312](https://github.com/ant-design/ant-design/pull/19312) [#19342](https://github.com/ant-design/ant-design/pull/19342)
|
||||
- 🐞 修复 Dropdown 中的 Menu 在 SubMenu 选中后父级菜单未高亮的问题。[#19313](https://github.com/ant-design/ant-design/pull/19313)
|
||||
- 🐞 修复 Typography & Drawer & Statistic 中的 moment.js 无法被 tree-shaking 的问题。[#19317](https://github.com/ant-design/ant-design/pull/19317)
|
||||
- 🐞 修复 Input.Search 出现 `non-boolean attribute` 和 `unique key` 警告信息。[#19357](https://github.com/ant-design/ant-design/pull/19357)
|
||||
- 🐞 修复 Modal 没有标题时,图标没能对齐的问题。[#19419](https://github.com/ant-design/ant-design/pull/19419)
|
||||
- 💄 修复 Checkbox 在被禁用时,光标仍为可选状态的问题。[#19403](https://github.com/ant-design/ant-design/pull/19403)
|
||||
- 💄 新增 `@modal-header-color` 变量。[#19385](https://github.com/ant-design/ant-design/pull/19385)
|
||||
- 🛠 多处 TypeScript 的定义更新。[#19377](https://github.com/ant-design/ant-design/pull/19377) [#19343](https://github.com/ant-design/ant-design/pull/19343) [#19333](https://github.com/ant-design/ant-design/pull/19333)
|
||||
|
||||
## 3.24.2
|
||||
|
||||
`2019-10-19`
|
||||
|
||||
- 🐞 修复 Table `scroll.x` 设置 `max-content` 无效导致横向滚动消失的问题。[#19284](https://github.com/ant-design/ant-design/pull/19284)
|
||||
- 🐞 修复 Table 将 `column.filterDropdown` 作为新属性设置时报错的问题。[#19302](https://github.com/ant-design/ant-design/pull/19302)
|
||||
- 🐞 Fix Upload 点击下载按钮会触发预览的问题。[#19268](https://github.com/ant-design/ant-design/pull/19268) [@qq645381995](https://github.com/qq645381995)
|
||||
- 🐞 修复 Comment 长作者名在小屏幕上破坏布局的问题。[#19272](https://github.com/ant-design/ant-design/pull/19272) [@rayronvictor](https://github.com/rayronvictor)
|
||||
- Typescript
|
||||
- 🐞 优化 RangePicker `value` 属性定义。[#19300](https://github.com/ant-design/ant-design/pull/19300) [@neung123](https://github.com/neung123)
|
||||
- 🐞 优化 Select `mode` 属性定义。[#19286](https://github.com/ant-design/ant-design/pull/19286) [@wleven](https://github.com/wleven)
|
||||
- 🐞 优化 Upload `customRequest` 属性定义。[#19278](https://github.com/ant-design/ant-design/pull/19278) [@broder](https://github.com/broder)
|
||||
|
||||
## 3.24.1
|
||||
|
||||
`2019-10-17`
|
||||
|
||||
- 🐞 修复 Table 在旧版 React 会报 `React.createRef is not a function` 的错误信息。[#19262](https://github.com/ant-design/ant-design/pull/19262)
|
||||
- 🐞 修复 Table TypeScript 定义丢失 Column 和 ColumnGroup 的问题。[#19251](https://github.com/ant-design/ant-design/pull/19251)
|
||||
|
||||
## 3.24.0
|
||||
|
||||
`2019-10-16`
|
||||
@ -1700,7 +1735,7 @@ timeline: true
|
||||
- Upload 组件升级 `rc-upload` 到 `2.5.0`
|
||||
- 🌟 新增 `directory` 属性,支持上传一个文件夹。[#7315](https://github.com/ant-design/ant-design/issues/7315)
|
||||
- 🌟 `action` 属性支持作为一个返回 `Promise` 对象的函数,使用更加灵活。[fd96967](https://github.com/ant-design/ant-design/commit/fd96967c872600b79bb608e9ddf9f8c38814a704)
|
||||
- Dropdown 增加新特性, 可以做为右键菜单来使用。
|
||||
- Dropdown 增加新特性,可以做为右键菜单来使用。
|
||||
- 🌟 给菜单项的 icon 提供默认的外间距样式。[8e60a59](https://github.com/ant-design/ant-design/commit/8e60a591fd24f644de4f67d69c2210e9270be9cc)
|
||||
- 🌟 触发方式为 `contextMenu` 时自动调整菜单的位置。[16e4260](https://github.com/ant-design/ant-design/commit/16e42601d6772fc0830ee237a1e751a38a118676)
|
||||
- Table 组件升级 `rc-table` 到 `6.2.2`。[f2fddff](https://github.com/ant-design/ant-design/commit/f2fddff3fd0d6b36e8e6d8ee06bfcbcc85ead4f0)
|
||||
@ -1831,7 +1866,7 @@ timeline: true
|
||||
- 💄 统一 less 的变量命名 [12d3046](https://github.com/ant-design/ant-design/commit/12d3046687a0dcdb51fece08dd2bea64f185cc40)
|
||||
- 💄 微调了 `Dropdown` 的样式 [8e2f72f](https://github.com/ant-design/ant-design/commit/8e2f72ffe0eb300f5997296726b02246bf990c8f)
|
||||
- 💄 现在中文文档的组件会用中文语言包进行演示。[9b17a94](https://github.com/ant-design/ant-design/commit/9b17a943f5d57d40d65041b7b0c247add09d2851)
|
||||
- 💄 主站主题切换 修改为 `antd-theme-generato` ,感谢 [@mzohaibqc](https://github.com/mzohaibqc) 的工作.
|
||||
- 💄 主站主题切换 修改为 `antd-theme-generator` ,感谢 [@mzohaibqc](https://github.com/mzohaibqc) 的工作.
|
||||
- TypeScript
|
||||
- 🐞 修复了 `Row` 中 gutter 属性的类型问题 [b7d508e](https://github.com/ant-design/ant-design/commit/b7d508e1662bf20a0cacbe6440a2ce31a65a8a59)
|
||||
- 💄 改进了 `Form` 组件类型 [#10564](https://github.com/ant-design/ant-design/pull/10564)
|
||||
@ -1842,7 +1877,7 @@ timeline: true
|
||||
`2018-05-13`
|
||||
|
||||
- 🐞 修复 `Table` 过滤器和 `Transfer` 复选框无法点击的问题。[#10452](https://github.com/ant-design/ant-design/issues/10452)
|
||||
- 🐞 修复 `Cascader` 的 `displayRender` 里的链接无法点击的问题。[#10433](https://github.com/ant-design/ant-design/issues/10433)
|
||||
- 🐞 修复 `Cascader` 的 `displayRender` 里的链接无法点击的问题。[#10433](https://github.com/ant-design/ant-design/issues/10433)
|
||||
- 🐞 修复 `Button` ref 不兼容问题。[#10405](https://github.com/ant-design/ant-design/issues/10405)
|
||||
- 🐞 修复 `Form` 表单项校验位置高度时出现抖动问题。[#10445](https://github.com/ant-design/ant-design/issues/10445)
|
||||
- 🌟 设置 `Layout` 宽度时,允许使用任何的 CSS 单位。[#10479](https://github.com/ant-design/ant-design/pull/10479)
|
||||
@ -1964,7 +1999,7 @@ timeline: true
|
||||
- 🌟 新增 `defaultExpandParent` 用于在第一次渲染时自动展开父节点。
|
||||
- 🌟 新增 `disabled` 用于禁用整棵树。
|
||||
- 🌟 TreeNode 新增 `icon` 用于设置自定义图标。
|
||||
- 🌟 优化了 TreeNode 设置 `disabled` 时的 勾选逻辑。
|
||||
- 🌟 优化了 TreeNode 设置 `disabled` 时的勾选逻辑。
|
||||
- 🌟 Anchor 新增 `getContainer` 用于指定内容滚动的容器。
|
||||
- 🌟 Table 新增 less 变量 `@table-expanded-row-bg`。[#9789](https://github.com/ant-design/ant-design/pull/9789)
|
||||
- 🐞 修复一处 less 语法错误。[#9832](https://github.com/ant-design/ant-design/pull/9832) [@jojoLockLock](https://github.com/jojoLockLock)
|
||||
|
12
CODEOWNERS
Normal file
12
CODEOWNERS
Normal file
@ -0,0 +1,12 @@
|
||||
# CODEOWNERS syntax
|
||||
# A CODEOWNERS file uses a pattern that follows the same rules used in gitignore files.
|
||||
# The pattern is followed by one or more GitHub usernames or team names using the standard @username or @org/team-name format.
|
||||
# You can also refer to a user by an email address that has been added to their GitHub account, for example user@example.com.
|
||||
|
||||
# no default file owner
|
||||
#/* @afc163
|
||||
/components/tree/* @zombieJ
|
||||
/components/tree-select/* @zombieJ
|
||||
|
||||
# ...
|
||||
# other components
|
@ -4,11 +4,11 @@ type: Navigation
|
||||
title: Affix
|
||||
---
|
||||
|
||||
Make an element stick to viewport.
|
||||
Wrap Affix around another component to make it stick the viewport.
|
||||
|
||||
## When To Use
|
||||
|
||||
When user browses a long web page, some content need to stick to the viewport. This is common for menus and actions.
|
||||
On longer web pages, its helpful for some content to stick to the viewport. This is common for menus and actions.
|
||||
|
||||
Please note that Affix should not cover other content on the page, especially when the size of the viewport is small.
|
||||
|
||||
@ -16,12 +16,12 @@ Please note that Affix should not cover other content on the page, especially wh
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| offsetBottom | Pixels to offset from bottom when calculating position of scroll | number | - | |
|
||||
| offsetTop | Pixels to offset from top when calculating position of scroll | number | 0 | |
|
||||
| target | specifies the scrollable area dom node | () => HTMLElement | () => window | |
|
||||
| onChange | Callback for when affix state is changed | Function(affixed) | - | |
|
||||
| offsetBottom | Offset from the bottom of the viewport (in pixels) | number | - | |
|
||||
| offsetTop | Offset from the top of the viewport (in pixels) | number | 0 | |
|
||||
| target | Specifies the scrollable area DOM node | () => HTMLElement | () => window | |
|
||||
| onChange | Callback for when Affix state is changed | Function(affixed) | - | |
|
||||
|
||||
**Note:** Children of `Affix` can not be `position: absolute`, but you can set `Affix` as `position: absolute`:
|
||||
**Note:** Children of `Affix` must not have the property `position: absolute`, but you can set `position: absolute` on `Affix` itself:
|
||||
|
||||
```jsx
|
||||
<Affix style={{ position: 'absolute', top: y, left: x }}>...</Affix>
|
||||
@ -33,4 +33,4 @@ Please note that Affix should not cover other content on the page, especially wh
|
||||
|
||||
We don't listen window scroll for performance consideration. You can add listener if you still want: <https://codesandbox.io/s/2xyj5zr85p>
|
||||
|
||||
Related issue:[#3938](https://github.com/ant-design/ant-design/issues/3938) [#5642](https://github.com/ant-design/ant-design/issues/5642) [#16120](https://github.com/ant-design/ant-design/issues/16120)
|
||||
Related issues:[#3938](https://github.com/ant-design/ant-design/issues/3938) [#5642](https://github.com/ant-design/ant-design/issues/5642) [#16120](https://github.com/ant-design/ant-design/issues/16120)
|
||||
|
@ -66,7 +66,7 @@ const iconMapOutlined = {
|
||||
|
||||
export default class Alert extends React.Component<AlertProps, AlertState> {
|
||||
state = {
|
||||
closing: true,
|
||||
closing: false,
|
||||
closed: false,
|
||||
};
|
||||
|
||||
@ -79,15 +79,15 @@ export default class Alert extends React.Component<AlertProps, AlertState> {
|
||||
dom.style.height = `${dom.offsetHeight}px`;
|
||||
|
||||
this.setState({
|
||||
closing: false,
|
||||
closing: true,
|
||||
});
|
||||
(this.props.onClose || noop)(e);
|
||||
};
|
||||
|
||||
animationEnd = () => {
|
||||
this.setState({
|
||||
closing: false,
|
||||
closed: true,
|
||||
closing: true,
|
||||
});
|
||||
(this.props.afterClose || noop)();
|
||||
};
|
||||
@ -104,6 +104,7 @@ export default class Alert extends React.Component<AlertProps, AlertState> {
|
||||
icon,
|
||||
} = this.props;
|
||||
let { closable, type, showIcon } = this.props;
|
||||
const { closing, closed } = this.state;
|
||||
|
||||
const prefixCls = getPrefixCls('alert', customizePrefixCls);
|
||||
|
||||
@ -124,7 +125,7 @@ export default class Alert extends React.Component<AlertProps, AlertState> {
|
||||
prefixCls,
|
||||
`${prefixCls}-${type}`,
|
||||
{
|
||||
[`${prefixCls}-close`]: !this.state.closing,
|
||||
[`${prefixCls}-closing`]: closing,
|
||||
[`${prefixCls}-with-description`]: !!description,
|
||||
[`${prefixCls}-no-icon`]: !showIcon,
|
||||
[`${prefixCls}-banner`]: !!banner,
|
||||
@ -150,9 +151,8 @@ export default class Alert extends React.Component<AlertProps, AlertState> {
|
||||
(icon &&
|
||||
(React.isValidElement<{ className?: string }>(icon) ? (
|
||||
React.cloneElement(icon, {
|
||||
className: classNames({
|
||||
className: classNames(`${prefixCls}-icon`, {
|
||||
[icon.props.className as string]: icon.props.className,
|
||||
[`${prefixCls}-icon`]: true,
|
||||
}),
|
||||
})
|
||||
) : (
|
||||
@ -160,14 +160,14 @@ export default class Alert extends React.Component<AlertProps, AlertState> {
|
||||
))) ||
|
||||
React.createElement(iconType, { className: `${prefixCls}-icon` });
|
||||
|
||||
return this.state.closed ? null : (
|
||||
return closed ? null : (
|
||||
<Animate
|
||||
component=""
|
||||
showProp="data-show"
|
||||
transitionName={`${prefixCls}-slide-up`}
|
||||
onEnd={this.animationEnd}
|
||||
>
|
||||
<div data-show={this.state.closing} className={alertCls} style={style} {...dataOrAriaProps}>
|
||||
<div data-show={!closing} className={alertCls} style={style} {...dataOrAriaProps}>
|
||||
{showIcon ? iconNode : null}
|
||||
<span className={`${prefixCls}-message`}>{message}</span>
|
||||
<span className={`${prefixCls}-description`}>{description}</span>
|
||||
|
@ -77,6 +77,7 @@
|
||||
line-height: 22px;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
|
||||
.@{iconfont-css-prefix}-close {
|
||||
@ -138,7 +139,7 @@
|
||||
display: block;
|
||||
}
|
||||
|
||||
&&-close {
|
||||
&&-closing {
|
||||
height: 0 !important;
|
||||
margin: 0;
|
||||
padding-top: 0;
|
||||
|
@ -149,7 +149,8 @@ export default class Breadcrumb extends React.Component<BreadcrumbProps, any> {
|
||||
|
||||
warning(
|
||||
element.type &&
|
||||
(element.type.__ANT_BREADCRUMB_ITEM || element.type.__ANT_BREADCRUMB_SEPARATOR),
|
||||
(element.type.__ANT_BREADCRUMB_ITEM === true ||
|
||||
element.type.__ANT_BREADCRUMB_SEPARATOR === true),
|
||||
'Breadcrumb',
|
||||
"Only accepts Breadcrumb.Item and Breadcrumb.Separator as it's children",
|
||||
);
|
||||
|
@ -29,15 +29,15 @@ To get a customized button, just set `type`/`shape`/`size`/`loading`/`disabled`.
|
||||
| onClick | set the handler to handle `click` event | (event) => void | - | |
|
||||
| block | option to fit button width to its parent width | boolean | `false` | 3.8.0 |
|
||||
|
||||
It accepts all props which native button support.
|
||||
It accepts all props which native buttons support.
|
||||
|
||||
## FAQ
|
||||
|
||||
### How to remove space between 2 chinese characters?
|
||||
### How to remove space between 2 chinese characters
|
||||
|
||||
Following Ant Design specification, we will add one space between if Button contains two chinese characters only. If you don't need that, you can use [ConfigProvider](/components/config-provider/#API) to set `autoInsertSpaceInButton` as `false`.
|
||||
Following the Ant Design specification, we will add one space between if Button contains two Chinese characters only. If you don't need that, you can use [ConfigProvider](/components/config-provider/#API) to set `autoInsertSpaceInButton` as `false`.
|
||||
|
||||
![](https://gw.alipayobjects.com/zos/antfincdn/Hz5HL9gsT4/f29f170d-b78d-4d2b-aa71-0da6a9ead4d9.png)
|
||||
![Button with two Chinese characters](https://gw.alipayobjects.com/zos/antfincdn/Hz5HL9gsT4/f29f170d-b78d-4d2b-aa71-0da6a9ead4d9.png)
|
||||
|
||||
<style>
|
||||
[id^=components-button-demo-] .ant-btn {
|
||||
|
@ -124,6 +124,9 @@
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
> .@{btnClassName}-icon-only {
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
// size
|
||||
&-lg > .@{btnClassName},
|
||||
&-lg > span > .@{btnClassName} {
|
||||
|
@ -72,9 +72,3 @@ interface Option {
|
||||
| ------- | ------------ | ------- |
|
||||
| blur() | remove focus | |
|
||||
| focus() | get focus | |
|
||||
|
||||
<style>
|
||||
.ant-cascader-picker {
|
||||
width: 300px;
|
||||
}
|
||||
</style>
|
||||
|
@ -74,10 +74,4 @@ interface Option {
|
||||
| blur() | 移除焦点 | |
|
||||
| focus() | 获取焦点 | |
|
||||
|
||||
<style>
|
||||
.ant-cascader-picker {
|
||||
width: 300px;
|
||||
}
|
||||
</style>
|
||||
|
||||
> 注意,如果需要获得中国省市区数据,可以参考 [china-division](https://gist.github.com/afc163/7582f35654fd03d5be7009444345ea17)。
|
||||
|
@ -61,7 +61,7 @@
|
||||
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 21%;
|
||||
left: 22%;
|
||||
display: table;
|
||||
width: @check-width;
|
||||
height: @check-height;
|
||||
@ -151,6 +151,9 @@
|
||||
display: inline-block;
|
||||
line-height: unset;
|
||||
cursor: pointer;
|
||||
&.@{checkbox-prefix-cls}-wrapper-disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
& + & {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
@ -32,12 +32,12 @@
|
||||
|
||||
&-author {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
margin-bottom: 4px;
|
||||
font-size: @comment-font-size-base;
|
||||
& > a,
|
||||
& > span {
|
||||
height: 18px;
|
||||
padding-right: 8px;
|
||||
font-size: @comment-font-size-sm;
|
||||
line-height: 18px;
|
||||
|
@ -17700,62 +17700,62 @@ exports[`ConfigProvider components Upload configProvider 1`] = `
|
||||
title="xxx.png"
|
||||
>
|
||||
xxx.png
|
||||
<span
|
||||
class="config-upload-list-item-card-actions "
|
||||
</span>
|
||||
<span
|
||||
class="config-upload-list-item-card-actions "
|
||||
>
|
||||
<a
|
||||
title="Download file"
|
||||
>
|
||||
<a
|
||||
<span
|
||||
aria-label="download"
|
||||
class="anticon anticon-download"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
title="Download file"
|
||||
>
|
||||
<span
|
||||
aria-label="download"
|
||||
class="anticon anticon-download"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
title="Download file"
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="download"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="download"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M505.7 661a8 8 0 0012.6 0l112-141.7c4.1-5.2.4-12.9-6.3-12.9h-74.1V168c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v338.3H400c-6.7 0-10.4 7.7-6.3 12.9l112 141.8zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
<path
|
||||
d="M505.7 661a8 8 0 0012.6 0l112-141.7c4.1-5.2.4-12.9-6.3-12.9h-74.1V168c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v338.3H400c-6.7 0-10.4 7.7-6.3 12.9l112 141.8zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
title="Remove file"
|
||||
>
|
||||
<span
|
||||
aria-label="delete"
|
||||
class="anticon anticon-delete"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
title="Remove file"
|
||||
>
|
||||
<span
|
||||
aria-label="delete"
|
||||
class="anticon anticon-delete"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
title="Remove file"
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="delete"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="delete"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
</span>
|
||||
<path
|
||||
d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
@ -17806,62 +17806,62 @@ exports[`ConfigProvider components Upload normal 1`] = `
|
||||
title="xxx.png"
|
||||
>
|
||||
xxx.png
|
||||
<span
|
||||
class="ant-upload-list-item-card-actions "
|
||||
</span>
|
||||
<span
|
||||
class="ant-upload-list-item-card-actions "
|
||||
>
|
||||
<a
|
||||
title="Download file"
|
||||
>
|
||||
<a
|
||||
<span
|
||||
aria-label="download"
|
||||
class="anticon anticon-download"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
title="Download file"
|
||||
>
|
||||
<span
|
||||
aria-label="download"
|
||||
class="anticon anticon-download"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
title="Download file"
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="download"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="download"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M505.7 661a8 8 0 0012.6 0l112-141.7c4.1-5.2.4-12.9-6.3-12.9h-74.1V168c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v338.3H400c-6.7 0-10.4 7.7-6.3 12.9l112 141.8zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
<path
|
||||
d="M505.7 661a8 8 0 0012.6 0l112-141.7c4.1-5.2.4-12.9-6.3-12.9h-74.1V168c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v338.3H400c-6.7 0-10.4 7.7-6.3 12.9l112 141.8zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
title="Remove file"
|
||||
>
|
||||
<span
|
||||
aria-label="delete"
|
||||
class="anticon anticon-delete"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
title="Remove file"
|
||||
>
|
||||
<span
|
||||
aria-label="delete"
|
||||
class="anticon anticon-delete"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
title="Remove file"
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="delete"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="delete"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
</span>
|
||||
<path
|
||||
d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
@ -17912,62 +17912,62 @@ exports[`ConfigProvider components Upload prefixCls 1`] = `
|
||||
title="xxx.png"
|
||||
>
|
||||
xxx.png
|
||||
<span
|
||||
class="ant-upload-list-item-card-actions "
|
||||
</span>
|
||||
<span
|
||||
class="ant-upload-list-item-card-actions "
|
||||
>
|
||||
<a
|
||||
title="Download file"
|
||||
>
|
||||
<a
|
||||
<span
|
||||
aria-label="download"
|
||||
class="anticon anticon-download"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
title="Download file"
|
||||
>
|
||||
<span
|
||||
aria-label="download"
|
||||
class="anticon anticon-download"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
title="Download file"
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="download"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="download"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M505.7 661a8 8 0 0012.6 0l112-141.7c4.1-5.2.4-12.9-6.3-12.9h-74.1V168c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v338.3H400c-6.7 0-10.4 7.7-6.3 12.9l112 141.8zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
<path
|
||||
d="M505.7 661a8 8 0 0012.6 0l112-141.7c4.1-5.2.4-12.9-6.3-12.9h-74.1V168c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v338.3H400c-6.7 0-10.4 7.7-6.3 12.9l112 141.8zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
title="Remove file"
|
||||
>
|
||||
<span
|
||||
aria-label="delete"
|
||||
class="anticon anticon-delete"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
title="Remove file"
|
||||
>
|
||||
<span
|
||||
aria-label="delete"
|
||||
class="anticon anticon-delete"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
title="Remove file"
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="delete"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="delete"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
</span>
|
||||
<path
|
||||
d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
@ -61,6 +61,7 @@ jest.mock('rc-util/lib/Portal');
|
||||
describe('ConfigProvider', () => {
|
||||
describe('components', () => {
|
||||
function testPair(name, renderComponent) {
|
||||
// eslint-disable-next-line jest/valid-describe
|
||||
describe(`${name}`, () => {
|
||||
// normal
|
||||
it('normal', () => {
|
||||
|
@ -1,33 +0,0 @@
|
||||
import { createContext } from 'react';
|
||||
import defaultRenderEmpty, { RenderEmptyHandler } from './renderEmpty';
|
||||
import { Locale } from '../locale-provider';
|
||||
|
||||
export interface CSPConfig {
|
||||
nonce?: string;
|
||||
}
|
||||
|
||||
export interface ConfigConsumerProps {
|
||||
getPopupContainer?: (triggerNode: HTMLElement) => HTMLElement;
|
||||
rootPrefixCls?: string;
|
||||
getPrefixCls: (suffixCls: string, customizePrefixCls?: string) => string;
|
||||
renderEmpty: RenderEmptyHandler;
|
||||
csp?: CSPConfig;
|
||||
autoInsertSpaceInButton?: boolean;
|
||||
locale?: Locale;
|
||||
pageHeader?: {
|
||||
ghost: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export const ConfigContext = createContext<ConfigConsumerProps>({
|
||||
// We provide a default function for Context without provider
|
||||
getPrefixCls: (suffixCls: string, customizePrefixCls?: string) => {
|
||||
if (customizePrefixCls) return customizePrefixCls;
|
||||
|
||||
return `ant-${suffixCls}`;
|
||||
},
|
||||
|
||||
renderEmpty: defaultRenderEmpty,
|
||||
});
|
||||
|
||||
export const ConfigConsumer = ConfigContext.Consumer;
|
77
components/config-provider/context.tsx
Normal file
77
components/config-provider/context.tsx
Normal file
@ -0,0 +1,77 @@
|
||||
import * as React from 'react';
|
||||
import defaultRenderEmpty, { RenderEmptyHandler } from './renderEmpty';
|
||||
import { Locale } from '../locale-provider';
|
||||
|
||||
export interface CSPConfig {
|
||||
nonce?: string;
|
||||
}
|
||||
|
||||
export interface ConfigConsumerProps {
|
||||
getPopupContainer?: (triggerNode: HTMLElement) => HTMLElement;
|
||||
rootPrefixCls?: string;
|
||||
getPrefixCls: (suffixCls: string, customizePrefixCls?: string) => string;
|
||||
renderEmpty: RenderEmptyHandler;
|
||||
csp?: CSPConfig;
|
||||
autoInsertSpaceInButton?: boolean;
|
||||
locale?: Locale;
|
||||
pageHeader?: {
|
||||
ghost: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export const ConfigContext = React.createContext<ConfigConsumerProps>({
|
||||
// We provide a default function for Context without provider
|
||||
getPrefixCls: (suffixCls: string, customizePrefixCls?: string) => {
|
||||
if (customizePrefixCls) return customizePrefixCls;
|
||||
|
||||
return `ant-${suffixCls}`;
|
||||
},
|
||||
|
||||
renderEmpty: defaultRenderEmpty,
|
||||
});
|
||||
|
||||
export const ConfigConsumer = ConfigContext.Consumer;
|
||||
|
||||
// =========================== withConfigConsumer ===========================
|
||||
// We need define many types here. So let's put in the block region
|
||||
type IReactComponent<P = any> =
|
||||
| React.StatelessComponent<P>
|
||||
| React.ComponentClass<P>
|
||||
| React.ClassicComponentClass<P>;
|
||||
|
||||
interface BasicExportProps {
|
||||
prefixCls?: string;
|
||||
}
|
||||
|
||||
interface ConsumerConfig {
|
||||
prefixCls: string;
|
||||
}
|
||||
|
||||
interface ConstructorProps {
|
||||
displayName?: string;
|
||||
}
|
||||
export function withConfigConsumer<ExportProps extends BasicExportProps>(config: ConsumerConfig) {
|
||||
return function withConfigConsumerFunc<ComponentDef>(
|
||||
Component: IReactComponent,
|
||||
): React.SFC<ExportProps> & ComponentDef {
|
||||
// Wrap with ConfigConsumer. Since we need compatible with react 15, be care when using ref methods
|
||||
const SFC = ((props: ExportProps) => (
|
||||
<ConfigConsumer>
|
||||
{(configProps: ConfigConsumerProps) => {
|
||||
const { prefixCls: basicPrefixCls } = config;
|
||||
const { getPrefixCls } = configProps;
|
||||
const { prefixCls: customizePrefixCls } = props;
|
||||
const prefixCls = getPrefixCls(basicPrefixCls, customizePrefixCls);
|
||||
return <Component {...configProps} {...props} prefixCls={prefixCls} />;
|
||||
}}
|
||||
</ConfigConsumer>
|
||||
)) as React.SFC<ExportProps> & ComponentDef;
|
||||
|
||||
const cons: ConstructorProps = Component.constructor as ConstructorProps;
|
||||
const name = (cons && cons.displayName) || Component.name || 'Component';
|
||||
|
||||
SFC.displayName = `withConfigConsumer(${name})`;
|
||||
|
||||
return SFC;
|
||||
};
|
||||
}
|
@ -109,49 +109,4 @@ class ConfigProvider extends React.Component<ConfigProviderProps> {
|
||||
}
|
||||
}
|
||||
|
||||
// =========================== withConfigConsumer ===========================
|
||||
// We need define many types here. So let's put in the block region
|
||||
type IReactComponent<P = any> =
|
||||
| React.StatelessComponent<P>
|
||||
| React.ComponentClass<P>
|
||||
| React.ClassicComponentClass<P>;
|
||||
|
||||
interface BasicExportProps {
|
||||
prefixCls?: string;
|
||||
}
|
||||
|
||||
interface ConsumerConfig {
|
||||
prefixCls: string;
|
||||
}
|
||||
|
||||
interface ConstructorProps {
|
||||
displayName?: string;
|
||||
}
|
||||
|
||||
export function withConfigConsumer<ExportProps extends BasicExportProps>(config: ConsumerConfig) {
|
||||
return function withConfigConsumerFunc<ComponentDef>(
|
||||
Component: IReactComponent,
|
||||
): React.SFC<ExportProps> & ComponentDef {
|
||||
// Wrap with ConfigConsumer. Since we need compatible with react 15, be care when using ref methods
|
||||
const SFC = ((props: ExportProps) => (
|
||||
<ConfigConsumer>
|
||||
{(configProps: ConfigConsumerProps) => {
|
||||
const { prefixCls: basicPrefixCls } = config;
|
||||
const { getPrefixCls } = configProps;
|
||||
const { prefixCls: customizePrefixCls } = props;
|
||||
const prefixCls = getPrefixCls(basicPrefixCls, customizePrefixCls);
|
||||
return <Component {...configProps} {...props} prefixCls={prefixCls} />;
|
||||
}}
|
||||
</ConfigConsumer>
|
||||
)) as React.SFC<ExportProps> & ComponentDef;
|
||||
|
||||
const cons: ConstructorProps = Component.constructor as ConstructorProps;
|
||||
const name = (cons && cons.displayName) || Component.name || 'Component';
|
||||
|
||||
SFC.displayName = `withConfigConsumer(${name})`;
|
||||
|
||||
return SFC;
|
||||
};
|
||||
}
|
||||
|
||||
export default ConfigProvider;
|
||||
|
@ -45,4 +45,4 @@ return (
|
||||
| getPopupContainer | 弹出框(Select, Tooltip, Menu 等等)渲染父节点,默认渲染到 body 上。 | Function(triggerNode) | () => document.body | 3.11.0 |
|
||||
| locale | 语言包配置,语言包可到 [antd/es/locale](http://unpkg.com/antd/es/locale/) 目录下寻找 | object | - | 3.21.0 |
|
||||
| prefixCls | 设置统一样式前缀 | string | ant | 3.12.0 |
|
||||
| pageHeader | 统一设置 pageHeader 的 type,参考 [pageHeader](<(/components/page-header)>) | { ghost: boolean } | 'true' | 3.24.0 |
|
||||
| pageHeader | 统一设置 pageHeader 的 ghost,参考 [pageHeader](<(/components/page-header)>) | { ghost: boolean } | 'true' | 3.24.0 |
|
||||
|
@ -144,6 +144,7 @@ class WeekPicker extends React.Component<any, WeekPickerState> {
|
||||
onBlur,
|
||||
id,
|
||||
suffixIcon,
|
||||
defaultPickerValue,
|
||||
} = this.props;
|
||||
|
||||
const prefixCls = getPrefixCls('calendar', customizePrefixCls);
|
||||
@ -171,6 +172,7 @@ class WeekPicker extends React.Component<any, WeekPickerState> {
|
||||
showToday={false}
|
||||
disabledDate={disabledDate}
|
||||
renderFooter={this.renderFooter}
|
||||
defaultValue={defaultPickerValue}
|
||||
/>
|
||||
);
|
||||
const clearIcon =
|
||||
|
@ -63,6 +63,7 @@ export type RangePickerValue =
|
||||
| undefined[]
|
||||
| [moment.Moment]
|
||||
| [undefined, moment.Moment]
|
||||
| [moment.Moment, undefined]
|
||||
| [moment.Moment, moment.Moment];
|
||||
export type RangePickerPresetRange = RangePickerValue | (() => RangePickerValue);
|
||||
|
||||
|
@ -192,6 +192,7 @@ export default function wrapPicker(Picker: React.ComponentClass<any>, pickerType
|
||||
className={timePickerCls}
|
||||
placeholder={locale.timePickerLocale.placeholder}
|
||||
transitionName="slide-up"
|
||||
onEsc={() => {}}
|
||||
/>
|
||||
) : null;
|
||||
|
||||
|
@ -6,7 +6,8 @@ import classNames from 'classnames';
|
||||
import omit from 'omit.js';
|
||||
|
||||
import warning from '../_util/warning';
|
||||
import { withConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import { ConfigConsumerProps } from '../config-provider';
|
||||
import { withConfigConsumer } from '../config-provider/context';
|
||||
import { tuple } from '../_util/type';
|
||||
|
||||
const DrawerContext = createReactContext<Drawer | null>(null);
|
||||
|
@ -8,7 +8,7 @@ A dropdown list.
|
||||
|
||||
## When To Use
|
||||
|
||||
If there are too many operations to display, you can wrap them in a `Dropdown`. By clicking/hovering on the trigger, a dropdown menu should appear, which allows you to choose one option and execute relevant actions.
|
||||
When there are more than a few options to choose from, you can wrap them in a `Dropdown`. By hovering or clicking on the trigger, a dropdown menu will appear, which allows you to choose an option and execute the relevant action.
|
||||
|
||||
## API
|
||||
|
||||
@ -16,15 +16,15 @@ If there are too many operations to display, you can wrap them in a `Dropdown`.
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| disabled | whether the dropdown menu is disabled | boolean | - | |
|
||||
| getPopupContainer | to set the container of the dropdown menu. The default is to create a `div` element in `body`, you can reset it to the scrolling area and make a relative reposition. [example](https://codepen.io/afc163/pen/zEjNOy?editors=0010) | Function(triggerNode) | `() => document.body` | |
|
||||
| overlay | the dropdown menu | [Menu](/components/menu) \| () => Menu | - | |
|
||||
| disabled | Whether the dropdown menu is disabled | boolean | - | |
|
||||
| getPopupContainer | To set the container of the dropdown menu. The default is to create a `div` element in `body`, but you can reset it to the scrolling area and make a relative reposition. [Example on CodePen](https://codepen.io/afc163/pen/zEjNOy?editors=0010). | Function(triggerNode) | `() => document.body` | |
|
||||
| overlay | The dropdown menu | [Menu](/components/menu) \| () => Menu | - | |
|
||||
| overlayClassName | Class name of the dropdown root element | string | - | 3.11.0 |
|
||||
| overlayStyle | Style of the dropdown root element | object | - | 3.11.0 |
|
||||
| placement | placement of pop menu: `bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | String | `bottomLeft` | |
|
||||
| trigger | the trigger mode which executes the drop-down action, hover doesn't work on mobile device | Array<`click`\|`hover`\|`contextMenu`> | `['hover']` | |
|
||||
| visible | whether the dropdown menu is visible | boolean | - | |
|
||||
| onVisibleChange | a callback function takes an argument: `visible`, is executed when the visible state is changed | Function(visible) | - | |
|
||||
| placement | Placement of popup menu: `bottomLeft`, `bottomCenter`, `bottomRight`, `topLeft`, `topCenter` or `topRight` | String | `bottomLeft` | |
|
||||
| trigger | The trigger mode which executes the dropdown action. Note that hover can't be used on touchscreens. | Array<`click`\|`hover`\|`contextMenu`> | `['hover']` | |
|
||||
| visible | Whether the dropdown menu is currently visible | boolean | - | |
|
||||
| onVisibleChange | Called when the visible state is changed. | Function(visible) | - | |
|
||||
|
||||
You should use [Menu](/components/menu/) as `overlay`. The menu items and dividers are also available by using `Menu.Item` and `Menu.Divider`.
|
||||
|
||||
@ -36,13 +36,13 @@ You should use [Menu](/components/menu/) as `overlay`. The menu items and divide
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| disabled | whether the dropdown menu is disabled | boolean | - | |
|
||||
| icon | icon of right | ReactNode | - | 3.17.0 |
|
||||
| overlay | the dropdown menu | [Menu](/components/menu) | - | |
|
||||
| placement | placement of pop menu: `bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | String | `bottomLeft` | |
|
||||
| size | size of the button, the same as [Button](/components/button) | string | `default` | |
|
||||
| trigger | the trigger mode which executes the drop-down action | Array<`click`\|`hover`\|`contextMenu`> | `['hover']` | |
|
||||
| type | type of the button, the same as [Button](/components/button) | string | `default` | |
|
||||
| visible | whether the dropdown menu is visible | boolean | - | |
|
||||
| onClick | a callback function, the same as [Button](/components/button), which will be executed when you click the button on the left | Function | - | |
|
||||
| onVisibleChange | a callback function takes an argument: `visible`, is executed when the visible state is changed | Function | - | |
|
||||
| disabled | Whether the dropdown menu is disabled | boolean | - | |
|
||||
| icon | Icon (appears on the right) | ReactNode | - | 3.17.0 |
|
||||
| overlay | The dropdown menu | [Menu](/components/menu) | - | |
|
||||
| placement | Placement of popup menu: `bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | String | `bottomLeft` | |
|
||||
| size | Size of the button, the same as [Button](/components/button) | string | `default` | |
|
||||
| trigger | The trigger mode which executes the dropdown action | Array<`click`\|`hover`\|`contextMenu`> | `['hover']` | |
|
||||
| type | Type of the button, the same as [Button](/components/button) | string | `default` | |
|
||||
| visible | Whether the dropdown menu is currently visible | boolean | - | |
|
||||
| onClick | The same as [Button](/components/button): called when you click the button on the left | Function | - | |
|
||||
| onVisibleChange | Called when the visible state is changed | Function | - | |
|
||||
|
@ -175,6 +175,11 @@
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/19264
|
||||
&-submenu-selected &-submenu-title {
|
||||
color: @primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
&.slide-down-enter.slide-down-enter-active&-placement-bottomLeft,
|
||||
|
@ -35,10 +35,36 @@ describe('Grid', () => {
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('when typeof getGutter is object', () => {
|
||||
it('when typeof gutter is object', () => {
|
||||
const wrapper = mount(<Row gutter={{ xs: 8, sm: 16, md: 24 }} />);
|
||||
expect(wrapper.instance().getGutter()).toEqual([8, 0]);
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
it('when typeof gutter is object array', () => {
|
||||
const wrapper = mount(
|
||||
<Row
|
||||
gutter={[
|
||||
{ xs: 8, sm: 16, md: 24, lg: 32, xl: 40 },
|
||||
{ xs: 8, sm: 16, md: 24, lg: 32, xl: 40 },
|
||||
]}
|
||||
/>,
|
||||
);
|
||||
expect(wrapper.instance().getGutter()).toEqual([8, 8]);
|
||||
});
|
||||
|
||||
it('when typeof gutter is object array in large screen', () => {
|
||||
const wrapper = mount(
|
||||
<Row
|
||||
gutter={[
|
||||
{ xs: 8, sm: 16, md: 24, lg: 32, xl: 40 },
|
||||
{ xs: 8, sm: 16, md: 24, lg: 100, xl: 400 },
|
||||
]}
|
||||
/>,
|
||||
);
|
||||
wrapper.setState({
|
||||
screens: { md: true, lg: true, xl: true },
|
||||
});
|
||||
expect(wrapper.instance().getGutter()).toEqual([40, 400]);
|
||||
});
|
||||
|
||||
it('renders wrapped Col correctly', () => {
|
||||
|
@ -13,6 +13,8 @@ title:
|
||||
|
||||
如果需要垂直间距,可以写成数组形式 `[水平间距, 垂直间距]` `[16, { xs: 8, sm: 16, md: 24, lg: 32 }]`。
|
||||
|
||||
> 数组形式垂直间距在 `3.24.0` 之后支持。
|
||||
|
||||
## en-US
|
||||
|
||||
You can use the `gutter` property of `Row` as grid spacing, we recommend set it to `(16 + 8n) px`. (`n` stands for natural number.)
|
||||
@ -21,6 +23,8 @@ You can set it to a object like `{ xs: 8, sm: 16, md: 24, lg: 32 }` for responsi
|
||||
|
||||
You can use a array to set vertical spacing, `[horizontal, vertical]` `[16, { xs: 8, sm: 16, md: 24, lg: 32 }]`.
|
||||
|
||||
> vertical gutter was supported after `3.24.0`.
|
||||
|
||||
```jsx
|
||||
import { Row, Col } from 'antd';
|
||||
|
||||
|
@ -13,7 +13,7 @@ title:
|
||||
|
||||
## en-US
|
||||
|
||||
`span` `pull` `push` `offset` `order` property can be embedded into `xs` `sm` `md` `lg` `xl` properties to use, where `xs = {6}` is equivalent to `xs = {{span: 6}}`.
|
||||
`span` `pull` `push` `offset` `order` property can be embedded into `xs` `sm` `md` `lg` `xl` properties to use, where `xs={6}` is equivalent to `xs={{span: 6}}`.
|
||||
|
||||
```jsx
|
||||
import { Row, Col } from 'antd';
|
||||
|
@ -70,7 +70,7 @@ Following is a brief look at how it works:
|
||||
|
||||
- Establish a set of `column` in the horizontal space defined by `row` (abbreviated col)
|
||||
- Your content elements should be placed directly in the `col`, and only `col` should be placed directly in `row`
|
||||
- The column grid system is a value of 1-24 to represent its range spans. For example, three columns of equal width can be created by `.col-8` (`span=8`).
|
||||
- The column grid system is a value of 1-24 to represent its range spans. For example, three columns of equal width can be created by `<Col span={8} />`.
|
||||
- If the sum of `col` spans in a `row` are more than 24, then the overflowing `col` as a whole will start a new line arrangement.
|
||||
|
||||
## Flex layout
|
||||
@ -91,7 +91,7 @@ If the Ant Design grid layout component does not meet your needs, you can use th
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| align | the vertical alignment of the flex layout: `top` `middle` `bottom` | string | `top` | |
|
||||
| gutter | spacing between grids, could be a number or a object like `{ xs: 8, sm: 16, md: 24}`, or you can use array to make horizontal and vertical spacing work at the same time `[horizontal, vertical]` | number/object/array | 0 | |
|
||||
| gutter | spacing between grids, could be a number or a object like `{ xs: 8, sm: 16, md: 24}`. or you can use array to make horizontal and vertical spacing work at the same time `[horizontal, vertical]` (supported after `3.24.0`) | number/object/array | 0 | |
|
||||
| justify | horizontal arrangement of the flex layout: `start` `end` `center` `space-around` `space-between` | string | `start` | |
|
||||
| type | layout mode, optional `flex`, [browser support](http://caniuse.com/#search=flex) | string | | |
|
||||
|
||||
|
@ -67,10 +67,10 @@ title: Grid
|
||||
|
||||
布局的栅格化系统,我们是基于行(row)和列(col)来定义信息区块的外部框架,以保证页面的每个区域能够稳健地排布起来。下面简单介绍一下它的工作原理:
|
||||
|
||||
- 通过`row`在水平方向建立一组`column`(简写 col)
|
||||
- 你的内容应当放置于`col`内,并且,只有`col`可以作为`row`的直接元素
|
||||
- 栅格系统中的列是指 1 到 24 的值来表示其跨越的范围。例如,三个等宽的列可以使用`.col-8`来创建
|
||||
- 如果一个`row`中的`col`总和超过 24,那么多余的`col`会作为一个整体另起一行排列
|
||||
- 通过 `row` 在水平方向建立一组 `column`(简写 col)
|
||||
- 你的内容应当放置于 `col` 内,并且,只有 `col` 可以作为 `row` 的直接元素
|
||||
- 栅格系统中的列是指 1 到 24 的值来表示其跨越的范围。例如,三个等宽的列可以使用 `<Col span={8} />` 来创建
|
||||
- 如果一个 `row` 中的 `col` 总和超过 24,那么多余的 `col` 会作为一个整体另起一行排列
|
||||
|
||||
## Flex 布局
|
||||
|
||||
@ -90,7 +90,7 @@ Ant Design 的布局组件若不能满足你的需求,你也可以直接使用
|
||||
| 成员 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| align | flex 布局下的垂直对齐方式:`top` `middle` `bottom` | string | `top` | |
|
||||
| gutter | 栅格间隔,可以写成像素值或支持响应式的对象写法来设置水平间隔 `{ xs: 8, sm: 16, md: 24}`,或者使用数组形式同时设置`[水平间距, 垂直间距]` | number/object/array | 0 | |
|
||||
| gutter | 栅格间隔,可以写成像素值或支持响应式的对象写法来设置水平间隔 `{ xs: 8, sm: 16, md: 24}`。或者使用数组形式同时设置 `[水平间距, 垂直间距]`(`3.24.0 后支持`)。 | number/object/array | 0 | |
|
||||
| justify | flex 布局下的水平排列方式:`start` `end` `center` `space-around` `space-between` | string | `start` | |
|
||||
| type | 布局模式,可选 `flex`,[现代浏览器](http://caniuse.com/#search=flex) 下有效 | string | | |
|
||||
|
||||
|
@ -64,23 +64,24 @@ export default class Row extends React.Component<RowProps, RowState> {
|
||||
}
|
||||
|
||||
getGutter(): [number, number] {
|
||||
const gutter: [number, number] = [0, 0];
|
||||
const { gutter: gutter_setting } = this.props;
|
||||
|
||||
(Array.isArray(gutter_setting) ? gutter_setting : [gutter_setting, 0]).forEach((g, index) => {
|
||||
const results: [number, number] = [0, 0];
|
||||
const { gutter } = this.props;
|
||||
const { screens } = this.state;
|
||||
const normalizedGutter = Array.isArray(gutter) ? gutter : [gutter, 0];
|
||||
normalizedGutter.forEach((g, index) => {
|
||||
if (typeof g === 'object') {
|
||||
for (let i = 0; i < responsiveArray.length; i++) {
|
||||
const breakpoint: Breakpoint = responsiveArray[i];
|
||||
if (this.state.screens[breakpoint] && g[breakpoint] !== undefined) {
|
||||
gutter[index] = g[breakpoint] as number;
|
||||
if (screens[breakpoint] && g[breakpoint] !== undefined) {
|
||||
results[index] = g[breakpoint] as number;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
gutter[index] = g as number;
|
||||
results[index] = g || 0;
|
||||
}
|
||||
});
|
||||
|
||||
return gutter;
|
||||
return results;
|
||||
}
|
||||
|
||||
renderRow = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
|
@ -22,7 +22,7 @@ ReactDOM.render(<IconDisplay />, mountNode);
|
||||
| --- | --- | --- | --- | --- |
|
||||
| style | Style properties of icon, like `fontSize` and `color` | CSSProperties | - | |
|
||||
| spin | Rotate icon with animation | boolean | false | |
|
||||
| rotate | Rotate degrees (added in 3.13.0, not working in IE9) | number | - | 3.13.0 |
|
||||
| rotate | Rotate by n degrees (added in 3.13.0, not working in IE9) | number | - | 3.13.0 |
|
||||
| twoToneColor | Only supports the two-tone icon. Specify the primary color. | string (hex color) | - | 3.9.0 |
|
||||
|
||||
We still have three different themes for icons, icon component name is the icon name suffixed by the theme name.
|
||||
@ -46,20 +46,20 @@ import { Star, StarFilled, StarTwoTone } from '@ant-design/icons';
|
||||
|
||||
### About SVG icons
|
||||
|
||||
We introduced SVG icons in `3.9.0` version replacing font icons which brings benefits below:
|
||||
We introduced SVG icons in version `3.9.0`, replacing font icons. This has the following benefits:
|
||||
|
||||
- Complete offline usage of icon, no dependency of CDN font icon file. No more empty square during downloading and no need to deploy icon font files locally either.
|
||||
- Much more display accuracy in lower-level screens.
|
||||
- Support multiple colors for icon.
|
||||
- No need to change built-in icons with overriding styles by providing more props in component.
|
||||
- Complete offline usage of icons, without dependency on a CDN-hosted font icon file (No more empty square during downloading and no need to deploy icon font files locally either!)
|
||||
- Much more display accuracy on lower-resolution screens
|
||||
- The ability to choose icon color
|
||||
- No need to change built-in icons with overriding styles by providing more props in component
|
||||
|
||||
More discussion of SVG icon reference to [#10353](https://github.com/ant-design/ant-design/issues/10353).
|
||||
More discussion of SVG icon reference at [#10353](https://github.com/ant-design/ant-design/issues/10353).
|
||||
|
||||
> ⚠️ About the extra bundle size brought by all SVG icons we imported in 3.9.0, we will provide new API to allow developers importing icons as your need, you can trace [#12011](https://github.com/ant-design/ant-design/issues/12011) for further progress.
|
||||
> ⚠️ Given the extra bundle size caused by all SVG icons imported in 3.9.0, we will provide a new API to allow developers to import icons as needed, you can track [#12011](https://github.com/ant-design/ant-design/issues/12011) for updates.
|
||||
>
|
||||
> Before this, you can use [webpack plugin](https://github.com/Beven91/webpack-ant-icon-loader) from community to chunk the icon file.
|
||||
> While you wait, you can use [webpack plugin](https://github.com/Beven91/webpack-ant-icon-loader) from the community to chunk the icon file.
|
||||
|
||||
The properties `theme`, `component` and `twoToneColor` are added in `3.9.0`. The best practice is to pass the property `theme` to every `<Icon />` components.
|
||||
The properties `theme`, `component` and `twoToneColor` were added in `3.9.0`. The best practice is to pass the property `theme` to every `<Icon />` component.
|
||||
|
||||
```jsx
|
||||
import { Message } from '@ant-design/icons';
|
||||
@ -75,7 +75,9 @@ All the icons will render to `<svg>`. You can still set `style` and `className`
|
||||
|
||||
### Set TwoTone Color
|
||||
|
||||
When using the two-tone icons, you can use the static methods `getTwoToneColor()` and `setTwoToneColor(colorString)` to spicify the primary color.
|
||||
<<<<<<< HEAD When using the two-tone icons, you can use the static methods `getTwoToneColor()` and `setTwoToneColor(colorString)` to spicify the primary color. ======= When using the two-tone icons, you can use the static methods `Icon.getTwoToneColor()` and `Icon.setTwoToneColor(colorString)` to specify the primary color.
|
||||
|
||||
> > > > > > > origin/master
|
||||
|
||||
```jsx
|
||||
import { getTwoToneColor, setTwoToneColor } from '@ant-design/icons';
|
||||
|
@ -69,7 +69,7 @@ export default class Search extends React.Component<SearchProps, any> {
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
return <IconLoading className={`${prefixCls}-icon`} />;
|
||||
return <IconLoading className={`${prefixCls}-icon`} key="loadingIcon" />;
|
||||
};
|
||||
|
||||
renderSuffix = (prefixCls: string) => {
|
||||
@ -81,21 +81,22 @@ export default class Search extends React.Component<SearchProps, any> {
|
||||
|
||||
if (enterButton) return suffix;
|
||||
|
||||
const node = (
|
||||
const icon = (
|
||||
<IconSearch className={`${prefixCls}-icon`} key="searchIcon" onClick={this.onSearch} />
|
||||
);
|
||||
|
||||
if (suffix) {
|
||||
let cloneSuffix = suffix;
|
||||
if (React.isValidElement(cloneSuffix) && !cloneSuffix.key) {
|
||||
cloneSuffix = React.cloneElement(cloneSuffix, {
|
||||
key: 'originSuffix',
|
||||
});
|
||||
}
|
||||
return [cloneSuffix, node];
|
||||
return [
|
||||
React.isValidElement(suffix)
|
||||
? React.cloneElement(suffix, {
|
||||
key: 'suffix',
|
||||
})
|
||||
: null,
|
||||
icon,
|
||||
];
|
||||
}
|
||||
|
||||
return node;
|
||||
return icon;
|
||||
};
|
||||
|
||||
renderAddonAfter = (prefixCls: string) => {
|
||||
@ -140,7 +141,14 @@ export default class Search extends React.Component<SearchProps, any> {
|
||||
}
|
||||
|
||||
if (addonAfter) {
|
||||
return [button, addonAfter];
|
||||
return [
|
||||
button,
|
||||
React.isValidElement(addonAfter)
|
||||
? React.cloneElement(addonAfter, {
|
||||
key: 'addonAfter',
|
||||
})
|
||||
: null,
|
||||
];
|
||||
}
|
||||
|
||||
return button;
|
||||
@ -157,6 +165,7 @@ export default class Search extends React.Component<SearchProps, any> {
|
||||
} = this.props;
|
||||
|
||||
delete (restProps as any).onSearch;
|
||||
delete (restProps as any).loading;
|
||||
|
||||
const prefixCls = getPrefixCls('input-search', customizePrefixCls);
|
||||
const inputPrefixCls = getPrefixCls('input', customizeInputPrefixCls);
|
||||
|
@ -166,4 +166,23 @@ describe('Input.Search', () => {
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
expect(wrapperWithEnterButton.render()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should support addonAfter and suffix for loading', () => {
|
||||
const wrapper = mount(<Search loading suffix="suffix" addonAfter="addonAfter" />);
|
||||
const wrapperWithEnterButton = mount(
|
||||
<Search loading enterButton suffix="suffix" addonAfter="addonAfter" />,
|
||||
);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
expect(wrapperWithEnterButton.render()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should support invalid suffix', () => {
|
||||
const wrapper = mount(<Search suffix={[]} />);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should support invalid addonAfter', () => {
|
||||
const wrapper = mount(<Search addonAfter={[]} enterButton />);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
@ -100,6 +100,111 @@ exports[`Input.Search should support addonAfter 2`] = `
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Input.Search should support addonAfter and suffix for loading 1`] = `
|
||||
<span
|
||||
class="ant-input-search ant-input-group-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-input-wrapper ant-input-group"
|
||||
>
|
||||
<span
|
||||
class="ant-input-search ant-input-affix-wrapper"
|
||||
>
|
||||
<input
|
||||
class="ant-input"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-input-suffix"
|
||||
>
|
||||
suffix
|
||||
<span
|
||||
aria-label="loading"
|
||||
class="anticon anticon-loading ant-input-search-icon"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="anticon-spin"
|
||||
data-icon="loading"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="0 0 1024 1024"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 00-94.3-139.9 437.71 437.71 0 00-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
class="ant-input-group-addon"
|
||||
>
|
||||
addonAfter
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Input.Search should support addonAfter and suffix for loading 2`] = `
|
||||
<span
|
||||
class="ant-input-search ant-input-search-enter-button ant-input-group-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-input-wrapper ant-input-group"
|
||||
>
|
||||
<span
|
||||
class="ant-input-search ant-input-search-enter-button ant-input-affix-wrapper"
|
||||
>
|
||||
<input
|
||||
class="ant-input"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-input-suffix"
|
||||
>
|
||||
suffix
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
class="ant-input-group-addon"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-input-search-button ant-btn-primary"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-label="loading"
|
||||
class="anticon anticon-loading"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="anticon-spin"
|
||||
data-icon="loading"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="0 0 1024 1024"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 00-94.3-139.9 437.71 437.71 0 00-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
addonAfter
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Input.Search should support custom Button 1`] = `
|
||||
<span
|
||||
class="ant-input-search ant-input-search-enter-button ant-input-group-wrapper"
|
||||
@ -153,6 +258,88 @@ exports[`Input.Search should support custom button 1`] = `
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Input.Search should support invalid addonAfter 1`] = `
|
||||
<span
|
||||
class="ant-input-search ant-input-search-enter-button ant-input-group-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-input-wrapper ant-input-group"
|
||||
>
|
||||
<input
|
||||
class="ant-input"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-input-group-addon"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-input-search-button ant-btn-primary"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-label="search"
|
||||
class="anticon anticon-search"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="search"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0011.6 0l43.6-43.5a8.2 8.2 0 000-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Input.Search should support invalid suffix 1`] = `
|
||||
<span
|
||||
class="ant-input-search ant-input-affix-wrapper"
|
||||
>
|
||||
<input
|
||||
class="ant-input"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-input-suffix"
|
||||
>
|
||||
<span
|
||||
aria-label="search"
|
||||
class="anticon anticon-search ant-input-search-icon"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="search"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0011.6 0l43.6-43.5a8.2 8.2 0 000-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Input.Search should support loading 1`] = `
|
||||
<span
|
||||
class="ant-input-search ant-input-affix-wrapper"
|
||||
|
@ -245,6 +245,34 @@ exports[`renders ./components/input/demo/align.md correctly 1`] = `
|
||||
class="ant-typography"
|
||||
>
|
||||
Ant Design
|
||||
<div
|
||||
aria-label="Copy"
|
||||
class="ant-typography-copy"
|
||||
role="button"
|
||||
style="border:0;background:transparent;padding:0;line-height:inherit;display:inline-block"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
aria-label="copy"
|
||||
class="anticon anticon-copy"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="copy"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
<span
|
||||
class="ant-input-affix-wrapper"
|
||||
@ -1850,43 +1878,6 @@ exports[`renders ./components/input/demo/search-input-loading.md correctly 1`] =
|
||||
</span>
|
||||
<br />
|
||||
<br />
|
||||
<span
|
||||
class="ant-input-search ant-input-affix-wrapper"
|
||||
>
|
||||
<input
|
||||
class="ant-input"
|
||||
placeholder="input search loading with suffix"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-input-suffix"
|
||||
>
|
||||
suffix
|
||||
<span
|
||||
aria-label="loading"
|
||||
class="anticon anticon-loading ant-input-search-icon"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="anticon-spin"
|
||||
data-icon="loading"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="0 0 1024 1024"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 00-94.3-139.9 437.71 437.71 0 00-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<br />
|
||||
<br />
|
||||
<span
|
||||
class="ant-input-search ant-input-search-enter-button ant-input-group-wrapper"
|
||||
>
|
||||
@ -1930,52 +1921,6 @@ exports[`renders ./components/input/demo/search-input-loading.md correctly 1`] =
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<br />
|
||||
<br />
|
||||
<span
|
||||
class="ant-input-search ant-input-search-enter-button ant-input-group-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-input-wrapper ant-input-group"
|
||||
>
|
||||
<input
|
||||
class="ant-input"
|
||||
placeholder="input search loading with enterButton and addonAfter"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-input-group-addon"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-input-search-button ant-btn-primary"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-label="loading"
|
||||
class="anticon anticon-loading"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="anticon-spin"
|
||||
data-icon="loading"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="0 0 1024 1024"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 00-94.3-139.9 437.71 437.71 0 00-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
addonAfter
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@ -2026,7 +1971,7 @@ exports[`renders ./components/input/demo/textarea-resize.md correctly 1`] = `
|
||||
class="ant-input"
|
||||
rows="4"
|
||||
>
|
||||
autoSize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autoSize 可以设定为一个对象,指定最小行数和最大行数。autoSize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autoSize 可以设定为一个对象,指定最小行数和最大行数。autoSize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autoSize 可以设定为一个对象,指定最小行数和最大行数。autoSize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autoSize 可以设定为一个对象,指定最小行数和最大行数。autoSize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autoSize 可以设定为一个对象,指定最小行数和最大行数。autoSize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autoSize 可以设定为一个对象,指定最小行数和最大行数。autoSize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autoSize 可以设定为一个对象,指定最小行数和最大行数。ending
|
||||
The autoSize property applies to textarea nodes, and only the height changes automatically. In addition, autoSize can be set to an object, specifying the minimum number of rows and the maximum number of rows. The autoSize property applies to textarea nodes, and only the height changes automatically. In addition, autoSize can be set to an object, specifying the minimum number of rows and the maximum number of rows.
|
||||
</textarea>
|
||||
</div>
|
||||
`;
|
||||
|
@ -299,7 +299,7 @@ exports[`Input.Search should support suffix 1`] = `
|
||||
prefixCls="ant-input"
|
||||
suffix={
|
||||
Array [
|
||||
"suffix",
|
||||
null,
|
||||
<Search
|
||||
className="ant-input-search-icon"
|
||||
onClick={[Function]}
|
||||
@ -322,7 +322,6 @@ exports[`Input.Search should support suffix 1`] = `
|
||||
<span
|
||||
className="ant-input-suffix"
|
||||
>
|
||||
suffix
|
||||
<Search
|
||||
className="ant-input-search-icon"
|
||||
key="searchIcon"
|
||||
|
@ -69,7 +69,7 @@ ReactDOM.render(
|
||||
<Input.TextArea rows={1} style={{ width: 100 }} />
|
||||
<Button type="primary">Button</Button>
|
||||
<Input style={{ width: 100 }} />
|
||||
<Text copiable>Ant Design</Text>
|
||||
<Text copyable>Ant Design</Text>
|
||||
<Input prefix="1" suffix="2" style={{ width: 100 }} />
|
||||
<Input addonBefore="1" addonAfter="2" style={{ width: 100 }} />
|
||||
<InputNumber style={{ width: 100 }} />
|
||||
|
@ -23,18 +23,7 @@ ReactDOM.render(
|
||||
<Search placeholder="input search loading deault" loading />
|
||||
<br />
|
||||
<br />
|
||||
<Search placeholder="input search loading with suffix" loading suffix="suffix" />
|
||||
<br />
|
||||
<br />
|
||||
<Search placeholder="input search loading with enterButton" loading enterButton />
|
||||
<br />
|
||||
<br />
|
||||
<Search
|
||||
placeholder="input search loading with enterButton and addonAfter"
|
||||
loading
|
||||
enterButton
|
||||
addonAfter="addonAfter"
|
||||
/>
|
||||
</div>,
|
||||
mountNode,
|
||||
);
|
||||
|
@ -20,7 +20,7 @@ import { Input, Button } from 'antd';
|
||||
const { TextArea } = Input;
|
||||
|
||||
const defaultValue =
|
||||
'autoSize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autoSize 可以设定为一个对象,指定最小行数和最大行数。autoSize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autoSize 可以设定为一个对象,指定最小行数和最大行数。autoSize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autoSize 可以设定为一个对象,指定最小行数和最大行数。autoSize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autoSize 可以设定为一个对象,指定最小行数和最大行数。autoSize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autoSize 可以设定为一个对象,指定最小行数和最大行数。autoSize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autoSize 可以设定为一个对象,指定最小行数和最大行数。autoSize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autoSize 可以设定为一个对象,指定最小行数和最大行数。ending';
|
||||
'The autoSize property applies to textarea nodes, and only the height changes automatically. In addition, autoSize can be set to an object, specifying the minimum number of rows and the maximum number of rows. The autoSize property applies to textarea nodes, and only the height changes automatically. In addition, autoSize can be set to an object, specifying the minimum number of rows and the maximum number of rows.';
|
||||
|
||||
class Demo extends React.Component {
|
||||
state = {
|
||||
|
@ -22,6 +22,7 @@ A basic widget for getting the user input is a text field. Keyboard and mouse ca
|
||||
| defaultValue | The initial input content | string | | |
|
||||
| disabled | Whether the input is disabled. | boolean | false | |
|
||||
| id | The ID for input | string | | |
|
||||
| maxLength | max length | number | | |
|
||||
| prefix | The prefix icon for the Input. | string\|ReactNode | | |
|
||||
| size | The size of the input box. Note: in the context of a form, the `large` size is used. Available: `large` `default` `small` | string | `default` | |
|
||||
| suffix | The suffix icon for the Input. | string\|ReactNode | | |
|
||||
|
@ -23,6 +23,7 @@ title: Input
|
||||
| defaultValue | 输入框默认内容 | string | | |
|
||||
| disabled | 是否禁用状态,默认为 false | boolean | false | |
|
||||
| id | 输入框的 id | string | | |
|
||||
| maxLength | 最大长度 | number | | |
|
||||
| prefix | 带有前缀图标的 input | string\|ReactNode | | |
|
||||
| size | 控件大小。注:标准表单内的输入框大小限制为 `large`。可选 `large` `default` `small` | string | `default` | |
|
||||
| suffix | 带有后缀图标的 input | string\|ReactNode | | |
|
||||
|
@ -5,13 +5,13 @@ type: Navigation
|
||||
title: Menu
|
||||
---
|
||||
|
||||
Menu list of Navigation.
|
||||
A versatile menu for navigation.
|
||||
|
||||
## When To Use
|
||||
|
||||
Navigation menu is important for a website, it helps users jump from one site section to another quickly. Mostly, it includes top navigation and side navigation. Top navigation provides all the category and functions of the website. Side navigation provides the Multi-level structure of the website.
|
||||
Navigation is an important part of any website, as a good navigation setup allows users to move around the site quickly and efficiently. Ant Design offers top and side navigation options. Top navigation provides all the categories and functions of the website. Side navigation provides the multi-level structure of the website.
|
||||
|
||||
More layouts with navigation: [layout](/components/layout).
|
||||
More layouts with navigation: [Layout](/components/layout).
|
||||
|
||||
## API
|
||||
|
||||
@ -28,25 +28,25 @@ More layouts with navigation: [layout](/components/layout).
|
||||
|
||||
| Param | Description | Type | Default value | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| defaultOpenKeys | array with the keys of default opened sub menus | string\[] | | |
|
||||
| defaultSelectedKeys | array with the keys of default selected menu items | string\[] | | |
|
||||
| forceSubMenuRender | render submenu into DOM before it shows | boolean | false | |
|
||||
| inlineCollapsed | specifies the collapsed status when menu is inline mode | boolean | - | |
|
||||
| inlineIndent | indent px of inline menu item on each level | number | 24 | |
|
||||
| mode | type of the menu; `vertical`, `horizontal`, and `inline` modes are supported | string: `vertical` \| `horizontal` \| `inline` | `vertical` | |
|
||||
| multiple | Allow selection of multiple items | boolean | false | |
|
||||
| openKeys | array with the keys of currently opened sub menus | string\[] | | |
|
||||
| selectable | allow selecting menu items | boolean | true | |
|
||||
| selectedKeys | array with the keys of currently selected menu items | string\[] | | |
|
||||
| style | style of the root node | object | | |
|
||||
| subMenuCloseDelay | delay time to hide submenu when mouse leave, unit: second | number | 0.1 | |
|
||||
| subMenuOpenDelay | delay time to show submenu when mouse enter, unit: second | number | 0 | |
|
||||
| theme | color theme of the menu | string: `light` `dark` | `light` | |
|
||||
| onClick | callback executed when a menu item is clicked | function({ item, key, keyPath, domEvent }) | - | |
|
||||
| onDeselect | callback executed when a menu item is deselected, only supported for multiple mode | function({ item, key, keyPath, selectedKeys, domEvent }) | - | |
|
||||
| onOpenChange | called when open/close sub menu | function(openKeys: string\[]) | noop | |
|
||||
| onSelect | callback executed when a menu item is selected | function({ item, key, keyPath, selectedKeys, domEvent }) | none | |
|
||||
| overflowedIndicator | Customized icon when menu collapsed | ReactNode | - | 3.16.0 |
|
||||
| defaultOpenKeys | Array with the keys of default opened sub menus | string\[] | | |
|
||||
| defaultSelectedKeys | Array with the keys of default selected menu items | string\[] | | |
|
||||
| forceSubMenuRender | Render submenu into DOM before it becomes visible | boolean | false | |
|
||||
| inlineCollapsed | Specifies the collapsed status when menu is inline mode | boolean | - | |
|
||||
| inlineIndent | Indent (in pixels) of inline menu items on each level | number | 24 | |
|
||||
| mode | Type of menu; `vertical`, `horizontal`, or `inline` | string: `vertical` \| `horizontal` \| `inline` | `vertical` | |
|
||||
| multiple | Allows selection of multiple items | boolean | false | |
|
||||
| openKeys | Array with the keys of currently opened sub-menus | string\[] | | |
|
||||
| selectable | Allows selecting menu items | boolean | true | |
|
||||
| selectedKeys | Array with the keys of currently selected menu items | string\[] | | |
|
||||
| style | Style of the root node | object | | |
|
||||
| subMenuCloseDelay | Delay time to hide submenu when mouse leaves (in seconds) | number | 0.1 | |
|
||||
| subMenuOpenDelay | Delay time to show submenu when mouse enters, (in seconds) | number | 0 | |
|
||||
| theme | Color theme of the menu | string: `light` \| `dark` | `light` | |
|
||||
| onClick | Called when a menu item is clicked | function({ item, key, keyPath, domEvent }) | - | |
|
||||
| onDeselect | Called when a menu item is deselected (multiple mode only) | function({ item, key, keyPath, selectedKeys, domEvent }) | - | |
|
||||
| onOpenChange | Called when sub-menus are opened or closed | function(openKeys: string\[]) | noop | |
|
||||
| onSelect | Called when a menu item is selected | function({ item, key, keyPath, selectedKeys, domEvent }) | none | |
|
||||
| overflowedIndicator | Customized icon when menu is collapsed | ReactNode | - | 3.16.0 |
|
||||
|
||||
> More options in [rc-menu](https://github.com/react-component/menu#api)
|
||||
|
||||
@ -54,26 +54,26 @@ More layouts with navigation: [layout](/components/layout).
|
||||
|
||||
| Param | Description | Type | Default value | Version |
|
||||
| -------- | ------------------------------------ | ------- | ------------- | ------- |
|
||||
| disabled | whether menu item is disabled or not | boolean | false | |
|
||||
| key | unique id of the menu item | string | | |
|
||||
| title | set display title for collapsed item | string | | 3.11.0 |
|
||||
| disabled | Whether menu item is disabled | boolean | false | |
|
||||
| key | Unique ID of the menu item | string | | |
|
||||
| title | Set display title for collapsed item | string | | 3.11.0 |
|
||||
|
||||
### Menu.SubMenu
|
||||
|
||||
| Param | Description | Type | Default value | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| popupClassName | sub menu class name | string | | 3.22.0 |
|
||||
| children | sub menus or sub menu items | Array<MenuItem\|SubMenu> | | |
|
||||
| disabled | whether sub menu is disabled or not | boolean | false | |
|
||||
| key | unique id of the sub menu | string | | |
|
||||
| title | title of the sub menu | string\|ReactNode | | |
|
||||
| onTitleClick | callback executed when the sub menu title is clicked | function({ key, domEvent }) | | |
|
||||
| popupClassName | Sub-menu class name | string | | 3.22.0 |
|
||||
| children | Sub-menus or sub-menu items | Array<MenuItem\|SubMenu> | | |
|
||||
| disabled | Whether sub-menu is disabled | boolean | false | |
|
||||
| key | Unique ID of the sub-menu | string | | |
|
||||
| title | Title of the sub-menu | string\|ReactNode | | |
|
||||
| onTitleClick | Callback executed when the sub-menu title is clicked | function({ key, domEvent }) | | |
|
||||
|
||||
### Menu.ItemGroup
|
||||
|
||||
| Param | Description | Type | Default value | Version |
|
||||
| -------- | ------------------ | ----------------- | ------------- | ------- |
|
||||
| children | sub menu items | MenuItem\[] | | |
|
||||
| children | sub-menu items | MenuItem\[] | | |
|
||||
| title | title of the group | string\|ReactNode | | |
|
||||
|
||||
### Menu.Divider
|
||||
|
@ -364,7 +364,7 @@
|
||||
|
||||
// disable margin collapsed
|
||||
.@{menu-prefix-cls}-submenu {
|
||||
padding-bottom: 0.01px;
|
||||
padding-bottom: 0.02px;
|
||||
}
|
||||
|
||||
.@{menu-prefix-cls}-item:not(:last-child) {
|
||||
|
@ -27,6 +27,13 @@ describe('Modal.confirm triggers callbacks correctly', () => {
|
||||
});
|
||||
}
|
||||
|
||||
it('should not render title when title not defined', () => {
|
||||
confirm({
|
||||
content: 'some descriptions',
|
||||
});
|
||||
expect(document.querySelector('.ant-modal-confirm-title')).toBe(null);
|
||||
});
|
||||
|
||||
it('trigger onCancel once when click on cancel button', () => {
|
||||
const onCancel = jest.fn();
|
||||
const onOk = jest.fn();
|
||||
|
@ -91,7 +91,9 @@ const ConfirmDialog = (props: ConfirmDialogProps) => {
|
||||
<div className={`${contentPrefixCls}-body-wrapper`}>
|
||||
<div className={`${contentPrefixCls}-body`}>
|
||||
{icon}
|
||||
<span className={`${contentPrefixCls}-title`}>{props.title}</span>
|
||||
{props.title === undefined ? null : (
|
||||
<span className={`${contentPrefixCls}-title`}>{props.title}</span>
|
||||
)}
|
||||
<div className={`${contentPrefixCls}-content`}>{props.content}</div>
|
||||
</div>
|
||||
<div className={`${contentPrefixCls}-btns`}>
|
||||
|
@ -31,7 +31,6 @@ function info() {
|
||||
|
||||
function success() {
|
||||
Modal.success({
|
||||
title: 'This is a success message',
|
||||
content: 'some messages...some messages...',
|
||||
});
|
||||
}
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
&-title {
|
||||
margin: 0;
|
||||
color: @heading-color;
|
||||
color: @modal-heading-color;
|
||||
font-weight: 500;
|
||||
font-size: @font-size-lg;
|
||||
line-height: 22px;
|
||||
|
@ -6,23 +6,23 @@ cols: 1
|
||||
subtitle:
|
||||
---
|
||||
|
||||
The header can be used to declare the page topic, display important information about the page that the user is interested in, and carry the action items related to the current page (including page-level operations, inter-page navigation, etc.)
|
||||
A header with common actions and design elements built in.
|
||||
|
||||
## When To Use
|
||||
|
||||
It can also be used as inter-page navigation when it is needed to make the user quickly understand what the current page is and to facilitate the user to use the page function.
|
||||
PageHeader can be used to highlight the page topic, display important information about the page, and carry the action items related to the current page (including page-level operations, inter-page navigation, etc.) It can also be used as inter-page navigation.
|
||||
|
||||
## API
|
||||
|
||||
| Param | Description | Type | Default value | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| title | custom title text | ReactNode | - | 3.14.0 |
|
||||
| subTitle | custom subTitle text | ReactNode | - | 3.14.0 |
|
||||
| type | pageHeader type, will change background color | boolean | true | 3.24.0 |
|
||||
| title | Custom title text | ReactNode | - | 3.14.0 |
|
||||
| subTitle | Custom subtitle text | ReactNode | - | 3.14.0 |
|
||||
| ghost | PageHeader type, will change background color | boolean | true | 3.24.0 |
|
||||
| avatar | Avatar next to the title bar | [avatar props](/components/avatar/) | - | 3.22.0 |
|
||||
| backIcon | custom back icon, if false the back icon will not be displayed | ReactNode | `<ArrowLeft />` | 3.14.0 |
|
||||
| backIcon | Custom back icon, if false the back icon will not be displayed | ReactNode | `<ArrowLeft />` | 3.14.0 |
|
||||
| tags | Tag list next to title | [Tag](https://ant.design/components/tag-cn/)[] \| [Tag](https://ant.design/components/tag-cn/) | - | 3.14.0 |
|
||||
| extra | Operating area, at the end of the line of the title line | ReactNode | - | 3.14.0 |
|
||||
| breadcrumb | breadcrumb config | [breadcrumb](https://ant.design/components/breadcrumb-cn/) | - | 3.14.0 |
|
||||
| breadcrumb | Breadcrumb configuration | [breadcrumb](https://ant.design/components/breadcrumb-cn/) | - | 3.14.0 |
|
||||
| footer | PageHeader's footer, generally used to render TabBar | ReactNode | - | 3.14.0 |
|
||||
| onBack | back icon click event | `()=>void` | `()=>history.back()` | 3.14.0 |
|
||||
| onBack | Back icon click event | `()=>void` | `()=>history.back()` | 3.14.0 |
|
||||
|
@ -5,7 +5,7 @@ title: Pagination
|
||||
cols: 1
|
||||
---
|
||||
|
||||
A long list can be divided into several pages by `Pagination`, and only one page will be loaded at a time.
|
||||
A long list can be divided into several pages using `Pagination`, and only one page will be loaded at a time.
|
||||
|
||||
## When To Use
|
||||
|
||||
@ -20,21 +20,21 @@ A long list can be divided into several pages by `Pagination`, and only one page
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| current | current page number | number | - | |
|
||||
| defaultCurrent | default initial page number | number | 1 | |
|
||||
| defaultPageSize | default number of data items per page | number | 10 | |
|
||||
| disabled | disable pagination | boolean | - | 3.18.0 |
|
||||
| current | Current page number | number | - | |
|
||||
| defaultCurrent | Default initial page number | number | 1 | |
|
||||
| defaultPageSize | Default number of data items per page | number | 10 | |
|
||||
| disabled | Disable pagination | boolean | - | 3.18.0 |
|
||||
| hideOnSinglePage | Whether to hide pager on single page | boolean | false | 3.1.0 |
|
||||
| itemRender | to customize item innerHTML | (page, type: 'page' \| 'prev' \| 'next', originalElement) => React.ReactNode | - | |
|
||||
| pageSize | number of data items per page | number | - | |
|
||||
| pageSizeOptions | specify the sizeChanger options | string\[] | \['10', '20', '30', '40'] | |
|
||||
| showLessItems | show less page items | boolean | false | 3.16.3 |
|
||||
| showQuickJumper | determine whether you can jump to pages directly | boolean \| `{ goButton: ReactNode }` | false | |
|
||||
| showSizeChanger | determine whether `pageSize` can be changed | boolean | false | |
|
||||
| showTitle | show page items title | boolean | true | |
|
||||
| showTotal | to display the total number and range | Function(total, range) | - | |
|
||||
| simple | whether to use simple mode | boolean | - | |
|
||||
| size | specify the size of `Pagination`, can be set to `small` | string | "" | |
|
||||
| total | total number of data items | number | 0 | |
|
||||
| onChange | a callback function, executed when the page number is changed, and it takes the resulting page number and pageSize as its arguments | Function(page, pageSize) | noop | |
|
||||
| onShowSizeChange | a callback function, executed when `pageSize` is changed | Function(current, size) | noop | |
|
||||
| itemRender | To customize item's innerHTML | (page, type: 'page' \| 'prev' \| 'next', originalElement) => React.ReactNode | - | |
|
||||
| pageSize | Number of data items per page | number | - | |
|
||||
| pageSizeOptions | Specify the sizeChanger options | string\[] | \['10', '20', '30', '40'] | |
|
||||
| showLessItems | Show less page items | boolean | false | 3.16.3 |
|
||||
| showQuickJumper | Determine whether you can jump to pages directly | boolean \| `{ goButton: ReactNode }` | false | |
|
||||
| showSizeChanger | Determine whether `pageSize` can be changed | boolean | false | |
|
||||
| showTitle | Show page item's title | boolean | true | |
|
||||
| showTotal | To display the total number and range | Function(total, range) | - | |
|
||||
| simple | Whether to use simple mode | boolean | - | |
|
||||
| size | Specify the size of `Pagination`, can be set to `small` | string | "" | |
|
||||
| total | Total number of data items | number | 0 | |
|
||||
| onChange | Called when the page number is changed, and it takes the resulting page number and pageSize as its arguments | Function(page, pageSize) | noop | |
|
||||
| onShowSizeChange | Called when `pageSize` is changed | Function(current, size) | noop | |
|
||||
|
@ -1038,11 +1038,9 @@ exports[`renders ./components/slider/demo/tip-formatter.md correctly 1`] = `
|
||||
`;
|
||||
|
||||
exports[`renders ./components/slider/demo/vertical.md correctly 1`] = `
|
||||
<div
|
||||
style="height:300px"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
style="float:left;height:300px;margin-left:70px"
|
||||
style="display:inline-block;height:300px;margin-left:70px"
|
||||
>
|
||||
<div
|
||||
class="ant-slider ant-slider-vertical"
|
||||
@ -1073,7 +1071,7 @@ exports[`renders ./components/slider/demo/vertical.md correctly 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style="float:left;height:300px;margin-left:70px"
|
||||
style="display:inline-block;height:300px;margin-left:70px"
|
||||
>
|
||||
<div
|
||||
class="ant-slider ant-slider-vertical"
|
||||
@ -1114,7 +1112,7 @@ exports[`renders ./components/slider/demo/vertical.md correctly 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style="float:left;height:300px;margin-left:70px"
|
||||
style="display:inline-block;height:300px;margin-left:70px"
|
||||
>
|
||||
<div
|
||||
class="ant-slider ant-slider-with-marks ant-slider-vertical"
|
||||
|
@ -17,7 +17,7 @@ The vertical Slider.
|
||||
import { Slider } from 'antd';
|
||||
|
||||
const style = {
|
||||
float: 'left',
|
||||
display: 'inline-block',
|
||||
height: 300,
|
||||
marginLeft: 70,
|
||||
};
|
||||
@ -35,7 +35,7 @@ const marks = {
|
||||
};
|
||||
|
||||
ReactDOM.render(
|
||||
<div style={{ height: 300 }}>
|
||||
<div>
|
||||
<div style={style}>
|
||||
<Slider vertical defaultValue={30} />
|
||||
</div>
|
||||
|
@ -1,7 +1,8 @@
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { withConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import { ConfigConsumerProps } from '../config-provider';
|
||||
import { withConfigConsumer } from '../config-provider/context';
|
||||
import StatisticNumber from './Number';
|
||||
import Countdown from './Countdown';
|
||||
import { valueType, FormatConfig } from './utils';
|
||||
|
@ -9,7 +9,7 @@ title: Steps
|
||||
|
||||
## When To Use
|
||||
|
||||
When the task is complicated or has a certain sequence in the series of subtasks, we can decompose it into several steps to make things easier.
|
||||
When a given task is complicated or has a certain sequence in the series of subtasks, we can decompose it into several steps to make things easier.
|
||||
|
||||
## API
|
||||
|
||||
@ -27,16 +27,16 @@ The whole of the step bar.
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| className | additional class to Steps | string | - | 3.11.3 |
|
||||
| type | type of steps, can be set to one of the following values: `default`, `navigation` | string | `default` | 3.22.0 |
|
||||
| current | to set the current step, counting from 0. You can overwrite this state by using `status` of `Step` | number | 0 | |
|
||||
| direction | to specify the direction of the step bar, `horizontal` or `vertical` | string | `horizontal` | |
|
||||
| labelPlacement | place title and description with `horizontal` or `vertical` direction | string | `horizontal` | 3.7.3 |
|
||||
| className | Additional class to Steps | string | - | 3.11.3 |
|
||||
| type | Type of steps, can be set to one of the following values: `default`, `navigation` | string | `default` | 3.22.0 |
|
||||
| current | To set the current step, counting from 0. You can overwrite this state by using `status` of `Step` | number | 0 | |
|
||||
| direction | To specify the direction of the step bar, `horizontal` or `vertical` | string | `horizontal` | |
|
||||
| labelPlacement | Place title and description with `horizontal` or `vertical` direction | string | `horizontal` | 3.7.3 |
|
||||
| progressDot | Steps with progress dot style, customize the progress dot by setting it to a function. labelPlacement will be `vertical` | Boolean or (iconDot, {index, status, title, description}) => ReactNode | false | |
|
||||
| size | to specify the size of the step bar, `default` and `small` are currently supported | string | `default` | |
|
||||
| status | to specify the status of current step, can be set to one of the following values: `wait` `process` `finish` `error` | string | `process` | |
|
||||
| initial | set the initial step, counting from 0 | number | 0 | 3.9.0 |
|
||||
| onChange | Trigger when Step click to change | (current) => void | - | 3.19.0 |
|
||||
| size | To specify the size of the step bar, `default` and `small` are currently supported | string | `default` | |
|
||||
| status | To specify the status of current step, can be set to one of the following values: `wait` `process` `finish` `error` | string | `process` | |
|
||||
| initial | Set the initial step, counting from 0 | number | 0 | 3.9.0 |
|
||||
| onChange | Trigger when Step is changed | (current) => void | - | 3.19.0 |
|
||||
|
||||
### Steps.Step
|
||||
|
||||
@ -44,9 +44,9 @@ A single step in the step bar.
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| description | description of the step, optional property | string\|ReactNode | - | |
|
||||
| icon | icon of the step, optional property | ReactNode | - | |
|
||||
| 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` | |
|
||||
| title | title of the step | string\|ReactNode | - | |
|
||||
| subTitle | subTitle of the step | string\|ReactNode | - | 3.22.0 |
|
||||
| disabled | disable click | boolean | false | 3.22.0 |
|
||||
| description | Description of the step, optional property | string\|ReactNode | - | |
|
||||
| icon | Icon of the step, optional property | string\|ReactNode | - | |
|
||||
| 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` | |
|
||||
| title | Title of the step | string\|ReactNode | - | |
|
||||
| subTitle | Subtitle of the step | string\|ReactNode | - | 3.22.0 |
|
||||
| disabled | Disable click | boolean | false | 3.22.0 |
|
||||
|
@ -380,6 +380,7 @@
|
||||
// --
|
||||
@modal-body-padding: 24px;
|
||||
@modal-header-bg: @component-background;
|
||||
@modal-heading-color: @heading-color;
|
||||
@modal-footer-bg: transparent;
|
||||
@modal-footer-border-color-split: @border-color-split;
|
||||
@modal-mask-bg: fade(@black, 45%);
|
||||
|
@ -17,6 +17,7 @@ import { flatArray, treeMap, flatFilter, normalizeColumns } from './util';
|
||||
import scrollTo from '../_util/scrollTo';
|
||||
import {
|
||||
TableProps,
|
||||
InternalTableProps,
|
||||
TableSize,
|
||||
TableState,
|
||||
TableComponents,
|
||||
@ -34,7 +35,6 @@ import {
|
||||
PaginationConfig,
|
||||
PrepareParamsArgumentsReturn,
|
||||
ExpandIconProps,
|
||||
WithStore,
|
||||
CheckboxPropsCache,
|
||||
} from './interface';
|
||||
import Pagination from '../pagination';
|
||||
@ -68,9 +68,14 @@ function isSameColumn<T>(a: ColumnProps<T> | null, b: ColumnProps<T> | null) {
|
||||
return (
|
||||
a === b ||
|
||||
shallowEqual(a, b, (value: any, other: any) => {
|
||||
// https://github.com/ant-design/ant-design/issues/12737
|
||||
if (typeof value === 'function' && typeof other === 'function') {
|
||||
return value === other || value.toString() === other.toString();
|
||||
}
|
||||
// https://github.com/ant-design/ant-design/issues/19398
|
||||
if (Array.isArray(value) && Array.isArray(other)) {
|
||||
return value === other || shallowEqual(value, other);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
@ -132,7 +137,7 @@ function isFiltersChanged<T>(state: TableState<T>, filters: TableStateFilters):
|
||||
return Object.keys(filters).some(columnKey => filters[columnKey] !== state.filters[columnKey]);
|
||||
}
|
||||
|
||||
class Table<T> extends React.Component<TableProps<T>, TableState<T>> {
|
||||
class Table<T> extends React.Component<InternalTableProps<T>, TableState<T>> {
|
||||
static propTypes = {
|
||||
dataSource: PropTypes.array,
|
||||
columns: PropTypes.array,
|
||||
@ -165,7 +170,7 @@ class Table<T> extends React.Component<TableProps<T>, TableState<T>> {
|
||||
childrenColumnName: 'children',
|
||||
};
|
||||
|
||||
static getDerivedStateFromProps(nextProps: TableProps<any>, prevState: TableState<any>) {
|
||||
static getDerivedStateFromProps(nextProps: InternalTableProps<any>, prevState: TableState<any>) {
|
||||
const { prevProps } = prevState;
|
||||
const columns =
|
||||
nextProps.columns || normalizeColumns(nextProps.children as React.ReactChildren);
|
||||
@ -238,11 +243,10 @@ class Table<T> extends React.Component<TableProps<T>, TableState<T>> {
|
||||
|
||||
row: React.ComponentType<any>;
|
||||
|
||||
rcTable: React.RefObject<any>;
|
||||
rcTable: any;
|
||||
|
||||
constructor(props: TableProps<T>) {
|
||||
constructor(props: InternalTableProps<T>) {
|
||||
super(props);
|
||||
this.rcTable = React.createRef();
|
||||
|
||||
const { expandedRowRender, columns: columnsProp = [] } = props;
|
||||
|
||||
@ -278,6 +282,10 @@ class Table<T> extends React.Component<TableProps<T>, TableState<T>> {
|
||||
}
|
||||
}
|
||||
|
||||
setTableRef = (table: any) => {
|
||||
this.rcTable = table;
|
||||
};
|
||||
|
||||
getCheckboxPropsByItem = (item: T, index: number) => {
|
||||
const rowSelection = getRowSelection(this.props);
|
||||
if (!rowSelection.getCheckboxProps) {
|
||||
@ -527,7 +535,7 @@ class Table<T> extends React.Component<TableProps<T>, TableState<T>> {
|
||||
|
||||
generatePopupContainerFunc = (getPopupContainer: TableProps<T>['getPopupContainer']) => {
|
||||
const { scroll } = this.props;
|
||||
const table = this.rcTable.current;
|
||||
const table = this.rcTable;
|
||||
if (getPopupContainer) {
|
||||
return getPopupContainer;
|
||||
}
|
||||
@ -539,7 +547,7 @@ class Table<T> extends React.Component<TableProps<T>, TableState<T>> {
|
||||
const { scroll } = this.props;
|
||||
if (scroll && scroll.scrollToFirstRowOnChange !== false) {
|
||||
scrollTo(0, {
|
||||
getContainer: () => this.rcTable.current.bodyTable,
|
||||
getContainer: () => this.rcTable.bodyTable,
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -1271,7 +1279,7 @@ class Table<T> extends React.Component<TableProps<T>, TableState<T>> {
|
||||
|
||||
return (
|
||||
<RcTable
|
||||
ref={this.rcTable}
|
||||
ref={this.setTableRef}
|
||||
key="table"
|
||||
expandIcon={this.renderExpandIcon(prefixCls)}
|
||||
{...restProps}
|
||||
@ -1347,43 +1355,40 @@ class Table<T> extends React.Component<TableProps<T>, TableState<T>> {
|
||||
}
|
||||
}
|
||||
|
||||
function withStore(
|
||||
WrappedComponent: typeof Table,
|
||||
): React.ComponentClass<Omit<TableProps<any>, keyof WithStore>> {
|
||||
class Component<T> extends React.Component<TableProps<T>> {
|
||||
static Column = Column;
|
||||
class StoreTable<T> extends React.Component<TableProps<T>> {
|
||||
static displayName = 'withStore(Table)';
|
||||
|
||||
static ColumnGroup = ColumnGroup;
|
||||
static Column = Column;
|
||||
|
||||
store: Store;
|
||||
static ColumnGroup = ColumnGroup;
|
||||
|
||||
CheckboxPropsCache: CheckboxPropsCache;
|
||||
store: Store;
|
||||
|
||||
constructor(props: TableProps<T>) {
|
||||
super(props);
|
||||
CheckboxPropsCache: CheckboxPropsCache;
|
||||
|
||||
this.CheckboxPropsCache = {};
|
||||
constructor(props: TableProps<T>) {
|
||||
super(props);
|
||||
|
||||
this.store = createStore({
|
||||
selectedRowKeys: getRowSelection(props).selectedRowKeys || [],
|
||||
selectionDirty: false,
|
||||
});
|
||||
}
|
||||
this.CheckboxPropsCache = {};
|
||||
|
||||
setCheckboxPropsCache = (cache: CheckboxPropsCache) => (this.CheckboxPropsCache = cache);
|
||||
|
||||
render() {
|
||||
return (
|
||||
<WrappedComponent<T>
|
||||
{...this.props}
|
||||
store={this.store}
|
||||
checkboxPropsCache={this.CheckboxPropsCache}
|
||||
setCheckboxPropsCache={this.setCheckboxPropsCache}
|
||||
/>
|
||||
);
|
||||
}
|
||||
this.store = createStore({
|
||||
selectedRowKeys: getRowSelection(props).selectedRowKeys || [],
|
||||
selectionDirty: false,
|
||||
});
|
||||
}
|
||||
|
||||
setCheckboxPropsCache = (cache: CheckboxPropsCache) => (this.CheckboxPropsCache = cache);
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Table<T>
|
||||
{...this.props}
|
||||
store={this.store}
|
||||
checkboxPropsCache={this.CheckboxPropsCache}
|
||||
setCheckboxPropsCache={this.setCheckboxPropsCache}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return Component;
|
||||
}
|
||||
|
||||
export default withStore(Table);
|
||||
export default StoreTable;
|
||||
|
@ -916,4 +916,32 @@ describe('Table.filter', () => {
|
||||
);
|
||||
expect(wrapper.find('.ant-pagination-item-active').text()).toBe('3');
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/19274
|
||||
it('should not crash', () => {
|
||||
class TestTable extends React.Component {
|
||||
state = {
|
||||
cols: [],
|
||||
};
|
||||
|
||||
componentDidMount = () => {
|
||||
this.setState({
|
||||
cols: [
|
||||
{
|
||||
title: 'test',
|
||||
itemKey: 'test',
|
||||
filterDropdown: 123,
|
||||
},
|
||||
],
|
||||
});
|
||||
};
|
||||
|
||||
render = () => {
|
||||
const { cols } = this.state;
|
||||
return <Table columns={cols} dataSource={[]} scroll={{ x: 1000 }} />;
|
||||
};
|
||||
}
|
||||
|
||||
mount(<TestTable />);
|
||||
});
|
||||
});
|
||||
|
@ -354,6 +354,7 @@ describe('Table.sorter', () => {
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/12737
|
||||
// https://github.com/ant-design/ant-design/issues/19398
|
||||
it('should toggle sort state when columns with non primitive properties are put in render', () => {
|
||||
const testData = [
|
||||
{ key: 0, name: 'Jack', age: 11 },
|
||||
@ -377,6 +378,7 @@ describe('Table.sorter', () => {
|
||||
dataIndex: 'name',
|
||||
sorter: true,
|
||||
render: text => text,
|
||||
array: ['1', '2', 3],
|
||||
},
|
||||
];
|
||||
const { pagination } = this.state;
|
||||
|
@ -11,7 +11,7 @@ exports[`Table.rowSelection fix selection column on the left 1`] = `
|
||||
class="ant-spin-container"
|
||||
>
|
||||
<div
|
||||
class="ant-table ant-table-default ant-table-scroll-position-left ant-table-layout-fixed"
|
||||
class="ant-table ant-table-default ant-table-scroll-position-left"
|
||||
>
|
||||
<div
|
||||
class="ant-table-content"
|
||||
@ -486,7 +486,7 @@ exports[`Table.rowSelection fix selection column on the left when any other colu
|
||||
class="ant-spin-container"
|
||||
>
|
||||
<div
|
||||
class="ant-table ant-table-default ant-table-scroll-position-left ant-table-layout-fixed"
|
||||
class="ant-table ant-table-default ant-table-scroll-position-left"
|
||||
>
|
||||
<div
|
||||
class="ant-table-content"
|
||||
|
@ -4610,21 +4610,25 @@ exports[`renders ./components/table/demo/ellipsis.md correctly 1`] = `
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-row-cell-ellipsis"
|
||||
title="New York No. 1 Lake Park, New York No. 1 Lake Park"
|
||||
>
|
||||
New York No. 1 Lake Park, New York No. 1 Lake Park
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-row-cell-ellipsis"
|
||||
title="New York No. 1 Lake Park, New York No. 1 Lake Park"
|
||||
>
|
||||
New York No. 1 Lake Park, New York No. 1 Lake Park
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-row-cell-ellipsis"
|
||||
title="New York No. 1 Lake Park, New York No. 1 Lake Park"
|
||||
>
|
||||
New York No. 1 Lake Park, New York No. 1 Lake Park
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-row-cell-ellipsis"
|
||||
title="New York No. 1 Lake Park, New York No. 1 Lake Park"
|
||||
>
|
||||
New York No. 1 Lake Park, New York No. 1 Lake Park
|
||||
</td>
|
||||
@ -4647,21 +4651,25 @@ exports[`renders ./components/table/demo/ellipsis.md correctly 1`] = `
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-row-cell-ellipsis"
|
||||
title="London No. 2 Lake Park, London No. 2 Lake Park"
|
||||
>
|
||||
London No. 2 Lake Park, London No. 2 Lake Park
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-row-cell-ellipsis"
|
||||
title="London No. 2 Lake Park, London No. 2 Lake Park"
|
||||
>
|
||||
London No. 2 Lake Park, London No. 2 Lake Park
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-row-cell-ellipsis"
|
||||
title="London No. 2 Lake Park, London No. 2 Lake Park"
|
||||
>
|
||||
London No. 2 Lake Park, London No. 2 Lake Park
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-row-cell-ellipsis"
|
||||
title="London No. 2 Lake Park, London No. 2 Lake Park"
|
||||
>
|
||||
London No. 2 Lake Park, London No. 2 Lake Park
|
||||
</td>
|
||||
@ -4684,21 +4692,25 @@ exports[`renders ./components/table/demo/ellipsis.md correctly 1`] = `
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-row-cell-ellipsis"
|
||||
title="Sidney No. 1 Lake Park, Sidney No. 1 Lake Park"
|
||||
>
|
||||
Sidney No. 1 Lake Park, Sidney No. 1 Lake Park
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-row-cell-ellipsis"
|
||||
title="Sidney No. 1 Lake Park, Sidney No. 1 Lake Park"
|
||||
>
|
||||
Sidney No. 1 Lake Park, Sidney No. 1 Lake Park
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-row-cell-ellipsis"
|
||||
title="Sidney No. 1 Lake Park, Sidney No. 1 Lake Park"
|
||||
>
|
||||
Sidney No. 1 Lake Park, Sidney No. 1 Lake Park
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-row-cell-ellipsis"
|
||||
title="Sidney No. 1 Lake Park, Sidney No. 1 Lake Park"
|
||||
>
|
||||
Sidney No. 1 Lake Park, Sidney No. 1 Lake Park
|
||||
</td>
|
||||
@ -8810,17 +8822,17 @@ exports[`renders ./components/table/demo/grouping-columns.md correctly 1`] = `
|
||||
>
|
||||
<table
|
||||
class="ant-table-fixed"
|
||||
style="width:130%"
|
||||
style="width:calc(700px + 50%)"
|
||||
>
|
||||
<colgroup>
|
||||
<col
|
||||
style="width:100px;min-width:100px"
|
||||
/>
|
||||
<col
|
||||
style="width:200px;min-width:200px"
|
||||
style="width:150px;min-width:150px"
|
||||
/>
|
||||
<col
|
||||
style="width:200px;min-width:200px"
|
||||
style="width:150px;min-width:150px"
|
||||
/>
|
||||
<col
|
||||
style="width:100px;min-width:100px"
|
||||
@ -9153,17 +9165,17 @@ exports[`renders ./components/table/demo/grouping-columns.md correctly 1`] = `
|
||||
>
|
||||
<table
|
||||
class="ant-table-fixed"
|
||||
style="width:130%"
|
||||
style="width:calc(700px + 50%)"
|
||||
>
|
||||
<colgroup>
|
||||
<col
|
||||
style="width:100px;min-width:100px"
|
||||
/>
|
||||
<col
|
||||
style="width:200px;min-width:200px"
|
||||
style="width:150px;min-width:150px"
|
||||
/>
|
||||
<col
|
||||
style="width:200px;min-width:200px"
|
||||
style="width:150px;min-width:150px"
|
||||
/>
|
||||
<col
|
||||
style="width:100px;min-width:100px"
|
||||
@ -11725,6 +11737,7 @@ exports[`renders ./components/table/demo/reset-filter.md correctly 1`] = `
|
||||
>
|
||||
<td
|
||||
class="ant-table-column-has-actions ant-table-column-has-filters ant-table-column-has-sorters ant-table-row-cell-ellipsis"
|
||||
title="John Brown"
|
||||
>
|
||||
John Brown
|
||||
</td>
|
||||
@ -11735,6 +11748,7 @@ exports[`renders ./components/table/demo/reset-filter.md correctly 1`] = `
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-column-has-actions ant-table-column-has-filters ant-table-column-has-sorters ant-table-row-cell-ellipsis"
|
||||
title="New York No. 1 Lake Park"
|
||||
>
|
||||
New York No. 1 Lake Park
|
||||
</td>
|
||||
@ -11745,6 +11759,7 @@ exports[`renders ./components/table/demo/reset-filter.md correctly 1`] = `
|
||||
>
|
||||
<td
|
||||
class="ant-table-column-has-actions ant-table-column-has-filters ant-table-column-has-sorters ant-table-row-cell-ellipsis"
|
||||
title="Jim Green"
|
||||
>
|
||||
Jim Green
|
||||
</td>
|
||||
@ -11755,6 +11770,7 @@ exports[`renders ./components/table/demo/reset-filter.md correctly 1`] = `
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-column-has-actions ant-table-column-has-filters ant-table-column-has-sorters ant-table-row-cell-ellipsis"
|
||||
title="London No. 1 Lake Park"
|
||||
>
|
||||
London No. 1 Lake Park
|
||||
</td>
|
||||
@ -11765,6 +11781,7 @@ exports[`renders ./components/table/demo/reset-filter.md correctly 1`] = `
|
||||
>
|
||||
<td
|
||||
class="ant-table-column-has-actions ant-table-column-has-filters ant-table-column-has-sorters ant-table-row-cell-ellipsis"
|
||||
title="Joe Black"
|
||||
>
|
||||
Joe Black
|
||||
</td>
|
||||
@ -11775,6 +11792,7 @@ exports[`renders ./components/table/demo/reset-filter.md correctly 1`] = `
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-column-has-actions ant-table-column-has-filters ant-table-column-has-sorters ant-table-row-cell-ellipsis"
|
||||
title="Sidney No. 1 Lake Park"
|
||||
>
|
||||
Sidney No. 1 Lake Park
|
||||
</td>
|
||||
@ -11785,6 +11803,7 @@ exports[`renders ./components/table/demo/reset-filter.md correctly 1`] = `
|
||||
>
|
||||
<td
|
||||
class="ant-table-column-has-actions ant-table-column-has-filters ant-table-column-has-sorters ant-table-row-cell-ellipsis"
|
||||
title="Jim Red"
|
||||
>
|
||||
Jim Red
|
||||
</td>
|
||||
@ -11795,6 +11814,7 @@ exports[`renders ./components/table/demo/reset-filter.md correctly 1`] = `
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-column-has-actions ant-table-column-has-filters ant-table-column-has-sorters ant-table-row-cell-ellipsis"
|
||||
title="London No. 2 Lake Park"
|
||||
>
|
||||
London No. 2 Lake Park
|
||||
</td>
|
||||
|
@ -453,7 +453,7 @@ exports[`Table renders empty table with fixed columns 1`] = `
|
||||
class="ant-spin-container"
|
||||
>
|
||||
<div
|
||||
class="ant-table ant-table-default ant-table-empty ant-table-scroll-position-left ant-table-layout-fixed"
|
||||
class="ant-table ant-table-default ant-table-empty ant-table-scroll-position-left"
|
||||
>
|
||||
<div
|
||||
class="ant-table-content"
|
||||
|
@ -42,7 +42,7 @@ const columns = [
|
||||
title: 'Age',
|
||||
dataIndex: 'age',
|
||||
key: 'age',
|
||||
width: 200,
|
||||
width: 150,
|
||||
sorter: (a, b) => a.age - b.age,
|
||||
},
|
||||
{
|
||||
@ -52,7 +52,7 @@ const columns = [
|
||||
title: 'Street',
|
||||
dataIndex: 'street',
|
||||
key: 'street',
|
||||
width: 200,
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: 'Block',
|
||||
@ -121,7 +121,7 @@ ReactDOM.render(
|
||||
dataSource={data}
|
||||
bordered
|
||||
size="middle"
|
||||
scroll={{ x: '130%', y: 240 }}
|
||||
scroll={{ x: 'calc(700px + 50%)', y: 240 }}
|
||||
/>,
|
||||
mountNode,
|
||||
);
|
||||
|
@ -161,7 +161,7 @@ export interface WithStore {
|
||||
setCheckboxPropsCache: (cache: CheckboxPropsCache) => void;
|
||||
}
|
||||
|
||||
export interface TableProps<T> extends WithStore {
|
||||
export interface TableProps<T> {
|
||||
prefixCls?: string;
|
||||
dropdownPrefixCls?: string;
|
||||
rowSelection?: TableRowSelection<T>;
|
||||
@ -219,6 +219,8 @@ export interface TableProps<T> extends WithStore {
|
||||
getPopupContainer?: (triggerNode: HTMLElement) => HTMLElement;
|
||||
}
|
||||
|
||||
export type InternalTableProps<T> = TableProps<T> & WithStore;
|
||||
|
||||
export interface TableStateFilters {
|
||||
[key: string]: string[];
|
||||
}
|
||||
|
@ -102,6 +102,7 @@
|
||||
|
||||
.@{table-prefix-cls}-header {
|
||||
background-color: @component-background;
|
||||
border-radius: @table-border-radius-base @table-border-radius-base 0 0;
|
||||
}
|
||||
|
||||
.@{table-prefix-cls}-placeholder,
|
||||
@ -160,4 +161,12 @@
|
||||
margin: -@table-padding-vertical-sm -@table-padding-horizontal / 2 -@table-padding-vertical-sm -
|
||||
1px;
|
||||
}
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/19287#issuecomment-544368967
|
||||
&.@{table-prefix-cls}-fixed-header
|
||||
> .@{table-prefix-cls}-content
|
||||
> .@{table-prefix-cls}-scroll
|
||||
> .@{table-prefix-cls}-body {
|
||||
border-radius: 0 0 @table-border-radius-base @table-border-radius-base;
|
||||
}
|
||||
}
|
||||
|
@ -95,9 +95,9 @@ const splitObject = (obj: any, keys: string[]) => {
|
||||
function getDisabledCompatibleChildren(element: React.ReactElement<any>) {
|
||||
const elementType = element.type as any;
|
||||
if (
|
||||
(elementType.__ANT_BUTTON ||
|
||||
elementType.__ANT_SWITCH ||
|
||||
elementType.__ANT_CHECKBOX ||
|
||||
(elementType.__ANT_BUTTON === true ||
|
||||
elementType.__ANT_SWITCH === true ||
|
||||
elementType.__ANT_CHECKBOX === true ||
|
||||
element.type === 'button') &&
|
||||
element.props.disabled
|
||||
) {
|
||||
|
@ -3,7 +3,7 @@
|
||||
exports[`renders ./components/tree-select/demo/async.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-select ant-tree-select ant-select-single ant-select-show-arrow"
|
||||
style="width:300px"
|
||||
style="width:100%"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
@ -63,7 +63,7 @@ exports[`renders ./components/tree-select/demo/async.md correctly 1`] = `
|
||||
exports[`renders ./components/tree-select/demo/basic.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-select ant-tree-select ant-select-single ant-select-allow-clear ant-select-show-arrow ant-select-show-search"
|
||||
style="width:300px"
|
||||
style="width:100%"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
@ -123,7 +123,7 @@ exports[`renders ./components/tree-select/demo/basic.md correctly 1`] = `
|
||||
exports[`renders ./components/tree-select/demo/checkable.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-select ant-tree-select ant-select-multiple ant-select-show-search"
|
||||
style="width:300px"
|
||||
style="width:100%"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
@ -195,7 +195,7 @@ exports[`renders ./components/tree-select/demo/multiple.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-select ant-tree-select ant-select-multiple ant-select-allow-clear ant-select-show-search"
|
||||
multiple=""
|
||||
style="width:300px"
|
||||
style="width:100%"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
@ -235,7 +235,7 @@ exports[`renders ./components/tree-select/demo/multiple.md correctly 1`] = `
|
||||
exports[`renders ./components/tree-select/demo/suffix.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-select ant-tree-select ant-select-single ant-select-allow-clear ant-select-show-arrow ant-select-show-search"
|
||||
style="width:300px"
|
||||
style="width:100%"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
@ -295,7 +295,7 @@ exports[`renders ./components/tree-select/demo/suffix.md correctly 1`] = `
|
||||
exports[`renders ./components/tree-select/demo/treeData.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-select ant-tree-select ant-select-single ant-select-show-arrow"
|
||||
style="width:300px"
|
||||
style="width:100%"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
|
@ -63,7 +63,7 @@ class Demo extends React.Component {
|
||||
return (
|
||||
<TreeSelect
|
||||
treeDataSimpleMode
|
||||
style={{ width: 300 }}
|
||||
style={{ width: '100%' }}
|
||||
value={this.state.value}
|
||||
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
|
||||
placeholder="Please select"
|
||||
|
@ -32,7 +32,7 @@ class Demo extends React.Component {
|
||||
return (
|
||||
<TreeSelect
|
||||
showSearch
|
||||
style={{ width: 300 }}
|
||||
style={{ width: '100%' }}
|
||||
value={this.state.value}
|
||||
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
|
||||
placeholder="Please select"
|
||||
|
@ -74,7 +74,7 @@ class Demo extends React.Component {
|
||||
showCheckedStrategy: SHOW_PARENT,
|
||||
searchPlaceholder: 'Please select',
|
||||
style: {
|
||||
width: 300,
|
||||
width: '100%',
|
||||
},
|
||||
};
|
||||
return <TreeSelect {...tProps} />;
|
||||
|
@ -32,7 +32,7 @@ class Demo extends React.Component {
|
||||
return (
|
||||
<TreeSelect
|
||||
showSearch
|
||||
style={{ width: 300 }}
|
||||
style={{ width: '100%' }}
|
||||
value={this.state.value}
|
||||
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
|
||||
placeholder="Please select"
|
||||
|
@ -36,7 +36,7 @@ class Demo extends React.Component {
|
||||
<TreeSelect
|
||||
showSearch
|
||||
suffixIcon={icon}
|
||||
style={{ width: 300 }}
|
||||
style={{ width: '100%' }}
|
||||
value={this.state.value}
|
||||
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
|
||||
placeholder="Please select"
|
||||
|
@ -54,7 +54,7 @@ class Demo extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<TreeSelect
|
||||
style={{ width: 300 }}
|
||||
style={{ width: '100%' }}
|
||||
value={this.state.value}
|
||||
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
|
||||
treeData={treeData}
|
||||
|
@ -7,7 +7,8 @@ import copy from 'copy-to-clipboard';
|
||||
import omit from 'omit.js';
|
||||
import { Edit, Check, Copy } from '@ant-design/icons';
|
||||
import ResizeObserver from 'rc-resize-observer';
|
||||
import { withConfigConsumer, ConfigConsumerProps, configConsumerProps } from '../config-provider';
|
||||
import { ConfigConsumerProps, configConsumerProps } from '../config-provider';
|
||||
import { withConfigConsumer } from '../config-provider/context';
|
||||
import LocaleReceiver from '../locale-provider/LocaleReceiver';
|
||||
import warning from '../_util/warning';
|
||||
import TransButton from '../_util/transButton';
|
||||
|
@ -9,7 +9,7 @@ Basic text writing, including headings, body text, lists, and more.
|
||||
|
||||
## When To Use
|
||||
|
||||
- When need to display title or paragraph contents in Articles/Blogs/Notes.
|
||||
- When need to display a title or paragraph contents in Articles/Blogs/Notes.
|
||||
- When you need copyable/editable/ellipsis texts.
|
||||
|
||||
## API
|
||||
@ -18,46 +18,46 @@ Basic text writing, including headings, body text, lists, and more.
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| code | code style | boolean | false | 3.15.1 |
|
||||
| code | Code style | boolean | false | 3.15.1 |
|
||||
| copyable | Config copy. Can set copy text and callback when is an object | boolean \| { text: string, onCopy: Function } | false | 3.14.0 |
|
||||
| delete | delete line style | boolean | false | 3.14.0 |
|
||||
| disabled | Disable content | boolean | false | 3.14.0 |
|
||||
| delete | Deleted line style | boolean | false | 3.14.0 |
|
||||
| disabled | Disabled content | boolean | false | 3.14.0 |
|
||||
| editable | Editable. Can control edit state when is object | boolean \| { editing: boolean, onStart: Function, onChange: Function(string) } | false | 3.14.0 |
|
||||
| ellipsis | Display ellipsis when overflow | boolean | false | 3.14.0 |
|
||||
| mark | mark style | boolean | false | 3.14.0 |
|
||||
| underline | underline style | boolean | false | 3.14.0 |
|
||||
| onChange | Trigger when user edit the content | Function(string) | - | 3.14.0 |
|
||||
| strong | bold style | boolean | false | 3.14.0 |
|
||||
| ellipsis | Display ellipsis when text overflows | boolean | false | 3.14.0 |
|
||||
| mark | Marked style | boolean | false | 3.14.0 |
|
||||
| underline | Underlined style | boolean | false | 3.14.0 |
|
||||
| onChange | Trigger when user edits the content | Function(string) | - | 3.14.0 |
|
||||
| strong | Bold style | boolean | false | 3.14.0 |
|
||||
| type | Content type | `secondary`, `warning`, `danger` | - | 3.14.0 |
|
||||
|
||||
### Typography.Title
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| code | code style | boolean | false | 3.15.1 |
|
||||
| code | Code style | boolean | false | 3.15.1 |
|
||||
| copyable | Config copy. Can set copy text and callback when is an object | boolean \| { text: string, onCopy: Function } | false | 3.14.0 |
|
||||
| delete | delete line style | boolean | false | 3.14.0 |
|
||||
| disabled | Disable content | boolean | false | 3.14.0 |
|
||||
| delete | Deleted line style | boolean | false | 3.14.0 |
|
||||
| disabled | Disabled content | boolean | false | 3.14.0 |
|
||||
| editable | Editable. Can control edit state when is object | boolean \| { editing: boolean, onStart: Function, onChange: Function(string) } | false | 3.14.0 |
|
||||
| ellipsis | Display ellipsis when overflow. Can config rows and expandable by using object | boolean \| { rows: number, expandable: boolean, onExpand: Function } | false | 3.14.0 |
|
||||
| ellipsis | Display ellipsis when text overflows. Can configure rows and expandable by using object | boolean \| { rows: number, expandable: boolean, onExpand: Function } | false | 3.14.0 |
|
||||
| level | Set content importance. Match with `h1`, `h2`, `h3`, `h4` | number: `1`, `2`, `3`, `4` | 1 | 3.14.0 |
|
||||
| mark | mark style | boolean | false | 3.14.0 |
|
||||
| underline | underline style | boolean | false | 3.14.0 |
|
||||
| onChange | Trigger when user edit the content | Function(string) | - | 3.14.0 |
|
||||
| mark | Marked style | boolean | false | 3.14.0 |
|
||||
| underline | Underlined style | boolean | false | 3.14.0 |
|
||||
| onChange | Trigger when user edits the content | Function(string) | - | 3.14.0 |
|
||||
| type | Content type | `secondary`, `warning`, `danger` | - | 3.14.0 |
|
||||
|
||||
### Typography.Paragraph
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| code | code style | boolean | false | 3.15.1 |
|
||||
| code | Code style | boolean | false | 3.15.1 |
|
||||
| copyable | Config copy. Can set copy text and callback when is an object | boolean \| { text: string, onCopy: Function } | false | 3.14.0 |
|
||||
| delete | delete line style | boolean | false | 3.14.0 |
|
||||
| disabled | Disable content | boolean | false | 3.14.0 |
|
||||
| delete | Deleted line style | boolean | false | 3.14.0 |
|
||||
| disabled | Disabled content | boolean | false | 3.14.0 |
|
||||
| editable | Editable. Can control edit state when is object | boolean \| { editing: boolean, onStart: Function, onChange: Function(string) } | false | 3.14.0 |
|
||||
| ellipsis | Display ellipsis when overflow. Can config rows and expandable by using object | boolean \| { rows: number, expandable: boolean, onExpand: Function } | false | 3.14.0 |
|
||||
| mark | mark style | boolean | false | 3.14.0 |
|
||||
| underline | underline style | boolean | false | 3.14.0 |
|
||||
| onChange | Trigger when user edit the content | Function(string) | - | 3.14.0 |
|
||||
| strong | bold style | boolean | false | 3.14.0 |
|
||||
| ellipsis | Display ellipsis when text overflows. Can configure rows and expandable by using object | boolean \| { rows: number, expandable: boolean, onExpand: Function } | false | 3.14.0 |
|
||||
| mark | Marked style | boolean | false | 3.14.0 |
|
||||
| underline | Underlined style | boolean | false | 3.14.0 |
|
||||
| onChange | Trigger when user edits the content | Function(string) | - | 3.14.0 |
|
||||
| strong | Bold style | boolean | false | 3.14.0 |
|
||||
| type | Content type | `secondary`, `warning`, `danger` | - | 3.14.0 |
|
||||
|
@ -173,32 +173,33 @@ export default class UploadList extends React.Component<UploadListProps, any> {
|
||||
[downloadIcon, removeIcon].filter(x => x).length
|
||||
}`]: true,
|
||||
});
|
||||
const preview = file.url ? (
|
||||
[
|
||||
<a
|
||||
key="view"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={listItemNameClass}
|
||||
title={file.name}
|
||||
{...linkProps}
|
||||
href={file.url}
|
||||
onClick={e => this.handlePreview(file, e)}
|
||||
>
|
||||
{file.name}
|
||||
</a>,
|
||||
downloadOrDelete,
|
||||
]
|
||||
) : (
|
||||
<span
|
||||
className={listItemNameClass}
|
||||
onClick={e => this.handlePreview(file, e)}
|
||||
title={file.name}
|
||||
>
|
||||
{file.name}
|
||||
{downloadOrDelete}
|
||||
</span>
|
||||
);
|
||||
const preview = file.url
|
||||
? [
|
||||
<a
|
||||
key="view"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={listItemNameClass}
|
||||
title={file.name}
|
||||
{...linkProps}
|
||||
href={file.url}
|
||||
onClick={e => this.handlePreview(file, e)}
|
||||
>
|
||||
{file.name}
|
||||
</a>,
|
||||
downloadOrDelete,
|
||||
]
|
||||
: [
|
||||
<span
|
||||
key="view"
|
||||
className={listItemNameClass}
|
||||
onClick={e => this.handlePreview(file, e)}
|
||||
title={file.name}
|
||||
>
|
||||
{file.name}
|
||||
</span>,
|
||||
downloadOrDelete,
|
||||
];
|
||||
const style: React.CSSProperties = {
|
||||
pointerEvents: 'none',
|
||||
opacity: 0.5,
|
||||
|
@ -59,36 +59,36 @@ exports[`Upload List handle error 1`] = `
|
||||
title="foo.png"
|
||||
>
|
||||
foo.png
|
||||
<span
|
||||
class="ant-upload-list-item-card-actions "
|
||||
</span>
|
||||
<span
|
||||
class="ant-upload-list-item-card-actions "
|
||||
>
|
||||
<a
|
||||
title="Remove file"
|
||||
>
|
||||
<a
|
||||
<span
|
||||
aria-label="delete"
|
||||
class="anticon anticon-delete"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
title="Remove file"
|
||||
>
|
||||
<span
|
||||
aria-label="delete"
|
||||
class="anticon anticon-delete"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
title="Remove file"
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="delete"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="delete"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
</span>
|
||||
<path
|
||||
d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
@ -178,36 +178,36 @@ exports[`Upload List should be uploading when upload a file 1`] = `
|
||||
title="foo.png"
|
||||
>
|
||||
foo.png
|
||||
<span
|
||||
class="ant-upload-list-item-card-actions "
|
||||
</span>
|
||||
<span
|
||||
class="ant-upload-list-item-card-actions "
|
||||
>
|
||||
<a
|
||||
title="Remove file"
|
||||
>
|
||||
<a
|
||||
<span
|
||||
aria-label="delete"
|
||||
class="anticon anticon-delete"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
title="Remove file"
|
||||
>
|
||||
<span
|
||||
aria-label="delete"
|
||||
class="anticon anticon-delete"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
title="Remove file"
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="delete"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="delete"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
</span>
|
||||
<path
|
||||
d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
@ -297,62 +297,62 @@ exports[`Upload List should be uploading when upload a file 2`] = `
|
||||
title="foo.png"
|
||||
>
|
||||
foo.png
|
||||
<span
|
||||
class="ant-upload-list-item-card-actions "
|
||||
</span>
|
||||
<span
|
||||
class="ant-upload-list-item-card-actions "
|
||||
>
|
||||
<a
|
||||
title="Download file"
|
||||
>
|
||||
<a
|
||||
<span
|
||||
aria-label="download"
|
||||
class="anticon anticon-download"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
title="Download file"
|
||||
>
|
||||
<span
|
||||
aria-label="download"
|
||||
class="anticon anticon-download"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
title="Download file"
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="download"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="download"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M505.7 661a8 8 0 0012.6 0l112-141.7c4.1-5.2.4-12.9-6.3-12.9h-74.1V168c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v338.3H400c-6.7 0-10.4 7.7-6.3 12.9l112 141.8zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
<path
|
||||
d="M505.7 661a8 8 0 0012.6 0l112-141.7c4.1-5.2.4-12.9-6.3-12.9h-74.1V168c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v338.3H400c-6.7 0-10.4 7.7-6.3 12.9l112 141.8zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
title="Remove file"
|
||||
>
|
||||
<span
|
||||
aria-label="delete"
|
||||
class="anticon anticon-delete"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
title="Remove file"
|
||||
>
|
||||
<span
|
||||
aria-label="delete"
|
||||
class="anticon anticon-delete"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
title="Remove file"
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="delete"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="delete"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
</span>
|
||||
<path
|
||||
d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
@ -12,7 +12,19 @@ export interface RcFile extends File {
|
||||
readonly webkitRelativePath: string;
|
||||
}
|
||||
|
||||
export interface UploadFile {
|
||||
export interface RcCustomRequestOptions {
|
||||
onProgress: (event: { percent: number }, file: File) => void;
|
||||
onError: (error: Error) => void;
|
||||
onSuccess: (response: object, file: File) => void;
|
||||
data: object;
|
||||
filename: string;
|
||||
file: File;
|
||||
withCredentials: boolean;
|
||||
action: string;
|
||||
headers: object;
|
||||
}
|
||||
|
||||
export interface UploadFile<T = any> {
|
||||
uid: string;
|
||||
size: number;
|
||||
name: string;
|
||||
@ -24,7 +36,7 @@ export interface UploadFile {
|
||||
percent?: number;
|
||||
thumbUrl?: string;
|
||||
originFileObj?: File | Blob;
|
||||
response?: any;
|
||||
response?: T;
|
||||
error?: any;
|
||||
linkProps?: any;
|
||||
type: string;
|
||||
@ -82,7 +94,7 @@ export interface UploadProps {
|
||||
style?: React.CSSProperties;
|
||||
disabled?: boolean;
|
||||
prefixCls?: string;
|
||||
customRequest?: (option: object) => void;
|
||||
customRequest?: (options: RcCustomRequestOptions) => void;
|
||||
withCredentials?: boolean;
|
||||
openFileDialogOnClick?: boolean;
|
||||
locale?: UploadLocale;
|
||||
|
@ -4,7 +4,7 @@ title: Contributing
|
||||
toc: false
|
||||
---
|
||||
|
||||
The following is a set of guidelines for contributing to Ant Design. Please spend several minutes in reading these guidelines before you create an issue or pull request.
|
||||
The following is a set of guidelines for contributing to Ant Design. Please spend several minutes reading these guidelines before you create an issue or pull request.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
@ -20,15 +20,15 @@ According to our [release schedule](changelog#Release-Schedule), we maintain two
|
||||
|
||||
## Bugs
|
||||
|
||||
We are using [GitHub Issues](https://github.com/ant-design/ant-design/issues) for bug tracing. The best way to get your bug fixed is using our [issue helper](http://new-issue.ant.design) and provide a reproduction with this [template](https://u.ant.design/codesandbox-repro).
|
||||
We are using [GitHub Issues](https://github.com/ant-design/ant-design/issues) for bug tracking. The best way to get your bug fixed is using our [issue helper](http://new-issue.ant.design) and provide reproduction steps with this [template](https://u.ant.design/codesandbox-repro).
|
||||
|
||||
Before you reporting a bug, please make sure you've searched exists issues, and read our [FAQ](/docs/react/faq).
|
||||
Before you report a bug, please make sure you've searched exists issues, and read our [FAQ](/docs/react/faq).
|
||||
|
||||
## Proposing a Change
|
||||
|
||||
If you intend to change the public API or introduce new feature, we also recommend use our [issue helper](http://new-issue.ant.design) to create a feature request issue.
|
||||
If you intend to change the public API or introduce new feature, we also recommend you use our [issue helper](http://new-issue.ant.design) to create a feature request issue.
|
||||
|
||||
If you want to help on new API, please ref [API Naming Rules](https://github.com/ant-design/ant-design/wiki/API-Naming-rules) to name it.
|
||||
If you want to help on new API, please reference [API Naming Rules](https://github.com/ant-design/ant-design/wiki/API-Naming-rules) to name it.
|
||||
|
||||
## Your First Pull Request
|
||||
|
||||
@ -48,16 +48,16 @@ The core team is monitoring for pull requests. We will review your pull request
|
||||
|
||||
**Before submitting a pull request**, please make sure the following is done:
|
||||
|
||||
1. Fork the repository and create your branch from [proper branch](#Branch-Organization).
|
||||
1. Fork the repository and create your branch from the [correct branch](#Branch-Organization).
|
||||
1. Run `npm install` in the repository root.
|
||||
1. If you've fixed a bug or added code that should be tested, add tests!
|
||||
1. Ensure the test suite passes (npm run test). Tip: `npm test -- --watch TestName` is helpful in development.
|
||||
1. Run `npm test -- -u` to update [jest snapshot](http://facebook.github.io/jest/docs/en/snapshot-testing.html#snapshot-testing-with-jest) and commit these changes as well (if has).
|
||||
1. Make sure your code lints (npm run lint). Tip: Lint runs automatically when you `git commit`.
|
||||
1. Run `npm test -- -u` to update the [jest snapshots](http://facebook.github.io/jest/docs/en/snapshot-testing.html#snapshot-testing-with-jest) and commit these changes as well (if there are any updates).
|
||||
1. Make sure your code lints (npm run lint). Tip: Lint runs automatically when you `git commit` (Use [Git Hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks)).
|
||||
|
||||
Sending a Pull Request to [react-component](https://github.com/react-component/):
|
||||
|
||||
Since antd's components are based on react-component, sometimes you may need to send pull request to the corresponding react-component repository. If it's a bugfix pull request, after it's merged, the core team will release a patch release for that component as soon as possible, then you only need to do is reinstalling antd in your project to get the latest patch release. If it's a feature pull request, after it's merged, the core team will release a minor release, then you need raise another pull request to [Ant Design](https://github.com/ant-design/ant-design/) to update dependencies, document and TypeScript interfaces (if needed).
|
||||
Since antd's components are based on react-component, sometimes you may need to send pull request to the corresponding react-component repository. If it's a bugfix pull request, after it's merged, the core team will release a patch release for that component as soon as possible, then you only need to reinstall antd in your project to get the latest patch release. If it's a feature pull request, after it's merged, the core team will release a minor release, then you need raise another pull request to [Ant Design](https://github.com/ant-design/ant-design/) to update dependencies, document and TypeScript interfaces (if needed).
|
||||
|
||||
## Development Workflow
|
||||
|
||||
|
@ -53,7 +53,7 @@ Ant Design 团队会关注所有的 pull request,我们会 review 以及合并
|
||||
3. 如果你修复了一个 bug 或者新增了一个功能,请确保写了相应的测试,这很重要。
|
||||
4. 确认所有的测试都是通过的 `npm run test`。 小贴士:开发过程中可以用 `npm test -- --watch TestName` 来运行指定的测试。
|
||||
5. 运行 `npm test -- -u` 来更新 [jest snapshot](http://facebook.github.io/jest/docs/en/snapshot-testing.html#snapshot-testing-with-jest) 并且把这些更新也提交上来(如果有的话)。
|
||||
6. 确保你的代码通过了 lint 检查 `npm run lint`. 小贴士: Lint 会在你 `git commit` 的时候自动运行。
|
||||
6. 确保你的代码通过了 lint 检查 `npm run lint`. 小贴士: Lint 会在你 `git commit` 的时候自动运行(通过[Git Hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks))。
|
||||
|
||||
给 [react-component](https://github.com/react-component/) 发送 pull request:
|
||||
|
||||
|
@ -7,120 +7,66 @@ In real project development, you might need a data flow solution like Redux or M
|
||||
|
||||
Dva is a lightweight data flow solution based on Redux. The concept comes from elm. It supports side effects, hot module replacement, dynamic loading, react-native, SSR, etc. It has been widely used in production.
|
||||
|
||||
And [umi](http://umijs.org/) is a routing-based framework that supports [next.js-like conventional routing](https://umijs.org/guide/router.html) and various advanced routing functions, such as [routing-level on-demand loading](https://umijs.org/en/plugin/umi-plugin-react.html#dynamicimport). With a complete [plugin system](https://umijs.org/plugin/) that covers every life cycle from source code to build product, umi is able to support various functional extensions and business needs.
|
||||
And [umi](http://umijs.org/) is a routing-based framework that supports [next.js-like conventional routing](https://umijs.org/guide/router.html) and various advanced routing functions, such as [routing-level on-demand loading](https://umijs.org/en/plugin/umi-plugin-react.html#dynamicimport). With a complete [plugin system](https://umijs.org/plugin/) that covers every life cycle from source code to build product, umi is able to support various functional extensions and business needs; meanwhile [Umi UI](https://umijs.org/guide/umi-ui.html) is provided to enhance the development experience and development efficiency through Visual Aided Programming (VAP).
|
||||
|
||||
> You may also be interested in [Ant Design Pro](https://pro.ant.design/), an Out-of-box UI solution for enterprise applications based on umi, dva and ant design.
|
||||
|
||||
This article will guide you to create a simple application from zero using umi, dva and antd.
|
||||
This article will guide you to create a simple application from zero using Umi UI, dva and antd.
|
||||
|
||||
## Create New App
|
||||
|
||||
First create an empty directory,
|
||||
|
||||
```bash
|
||||
$ mkdir myapp
|
||||
$ cd myapp
|
||||
```
|
||||
## Install Umi UI
|
||||
|
||||
It is recommended to use yarn to create an application and execute the following command.
|
||||
|
||||
> If you are using npm, execute `npm create umi` and the effect will be the same.
|
||||
> If you are using npm, execute `npm install umi -g` and the effect will be the same.
|
||||
|
||||
```bash
|
||||
$ yarn create umi
|
||||
|
||||
yarn create v1.12.0
|
||||
[1/4] 🔍 Resolving packages...
|
||||
[2/4] 🚚 Fetching packages...
|
||||
[3/4] 🔗 Linking dependencies...
|
||||
[4/4] 📃 Building fresh packages...
|
||||
|
||||
success Installed "create-umi@0.9.5" with binaries:
|
||||
- create-umi
|
||||
$ yarn global add umi
|
||||
$ umi -v
|
||||
2.10.4
|
||||
```
|
||||
|
||||
Yarn will install the latest version of [create-umi](https://github.com/umijs/create-umi) and then create the app with interactive ui.
|
||||
Make sure the umi version is above 2.10.0.
|
||||
|
||||
Select `app` and press Enter to confirm.
|
||||
## Create New App
|
||||
|
||||
```
|
||||
? Select the boilerplate type
|
||||
ant-design-pro - Create project with an layout-only ant-design-pro boilerplate, use together with umi block.
|
||||
❯ app - Create project with a simple boilerplate, support typescript.
|
||||
block - Create a umi block.
|
||||
library - Create a library with umi.
|
||||
plugin - Create a umi plugin.
|
||||
```
|
||||
|
||||
Select `antd` and `dva` and press Enter to confirm.
|
||||
Start the app,
|
||||
|
||||
```bash
|
||||
create package.json
|
||||
create mock/.gitkeep
|
||||
create src/assets/yay.jpg
|
||||
create src/layouts/index.css
|
||||
create src/layouts/index.js
|
||||
create src/pages/index.css
|
||||
create src/pages/index.js
|
||||
create src/global.css
|
||||
create .gitignore
|
||||
create .editorconfig
|
||||
create .env
|
||||
create .umirc.js
|
||||
create .eslintrc
|
||||
create .prettierrc
|
||||
create .prettierignore
|
||||
create src/models/.gitkeep
|
||||
create src/dva.js
|
||||
✨ File Generate Done
|
||||
✨ Done in 966.73s.
|
||||
$ umi ui
|
||||
|
||||
🚀 Starting Umi UI using umi@2.10.4...
|
||||
🧨 Ready on http://localhost:3000/
|
||||
```
|
||||
|
||||
Then install dependencies,
|
||||
After starting, Umi UI will automatically open the browser, then click `Create Project`, select the path and enter `App name`, as shown below.
|
||||
|
||||
```bash
|
||||
$ yarn
|
||||
```
|
||||
<img src="https://gw.alipayobjects.com/zos/antfincdn/kQSR2zWDQ6/26543f59-07de-44b7-8b1d-b34e1266de8b.png" width="718" />
|
||||
|
||||
Then start the app,
|
||||
Click `Next`, select `Basic Template`, select `antd` and `dva` on the technology stack, then click `Finish`.
|
||||
|
||||
```bash
|
||||
$ yarn start
|
||||
```
|
||||
<img src="https://gw.alipayobjects.com/zos/antfincdn/Pz9ayQpkWw/3c8a0190-ac32-444f-812e-3d1eff422507.png" width="718" />
|
||||
|
||||
After a few seconds, you will see the following output,
|
||||
In the project creation process, wait a few minutes.
|
||||
|
||||
```bash
|
||||
DONE Compiled successfully in 212ms
|
||||
<img src="https://gw.alipayobjects.com/zos/antfincdn/UtFy3fYg9n/bb7ef7c0-2fdb-403e-9b5a-d4ba02390483.png" width="718" />
|
||||
|
||||
App running at:
|
||||
- Local: http://localhost:8000/
|
||||
- Network: http://{{ YourIP }}:8000/
|
||||
```
|
||||
After creating, go to `Overview` and click on the shortcut entry `Run Dev`.
|
||||
|
||||
Open [http://localhost:8000](http://localhost:8000) in your browser, you will see the welcome page of umi.
|
||||
<img src="https://gw.alipayobjects.com/zos/antfincdn/sZj2WeXiqc/44ddbc70-386c-4c8a-8deb-6a4a93a3afb2.png" width="718" />
|
||||
|
||||
<img src="https://gw.alipayobjects.com/zos/rmsportal/lewbQdlEHzuNDpaxykUP.png" width="718" />
|
||||
In the task page, click `Start`,
|
||||
|
||||
<img src="https://gw.alipayobjects.com/zos/antfincdn/%24ot6F6Bj2L/a4c49cda-4ff8-409f-8054-9281199b6270.png" width="718" />
|
||||
|
||||
When prompted, open [http://localhost:8000](http://localhost:8000) in your browser, you will see the welcome page of umi.
|
||||
|
||||
<img src="https://gw.alipayobjects.com/zos/antfincdn/2Bm%24zoeBpz/ba708131-c7ac-41f0-92a0-c86007291b6a.png" width="718" />
|
||||
|
||||
## Integrate antd
|
||||
|
||||
After selecting `antd` earlier, antd's dependencies are automatically handled and loaded on demand. You can check the configuration in `.umirc.js` to make sure antd is turned on.
|
||||
After selecting `antd` earlier, antd's dependencies are automatically handled and loaded on demand. You can check the `Configuration` to make sure antd is turned on.
|
||||
|
||||
```js
|
||||
// ref: https://umijs.org/config/
|
||||
export default {
|
||||
plugins: [
|
||||
// ref: https://umijs.org/plugin/umi-plugin-react.html
|
||||
[
|
||||
'umi-plugin-react',
|
||||
{
|
||||
antd: true,
|
||||
dva: true,
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
||||
```
|
||||
<img src="https://gw.alipayobjects.com/zos/antfincdn/0EFiWipONe/7aea9287-09ff-4396-bb20-d8da28483c2c.png" width="718" />
|
||||
|
||||
> And if you want to use a fixed version of antd, you can install additional antd dependency in your project, and the antd dependencies declared in package.json will be used first.
|
||||
|
||||
@ -152,6 +98,10 @@ As your application grows and you notice you are sharing UI elements between mul
|
||||
|
||||
Let's create a `ProductList` component that we can use in multiple places to show a list of products.
|
||||
|
||||
Click `Open in editor`,
|
||||
|
||||
<img src="https://gw.alipayobjects.com/zos/antfincdn/yXRYDK88RS/2252c0f6-747f-422c-aeb6-dc518d74c8ea.png" width="718" />
|
||||
|
||||
Create `src/components/ProductList.js` by typing:
|
||||
|
||||
```js
|
||||
@ -262,28 +212,9 @@ Refresh your browser, you should see the following result:
|
||||
|
||||
## Build
|
||||
|
||||
Now that we've written our application and verified that it works in development, it's time to get it ready for deployment to our users. To do so, run the following command,
|
||||
Now that we've written our application and verified that it works in development, it's time to get it ready for deployment to our users. To do so, click `build` in Task page.
|
||||
|
||||
```bash
|
||||
$ npm run build
|
||||
```
|
||||
|
||||
After a few seconds, the output should be as follows,
|
||||
|
||||
```bash
|
||||
> @ build /private/tmp/sorrycc-V0lLrF
|
||||
> umi build
|
||||
|
||||
[5:01:58 PM] webpack compiled in 11s 615ms
|
||||
|
||||
|
||||
DONE Compiled successfully in 11622ms 5:01:58 PM
|
||||
|
||||
File sizes after gzip:
|
||||
|
||||
340.44 KB dist/umi.js
|
||||
17.82 KB dist/umi.css
|
||||
```
|
||||
<img src="https://gw.alipayobjects.com/zos/antfincdn/P31ZGMwzGe/d5365860-f7c6-4abe-98c0-36d6b1b3a65a.png" width="718" />
|
||||
|
||||
The `build` command packages up all of the assets that make up your application —— JavaScript, templates, CSS, web fonts, images, and more. Then you can find these files in the `dist/` directory.
|
||||
|
||||
|
@ -7,120 +7,66 @@ title: 项目实战
|
||||
|
||||
[dva](http://dvajs.com/) 是一个基于 Redux 的 轻量级数据流方案,概念来自 elm,支持 side effects、热替换、动态加载、react-native、SSR 等,已在生产环境广泛应用。
|
||||
|
||||
[umi](http://umijs.org/) 则是一个可插拔的企业级 react 应用框架。umi 以路由为基础的,支持[类 next.js 的约定式路由](https://umijs.org/zh/guide/router.html),以及各种进阶的路由功能,并以此进行功能扩展,比如[支持路由级的按需加载](https://umijs.org/zh/plugin/umi-plugin-react.html#dynamicimport)。然后配以完善的[插件体系](https://umijs.org/zh/plugin/),覆盖从源码到构建产物的每个生命周期,支持各种功能扩展和业务需求。
|
||||
[umi](http://umijs.org/) 则是一个可插拔的企业级 react 应用框架。umi 以路由为基础的,支持[类 next.js 的约定式路由](https://umijs.org/zh/guide/router.html),以及各种进阶的路由功能,并以此进行功能扩展,比如[支持路由级的按需加载](https://umijs.org/zh/plugin/umi-plugin-react.html#dynamicimport)。然后配以完善的[插件体系](https://umijs.org/zh/plugin/),覆盖从源码到构建产物的每个生命周期,支持各种功能扩展和业务需求,同时提供 [Umi UI](https://umijs.org/zh/guide/umi-ui.html) 通过可视化辅助编程(VAP)提高开发体验和研发效率。
|
||||
|
||||
> 你可能也会对 [Ant Design Pro](https://pro.ant.design/) 感兴趣,这是一个基于 umi、dva 和 ant design 的开箱即用的中台前端/设计解决方案。
|
||||
|
||||
本文会引导你使用 umi、dva 和 antd 从 0 开始创建一个简单应用。
|
||||
本文会引导你使用 Umi UI、dva 和 antd 从 0 开始创建一个简单应用。
|
||||
|
||||
## 安装 Umi UI
|
||||
|
||||
推荐使用 yarn 安装 Umi UI,执行以下命令。
|
||||
|
||||
> 如果你使用 npm,可执行 `npm install umi -g`,效果一致。
|
||||
|
||||
```bash
|
||||
$ yarn global add umi
|
||||
$ umi -v
|
||||
2.10.4
|
||||
```
|
||||
|
||||
确保 umi 版本在 2.10.0 以上。
|
||||
|
||||
## 创建新应用
|
||||
|
||||
先创建一个空目录,
|
||||
启动 Umi UI,
|
||||
|
||||
```bash
|
||||
$ mkdir myapp
|
||||
$ cd myapp
|
||||
$ umi ui
|
||||
|
||||
🚀 Starting Umi UI using umi@2.10.4...
|
||||
🧨 Ready on http://localhost:3000/
|
||||
```
|
||||
|
||||
推荐使用 yarn 创建应用,执行以下命令,
|
||||
启动后, Umi UI 会自动打开浏览器,点击 `创建项目`,选择路径并输入 `应用名`,如下图:
|
||||
|
||||
> 如果你使用 npm,可执行 `npm create umi`,效果一致。
|
||||
<img src="https://gw.alipayobjects.com/zos/antfincdn/1%24I%24KuXNop/60f0bae2-d803-4339-bc09-8df618ebd916.png" width="718" />
|
||||
|
||||
```bash
|
||||
$ yarn create umi
|
||||
点击 `下一步`,选择 `基础模板`,技术栈选上 `antd` 和 `dva`,然后点击 `完成`。
|
||||
|
||||
yarn create v1.12.0
|
||||
[1/4] 🔍 Resolving packages...
|
||||
[2/4] 🚚 Fetching packages...
|
||||
[3/4] 🔗 Linking dependencies...
|
||||
[4/4] 📃 Building fresh packages...
|
||||
<img src="https://gw.alipayobjects.com/zos/antfincdn/9gmy78Evsp/7978f0b2-8b8c-44fa-84df-bfe9dc6065f4.png" width="718" />
|
||||
|
||||
success Installed "create-umi@0.9.5" with binaries:
|
||||
- create-umi
|
||||
```
|
||||
进入到项目创建流程,等待几分钟,
|
||||
|
||||
yarn 会先安装最新版的 [create-umi](https://github.com/umijs/create-umi),然后提供交互式的提示来创建应用。
|
||||
<img src="https://gw.alipayobjects.com/zos/antfincdn/cT35jkUl4j/8381545c-7f89-48ef-9e93-8adcdd6a3bb4.png" width="718" />
|
||||
|
||||
选择 `app`, 然后回车确认。
|
||||
创建完成后,进入到 `总览`,点击快捷入口 `本地启动`,
|
||||
|
||||
```
|
||||
? Select the boilerplate type
|
||||
ant-design-pro - Create project with an layout-only ant-design-pro boilerplate, use together with umi block.
|
||||
❯ app - Create project with a simple boilerplate, support typescript.
|
||||
block - Create a umi block.
|
||||
library - Create a library with umi.
|
||||
plugin - Create a umi plugin.
|
||||
```
|
||||
<img src="https://gw.alipayobjects.com/zos/antfincdn/vGsor%24iku8/531acbd7-f48e-4246-bc77-152117ef56db.png" width="718" />
|
||||
|
||||
选上 `antd` 和 `dva`,然后回车确认。
|
||||
在任务页中,点击 `启动`,
|
||||
|
||||
```
|
||||
create package.json
|
||||
create mock/.gitkeep
|
||||
create src/assets/yay.jpg
|
||||
create src/layouts/index.css
|
||||
create src/layouts/index.js
|
||||
create src/pages/index.css
|
||||
create src/pages/index.js
|
||||
create src/global.css
|
||||
create .gitignore
|
||||
create .editorconfig
|
||||
create .env
|
||||
create .umirc.js
|
||||
create .eslintrc
|
||||
create .prettierrc
|
||||
create .prettierignore
|
||||
create src/models/.gitkeep
|
||||
create src/dva.js
|
||||
✨ File Generate Done
|
||||
✨ Done in 966.73s.
|
||||
```
|
||||
<img src="https://gw.alipayobjects.com/zos/antfincdn/RRYNqxBs9g/72ec5739-ac1f-40a6-8f7a-204c7faba0a7.png" width="718" />
|
||||
|
||||
然后安装依赖,
|
||||
按提示,点击 [http://localhost:8000](http://localhost:8000),你会看到 umi 的欢迎界面。
|
||||
|
||||
```bash
|
||||
$ yarn
|
||||
```
|
||||
|
||||
然后启动应用,
|
||||
|
||||
```bash
|
||||
$ yarn start
|
||||
```
|
||||
|
||||
几秒钟后,你会看到以下输出,
|
||||
|
||||
```bash
|
||||
DONE Compiled successfully in 212ms
|
||||
|
||||
App running at:
|
||||
- Local: http://localhost:8000/
|
||||
- Network: http://{{ YourIP }}:8000/
|
||||
```
|
||||
|
||||
在浏览器里打开 [http://localhost:8000](http://localhost:8000),你会看到 umi 的欢迎界面。
|
||||
|
||||
<img src="https://gw.alipayobjects.com/zos/rmsportal/lewbQdlEHzuNDpaxykUP.png" width="718" />
|
||||
<img src="https://gw.alipayobjects.com/zos/antfincdn/2Bm%24zoeBpz/ba708131-c7ac-41f0-92a0-c86007291b6a.png" width="718" />
|
||||
|
||||
## 使用 antd
|
||||
|
||||
前面选择 antd 之后,会自动处理 antd 的依赖以及按需加载。你可以检查 `.umirc.js` 里的配置,确保 antd 已开启。
|
||||
前面选择 antd 之后,会自动处理 antd 的依赖以及按需加载。你可以检查 `配置`,确保 antd 已开启。
|
||||
|
||||
```js
|
||||
// ref: https://umijs.org/config/
|
||||
export default {
|
||||
plugins: [
|
||||
// ref: https://umijs.org/plugin/umi-plugin-react.html
|
||||
[
|
||||
'umi-plugin-react',
|
||||
{
|
||||
antd: true,
|
||||
dva: true,
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
||||
```
|
||||
<img src="https://gw.alipayobjects.com/zos/antfincdn/0EFiWipONe/7aea9287-09ff-4396-bb20-d8da28483c2c.png" width="718" />
|
||||
|
||||
> 而如果要使用固定版本的 antd,你可以在项目里安装额外的 antd 依赖,package.json 里声明的 antd 依赖会被优先使用。
|
||||
|
||||
@ -128,16 +74,10 @@ export default {
|
||||
|
||||
我们要写个应用来先显示产品列表。首先第一步是创建路由,路由可以想象成是组成应用的不同页面。
|
||||
|
||||
如果你没有 npx,需要先安装他,用于执行 node_modules 下的命令,
|
||||
|
||||
```bash
|
||||
$ yarn global add npx
|
||||
```
|
||||
|
||||
然后通过命令创建 `/products` 路由,
|
||||
|
||||
```bash
|
||||
$ npx umi g page products
|
||||
$ umi g page products
|
||||
|
||||
create src/pages/products.js
|
||||
create src/pages/products.css
|
||||
@ -152,7 +92,11 @@ $ npx umi g page products
|
||||
|
||||
我们来编写一个 `ProductList` component,这样就能在不同的地方显示产品列表了。
|
||||
|
||||
新建 `src/components/ProductList.js` 文件:
|
||||
点击 `在编辑器中打开`,
|
||||
|
||||
<img src="https://gw.alipayobjects.com/zos/antfincdn/ffPr49NZ%26p/64fa0ad5-9a7a-43c0-b308-ffe28e680a8b.png" width="718" />
|
||||
|
||||
然后新建 `src/components/ProductList.js` 文件:
|
||||
|
||||
```js
|
||||
import { Table, Popconfirm, Button } from 'antd';
|
||||
@ -262,30 +206,11 @@ export const dva = {
|
||||
|
||||
## 构建应用
|
||||
|
||||
完成开发并且在开发环境验证之后,就需要部署给我们的用户了。先执行下面的命令,
|
||||
完成开发并且在开发环境验证之后,就需要部署给我们的用户了。点击 `构建`,
|
||||
|
||||
```bash
|
||||
$ npm run build
|
||||
```
|
||||
<img src="https://gw.alipayobjects.com/zos/antfincdn/D%2671c0zDk%26/a6c69c76-28e1-4001-9228-3affe8468e2f.png" width="718" />
|
||||
|
||||
几秒后,输出应该如下:
|
||||
|
||||
```bash
|
||||
> @ build /private/tmp/sorrycc-V0lLrF
|
||||
> umi build
|
||||
|
||||
[5:01:58 PM] webpack compiled in 11s 615ms
|
||||
|
||||
|
||||
DONE Compiled successfully in 11622ms 5:01:58 PM
|
||||
|
||||
File sizes after gzip:
|
||||
|
||||
340.44 KB dist/umi.js
|
||||
17.82 KB dist/umi.css
|
||||
```
|
||||
|
||||
build 命令会打包所有的资源,包含 JavaScript, CSS, web fonts, images, html 等。你可以在 `dist/` 目录下找到这些文件。
|
||||
构建会打包所有的资源,包含 JavaScript, CSS, web fonts, images, html 等。你可以在 `dist/` 目录下找到这些文件。
|
||||
|
||||
## 下一步
|
||||
|
||||
|
@ -88,7 +88,7 @@ Ok, you should now see a blue primary button displayed on the page. Next you can
|
||||
|
||||
## Advanced Guides
|
||||
|
||||
We are successfully running antd components now but in the real world, there are still lots of problems about antd-demo. For instance, we actually import styles of all components in the project which may be a css bundle size issue (It is OK then if you don't case the gzipped 60kb css file size).
|
||||
We are successfully running antd components now but in the real world, there are still lots of problems about antd-demo. For instance, we actually import styles of all components in the project which may be a css bundle size issue (It is OK then if you don't care the gzipped 60kb css file size).
|
||||
|
||||
Now we need to customize the default webpack config. We can achieve that by using [react-app-rewired](https://github.com/timarney/react-app-rewired) which is one of create-react-app's custom config solutions.
|
||||
|
||||
|
11
package.json
11
package.json
@ -45,7 +45,7 @@
|
||||
"bundlesize": "bundlesize",
|
||||
"check-commit": "node ./scripts/check-commit.js",
|
||||
"compile": "antd-tools run compile",
|
||||
"predeploy": "antd-tools run clean && npm run site && cp netlify.toml CNAME _site && cp .circleci/config.yml _site",
|
||||
"predeploy": "antd-tools run clean && npm run site && cp netlify.toml CNAME _site && cp .circleci/config.yml _site && npm run site:test",
|
||||
"deploy": "bisheng gh-pages --push-only",
|
||||
"deploy:china-mirror": "git checkout gh-pages && git pull origin gh-pages && git push git@gitee.com:ant-design/ant-design.git gh-pages",
|
||||
"dist": "antd-tools run dist",
|
||||
@ -73,7 +73,8 @@
|
||||
"test": "jest --config .jest.js --no-cache",
|
||||
"test-all": "./scripts/test-all.sh",
|
||||
"test-node": "jest --config .jest.node.js --no-cache",
|
||||
"tsc": "tsc"
|
||||
"tsc": "tsc",
|
||||
"site:test": "jest --config .jest.site.js --cache=false"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
@ -127,7 +128,7 @@
|
||||
"rc-slider": "~8.7.1",
|
||||
"rc-steps": "~3.5.0",
|
||||
"rc-switch": "~1.9.0",
|
||||
"rc-table": "~6.8.6",
|
||||
"rc-table": "~6.9.4",
|
||||
"rc-tabs": "~9.6.4",
|
||||
"rc-time-picker": "~3.7.1",
|
||||
"rc-tooltip": "~3.7.3",
|
||||
@ -159,7 +160,7 @@
|
||||
"@types/shallowequal": "^1.1.1",
|
||||
"@types/warning": "^3.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^2.0.0",
|
||||
"@typescript-eslint/parser": "^2.0.0",
|
||||
"@typescript-eslint/parser": "~2.4.0",
|
||||
"@yesmeck/offline-plugin": "^5.0.5",
|
||||
"antd-theme-generator": "^1.1.6",
|
||||
"babel-eslint": "^10.0.1",
|
||||
@ -171,6 +172,7 @@
|
||||
"bisheng-plugin-toc": "^0.4.4",
|
||||
"bundlesize": "^0.18.0",
|
||||
"chalk": "^2.4.2",
|
||||
"cheerio": "^1.0.0-rc.3",
|
||||
"cross-env": "^6.0.0",
|
||||
"css-split-webpack-plugin": "^0.2.6",
|
||||
"dekko": "^0.2.1",
|
||||
@ -192,6 +194,7 @@
|
||||
"fetch-jsonp": "^1.1.3",
|
||||
"full-icu": "^1.3.0",
|
||||
"glob": "^7.1.4",
|
||||
"http-server": "^0.11.1",
|
||||
"husky": "^3.0.2",
|
||||
"immutability-helper": "^3.0.0",
|
||||
"intersection-observer": "^0.7.0",
|
||||
|
93
scripts/check-site.js
Executable file
93
scripts/check-site.js
Executable file
@ -0,0 +1,93 @@
|
||||
/* eslint-disable no-await-in-loop */
|
||||
/* eslint-disable no-restricted-syntax */
|
||||
const fetch = require('node-fetch');
|
||||
const { join } = require('path');
|
||||
const cheerio = require('cheerio');
|
||||
const glob = require('glob');
|
||||
const uniq = require('lodash/uniq');
|
||||
const { createServer } = require('http-server');
|
||||
const zhCN = require('../site/theme/zh-CN');
|
||||
const enUS = require('../site/theme/en-US');
|
||||
|
||||
const components = uniq(
|
||||
glob
|
||||
.sync('components/*/*.md', {
|
||||
ignore: '**/{__tests__,_util,version,index.tsx}',
|
||||
cwd: join(process.cwd()),
|
||||
dot: false,
|
||||
})
|
||||
.map(path => path.replace(/(\/index)?((\.zh-CN)|(\.en-US))?\.md$/i, '')),
|
||||
);
|
||||
|
||||
describe('site test', () => {
|
||||
let server;
|
||||
const host = 3000;
|
||||
const render = async path => {
|
||||
const resp = await fetch(`http://localhost:${host}${path}`).then(async res => {
|
||||
const html = await res.text();
|
||||
const $ = cheerio.load(html, { decodeEntities: false, recognizeSelfClosing: true });
|
||||
return {
|
||||
html,
|
||||
status: res.status,
|
||||
$,
|
||||
};
|
||||
});
|
||||
return resp;
|
||||
};
|
||||
const handleComponentName = name => {
|
||||
const componentMap = {
|
||||
descriptions: 'description list',
|
||||
};
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const [_, componentName] = name.split('/');
|
||||
const compName = componentName.toLowerCase().replace('-', '');
|
||||
return componentMap[compName] || compName;
|
||||
};
|
||||
|
||||
const expectComponent = async component => {
|
||||
const { status, $ } = await render(`/${component}/`);
|
||||
expect(status).toBe(200);
|
||||
expect(
|
||||
$('.markdown > h1')
|
||||
.text()
|
||||
.toLowerCase(),
|
||||
).toMatch(handleComponentName(component));
|
||||
};
|
||||
|
||||
beforeAll(() => {
|
||||
server = createServer({
|
||||
root: join(process.cwd(), '_site'),
|
||||
});
|
||||
server.listen(host);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('site static server run: http://localhost:3000');
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
if (server) {
|
||||
server.close();
|
||||
}
|
||||
});
|
||||
|
||||
it('Basic Pages en', async () => {
|
||||
const { status, $ } = await render('/');
|
||||
expect($('title').text()).toEqual(`Ant Design - ${enUS.messages['app.home.slogan']}`);
|
||||
expect(status).toBe(200);
|
||||
});
|
||||
|
||||
it('Basic Pages zh', async () => {
|
||||
const { status, $ } = await render('/index-cn');
|
||||
expect($('title').text()).toEqual(`Ant Design - ${zhCN.messages['app.home.slogan']}`);
|
||||
expect(status).toBe(200);
|
||||
});
|
||||
|
||||
for (const component of components) {
|
||||
it(`Component ${component} zh Page`, async () => {
|
||||
await expectComponent(component);
|
||||
});
|
||||
|
||||
it(`Component ${component} en Page`, async () => {
|
||||
await expectComponent(component);
|
||||
});
|
||||
}
|
||||
});
|
@ -125,6 +125,7 @@ module.exports = {
|
||||
'app.docs.components.icon.pic-searcher.server-error':
|
||||
'Predict service is temporarily unavailable',
|
||||
'app.docs.components.icon.pic-searcher.matching': 'Matching...',
|
||||
'app.docs.components.icon.pic-searcher.modelloading': 'Model is loading...',
|
||||
'app.docs.components.icon.pic-searcher.result-tip': 'Match the following icons for you:',
|
||||
'app.docs.components.icon.pic-searcher.th-icon': 'Icon',
|
||||
'app.docs.components.icon.pic-searcher.th-score': 'Probability',
|
||||
|
@ -66,8 +66,8 @@
|
||||
width: 54%;
|
||||
min-width: 420px;
|
||||
max-width: 560px;
|
||||
min-height: 336px;
|
||||
color: #0d1a26;
|
||||
min-height: 400px;
|
||||
color: @home-text-color;
|
||||
> * {
|
||||
will-change: transform;
|
||||
}
|
||||
|
@ -392,6 +392,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
[id='components-grid-demo-playground'],
|
||||
[id='components-grid-demo-gutter'] {
|
||||
> .code-box-demo .ant-row > div {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// For Changelog
|
||||
.markdown ul.ant-timeline {
|
||||
line-height: 2;
|
||||
|
@ -68,7 +68,6 @@ const Banner = ({ isMobile }) => {
|
||||
{!isMobile && (
|
||||
<GitHubButton
|
||||
style={{ marginLeft: 16 }}
|
||||
key="github-button"
|
||||
size="large"
|
||||
type="stargazers"
|
||||
namespace="ant-design"
|
||||
|
@ -9,6 +9,15 @@ const allIcons: {
|
||||
} = AntdIcons;
|
||||
|
||||
const { Dragger } = Upload;
|
||||
interface AntdIconClassifier {
|
||||
load: Function;
|
||||
predict: Function;
|
||||
}
|
||||
declare global {
|
||||
interface Window {
|
||||
antdIconClassifier: AntdIconClassifier;
|
||||
}
|
||||
}
|
||||
|
||||
interface PicSearcherProps {
|
||||
intl: any;
|
||||
@ -21,6 +30,7 @@ interface PicSearcherState {
|
||||
icons: Array<string>;
|
||||
fileList: Array<any>;
|
||||
error: boolean;
|
||||
modelLoaded: boolean;
|
||||
}
|
||||
|
||||
interface iconObject {
|
||||
@ -36,10 +46,11 @@ class PicSearcher extends Component<PicSearcherProps, PicSearcherState> {
|
||||
icons: [],
|
||||
fileList: [],
|
||||
error: false,
|
||||
modelLoaded: false,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
document.addEventListener('paste', this.onPaste);
|
||||
this.loadModel();
|
||||
this.setState({ popoverVisible: !localStorage.getItem('disableIconTip') });
|
||||
}
|
||||
|
||||
@ -47,6 +58,17 @@ class PicSearcher extends Component<PicSearcherProps, PicSearcherState> {
|
||||
document.removeEventListener('paste', this.onPaste);
|
||||
}
|
||||
|
||||
loadModel = () => {
|
||||
const script = document.createElement('script');
|
||||
script.onload = async () => {
|
||||
await window.antdIconClassifier.load();
|
||||
this.setState({ modelLoaded: true });
|
||||
document.addEventListener('paste', this.onPaste);
|
||||
};
|
||||
script.src = 'https://cdn.jsdelivr.net/gh/lewis617/antd-icon-classifier@0.0/dist/main.js';
|
||||
document.head.appendChild(script);
|
||||
};
|
||||
|
||||
onPaste = (event: ClipboardEvent) => {
|
||||
const items = event.clipboardData && event.clipboardData.items;
|
||||
let file = null;
|
||||
@ -62,9 +84,10 @@ class PicSearcher extends Component<PicSearcherProps, PicSearcherState> {
|
||||
};
|
||||
|
||||
uploadFile = (file: File) => {
|
||||
this.setState(() => ({ loading: true }));
|
||||
const reader: FileReader = new FileReader();
|
||||
reader.onload = () => {
|
||||
this.downscaleImage(reader.result).then(this.predict);
|
||||
this.toImage(reader.result).then(this.predict);
|
||||
this.setState(() => ({
|
||||
fileList: [{ uid: 1, name: file.name, status: 'done', url: reader.result }],
|
||||
}));
|
||||
@ -72,46 +95,27 @@ class PicSearcher extends Component<PicSearcherProps, PicSearcherState> {
|
||||
reader.readAsDataURL(file);
|
||||
};
|
||||
|
||||
downscaleImage = (url: any) => {
|
||||
toImage = (url: any) => {
|
||||
return new Promise(resolve => {
|
||||
const img = new Image();
|
||||
img.setAttribute('crossOrigin', 'anonymous');
|
||||
img.src = url;
|
||||
img.onload = function onload() {
|
||||
const scale = Math.min(1, 300 / Math.max(img.width, img.height));
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = img.width * scale;
|
||||
canvas.height = img.height * scale;
|
||||
const ctx = canvas.getContext('2d');
|
||||
(ctx as CanvasRenderingContext2D).drawImage(img, 0, 0, canvas.width, canvas.height);
|
||||
const newDataUrl = canvas.toDataURL('image/jpeg');
|
||||
resolve(newDataUrl);
|
||||
resolve(img);
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
predict = async (imageBase64: any) => {
|
||||
this.setState(() => ({ loading: true }));
|
||||
predict = (imgEl: any) => {
|
||||
try {
|
||||
const res = await fetch(
|
||||
'//1647796581073291.cn-shanghai.fc.aliyuncs.com/2016-08-15/proxy/cr-sh.cr-fc-predict__stable/cr-fc-predict/',
|
||||
{
|
||||
method: 'post',
|
||||
body: JSON.stringify({
|
||||
modelId: 'data_icon',
|
||||
type: 'ic',
|
||||
imageBase64,
|
||||
}),
|
||||
},
|
||||
);
|
||||
let icons = await res.json();
|
||||
let icons = window.antdIconClassifier.predict(imgEl);
|
||||
if (gtag && icons.length >= 1) {
|
||||
gtag('event', 'icon', {
|
||||
event_category: 'search-by-image',
|
||||
event_label: icons[0].class_name,
|
||||
event_label: icons[0].className,
|
||||
});
|
||||
}
|
||||
icons = icons.map((i: any) => ({ score: i.score, type: i.class_name.replace(/\s/g, '-') }));
|
||||
icons = icons.map((i: any) => ({ score: i.score, type: i.className.replace(/\s/g, '-') }));
|
||||
this.setState(() => ({ icons, loading: false, error: false }));
|
||||
} catch (err) {
|
||||
this.setState(() => ({ loading: false, error: true }));
|
||||
@ -142,7 +146,15 @@ class PicSearcher extends Component<PicSearcherProps, PicSearcherState> {
|
||||
const {
|
||||
intl: { messages },
|
||||
} = this.props;
|
||||
const { modalVisible, popoverVisible, icons, fileList, loading, error } = this.state;
|
||||
const {
|
||||
modalVisible,
|
||||
popoverVisible,
|
||||
icons,
|
||||
fileList,
|
||||
loading,
|
||||
modelLoaded,
|
||||
error,
|
||||
} = this.state;
|
||||
return (
|
||||
<div className="icon-pic-searcher">
|
||||
<Popover
|
||||
@ -157,23 +169,33 @@ class PicSearcher extends Component<PicSearcherProps, PicSearcherState> {
|
||||
onCancel={this.toggleModal}
|
||||
footer={null}
|
||||
>
|
||||
<Dragger
|
||||
accept="image/jpeg, image/png"
|
||||
listType="picture"
|
||||
customRequest={(o: any) => this.uploadFile(o.file)}
|
||||
fileList={fileList}
|
||||
showUploadList={{ showPreviewIcon: false, showRemoveIcon: false }}
|
||||
>
|
||||
<p className="ant-upload-drag-icon">
|
||||
<AntdIcons.Inbox />
|
||||
</p>
|
||||
<p className="ant-upload-text">
|
||||
{messages['app.docs.components.icon.pic-searcher.upload-text']}
|
||||
</p>
|
||||
<p className="ant-upload-hint">
|
||||
{messages['app.docs.components.icon.pic-searcher.upload-hint']}
|
||||
</p>
|
||||
</Dragger>
|
||||
{modelLoaded || (
|
||||
<Spin
|
||||
spinning={!modelLoaded}
|
||||
tip={messages['app.docs.components.icon.pic-searcher.modelloading']}
|
||||
>
|
||||
<div style={{ height: 100 }} />
|
||||
</Spin>
|
||||
)}
|
||||
{modelLoaded && (
|
||||
<Dragger
|
||||
accept="image/jpeg, image/png"
|
||||
listType="picture"
|
||||
customRequest={(o: any) => this.uploadFile(o.file)}
|
||||
fileList={fileList}
|
||||
showUploadList={{ showPreviewIcon: false, showRemoveIcon: false }}
|
||||
>
|
||||
<p className="ant-upload-drag-icon">
|
||||
<AntdIcons.Inbox />
|
||||
</p>
|
||||
<p className="ant-upload-text">
|
||||
{messages['app.docs.components.icon.pic-searcher.upload-text']}
|
||||
</p>
|
||||
<p className="ant-upload-hint">
|
||||
{messages['app.docs.components.icon.pic-searcher.upload-hint']}
|
||||
</p>
|
||||
</Dragger>
|
||||
)}
|
||||
<Spin spinning={loading} tip={messages['app.docs.components.icon.pic-searcher.matching']}>
|
||||
<div className="icon-pic-search-result">
|
||||
{icons.length > 0 && (
|
||||
|
@ -4,12 +4,13 @@ import { Radio, Input } from 'antd';
|
||||
import { RadioChangeEvent } from 'antd/es/radio/interface';
|
||||
import { injectIntl } from 'react-intl';
|
||||
import debounce from 'lodash/debounce';
|
||||
import { ThemeType } from 'antd/es/icon';
|
||||
import Category from './Category';
|
||||
import IconPicSearcher from './IconPicSearcher';
|
||||
import { FilledIcon, OutlinedIcon, TwoToneIcon } from './themeIcons';
|
||||
import { categories, Categories, CategoriesKeys } from './fields';
|
||||
|
||||
type ThemeType = 'filled' | 'outlined' | 'twoTone';
|
||||
|
||||
const allIcons: {
|
||||
[key: string]: any;
|
||||
} = AntdIcons;
|
||||
|
@ -1,5 +1,16 @@
|
||||
import * as React from 'react';
|
||||
import { CustomIconComponentProps } from 'antd/es/icon';
|
||||
|
||||
interface CustomIconComponentProps {
|
||||
width: string | number;
|
||||
height: string | number;
|
||||
fill: string;
|
||||
viewBox?: string;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
spin?: boolean;
|
||||
rotate?: number;
|
||||
['aria-hidden']?: React.AriaAttributes['aria-hidden'];
|
||||
}
|
||||
|
||||
export const FilledIcon: React.SFC<CustomIconComponentProps> = props => {
|
||||
const path =
|
||||
|
@ -119,6 +119,7 @@ module.exports = {
|
||||
'我们会通过上传的图片进行匹配,得到最相似的图标',
|
||||
'app.docs.components.icon.pic-searcher.server-error': '识别服务暂不可用',
|
||||
'app.docs.components.icon.pic-searcher.matching': '匹配中...',
|
||||
'app.docs.components.icon.pic-searcher.modelloading': '神经网络模型加载中...',
|
||||
'app.docs.components.icon.pic-searcher.result-tip': '为您匹配到以下图标:',
|
||||
'app.docs.components.icon.pic-searcher.th-icon': '图标',
|
||||
'app.docs.components.icon.pic-searcher.th-score': '匹配度',
|
||||
|
18
tests/__mocks__/react.js
vendored
18
tests/__mocks__/react.js
vendored
@ -1,18 +0,0 @@
|
||||
import createReactContext from '@ant-design/create-react-context/lib/implementation';
|
||||
|
||||
const React = require.requireActual('react');
|
||||
|
||||
if (!React.createContext) {
|
||||
React.createContext = createReactContext;
|
||||
}
|
||||
|
||||
if (!React.createRef) {
|
||||
React.createRef = () => {
|
||||
const ref = function setRef(node) {
|
||||
ref.current = node;
|
||||
};
|
||||
return ref;
|
||||
};
|
||||
}
|
||||
|
||||
Object.assign(module.exports, React);
|
@ -1,3 +1,8 @@
|
||||
const React = require('react');
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Current React Version:', React.version);
|
||||
|
||||
/* eslint-disable global-require */
|
||||
if (typeof window !== 'undefined') {
|
||||
global.window.resizeTo = (width, height) => {
|
||||
|
@ -1,5 +1,10 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"antd": ["components/index.tsx"],
|
||||
"antd/es/*": ["components/*"]
|
||||
},
|
||||
"strictNullChecks": true,
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"extends": ["./node_modules/@ant-design/tools/lib/tslint.json"]
|
||||
}
|
11
typings/custom-typings.d.ts
vendored
11
typings/custom-typings.d.ts
vendored
@ -18,16 +18,10 @@ declare module 'rc-cascader';
|
||||
|
||||
declare module 'rc-checkbox';
|
||||
|
||||
declare module 'rc-radio';
|
||||
|
||||
declare module 'rc-dropdown';
|
||||
|
||||
declare module 'rc-editor-mention';
|
||||
|
||||
declare module 'rc-progress';
|
||||
|
||||
declare module 'rc-drawer';
|
||||
|
||||
declare module 'rc-tabs*';
|
||||
|
||||
declare module 'rc-tree';
|
||||
@ -79,6 +73,7 @@ declare module '*.json' {
|
||||
export default value;
|
||||
}
|
||||
|
||||
declare module 'react-lifecycles-compat';
|
||||
|
||||
declare module 'react-copy-to-clipboard';
|
||||
|
||||
// https://github.com/ant-design/ant-design/pull/19254
|
||||
declare module 'react-lifecycles-compat';
|
||||
|
Loading…
Reference in New Issue
Block a user