Merge pull request #20899 from ant-design/master

chore: Feature merge master
This commit is contained in:
二货机器人 2020-01-14 19:14:18 +08:00 committed by GitHub
commit e320904461
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
55 changed files with 876 additions and 284 deletions

View File

@ -15,6 +15,46 @@ timeline: true
---
## 4.0.0-rc.1
`2020-01-11`
- 🌟 Drawer Added `footer` and `footerStyle` properties. [#20690](https://github.com/ant-design/ant-design/pull/20690) [@DeanVanNiekerk](https://github.com/DeanVanNiekerk)
- 🌟 Switch Added `@switch-min-width` and `@switch-sm-min-width` less variables. [#20829](https://github.com/ant-design/ant-design/pull/20829) [@abdih](https://github.com/abdih)
- Table
- 🐞 Fix expanded icon not work when `expandRowByClick` is set. [#20808](https://github.com/ant-design/ant-design/pull/20808)
- 🐞 Fix expanded row width in scaled dom element and border style. [#20805](https://github.com/ant-design/ant-design/pull/20805)
- 🐞 Fix background color css priority too high to override user customize style. [#20794](https://github.com/ant-design/ant-design/pull/20794)
- 🐞 Fix `rowSelection` of `fixed` not work. [#20735](https://github.com/ant-design/ant-design/pull/20735)
- 🐞 Fix fixed columns in Chrome show the vertical scrollbar. [#20705](https://github.com/ant-design/ant-design/pull/20705)
- 🐞 Fix crash when columns with empty children. [#20703](https://github.com/ant-design/ant-design/pull/20703)
- 💄 Tweak Calendar basic style month drop-down box width and notice items of word order and card mode, select the size of the box. [#20790](https://github.com/ant-design/ant-design/pull/20790) [@xrkffgg](https://github.com/xrkffgg)
- DatePicker
- 💄 Optimize the `border-radius` of the rounded corners connection. [#20736](https://github.com/ant-design/ant-design/pull/20736)
- 🐞 Fix selected style overlap. [#20736](https://github.com/ant-design/ant-design/pull/20736)
- 🐞 Fix extra dividing line at the bottom. [#20736](https://github.com/ant-design/ant-design/pull/20736)
- 🐞 Fix button style for DatePicker's default range. [#20760](https://github.com/ant-design/ant-design/pull/20760) [@xrkffgg](https://github.com/xrkffgg)
- 🐞 Input not block user input when value is `undefined`. [#20783](https://github.com/ant-design/ant-design/pull/20783)
- 🐞 Fix Carousel card carousel orientation in left / right mode. [#20781](https://github.com/ant-design/ant-design/pull/20781) [@xrkffgg](https://github.com/xrkffgg)
- 🐞 Fix Grid responsive gutter under SSR initial value of `0`. [#20762](https://github.com/ant-design/ant-design/pull/20762)
- 🐞 Fix InputNumber, Select and other components icon size. [#20765](https://github.com/ant-design/ant-design/pull/20765)
- 🐞 Fix Badge `z-index` higher than Table fixed columns. [#20751](https://github.com/ant-design/ant-design/pull/20751)
- 💄 Tweak font family to be same as tailwindcss. [#20747](https://github.com/ant-design/ant-design/pull/20747)
- 🐞 Fix TextArea `autoSize` blink in FireFox. [#20737](https://github.com/ant-design/ant-design/pull/20737)
- 🐞 Fix Form.Item not keep error message sync when hit rule changed. [#20725](https://github.com/ant-design/ant-design/pull/20725)
- 🐞 Fix Form.Item add additional feedback style when `hasFeedback` is not set. [#20691](https://github.com/ant-design/ant-design/pull/20691)
- 🐞 Fix Cascader search bug when `fieldNames` is existed and label/value share same name. [#20720](https://github.com/ant-design/ant-design/pull/20720)
- 🐞 Fix Collapse background color with wrong less variable. [#20718](https://github.com/ant-design/ant-design/pull/20718) [@kuitos](https://github.com/kuitos)
- 🐞 Fix Slider's Tooltip not follow handle. [#20699](https://github.com/ant-design/ant-design/pull/20699)
- 🐞 Fix Card cover image get skretched. [#20701](https://github.com/ant-design/ant-design/pull/20701)
- 🐞 Fix Typography automatic overflow with `suffix` property. [#20689](https://github.com/ant-design/ant-design/pull/20689) [@zouxiaomingya](https://github.com/zouxiaomingya)
- 🐞 Fix AutoComplete with customize component with wrong style. [#20686](https://github.com/ant-design/ant-design/pull/20686)
- 🐞 Fix Input.Group to be partial to a pixel in Form. [#20681](https://github.com/ant-design/ant-design/pull/20681)
- TypeScript
- 🐞 Export Form interfaces. [3a1c5](https://github.com/ant-design/ant-design/commit/3a1c51010fecfa59f63f5e09027805a141e9ec11)
- 🐞 Fix Table types. [#20789](https://github.com/ant-design/ant-design/pull/20789)
- 🐞 Fix Table.Column and Table.ColumnGroup definition. [#20695](https://github.com/ant-design/ant-design/pull/20695)
## 4.0.0-rc.0
`2020-01-04`

View File

@ -15,6 +15,46 @@ timeline: true
---
## 4.0.0-rc.1
`2020-01-11`
- 🌟 Drawer 增加 `footer``footerStyle` 属性。[#20690](https://github.com/ant-design/ant-design/pull/20690) [@DeanVanNiekerk](https://github.com/DeanVanNiekerk)
- 🌟 Switch 增加 `@switch-min-width``@switch-sm-min-width` less 变量。[#20829](https://github.com/ant-design/ant-design/pull/20829) [@abdih](https://github.com/abdih)
- Table
- 🐞 修复在 `expandRowByClick` 下展开 Icon 点击失效。[#20808](https://github.com/ant-design/ant-design/pull/20808)
- 🐞 修复在缩放下的展开行宽度样式。[#20805](https://github.com/ant-design/ant-design/pull/20805)
- 🐞 修复背景色优先级高导致用户自定义样式被覆盖的问题。[#20794](https://github.com/ant-design/ant-design/pull/20794)
- 🐞 修复在 `rowSelection``fixed` 属性失效。[#20735](https://github.com/ant-design/ant-design/pull/20735)
- 🐞 修复固定列在 Chrome 下放大时出现纵向滚动条问题。[#20705](https://github.com/ant-design/ant-design/pull/20705)
- 🐞 修复 `columns` 为空时 Table 报错问题。[#20703](https://github.com/ant-design/ant-design/pull/20703)
- 💄 优化 Calendar 基本样式月份下拉框宽度、通知事项的文字顺序以及卡片模式,选择框的尺寸。[#20790](https://github.com/ant-design/ant-design/pull/20790) [@xrkffgg](https://github.com/xrkffgg)
- DatePicker
- 💄 优化圆角连接处 `border-radius`。[#20736](https://github.com/ant-design/ant-design/pull/20736)
- 🐞 修复选中样式重叠。[#20736](https://github.com/ant-design/ant-design/pull/20736)
- 🐞 修复底部额外分割线。[#20736](https://github.com/ant-design/ant-design/pull/20736)
- 🐞 修复预设范围的按钮样式。[#20760](https://github.com/ant-design/ant-design/pull/20760) [@xrkffgg](https://github.com/xrkffgg)
- 🐞 修复 Input 值为 `undefined` 时不能输入的问题。[#20783](https://github.com/ant-design/ant-design/pull/20783)
- 🐞 修复 Carousel 组件 left/right 模式下卡片轮播方向。[#20781](https://github.com/ant-design/ant-design/pull/20781) [@xrkffgg](https://github.com/xrkffgg)
- 🐞 修复 Grid 响应式 gutter 在 SSR 下初始值为 `0` zIndex 的问题。[#20762](https://github.com/ant-design/ant-design/pull/20762)
- 🐞 修复 InputNumber、Select、Table 等组件的图标大小问题。[#20765](https://github.com/ant-design/ant-design/pull/20765)
- 🐞 修复 Badge 在 Table 固定列中穿透的问题。[#20751](https://github.com/ant-design/ant-design/pull/20751)
- 💄 微调默认字体和 tailwindcss 一致。[#20747](https://github.com/ant-design/ant-design/pull/20747)
- 🐞 修复 TextArea `autoSize` 在 FireFox 浏览器下闪烁问题。[#20737](https://github.com/ant-design/ant-design/pull/20737)
- 🐞 修复 Form.Item 动态校验下错误提示不同步的问题。[#20725](https://github.com/ant-design/ant-design/pull/20725)
- 🐞 修复 Form.Item 不设置 `hasFeedback` 时校验,图标闪动问题。[#20691](https://github.com/ant-design/ant-design/pull/20691)
- 🐞 修复 Cascader `fieldNames``label``value` 共用一个值时搜索功能失效的问题。[#20720](https://github.com/ant-design/ant-design/pull/20720)
- 🐞 修复 Collapse 背景使用错误的 less 变量。[#20718](https://github.com/ant-design/ant-design/pull/20718) [@kuitos](https://github.com/kuitos)
- 🐞 修复 Slider 中 Tooltip 不跟随鼠标的问题。[#20699](https://github.com/ant-design/ant-design/pull/20699)
- 🐞 修复 Card 封面图片被拉伸的问题。[#20701](https://github.com/ant-design/ant-design/pull/20701)
- 🐞 修复 Typography 使用 `suffix` 属性时溢出问题。[#20689](https://github.com/ant-design/ant-design/pull/20689) [@zouxiaomingya](https://github.com/zouxiaomingya)
- 🐞 修复 AutoComplete 下使用 Input 时的样式错误。[#20686](https://github.com/ant-design/ant-design/pull/20686)
- 🐞 修复 Form 下 Input.Group 偏上一像素的问题。[#20681](https://github.com/ant-design/ant-design/pull/20681)
- TypeScript
- 🐞 导出 Form 接口类型。[3a1c5](https://github.com/ant-design/ant-design/commit/3a1c51010fecfa59f63f5e09027805a141e9ec11)
- 🐞 修复 Table 类型缺失。[#20789](https://github.com/ant-design/ant-design/pull/20789)
- 🐞 修复 Table.Column 及 Table.ColumnGroup 定义。[#20695](https://github.com/ant-design/ant-design/pull/20695)
## 4.0.0-rc.0
`2020-01-04`

View File

@ -1,52 +1,38 @@
# Node.js
# Build a general Node.js project with npm.
# Add steps that analyze code, save build artifacts, deploy, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/javascript
name: ant design
name: Ant Design
trigger:
batch: true
trigger: none
pr:
autoCancel: true
branches:
exclude:
- gh-pages
jobs:
- job: test_
pool:
vmImage: 'Ubuntu-16.04'
strategy:
matrix:
Lint:
TEST_TYPE: lint
dist-react@16:
REACT: 16
TEST_TYPE: test:dist
lib-react@16:
REACT: 16
TEST_TYPE: test:lib
es-react@16:
REACT: 16
TEST_TYPE: test:es
dom-react@16:
REACT: 16
TEST_TYPE: test:dom
node-react@16:
REACT: 16
TEST_TYPE: test:node
steps:
- checkout: self
fetchDepth: 1
clean: false
- task: NodeTool@0
inputs:
versionSpec: '10.x'
- script: npm install
displayName: install
- script: scripts/travis-script.sh
displayName: test
- task: PublishBuildArtifacts@1
# 主分支,并且运行成功
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
inputs:
pathtoPublish: './package-lock.json'
artifactName: lock
pool:
vmImage: 'ubuntu-latest'
stages:
- stage: site
jobs:
- job: Build_Site
steps:
- checkout: self
displayName: 'Checkout'
clean: true
fetchDepth: 1
- task: NodeTool@0
displayName: 'Install Node.js'
inputs:
versionSpec: '12.13.1'
- script: npm install
displayName: 'Install modules'
- script: npm run site
displayName: 'Build sites'
- script: ls -al _site/
displayName: 'List build'
- script: |
export DEPLOY_DOMAIN=https://preview-${SYSTEM_PULLREQUEST_PULLREQUESTNUMBER}-ant-design.surge.sh
echo "Deploy to $DEPLOY_DOMAIN"
npx surge --project ./_site --domain $DEPLOY_DOMAIN
curl -X POST -u ${ACCESS_TOKEN} -H "Accept: application/json" -H "Content-Type:application/json" https://api.github.com/repos/ant-design/ant-design/issues/${SYSTEM_PULLREQUEST_PULLREQUESTNUMBER}/comments -d '{ "body": "Preview deploy to '${DEPLOY_DOMAIN}'" }'
displayName: 'Deploy Site'

View File

@ -15,12 +15,11 @@
// Fixing https://github.com/ant-design/ant-design/issues/12978
// Fixing https://github.com/ant-design/ant-design/issues/20058
// Fixing https://github.com/ant-design/ant-design/issues/19972
// Fixing https://github.com/ant-design/ant-design/issues/12978
// Fixing https://github.com/ant-design/ant-design/issues/18107
// Fixing https://github.com/ant-design/ant-design/issues/13214
// It is a render problem of chrome, which is only happened in the codesandbox demo
// 0.001px solution works and I don't why
line-height: @line-height-base - 0.001;
line-height: @line-height-base;
.btn;
.btn-default;

View File

@ -1,8 +1,11 @@
// mixins for button
// ------------------------
.button-size(@height; @padding; @font-size; @border-radius) {
.button-size(@height; @padding-horizontal; @font-size; @border-radius) {
@padding-vertical: round((@height - @font-size * @line-height-base) / 2 * 10) / 10 -
@border-width-base;
height: @height;
padding: @padding;
padding: @padding-vertical @padding-horizontal;
font-size: @font-size;
border-radius: @border-radius;
}
@ -181,7 +184,7 @@
// size
&-lg > .@{btnClassName},
&-lg > span > .@{btnClassName} {
.button-size(@btn-height-lg; @btn-padding-lg; @btn-font-size-lg; 0);
.button-size(@btn-height-lg; @btn-padding-horizontal-lg; @btn-font-size-lg; 0);
line-height: @btn-height-lg - 2px;
}
&-lg > .@{btnClassName}.@{btnClassName}-icon-only {
@ -191,7 +194,7 @@
}
&-sm > .@{btnClassName},
&-sm > span > .@{btnClassName} {
.button-size(@btn-height-sm; @btn-padding-sm; @font-size-base; 0);
.button-size(@btn-height-sm; @btn-padding-horizontal-sm; @font-size-base; 0);
line-height: @btn-height-sm - 2px;
> .@{iconfont-css-prefix} {
font-size: @font-size-base;
@ -218,7 +221,9 @@
transition: all 0.3s @ease-in-out;
user-select: none;
touch-action: manipulation;
.button-size(@btn-height-base; @btn-padding-base; @font-size-base; @btn-border-radius-base);
.button-size(
@btn-height-base; @btn-padding-horizontal-base; @font-size-base; @btn-border-radius-base
);
> .@{iconfont-css-prefix} {
line-height: 1;
}
@ -242,10 +247,14 @@
}
}
&-lg {
.button-size(@btn-height-lg; @btn-padding-lg; @btn-font-size-lg; @btn-border-radius-base);
.button-size(
@btn-height-lg; @btn-padding-horizontal-lg; @btn-font-size-lg; @btn-border-radius-base
);
}
&-sm {
.button-size(@btn-height-sm; @btn-padding-sm; @btn-font-size-sm; @btn-border-radius-sm);
.button-size(
@btn-height-sm; @btn-padding-horizontal-sm; @btn-font-size-sm; @btn-border-radius-sm
);
}
}
// primary button style
@ -347,15 +356,15 @@
}
// round button
.btn-round(@btnClassName: btn) {
.button-size(@btn-circle-size; 0 @btn-circle-size / 2; @font-size-base; @btn-circle-size);
.button-size(@btn-circle-size; @btn-circle-size / 2; @font-size-base; @btn-circle-size);
&.@{btnClassName}-lg {
.button-size(
@btn-circle-size-lg; 0 @btn-circle-size-lg / 2; @btn-font-size-lg; @btn-circle-size-lg
@btn-circle-size-lg; @btn-circle-size-lg / 2; @btn-font-size-lg; @btn-circle-size-lg
);
}
&.@{btnClassName}-sm {
.button-size(
@btn-circle-size-sm; 0 @btn-circle-size-sm / 2; @font-size-base; @btn-circle-size-sm
@btn-circle-size-sm; @btn-circle-size-sm / 2; @font-size-base; @btn-circle-size-sm
);
}
}

View File

@ -155,6 +155,43 @@ exports[`renders ./components/dropdown/demo/dropdown-button.md correctly 1`] = `
</span>
</button>
</div>
<div
class="ant-btn-group ant-dropdown-button"
>
<button
class="ant-btn ant-btn-default"
type="button"
>
<span>
With Tooltip
</span>
</button>
<button
class="ant-btn ant-dropdown-trigger ant-btn-default"
type="button"
>
<span
aria-label="ellipsis"
class="anticon anticon-ellipsis"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="ellipsis"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
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"
/>
</svg>
</span>
</button>
</div>
<button
class="ant-btn ant-dropdown-trigger"
type="button"

View File

@ -14,7 +14,7 @@ title:
A button is on the left, and a related functional menu is on the right. You can set the icon property to modify the icon of right.
```jsx
import { Menu, Dropdown, Button, message } from 'antd';
import { Menu, Dropdown, Button, message, Tooltip } from 'antd';
import { DownOutlined, UserOutlined } from '@ant-design/icons';
function handleButtonClick(e) {
@ -55,6 +55,17 @@ ReactDOM.render(
<Dropdown.Button onClick={handleButtonClick} overlay={menu} disabled>
Dropdown
</Dropdown.Button>
<Dropdown.Button
overlay={menu}
buttonsRender={([leftButton, rightButton]) => [
<Tooltip title="tooltip" key="leftButton">
{leftButton}
</Tooltip>,
rightButton,
]}
>
With Tooltip
</Dropdown.Button>
<Dropdown overlay={menu}>
<Button>
Button <DownOutlined />

View File

@ -17,19 +17,18 @@ export interface DropdownButtonProps extends ButtonGroupProps, DropDownProps {
htmlType?: ButtonHTMLType;
disabled?: boolean;
onClick?: React.MouseEventHandler<HTMLButtonElement>;
/**
* @since 3.17.0
*/
icon?: React.ReactNode;
href?: string;
children?: React.ReactNode;
title?: string;
buttonsRender?: (buttons: React.ReactNode[]) => React.ReactNode[];
}
export default class DropdownButton extends React.Component<DropdownButtonProps, any> {
static defaultProps = {
placement: 'bottomRight' as DropDownProps['placement'],
type: 'default' as DropdownButtonType,
buttonsRender: (buttons: React.ReactNode[]) => buttons,
};
renderButton = ({
@ -54,6 +53,7 @@ export default class DropdownButton extends React.Component<DropdownButtonProps,
href,
icon = <EllipsisOutlined />,
title,
buttonsRender,
...restProps
} = this.props;
@ -67,25 +67,32 @@ export default class DropdownButton extends React.Component<DropdownButtonProps,
placement,
getPopupContainer: getPopupContainer || getContextPopupContainer,
} as DropDownProps;
if ('visible' in this.props) {
dropdownProps.visible = visible;
}
const leftButton = (
<Button
type={type}
disabled={disabled}
onClick={onClick}
htmlType={htmlType}
href={href}
title={title}
>
{children}
</Button>
);
const rightButton = <Button type={type}>{icon}</Button>;
const [leftButtonToRender, rightButtonToRender] = buttonsRender!([leftButton, rightButton]);
return (
<ButtonGroup {...restProps} className={classNames(prefixCls, className)}>
<Button
type={type}
disabled={disabled}
onClick={onClick}
htmlType={htmlType}
href={href}
title={title}
>
{children}
</Button>
<Dropdown {...dropdownProps}>
<Button type={type}>{icon}</Button>
</Dropdown>
{leftButtonToRender}
<Dropdown {...dropdownProps}>{rightButtonToRender}</Dropdown>
</ButtonGroup>
);
};

View File

@ -46,3 +46,4 @@ You should use [Menu](/components/menu/) as `overlay`. The menu items and divide
| visible | Whether the dropdown menu is currently visible | boolean | - | |
| onClick | The same as [Button](/components/button): called when you click the button on the left | Function | - | |
| onVisibleChange | Called when the visible state is changed | Function | - | |
| buttonsRender | custom buttons inside Dropdown.Button | `([buttons: ReactNode[]]) => ReactNode` | - | |

View File

@ -47,3 +47,4 @@ title: Dropdown
| visible | 菜单是否显示 | boolean | - | |
| onClick | 点击左侧按钮的回调,和 [Button](/components/button/) 一致 | Function | - | |
| onVisibleChange | 菜单显示状态改变时调用,参数为 visible | Function | - | |
| buttonsRender | 自定义左右两个按钮 | `([buttons: ReactNode[]]) => ReactNode` | - | |

View File

@ -42,6 +42,7 @@ const FormItemInput: React.FC<FormItemInputProps & FormItemInputMiscProps> = ({
prefixCls,
wrapperCol,
children,
help,
errors,
onDomErrorVisibleChange,
hasFeedback,
@ -63,7 +64,7 @@ const FormItemInput: React.FC<FormItemInputProps & FormItemInputMiscProps> = ({
onDomErrorVisibleChange(true);
}
forceUpdate({});
});
}, !!help);
const memoErrors = useMemo(
() => cacheErrors,

View File

@ -324,4 +324,24 @@ describe('Form', () => {
}
/* eslint-enable */
});
// https://github.com/ant-design/ant-design/issues/20813
it('should update help directly when provided', () => {
function App() {
const [message, updateMessage] = React.useState('');
return (
<Form>
<Form.Item label="hello" help={message}>
<Input />
</Form.Item>
<Button onClick={() => updateMessage('bamboo')} />
</Form>
);
}
const wrapper = mount(<App />);
wrapper.find('button').simulate('click');
expect(wrapper.find('.ant-form-item').first().hasClass('ant-form-item-with-help')).toBeTruthy();
expect(wrapper.find('.ant-form-item-explain').text()).toEqual('bamboo');
});
});

View File

@ -14,7 +14,7 @@ title:
- <Input />
- </Form.Item>
+ <Form.Item label="Field">
+ <Form.Item name="field" onStyle><Input /></Form.Item> // 直接包裹才会绑定表单
+ <Form.Item name="field" noStyle><Input /></Form.Item> // 直接包裹才会绑定表单
+ <span>description</span>
+ </Form.Item>
```
@ -38,7 +38,7 @@ This demo show how to use `Form.Item` with multiple controls. `<Form.Item name="
- <Input />
- </Form.Item>
+ <Form.Item label="Field">
+ <Form.Item name="field" onStyle><Input /></Form.Item> // that will bind input
+ <Form.Item name="field" noStyle><Input /></Form.Item> // that will bind input
+ <span>description</span>
+ </Form.Item>
```

View File

@ -20,6 +20,12 @@
}
}
.make-vertical-layout() {
.@{form-prefix-cls}-item .@{form-prefix-cls}-item-label {
.make-vertical-layout-label();
}
}
.@{form-prefix-cls}-vertical {
.@{form-item-prefix-cls} {
flex-direction: column;
@ -34,6 +40,7 @@
}
@media (max-width: @screen-xs-max) {
.make-vertical-layout();
.@{ant-prefix}-col-xs-24.@{form-item-prefix-cls}-label {
.make-vertical-layout-label();
}

View File

@ -10,6 +10,7 @@ type InternalNamePath = (string | number)[];
export function useCacheErrors(
errors: React.ReactNode[],
changeTrigger: (visible: boolean) => void,
directly: boolean,
): [boolean, React.ReactNode[]] {
const cacheRef = React.useRef({
errors,
@ -18,27 +19,35 @@ export function useCacheErrors(
const [, forceUpdate] = React.useState({});
const update = () => {
const prevVisible = cacheRef.current.visible;
const newVisible = !!errors.length;
const prevErrors = cacheRef.current.errors;
cacheRef.current.errors = errors;
cacheRef.current.visible = newVisible;
if (prevVisible !== newVisible) {
changeTrigger(newVisible);
} else if (
prevErrors.length !== errors.length ||
prevErrors.some((prevErr, index) => prevErr !== errors[index])
) {
forceUpdate({});
}
};
React.useEffect(() => {
const timeout = setTimeout(() => {
const prevVisible = cacheRef.current.visible;
const newVisible = !!errors.length;
const prevErrors = cacheRef.current.errors;
cacheRef.current.errors = errors;
cacheRef.current.visible = newVisible;
if (prevVisible !== newVisible) {
changeTrigger(newVisible);
} else if (
prevErrors.length !== errors.length ||
prevErrors.some((prevErr, index) => prevErr !== errors[index])
) {
forceUpdate({});
}
}, 10);
return () => clearTimeout(timeout);
if (!directly) {
const timeout = setTimeout(update, 10);
return () => clearTimeout(timeout);
}
}, [errors]);
if (directly) {
update();
}
return [cacheRef.current.visible, cacheRef.current.errors];
}

View File

@ -25,6 +25,7 @@ interface BasicProps {
style?: object;
disabled?: boolean;
direction?: any;
focused?: boolean;
}
/**
@ -65,34 +66,44 @@ class ClearableLabeledInput extends React.Component<ClearableInputProps> {
}
renderLabeledIcon(prefixCls: string, element: React.ReactElement<any>) {
const props = this.props;
const suffix = this.renderSuffix(prefixCls);
if (!hasPrefixSuffix(props)) {
const {
focused,
value,
prefix,
className,
size,
suffix,
disabled,
allowClear,
direction,
style,
} = this.props;
const suffixNode = this.renderSuffix(prefixCls);
if (!hasPrefixSuffix(this.props)) {
return React.cloneElement(element, {
value: props.value,
value,
});
}
const prefix = props.prefix ? (
<span className={`${prefixCls}-prefix`}>{props.prefix}</span>
) : null;
const prefixNode = prefix ? <span className={`${prefixCls}-prefix`}>{prefix}</span> : null;
const affixWrapperCls = classNames(props.className, `${prefixCls}-affix-wrapper`, {
[`${prefixCls}-affix-wrapper-sm`]: props.size === 'small',
[`${prefixCls}-affix-wrapper-lg`]: props.size === 'large',
[`${prefixCls}-affix-wrapper-input-with-clear-btn`]:
props.suffix && props.allowClear && this.props.value,
[`${prefixCls}-affix-wrapper-rtl`]: props.direction === 'rtl',
const affixWrapperCls = classNames(className, `${prefixCls}-affix-wrapper`, {
[`${prefixCls}-affix-wrapper-focused`]: focused,
[`${prefixCls}-affix-wrapper-disabled`]: disabled,
[`${prefixCls}-affix-wrapper-sm`]: size === 'small',
[`${prefixCls}-affix-wrapper-lg`]: size === 'large',
[`${prefixCls}-affix-wrapper-input-with-clear-btn`]: suffix && allowClear && value,
[`${prefixCls}-affix-wrapper-rtl`]: direction === 'rtl',
});
return (
<span className={affixWrapperCls} style={props.style}>
{prefix}
<span className={affixWrapperCls} style={style}>
{prefixNode}
{React.cloneElement(element, {
style: null,
value: props.value,
className: getInputClassName(prefixCls, props.size, props.disabled),
value,
className: getInputClassName(prefixCls, size, disabled),
})}
{suffix}
{suffixNode}
</span>
);
}

View File

@ -72,6 +72,7 @@ export function getInputClassName(
export interface InputState {
value: any;
focused: boolean;
/** `value` from prev props */
prevValue: any;
}
@ -102,6 +103,7 @@ class Input extends React.Component<InputProps, InputState> {
const value = typeof props.value === 'undefined' ? props.defaultValue : props.value;
this.state = {
value,
focused: false,
// eslint-disable-next-line react/no-unused-state
prevValue: props.value,
};
@ -160,6 +162,22 @@ class Input extends React.Component<InputProps, InputState> {
this.input = input;
};
onFocus: React.FocusEventHandler<HTMLInputElement> = e => {
const { onFocus } = this.props;
this.setState({ focused: true });
if (onFocus) {
onFocus(e);
}
};
onBlur: React.FocusEventHandler<HTMLInputElement> = e => {
const { onBlur } = this.props;
this.setState({ focused: false });
if (onBlur) {
onBlur(e);
}
};
setValue(value: string, callback?: () => void) {
if (this.props.value === undefined) {
this.setState({ value }, callback);
@ -194,6 +212,8 @@ class Input extends React.Component<InputProps, InputState> {
<input
{...otherProps}
onChange={this.handleChange}
onFocus={this.onFocus}
onBlur={this.onBlur}
onKeyDown={this.handleKeyDown}
className={classNames(
getInputClassName(prefixCls, customizeSize || size, disabled, this.direction),
@ -235,7 +255,7 @@ class Input extends React.Component<InputProps, InputState> {
};
renderComponent = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
const { value } = this.state;
const { value, focused } = this.state;
const { prefixCls: customizePrefixCls } = this.props;
const prefixCls = getPrefixCls('input', customizePrefixCls);
this.direction = direction;
@ -251,6 +271,7 @@ class Input extends React.Component<InputProps, InputState> {
handleReset={this.handleReset}
ref={this.saveClearableInput}
direction={direction}
focused={focused}
/>
)}
</SizeContext.Consumer>

View File

@ -68,11 +68,14 @@ exports[`Input.Password should change type when click 1`] = `
<input
action="click"
className="ant-input ant-input-password"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="password"
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
prefixCls="ant-input"
@ -92,7 +95,9 @@ exports[`Input.Password should change type when click 1`] = `
<input
action="click"
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
style={null}
type="password"
@ -235,11 +240,14 @@ exports[`Input.Password should change type when click 2`] = `
<input
action="click"
className="ant-input ant-input-password"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="text"
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
prefixCls="ant-input"
@ -259,7 +267,9 @@ exports[`Input.Password should change type when click 2`] = `
<input
action="click"
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
style={null}
type="text"
@ -386,11 +396,14 @@ exports[`Input.Password should change type when click 3`] = `
<input
action="click"
className="ant-input ant-input-password"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="password"
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
prefixCls="ant-input"
@ -410,7 +423,9 @@ exports[`Input.Password should change type when click 3`] = `
<input
action="click"
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
style={null}
type="password"

View File

@ -1782,6 +1782,28 @@ exports[`renders ./components/input/demo/presuffix.md correctly 1`] = `
RMB
</span>
</span>
<br />
<br />
<span
class="ant-input-affix-wrapper ant-input-affix-wrapper-disabled"
>
<span
class="ant-input-prefix"
>
</span>
<input
class="ant-input ant-input-disabled"
disabled=""
type="text"
value=""
/>
<span
class="ant-input-suffix"
>
RMB
</span>
</span>
</div>
`;

View File

@ -10,11 +10,14 @@ exports[`Input allowClear should change type when click 1`] = `
element={
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="text"
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
prefixCls="ant-input"
@ -26,7 +29,9 @@ exports[`Input allowClear should change type when click 1`] = `
>
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
style={null}
type="text"
@ -133,11 +138,14 @@ exports[`Input allowClear should change type when click 2`] = `
element={
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="text"
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
prefixCls="ant-input"
@ -149,7 +157,9 @@ exports[`Input allowClear should change type when click 2`] = `
>
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
style={null}
type="text"
@ -175,11 +185,14 @@ exports[`Input allowClear should not show icon if defaultValue is undefined, nul
element={
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="text"
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
prefixCls="ant-input"
@ -191,7 +204,9 @@ exports[`Input allowClear should not show icon if defaultValue is undefined, nul
>
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
style={null}
type="text"
@ -215,11 +230,14 @@ exports[`Input allowClear should not show icon if defaultValue is undefined, nul
element={
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="text"
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
prefixCls="ant-input"
@ -231,7 +249,9 @@ exports[`Input allowClear should not show icon if defaultValue is undefined, nul
>
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
style={null}
type="text"
@ -257,11 +277,14 @@ exports[`Input allowClear should not show icon if defaultValue is undefined, nul
element={
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="text"
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
prefixCls="ant-input"
@ -273,7 +296,9 @@ exports[`Input allowClear should not show icon if defaultValue is undefined, nul
>
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
style={null}
type="text"
@ -298,12 +323,15 @@ exports[`Input allowClear should not show icon if value is undefined, null or em
element={
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="text"
value={null}
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
prefixCls="ant-input"
@ -315,7 +343,9 @@ exports[`Input allowClear should not show icon if value is undefined, null or em
>
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
style={null}
type="text"
@ -339,11 +369,14 @@ exports[`Input allowClear should not show icon if value is undefined, null or em
element={
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="text"
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
prefixCls="ant-input"
@ -355,7 +388,9 @@ exports[`Input allowClear should not show icon if value is undefined, null or em
>
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
style={null}
type="text"
@ -380,12 +415,15 @@ exports[`Input allowClear should not show icon if value is undefined, null or em
element={
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="text"
value=""
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
prefixCls="ant-input"
@ -397,7 +435,9 @@ exports[`Input allowClear should not show icon if value is undefined, null or em
>
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
style={null}
type="text"
@ -435,11 +475,14 @@ exports[`Input should support maxLength 1`] = `
<input
className="ant-input"
maxLength={3}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="text"
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
maxLength={3}
@ -450,7 +493,9 @@ exports[`Input should support maxLength 1`] = `
<input
className="ant-input"
maxLength={3}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="text"
value=""
@ -485,11 +530,14 @@ exports[`Input.Search should support suffix 1`] = `
element={
<input
className="ant-input ant-input-search"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
type="text"
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
onChange={[Function]}
@ -512,7 +560,9 @@ exports[`Input.Search should support suffix 1`] = `
>
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
style={null}
type="text"

View File

@ -28,11 +28,14 @@ ReactDOM.render(
</Tooltip>
}
/>
<br />
<br />
<Input prefix="¥" suffix="RMB" />
<br />
<br />
<Input prefix="¥" suffix="RMB" disabled />
</div>,
mountNode,
);

View File

@ -0,0 +1,50 @@
@import './index';
@import './mixin';
@input-affix-margin: 4px;
.@{ant-prefix}-input {
&-affix-wrapper {
.input();
display: inline-flex;
> .@{ant-prefix}-input {
padding: 0;
border: none;
outline: none;
&:focus {
box-shadow: none;
}
}
.@{ant-prefix}-input-clear-icon {
margin: 0 @input-affix-margin;
vertical-align: -1px;
}
}
&-prefix,
&-suffix {
flex: none;
}
&-prefix {
margin-right: @input-affix-margin;
}
&-suffix {
margin-left: @input-affix-margin;
}
// ======================== RTL ========================
&-affix-wrapper-rtl {
.@{ant-prefix}-input-prefix {
margin: 0 0 0 @input-affix-margin;
}
.@{ant-prefix}-input-suffix {
margin: 0 @input-affix-margin 0 0;
}
}
}

View File

@ -1,6 +1,7 @@
@import '../../style/themes/index';
@import '../../style/mixins/index';
@import './mixin';
@import './affix';
// Input styles
.@{ant-prefix}-input {
@ -26,17 +27,6 @@
}
}
// Input with affix: prefix or suffix
.@{ant-prefix}-input-affix-wrapper {
.reset-component;
.input-affix-wrapper(~'@{ant-prefix}-input');
// https://github.com/ant-design/ant-design/issues/6144
.@{ant-prefix}-input {
min-height: 100%; // use min-height, assume that no smaller height to override
}
}
.@{ant-prefix}-input-password-icon {
color: @text-color-secondary;
cursor: pointer;

View File

@ -3,18 +3,15 @@
@input-rtl-cls: ~'@{ant-prefix}-input-rtl';
@input-affix-width: 19px;
@input-affix-with-clear-btn-width: 38px;
// size mixins for input
.input-lg() {
height: @input-height-lg;
padding: @input-padding-vertical-lg @input-padding-horizontal-lg;
font-size: @font-size-lg;
}
.input-sm() {
height: @input-height-sm;
padding: @input-padding-vertical-sm @input-padding-horizontal-sm;
}
@ -64,7 +61,6 @@
position: relative;
display: inline-block;
width: 100%;
height: @input-height-base;
padding: @input-padding-vertical-base @input-padding-horizontal-base;
color: @input-color;
font-size: @font-size-base;
@ -80,7 +76,8 @@
.hover();
}
&:focus {
&:focus,
&-focused {
.active();
}
@ -423,101 +420,6 @@
}
}
.input-affix-wrapper(@inputClass) {
position: relative;
display: inline-block;
width: 100%;
text-align: start;
&:hover .@{inputClass}:not(.@{inputClass}-disabled) {
.hover();
}
.@{inputClass} {
position: relative;
text-align: inherit;
}
// Should not break align of icon & text
// https://github.com/ant-design/ant-design/issues/18087
// https://github.com/ant-design/ant-design/issues/17414
// https://github.com/ant-design/ant-design/pull/17684
// https://codesandbox.io/embed/pensive-paper-di2wk
// https://codesandbox.io/embed/nifty-benz-gb7ml
.@{inputClass}-prefix,
.@{inputClass}-suffix {
position: absolute;
top: 50%;
z-index: 2;
display: flex;
align-items: center;
color: @input-icon-color;
line-height: 0;
transform: translateY(-50%);
:not(.anticon) {
line-height: @line-height-base;
}
}
.@{inputClass}-disabled ~ .@{inputClass}-suffix {
.anticon {
color: @disabled-color;
cursor: not-allowed;
}
}
.@{inputClass}-prefix {
left: @input-padding-horizontal-base + 1px;
.@{inputClass}-affix-wrapper-rtl& {
right: @input-padding-horizontal-base + 1px;
left: auto;
}
}
.@{inputClass}-suffix {
right: @input-padding-horizontal-base + 1px;
.@{inputClass}-affix-wrapper-rtl& {
right: auto;
left: @input-padding-horizontal-base + 1px;
}
}
.@{inputClass}:not(:first-child) {
padding-left: @input-padding-horizontal-base + @input-affix-width;
}
.@{inputClass}:not(:last-child) {
padding-right: @input-padding-horizontal-base + @input-affix-width;
}
// Needed to change priority of classes in rtl direction (last-child comes before first-child)
.@{inputClass}-affix-wrapper-rtl& .@{inputClass}:not(:last-child) {
padding-right: @input-padding-horizontal-base;
padding-left: @input-padding-horizontal-base + @input-affix-width;
}
.@{inputClass}-affix-wrapper-rtl& .@{inputClass}:not(:first-child) {
padding-right: @input-padding-horizontal-base + @input-affix-width;
padding-left: @input-padding-horizontal-base;
}
&.@{inputClass}-affix-wrapper-input-with-clear-btn .@{inputClass}:not(:last-child) {
padding-right: @input-padding-horizontal-base + @input-affix-with-clear-btn-width;
.@{inputClass}-affix-wrapper-rtl& {
padding-right: @input-padding-horizontal-base;
padding-left: @input-padding-horizontal-base + @input-affix-with-clear-btn-width;
}
}
&.@{inputClass}-affix-wrapper-textarea-with-clear-btn .@{inputClass} {
padding-right: 22px;
}
}
.clear-icon() {
color: @disabled-color;
font-size: @font-size-sm;

View File

@ -55,7 +55,6 @@
}
&-notice.move-up-leave.move-up-leave-active {
overflow: hidden;
animation-name: MessageMoveOut;
animation-duration: 0.3s;
}

View File

@ -72,6 +72,9 @@
// ======================= Placeholder =======================
&-selection-placeholder {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
opacity: 0.4;
}

View File

@ -1,7 +1,10 @@
@import './index';
@select-selection-height: @input-height-base - @input-padding-vertical-base * 2;
@select-multiple-padding: @input-padding-vertical-base - @border-width-base;
@select-multiple-padding: @input-padding-vertical-base;
@select-multiple-item-margin-vertical: round(
(@select-selection-height - @font-size-base * @line-height-base) / 2 * 10
) / 10;
/**
* Do not merge `height` & `line-height` under style with `selection` & `search`,
@ -18,7 +21,7 @@
flex-wrap: wrap;
align-items: center;
// Multiple is little different that horizontal is follow the vertical
padding: 0 @select-multiple-padding @select-multiple-padding;
padding: @select-multiple-padding @select-multiple-padding;
.@{select-prefix-cls}-show-search& {
cursor: text;
@ -34,15 +37,13 @@
max-width: 100%;
height: @select-selection-height;
margin-top: @select-multiple-padding;
margin-top: -@select-multiple-item-margin-vertical;
margin-right: @input-padding-vertical-base;
margin-bottom: -@select-multiple-item-margin-vertical;
padding: 0 (@padding-xs / 2) 0 @padding-xs;
line-height: @select-selection-height - @border-width-base * 2;
background: @select-selection-item-bg;
border: 1px solid @select-selection-item-border-color;
// strange align fix for chrome but works
// https://gw.alipayobjects.com/zos/rmsportal/VFTfKXJuogBAXcvfAUWJ.gif
border-top-width: @border-width-base + 0.4px;
border-radius: @border-radius-base;
cursor: default;
transition: font-size 0.3s, line-height 0.3s, height 0.3s;
@ -97,15 +98,13 @@
&-input,
&-mirror {
height: @select-selection-height;
font-family: @font-family;
line-height: @select-selection-height - @border-width-base * 2;
line-height: @line-height-base;
transition: all 0.3s;
}
&-input {
width: 100%;
margin-top: @select-multiple-padding;
}
&-mirror {
@ -127,13 +126,14 @@
.@{select-prefix-cls}-selection-placeholder {
position: absolute;
top: 0;
left: @control-padding-horizontal;
right: @input-padding-horizontal;
left: @input-padding-horizontal;
height: @select-height-without-border;
line-height: @select-height-without-border;
transition: all 0.3s;
.@{select-prefix-cls}-rtl& {
right: @control-padding-horizontal;
right: @input-padding-horizontal;
left: auto;
}
}
@ -171,4 +171,15 @@
.select-size('lg', @input-height-lg);
.select-size('sm', @input-height-sm);
// Size small need additional set padding
&.@{select-prefix-cls}-sm {
.@{select-prefix-cls}-selection-placeholder {
left: @input-padding-horizontal-sm;
.@{select-prefix-cls}-rtl& {
right: @input-padding-horizontal-sm;
}
}
}
}

View File

@ -4,7 +4,6 @@
// ========================= Selector =========================
.@{select-prefix-cls}-selector {
display: flex;
border-top-width: @border-width-base + 0.375px;
.@{select-prefix-cls}-selection-search {
position: absolute;
@ -59,7 +58,7 @@
padding-right: @font-size-base;
.@{select-prefix-cls}-rtl& {
padding-right: @input-padding-horizontal-base;
padding-right: 0;
padding-left: @font-size-base;
}
}
@ -158,11 +157,19 @@
// With arrow should provides `padding-right` to show the arrow
&.@{select-prefix-cls}-show-arrow .@{select-prefix-cls}-selection-search {
right: @input-padding-horizontal-sm + @font-size-base * 1.5;
.@{select-prefix-cls}-rtl& {
right: 0;
}
}
&.@{select-prefix-cls}-show-arrow .@{select-prefix-cls}-selection-item,
&.@{select-prefix-cls}-show-arrow .@{select-prefix-cls}-selection-placeholder {
padding-right: @font-size-base * 1.5;
.@{select-prefix-cls}-rtl& {
padding-right: 0;
}
}
}
}

View File

@ -3,6 +3,10 @@
// Placeholder text
.placeholder(@color: @input-placeholder-color) {
// Firefox
&::-moz-placeholder {
opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526
}
&::placeholder {
color: @color;
}

View File

@ -71,6 +71,7 @@
// https://github.com/ant-design/ant-design/issues/20210
@line-height-base: 1.5715;
@border-radius-base: 2px;
@border-radius-sm: @border-radius-base;
// vertical paddings
@padding-lg: 24px; // containers
@ -177,11 +178,11 @@
@btn-default-ghost-bg: transparent;
@btn-default-ghost-border: @component-background;
@btn-padding-base: 0 @padding-md - 1px;
@btn-font-size-lg: @font-size-lg;
@btn-font-size-sm: @font-size-base;
@btn-padding-lg: @btn-padding-base;
@btn-padding-sm: 0 @padding-xs - 1px;
@btn-padding-horizontal-base: @padding-md - 1px;
@btn-padding-horizontal-lg: @btn-padding-horizontal-base;
@btn-padding-horizontal-sm: @padding-xs - 1px;
@btn-height-base: 32px;
@btn-height-lg: 40px;
@ -339,9 +340,13 @@
@input-padding-horizontal-base: @input-padding-horizontal;
@input-padding-horizontal-sm: @control-padding-horizontal-sm - 1px;
@input-padding-horizontal-lg: @input-padding-horizontal;
@input-padding-vertical-base: 4px;
@input-padding-vertical-sm: 1px;
@input-padding-vertical-lg: 6px;
@input-padding-vertical-base: round(
(@input-height-base - @font-size-base * @line-height-base) / 2 * 10
) / 10 - @border-width-base;
@input-padding-vertical-sm: round((@input-height-sm - @font-size-base * @line-height-base) / 2 * 10) /
10 - @border-width-base;
@input-padding-vertical-lg: round((@input-height-lg - @font-size-lg * @line-height-base) / 2 * 10) /
10 - @border-width-base;
@input-placeholder-color: hsv(0, 0, 75%);
@input-color: @text-color;
@input-icon-color: @input-color;

View File

@ -1104,4 +1104,71 @@ describe('Table.filter', () => {
mount(<TestTable />);
});
// https://github.com/ant-design/ant-design/issues/20854
it('Not cache for onChange state', () => {
const onChange = jest.fn();
const wrapper = mount(
<Table
columns={[
{
title: 'Name',
dataIndex: 'name',
sorter: true,
},
{
title: 'Gender',
dataIndex: 'gender',
filters: [
{ text: 'Male', value: 'male' },
{ text: 'Female', value: 'female' },
],
},
]}
dataSource={[]}
onChange={onChange}
/>,
);
// Sort it
wrapper.find('.ant-table-column-sorters').simulate('click');
expect(onChange).toHaveBeenCalledWith(
expect.anything(),
{
gender: null,
},
expect.objectContaining({
column: {
dataIndex: 'name',
sorter: true,
title: 'Name',
},
}),
expect.anything(),
);
// Filter it
onChange.mockReset();
wrapper.find('span.ant-dropdown-trigger').simulate('click', nativeEvent);
wrapper
.find('.ant-dropdown-menu-item')
.first()
.simulate('click');
wrapper.find('.ant-table-filter-dropdown-link.confirm').simulate('click');
expect(onChange).toHaveBeenCalledWith(
expect.anything(),
{
gender: ['male'],
},
expect.objectContaining({
column: {
dataIndex: 'name',
sorter: true,
title: 'Name',
},
}),
expect.anything(),
);
});
});

View File

@ -39,6 +39,7 @@ exports[`Table.expand click to expand 1`] = `
>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="1"
>
<td
class="ant-table-cell ant-table-cell-with-append"
@ -56,6 +57,7 @@ exports[`Table.expand click to expand 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-1"
data-row-key="1"
>
<td
class="ant-table-cell ant-table-cell-with-append"
@ -192,6 +194,7 @@ exports[`Table.expand should support expandIconColumnIndex 1`] = `
>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="1"
>
<td
class="ant-table-cell ant-table-cell-with-append"

View File

@ -108,6 +108,7 @@ exports[`Table.filter renders custom filter icon as string correctly 1`] = `
>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="0"
>
<td
class="ant-table-cell"
@ -117,6 +118,7 @@ exports[`Table.filter renders custom filter icon as string correctly 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="1"
>
<td
class="ant-table-cell"
@ -126,6 +128,7 @@ exports[`Table.filter renders custom filter icon as string correctly 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="2"
>
<td
class="ant-table-cell"
@ -135,6 +138,7 @@ exports[`Table.filter renders custom filter icon as string correctly 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="3"
>
<td
class="ant-table-cell"
@ -250,6 +254,7 @@ exports[`Table.filter renders custom filter icon with right Tooltip title 1`] =
>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="0"
>
<td
class="ant-table-cell"
@ -259,6 +264,7 @@ exports[`Table.filter renders custom filter icon with right Tooltip title 1`] =
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="1"
>
<td
class="ant-table-cell"
@ -268,6 +274,7 @@ exports[`Table.filter renders custom filter icon with right Tooltip title 1`] =
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="2"
>
<td
class="ant-table-cell"
@ -277,6 +284,7 @@ exports[`Table.filter renders custom filter icon with right Tooltip title 1`] =
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="3"
>
<td
class="ant-table-cell"
@ -371,6 +379,7 @@ exports[`Table.filter renders filter correctly 1`] = `
>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="0"
>
<td
class="ant-table-cell"
@ -380,6 +389,7 @@ exports[`Table.filter renders filter correctly 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="1"
>
<td
class="ant-table-cell"
@ -389,6 +399,7 @@ exports[`Table.filter renders filter correctly 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="2"
>
<td
class="ant-table-cell"
@ -398,6 +409,7 @@ exports[`Table.filter renders filter correctly 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="3"
>
<td
class="ant-table-cell"
@ -784,6 +796,7 @@ exports[`Table.filter should support getPopupContainer 1`] = `
>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="0"
>
<td
class="ant-table-cell"
@ -793,6 +806,7 @@ exports[`Table.filter should support getPopupContainer 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="1"
>
<td
class="ant-table-cell"
@ -802,6 +816,7 @@ exports[`Table.filter should support getPopupContainer 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="2"
>
<td
class="ant-table-cell"
@ -811,6 +826,7 @@ exports[`Table.filter should support getPopupContainer 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="3"
>
<td
class="ant-table-cell"
@ -1005,6 +1021,7 @@ exports[`Table.filter should support getPopupContainer from ConfigProvider 1`] =
>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="0"
>
<td
class="ant-table-cell"
@ -1014,6 +1031,7 @@ exports[`Table.filter should support getPopupContainer from ConfigProvider 1`] =
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="1"
>
<td
class="ant-table-cell"
@ -1023,6 +1041,7 @@ exports[`Table.filter should support getPopupContainer from ConfigProvider 1`] =
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="2"
>
<td
class="ant-table-cell"
@ -1032,6 +1051,7 @@ exports[`Table.filter should support getPopupContainer from ConfigProvider 1`] =
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="3"
>
<td
class="ant-table-cell"

View File

@ -39,6 +39,7 @@ exports[`Table.pagination Accepts pagination as true 1`] = `
>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="0"
>
<td
class="ant-table-cell"
@ -48,6 +49,7 @@ exports[`Table.pagination Accepts pagination as true 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="1"
>
<td
class="ant-table-cell"
@ -57,6 +59,7 @@ exports[`Table.pagination Accepts pagination as true 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="2"
>
<td
class="ant-table-cell"
@ -66,6 +69,7 @@ exports[`Table.pagination Accepts pagination as true 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="3"
>
<td
class="ant-table-cell"
@ -196,6 +200,7 @@ exports[`Table.pagination renders pagination correctly 1`] = `
>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="0"
>
<td
class="ant-table-cell"
@ -205,6 +210,7 @@ exports[`Table.pagination renders pagination correctly 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="1"
>
<td
class="ant-table-cell"

View File

@ -66,6 +66,7 @@ exports[`Table.rowSelection fix selection column on the left 1`] = `
>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="0"
>
<td
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left ant-table-cell-fix-left-last"
@ -95,6 +96,7 @@ exports[`Table.rowSelection fix selection column on the left 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="1"
>
<td
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left ant-table-cell-fix-left-last"
@ -124,6 +126,7 @@ exports[`Table.rowSelection fix selection column on the left 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="2"
>
<td
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left ant-table-cell-fix-left-last"
@ -153,6 +156,7 @@ exports[`Table.rowSelection fix selection column on the left 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="3"
>
<td
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left ant-table-cell-fix-left-last"
@ -331,6 +335,7 @@ exports[`Table.rowSelection fix selection column on the left when any other colu
>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="0"
>
<td
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left"
@ -361,6 +366,7 @@ exports[`Table.rowSelection fix selection column on the left when any other colu
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="1"
>
<td
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left"
@ -391,6 +397,7 @@ exports[`Table.rowSelection fix selection column on the left when any other colu
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="2"
>
<td
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left"
@ -421,6 +428,7 @@ exports[`Table.rowSelection fix selection column on the left when any other colu
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="3"
>
<td
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left"
@ -625,6 +633,7 @@ exports[`Table.rowSelection use column as selection column when key is \`selecti
>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="0"
>
<td
class="ant-table-cell ant-table-selection-column"
@ -653,6 +662,7 @@ exports[`Table.rowSelection use column as selection column when key is \`selecti
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="1"
>
<td
class="ant-table-cell ant-table-selection-column"
@ -681,6 +691,7 @@ exports[`Table.rowSelection use column as selection column when key is \`selecti
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="2"
>
<td
class="ant-table-cell ant-table-selection-column"
@ -709,6 +720,7 @@ exports[`Table.rowSelection use column as selection column when key is \`selecti
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="3"
>
<td
class="ant-table-cell ant-table-selection-column"

View File

@ -159,6 +159,7 @@ exports[`Table.sorter should support defaultOrder in Column 1`] = `
>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="1"
>
<td
class="ant-table-cell"

View File

@ -60,6 +60,7 @@ exports[`Table renders JSX correctly 1`] = `
>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="1"
>
<td
class="ant-table-cell"
@ -79,6 +80,7 @@ exports[`Table renders JSX correctly 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="2"
>
<td
class="ant-table-cell"

File diff suppressed because it is too large Load Diff

View File

@ -208,18 +208,16 @@ function useFilter<RecordType>({
onFilterChange(generateFilterInfo(newFilterStates), newFilterStates);
};
const transformColumns = React.useMemo(() => {
return (innerColumns: ColumnsType<RecordType>) =>
injectFilter(
prefixCls,
dropdownPrefixCls,
innerColumns,
mergedFilterStates,
triggerFilter,
getPopupContainer,
tableLocale,
);
}, [mergedFilterStates]);
const transformColumns = (innerColumns: ColumnsType<RecordType>) =>
injectFilter(
prefixCls,
dropdownPrefixCls,
innerColumns,
mergedFilterStates,
triggerFilter,
getPopupContainer,
tableLocale,
);
return [transformColumns, mergedFilterStates, getFilters];
}

View File

@ -362,11 +362,8 @@ export default function useFilterSorter<RecordType>({
onSorterChange(generateSorterInfo(newSorterStates), newSorterStates);
}
const transformColumns = React.useCallback(
(innerColumns: ColumnsType<RecordType>) =>
injectSorter(prefixCls, innerColumns, mergedSorterStates, triggerSorter, sortDirections),
[mergedSorterStates],
);
const transformColumns = (innerColumns: ColumnsType<RecordType>) =>
injectSorter(prefixCls, innerColumns, mergedSorterStates, triggerSorter, sortDirections);
const getSorters = () => {
return generateSorterInfo(mergedSorterStates);

View File

@ -243,4 +243,14 @@ describe('Tooltip', () => {
expect(onVisibleChange).toHaveBeenCalledWith(false);
expect(wrapper.instance().tooltip.props.visible).toBe(false);
});
// https://github.com/ant-design/ant-design/issues/20891
it('should display zero', async () => {
const wrapper = mount(
<Tooltip title={0} visible>
<div />
</Tooltip>,
);
expect(wrapper.find('.ant-tooltip-inner').getDOMNode().innerHTML).toBe('0');
});
});

View File

@ -224,7 +224,15 @@ class Tooltip extends React.Component<TooltipProps, any> {
isNoTitle() {
const { title, overlay } = this.props;
return !title && !overlay; // overlay for old version compatibility
return !title && !overlay && title !== 0; // overlay for old version compatibility
}
getOverlay() {
const { title, overlay } = this.props;
if (title === 0) {
return title;
}
return overlay || title || '';
}
renderTooltip = ({
@ -235,8 +243,6 @@ class Tooltip extends React.Component<TooltipProps, any> {
const { props, state } = this;
const {
prefixCls: customizePrefixCls,
title,
overlay,
openClassName,
getPopupContainer,
getTooltipContainer,
@ -270,7 +276,7 @@ class Tooltip extends React.Component<TooltipProps, any> {
getTooltipContainer={getPopupContainer || getTooltipContainer || getContextPopupContainer}
ref={this.saveTooltip}
builtinPlacements={this.getPlacements()}
overlay={overlay || title || ''}
overlay={this.getOverlay()}
visible={visible}
onVisibleChange={this.onVisibleChange}
onPopupAlign={this.onPopupAlign}

View File

@ -1903,6 +1903,7 @@ exports[`renders ./components/transfer/demo/table-transfer.md correctly 1`] = `
>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="0"
>
<td
class="ant-table-cell ant-table-selection-column"
@ -1946,6 +1947,7 @@ exports[`renders ./components/transfer/demo/table-transfer.md correctly 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="1"
>
<td
class="ant-table-cell ant-table-selection-column"
@ -1988,6 +1990,7 @@ exports[`renders ./components/transfer/demo/table-transfer.md correctly 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="3"
>
<td
class="ant-table-cell ant-table-selection-column"
@ -2030,6 +2033,7 @@ exports[`renders ./components/transfer/demo/table-transfer.md correctly 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="4"
>
<td
class="ant-table-cell ant-table-selection-column"
@ -2073,6 +2077,7 @@ exports[`renders ./components/transfer/demo/table-transfer.md correctly 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="6"
>
<td
class="ant-table-cell ant-table-selection-column"
@ -2115,6 +2120,7 @@ exports[`renders ./components/transfer/demo/table-transfer.md correctly 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="7"
>
<td
class="ant-table-cell ant-table-selection-column"
@ -2157,6 +2163,7 @@ exports[`renders ./components/transfer/demo/table-transfer.md correctly 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="9"
>
<td
class="ant-table-cell ant-table-selection-column"
@ -2199,6 +2206,7 @@ exports[`renders ./components/transfer/demo/table-transfer.md correctly 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="10"
>
<td
class="ant-table-cell ant-table-selection-column"
@ -2241,6 +2249,7 @@ exports[`renders ./components/transfer/demo/table-transfer.md correctly 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="12"
>
<td
class="ant-table-cell ant-table-selection-column"
@ -2284,6 +2293,7 @@ exports[`renders ./components/transfer/demo/table-transfer.md correctly 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="13"
>
<td
class="ant-table-cell ant-table-selection-column"
@ -2562,6 +2572,7 @@ exports[`renders ./components/transfer/demo/table-transfer.md correctly 1`] = `
>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="2"
>
<td
class="ant-table-cell ant-table-selection-column"
@ -2590,6 +2601,7 @@ exports[`renders ./components/transfer/demo/table-transfer.md correctly 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="5"
>
<td
class="ant-table-cell ant-table-selection-column"
@ -2618,6 +2630,7 @@ exports[`renders ./components/transfer/demo/table-transfer.md correctly 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="8"
>
<td
class="ant-table-cell ant-table-selection-column"
@ -2647,6 +2660,7 @@ exports[`renders ./components/transfer/demo/table-transfer.md correctly 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="11"
>
<td
class="ant-table-cell ant-table-selection-column"
@ -2675,6 +2689,7 @@ exports[`renders ./components/transfer/demo/table-transfer.md correctly 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="14"
>
<td
class="ant-table-cell ant-table-selection-column"
@ -2703,6 +2718,7 @@ exports[`renders ./components/transfer/demo/table-transfer.md correctly 1`] = `
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
data-row-key="17"
>
<td
class="ant-table-cell ant-table-selection-column"

View File

@ -16,13 +16,16 @@ exports[`Transfer.Search should show cross icon when input value exists 1`] = `
element={
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder=""
type="text"
value=""
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
onChange={[Function]}
@ -33,7 +36,9 @@ exports[`Transfer.Search should show cross icon when input value exists 1`] = `
>
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder=""
type="text"
@ -138,13 +143,16 @@ exports[`Transfer.Search should show cross icon when input value exists 2`] = `
element={
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder=""
type="text"
value="a"
/>
}
focused={false}
handleReset={[Function]}
inputType="input"
onChange={[Function]}
@ -155,7 +163,9 @@ exports[`Transfer.Search should show cross icon when input value exists 2`] = `
>
<input
className="ant-input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder=""
type="text"

View File

@ -37,7 +37,8 @@ Tree selection control.
| showCheckedStrategy | The way show selected item in box. **Default:** just show child nodes. **`TreeSelect.SHOW_ALL`:** show all checked treeNodes (include parent treeNode). **`TreeSelect.SHOW_PARENT`:** show checked treeNodes (just show parent treeNode). | enum { TreeSelect.SHOW_ALL, TreeSelect.SHOW_PARENT, TreeSelect.SHOW_CHILD } | TreeSelect.SHOW_CHILD | |
| showSearch | Support search or not | boolean | single: `false` \| multiple: `true` | |
| size | To set the size of the select input, options: `large` `small` | string | 'default' | |
| suffixIcon | The custom suffix icon | ReactNode | - | |
| showArrow | Whether to show the `suffixIcon`when single selection mode, default `true` | boolean | | |
| suffixIcon | The custom suffix icon,you must set `showArrow` to `true` manually in multiple selection mode | ReactNode | - | |
| treeCheckable | Whether to show checkbox on the treeNodes | boolean | false | |
| treeCheckStrictly | Whether to check nodes precisely (in the `checkable` mode), means parent and child nodes are not associated, and it will make `labelInValue` be true | boolean | false | |
| treeData | Data of the treeNodes, manual construction work is no longer needed if this property has been set(ensure the Uniqueness of each value) | array\<{ value, title, children, \[disabled, disableCheckbox, selectable, checkable] }> | \[] | |

View File

@ -38,7 +38,8 @@ title: TreeSelect
| showCheckedStrategy | 定义选中项回填的方式。`TreeSelect.SHOW_ALL`: 显示所有选中节点(包括父节点). `TreeSelect.SHOW_PARENT`: 只显示父节点(当父节点下所有子节点都选中时). 默认只显示子节点. | enum{TreeSelect.SHOW_ALL, TreeSelect.SHOW_PARENT, TreeSelect.SHOW_CHILD } | TreeSelect.SHOW_CHILD | |
| showSearch | 是否支持搜索框 | boolean | 单选:`false` \| 多选:`true` | |
| size | 选择框大小,可选 `large` `small` | string | 'default' | |
| suffixIcon | 自定义的选择框后缀图标 | ReactNode | - | |
| showArrow | 是否显示 `suffixIcon`,单选模式下默认 `true` | boolean | | |
| suffixIcon | 自定义的选择框后缀图标, 多选模式下必须同时设置 `showArrow``true` | ReactNode | - | |
| treeCheckable | 显示 checkbox | boolean | false | |
| treeCheckStrictly | checkable 状态下节点选择完全受控(父子节点选中状态不再关联),会使得 `labelInValue` 强制为 true | boolean | false | |
| treeData | treeNodes 数据,如果设置则不需要手动构造 TreeNode 节点value 在整个树范围内唯一) | array\<{value, title, children, \[disabled, disableCheckbox, selectable, checkable]}> | \[] | |

View File

@ -115,7 +115,7 @@ Like [the explaination](https://github.com/ant-design/ant-design/issues/11586#is
##### Workaround
You can refer to [this article](https://juejin.im/post/5cf65c366fb9a07eca6968f9) or [this article](https://www.cnblogs.com/zyl-Tara/p/10197177.html), using `mode` and `onPanelChange` to encapsulate a `YearPicker` or `MonthRangePicker` for your needs. Or you can wait for our [antd@4.0](https://github.com/ant-design/ant-design/issues/16911), in which we are planing to [add more XxxPickers](https://github.com/ant-design/ant-design/issues/4524#issuecomment-480576884) for those requirments.
You can refer to [this article](https://juejin.im/post/5cf65c366fb9a07eca6968f9) or [this article](https://www.cnblogs.com/zyl-Tara/p/10197177.html), using `mode` and `onPanelChange` to encapsulate a `YearPicker` or `MonthRangePicker` for your needs. Or you can wait for our [antd@4.0](https://github.com/ant-design/ant-design/issues/16911), in which we are planing (already) to [add more XxxPickers](https://github.com/ant-design/ant-design/issues/4524#issuecomment-480576884) for those requirments.
### How to spell Ant Design correctly?

View File

@ -121,7 +121,7 @@ import { Menu, Breadcrumb, Icon } from 'antd';
##### 解决办法
你可以参照 [这篇文章](https://juejin.im/post/5cf65c366fb9a07eca6968f9) 或者 [这篇文章](https://www.cnblogs.com/zyl-Tara/p/10197177.html) 里的做法,利用 `mode``onPanelChange` 等方法去封装一个 `YearPicker` 等组件。我们计划在 [antd@4.0](https://github.com/ant-design/ant-design/issues/16911) 中直接[添加更多相关日期组件](https://github.com/ant-design/ant-design/issues/4524#issuecomment-480576884)来支持这些需求。届时不再需要使用 `mode="year|month"`,而是直接可以用 `YearPicker` `MonthPicker`,并且 `disabledDate` 也可以正确作用于这些 Picker。
你可以参照 [这篇文章](https://juejin.im/post/5cf65c366fb9a07eca6968f9) 或者 [这篇文章](https://www.cnblogs.com/zyl-Tara/p/10197177.html) 里的做法,利用 `mode``onPanelChange` 等方法去封装一个 `YearPicker` 等组件。我们计划(已经支持)在 [antd@4.0](https://github.com/ant-design/ant-design/issues/16911) 中直接[添加更多相关日期组件](https://github.com/ant-design/ant-design/issues/4524#issuecomment-480576884)来支持这些需求。届时不再需要使用 `mode="year|month"`,而是直接可以用 `YearPicker` `MonthPicker`,并且 `disabledDate` 也可以正确作用于这些 Picker。
### 如何正确的拼写 Ant Design

View File

@ -116,6 +116,7 @@ const Demo = () => (
- The Grid component uses flex layout.
- Button's `danger` is now treated as a property instead of a button type.
- Input, Select set `value` to `undefined` is uncontrolled mode now.
- Table will keep at least one column even if `columns` is empty.
## Start upgrading

View File

@ -116,6 +116,7 @@ const Demo = () => (
- Grid 组件使用 flex 布局。
- Button 的 `danger` 现在作为一个属性而不是按钮类型。
- Input、Select 的 `value``undefined` 时改为非受控状态。
- Table 在没有 `columns` 时仍然会保留一列。
## 开始升级

View File

@ -1,5 +1,5 @@
---
order: 5
order: 7.1
title: Replace Moment.js
---

View File

@ -1,5 +1,5 @@
---
order: 5
order: 7.1
title: 替换 Moment.js
---

View File

@ -1,6 +1,6 @@
{
"name": "antd",
"version": "4.0.0-rc.0",
"version": "4.0.0-rc.1",
"description": "An enterprise-class UI design language and React components implementation",
"keywords": [
"ant",
@ -121,7 +121,7 @@
"rc-slider": "~9.0.0-alpha.0",
"rc-steps": "~3.5.0",
"rc-switch": "~1.9.0",
"rc-table": "~7.0.0-rc.3",
"rc-table": "~7.0.0-rc.4",
"rc-tabs": "~10.0.0-alpha.1",
"rc-tooltip": "~4.0.0-alpha.3",
"rc-tree": "~3.0.0-alpha.37",
@ -182,7 +182,7 @@
"eslint-config-airbnb": "^18.0.0",
"eslint-config-prettier": "^6.0.0",
"eslint-plugin-babel": "^5.3.0",
"eslint-plugin-import": "~2.19.1",
"eslint-plugin-import": "~2.20.0",
"eslint-plugin-jest": "^23.0.2",
"eslint-plugin-jsx-a11y": "^6.2.1",
"eslint-plugin-markdown": "^1.0.0",
@ -198,7 +198,7 @@
"intersection-observer": "^0.7.0",
"jest": "^24.8.0",
"jquery": "^3.4.1",
"jsdom": "^15.1.1",
"jsdom": "^16.0.0",
"jsonml.js": "^0.1.0",
"less-vars-to-js": "^1.3.0",
"logrocket": "^1.0.0",
@ -237,7 +237,7 @@
"rimraf": "^3.0.0",
"scrollama": "^2.0.0",
"simple-git": "^1.113.0",
"stylelint": "^12.0.0",
"stylelint": "^13.0.0",
"stylelint-config-prettier": "^8.0.0",
"stylelint-config-rational-order": "^0.1.2",
"stylelint-config-standard": "^19.0.0",

View File

@ -1,8 +1,11 @@
.contributors-list {
display: flex;
flex-wrap: wrap;
margin-top: 120px !important;
a + a,
a,
.ant-avatar + .ant-avatar {
margin-left: 8px;
margin-right: 8px;
margin-bottom: 8px;
}
}

View File

@ -149,7 +149,7 @@ class Header extends React.Component {
.slice(0, -1)
.join('/');
let activeMenuItem = module || 'home';
if (location.pathname === 'changelog') {
if (location.pathname === 'changelog' || location.pathname === 'changelog-cn') {
activeMenuItem = 'docs/react';
}