Merge pull request #24108 from ant-design/feature-merge-master

chore: Feature merge master
This commit is contained in:
二货机器人 2020-05-13 12:32:22 +08:00 committed by GitHub
commit 63a32422e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 1341 additions and 1367 deletions

View File

@ -15,6 +15,60 @@ timeline: true
--- ---
## 4.2.2
`2020-05-11`
- 🐞 Fix `npm run version` install error. [#24059](https://github.com/ant-design/ant-design/pull/24059)
- 🐞 Fix Menu `@menu-item-font-size` not working. [#24052](https://github.com/ant-design/ant-design/pull/24052)
- 💄 Add `@modal-close-color` less variable. [#24053](https://github.com/ant-design/ant-design/pull/24053)
## 4.2.1
`2020-05-11`
- Form
- 🐞 Fix Form.Item get React warning for `getValueProps`. [#23875](https://github.com/ant-design/ant-design/pull/23875)
- 🐞 Fix Form.Item `help` style issue when `validateStatus` is not `error`. [#23945](https://github.com/ant-design/ant-design/pull/23945)
- Table
- 🐞 Fix selection column width issue when fix header. [#23806](https://github.com/ant-design/ant-design/pull/23806)
- 💄 Adjust selection column css selector priority to enable customize width. [#23914](https://github.com/ant-design/ant-design/pull/23914)
- DatePicker
- 🐞 Fix miss placeholder when `placeholder` is `undefined`. [#23818](https://github.com/ant-design/ant-design/pull/23818)
- 🐞 Fix clear icon color style. [#23811](https://github.com/ant-design/ant-design/pull/23811)
- Switch
- 🐞 Fix loading style for the dark theme. [#23766](https://github.com/ant-design/ant-design/pull/23766) [@vsn4ik](https://github.com/vsn4ik)
- 🐞 Fix `unCheckedChildren` not showing. [#23791](https://github.com/ant-design/ant-design/pull/23791)
- 🐞 Fix Upload error message location to scroll in the float layer. [#24001](https://github.com/ant-design/ant-design/pull/24001) [@mraiguo](https://github.com/mraiguo)
- 💄 Tweak Comment render unnecessary div style when `avatar` is empty. [#23994](https://github.com/ant-design/ant-design/pull/23994) [@Xuhao](https://github.com/Xuhao)
- 🐞 Fix Select `focus` border style in Input.Group. [#23985](https://github.com/ant-design/ant-design/pull/23985)
- 🐞 Fix Steps `subTitle` showing `[object Object]` title. [#23989](https://github.com/ant-design/ant-design/pull/23989)
- 💄 Tweak Select close icon position. [#23963](https://github.com/ant-design/ant-design/pull/23963)
- 🐞 Fix Drawer `width="50%"` hidden problem when no mask. [#23925](https://github.com/ant-design/ant-design/pull/23925)
- 🐞 Fix Textarea with `allowClear` has error height style. [#23835](https://github.com/ant-design/ant-design/pull/23835)
- 💄 Adjust Modal.xxx function async to avoid block React events. [#23826](https://github.com/ant-design/ant-design/pull/23826)
- 🐞 Fix Menu with controlled `openKeys` abnormal behavior when `inlineCollapsed` changed. [#23822](https://github.com/ant-design/ant-design/pull/23822)
- 🐞 Fix Button `loading` animation. [#23783](https://github.com/ant-design/ant-design/pull/23783)
- 🐞 Fix Slider `marks` selected problem when dragging. [#23773](https://github.com/ant-design/ant-design/pull/23773)
- 🛠 Timeline refactors with React Hooks. [#23631](https://github.com/ant-design/ant-design/pull/23631) [@hengkx](https://github.com/hengkx)
- 🌎 Localization
- 🌐 Add Farsi `fa_IR` default locale template localisations. [#23926](https://github.com/ant-design/ant-design/pull/23926) [@NarimanMov](https://github.com/NarimanMov)
- 🌐 Add default `en` default locale template localisations for Form. [#23859](https://github.com/ant-design/ant-design/pull/23859) [@mjfwebb](https://github.com/mjfwebb)
- 📦 Reduce bundle size
- 🗑 Reduce bundle size via removing `react-lifecycles-compat`. [#23969](https://github.com/ant-design/ant-design/pull/23969)
- 🛠 Reduce bundle size via excluding `package.json` from source code. [#23957](https://github.com/ant-design/ant-design/pull/23957)
- 🛠 Upgrade `rc-animate` to 3.x to reduce bundle size. [#23937](https://github.com/ant-design/ant-design/pull/23937)
- RTL
- 🐞 Fix Input clear icon style in RTL. [#23999](https://github.com/ant-design/ant-design/pull/23999)
- 🐞 Fix DatePicker panel style in RTL. [#24028](https://github.com/ant-design/ant-design/pull/24028) [@xrkffgg](https://github.com/xrkffgg)
- 💄 Optimize DatePicker active bar style in `RTL`. [#23981](https://github.com/ant-design/ant-design/pull/23981)
- 🐞 Fix Transfer search padding style in `RTL`. [#23962](https://github.com/ant-design/ant-design/pull/23962)
- 💄 Optimize Layout style of RTL. [#23921](https://github.com/ant-design/ant-design/pull/23921)
- 💄 Optimize Button `loading` style in RT. [#23776](https://github.com/ant-design/ant-design/pull/23776)
- 💄 Optimize Input.Search style in RTL. [#23797](https://github.com/ant-design/ant-design/pull/23797)
- TypeScript
- 🐞 Fix InputNumber `onChange` type. [#23871](https://github.com/ant-design/ant-design/pull/23871) [@jjhbw](https://github.com/jjhbw)
## 4.2.0 ## 4.2.0
`2020-04-29` `2020-04-29`

View File

@ -15,6 +15,60 @@ timeline: true
--- ---
## 4.2.2
`2020-05-11`
- 🐞 修复安装 antd `npm run version` 报错的问题。[#24059](https://github.com/ant-design/ant-design/pull/24059)
- 🐞 修复 Menu `@menu-item-font-size` 变量失效的问题。[#24052](https://github.com/ant-design/ant-design/pull/24052)
- 💄 新增 `@modal-close-color` less 变量。[#24053](https://github.com/ant-design/ant-design/pull/24053)
## 4.2.1
`2020-05-11`
- Form
- 🐞 修复 Form.Item 使用 `getValueProps` React 会报警的问题。[#23875](https://github.com/ant-design/ant-design/pull/23875)
- 🐞 修复 Form.Item `help``validateStatus` 不是 `error` 时的样式问题。[#23945](https://github.com/ant-design/ant-design/pull/23945)
- Table
- 🐞 修复 Table 固定表头时选择列的宽度问题。[#23806](https://github.com/ant-design/ant-design/pull/23806)
- 💄 调整 Table 选择列 css 选择器优先级以支持自定义宽度。[#23914](https://github.com/ant-design/ant-design/pull/23914)
- DatePicker
- 🐞 修复在 `placeholder``undefined` 时不展示的问题。[#23818](https://github.com/ant-design/ant-design/pull/23818)
- 🐞 修复清除图标的颜色。[#23811](https://github.com/ant-design/ant-design/pull/23811)
- Switch
- 🐞 修复暗色主题下的加载样式。[#23766](https://github.com/ant-design/ant-design/pull/23766) [@vsn4ik](https://github.com/vsn4ik)
- 🐞 修复 `unCheckedChildren` 不显示的问题。[#23791](https://github.com/ant-design/ant-design/pull/23791)
- 🐞 修复 Upload 在浮层中错误提示滚动定位问题。[#24001](https://github.com/ant-design/ant-design/pull/24001) [@mraiguo](https://github.com/mraiguo)
- 💄 调整 Comment 中 `avatar` 为空时不必要的 div 样式[#23994](https://github.com/ant-design/ant-design/pull/23994) [@Xuhao](https://github.com/Xuhao)
- 🐞 修复 Input.Group 中 Select 选项 `focus` 边框样式[#23985](https://github.com/ant-design/ant-design/pull/23985)
- 🐞 修复 Steps `subTitle` 上会显示 `[object Object]` 提示的问题。[#23989](https://github.com/ant-design/ant-design/pull/23989)
- 💄 微调 Select 移除图标的位置。[#23963](https://github.com/ant-design/ant-design/pull/23963)
- 🐞 修复无遮罩的 Drawer 设置 `50%` 宽度时不显示的问题。[#23925](https://github.com/ant-design/ant-design/pull/23925)
- 🐞 修复 Textarea 开启 `allowClear` 时高度错误的问题。[#23835](https://github.com/ant-design/ant-design/pull/23835)
- 💄 调整 Modal.xxx 方法为异步以防止其影响 React 事件响应。[#23826](https://github.com/ant-design/ant-design/pull/23826)
- 🐞 修复受控模式 Menu `inlineCollapsed` 折叠时的表现。[#23822](https://github.com/ant-design/ant-design/pull/23822)
- 🐞 修复 Button `loading` 动画切换不平滑的问题。[#23783](https://github.com/ant-design/ant-design/pull/23783)
- 🐞 修复 Slider 拖拽中选中 `marks` 文本的问题。[#23773](https://github.com/ant-design/ant-design/pull/23773)
- 🛠 Timeline 使用 React Hooks 重构。[#23631](https://github.com/ant-design/ant-design/pull/23631) [@hengkx](https://github.com/hengkx)
- 🌎 国际化
- 🌐 增加波斯语 `fa_IR` 国际化默认提示模板。[#23926](https://github.com/ant-design/ant-design/pull/23926) [@NarimanMov](https://github.com/NarimanMov)
- 🌐 增加 Form `en` 国际化默认提示模板[#23859](https://github.com/ant-design/ant-design/pull/23859) [@mjfwebb](https://github.com/mjfwebb)
- 📦 包体积优化
- 🗑 移除 `react-lifecycles-compat` 依赖以优化包体积。[#23969](https://github.com/ant-design/ant-design/pull/23969)
- 🛠 源码中不再引用 `package.json` 从而优化了一点包体积。[#23957](https://github.com/ant-design/ant-design/pull/23957)
- 🛠 更新 `rc-animate` 到 3.x 以优化包体积。[#23937](https://github.com/ant-design/ant-design/pull/23937)
- RTL
- 🐞 修复 Input 在 RTL 模式下清空按钮的样式。[#23999](https://github.com/ant-design/ant-design/pull/23999)
- 🐞 修复 DatePicker 下拉框在 RTL 模式下样式。[#24028](https://github.com/ant-design/ant-design/pull/24028) [@xrkffgg](https://github.com/xrkffgg)
- 💄 优化 DatePick 在 `RTL` 模式下的激活条样式。[#23981](https://github.com/ant-design/ant-design/pull/23981)
- 🐞 修复 Transfer 查询框在 `RTL` 模式下的边距样式。[#23962](https://github.com/ant-design/ant-design/pull/23962)
- 💄 优化 Layout RTL 样式。[#23921](https://github.com/ant-design/ant-design/pull/23921)
- 💄 优化 Button `loading` 状态在 RTL 下样式。[#23776](https://github.com/ant-design/ant-design/pull/23776)
- 💄 优化 Input.Search RTL 样式。[#23797](https://github.com/ant-design/ant-design/pull/23797)
- TypeScript
- 🐞 修复 InputNumber `onChange` 类型。[#23871](https://github.com/ant-design/ant-design/pull/23871) [@jjhbw](https://github.com/jjhbw)
## 4.2.0 ## 4.2.0
`2020-04-29` `2020-04-29`

View File

@ -41,4 +41,8 @@ ReactDOM.render(
margin-top: 16px; margin-top: 16px;
margin-right: 16px; margin-right: 16px;
} }
.ant-row-rtl #components-avatar-demo-basic .ant-avatar {
margin-right: 0;
margin-left: 16px;
}
</style> </style>

View File

@ -35,4 +35,8 @@ ReactDOM.render(
margin-top: 16px; margin-top: 16px;
margin-right: 16px; margin-right: 16px;
} }
.ant-row-rtl #components-avatar-demo-type .ant-avatar {
margin-right: 0;
margin-left: 16px;
}
</style> </style>

View File

@ -22,13 +22,6 @@
line-height: @line-height-base; line-height: @line-height-base;
.btn; .btn;
.btn-default; .btn-default;
// Make sure that the target of Button's click event always be `button`
// Ref: https://github.com/ant-design/ant-design/issues/7034
> i,
> span {
display: inline-block;
pointer-events: none;
}
&-primary { &-primary {
.btn-primary; .btn-primary;

View File

@ -53,14 +53,7 @@ describe('Cascader', () => {
it('popup correctly when panel is hidden', () => { it('popup correctly when panel is hidden', () => {
const wrapper = mount(<Cascader options={options} />); const wrapper = mount(<Cascader options={options} />);
expect( expect(render(wrapper.find('Trigger').instance().getComponent())).toMatchSnapshot();
render(
wrapper
.find('Trigger')
.instance()
.getComponent(),
),
).toMatchSnapshot();
}); });
it('popup correctly when panel is open', () => { it('popup correctly when panel is open', () => {
@ -69,14 +62,7 @@ describe('Cascader', () => {
<Cascader options={options} onPopupVisibleChange={onPopupVisibleChange} />, <Cascader options={options} onPopupVisibleChange={onPopupVisibleChange} />,
); );
wrapper.find('input').simulate('click'); wrapper.find('input').simulate('click');
expect( expect(render(wrapper.find('Trigger').instance().getComponent())).toMatchSnapshot();
render(
wrapper
.find('Trigger')
.instance()
.getComponent(),
),
).toMatchSnapshot();
expect(onPopupVisibleChange).toHaveBeenCalledWith(true); expect(onPopupVisibleChange).toHaveBeenCalledWith(true);
}); });
@ -91,97 +77,44 @@ describe('Cascader', () => {
it('popup correctly with defaultValue', () => { it('popup correctly with defaultValue', () => {
const wrapper = mount(<Cascader options={options} defaultValue={['zhejiang', 'hangzhou']} />); const wrapper = mount(<Cascader options={options} defaultValue={['zhejiang', 'hangzhou']} />);
wrapper.find('input').simulate('click'); wrapper.find('input').simulate('click');
expect( expect(render(wrapper.find('Trigger').instance().getComponent())).toMatchSnapshot();
render(
wrapper
.find('Trigger')
.instance()
.getComponent(),
),
).toMatchSnapshot();
}); });
it('should support popupVisible', () => { it('should support popupVisible', () => {
const wrapper = mount(<Cascader options={options} defaultValue={['zhejiang', 'hangzhou']} />); const wrapper = mount(<Cascader options={options} defaultValue={['zhejiang', 'hangzhou']} />);
expect( expect(wrapper.find('Trigger').instance().getComponent().props.visible).toBe(false);
wrapper
.find('Trigger')
.instance()
.getComponent().props.visible,
).toBe(false);
wrapper.setProps({ popupVisible: true }); wrapper.setProps({ popupVisible: true });
expect( expect(wrapper.find('Trigger').instance().getComponent().props.visible).toBe(true);
wrapper
.find('Trigger')
.instance()
.getComponent().props.visible,
).toBe(true);
}); });
it('can be selected', () => { it('can be selected', () => {
const onChange = jest.fn(); const onChange = jest.fn();
const wrapper = mount(<Cascader options={options} onChange={onChange} />); const wrapper = mount(<Cascader options={options} onChange={onChange} />);
wrapper.find('input').simulate('click'); wrapper.find('input').simulate('click');
let popupWrapper = mount( let popupWrapper = mount(wrapper.find('Trigger').instance().getComponent());
wrapper
.find('Trigger')
.instance()
.getComponent(),
);
popupWrapper popupWrapper
.find('.ant-cascader-menu') .find('.ant-cascader-menu')
.at(0) .at(0)
.find('.ant-cascader-menu-item') .find('.ant-cascader-menu-item')
.at(0) .at(0)
.simulate('click'); .simulate('click');
expect( expect(render(wrapper.find('Trigger').instance().getComponent())).toMatchSnapshot();
render( popupWrapper = mount(wrapper.find('Trigger').instance().getComponent());
wrapper
.find('Trigger')
.instance()
.getComponent(),
),
).toMatchSnapshot();
popupWrapper = mount(
wrapper
.find('Trigger')
.instance()
.getComponent(),
);
popupWrapper popupWrapper
.find('.ant-cascader-menu') .find('.ant-cascader-menu')
.at(1) .at(1)
.find('.ant-cascader-menu-item') .find('.ant-cascader-menu-item')
.at(0) .at(0)
.simulate('click'); .simulate('click');
expect( expect(render(wrapper.find('Trigger').instance().getComponent())).toMatchSnapshot();
render( popupWrapper = mount(wrapper.find('Trigger').instance().getComponent());
wrapper
.find('Trigger')
.instance()
.getComponent(),
),
).toMatchSnapshot();
popupWrapper = mount(
wrapper
.find('Trigger')
.instance()
.getComponent(),
);
popupWrapper popupWrapper
.find('.ant-cascader-menu') .find('.ant-cascader-menu')
.at(2) .at(2)
.find('.ant-cascader-menu-item') .find('.ant-cascader-menu-item')
.at(0) .at(0)
.simulate('click'); .simulate('click');
expect( expect(render(wrapper.find('Trigger').instance().getComponent())).toMatchSnapshot();
render(
wrapper
.find('Trigger')
.instance()
.getComponent(),
),
).toMatchSnapshot();
expect(onChange).toHaveBeenCalledWith(['zhejiang', 'hangzhou', 'xihu'], expect.anything()); expect(onChange).toHaveBeenCalledWith(['zhejiang', 'hangzhou', 'xihu'], expect.anything());
}); });
@ -199,12 +132,7 @@ describe('Cascader', () => {
wrapper.find('input').simulate('click'); wrapper.find('input').simulate('click');
wrapper.find('input').simulate('change', { target: { value: 'z' } }); wrapper.find('input').simulate('change', { target: { value: 'z' } });
expect(wrapper.state('inputValue')).toBe('z'); expect(wrapper.state('inputValue')).toBe('z');
const popupWrapper = mount( const popupWrapper = mount(wrapper.find('Trigger').instance().getComponent());
wrapper
.find('Trigger')
.instance()
.getComponent(),
);
expect(popupWrapper).toMatchSnapshot(); expect(popupWrapper).toMatchSnapshot();
}); });
@ -245,12 +173,7 @@ describe('Cascader', () => {
wrapper.find('input').simulate('click'); wrapper.find('input').simulate('click');
wrapper.find('input').simulate('change', { target: { value: 'z' } }); wrapper.find('input').simulate('change', { target: { value: 'z' } });
expect(wrapper.state('inputValue')).toBe('z'); expect(wrapper.state('inputValue')).toBe('z');
const popupWrapper = mount( const popupWrapper = mount(wrapper.find('Trigger').instance().getComponent());
wrapper
.find('Trigger')
.instance()
.getComponent(),
);
expect(popupWrapper.render()).toMatchSnapshot(); expect(popupWrapper.render()).toMatchSnapshot();
}); });
@ -259,22 +182,14 @@ describe('Cascader', () => {
wrapper.find('input').simulate('click'); wrapper.find('input').simulate('click');
wrapper.find('input').simulate('change', { target: { value: '__notfoundkeyword__' } }); wrapper.find('input').simulate('change', { target: { value: '__notfoundkeyword__' } });
expect(wrapper.state('inputValue')).toBe('__notfoundkeyword__'); expect(wrapper.state('inputValue')).toBe('__notfoundkeyword__');
const popupWrapper = mount( const popupWrapper = mount(wrapper.find('Trigger').instance().getComponent());
wrapper
.find('Trigger')
.instance()
.getComponent(),
);
expect(popupWrapper).toMatchSnapshot(); expect(popupWrapper).toMatchSnapshot();
}); });
it('should support to clear selection', () => { it('should support to clear selection', () => {
const wrapper = mount(<Cascader options={options} defaultValue={['zhejiang', 'hangzhou']} />); const wrapper = mount(<Cascader options={options} defaultValue={['zhejiang', 'hangzhou']} />);
expect(wrapper.find('.ant-cascader-picker-label').text()).toBe('Zhejiang / Hangzhou'); expect(wrapper.find('.ant-cascader-picker-label').text()).toBe('Zhejiang / Hangzhou');
wrapper wrapper.find('.ant-cascader-picker-clear').at(0).simulate('click');
.find('.ant-cascader-picker-clear')
.at(0)
.simulate('click');
expect(wrapper.find('.ant-cascader-picker-label').text()).toBe(''); expect(wrapper.find('.ant-cascader-picker-label').text()).toBe('');
}); });
@ -288,10 +203,7 @@ describe('Cascader', () => {
onPopupVisibleChange={onPopupVisibleChange} onPopupVisibleChange={onPopupVisibleChange}
/>, />,
); );
wrapper wrapper.find('.ant-cascader-picker-clear').at(0).simulate('click');
.find('.ant-cascader-picker-clear')
.at(0)
.simulate('click');
expect(onPopupVisibleChange).toHaveBeenCalledWith(false); expect(onPopupVisibleChange).toHaveBeenCalledWith(false);
}); });
@ -302,10 +214,7 @@ describe('Cascader', () => {
wrapper.find('input').simulate('click'); wrapper.find('input').simulate('click');
wrapper.find('input').simulate('change', { target: { value: 'xxx' } }); wrapper.find('input').simulate('change', { target: { value: 'xxx' } });
expect(wrapper.state('inputValue')).toBe('xxx'); expect(wrapper.state('inputValue')).toBe('xxx');
wrapper wrapper.find('.ant-cascader-picker-clear').at(0).simulate('click');
.find('.ant-cascader-picker-clear')
.at(0)
.simulate('click');
expect(wrapper.state('inputValue')).toBe(''); expect(wrapper.state('inputValue')).toBe('');
}); });
@ -393,24 +302,14 @@ describe('Cascader', () => {
/>, />,
); );
wrapper.instance().handleChange(['zhejiang', 'hangzhou', 'xihu'], customerOptions); wrapper.instance().handleChange(['zhejiang', 'hangzhou', 'xihu'], customerOptions);
expect( expect(wrapper.find('.ant-cascader-picker-label').text().split('/').length).toBe(3);
wrapper
.find('.ant-cascader-picker-label')
.text()
.split('/').length,
).toBe(3);
}); });
it('should show not found content when options.length is 0', () => { it('should show not found content when options.length is 0', () => {
const customerOptions = []; const customerOptions = [];
const wrapper = mount(<Cascader options={customerOptions} />); const wrapper = mount(<Cascader options={customerOptions} />);
wrapper.find('input').simulate('click'); wrapper.find('input').simulate('click');
const popupWrapper = mount( const popupWrapper = mount(wrapper.find('Trigger').instance().getComponent());
wrapper
.find('Trigger')
.instance()
.getComponent(),
);
expect(popupWrapper).toMatchSnapshot(); expect(popupWrapper).toMatchSnapshot();
}); });
@ -484,12 +383,7 @@ describe('Cascader', () => {
fieldNames={{ label: 'name', value: 'code', children: 'items' }} fieldNames={{ label: 'name', value: 'code', children: 'items' }}
/>, />,
); );
const popupWrapper = mount( const popupWrapper = mount(wrapper.find('Trigger').instance().getComponent());
wrapper
.find('Trigger')
.instance()
.getComponent(),
);
expect(popupWrapper.render()).toMatchSnapshot(); expect(popupWrapper.render()).toMatchSnapshot();
}); });
@ -510,18 +404,9 @@ describe('Cascader', () => {
<Cascader options={options} defaultValue={['zhejiang', 'hangzhou']} /> <Cascader options={options} defaultValue={['zhejiang', 'hangzhou']} />
</ConfigProvider>, </ConfigProvider>,
); );
wrapper wrapper.find('Cascader').find('input').simulate('click');
.find('Cascader')
.find('input')
.simulate('click');
expect( expect(
render( render(wrapper.find('Cascader').find('Trigger').instance().getComponent()),
wrapper
.find('Cascader')
.find('Trigger')
.instance()
.getComponent(),
),
).toMatchSnapshot(); ).toMatchSnapshot();
}); });
@ -572,17 +457,8 @@ describe('Cascader', () => {
</ConfigProvider>, </ConfigProvider>,
); );
wrapper wrapper.find('Cascader').find('input').simulate('click');
.find('Cascader') let popupWrapper = mount(wrapper.find('Cascader').find('Trigger').instance().getComponent());
.find('input')
.simulate('click');
let popupWrapper = mount(
wrapper
.find('Cascader')
.find('Trigger')
.instance()
.getComponent(),
);
popupWrapper popupWrapper
.find('.ant-cascader-menu') .find('.ant-cascader-menu')
.at(0) .at(0)
@ -590,21 +466,9 @@ describe('Cascader', () => {
.at(0) .at(0)
.simulate('click'); .simulate('click');
expect( expect(
render( render(wrapper.find('Cascader').find('Trigger').instance().getComponent()),
wrapper
.find('Cascader')
.find('Trigger')
.instance()
.getComponent(),
),
).toMatchSnapshot(); ).toMatchSnapshot();
popupWrapper = mount( popupWrapper = mount(wrapper.find('Cascader').find('Trigger').instance().getComponent());
wrapper
.find('Cascader')
.find('Trigger')
.instance()
.getComponent(),
);
popupWrapper popupWrapper
.find('.ant-cascader-menu') .find('.ant-cascader-menu')
.at(1) .at(1)
@ -612,21 +476,9 @@ describe('Cascader', () => {
.at(0) .at(0)
.simulate('click'); .simulate('click');
expect( expect(
render( render(wrapper.find('Cascader').find('Trigger').instance().getComponent()),
wrapper
.find('Cascader')
.find('Trigger')
.instance()
.getComponent(),
),
).toMatchSnapshot(); ).toMatchSnapshot();
popupWrapper = mount( popupWrapper = mount(wrapper.find('Cascader').find('Trigger').instance().getComponent());
wrapper
.find('Cascader')
.find('Trigger')
.instance()
.getComponent(),
);
popupWrapper popupWrapper
.find('.ant-cascader-menu') .find('.ant-cascader-menu')
.at(2) .at(2)
@ -635,4 +487,9 @@ describe('Cascader', () => {
.simulate('click'); .simulate('click');
expect(onChange).toHaveBeenCalledWith(['zhejiang', 'hangzhou', 'xihu'], expect.anything()); expect(onChange).toHaveBeenCalledWith(['zhejiang', 'hangzhou', 'xihu'], expect.anything());
}); });
it('defaultValue works correctly when no match options', () => {
const wrapper = mount(<Cascader options={options} defaultValue={['options1', 'options2']} />);
expect(wrapper.find('.ant-cascader-picker-label').text()).toBe('options1 / options2');
});
}); });

View File

@ -283,7 +283,7 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
(o: CascaderOptionType, level: number) => o[names.value] === unwrappedValue[level], (o: CascaderOptionType, level: number) => o[names.value] === unwrappedValue[level],
{ childrenKeyName: names.children }, { childrenKeyName: names.children },
); );
const label = selectedOptions.map(o => o[names.label]); const label = selectedOptions.length ? selectedOptions.map(o => o[names.label]) : value;
return displayRender(label, selectedOptions); return displayRender(label, selectedOptions);
} }
@ -522,8 +522,10 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
const names: FilledFieldNamesType = getFilledFieldNames(this.props); const names: FilledFieldNamesType = getFilledFieldNames(this.props);
if (options && options.length > 0) { if (options && options.length > 0) {
if (state.inputValue) { if (state.inputValue) {
const filteredOptions = this.generateFilteredOptions(prefixCls, renderEmpty); const filteredOptions = this.generateFilteredOptions(prefixCls, renderEmpty);
options = isEqual(filteredOptions, this.cachedOptions) ? this.cachedOptions : filteredOptions; options = isEqual(filteredOptions, this.cachedOptions)
? this.cachedOptions
: filteredOptions;
} }
} else { } else {
options = [ options = [

View File

@ -1,5 +1,4 @@
import * as React from 'react'; import * as React from 'react';
import * as PropTypes from 'prop-types';
import classNames from 'classnames'; import classNames from 'classnames';
import omit from 'omit.js'; import omit from 'omit.js';
import Checkbox, { CheckboxChangeEvent } from './Checkbox'; import Checkbox, { CheckboxChangeEvent } from './Checkbox';
@ -48,13 +47,6 @@ class CheckboxGroup extends React.PureComponent<CheckboxGroupProps, CheckboxGrou
options: [], options: [],
}; };
static propTypes = {
defaultValue: PropTypes.array,
value: PropTypes.array,
options: PropTypes.array.isRequired,
onChange: PropTypes.func,
};
static getDerivedStateFromProps(nextProps: CheckboxGroupProps) { static getDerivedStateFromProps(nextProps: CheckboxGroupProps) {
if ('value' in nextProps) { if ('value' in nextProps) {
return { return {

View File

@ -13321,7 +13321,7 @@ exports[`ConfigProvider components Dropdown configProvider 1`] = `
</span> </span>
</button> </button>
<button <button
class="config-btn config-dropdown-trigger config-btn-default" class="config-btn config-dropdown-trigger config-btn-default config-btn-icon-only"
type="button" type="button"
> >
<span <span
@ -13361,7 +13361,7 @@ exports[`ConfigProvider components Dropdown configProvider componentSize large 1
</span> </span>
</button> </button>
<button <button
class="config-btn config-dropdown-trigger config-btn-default config-btn-lg" class="config-btn config-dropdown-trigger config-btn-default config-btn-lg config-btn-icon-only"
type="button" type="button"
> >
<span <span
@ -13401,7 +13401,7 @@ exports[`ConfigProvider components Dropdown configProvider componentSize middle
</span> </span>
</button> </button>
<button <button
class="config-btn config-dropdown-trigger config-btn-default" class="config-btn config-dropdown-trigger config-btn-default config-btn-icon-only"
type="button" type="button"
> >
<span <span
@ -13441,7 +13441,7 @@ exports[`ConfigProvider components Dropdown configProvider virtual and dropdownM
</span> </span>
</button> </button>
<button <button
class="ant-btn ant-dropdown-trigger ant-btn-default" class="ant-btn ant-dropdown-trigger ant-btn-default ant-btn-icon-only"
type="button" type="button"
> >
<span <span
@ -13481,7 +13481,7 @@ exports[`ConfigProvider components Dropdown normal 1`] = `
</span> </span>
</button> </button>
<button <button
class="ant-btn ant-dropdown-trigger ant-btn-default" class="ant-btn ant-dropdown-trigger ant-btn-default ant-btn-icon-only"
type="button" type="button"
> >
<span <span
@ -13521,7 +13521,7 @@ exports[`ConfigProvider components Dropdown prefixCls 1`] = `
</span> </span>
</button> </button>
<button <button
class="ant-btn ant-dropdown-trigger ant-btn-default" class="ant-btn ant-dropdown-trigger ant-btn-default ant-btn-icon-only"
type="button" type="button"
> >
<span <span
@ -16138,24 +16138,22 @@ exports[`ConfigProvider components Modal configProvider 1`] = `
<div <div
class="config-modal-footer" class="config-modal-footer"
> >
<div> <button
<button class="config-btn"
class="config-btn" type="button"
type="button" >
> <span>
<span> Cancel
Cancel </span>
</span> </button>
</button> <button
<button class="config-btn config-btn-primary"
class="config-btn config-btn-primary" type="button"
type="button" >
> <span>
<span> OK
OK </span>
</span> </button>
</button>
</div>
</div> </div>
</div> </div>
<div <div
@ -16233,24 +16231,22 @@ exports[`ConfigProvider components Modal configProvider componentSize large 1`]
<div <div
class="config-modal-footer" class="config-modal-footer"
> >
<div> <button
<button class="config-btn config-btn-lg"
class="config-btn config-btn-lg" type="button"
type="button" >
> <span>
<span> Cancel
Cancel </span>
</span> </button>
</button> <button
<button class="config-btn config-btn-primary config-btn-lg"
class="config-btn config-btn-primary config-btn-lg" type="button"
type="button" >
> <span>
<span> OK
OK </span>
</span> </button>
</button>
</div>
</div> </div>
</div> </div>
<div <div
@ -16328,24 +16324,22 @@ exports[`ConfigProvider components Modal configProvider componentSize middle 1`]
<div <div
class="config-modal-footer" class="config-modal-footer"
> >
<div> <button
<button class="config-btn"
class="config-btn" type="button"
type="button" >
> <span>
<span> Cancel
Cancel </span>
</span> </button>
</button> <button
<button class="config-btn config-btn-primary"
class="config-btn config-btn-primary" type="button"
type="button" >
> <span>
<span> OK
OK </span>
</span> </button>
</button>
</div>
</div> </div>
</div> </div>
<div <div
@ -16423,24 +16417,22 @@ exports[`ConfigProvider components Modal configProvider virtual and dropdownMatc
<div <div
class="ant-modal-footer" class="ant-modal-footer"
> >
<div> <button
<button class="ant-btn"
class="ant-btn" type="button"
type="button" >
> <span>
<span> Cancel
Cancel </span>
</span> </button>
</button> <button
<button class="ant-btn ant-btn-primary"
class="ant-btn ant-btn-primary" type="button"
type="button" >
> <span>
<span> OK
OK </span>
</span> </button>
</button>
</div>
</div> </div>
</div> </div>
<div <div
@ -16518,24 +16510,22 @@ exports[`ConfigProvider components Modal normal 1`] = `
<div <div
class="ant-modal-footer" class="ant-modal-footer"
> >
<div> <button
<button class="ant-btn"
class="ant-btn" type="button"
type="button" >
> <span>
<span> Cancel
Cancel </span>
</span> </button>
</button> <button
<button class="ant-btn ant-btn-primary"
class="ant-btn ant-btn-primary" type="button"
type="button" >
> <span>
<span> OK
OK </span>
</span> </button>
</button>
</div>
</div> </div>
</div> </div>
<div <div
@ -16613,24 +16603,22 @@ exports[`ConfigProvider components Modal prefixCls 1`] = `
<div <div
class="prefix-Modal-footer" class="prefix-Modal-footer"
> >
<div> <button
<button class="ant-btn"
class="ant-btn" type="button"
type="button" >
> <span>
<span> Cancel
Cancel </span>
</span> </button>
</button> <button
<button class="ant-btn ant-btn-primary"
class="ant-btn ant-btn-primary" type="button"
type="button" >
> <span>
<span> OK
OK </span>
</span> </button>
</button>
</div>
</div> </div>
</div> </div>
<div <div

View File

@ -162,6 +162,9 @@ Added in `4.1.0`.
.code-box-demo .ant-picker { .code-box-demo .ant-picker {
margin: 0 8px 12px 0; margin: 0 8px 12px 0;
} }
.ant-row-rtl .code-box-demo .ant-picker {
margin: 0 0 12px 8px;
}
</style> </style>
## FAQ ## FAQ

View File

@ -164,6 +164,9 @@ import 'moment/locale/zh-cn';
.code-box-demo .ant-picker { .code-box-demo .ant-picker {
margin: 0 8px 12px 0; margin: 0 8px 12px 0;
} }
.ant-row-rtl .code-box-demo .ant-picker {
margin: 0 0 12px 8px;
}
</style> </style>
## FAQ ## FAQ

View File

@ -293,6 +293,7 @@
.@{picker-prefix-cls}-panels { .@{picker-prefix-cls}-panels {
display: inline-flex; display: inline-flex;
flex-wrap: nowrap; flex-wrap: nowrap;
direction: ltr;
} }
.@{picker-prefix-cls}-panel { .@{picker-prefix-cls}-panel {

View File

@ -136,12 +136,27 @@ class Drawer extends React.Component<DrawerProps & ConfigConsumerProps, IDrawerS
} }
}; };
getOffsetStyle() {
const { placement, width, height } = this.props;
const offsetStyle: any = {};
if (placement === 'left' || placement === 'right') {
offsetStyle.width = width;
} else {
offsetStyle.height = height;
}
return offsetStyle;
}
getRcDrawerStyle = () => { getRcDrawerStyle = () => {
const { zIndex, placement, style } = this.props; const { zIndex, placement, mask, style } = this.props;
const { push } = this.state; const { push } = this.state;
// 当无 mask 时,将 width 应用到外层容器上
// 解决 https://github.com/ant-design/ant-design/issues/12401 的问题
const offsetStyle = mask ? {} : this.getOffsetStyle();
return { return {
zIndex, zIndex,
transform: push ? this.getPushTransform(placement) : undefined, transform: push ? this.getPushTransform(placement) : undefined,
...offsetStyle,
...style, ...style,
}; };
}; };
@ -234,18 +249,14 @@ class Drawer extends React.Component<DrawerProps & ConfigConsumerProps, IDrawerS
// render Provider for Multi-level drawer // render Provider for Multi-level drawer
renderProvider = (value: Drawer) => { renderProvider = (value: Drawer) => {
const { prefixCls, placement, className, width, height, mask, direction, ...rest } = this.props; const { prefixCls, placement, className, mask, direction, visible, ...rest } = this.props;
const haveMask = mask ? '' : 'no-mask';
this.parentDrawer = value; this.parentDrawer = value;
const offsetStyle: any = {}; const drawerClassName = classNames(className, {
if (placement === 'left' || placement === 'right') { 'no-mask': !mask,
offsetStyle.width = width;
} else {
offsetStyle.height = height;
}
const drawerClassName = classNames(className, haveMask, {
[`${prefixCls}-rtl`]: direction === 'rtl', [`${prefixCls}-rtl`]: direction === 'rtl',
}); });
const offsetStyle = mask ? this.getOffsetStyle() : {};
return ( return (
<DrawerContext.Provider value={this}> <DrawerContext.Provider value={this}>
<RcDrawer <RcDrawer
@ -271,10 +282,12 @@ class Drawer extends React.Component<DrawerProps & ConfigConsumerProps, IDrawerS
'csp', 'csp',
'pageHeader', 'pageHeader',
'autoInsertSpaceInButton', 'autoInsertSpaceInButton',
'width',
'height',
])} ])}
{...offsetStyle} {...offsetStyle}
prefixCls={prefixCls} prefixCls={prefixCls}
open={this.props.visible} open={visible}
showMask={mask} showMask={mask}
placement={placement} placement={placement}
style={this.getRcDrawerStyle()} style={this.getRcDrawerStyle()}

View File

@ -19,7 +19,10 @@
&-content-wrapper { &-content-wrapper {
position: absolute; position: absolute;
width: 100%;
height: 100%;
} }
.@{drawer-prefix-cls}-content { .@{drawer-prefix-cls}-content {
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -37,13 +40,6 @@
width: 100%; width: 100%;
transition: transform @animation-duration-slow @ease-base-out; transition: transform @animation-duration-slow @ease-base-out;
} }
&.@{drawer-prefix-cls}-open.no-mask {
height: 0%;
.@{drawer-prefix-cls}-content-wrapper {
height: 100vh;
}
}
} }
&-left { &-left {
@ -95,13 +91,6 @@
height: 100%; height: 100%;
transition: transform @animation-duration-slow @ease-base-out; transition: transform @animation-duration-slow @ease-base-out;
} }
&.@{drawer-prefix-cls}-open.no-mask {
width: 0%;
.@{drawer-prefix-cls}-content-wrapper {
width: 100vw;
}
}
} }
&-top { &-top {
@ -168,7 +157,7 @@
z-index: @zindex-popup-close; z-index: @zindex-popup-close;
display: block; display: block;
padding: @drawer-header-close-padding; padding: @drawer-header-close-padding;
color: @text-color-secondary; color: @modal-close-color;
font-weight: 700; font-weight: 700;
font-size: @font-size-lg; font-size: @font-size-lg;
font-style: normal; font-style: normal;

View File

@ -53,7 +53,7 @@ exports[`renders ./components/dropdown/demo/dropdown-button.md correctly 1`] = `
</span> </span>
</button> </button>
<button <button
class="ant-btn ant-dropdown-trigger ant-btn-default" class="ant-btn ant-dropdown-trigger ant-btn-default ant-btn-icon-only"
type="button" type="button"
> >
<span <span
@ -90,7 +90,7 @@ exports[`renders ./components/dropdown/demo/dropdown-button.md correctly 1`] = `
</span> </span>
</button> </button>
<button <button
class="ant-btn ant-dropdown-trigger ant-btn-default" class="ant-btn ant-dropdown-trigger ant-btn-default ant-btn-icon-only"
type="button" type="button"
> >
<span <span
@ -128,7 +128,7 @@ exports[`renders ./components/dropdown/demo/dropdown-button.md correctly 1`] = `
</span> </span>
</button> </button>
<button <button
class="ant-btn ant-dropdown-trigger ant-btn-default" class="ant-btn ant-dropdown-trigger ant-btn-default ant-btn-icon-only"
disabled="" disabled=""
type="button" type="button"
> >
@ -166,28 +166,32 @@ exports[`renders ./components/dropdown/demo/dropdown-button.md correctly 1`] = `
</span> </span>
</button> </button>
<button <button
class="ant-btn ant-dropdown-trigger ant-btn-default" class="ant-btn ant-dropdown-trigger ant-btn-default ant-btn-icon-only ant-btn-loading"
type="button" type="button"
> >
<span <span
aria-label="ellipsis" class="ant-btn-loading-icon"
class="anticon anticon-ellipsis"
role="img"
> >
<svg <span
aria-hidden="true" aria-label="loading"
class="" class="anticon anticon-loading"
data-icon="ellipsis" role="img"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
> >
<path <svg
d="M176 511a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0z" aria-hidden="true"
/> class="anticon-spin"
</svg> 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>
</button> </button>
</div> </div>

View File

@ -15,7 +15,7 @@ exports[`DropdownButton rtl render component should be rendered correctly in RTL
type="button" type="button"
/> />
<button <button
class="ant-btn ant-dropdown-trigger ant-dropdown-rtl ant-btn-default ant-btn-rtl" class="ant-btn ant-dropdown-trigger ant-dropdown-rtl ant-btn-default ant-btn-icon-only ant-btn-rtl"
type="button" type="button"
> >
<span <span
@ -51,7 +51,7 @@ exports[`DropdownButton should support href like Button 1`] = `
href="https://ant.design" href="https://ant.design"
/> />
<button <button
class="ant-btn ant-dropdown-trigger ant-btn-default" class="ant-btn ant-dropdown-trigger ant-btn-default ant-btn-icon-only"
type="button" type="button"
> >
<span <span

View File

@ -58,7 +58,7 @@ ReactDOM.render(
<Tooltip title="tooltip" key="leftButton"> <Tooltip title="tooltip" key="leftButton">
{leftButton} {leftButton}
</Tooltip>, </Tooltip>,
rightButton, React.cloneElement(rightButton, { loading: true }),
]} ]}
> >
With Tooltip With Tooltip

View File

@ -67,4 +67,9 @@ ReactDOM.render(
margin-right: 8px; margin-right: 8px;
margin-bottom: 8px; margin-bottom: 8px;
} }
.ant-row-rtl #components-dropdown-demo-placement .ant-btn {
margin-right: 0;
margin-bottom: 8px;
margin-left: 8px;
}
``` ```

View File

@ -87,7 +87,7 @@ export default class DropdownButton extends React.Component<DropdownButtonProps,
</Button> </Button>
); );
const rightButton = <Button type={type}>{icon}</Button>; const rightButton = <Button type={type} icon={icon} />;
const [leftButtonToRender, rightButtonToRender] = buttonsRender!([leftButton, rightButton]); const [leftButtonToRender, rightButtonToRender] = buttonsRender!([leftButton, rightButton]);

View File

@ -100,8 +100,8 @@
cursor: pointer; cursor: pointer;
transition: all 0.3s; transition: all 0.3s;
> .anticon:first-child, > .@{iconfont-css-prefix}:first-child,
> span > .anticon:first-child { > span > .@{iconfont-css-prefix}:first-child {
min-width: 12px; min-width: 12px;
margin-right: 8px; margin-right: 8px;
font-size: @font-size-sm; font-size: @font-size-sm;
@ -251,10 +251,12 @@
.@{dropdown-prefix-cls}-button { .@{dropdown-prefix-cls}-button {
white-space: nowrap; white-space: nowrap;
&.@{ant-prefix}-btn-group > .@{ant-prefix}-btn:last-child:not(:first-child) { &.@{ant-prefix}-btn-group
> .@{ant-prefix}-btn:last-child:not(:first-child):not(.@{ant-prefix}-btn-icon-only) {
padding-right: @padding-xs; padding-right: @padding-xs;
padding-left: @padding-xs; padding-left: @padding-xs;
} }
.@{iconfont-css-prefix}.@{iconfont-css-prefix}-down { .@{iconfont-css-prefix}.@{iconfont-css-prefix}-down {
.iconfont-size-under-12px(10px); .iconfont-size-under-12px(10px);
} }

View File

@ -40,4 +40,8 @@ ReactDOM.render(
margin-right: 6px; margin-right: 6px;
font-size: 24px; font-size: 24px;
} }
.ant-row-rtl .icons-list > .anticon {
margin-right: 0;
margin-left: 6px;
}
</style> </style>

View File

@ -84,4 +84,8 @@ ReactDOM.render(
.custom-icons-list > .anticon { .custom-icons-list > .anticon {
margin-right: 6px; margin-right: 6px;
} }
.ant-row-rtl .custom-icons-list > .anticon {
margin-right: 0;
margin-left: 6px;
}
``` ```

View File

@ -34,4 +34,8 @@ ReactDOM.render(
.code-box-demo .ant-input-number { .code-box-demo .ant-input-number {
margin-right: 10px; margin-right: 10px;
} }
.ant-row-rtl .code-box-demo .ant-input-number {
margin-right: 0;
margin-left: 10px;
}
``` ```

View File

@ -220,7 +220,7 @@ describe('Locale Provider', () => {
'.ant-btn:not(.ant-btn-primary) span', '.ant-btn:not(.ant-btn-primary) span',
)[0].innerHTML; )[0].innerHTML;
let okButtonText = currentConfirmNode.querySelectorAll('.ant-btn-primary span')[0].innerHTML; let okButtonText = currentConfirmNode.querySelectorAll('.ant-btn-primary span')[0].innerHTML;
if (locale.locale === 'zh-cn') { if (locale.locale.indexOf('zh-') === 0) {
cancelButtonText = cancelButtonText.replace(' ', ''); cancelButtonText = cancelButtonText.replace(' ', '');
okButtonText = okButtonText.replace(' ', ''); okButtonText = okButtonText.replace(' ', '');
} }

View File

@ -1,30 +1,43 @@
/* eslint-disable no-template-curly-in-string */
import Pagination from 'rc-pagination/lib/locale/zh_TW'; import Pagination from 'rc-pagination/lib/locale/zh_TW';
import DatePicker from '../date-picker/locale/zh_TW'; import DatePicker from '../date-picker/locale/zh_TW';
import TimePicker from '../time-picker/locale/zh_TW'; import TimePicker from '../time-picker/locale/zh_TW';
import Calendar from '../calendar/locale/zh_TW'; import Calendar from '../calendar/locale/zh_TW';
import { Locale } from '../locale-provider'; import { Locale } from '../locale-provider';
const typeTemplate = '${label}不是一個有效的${type}';
const localeValues: Locale = { const localeValues: Locale = {
locale: 'zh-tw', locale: 'zh-tw',
Pagination, Pagination,
DatePicker, DatePicker,
TimePicker, TimePicker,
Calendar, Calendar,
global: {
placeholder: '請選擇',
},
Table: { Table: {
filterTitle: '篩選器', filterTitle: '篩選器',
filterConfirm: '確 定', filterConfirm: '確定',
filterReset: '重 置', filterReset: '重置',
selectAll: '全部選取', selectAll: '全部選取',
selectInvert: '反向選取', selectInvert: '反向選取',
selectionAll: '全選所有',
sortTitle: '排序',
expand: '展開行',
collapse: '關閉行',
triggerDesc: '點擊降序',
triggerAsc: '點擊升序',
cancelSort: '取消排序',
}, },
Modal: { Modal: {
okText: '確 定', okText: '確定',
cancelText: '取 消', cancelText: '取消',
justOkText: 'OK', justOkText: '知道了',
}, },
Popconfirm: { Popconfirm: {
okText: '確 定', okText: '確定',
cancelText: '取 消', cancelText: '取消',
}, },
Transfer: { Transfer: {
searchPlaceholder: '搜尋資料', searchPlaceholder: '搜尋資料',
@ -41,9 +54,67 @@ const localeValues: Locale = {
Empty: { Empty: {
description: '無此資料', description: '無此資料',
}, },
Icon: {
icon: '圖標',
},
Text: {
edit: '編輯',
copy: '複製',
copied: '複製成功',
expand: '展開',
},
PageHeader: { PageHeader: {
back: '返回', back: '返回',
}, },
Form: {
defaultValidateMessages: {
default: '字段驗證錯誤${label}',
required: '請輸入${label}',
enum: '${label}必須是其中一個[${enum}]',
whitespace: '${label}不能為空字符',
date: {
format: '${label}日期格式無效',
parse: '${label}不能轉換為日期',
invalid: '${label}是一個無效日期',
},
types: {
string: typeTemplate,
method: typeTemplate,
array: typeTemplate,
object: typeTemplate,
number: typeTemplate,
date: typeTemplate,
boolean: typeTemplate,
integer: typeTemplate,
float: typeTemplate,
regexp: typeTemplate,
email: typeTemplate,
url: typeTemplate,
hex: typeTemplate,
},
string: {
len: '${label}須為${len}個字符',
min: '${label}最少${min}個字符',
max: '${label}最多${max}個字符',
range: '${label}須在${min}-${max}字符之間',
},
number: {
len: '${label}必須等於${len}',
min: '${label}最小值為${min}',
max: '${label}最大值為${max}',
range: '${label}須在${min}-${max}之間',
},
array: {
len: '須為${len}個${label}',
min: '最少${min}個${label}',
max: '最多${max}個${label}',
range: '${label}數量須在${min}-${max}之間',
},
pattern: {
mismatch: '${label}與模式不匹配${pattern}',
},
},
},
}; };
export default localeValues; export default localeValues;

View File

@ -11,6 +11,7 @@
margin-bottom: 0; margin-bottom: 0;
padding-left: 0; // Override default ul/ol padding-left: 0; // Override default ul/ol
color: @menu-item-color; color: @menu-item-color;
font-size: @menu-item-font-size;
line-height: 0; // Fix display inline-block gap line-height: 0; // Fix display inline-block gap
list-style: none; list-style: none;
background: @menu-bg; background: @menu-bg;
@ -34,7 +35,7 @@
height: @menu-item-group-height; height: @menu-item-group-height;
padding: 8px 16px; padding: 8px 16px;
color: @menu-item-group-title-color; color: @menu-item-group-title-color;
font-size: @font-size-base; font-size: @menu-item-group-title-font-size;
line-height: @menu-item-group-height; line-height: @menu-item-group-height;
transition: all 0.3s; transition: all 0.3s;
} }
@ -177,7 +178,7 @@
background 0.3s @ease-in-out, padding 0.15s @ease-in-out; background 0.3s @ease-in-out, padding 0.15s @ease-in-out;
.@{iconfont-css-prefix} { .@{iconfont-css-prefix} {
min-width: 14px; min-width: 14px;
margin-right: @menu-item-icon-margin-right; margin-right: @menu-icon-margin-right;
font-size: @menu-icon-size; font-size: @menu-icon-size;
transition: font-size 0.15s @ease-out, margin 0.3s @ease-in-out; transition: font-size 0.15s @ease-out, margin 0.3s @ease-in-out;
+ span { + span {
@ -399,7 +400,6 @@
margin-bottom: @menu-item-vertical-margin; margin-bottom: @menu-item-vertical-margin;
padding: 0 16px; padding: 0 16px;
overflow: hidden; overflow: hidden;
font-size: @menu-item-font-size;
line-height: @menu-item-height; line-height: @menu-item-height;
text-overflow: ellipsis; text-overflow: ellipsis;
} }

View File

@ -22,12 +22,10 @@
} }
} }
&-dark { &-dark&-inline,
.@{menu-prefix-cls}-inline, &-dark&-vertical {
.@{menu-prefix-cls}-vertical { .@{menu-prefix-cls}-rtl& {
.@{menu-prefix-cls}-rtl& { border-left: none;
border-left: none;
}
} }
} }
@ -152,6 +150,7 @@
} }
&-sub&-inline { &-sub&-inline {
border: 0;
& .@{menu-prefix-cls}-item-group-title { & .@{menu-prefix-cls}-item-group-title {
.@{menu-prefix-cls}-rtl& { .@{menu-prefix-cls}-rtl& {
padding-right: 32px; padding-right: 32px;

View File

@ -150,7 +150,7 @@ export default class Modal extends React.Component<ModalProps, {}> {
renderFooter = (locale: ModalLocale) => { renderFooter = (locale: ModalLocale) => {
const { okText, okType, cancelText, confirmLoading } = this.props; const { okText, okType, cancelText, confirmLoading } = this.props;
return ( return (
<div> <>
<Button onClick={this.handleCancel} {...this.props.cancelButtonProps}> <Button onClick={this.handleCancel} {...this.props.cancelButtonProps}>
{cancelText || locale.cancelText} {cancelText || locale.cancelText}
</Button> </Button>
@ -162,7 +162,7 @@ export default class Modal extends React.Component<ModalProps, {}> {
> >
{okText || locale.okText} {okText || locale.okText}
</Button> </Button>
</div> </>
); );
}; };

View File

@ -66,24 +66,22 @@ exports[`Modal render correctly 1`] = `
<div <div
class="ant-modal-footer" class="ant-modal-footer"
> >
<div> <button
<button class="ant-btn"
class="ant-btn" type="button"
type="button" >
> <span>
<span> Cancel
Cancel </span>
</span> </button>
</button> <button
<button class="ant-btn ant-btn-primary"
class="ant-btn ant-btn-primary" type="button"
type="button" >
> <span>
<span> OK
OK </span>
</span> </button>
</button>
</div>
</div> </div>
</div> </div>
<div <div
@ -222,24 +220,22 @@ exports[`Modal support closeIcon 1`] = `
<div <div
class="ant-modal-footer" class="ant-modal-footer"
> >
<div> <button
<button class="ant-btn"
class="ant-btn" type="button"
type="button" >
> <span>
<span> Cancel
Cancel </span>
</span> </button>
</button> <button
<button class="ant-btn ant-btn-primary"
class="ant-btn ant-btn-primary" type="button"
type="button" >
> <span>
<span> OK
OK </span>
</span> </button>
</button>
</div>
</div> </div>
</div> </div>
<div <div

View File

@ -48,7 +48,7 @@
right: 0; right: 0;
z-index: @zindex-popup-close; z-index: @zindex-popup-close;
padding: 0; padding: 0;
color: @text-color-secondary; color: @modal-close-color;
font-weight: 700; font-weight: 700;
line-height: 1; line-height: 1;
text-decoration: none; text-decoration: none;

View File

@ -85,6 +85,10 @@ ReactDOM.render(<SelectSizesDemo />, mountNode);
margin: 0 8px 10px 0; margin: 0 8px 10px 0;
} }
.ant-row-rtl .code-box-demo .ant-select {
margin: 0 0 10px 8px;
}
#components-select-demo-search-box .code-box-demo .ant-select { #components-select-demo-search-box .code-box-demo .ant-select {
margin: 0; margin: 0;
} }

View File

@ -59,7 +59,7 @@
@menu-item-height: 32px; @menu-item-height: 32px;
@menu-item-vertical-margin: 0px; @menu-item-vertical-margin: 0px;
@menu-item-boundary-margin: 0px; @menu-item-boundary-margin: 0px;
@menu-item-icon-margin-right: 8px; @menu-icon-margin-right: 8px;
// Checkbox // Checkbox
@checkbox-size: 14px; @checkbox-size: 14px;

View File

@ -492,6 +492,7 @@
@modal-header-close-size: 56px; @modal-header-close-size: 56px;
@modal-content-bg: @component-background; @modal-content-bg: @component-background;
@modal-heading-color: @heading-color; @modal-heading-color: @heading-color;
@modal-close-color: @text-color-secondary;
@modal-footer-bg: transparent; @modal-footer-bg: transparent;
@modal-footer-border-color-split: @border-color-split; @modal-footer-border-color-split: @border-color-split;
@modal-footer-padding-vertical: 10px; @modal-footer-padding-vertical: 10px;
@ -523,15 +524,15 @@
@menu-item-active-danger-bg: @red-1; @menu-item-active-danger-bg: @red-1;
@menu-item-active-border-width: 3px; @menu-item-active-border-width: 3px;
@menu-item-group-title-color: @text-color-secondary; @menu-item-group-title-color: @text-color-secondary;
@menu-icon-size: @font-size-base;
@menu-icon-size-lg: @font-size-lg;
@menu-item-vertical-margin: 4px; @menu-item-vertical-margin: 4px;
@menu-item-font-size: @font-size-base; @menu-item-font-size: @font-size-base;
@menu-item-boundary-margin: 8px; @menu-item-boundary-margin: 8px;
@menu-item-padding: 0 20px; @menu-item-padding: 0 20px;
@menu-horizontal-line-height: 46px; @menu-horizontal-line-height: 46px;
@menu-item-icon-margin-right: 10px; @menu-icon-margin-right: 10px;
@menu-icon-size: @menu-item-font-size;
@menu-icon-size-lg: @font-size-lg;
@menu-item-group-title-font-size: @menu-item-font-size;
// dark theme // dark theme
@menu-dark-color: @text-color-secondary-dark; @menu-dark-color: @text-color-secondary-dark;

View File

@ -68,7 +68,10 @@ Same props from [RangePicker](/components/date-picker/#RangePicker) of DatePicke
| -------- | ------------------------ | ------- | ------- | ------- | | -------- | ------------------------ | ------- | ------- | ------- |
| order | Order start and end time | boolean | true | 4.1.0 | | order | Order start and end time | boolean | true | 4.1.0 |
<style>.code-box-demo .ant-picker { margin: 0 8px 12px 0; }</style> <style>
.code-box-demo .ant-picker { margin: 0 8px 12px 0; }
.ant-row-rtl .code-box-demo .ant-picker { margin: 0 0 12px 8px; }
</style>
## FAQ ## FAQ

View File

@ -68,7 +68,10 @@ import moment from 'moment';
| ----- | -------------------- | ------- | ------ | ----- | | ----- | -------------------- | ------- | ------ | ----- |
| order | 始末时间是否自动排序 | boolean | true | 4.1.0 | | order | 始末时间是否自动排序 | boolean | true | 4.1.0 |
<style>.code-box-demo .ant-picker { margin: 0 8px 12px 0; }</style> <style>
.code-box-demo .ant-picker { margin: 0 8px 12px 0; }
.ant-row-rtl .code-box-demo .ant-picker { margin: 0 0 12px 8px; }
</style>
## FAQ ## FAQ

View File

@ -18,6 +18,12 @@
} }
} }
&-expand {
.@{typography-prefix-cls}-rtl & {
float: left;
}
}
// Text input area // Text input area
&-edit-content { &-edit-content {
div& { div& {

View File

@ -60,6 +60,10 @@ Please refer to [Replace Moment.js](/docs/react/replace-moment).
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).
### Why modify props in mutable way not trigger component update?
antd use shallow compare of props to optimize performance. You should always pass new object when state update. Please ref [React's document](https://reactjs.org/docs/thinking-in-react.html)
### I set the `value` of `Input`/`Select`(etc.), and then it cannot be changed by user's action. ### I set the `value` of `Input`/`Select`(etc.), and then it cannot be changed by user's action.
Try `defaultValue` or `onChange` to change `value`, and please read [React's documentation](https://facebook.github.io/react/docs/forms.html#controlled-components). Try `defaultValue` or `onChange` to change `value`, and please read [React's documentation](https://facebook.github.io/react/docs/forms.html#controlled-components).

View File

@ -60,6 +60,10 @@ import { Menu, Breadcrumb, Icon } from 'antd';
`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)。
### 为什么修改组件传入的对象或数组属性组件不会更新?
antd 内部会对 props 进行浅比较实现性能优化。当状态变更,你总是应该传递一个新的对象。具体请参考[React 的文档](https://reactjs.org/docs/thinking-in-react.html)
### 当我设置了 `Input`/`Select` 等的 `value` 时它就无法修改了。 ### 当我设置了 `Input`/`Select` 等的 `value` 时它就无法修改了。
尝试使用 `defaultValue``onChange` 来改变 `value`,请参考 [React 的文档](https://reactjs.org/docs/forms.html#controlled-components)。 尝试使用 `defaultValue``onChange` 来改变 `value`,请参考 [React 的文档](https://reactjs.org/docs/forms.html#controlled-components)。

View File

@ -1,6 +1,6 @@
{ {
"name": "antd", "name": "antd",
"version": "4.2.0", "version": "4.2.2",
"description": "An enterprise-class UI design language and React components implementation", "description": "An enterprise-class UI design language and React components implementation",
"keywords": [ "keywords": [
"ant", "ant",
@ -50,9 +50,12 @@
"build": "npm run compile && npm run dist", "build": "npm run compile && npm run dist",
"bundlesize": "bundlesize", "bundlesize": "bundlesize",
"check-commit": "node ./scripts/check-commit", "check-commit": "node ./scripts/check-commit",
"prestart": "npm run version",
"precompile": "npm run version", "precompile": "npm run version",
"pretest": "npm run version", "pretest": "npm run version",
"predist": "npm run version", "predist": "npm run version",
"presite": "npm run version",
"color-less": "node ./scripts/generate-color-less",
"compile": "antd-tools run compile", "compile": "antd-tools run compile",
"changelog": "node ./scripts/print-changelog", "changelog": "node ./scripts/print-changelog",
"predeploy": "antd-tools run clean && npm run site && cp netlify.toml CNAME _site && cp -r .circleci/ .github/ _site && npm run site:test", "predeploy": "antd-tools run clean && npm run site && cp netlify.toml CNAME _site && cp -r .circleci/ .github/ _site && npm run site:test",
@ -73,14 +76,13 @@
"pre-publish": "npm run check-commit && npm run test-all", "pre-publish": "npm run check-commit && npm run test-all",
"prettier": "prettier -c --write '**/*'", "prettier": "prettier -c --write '**/*'",
"pretty-quick": "pretty-quick", "pretty-quick": "pretty-quick",
"pub": "antd-tools run pub", "pub": "npm run version && antd-tools run pub",
"postinstall": "npm run version",
"prepublishOnly": "antd-tools run guard", "prepublishOnly": "antd-tools run guard",
"site": "cross-env NODE_ICU_DATA=node_modules/full-icu concurrently \"bisheng build --ssr -c ./site/bisheng.config.js\" \"node ./scripts/generateColorLess.js\"", "site": "cross-env NODE_ICU_DATA=node_modules/full-icu concurrently \"bisheng build --ssr -c ./site/bisheng.config.js\" \"npm run color-less\"",
"sort": "npx sort-package-json", "sort": "npx sort-package-json",
"sort-api": "antd-tools run sort-api-table", "sort-api": "antd-tools run sort-api-table",
"start": "rimraf _site && mkdir _site && cross-env NODE_ENV=development concurrently \"node ./scripts/generateColorLess.js\" \"bisheng start -c ./site/bisheng.config.js\"", "start": "antd-tools run clean && cross-env NODE_ENV=development concurrently \"npm run color-less\" \"bisheng start -c ./site/bisheng.config.js\"",
"start:preact": "node ./scripts/generateColorLess.js && cross-env NODE_ENV=development REACT_ENV=preact bisheng start -c ./site/bisheng.config.js", "start:preact": "antd-tools run clean && cross-env NODE_ENV=development REACT_ENV=preact concurrently \"npm run color-less\" \"bisheng start -c ./site/bisheng.config.js\"",
"test": "jest --config .jest.js --no-cache", "test": "jest --config .jest.js --no-cache",
"test:update": "jest --config .jest.js --no-cache --update-snapshot", "test:update": "jest --config .jest.js --no-cache --update-snapshot",
"test-all": "./scripts/test-all.sh", "test-all": "./scripts/test-all.sh",
@ -103,7 +105,7 @@
"dependencies": { "dependencies": {
"@ant-design/css-animation": "^1.7.2", "@ant-design/css-animation": "^1.7.2",
"@ant-design/icons": "^4.1.0", "@ant-design/icons": "^4.1.0",
"@ant-design/react-slick": "~0.25.5", "@ant-design/react-slick": "~0.26.1",
"array-tree-filter": "^2.1.0", "array-tree-filter": "^2.1.0",
"classnames": "~2.2.6", "classnames": "~2.2.6",
"copy-to-clipboard": "^3.2.0", "copy-to-clipboard": "^3.2.0",

View File

@ -1,6 +1,7 @@
ul.anticons-list { ul.anticons-list {
margin: 10px 0; margin: 10px 0;
overflow: hidden; overflow: hidden;
direction: ltr;
list-style: none; list-style: none;
li { li {
position: relative; position: relative;
@ -17,6 +18,10 @@ ul.anticons-list {
border-radius: 4px; border-radius: 4px;
cursor: pointer; cursor: pointer;
transition: color 0.3s ease-in-out, background-color 0.3s ease-in-out; transition: color 0.3s ease-in-out, background-color 0.3s ease-in-out;
.rtl & {
margin: 3px 0;
padding: 10px 0 0;
}
.anticon { .anticon {
margin: 12px 0 8px; margin: 12px 0 8px;
font-size: 36px; font-size: 36px;