merge master

This commit is contained in:
zombiej 2019-12-01 21:46:17 +08:00
commit d76283f2b9
58 changed files with 8577 additions and 2708 deletions

View File

@ -5,7 +5,6 @@ on: [push]
jobs: jobs:
setup: setup:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@master uses: actions/checkout@master
@ -21,7 +20,9 @@ jobs:
- name: hack for singe file - name: hack for singe file
run: | run: |
mkdir package-temp-dir if [ ! -d "package-temp-dir" ]; then
mkdir package-temp-dir
fi
cp package-lock.json package-temp-dir cp package-lock.json package-temp-dir
- name: cache node_modules - name: cache node_modules
@ -37,7 +38,6 @@ jobs:
compile: compile:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@master uses: actions/checkout@master
@ -71,12 +71,10 @@ jobs:
- name: check - name: check
run: node ./tests/dekko/lib.test.js run: node ./tests/dekko/lib.test.js
needs: setup needs: setup
dist: dist:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@master uses: actions/checkout@master
@ -103,12 +101,10 @@ jobs:
run: npm test run: npm test
env: env:
LIB_DIR: dist LIB_DIR: dist
needs: setup needs: setup
lint: lint:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@master uses: actions/checkout@master
@ -127,12 +123,10 @@ jobs:
- name: lint - name: lint
run: npm run lint run: npm run lint
needs: setup needs: setup
node: node:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@master uses: actions/checkout@master
@ -151,12 +145,10 @@ jobs:
- name: test - name: test
run: npm test run: npm test
needs: setup needs: setup
lib: lib:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@master uses: actions/checkout@master
@ -183,12 +175,10 @@ jobs:
run: npm test run: npm test
env: env:
LIB_DIR: lib LIB_DIR: lib
needs: compile needs: compile
es: es:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@master uses: actions/checkout@master
@ -215,5 +205,4 @@ jobs:
run: npm test run: npm test
env: env:
LIB_DIR: es LIB_DIR: es
needs: compile needs: compile

View File

@ -15,6 +15,26 @@ timeline: true
--- ---
## 3.26.0
`2019-12-01`
- 🏆 `3.26.0` will be the last minor version of antd v3. And v4 beta is coming!
- 🌟 Notification support `closeIcon` props. [#19618](https://github.com/ant-design/ant-design/pull/19618) [@liuchao233](https://github.com/liuchao233)
- 🌟 Typography support `pt_BR` locale. [#19651](https://github.com/ant-design/ant-design/pull/19651) [@liuchao233](https://github.com/liuchao233)
- 🌟 Table support `defaultFilteredValues` props. [#18925](https://github.com/ant-design/ant-design/pull/18925) [@mgcrea](https://github.com/mgcrea)
- 🇲🇰 Locale add Macedonian support. [#19647](https://github.com/ant-design/ant-design/pull/19647) [@sradevski](https://github.com/sradevski)
- 🐞 Fix Input.Group compat mode has wrong border radius for Input Addon. [#19926](https://github.com/ant-design/ant-design/pull/19926)
- 🐞 Fix Spin render default indicator when `indicator` is `null`. [#19943](https://github.com/ant-design/ant-design/pull/19943)
- 🐞 Fix Button component `disabled` with `loading` not prevent pointer-events. [#19958](https://github.com/ant-design/ant-design/pull/19958)
- 🐞 Fix message can not cancel when `key` is provided. [#19967](https://github.com/ant-design/ant-design/pull/19967)
- 🐞 Fix image in Upload with `picture-card` mode exceeds the border. [#20008](https://github.com/ant-design/ant-design/pull/20008) [@qq645381995](https://github.com/qq645381995)
- 🐞 Fix Input clear icon overlap with feedback icon. [#20017](https://github.com/ant-design/ant-design/pull/20017)
- 🐞 Fix Slider tooltip text not align center. [#20016](https://github.com/ant-design/ant-design/pull/20016)
- 🐞 Fix Descriptions items not working with React.Fragment. [#20019](https://github.com/ant-design/ant-design/pull/20019)
- 🛠 Upload under drag mode moves `className` and `style` to the real effect dom.[#19987](https://github.com/ant-design/ant-design/pull/19987)
- 💄Add less variable `@table-header-bg-sm` and fix small Table footer style. [#19939](https://github.com/ant-design/ant-design/pull/19939)
## 3.25.3 ## 3.25.3
`2019-11-24` `2019-11-24`

View File

@ -15,6 +15,26 @@ timeline: true
--- ---
## 3.26.0
`2019-12-01`
- 🏆 `3.26.0` 将为 antd v3 最后一个 minor 版本v4 beta 版即将发布!
- 🌟 Notification 支持 `closeIcon` 属性。[#19618](https://github.com/ant-design/ant-design/pull/19618) [@liuchao233](https://github.com/liuchao233)
- 🌟 Typography 添加 `pt_BR` 国际化支持。[#19651](https://github.com/ant-design/ant-design/pull/19651) [@liuchao233](https://github.com/liuchao233)
- 🌟 Table 支持 `defaultFilteredValues` 属性。[#18925](https://github.com/ant-design/ant-design/pull/18925) [@mgcrea](https://github.com/mgcrea)
- 🇲🇰 国际化添加北马其顿支持。[#19647](https://github.com/ant-design/ant-design/pull/19647) [@sradevski](https://github.com/sradevski)
- 🐞 修复 Input.Group 紧凑模式下使用 Input Addon 圆角不对的问题。[#19926](https://github.com/ant-design/ant-design/pull/19926)
- 🐞 修复 Spin 在 `indicator` 属性为 `null` 时,渲染默认的旋转图标。[#19943](https://github.com/ant-design/ant-design/pull/19943)
- 🐞 修复 Button 组件 `disabled``loading` 状态下没有阻止鼠标事件。[#19958](https://github.com/ant-design/ant-design/pull/19958)
- 🐞 修复 message 组件使用 `key` 时无法手动取消的问题。[#19967](https://github.com/ant-design/ant-design/pull/19967)
- 🐞 修复 Upload 在 `picture-card` 模式下,图片过长会超出边界的问题。[#20008](https://github.com/ant-design/ant-design/pull/20008) [@qq645381995](https://github.com/qq645381995)
- 🐞 修复 Input 清除图标和反馈图标重合的问题。[#20017](https://github.com/ant-design/ant-design/pull/20017)
- 🐞 修复 Slider 的 tooltip 内容没有居中的问题。[#20016](https://github.com/ant-design/ant-design/pull/20016)
- 🐞 修复 Descriptions 内使用 React.Fragment 的渲染问题。[#20019](https://github.com/ant-design/ant-design/pull/20019)
- 🛠 Upload 拖拽模式下的 `className``style` 将会作用到真正的 dom 上。[#19987](https://github.com/ant-design/ant-design/pull/19987)
- 💄 新增 less 变量 `@table-header-bg-sm` 并修复小号 Table 的 footer 样式。[#19939](https://github.com/ant-design/ant-design/pull/19939)
## 3.25.3 ## 3.25.3
`2019-11-24` `2019-11-24`

View File

@ -132,7 +132,9 @@
&&-loading { &&-loading {
position: relative; position: relative;
pointer-events: none; &:not([disabled]) {
pointer-events: none;
}
} }
&&-loading::before { &&-loading::before {

View File

@ -311,7 +311,7 @@ describe('Calendar', () => {
for (let index = start; index < end; index += 1) { for (let index = start; index < end; index += 1) {
monthOptions.push( monthOptions.push(
<Select.Option className="month-item" key={`${index}`}> <Select.Option className="month-item" key={`${index}`} value={index}>
{months[index]} {months[index]}
</Select.Option>, </Select.Option>,
); );

View File

@ -0,0 +1,3 @@
import mk_MK from '../../date-picker/locale/mk_MK';
export default mk_MK;

View File

@ -34,10 +34,20 @@ title: Checkbox
| defaultValue | 默认选中的选项 | string\[] | \[] | | | defaultValue | 默认选中的选项 | string\[] | \[] | |
| disabled | 整组失效 | boolean | false | | | disabled | 整组失效 | boolean | false | |
| name | CheckboxGroup 下所有 `input[type="checkbox"]``name` 属性 | string | - | | | name | CheckboxGroup 下所有 `input[type="checkbox"]``name` 属性 | string | - | |
| options | 指定可选项 | string\[] | \[] | | | options | 指定可选项 | string\[] \| Option\[] | \[] | |
| value | 指定选中的选项 | string\[] | \[] | | | value | 指定选中的选项 | string\[] | \[] | |
| onChange | 变化时回调函数 | Function(checkedValue) | - | | | onChange | 变化时回调函数 | Function(checkedValue) | - | |
##### Option
```typescript
interface Option {
label: string;
value: string;
disabled?: boolean;
}
```
### 方法 ### 方法
#### Checkbox #### Checkbox

View File

@ -11087,7 +11087,7 @@ exports[`ConfigProvider components Slider configProvider 1`] = `
/> />
<div> <div>
<div <div
class="config-tooltip config-tooltip-placement-top " class="config-tooltip config-slider-tooltip config-tooltip-placement-top "
> >
<div <div
class="config-tooltip-content" class="config-tooltip-content"
@ -11136,7 +11136,7 @@ exports[`ConfigProvider components Slider normal 1`] = `
/> />
<div> <div>
<div <div
class="ant-tooltip ant-tooltip-placement-top " class="ant-tooltip ant-slider-tooltip ant-tooltip-placement-top "
> >
<div <div
class="ant-tooltip-content" class="ant-tooltip-content"
@ -11185,7 +11185,7 @@ exports[`ConfigProvider components Slider prefixCls 1`] = `
/> />
<div> <div>
<div <div
class="prefix-Slider-tooltip prefix-Slider-tooltip-placement-top " class="prefix-Slider-tooltip prefix-Slider-tooltip prefix-Slider-tooltip-placement-top "
> >
<div <div
class="prefix-Slider-tooltip-content" class="prefix-Slider-tooltip-content"
@ -17756,95 +17756,93 @@ exports[`ConfigProvider components Upload configProvider 1`] = `
<div <div
class="config-upload-list-item config-upload-list-item-done config-upload-list-item-list-type-text" class="config-upload-list-item config-upload-list-item-done config-upload-list-item-list-type-text"
> >
<div> <div
<div class="config-upload-list-item-info"
class="config-upload-list-item-info" >
> <span>
<span> <span
<span aria-label="paper-clip"
aria-label="paper-clip" class="anticon anticon-paper-clip"
class="anticon anticon-paper-clip" role="img"
role="img" >
<svg
aria-hidden="true"
class=""
data-icon="paper-clip"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
> >
<svg <path
aria-hidden="true" d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z"
class="" />
data-icon="paper-clip" </svg>
fill="currentColor" </span>
focusable="false" <span
height="1em" class="config-upload-list-item-name config-upload-list-item-name-icon-count-2"
viewBox="64 64 896 896" title="xxx.png"
width="1em" >
> xxx.png
<path </span>
d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z" <span
/> class="config-upload-list-item-card-actions "
</svg> >
</span> <a
<span title="Download file"
class="config-upload-list-item-name config-upload-list-item-name-icon-count-2"
title="xxx.png"
> >
xxx.png <span
</span> aria-label="download"
<span class="anticon anticon-download"
class="config-upload-list-item-card-actions " role="img"
> tabindex="-1"
<a
title="Download file" title="Download file"
> >
<span <svg
aria-label="download" aria-hidden="true"
class="anticon anticon-download" class=""
role="img" data-icon="download"
tabindex="-1" fill="currentColor"
title="Download file" focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
> >
<svg <path
aria-hidden="true" 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"
class="" />
data-icon="download" </svg>
fill="currentColor" </span>
focusable="false" </a>
height="1em" <a
viewBox="64 64 896 896" title="Remove file"
width="1em" >
> <span
<path aria-label="delete"
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" class="anticon anticon-delete"
/> role="img"
</svg> tabindex="-1"
</span>
</a>
<a
title="Remove file" title="Remove file"
> >
<span <svg
aria-label="delete" aria-hidden="true"
class="anticon anticon-delete" class=""
role="img" data-icon="delete"
tabindex="-1" fill="currentColor"
title="Remove file" focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
> >
<svg <path
aria-hidden="true" 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"
class="" />
data-icon="delete" </svg>
fill="currentColor" </span>
focusable="false" </a>
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>
</span> </span>
</div> </span>
</div> </div>
</div> </div>
</span> </span>
@ -17870,95 +17868,93 @@ exports[`ConfigProvider components Upload normal 1`] = `
<div <div
class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-text" class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-text"
> >
<div> <div
<div class="ant-upload-list-item-info"
class="ant-upload-list-item-info" >
> <span>
<span> <span
<span aria-label="paper-clip"
aria-label="paper-clip" class="anticon anticon-paper-clip"
class="anticon anticon-paper-clip" role="img"
role="img" >
<svg
aria-hidden="true"
class=""
data-icon="paper-clip"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
> >
<svg <path
aria-hidden="true" d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z"
class="" />
data-icon="paper-clip" </svg>
fill="currentColor" </span>
focusable="false" <span
height="1em" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-2"
viewBox="64 64 896 896" title="xxx.png"
width="1em" >
> xxx.png
<path </span>
d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z" <span
/> class="ant-upload-list-item-card-actions "
</svg> >
</span> <a
<span title="Download file"
class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-2"
title="xxx.png"
> >
xxx.png <span
</span> aria-label="download"
<span class="anticon anticon-download"
class="ant-upload-list-item-card-actions " role="img"
> tabindex="-1"
<a
title="Download file" title="Download file"
> >
<span <svg
aria-label="download" aria-hidden="true"
class="anticon anticon-download" class=""
role="img" data-icon="download"
tabindex="-1" fill="currentColor"
title="Download file" focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
> >
<svg <path
aria-hidden="true" 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"
class="" />
data-icon="download" </svg>
fill="currentColor" </span>
focusable="false" </a>
height="1em" <a
viewBox="64 64 896 896" title="Remove file"
width="1em" >
> <span
<path aria-label="delete"
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" class="anticon anticon-delete"
/> role="img"
</svg> tabindex="-1"
</span>
</a>
<a
title="Remove file" title="Remove file"
> >
<span <svg
aria-label="delete" aria-hidden="true"
class="anticon anticon-delete" class=""
role="img" data-icon="delete"
tabindex="-1" fill="currentColor"
title="Remove file" focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
> >
<svg <path
aria-hidden="true" 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"
class="" />
data-icon="delete" </svg>
fill="currentColor" </span>
focusable="false" </a>
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>
</span> </span>
</div> </span>
</div> </div>
</div> </div>
</span> </span>
@ -17984,95 +17980,93 @@ exports[`ConfigProvider components Upload prefixCls 1`] = `
<div <div
class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-text" class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-text"
> >
<div> <div
<div class="ant-upload-list-item-info"
class="ant-upload-list-item-info" >
> <span>
<span> <span
<span aria-label="paper-clip"
aria-label="paper-clip" class="anticon anticon-paper-clip"
class="anticon anticon-paper-clip" role="img"
role="img" >
<svg
aria-hidden="true"
class=""
data-icon="paper-clip"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
> >
<svg <path
aria-hidden="true" d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z"
class="" />
data-icon="paper-clip" </svg>
fill="currentColor" </span>
focusable="false" <span
height="1em" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-2"
viewBox="64 64 896 896" title="xxx.png"
width="1em" >
> xxx.png
<path </span>
d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z" <span
/> class="ant-upload-list-item-card-actions "
</svg> >
</span> <a
<span title="Download file"
class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-2"
title="xxx.png"
> >
xxx.png <span
</span> aria-label="download"
<span class="anticon anticon-download"
class="ant-upload-list-item-card-actions " role="img"
> tabindex="-1"
<a
title="Download file" title="Download file"
> >
<span <svg
aria-label="download" aria-hidden="true"
class="anticon anticon-download" class=""
role="img" data-icon="download"
tabindex="-1" fill="currentColor"
title="Download file" focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
> >
<svg <path
aria-hidden="true" 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"
class="" />
data-icon="download" </svg>
fill="currentColor" </span>
focusable="false" </a>
height="1em" <a
viewBox="64 64 896 896" title="Remove file"
width="1em" >
> <span
<path aria-label="delete"
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" class="anticon anticon-delete"
/> role="img"
</svg> tabindex="-1"
</span>
</a>
<a
title="Remove file" title="Remove file"
> >
<span <svg
aria-label="delete" aria-hidden="true"
class="anticon anticon-delete" class=""
role="img" data-icon="delete"
tabindex="-1" fill="currentColor"
title="Remove file" focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
> >
<svg <path
aria-hidden="true" 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"
class="" />
data-icon="delete" </svg>
fill="currentColor" </span>
focusable="false" </a>
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>
</span> </span>
</div> </span>
</div> </div>
</div> </div>
</span> </span>

View File

@ -0,0 +1,19 @@
import CalendarLocale from 'rc-calendar/lib/locale/mk_MK';
import TimePickerLocale from '../../time-picker/locale/mk_MK';
// Merge into a locale object
const locale = {
lang: {
placeholder: 'Избери датум',
rangePlaceholder: ['Од датум', 'До датум'],
...CalendarLocale,
},
timePickerLocale: {
...TimePickerLocale,
},
};
// All settings at:
// https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json
export default locale;

View File

@ -376,6 +376,78 @@ exports[`Descriptions column is number 1`] = `
</Descriptions> </Descriptions>
`; `;
exports[`Descriptions should work with React Fragment 1`] = `
<div
class="ant-descriptions"
>
<div
class="ant-descriptions-view"
>
<table>
<tbody>
<tr
class="ant-descriptions-row"
>
<td
class="ant-descriptions-item"
colspan="1"
>
<span
class="ant-descriptions-item-label ant-descriptions-item-colon"
>
bamboo
</span>
<span
class="ant-descriptions-item-content"
>
bamboo
</span>
</td>
</tr>
<tr
class="ant-descriptions-row"
>
<td
class="ant-descriptions-item"
colspan="1"
>
<span
class="ant-descriptions-item-label ant-descriptions-item-colon"
>
bamboo
</span>
<span
class="ant-descriptions-item-content"
>
bamboo
</span>
</td>
</tr>
<tr
class="ant-descriptions-row"
>
<td
class="ant-descriptions-item"
colspan="1"
>
<span
class="ant-descriptions-item-label ant-descriptions-item-colon"
>
bamboo
</span>
<span
class="ant-descriptions-item-content"
>
bamboo
</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
`;
exports[`Descriptions vertical layout 1`] = ` exports[`Descriptions vertical layout 1`] = `
<Descriptions <Descriptions
column={ column={

View File

@ -185,4 +185,22 @@ describe('Descriptions', () => {
expect(wrapper.find('Col').key()).toBe('label-bamboo'); expect(wrapper.find('Col').key()).toBe('label-bamboo');
}); });
// https://github.com/ant-design/ant-design/issues/19887
it('should work with React Fragment', () => {
if (!React.Fragment) {
return;
}
const wrapper = mount(
<Descriptions>
<Descriptions.Item label="bamboo">bamboo</Descriptions.Item>
<>
<Descriptions.Item label="bamboo">bamboo</Descriptions.Item>
<Descriptions.Item label="bamboo">bamboo</Descriptions.Item>
</>
</Descriptions>,
);
expect(wrapper.render()).toMatchSnapshot();
});
}); });

View File

@ -10,6 +10,20 @@ import ResponsiveObserve, {
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider'; import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
import Col from './Col'; import Col from './Col';
// https://github.com/smooth-code/react-flatten-children/
function flattenChildren(children: React.ReactNode): JSX.Element[] {
if (!children) {
return [];
}
return toArray(children).reduce((flatChildren: JSX.Element[], child: JSX.Element) => {
if (child && child.type === React.Fragment) {
return flatChildren.concat(flattenChildren(child.props.children));
}
flatChildren.push(child);
return flatChildren;
}, []);
}
export interface DescriptionsItemProps { export interface DescriptionsItemProps {
prefixCls?: string; prefixCls?: string;
className?: string; className?: string;
@ -47,7 +61,7 @@ const generateChildrenRows = (
let columns: React.ReactElement<DescriptionsItemProps>[] | null = null; let columns: React.ReactElement<DescriptionsItemProps>[] | null = null;
let leftSpans: number; let leftSpans: number;
const itemNodes = toArray(children); const itemNodes = flattenChildren(children);
itemNodes.forEach((node: React.ReactElement<DescriptionsItemProps>, index: number) => { itemNodes.forEach((node: React.ReactElement<DescriptionsItemProps>, index: number) => {
let itemNode = node; let itemNode = node;
@ -113,7 +127,7 @@ const renderRow = (
const cloneChildren: JSX.Element[] = []; const cloneChildren: JSX.Element[] = [];
const cloneContentChildren: JSX.Element[] = []; const cloneContentChildren: JSX.Element[] = [];
toArray(children).forEach( flattenChildren(children).forEach(
(childrenItem: React.ReactElement<DescriptionsItemProps>, idx: number) => { (childrenItem: React.ReactElement<DescriptionsItemProps>, idx: number) => {
cloneChildren.push(renderCol(childrenItem, 'label', idx)); cloneChildren.push(renderCol(childrenItem, 'label', idx));
if (layout === 'vertical') { if (layout === 'vertical') {
@ -225,7 +239,7 @@ class Descriptions extends React.Component<
const prefixCls = getPrefixCls('descriptions', customizePrefixCls); const prefixCls = getPrefixCls('descriptions', customizePrefixCls);
const column = this.getColumn(); const column = this.getColumn();
const cloneChildren = toArray(children) const cloneChildren = flattenChildren(children)
.map((child: React.ReactElement<DescriptionsItemProps>) => { .map((child: React.ReactElement<DescriptionsItemProps>) => {
if (React.isValidElement(child)) { if (React.isValidElement(child)) {
return React.cloneElement(child, { return React.cloneElement(child, {
@ -236,9 +250,9 @@ class Descriptions extends React.Component<
}) })
.filter((node: React.ReactElement) => node); .filter((node: React.ReactElement) => node);
const childrenArray: Array< const childrenArray: Array<React.ReactElement<
React.ReactElement<DescriptionsItemProps>[] DescriptionsItemProps
> = generateChildrenRows(cloneChildren, column); >[]> = generateChildrenRows(cloneChildren, column);
return ( return (
<div <div
className={classNames(prefixCls, className, { className={classNames(prefixCls, className, {

View File

@ -203,12 +203,16 @@ const FormItem: React.FC<FormItemProps> = (props: FormItemProps) => {
'colon', 'colon',
'extra', 'extra',
'getValueFromEvent', 'getValueFromEvent',
'hasFeedback',
'help',
'htmlFor', 'htmlFor',
'id', // It is deprecated because `htmlFor` is its replacement. 'id', // It is deprecated because `htmlFor` is its replacement.
'label', 'label',
'labelAlign', 'labelAlign',
'labelCol', 'labelCol',
'normalize', 'normalize',
'required',
'validateStatus',
'valuePropName', 'valuePropName',
'wrapperCol', 'wrapperCol',
])} ])}

View File

@ -4030,9 +4030,7 @@ exports[`renders ./components/form/demo/validate-other.md correctly 1`] = `
<div <div
class="ant-form-item-control-input" class="ant-form-item-control-input"
> >
<span <span>
class=""
>
<div <div
class="ant-upload ant-upload-drag" class="ant-upload ant-upload-drag"
/> />

View File

@ -286,3 +286,38 @@ validator(rule, value, callback) => {
} }
} }
``` ```
### Get form instance from function component
You can combine `forwardRef` with `useImperativeHandle` to get form instance:
```tsx
import React, { forwardRef, useImperativeHandle } from 'react';
import Form, { FormComponentProps } from 'antd/lib/form/Form';
const FCForm = forwardRef<FormComponentProps, FCFormProps>(({ form, onSubmit }, ref) => {
useImperativeHandle(ref, () => ({
form,
}));
`...the rest of your form`;
});
const EnhancedFCForm = Form.create<FCFormProps>()(FCForm);
```
You can use your form component like this
```tsx
const TestForm = () => {
const formRef = createRef<Ref>();
return (
<EnhancedFCForm
onSubmit={() => console.log(formRef.current!.form.getFieldValue('name'))}
wrappedComponentRef={formRef}
/>
);
};
```
Online demo:
[![Edit wrappedComponentRef-in-function-component](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/wrappedcomponentref-in-function-component-fj43c?fontsize=14&hidenavigation=1&theme=dark)

View File

@ -287,3 +287,38 @@ validator(rule, value, callback) => {
} }
} }
``` ```
### 如何在函数组件中拿到 form 实例?
你需要通过 `forwardRef``useImperativeHandle` 的组合使用来实现在函数组件中正确拿到 form 实例:
```tsx
import React, { forwardRef, useImperativeHandle } from 'react';
import Form, { FormComponentProps } from 'antd/lib/form/Form';
const FCForm = forwardRef<FormComponentProps, FCFormProps>(({ form, onSubmit }, ref) => {
useImperativeHandle(ref, () => ({
form,
}));
`...the rest of your form`;
});
const EnhancedFCForm = Form.create<FCFormProps>()(FCForm);
```
使用表单组件可以写成这样:
```tsx
const TestForm = () => {
const formRef = createRef<Ref>();
return (
<EnhancedFCForm
onSubmit={() => console.log(formRef.current!.form.getFieldValue('name'))}
wrappedComponentRef={formRef}
/>
);
};
```
在线示例:
[![Edit wrappedComponentRef-in-function-component](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/wrappedcomponentref-in-function-component-fj43c?fontsize=14&hidenavigation=1&theme=dark)

View File

@ -307,13 +307,14 @@
float: none; float: none;
} }
// reset border for Select, DatePicker, AutoComplete, Cascader, Mention, TimePicker // reset border for Select, DatePicker, AutoComplete, Cascader, Mention, TimePicker, Input
& > .@{ant-prefix}-select > .@{ant-prefix}-select-selector, & > .@{ant-prefix}-select > .@{ant-prefix}-select-selector,
& > .@{ant-prefix}-calendar-picker .@{ant-prefix}-input, & > .@{ant-prefix}-calendar-picker .@{ant-prefix}-input,
& > .@{ant-prefix}-select-auto-complete .@{ant-prefix}-input, & > .@{ant-prefix}-select-auto-complete .@{ant-prefix}-input,
& > .@{ant-prefix}-cascader-picker .@{ant-prefix}-input, & > .@{ant-prefix}-cascader-picker .@{ant-prefix}-input,
& > .@{ant-prefix}-mention-wrapper .@{ant-prefix}-mention-editor, & > .@{ant-prefix}-mention-wrapper .@{ant-prefix}-mention-editor,
& > .@{ant-prefix}-time-picker .@{ant-prefix}-time-picker-input { & > .@{ant-prefix}-time-picker .@{ant-prefix}-time-picker-input,
& > .@{ant-prefix}-input-group-wrapper .@{ant-prefix}-input {
border-right-width: @border-width-base; border-right-width: @border-width-base;
border-radius: 0; border-radius: 0;

View File

@ -42,6 +42,7 @@ import jaJP from '../ja_JP';
import knIN from '../kn_IN'; import knIN from '../kn_IN';
import koKR from '../ko_KR'; import koKR from '../ko_KR';
import kuIQ from '../ku_IQ'; import kuIQ from '../ku_IQ';
import mkMK from '../mk_MK';
import mnMN from '../mn_MN'; import mnMN from '../mn_MN';
import msMY from '../ms_MY'; import msMY from '../ms_MY';
import nbNO from '../nb_NO'; import nbNO from '../nb_NO';
@ -94,6 +95,7 @@ const locales = [
knIN, knIN,
koKR, koKR,
kuIQ, kuIQ,
mkMK,
msMY, msMY,
mnMN, mnMN,
nbNO, nbNO,

View File

@ -0,0 +1,3 @@
import locale from '../locale/mk_MK';
export default locale;

View File

@ -0,0 +1,58 @@
import Pagination from 'rc-pagination/lib/locale/mk_MK';
import DatePicker from '../date-picker/locale/mk_MK';
import TimePicker from '../time-picker/locale/mk_MK';
import Calendar from '../calendar/locale/mk_MK';
export default {
locale: 'mk',
Pagination,
DatePicker,
TimePicker,
Calendar,
global: {
placeholder: 'Ве молиме означете',
},
Table: {
filterTitle: 'Мени за филтрирање',
filterConfirm: 'ОК',
filterReset: 'Избриши',
selectAll: 'Одбери страница',
selectInvert: 'Инвертирај страница',
},
Modal: {
okText: 'ОК',
cancelText: 'Откажи',
justOkText: 'ОК',
},
Popconfirm: {
okText: 'ОК',
cancelText: 'Откажи',
},
Transfer: {
searchPlaceholder: 'Пребарај тука',
itemUnit: 'предмет',
itemsUnit: 'предмети',
},
Upload: {
uploading: 'Се прикачува...',
removeFile: 'Избриши фајл',
uploadError: 'Грешка при прикачување',
previewFile: 'Прикажи фајл',
downloadFile: 'Преземи фајл',
},
Empty: {
description: 'Нема податоци',
},
Icon: {
icon: 'Икона',
},
Text: {
edit: 'Уреди',
copy: 'Копирај',
copied: 'Копирано',
expand: 'Зголеми',
},
PageHeader: {
back: 'Назад',
},
};

View File

@ -40,4 +40,10 @@ export default {
Empty: { Empty: {
description: 'Não há dados', description: 'Não há dados',
}, },
Text: {
edit: 'editar',
copy: 'copiar',
copied: 'copiado',
expand: 'expandir',
},
}; };

View File

@ -170,4 +170,24 @@ describe('message', () => {
jest.runAllTimers(); jest.runAllTimers();
expect(document.querySelectorAll('.ant-message-notice').length).toBe(0); expect(document.querySelectorAll('.ant-message-notice').length).toBe(0);
}); });
it('update message content with a unique key and cancel manually', () => {
const key = 'updatable';
class Test extends React.Component {
componentDidMount() {
const hideLoading = message.loading({ content: 'Loading...', key, duration: 0 });
// Testing that content of the message should be cancel manually.
setTimeout(hideLoading, 1000);
}
render() {
return <div>test</div>;
}
}
mount(<Test />);
expect(document.querySelectorAll('.ant-message-notice').length).toBe(1);
jest.advanceTimersByTime(1500);
expect(document.querySelectorAll('.ant-message-notice').length).toBe(0);
});
}); });

View File

@ -22,7 +22,7 @@ const openMessage = () => {
message.loading({ content: 'Loading...', key }); message.loading({ content: 'Loading...', key });
setTimeout(() => { setTimeout(() => {
message.success({ content: 'Loaded!', key, duration: 2 }); message.success({ content: 'Loaded!', key, duration: 2 });
}); }, 1000);
}; };
ReactDOM.render( ReactDOM.render(

View File

@ -74,7 +74,7 @@ function notice(args: ArgsProps): MessageType {
const duration = args.duration !== undefined ? args.duration : defaultDuration; const duration = args.duration !== undefined ? args.duration : defaultDuration;
const IconComponent = iconMap[args.type]; const IconComponent = iconMap[args.type];
const target = key++; const target = args.key || key++;
const closePromise = new Promise(resolve => { const closePromise = new Promise(resolve => {
const callback = () => { const callback = () => {
if (typeof args.onClose === 'function') { if (typeof args.onClose === 'function') {
@ -84,7 +84,7 @@ function notice(args: ArgsProps): MessageType {
}; };
getMessageInstance(instance => { getMessageInstance(instance => {
instance.notice({ instance.notice({
key: args.key || target, key: target,
duration, duration,
style: {}, style: {},
content: ( content: (

View File

@ -1,3 +1,4 @@
import React from 'react';
import notification from '..'; import notification from '..';
describe('notification', () => { describe('notification', () => {
@ -78,4 +79,25 @@ describe('notification', () => {
}); });
expect(document.querySelectorAll('.ant-notification').length).toBe(1); expect(document.querySelectorAll('.ant-notification').length).toBe(1);
}); });
it('support closeIcon', () => {
notification.open({
message: 'Notification Title',
duration: 0,
closeIcon: <span className="test-customize-icon" />,
});
expect(document.querySelectorAll('.test-customize-icon').length).toBe(1);
});
it('support config closeIcon', () => {
notification.config({
closeIcon: <span className="test-customize-icon" />,
});
notification.open({
message: 'Notification Title',
duration: 0,
closeIcon: <span className="test-customize-icon" />,
});
expect(document.querySelectorAll('.test-customize-icon').length).toBe(1);
});
}); });

View File

@ -37,6 +37,7 @@ The properties of config are as follows:
| duration | Time in seconds before Notification is closed. When set to 0 or null, it will never be closed automatically | number | 4.5 | | duration | Time in seconds before Notification is closed. When set to 0 or null, it will never be closed automatically | number | 4.5 |
| getContainer | Return the mount node for Notification | () => HTMLNode | () => document.body | | getContainer | Return the mount node for Notification | () => HTMLNode | () => document.body |
| icon | Customized icon | ReactNode | - | | icon | Customized icon | ReactNode | - |
| closeIcon | custom close icon | ReactNode | - |
| key | The unique identifier of the Notification | string | - | | key | The unique identifier of the Notification | string | - |
| message | The title of notification box (required) | string\|ReactNode | - | | message | The title of notification box (required) | string\|ReactNode | - |
| onClose | Specify a function that will be called when the close button is clicked | Function | - | | onClose | Specify a function that will be called when the close button is clicked | Function | - |
@ -60,6 +61,7 @@ notification.config({
| Property | Description | Type | Default | | Property | Description | Type | Default |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| bottom | Distance from the bottom of the viewport, when `placement` is `bottomRight` or `bottomLeft` (unit: pixels). | number | 24 | | bottom | Distance from the bottom of the viewport, when `placement` is `bottomRight` or `bottomLeft` (unit: pixels). | number | 24 |
| closeIcon | custom close icon | ReactNode | - |
| duration | Time in seconds before Notification is closed. When set to 0 or null, it will never be closed automatically | number | 4.5 | | duration | Time in seconds before Notification is closed. When set to 0 or null, it will never be closed automatically | number | 4.5 |
| getContainer | Return the mount node for Notification | () => HTMLNode | () => document.body | | getContainer | Return the mount node for Notification | () => HTMLNode | () => document.body |
| placement | Position of Notification, can be one of `topLeft` `topRight` `bottomLeft` `bottomRight` | string | `topRight` | | placement | Position of Notification, can be one of `topLeft` `topRight` `bottomLeft` `bottomRight` | string | `topRight` |

View File

@ -18,6 +18,7 @@ let defaultTop = 24;
let defaultBottom = 24; let defaultBottom = 24;
let defaultPlacement: NotificationPlacement = 'topRight'; let defaultPlacement: NotificationPlacement = 'topRight';
let defaultGetContainer: () => HTMLElement; let defaultGetContainer: () => HTMLElement;
let defaultCloseIcon: React.ReactNode;
export interface ConfigProps { export interface ConfigProps {
top?: number; top?: number;
@ -25,10 +26,11 @@ export interface ConfigProps {
duration?: number; duration?: number;
placement?: NotificationPlacement; placement?: NotificationPlacement;
getContainer?: () => HTMLElement; getContainer?: () => HTMLElement;
closeIcon?: React.ReactNode;
} }
function setNotificationConfig(options: ConfigProps) { function setNotificationConfig(options: ConfigProps) {
const { duration, placement, bottom, top, getContainer } = options; const { duration, placement, bottom, top, getContainer, closeIcon } = options;
if (duration !== undefined) { if (duration !== undefined) {
defaultDuration = duration; defaultDuration = duration;
} }
@ -44,6 +46,9 @@ function setNotificationConfig(options: ConfigProps) {
if (getContainer !== undefined) { if (getContainer !== undefined) {
defaultGetContainer = getContainer; defaultGetContainer = getContainer;
} }
if (closeIcon !== undefined) {
defaultCloseIcon = closeIcon;
}
} }
function getPlacementStyle( function getPlacementStyle(
@ -91,6 +96,7 @@ type NotificationInstanceProps = {
getContainer?: () => HTMLElement; getContainer?: () => HTMLElement;
top?: number; top?: number;
bottom?: number; bottom?: number;
closeIcon?: React.ReactNode;
}; };
function getNotificationInstance( function getNotificationInstance(
@ -100,6 +106,7 @@ function getNotificationInstance(
getContainer = defaultGetContainer, getContainer = defaultGetContainer,
top, top,
bottom, bottom,
closeIcon = defaultCloseIcon,
}: NotificationInstanceProps, }: NotificationInstanceProps,
callback: (n: any) => void, callback: (n: any) => void,
) { ) {
@ -108,13 +115,20 @@ function getNotificationInstance(
callback(notificationInstance[cacheKey]); callback(notificationInstance[cacheKey]);
return; return;
} }
const closeIconToRender = (
<span className={`${prefixCls}-close-x`}>
{closeIcon || <CloseOutlined className={`${prefixCls}-close-icon`} />}
</span>
);
(Notification as any).newInstance( (Notification as any).newInstance(
{ {
prefixCls, prefixCls,
className: `${prefixCls}-${placement}`, className: `${prefixCls}-${placement}`,
style: getPlacementStyle(placement, top, bottom), style: getPlacementStyle(placement, top, bottom),
getContainer, getContainer,
closeIcon: <CloseOutlined className={`${prefixCls}-close-icon`} />, closeIcon: closeIconToRender,
}, },
(notification: any) => { (notification: any) => {
notificationInstance[cacheKey] = notification; notificationInstance[cacheKey] = notification;
@ -147,6 +161,7 @@ export interface ArgsProps {
top?: number; top?: number;
bottom?: number; bottom?: number;
getContainer?: () => HTMLElement; getContainer?: () => HTMLElement;
closeIcon?: React.ReactNode;
} }
function notice(args: ArgsProps) { function notice(args: ArgsProps) {
@ -168,7 +183,7 @@ function notice(args: ArgsProps) {
<span className={`${prefixCls}-message-single-line-auto-margin`} /> <span className={`${prefixCls}-message-single-line-auto-margin`} />
) : null; ) : null;
const { placement, top, bottom, getContainer } = args; const { placement, top, bottom, getContainer, closeIcon } = args;
getNotificationInstance( getNotificationInstance(
{ {
@ -177,6 +192,7 @@ function notice(args: ArgsProps) {
top, top,
bottom, bottom,
getContainer, getContainer,
closeIcon,
}, },
(notification: any) => { (notification: any) => {
notification.notice({ notification.notice({

View File

@ -34,6 +34,7 @@ config 参数如下:
| btn | 自定义关闭按钮 | ReactNode | - | | btn | 自定义关闭按钮 | ReactNode | - |
| bottom | 消息从底部弹出时,距离底部的位置,单位像素。 | number | 24 | | bottom | 消息从底部弹出时,距离底部的位置,单位像素。 | number | 24 |
| className | 自定义 CSS class | string | - | | className | 自定义 CSS class | string | - |
| closeIcon | 自定义关闭图标 | ReactNode | - |
| description | 通知提醒内容,必选 | string\|ReactNode | - | | description | 通知提醒内容,必选 | string\|ReactNode | - |
| duration | 默认 4.5 秒后自动关闭,配置为 null 则不自动关闭 | number | 4.5 | | duration | 默认 4.5 秒后自动关闭,配置为 null 则不自动关闭 | number | 4.5 |
| getContainer | 配置渲染节点的输出位置 | () => HTMLNode | () => document.body | | getContainer | 配置渲染节点的输出位置 | () => HTMLNode | () => document.body |
@ -61,6 +62,7 @@ notification.config({
| 参数 | 说明 | 类型 | 默认值 | | 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| bottom | 消息从底部弹出时,距离底部的位置,单位像素。 | number | 24 | | bottom | 消息从底部弹出时,距离底部的位置,单位像素。 | number | 24 |
| closeIcon | 自定义关闭图标 | ReactNode | - |
| duration | 默认自动关闭延时,单位秒 | number | 4.5 | | duration | 默认自动关闭延时,单位秒 | number | 4.5 |
| getContainer | 配置渲染节点的输出位置 | () => HTMLNode | () => document.body | | getContainer | 配置渲染节点的输出位置 | () => HTMLNode | () => document.body |
| placement | 弹出位置,可选 `topLeft` `topRight` `bottomLeft` `bottomRight` | string | topRight | | placement | 弹出位置,可选 `topLeft` `topRight` `bottomLeft` `bottomRight` | string | topRight |

View File

@ -955,7 +955,7 @@ exports[`renders ./components/slider/demo/show-tooltip.md correctly 1`] = `
/> />
<div> <div>
<div <div
class="ant-tooltip ant-tooltip-placement-top " class="ant-tooltip ant-slider-tooltip ant-tooltip-placement-top "
> >
<div <div
class="ant-tooltip-content" class="ant-tooltip-content"

View File

@ -3,7 +3,7 @@
exports[`Slider should show tooltip when hovering slider handler 1`] = ` exports[`Slider should show tooltip when hovering slider handler 1`] = `
<div> <div>
<div <div
class="ant-tooltip ant-tooltip-placement-top " class="ant-tooltip ant-slider-tooltip ant-tooltip-placement-top "
> >
<div <div
class="ant-tooltip-content" class="ant-tooltip-content"
@ -25,7 +25,7 @@ exports[`Slider should show tooltip when hovering slider handler 1`] = `
exports[`Slider should show tooltip when hovering slider handler 2`] = ` exports[`Slider should show tooltip when hovering slider handler 2`] = `
<div> <div>
<div <div
class="ant-tooltip ant-tooltip-placement-top ant-tooltip-hidden" class="ant-tooltip ant-slider-tooltip ant-tooltip-placement-top ant-tooltip-hidden"
> >
<div <div
class="ant-tooltip-content" class="ant-tooltip-content"

View File

@ -22,10 +22,12 @@ interface HandleGeneratorInfo {
index: number; index: number;
rest: any[]; rest: any[];
} }
export type HandleGeneratorFn = (
tooltipPrefixCls: string, export type HandleGeneratorFn = (config: {
info: HandleGeneratorInfo, tooltipPrefixCls?: string;
) => React.ReactNode; prefixCls?: string;
info: HandleGeneratorInfo;
}) => React.ReactNode;
export interface SliderProps { export interface SliderProps {
prefixCls?: string; prefixCls?: string;
@ -82,10 +84,11 @@ export default class Slider extends React.Component<SliderProps, SliderState> {
})); }));
}; };
handleWithTooltip: HandleGeneratorFn = ( handleWithTooltip: HandleGeneratorFn = ({
tooltipPrefixCls: string, tooltipPrefixCls,
{ value, dragging, index, ...restProps }, prefixCls,
) => { info: { value, dragging, index, ...restProps },
}) => {
const { tipFormatter, tooltipVisible, tooltipPlacement, getTooltipPopupContainer } = this.props; const { tipFormatter, tooltipVisible, tooltipPlacement, getTooltipPopupContainer } = this.props;
const { visibles } = this.state; const { visibles } = this.state;
const isTipFormatter = tipFormatter ? visibles[index] || dragging : false; const isTipFormatter = tipFormatter ? visibles[index] || dragging : false;
@ -98,6 +101,7 @@ export default class Slider extends React.Component<SliderProps, SliderState> {
placement={tooltipPlacement || 'top'} placement={tooltipPlacement || 'top'}
transitionName="zoom-down" transitionName="zoom-down"
key={index} key={index}
overlayClassName={`${prefixCls}-tooltip`}
getPopupContainer={getTooltipPopupContainer || (() => document.body)} getPopupContainer={getTooltipPopupContainer || (() => document.body)}
> >
<RcHandle <RcHandle
@ -136,7 +140,13 @@ export default class Slider extends React.Component<SliderProps, SliderState> {
<RcRange <RcRange
{...restProps} {...restProps}
ref={this.saveSlider} ref={this.saveSlider}
handle={(info: HandleGeneratorInfo) => this.handleWithTooltip(tooltipPrefixCls, info)} handle={(info: HandleGeneratorInfo) =>
this.handleWithTooltip({
tooltipPrefixCls,
prefixCls,
info,
})
}
prefixCls={prefixCls} prefixCls={prefixCls}
tooltipPrefixCls={tooltipPrefixCls} tooltipPrefixCls={tooltipPrefixCls}
/> />
@ -146,7 +156,13 @@ export default class Slider extends React.Component<SliderProps, SliderState> {
<RcSlider <RcSlider
{...restProps} {...restProps}
ref={this.saveSlider} ref={this.saveSlider}
handle={(info: HandleGeneratorInfo) => this.handleWithTooltip(tooltipPrefixCls, info)} handle={(info: HandleGeneratorInfo) =>
this.handleWithTooltip({
tooltipPrefixCls,
prefixCls,
info,
})
}
prefixCls={prefixCls} prefixCls={prefixCls}
tooltipPrefixCls={tooltipPrefixCls} tooltipPrefixCls={tooltipPrefixCls}
/> />

View File

@ -187,4 +187,11 @@
margin-bottom: -4px; margin-bottom: -4px;
} }
} }
&-tooltip {
// https://github.com/ant-design/ant-design/issues/20014
.@{ant-prefix}-tooltip-inner {
min-width: unset;
}
}
} }

View File

@ -1,5 +1,18 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Spin if indicator set null should not be render default indicator 1`] = `
<Spin
indicator={null}
size="default"
spinning={true}
wrapperClassName=""
>
<div
className="ant-spin ant-spin-spinning"
/>
</Spin>
`;
exports[`Spin should render custom indicator when it's set 1`] = ` exports[`Spin should render custom indicator when it's set 1`] = `
<div <div
class="ant-spin ant-spin-spinning" class="ant-spin ant-spin-spinning"

View File

@ -38,4 +38,9 @@ describe('Spin', () => {
wrapper.setProps({ spinning: true }); wrapper.setProps({ spinning: true });
expect(wrapper.instance().state.spinning).toBe(true); expect(wrapper.instance().state.spinning).toBe(true);
}); });
it('if indicator set null should not be render default indicator', () => {
const wrapper = mount(<Spin indicator={null} />);
expect(wrapper).toMatchSnapshot();
});
}); });

View File

@ -7,7 +7,7 @@ import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
import { tuple } from '../_util/type'; import { tuple } from '../_util/type';
const SpinSizes = tuple('small', 'default', 'large'); const SpinSizes = tuple('small', 'default', 'large');
export type SpinSize = (typeof SpinSizes)[number]; export type SpinSize = typeof SpinSizes[number];
export type SpinIndicator = React.ReactElement<HTMLElement>; export type SpinIndicator = React.ReactElement<HTMLElement>;
export interface SpinProps { export interface SpinProps {
@ -33,6 +33,12 @@ let defaultIndicator: React.ReactNode = null;
function renderIndicator(prefixCls: string, props: SpinProps): React.ReactNode { function renderIndicator(prefixCls: string, props: SpinProps): React.ReactNode {
const { indicator } = props; const { indicator } = props;
const dotClassName = `${prefixCls}-dot`; const dotClassName = `${prefixCls}-dot`;
// should not be render default indicator when indicator value is null
if (indicator === null) {
return null;
}
if (React.isValidElement(indicator)) { if (React.isValidElement(indicator)) {
return React.cloneElement(indicator, { return React.cloneElement(indicator, {
className: classNames(indicator.props.className, dotClassName), className: classNames(indicator.props.className, dotClassName),

View File

@ -467,6 +467,7 @@
@table-border-radius-base: @border-radius-base; @table-border-radius-base: @border-radius-base;
@table-footer-bg: @background-color-light; @table-footer-bg: @background-color-light;
@table-footer-color: @heading-color; @table-footer-color: @heading-color;
@table-header-bg-sm: transparent;
// Tag // Tag
// -- // --

View File

@ -19,6 +19,8 @@ title:
Use `filters` to generate filter menu in columns, `onFilter` to determine filtered result, and `filterMultiple` to indicate whether it's multiple or single selection. Use `filters` to generate filter menu in columns, `onFilter` to determine filtered result, and `filterMultiple` to indicate whether it's multiple or single selection.
Uses `defaultFilterValues` to make a column filtered by default.
Use `sorter` to make a column sortable. `sorter` can be a function of the type `function(a, b) { ... }` for sorting data locally. Use `sorter` to make a column sortable. `sorter` can be a function of the type `function(a, b) { ... }` for sorting data locally.
`sortDirections: ['ascend' | 'descend']` defines available sort methods for each columns, effective for all columns when set on table props. `sortDirections: ['ascend' | 'descend']` defines available sort methods for each columns, effective for all columns when set on table props.
@ -58,6 +60,7 @@ const columns = [
], ],
}, },
], ],
defaultFilterValues: ['Jim'],
// specify the condition of filtering result // specify the condition of filtering result
// here is that finding the name started with `value` // here is that finding the name started with `value`
onFilter: (value, record) => record.name.indexOf(value) === 0, onFilter: (value, record) => record.name.indexOf(value) === 0,

View File

@ -33,3 +33,9 @@
// = Small = // = Small =
// ================================================================ // ================================================================
.table-size(~'small', @table-padding-vertical-sm, @table-padding-horizontal-sm); .table-size(~'small', @table-padding-vertical-sm, @table-padding-horizontal-sm);
.@{table-prefix-cls}.@{table-prefix-cls}-small {
thead > tr > th {
background-color: @table-header-bg-sm;
}
}

View File

@ -0,0 +1,5 @@
const locale = {
placeholder: 'Избери време',
};
export default locale;

View File

@ -282,6 +282,7 @@ class Upload extends React.Component<UploadProps, UploadState> {
type, type,
disabled, disabled,
children, children,
style,
} = this.props; } = this.props;
const { fileList, dragState } = this.state; const { fileList, dragState } = this.state;
@ -298,6 +299,7 @@ class Upload extends React.Component<UploadProps, UploadState> {
}; };
delete rcUploadProps.className; delete rcUploadProps.className;
delete rcUploadProps.style;
const uploadList = showUploadList ? ( const uploadList = showUploadList ? (
<LocaleReceiver componentName="Upload" defaultLocale={defaultLocale.Upload}> <LocaleReceiver componentName="Upload" defaultLocale={defaultLocale.Upload}>
@ -306,19 +308,24 @@ class Upload extends React.Component<UploadProps, UploadState> {
) : null; ) : null;
if (type === 'drag') { if (type === 'drag') {
const dragCls = classNames(prefixCls, { const dragCls = classNames(
[`${prefixCls}-drag`]: true, prefixCls,
[`${prefixCls}-drag-uploading`]: fileList.some(file => file.status === 'uploading'), {
[`${prefixCls}-drag-hover`]: dragState === 'dragover', [`${prefixCls}-drag`]: true,
[`${prefixCls}-disabled`]: disabled, [`${prefixCls}-drag-uploading`]: fileList.some(file => file.status === 'uploading'),
}); [`${prefixCls}-drag-hover`]: dragState === 'dragover',
[`${prefixCls}-disabled`]: disabled,
},
className,
);
return ( return (
<span className={className}> <span>
<div <div
className={dragCls} className={dragCls}
onDrop={this.onFileDrop} onDrop={this.onFileDrop}
onDragOver={this.onFileDrop} onDragOver={this.onFileDrop}
onDragLeave={this.onFileDrop} onDragLeave={this.onFileDrop}
style={style}
> >
<RcUpload {...rcUploadProps} ref={this.saveUpload} className={`${prefixCls}-btn`}> <RcUpload {...rcUploadProps} ref={this.saveUpload} className={`${prefixCls}-btn`}>
<div className={`${prefixCls}-drag-container`}>{children}</div> <div className={`${prefixCls}-drag-container`}>{children}</div>

View File

@ -239,13 +239,11 @@ export default class UploadList extends React.Component<UploadListProps, any> {
); );
const dom = ( const dom = (
<div className={infoUploadingClass}> <div className={infoUploadingClass}>
<div> <div className={`${prefixCls}-list-item-info`}>{iconAndPreview}</div>
<div className={`${prefixCls}-list-item-info`}>{iconAndPreview}</div> {actions}
{actions} <Animate transitionName="fade" component="">
<Animate transitionName="fade" component=""> {progress}
{progress} </Animate>
</Animate>
</div>
</div> </div>
); );
const listContainerNameClass = classNames({ const listContainerNameClass = classNames({

File diff suppressed because it is too large Load Diff

View File

@ -443,6 +443,8 @@
} }
.anticon-picture + .@{upload-item}-name { .anticon-picture + .@{upload-item}-name {
position: absolute;
bottom: 10px;
display: block; display: block;
} }

View File

@ -56,6 +56,10 @@ import { Menu, Breadcrumb, Icon } from 'antd';
See: https://github.com/jmblog/how-to-optimize-momentjs-with-webpack See: https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
### How to replace momentjs to Day.js to reduce bundle size
We provide `antd-dayjs-webpack-plugin` plugin to replace `momentjs` to `Day.js` directly without changing a line of existing code. More info at [antd-dayjs-webpack-plugin](https://github.com/ant-design/antd-dayjs-webpack-plugin).
### It doesn't work when I change `defaultValue` dynamically. ### It doesn't work when I change `defaultValue` dynamically.
The `defaultXxxx` (like `defaultValue`) of `Input`/`Select`(etc...) only works on the first render. It is a specification of React. Please read [React's documentation](https://facebook.github.io/react/docs/forms.html#controlled-components). The `defaultXxxx` (like `defaultValue`) of `Input`/`Select`(etc...) only works on the first render. It is a specification of React. Please read [React's documentation](https://facebook.github.io/react/docs/forms.html#controlled-components).

View File

@ -56,6 +56,10 @@ import { Menu, Breadcrumb, Icon } from 'antd';
参考https://github.com/jmblog/how-to-optimize-momentjs-with-webpack 。 参考https://github.com/jmblog/how-to-optimize-momentjs-with-webpack 。
### 如何使用 Day.js 替换 momentjs 来减小打包大小?
我们提供了 `antd-dayjs-webpack-plugin` 插件,无需对现有代码做任何修改直接替换成 `Day.js`。请参考 [antd-dayjs-webpack-plugin](https://github.com/ant-design/antd-dayjs-webpack-plugin)。
### 当我动态改变 `defaultValue` 的时候它并没有生效。 ### 当我动态改变 `defaultValue` 的时候它并没有生效。
`Input`/`Select` 等的 `defaultXxxx`(例如 `defaultValue`)只有在第一次渲染的时候有效,这是 React 的规范,请阅读 [React 的文档](https://reactjs.org/docs/forms.html#controlled-components)。 `Input`/`Select` 等的 `defaultXxxx`(例如 `defaultValue`)只有在第一次渲染的时候有效,这是 React 的规范,请阅读 [React 的文档](https://reactjs.org/docs/forms.html#controlled-components)。

View File

@ -151,6 +151,20 @@ And this plugin can load styles too. Read [usage](https://github.com/ant-design/
> FYI, babel-plugin-import's `style` option will importing some global reset styles, don't use it if you don't need those styles. You can import styles manually via `import 'antd/dist/antd.css'` and override the global reset styles. > FYI, babel-plugin-import's `style` option will importing some global reset styles, don't use it if you don't need those styles. You can import styles manually via `import 'antd/dist/antd.css'` and override the global reset styles.
## Replace momentjs to Day.js
You can use [antd-dayjs-webpack-plugin](https://github.com/ant-design/antd-dayjs-webpack-plugin) plugin to replace momentjs to Day.js to reduce bundle size dramatically. You need to update your webpack config file like this:
```js
// webpack-config.js
import AntdDayjsWebpackPlugin from 'antd-dayjs-webpack-plugin';
module.exports = {
// ...
plugins: [new AntdDayjsWebpackPlugin()],
};
```
## Customization ## Customization
- [Customize Theme](/docs/react/customize-theme) - [Customize Theme](/docs/react/customize-theme)

View File

@ -156,6 +156,20 @@ import { Button } from 'antd';
> 注意babel-plugin-import 的 `style` 属性除了引入对应组件的样式,也会引入一些必要的全局样式。如果你不需要它们,建议不要使用此属性。你可以 `import 'antd/dist/antd.css'` 手动引入,并覆盖全局样式。 > 注意babel-plugin-import 的 `style` 属性除了引入对应组件的样式,也会引入一些必要的全局样式。如果你不需要它们,建议不要使用此属性。你可以 `import 'antd/dist/antd.css'` 手动引入,并覆盖全局样式。
## 使用 Day.js 替换 momentjs 优化打包大小
你可以使用 [antd-dayjs-webpack-plugin](https://github.com/ant-design/antd-dayjs-webpack-plugin) 插件用 Day.js 替换 momentjs 来大幅减小打包大小。这需要更新 webpack 的配置文件如下:
```js
// webpack-config.js
import AntdDayjsWebpackPlugin from 'antd-dayjs-webpack-plugin';
module.exports = {
// ...
plugins: [new AntdDayjsWebpackPlugin()],
};
```
## 配置主题和字体 ## 配置主题和字体
- [改变主题](/docs/react/customize-theme) - [改变主题](/docs/react/customize-theme)

View File

@ -53,6 +53,7 @@ Supported languages:
| Japanese | ja_JP | | Japanese | ja_JP |
| Kannada | kn_IN | | Kannada | kn_IN |
| Korean | ko_KR | | Korean | ko_KR |
| Macedonian | mk_MK |
| Norwegian | nb_NO | | Norwegian | nb_NO |
| Nepal | ne_NP | | Nepal | ne_NP |
| Dutch (Belgium) | nl_BE | | Dutch (Belgium) | nl_BE |

View File

@ -52,6 +52,7 @@ return (
| 日语 | ja_JP | | 日语 | ja_JP |
| 卡纳达语 | kn_IN | | 卡纳达语 | kn_IN |
| 韩语/朝鲜语 | ko_KR | | 韩语/朝鲜语 | ko_KR |
| 马其顿语 | mk_MK |
| 挪威语 | nb_NO | | 挪威语 | nb_NO |
| 尼泊尔语 | ne_NP | | 尼泊尔语 | ne_NP |
| 荷兰语(比利时) | nl_BE | | 荷兰语(比利时) | nl_BE |

View File

@ -199,6 +199,21 @@ We use `modifyVars` option of [less-loader](https://github.com/webpack/less-load
> You could also try [craco](https://github.com/sharegate/craco) and [craco-antd](https://github.com/FormAPI/craco-antd) to customize create-react-app webpack config same as customize-cra does. > You could also try [craco](https://github.com/sharegate/craco) and [craco-antd](https://github.com/FormAPI/craco-antd) to customize create-react-app webpack config same as customize-cra does.
## Replace momentjs to Day.js
You can use [antd-dayjs-webpack-plugin](https://github.com/ant-design/antd-dayjs-webpack-plugin) plugin to replace momentjs to Day.js to reduce bundle size dramatically.
```bash
$ yarn add antd-dayjs-webpack-plugin
```
```js
const { override, addWebpackPlugin } = require('customize-cra');
const AntdDayjsWebpackPlugin = require('antd-dayjs-webpack-plugin');
module.exports = override(addWebpackPlugin(new AntdDayjsWebpackPlugin()));
```
## eject ## eject
You can also eject your application using [yarn run eject](https://facebook.github.io/create-react-app/docs/available-scripts#npm-run-eject) for a custom setup of create-react-app, although you should dig into it by yourself. You can also eject your application using [yarn run eject](https://facebook.github.io/create-react-app/docs/available-scripts#npm-run-eject) for a custom setup of create-react-app, although you should dig into it by yourself.

View File

@ -201,6 +201,21 @@ module.exports = override(
> 你也可以使用 [craco](https://github.com/sharegate/craco) 和 [craco-antd](https://github.com/FormAPI/craco-antd) 来实现和 customize-cra 一样的修改 create-react-app 配置的功能。 > 你也可以使用 [craco](https://github.com/sharegate/craco) 和 [craco-antd](https://github.com/FormAPI/craco-antd) 来实现和 customize-cra 一样的修改 create-react-app 配置的功能。
## 使用 Day.js 替换 momentjs 优化打包大小
你可以使用 [antd-dayjs-webpack-plugin](https://github.com/ant-design/antd-dayjs-webpack-plugin) 插件用 Day.js 替换 momentjs 来大幅减小打包大小。
```bash
$ yarn add antd-dayjs-webpack-plugin
```
```js
const { override, addWebpackPlugin } = require('customize-cra');
const AntdDayjsWebpackPlugin = require('antd-dayjs-webpack-plugin');
module.exports = override(addWebpackPlugin(new AntdDayjsWebpackPlugin()));
```
## eject ## eject
你也可以使用 create-react-app 提供的 [yarn run eject](https://facebook.github.io/create-react-app/docs/available-scripts#npm-run-eject) 命令将所有内建的配置暴露出来。不过这种配置方式需要你自行探索,不在本文讨论范围内。 你也可以使用 create-react-app 提供的 [yarn run eject](https://facebook.github.io/create-react-app/docs/available-scripts#npm-run-eject) 命令将所有内建的配置暴露出来。不过这种配置方式需要你自行探索,不在本文讨论范围内。

View File

@ -107,7 +107,7 @@
"prop-types": "^15.7.2", "prop-types": "^15.7.2",
"raf": "^3.4.1", "raf": "^3.4.1",
"rc-animate": "^2.10.2", "rc-animate": "^2.10.2",
"rc-calendar": "~9.15.5", "rc-calendar": "~9.15.7",
"rc-cascader": "~1.0.0-alpha.0", "rc-cascader": "~1.0.0-alpha.0",
"rc-checkbox": "~2.1.6", "rc-checkbox": "~2.1.6",
"rc-collapse": "~1.11.3", "rc-collapse": "~1.11.3",
@ -119,7 +119,7 @@
"rc-mentions": "~0.4.0", "rc-mentions": "~0.4.0",
"rc-menu": "~8.0.0-alpha.4", "rc-menu": "~8.0.0-alpha.4",
"rc-notification": "~3.3.1", "rc-notification": "~3.3.1",
"rc-pagination": "~1.20.5", "rc-pagination": "~1.20.11",
"rc-progress": "~2.5.0", "rc-progress": "~2.5.0",
"rc-rate": "~2.5.0", "rc-rate": "~2.5.0",
"rc-resize-observer": "^0.1.0", "rc-resize-observer": "^0.1.0",
@ -161,7 +161,7 @@
"@types/shallowequal": "^1.1.1", "@types/shallowequal": "^1.1.1",
"@types/warning": "^3.0.0", "@types/warning": "^3.0.0",
"@typescript-eslint/eslint-plugin": "^2.0.0", "@typescript-eslint/eslint-plugin": "^2.0.0",
"@typescript-eslint/parser": "~2.8.0", "@typescript-eslint/parser": "~2.9.0",
"antd-theme-generator": "^1.1.6", "antd-theme-generator": "^1.1.6",
"babel-eslint": "^10.0.1", "babel-eslint": "^10.0.1",
"babel-plugin-add-react-displayname": "^0.0.5", "babel-plugin-add-react-displayname": "^0.0.5",
@ -194,7 +194,7 @@
"fetch-jsonp": "^1.1.3", "fetch-jsonp": "^1.1.3",
"full-icu": "^1.3.0", "full-icu": "^1.3.0",
"glob": "^7.1.4", "glob": "^7.1.4",
"http-server": "^0.11.1", "http-server": "^0.12.0",
"husky": "^3.0.2", "husky": "^3.0.2",
"immutability-helper": "^3.0.0", "immutability-helper": "^3.0.0",
"intersection-observer": "^0.7.0", "intersection-observer": "^0.7.0",
@ -238,7 +238,7 @@
"scrollama": "^2.0.0", "scrollama": "^2.0.0",
"simple-git": "^1.113.0", "simple-git": "^1.113.0",
"stylelint": "^12.0.0", "stylelint": "^12.0.0",
"stylelint-config-prettier": "^6.0.0", "stylelint-config-prettier": "^7.0.0",
"stylelint-config-rational-order": "^0.1.2", "stylelint-config-rational-order": "^0.1.2",
"stylelint-config-standard": "^19.0.0", "stylelint-config-standard": "^19.0.0",
"stylelint-declaration-block-no-ignored-properties": "^2.1.0", "stylelint-declaration-block-no-ignored-properties": "^2.1.0",

View File

@ -50,7 +50,7 @@ module.exports = {
'app.home.getting-started': 'Getting Started', 'app.home.getting-started': 'Getting Started',
'app.home.recommend': 'Recommend', 'app.home.recommend': 'Recommend',
'app.home.recommend.yuque': 'Yuque, our favorite documentation tool', 'app.home.recommend.yuque': 'Yuque, our favorite documentation tool',
'app.home.recommend.antv': 'AntV: brand new data visualization solution', 'app.home.recommend.antv': 'G2Plot, the new charting library',
'app.home.more': 'Learn more', 'app.home.more': 'Learn more',
'app.home.more-mobile-react': 'Ant Design Mobile of React', 'app.home.more-mobile-react': 'Ant Design Mobile of React',
'app.home.more-mobile-angular': 'Ant Design Mobile of Angular', 'app.home.more-mobile-angular': 'Ant Design Mobile of Angular',

View File

@ -3,8 +3,11 @@ body {
height: 100%; height: 100%;
} }
body { html {
overflow-x: hidden; overflow-x: hidden;
}
body {
color: @site-text-color; color: @site-text-color;
font-size: 14px; font-size: 14px;
font-family: @font-family; font-family: @font-family;

View File

@ -98,20 +98,20 @@ const Banner = ({ isMobile }) => {
<FormattedMessage id="app.home.recommend" /> <FormattedMessage id="app.home.recommend" />
</Divider> </Divider>
<a <a
href={`https://antv.vision/${isZhCN ? 'zh' : 'en'}?from=antd`} href="https://github.com/antvis/g2plot?from=antd"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
onClick={() => { onClick={() => {
if (window.gtag) { if (window.gtag) {
window.gtag('event', '点击', { window.gtag('event', '点击', {
event_category: '首页推广', event_category: '首页推广',
event_label: `https://antv.vision/${isZhCN ? 'zh' : 'en'}?from=antd`, event_label: `https://github.com/antvis/g2plot?from=antd`,
}); });
} }
}} }}
> >
<img src="https://antv.vision/icons/icon-512x512.png" alt="AntV logo" /> <img src="https://antv.vision/icons/icon-512x512.png" alt="AntV logo" />
<FormattedMessage id="app.home.recommend.antv" /> <FormattedMessage id="app.home.recommend.antv.g2plot" />
<RightOutlined style={{ marginLeft: 6, fontSize: 12, opacity: 0.6 }} /> <RightOutlined style={{ marginLeft: 6, fontSize: 12, opacity: 0.6 }} />
</a> </a>
</div> </div>

View File

@ -47,7 +47,7 @@ module.exports = {
'app.home.getting-started': '开始使用', 'app.home.getting-started': '开始使用',
'app.home.recommend': '推荐', 'app.home.recommend': '推荐',
'app.home.recommend.yuque': '语雀,我们都喜欢的文档工具', 'app.home.recommend.yuque': '语雀,我们都喜欢的文档工具',
'app.home.recommend.antv': 'AntV全新的蚂蚁金服数据可视化解决方案', 'app.home.recommend.antv.g2plot': 'G2Plot全新企业级图表',
'app.home.more': '查看更多', 'app.home.more': '查看更多',
'app.home.more-mobile-react': 'Ant Design Mobile of React', 'app.home.more-mobile-react': 'Ant Design Mobile of React',
'app.home.more-mobile-angular': 'Ant Design Mobile of Angular', 'app.home.more-mobile-angular': 'Ant Design Mobile of Angular',