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

chore: 🔀 Master to merge feature
This commit is contained in:
偏右 2020-05-09 21:16:15 +08:00 committed by GitHub
commit 741ff5c3bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 354 additions and 205 deletions

2
.github/FUNDING.yml vendored
View File

@ -6,4 +6,4 @@ patreon: ant_design
ko_fi: # Replace with a single Ko-fi username
issuehunt: ant-design/ant-design
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
custom: # Replace with a single custom sponsorship URL
custom: https://www.buymeacoffee.com/antdesign

View File

@ -163,7 +163,7 @@ exports[`renders ./components/alert/demo/basic.md correctly 1`] = `
`;
exports[`renders ./components/alert/demo/closable.md correctly 1`] = `
<div>
Array [
<div
class="ant-alert ant-alert-warning ant-alert-no-icon ant-alert-closable"
data-show="true"
@ -202,7 +202,7 @@ exports[`renders ./components/alert/demo/closable.md correctly 1`] = `
</svg>
</span>
</button>
</div>
</div>,
<div
class="ant-alert ant-alert-error ant-alert-with-description ant-alert-no-icon ant-alert-closable"
data-show="true"
@ -243,8 +243,8 @@ exports[`renders ./components/alert/demo/closable.md correctly 1`] = `
</svg>
</span>
</button>
</div>
</div>
</div>,
]
`;
exports[`renders ./components/alert/demo/close-text.md correctly 1`] = `
@ -275,7 +275,7 @@ exports[`renders ./components/alert/demo/close-text.md correctly 1`] = `
`;
exports[`renders ./components/alert/demo/custom-icon.md correctly 1`] = `
<div>
Array [
<div
class="ant-alert ant-alert-success ant-alert-no-icon"
data-show="true"
@ -288,7 +288,7 @@ exports[`renders ./components/alert/demo/custom-icon.md correctly 1`] = `
<span
class="ant-alert-description"
/>
</div>
</div>,
<div
class="ant-alert ant-alert-success"
data-show="true"
@ -321,7 +321,7 @@ exports[`renders ./components/alert/demo/custom-icon.md correctly 1`] = `
<span
class="ant-alert-description"
/>
</div>
</div>,
<div
class="ant-alert ant-alert-info"
data-show="true"
@ -354,7 +354,7 @@ exports[`renders ./components/alert/demo/custom-icon.md correctly 1`] = `
<span
class="ant-alert-description"
/>
</div>
</div>,
<div
class="ant-alert ant-alert-warning"
data-show="true"
@ -387,7 +387,7 @@ exports[`renders ./components/alert/demo/custom-icon.md correctly 1`] = `
<span
class="ant-alert-description"
/>
</div>
</div>,
<div
class="ant-alert ant-alert-error"
data-show="true"
@ -420,7 +420,7 @@ exports[`renders ./components/alert/demo/custom-icon.md correctly 1`] = `
<span
class="ant-alert-description"
/>
</div>
</div>,
<div
class="ant-alert ant-alert-success ant-alert-with-description"
data-show="true"
@ -455,7 +455,7 @@ exports[`renders ./components/alert/demo/custom-icon.md correctly 1`] = `
>
Detailed description and advices about successful copywriting.
</span>
</div>
</div>,
<div
class="ant-alert ant-alert-info ant-alert-with-description"
data-show="true"
@ -490,7 +490,7 @@ exports[`renders ./components/alert/demo/custom-icon.md correctly 1`] = `
>
Additional description and informations about copywriting.
</span>
</div>
</div>,
<div
class="ant-alert ant-alert-warning ant-alert-with-description"
data-show="true"
@ -525,7 +525,7 @@ exports[`renders ./components/alert/demo/custom-icon.md correctly 1`] = `
>
This is a warning notice about copywriting.
</span>
</div>
</div>,
<div
class="ant-alert ant-alert-error ant-alert-with-description"
data-show="true"
@ -560,12 +560,12 @@ exports[`renders ./components/alert/demo/custom-icon.md correctly 1`] = `
>
This is an error message about copywriting.
</span>
</div>
</div>
</div>,
]
`;
exports[`renders ./components/alert/demo/description.md correctly 1`] = `
<div>
Array [
<div
class="ant-alert ant-alert-success ant-alert-with-description ant-alert-no-icon"
data-show="true"
@ -580,7 +580,7 @@ exports[`renders ./components/alert/demo/description.md correctly 1`] = `
>
Success Description Success Description Success Description
</span>
</div>
</div>,
<div
class="ant-alert ant-alert-info ant-alert-with-description ant-alert-no-icon"
data-show="true"
@ -595,7 +595,7 @@ exports[`renders ./components/alert/demo/description.md correctly 1`] = `
>
Info Description Info Description Info Description Info Description
</span>
</div>
</div>,
<div
class="ant-alert ant-alert-warning ant-alert-with-description ant-alert-no-icon"
data-show="true"
@ -610,7 +610,7 @@ exports[`renders ./components/alert/demo/description.md correctly 1`] = `
>
Warning Description Warning Description Warning Description Warning Description
</span>
</div>
</div>,
<div
class="ant-alert ant-alert-error ant-alert-with-description ant-alert-no-icon"
data-show="true"
@ -625,8 +625,8 @@ exports[`renders ./components/alert/demo/description.md correctly 1`] = `
>
Error Description Error Description Error Description Error Description
</span>
</div>
</div>
</div>,
]
`;
exports[`renders ./components/alert/demo/error-boundary.md correctly 1`] = `
@ -641,7 +641,7 @@ exports[`renders ./components/alert/demo/error-boundary.md correctly 1`] = `
`;
exports[`renders ./components/alert/demo/icon.md correctly 1`] = `
<div>
Array [
<div
class="ant-alert ant-alert-success"
data-show="true"
@ -674,7 +674,7 @@ exports[`renders ./components/alert/demo/icon.md correctly 1`] = `
<span
class="ant-alert-description"
/>
</div>
</div>,
<div
class="ant-alert ant-alert-info"
data-show="true"
@ -707,7 +707,7 @@ exports[`renders ./components/alert/demo/icon.md correctly 1`] = `
<span
class="ant-alert-description"
/>
</div>
</div>,
<div
class="ant-alert ant-alert-warning ant-alert-closable"
data-show="true"
@ -766,7 +766,7 @@ exports[`renders ./components/alert/demo/icon.md correctly 1`] = `
</svg>
</span>
</button>
</div>
</div>,
<div
class="ant-alert ant-alert-error"
data-show="true"
@ -799,7 +799,7 @@ exports[`renders ./components/alert/demo/icon.md correctly 1`] = `
<span
class="ant-alert-description"
/>
</div>
</div>,
<div
class="ant-alert ant-alert-success ant-alert-with-description"
data-show="true"
@ -837,7 +837,7 @@ exports[`renders ./components/alert/demo/icon.md correctly 1`] = `
>
Detailed description and advice about successful copywriting.
</span>
</div>
</div>,
<div
class="ant-alert ant-alert-info ant-alert-with-description"
data-show="true"
@ -875,7 +875,7 @@ exports[`renders ./components/alert/demo/icon.md correctly 1`] = `
>
Additional description and information about copywriting.
</span>
</div>
</div>,
<div
class="ant-alert ant-alert-warning ant-alert-with-description ant-alert-closable"
data-show="true"
@ -939,7 +939,7 @@ exports[`renders ./components/alert/demo/icon.md correctly 1`] = `
</svg>
</span>
</button>
</div>
</div>,
<div
class="ant-alert ant-alert-error ant-alert-with-description"
data-show="true"
@ -977,8 +977,8 @@ exports[`renders ./components/alert/demo/icon.md correctly 1`] = `
>
This is an error message about copywriting.
</span>
</div>
</div>
</div>,
]
`;
exports[`renders ./components/alert/demo/loop-banner.md correctly 1`] = `
@ -1080,7 +1080,7 @@ exports[`renders ./components/alert/demo/smooth-closed.md correctly 1`] = `
`;
exports[`renders ./components/alert/demo/style.md correctly 1`] = `
<div>
Array [
<div
class="ant-alert ant-alert-success ant-alert-no-icon"
data-show="true"
@ -1093,7 +1093,7 @@ exports[`renders ./components/alert/demo/style.md correctly 1`] = `
<span
class="ant-alert-description"
/>
</div>
</div>,
<div
class="ant-alert ant-alert-info ant-alert-no-icon"
data-show="true"
@ -1106,7 +1106,7 @@ exports[`renders ./components/alert/demo/style.md correctly 1`] = `
<span
class="ant-alert-description"
/>
</div>
</div>,
<div
class="ant-alert ant-alert-warning ant-alert-no-icon"
data-show="true"
@ -1119,7 +1119,7 @@ exports[`renders ./components/alert/demo/style.md correctly 1`] = `
<span
class="ant-alert-description"
/>
</div>
</div>,
<div
class="ant-alert ant-alert-error ant-alert-no-icon"
data-show="true"
@ -1132,6 +1132,6 @@ exports[`renders ./components/alert/demo/style.md correctly 1`] = `
<span
class="ant-alert-description"
/>
</div>
</div>
</div>,
]
`;

View File

@ -22,6 +22,27 @@ exports[`Alert ErrorBoundary 1`] = `
</div>
`;
exports[`Alert could accept none react element icon 1`] = `
<div
class="ant-alert ant-alert-success"
data-show="true"
>
<span
class="ant-alert-icon"
>
icon
</span>
<span
class="ant-alert-message"
>
Success Tips
</span>
<span
class="ant-alert-description"
/>
</div>
`;
exports[`Alert rtl render component should be rendered correctly in RTL direction 1`] = `
<div
class="ant-alert ant-alert-info ant-alert-no-icon ant-alert-rtl"

View File

@ -105,4 +105,9 @@ describe('Alert', () => {
expect(ref.current.getPopupDomNode()).toBeTruthy();
jest.useFakeTimers();
});
it('could accept none react element icon', () => {
const wrapper = mount(<Alert message="Success Tips" type="success" showIcon icon="icon" />);
expect(wrapper).toMatchRenderedSnapshot();
});
});

View File

@ -21,7 +21,7 @@ const onClose = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
};
ReactDOM.render(
<div>
<>
<Alert
message="Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text"
type="warning"
@ -35,7 +35,7 @@ ReactDOM.render(
closable
onClose={onClose}
/>
</div>,
</>,
mountNode,
);
```

View File

@ -21,7 +21,7 @@ import { SmileOutlined } from '@ant-design/icons';
const icon = <SmileOutlined />;
ReactDOM.render(
<div>
<>
<Alert icon={icon} message="showIcon = false" type="success" />
<Alert icon={icon} message="Success Tips" type="success" showIcon />
<Alert icon={icon} message="Informational Notes" type="info" showIcon />
@ -55,7 +55,7 @@ ReactDOM.render(
type="error"
showIcon
/>
</div>,
</>,
mountNode,
);
```

View File

@ -17,7 +17,7 @@ Additional description for alert message.
import { Alert } from 'antd';
ReactDOM.render(
<div>
<>
<Alert
message="Success Text"
description="Success Description Success Description Success Description"
@ -38,7 +38,7 @@ ReactDOM.render(
description="Error Description Error Description Error Description Error Description"
type="error"
/>
</div>,
</>,
mountNode,
);
```

View File

@ -17,7 +17,7 @@ A relevant icon will make information clearer and more friendly.
import { Alert } from 'antd';
ReactDOM.render(
<div>
<>
<Alert message="Success Tips" type="success" showIcon />
<Alert message="Informational Notes" type="info" showIcon />
<Alert message="Warning" type="warning" showIcon closable />
@ -47,7 +47,7 @@ ReactDOM.render(
type="error"
showIcon
/>
</div>,
</>,
mountNode,
);
```

View File

@ -17,12 +17,12 @@ There are 4 types of Alert: `success`, `info`, `warning`, `error`.
import { Alert } from 'antd';
ReactDOM.render(
<div>
<>
<Alert message="Success Text" type="success" />
<Alert message="Info Text" type="info" />
<Alert message="Warning Text" type="warning" />
<Alert message="Error Text" type="error" />
</div>,
</>,
mountNode,
);
```

View File

@ -16,8 +16,6 @@ import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
import getDataOrAriaProps from '../_util/getDataOrAriaProps';
import ErrorBoundary from './ErrorBoundary';
function noop() {}
export interface AlertProps {
/**
* Type of Alert styles, options:`success`, `info`, `warning`, `error`
@ -87,7 +85,7 @@ export default class Alert extends React.Component<AlertProps, AlertState> {
this.setState({
closing: true,
});
(this.props.onClose || noop)(e);
this.props.onClose?.(e);
};
animationEnd = () => {
@ -95,56 +93,56 @@ export default class Alert extends React.Component<AlertProps, AlertState> {
closing: false,
closed: true,
});
(this.props.afterClose || noop)();
this.props.afterClose?.();
};
renderAlert = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
const {
description,
prefixCls: customizePrefixCls,
message,
closeText,
banner,
className = '',
style,
icon,
onMouseEnter,
onMouseLeave,
onClick,
} = this.props;
let { closable, type, showIcon } = this.props;
const { closing, closed } = this.state;
getShowIcon() {
const { banner, showIcon } = this.props;
// banner 模式默认有 Icon
return banner && showIcon === undefined ? true : showIcon;
}
const prefixCls = getPrefixCls('alert', customizePrefixCls);
// banner模式默认有 Icon
showIcon = banner && showIcon === undefined ? true : showIcon;
// banner模式默认为警告
type = banner && type === undefined ? 'warning' : type || 'info';
// use outline icon in alert with description
const iconType = (description ? iconMapOutlined : iconMapFilled)[type] || null;
// closeable when closeText is assigned
if (closeText) {
closable = true;
getType() {
const { banner, type } = this.props;
if (type !== undefined) {
return type;
}
// banner 模式默认为警告
return banner ? 'warning' : 'info';
}
const alertCls = classNames(
prefixCls,
`${prefixCls}-${type}`,
{
[`${prefixCls}-closing`]: closing,
[`${prefixCls}-with-description`]: !!description,
[`${prefixCls}-no-icon`]: !showIcon,
[`${prefixCls}-banner`]: !!banner,
[`${prefixCls}-closable`]: closable,
[`${prefixCls}-rtl`]: direction === 'rtl',
},
className,
);
getClosable() {
const { closable, closeText } = this.props;
// closeable when closeText is assigned
return closeText ? true : closable;
}
const closeIcon = closable ? (
getIconType() {
const { description } = this.props;
// use outline icon in alert with description
return (description ? iconMapOutlined : iconMapFilled)[this.getType()] || null;
}
renderIconNode({ prefixCls }: { prefixCls: string }) {
const { icon } = this.props;
const iconType = this.getIconType();
if (icon) {
return React.isValidElement<{ className?: string }>(icon) ? (
React.cloneElement(icon, {
className: classNames(`${prefixCls}-icon`, {
[icon.props.className as string]: icon.props.className,
}),
})
) : (
<span className={`${prefixCls}-icon`}>{icon}</span>
);
}
return React.createElement(iconType, { className: `${prefixCls}-icon` });
}
renderCloseIcon({ prefixCls }: { prefixCls: string }) {
const { closeText } = this.props;
return this.getClosable() ? (
<button
type="button"
onClick={this.handleClose}
@ -158,21 +156,47 @@ export default class Alert extends React.Component<AlertProps, AlertState> {
)}
</button>
) : null;
}
renderAlert = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
const {
description,
prefixCls: customizePrefixCls,
message,
banner,
className = '',
style,
onMouseEnter,
onMouseLeave,
onClick,
} = this.props;
const { closing, closed } = this.state;
const prefixCls = getPrefixCls('alert', customizePrefixCls);
const isShowIcon = this.getShowIcon();
const type = this.getType();
const closable = this.getClosable();
const alertCls = classNames(
prefixCls,
`${prefixCls}-${type}`,
{
[`${prefixCls}-closing`]: closing,
[`${prefixCls}-with-description`]: !!description,
[`${prefixCls}-no-icon`]: !isShowIcon,
[`${prefixCls}-banner`]: !!banner,
[`${prefixCls}-closable`]: closable,
[`${prefixCls}-rtl`]: direction === 'rtl',
},
className,
);
const closeIcon = this.renderCloseIcon({ prefixCls });
const dataOrAriaProps = getDataOrAriaProps(this.props);
const iconNode =
(icon &&
(React.isValidElement<{ className?: string }>(icon) ? (
React.cloneElement(icon, {
className: classNames(`${prefixCls}-icon`, {
[icon.props.className as string]: icon.props.className,
}),
})
) : (
<span className={`${prefixCls}-icon`}>{icon}</span>
))) ||
React.createElement(iconType, { className: `${prefixCls}-icon` });
const iconNode = this.renderIconNode({ prefixCls });
return closed ? null : (
<Animate
@ -190,7 +214,7 @@ export default class Alert extends React.Component<AlertProps, AlertState> {
onClick={onClick}
{...dataOrAriaProps}
>
{showIcon ? iconNode : null}
{isShowIcon ? iconNode : null}
<span className={`${prefixCls}-message`}>{message}</span>
<span className={`${prefixCls}-description`}>{description}</span>
{closeIcon}

View File

@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders ./components/auto-complete/demo/basic.md correctly 1`] = `
<div>
Array [
<div
class="ant-select ant-select-auto-complete ant-select-single ant-select-show-search"
style="width:200px"
@ -30,9 +30,9 @@ exports[`renders ./components/auto-complete/demo/basic.md correctly 1`] = `
input here
</span>
</div>
</div>
<br />
<br />
</div>,
<br />,
<br />,
<div
class="ant-select ant-select-auto-complete ant-select-single ant-select-show-search"
style="width:200px"
@ -61,8 +61,8 @@ exports[`renders ./components/auto-complete/demo/basic.md correctly 1`] = `
control mode
</span>
</div>
</div>
</div>
</div>,
]
`;
exports[`renders ./components/auto-complete/demo/certain-category.md correctly 1`] = `

View File

@ -1,6 +1,86 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`AutoComplete with Custom Input Element Render rtl render component should be rendered correctly in RTL direction 1`] = `
exports[`AutoComplete legacy dataSource should accept react element option 1`] = `
<div
class="ant-select ant-select-auto-complete ant-select-single ant-select-open ant-select-show-search"
>
<div
class="ant-select-selector"
>
<span
class="ant-select-selection-search"
>
<input
aria-activedescendant="undefined_list_0"
aria-autocomplete="list"
aria-controls="undefined_list"
aria-expanded="true"
aria-haspopup="listbox"
aria-owns="undefined_list"
autocomplete="off"
class="ant-select-selection-search-input"
role="combobox"
value=""
/>
</span>
<span
class="ant-select-selection-placeholder"
/>
</div>
<div>
<div
class="ant-select-dropdown"
style="opacity:0"
>
<div>
<div
id="undefined_list"
role="listbox"
style="height:0;width:0;overflow:hidden"
>
<div
aria-selected="false"
id="undefined_list_0"
role="option"
>
key
</div>
</div>
<div
class=""
style="height:256px"
>
<div>
<div
class=""
style="display:flex;flex-direction:column"
>
<div
aria-selected="false"
class="ant-select-item ant-select-item-option ant-select-item-option-active"
>
<div
class="ant-select-item-option-content"
>
ReactNode
</div>
<span
aria-hidden="true"
class="ant-select-item-option-state"
style="user-select:none;-webkit-user-select:none"
unselectable="on"
/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`AutoComplete rtl render component should be rendered correctly in RTL direction 1`] = `
<div
class="ant-select ant-select-auto-complete ant-select-rtl ant-select-single ant-select-show-search"
>

View File

@ -4,7 +4,7 @@ import AutoComplete from '..';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
describe('AutoComplete with Custom Input Element Render', () => {
describe('AutoComplete', () => {
mountTest(AutoComplete);
rtlTest(AutoComplete);
@ -52,4 +52,21 @@ describe('AutoComplete with Custom Input Element Render', () => {
// eslint-disable-next-line no-console
console.error.mockRestore();
});
it('legacy dataSource should accept react element option', () => {
const wrapper = mount(<AutoComplete open dataSource={[<span key="key">ReactNode</span>]} />);
expect(wrapper).toMatchRenderedSnapshot();
});
it('legacy AutoComplete.Option should be compatiable', () => {
const wrapper = mount(
<AutoComplete>
<AutoComplete.Option value="111">111</AutoComplete.Option>
<AutoComplete.Option value="222">222</AutoComplete.Option>
</AutoComplete>,
);
expect(wrapper.find('input').length).toBe(1);
wrapper.find('input').simulate('change', { target: { value: '1' } });
expect(wrapper.find('.ant-select-item-option').length).toBe(2);
});
});

View File

@ -37,7 +37,7 @@ const Complete: React.FC = () => {
setValue(data);
};
return (
<div>
<>
<AutoComplete
options={options}
style={{ width: 200 }}
@ -56,7 +56,7 @@ const Complete: React.FC = () => {
onChange={onChange}
placeholder="control mode"
/>
</div>
</>
);
};

View File

@ -67,18 +67,16 @@ const options = [
},
];
const Complete: React.FC = () => {
return (
<AutoComplete
dropdownClassName="certain-category-search-dropdown"
dropdownMatchSelectWidth={500}
style={{ width: 250 }}
options={options}
>
<Input.Search size="large" placeholder="input here" />
</AutoComplete>
);
};
const Complete: React.FC = () => (
<AutoComplete
dropdownClassName="certain-category-search-dropdown"
dropdownMatchSelectWidth={500}
style={{ width: 250 }}
options={options}
>
<Input.Search size="large" placeholder="input here" />
</AutoComplete>
);
ReactDOM.render(<Complete />, mountNode);
```

View File

@ -22,25 +22,25 @@ const formItemLayout = {
};
ReactDOM.render(
<Form style={{ margin: '0 auto' }}>
<Form.Item label="单独 AutoComplete" {...formItemLayout}>
<Form style={{ margin: '0 auto' }} {...formItemLayout}>
<Form.Item label="单独 AutoComplete">
<AutoComplete />
</Form.Item>
<Form.Item label="单独 TreeSelect" {...formItemLayout}>
<Form.Item label="单独 TreeSelect">
<TreeSelect />
</Form.Item>
<Form.Item label="添加 Input.Group 正常" {...formItemLayout}>
<Form.Item label="添加 Input.Group 正常">
<Input.Group compact>
<TreeSelect style={{ width: '30%' }} />
<AutoComplete />
</Input.Group>
</Form.Item>
<Form.Item label="包含 search 图标正常" {...formItemLayout}>
<Form.Item label="包含 search 图标正常">
<AutoComplete>
<Input suffix={<SearchOutlined />} />
</AutoComplete>
</Form.Item>
<Form.Item label="同时有 Input.Group 和图标发生移位" {...formItemLayout}>
<Form.Item label="同时有 Input.Group 和图标发生移位">
<Input.Group compact>
<TreeSelect style={{ width: '30%' }} />
<AutoComplete>
@ -48,7 +48,7 @@ ReactDOM.render(
</AutoComplete>
</Input.Group>
</Form.Item>
<Form.Item label="同时有 Input.Group 和 Search 组件发生移位" {...formItemLayout}>
<Form.Item label="同时有 Input.Group 和 Search 组件发生移位">
<Input.Group compact>
<TreeSelect style={{ width: '30%' }} />
<AutoComplete>
@ -56,7 +56,7 @@ ReactDOM.render(
</AutoComplete>
</Input.Group>
</Form.Item>
<Form.Item label="Input Group 和 Button 结合" {...formItemLayout}>
<Form.Item label="Input Group 和 Button 结合">
<Input.Group compact>
<TreeSelect style={{ width: '20%' }} />
<AutoComplete>

View File

@ -22,18 +22,16 @@ const options = [
{ value: 'Wall Street' },
];
const Complete: React.FC = () => {
return (
<AutoComplete
style={{ width: 200 }}
options={options}
placeholder="try to type `b`"
filterOption={(inputValue, option) =>
option.value.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1
}
/>
);
}
const Complete: React.FC = () => (
<AutoComplete
style={{ width: 200 }}
options={options}
placeholder="try to type `b`"
filterOption={(inputValue, option) =>
option.value.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1
}
/>
);
ReactDOM.render(<Complete />, mountNode);
```

View File

@ -30,14 +30,13 @@ const Complete: React.FC = () => {
}
setResult(res);
};
const children = result.map((email: string) => (
<Option key={email} value={email}>
{email}
</Option>
));
return (
<AutoComplete style={{ width: 200 }} onSearch={handleSearch} placeholder="input here">
{children}
{result.map((email: string) => (
<Option key={email} value={email}>
{email}
</Option>
))}
</AutoComplete>
);
};

View File

@ -43,7 +43,7 @@ subtitle: 按钮
| shape | 设置按钮形状,可选值为 `circle``round` 或者不设 | string | - | |
| size | 设置按钮大小 | `large` \| `middle` \| `small` | 无 | |
| target | 相当于 a 链接的 target 属性href 存在时生效 | string | - | |
| type | 设置按钮类型 | `primary` \| `ghost` \| `dashed` \| `danger` \| `link` \| `text` | - | |
| type | 设置按钮类型 | `primary` \| `ghost` \| `dashed` \| `danger` \| `link` \| `text` | - | |
| onClick | 点击按钮时的回调 | (event) => void | - | |
| block | 将按钮宽度调整为其父宽度的选项 | boolean | `false` | |
| danger | 设置危险按钮 | boolean | `false` | |

View File

@ -7,9 +7,6 @@ exports[`Comment rtl render component should be rendered correctly in RTL direct
<div
class="ant-comment-inner"
>
<div
class="ant-comment-avatar"
/>
<div
class="ant-comment-content"
>

View File

@ -52,11 +52,11 @@ const Comment: React.FC<CommentProps> = ({
const prefixCls = getPrefixCls('comment', customizePrefixCls);
const avatarDom = (
const avatarDom = avatar ? (
<div className={`${prefixCls}-avatar`}>
{typeof avatar === 'string' ? <img src={avatar} alt="comment-avatar" /> : avatar}
</div>
);
) : null;
const actionDom =
actions && actions.length ? (

View File

@ -11299,9 +11299,6 @@ exports[`ConfigProvider components Comment configProvider 1`] = `
<div
class="config-comment-inner"
>
<div
class="config-comment-avatar"
/>
<div
class="config-comment-content"
>
@ -11324,9 +11321,6 @@ exports[`ConfigProvider components Comment configProvider 1`] = `
<div
class="config-comment-inner"
>
<div
class="config-comment-avatar"
/>
<div
class="config-comment-content"
>
@ -11352,9 +11346,6 @@ exports[`ConfigProvider components Comment configProvider componentSize large 1`
<div
class="config-comment-inner"
>
<div
class="config-comment-avatar"
/>
<div
class="config-comment-content"
>
@ -11377,9 +11368,6 @@ exports[`ConfigProvider components Comment configProvider componentSize large 1`
<div
class="config-comment-inner"
>
<div
class="config-comment-avatar"
/>
<div
class="config-comment-content"
>
@ -11405,9 +11393,6 @@ exports[`ConfigProvider components Comment configProvider componentSize middle 1
<div
class="config-comment-inner"
>
<div
class="config-comment-avatar"
/>
<div
class="config-comment-content"
>
@ -11430,9 +11415,6 @@ exports[`ConfigProvider components Comment configProvider componentSize middle 1
<div
class="config-comment-inner"
>
<div
class="config-comment-avatar"
/>
<div
class="config-comment-content"
>
@ -11458,9 +11440,6 @@ exports[`ConfigProvider components Comment configProvider virtual and dropdownMa
<div
class="ant-comment-inner"
>
<div
class="ant-comment-avatar"
/>
<div
class="ant-comment-content"
>
@ -11483,9 +11462,6 @@ exports[`ConfigProvider components Comment configProvider virtual and dropdownMa
<div
class="ant-comment-inner"
>
<div
class="ant-comment-avatar"
/>
<div
class="ant-comment-content"
>
@ -11511,9 +11487,6 @@ exports[`ConfigProvider components Comment normal 1`] = `
<div
class="ant-comment-inner"
>
<div
class="ant-comment-avatar"
/>
<div
class="ant-comment-content"
>
@ -11536,9 +11509,6 @@ exports[`ConfigProvider components Comment normal 1`] = `
<div
class="ant-comment-inner"
>
<div
class="ant-comment-avatar"
/>
<div
class="ant-comment-content"
>
@ -11564,9 +11534,6 @@ exports[`ConfigProvider components Comment prefixCls 1`] = `
<div
class="prefix-Comment-inner"
>
<div
class="prefix-Comment-avatar"
/>
<div
class="prefix-Comment-content"
>
@ -11589,9 +11556,6 @@ exports[`ConfigProvider components Comment prefixCls 1`] = `
<div
class="prefix-Comment-inner"
>
<div
class="prefix-Comment-avatar"
/>
<div
class="prefix-Comment-content"
>

View File

@ -52,6 +52,14 @@
left: @input-padding-horizontal-base;
}
}
// Active bar
.@{picker-prefix-cls}-active-bar {
.@{picker-prefix-cls}-rtl& {
margin-right: @input-padding-horizontal-base;
margin-left: 0;
}
}
}
// ======================== Ranges ========================

View File

@ -175,7 +175,7 @@ class ClearableLabeledInput extends React.Component<ClearableInputProps> {
}
renderTextAreaWithClearIcon(prefixCls: string, element: React.ReactElement<any>) {
const { value, allowClear, className, style } = this.props;
const { value, allowClear, className, style, direction } = this.props;
if (!allowClear) {
return React.cloneElement(element, {
value,
@ -184,6 +184,7 @@ class ClearableLabeledInput extends React.Component<ClearableInputProps> {
const affixWrapperCls = classNames(
className,
`${prefixCls}-affix-wrapper`,
{ [`${prefixCls}-affix-wrapper-rtl`]: direction === 'rtl' },
`${prefixCls}-affix-wrapper-textarea-with-clear-btn`,
);
return (

View File

@ -99,7 +99,7 @@ class TextArea extends React.Component<TextAreaProps, TextAreaState> {
);
};
renderComponent = ({ getPrefixCls }: ConfigConsumerProps) => {
renderComponent = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
const { value } = this.state;
const { prefixCls: customizePrefixCls } = this.props;
const prefixCls = getPrefixCls('input', customizePrefixCls);
@ -107,6 +107,7 @@ class TextArea extends React.Component<TextAreaProps, TextAreaState> {
<ClearableLabeledInput
{...this.props}
prefixCls={prefixCls}
direction={direction}
inputType="text"
value={fixControlledValue(value)}
element={this.renderTextArea(prefixCls)}

View File

@ -179,7 +179,8 @@ ReactDOM.render(<App />, mountNode);
border-left-width: 0;
}
.site-input-group-wrapper .site-input-right:hover {
.site-input-group-wrapper .site-input-right:hover,
.site-input-group-wrapper .site-input-right:focus {
border-left-width: 1px;
}
@ -187,7 +188,8 @@ ReactDOM.render(<App />, mountNode);
border-right-width: 0;
}
.site-input-group-wrapper .ant-input-rtl.site-input-right:hover {
.site-input-group-wrapper .ant-input-rtl.site-input-right:hover,
.site-input-group-wrapper .ant-input-rtl.site-input-right:focus {
border-right-width: 1px;
}
```

View File

@ -344,6 +344,10 @@
}
}
& > .@{ant-prefix}-select-focused {
z-index: 1;
}
// update z-index for arrow icon
& > .@{ant-prefix}-select > .@{ant-prefix}-select-arrow {
z-index: 1; // https://github.com/ant-design/ant-design/issues/20371

View File

@ -35,6 +35,24 @@
}
}
// allow-clear
.@{ant-prefix}-input-clear-icon {
&:last-child {
.@{ant-prefix}-input-affix-wrapper-rtl & {
margin-right: @input-affix-margin;
margin-left: 0;
}
}
}
.@{ant-prefix}-input-textarea-clear-icon {
.@{ant-prefix}-input-affix-wrapper-rtl & {
right: auto;
left: 0;
margin: 8px 0 0 8px;
}
}
// mixin
@input-rtl-cls: ~'@{ant-prefix}-input-rtl';

View File

@ -11224,6 +11224,7 @@ Array [
</td>
<td
class="ant-table-cell ant-table-cell-ellipsis"
title="32"
>
32
</td>
@ -11246,6 +11247,7 @@ Array [
</td>
<td
class="ant-table-cell ant-table-cell-ellipsis"
title="42"
>
42
</td>
@ -11268,6 +11270,7 @@ Array [
</td>
<td
class="ant-table-cell ant-table-cell-ellipsis"
title="32"
>
32
</td>
@ -11290,6 +11293,7 @@ Array [
</td>
<td
class="ant-table-cell ant-table-cell-ellipsis"
title="32"
>
32
</td>

View File

@ -130,6 +130,7 @@ One of the Table `columns` prop for describing the table's columns, Column has t
| fixed | (IE not support) Set column to be fixed: `true`(same as left) `'left'` `'right'` | boolean\|string | `false` | |
| key | Unique key of this column, you can ignore this prop if you've set a unique `dataIndex` | string | - | |
| render | Renderer of the table cell. The return value should be a ReactNode, or an object for [colSpan/rowSpan config](#components-table-demo-colspan-rowspan) | Function(text, record, index) {} | - | |
| responsive | The list of breakpoints at which to display this column. Always visible if not set. | [Breakpoint](https://github.com/ant-design/ant-design/blob/015109b42b85c63146371b4e32b883cf97b088e8/components/_util/responsiveObserve.ts#L1)\[] | - | 4.2.0 |
| shouldCellUpdate | Control cell render logic | (record) => boolean | - | 4.3.0 |
| sorter | Sort function for local sort, see [Array.sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)'s compareFunction. If you need sort buttons only, set to `true` | Function\|boolean | - | |
| sortOrder | Order of sorted values: `'ascend'` `'descend'` `false` | boolean\|string | - | |

View File

@ -135,6 +135,7 @@ const columns = [
| fixed | IE 下无效)列是否固定,可选 `true`(等效于 left) `'left'` `'right'` | boolean\|string | false | |
| key | React 需要的 key如果已经设置了唯一的 `dataIndex`,可以忽略这个属性 | string | - | |
| render | 生成复杂数据的渲染函数,参数分别为当前行的值,当前行数据,行索引,@return 里面可以设置表格[行/列合并](#components-table-demo-colspan-rowspan) | Function(text, record, index) {} | - | |
| responsive | 响应式 breakpoint 配置列表。未设置则始终可见。 | [Breakpoint](https://github.com/ant-design/ant-design/blob/015109b42b85c63146371b4e32b883cf97b088e8/components/_util/responsiveObserve.ts#L1)\[] | - | 4.2.0 |
| shouldCellUpdate | 自定义单元格渲染时机 | (record) => boolean | - | 4.3.0 |
| sorter | 排序函数,本地排序使用一个函数(参考 [Array.sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) 的 compareFunction),需要服务端排序可设为 true | Function\|boolean | - | |
| sortOrder | 排序的受控属性,外界可用此控制列的排序,可设置为 `'ascend'` `'descend'` `false` | boolean\|string | - | |

View File

@ -313,7 +313,13 @@ export default class UploadList extends React.Component<UploadListProps, any> {
});
return (
<div key={file.uid} className={listContainerNameClass}>
{file.status === 'error' ? <Tooltip title={message}>{dom}</Tooltip> : <span>{dom}</span>}
{file.status === 'error' ? (
<Tooltip title={message} getPopupContainer={node => node.parentNode as HTMLElement}>
{dom}
</Tooltip>
) : (
<span>{dom}</span>
)}
</div>
);
});

View File

@ -131,7 +131,7 @@
"rc-resize-observer": "^0.2.0",
"rc-select": "~10.3.0",
"rc-slider": "~9.2.3",
"rc-steps": "~3.5.0",
"rc-steps": "~3.6.0",
"rc-switch": "~2.0.0",
"rc-table": "~7.6.0",
"rc-tabs": "~10.1.1",
@ -187,7 +187,7 @@
"enzyme-adapter-react-16": "^1.14.0",
"enzyme-to-json": "^3.3.5",
"esbuild-webpack-plugin": "^1.0.0-beta.3",
"eslint": "^6.8.0",
"eslint": "^7.0.0",
"eslint-config-airbnb": "^18.0.0",
"eslint-config-prettier": "^6.0.0",
"eslint-plugin-babel": "^5.3.0",